mtd: nand_imx: Add devicetree probe support
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
aa9e85c555
commit
4a98bf1a0b
|
@ -27,6 +27,7 @@
|
||||||
#include <mach/generic.h>
|
#include <mach/generic.h>
|
||||||
#include <mach/imx-nand.h>
|
#include <mach/imx-nand.h>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
#include <of_mtd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#define NFC_V3_FLASH_CMD (host->regs_axi + 0x00)
|
#define NFC_V3_FLASH_CMD (host->regs_axi + 0x00)
|
||||||
|
@ -100,6 +101,10 @@ struct imx_nand_host {
|
||||||
int spare_len;
|
int spare_len;
|
||||||
int eccsize;
|
int eccsize;
|
||||||
|
|
||||||
|
int hw_ecc;
|
||||||
|
int data_width;
|
||||||
|
int flash_bbt;
|
||||||
|
|
||||||
void (*preset)(struct mtd_info *);
|
void (*preset)(struct mtd_info *);
|
||||||
void (*send_cmd)(struct imx_nand_host *, uint16_t);
|
void (*send_cmd)(struct imx_nand_host *, uint16_t);
|
||||||
void (*send_addr)(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,
|
.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.
|
* 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 nand_chip *this;
|
||||||
struct mtd_info *mtd;
|
struct mtd_info *mtd;
|
||||||
struct imx_nand_platform_data *pdata = dev->platform_data;
|
|
||||||
struct imx_nand_host *host;
|
struct imx_nand_host *host;
|
||||||
struct nand_ecclayout *oob_smallpage, *oob_largepage, *oob_4kpage;
|
struct nand_ecclayout *oob_smallpage, *oob_largepage, *oob_4kpage;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
@ -1112,6 +1141,21 @@ static int __init imxnd_probe(struct device_d *dev)
|
||||||
if (!host)
|
if (!host)
|
||||||
return -ENOMEM;
|
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);
|
host->data_buf = (uint8_t *)(host + 1);
|
||||||
|
|
||||||
if (nfc_is_v1() || nfc_is_v21()) {
|
if (nfc_is_v1() || nfc_is_v21()) {
|
||||||
|
@ -1173,7 +1217,6 @@ static int __init imxnd_probe(struct device_d *dev)
|
||||||
goto escan;
|
goto escan;
|
||||||
}
|
}
|
||||||
|
|
||||||
host->dev = dev;
|
|
||||||
/* structures must be linked */
|
/* structures must be linked */
|
||||||
this = &host->nand;
|
this = &host->nand;
|
||||||
mtd = &host->mtd;
|
mtd = &host->mtd;
|
||||||
|
@ -1194,7 +1237,7 @@ static int __init imxnd_probe(struct device_d *dev)
|
||||||
this->read_buf = imx_nand_read_buf;
|
this->read_buf = imx_nand_read_buf;
|
||||||
this->verify_buf = imx_nand_verify_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.calculate = imx_nand_calculate_ecc;
|
||||||
this->ecc.hwctl = imx_nand_enable_hwecc;
|
this->ecc.hwctl = imx_nand_enable_hwecc;
|
||||||
if (nfc_is_v1())
|
if (nfc_is_v1())
|
||||||
|
@ -1211,13 +1254,13 @@ static int __init imxnd_probe(struct device_d *dev)
|
||||||
this->ecc.layout = oob_smallpage;
|
this->ecc.layout = oob_smallpage;
|
||||||
|
|
||||||
/* NAND bus width determines access functions used by upper layer */
|
/* 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->options |= NAND_BUSWIDTH_16;
|
||||||
this->ecc.layout = &nandv1_hw_eccoob_smallpage;
|
this->ecc.layout = &nandv1_hw_eccoob_smallpage;
|
||||||
imx_nand_set_layout(0, 16);
|
imx_nand_set_layout(0, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pdata->flash_bbt) {
|
if (host->flash_bbt) {
|
||||||
this->bbt_td = &bbt_main_descr;
|
this->bbt_td = &bbt_main_descr;
|
||||||
this->bbt_md = &bbt_mirror_descr;
|
this->bbt_md = &bbt_mirror_descr;
|
||||||
/* update flash based bbt */
|
/* 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 */
|
/* Call preset again, with correct writesize this time */
|
||||||
host->preset(mtd);
|
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 (mtd->writesize >= 2048) {
|
||||||
if (!pdata->flash_bbt)
|
if (!host->flash_bbt)
|
||||||
dev_warn(dev, "2k or 4k flash detected without flash_bbt. "
|
dev_warn(dev, "2k or 4k flash detected without flash_bbt. "
|
||||||
"You will loose factory bad block markers!\n");
|
"You will loose factory bad block markers!\n");
|
||||||
|
|
||||||
|
@ -1261,7 +1304,7 @@ static int __init imxnd_probe(struct device_d *dev)
|
||||||
goto escan;
|
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");
|
dev_warn(dev, "no BBT found. create one using the imx_nand_bbm command\n");
|
||||||
} else {
|
} else {
|
||||||
bbt_main_descr.options |= NAND_BBT_WRITE | NAND_BBT_CREATE;
|
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 = {
|
static struct driver_d imx_nand_driver = {
|
||||||
.name = "imx_nand",
|
.name = "imx_nand",
|
||||||
.probe = imxnd_probe,
|
.probe = imxnd_probe,
|
||||||
|
.of_compatible = DRV_OF_COMPAT(imx_nand_compatible),
|
||||||
};
|
};
|
||||||
device_platform_driver(imx_nand_driver);
|
device_platform_driver(imx_nand_driver);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue