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/clockchips.h> 7 #include <linux/init.h> 8 #include <linux/kernel.h> 9 #include <linux/sched.h> 10 #include <linux/interrupt.h> 11 #include <linux/kernel_stat.h> 12 #include <linux/param.h> 13 #include <linux/time.h> 14 #include <linux/timex.h> 15 #include <linux/mm.h> 16 17 #include <asm/time.h> 18 #include <asm/pgtable.h> 19 #include <asm/sgialib.h> 20 #include <asm/sn/ioc3.h> 21 #include <asm/m48t35.h> 22 #include <asm/sn/klconfig.h> 23 #include <asm/sn/arch.h> 24 #include <asm/sn/addrs.h> 25 #include <asm/sn/sn_private.h> 26 #include <asm/sn/sn0/ip27.h> 27 #include <asm/sn/sn0/hub.h> 28 29 #define TICK_SIZE (tick_nsec / 1000) 30 31 #if 0 32 static int set_rtc_mmss(unsigned long nowtime) 33 { 34 int retval = 0; 35 int real_seconds, real_minutes, cmos_minutes; 36 struct m48t35_rtc *rtc; 37 nasid_t nid; 38 39 nid = get_nasid(); 40 rtc = (struct m48t35_rtc *)(KL_CONFIG_CH_CONS_INFO(nid)->memory_base + 41 IOC3_BYTEBUS_DEV0); 42 43 rtc->control |= M48T35_RTC_READ; 44 cmos_minutes = BCD2BIN(rtc->min); 45 rtc->control &= ~M48T35_RTC_READ; 46 47 /* 48 * Since we're only adjusting minutes and seconds, don't interfere with 49 * hour overflow. This avoids messing with unknown time zones but 50 * requires your RTC not to be off by more than 15 minutes 51 */ 52 real_seconds = nowtime % 60; 53 real_minutes = nowtime / 60; 54 if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) 55 real_minutes += 30; /* correct for half hour time zone */ 56 real_minutes %= 60; 57 58 if (abs(real_minutes - cmos_minutes) < 30) { 59 real_seconds = BIN2BCD(real_seconds); 60 real_minutes = BIN2BCD(real_minutes); 61 rtc->control |= M48T35_RTC_SET; 62 rtc->sec = real_seconds; 63 rtc->min = real_minutes; 64 rtc->control &= ~M48T35_RTC_SET; 65 } else { 66 printk(KERN_WARNING 67 "set_rtc_mmss: can't update from %d to %d\n", 68 cmos_minutes, real_minutes); 69 retval = -1; 70 } 71 72 return retval; 73 } 74 #endif 75 76 /* Includes for ioc3_init(). */ 77 #include <asm/sn/types.h> 78 #include <asm/sn/sn0/addrs.h> 79 #include <asm/sn/sn0/hubni.h> 80 #include <asm/sn/sn0/hubio.h> 81 #include <asm/pci/bridge.h> 82 83 unsigned long read_persistent_clock(void) 84 { 85 unsigned int year, month, date, hour, min, sec; 86 struct m48t35_rtc *rtc; 87 nasid_t nid; 88 89 nid = get_nasid(); 90 rtc = (struct m48t35_rtc *)(KL_CONFIG_CH_CONS_INFO(nid)->memory_base + 91 IOC3_BYTEBUS_DEV0); 92 93 rtc->control |= M48T35_RTC_READ; 94 sec = rtc->sec; 95 min = rtc->min; 96 hour = rtc->hour; 97 date = rtc->date; 98 month = rtc->month; 99 year = rtc->year; 100 rtc->control &= ~M48T35_RTC_READ; 101 102 sec = BCD2BIN(sec); 103 min = BCD2BIN(min); 104 hour = BCD2BIN(hour); 105 date = BCD2BIN(date); 106 month = BCD2BIN(month); 107 year = BCD2BIN(year); 108 109 year += 1970; 110 111 return mktime(year, month, date, hour, min, sec); 112 } 113 114 static int rt_set_next_event(unsigned long delta, 115 struct clock_event_device *evt) 116 { 117 unsigned int cpu = smp_processor_id(); 118 int slice = cputoslice(cpu) == 0; 119 unsigned long cnt; 120 121 cnt = LOCAL_HUB_L(PI_RT_COUNT); 122 cnt += delta; 123 LOCAL_HUB_S(slice ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, cnt); 124 125 return LOCAL_HUB_L(PI_RT_COUNT) >= cnt ? -ETIME : 0; 126 } 127 128 static void rt_set_mode(enum clock_event_mode mode, 129 struct clock_event_device *evt) 130 { 131 switch (mode) { 132 case CLOCK_EVT_MODE_PERIODIC: 133 /* The only mode supported */ 134 break; 135 136 case CLOCK_EVT_MODE_UNUSED: 137 case CLOCK_EVT_MODE_SHUTDOWN: 138 case CLOCK_EVT_MODE_ONESHOT: 139 case CLOCK_EVT_MODE_RESUME: 140 /* Nothing to do */ 141 break; 142 } 143 } 144 145 struct clock_event_device rt_clock_event_device = { 146 .name = "HUB-RT", 147 .features = CLOCK_EVT_FEAT_ONESHOT, 148 149 .rating = 300, 150 .set_next_event = rt_set_next_event, 151 .set_mode = rt_set_mode, 152 }; 153 154 static void enable_rt_irq(unsigned int irq) 155 { 156 } 157 158 static void disable_rt_irq(unsigned int irq) 159 { 160 } 161 162 static struct irq_chip rt_irq_type = { 163 .name = "SN HUB RT timer", 164 .ack = disable_rt_irq, 165 .mask = disable_rt_irq, 166 .mask_ack = disable_rt_irq, 167 .unmask = enable_rt_irq, 168 .eoi = enable_rt_irq, 169 }; 170 171 unsigned int rt_timer_irq; 172 173 static irqreturn_t ip27_rt_timer_interrupt(int irq, void *dev_id) 174 { 175 struct clock_event_device *cd = &rt_clock_event_device; 176 unsigned int cpu = smp_processor_id(); 177 int slice = cputoslice(cpu) == 0; 178 179 LOCAL_HUB_S(slice ? PI_RT_PEND_A : PI_RT_PEND_B, 0); /* Ack */ 180 cd->event_handler(cd); 181 182 return IRQ_HANDLED; 183 } 184 185 static struct irqaction rt_irqaction = { 186 .handler = (irq_handler_t) ip27_rt_timer_interrupt, 187 .flags = IRQF_DISABLED, 188 .mask = CPU_MASK_NONE, 189 .name = "timer" 190 }; 191 192 /* 193 * This is a hack; we really need to figure these values out dynamically 194 * 195 * Since 800 ns works very well with various HUB frequencies, such as 196 * 360, 380, 390 and 400 MHZ, we use 800 ns rtc cycle time. 197 * 198 * Ralf: which clock rate is used to feed the counter? 199 */ 200 #define NSEC_PER_CYCLE 800 201 #define CYCLES_PER_SEC (NSEC_PER_SEC / NSEC_PER_CYCLE) 202 203 static void __init ip27_rt_clock_event_init(void) 204 { 205 struct clock_event_device *cd = &rt_clock_event_device; 206 unsigned int cpu = smp_processor_id(); 207 int irq = allocate_irqno(); 208 209 if (irq < 0) 210 panic("Can't allocate interrupt number for timer interrupt"); 211 212 rt_timer_irq = irq; 213 214 cd->irq = irq, 215 cd->cpumask = cpumask_of_cpu(cpu), 216 217 /* 218 * Calculate the min / max delta 219 */ 220 cd->mult = 221 div_sc((unsigned long) CYCLES_PER_SEC, NSEC_PER_SEC, 32); 222 cd->shift = 32; 223 cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); 224 cd->min_delta_ns = clockevent_delta2ns(0x300, cd); 225 clockevents_register_device(cd); 226 227 set_irq_chip_and_handler(irq, &rt_irq_type, handle_percpu_irq); 228 setup_irq(irq, &rt_irqaction); 229 } 230 231 static cycle_t hub_rt_read(void) 232 { 233 return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT); 234 } 235 236 struct clocksource ht_rt_clocksource = { 237 .name = "HUB-RT", 238 .rating = 200, 239 .read = hub_rt_read, 240 .mask = CLOCKSOURCE_MASK(52), 241 .shift = 32, 242 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 243 }; 244 245 static void __init ip27_rt_clocksource_init(void) 246 { 247 clocksource_register(&ht_rt_clocksource); 248 } 249 250 void __init plat_time_init(void) 251 { 252 ip27_rt_clock_event_init(); 253 ip27_rt_clocksource_init(); 254 } 255 256 void __init cpu_time_init(void) 257 { 258 lboard_t *board; 259 klcpu_t *cpu; 260 int cpuid; 261 262 /* Don't use ARCS. ARCS is fragile. Klconfig is simple and sane. */ 263 board = find_lboard(KL_CONFIG_INFO(get_nasid()), KLTYPE_IP27); 264 if (!board) 265 panic("Can't find board info for myself."); 266 267 cpuid = LOCAL_HUB_L(PI_CPU_NUM) ? IP27_CPU0_INDEX : IP27_CPU1_INDEX; 268 cpu = (klcpu_t *) KLCF_COMP(board, cpuid); 269 if (!cpu) 270 panic("No information about myself?"); 271 272 printk("CPU %d clock is %dMHz.\n", smp_processor_id(), cpu->cpu_speed); 273 274 set_c0_status(SRB_TIMOCLK); 275 } 276 277 void __init hub_rtc_init(cnodeid_t cnode) 278 { 279 /* 280 * We only need to initialize the current node. 281 * If this is not the current node then it is a cpuless 282 * node and timeouts will not happen there. 283 */ 284 if (get_compact_nodeid() == cnode) { 285 LOCAL_HUB_S(PI_RT_EN_A, 1); 286 LOCAL_HUB_S(PI_RT_EN_B, 1); 287 LOCAL_HUB_S(PI_PROF_EN_A, 0); 288 LOCAL_HUB_S(PI_PROF_EN_B, 0); 289 LOCAL_HUB_S(PI_RT_COUNT, 0); 290 LOCAL_HUB_S(PI_RT_PEND_A, 0); 291 LOCAL_HUB_S(PI_RT_PEND_B, 0); 292 } 293 } 294