]> bbs.cooldavid.org Git - net-next-2.6.git/blame - arch/arm/mach-integrator/integrator_ap.c
ARM: Move platform memory reservations out of generic code
[net-next-2.6.git] / arch / arm / mach-integrator / integrator_ap.c
CommitLineData
1da177e4
LT
1/*
2 * linux/arch/arm/mach-integrator/integrator_ap.c
3 *
4 * Copyright (C) 2000-2003 Deep Blue Solutions Ltd
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <linux/types.h>
21#include <linux/kernel.h>
22#include <linux/init.h>
23#include <linux/list.h>
d052d1be 24#include <linux/platform_device.h>
1da177e4
LT
25#include <linux/slab.h>
26#include <linux/string.h>
27#include <linux/sysdev.h>
a62c80e5
RK
28#include <linux/amba/bus.h>
29#include <linux/amba/kmi.h>
6be4826e
RK
30#include <linux/clocksource.h>
31#include <linux/clockchips.h>
32#include <linux/interrupt.h>
fced80c7 33#include <linux/io.h>
1da177e4 34
a09e64fb 35#include <mach/hardware.h>
a285edcf 36#include <mach/platform.h>
6be4826e 37#include <asm/hardware/arm_timer.h>
1da177e4
LT
38#include <asm/irq.h>
39#include <asm/setup.h>
4e57b681 40#include <asm/param.h> /* HZ */
1da177e4 41#include <asm/mach-types.h>
1da177e4 42
a09e64fb 43#include <mach/lm.h>
1da177e4
LT
44
45#include <asm/mach/arch.h>
46#include <asm/mach/flash.h>
47#include <asm/mach/irq.h>
48#include <asm/mach/map.h>
49#include <asm/mach/time.h>
50
98c672cf
RK
51#include "common.h"
52
1da177e4
LT
53/*
54 * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx
55 * is the (PA >> 12).
56 *
57 * Setup a VA for the Integrator interrupt controller (for header #0,
58 * just for now).
59 */
60#define VA_IC_BASE IO_ADDRESS(INTEGRATOR_IC_BASE)
61#define VA_SC_BASE IO_ADDRESS(INTEGRATOR_SC_BASE)
62#define VA_EBI_BASE IO_ADDRESS(INTEGRATOR_EBI_BASE)
b830b9b5 63#define VA_CMIC_BASE IO_ADDRESS(INTEGRATOR_HDR_IC)
1da177e4
LT
64
65/*
66 * Logical Physical
67 * e8000000 40000000 PCI memory PHYS_PCI_MEM_BASE (max 512M)
68 * ec000000 61000000 PCI config space PHYS_PCI_CONFIG_BASE (max 16M)
69 * ed000000 62000000 PCI V3 regs PHYS_PCI_V3_BASE (max 64k)
70 * ee000000 60000000 PCI IO PHYS_PCI_IO_BASE (max 16M)
71 * ef000000 Cache flush
72 * f1000000 10000000 Core module registers
73 * f1100000 11000000 System controller registers
74 * f1200000 12000000 EBI registers
75 * f1300000 13000000 Counter/Timer
76 * f1400000 14000000 Interrupt controller
77 * f1600000 16000000 UART 0
78 * f1700000 17000000 UART 1
79 * f1a00000 1a000000 Debug LEDs
80 * f1b00000 1b000000 GPIO
81 */
82
83static struct map_desc ap_io_desc[] __initdata = {
c8d27298
DS
84 {
85 .virtual = IO_ADDRESS(INTEGRATOR_HDR_BASE),
86 .pfn = __phys_to_pfn(INTEGRATOR_HDR_BASE),
87 .length = SZ_4K,
88 .type = MT_DEVICE
89 }, {
90 .virtual = IO_ADDRESS(INTEGRATOR_SC_BASE),
91 .pfn = __phys_to_pfn(INTEGRATOR_SC_BASE),
92 .length = SZ_4K,
93 .type = MT_DEVICE
94 }, {
95 .virtual = IO_ADDRESS(INTEGRATOR_EBI_BASE),
96 .pfn = __phys_to_pfn(INTEGRATOR_EBI_BASE),
97 .length = SZ_4K,
98 .type = MT_DEVICE
99 }, {
100 .virtual = IO_ADDRESS(INTEGRATOR_CT_BASE),
101 .pfn = __phys_to_pfn(INTEGRATOR_CT_BASE),
102 .length = SZ_4K,
103 .type = MT_DEVICE
104 }, {
105 .virtual = IO_ADDRESS(INTEGRATOR_IC_BASE),
106 .pfn = __phys_to_pfn(INTEGRATOR_IC_BASE),
107 .length = SZ_4K,
108 .type = MT_DEVICE
109 }, {
110 .virtual = IO_ADDRESS(INTEGRATOR_UART0_BASE),
111 .pfn = __phys_to_pfn(INTEGRATOR_UART0_BASE),
112 .length = SZ_4K,
113 .type = MT_DEVICE
114 }, {
115 .virtual = IO_ADDRESS(INTEGRATOR_UART1_BASE),
116 .pfn = __phys_to_pfn(INTEGRATOR_UART1_BASE),
117 .length = SZ_4K,
118 .type = MT_DEVICE
119 }, {
120 .virtual = IO_ADDRESS(INTEGRATOR_DBG_BASE),
121 .pfn = __phys_to_pfn(INTEGRATOR_DBG_BASE),
122 .length = SZ_4K,
123 .type = MT_DEVICE
124 }, {
da7ba956
RK
125 .virtual = IO_ADDRESS(INTEGRATOR_AP_GPIO_BASE),
126 .pfn = __phys_to_pfn(INTEGRATOR_AP_GPIO_BASE),
c8d27298
DS
127 .length = SZ_4K,
128 .type = MT_DEVICE
129 }, {
130 .virtual = PCI_MEMORY_VADDR,
131 .pfn = __phys_to_pfn(PHYS_PCI_MEM_BASE),
132 .length = SZ_16M,
133 .type = MT_DEVICE
134 }, {
135 .virtual = PCI_CONFIG_VADDR,
136 .pfn = __phys_to_pfn(PHYS_PCI_CONFIG_BASE),
137 .length = SZ_16M,
138 .type = MT_DEVICE
139 }, {
140 .virtual = PCI_V3_VADDR,
141 .pfn = __phys_to_pfn(PHYS_PCI_V3_BASE),
142 .length = SZ_64K,
143 .type = MT_DEVICE
144 }, {
145 .virtual = PCI_IO_VADDR,
146 .pfn = __phys_to_pfn(PHYS_PCI_IO_BASE),
147 .length = SZ_64K,
148 .type = MT_DEVICE
149 }
1da177e4
LT
150};
151
152static void __init ap_map_io(void)
153{
154 iotable_init(ap_io_desc, ARRAY_SIZE(ap_io_desc));
155}
156
157#define INTEGRATOR_SC_VALID_INT 0x003fffff
158
159static void sc_mask_irq(unsigned int irq)
160{
161 writel(1 << irq, VA_IC_BASE + IRQ_ENABLE_CLEAR);
162}
163
164static void sc_unmask_irq(unsigned int irq)
165{
166 writel(1 << irq, VA_IC_BASE + IRQ_ENABLE_SET);
167}
168
38c677cb
DB
169static struct irq_chip sc_chip = {
170 .name = "SC",
1da177e4
LT
171 .ack = sc_mask_irq,
172 .mask = sc_mask_irq,
173 .unmask = sc_unmask_irq,
174};
175
176static void __init ap_init_irq(void)
177{
178 unsigned int i;
179
180 /* Disable all interrupts initially. */
181 /* Do the core module ones */
182 writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
183
184 /* do the header card stuff next */
185 writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
186 writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
187
188 for (i = 0; i < NR_IRQS; i++) {
189 if (((1 << i) & INTEGRATOR_SC_VALID_INT) != 0) {
190 set_irq_chip(i, &sc_chip);
10dd5ce2 191 set_irq_handler(i, handle_level_irq);
1da177e4
LT
192 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
193 }
194 }
195}
196
197#ifdef CONFIG_PM
198static unsigned long ic_irq_enable;
199
200static int irq_suspend(struct sys_device *dev, pm_message_t state)
201{
202 ic_irq_enable = readl(VA_IC_BASE + IRQ_ENABLE);
203 return 0;
204}
205
206static int irq_resume(struct sys_device *dev)
207{
208 /* disable all irq sources */
209 writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
210 writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
211 writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
212
213 writel(ic_irq_enable, VA_IC_BASE + IRQ_ENABLE_SET);
214 return 0;
215}
216#else
217#define irq_suspend NULL
218#define irq_resume NULL
219#endif
220
221static struct sysdev_class irq_class = {
af5ca3f4 222 .name = "irq",
1da177e4
LT
223 .suspend = irq_suspend,
224 .resume = irq_resume,
225};
226
227static struct sys_device irq_device = {
228 .id = 0,
229 .cls = &irq_class,
230};
231
232static int __init irq_init_sysfs(void)
233{
234 int ret = sysdev_class_register(&irq_class);
235 if (ret == 0)
236 ret = sysdev_register(&irq_device);
237 return ret;
238}
239
240device_initcall(irq_init_sysfs);
241
242/*
243 * Flash handling.
244 */
245#define SC_CTRLC (VA_SC_BASE + INTEGRATOR_SC_CTRLC_OFFSET)
246#define SC_CTRLS (VA_SC_BASE + INTEGRATOR_SC_CTRLS_OFFSET)
247#define EBI_CSR1 (VA_EBI_BASE + INTEGRATOR_EBI_CSR1_OFFSET)
248#define EBI_LOCK (VA_EBI_BASE + INTEGRATOR_EBI_LOCK_OFFSET)
249
250static int ap_flash_init(void)
251{
252 u32 tmp;
253
254 writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
255
256 tmp = readl(EBI_CSR1) | INTEGRATOR_EBI_WRITE_ENABLE;
257 writel(tmp, EBI_CSR1);
258
259 if (!(readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE)) {
260 writel(0xa05f, EBI_LOCK);
261 writel(tmp, EBI_CSR1);
262 writel(0, EBI_LOCK);
263 }
264 return 0;
265}
266
267static void ap_flash_exit(void)
268{
269 u32 tmp;
270
271 writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
272
273 tmp = readl(EBI_CSR1) & ~INTEGRATOR_EBI_WRITE_ENABLE;
274 writel(tmp, EBI_CSR1);
275
276 if (readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE) {
277 writel(0xa05f, EBI_LOCK);
278 writel(tmp, EBI_CSR1);
279 writel(0, EBI_LOCK);
280 }
281}
282
283static void ap_flash_set_vpp(int on)
284{
285 unsigned long reg = on ? SC_CTRLS : SC_CTRLC;
286
287 writel(INTEGRATOR_SC_CTRL_nFLVPPEN, reg);
288}
289
290static struct flash_platform_data ap_flash_data = {
291 .map_name = "cfi_probe",
292 .width = 4,
293 .init = ap_flash_init,
294 .exit = ap_flash_exit,
295 .set_vpp = ap_flash_set_vpp,
296};
297
298static struct resource cfi_flash_resource = {
299 .start = INTEGRATOR_FLASH_BASE,
300 .end = INTEGRATOR_FLASH_BASE + INTEGRATOR_FLASH_SIZE - 1,
301 .flags = IORESOURCE_MEM,
302};
303
304static struct platform_device cfi_flash_device = {
305 .name = "armflash",
306 .id = 0,
307 .dev = {
308 .platform_data = &ap_flash_data,
309 },
310 .num_resources = 1,
311 .resource = &cfi_flash_resource,
312};
313
314static void __init ap_init(void)
315{
316 unsigned long sc_dec;
317 int i;
318
319 platform_device_register(&cfi_flash_device);
320
321 sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET);
322 for (i = 0; i < 4; i++) {
323 struct lm_device *lmdev;
324
325 if ((sc_dec & (16 << i)) == 0)
326 continue;
327
d2a02b93 328 lmdev = kzalloc(sizeof(struct lm_device), GFP_KERNEL);
1da177e4
LT
329 if (!lmdev)
330 continue;
331
1da177e4
LT
332 lmdev->resource.start = 0xc0000000 + 0x10000000 * i;
333 lmdev->resource.end = lmdev->resource.start + 0x0fffffff;
334 lmdev->resource.flags = IORESOURCE_MEM;
335 lmdev->irq = IRQ_AP_EXPINT0 + i;
336 lmdev->id = i;
337
338 lm_device_register(lmdev);
339 }
340}
341
6be4826e
RK
342/*
343 * Where is the timer (VA)?
344 */
345#define TIMER0_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER0_BASE)
346#define TIMER1_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER1_BASE)
347#define TIMER2_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER2_BASE)
348
349/*
350 * How long is the timer interval?
351 */
352#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10)
353#if TIMER_INTERVAL >= 0x100000
354#define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC)
355#elif TIMER_INTERVAL >= 0x10000
356#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC)
357#else
358#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
359#endif
360
361static unsigned long timer_reload;
362
363static void __iomem * const clksrc_base = (void __iomem *)TIMER2_VA_BASE;
364
365static cycle_t timersp_read(struct clocksource *cs)
366{
367 return ~(readl(clksrc_base + TIMER_VALUE) & 0xffff);
368}
369
370static struct clocksource clocksource_timersp = {
371 .name = "timer2",
372 .rating = 200,
373 .read = timersp_read,
374 .mask = CLOCKSOURCE_MASK(16),
375 .shift = 16,
376 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
377};
378
379static void integrator_clocksource_init(u32 khz)
380{
381 struct clocksource *cs = &clocksource_timersp;
382 void __iomem *base = clksrc_base;
383 u32 ctrl = TIMER_CTRL_ENABLE;
384
385 if (khz >= 1500) {
386 khz /= 16;
387 ctrl = TIMER_CTRL_DIV16;
388 }
389
390 writel(ctrl, base + TIMER_CTRL);
391 writel(0xffff, base + TIMER_LOAD);
392
393 cs->mult = clocksource_khz2mult(khz, cs->shift);
394 clocksource_register(cs);
395}
396
397static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE;
398
399/*
400 * IRQ handler for the timer
401 */
402static irqreturn_t integrator_timer_interrupt(int irq, void *dev_id)
403{
404 struct clock_event_device *evt = dev_id;
405
406 /* clear the interrupt */
407 writel(1, clkevt_base + TIMER_INTCLR);
408
409 evt->event_handler(evt);
410
411 return IRQ_HANDLED;
412}
413
414static void clkevt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt)
415{
416 u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE;
417
418 BUG_ON(mode == CLOCK_EVT_MODE_ONESHOT);
419
420 if (mode == CLOCK_EVT_MODE_PERIODIC) {
421 writel(ctrl, clkevt_base + TIMER_CTRL);
422 writel(timer_reload, clkevt_base + TIMER_LOAD);
423 ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
424 }
425
426 writel(ctrl, clkevt_base + TIMER_CTRL);
427}
428
429static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt)
430{
431 unsigned long ctrl = readl(clkevt_base + TIMER_CTRL);
432
433 writel(ctrl & ~TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
434 writel(next, clkevt_base + TIMER_LOAD);
435 writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
436
437 return 0;
438}
439
440static struct clock_event_device integrator_clockevent = {
441 .name = "timer1",
442 .shift = 34,
443 .features = CLOCK_EVT_FEAT_PERIODIC,
444 .set_mode = clkevt_set_mode,
445 .set_next_event = clkevt_set_next_event,
446 .rating = 300,
447 .cpumask = cpu_all_mask,
448};
449
450static struct irqaction integrator_timer_irq = {
451 .name = "timer",
452 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
453 .handler = integrator_timer_interrupt,
454 .dev_id = &integrator_clockevent,
455};
456
457static void integrator_clockevent_init(u32 khz)
458{
459 struct clock_event_device *evt = &integrator_clockevent;
460 unsigned int ctrl = 0;
461
462 if (khz * 1000 > 0x100000 * HZ) {
463 khz /= 256;
464 ctrl |= TIMER_CTRL_DIV256;
465 } else if (khz * 1000 > 0x10000 * HZ) {
466 khz /= 16;
467 ctrl |= TIMER_CTRL_DIV16;
468 }
469
470 timer_reload = khz * 1000 / HZ;
471 writel(ctrl, clkevt_base + TIMER_CTRL);
472
473 evt->irq = IRQ_TIMERINT1;
474 evt->mult = div_sc(khz, NSEC_PER_MSEC, evt->shift);
475 evt->max_delta_ns = clockevent_delta2ns(0xffff, evt);
476 evt->min_delta_ns = clockevent_delta2ns(0xf, evt);
477
478 setup_irq(IRQ_TIMERINT1, &integrator_timer_irq);
479 clockevents_register_device(evt);
480}
481
482/*
483 * Set up timer(s).
484 */
1da177e4
LT
485static void __init ap_init_timer(void)
486{
6be4826e
RK
487 u32 khz = TICKS_PER_uSEC * 1000;
488
489 writel(0, TIMER0_VA_BASE + TIMER_CTRL);
490 writel(0, TIMER1_VA_BASE + TIMER_CTRL);
491 writel(0, TIMER2_VA_BASE + TIMER_CTRL);
492
493 integrator_clocksource_init(khz);
494 integrator_clockevent_init(khz);
1da177e4
LT
495}
496
497static struct sys_timer ap_timer = {
498 .init = ap_init_timer,
1da177e4
LT
499};
500
501MACHINE_START(INTEGRATOR, "ARM-Integrator")
e9dea0c6 502 /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
e9dea0c6
RK
503 .phys_io = 0x16000000,
504 .io_pg_offst = ((0xf1600000) >> 18) & 0xfffc,
505 .boot_params = 0x00000100,
506 .map_io = ap_map_io,
98c672cf 507 .reserve = integrator_reserve,
e9dea0c6 508 .init_irq = ap_init_irq,
1da177e4 509 .timer = &ap_timer,
e9dea0c6 510 .init_machine = ap_init,
1da177e4 511MACHINE_END