diff options
Diffstat (limited to 'drivers/mtd/nand/davinci_nand.c')
-rw-r--r-- | drivers/mtd/nand/davinci_nand.c | 93 |
1 files changed, 50 insertions, 43 deletions
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index b77a01efb483..a4989ec6292e 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -35,6 +35,7 @@ #include <linux/slab.h> #include <linux/of_device.h> #include <linux/of.h> +#include <linux/of_mtd.h> #include <linux/platform_data/mtd-davinci.h> #include <linux/platform_data/mtd-davinci-aemif.h> @@ -487,7 +488,7 @@ static int nand_davinci_dev_ready(struct mtd_info *mtd) * ten ECC bytes plus the manufacturer's bad block marker byte, and * and not overlapping the default BBT markers. */ -static struct nand_ecclayout hwecc4_small __initconst = { +static struct nand_ecclayout hwecc4_small = { .eccbytes = 10, .eccpos = { 0, 1, 2, 3, 4, /* offset 5 holds the badblock marker */ @@ -503,7 +504,7 @@ static struct nand_ecclayout hwecc4_small __initconst = { * storing ten ECC bytes plus the manufacturer's bad block marker byte, * and not overlapping the default BBT markers. */ -static struct nand_ecclayout hwecc4_2048 __initconst = { +static struct nand_ecclayout hwecc4_2048 = { .eccbytes = 40, .eccpos = { /* at the end of spare sector */ @@ -534,17 +535,19 @@ static struct davinci_nand_pdata struct davinci_nand_pdata *pdata; const char *mode; u32 prop; - int len; pdata = devm_kzalloc(&pdev->dev, sizeof(struct davinci_nand_pdata), GFP_KERNEL); pdev->dev.platform_data = pdata; if (!pdata) - return NULL; + return ERR_PTR(-ENOMEM); if (!of_property_read_u32(pdev->dev.of_node, "ti,davinci-chipselect", &prop)) pdev->id = prop; + else + return ERR_PTR(-EINVAL); + if (!of_property_read_u32(pdev->dev.of_node, "ti,davinci-mask-ale", &prop)) pdata->mask_ale = prop; @@ -555,6 +558,8 @@ static struct davinci_nand_pdata "ti,davinci-mask-chipsel", &prop)) pdata->mask_chipsel = prop; if (!of_property_read_string(pdev->dev.of_node, + "nand-ecc-mode", &mode) || + !of_property_read_string(pdev->dev.of_node, "ti,davinci-ecc-mode", &mode)) { if (!strncmp("none", mode, 4)) pdata->ecc_mode = NAND_ECC_NONE; @@ -566,12 +571,16 @@ static struct davinci_nand_pdata if (!of_property_read_u32(pdev->dev.of_node, "ti,davinci-ecc-bits", &prop)) pdata->ecc_bits = prop; - if (!of_property_read_u32(pdev->dev.of_node, + + prop = of_get_nand_bus_width(pdev->dev.of_node); + if (0 < prop || !of_property_read_u32(pdev->dev.of_node, "ti,davinci-nand-buswidth", &prop)) if (prop == 16) pdata->options |= NAND_BUSWIDTH_16; - if (of_find_property(pdev->dev.of_node, - "ti,davinci-nand-use-bbt", &len)) + if (of_property_read_bool(pdev->dev.of_node, + "nand-on-flash-bbt") || + of_property_read_bool(pdev->dev.of_node, + "ti,davinci-nand-use-bbt")) pdata->bbt_options = NAND_BBT_USE_FLASH; } @@ -585,7 +594,7 @@ static struct davinci_nand_pdata } #endif -static int __init nand_davinci_probe(struct platform_device *pdev) +static int nand_davinci_probe(struct platform_device *pdev) { struct davinci_nand_pdata *pdata; struct davinci_nand_info *info; @@ -598,6 +607,9 @@ static int __init nand_davinci_probe(struct platform_device *pdev) nand_ecc_modes_t ecc_mode; pdata = nand_davinci_get_pdata(pdev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + /* insist on board-specific configuration */ if (!pdata) return -ENODEV; @@ -607,11 +619,8 @@ static int __init nand_davinci_probe(struct platform_device *pdev) return -ENODEV; info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); - if (!info) { - dev_err(&pdev->dev, "unable to allocate memory\n"); - ret = -ENOMEM; - goto err_nomem; - } + if (!info) + return -ENOMEM; platform_set_drvdata(pdev, info); @@ -619,19 +628,23 @@ static int __init nand_davinci_probe(struct platform_device *pdev) res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!res1 || !res2) { dev_err(&pdev->dev, "resource missing\n"); - ret = -EINVAL; - goto err_nomem; + return -EINVAL; } vaddr = devm_ioremap_resource(&pdev->dev, res1); - if (IS_ERR(vaddr)) { - ret = PTR_ERR(vaddr); - goto err_ioremap; - } - base = devm_ioremap_resource(&pdev->dev, res2); - if (IS_ERR(base)) { - ret = PTR_ERR(base); - goto err_ioremap; + if (IS_ERR(vaddr)) + return PTR_ERR(vaddr); + + /* + * This registers range is used to setup NAND settings. In case with + * TI AEMIF driver, the same memory address range is requested already + * by AEMIF, so we cannot request it twice, just ioremap. + * The AEMIF and NAND drivers not use the same registers in this range. + */ + base = devm_ioremap(&pdev->dev, res2->start, resource_size(res2)); + if (!base) { + dev_err(&pdev->dev, "ioremap failed for resource %pR\n", res2); + return -EADDRNOTAVAIL; } info->dev = &pdev->dev; @@ -699,7 +712,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev) spin_unlock_irq(&davinci_nand_lock); if (ret == -EBUSY) - goto err_ecc; + return ret; info->chip.ecc.calculate = nand_davinci_calculate_4bit; info->chip.ecc.correct = nand_davinci_correct_4bit; @@ -715,8 +728,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev) info->chip.ecc.strength = pdata->ecc_bits; break; default: - ret = -EINVAL; - goto err_ecc; + return -EINVAL; } info->chip.ecc.mode = ecc_mode; @@ -724,7 +736,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev) if (IS_ERR(info->clk)) { ret = PTR_ERR(info->clk); dev_dbg(&pdev->dev, "unable to get AEMIF clock, err %d\n", ret); - goto err_clk; + return ret; } ret = clk_prepare_enable(info->clk); @@ -753,7 +765,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev) info->core_chipsel); if (ret < 0) { dev_dbg(&pdev->dev, "NAND timing values setup fail\n"); - goto err_timing; + goto err; } spin_lock_irq(&davinci_nand_lock); @@ -769,7 +781,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev) ret = nand_scan_ident(&info->mtd, pdata->mask_chipsel ? 2 : 1, NULL); if (ret < 0) { dev_dbg(&pdev->dev, "no NAND chip(s) found\n"); - goto err_scan; + goto err; } /* Update ECC layout if needed ... for 1-bit HW ECC, the default @@ -783,7 +795,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev) if (!chunks || info->mtd.oobsize < 16) { dev_dbg(&pdev->dev, "too small\n"); ret = -EINVAL; - goto err_scan; + goto err; } /* For small page chips, preserve the manufacturer's @@ -814,7 +826,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "no 4-bit ECC support yet " "for 4KiB-page NAND\n"); ret = -EIO; - goto err_scan; + goto err; syndrome_done: info->chip.ecc.layout = &info->ecclayout; @@ -822,7 +834,7 @@ syndrome_done: ret = nand_scan_tail(&info->mtd); if (ret < 0) - goto err_scan; + goto err; if (pdata->parts) ret = mtd_device_parse_register(&info->mtd, NULL, NULL, @@ -835,7 +847,7 @@ syndrome_done: NULL, 0); } if (ret < 0) - goto err_scan; + goto err; val = davinci_nand_readl(info, NRCSR_OFFSET); dev_info(&pdev->dev, "controller rev. %d.%d\n", @@ -843,8 +855,7 @@ syndrome_done: return 0; -err_scan: -err_timing: +err: clk_disable_unprepare(info->clk); err_clk_enable: @@ -852,15 +863,10 @@ err_clk_enable: if (ecc_mode == NAND_ECC_HW_SYNDROME) ecc4_busy = false; spin_unlock_irq(&davinci_nand_lock); - -err_ecc: -err_clk: -err_ioremap: -err_nomem: return ret; } -static int __exit nand_davinci_remove(struct platform_device *pdev) +static int nand_davinci_remove(struct platform_device *pdev) { struct davinci_nand_info *info = platform_get_drvdata(pdev); @@ -877,7 +883,8 @@ static int __exit nand_davinci_remove(struct platform_device *pdev) } static struct platform_driver nand_davinci_driver = { - .remove = __exit_p(nand_davinci_remove), + .probe = nand_davinci_probe, + .remove = nand_davinci_remove, .driver = { .name = "davinci_nand", .owner = THIS_MODULE, @@ -886,7 +893,7 @@ static struct platform_driver nand_davinci_driver = { }; MODULE_ALIAS("platform:davinci_nand"); -module_platform_driver_probe(nand_davinci_driver, nand_davinci_probe); +module_platform_driver(nand_davinci_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Texas Instruments"); |