aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-realview
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-realview')
-rw-r--r--arch/arm/mach-realview/Kconfig21
-rw-r--r--arch/arm/mach-realview/Makefile3
-rw-r--r--arch/arm/mach-realview/core.c179
-rw-r--r--arch/arm/mach-realview/core.h71
-rw-r--r--arch/arm/mach-realview/localtimer.c144
-rw-r--r--arch/arm/mach-realview/platsmp.c20
-rw-r--r--arch/arm/mach-realview/realview_eb.c234
7 files changed, 442 insertions, 230 deletions
diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig
index 35156ca39df7..39b3bb7f1020 100644
--- a/arch/arm/mach-realview/Kconfig
+++ b/arch/arm/mach-realview/Kconfig
@@ -7,24 +7,21 @@ config MACH_REALVIEW_EB
7 help 7 help
8 Include support for the ARM(R) RealView Emulation Baseboard platform. 8 Include support for the ARM(R) RealView Emulation Baseboard platform.
9 9
10config REALVIEW_MPCORE 10config REALVIEW_EB_ARM11MP
11 bool "Support MPcore tile" 11 bool "Support ARM11MPCore tile"
12 depends on MACH_REALVIEW_EB 12 depends on MACH_REALVIEW_EB
13 select CACHE_L2X0 13 select CACHE_L2X0
14 help 14 help
15 Enable support for the MPCore tile on the Realview platform. 15 Enable support for the ARM11MPCore tile on the Realview platform.
16 Since there are device address and interrupt differences, a
17 kernel built with this option enabled is not compatible with
18 other tiles.
19 16
20config REALVIEW_MPCORE_REVB 17config REALVIEW_EB_ARM11MP_REVB
21 bool "Support MPcore RevB tile" 18 bool "Support ARM11MPCore RevB tile"
22 depends on REALVIEW_MPCORE 19 depends on REALVIEW_EB_ARM11MP
23 default n 20 default n
24 help 21 help
25 Enable support for the MPCore RevB tile on the Realview platform. 22 Enable support for the ARM11MPCore RevB tile on the Realview
26 Since there are device address differences, a 23 platform. Since there are device address differences, a
27 kernel built with this option enabled is not compatible with 24 kernel built with this option enabled is not compatible with
28 other tiles. 25 other revisions of the ARM11MPCore tile.
29 26
30endmenu 27endmenu
diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile
index 36e76ba937fc..ca1e390c3c28 100644
--- a/arch/arm/mach-realview/Makefile
+++ b/arch/arm/mach-realview/Makefile
@@ -4,6 +4,5 @@
4 4
5obj-y := core.o clock.o 5obj-y := core.o clock.o
6obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o 6obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o
7obj-$(CONFIG_SMP) += platsmp.o headsmp.o 7obj-$(CONFIG_SMP) += platsmp.o headsmp.o localtimer.o
8obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o 8obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
9obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 61d70218f1e8..98aefc9f4df3 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -25,6 +25,8 @@
25#include <linux/interrupt.h> 25#include <linux/interrupt.h>
26#include <linux/amba/bus.h> 26#include <linux/amba/bus.h>
27#include <linux/amba/clcd.h> 27#include <linux/amba/clcd.h>
28#include <linux/clocksource.h>
29#include <linux/clockchips.h>
28 30
29#include <asm/system.h> 31#include <asm/system.h>
30#include <asm/hardware.h> 32#include <asm/hardware.h>
@@ -37,7 +39,6 @@
37#include <asm/mach/arch.h> 39#include <asm/mach/arch.h>
38#include <asm/mach/flash.h> 40#include <asm/mach/flash.h>
39#include <asm/mach/irq.h> 41#include <asm/mach/irq.h>
40#include <asm/mach/time.h>
41#include <asm/mach/map.h> 42#include <asm/mach/map.h>
42#include <asm/mach/mmc.h> 43#include <asm/mach/mmc.h>
43 44
@@ -48,6 +49,9 @@
48 49
49#define REALVIEW_REFCOUNTER (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_24MHz_OFFSET) 50#define REALVIEW_REFCOUNTER (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_24MHz_OFFSET)
50 51
52/* used by entry-macro.S */
53void __iomem *gic_cpu_base_addr;
54
51/* 55/*
52 * This is the RealView sched_clock implementation. This has 56 * This is the RealView sched_clock implementation. This has
53 * a resolution of 41.7ns, and a maximum value of about 179s. 57 * a resolution of 41.7ns, and a maximum value of about 179s.
@@ -121,26 +125,6 @@ struct platform_device realview_flash_device = {
121 .resource = &realview_flash_resource, 125 .resource = &realview_flash_resource,
122}; 126};
123 127
124static struct resource realview_smc91x_resources[] = {
125 [0] = {
126 .start = REALVIEW_ETH_BASE,
127 .end = REALVIEW_ETH_BASE + SZ_64K - 1,
128 .flags = IORESOURCE_MEM,
129 },
130 [1] = {
131 .start = IRQ_ETH,
132 .end = IRQ_ETH,
133 .flags = IORESOURCE_IRQ,
134 },
135};
136
137struct platform_device realview_smc91x_device = {
138 .name = "smc91x",
139 .id = 0,
140 .num_resources = ARRAY_SIZE(realview_smc91x_resources),
141 .resource = realview_smc91x_resources,
142};
143
144static struct resource realview_i2c_resource = { 128static struct resource realview_i2c_resource = {
145 .start = REALVIEW_I2C_BASE, 129 .start = REALVIEW_I2C_BASE,
146 .end = REALVIEW_I2C_BASE + SZ_4K - 1, 130 .end = REALVIEW_I2C_BASE + SZ_4K - 1,
@@ -484,45 +468,64 @@ void realview_leds_event(led_event_t ledevt)
484#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC) 468#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
485#endif 469#endif
486 470
487/* 471static void timer_set_mode(enum clock_event_mode mode,
488 * Returns number of ms since last clock interrupt. Note that interrupts 472 struct clock_event_device *clk)
489 * will have been disabled by do_gettimeoffset()
490 */
491static unsigned long realview_gettimeoffset(void)
492{ 473{
493 unsigned long ticks1, ticks2, status; 474 unsigned long ctrl;
494 475
495 /* 476 switch(mode) {
496 * Get the current number of ticks. Note that there is a race 477 case CLOCK_EVT_MODE_PERIODIC:
497 * condition between us reading the timer and checking for 478 writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
498 * an interrupt. We get around this by ensuring that the
499 * counter has not reloaded between our two reads.
500 */
501 ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
502 do {
503 ticks1 = ticks2;
504 status = __raw_readl(__io_address(REALVIEW_GIC_DIST_BASE + GIC_DIST_PENDING_SET)
505 + ((IRQ_TIMERINT0_1 >> 5) << 2));
506 ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
507 } while (ticks2 > ticks1);
508 479
509 /* 480 ctrl = TIMER_CTRL_PERIODIC;
510 * Number of ticks since last interrupt. 481 ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE | TIMER_CTRL_ENABLE;
511 */ 482 break;
512 ticks1 = TIMER_RELOAD - ticks2; 483 case CLOCK_EVT_MODE_ONESHOT:
484 /* period set, and timer enabled in 'next_event' hook */
485 ctrl = TIMER_CTRL_ONESHOT;
486 ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE;
487 break;
488 case CLOCK_EVT_MODE_UNUSED:
489 case CLOCK_EVT_MODE_SHUTDOWN:
490 default:
491 ctrl = 0;
492 }
513 493
514 /* 494 writel(ctrl, TIMER0_VA_BASE + TIMER_CTRL);
515 * Interrupt pending? If so, we've reloaded once already. 495}
516 *
517 * FIXME: Need to check this is effectively timer 0 that expires
518 */
519 if (status & IRQMASK_TIMERINT0_1)
520 ticks1 += TIMER_RELOAD;
521 496
522 /* 497static int timer_set_next_event(unsigned long evt,
523 * Convert the ticks to usecs 498 struct clock_event_device *unused)
524 */ 499{
525 return TICKS2USECS(ticks1); 500 unsigned long ctrl = readl(TIMER0_VA_BASE + TIMER_CTRL);
501
502 writel(evt, TIMER0_VA_BASE + TIMER_LOAD);
503 writel(ctrl | TIMER_CTRL_ENABLE, TIMER0_VA_BASE + TIMER_CTRL);
504
505 return 0;
506}
507
508static struct clock_event_device timer0_clockevent = {
509 .name = "timer0",
510 .shift = 32,
511 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
512 .set_mode = timer_set_mode,
513 .set_next_event = timer_set_next_event,
514 .rating = 300,
515 .cpumask = CPU_MASK_ALL,
516};
517
518static void __init realview_clockevents_init(unsigned int timer_irq)
519{
520 timer0_clockevent.irq = timer_irq;
521 timer0_clockevent.mult =
522 div_sc(1000000, NSEC_PER_SEC, timer0_clockevent.shift);
523 timer0_clockevent.max_delta_ns =
524 clockevent_delta2ns(0xffffffff, &timer0_clockevent);
525 timer0_clockevent.min_delta_ns =
526 clockevent_delta2ns(0xf, &timer0_clockevent);
527
528 clockevents_register_device(&timer0_clockevent);
526} 529}
527 530
528/* 531/*
@@ -530,15 +533,12 @@ static unsigned long realview_gettimeoffset(void)
530 */ 533 */
531static irqreturn_t realview_timer_interrupt(int irq, void *dev_id) 534static irqreturn_t realview_timer_interrupt(int irq, void *dev_id)
532{ 535{
533 // ...clear the interrupt 536 struct clock_event_device *evt = &timer0_clockevent;
537
538 /* clear the interrupt */
534 writel(1, TIMER0_VA_BASE + TIMER_INTCLR); 539 writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
535 540
536 timer_tick(); 541 evt->event_handler(evt);
537
538#if defined(CONFIG_SMP) && !defined(CONFIG_LOCAL_TIMERS)
539 smp_send_timer();
540 update_process_times(user_mode(get_irq_regs()));
541#endif
542 542
543 return IRQ_HANDLED; 543 return IRQ_HANDLED;
544} 544}
@@ -549,13 +549,49 @@ static struct irqaction realview_timer_irq = {
549 .handler = realview_timer_interrupt, 549 .handler = realview_timer_interrupt,
550}; 550};
551 551
552static cycle_t realview_get_cycles(void)
553{
554 return ~readl(TIMER3_VA_BASE + TIMER_VALUE);
555}
556
557static struct clocksource clocksource_realview = {
558 .name = "timer3",
559 .rating = 200,
560 .read = realview_get_cycles,
561 .mask = CLOCKSOURCE_MASK(32),
562 .shift = 20,
563 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
564};
565
566static void __init realview_clocksource_init(void)
567{
568 /* setup timer 0 as free-running clocksource */
569 writel(0, TIMER3_VA_BASE + TIMER_CTRL);
570 writel(0xffffffff, TIMER3_VA_BASE + TIMER_LOAD);
571 writel(0xffffffff, TIMER3_VA_BASE + TIMER_VALUE);
572 writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
573 TIMER3_VA_BASE + TIMER_CTRL);
574
575 clocksource_realview.mult =
576 clocksource_khz2mult(1000, clocksource_realview.shift);
577 clocksource_register(&clocksource_realview);
578}
579
552/* 580/*
553 * Set up timer interrupt, and return the current time in seconds. 581 * Set up the clock source and clock events devices
554 */ 582 */
555static void __init realview_timer_init(void) 583void __init realview_timer_init(unsigned int timer_irq)
556{ 584{
557 u32 val; 585 u32 val;
558 586
587#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
588 /*
589 * The dummy clock device has to be registered before the main device
590 * so that the latter will broadcast the clock events
591 */
592 local_timer_setup(smp_processor_id());
593#endif
594
559 /* 595 /*
560 * set clock frequency: 596 * set clock frequency:
561 * REALVIEW_REFCLK is 32KHz 597 * REALVIEW_REFCLK is 32KHz
@@ -576,18 +612,11 @@ static void __init realview_timer_init(void)
576 writel(0, TIMER2_VA_BASE + TIMER_CTRL); 612 writel(0, TIMER2_VA_BASE + TIMER_CTRL);
577 writel(0, TIMER3_VA_BASE + TIMER_CTRL); 613 writel(0, TIMER3_VA_BASE + TIMER_CTRL);
578 614
579 writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
580 writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_VALUE);
581 writel(TIMER_DIVISOR | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC |
582 TIMER_CTRL_IE, TIMER0_VA_BASE + TIMER_CTRL);
583
584 /* 615 /*
585 * Make irqs happen for the system timer 616 * Make irqs happen for the system timer
586 */ 617 */
587 setup_irq(IRQ_TIMERINT0_1, &realview_timer_irq); 618 setup_irq(timer_irq, &realview_timer_irq);
588}
589 619
590struct sys_timer realview_timer = { 620 realview_clocksource_init();
591 .init = realview_timer_init, 621 realview_clockevents_init(timer_irq);
592 .offset = realview_gettimeoffset, 622}
593};
diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h
index 2b53420f9c1b..492a14c0d604 100644
--- a/arch/arm/mach-realview/core.h
+++ b/arch/arm/mach-realview/core.h
@@ -27,8 +27,6 @@
27#include <asm/leds.h> 27#include <asm/leds.h>
28#include <asm/io.h> 28#include <asm/io.h>
29 29
30extern struct sys_timer realview_timer;
31
32#define AMBA_DEVICE(name,busid,base,plat) \ 30#define AMBA_DEVICE(name,busid,base,plat) \
33static struct amba_device name##_device = { \ 31static struct amba_device name##_device = { \
34 .dev = { \ 32 .dev = { \
@@ -38,7 +36,7 @@ static struct amba_device name##_device = { \
38 }, \ 36 }, \
39 .res = { \ 37 .res = { \
40 .start = REALVIEW_##base##_BASE, \ 38 .start = REALVIEW_##base##_BASE, \
41 .end = (REALVIEW_##base##_BASE) + SZ_4K - 1,\ 39 .end = (REALVIEW_##base##_BASE) + SZ_4K - 1, \
42 .flags = IORESOURCE_MEM, \ 40 .flags = IORESOURCE_MEM, \
43 }, \ 41 }, \
44 .dma_mask = ~0, \ 42 .dma_mask = ~0, \
@@ -46,74 +44,19 @@ static struct amba_device name##_device = { \
46 /* .dma = base##_DMA,*/ \ 44 /* .dma = base##_DMA,*/ \
47} 45}
48 46
49/*
50 * These devices are connected via the core APB bridge
51 */
52#define GPIO2_IRQ { IRQ_GPIOINT2, NO_IRQ }
53#define GPIO2_DMA { 0, 0 }
54#define GPIO3_IRQ { IRQ_GPIOINT3, NO_IRQ }
55#define GPIO3_DMA { 0, 0 }
56
57#define AACI_IRQ { IRQ_AACI, NO_IRQ }
58#define AACI_DMA { 0x80, 0x81 }
59#define MMCI0_IRQ { IRQ_MMCI0A,IRQ_MMCI0B }
60#define MMCI0_DMA { 0x84, 0 }
61#define KMI0_IRQ { IRQ_KMI0, NO_IRQ }
62#define KMI0_DMA { 0, 0 }
63#define KMI1_IRQ { IRQ_KMI1, NO_IRQ }
64#define KMI1_DMA { 0, 0 }
65
66/*
67 * These devices are connected directly to the multi-layer AHB switch
68 */
69#define SMC_IRQ { NO_IRQ, NO_IRQ }
70#define SMC_DMA { 0, 0 }
71#define MPMC_IRQ { NO_IRQ, NO_IRQ }
72#define MPMC_DMA { 0, 0 }
73#define CLCD_IRQ { IRQ_CLCDINT, NO_IRQ }
74#define CLCD_DMA { 0, 0 }
75#define DMAC_IRQ { IRQ_DMAINT, NO_IRQ }
76#define DMAC_DMA { 0, 0 }
77
78/*
79 * These devices are connected via the core APB bridge
80 */
81#define SCTL_IRQ { NO_IRQ, NO_IRQ }
82#define SCTL_DMA { 0, 0 }
83#define WATCHDOG_IRQ { IRQ_WDOGINT, NO_IRQ }
84#define WATCHDOG_DMA { 0, 0 }
85#define GPIO0_IRQ { IRQ_GPIOINT0, NO_IRQ }
86#define GPIO0_DMA { 0, 0 }
87#define GPIO1_IRQ { IRQ_GPIOINT1, NO_IRQ }
88#define GPIO1_DMA { 0, 0 }
89#define RTC_IRQ { IRQ_RTCINT, NO_IRQ }
90#define RTC_DMA { 0, 0 }
91
92/*
93 * These devices are connected via the DMA APB bridge
94 */
95#define SCI_IRQ { IRQ_SCIINT, NO_IRQ }
96#define SCI_DMA { 7, 6 }
97#define UART0_IRQ { IRQ_UARTINT0, NO_IRQ }
98#define UART0_DMA { 15, 14 }
99#define UART1_IRQ { IRQ_UARTINT1, NO_IRQ }
100#define UART1_DMA { 13, 12 }
101#define UART2_IRQ { IRQ_UARTINT2, NO_IRQ }
102#define UART2_DMA { 11, 10 }
103#define UART3_IRQ { IRQ_UART3, NO_IRQ }
104#define UART3_DMA { 0x86, 0x87 }
105#define SSP_IRQ { IRQ_SSPINT, NO_IRQ }
106#define SSP_DMA { 9, 8 }
107
108
109extern struct platform_device realview_flash_device; 47extern struct platform_device realview_flash_device;
110extern struct platform_device realview_smc91x_device;
111extern struct platform_device realview_i2c_device; 48extern struct platform_device realview_i2c_device;
112extern struct mmc_platform_data realview_mmc0_plat_data; 49extern struct mmc_platform_data realview_mmc0_plat_data;
113extern struct mmc_platform_data realview_mmc1_plat_data; 50extern struct mmc_platform_data realview_mmc1_plat_data;
114extern struct clk realview_clcd_clk; 51extern struct clk realview_clcd_clk;
115extern struct clcd_board clcd_plat_data; 52extern struct clcd_board clcd_plat_data;
53extern void __iomem *gic_cpu_base_addr;
54#ifdef CONFIG_LOCAL_TIMERS
55extern void __iomem *twd_base_addr;
56extern unsigned int twd_size;
57#endif
116 58
117extern void realview_leds_event(led_event_t ledevt); 59extern void realview_leds_event(led_event_t ledevt);
60extern void realview_timer_init(unsigned int timer_irq);
118 61
119#endif 62#endif
diff --git a/arch/arm/mach-realview/localtimer.c b/arch/arm/mach-realview/localtimer.c
index c7bdf04ab094..50604360479f 100644
--- a/arch/arm/mach-realview/localtimer.c
+++ b/arch/arm/mach-realview/localtimer.c
@@ -14,19 +14,75 @@
14#include <linux/device.h> 14#include <linux/device.h>
15#include <linux/smp.h> 15#include <linux/smp.h>
16#include <linux/jiffies.h> 16#include <linux/jiffies.h>
17#include <linux/percpu.h>
18#include <linux/clockchips.h>
19#include <linux/irq.h>
17 20
18#include <asm/mach/time.h>
19#include <asm/hardware/arm_twd.h> 21#include <asm/hardware/arm_twd.h>
20#include <asm/hardware/gic.h> 22#include <asm/hardware/gic.h>
21#include <asm/hardware.h> 23#include <asm/hardware.h>
22#include <asm/io.h> 24#include <asm/io.h>
23#include <asm/irq.h> 25#include <asm/irq.h>
24 26
25#define TWD_BASE(cpu) (__io_address(REALVIEW_TWD_BASE) + \ 27static DEFINE_PER_CPU(struct clock_event_device, local_clockevent);
26 ((cpu) * REALVIEW_TWD_SIZE)) 28
29/*
30 * Used on SMP for either the local timer or IPI_TIMER
31 */
32void local_timer_interrupt(void)
33{
34 struct clock_event_device *clk = &__get_cpu_var(local_clockevent);
35
36 clk->event_handler(clk);
37}
38
39#ifdef CONFIG_LOCAL_TIMERS
40
41#define TWD_BASE(cpu) (twd_base_addr + (cpu) * twd_size)
42
43/* set up by the platform code */
44void __iomem *twd_base_addr;
45unsigned int twd_size;
27 46
28static unsigned long mpcore_timer_rate; 47static unsigned long mpcore_timer_rate;
29 48
49static void local_timer_set_mode(enum clock_event_mode mode,
50 struct clock_event_device *clk)
51{
52 void __iomem *base = TWD_BASE(smp_processor_id());
53 unsigned long ctrl;
54
55 switch(mode) {
56 case CLOCK_EVT_MODE_PERIODIC:
57 /* timer load already set up */
58 ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE
59 | TWD_TIMER_CONTROL_PERIODIC;
60 break;
61 case CLOCK_EVT_MODE_ONESHOT:
62 /* period set, and timer enabled in 'next_event' hook */
63 ctrl = TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_ONESHOT;
64 break;
65 case CLOCK_EVT_MODE_UNUSED:
66 case CLOCK_EVT_MODE_SHUTDOWN:
67 default:
68 ctrl = 0;
69 }
70
71 __raw_writel(ctrl, base + TWD_TIMER_CONTROL);
72}
73
74static int local_timer_set_next_event(unsigned long evt,
75 struct clock_event_device *unused)
76{
77 void __iomem *base = TWD_BASE(smp_processor_id());
78 unsigned long ctrl = __raw_readl(base + TWD_TIMER_CONTROL);
79
80 __raw_writel(evt, base + TWD_TIMER_COUNTER);
81 __raw_writel(ctrl | TWD_TIMER_CONTROL_ENABLE, base + TWD_TIMER_CONTROL);
82
83 return 0;
84}
85
30/* 86/*
31 * local_timer_ack: checks for a local timer interrupt. 87 * local_timer_ack: checks for a local timer interrupt.
32 * 88 *
@@ -45,12 +101,11 @@ int local_timer_ack(void)
45 return 0; 101 return 0;
46} 102}
47 103
48void __cpuinit local_timer_setup(unsigned int cpu) 104static void __cpuinit twd_calibrate_rate(unsigned int cpu)
49{ 105{
50 void __iomem *base = TWD_BASE(cpu); 106 void __iomem *base = TWD_BASE(cpu);
51 unsigned int load, offset; 107 unsigned long load, count;
52 u64 waitjiffies; 108 u64 waitjiffies;
53 unsigned int count;
54 109
55 /* 110 /*
56 * If this is the first time round, we need to work out how fast 111 * If this is the first time round, we need to work out how fast
@@ -88,36 +143,36 @@ void __cpuinit local_timer_setup(unsigned int cpu)
88 load = mpcore_timer_rate / HZ; 143 load = mpcore_timer_rate / HZ;
89 144
90 __raw_writel(load, base + TWD_TIMER_LOAD); 145 __raw_writel(load, base + TWD_TIMER_LOAD);
91 __raw_writel(0x7, base + TWD_TIMER_CONTROL); 146}
92
93 /*
94 * Now maneuver our local tick into the right part of the jiffy.
95 * Start by working out where within the tick our local timer
96 * interrupt should go.
97 */
98 offset = ((mpcore_timer_rate / HZ) / (NR_CPUS + 1)) * (cpu + 1);
99
100 /*
101 * gettimeoffset() will return a number of us since the last tick.
102 * Convert this number of us to a local timer tick count.
103 * Be careful of integer overflow whilst keeping maximum precision.
104 *
105 * with HZ=100 and 1MHz (fpga) ~ 1GHz processor:
106 * load = 1 ~ 10,000
107 * mpcore_timer_rate/10000 = 100 ~ 100,000
108 *
109 * so the multiply value will be less than 10^9 always.
110 */
111 load = (system_timer->offset() * (mpcore_timer_rate / 10000)) / 100;
112
113 /* Add on our offset to get the load value */
114 load = (load + offset) % (mpcore_timer_rate / HZ);
115 147
116 __raw_writel(load, base + TWD_TIMER_COUNTER); 148/*
149 * Setup the local clock events for a CPU.
150 */
151void __cpuinit local_timer_setup(unsigned int cpu)
152{
153 struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
154 unsigned long flags;
155
156 twd_calibrate_rate(cpu);
157
158 clk->name = "local_timer";
159 clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
160 clk->rating = 350;
161 clk->set_mode = local_timer_set_mode;
162 clk->set_next_event = local_timer_set_next_event;
163 clk->irq = IRQ_LOCALTIMER;
164 clk->cpumask = cpumask_of_cpu(cpu);
165 clk->shift = 20;
166 clk->mult = div_sc(mpcore_timer_rate, NSEC_PER_SEC, clk->shift);
167 clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk);
168 clk->min_delta_ns = clockevent_delta2ns(0xf, clk);
117 169
118 /* Make sure our local interrupt controller has this enabled */ 170 /* Make sure our local interrupt controller has this enabled */
119 __raw_writel(1 << IRQ_LOCALTIMER, 171 local_irq_save(flags);
120 __io_address(REALVIEW_GIC_DIST_BASE) + GIC_DIST_ENABLE_SET); 172 get_irq_chip(IRQ_LOCALTIMER)->unmask(IRQ_LOCALTIMER);
173 local_irq_restore(flags);
174
175 clockevents_register_device(clk);
121} 176}
122 177
123/* 178/*
@@ -127,3 +182,26 @@ void __cpuexit local_timer_stop(unsigned int cpu)
127{ 182{
128 __raw_writel(0, TWD_BASE(cpu) + TWD_TIMER_CONTROL); 183 __raw_writel(0, TWD_BASE(cpu) + TWD_TIMER_CONTROL);
129} 184}
185
186#else /* CONFIG_LOCAL_TIMERS */
187
188static void dummy_timer_set_mode(enum clock_event_mode mode,
189 struct clock_event_device *clk)
190{
191}
192
193void __cpuinit local_timer_setup(unsigned int cpu)
194{
195 struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
196
197 clk->name = "dummy_timer";
198 clk->features = CLOCK_EVT_FEAT_DUMMY;
199 clk->rating = 200;
200 clk->set_mode = dummy_timer_set_mode;
201 clk->broadcast = smp_timer_broadcast;
202 clk->cpumask = cpumask_of_cpu(cpu);
203
204 clockevents_register_device(clk);
205}
206
207#endif /* !CONFIG_LOCAL_TIMERS */
diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c
index fce3596f9950..de2b7159557d 100644
--- a/arch/arm/mach-realview/platsmp.c
+++ b/arch/arm/mach-realview/platsmp.c
@@ -18,6 +18,7 @@
18#include <asm/hardware/arm_scu.h> 18#include <asm/hardware/arm_scu.h>
19#include <asm/hardware.h> 19#include <asm/hardware.h>
20#include <asm/io.h> 20#include <asm/io.h>
21#include <asm/mach-types.h>
21 22
22extern void realview_secondary_startup(void); 23extern void realview_secondary_startup(void);
23 24
@@ -31,9 +32,13 @@ static unsigned int __init get_core_count(void)
31{ 32{
32 unsigned int ncores; 33 unsigned int ncores;
33 34
34 ncores = __raw_readl(__io_address(REALVIEW_MPCORE_SCU_BASE) + SCU_CONFIG); 35 if (machine_is_realview_eb() && core_tile_eb11mp()) {
36 ncores = __raw_readl(__io_address(REALVIEW_EB11MP_SCU_BASE) + SCU_CONFIG);
37 ncores = (ncores & 0x03) + 1;
38 } else
39 ncores = 1;
35 40
36 return (ncores & 0x03) + 1; 41 return ncores;
37} 42}
38 43
39static DEFINE_SPINLOCK(boot_lock); 44static DEFINE_SPINLOCK(boot_lock);
@@ -52,7 +57,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
52 * core (e.g. timer irq), then they will not have been enabled 57 * core (e.g. timer irq), then they will not have been enabled
53 * for us: do so 58 * for us: do so
54 */ 59 */
55 gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE)); 60 gic_cpu_init(0, __io_address(REALVIEW_EB11MP_GIC_CPU_BASE));
56 61
57 /* 62 /*
58 * let the primary processor know we're out of the 63 * let the primary processor know we're out of the
@@ -187,10 +192,15 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
187 if (max_cpus > ncores) 192 if (max_cpus > ncores)
188 max_cpus = ncores; 193 max_cpus = ncores;
189 194
195#ifdef CONFIG_LOCAL_TIMERS
190 /* 196 /*
191 * Enable the local timer for primary CPU 197 * Enable the local timer for primary CPU. If the device is
198 * dummy (!CONFIG_LOCAL_TIMERS), it was already registers in
199 * realview_timer_init
192 */ 200 */
193 local_timer_setup(cpu); 201 if (machine_is_realview_eb() && core_tile_eb11mp())
202 local_timer_setup(cpu);
203#endif
194 204
195 /* 205 /*
196 * Initialise the present map, which describes the set of CPUs 206 * Initialise the present map, which describes the set of CPUs
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index ecec2f85c4cd..60d9eb810246 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -36,7 +36,9 @@
36#include <asm/mach/arch.h> 36#include <asm/mach/arch.h>
37#include <asm/mach/map.h> 37#include <asm/mach/map.h>
38#include <asm/mach/mmc.h> 38#include <asm/mach/mmc.h>
39#include <asm/mach/time.h>
39 40
41#include <asm/arch/board-eb.h>
40#include <asm/arch/irqs.h> 42#include <asm/arch/irqs.h>
41 43
42#include "core.h" 44#include "core.h"
@@ -58,26 +60,7 @@ static struct map_desc realview_eb_io_desc[] __initdata = {
58 .pfn = __phys_to_pfn(REALVIEW_GIC_DIST_BASE), 60 .pfn = __phys_to_pfn(REALVIEW_GIC_DIST_BASE),
59 .length = SZ_4K, 61 .length = SZ_4K,
60 .type = MT_DEVICE, 62 .type = MT_DEVICE,
61 },
62#ifdef CONFIG_REALVIEW_MPCORE
63 {
64 .virtual = IO_ADDRESS(REALVIEW_GIC1_CPU_BASE),
65 .pfn = __phys_to_pfn(REALVIEW_GIC1_CPU_BASE),
66 .length = SZ_4K,
67 .type = MT_DEVICE,
68 }, { 63 }, {
69 .virtual = IO_ADDRESS(REALVIEW_GIC1_DIST_BASE),
70 .pfn = __phys_to_pfn(REALVIEW_GIC1_DIST_BASE),
71 .length = SZ_4K,
72 .type = MT_DEVICE,
73 }, {
74 .virtual = IO_ADDRESS(REALVIEW_MPCORE_L220_BASE),
75 .pfn = __phys_to_pfn(REALVIEW_MPCORE_L220_BASE),
76 .length = SZ_8K,
77 .type = MT_DEVICE,
78 },
79#endif
80 {
81 .virtual = IO_ADDRESS(REALVIEW_SCTL_BASE), 64 .virtual = IO_ADDRESS(REALVIEW_SCTL_BASE),
82 .pfn = __phys_to_pfn(REALVIEW_SCTL_BASE), 65 .pfn = __phys_to_pfn(REALVIEW_SCTL_BASE),
83 .length = SZ_4K, 66 .length = SZ_4K,
@@ -103,11 +86,95 @@ static struct map_desc realview_eb_io_desc[] __initdata = {
103#endif 86#endif
104}; 87};
105 88
89static struct map_desc realview_eb11mp_io_desc[] __initdata = {
90 {
91 .virtual = IO_ADDRESS(REALVIEW_EB11MP_GIC_CPU_BASE),
92 .pfn = __phys_to_pfn(REALVIEW_EB11MP_GIC_CPU_BASE),
93 .length = SZ_4K,
94 .type = MT_DEVICE,
95 }, {
96 .virtual = IO_ADDRESS(REALVIEW_EB11MP_GIC_DIST_BASE),
97 .pfn = __phys_to_pfn(REALVIEW_EB11MP_GIC_DIST_BASE),
98 .length = SZ_4K,
99 .type = MT_DEVICE,
100 }, {
101 .virtual = IO_ADDRESS(REALVIEW_EB11MP_L220_BASE),
102 .pfn = __phys_to_pfn(REALVIEW_EB11MP_L220_BASE),
103 .length = SZ_8K,
104 .type = MT_DEVICE,
105 }
106};
107
106static void __init realview_eb_map_io(void) 108static void __init realview_eb_map_io(void)
107{ 109{
108 iotable_init(realview_eb_io_desc, ARRAY_SIZE(realview_eb_io_desc)); 110 iotable_init(realview_eb_io_desc, ARRAY_SIZE(realview_eb_io_desc));
111 if (core_tile_eb11mp())
112 iotable_init(realview_eb11mp_io_desc, ARRAY_SIZE(realview_eb11mp_io_desc));
109} 113}
110 114
115/*
116 * RealView EB AMBA devices
117 */
118
119/*
120 * These devices are connected via the core APB bridge
121 */
122#define GPIO2_IRQ { IRQ_EB_GPIO2, NO_IRQ }
123#define GPIO2_DMA { 0, 0 }
124#define GPIO3_IRQ { IRQ_EB_GPIO3, NO_IRQ }
125#define GPIO3_DMA { 0, 0 }
126
127#define AACI_IRQ { IRQ_EB_AACI, NO_IRQ }
128#define AACI_DMA { 0x80, 0x81 }
129#define MMCI0_IRQ { IRQ_EB_MMCI0A, IRQ_EB_MMCI0B }
130#define MMCI0_DMA { 0x84, 0 }
131#define KMI0_IRQ { IRQ_EB_KMI0, NO_IRQ }
132#define KMI0_DMA { 0, 0 }
133#define KMI1_IRQ { IRQ_EB_KMI1, NO_IRQ }
134#define KMI1_DMA { 0, 0 }
135
136/*
137 * These devices are connected directly to the multi-layer AHB switch
138 */
139#define SMC_IRQ { NO_IRQ, NO_IRQ }
140#define SMC_DMA { 0, 0 }
141#define MPMC_IRQ { NO_IRQ, NO_IRQ }
142#define MPMC_DMA { 0, 0 }
143#define CLCD_IRQ { IRQ_EB_CLCD, NO_IRQ }
144#define CLCD_DMA { 0, 0 }
145#define DMAC_IRQ { IRQ_EB_DMA, NO_IRQ }
146#define DMAC_DMA { 0, 0 }
147
148/*
149 * These devices are connected via the core APB bridge
150 */
151#define SCTL_IRQ { NO_IRQ, NO_IRQ }
152#define SCTL_DMA { 0, 0 }
153#define WATCHDOG_IRQ { IRQ_EB_WDOG, NO_IRQ }
154#define WATCHDOG_DMA { 0, 0 }
155#define GPIO0_IRQ { IRQ_EB_GPIO0, NO_IRQ }
156#define GPIO0_DMA { 0, 0 }
157#define GPIO1_IRQ { IRQ_EB_GPIO1, NO_IRQ }
158#define GPIO1_DMA { 0, 0 }
159#define RTC_IRQ { IRQ_EB_RTC, NO_IRQ }
160#define RTC_DMA { 0, 0 }
161
162/*
163 * These devices are connected via the DMA APB bridge
164 */
165#define SCI_IRQ { IRQ_EB_SCI, NO_IRQ }
166#define SCI_DMA { 7, 6 }
167#define UART0_IRQ { IRQ_EB_UART0, NO_IRQ }
168#define UART0_DMA { 15, 14 }
169#define UART1_IRQ { IRQ_EB_UART1, NO_IRQ }
170#define UART1_DMA { 13, 12 }
171#define UART2_IRQ { IRQ_EB_UART2, NO_IRQ }
172#define UART2_DMA { 11, 10 }
173#define UART3_IRQ { IRQ_EB_UART3, NO_IRQ }
174#define UART3_DMA { 0x86, 0x87 }
175#define SSP_IRQ { IRQ_EB_SSP, NO_IRQ }
176#define SSP_DMA { 9, 8 }
177
111/* FPGA Primecells */ 178/* FPGA Primecells */
112AMBA_DEVICE(aaci, "fpga:04", AACI, NULL); 179AMBA_DEVICE(aaci, "fpga:04", AACI, NULL);
113AMBA_DEVICE(mmc0, "fpga:05", MMCI0, &realview_mmc0_plat_data); 180AMBA_DEVICE(mmc0, "fpga:05", MMCI0, &realview_mmc0_plat_data);
@@ -153,38 +220,127 @@ static struct amba_device *amba_devs[] __initdata = {
153 &kmi1_device, 220 &kmi1_device,
154}; 221};
155 222
223/*
224 * RealView EB platform devices
225 */
226
227static struct resource realview_eb_smc91x_resources[] = {
228 [0] = {
229 .start = REALVIEW_ETH_BASE,
230 .end = REALVIEW_ETH_BASE + SZ_64K - 1,
231 .flags = IORESOURCE_MEM,
232 },
233 [1] = {
234 .start = IRQ_EB_ETH,
235 .end = IRQ_EB_ETH,
236 .flags = IORESOURCE_IRQ,
237 },
238};
239
240static struct platform_device realview_eb_smc91x_device = {
241 .name = "smc91x",
242 .id = 0,
243 .num_resources = ARRAY_SIZE(realview_eb_smc91x_resources),
244 .resource = realview_eb_smc91x_resources,
245};
246
156static void __init gic_init_irq(void) 247static void __init gic_init_irq(void)
157{ 248{
158#ifdef CONFIG_REALVIEW_MPCORE 249 if (core_tile_eb11mp()) {
159 unsigned int pldctrl; 250 unsigned int pldctrl;
160 writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK)); 251
161 pldctrl = readl(__io_address(REALVIEW_SYS_BASE) + REALVIEW_MPCORE_SYS_PLD_CTRL1); 252 /* new irq mode */
162 pldctrl |= 0x00800000; /* New irq mode */ 253 writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK));
163 writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + REALVIEW_MPCORE_SYS_PLD_CTRL1); 254 pldctrl = readl(__io_address(REALVIEW_SYS_BASE) + REALVIEW_EB11MP_SYS_PLD_CTRL1);
164 writel(0x00000000, __io_address(REALVIEW_SYS_LOCK)); 255 pldctrl |= 0x00800000;
256 writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + REALVIEW_EB11MP_SYS_PLD_CTRL1);
257 writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
258
259 /* core tile GIC, primary */
260 gic_cpu_base_addr = __io_address(REALVIEW_EB11MP_GIC_CPU_BASE);
261 gic_dist_init(0, __io_address(REALVIEW_EB11MP_GIC_DIST_BASE), 29);
262 gic_cpu_init(0, gic_cpu_base_addr);
263
264#ifndef CONFIG_REALVIEW_EB_ARM11MP_REVB
265 /* board GIC, secondary */
266 gic_dist_init(1, __io_address(REALVIEW_GIC_DIST_BASE), 64);
267 gic_cpu_init(1, __io_address(REALVIEW_GIC_CPU_BASE));
268 gic_cascade_irq(1, IRQ_EB11MP_EB_IRQ1);
165#endif 269#endif
166 gic_dist_init(0, __io_address(REALVIEW_GIC_DIST_BASE), 29); 270 } else {
167 gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE)); 271 /* board GIC, primary */
168#if defined(CONFIG_REALVIEW_MPCORE) && !defined(CONFIG_REALVIEW_MPCORE_REVB) 272 gic_cpu_base_addr = __io_address(REALVIEW_GIC_CPU_BASE);
169 gic_dist_init(1, __io_address(REALVIEW_GIC1_DIST_BASE), 64); 273 gic_dist_init(0, __io_address(REALVIEW_GIC_DIST_BASE), 29);
170 gic_cpu_init(1, __io_address(REALVIEW_GIC1_CPU_BASE)); 274 gic_cpu_init(0, gic_cpu_base_addr);
171 gic_cascade_irq(1, IRQ_EB_IRQ1); 275 }
276}
277
278/*
279 * Fix up the IRQ numbers for the RealView EB/ARM11MPCore tile
280 */
281static void realview_eb11mp_fixup(void)
282{
283 /* AMBA devices */
284 dmac_device.irq[0] = IRQ_EB11MP_DMA;
285 uart0_device.irq[0] = IRQ_EB11MP_UART0;
286 uart1_device.irq[0] = IRQ_EB11MP_UART1;
287 uart2_device.irq[0] = IRQ_EB11MP_UART2;
288 uart3_device.irq[0] = IRQ_EB11MP_UART3;
289 clcd_device.irq[0] = IRQ_EB11MP_CLCD;
290 wdog_device.irq[0] = IRQ_EB11MP_WDOG;
291 gpio0_device.irq[0] = IRQ_EB11MP_GPIO0;
292 gpio1_device.irq[0] = IRQ_EB11MP_GPIO1;
293 gpio2_device.irq[0] = IRQ_EB11MP_GPIO2;
294 rtc_device.irq[0] = IRQ_EB11MP_RTC;
295 sci0_device.irq[0] = IRQ_EB11MP_SCI;
296 ssp0_device.irq[0] = IRQ_EB11MP_SSP;
297 aaci_device.irq[0] = IRQ_EB11MP_AACI;
298 mmc0_device.irq[0] = IRQ_EB11MP_MMCI0A;
299 mmc0_device.irq[1] = IRQ_EB11MP_MMCI0B;
300 kmi0_device.irq[0] = IRQ_EB11MP_KMI0;
301 kmi1_device.irq[0] = IRQ_EB11MP_KMI1;
302
303 /* platform devices */
304 realview_eb_smc91x_resources[1].start = IRQ_EB11MP_ETH;
305 realview_eb_smc91x_resources[1].end = IRQ_EB11MP_ETH;
306}
307
308static void __init realview_eb_timer_init(void)
309{
310 unsigned int timer_irq;
311
312 if (core_tile_eb11mp()) {
313#ifdef CONFIG_LOCAL_TIMERS
314 twd_base_addr = __io_address(REALVIEW_EB11MP_TWD_BASE);
315 twd_size = REALVIEW_EB11MP_TWD_SIZE;
172#endif 316#endif
317 timer_irq = IRQ_EB11MP_TIMER0_1;
318 } else
319 timer_irq = IRQ_EB_TIMER0_1;
320
321 realview_timer_init(timer_irq);
173} 322}
174 323
324static struct sys_timer realview_eb_timer = {
325 .init = realview_eb_timer_init,
326};
327
175static void __init realview_eb_init(void) 328static void __init realview_eb_init(void)
176{ 329{
177 int i; 330 int i;
178 331
179#ifdef CONFIG_REALVIEW_MPCORE 332 if (core_tile_eb11mp()) {
180 /* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled 333 realview_eb11mp_fixup();
181 * Bits: .... ...0 0111 1001 0000 .... .... .... */ 334
182 l2x0_init(__io_address(REALVIEW_MPCORE_L220_BASE), 0x00790000, 0xfe000fff); 335 /* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled
183#endif 336 * Bits: .... ...0 0111 1001 0000 .... .... .... */
337 l2x0_init(__io_address(REALVIEW_EB11MP_L220_BASE), 0x00790000, 0xfe000fff);
338 }
339
184 clk_register(&realview_clcd_clk); 340 clk_register(&realview_clcd_clk);
185 341
186 platform_device_register(&realview_flash_device); 342 platform_device_register(&realview_flash_device);
187 platform_device_register(&realview_smc91x_device); 343 platform_device_register(&realview_eb_smc91x_device);
188 platform_device_register(&realview_i2c_device); 344 platform_device_register(&realview_i2c_device);
189 345
190 for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { 346 for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
@@ -204,6 +360,6 @@ MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
204 .boot_params = 0x00000100, 360 .boot_params = 0x00000100,
205 .map_io = realview_eb_map_io, 361 .map_io = realview_eb_map_io,
206 .init_irq = gic_init_irq, 362 .init_irq = gic_init_irq,
207 .timer = &realview_timer, 363 .timer = &realview_eb_timer,
208 .init_machine = realview_eb_init, 364 .init_machine = realview_eb_init,
209MACHINE_END 365MACHINE_END