diff options
Diffstat (limited to 'arch/mips/sgi-ip27')
-rw-r--r-- | arch/mips/sgi-ip27/ip27-berr.c | 2 | ||||
-rw-r--r-- | arch/mips/sgi-ip27/ip27-init.c | 6 | ||||
-rw-r--r-- | arch/mips/sgi-ip27/ip27-irq.c | 5 | ||||
-rw-r--r-- | arch/mips/sgi-ip27/ip27-smp.c | 4 | ||||
-rw-r--r-- | arch/mips/sgi-ip27/ip27-timer.c | 189 |
5 files changed, 110 insertions, 96 deletions
diff --git a/arch/mips/sgi-ip27/ip27-berr.c b/arch/mips/sgi-ip27/ip27-berr.c index 123141ab21a2..7d05e68fdc77 100644 --- a/arch/mips/sgi-ip27/ip27-berr.c +++ b/arch/mips/sgi-ip27/ip27-berr.c @@ -21,8 +21,6 @@ #include <asm/traps.h> #include <asm/uaccess.h> -extern void dump_tlb_all(void); - static void dump_hub_information(unsigned long errst0, unsigned long errst1) { static char *err_type[2][8] = { diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c index 74158d349630..681b593071cb 100644 --- a/arch/mips/sgi-ip27/ip27-init.c +++ b/arch/mips/sgi-ip27/ip27-init.c @@ -47,6 +47,9 @@ cnodeid_t cpuid_to_compact_node[MAXCPUS]; EXPORT_SYMBOL(nasid_to_compact_node); +struct cpuinfo_ip27 sn_cpu_info[NR_CPUS]; +EXPORT_SYMBOL_GPL(sn_cpu_info); + extern void pcibr_setup(cnodeid_t); extern void xtalk_probe_node(cnodeid_t nid); @@ -191,7 +194,6 @@ static inline void ioc3_eth_init(void) ioc3->eier = 0; } -extern void ip27_time_init(void); extern void ip27_reboot_setup(void); void __init plat_mem_setup(void) @@ -238,6 +240,4 @@ void __init plat_mem_setup(void) per_cpu_init(); set_io_port_base(IO_BASE); - - board_time_init = ip27_time_init; } diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index 856649cf9f1e..1bb692a3b319 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -374,14 +374,13 @@ int __devinit request_bridge_irq(struct bridge_controller *bc) return irq; } -extern void ip27_rt_timer_interrupt(void); - asmlinkage void plat_irq_dispatch(void) { unsigned long pending = read_c0_cause() & read_c0_status(); + extern unsigned int rt_timer_irq; if (pending & CAUSEF_IP4) - ip27_rt_timer_interrupt(); + do_IRQ(rt_timer_irq); else if (pending & CAUSEF_IP2) /* PI_INT_PEND_0 or CC_PEND_{A|B} */ ip27_do_irq_mask0(); else if (pending & CAUSEF_IP3) /* PI_INT_PEND_1 */ diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c index fbb27728a76a..a70656d42191 100644 --- a/arch/mips/sgi-ip27/ip27-smp.c +++ b/arch/mips/sgi-ip27/ip27-smp.c @@ -33,7 +33,7 @@ static void alloc_cpupda(cpuid_t cpu, int cpunum) nasid_t nasid = COMPACT_TO_NASID_NODEID(node); cputonasid(cpunum) = nasid; - cpu_data[cpunum].p_nodeid = node; + sn_cpu_info[cpunum].p_nodeid = node; cputoslice(cpunum) = get_cpu_slice(cpu); } @@ -176,7 +176,7 @@ void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle) unsigned long gp = (unsigned long)task_thread_info(idle); unsigned long sp = __KSTK_TOS(idle); - LAUNCH_SLAVE(cputonasid(cpu),cputoslice(cpu), + LAUNCH_SLAVE(cputonasid(cpu), cputoslice(cpu), (launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap), 0, (void *) sp, (void *) gp); } diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index 8c3c78c63ccd..d467bf4f6c3f 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -3,6 +3,7 @@ * Copytight (C) 1999, 2000 Silicon Graphics, Inc. */ #include <linux/bcd.h> +#include <linux/clockchips.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/sched.h> @@ -25,23 +26,8 @@ #include <asm/sn/sn0/ip27.h> #include <asm/sn/sn0/hub.h> -/* - * This is a hack; we really need to figure these values out dynamically - * - * Since 800 ns works very well with various HUB frequencies, such as - * 360, 380, 390 and 400 MHZ, we use 800 ns rtc cycle time. - * - * Ralf: which clock rate is used to feed the counter? - */ -#define NSEC_PER_CYCLE 800 -#define CYCLES_PER_SEC (NSEC_PER_SEC/NSEC_PER_CYCLE) -#define CYCLES_PER_JIFFY (CYCLES_PER_SEC/HZ) - #define TICK_SIZE (tick_nsec / 1000) -static unsigned long ct_cur[NR_CPUS]; /* What counter should be at next timer irq */ -static long last_rtc_update; /* Last time the rtc clock got updated */ - #if 0 static int set_rtc_mmss(unsigned long nowtime) { @@ -87,53 +73,6 @@ static int set_rtc_mmss(unsigned long nowtime) } #endif -static unsigned int rt_timer_irq; - -void ip27_rt_timer_interrupt(void) -{ - int cpu = smp_processor_id(); - int cpuA = cputoslice(cpu) == 0; - unsigned int irq = rt_timer_irq; - - irq_enter(); - write_seqlock(&xtime_lock); - -again: - LOCAL_HUB_S(cpuA ? PI_RT_PEND_A : PI_RT_PEND_B, 0); /* Ack */ - ct_cur[cpu] += CYCLES_PER_JIFFY; - LOCAL_HUB_S(cpuA ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, ct_cur[cpu]); - - if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur[cpu]) - goto again; - - kstat_this_cpu.irqs[irq]++; /* kstat only for bootcpu? */ - - if (cpu == 0) - do_timer(1); - - update_process_times(user_mode(get_irq_regs())); - - /* - * If we have an externally synchronized Linux clock, then update - * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be - * called as close as possible to when a second starts. - */ - if (ntp_synced() && - xtime.tv_sec > last_rtc_update + 660 && - (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 && - (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) { - if (rtc_mips_set_time(xtime.tv_sec) == 0) { - last_rtc_update = xtime.tv_sec; - } else { - last_rtc_update = xtime.tv_sec - 600; - /* do it again in 60 s */ - } - } - - write_sequnlock(&xtime_lock); - irq_exit(); -} - /* Includes for ioc3_init(). */ #include <asm/sn/types.h> #include <asm/sn/sn0/addrs.h> @@ -141,7 +80,7 @@ again: #include <asm/sn/sn0/hubio.h> #include <asm/pci/bridge.h> -static __init unsigned long get_m48t35_time(void) +unsigned long read_persistent_clock(void) { unsigned int year, month, date, hour, min, sec; struct m48t35_rtc *rtc; @@ -172,6 +111,46 @@ static __init unsigned long get_m48t35_time(void) return mktime(year, month, date, hour, min, sec); } +static int rt_set_next_event(unsigned long delta, + struct clock_event_device *evt) +{ + unsigned int cpu = smp_processor_id(); + int slice = cputoslice(cpu) == 0; + unsigned long cnt; + + cnt = LOCAL_HUB_L(PI_RT_COUNT); + cnt += delta; + LOCAL_HUB_S(slice ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, cnt); + + return LOCAL_HUB_L(PI_RT_COUNT) >= cnt ? -ETIME : 0; +} + +static void rt_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + /* The only mode supported */ + break; + + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_RESUME: + /* Nothing to do */ + break; + } +} + +struct clock_event_device rt_clock_event_device = { + .name = "HUB-RT", + .features = CLOCK_EVT_FEAT_ONESHOT, + + .rating = 300, + .set_next_event = rt_set_next_event, + .set_mode = rt_set_mode, +}; + static void enable_rt_irq(unsigned int irq) { } @@ -189,6 +168,20 @@ static struct irq_chip rt_irq_type = { .eoi = enable_rt_irq, }; +unsigned int rt_timer_irq; + +static irqreturn_t ip27_rt_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *cd = &rt_clock_event_device; + unsigned int cpu = smp_processor_id(); + int slice = cputoslice(cpu) == 0; + + LOCAL_HUB_S(slice ? PI_RT_PEND_A : PI_RT_PEND_B, 0); /* Ack */ + cd->event_handler(cd); + + return IRQ_HANDLED; +} + static struct irqaction rt_irqaction = { .handler = (irq_handler_t) ip27_rt_timer_interrupt, .flags = IRQF_DISABLED, @@ -196,39 +189,68 @@ static struct irqaction rt_irqaction = { .name = "timer" }; -void __init plat_timer_setup(struct irqaction *irq) +/* + * This is a hack; we really need to figure these values out dynamically + * + * Since 800 ns works very well with various HUB frequencies, such as + * 360, 380, 390 and 400 MHZ, we use 800 ns rtc cycle time. + * + * Ralf: which clock rate is used to feed the counter? + */ +#define NSEC_PER_CYCLE 800 +#define CYCLES_PER_SEC (NSEC_PER_SEC / NSEC_PER_CYCLE) + +static void __init ip27_rt_clock_event_init(void) { - int irqno = allocate_irqno(); + struct clock_event_device *cd = &rt_clock_event_device; + unsigned int cpu = smp_processor_id(); + int irq = allocate_irqno(); - if (irqno < 0) + if (irq < 0) panic("Can't allocate interrupt number for timer interrupt"); - set_irq_chip_and_handler(irqno, &rt_irq_type, handle_percpu_irq); + rt_timer_irq = irq; - /* over-write the handler, we use our own way */ - irq->handler = no_action; + cd->irq = irq, + cd->cpumask = cpumask_of_cpu(cpu), - /* setup irqaction */ - irq_desc[irqno].status |= IRQ_PER_CPU; - - rt_timer_irq = irqno; /* - * Only needed to get /proc/interrupt to display timer irq stats + * Calculate the min / max delta */ - setup_irq(irqno, &rt_irqaction); + cd->mult = + div_sc((unsigned long) CYCLES_PER_SEC, NSEC_PER_SEC, 32); + cd->shift = 32; + cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); + cd->min_delta_ns = clockevent_delta2ns(0x300, cd); + clockevents_register_device(cd); + + set_irq_chip_and_handler(irq, &rt_irq_type, handle_percpu_irq); + setup_irq(irq, &rt_irqaction); } -static cycle_t ip27_hpt_read(void) +static cycle_t hub_rt_read(void) { return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT); } -void __init ip27_time_init(void) +struct clocksource ht_rt_clocksource = { + .name = "HUB-RT", + .rating = 200, + .read = hub_rt_read, + .mask = CLOCKSOURCE_MASK(52), + .shift = 32, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static void __init ip27_rt_clocksource_init(void) { - clocksource_mips.read = ip27_hpt_read; - mips_hpt_frequency = CYCLES_PER_SEC; - xtime.tv_sec = get_m48t35_time(); - xtime.tv_nsec = 0; + clocksource_register(&ht_rt_clocksource); +} + +void __init plat_time_init(void) +{ + ip27_rt_clock_event_init(); + ip27_rt_clocksource_init(); } void __init cpu_time_init(void) @@ -260,17 +282,12 @@ void __init hub_rtc_init(cnodeid_t cnode) * node and timeouts will not happen there. */ if (get_compact_nodeid() == cnode) { - int cpu = smp_processor_id(); LOCAL_HUB_S(PI_RT_EN_A, 1); LOCAL_HUB_S(PI_RT_EN_B, 1); LOCAL_HUB_S(PI_PROF_EN_A, 0); LOCAL_HUB_S(PI_PROF_EN_B, 0); - ct_cur[cpu] = CYCLES_PER_JIFFY; - LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur[cpu]); LOCAL_HUB_S(PI_RT_COUNT, 0); LOCAL_HUB_S(PI_RT_PEND_A, 0); - LOCAL_HUB_S(PI_RT_COMPARE_B, ct_cur[cpu]); - LOCAL_HUB_S(PI_RT_COUNT, 0); LOCAL_HUB_S(PI_RT_PEND_B, 0); } } |