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.
12 #include <linux/kernel.h>
13 #include <linux/init.h>
14 #include <linux/err.h>
15 #include <linux/clk.h>
16 #include <linux/ioport.h>
17 #include <linux/spinlock.h>
20 #include <asm/arch/gpmc.h>
24 #define GPMC_BASE 0x6800a000
25 #define GPMC_REVISION 0x00
26 #define GPMC_SYSCONFIG 0x10
27 #define GPMC_SYSSTATUS 0x14
28 #define GPMC_IRQSTATUS 0x18
29 #define GPMC_IRQENABLE 0x1c
30 #define GPMC_TIMEOUT_CONTROL 0x40
31 #define GPMC_ERR_ADDRESS 0x44
32 #define GPMC_ERR_TYPE 0x48
33 #define GPMC_CONFIG 0x50
34 #define GPMC_STATUS 0x54
35 #define GPMC_PREFETCH_CONFIG1 0x1e0
36 #define GPMC_PREFETCH_CONFIG2 0x1e4
37 #define GPMC_PREFETCH_CONTROL 0x1e8
38 #define GPMC_PREFETCH_STATUS 0x1f0
39 #define GPMC_ECC_CONFIG 0x1f4
40 #define GPMC_ECC_CONTROL 0x1f8
41 #define GPMC_ECC_SIZE_CONFIG 0x1fc
44 #define GPMC_CS_SIZE 0x30
47 #define GPMC_MEM_START 0x00000000
48 #define GPMC_MEM_END 0x3FFFFFFF
49 #define BOOT_ROM_SPACE 0x100000 /* 1MB */
51 #define GPMC_CHUNK_SHIFT 24 /* 16 MB */
52 #define GPMC_SECTION_SHIFT 28 /* 128 MB */
54 static struct resource gpmc_mem_root
;
55 static struct resource gpmc_cs_mem
[GPMC_CS_NUM
];
56 static spinlock_t gpmc_mem_lock
= SPIN_LOCK_UNLOCKED
;
57 static unsigned gpmc_cs_map
;
59 static void __iomem
*gpmc_base
=
60 (void __iomem
*) IO_ADDRESS(GPMC_BASE
);
61 static void __iomem
*gpmc_cs_base
=
62 (void __iomem
*) IO_ADDRESS(GPMC_BASE
) + GPMC_CS0
;
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_cs_base
+ (cs
* GPMC_CS_SIZE
) + idx
;
81 __raw_writel(val
, reg_addr
);
84 u32
gpmc_cs_read_reg(int cs
, int idx
)
86 return __raw_readl(gpmc_cs_base
+ (cs
* GPMC_CS_SIZE
) + idx
);
89 /* TODO: Add support for gpmc_fck to clock framework and use it */
90 static unsigned long gpmc_get_fclk_period(void)
93 return 1000000000 / ((clk_get_rate(gpmc_l3_clk
)) / 1000);
96 unsigned int gpmc_ns_to_ticks(unsigned int time_ns
)
98 unsigned long tick_ps
;
100 /* Calculate in picosecs to yield more exact results */
101 tick_ps
= gpmc_get_fclk_period();
103 return (time_ns
* 1000 + tick_ps
- 1) / tick_ps
;
107 static int set_gpmc_timing_reg(int cs
, int reg
, int st_bit
, int end_bit
,
108 int time
, const char *name
)
110 static int set_gpmc_timing_reg(int cs
, int reg
, int st_bit
, int end_bit
,
115 int ticks
, mask
, nr_bits
;
120 ticks
= gpmc_ns_to_ticks(time
);
121 nr_bits
= end_bit
- st_bit
+ 1;
122 if (ticks
>= 1 << nr_bits
)
125 mask
= (1 << nr_bits
) - 1;
126 l
= gpmc_cs_read_reg(cs
, reg
);
128 printk(KERN_INFO
"GPMC CS%d: %-10s: %d ticks, %3lu ns (was %i ticks)\n",
129 cs
, name
, ticks
, gpmc_get_fclk_period() * ticks
/ 1000,
130 (l
>> st_bit
) & mask
);
132 l
&= ~(mask
<< st_bit
);
133 l
|= ticks
<< st_bit
;
134 gpmc_cs_write_reg(cs
, reg
, l
);
140 #define GPMC_SET_ONE(reg, st, end, field) \
141 if (set_gpmc_timing_reg(cs, (reg), (st), (end), \
142 t->field, #field) < 0) \
145 #define GPMC_SET_ONE(reg, st, end, field) \
146 if (set_gpmc_timing_reg(cs, (reg), (st), (end), t->field) < 0) \
150 int gpmc_cs_calc_divider(int cs
, unsigned int sync_clk
)
155 l
= sync_clk
* 1000 + (gpmc_get_fclk_period() - 1);
156 div
= l
/ gpmc_get_fclk_period();
165 int gpmc_cs_set_timings(int cs
, const struct gpmc_timings
*t
)
170 div
= gpmc_cs_calc_divider(cs
, t
->sync_clk
);
174 GPMC_SET_ONE(GPMC_CS_CONFIG2
, 0, 3, cs_on
);
175 GPMC_SET_ONE(GPMC_CS_CONFIG2
, 8, 12, cs_rd_off
);
176 GPMC_SET_ONE(GPMC_CS_CONFIG2
, 16, 20, cs_wr_off
);
178 GPMC_SET_ONE(GPMC_CS_CONFIG3
, 0, 3, adv_on
);
179 GPMC_SET_ONE(GPMC_CS_CONFIG3
, 8, 12, adv_rd_off
);
180 GPMC_SET_ONE(GPMC_CS_CONFIG3
, 16, 20, adv_wr_off
);
182 GPMC_SET_ONE(GPMC_CS_CONFIG4
, 0, 3, oe_on
);
183 GPMC_SET_ONE(GPMC_CS_CONFIG4
, 8, 12, oe_off
);
184 GPMC_SET_ONE(GPMC_CS_CONFIG4
, 16, 19, we_on
);
185 GPMC_SET_ONE(GPMC_CS_CONFIG4
, 24, 28, we_off
);
187 GPMC_SET_ONE(GPMC_CS_CONFIG5
, 0, 4, rd_cycle
);
188 GPMC_SET_ONE(GPMC_CS_CONFIG5
, 8, 12, wr_cycle
);
189 GPMC_SET_ONE(GPMC_CS_CONFIG5
, 16, 20, access
);
191 GPMC_SET_ONE(GPMC_CS_CONFIG5
, 24, 27, page_burst_access
);
194 printk(KERN_INFO
"GPMC CS%d CLK period is %lu (div %d)\n",
195 cs
, gpmc_get_fclk_period(), div
);
198 l
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG1
);
205 static void gpmc_cs_enable_mem(int cs
, u32 base
, u32 size
)
210 mask
= (1 << GPMC_SECTION_SHIFT
) - size
;
211 l
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG7
);
213 l
= (base
>> GPMC_CHUNK_SHIFT
) & 0x3f;
215 l
|= ((mask
>> GPMC_CHUNK_SHIFT
) & 0x0f) << 8;
216 l
|= 1 << 6; /* CSVALID */
217 gpmc_cs_write_reg(cs
, GPMC_CS_CONFIG7
, l
);
220 static void gpmc_cs_disable_mem(int cs
)
224 l
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG7
);
225 l
&= ~(1 << 6); /* CSVALID */
226 gpmc_cs_write_reg(cs
, GPMC_CS_CONFIG7
, l
);
229 static void gpmc_cs_get_memconf(int cs
, u32
*base
, u32
*size
)
234 l
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG7
);
235 *base
= (l
& 0x3f) << GPMC_CHUNK_SHIFT
;
236 mask
= (l
>> 8) & 0x0f;
237 *size
= (1 << GPMC_SECTION_SHIFT
) - (mask
<< GPMC_CHUNK_SHIFT
);
240 static int gpmc_cs_mem_enabled(int cs
)
244 l
= gpmc_cs_read_reg(cs
, GPMC_CS_CONFIG7
);
248 static void gpmc_cs_set_reserved(int cs
, int reserved
)
250 gpmc_cs_map
&= ~(1 << cs
);
251 gpmc_cs_map
|= (reserved
? 1 : 0) << cs
;
254 static int gpmc_cs_reserved(int cs
)
256 return gpmc_cs_map
& (1 << cs
);
259 static unsigned long gpmc_mem_align(unsigned long size
)
263 size
= (size
- 1) >> (GPMC_CHUNK_SHIFT
- 1);
264 order
= GPMC_CHUNK_SHIFT
- 1;
273 static int gpmc_cs_insert_mem(int cs
, unsigned long base
, unsigned long size
)
275 struct resource
*res
= &gpmc_cs_mem
[cs
];
278 size
= gpmc_mem_align(size
);
279 spin_lock(&gpmc_mem_lock
);
281 res
->end
= base
+ size
- 1;
282 r
= request_resource(&gpmc_mem_root
, res
);
283 spin_unlock(&gpmc_mem_lock
);
288 int gpmc_cs_request(int cs
, unsigned long size
, unsigned long *base
)
290 struct resource
*res
= &gpmc_cs_mem
[cs
];
293 if (cs
> GPMC_CS_NUM
)
296 size
= gpmc_mem_align(size
);
297 if (size
> (1 << GPMC_SECTION_SHIFT
))
300 spin_lock(&gpmc_mem_lock
);
301 if (gpmc_cs_reserved(cs
)) {
305 if (gpmc_cs_mem_enabled(cs
))
306 r
= adjust_resource(res
, res
->start
& ~(size
- 1), size
);
308 r
= allocate_resource(&gpmc_mem_root
, res
, size
, 0, ~0,
313 gpmc_cs_enable_mem(cs
, res
->start
, res
->end
- res
->start
+ 1);
315 gpmc_cs_set_reserved(cs
, 1);
317 spin_unlock(&gpmc_mem_lock
);
321 void gpmc_cs_free(int cs
)
323 spin_lock(&gpmc_mem_lock
);
324 if (cs
>= GPMC_CS_NUM
|| !gpmc_cs_reserved(cs
)) {
325 printk(KERN_ERR
"Trying to free non-reserved GPMC CS%d\n", cs
);
327 spin_unlock(&gpmc_mem_lock
);
330 gpmc_cs_disable_mem(cs
);
331 release_resource(&gpmc_cs_mem
[cs
]);
332 gpmc_cs_set_reserved(cs
, 0);
333 spin_unlock(&gpmc_mem_lock
);
336 void __init
gpmc_mem_init(void)
339 unsigned long boot_rom_space
= 0;
341 if (cpu_is_omap242x()) {
343 l
= omap_readl(OMAP242X_CONTROL_STATUS
);
344 /* In case of internal boot the 1st MB is redirected to the
345 * boot ROM memory space.
348 boot_rom_space
= BOOT_ROM_SPACE
;
350 /* We assume internal boot if the mode can't be
353 boot_rom_space
= BOOT_ROM_SPACE
;
354 gpmc_mem_root
.start
= GPMC_MEM_START
+ boot_rom_space
;
355 gpmc_mem_root
.end
= GPMC_MEM_END
;
357 /* Reserve all regions that has been set up by bootloader */
358 for (cs
= 0; cs
< GPMC_CS_NUM
; cs
++) {
361 if (!gpmc_cs_mem_enabled(cs
))
363 gpmc_cs_get_memconf(cs
, &base
, &size
);
364 if (gpmc_cs_insert_mem(cs
, base
, size
) < 0)
369 void __init
gpmc_init(void)
373 gpmc_l3_clk
= clk_get(NULL
, "core_l3_ck");
374 BUG_ON(IS_ERR(gpmc_l3_clk
));
376 l
= gpmc_read_reg(GPMC_REVISION
);
377 printk(KERN_INFO
"GPMC revision %d.%d\n", (l
>> 4) & 0x0f, l
& 0x0f);
378 /* Set smart idle mode and automatic L3 clock gating */
379 l
= gpmc_read_reg(GPMC_SYSCONFIG
);
381 l
|= (0x02 << 3) | (1 << 0);
382 gpmc_write_reg(GPMC_SYSCONFIG
, l
);