]> rtime.felk.cvut.cz Git - can-eth-gw-linux.git/blob - arch/arm/mach-omap2/gpmc-onenand.c
mm/bootmem.c: remove unused wrapper function reserve_bootmem_generic()
[can-eth-gw-linux.git] / arch / arm / mach-omap2 / gpmc-onenand.c
1 /*
2  * linux/arch/arm/mach-omap2/gpmc-onenand.c
3  *
4  * Copyright (C) 2006 - 2009 Nokia Corporation
5  * Contacts:    Juha Yrjola
6  *              Tony Lindgren
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12
13 #include <linux/string.h>
14 #include <linux/kernel.h>
15 #include <linux/platform_device.h>
16 #include <linux/mtd/onenand_regs.h>
17 #include <linux/io.h>
18 #include <linux/platform_data/mtd-onenand-omap2.h>
19 #include <linux/err.h>
20
21 #include <asm/mach/flash.h>
22
23 #include "gpmc.h"
24 #include "soc.h"
25 #include "gpmc-onenand.h"
26
27 #define ONENAND_IO_SIZE SZ_128K
28
29 #define ONENAND_FLAG_SYNCREAD   (1 << 0)
30 #define ONENAND_FLAG_SYNCWRITE  (1 << 1)
31 #define ONENAND_FLAG_HF         (1 << 2)
32 #define ONENAND_FLAG_VHF        (1 << 3)
33
34 static unsigned onenand_flags;
35 static unsigned latency;
36 static int fclk_offset;
37
38 static struct omap_onenand_platform_data *gpmc_onenand_data;
39
40 static struct resource gpmc_onenand_resource = {
41         .flags          = IORESOURCE_MEM,
42 };
43
44 static struct platform_device gpmc_onenand_device = {
45         .name           = "omap2-onenand",
46         .id             = -1,
47         .num_resources  = 1,
48         .resource       = &gpmc_onenand_resource,
49 };
50
51 static struct gpmc_timings omap2_onenand_calc_async_timings(void)
52 {
53         struct gpmc_timings t;
54
55         const int t_cer = 15;
56         const int t_avdp = 12;
57         const int t_aavdh = 7;
58         const int t_ce = 76;
59         const int t_aa = 76;
60         const int t_oe = 20;
61         const int t_cez = 20; /* max of t_cez, t_oez */
62         const int t_ds = 30;
63         const int t_wpl = 40;
64         const int t_wph = 30;
65
66         memset(&t, 0, sizeof(t));
67         t.sync_clk = 0;
68         t.cs_on = 0;
69         t.adv_on = 0;
70
71         /* Read */
72         t.adv_rd_off = gpmc_round_ns_to_ticks(max_t(int, t_avdp, t_cer));
73         t.oe_on  = t.adv_rd_off + gpmc_round_ns_to_ticks(t_aavdh);
74         t.access = t.adv_on + gpmc_round_ns_to_ticks(t_aa);
75         t.access = max_t(int, t.access, t.cs_on + gpmc_round_ns_to_ticks(t_ce));
76         t.access = max_t(int, t.access, t.oe_on + gpmc_round_ns_to_ticks(t_oe));
77         t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
78         t.cs_rd_off = t.oe_off;
79         t.rd_cycle  = t.cs_rd_off + gpmc_round_ns_to_ticks(t_cez);
80
81         /* Write */
82         t.adv_wr_off = t.adv_rd_off;
83         t.we_on  = t.oe_on;
84         if (cpu_is_omap34xx()) {
85                 t.wr_data_mux_bus = t.we_on;
86                 t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds);
87         }
88         t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl);
89         t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph);
90         t.wr_cycle  = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez);
91
92         return t;
93 }
94
95 static int gpmc_set_async_mode(int cs, struct gpmc_timings *t)
96 {
97         /* Configure GPMC for asynchronous read */
98         gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
99                           GPMC_CONFIG1_DEVICESIZE_16 |
100                           GPMC_CONFIG1_MUXADDDATA);
101
102         return gpmc_cs_set_timings(cs, t);
103 }
104
105 static void omap2_onenand_set_async_mode(void __iomem *onenand_base)
106 {
107         u32 reg;
108
109         /* Ensure sync read and sync write are disabled */
110         reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
111         reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE;
112         writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
113 }
114
115 static void set_onenand_cfg(void __iomem *onenand_base)
116 {
117         u32 reg;
118
119         reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
120         reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9));
121         reg |=  (latency << ONENAND_SYS_CFG1_BRL_SHIFT) |
122                 ONENAND_SYS_CFG1_BL_16;
123         if (onenand_flags & ONENAND_FLAG_SYNCREAD)
124                 reg |= ONENAND_SYS_CFG1_SYNC_READ;
125         else
126                 reg &= ~ONENAND_SYS_CFG1_SYNC_READ;
127         if (onenand_flags & ONENAND_FLAG_SYNCWRITE)
128                 reg |= ONENAND_SYS_CFG1_SYNC_WRITE;
129         else
130                 reg &= ~ONENAND_SYS_CFG1_SYNC_WRITE;
131         if (onenand_flags & ONENAND_FLAG_HF)
132                 reg |= ONENAND_SYS_CFG1_HF;
133         else
134                 reg &= ~ONENAND_SYS_CFG1_HF;
135         if (onenand_flags & ONENAND_FLAG_VHF)
136                 reg |= ONENAND_SYS_CFG1_VHF;
137         else
138                 reg &= ~ONENAND_SYS_CFG1_VHF;
139         writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
140 }
141
142 static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg,
143                                   void __iomem *onenand_base)
144 {
145         u16 ver = readw(onenand_base + ONENAND_REG_VERSION_ID);
146         int freq;
147
148         switch ((ver >> 4) & 0xf) {
149         case 0:
150                 freq = 40;
151                 break;
152         case 1:
153                 freq = 54;
154                 break;
155         case 2:
156                 freq = 66;
157                 break;
158         case 3:
159                 freq = 83;
160                 break;
161         case 4:
162                 freq = 104;
163                 break;
164         default:
165                 freq = 54;
166                 break;
167         }
168
169         return freq;
170 }
171
172 static struct gpmc_timings
173 omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
174                                 int freq)
175 {
176         struct gpmc_timings t;
177         const int t_cer  = 15;
178         const int t_avdp = 12;
179         const int t_cez  = 20; /* max of t_cez, t_oez */
180         const int t_ds   = 30;
181         const int t_wpl  = 40;
182         const int t_wph  = 30;
183         int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo;
184         u32 reg;
185         int div, fclk_offset_ns, gpmc_clk_ns;
186         int ticks_cez;
187         int cs = cfg->cs;
188
189         if (cfg->flags & ONENAND_SYNC_READ)
190                 onenand_flags = ONENAND_FLAG_SYNCREAD;
191         else if (cfg->flags & ONENAND_SYNC_READWRITE)
192                 onenand_flags = ONENAND_FLAG_SYNCREAD | ONENAND_FLAG_SYNCWRITE;
193
194         switch (freq) {
195         case 104:
196                 min_gpmc_clk_period = 9600; /* 104 MHz */
197                 t_ces   = 3;
198                 t_avds  = 4;
199                 t_avdh  = 2;
200                 t_ach   = 3;
201                 t_aavdh = 6;
202                 t_rdyo  = 6;
203                 break;
204         case 83:
205                 min_gpmc_clk_period = 12000; /* 83 MHz */
206                 t_ces   = 5;
207                 t_avds  = 4;
208                 t_avdh  = 2;
209                 t_ach   = 6;
210                 t_aavdh = 6;
211                 t_rdyo  = 9;
212                 break;
213         case 66:
214                 min_gpmc_clk_period = 15000; /* 66 MHz */
215                 t_ces   = 6;
216                 t_avds  = 5;
217                 t_avdh  = 2;
218                 t_ach   = 6;
219                 t_aavdh = 6;
220                 t_rdyo  = 11;
221                 break;
222         default:
223                 min_gpmc_clk_period = 18500; /* 54 MHz */
224                 t_ces   = 7;
225                 t_avds  = 7;
226                 t_avdh  = 7;
227                 t_ach   = 9;
228                 t_aavdh = 7;
229                 t_rdyo  = 15;
230                 onenand_flags &= ~ONENAND_FLAG_SYNCWRITE;
231                 break;
232         }
233
234         div = gpmc_calc_divider(min_gpmc_clk_period);
235         gpmc_clk_ns = gpmc_ticks_to_ns(div);
236         if (gpmc_clk_ns < 15) /* >66Mhz */
237                 onenand_flags |= ONENAND_FLAG_HF;
238         else
239                 onenand_flags &= ~ONENAND_FLAG_HF;
240         if (gpmc_clk_ns < 12) /* >83Mhz */
241                 onenand_flags |= ONENAND_FLAG_VHF;
242         else
243                 onenand_flags &= ~ONENAND_FLAG_VHF;
244         if (onenand_flags & ONENAND_FLAG_VHF)
245                 latency = 8;
246         else if (onenand_flags & ONENAND_FLAG_HF)
247                 latency = 6;
248         else if (gpmc_clk_ns >= 25) /* 40 MHz*/
249                 latency = 3;
250         else
251                 latency = 4;
252
253         /* Set synchronous read timings */
254         memset(&t, 0, sizeof(t));
255
256         if (div == 1) {
257                 reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
258                 reg |= (1 << 7);
259                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
260                 reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
261                 reg |= (1 << 7);
262                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
263                 reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
264                 reg |= (1 << 7);
265                 reg |= (1 << 23);
266                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
267         } else {
268                 reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
269                 reg &= ~(1 << 7);
270                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
271                 reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
272                 reg &= ~(1 << 7);
273                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
274                 reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
275                 reg &= ~(1 << 7);
276                 reg &= ~(1 << 23);
277                 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
278         }
279
280         t.sync_clk = min_gpmc_clk_period;
281         t.cs_on = 0;
282         t.adv_on = 0;
283         fclk_offset_ns = gpmc_round_ns_to_ticks(max_t(int, t_ces, t_avds));
284         fclk_offset = gpmc_ns_to_ticks(fclk_offset_ns);
285         t.page_burst_access = gpmc_clk_ns;
286
287         /* Read */
288         t.adv_rd_off = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_avdh));
289         t.oe_on = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_ach));
290         /* Force at least 1 clk between AVD High to OE Low */
291         if (t.oe_on <= t.adv_rd_off)
292                 t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(1);
293         t.access = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div);
294         t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
295         t.cs_rd_off = t.oe_off;
296         ticks_cez = ((gpmc_ns_to_ticks(t_cez) + div - 1) / div) * div;
297         t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div +
298                      ticks_cez);
299
300         /* Write */
301         if (onenand_flags & ONENAND_FLAG_SYNCWRITE) {
302                 t.adv_wr_off = t.adv_rd_off;
303                 t.we_on  = 0;
304                 t.we_off = t.cs_rd_off;
305                 t.cs_wr_off = t.cs_rd_off;
306                 t.wr_cycle  = t.rd_cycle;
307                 if (cpu_is_omap34xx()) {
308                         t.wr_data_mux_bus = gpmc_ticks_to_ns(fclk_offset +
309                                         gpmc_ps_to_ticks(min_gpmc_clk_period +
310                                         t_rdyo * 1000));
311                         t.wr_access = t.access;
312                 }
313         } else {
314                 t.adv_wr_off = gpmc_round_ns_to_ticks(max_t(int,
315                                                         t_avdp, t_cer));
316                 t.we_on  = t.adv_wr_off + gpmc_round_ns_to_ticks(t_aavdh);
317                 t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl);
318                 t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph);
319                 t.wr_cycle  = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez);
320                 if (cpu_is_omap34xx()) {
321                         t.wr_data_mux_bus = t.we_on;
322                         t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds);
323                 }
324         }
325
326         return t;
327 }
328
329 static int gpmc_set_sync_mode(int cs, struct gpmc_timings *t)
330 {
331         unsigned sync_read = onenand_flags & ONENAND_FLAG_SYNCREAD;
332         unsigned sync_write = onenand_flags & ONENAND_FLAG_SYNCWRITE;
333
334         /* Configure GPMC for synchronous read */
335         gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
336                           GPMC_CONFIG1_WRAPBURST_SUPP |
337                           GPMC_CONFIG1_READMULTIPLE_SUPP |
338                           (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) |
339                           (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) |
340                           (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) |
341                           GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) |
342                           GPMC_CONFIG1_PAGE_LEN(2) |
343                           (cpu_is_omap34xx() ? 0 :
344                                 (GPMC_CONFIG1_WAIT_READ_MON |
345                                  GPMC_CONFIG1_WAIT_PIN_SEL(0))) |
346                           GPMC_CONFIG1_DEVICESIZE_16 |
347                           GPMC_CONFIG1_DEVICETYPE_NOR |
348                           GPMC_CONFIG1_MUXADDDATA);
349
350         return gpmc_cs_set_timings(cs, t);
351 }
352
353 static int omap2_onenand_setup_async(void __iomem *onenand_base)
354 {
355         struct gpmc_timings t;
356         int ret;
357
358         omap2_onenand_set_async_mode(onenand_base);
359
360         t = omap2_onenand_calc_async_timings();
361
362         ret = gpmc_set_async_mode(gpmc_onenand_data->cs, &t);
363         if (IS_ERR_VALUE(ret))
364                 return ret;
365
366         omap2_onenand_set_async_mode(onenand_base);
367
368         return 0;
369 }
370
371 static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr)
372 {
373         int ret, freq = *freq_ptr;
374         struct gpmc_timings t;
375
376         if (!freq) {
377                 /* Very first call freq is not known */
378                 freq = omap2_onenand_get_freq(gpmc_onenand_data, onenand_base);
379                 set_onenand_cfg(onenand_base);
380         }
381
382         t = omap2_onenand_calc_sync_timings(gpmc_onenand_data, freq);
383
384         ret = gpmc_set_sync_mode(gpmc_onenand_data->cs, &t);
385         if (IS_ERR_VALUE(ret))
386                 return ret;
387
388         set_onenand_cfg(onenand_base);
389
390         *freq_ptr = freq;
391
392         return 0;
393 }
394
395 static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
396 {
397         struct device *dev = &gpmc_onenand_device.dev;
398         unsigned l = ONENAND_SYNC_READ | ONENAND_SYNC_READWRITE;
399         int ret;
400
401         ret = omap2_onenand_setup_async(onenand_base);
402         if (ret) {
403                 dev_err(dev, "unable to set to async mode\n");
404                 return ret;
405         }
406
407         if (!(gpmc_onenand_data->flags & l))
408                 return 0;
409
410         ret = omap2_onenand_setup_sync(onenand_base, freq_ptr);
411         if (ret)
412                 dev_err(dev, "unable to set to sync mode\n");
413         return ret;
414 }
415
416 void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
417 {
418         int err;
419
420         gpmc_onenand_data = _onenand_data;
421         gpmc_onenand_data->onenand_setup = gpmc_onenand_setup;
422         gpmc_onenand_device.dev.platform_data = gpmc_onenand_data;
423
424         if (cpu_is_omap24xx() &&
425                         (gpmc_onenand_data->flags & ONENAND_SYNC_READWRITE)) {
426                 printk(KERN_ERR "Onenand using only SYNC_READ on 24xx\n");
427                 gpmc_onenand_data->flags &= ~ONENAND_SYNC_READWRITE;
428                 gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
429         }
430
431         if (cpu_is_omap34xx())
432                 gpmc_onenand_data->flags |= ONENAND_IN_OMAP34XX;
433         else
434                 gpmc_onenand_data->flags &= ~ONENAND_IN_OMAP34XX;
435
436         err = gpmc_cs_request(gpmc_onenand_data->cs, ONENAND_IO_SIZE,
437                                 (unsigned long *)&gpmc_onenand_resource.start);
438         if (err < 0) {
439                 pr_err("%s: Cannot request GPMC CS\n", __func__);
440                 return;
441         }
442
443         gpmc_onenand_resource.end = gpmc_onenand_resource.start +
444                                                         ONENAND_IO_SIZE - 1;
445
446         if (platform_device_register(&gpmc_onenand_device) < 0) {
447                 pr_err("%s: Unable to register OneNAND device\n", __func__);
448                 gpmc_cs_free(gpmc_onenand_data->cs);
449                 return;
450         }
451 }