Skip to content

Commit c9711ec

Browse files
author
Roger Quadros
committed
mtd: nand: omap: Clean up device tree support
Move NAND specific device tree parsing to NAND driver. The NAND controller node must have a compatible id, register space resource and interrupt resource. Signed-off-by: Roger Quadros <[email protected]> Acked-by: Brian Norris <[email protected]> Acked-by: Tony Lindgren <[email protected]>
1 parent 01b95fc commit c9711ec

File tree

4 files changed

+153
-132
lines changed

4 files changed

+153
-132
lines changed

arch/arm/mach-omap2/gpmc-nand.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,7 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
9797
gpmc_nand_res[2].start = gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT);
9898

9999
memset(&s, 0, sizeof(struct gpmc_settings));
100-
if (gpmc_nand_data->of_node)
101-
gpmc_read_settings_dt(gpmc_nand_data->of_node, &s);
102-
else
103-
gpmc_set_legacy(gpmc_nand_data, &s);
100+
gpmc_set_legacy(gpmc_nand_data, &s);
104101

105102
s.device_nand = true;
106103

drivers/memory/omap-gpmc.c

Lines changed: 37 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
#include <linux/of_device.h>
3131
#include <linux/of_platform.h>
3232
#include <linux/omap-gpmc.h>
33-
#include <linux/mtd/nand.h>
3433
#include <linux/pm_runtime.h>
3534

3635
#include <linux/platform_data/mtd-nand-omap2.h>
@@ -1852,105 +1851,6 @@ static void __maybe_unused gpmc_read_timings_dt(struct device_node *np,
18521851
of_property_read_bool(np, "gpmc,time-para-granularity");
18531852
}
18541853

1855-
#if IS_ENABLED(CONFIG_MTD_NAND)
1856-
1857-
static const char * const nand_xfer_types[] = {
1858-
[NAND_OMAP_PREFETCH_POLLED] = "prefetch-polled",
1859-
[NAND_OMAP_POLLED] = "polled",
1860-
[NAND_OMAP_PREFETCH_DMA] = "prefetch-dma",
1861-
[NAND_OMAP_PREFETCH_IRQ] = "prefetch-irq",
1862-
};
1863-
1864-
static int gpmc_probe_nand_child(struct platform_device *pdev,
1865-
struct device_node *child)
1866-
{
1867-
u32 val;
1868-
const char *s;
1869-
struct gpmc_timings gpmc_t;
1870-
struct omap_nand_platform_data *gpmc_nand_data;
1871-
1872-
if (of_property_read_u32(child, "reg", &val) < 0) {
1873-
dev_err(&pdev->dev, "%s has no 'reg' property\n",
1874-
child->full_name);
1875-
return -ENODEV;
1876-
}
1877-
1878-
gpmc_nand_data = devm_kzalloc(&pdev->dev, sizeof(*gpmc_nand_data),
1879-
GFP_KERNEL);
1880-
if (!gpmc_nand_data)
1881-
return -ENOMEM;
1882-
1883-
gpmc_nand_data->cs = val;
1884-
gpmc_nand_data->of_node = child;
1885-
1886-
/* Detect availability of ELM module */
1887-
gpmc_nand_data->elm_of_node = of_parse_phandle(child, "ti,elm-id", 0);
1888-
if (gpmc_nand_data->elm_of_node == NULL)
1889-
gpmc_nand_data->elm_of_node =
1890-
of_parse_phandle(child, "elm_id", 0);
1891-
1892-
/* select ecc-scheme for NAND */
1893-
if (of_property_read_string(child, "ti,nand-ecc-opt", &s)) {
1894-
pr_err("%s: ti,nand-ecc-opt not found\n", __func__);
1895-
return -ENODEV;
1896-
}
1897-
1898-
if (!strcmp(s, "sw"))
1899-
gpmc_nand_data->ecc_opt = OMAP_ECC_HAM1_CODE_SW;
1900-
else if (!strcmp(s, "ham1") ||
1901-
!strcmp(s, "hw") || !strcmp(s, "hw-romcode"))
1902-
gpmc_nand_data->ecc_opt =
1903-
OMAP_ECC_HAM1_CODE_HW;
1904-
else if (!strcmp(s, "bch4"))
1905-
if (gpmc_nand_data->elm_of_node)
1906-
gpmc_nand_data->ecc_opt =
1907-
OMAP_ECC_BCH4_CODE_HW;
1908-
else
1909-
gpmc_nand_data->ecc_opt =
1910-
OMAP_ECC_BCH4_CODE_HW_DETECTION_SW;
1911-
else if (!strcmp(s, "bch8"))
1912-
if (gpmc_nand_data->elm_of_node)
1913-
gpmc_nand_data->ecc_opt =
1914-
OMAP_ECC_BCH8_CODE_HW;
1915-
else
1916-
gpmc_nand_data->ecc_opt =
1917-
OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
1918-
else if (!strcmp(s, "bch16"))
1919-
if (gpmc_nand_data->elm_of_node)
1920-
gpmc_nand_data->ecc_opt =
1921-
OMAP_ECC_BCH16_CODE_HW;
1922-
else
1923-
pr_err("%s: BCH16 requires ELM support\n", __func__);
1924-
else
1925-
pr_err("%s: ti,nand-ecc-opt invalid value\n", __func__);
1926-
1927-
/* select data transfer mode for NAND controller */
1928-
if (!of_property_read_string(child, "ti,nand-xfer-type", &s))
1929-
for (val = 0; val < ARRAY_SIZE(nand_xfer_types); val++)
1930-
if (!strcasecmp(s, nand_xfer_types[val])) {
1931-
gpmc_nand_data->xfer_type = val;
1932-
break;
1933-
}
1934-
1935-
gpmc_nand_data->flash_bbt = of_get_nand_on_flash_bbt(child);
1936-
1937-
val = of_get_nand_bus_width(child);
1938-
if (val == 16)
1939-
gpmc_nand_data->devsize = NAND_BUSWIDTH_16;
1940-
1941-
gpmc_read_timings_dt(child, &gpmc_t);
1942-
gpmc_nand_init(gpmc_nand_data, &gpmc_t);
1943-
1944-
return 0;
1945-
}
1946-
#else
1947-
static int gpmc_probe_nand_child(struct platform_device *pdev,
1948-
struct device_node *child)
1949-
{
1950-
return 0;
1951-
}
1952-
#endif
1953-
19541854
#if IS_ENABLED(CONFIG_MTD_ONENAND)
19551855
static int gpmc_probe_onenand_child(struct platform_device *pdev,
19561856
struct device_node *child)
@@ -2069,9 +1969,42 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
20691969
goto err;
20701970
}
20711971

2072-
ret = of_property_read_u32(child, "bank-width", &gpmc_s.device_width);
2073-
if (ret < 0)
2074-
goto err;
1972+
if (of_node_cmp(child->name, "nand") == 0) {
1973+
/* Warn about older DT blobs with no compatible property */
1974+
if (!of_property_read_bool(child, "compatible")) {
1975+
dev_warn(&pdev->dev,
1976+
"Incompatible NAND node: missing compatible");
1977+
ret = -EINVAL;
1978+
goto err;
1979+
}
1980+
}
1981+
1982+
if (of_device_is_compatible(child, "ti,omap2-nand")) {
1983+
/* NAND specific setup */
1984+
val = of_get_nand_bus_width(child);
1985+
switch (val) {
1986+
case 8:
1987+
gpmc_s.device_width = GPMC_DEVWIDTH_8BIT;
1988+
break;
1989+
case 16:
1990+
gpmc_s.device_width = GPMC_DEVWIDTH_16BIT;
1991+
break;
1992+
default:
1993+
dev_err(&pdev->dev, "%s: invalid 'nand-bus-width'\n",
1994+
child->name);
1995+
ret = -EINVAL;
1996+
goto err;
1997+
}
1998+
1999+
/* disable write protect */
2000+
gpmc_configure(GPMC_CONFIG_WP, 0);
2001+
gpmc_s.device_nand = true;
2002+
} else {
2003+
ret = of_property_read_u32(child, "bank-width",
2004+
&gpmc_s.device_width);
2005+
if (ret < 0)
2006+
goto err;
2007+
}
20752008

20762009
gpmc_cs_show_timings(cs, "before gpmc_cs_program_settings");
20772010
ret = gpmc_cs_program_settings(cs, &gpmc_s);
@@ -2155,9 +2088,7 @@ static int gpmc_probe_dt(struct platform_device *pdev)
21552088
if (!child->name)
21562089
continue;
21572090

2158-
if (of_node_cmp(child->name, "nand") == 0)
2159-
ret = gpmc_probe_nand_child(pdev, child);
2160-
else if (of_node_cmp(child->name, "onenand") == 0)
2091+
if (of_node_cmp(child->name, "onenand") == 0)
21612092
ret = gpmc_probe_onenand_child(pdev, child);
21622093
else
21632094
ret = gpmc_probe_generic_child(pdev, child);

drivers/mtd/nand/omap2.c

Lines changed: 114 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <linux/slab.h>
2525
#include <linux/of.h>
2626
#include <linux/of_device.h>
27+
#include <linux/of_mtd.h>
2728

2829
#include <linux/mtd/nand_bch.h>
2930
#include <linux/platform_data/elm.h>
@@ -176,11 +177,11 @@ struct omap_nand_info {
176177
/* Interface to GPMC */
177178
struct gpmc_nand_regs reg;
178179
struct gpmc_nand_ops *ops;
180+
bool flash_bbt;
179181
/* generated at runtime depending on ECC algorithm and layout selected */
180182
struct nand_ecclayout oobinfo;
181183
/* fields specific for BCHx_HW ECC scheme */
182184
struct device *elm_dev;
183-
struct device_node *of_node;
184185
};
185186

186187
static 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,
16431644
return true;
16441645
}
16451646

1647+
static 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+
1654+
static 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+
1714+
next:
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+
16461723
static int omap_nand_probe(struct platform_device *pdev)
16471724
{
16481725
struct omap_nand_info *info;
1649-
struct omap_nand_platform_data *pdata;
1726+
struct omap_nand_platform_data *pdata = NULL;
16501727
struct mtd_info *mtd;
16511728
struct nand_chip *nand_chip;
16521729
struct nand_ecclayout *ecclayout;
@@ -1656,39 +1733,47 @@ static int omap_nand_probe(struct platform_device *pdev)
16561733
unsigned sig;
16571734
unsigned oob_index;
16581735
struct resource *res;
1659-
1660-
pdata = dev_get_platdata(&pdev->dev);
1661-
if (pdata == NULL) {
1662-
dev_err(&pdev->dev, "platform data missing\n");
1663-
return -ENODEV;
1664-
}
1736+
struct device *dev = &pdev->dev;
16651737

16661738
info = devm_kzalloc(&pdev->dev, sizeof(struct omap_nand_info),
16671739
GFP_KERNEL);
16681740
if (!info)
16691741
return -ENOMEM;
16701742

1671-
platform_set_drvdata(pdev, info);
1743+
info->pdev = pdev;
16721744

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);
16731766
info->ops = gpmc_omap_get_nand_ops(&info->reg, info->gpmc_cs);
16741767
if (!info->ops) {
16751768
dev_err(&pdev->dev, "Failed to get GPMC->NAND interface\n");
16761769
return -ENODEV;
16771770
}
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;
16861771

16871772
nand_chip = &info->nand;
16881773
mtd = nand_to_mtd(nand_chip);
16891774
mtd->dev.parent = &pdev->dev;
16901775
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);
16921777

16931778
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
16941779
nand_chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res);
@@ -1717,7 +1802,7 @@ static int omap_nand_probe(struct platform_device *pdev)
17171802
nand_chip->chip_delay = 50;
17181803
}
17191804

1720-
if (pdata->flash_bbt)
1805+
if (info->flash_bbt)
17211806
nand_chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB;
17221807
else
17231808
nand_chip->options |= NAND_SKIP_BBTSCAN;
@@ -2035,7 +2120,10 @@ static int omap_nand_probe(struct platform_device *pdev)
20352120
goto return_error;
20362121
}
20372122

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);
20392127

20402128
platform_set_drvdata(pdev, mtd);
20412129

@@ -2066,11 +2154,17 @@ static int omap_nand_remove(struct platform_device *pdev)
20662154
return 0;
20672155
}
20682156

2157+
static const struct of_device_id omap_nand_ids[] = {
2158+
{ .compatible = "ti,omap2-nand", },
2159+
{},
2160+
};
2161+
20692162
static struct platform_driver omap_nand_driver = {
20702163
.probe = omap_nand_probe,
20712164
.remove = omap_nand_remove,
20722165
.driver = {
20732166
.name = DRIVER_NAME,
2167+
.of_match_table = of_match_ptr(omap_nand_ids),
20742168
},
20752169
};
20762170

0 commit comments

Comments
 (0)