1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copytight (C) 1999, 2000, 05, 06 Ralf Baechle (ralf@linux-mips.org) 4 * Copytight (C) 1999, 2000 Silicon Graphics, Inc. 5 */ 6 #include <linux/bcd.h> 7 #include <linux/clockchips.h> 8 #include <linux/init.h> 9 #include <linux/kernel.h> 10 #include <linux/sched.h> 11 #include <linux/sched_clock.h> 12 #include <linux/interrupt.h> 13 #include <linux/kernel_stat.h> 14 #include <linux/param.h> 15 #include <linux/smp.h> 16 #include <linux/time.h> 17 #include <linux/timex.h> 18 #include <linux/mm.h> 19 #include <linux/platform_device.h> 20 21 #include <asm/time.h> 22 #include <asm/pgtable.h> 23 #include <asm/sgialib.h> 24 #include <asm/sn/ioc3.h> 25 #include <asm/sn/klconfig.h> 26 #include <asm/sn/arch.h> 27 #include <asm/sn/addrs.h> 28 #include <asm/sn/sn_private.h> 29 #include <asm/sn/sn0/ip27.h> 30 #include <asm/sn/sn0/hub.h> 31 32 #define TICK_SIZE (tick_nsec / 1000) 33 34 /* Includes for ioc3_init(). */ 35 #include <asm/sn/types.h> 36 #include <asm/sn/sn0/addrs.h> 37 #include <asm/sn/sn0/hubni.h> 38 #include <asm/sn/sn0/hubio.h> 39 #include <asm/pci/bridge.h> 40 41 #include "ip27-common.h" 42 43 static int rt_next_event(unsigned long delta, struct clock_event_device *evt) 44 { 45 unsigned int cpu = smp_processor_id(); 46 int slice = cputoslice(cpu); 47 unsigned long cnt; 48 49 cnt = LOCAL_HUB_L(PI_RT_COUNT); 50 cnt += delta; 51 LOCAL_HUB_S(PI_RT_COMPARE_A + PI_COUNT_OFFSET * slice, cnt); 52 53 return LOCAL_HUB_L(PI_RT_COUNT) >= cnt ? -ETIME : 0; 54 } 55 56 static DEFINE_PER_CPU(struct clock_event_device, hub_rt_clockevent); 57 static DEFINE_PER_CPU(char [11], hub_rt_name); 58 59 static irqreturn_t hub_rt_counter_handler(int irq, void *dev_id) 60 { 61 unsigned int cpu = smp_processor_id(); 62 struct clock_event_device *cd = &per_cpu(hub_rt_clockevent, cpu); 63 int slice = cputoslice(cpu); 64 65 /* 66 * Ack 67 */ 68 LOCAL_HUB_S(PI_RT_PEND_A + PI_COUNT_OFFSET * slice, 0); 69 cd->event_handler(cd); 70 71 return IRQ_HANDLED; 72 } 73 74 struct irqaction hub_rt_irqaction = { 75 .handler = hub_rt_counter_handler, 76 .percpu_dev_id = &hub_rt_clockevent, 77 .flags = IRQF_PERCPU | IRQF_TIMER, 78 .name = "hub-rt", 79 }; 80 81 /* 82 * This is a hack; we really need to figure these values out dynamically 83 * 84 * Since 800 ns works very well with various HUB frequencies, such as 85 * 360, 380, 390 and 400 MHZ, we use 800 ns rtc cycle time. 86 * 87 * Ralf: which clock rate is used to feed the counter? 88 */ 89 #define NSEC_PER_CYCLE 800 90 #define CYCLES_PER_SEC (NSEC_PER_SEC / NSEC_PER_CYCLE) 91 92 void hub_rt_clock_event_init(void) 93 { 94 unsigned int cpu = smp_processor_id(); 95 struct clock_event_device *cd = &per_cpu(hub_rt_clockevent, cpu); 96 unsigned char *name = per_cpu(hub_rt_name, cpu); 97 98 sprintf(name, "hub-rt %d", cpu); 99 cd->name = name; 100 cd->features = CLOCK_EVT_FEAT_ONESHOT; 101 clockevent_set_clock(cd, CYCLES_PER_SEC); 102 cd->max_delta_ns = clockevent_delta2ns(0xfffffffffffff, cd); 103 cd->max_delta_ticks = 0xfffffffffffff; 104 cd->min_delta_ns = clockevent_delta2ns(0x300, cd); 105 cd->min_delta_ticks = 0x300; 106 cd->rating = 200; 107 cd->irq = IP27_RT_TIMER_IRQ; 108 cd->cpumask = cpumask_of(cpu); 109 cd->set_next_event = rt_next_event; 110 clockevents_register_device(cd); 111 112 enable_percpu_irq(IP27_RT_TIMER_IRQ, IRQ_TYPE_NONE); 113 } 114 115 static void __init hub_rt_clock_event_global_init(void) 116 { 117 irq_set_handler(IP27_RT_TIMER_IRQ, handle_percpu_devid_irq); 118 irq_set_percpu_devid(IP27_RT_TIMER_IRQ); 119 setup_percpu_irq(IP27_RT_TIMER_IRQ, &hub_rt_irqaction); 120 } 121 122 static u64 hub_rt_read(struct clocksource *cs) 123 { 124 return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT); 125 } 126 127 struct clocksource hub_rt_clocksource = { 128 .name = "HUB-RT", 129 .rating = 200, 130 .read = hub_rt_read, 131 .mask = CLOCKSOURCE_MASK(52), 132 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 133 }; 134 135 static u64 notrace hub_rt_read_sched_clock(void) 136 { 137 return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT); 138 } 139 140 static void __init hub_rt_clocksource_init(void) 141 { 142 struct clocksource *cs = &hub_rt_clocksource; 143 144 clocksource_register_hz(cs, CYCLES_PER_SEC); 145 146 sched_clock_register(hub_rt_read_sched_clock, 52, CYCLES_PER_SEC); 147 } 148 149 void __init plat_time_init(void) 150 { 151 hub_rt_clocksource_init(); 152 hub_rt_clock_event_global_init(); 153 hub_rt_clock_event_init(); 154 } 155 156 void cpu_time_init(void) 157 { 158 lboard_t *board; 159 klcpu_t *cpu; 160 int cpuid; 161 162 /* Don't use ARCS. ARCS is fragile. Klconfig is simple and sane. */ 163 board = find_lboard(KL_CONFIG_INFO(get_nasid()), KLTYPE_IP27); 164 if (!board) 165 panic("Can't find board info for myself."); 166 167 cpuid = LOCAL_HUB_L(PI_CPU_NUM) ? IP27_CPU0_INDEX : IP27_CPU1_INDEX; 168 cpu = (klcpu_t *) KLCF_COMP(board, cpuid); 169 if (!cpu) 170 panic("No information about myself?"); 171 172 printk("CPU %d clock is %dMHz.\n", smp_processor_id(), cpu->cpu_speed); 173 } 174 175 void hub_rtc_init(nasid_t nasid) 176 { 177 178 /* 179 * We only need to initialize the current node. 180 * If this is not the current node then it is a cpuless 181 * node and timeouts will not happen there. 182 */ 183 if (get_nasid() == nasid) { 184 LOCAL_HUB_S(PI_RT_EN_A, 1); 185 LOCAL_HUB_S(PI_RT_EN_B, 1); 186 LOCAL_HUB_S(PI_PROF_EN_A, 0); 187 LOCAL_HUB_S(PI_PROF_EN_B, 0); 188 LOCAL_HUB_S(PI_RT_COUNT, 0); 189 LOCAL_HUB_S(PI_RT_PEND_A, 0); 190 LOCAL_HUB_S(PI_RT_PEND_B, 0); 191 } 192 } 193 194 static int __init sgi_ip27_rtc_devinit(void) 195 { 196 struct resource res; 197 198 memset(&res, 0, sizeof(res)); 199 res.start = XPHYSADDR(KL_CONFIG_CH_CONS_INFO(master_nasid)->memory_base + 200 IOC3_BYTEBUS_DEV0); 201 res.end = res.start + 32767; 202 res.flags = IORESOURCE_MEM; 203 204 return IS_ERR(platform_device_register_simple("rtc-m48t35", -1, 205 &res, 1)); 206 } 207 208 /* 209 * kludge make this a device_initcall after ioc3 resource conflicts 210 * are resolved 211 */ 212 late_initcall(sgi_ip27_rtc_devinit); 213