1/* 2 * Copytight (C) 1999, 2000, 05, 06 Ralf Baechle (ralf@linux-mips.org) 3 * Copytight (C) 1999, 2000 Silicon Graphics, Inc. 4 */ 5#include <linux/bcd.h> 6#include <linux/init.h> 7#include <linux/kernel.h> 8#include <linux/sched.h> 9#include <linux/interrupt.h> 10#include <linux/kernel_stat.h> 11#include <linux/param.h> 12#include <linux/time.h> 13#include <linux/timex.h> 14#include <linux/mm.h> 15 16#include <asm/time.h> 17#include <asm/pgtable.h> 18#include <asm/sgialib.h> 19#include <asm/sn/ioc3.h> 20#include <asm/m48t35.h> 21#include <asm/sn/klconfig.h> 22#include <asm/sn/arch.h> 23#include <asm/sn/addrs.h> 24#include <asm/sn/sn_private.h> 25#include <asm/sn/sn0/ip27.h> 26#include <asm/sn/sn0/hub.h> 27 28/* 29 * This is a hack; we really need to figure these values out dynamically 30 * 31 * Since 800 ns works very well with various HUB frequencies, such as 32 * 360, 380, 390 and 400 MHZ, we use 800 ns rtc cycle time. 33 * 34 * Ralf: which clock rate is used to feed the counter? 35 */ 36#define NSEC_PER_CYCLE 800 37#define CYCLES_PER_SEC (NSEC_PER_SEC/NSEC_PER_CYCLE) 38#define CYCLES_PER_JIFFY (CYCLES_PER_SEC/HZ) 39 40#define TICK_SIZE (tick_nsec / 1000) 41 42static unsigned long ct_cur[NR_CPUS]; /* What counter should be at next timer irq */ 43static long last_rtc_update; /* Last time the rtc clock got updated */ 44 45 46static unsigned int rt_timer_irq; 47 48void ip27_rt_timer_interrupt(void) 49{ 50 int cpu = smp_processor_id(); 51 int cpuA = cputoslice(cpu) == 0; 52 unsigned int irq = rt_timer_irq; 53 54 irq_enter(); 55 write_seqlock(&xtime_lock); 56 57again: 58 LOCAL_HUB_S(cpuA ? PI_RT_PEND_A : PI_RT_PEND_B, 0); /* Ack */ 59 ct_cur[cpu] += CYCLES_PER_JIFFY; 60 LOCAL_HUB_S(cpuA ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, ct_cur[cpu]); 61 62 if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur[cpu]) 63 goto again; 64 65 kstat_this_cpu.irqs[irq]++; /* kstat only for bootcpu? */ 66 67 if (cpu == 0) 68 do_timer(1); 69 70 update_process_times(user_mode(get_irq_regs())); 71 72 /* 73 * If we have an externally synchronized Linux clock, then update 74 * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be 75 * called as close as possible to when a second starts. 76 */ 77 if (ntp_synced() && 78 xtime.tv_sec > last_rtc_update + 660 && 79 (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 && 80 (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) { 81 if (rtc_mips_set_time(xtime.tv_sec) == 0) { 82 last_rtc_update = xtime.tv_sec; 83 } else { 84 last_rtc_update = xtime.tv_sec - 600; 85 /* do it again in 60 s */ 86 } 87 } 88 89 write_sequnlock(&xtime_lock); 90 irq_exit(); 91} 92 93/* Includes for ioc3_init(). */ 94#include <asm/sn/types.h> 95#include <asm/sn/sn0/addrs.h> 96#include <asm/sn/sn0/hubni.h> 97#include <asm/sn/sn0/hubio.h> 98#include <asm/pci/bridge.h> 99 100static __init unsigned long get_m48t35_time(void) 101{ 102 unsigned int year, month, date, hour, min, sec; 103 struct m48t35_rtc *rtc; 104 nasid_t nid; 105 106 nid = get_nasid(); 107 rtc = (struct m48t35_rtc *)(KL_CONFIG_CH_CONS_INFO(nid)->memory_base + 108 IOC3_BYTEBUS_DEV0); 109 110 rtc->control |= M48T35_RTC_READ; 111 sec = rtc->sec; 112 min = rtc->min; 113 hour = rtc->hour; 114 date = rtc->date; 115 month = rtc->month; 116 year = rtc->year; 117 rtc->control &= ~M48T35_RTC_READ; 118 119 sec = BCD2BIN(sec); 120 min = BCD2BIN(min); 121 hour = BCD2BIN(hour); 122 date = BCD2BIN(date); 123 month = BCD2BIN(month); 124 year = BCD2BIN(year); 125 126 year += 1970; 127 128 return mktime(year, month, date, hour, min, sec); 129} 130 131static void enable_rt_irq(unsigned int irq) 132{ 133} 134 135static void disable_rt_irq(unsigned int irq) 136{ 137} 138 139static struct irq_chip rt_irq_type = { 140 .name = "SN HUB RT timer", 141 .ack = disable_rt_irq, 142 .mask = disable_rt_irq, 143 .mask_ack = disable_rt_irq, 144 .unmask = enable_rt_irq, 145 .eoi = enable_rt_irq, 146}; 147 148static struct irqaction rt_irqaction = { 149 .handler = (irq_handler_t) ip27_rt_timer_interrupt, 150 .flags = IRQF_DISABLED, 151 .mask = CPU_MASK_NONE, 152 .name = "timer" 153}; 154 155void __init plat_timer_setup(struct irqaction *irq) 156{ 157 int irqno = allocate_irqno(); 158 159 if (irqno < 0) 160 panic("Can't allocate interrupt number for timer interrupt"); 161 162 set_irq_chip_and_handler(irqno, &rt_irq_type, handle_percpu_irq); 163 164 /* over-write the handler, we use our own way */ 165 irq->handler = no_action; 166 167 /* setup irqaction */ 168 irq_desc[irqno].status |= IRQ_PER_CPU; 169 170 rt_timer_irq = irqno; 171 /* 172 * Only needed to get /proc/interrupt to display timer irq stats 173 */ 174 setup_irq(irqno, &rt_irqaction); 175} 176 177static cycle_t ip27_hpt_read(void) 178{ 179 return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT); 180} 181 182void __init ip27_time_init(void) 183{ 184 clocksource_mips.read = ip27_hpt_read; 185 mips_hpt_frequency = CYCLES_PER_SEC; 186 xtime.tv_sec = get_m48t35_time(); 187 xtime.tv_nsec = 0; 188} 189 190void __init cpu_time_init(void) 191{ 192 lboard_t *board; 193 klcpu_t *cpu; 194 int cpuid; 195 196 /* Don't use ARCS. ARCS is fragile. Klconfig is simple and sane. */ 197 board = find_lboard(KL_CONFIG_INFO(get_nasid()), KLTYPE_IP27); 198 if (!board) 199 panic("Can't find board info for myself."); 200 201 cpuid = LOCAL_HUB_L(PI_CPU_NUM) ? IP27_CPU0_INDEX : IP27_CPU1_INDEX; 202 cpu = (klcpu_t *) KLCF_COMP(board, cpuid); 203 if (!cpu) 204 panic("No information about myself?"); 205 206 printk("CPU %d clock is %dMHz.\n", smp_processor_id(), cpu->cpu_speed); 207 208 set_c0_status(SRB_TIMOCLK); 209} 210 211void __init hub_rtc_init(cnodeid_t cnode) 212{ 213 /* 214 * We only need to initialize the current node. 215 * If this is not the current node then it is a cpuless 216 * node and timeouts will not happen there. 217 */ 218 if (get_compact_nodeid() == cnode) { 219 int cpu = smp_processor_id(); 220 LOCAL_HUB_S(PI_RT_EN_A, 1); 221 LOCAL_HUB_S(PI_RT_EN_B, 1); 222 LOCAL_HUB_S(PI_PROF_EN_A, 0); 223 LOCAL_HUB_S(PI_PROF_EN_B, 0); 224 ct_cur[cpu] = CYCLES_PER_JIFFY; 225 LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur[cpu]); 226 LOCAL_HUB_S(PI_RT_COUNT, 0); 227 LOCAL_HUB_S(PI_RT_PEND_A, 0); 228 LOCAL_HUB_S(PI_RT_COMPARE_B, ct_cur[cpu]); 229 LOCAL_HUB_S(PI_RT_COUNT, 0); 230 LOCAL_HUB_S(PI_RT_PEND_B, 0); 231 } 232} 233