1 /* 2 * Copyright (C) 2007-2009 Michal Simek <[email protected]> 3 * Copyright (C) 2007-2009 PetaLogix 4 * Copyright (C) 2006 Atmark Techno, Inc. 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file "COPYING" in the main directory of this archive 8 * for more details. 9 */ 10 11 #include <linux/interrupt.h> 12 #include <linux/delay.h> 13 #include <linux/sched.h> 14 #include <linux/clk.h> 15 #include <linux/clockchips.h> 16 #include <linux/of_address.h> 17 #include <asm/cpuinfo.h> 18 #include <linux/cnt32_to_63.h> 19 20 static void __iomem *timer_baseaddr; 21 22 static unsigned int freq_div_hz; 23 static unsigned int timer_clock_freq; 24 25 #define TCSR0 (0x00) 26 #define TLR0 (0x04) 27 #define TCR0 (0x08) 28 #define TCSR1 (0x10) 29 #define TLR1 (0x14) 30 #define TCR1 (0x18) 31 32 #define TCSR_MDT (1<<0) 33 #define TCSR_UDT (1<<1) 34 #define TCSR_GENT (1<<2) 35 #define TCSR_CAPT (1<<3) 36 #define TCSR_ARHT (1<<4) 37 #define TCSR_LOAD (1<<5) 38 #define TCSR_ENIT (1<<6) 39 #define TCSR_ENT (1<<7) 40 #define TCSR_TINT (1<<8) 41 #define TCSR_PWMA (1<<9) 42 #define TCSR_ENALL (1<<10) 43 44 static inline void microblaze_timer0_stop(void) 45 { 46 out_be32(timer_baseaddr + TCSR0, 47 in_be32(timer_baseaddr + TCSR0) & ~TCSR_ENT); 48 } 49 50 static inline void microblaze_timer0_start_periodic(unsigned long load_val) 51 { 52 if (!load_val) 53 load_val = 1; 54 /* loading value to timer reg */ 55 out_be32(timer_baseaddr + TLR0, load_val); 56 57 /* load the initial value */ 58 out_be32(timer_baseaddr + TCSR0, TCSR_LOAD); 59 60 /* see timer data sheet for detail 61 * !ENALL - don't enable 'em all 62 * !PWMA - disable pwm 63 * TINT - clear interrupt status 64 * ENT- enable timer itself 65 * ENIT - enable interrupt 66 * !LOAD - clear the bit to let go 67 * ARHT - auto reload 68 * !CAPT - no external trigger 69 * !GENT - no external signal 70 * UDT - set the timer as down counter 71 * !MDT0 - generate mode 72 */ 73 out_be32(timer_baseaddr + TCSR0, 74 TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT); 75 } 76 77 static inline void microblaze_timer0_start_oneshot(unsigned long load_val) 78 { 79 if (!load_val) 80 load_val = 1; 81 /* loading value to timer reg */ 82 out_be32(timer_baseaddr + TLR0, load_val); 83 84 /* load the initial value */ 85 out_be32(timer_baseaddr + TCSR0, TCSR_LOAD); 86 87 out_be32(timer_baseaddr + TCSR0, 88 TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT); 89 } 90 91 static int microblaze_timer_set_next_event(unsigned long delta, 92 struct clock_event_device *dev) 93 { 94 pr_debug("%s: next event, delta %x\n", __func__, (u32)delta); 95 microblaze_timer0_start_oneshot(delta); 96 return 0; 97 } 98 99 static void microblaze_timer_set_mode(enum clock_event_mode mode, 100 struct clock_event_device *evt) 101 { 102 switch (mode) { 103 case CLOCK_EVT_MODE_PERIODIC: 104 pr_info("%s: periodic\n", __func__); 105 microblaze_timer0_start_periodic(freq_div_hz); 106 break; 107 case CLOCK_EVT_MODE_ONESHOT: 108 pr_info("%s: oneshot\n", __func__); 109 break; 110 case CLOCK_EVT_MODE_UNUSED: 111 pr_info("%s: unused\n", __func__); 112 break; 113 case CLOCK_EVT_MODE_SHUTDOWN: 114 pr_info("%s: shutdown\n", __func__); 115 microblaze_timer0_stop(); 116 break; 117 case CLOCK_EVT_MODE_RESUME: 118 pr_info("%s: resume\n", __func__); 119 break; 120 } 121 } 122 123 static struct clock_event_device clockevent_microblaze_timer = { 124 .name = "microblaze_clockevent", 125 .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, 126 .shift = 8, 127 .rating = 300, 128 .set_next_event = microblaze_timer_set_next_event, 129 .set_mode = microblaze_timer_set_mode, 130 }; 131 132 static inline void timer_ack(void) 133 { 134 out_be32(timer_baseaddr + TCSR0, in_be32(timer_baseaddr + TCSR0)); 135 } 136 137 static irqreturn_t timer_interrupt(int irq, void *dev_id) 138 { 139 struct clock_event_device *evt = &clockevent_microblaze_timer; 140 #ifdef CONFIG_HEART_BEAT 141 heartbeat(); 142 #endif 143 timer_ack(); 144 evt->event_handler(evt); 145 return IRQ_HANDLED; 146 } 147 148 static struct irqaction timer_irqaction = { 149 .handler = timer_interrupt, 150 .flags = IRQF_DISABLED | IRQF_TIMER, 151 .name = "timer", 152 .dev_id = &clockevent_microblaze_timer, 153 }; 154 155 static __init void microblaze_clockevent_init(void) 156 { 157 clockevent_microblaze_timer.mult = 158 div_sc(timer_clock_freq, NSEC_PER_SEC, 159 clockevent_microblaze_timer.shift); 160 clockevent_microblaze_timer.max_delta_ns = 161 clockevent_delta2ns((u32)~0, &clockevent_microblaze_timer); 162 clockevent_microblaze_timer.min_delta_ns = 163 clockevent_delta2ns(1, &clockevent_microblaze_timer); 164 clockevent_microblaze_timer.cpumask = cpumask_of(0); 165 clockevents_register_device(&clockevent_microblaze_timer); 166 } 167 168 static cycle_t microblaze_read(struct clocksource *cs) 169 { 170 /* reading actual value of timer 1 */ 171 return (cycle_t) (in_be32(timer_baseaddr + TCR1)); 172 } 173 174 static struct timecounter microblaze_tc = { 175 .cc = NULL, 176 }; 177 178 static cycle_t microblaze_cc_read(const struct cyclecounter *cc) 179 { 180 return microblaze_read(NULL); 181 } 182 183 static struct cyclecounter microblaze_cc = { 184 .read = microblaze_cc_read, 185 .mask = CLOCKSOURCE_MASK(32), 186 .shift = 8, 187 }; 188 189 static int __init init_microblaze_timecounter(void) 190 { 191 microblaze_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC, 192 microblaze_cc.shift); 193 194 timecounter_init(µblaze_tc, µblaze_cc, sched_clock()); 195 196 return 0; 197 } 198 199 static struct clocksource clocksource_microblaze = { 200 .name = "microblaze_clocksource", 201 .rating = 300, 202 .read = microblaze_read, 203 .mask = CLOCKSOURCE_MASK(32), 204 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 205 }; 206 207 static int __init microblaze_clocksource_init(void) 208 { 209 if (clocksource_register_hz(&clocksource_microblaze, timer_clock_freq)) 210 panic("failed to register clocksource"); 211 212 /* stop timer1 */ 213 out_be32(timer_baseaddr + TCSR1, 214 in_be32(timer_baseaddr + TCSR1) & ~TCSR_ENT); 215 /* start timer1 - up counting without interrupt */ 216 out_be32(timer_baseaddr + TCSR1, TCSR_TINT|TCSR_ENT|TCSR_ARHT); 217 218 /* register timecounter - for ftrace support */ 219 init_microblaze_timecounter(); 220 return 0; 221 } 222 223 /* 224 * We have to protect accesses before timer initialization 225 * and return 0 for sched_clock function below. 226 */ 227 static int timer_initialized; 228 229 static void __init xilinx_timer_init(struct device_node *timer) 230 { 231 u32 irq; 232 u32 timer_num = 1; 233 int ret; 234 235 timer_baseaddr = of_iomap(timer, 0); 236 if (!timer_baseaddr) { 237 pr_err("ERROR: invalid timer base address\n"); 238 BUG(); 239 } 240 241 irq = irq_of_parse_and_map(timer, 0); 242 243 of_property_read_u32(timer, "xlnx,one-timer-only", &timer_num); 244 if (timer_num) { 245 pr_emerg("Please enable two timers in HW\n"); 246 BUG(); 247 } 248 249 pr_info("%s: irq=%d\n", timer->full_name, irq); 250 251 /* If there is clock-frequency property than use it */ 252 ret = of_property_read_u32(timer, "clock-frequency", &timer_clock_freq); 253 if (ret < 0) 254 timer_clock_freq = cpuinfo.cpu_clock_freq; 255 256 freq_div_hz = timer_clock_freq / HZ; 257 258 setup_irq(irq, &timer_irqaction); 259 #ifdef CONFIG_HEART_BEAT 260 setup_heartbeat(); 261 #endif 262 microblaze_clocksource_init(); 263 microblaze_clockevent_init(); 264 timer_initialized = 1; 265 } 266 267 unsigned long long notrace sched_clock(void) 268 { 269 if (timer_initialized) { 270 struct clocksource *cs = &clocksource_microblaze; 271 272 cycle_t cyc = cnt32_to_63(cs->read(NULL)) & LLONG_MAX; 273 return clocksource_cyc2ns(cyc, cs->mult, cs->shift); 274 } 275 return 0; 276 } 277 278 CLOCKSOURCE_OF_DECLARE(xilinx_timer, "xlnx,xps-timer-1.00.a", 279 xilinx_timer_init); 280