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