Signed-off-by: Boris BREZILLON <[email protected]>
---
drivers/mtd/nand/Kconfig | 1 +
drivers/mtd/nand/sunxi_nand.c | 63 ++++++++++++++++++++++++++++++++++++-----
2 files changed, 57 insertions(+), 7 deletions(-)
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index c712435..4cb75b0 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -517,6 +517,7 @@ config MTD_NAND_XWAY
config MTD_NAND_SUNXI
tristate "Support for NAND on Allwinner SoCs"
depends on ARCH_SUNXI
+ select MTD_OF_NAND_PARTS
help
Enables support for NAND Flash chips on Allwinner SoCs.
diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c
index d300adb..aaf1460 100644
--- a/drivers/mtd/nand/sunxi_nand.c
+++ b/drivers/mtd/nand/sunxi_nand.c
@@ -168,6 +168,17 @@ struct sunxi_nand_hw_ecc {
struct nand_ecclayout layout;
};
+struct sunxi_nand_part {
+ struct nand_part part;
+ struct nand_ecc_ctrl ecc;
+};
+
+static inline struct sunxi_nand_part *
+to_sunxi_nand_part(struct nand_part *part)
+{
+ return container_of(part, struct sunxi_nand_part, part);
+}
+
struct sunxi_nand_chip {
struct list_head node;
struct nand_chip nand;
@@ -416,7 +427,7 @@ static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd,
int oob_required, int page)
{
struct sunxi_nfc *nfc = to_sunxi_nfc(chip->controller);
- struct nand_ecc_ctrl *ecc = &chip->ecc;
+ struct nand_ecc_ctrl *ecc = chip->cur_ecc;
struct nand_ecclayout *layout = ecc->layout;
struct sunxi_nand_hw_ecc *data = ecc->priv;
int steps = mtd->writesize / ecc->size;
@@ -492,7 +503,7 @@ static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd,
const uint8_t *buf, int oob_required)
{
struct sunxi_nfc *nfc = to_sunxi_nfc(chip->controller);
- struct nand_ecc_ctrl *ecc = &chip->ecc;
+ struct nand_ecc_ctrl *ecc = chip->cur_ecc;
struct nand_ecclayout *layout = ecc->layout;
struct sunxi_nand_hw_ecc *data = ecc->priv;
int offset;
@@ -559,7 +570,7 @@ static int sunxi_nfc_hw_syndrome_ecc_read_page(struct
mtd_info *mtd,
int page)
{
struct sunxi_nfc *nfc = to_sunxi_nfc(chip->controller);
- struct nand_ecc_ctrl *ecc = &chip->ecc;
+ struct nand_ecc_ctrl *ecc = chip->cur_ecc;
struct sunxi_nand_hw_ecc *data = ecc->priv;
int steps = mtd->writesize / ecc->size;
unsigned int max_bitflips = 0;
@@ -623,7 +634,7 @@ static int sunxi_nfc_hw_syndrome_ecc_write_page(struct
mtd_info *mtd,
int oob_required)
{
struct sunxi_nfc *nfc = to_sunxi_nfc(chip->controller);
- struct nand_ecc_ctrl *ecc = &chip->ecc;
+ struct nand_ecc_ctrl *ecc = chip->cur_ecc;
struct sunxi_nand_hw_ecc *data = ecc->priv;
int steps = mtd->writesize / ecc->size;
uint8_t *oob = chip->oob_poi;
@@ -980,6 +991,11 @@ static int sunxi_nand_ecc_init(struct mtd_info *mtd,
struct nand_ecc_ctrl *ecc,
ecc->strength = nand->ecc_strength_ds;
}
+ if ((!ecc->size || !ecc->strength) && ecc != &nand->ecc) {
+ ecc->size = nand->ecc.size;
+ ecc->strength = nand->ecc.strength;
+ }
+
ecc->mode = of_get_nand_ecc_mode(np);
switch (ecc->mode) {
case NAND_ECC_SOFT_BCH:
@@ -1007,12 +1023,39 @@ static int sunxi_nand_ecc_init(struct mtd_info *mtd,
struct nand_ecc_ctrl *ecc,
return 0;
}
+static void sunxi_nand_part_release(struct nand_part *part)
+{
+ kfree(to_sunxi_nand_part(part));
+}
+
+struct nand_part *sunxi_ofnandpart_parse(void *priv, struct mtd_info *master,
+ struct device_node *pp)
+{
+ struct sunxi_nand_part *part;
+ int ret;
+
+ part = kzalloc(sizeof(*part), GFP_KERNEL);
+ part->part.release = sunxi_nand_part_release;
+
+ ret = sunxi_nand_ecc_init(master, &part->ecc, pp);
+ if (ret)
+ goto err;
+
+ part->part.ecc = &part->ecc;
+
+ return &part->part;
+
+err:
+ kfree(part);
+ return ERR_PTR(ret);
+}
+
static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
struct device_node *np)
{
const struct nand_sdr_timings *timings;
struct sunxi_nand_chip *chip;
- struct mtd_part_parser_data ppdata;
+ struct ofnandpart_data ppdata;
struct mtd_info *mtd;
struct nand_chip *nand;
int nsels;
@@ -1119,9 +1162,15 @@ static int sunxi_nand_chip_init(struct device *dev,
struct sunxi_nfc *nfc,
mtd->name = chip->default_name;
}
- ppdata.of_node = np;
- ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
+ ppdata.node = np;
+ ppdata.parse = sunxi_ofnandpart_parse;
+ ret = ofnandpart_parse(mtd, &ppdata);
if (!ret)
+ ret = mtd_device_register(mtd, NULL, 0);
+ else if (ret > 0)
+ ret = 0;
+
+ if (ret)
return ret;
list_add_tail(&chip->node, &nfc->chips);
--
1.7.9.5
--
You received this message because you are subscribed to the Google Groups
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.