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/kernel.h>
14 #include <linux/platform_device.h>
15 #include <linux/mtd/onenand_regs.h>
18 #include <asm/mach/flash.h>
20 #include <mach/onenand.h>
21 #include <mach/board.h>
22 #include <mach/gpmc.h>
24 static struct omap_onenand_platform_data
*gpmc_onenand_data
;
26 static struct platform_device gpmc_onenand_device
= {
27 .name
= "omap2-onenand",
31 static int omap2_onenand_set_async_mode(int cs
, void __iomem
*onenand_base
)
33 struct gpmc_timings t
;
36 const int t_avdp
= 12;
37 const int t_aavdh
= 7;
41 const int t_cez
= 20; /* max of t_cez, t_oez */
46 memset(&t
, 0, sizeof(t
));
52 t
.adv_rd_off
= gpmc_round_ns_to_ticks(max_t(int, t_avdp
, t_cer
));
53 t
.oe_on
= t
.adv_rd_off
+ gpmc_round_ns_to_ticks(t_aavdh
);
54 t
.access
= t
.adv_on
+ gpmc_round_ns_to_ticks(t_aa
);
55 t
.access
= max_t(int, t
.access
, t
.cs_on
+ gpmc_round_ns_to_ticks(t_ce
));
56 t
.access
= max_t(int, t
.access
, t
.oe_on
+ gpmc_round_ns_to_ticks(t_oe
));
57 t
.oe_off
= t
.access
+ gpmc_round_ns_to_ticks(1);
58 t
.cs_rd_off
= t
.oe_off
;
59 t
.rd_cycle
= t
.cs_rd_off
+ gpmc_round_ns_to_ticks(t_cez
);
62 t
.adv_wr_off
= t
.adv_rd_off
;
64 if (cpu_is_omap34xx()) {
65 t
.wr_data_mux_bus
= t
.we_on
;
66 t
.wr_access
= t
.we_on
+ gpmc_round_ns_to_ticks(t_ds
);
68 t
.we_off
= t
.we_on
+ gpmc_round_ns_to_ticks(t_wpl
);
69 t
.cs_wr_off
= t
.we_off
+ gpmc_round_ns_to_ticks(t_wph
);
70 t
.wr_cycle
= t
.cs_wr_off
+ gpmc_round_ns_to_ticks(t_cez
);
72 /* Configure GPMC for asynchronous read */
73 gpmc_cs_write_reg(cs
, GPMC_CS_CONFIG1
,
74 GPMC_CONFIG1_DEVICESIZE_16
|
75 GPMC_CONFIG1_MUXADDDATA
);
77 return gpmc_cs_set_timings(cs
, &t
);
80 static void set_onenand_cfg(void __iomem
*onenand_base
, int latency
,
81 int sync_read
, int sync_write
, int hf
)
85 reg
= readw(onenand_base
+ ONENAND_REG_SYS_CFG1
);
86 reg
&= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT
) | (0x7 << 9));
87 reg
|= (latency
<< ONENAND_SYS_CFG1_BRL_SHIFT
) |
88 ONENAND_SYS_CFG1_BL_16
;
90 reg
|= ONENAND_SYS_CFG1_SYNC_READ
;
92 reg
&= ~ONENAND_SYS_CFG1_SYNC_READ
;
94 reg
|= ONENAND_SYS_CFG1_SYNC_WRITE
;
96 reg
&= ~ONENAND_SYS_CFG1_SYNC_WRITE
;
98 reg
|= ONENAND_SYS_CFG1_HF
;
100 reg
&= ~ONENAND_SYS_CFG1_HF
;
101 writew(reg
, onenand_base
+ ONENAND_REG_SYS_CFG1
);
104 static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data
*cfg
,
105 void __iomem
*onenand_base
,
108 struct gpmc_timings t
;
109 const int t_cer
= 15;
110 const int t_avdp
= 12;
111 const int t_cez
= 20; /* max of t_cez, t_oez */
113 const int t_wpl
= 40;
114 const int t_wph
= 30;
115 int min_gpmc_clk_period
, t_ces
, t_avds
, t_avdh
, t_ach
, t_aavdh
, t_rdyo
;
116 int tick_ns
, div
, fclk_offset_ns
, fclk_offset
, gpmc_clk_ns
, latency
;
117 int first_time
= 0, hf
= 0, sync_read
= 0, sync_write
= 0;
122 if (cfg
->flags
& ONENAND_SYNC_READ
) {
124 } else if (cfg
->flags
& ONENAND_SYNC_READWRITE
) {
130 /* Very first call freq is not known */
131 err
= omap2_onenand_set_async_mode(cs
, onenand_base
);
134 reg
= readw(onenand_base
+ ONENAND_REG_VERSION_ID
);
135 switch ((reg
>> 4) & 0xf) {
160 min_gpmc_clk_period
= 12; /* 83 MHz */
169 min_gpmc_clk_period
= 15; /* 66 MHz */
178 min_gpmc_clk_period
= 18; /* 54 MHz */
189 tick_ns
= gpmc_ticks_to_ns(1);
190 div
= gpmc_cs_calc_divider(cs
, min_gpmc_clk_period
);
191 gpmc_clk_ns
= gpmc_ticks_to_ns(div
);
192 if (gpmc_clk_ns
< 15) /* >66Mhz */
196 else if (gpmc_clk_ns
>= 25) /* 40 MHz*/
202 set_onenand_cfg(onenand_base
, latency
,
203 sync_read
, sync_write
, hf
);
206 reg
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG2
);
208 gpmc_cs_write_reg(cs
, GPMC_CS_CONFIG2
, reg
);
209 reg
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG3
);
211 gpmc_cs_write_reg(cs
, GPMC_CS_CONFIG3
, reg
);
212 reg
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG4
);
215 gpmc_cs_write_reg(cs
, GPMC_CS_CONFIG4
, reg
);
217 reg
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG2
);
219 gpmc_cs_write_reg(cs
, GPMC_CS_CONFIG2
, reg
);
220 reg
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG3
);
222 gpmc_cs_write_reg(cs
, GPMC_CS_CONFIG3
, reg
);
223 reg
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG4
);
226 gpmc_cs_write_reg(cs
, GPMC_CS_CONFIG4
, reg
);
229 /* Set synchronous read timings */
230 memset(&t
, 0, sizeof(t
));
231 t
.sync_clk
= min_gpmc_clk_period
;
234 fclk_offset_ns
= gpmc_round_ns_to_ticks(max_t(int, t_ces
, t_avds
));
235 fclk_offset
= gpmc_ns_to_ticks(fclk_offset_ns
);
236 t
.page_burst_access
= gpmc_clk_ns
;
239 t
.adv_rd_off
= gpmc_ticks_to_ns(fclk_offset
+ gpmc_ns_to_ticks(t_avdh
));
240 t
.oe_on
= gpmc_ticks_to_ns(fclk_offset
+ gpmc_ns_to_ticks(t_ach
));
241 t
.access
= gpmc_ticks_to_ns(fclk_offset
+ (latency
+ 1) * div
);
242 t
.oe_off
= t
.access
+ gpmc_round_ns_to_ticks(1);
243 t
.cs_rd_off
= t
.oe_off
;
244 ticks_cez
= ((gpmc_ns_to_ticks(t_cez
) + div
- 1) / div
) * div
;
245 t
.rd_cycle
= gpmc_ticks_to_ns(fclk_offset
+ (latency
+ 1) * div
+
250 t
.adv_wr_off
= t
.adv_rd_off
;
252 t
.we_off
= t
.cs_rd_off
;
253 t
.cs_wr_off
= t
.cs_rd_off
;
254 t
.wr_cycle
= t
.rd_cycle
;
255 if (cpu_is_omap34xx()) {
256 t
.wr_data_mux_bus
= gpmc_ticks_to_ns(fclk_offset
+
257 gpmc_ns_to_ticks(min_gpmc_clk_period
+
259 t
.wr_access
= t
.access
;
262 t
.adv_wr_off
= gpmc_round_ns_to_ticks(max_t(int,
264 t
.we_on
= t
.adv_wr_off
+ gpmc_round_ns_to_ticks(t_aavdh
);
265 t
.we_off
= t
.we_on
+ gpmc_round_ns_to_ticks(t_wpl
);
266 t
.cs_wr_off
= t
.we_off
+ gpmc_round_ns_to_ticks(t_wph
);
267 t
.wr_cycle
= t
.cs_wr_off
+ gpmc_round_ns_to_ticks(t_cez
);
268 if (cpu_is_omap34xx()) {
269 t
.wr_data_mux_bus
= t
.we_on
;
270 t
.wr_access
= t
.we_on
+ gpmc_round_ns_to_ticks(t_ds
);
274 /* Configure GPMC for synchronous read */
275 gpmc_cs_write_reg(cs
, GPMC_CS_CONFIG1
,
276 GPMC_CONFIG1_WRAPBURST_SUPP
|
277 GPMC_CONFIG1_READMULTIPLE_SUPP
|
278 (sync_read
? GPMC_CONFIG1_READTYPE_SYNC
: 0) |
279 (sync_write
? GPMC_CONFIG1_WRITEMULTIPLE_SUPP
: 0) |
280 (sync_write
? GPMC_CONFIG1_WRITETYPE_SYNC
: 0) |
281 GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset
) |
282 GPMC_CONFIG1_PAGE_LEN(2) |
283 (cpu_is_omap34xx() ? 0 :
284 (GPMC_CONFIG1_WAIT_READ_MON
|
285 GPMC_CONFIG1_WAIT_PIN_SEL(0))) |
286 GPMC_CONFIG1_DEVICESIZE_16
|
287 GPMC_CONFIG1_DEVICETYPE_NOR
|
288 GPMC_CONFIG1_MUXADDDATA
);
290 err
= gpmc_cs_set_timings(cs
, &t
);
294 set_onenand_cfg(onenand_base
, latency
, sync_read
, sync_write
, hf
);
299 static int gpmc_onenand_setup(void __iomem
*onenand_base
, int freq
)
301 struct device
*dev
= &gpmc_onenand_device
.dev
;
303 /* Set sync timings in GPMC */
304 if (omap2_onenand_set_sync_mode(gpmc_onenand_data
, onenand_base
,
306 dev_err(dev
, "Unable to set synchronous mode\n");
313 void __init
gpmc_onenand_init(struct omap_onenand_platform_data
*_onenand_data
)
315 gpmc_onenand_data
= _onenand_data
;
316 gpmc_onenand_data
->onenand_setup
= gpmc_onenand_setup
;
317 gpmc_onenand_device
.dev
.platform_data
= gpmc_onenand_data
;
319 if (cpu_is_omap24xx() &&
320 (gpmc_onenand_data
->flags
& ONENAND_SYNC_READWRITE
)) {
321 printk(KERN_ERR
"Onenand using only SYNC_READ on 24xx\n");
322 gpmc_onenand_data
->flags
&= ~ONENAND_SYNC_READWRITE
;
323 gpmc_onenand_data
->flags
|= ONENAND_SYNC_READ
;
326 if (platform_device_register(&gpmc_onenand_device
) < 0) {
327 printk(KERN_ERR
"Unable to register OneNAND device\n");