aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/gpmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/gpmc.c')
-rw-r--r--arch/arm/mach-omap2/gpmc.c90
1 files changed, 74 insertions, 16 deletions
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 9f4795aff48a..81de56251955 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -1341,14 +1341,6 @@ static void __maybe_unused gpmc_read_timings_dt(struct device_node *np,
1341 1341
1342#ifdef CONFIG_MTD_NAND 1342#ifdef CONFIG_MTD_NAND
1343 1343
1344static const char * const nand_ecc_opts[] = {
1345 [OMAP_ECC_HAMMING_CODE_DEFAULT] = "sw",
1346 [OMAP_ECC_HAMMING_CODE_HW] = "hw",
1347 [OMAP_ECC_HAMMING_CODE_HW_ROMCODE] = "hw-romcode",
1348 [OMAP_ECC_BCH4_CODE_HW] = "bch4",
1349 [OMAP_ECC_BCH8_CODE_HW] = "bch8",
1350};
1351
1352static const char * const nand_xfer_types[] = { 1344static const char * const nand_xfer_types[] = {
1353 [NAND_OMAP_PREFETCH_POLLED] = "prefetch-polled", 1345 [NAND_OMAP_PREFETCH_POLLED] = "prefetch-polled",
1354 [NAND_OMAP_POLLED] = "polled", 1346 [NAND_OMAP_POLLED] = "polled",
@@ -1378,13 +1370,41 @@ static int gpmc_probe_nand_child(struct platform_device *pdev,
1378 gpmc_nand_data->cs = val; 1370 gpmc_nand_data->cs = val;
1379 gpmc_nand_data->of_node = child; 1371 gpmc_nand_data->of_node = child;
1380 1372
1381 if (!of_property_read_string(child, "ti,nand-ecc-opt", &s)) 1373 /* Detect availability of ELM module */
1382 for (val = 0; val < ARRAY_SIZE(nand_ecc_opts); val++) 1374 gpmc_nand_data->elm_of_node = of_parse_phandle(child, "ti,elm-id", 0);
1383 if (!strcasecmp(s, nand_ecc_opts[val])) { 1375 if (gpmc_nand_data->elm_of_node == NULL)
1384 gpmc_nand_data->ecc_opt = val; 1376 gpmc_nand_data->elm_of_node =
1385 break; 1377 of_parse_phandle(child, "elm_id", 0);
1386 } 1378 if (gpmc_nand_data->elm_of_node == NULL)
1379 pr_warn("%s: ti,elm-id property not found\n", __func__);
1380
1381 /* select ecc-scheme for NAND */
1382 if (of_property_read_string(child, "ti,nand-ecc-opt", &s)) {
1383 pr_err("%s: ti,nand-ecc-opt not found\n", __func__);
1384 return -ENODEV;
1385 }
1386 if (!strcmp(s, "ham1") || !strcmp(s, "sw") ||
1387 !strcmp(s, "hw") || !strcmp(s, "hw-romcode"))
1388 gpmc_nand_data->ecc_opt =
1389 OMAP_ECC_HAM1_CODE_HW;
1390 else if (!strcmp(s, "bch4"))
1391 if (gpmc_nand_data->elm_of_node)
1392 gpmc_nand_data->ecc_opt =
1393 OMAP_ECC_BCH4_CODE_HW;
1394 else
1395 gpmc_nand_data->ecc_opt =
1396 OMAP_ECC_BCH4_CODE_HW_DETECTION_SW;
1397 else if (!strcmp(s, "bch8"))
1398 if (gpmc_nand_data->elm_of_node)
1399 gpmc_nand_data->ecc_opt =
1400 OMAP_ECC_BCH8_CODE_HW;
1401 else
1402 gpmc_nand_data->ecc_opt =
1403 OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
1404 else
1405 pr_err("%s: ti,nand-ecc-opt invalid value\n", __func__);
1387 1406
1407 /* select data transfer mode for NAND controller */
1388 if (!of_property_read_string(child, "ti,nand-xfer-type", &s)) 1408 if (!of_property_read_string(child, "ti,nand-xfer-type", &s))
1389 for (val = 0; val < ARRAY_SIZE(nand_xfer_types); val++) 1409 for (val = 0; val < ARRAY_SIZE(nand_xfer_types); val++)
1390 if (!strcasecmp(s, nand_xfer_types[val])) { 1410 if (!strcasecmp(s, nand_xfer_types[val])) {
@@ -1491,8 +1511,8 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
1491 */ 1511 */
1492 ret = gpmc_cs_remap(cs, res.start); 1512 ret = gpmc_cs_remap(cs, res.start);
1493 if (ret < 0) { 1513 if (ret < 0) {
1494 dev_err(&pdev->dev, "cannot remap GPMC CS %d to 0x%x\n", 1514 dev_err(&pdev->dev, "cannot remap GPMC CS %d to %pa\n",
1495 cs, res.start); 1515 cs, &res.start);
1496 goto err; 1516 goto err;
1497 } 1517 }
1498 1518
@@ -1521,6 +1541,42 @@ err:
1521 return ret; 1541 return ret;
1522} 1542}
1523 1543
1544/*
1545 * REVISIT: Add timing support from slls644g.pdf
1546 */
1547static int gpmc_probe_8250(struct platform_device *pdev,
1548 struct device_node *child)
1549{
1550 struct resource res;
1551 unsigned long base;
1552 int ret, cs;
1553
1554 if (of_property_read_u32(child, "reg", &cs) < 0) {
1555 dev_err(&pdev->dev, "%s has no 'reg' property\n",
1556 child->full_name);
1557 return -ENODEV;
1558 }
1559
1560 if (of_address_to_resource(child, 0, &res) < 0) {
1561 dev_err(&pdev->dev, "%s has malformed 'reg' property\n",
1562 child->full_name);
1563 return -ENODEV;
1564 }
1565
1566 ret = gpmc_cs_request(cs, resource_size(&res), &base);
1567 if (ret < 0) {
1568 dev_err(&pdev->dev, "cannot request GPMC CS %d\n", cs);
1569 return ret;
1570 }
1571
1572 if (of_platform_device_create(child, NULL, &pdev->dev))
1573 return 0;
1574
1575 dev_err(&pdev->dev, "failed to create gpmc child %s\n", child->name);
1576
1577 return -ENODEV;
1578}
1579
1524static int gpmc_probe_dt(struct platform_device *pdev) 1580static int gpmc_probe_dt(struct platform_device *pdev)
1525{ 1581{
1526 int ret; 1582 int ret;
@@ -1564,6 +1620,8 @@ static int gpmc_probe_dt(struct platform_device *pdev)
1564 else if (of_node_cmp(child->name, "ethernet") == 0 || 1620 else if (of_node_cmp(child->name, "ethernet") == 0 ||
1565 of_node_cmp(child->name, "nor") == 0) 1621 of_node_cmp(child->name, "nor") == 0)
1566 ret = gpmc_probe_generic_child(pdev, child); 1622 ret = gpmc_probe_generic_child(pdev, child);
1623 else if (of_node_cmp(child->name, "8250") == 0)
1624 ret = gpmc_probe_8250(pdev, child);
1567 1625
1568 if (WARN(ret < 0, "%s: probing gpmc child %s failed\n", 1626 if (WARN(ret < 0, "%s: probing gpmc child %s failed\n",
1569 __func__, child->full_name)) 1627 __func__, child->full_name))