aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/omap2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/omap2.c')
-rw-r--r--drivers/mtd/nand/omap2.c134
1 files changed, 114 insertions, 20 deletions
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 7e4e263c7d9c..35b8f3359c17 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -24,6 +24,7 @@
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/of.h> 25#include <linux/of.h>
26#include <linux/of_device.h> 26#include <linux/of_device.h>
27#include <linux/of_mtd.h>
27 28
28#include <linux/mtd/nand_bch.h> 29#include <linux/mtd/nand_bch.h>
29#include <linux/platform_data/elm.h> 30#include <linux/platform_data/elm.h>
@@ -176,11 +177,11 @@ struct omap_nand_info {
176 /* Interface to GPMC */ 177 /* Interface to GPMC */
177 struct gpmc_nand_regs reg; 178 struct gpmc_nand_regs reg;
178 struct gpmc_nand_ops *ops; 179 struct gpmc_nand_ops *ops;
180 bool flash_bbt;
179 /* generated at runtime depending on ECC algorithm and layout selected */ 181 /* generated at runtime depending on ECC algorithm and layout selected */
180 struct nand_ecclayout oobinfo; 182 struct nand_ecclayout oobinfo;
181 /* fields specific for BCHx_HW ECC scheme */ 183 /* fields specific for BCHx_HW ECC scheme */
182 struct device *elm_dev; 184 struct device *elm_dev;
183 struct device_node *of_node;
184}; 185};
185 186
186static inline struct omap_nand_info *mtd_to_omap(struct mtd_info *mtd) 187static inline struct omap_nand_info *mtd_to_omap(struct mtd_info *mtd)
@@ -1643,10 +1644,86 @@ static bool omap2_nand_ecc_check(struct omap_nand_info *info,
1643 return true; 1644 return true;
1644} 1645}
1645 1646
1647static const char * const nand_xfer_types[] = {
1648 [NAND_OMAP_PREFETCH_POLLED] = "prefetch-polled",
1649 [NAND_OMAP_POLLED] = "polled",
1650 [NAND_OMAP_PREFETCH_DMA] = "prefetch-dma",
1651 [NAND_OMAP_PREFETCH_IRQ] = "prefetch-irq",
1652};
1653
1654static int omap_get_dt_info(struct device *dev, struct omap_nand_info *info)
1655{
1656 struct device_node *child = dev->of_node;
1657 int i;
1658 const char *s;
1659 u32 cs;
1660
1661 if (of_property_read_u32(child, "reg", &cs) < 0) {
1662 dev_err(dev, "reg not found in DT\n");
1663 return -EINVAL;
1664 }
1665
1666 info->gpmc_cs = cs;
1667
1668 /* detect availability of ELM module. Won't be present pre-OMAP4 */
1669 info->elm_of_node = of_parse_phandle(child, "ti,elm-id", 0);
1670 if (!info->elm_of_node)
1671 dev_dbg(dev, "ti,elm-id not in DT\n");
1672
1673 /* select ecc-scheme for NAND */
1674 if (of_property_read_string(child, "ti,nand-ecc-opt", &s)) {
1675 dev_err(dev, "ti,nand-ecc-opt not found\n");
1676 return -EINVAL;
1677 }
1678
1679 if (!strcmp(s, "sw")) {
1680 info->ecc_opt = OMAP_ECC_HAM1_CODE_SW;
1681 } else if (!strcmp(s, "ham1") ||
1682 !strcmp(s, "hw") || !strcmp(s, "hw-romcode")) {
1683 info->ecc_opt = OMAP_ECC_HAM1_CODE_HW;
1684 } else if (!strcmp(s, "bch4")) {
1685 if (info->elm_of_node)
1686 info->ecc_opt = OMAP_ECC_BCH4_CODE_HW;
1687 else
1688 info->ecc_opt = OMAP_ECC_BCH4_CODE_HW_DETECTION_SW;
1689 } else if (!strcmp(s, "bch8")) {
1690 if (info->elm_of_node)
1691 info->ecc_opt = OMAP_ECC_BCH8_CODE_HW;
1692 else
1693 info->ecc_opt = OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
1694 } else if (!strcmp(s, "bch16")) {
1695 info->ecc_opt = OMAP_ECC_BCH16_CODE_HW;
1696 } else {
1697 dev_err(dev, "unrecognized value for ti,nand-ecc-opt\n");
1698 return -EINVAL;
1699 }
1700
1701 /* select data transfer mode */
1702 if (!of_property_read_string(child, "ti,nand-xfer-type", &s)) {
1703 for (i = 0; i < ARRAY_SIZE(nand_xfer_types); i++) {
1704 if (!strcasecmp(s, nand_xfer_types[i])) {
1705 info->xfer_type = i;
1706 goto next;
1707 }
1708 }
1709
1710 dev_err(dev, "unrecognized value for ti,nand-xfer-type\n");
1711 return -EINVAL;
1712 }
1713
1714next:
1715 of_get_nand_on_flash_bbt(child);
1716
1717 if (of_get_nand_bus_width(child) == 16)
1718 info->devsize = NAND_BUSWIDTH_16;
1719
1720 return 0;
1721}
1722
1646static int omap_nand_probe(struct platform_device *pdev) 1723static int omap_nand_probe(struct platform_device *pdev)
1647{ 1724{
1648 struct omap_nand_info *info; 1725 struct omap_nand_info *info;
1649 struct omap_nand_platform_data *pdata; 1726 struct omap_nand_platform_data *pdata = NULL;
1650 struct mtd_info *mtd; 1727 struct mtd_info *mtd;
1651 struct nand_chip *nand_chip; 1728 struct nand_chip *nand_chip;
1652 struct nand_ecclayout *ecclayout; 1729 struct nand_ecclayout *ecclayout;
@@ -1656,39 +1733,47 @@ static int omap_nand_probe(struct platform_device *pdev)
1656 unsigned sig; 1733 unsigned sig;
1657 unsigned oob_index; 1734 unsigned oob_index;
1658 struct resource *res; 1735 struct resource *res;
1659 1736 struct device *dev = &pdev->dev;
1660 pdata = dev_get_platdata(&pdev->dev);
1661 if (pdata == NULL) {
1662 dev_err(&pdev->dev, "platform data missing\n");
1663 return -ENODEV;
1664 }
1665 1737
1666 info = devm_kzalloc(&pdev->dev, sizeof(struct omap_nand_info), 1738 info = devm_kzalloc(&pdev->dev, sizeof(struct omap_nand_info),
1667 GFP_KERNEL); 1739 GFP_KERNEL);
1668 if (!info) 1740 if (!info)
1669 return -ENOMEM; 1741 return -ENOMEM;
1670 1742
1671 platform_set_drvdata(pdev, info); 1743 info->pdev = pdev;
1672 1744
1745 if (dev->of_node) {
1746 if (omap_get_dt_info(dev, info))
1747 return -EINVAL;
1748 } else {
1749 pdata = dev_get_platdata(&pdev->dev);
1750 if (!pdata) {
1751 dev_err(&pdev->dev, "platform data missing\n");
1752 return -EINVAL;
1753 }
1754
1755 info->gpmc_cs = pdata->cs;
1756 info->reg = pdata->reg;
1757 info->ecc_opt = pdata->ecc_opt;
1758 info->dev_ready = pdata->dev_ready;
1759 info->xfer_type = pdata->xfer_type;
1760 info->devsize = pdata->devsize;
1761 info->elm_of_node = pdata->elm_of_node;
1762 info->flash_bbt = pdata->flash_bbt;
1763 }
1764
1765 platform_set_drvdata(pdev, info);
1673 info->ops = gpmc_omap_get_nand_ops(&info->reg, info->gpmc_cs); 1766 info->ops = gpmc_omap_get_nand_ops(&info->reg, info->gpmc_cs);
1674 if (!info->ops) { 1767 if (!info->ops) {
1675 dev_err(&pdev->dev, "Failed to get GPMC->NAND interface\n"); 1768 dev_err(&pdev->dev, "Failed to get GPMC->NAND interface\n");
1676 return -ENODEV; 1769 return -ENODEV;
1677 } 1770 }
1678 info->pdev = pdev;
1679 info->gpmc_cs = pdata->cs;
1680 info->of_node = pdata->of_node;
1681 info->ecc_opt = pdata->ecc_opt;
1682 info->dev_ready = pdata->dev_ready;
1683 info->xfer_type = pdata->xfer_type;
1684 info->devsize = pdata->devsize;
1685 info->elm_of_node = pdata->elm_of_node;
1686 1771
1687 nand_chip = &info->nand; 1772 nand_chip = &info->nand;
1688 mtd = nand_to_mtd(nand_chip); 1773 mtd = nand_to_mtd(nand_chip);
1689 mtd->dev.parent = &pdev->dev; 1774 mtd->dev.parent = &pdev->dev;
1690 nand_chip->ecc.priv = NULL; 1775 nand_chip->ecc.priv = NULL;
1691 nand_set_flash_node(nand_chip, pdata->of_node); 1776 nand_set_flash_node(nand_chip, dev->of_node);
1692 1777
1693 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1778 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1694 nand_chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res); 1779 nand_chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res);
@@ -1717,7 +1802,7 @@ static int omap_nand_probe(struct platform_device *pdev)
1717 nand_chip->chip_delay = 50; 1802 nand_chip->chip_delay = 50;
1718 } 1803 }
1719 1804
1720 if (pdata->flash_bbt) 1805 if (info->flash_bbt)
1721 nand_chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; 1806 nand_chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB;
1722 else 1807 else
1723 nand_chip->options |= NAND_SKIP_BBTSCAN; 1808 nand_chip->options |= NAND_SKIP_BBTSCAN;
@@ -2035,7 +2120,10 @@ scan_tail:
2035 goto return_error; 2120 goto return_error;
2036 } 2121 }
2037 2122
2038 mtd_device_register(mtd, pdata->parts, pdata->nr_parts); 2123 if (dev->of_node)
2124 mtd_device_register(mtd, NULL, 0);
2125 else
2126 mtd_device_register(mtd, pdata->parts, pdata->nr_parts);
2039 2127
2040 platform_set_drvdata(pdev, mtd); 2128 platform_set_drvdata(pdev, mtd);
2041 2129
@@ -2066,11 +2154,17 @@ static int omap_nand_remove(struct platform_device *pdev)
2066 return 0; 2154 return 0;
2067} 2155}
2068 2156
2157static const struct of_device_id omap_nand_ids[] = {
2158 { .compatible = "ti,omap2-nand", },
2159 {},
2160};
2161
2069static struct platform_driver omap_nand_driver = { 2162static struct platform_driver omap_nand_driver = {
2070 .probe = omap_nand_probe, 2163 .probe = omap_nand_probe,
2071 .remove = omap_nand_remove, 2164 .remove = omap_nand_remove,
2072 .driver = { 2165 .driver = {
2073 .name = DRIVER_NAME, 2166 .name = DRIVER_NAME,
2167 .of_match_table = of_match_ptr(omap_nand_ids),
2074 }, 2168 },
2075}; 2169};
2076 2170