1 /* 2 * linux/drivers/clocksource/timer-sp.c 3 * 4 * Copyright (C) 1999 - 2003 ARM Limited 5 * Copyright (C) 2000 Deep Blue Solutions Ltd 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 #include <linux/clk.h> 22 #include <linux/clocksource.h> 23 #include <linux/clockchips.h> 24 #include <linux/err.h> 25 #include <linux/interrupt.h> 26 #include <linux/irq.h> 27 #include <linux/io.h> 28 #include <linux/of.h> 29 #include <linux/of_address.h> 30 #include <linux/of_irq.h> 31 #include <linux/sched_clock.h> 32 33 #include <clocksource/timer-sp804.h> 34 35 #include "timer-sp.h" 36 37 static long __init sp804_get_clock_rate(struct clk *clk) 38 { 39 long rate; 40 int err; 41 42 err = clk_prepare(clk); 43 if (err) { 44 pr_err("sp804: clock failed to prepare: %d\n", err); 45 clk_put(clk); 46 return err; 47 } 48 49 err = clk_enable(clk); 50 if (err) { 51 pr_err("sp804: clock failed to enable: %d\n", err); 52 clk_unprepare(clk); 53 clk_put(clk); 54 return err; 55 } 56 57 rate = clk_get_rate(clk); 58 if (rate < 0) { 59 pr_err("sp804: clock failed to get rate: %ld\n", rate); 60 clk_disable(clk); 61 clk_unprepare(clk); 62 clk_put(clk); 63 } 64 65 return rate; 66 } 67 68 static void __iomem *sched_clock_base; 69 70 static u64 notrace sp804_read(void) 71 { 72 return ~readl_relaxed(sched_clock_base + TIMER_VALUE); 73 } 74 75 void __init sp804_timer_disable(void __iomem *base) 76 { 77 writel(0, base + TIMER_CTRL); 78 } 79 80 int __init __sp804_clocksource_and_sched_clock_init(void __iomem *base, 81 const char *name, 82 struct clk *clk, 83 int use_sched_clock) 84 { 85 long rate; 86 87 if (!clk) { 88 clk = clk_get_sys("sp804", name); 89 if (IS_ERR(clk)) { 90 pr_err("sp804: clock not found: %d\n", 91 (int)PTR_ERR(clk)); 92 return PTR_ERR(clk); 93 } 94 } 95 96 rate = sp804_get_clock_rate(clk); 97 if (rate < 0) 98 return -EINVAL; 99 100 /* setup timer 0 as free-running clocksource */ 101 writel(0, base + TIMER_CTRL); 102 writel(0xffffffff, base + TIMER_LOAD); 103 writel(0xffffffff, base + TIMER_VALUE); 104 writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, 105 base + TIMER_CTRL); 106 107 clocksource_mmio_init(base + TIMER_VALUE, name, 108 rate, 200, 32, clocksource_mmio_readl_down); 109 110 if (use_sched_clock) { 111 sched_clock_base = base; 112 sched_clock_register(sp804_read, 32, rate); 113 } 114 115 return 0; 116 } 117 118 119 static void __iomem *clkevt_base; 120 static unsigned long clkevt_reload; 121 122 /* 123 * IRQ handler for the timer 124 */ 125 static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id) 126 { 127 struct clock_event_device *evt = dev_id; 128 129 /* clear the interrupt */ 130 writel(1, clkevt_base + TIMER_INTCLR); 131 132 evt->event_handler(evt); 133 134 return IRQ_HANDLED; 135 } 136 137 static inline void timer_shutdown(struct clock_event_device *evt) 138 { 139 writel(0, clkevt_base + TIMER_CTRL); 140 } 141 142 static int sp804_shutdown(struct clock_event_device *evt) 143 { 144 timer_shutdown(evt); 145 return 0; 146 } 147 148 static int sp804_set_periodic(struct clock_event_device *evt) 149 { 150 unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE | 151 TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE; 152 153 timer_shutdown(evt); 154 writel(clkevt_reload, clkevt_base + TIMER_LOAD); 155 writel(ctrl, clkevt_base + TIMER_CTRL); 156 return 0; 157 } 158 159 static int sp804_set_next_event(unsigned long next, 160 struct clock_event_device *evt) 161 { 162 unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE | 163 TIMER_CTRL_ONESHOT | TIMER_CTRL_ENABLE; 164 165 writel(next, clkevt_base + TIMER_LOAD); 166 writel(ctrl, clkevt_base + TIMER_CTRL); 167 168 return 0; 169 } 170 171 static struct clock_event_device sp804_clockevent = { 172 .features = CLOCK_EVT_FEAT_PERIODIC | 173 CLOCK_EVT_FEAT_ONESHOT | 174 CLOCK_EVT_FEAT_DYNIRQ, 175 .set_state_shutdown = sp804_shutdown, 176 .set_state_periodic = sp804_set_periodic, 177 .set_state_oneshot = sp804_shutdown, 178 .tick_resume = sp804_shutdown, 179 .set_next_event = sp804_set_next_event, 180 .rating = 300, 181 }; 182 183 static struct irqaction sp804_timer_irq = { 184 .name = "timer", 185 .flags = IRQF_TIMER | IRQF_IRQPOLL, 186 .handler = sp804_timer_interrupt, 187 .dev_id = &sp804_clockevent, 188 }; 189 190 int __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struct clk *clk, const char *name) 191 { 192 struct clock_event_device *evt = &sp804_clockevent; 193 long rate; 194 195 if (!clk) 196 clk = clk_get_sys("sp804", name); 197 if (IS_ERR(clk)) { 198 pr_err("sp804: %s clock not found: %d\n", name, 199 (int)PTR_ERR(clk)); 200 return PTR_ERR(clk); 201 } 202 203 rate = sp804_get_clock_rate(clk); 204 if (rate < 0) 205 return -EINVAL; 206 207 clkevt_base = base; 208 clkevt_reload = DIV_ROUND_CLOSEST(rate, HZ); 209 evt->name = name; 210 evt->irq = irq; 211 evt->cpumask = cpu_possible_mask; 212 213 writel(0, base + TIMER_CTRL); 214 215 setup_irq(irq, &sp804_timer_irq); 216 clockevents_config_and_register(evt, rate, 0xf, 0xffffffff); 217 218 return 0; 219 } 220 221 static int __init sp804_of_init(struct device_node *np) 222 { 223 static bool initialized = false; 224 void __iomem *base; 225 int irq, ret = -EINVAL; 226 u32 irq_num = 0; 227 struct clk *clk1, *clk2; 228 const char *name = of_get_property(np, "compatible", NULL); 229 230 base = of_iomap(np, 0); 231 if (!base) 232 return -ENXIO; 233 234 /* Ensure timers are disabled */ 235 writel(0, base + TIMER_CTRL); 236 writel(0, base + TIMER_2_BASE + TIMER_CTRL); 237 238 if (initialized || !of_device_is_available(np)) { 239 ret = -EINVAL; 240 goto err; 241 } 242 243 clk1 = of_clk_get(np, 0); 244 if (IS_ERR(clk1)) 245 clk1 = NULL; 246 247 /* Get the 2nd clock if the timer has 3 timer clocks */ 248 if (of_count_phandle_with_args(np, "clocks", "#clock-cells") == 3) { 249 clk2 = of_clk_get(np, 1); 250 if (IS_ERR(clk2)) { 251 pr_err("sp804: %s clock not found: %d\n", np->name, 252 (int)PTR_ERR(clk2)); 253 clk2 = NULL; 254 } 255 } else 256 clk2 = clk1; 257 258 irq = irq_of_parse_and_map(np, 0); 259 if (irq <= 0) 260 goto err; 261 262 of_property_read_u32(np, "arm,sp804-has-irq", &irq_num); 263 if (irq_num == 2) { 264 265 ret = __sp804_clockevents_init(base + TIMER_2_BASE, irq, clk2, name); 266 if (ret) 267 goto err; 268 269 ret = __sp804_clocksource_and_sched_clock_init(base, name, clk1, 1); 270 if (ret) 271 goto err; 272 } else { 273 274 ret = __sp804_clockevents_init(base, irq, clk1 , name); 275 if (ret) 276 goto err; 277 278 ret =__sp804_clocksource_and_sched_clock_init(base + TIMER_2_BASE, 279 name, clk2, 1); 280 if (ret) 281 goto err; 282 } 283 initialized = true; 284 285 return 0; 286 err: 287 iounmap(base); 288 return ret; 289 } 290 CLOCKSOURCE_OF_DECLARE(sp804, "arm,sp804", sp804_of_init); 291 292 static int __init integrator_cp_of_init(struct device_node *np) 293 { 294 static int init_count = 0; 295 void __iomem *base; 296 int irq, ret = -EINVAL; 297 const char *name = of_get_property(np, "compatible", NULL); 298 struct clk *clk; 299 300 base = of_iomap(np, 0); 301 if (!base) { 302 pr_err("Failed to iomap"); 303 return -ENXIO; 304 } 305 306 clk = of_clk_get(np, 0); 307 if (IS_ERR(clk)) { 308 pr_err("Failed to get clock"); 309 return PTR_ERR(clk); 310 } 311 312 /* Ensure timer is disabled */ 313 writel(0, base + TIMER_CTRL); 314 315 if (init_count == 2 || !of_device_is_available(np)) 316 goto err; 317 318 if (!init_count) { 319 ret = __sp804_clocksource_and_sched_clock_init(base, name, clk, 0); 320 if (ret) 321 goto err; 322 } else { 323 irq = irq_of_parse_and_map(np, 0); 324 if (irq <= 0) 325 goto err; 326 327 ret = __sp804_clockevents_init(base, irq, clk, name); 328 if (ret) 329 goto err; 330 } 331 332 init_count++; 333 return 0; 334 err: 335 iounmap(base); 336 return ret; 337 } 338 CLOCKSOURCE_OF_DECLARE(intcp, "arm,integrator-cp-timer", integrator_cp_of_init); 339