X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=arch%2Fmips%2Fsni%2Ftime.c;h=69f5f88711cca8721cbc97ad4fda96e6682ecffd;hb=d9be28ea9110c596a05bd2d56afa94251bd19818;hp=b80877349d3897718d6ee52672d00e83701c93d7;hpb=2843483d2eb02ad104edbe8b2429fb6a39d25063;p=mv-sheeva.git diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c index b80877349d3..69f5f88711c 100644 --- a/arch/mips/sni/time.c +++ b/arch/mips/sni/time.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -11,27 +12,78 @@ #define SNI_COUNTER2_DIV 64 #define SNI_COUNTER0_DIV ((SNI_CLOCK_TICK_RATE / SNI_COUNTER2_DIV) / HZ) -static void sni_a20r_timer_ack(void) +static void a20r_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) { - *(volatile u8 *)A20R_PT_TIM0_ACK = 0x0; wmb(); + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0x34; + wmb(); + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV; + wmb(); + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV >> 8; + wmb(); + + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0xb4; + wmb(); + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV; + wmb(); + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV >> 8; + wmb(); + + break; + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + break; + case CLOCK_EVT_MODE_RESUME: + break; + } } +static struct clock_event_device a20r_clockevent_device = { + .name = "a20r-timer", + .features = CLOCK_EVT_FEAT_PERIODIC, + + /* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */ + + .rating = 300, + .irq = SNI_A20R_IRQ_TIMER, + .set_mode = a20r_set_mode, +}; + +static irqreturn_t a20r_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *cd = dev_id; + + *(volatile u8 *)A20R_PT_TIM0_ACK = 0; + wmb(); + + cd->event_handler(cd); + + return IRQ_HANDLED; +} + +static struct irqaction a20r_irqaction = { + .handler = a20r_interrupt, + .flags = IRQF_DISABLED | IRQF_PERCPU, + .name = "a20r-timer", +}; + /* * a20r platform uses 2 counters to divide the input frequency. * Counter 2 output is connected to Counter 0 & 1 input. */ -static void __init sni_a20r_timer_setup(struct irqaction *irq) +static void __init sni_a20r_timer_setup(void) { - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0x34; wmb(); - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = (SNI_COUNTER0_DIV) & 0xff; wmb(); - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = (SNI_COUNTER0_DIV >> 8) & 0xff; wmb(); - - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0xb4; wmb(); - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = (SNI_COUNTER2_DIV) & 0xff; wmb(); - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = (SNI_COUNTER2_DIV >> 8) & 0xff; wmb(); - - setup_irq(SNI_A20R_IRQ_TIMER, irq); - mips_timer_ack = sni_a20r_timer_ack; + struct clock_event_device *cd = &a20r_clockevent_device; + struct irqaction *action = &a20r_irqaction; + unsigned int cpu = smp_processor_id(); + + cd->cpumask = cpumask_of(cpu); + clockevents_register_device(cd); + action->dev_id = cd; + setup_irq(SNI_A20R_IRQ_TIMER, &a20r_irqaction); } #define SNI_8254_TICK_RATE 1193182UL @@ -118,37 +170,15 @@ void __init plat_time_init(void) mips_hpt_frequency = r4k_tick * HZ; - setup_pit_timer(); -} - -/* - * R4k counter based timer interrupt. Works on RM200-225 and possibly - * others but not on RM400 - */ -static void __init sni_cpu_timer_setup(struct irqaction *irq) -{ - setup_irq(SNI_MIPS_IRQ_CPU_TIMER, irq); -} - -void __init plat_timer_setup(struct irqaction *irq) -{ switch (sni_brd_type) { case SNI_BRD_10: case SNI_BRD_10NEW: case SNI_BRD_TOWER_OASIC: case SNI_BRD_MINITOWER: - sni_a20r_timer_setup(irq); - break; - - case SNI_BRD_PCI_TOWER: - case SNI_BRD_RM200: - case SNI_BRD_PCI_MTOWER: - case SNI_BRD_PCI_DESKTOP: - case SNI_BRD_PCI_TOWER_CPLUS: - case SNI_BRD_PCI_MTOWER_CPLUS: - sni_cpu_timer_setup(irq); - break; + sni_a20r_timer_setup(); + break; } + setup_pit_timer(); } unsigned long read_persistent_clock(void)