diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c index 6eac36d1b8c893fcb1c56d16d1ba0808ce19e90d..02b266a31c467e44a717700d795bde4ed0d4116a 100644 --- a/arch/mips/sibyte/bcm1480/smp.c +++ b/arch/mips/sibyte/bcm1480/smp.c @@ -69,8 +69,9 @@ void bcm1480_smp_init(void) void bcm1480_smp_finish(void) { - extern void bcm1480_time_init(void); - bcm1480_time_init(); + extern void sb1480_clockevent_init(void); + + sb1480_clockevent_init(); local_irq_enable(); } diff --git a/arch/mips/sibyte/bcm1480/time.c b/arch/mips/sibyte/bcm1480/time.c index 5b4bfbbb5a24b053c9176cb1bec5860e894fdd8f..c730744aa474db7efb1bf48b7af13b904734761a 100644 --- a/arch/mips/sibyte/bcm1480/time.c +++ b/arch/mips/sibyte/bcm1480/time.c @@ -27,9 +27,8 @@ */ #include #include -#include +#include #include -#include #include #include @@ -101,25 +100,36 @@ static void sibyte_set_mode(enum clock_event_mode mode, break; case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */ + case CLOCK_EVT_MODE_RESUME: ; } } -struct clock_event_device sibyte_hpt_clockevent = { - .name = "bcm1480-counter", - .features = CLOCK_EVT_FEAT_PERIODIC, - .set_mode = sibyte_set_mode, - .shift = 32, - .irq = 0, -}; +static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd) +{ + unsigned int cpu = smp_processor_id(); + void __iomem *timer_init; + unsigned int cnt; + int res; + + timer_init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); + cnt = __raw_readq(timer_init); + cnt += delta; + __raw_writeq(cnt, timer_init); + res = ((long)(__raw_readq(timer_init) - cnt ) > 0) ? -ETIME : 0; + + return res; +} + +static DEFINE_PER_CPU(struct clock_event_device, sibyte_hpt_clockevent); static irqreturn_t sibyte_counter_handler(int irq, void *dev_id) { - struct clock_event_device *cd = &sibyte_hpt_clockevent; unsigned int cpu = smp_processor_id(); + struct clock_event_device *cd = &per_cpu(sibyte_hpt_clockevent, cpu); /* Reset the timer */ - __raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS, + __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); cd->event_handler(cd); @@ -140,24 +150,21 @@ static struct irqaction sibyte_counter_irqaction = { * called directly from irq_handler.S when IP[4] is set during an * interrupt */ -static void __init sb1480_clockevent_init(void) +void __cpuinit sb1480_clockevent_init(void) { unsigned int cpu = smp_processor_id(); unsigned int irq = K_BCM1480_INT_TIMER_0 + cpu; + struct clock_event_device *cd = &per_cpu(sibyte_hpt_clockevent, cpu); - setup_irq(irq, &sibyte_counter_irqaction); -} + cd->name = "bcm1480-counter"; + cd->features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_MODE_ONESHOT; + cd->set_next_event = sibyte_next_event; + cd->set_mode = sibyte_set_mode; + cd->irq = irq; + clockevent_set_clock(cd, BCM1480_HPT_VALUE); -void bcm1480_timer_interrupt(void) -{ - int cpu = smp_processor_id(); - int irq = K_BCM1480_INT_TIMER_0 + cpu; - - /* Reset the timer */ - __raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS, - IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); - - ll_timer_interrupt(irq); + setup_irq(irq, &sibyte_counter_irqaction); } static cycle_t bcm1480_hpt_read(void) @@ -168,9 +175,26 @@ static cycle_t bcm1480_hpt_read(void) return (jiffies + 1) * (BCM1480_HPT_VALUE / HZ) - count; } +struct clocksource bcm1480_clocksource = { + .name = "MIPS", + .rating = 200, + .read = bcm1480_hpt_read, + .mask = CLOCKSOURCE_MASK(32), + .shift = 32, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +void __init sb1480_clocksource_init(void) +{ + struct clocksource *cs = &bcm1480_clocksource; + + clocksource_set_clock(cs, BCM1480_HPT_VALUE); + clocksource_register(cs); +} + void __init bcm1480_hpt_setup(void) { - clocksource_mips.read = bcm1480_hpt_read; mips_hpt_frequency = BCM1480_HPT_VALUE; + sb1480_clocksource_init(); sb1480_clockevent_init(); } diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c index 7659174819c65720f0a3de051a416ac0dbcf533d..500d17e84c090bbf3e57616f72e9b1b28727fef0 100644 --- a/arch/mips/sibyte/sb1250/irq.c +++ b/arch/mips/sibyte/sb1250/irq.c @@ -400,43 +400,11 @@ static void sb1250_kgdb_interrupt(void) #endif /* CONFIG_KGDB */ -static inline void sb1250_timer_interrupt(void) -{ - int cpu = smp_processor_id(); - int irq = K_INT_TIMER_0 + cpu; - - irq_enter(); - kstat_this_cpu.irqs[irq]++; - - write_seqlock(&xtime_lock); - - /* ACK interrupt */ - ____raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, - IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); - - /* - * call the generic timer interrupt handling - */ - do_timer(1); - - write_sequnlock(&xtime_lock); - - /* - * In UP mode, we call local_timer_interrupt() to do profiling - * and process accouting. - * - * In SMP mode, local_timer_interrupt() is invoked by appropriate - * low-level local timer interrupt handler. - */ - local_timer_interrupt(irq); - - irq_exit(); -} - extern void sb1250_mailbox_interrupt(void); asmlinkage void plat_irq_dispatch(void) { + unsigned int cpu = smp_processor_id(); unsigned int pending; /* @@ -454,7 +422,7 @@ asmlinkage void plat_irq_dispatch(void) if (pending & CAUSEF_IP7) /* CPU performance counter interrupt */ do_IRQ(MIPS_CPU_IRQ_BASE + 7); else if (pending & CAUSEF_IP4) - sb1250_timer_interrupt(); + do_IRQ(K_INT_TIMER_0 + cpu); /* sb1250_timer_interrupt() */ #ifdef CONFIG_SMP else if (pending & CAUSEF_IP3) diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c index c38e1f34460d44847473d17f297af2f4a3a14d6b..aaa4f30dda7904dc9dae44a8844da0a303999b2c 100644 --- a/arch/mips/sibyte/sb1250/smp.c +++ b/arch/mips/sibyte/sb1250/smp.c @@ -57,8 +57,9 @@ void sb1250_smp_init(void) void sb1250_smp_finish(void) { - extern void sb1250_time_init(void); - sb1250_time_init(); + extern void sb1250_clockevent_init(void); + + sb1250_clockevent_init(); local_irq_enable(); } diff --git a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c index fe11fed8e0d73e25857678d0c68746d9abb21887..9ef54628bc9c8eecac4203d31f004cc790b0d210 100644 --- a/arch/mips/sibyte/sb1250/time.c +++ b/arch/mips/sibyte/sb1250/time.c @@ -100,6 +100,7 @@ static void sibyte_set_mode(enum clock_event_mode mode, break; case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */ + case CLOCK_EVT_MODE_RESUME: ; } } @@ -144,79 +145,7 @@ static struct irqaction sibyte_irqaction = { .name = "timer", }; -/* - * The general purpose timer ticks at 1 Mhz independent if - * the rest of the system - */ -static void sibyte_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) -{ - unsigned int cpu = smp_processor_id(); - void __iomem *timer_cfg, *timer_init; - - timer_cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); - timer_init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); - - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - __raw_writeq(0, timer_cfg); - __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, timer_init); - __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, - timer_cfg); - break; - - case CLOCK_EVT_MODE_ONESHOT: - /* Stop the timer until we actually program a shot */ - case CLOCK_EVT_MODE_SHUTDOWN: - __raw_writeq(0, timer_cfg); - break; - - case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */ - ; - } -} - -static int -sibyte_next_event(unsigned long delta, struct clock_event_device *evt) -{ - unsigned int cpu = smp_processor_id(); - void __iomem *timer_cfg, *timer_init; - - timer_cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); - timer_init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); - - __raw_writeq(0, timer_cfg); - __raw_writeq(delta, timer_init); - __raw_writeq(M_SCD_TIMER_ENABLE, timer_cfg); - - return 0; -} - -struct clock_event_device sibyte_hpt_clockevent = { - .name = "sb1250-counter", - .features = CLOCK_EVT_FEAT_PERIODIC, - .set_mode = sibyte_set_mode, - .set_next_event = sibyte_next_event, - .shift = 32, - .irq = 0, -}; - -static irqreturn_t sibyte_counter_handler(int irq, void *dev_id) -{ - struct clock_event_device *cd = &sibyte_hpt_clockevent; - - cd->event_handler(cd); - - return IRQ_HANDLED; -} - -static struct irqaction sibyte_irqaction = { - .handler = sibyte_counter_handler, - .flags = IRQF_DISABLED | IRQF_PERCPU, - .name = "timer", -}; - -static void __init sb1250_clockevent_init(void) +void __cpuinit sb1250_clockevent_init(void) { struct clock_event_device *cd = &sibyte_hpt_clockevent; unsigned int cpu = smp_processor_id(); @@ -249,12 +178,6 @@ static void __init sb1250_clockevent_init(void) clockevents_register_device(cd); } -void __init plat_time_init(void) -{ - sb1250_clocksource_init(); - sb1250_clockevent_init(); -} - /* * The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over * again. @@ -267,3 +190,26 @@ static cycle_t sb1250_hpt_read(void) return SB1250_HPT_VALUE - count; } + +struct clocksource bcm1250_clocksource = { + .name = "MIPS", + .rating = 200, + .read = sb1250_hpt_read, + .mask = CLOCKSOURCE_MASK(32), + .shift = 32, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +void __init sb1250_clocksource_init(void) +{ + struct clocksource *cs = &bcm1250_clocksource; + + clocksource_set_clock(cs, V_SCD_TIMER_FREQ); + clocksource_register(cs); +} + +void __init plat_time_init(void) +{ + sb1250_clocksource_init(); + sb1250_clockevent_init(); +} diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c index 8b3ef0e4cd555c735bf3cfe60c5a42110fc0ac9e..080c966263b701aa608bb536f8147803aa11fc41 100644 --- a/arch/mips/sibyte/swarm/setup.c +++ b/arch/mips/sibyte/swarm/setup.c @@ -69,31 +69,6 @@ const char *get_system_type(void) return "SiByte " SIBYTE_BOARD_NAME; } -void __init plat_time_init(void) -{ -#if defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X) - /* Setup HPT */ - sb1250_hpt_setup(); -#endif -} - -void __init plat_timer_setup(struct irqaction *irq) -{ - /* - * we don't set up irqaction, because we will deliver timer - * interrupts through low-level (direct) meachanism. - */ - - /* We only need to setup the generic timer */ -#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) - bcm1480_time_init(); -#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X) - sb1250_time_init(); -#else -#error invalid SiByte board configuration -#endif -} - int swarm_be_handler(struct pt_regs *regs, int is_fixup) { if (!is_fixup && (regs->cp0_cause & 4)) {