diff --git a/drivers/mtd/nand/nand_imx.c b/drivers/mtd/nand/nand_imx.c index 75aefd6e8..1d7d3e8de 100644 --- a/drivers/mtd/nand/nand_imx.c +++ b/drivers/mtd/nand/nand_imx.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #define NFC_V3_FLASH_CMD (host->regs_axi + 0x00) @@ -100,6 +101,10 @@ struct imx_nand_host { int spare_len; int eccsize; + int hw_ecc; + int data_width; + int flash_bbt; + void (*preset)(struct mtd_info *); void (*send_cmd)(struct imx_nand_host *, uint16_t); void (*send_addr)(struct imx_nand_host *, uint16_t); @@ -1087,6 +1092,31 @@ static struct nand_bbt_descr bbt_mirror_descr = { .pattern = mirror_pattern, }; +static int __init mxcnd_probe_dt(struct imx_nand_host *host) +{ + struct device_node *np = host->dev->device_node; + int buswidth; + + if (!IS_ENABLED(CONFIG_OFDEVICE)) + return 1; + + if (!np) + return 1; + + if (of_get_nand_ecc_mode(np) == NAND_ECC_HW) + host->hw_ecc = 1; + + host->flash_bbt = of_get_nand_on_flash_bbt(np); + + buswidth = of_get_nand_bus_width(np); + if (buswidth < 0) + return buswidth; + + host->data_width = buswidth / 8; + + return 0; +} + /* * This function is called during the driver binding process. * @@ -1101,7 +1131,6 @@ static int __init imxnd_probe(struct device_d *dev) { struct nand_chip *this; struct mtd_info *mtd; - struct imx_nand_platform_data *pdata = dev->platform_data; struct imx_nand_host *host; struct nand_ecclayout *oob_smallpage, *oob_largepage, *oob_4kpage; int err = 0; @@ -1112,6 +1141,21 @@ static int __init imxnd_probe(struct device_d *dev) if (!host) return -ENOMEM; + host->dev = dev; + + err = mxcnd_probe_dt(host); + if (err < 0) + goto escan; + + if (err > 0) { + struct imx_nand_platform_data *pdata; + + pdata = dev->platform_data; + host->flash_bbt = pdata->flash_bbt; + host->data_width = pdata->width; + host->hw_ecc = pdata->hw_ecc; + } + host->data_buf = (uint8_t *)(host + 1); if (nfc_is_v1() || nfc_is_v21()) { @@ -1173,7 +1217,6 @@ static int __init imxnd_probe(struct device_d *dev) goto escan; } - host->dev = dev; /* structures must be linked */ this = &host->nand; mtd = &host->mtd; @@ -1194,7 +1237,7 @@ static int __init imxnd_probe(struct device_d *dev) this->read_buf = imx_nand_read_buf; this->verify_buf = imx_nand_verify_buf; - if (pdata->hw_ecc) { + if (host->hw_ecc) { this->ecc.calculate = imx_nand_calculate_ecc; this->ecc.hwctl = imx_nand_enable_hwecc; if (nfc_is_v1()) @@ -1211,13 +1254,13 @@ static int __init imxnd_probe(struct device_d *dev) this->ecc.layout = oob_smallpage; /* NAND bus width determines access functions used by upper layer */ - if (pdata->width == 2) { + if (host->data_width == 2) { this->options |= NAND_BUSWIDTH_16; this->ecc.layout = &nandv1_hw_eccoob_smallpage; imx_nand_set_layout(0, 16); } - if (pdata->flash_bbt) { + if (host->flash_bbt) { this->bbt_td = &bbt_main_descr; this->bbt_md = &bbt_mirror_descr; /* update flash based bbt */ @@ -1233,10 +1276,10 @@ static int __init imxnd_probe(struct device_d *dev) /* Call preset again, with correct writesize this time */ host->preset(mtd); - imx_nand_set_layout(mtd->writesize, pdata->width == 2 ? 16 : 8); + imx_nand_set_layout(mtd->writesize, host->data_width == 2 ? 16 : 8); if (mtd->writesize >= 2048) { - if (!pdata->flash_bbt) + if (!host->flash_bbt) dev_warn(dev, "2k or 4k flash detected without flash_bbt. " "You will loose factory bad block markers!\n"); @@ -1261,7 +1304,7 @@ static int __init imxnd_probe(struct device_d *dev) goto escan; } - if (pdata->flash_bbt && this->bbt_td->pages[0] == -1 && this->bbt_md->pages[0] == -1) { + if (host->flash_bbt && this->bbt_td->pages[0] == -1 && this->bbt_md->pages[0] == -1) { dev_warn(dev, "no BBT found. create one using the imx_nand_bbm command\n"); } else { bbt_main_descr.options |= NAND_BBT_WRITE | NAND_BBT_CREATE; @@ -1281,9 +1324,26 @@ escan: } +static __maybe_unused struct of_device_id imx_nand_compatible[] = { + { + .compatible = "fsl,imx21-nand", + }, { + .compatible = "fsl,imx25-nand", + }, { + .compatible = "fsl,imx27-nand", + }, { + .compatible = "fsl,imx51-nand", + }, { + .compatible = "fsl,imx53-nand", + }, { + /* sentinel */ + } +}; + static struct driver_d imx_nand_driver = { .name = "imx_nand", .probe = imxnd_probe, + .of_compatible = DRV_OF_COMPAT(imx_nand_compatible), }; device_platform_driver(imx_nand_driver);