Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gpmc-onenand.c
Go to the documentation of this file.
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>
19 
20 #include <asm/mach/flash.h>
21 
22 #include <plat/gpmc.h>
23 
24 #include "soc.h"
25 
26 #define ONENAND_IO_SIZE SZ_128K
27 
28 static struct omap_onenand_platform_data *gpmc_onenand_data;
29 
30 static struct resource gpmc_onenand_resource = {
31  .flags = IORESOURCE_MEM,
32 };
33 
34 static struct platform_device gpmc_onenand_device = {
35  .name = "omap2-onenand",
36  .id = -1,
37  .num_resources = 1,
38  .resource = &gpmc_onenand_resource,
39 };
40 
41 static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
42 {
43  struct gpmc_timings t;
44  u32 reg;
45  int err;
46 
47  const int t_cer = 15;
48  const int t_avdp = 12;
49  const int t_aavdh = 7;
50  const int t_ce = 76;
51  const int t_aa = 76;
52  const int t_oe = 20;
53  const int t_cez = 20; /* max of t_cez, t_oez */
54  const int t_ds = 30;
55  const int t_wpl = 40;
56  const int t_wph = 30;
57 
58  /* Ensure sync read and sync write are disabled */
59  reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
61  writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
62 
63  memset(&t, 0, sizeof(t));
64  t.sync_clk = 0;
65  t.cs_on = 0;
66  t.adv_on = 0;
67 
68  /* Read */
69  t.adv_rd_off = gpmc_round_ns_to_ticks(max_t(int, t_avdp, t_cer));
70  t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(t_aavdh);
71  t.access = t.adv_on + gpmc_round_ns_to_ticks(t_aa);
72  t.access = max_t(int, t.access, t.cs_on + gpmc_round_ns_to_ticks(t_ce));
73  t.access = max_t(int, t.access, t.oe_on + gpmc_round_ns_to_ticks(t_oe));
74  t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
75  t.cs_rd_off = t.oe_off;
76  t.rd_cycle = t.cs_rd_off + gpmc_round_ns_to_ticks(t_cez);
77 
78  /* Write */
79  t.adv_wr_off = t.adv_rd_off;
80  t.we_on = t.oe_on;
81  if (cpu_is_omap34xx()) {
82  t.wr_data_mux_bus = t.we_on;
83  t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds);
84  }
85  t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl);
86  t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph);
87  t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez);
88 
89  /* Configure GPMC for asynchronous read */
93 
94  err = gpmc_cs_set_timings(cs, &t);
95  if (err)
96  return err;
97 
98  /* Ensure sync read and sync write are disabled */
99  reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
101  writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
102 
103  return 0;
104 }
105 
106 static void set_onenand_cfg(void __iomem *onenand_base, int latency,
107  int sync_read, int sync_write, int hf, int vhf)
108 {
109  u32 reg;
110 
111  reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
112  reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9));
113  reg |= (latency << ONENAND_SYS_CFG1_BRL_SHIFT) |
115  if (sync_read)
117  else
119  if (sync_write)
121  else
123  if (hf)
124  reg |= ONENAND_SYS_CFG1_HF;
125  else
126  reg &= ~ONENAND_SYS_CFG1_HF;
127  if (vhf)
128  reg |= ONENAND_SYS_CFG1_VHF;
129  else
130  reg &= ~ONENAND_SYS_CFG1_VHF;
131  writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
132 }
133 
134 static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg,
135  void __iomem *onenand_base, bool *clk_dep)
136 {
137  u16 ver = readw(onenand_base + ONENAND_REG_VERSION_ID);
138  int freq = 0;
139 
140  if (cfg->get_freq) {
141  struct onenand_freq_info fi;
142 
143  fi.maf_id = readw(onenand_base + ONENAND_REG_MANUFACTURER_ID);
144  fi.dev_id = readw(onenand_base + ONENAND_REG_DEVICE_ID);
145  fi.ver_id = ver;
146  freq = cfg->get_freq(&fi, clk_dep);
147  if (freq)
148  return freq;
149  }
150 
151  switch ((ver >> 4) & 0xf) {
152  case 0:
153  freq = 40;
154  break;
155  case 1:
156  freq = 54;
157  break;
158  case 2:
159  freq = 66;
160  break;
161  case 3:
162  freq = 83;
163  break;
164  case 4:
165  freq = 104;
166  break;
167  default:
168  freq = 54;
169  break;
170  }
171 
172  return freq;
173 }
174 
175 static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
176  void __iomem *onenand_base,
177  int *freq_ptr)
178 {
179  struct gpmc_timings t;
180  const int t_cer = 15;
181  const int t_avdp = 12;
182  const int t_cez = 20; /* max of t_cez, t_oez */
183  const int t_ds = 30;
184  const int t_wpl = 40;
185  const int t_wph = 30;
186  int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo;
187  int div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency;
188  int first_time = 0, hf = 0, vhf = 0, sync_read = 0, sync_write = 0;
189  int err, ticks_cez;
190  int cs = cfg->cs, freq = *freq_ptr;
191  u32 reg;
192  bool clk_dep = false;
193 
194  if (cfg->flags & ONENAND_SYNC_READ) {
195  sync_read = 1;
196  } else if (cfg->flags & ONENAND_SYNC_READWRITE) {
197  sync_read = 1;
198  sync_write = 1;
199  } else
200  return omap2_onenand_set_async_mode(cs, onenand_base);
201 
202  if (!freq) {
203  /* Very first call freq is not known */
204  err = omap2_onenand_set_async_mode(cs, onenand_base);
205  if (err)
206  return err;
207  freq = omap2_onenand_get_freq(cfg, onenand_base, &clk_dep);
208  first_time = 1;
209  }
210 
211  switch (freq) {
212  case 104:
213  min_gpmc_clk_period = 9600; /* 104 MHz */
214  t_ces = 3;
215  t_avds = 4;
216  t_avdh = 2;
217  t_ach = 3;
218  t_aavdh = 6;
219  t_rdyo = 6;
220  break;
221  case 83:
222  min_gpmc_clk_period = 12000; /* 83 MHz */
223  t_ces = 5;
224  t_avds = 4;
225  t_avdh = 2;
226  t_ach = 6;
227  t_aavdh = 6;
228  t_rdyo = 9;
229  break;
230  case 66:
231  min_gpmc_clk_period = 15000; /* 66 MHz */
232  t_ces = 6;
233  t_avds = 5;
234  t_avdh = 2;
235  t_ach = 6;
236  t_aavdh = 6;
237  t_rdyo = 11;
238  break;
239  default:
240  min_gpmc_clk_period = 18500; /* 54 MHz */
241  t_ces = 7;
242  t_avds = 7;
243  t_avdh = 7;
244  t_ach = 9;
245  t_aavdh = 7;
246  t_rdyo = 15;
247  sync_write = 0;
248  break;
249  }
250 
251  div = gpmc_cs_calc_divider(cs, min_gpmc_clk_period);
252  gpmc_clk_ns = gpmc_ticks_to_ns(div);
253  if (gpmc_clk_ns < 15) /* >66Mhz */
254  hf = 1;
255  if (gpmc_clk_ns < 12) /* >83Mhz */
256  vhf = 1;
257  if (vhf)
258  latency = 8;
259  else if (hf)
260  latency = 6;
261  else if (gpmc_clk_ns >= 25) /* 40 MHz*/
262  latency = 3;
263  else
264  latency = 4;
265 
266  if (clk_dep) {
267  if (gpmc_clk_ns < 12) { /* >83Mhz */
268  t_ces = 3;
269  t_avds = 4;
270  } else if (gpmc_clk_ns < 15) { /* >66Mhz */
271  t_ces = 5;
272  t_avds = 4;
273  } else if (gpmc_clk_ns < 25) { /* >40Mhz */
274  t_ces = 6;
275  t_avds = 5;
276  } else {
277  t_ces = 7;
278  t_avds = 7;
279  }
280  }
281 
282  if (first_time)
283  set_onenand_cfg(onenand_base, latency,
284  sync_read, sync_write, hf, vhf);
285 
286  if (div == 1) {
288  reg |= (1 << 7);
291  reg |= (1 << 7);
294  reg |= (1 << 7);
295  reg |= (1 << 23);
297  } else {
299  reg &= ~(1 << 7);
302  reg &= ~(1 << 7);
305  reg &= ~(1 << 7);
306  reg &= ~(1 << 23);
308  }
309 
310  /* Set synchronous read timings */
311  memset(&t, 0, sizeof(t));
312  t.sync_clk = min_gpmc_clk_period;
313  t.cs_on = 0;
314  t.adv_on = 0;
315  fclk_offset_ns = gpmc_round_ns_to_ticks(max_t(int, t_ces, t_avds));
316  fclk_offset = gpmc_ns_to_ticks(fclk_offset_ns);
317  t.page_burst_access = gpmc_clk_ns;
318 
319  /* Read */
320  t.adv_rd_off = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_avdh));
321  t.oe_on = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_ach));
322  /* Force at least 1 clk between AVD High to OE Low */
323  if (t.oe_on <= t.adv_rd_off)
324  t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(1);
325  t.access = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div);
326  t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
327  t.cs_rd_off = t.oe_off;
328  ticks_cez = ((gpmc_ns_to_ticks(t_cez) + div - 1) / div) * div;
329  t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div +
330  ticks_cez);
331 
332  /* Write */
333  if (sync_write) {
334  t.adv_wr_off = t.adv_rd_off;
335  t.we_on = 0;
336  t.we_off = t.cs_rd_off;
337  t.cs_wr_off = t.cs_rd_off;
338  t.wr_cycle = t.rd_cycle;
339  if (cpu_is_omap34xx()) {
340  t.wr_data_mux_bus = gpmc_ticks_to_ns(fclk_offset +
341  gpmc_ps_to_ticks(min_gpmc_clk_period +
342  t_rdyo * 1000));
343  t.wr_access = t.access;
344  }
345  } else {
346  t.adv_wr_off = gpmc_round_ns_to_ticks(max_t(int,
347  t_avdp, t_cer));
348  t.we_on = t.adv_wr_off + gpmc_round_ns_to_ticks(t_aavdh);
349  t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl);
350  t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph);
351  t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez);
352  if (cpu_is_omap34xx()) {
353  t.wr_data_mux_bus = t.we_on;
354  t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds);
355  }
356  }
357 
358  /* Configure GPMC for synchronous read */
362  (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) |
363  (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) |
364  (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) |
365  GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) |
367  (cpu_is_omap34xx() ? 0 :
373 
374  err = gpmc_cs_set_timings(cs, &t);
375  if (err)
376  return err;
377 
378  set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf, vhf);
379 
380  *freq_ptr = freq;
381 
382  return 0;
383 }
384 
385 static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
386 {
387  struct device *dev = &gpmc_onenand_device.dev;
388 
389  /* Set sync timings in GPMC */
390  if (omap2_onenand_set_sync_mode(gpmc_onenand_data, onenand_base,
391  freq_ptr) < 0) {
392  dev_err(dev, "Unable to set synchronous mode\n");
393  return -EINVAL;
394  }
395 
396  return 0;
397 }
398 
400 {
401  int err;
402 
403  gpmc_onenand_data = _onenand_data;
404  gpmc_onenand_data->onenand_setup = gpmc_onenand_setup;
405  gpmc_onenand_device.dev.platform_data = gpmc_onenand_data;
406 
407  if (cpu_is_omap24xx() &&
408  (gpmc_onenand_data->flags & ONENAND_SYNC_READWRITE)) {
409  printk(KERN_ERR "Onenand using only SYNC_READ on 24xx\n");
410  gpmc_onenand_data->flags &= ~ONENAND_SYNC_READWRITE;
411  gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
412  }
413 
414  err = gpmc_cs_request(gpmc_onenand_data->cs, ONENAND_IO_SIZE,
415  (unsigned long *)&gpmc_onenand_resource.start);
416  if (err < 0) {
417  pr_err("%s: Cannot request GPMC CS\n", __func__);
418  return;
419  }
420 
421  gpmc_onenand_resource.end = gpmc_onenand_resource.start +
422  ONENAND_IO_SIZE - 1;
423 
424  if (platform_device_register(&gpmc_onenand_device) < 0) {
425  pr_err("%s: Unable to register OneNAND device\n", __func__);
426  gpmc_cs_free(gpmc_onenand_data->cs);
427  return;
428  }
429 }