2 * linux/arch/arm/mach-omap2/gpmc-onenand.c
4 * Copyright (C) 2006 - 2009 Nokia Corporation
5 * Contacts: Juha Yrjola
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.
13 #include <linux/string.h>
14 #include <linux/kernel.h>
15 #include <linux/platform_device.h>
16 #include <linux/mtd/onenand_regs.h>
19 #include <asm/mach/flash.h>
22 #include <plat/onenand.h>
23 #include <plat/board.h>
24 #include <plat/gpmc.h>
26 #define ONENAND_IO_SIZE SZ_128K
28 static struct omap_onenand_platform_data
*gpmc_onenand_data
;
30 static struct resource gpmc_onenand_resource
= {
31 .flags
= IORESOURCE_MEM
,
34 static struct platform_device gpmc_onenand_device
= {
35 .name
= "omap2-onenand",
38 .resource
= &gpmc_onenand_resource
,
41 static int omap2_onenand_set_async_mode(int cs
, void __iomem
*onenand_base
)
43 struct gpmc_timings t
;
48 const int t_avdp
= 12;
49 const int t_aavdh
= 7;
53 const int t_cez
= 20; /* max of t_cez, t_oez */
58 /* Ensure sync read and sync write are disabled */
59 reg
= readw(onenand_base
+ ONENAND_REG_SYS_CFG1
);
60 reg
&= ~ONENAND_SYS_CFG1_SYNC_READ
& ~ONENAND_SYS_CFG1_SYNC_WRITE
;
61 writew(reg
, onenand_base
+ ONENAND_REG_SYS_CFG1
);
63 memset(&t
, 0, sizeof(t
));
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
);
79 t
.adv_wr_off
= t
.adv_rd_off
;
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
);
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
);
89 /* Configure GPMC for asynchronous read */
90 gpmc_cs_write_reg(cs
, GPMC_CS_CONFIG1
,
91 GPMC_CONFIG1_DEVICESIZE_16
|
92 GPMC_CONFIG1_MUXADDDATA
);
94 err
= gpmc_cs_set_timings(cs
, &t
);
98 /* Ensure sync read and sync write are disabled */
99 reg
= readw(onenand_base
+ ONENAND_REG_SYS_CFG1
);
100 reg
&= ~ONENAND_SYS_CFG1_SYNC_READ
& ~ONENAND_SYS_CFG1_SYNC_WRITE
;
101 writew(reg
, onenand_base
+ ONENAND_REG_SYS_CFG1
);
106 static void set_onenand_cfg(void __iomem
*onenand_base
, int latency
,
107 int sync_read
, int sync_write
, int hf
, int vhf
)
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
) |
114 ONENAND_SYS_CFG1_BL_16
;
116 reg
|= ONENAND_SYS_CFG1_SYNC_READ
;
118 reg
&= ~ONENAND_SYS_CFG1_SYNC_READ
;
120 reg
|= ONENAND_SYS_CFG1_SYNC_WRITE
;
122 reg
&= ~ONENAND_SYS_CFG1_SYNC_WRITE
;
124 reg
|= ONENAND_SYS_CFG1_HF
;
126 reg
&= ~ONENAND_SYS_CFG1_HF
;
128 reg
|= ONENAND_SYS_CFG1_VHF
;
130 reg
&= ~ONENAND_SYS_CFG1_VHF
;
131 writew(reg
, onenand_base
+ ONENAND_REG_SYS_CFG1
);
134 static int omap2_onenand_get_freq(struct omap_onenand_platform_data
*cfg
,
135 void __iomem
*onenand_base
, bool *clk_dep
)
137 u16 ver
= readw(onenand_base
+ ONENAND_REG_VERSION_ID
);
141 struct onenand_freq_info fi
;
143 fi
.maf_id
= readw(onenand_base
+ ONENAND_REG_MANUFACTURER_ID
);
144 fi
.dev_id
= readw(onenand_base
+ ONENAND_REG_DEVICE_ID
);
146 freq
= cfg
->get_freq(&fi
, clk_dep
);
151 switch ((ver
>> 4) & 0xf) {
175 static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data
*cfg
,
176 void __iomem
*onenand_base
,
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 */
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;
190 int cs
= cfg
->cs
, freq
= *freq_ptr
;
192 bool clk_dep
= false;
194 if (cfg
->flags
& ONENAND_SYNC_READ
) {
196 } else if (cfg
->flags
& ONENAND_SYNC_READWRITE
) {
200 return omap2_onenand_set_async_mode(cs
, onenand_base
);
203 /* Very first call freq is not known */
204 err
= omap2_onenand_set_async_mode(cs
, onenand_base
);
207 freq
= omap2_onenand_get_freq(cfg
, onenand_base
, &clk_dep
);
213 min_gpmc_clk_period
= 9600; /* 104 MHz */
222 min_gpmc_clk_period
= 12000; /* 83 MHz */
231 min_gpmc_clk_period
= 15000; /* 66 MHz */
240 min_gpmc_clk_period
= 18500; /* 54 MHz */
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 */
255 if (gpmc_clk_ns
< 12) /* >83Mhz */
261 else if (gpmc_clk_ns
>= 25) /* 40 MHz*/
267 if (gpmc_clk_ns
< 12) { /* >83Mhz */
270 } else if (gpmc_clk_ns
< 15) { /* >66Mhz */
273 } else if (gpmc_clk_ns
< 25) { /* >40Mhz */
283 set_onenand_cfg(onenand_base
, latency
,
284 sync_read
, sync_write
, hf
, vhf
);
287 reg
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG2
);
289 gpmc_cs_write_reg(cs
, GPMC_CS_CONFIG2
, reg
);
290 reg
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG3
);
292 gpmc_cs_write_reg(cs
, GPMC_CS_CONFIG3
, reg
);
293 reg
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG4
);
296 gpmc_cs_write_reg(cs
, GPMC_CS_CONFIG4
, reg
);
298 reg
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG2
);
300 gpmc_cs_write_reg(cs
, GPMC_CS_CONFIG2
, reg
);
301 reg
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG3
);
303 gpmc_cs_write_reg(cs
, GPMC_CS_CONFIG3
, reg
);
304 reg
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG4
);
307 gpmc_cs_write_reg(cs
, GPMC_CS_CONFIG4
, reg
);
310 /* Set synchronous read timings */
311 memset(&t
, 0, sizeof(t
));
312 t
.sync_clk
= min_gpmc_clk_period
;
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
;
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
+
334 t
.adv_wr_off
= t
.adv_rd_off
;
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
+
343 t
.wr_access
= t
.access
;
346 t
.adv_wr_off
= gpmc_round_ns_to_ticks(max_t(int,
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
);
358 /* Configure GPMC for synchronous read */
359 gpmc_cs_write_reg(cs
, GPMC_CS_CONFIG1
,
360 GPMC_CONFIG1_WRAPBURST_SUPP
|
361 GPMC_CONFIG1_READMULTIPLE_SUPP
|
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
) |
366 GPMC_CONFIG1_PAGE_LEN(2) |
367 (cpu_is_omap34xx() ? 0 :
368 (GPMC_CONFIG1_WAIT_READ_MON
|
369 GPMC_CONFIG1_WAIT_PIN_SEL(0))) |
370 GPMC_CONFIG1_DEVICESIZE_16
|
371 GPMC_CONFIG1_DEVICETYPE_NOR
|
372 GPMC_CONFIG1_MUXADDDATA
);
374 err
= gpmc_cs_set_timings(cs
, &t
);
378 set_onenand_cfg(onenand_base
, latency
, sync_read
, sync_write
, hf
, vhf
);
385 static int gpmc_onenand_setup(void __iomem
*onenand_base
, int *freq_ptr
)
387 struct device
*dev
= &gpmc_onenand_device
.dev
;
389 /* Set sync timings in GPMC */
390 if (omap2_onenand_set_sync_mode(gpmc_onenand_data
, onenand_base
,
392 dev_err(dev
, "Unable to set synchronous mode\n");
399 void __init
gpmc_onenand_init(struct omap_onenand_platform_data
*_onenand_data
)
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
;
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
;
414 err
= gpmc_cs_request(gpmc_onenand_data
->cs
, ONENAND_IO_SIZE
,
415 (unsigned long *)&gpmc_onenand_resource
.start
);
417 pr_err("%s: Cannot request GPMC CS\n", __func__
);
421 gpmc_onenand_resource
.end
= gpmc_onenand_resource
.start
+
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
);