2 * GPMC support functions
4 * Copyright (C) 2005-2006 Nokia Corporation
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.
14 #include <linux/kernel.h>
15 #include <linux/init.h>
16 #include <linux/err.h>
17 #include <linux/clk.h>
18 #include <linux/ioport.h>
19 #include <linux/spinlock.h>
21 #include <linux/module.h>
23 #include <asm/mach-types.h>
24 #include <mach/gpmc.h>
26 #include <mach/sdrc.h>
28 /* GPMC register offsets */
29 #define GPMC_REVISION 0x00
30 #define GPMC_SYSCONFIG 0x10
31 #define GPMC_SYSSTATUS 0x14
32 #define GPMC_IRQSTATUS 0x18
33 #define GPMC_IRQENABLE 0x1c
34 #define GPMC_TIMEOUT_CONTROL 0x40
35 #define GPMC_ERR_ADDRESS 0x44
36 #define GPMC_ERR_TYPE 0x48
37 #define GPMC_CONFIG 0x50
38 #define GPMC_STATUS 0x54
39 #define GPMC_PREFETCH_CONFIG1 0x1e0
40 #define GPMC_PREFETCH_CONFIG2 0x1e4
41 #define GPMC_PREFETCH_CONTROL 0x1ec
42 #define GPMC_PREFETCH_STATUS 0x1f0
43 #define GPMC_ECC_CONFIG 0x1f4
44 #define GPMC_ECC_CONTROL 0x1f8
45 #define GPMC_ECC_SIZE_CONFIG 0x1fc
48 #define GPMC_CS_SIZE 0x30
50 #define GPMC_MEM_START 0x00000000
51 #define GPMC_MEM_END 0x3FFFFFFF
52 #define BOOT_ROM_SPACE 0x100000 /* 1MB */
54 #define GPMC_CHUNK_SHIFT 24 /* 16 MB */
55 #define GPMC_SECTION_SHIFT 28 /* 128 MB */
57 static struct resource gpmc_mem_root
;
58 static struct resource gpmc_cs_mem
[GPMC_CS_NUM
];
59 static DEFINE_SPINLOCK(gpmc_mem_lock
);
60 static unsigned gpmc_cs_map
;
62 static void __iomem
*gpmc_base
;
64 static struct clk
*gpmc_l3_clk
;
66 static void gpmc_write_reg(int idx
, u32 val
)
68 __raw_writel(val
, gpmc_base
+ idx
);
71 static u32
gpmc_read_reg(int idx
)
73 return __raw_readl(gpmc_base
+ idx
);
76 void gpmc_cs_write_reg(int cs
, int idx
, u32 val
)
78 void __iomem
*reg_addr
;
80 reg_addr
= gpmc_base
+ GPMC_CS0
+ (cs
* GPMC_CS_SIZE
) + idx
;
81 __raw_writel(val
, reg_addr
);
84 u32
gpmc_cs_read_reg(int cs
, int idx
)
86 void __iomem
*reg_addr
;
88 reg_addr
= gpmc_base
+ GPMC_CS0
+ (cs
* GPMC_CS_SIZE
) + idx
;
89 return __raw_readl(reg_addr
);
92 /* TODO: Add support for gpmc_fck to clock framework and use it */
93 unsigned long gpmc_get_fclk_period(void)
95 unsigned long rate
= clk_get_rate(gpmc_l3_clk
);
98 printk(KERN_WARNING
"gpmc_l3_clk not enabled\n");
103 rate
= 1000000000 / rate
; /* In picoseconds */
108 unsigned int gpmc_ns_to_ticks(unsigned int time_ns
)
110 unsigned long tick_ps
;
112 /* Calculate in picosecs to yield more exact results */
113 tick_ps
= gpmc_get_fclk_period();
115 return (time_ns
* 1000 + tick_ps
- 1) / tick_ps
;
118 unsigned int gpmc_ticks_to_ns(unsigned int ticks
)
120 return ticks
* gpmc_get_fclk_period() / 1000;
123 unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns
)
125 unsigned long ticks
= gpmc_ns_to_ticks(time_ns
);
127 return ticks
* gpmc_get_fclk_period() / 1000;
131 static int set_gpmc_timing_reg(int cs
, int reg
, int st_bit
, int end_bit
,
132 int time
, const char *name
)
134 static int set_gpmc_timing_reg(int cs
, int reg
, int st_bit
, int end_bit
,
139 int ticks
, mask
, nr_bits
;
144 ticks
= gpmc_ns_to_ticks(time
);
145 nr_bits
= end_bit
- st_bit
+ 1;
146 if (ticks
>= 1 << nr_bits
) {
148 printk(KERN_INFO
"GPMC CS%d: %-10s* %3d ns, %3d ticks >= %d\n",
149 cs
, name
, time
, ticks
, 1 << nr_bits
);
154 mask
= (1 << nr_bits
) - 1;
155 l
= gpmc_cs_read_reg(cs
, reg
);
158 "GPMC CS%d: %-10s: %3d ticks, %3lu ns (was %3i ticks) %3d ns\n",
159 cs
, name
, ticks
, gpmc_get_fclk_period() * ticks
/ 1000,
160 (l
>> st_bit
) & mask
, time
);
162 l
&= ~(mask
<< st_bit
);
163 l
|= ticks
<< st_bit
;
164 gpmc_cs_write_reg(cs
, reg
, l
);
170 #define GPMC_SET_ONE(reg, st, end, field) \
171 if (set_gpmc_timing_reg(cs, (reg), (st), (end), \
172 t->field, #field) < 0) \
175 #define GPMC_SET_ONE(reg, st, end, field) \
176 if (set_gpmc_timing_reg(cs, (reg), (st), (end), t->field) < 0) \
180 int gpmc_cs_calc_divider(int cs
, unsigned int sync_clk
)
185 l
= sync_clk
* 1000 + (gpmc_get_fclk_period() - 1);
186 div
= l
/ gpmc_get_fclk_period();
195 int gpmc_cs_set_timings(int cs
, const struct gpmc_timings
*t
)
200 div
= gpmc_cs_calc_divider(cs
, t
->sync_clk
);
204 GPMC_SET_ONE(GPMC_CS_CONFIG2
, 0, 3, cs_on
);
205 GPMC_SET_ONE(GPMC_CS_CONFIG2
, 8, 12, cs_rd_off
);
206 GPMC_SET_ONE(GPMC_CS_CONFIG2
, 16, 20, cs_wr_off
);
208 GPMC_SET_ONE(GPMC_CS_CONFIG3
, 0, 3, adv_on
);
209 GPMC_SET_ONE(GPMC_CS_CONFIG3
, 8, 12, adv_rd_off
);
210 GPMC_SET_ONE(GPMC_CS_CONFIG3
, 16, 20, adv_wr_off
);
212 GPMC_SET_ONE(GPMC_CS_CONFIG4
, 0, 3, oe_on
);
213 GPMC_SET_ONE(GPMC_CS_CONFIG4
, 8, 12, oe_off
);
214 GPMC_SET_ONE(GPMC_CS_CONFIG4
, 16, 19, we_on
);
215 GPMC_SET_ONE(GPMC_CS_CONFIG4
, 24, 28, we_off
);
217 GPMC_SET_ONE(GPMC_CS_CONFIG5
, 0, 4, rd_cycle
);
218 GPMC_SET_ONE(GPMC_CS_CONFIG5
, 8, 12, wr_cycle
);
219 GPMC_SET_ONE(GPMC_CS_CONFIG5
, 16, 20, access
);
221 GPMC_SET_ONE(GPMC_CS_CONFIG5
, 24, 27, page_burst_access
);
223 if (cpu_is_omap34xx()) {
224 GPMC_SET_ONE(GPMC_CS_CONFIG6
, 16, 19, wr_data_mux_bus
);
225 GPMC_SET_ONE(GPMC_CS_CONFIG6
, 24, 28, wr_access
);
228 /* caller is expected to have initialized CONFIG1 to cover
229 * at least sync vs async
231 l
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG1
);
232 if (l
& (GPMC_CONFIG1_READTYPE_SYNC
| GPMC_CONFIG1_WRITETYPE_SYNC
)) {
234 printk(KERN_INFO
"GPMC CS%d CLK period is %lu ns (div %d)\n",
235 cs
, (div
* gpmc_get_fclk_period()) / 1000, div
);
239 gpmc_cs_write_reg(cs
, GPMC_CS_CONFIG1
, l
);
245 static void gpmc_cs_enable_mem(int cs
, u32 base
, u32 size
)
250 mask
= (1 << GPMC_SECTION_SHIFT
) - size
;
251 l
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG7
);
253 l
= (base
>> GPMC_CHUNK_SHIFT
) & 0x3f;
255 l
|= ((mask
>> GPMC_CHUNK_SHIFT
) & 0x0f) << 8;
256 l
|= 1 << 6; /* CSVALID */
257 gpmc_cs_write_reg(cs
, GPMC_CS_CONFIG7
, l
);
260 static void gpmc_cs_disable_mem(int cs
)
264 l
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG7
);
265 l
&= ~(1 << 6); /* CSVALID */
266 gpmc_cs_write_reg(cs
, GPMC_CS_CONFIG7
, l
);
269 static void gpmc_cs_get_memconf(int cs
, u32
*base
, u32
*size
)
274 l
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG7
);
275 *base
= (l
& 0x3f) << GPMC_CHUNK_SHIFT
;
276 mask
= (l
>> 8) & 0x0f;
277 *size
= (1 << GPMC_SECTION_SHIFT
) - (mask
<< GPMC_CHUNK_SHIFT
);
280 static int gpmc_cs_mem_enabled(int cs
)
284 l
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG7
);
288 int gpmc_cs_set_reserved(int cs
, int reserved
)
290 if (cs
> GPMC_CS_NUM
)
293 gpmc_cs_map
&= ~(1 << cs
);
294 gpmc_cs_map
|= (reserved
? 1 : 0) << cs
;
299 int gpmc_cs_reserved(int cs
)
301 if (cs
> GPMC_CS_NUM
)
304 return gpmc_cs_map
& (1 << cs
);
307 static unsigned long gpmc_mem_align(unsigned long size
)
311 size
= (size
- 1) >> (GPMC_CHUNK_SHIFT
- 1);
312 order
= GPMC_CHUNK_SHIFT
- 1;
321 static int gpmc_cs_insert_mem(int cs
, unsigned long base
, unsigned long size
)
323 struct resource
*res
= &gpmc_cs_mem
[cs
];
326 size
= gpmc_mem_align(size
);
327 spin_lock(&gpmc_mem_lock
);
329 res
->end
= base
+ size
- 1;
330 r
= request_resource(&gpmc_mem_root
, res
);
331 spin_unlock(&gpmc_mem_lock
);
336 int gpmc_cs_request(int cs
, unsigned long size
, unsigned long *base
)
338 struct resource
*res
= &gpmc_cs_mem
[cs
];
341 if (cs
> GPMC_CS_NUM
)
344 size
= gpmc_mem_align(size
);
345 if (size
> (1 << GPMC_SECTION_SHIFT
))
348 spin_lock(&gpmc_mem_lock
);
349 if (gpmc_cs_reserved(cs
)) {
353 if (gpmc_cs_mem_enabled(cs
))
354 r
= adjust_resource(res
, res
->start
& ~(size
- 1), size
);
356 r
= allocate_resource(&gpmc_mem_root
, res
, size
, 0, ~0,
361 gpmc_cs_enable_mem(cs
, res
->start
, res
->end
- res
->start
+ 1);
363 gpmc_cs_set_reserved(cs
, 1);
365 spin_unlock(&gpmc_mem_lock
);
368 EXPORT_SYMBOL(gpmc_cs_request
);
370 void gpmc_cs_free(int cs
)
372 spin_lock(&gpmc_mem_lock
);
373 if (cs
>= GPMC_CS_NUM
|| !gpmc_cs_reserved(cs
)) {
374 printk(KERN_ERR
"Trying to free non-reserved GPMC CS%d\n", cs
);
376 spin_unlock(&gpmc_mem_lock
);
379 gpmc_cs_disable_mem(cs
);
380 release_resource(&gpmc_cs_mem
[cs
]);
381 gpmc_cs_set_reserved(cs
, 0);
382 spin_unlock(&gpmc_mem_lock
);
384 EXPORT_SYMBOL(gpmc_cs_free
);
386 static void __init
gpmc_mem_init(void)
389 unsigned long boot_rom_space
= 0;
391 /* never allocate the first page, to facilitate bug detection;
392 * even if we didn't boot from ROM.
394 boot_rom_space
= BOOT_ROM_SPACE
;
395 /* In apollon the CS0 is mapped as 0x0000 0000 */
396 if (machine_is_omap_apollon())
398 gpmc_mem_root
.start
= GPMC_MEM_START
+ boot_rom_space
;
399 gpmc_mem_root
.end
= GPMC_MEM_END
;
401 /* Reserve all regions that has been set up by bootloader */
402 for (cs
= 0; cs
< GPMC_CS_NUM
; cs
++) {
405 if (!gpmc_cs_mem_enabled(cs
))
407 gpmc_cs_get_memconf(cs
, &base
, &size
);
408 if (gpmc_cs_insert_mem(cs
, base
, size
) < 0)
413 void __init
gpmc_init(void)
418 if (cpu_is_omap24xx()) {
420 if (cpu_is_omap2420())
421 l
= OMAP2420_GPMC_BASE
;
423 l
= OMAP34XX_GPMC_BASE
;
424 } else if (cpu_is_omap34xx()) {
426 l
= OMAP34XX_GPMC_BASE
;
429 gpmc_l3_clk
= clk_get(NULL
, ck
);
430 if (IS_ERR(gpmc_l3_clk
)) {
431 printk(KERN_ERR
"Could not get GPMC clock %s\n", ck
);
435 gpmc_base
= ioremap(l
, SZ_4K
);
437 clk_put(gpmc_l3_clk
);
438 printk(KERN_ERR
"Could not get GPMC register memory\n");
442 l
= gpmc_read_reg(GPMC_REVISION
);
443 printk(KERN_INFO
"GPMC revision %d.%d\n", (l
>> 4) & 0x0f, l
& 0x0f);
444 /* Set smart idle mode and automatic L3 clock gating */
445 l
= gpmc_read_reg(GPMC_SYSCONFIG
);
447 l
|= (0x02 << 3) | (1 << 0);
448 gpmc_write_reg(GPMC_SYSCONFIG
, l
);