diff options
author | Olof Johansson <olof@lixom.net> | 2013-06-14 17:36:51 -0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2013-06-14 17:36:51 -0400 |
commit | f54ffe0fef2b0bd635e2ee2738155fca70854675 (patch) | |
tree | 428619d8ce8cd123c2733bb96e7e641058665e6d /arch/arm/mach-omap2 | |
parent | ff299f1b1cb4e0c44a3f76d1f8ee4eb2f64f098f (diff) | |
parent | b3f5525c55ce5cb67af06f04dbbf28358da23a2c (diff) |
Merge tag 'omap-for-v3.11/gpmc-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/drivers
From Tony Lindgren:
Omap GPMC (General Purpose Memory Controller) changes.
* tag 'omap-for-v3.11/gpmc-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap:
ARM: OMAP2+: gpmc: Converts GPMC driver to pm_runtime capable
ARM: OMAP2+: gpmc: get number of useable GPMC chip-selects via DT
ARM: dts: OMAP2+: Simplify NAND support
ARM: OMAP2+: Allow NAND transfer mode to be specified in DT
ARM: OMAP2+: nand: reorganize gpmc timing values
Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r-- | arch/arm/mach-omap2/board-flash.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-omap2/gpmc-nand.c | 44 | ||||
-rw-r--r-- | arch/arm/mach-omap2/gpmc.c | 61 |
3 files changed, 55 insertions, 53 deletions
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index c33adea0247c..fc20a61f6b2a 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c | |||
@@ -112,6 +112,9 @@ struct gpmc_timings nand_default_timings[1] = { | |||
112 | .cs_rd_off = 36, | 112 | .cs_rd_off = 36, |
113 | .cs_wr_off = 36, | 113 | .cs_wr_off = 36, |
114 | 114 | ||
115 | .we_on = 6, | ||
116 | .oe_on = 6, | ||
117 | |||
115 | .adv_on = 6, | 118 | .adv_on = 6, |
116 | .adv_rd_off = 24, | 119 | .adv_rd_off = 24, |
117 | .adv_wr_off = 36, | 120 | .adv_wr_off = 36, |
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index d9c27195caf0..662c7fd633cc 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c | |||
@@ -43,44 +43,6 @@ static struct platform_device gpmc_nand_device = { | |||
43 | .resource = gpmc_nand_resource, | 43 | .resource = gpmc_nand_resource, |
44 | }; | 44 | }; |
45 | 45 | ||
46 | static int omap2_nand_gpmc_retime( | ||
47 | struct omap_nand_platform_data *gpmc_nand_data, | ||
48 | struct gpmc_timings *gpmc_t) | ||
49 | { | ||
50 | struct gpmc_timings t; | ||
51 | int err; | ||
52 | |||
53 | memset(&t, 0, sizeof(t)); | ||
54 | t.sync_clk = gpmc_t->sync_clk; | ||
55 | t.cs_on = gpmc_t->cs_on; | ||
56 | t.adv_on = gpmc_t->adv_on; | ||
57 | |||
58 | /* Read */ | ||
59 | t.adv_rd_off = gpmc_t->adv_rd_off; | ||
60 | t.oe_on = t.adv_on; | ||
61 | t.access = gpmc_t->access; | ||
62 | t.oe_off = gpmc_t->oe_off; | ||
63 | t.cs_rd_off = gpmc_t->cs_rd_off; | ||
64 | t.rd_cycle = gpmc_t->rd_cycle; | ||
65 | |||
66 | /* Write */ | ||
67 | t.adv_wr_off = gpmc_t->adv_wr_off; | ||
68 | t.we_on = t.oe_on; | ||
69 | if (cpu_is_omap34xx()) { | ||
70 | t.wr_data_mux_bus = gpmc_t->wr_data_mux_bus; | ||
71 | t.wr_access = gpmc_t->wr_access; | ||
72 | } | ||
73 | t.we_off = gpmc_t->we_off; | ||
74 | t.cs_wr_off = gpmc_t->cs_wr_off; | ||
75 | t.wr_cycle = gpmc_t->wr_cycle; | ||
76 | |||
77 | err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t); | ||
78 | if (err) | ||
79 | return err; | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static bool gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt) | 46 | static bool gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt) |
85 | { | 47 | { |
86 | /* support only OMAP3 class */ | 48 | /* support only OMAP3 class */ |
@@ -131,7 +93,7 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data, | |||
131 | gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT); | 93 | gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT); |
132 | 94 | ||
133 | if (gpmc_t) { | 95 | if (gpmc_t) { |
134 | err = omap2_nand_gpmc_retime(gpmc_nand_data, gpmc_t); | 96 | err = gpmc_cs_set_timings(gpmc_nand_data->cs, gpmc_t); |
135 | if (err < 0) { | 97 | if (err < 0) { |
136 | dev_err(dev, "Unable to set gpmc timings: %d\n", err); | 98 | dev_err(dev, "Unable to set gpmc timings: %d\n", err); |
137 | return err; | 99 | return err; |
@@ -140,8 +102,6 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data, | |||
140 | if (gpmc_nand_data->of_node) { | 102 | if (gpmc_nand_data->of_node) { |
141 | gpmc_read_settings_dt(gpmc_nand_data->of_node, &s); | 103 | gpmc_read_settings_dt(gpmc_nand_data->of_node, &s); |
142 | } else { | 104 | } else { |
143 | s.device_nand = true; | ||
144 | |||
145 | /* Enable RD PIN Monitoring Reg */ | 105 | /* Enable RD PIN Monitoring Reg */ |
146 | if (gpmc_nand_data->dev_ready) { | 106 | if (gpmc_nand_data->dev_ready) { |
147 | s.wait_on_read = true; | 107 | s.wait_on_read = true; |
@@ -149,6 +109,8 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data, | |||
149 | } | 109 | } |
150 | } | 110 | } |
151 | 111 | ||
112 | s.device_nand = true; | ||
113 | |||
152 | if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16) | 114 | if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16) |
153 | s.device_width = GPMC_DEVWIDTH_16BIT; | 115 | s.device_width = GPMC_DEVWIDTH_16BIT; |
154 | else | 116 | else |
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 6c4da1254f53..bac18b3ebbfb 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/of_mtd.h> | 30 | #include <linux/of_mtd.h> |
31 | #include <linux/of_device.h> | 31 | #include <linux/of_device.h> |
32 | #include <linux/mtd/nand.h> | 32 | #include <linux/mtd/nand.h> |
33 | #include <linux/pm_runtime.h> | ||
33 | 34 | ||
34 | #include <linux/platform_data/mtd-nand-omap2.h> | 35 | #include <linux/platform_data/mtd-nand-omap2.h> |
35 | 36 | ||
@@ -155,6 +156,7 @@ static struct resource gpmc_cs_mem[GPMC_CS_NUM]; | |||
155 | static DEFINE_SPINLOCK(gpmc_mem_lock); | 156 | static DEFINE_SPINLOCK(gpmc_mem_lock); |
156 | /* Define chip-selects as reserved by default until probe completes */ | 157 | /* Define chip-selects as reserved by default until probe completes */ |
157 | static unsigned int gpmc_cs_map = ((1 << GPMC_CS_NUM) - 1); | 158 | static unsigned int gpmc_cs_map = ((1 << GPMC_CS_NUM) - 1); |
159 | static unsigned int gpmc_cs_num = GPMC_CS_NUM; | ||
158 | static unsigned int gpmc_nr_waitpins; | 160 | static unsigned int gpmc_nr_waitpins; |
159 | static struct device *gpmc_dev; | 161 | static struct device *gpmc_dev; |
160 | static int gpmc_irq; | 162 | static int gpmc_irq; |
@@ -521,8 +523,10 @@ static int gpmc_cs_remap(int cs, u32 base) | |||
521 | int ret; | 523 | int ret; |
522 | u32 old_base, size; | 524 | u32 old_base, size; |
523 | 525 | ||
524 | if (cs > GPMC_CS_NUM) | 526 | if (cs > gpmc_cs_num) { |
527 | pr_err("%s: requested chip-select is disabled\n", __func__); | ||
525 | return -ENODEV; | 528 | return -ENODEV; |
529 | } | ||
526 | gpmc_cs_get_memconf(cs, &old_base, &size); | 530 | gpmc_cs_get_memconf(cs, &old_base, &size); |
527 | if (base == old_base) | 531 | if (base == old_base) |
528 | return 0; | 532 | return 0; |
@@ -545,9 +549,10 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base) | |||
545 | struct resource *res = &gpmc_cs_mem[cs]; | 549 | struct resource *res = &gpmc_cs_mem[cs]; |
546 | int r = -1; | 550 | int r = -1; |
547 | 551 | ||
548 | if (cs > GPMC_CS_NUM) | 552 | if (cs > gpmc_cs_num) { |
553 | pr_err("%s: requested chip-select is disabled\n", __func__); | ||
549 | return -ENODEV; | 554 | return -ENODEV; |
550 | 555 | } | |
551 | size = gpmc_mem_align(size); | 556 | size = gpmc_mem_align(size); |
552 | if (size > (1 << GPMC_SECTION_SHIFT)) | 557 | if (size > (1 << GPMC_SECTION_SHIFT)) |
553 | return -ENOMEM; | 558 | return -ENOMEM; |
@@ -582,7 +587,7 @@ EXPORT_SYMBOL(gpmc_cs_request); | |||
582 | void gpmc_cs_free(int cs) | 587 | void gpmc_cs_free(int cs) |
583 | { | 588 | { |
584 | spin_lock(&gpmc_mem_lock); | 589 | spin_lock(&gpmc_mem_lock); |
585 | if (cs >= GPMC_CS_NUM || cs < 0 || !gpmc_cs_reserved(cs)) { | 590 | if (cs >= gpmc_cs_num || cs < 0 || !gpmc_cs_reserved(cs)) { |
586 | printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs); | 591 | printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs); |
587 | BUG(); | 592 | BUG(); |
588 | spin_unlock(&gpmc_mem_lock); | 593 | spin_unlock(&gpmc_mem_lock); |
@@ -777,7 +782,7 @@ static void gpmc_mem_exit(void) | |||
777 | { | 782 | { |
778 | int cs; | 783 | int cs; |
779 | 784 | ||
780 | for (cs = 0; cs < GPMC_CS_NUM; cs++) { | 785 | for (cs = 0; cs < gpmc_cs_num; cs++) { |
781 | if (!gpmc_cs_mem_enabled(cs)) | 786 | if (!gpmc_cs_mem_enabled(cs)) |
782 | continue; | 787 | continue; |
783 | gpmc_cs_delete_mem(cs); | 788 | gpmc_cs_delete_mem(cs); |
@@ -798,7 +803,7 @@ static void gpmc_mem_init(void) | |||
798 | gpmc_mem_root.end = GPMC_MEM_END; | 803 | gpmc_mem_root.end = GPMC_MEM_END; |
799 | 804 | ||
800 | /* Reserve all regions that has been set up by bootloader */ | 805 | /* Reserve all regions that has been set up by bootloader */ |
801 | for (cs = 0; cs < GPMC_CS_NUM; cs++) { | 806 | for (cs = 0; cs < gpmc_cs_num; cs++) { |
802 | u32 base, size; | 807 | u32 base, size; |
803 | 808 | ||
804 | if (!gpmc_cs_mem_enabled(cs)) | 809 | if (!gpmc_cs_mem_enabled(cs)) |
@@ -1245,7 +1250,6 @@ void gpmc_read_settings_dt(struct device_node *np, struct gpmc_settings *p) | |||
1245 | 1250 | ||
1246 | p->sync_read = of_property_read_bool(np, "gpmc,sync-read"); | 1251 | p->sync_read = of_property_read_bool(np, "gpmc,sync-read"); |
1247 | p->sync_write = of_property_read_bool(np, "gpmc,sync-write"); | 1252 | p->sync_write = of_property_read_bool(np, "gpmc,sync-write"); |
1248 | p->device_nand = of_property_read_bool(np, "gpmc,device-nand"); | ||
1249 | of_property_read_u32(np, "gpmc,device-width", &p->device_width); | 1253 | of_property_read_u32(np, "gpmc,device-width", &p->device_width); |
1250 | of_property_read_u32(np, "gpmc,mux-add-data", &p->mux_add_data); | 1254 | of_property_read_u32(np, "gpmc,mux-add-data", &p->mux_add_data); |
1251 | 1255 | ||
@@ -1345,6 +1349,13 @@ static const char * const nand_ecc_opts[] = { | |||
1345 | [OMAP_ECC_BCH8_CODE_HW] = "bch8", | 1349 | [OMAP_ECC_BCH8_CODE_HW] = "bch8", |
1346 | }; | 1350 | }; |
1347 | 1351 | ||
1352 | static const char * const nand_xfer_types[] = { | ||
1353 | [NAND_OMAP_PREFETCH_POLLED] = "prefetch-polled", | ||
1354 | [NAND_OMAP_POLLED] = "polled", | ||
1355 | [NAND_OMAP_PREFETCH_DMA] = "prefetch-dma", | ||
1356 | [NAND_OMAP_PREFETCH_IRQ] = "prefetch-irq", | ||
1357 | }; | ||
1358 | |||
1348 | static int gpmc_probe_nand_child(struct platform_device *pdev, | 1359 | static int gpmc_probe_nand_child(struct platform_device *pdev, |
1349 | struct device_node *child) | 1360 | struct device_node *child) |
1350 | { | 1361 | { |
@@ -1374,6 +1385,13 @@ static int gpmc_probe_nand_child(struct platform_device *pdev, | |||
1374 | break; | 1385 | break; |
1375 | } | 1386 | } |
1376 | 1387 | ||
1388 | if (!of_property_read_string(child, "ti,nand-xfer-type", &s)) | ||
1389 | for (val = 0; val < ARRAY_SIZE(nand_xfer_types); val++) | ||
1390 | if (!strcasecmp(s, nand_xfer_types[val])) { | ||
1391 | gpmc_nand_data->xfer_type = val; | ||
1392 | break; | ||
1393 | } | ||
1394 | |||
1377 | val = of_get_nand_bus_width(child); | 1395 | val = of_get_nand_bus_width(child); |
1378 | if (val == 16) | 1396 | if (val == 16) |
1379 | gpmc_nand_data->devsize = NAND_BUSWIDTH_16; | 1397 | gpmc_nand_data->devsize = NAND_BUSWIDTH_16; |
@@ -1513,6 +1531,20 @@ static int gpmc_probe_dt(struct platform_device *pdev) | |||
1513 | if (!of_id) | 1531 | if (!of_id) |
1514 | return 0; | 1532 | return 0; |
1515 | 1533 | ||
1534 | ret = of_property_read_u32(pdev->dev.of_node, "gpmc,num-cs", | ||
1535 | &gpmc_cs_num); | ||
1536 | if (ret < 0) { | ||
1537 | pr_err("%s: number of chip-selects not defined\n", __func__); | ||
1538 | return ret; | ||
1539 | } else if (gpmc_cs_num < 1) { | ||
1540 | pr_err("%s: all chip-selects are disabled\n", __func__); | ||
1541 | return -EINVAL; | ||
1542 | } else if (gpmc_cs_num > GPMC_CS_NUM) { | ||
1543 | pr_err("%s: number of supported chip-selects cannot be > %d\n", | ||
1544 | __func__, GPMC_CS_NUM); | ||
1545 | return -EINVAL; | ||
1546 | } | ||
1547 | |||
1516 | ret = of_property_read_u32(pdev->dev.of_node, "gpmc,num-waitpins", | 1548 | ret = of_property_read_u32(pdev->dev.of_node, "gpmc,num-waitpins", |
1517 | &gpmc_nr_waitpins); | 1549 | &gpmc_nr_waitpins); |
1518 | if (ret < 0) { | 1550 | if (ret < 0) { |
@@ -1577,7 +1609,8 @@ static int gpmc_probe(struct platform_device *pdev) | |||
1577 | return PTR_ERR(gpmc_l3_clk); | 1609 | return PTR_ERR(gpmc_l3_clk); |
1578 | } | 1610 | } |
1579 | 1611 | ||
1580 | clk_prepare_enable(gpmc_l3_clk); | 1612 | pm_runtime_enable(&pdev->dev); |
1613 | pm_runtime_get_sync(&pdev->dev); | ||
1581 | 1614 | ||
1582 | gpmc_dev = &pdev->dev; | 1615 | gpmc_dev = &pdev->dev; |
1583 | 1616 | ||
@@ -1610,12 +1643,14 @@ static int gpmc_probe(struct platform_device *pdev) | |||
1610 | /* Now the GPMC is initialised, unreserve the chip-selects */ | 1643 | /* Now the GPMC is initialised, unreserve the chip-selects */ |
1611 | gpmc_cs_map = 0; | 1644 | gpmc_cs_map = 0; |
1612 | 1645 | ||
1613 | if (!pdev->dev.of_node) | 1646 | if (!pdev->dev.of_node) { |
1647 | gpmc_cs_num = GPMC_CS_NUM; | ||
1614 | gpmc_nr_waitpins = GPMC_NR_WAITPINS; | 1648 | gpmc_nr_waitpins = GPMC_NR_WAITPINS; |
1649 | } | ||
1615 | 1650 | ||
1616 | rc = gpmc_probe_dt(pdev); | 1651 | rc = gpmc_probe_dt(pdev); |
1617 | if (rc < 0) { | 1652 | if (rc < 0) { |
1618 | clk_disable_unprepare(gpmc_l3_clk); | 1653 | pm_runtime_put_sync(&pdev->dev); |
1619 | clk_put(gpmc_l3_clk); | 1654 | clk_put(gpmc_l3_clk); |
1620 | dev_err(gpmc_dev, "failed to probe DT parameters\n"); | 1655 | dev_err(gpmc_dev, "failed to probe DT parameters\n"); |
1621 | return rc; | 1656 | return rc; |
@@ -1628,6 +1663,8 @@ static int gpmc_remove(struct platform_device *pdev) | |||
1628 | { | 1663 | { |
1629 | gpmc_free_irq(); | 1664 | gpmc_free_irq(); |
1630 | gpmc_mem_exit(); | 1665 | gpmc_mem_exit(); |
1666 | pm_runtime_put_sync(&pdev->dev); | ||
1667 | pm_runtime_disable(&pdev->dev); | ||
1631 | gpmc_dev = NULL; | 1668 | gpmc_dev = NULL; |
1632 | return 0; | 1669 | return 0; |
1633 | } | 1670 | } |
@@ -1715,7 +1752,7 @@ void omap3_gpmc_save_context(void) | |||
1715 | gpmc_context.prefetch_config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1); | 1752 | gpmc_context.prefetch_config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1); |
1716 | gpmc_context.prefetch_config2 = gpmc_read_reg(GPMC_PREFETCH_CONFIG2); | 1753 | gpmc_context.prefetch_config2 = gpmc_read_reg(GPMC_PREFETCH_CONFIG2); |
1717 | gpmc_context.prefetch_control = gpmc_read_reg(GPMC_PREFETCH_CONTROL); | 1754 | gpmc_context.prefetch_control = gpmc_read_reg(GPMC_PREFETCH_CONTROL); |
1718 | for (i = 0; i < GPMC_CS_NUM; i++) { | 1755 | for (i = 0; i < gpmc_cs_num; i++) { |
1719 | gpmc_context.cs_context[i].is_valid = gpmc_cs_mem_enabled(i); | 1756 | gpmc_context.cs_context[i].is_valid = gpmc_cs_mem_enabled(i); |
1720 | if (gpmc_context.cs_context[i].is_valid) { | 1757 | if (gpmc_context.cs_context[i].is_valid) { |
1721 | gpmc_context.cs_context[i].config1 = | 1758 | gpmc_context.cs_context[i].config1 = |
@@ -1747,7 +1784,7 @@ void omap3_gpmc_restore_context(void) | |||
1747 | gpmc_write_reg(GPMC_PREFETCH_CONFIG1, gpmc_context.prefetch_config1); | 1784 | gpmc_write_reg(GPMC_PREFETCH_CONFIG1, gpmc_context.prefetch_config1); |
1748 | gpmc_write_reg(GPMC_PREFETCH_CONFIG2, gpmc_context.prefetch_config2); | 1785 | gpmc_write_reg(GPMC_PREFETCH_CONFIG2, gpmc_context.prefetch_config2); |
1749 | gpmc_write_reg(GPMC_PREFETCH_CONTROL, gpmc_context.prefetch_control); | 1786 | gpmc_write_reg(GPMC_PREFETCH_CONTROL, gpmc_context.prefetch_control); |
1750 | for (i = 0; i < GPMC_CS_NUM; i++) { | 1787 | for (i = 0; i < gpmc_cs_num; i++) { |
1751 | if (gpmc_context.cs_context[i].is_valid) { | 1788 | if (gpmc_context.cs_context[i].is_valid) { |
1752 | gpmc_cs_write_reg(i, GPMC_CS_CONFIG1, | 1789 | gpmc_cs_write_reg(i, GPMC_CS_CONFIG1, |
1753 | gpmc_context.cs_context[i].config1); | 1790 | gpmc_context.cs_context[i].config1); |