aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-realview/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-realview/core.c')
-rw-r--r--arch/arm/mach-realview/core.c179
1 files changed, 104 insertions, 75 deletions
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};