aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/mxc_nand.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/mxc_nand.c')
-rw-r--r--drivers/mtd/nand/mxc_nand.c168
1 files changed, 81 insertions, 87 deletions
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 5683604967d7..72e31d86030d 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -43,8 +43,8 @@
43 43
44#define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35()) 44#define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35())
45#define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21()) 45#define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
46#define nfc_is_v3_2() (cpu_is_mx51() || cpu_is_mx53()) 46#define nfc_is_v3_2a() cpu_is_mx51()
47#define nfc_is_v3() nfc_is_v3_2() 47#define nfc_is_v3_2b() cpu_is_mx53()
48 48
49/* Addresses for NFC registers */ 49/* Addresses for NFC registers */
50#define NFC_V1_V2_BUF_SIZE (host->regs + 0x00) 50#define NFC_V1_V2_BUF_SIZE (host->regs + 0x00)
@@ -122,7 +122,7 @@
122#define NFC_V3_CONFIG2_2CMD_PHASES (1 << 4) 122#define NFC_V3_CONFIG2_2CMD_PHASES (1 << 4)
123#define NFC_V3_CONFIG2_NUM_ADDR_PHASE0 (1 << 5) 123#define NFC_V3_CONFIG2_NUM_ADDR_PHASE0 (1 << 5)
124#define NFC_V3_CONFIG2_ECC_MODE_8 (1 << 6) 124#define NFC_V3_CONFIG2_ECC_MODE_8 (1 << 6)
125#define NFC_V3_CONFIG2_PPB(x) (((x) & 0x3) << 7) 125#define NFC_V3_CONFIG2_PPB(x, shift) (((x) & 0x3) << shift)
126#define NFC_V3_CONFIG2_NUM_ADDR_PHASE1(x) (((x) & 0x3) << 12) 126#define NFC_V3_CONFIG2_NUM_ADDR_PHASE1(x) (((x) & 0x3) << 12)
127#define NFC_V3_CONFIG2_INT_MSK (1 << 15) 127#define NFC_V3_CONFIG2_INT_MSK (1 << 15)
128#define NFC_V3_CONFIG2_ST_CMD(x) (((x) & 0xff) << 24) 128#define NFC_V3_CONFIG2_ST_CMD(x) (((x) & 0xff) << 24)
@@ -174,6 +174,7 @@ struct mxc_nand_devtype_data {
174 int spare_len; 174 int spare_len;
175 int eccbytes; 175 int eccbytes;
176 int eccsize; 176 int eccsize;
177 int ppb_shift;
177}; 178};
178 179
179struct mxc_nand_host { 180struct mxc_nand_host {
@@ -745,14 +746,6 @@ static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
745 host->buf_start += n; 746 host->buf_start += n;
746} 747}
747 748
748/* Used by the upper layer to verify the data in NAND Flash
749 * with the data in the buf. */
750static int mxc_nand_verify_buf(struct mtd_info *mtd,
751 const u_char *buf, int len)
752{
753 return -EFAULT;
754}
755
756/* This function is used by upper layer for select and 749/* This function is used by upper layer for select and
757 * deselect of the NAND chip */ 750 * deselect of the NAND chip */
758static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip) 751static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
@@ -784,7 +777,7 @@ static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
784 if (chip == -1) { 777 if (chip == -1) {
785 /* Disable the NFC clock */ 778 /* Disable the NFC clock */
786 if (host->clk_act) { 779 if (host->clk_act) {
787 clk_disable(host->clk); 780 clk_disable_unprepare(host->clk);
788 host->clk_act = 0; 781 host->clk_act = 0;
789 } 782 }
790 return; 783 return;
@@ -792,7 +785,7 @@ static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
792 785
793 if (!host->clk_act) { 786 if (!host->clk_act) {
794 /* Enable the NFC clock */ 787 /* Enable the NFC clock */
795 clk_enable(host->clk); 788 clk_prepare_enable(host->clk);
796 host->clk_act = 1; 789 host->clk_act = 1;
797 } 790 }
798 791
@@ -1021,7 +1014,9 @@ static void preset_v3(struct mtd_info *mtd)
1021 } 1014 }
1022 1015
1023 if (mtd->writesize) { 1016 if (mtd->writesize) {
1024 config2 |= NFC_V3_CONFIG2_PPB(ffs(mtd->erasesize / mtd->writesize) - 6); 1017 config2 |= NFC_V3_CONFIG2_PPB(
1018 ffs(mtd->erasesize / mtd->writesize) - 6,
1019 host->devtype_data->ppb_shift);
1025 host->eccsize = get_eccsize(mtd); 1020 host->eccsize = get_eccsize(mtd);
1026 if (host->eccsize == 8) 1021 if (host->eccsize == 8)
1027 config2 |= NFC_V3_CONFIG2_ECC_MODE_8; 1022 config2 |= NFC_V3_CONFIG2_ECC_MODE_8;
@@ -1234,7 +1229,7 @@ static const struct mxc_nand_devtype_data imx25_nand_devtype_data = {
1234 .eccsize = 0, 1229 .eccsize = 0,
1235}; 1230};
1236 1231
1237/* v3: i.MX51, i.MX53 */ 1232/* v3.2a: i.MX51 */
1238static const struct mxc_nand_devtype_data imx51_nand_devtype_data = { 1233static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
1239 .preset = preset_v3, 1234 .preset = preset_v3,
1240 .send_cmd = send_cmd_v3, 1235 .send_cmd = send_cmd_v3,
@@ -1258,6 +1253,34 @@ static const struct mxc_nand_devtype_data imx51_nand_devtype_data = {
1258 .spare_len = 64, 1253 .spare_len = 64,
1259 .eccbytes = 0, 1254 .eccbytes = 0,
1260 .eccsize = 0, 1255 .eccsize = 0,
1256 .ppb_shift = 7,
1257};
1258
1259/* v3.2b: i.MX53 */
1260static const struct mxc_nand_devtype_data imx53_nand_devtype_data = {
1261 .preset = preset_v3,
1262 .send_cmd = send_cmd_v3,
1263 .send_addr = send_addr_v3,
1264 .send_page = send_page_v3,
1265 .send_read_id = send_read_id_v3,
1266 .get_dev_status = get_dev_status_v3,
1267 .check_int = check_int_v3,
1268 .irq_control = irq_control_v3,
1269 .get_ecc_status = get_ecc_status_v3,
1270 .ecclayout_512 = &nandv2_hw_eccoob_smallpage,
1271 .ecclayout_2k = &nandv2_hw_eccoob_largepage,
1272 .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */
1273 .select_chip = mxc_nand_select_chip_v1_v3,
1274 .correct_data = mxc_nand_correct_data_v2_v3,
1275 .irqpending_quirk = 0,
1276 .needs_ip = 1,
1277 .regs_offset = 0,
1278 .spare0_offset = 0x1000,
1279 .axi_offset = 0x1e00,
1280 .spare_len = 64,
1281 .eccbytes = 0,
1282 .eccsize = 0,
1283 .ppb_shift = 8,
1261}; 1284};
1262 1285
1263#ifdef CONFIG_OF_MTD 1286#ifdef CONFIG_OF_MTD
@@ -1274,6 +1297,9 @@ static const struct of_device_id mxcnd_dt_ids[] = {
1274 }, { 1297 }, {
1275 .compatible = "fsl,imx51-nand", 1298 .compatible = "fsl,imx51-nand",
1276 .data = &imx51_nand_devtype_data, 1299 .data = &imx51_nand_devtype_data,
1300 }, {
1301 .compatible = "fsl,imx53-nand",
1302 .data = &imx53_nand_devtype_data,
1277 }, 1303 },
1278 { /* sentinel */ } 1304 { /* sentinel */ }
1279}; 1305};
@@ -1327,15 +1353,17 @@ static int __init mxcnd_probe_pdata(struct mxc_nand_host *host)
1327 host->devtype_data = &imx27_nand_devtype_data; 1353 host->devtype_data = &imx27_nand_devtype_data;
1328 } else if (nfc_is_v21()) { 1354 } else if (nfc_is_v21()) {
1329 host->devtype_data = &imx25_nand_devtype_data; 1355 host->devtype_data = &imx25_nand_devtype_data;
1330 } else if (nfc_is_v3_2()) { 1356 } else if (nfc_is_v3_2a()) {
1331 host->devtype_data = &imx51_nand_devtype_data; 1357 host->devtype_data = &imx51_nand_devtype_data;
1358 } else if (nfc_is_v3_2b()) {
1359 host->devtype_data = &imx53_nand_devtype_data;
1332 } else 1360 } else
1333 BUG(); 1361 BUG();
1334 1362
1335 return 0; 1363 return 0;
1336} 1364}
1337 1365
1338static int __init mxcnd_probe(struct platform_device *pdev) 1366static int __devinit mxcnd_probe(struct platform_device *pdev)
1339{ 1367{
1340 struct nand_chip *this; 1368 struct nand_chip *this;
1341 struct mtd_info *mtd; 1369 struct mtd_info *mtd;
@@ -1344,8 +1372,8 @@ static int __init mxcnd_probe(struct platform_device *pdev)
1344 int err = 0; 1372 int err = 0;
1345 1373
1346 /* Allocate memory for MTD device structure and private data */ 1374 /* Allocate memory for MTD device structure and private data */
1347 host = kzalloc(sizeof(struct mxc_nand_host) + NAND_MAX_PAGESIZE + 1375 host = devm_kzalloc(&pdev->dev, sizeof(struct mxc_nand_host) +
1348 NAND_MAX_OOBSIZE, GFP_KERNEL); 1376 NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE, GFP_KERNEL);
1349 if (!host) 1377 if (!host)
1350 return -ENOMEM; 1378 return -ENOMEM;
1351 1379
@@ -1370,36 +1398,38 @@ static int __init mxcnd_probe(struct platform_device *pdev)
1370 this->read_word = mxc_nand_read_word; 1398 this->read_word = mxc_nand_read_word;
1371 this->write_buf = mxc_nand_write_buf; 1399 this->write_buf = mxc_nand_write_buf;
1372 this->read_buf = mxc_nand_read_buf; 1400 this->read_buf = mxc_nand_read_buf;
1373 this->verify_buf = mxc_nand_verify_buf;
1374 1401
1375 host->clk = clk_get(&pdev->dev, "nfc"); 1402 host->clk = devm_clk_get(&pdev->dev, NULL);
1376 if (IS_ERR(host->clk)) { 1403 if (IS_ERR(host->clk))
1377 err = PTR_ERR(host->clk); 1404 return PTR_ERR(host->clk);
1378 goto eclk;
1379 }
1380 1405
1381 clk_prepare_enable(host->clk); 1406 err = mxcnd_probe_dt(host);
1382 host->clk_act = 1; 1407 if (err > 0)
1408 err = mxcnd_probe_pdata(host);
1409 if (err < 0)
1410 return err;
1383 1411
1384 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1412 if (host->devtype_data->needs_ip) {
1385 if (!res) { 1413 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1386 err = -ENODEV; 1414 if (!res)
1387 goto eres; 1415 return -ENODEV;
1388 } 1416 host->regs_ip = devm_request_and_ioremap(&pdev->dev, res);
1417 if (!host->regs_ip)
1418 return -ENOMEM;
1389 1419
1390 host->base = ioremap(res->start, resource_size(res)); 1420 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1391 if (!host->base) { 1421 } else {
1392 err = -ENOMEM; 1422 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1393 goto eres;
1394 } 1423 }
1395 1424
1396 host->main_area0 = host->base; 1425 if (!res)
1426 return -ENODEV;
1397 1427
1398 err = mxcnd_probe_dt(host); 1428 host->base = devm_request_and_ioremap(&pdev->dev, res);
1399 if (err > 0) 1429 if (!host->base)
1400 err = mxcnd_probe_pdata(host); 1430 return -ENOMEM;
1401 if (err < 0) 1431
1402 goto eirq; 1432 host->main_area0 = host->base;
1403 1433
1404 if (host->devtype_data->regs_offset) 1434 if (host->devtype_data->regs_offset)
1405 host->regs = host->base + host->devtype_data->regs_offset; 1435 host->regs = host->base + host->devtype_data->regs_offset;
@@ -1414,19 +1444,6 @@ static int __init mxcnd_probe(struct platform_device *pdev)
1414 this->ecc.size = 512; 1444 this->ecc.size = 512;
1415 this->ecc.layout = host->devtype_data->ecclayout_512; 1445 this->ecc.layout = host->devtype_data->ecclayout_512;
1416 1446
1417 if (host->devtype_data->needs_ip) {
1418 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1419 if (!res) {
1420 err = -ENODEV;
1421 goto eirq;
1422 }
1423 host->regs_ip = ioremap(res->start, resource_size(res));
1424 if (!host->regs_ip) {
1425 err = -ENOMEM;
1426 goto eirq;
1427 }
1428 }
1429
1430 if (host->pdata.hw_ecc) { 1447 if (host->pdata.hw_ecc) {
1431 this->ecc.calculate = mxc_nand_calculate_ecc; 1448 this->ecc.calculate = mxc_nand_calculate_ecc;
1432 this->ecc.hwctl = mxc_nand_enable_hwecc; 1449 this->ecc.hwctl = mxc_nand_enable_hwecc;
@@ -1458,9 +1475,13 @@ static int __init mxcnd_probe(struct platform_device *pdev)
1458 */ 1475 */
1459 host->devtype_data->irq_control(host, 0); 1476 host->devtype_data->irq_control(host, 0);
1460 1477
1461 err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host); 1478 err = devm_request_irq(&pdev->dev, host->irq, mxc_nfc_irq,
1479 IRQF_DISABLED, DRIVER_NAME, host);
1462 if (err) 1480 if (err)
1463 goto eirq; 1481 return err;
1482
1483 clk_prepare_enable(host->clk);
1484 host->clk_act = 1;
1464 1485
1465 /* 1486 /*
1466 * Now that we "own" the interrupt make sure the interrupt mask bit is 1487 * Now that we "own" the interrupt make sure the interrupt mask bit is
@@ -1512,15 +1533,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
1512 return 0; 1533 return 0;
1513 1534
1514escan: 1535escan:
1515 free_irq(host->irq, host); 1536 clk_disable_unprepare(host->clk);
1516eirq:
1517 if (host->regs_ip)
1518 iounmap(host->regs_ip);
1519 iounmap(host->base);
1520eres:
1521 clk_put(host->clk);
1522eclk:
1523 kfree(host);
1524 1537
1525 return err; 1538 return err;
1526} 1539}
@@ -1529,16 +1542,9 @@ static int __devexit mxcnd_remove(struct platform_device *pdev)
1529{ 1542{
1530 struct mxc_nand_host *host = platform_get_drvdata(pdev); 1543 struct mxc_nand_host *host = platform_get_drvdata(pdev);
1531 1544
1532 clk_put(host->clk);
1533
1534 platform_set_drvdata(pdev, NULL); 1545 platform_set_drvdata(pdev, NULL);
1535 1546
1536 nand_release(&host->mtd); 1547 nand_release(&host->mtd);
1537 free_irq(host->irq, host);
1538 if (host->regs_ip)
1539 iounmap(host->regs_ip);
1540 iounmap(host->base);
1541 kfree(host);
1542 1548
1543 return 0; 1549 return 0;
1544} 1550}
@@ -1549,22 +1555,10 @@ static struct platform_driver mxcnd_driver = {
1549 .owner = THIS_MODULE, 1555 .owner = THIS_MODULE,
1550 .of_match_table = of_match_ptr(mxcnd_dt_ids), 1556 .of_match_table = of_match_ptr(mxcnd_dt_ids),
1551 }, 1557 },
1558 .probe = mxcnd_probe,
1552 .remove = __devexit_p(mxcnd_remove), 1559 .remove = __devexit_p(mxcnd_remove),
1553}; 1560};
1554 1561module_platform_driver(mxcnd_driver);
1555static int __init mxc_nd_init(void)
1556{
1557 return platform_driver_probe(&mxcnd_driver, mxcnd_probe);
1558}
1559
1560static void __exit mxc_nd_cleanup(void)
1561{
1562 /* Unregister the device structure */
1563 platform_driver_unregister(&mxcnd_driver);
1564}
1565
1566module_init(mxc_nd_init);
1567module_exit(mxc_nd_cleanup);
1568 1562
1569MODULE_AUTHOR("Freescale Semiconductor, Inc."); 1563MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1570MODULE_DESCRIPTION("MXC NAND MTD driver"); 1564MODULE_DESCRIPTION("MXC NAND MTD driver");