diff options
author | Tony Lindgren <tony@atomide.com> | 2012-11-09 17:54:17 -0500 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2012-11-09 17:54:17 -0500 |
commit | f56f52e02a9c3da4bc2cc6eb9ddcf5602ea44b37 (patch) | |
tree | a9ce4f46ea3b2e516698b2c3817e40414a8bbf51 /arch/arm/mach-omap2/gpmc-nand.c | |
parent | 84fbd2b8c8da49b4e53fcb484a1564a9b5da61b3 (diff) | |
parent | 6ba54ab4a49bbad736b0254aa6bdf0cb83013815 (diff) |
Merge branch 'omap-for-v3.8/cleanup-headers-prepare-multiplatform-v3' into omap-for-v3.8/dt
Conflicts:
arch/arm/plat-omap/dmtimer.c
Resolved as suggested by Jon Hunter.
Diffstat (limited to 'arch/arm/mach-omap2/gpmc-nand.c')
-rw-r--r-- | arch/arm/mach-omap2/gpmc-nand.c | 85 |
1 files changed, 55 insertions, 30 deletions
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index 4acf497faeb3..8607735b3ab3 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c | |||
@@ -17,9 +17,12 @@ | |||
17 | 17 | ||
18 | #include <asm/mach/flash.h> | 18 | #include <asm/mach/flash.h> |
19 | 19 | ||
20 | #include <plat/gpmc.h> | 20 | #include "gpmc.h" |
21 | |||
22 | #include "soc.h" | 21 | #include "soc.h" |
22 | #include "gpmc-nand.h" | ||
23 | |||
24 | /* minimum size for IO mapping */ | ||
25 | #define NAND_IO_SIZE 4 | ||
23 | 26 | ||
24 | static struct resource gpmc_nand_resource[] = { | 27 | static struct resource gpmc_nand_resource[] = { |
25 | { | 28 | { |
@@ -40,41 +43,36 @@ static struct platform_device gpmc_nand_device = { | |||
40 | .resource = gpmc_nand_resource, | 43 | .resource = gpmc_nand_resource, |
41 | }; | 44 | }; |
42 | 45 | ||
43 | static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data) | 46 | static int omap2_nand_gpmc_retime( |
47 | struct omap_nand_platform_data *gpmc_nand_data, | ||
48 | struct gpmc_timings *gpmc_t) | ||
44 | { | 49 | { |
45 | struct gpmc_timings t; | 50 | struct gpmc_timings t; |
46 | int err; | 51 | int err; |
47 | 52 | ||
48 | if (!gpmc_nand_data->gpmc_t) | ||
49 | return 0; | ||
50 | |||
51 | memset(&t, 0, sizeof(t)); | 53 | memset(&t, 0, sizeof(t)); |
52 | t.sync_clk = gpmc_nand_data->gpmc_t->sync_clk; | 54 | t.sync_clk = gpmc_t->sync_clk; |
53 | t.cs_on = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_on); | 55 | t.cs_on = gpmc_round_ns_to_ticks(gpmc_t->cs_on); |
54 | t.adv_on = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->adv_on); | 56 | t.adv_on = gpmc_round_ns_to_ticks(gpmc_t->adv_on); |
55 | 57 | ||
56 | /* Read */ | 58 | /* Read */ |
57 | t.adv_rd_off = gpmc_round_ns_to_ticks( | 59 | t.adv_rd_off = gpmc_round_ns_to_ticks(gpmc_t->adv_rd_off); |
58 | gpmc_nand_data->gpmc_t->adv_rd_off); | ||
59 | t.oe_on = t.adv_on; | 60 | t.oe_on = t.adv_on; |
60 | t.access = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->access); | 61 | t.access = gpmc_round_ns_to_ticks(gpmc_t->access); |
61 | t.oe_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->oe_off); | 62 | t.oe_off = gpmc_round_ns_to_ticks(gpmc_t->oe_off); |
62 | t.cs_rd_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_rd_off); | 63 | t.cs_rd_off = gpmc_round_ns_to_ticks(gpmc_t->cs_rd_off); |
63 | t.rd_cycle = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->rd_cycle); | 64 | t.rd_cycle = gpmc_round_ns_to_ticks(gpmc_t->rd_cycle); |
64 | 65 | ||
65 | /* Write */ | 66 | /* Write */ |
66 | t.adv_wr_off = gpmc_round_ns_to_ticks( | 67 | t.adv_wr_off = gpmc_round_ns_to_ticks(gpmc_t->adv_wr_off); |
67 | gpmc_nand_data->gpmc_t->adv_wr_off); | ||
68 | t.we_on = t.oe_on; | 68 | t.we_on = t.oe_on; |
69 | if (cpu_is_omap34xx()) { | 69 | if (cpu_is_omap34xx()) { |
70 | t.wr_data_mux_bus = gpmc_round_ns_to_ticks( | 70 | t.wr_data_mux_bus = gpmc_round_ns_to_ticks(gpmc_t->wr_data_mux_bus); |
71 | gpmc_nand_data->gpmc_t->wr_data_mux_bus); | 71 | t.wr_access = gpmc_round_ns_to_ticks(gpmc_t->wr_access); |
72 | t.wr_access = gpmc_round_ns_to_ticks( | ||
73 | gpmc_nand_data->gpmc_t->wr_access); | ||
74 | } | 72 | } |
75 | t.we_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->we_off); | 73 | t.we_off = gpmc_round_ns_to_ticks(gpmc_t->we_off); |
76 | t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_wr_off); | 74 | t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_t->cs_wr_off); |
77 | t.wr_cycle = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle); | 75 | t.wr_cycle = gpmc_round_ns_to_ticks(gpmc_t->wr_cycle); |
78 | 76 | ||
79 | /* Configure GPMC */ | 77 | /* Configure GPMC */ |
80 | if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16) | 78 | if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16) |
@@ -91,7 +89,29 @@ static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data | |||
91 | return 0; | 89 | return 0; |
92 | } | 90 | } |
93 | 91 | ||
94 | int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) | 92 | static bool __init gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt) |
93 | { | ||
94 | /* support only OMAP3 class */ | ||
95 | if (!cpu_is_omap34xx()) { | ||
96 | pr_err("BCH ecc is not supported on this CPU\n"); | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | * For now, assume 4-bit mode is only supported on OMAP3630 ES1.x, x>=1. | ||
102 | * Other chips may be added if confirmed to work. | ||
103 | */ | ||
104 | if ((ecc_opt == OMAP_ECC_BCH4_CODE_HW) && | ||
105 | (!cpu_is_omap3630() || (GET_OMAP_REVISION() == 0))) { | ||
106 | pr_err("BCH 4-bit mode is not supported on this CPU\n"); | ||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | return 1; | ||
111 | } | ||
112 | |||
113 | int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data, | ||
114 | struct gpmc_timings *gpmc_t) | ||
95 | { | 115 | { |
96 | int err = 0; | 116 | int err = 0; |
97 | struct device *dev = &gpmc_nand_device.dev; | 117 | struct device *dev = &gpmc_nand_device.dev; |
@@ -112,11 +132,13 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) | |||
112 | gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE); | 132 | gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE); |
113 | gpmc_nand_resource[2].start = | 133 | gpmc_nand_resource[2].start = |
114 | gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT); | 134 | gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT); |
115 | /* Set timings in GPMC */ | 135 | |
116 | err = omap2_nand_gpmc_retime(gpmc_nand_data); | 136 | if (gpmc_t) { |
117 | if (err < 0) { | 137 | err = omap2_nand_gpmc_retime(gpmc_nand_data, gpmc_t); |
118 | dev_err(dev, "Unable to set gpmc timings: %d\n", err); | 138 | if (err < 0) { |
119 | return err; | 139 | dev_err(dev, "Unable to set gpmc timings: %d\n", err); |
140 | return err; | ||
141 | } | ||
120 | } | 142 | } |
121 | 143 | ||
122 | /* Enable RD PIN Monitoring Reg */ | 144 | /* Enable RD PIN Monitoring Reg */ |
@@ -126,6 +148,9 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) | |||
126 | 148 | ||
127 | gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs); | 149 | gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs); |
128 | 150 | ||
151 | if (!gpmc_hwecc_bch_capable(gpmc_nand_data->ecc_opt)) | ||
152 | return -EINVAL; | ||
153 | |||
129 | err = platform_device_register(&gpmc_nand_device); | 154 | err = platform_device_register(&gpmc_nand_device); |
130 | if (err < 0) { | 155 | if (err < 0) { |
131 | dev_err(dev, "Unable to register NAND device\n"); | 156 | dev_err(dev, "Unable to register NAND device\n"); |