diff options
-rw-r--r-- | arch/arm/mach-omap2/gpmc-onenand.c | 80 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/onenand.h | 8 |
2 files changed, 67 insertions, 21 deletions
diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 46786a606e90..d776ded9830d 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c | |||
@@ -121,6 +121,47 @@ static void set_onenand_cfg(void __iomem *onenand_base, int latency, | |||
121 | writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); | 121 | writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); |
122 | } | 122 | } |
123 | 123 | ||
124 | static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg, | ||
125 | void __iomem *onenand_base, bool *clk_dep) | ||
126 | { | ||
127 | u16 ver = readw(onenand_base + ONENAND_REG_VERSION_ID); | ||
128 | int freq = 0; | ||
129 | |||
130 | if (cfg->get_freq) { | ||
131 | struct onenand_freq_info fi; | ||
132 | |||
133 | fi.maf_id = readw(onenand_base + ONENAND_REG_MANUFACTURER_ID); | ||
134 | fi.dev_id = readw(onenand_base + ONENAND_REG_DEVICE_ID); | ||
135 | fi.ver_id = ver; | ||
136 | freq = cfg->get_freq(&fi, clk_dep); | ||
137 | if (freq) | ||
138 | return freq; | ||
139 | } | ||
140 | |||
141 | switch ((ver >> 4) & 0xf) { | ||
142 | case 0: | ||
143 | freq = 40; | ||
144 | break; | ||
145 | case 1: | ||
146 | freq = 54; | ||
147 | break; | ||
148 | case 2: | ||
149 | freq = 66; | ||
150 | break; | ||
151 | case 3: | ||
152 | freq = 83; | ||
153 | break; | ||
154 | case 4: | ||
155 | freq = 104; | ||
156 | break; | ||
157 | default: | ||
158 | freq = 54; | ||
159 | break; | ||
160 | } | ||
161 | |||
162 | return freq; | ||
163 | } | ||
164 | |||
124 | static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, | 165 | static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, |
125 | void __iomem *onenand_base, | 166 | void __iomem *onenand_base, |
126 | int *freq_ptr) | 167 | int *freq_ptr) |
@@ -138,6 +179,7 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, | |||
138 | int err, ticks_cez; | 179 | int err, ticks_cez; |
139 | int cs = cfg->cs, freq = *freq_ptr; | 180 | int cs = cfg->cs, freq = *freq_ptr; |
140 | u32 reg; | 181 | u32 reg; |
182 | bool clk_dep = false; | ||
141 | 183 | ||
142 | if (cfg->flags & ONENAND_SYNC_READ) { | 184 | if (cfg->flags & ONENAND_SYNC_READ) { |
143 | sync_read = 1; | 185 | sync_read = 1; |
@@ -152,27 +194,7 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, | |||
152 | err = omap2_onenand_set_async_mode(cs, onenand_base); | 194 | err = omap2_onenand_set_async_mode(cs, onenand_base); |
153 | if (err) | 195 | if (err) |
154 | return err; | 196 | return err; |
155 | reg = readw(onenand_base + ONENAND_REG_VERSION_ID); | 197 | freq = omap2_onenand_get_freq(cfg, onenand_base, &clk_dep); |
156 | switch ((reg >> 4) & 0xf) { | ||
157 | case 0: | ||
158 | freq = 40; | ||
159 | break; | ||
160 | case 1: | ||
161 | freq = 54; | ||
162 | break; | ||
163 | case 2: | ||
164 | freq = 66; | ||
165 | break; | ||
166 | case 3: | ||
167 | freq = 83; | ||
168 | break; | ||
169 | case 4: | ||
170 | freq = 104; | ||
171 | break; | ||
172 | default: | ||
173 | freq = 54; | ||
174 | break; | ||
175 | } | ||
176 | first_time = 1; | 198 | first_time = 1; |
177 | } | 199 | } |
178 | 200 | ||
@@ -232,6 +254,22 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, | |||
232 | else | 254 | else |
233 | latency = 4; | 255 | latency = 4; |
234 | 256 | ||
257 | if (clk_dep) { | ||
258 | if (gpmc_clk_ns < 12) { /* >83Mhz */ | ||
259 | t_ces = 3; | ||
260 | t_avds = 4; | ||
261 | } else if (gpmc_clk_ns < 15) { /* >66Mhz */ | ||
262 | t_ces = 5; | ||
263 | t_avds = 4; | ||
264 | } else if (gpmc_clk_ns < 25) { /* >40Mhz */ | ||
265 | t_ces = 6; | ||
266 | t_avds = 5; | ||
267 | } else { | ||
268 | t_ces = 7; | ||
269 | t_avds = 7; | ||
270 | } | ||
271 | } | ||
272 | |||
235 | if (first_time) | 273 | if (first_time) |
236 | set_onenand_cfg(onenand_base, latency, | 274 | set_onenand_cfg(onenand_base, latency, |
237 | sync_read, sync_write, hf, vhf); | 275 | sync_read, sync_write, hf, vhf); |
diff --git a/arch/arm/plat-omap/include/plat/onenand.h b/arch/arm/plat-omap/include/plat/onenand.h index 86118dc3f19a..cbe897ca7f9e 100644 --- a/arch/arm/plat-omap/include/plat/onenand.h +++ b/arch/arm/plat-omap/include/plat/onenand.h | |||
@@ -15,12 +15,20 @@ | |||
15 | #define ONENAND_SYNC_READ (1 << 0) | 15 | #define ONENAND_SYNC_READ (1 << 0) |
16 | #define ONENAND_SYNC_READWRITE (1 << 1) | 16 | #define ONENAND_SYNC_READWRITE (1 << 1) |
17 | 17 | ||
18 | struct onenand_freq_info { | ||
19 | u16 maf_id; | ||
20 | u16 dev_id; | ||
21 | u16 ver_id; | ||
22 | }; | ||
23 | |||
18 | struct omap_onenand_platform_data { | 24 | struct omap_onenand_platform_data { |
19 | int cs; | 25 | int cs; |
20 | int gpio_irq; | 26 | int gpio_irq; |
21 | struct mtd_partition *parts; | 27 | struct mtd_partition *parts; |
22 | int nr_parts; | 28 | int nr_parts; |
23 | int (*onenand_setup)(void __iomem *, int *freq_ptr); | 29 | int (*onenand_setup)(void __iomem *, int *freq_ptr); |
30 | int (*get_freq)(const struct onenand_freq_info *freq_info, | ||
31 | bool *clk_dep); | ||
24 | int dma_channel; | 32 | int dma_channel; |
25 | u8 flags; | 33 | u8 flags; |
26 | u8 regulator_can_sleep; | 34 | u8 regulator_can_sleep; |