timer-sp804.c (8936B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * linux/drivers/clocksource/timer-sp.c 4 * 5 * Copyright (C) 1999 - 2003 ARM Limited 6 * Copyright (C) 2000 Deep Blue Solutions Ltd 7 */ 8 9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 10 11#include <linux/clk.h> 12#include <linux/clocksource.h> 13#include <linux/clockchips.h> 14#include <linux/err.h> 15#include <linux/interrupt.h> 16#include <linux/irq.h> 17#include <linux/io.h> 18#include <linux/of.h> 19#include <linux/of_address.h> 20#include <linux/of_clk.h> 21#include <linux/of_irq.h> 22#include <linux/sched_clock.h> 23 24#include "timer-sp.h" 25 26/* Hisilicon 64-bit timer(a variant of ARM SP804) */ 27#define HISI_TIMER_1_BASE 0x00 28#define HISI_TIMER_2_BASE 0x40 29#define HISI_TIMER_LOAD 0x00 30#define HISI_TIMER_LOAD_H 0x04 31#define HISI_TIMER_VALUE 0x08 32#define HISI_TIMER_VALUE_H 0x0c 33#define HISI_TIMER_CTRL 0x10 34#define HISI_TIMER_INTCLR 0x14 35#define HISI_TIMER_RIS 0x18 36#define HISI_TIMER_MIS 0x1c 37#define HISI_TIMER_BGLOAD 0x20 38#define HISI_TIMER_BGLOAD_H 0x24 39 40static struct sp804_timer arm_sp804_timer __initdata = { 41 .load = TIMER_LOAD, 42 .value = TIMER_VALUE, 43 .ctrl = TIMER_CTRL, 44 .intclr = TIMER_INTCLR, 45 .timer_base = {TIMER_1_BASE, TIMER_2_BASE}, 46 .width = 32, 47}; 48 49static struct sp804_timer hisi_sp804_timer __initdata = { 50 .load = HISI_TIMER_LOAD, 51 .load_h = HISI_TIMER_LOAD_H, 52 .value = HISI_TIMER_VALUE, 53 .value_h = HISI_TIMER_VALUE_H, 54 .ctrl = HISI_TIMER_CTRL, 55 .intclr = HISI_TIMER_INTCLR, 56 .timer_base = {HISI_TIMER_1_BASE, HISI_TIMER_2_BASE}, 57 .width = 64, 58}; 59 60static struct sp804_clkevt sp804_clkevt[NR_TIMERS]; 61 62static long __init sp804_get_clock_rate(struct clk *clk, const char *name) 63{ 64 int err; 65 66 if (!clk) 67 clk = clk_get_sys("sp804", name); 68 if (IS_ERR(clk)) { 69 pr_err("%s clock not found: %ld\n", name, PTR_ERR(clk)); 70 return PTR_ERR(clk); 71 } 72 73 err = clk_prepare_enable(clk); 74 if (err) { 75 pr_err("clock failed to enable: %d\n", err); 76 clk_put(clk); 77 return err; 78 } 79 80 return clk_get_rate(clk); 81} 82 83static struct sp804_clkevt * __init sp804_clkevt_get(void __iomem *base) 84{ 85 int i; 86 87 for (i = 0; i < NR_TIMERS; i++) { 88 if (sp804_clkevt[i].base == base) 89 return &sp804_clkevt[i]; 90 } 91 92 /* It's impossible to reach here */ 93 WARN_ON(1); 94 95 return NULL; 96} 97 98static struct sp804_clkevt *sched_clkevt; 99 100static u64 notrace sp804_read(void) 101{ 102 return ~readl_relaxed(sched_clkevt->value); 103} 104 105static int __init sp804_clocksource_and_sched_clock_init(void __iomem *base, 106 const char *name, 107 struct clk *clk, 108 int use_sched_clock) 109{ 110 long rate; 111 struct sp804_clkevt *clkevt; 112 113 rate = sp804_get_clock_rate(clk, name); 114 if (rate < 0) 115 return -EINVAL; 116 117 clkevt = sp804_clkevt_get(base); 118 119 writel(0, clkevt->ctrl); 120 writel(0xffffffff, clkevt->load); 121 writel(0xffffffff, clkevt->value); 122 if (clkevt->width == 64) { 123 writel(0xffffffff, clkevt->load_h); 124 writel(0xffffffff, clkevt->value_h); 125 } 126 writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, 127 clkevt->ctrl); 128 129 clocksource_mmio_init(clkevt->value, name, 130 rate, 200, 32, clocksource_mmio_readl_down); 131 132 if (use_sched_clock) { 133 sched_clkevt = clkevt; 134 sched_clock_register(sp804_read, 32, rate); 135 } 136 137 return 0; 138} 139 140 141static struct sp804_clkevt *common_clkevt; 142 143/* 144 * IRQ handler for the timer 145 */ 146static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id) 147{ 148 struct clock_event_device *evt = dev_id; 149 150 /* clear the interrupt */ 151 writel(1, common_clkevt->intclr); 152 153 evt->event_handler(evt); 154 155 return IRQ_HANDLED; 156} 157 158static inline void timer_shutdown(struct clock_event_device *evt) 159{ 160 writel(0, common_clkevt->ctrl); 161} 162 163static int sp804_shutdown(struct clock_event_device *evt) 164{ 165 timer_shutdown(evt); 166 return 0; 167} 168 169static int sp804_set_periodic(struct clock_event_device *evt) 170{ 171 unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE | 172 TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE; 173 174 timer_shutdown(evt); 175 writel(common_clkevt->reload, common_clkevt->load); 176 writel(ctrl, common_clkevt->ctrl); 177 return 0; 178} 179 180static int sp804_set_next_event(unsigned long next, 181 struct clock_event_device *evt) 182{ 183 unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE | 184 TIMER_CTRL_ONESHOT | TIMER_CTRL_ENABLE; 185 186 writel(next, common_clkevt->load); 187 writel(ctrl, common_clkevt->ctrl); 188 189 return 0; 190} 191 192static struct clock_event_device sp804_clockevent = { 193 .features = CLOCK_EVT_FEAT_PERIODIC | 194 CLOCK_EVT_FEAT_ONESHOT | 195 CLOCK_EVT_FEAT_DYNIRQ, 196 .set_state_shutdown = sp804_shutdown, 197 .set_state_periodic = sp804_set_periodic, 198 .set_state_oneshot = sp804_shutdown, 199 .tick_resume = sp804_shutdown, 200 .set_next_event = sp804_set_next_event, 201 .rating = 300, 202}; 203 204static int __init sp804_clockevents_init(void __iomem *base, unsigned int irq, 205 struct clk *clk, const char *name) 206{ 207 struct clock_event_device *evt = &sp804_clockevent; 208 long rate; 209 210 rate = sp804_get_clock_rate(clk, name); 211 if (rate < 0) 212 return -EINVAL; 213 214 common_clkevt = sp804_clkevt_get(base); 215 common_clkevt->reload = DIV_ROUND_CLOSEST(rate, HZ); 216 evt->name = name; 217 evt->irq = irq; 218 evt->cpumask = cpu_possible_mask; 219 220 writel(0, common_clkevt->ctrl); 221 222 if (request_irq(irq, sp804_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL, 223 "timer", &sp804_clockevent)) 224 pr_err("request_irq() failed\n"); 225 clockevents_config_and_register(evt, rate, 0xf, 0xffffffff); 226 227 return 0; 228} 229 230static void __init sp804_clkevt_init(struct sp804_timer *timer, void __iomem *base) 231{ 232 int i; 233 234 for (i = 0; i < NR_TIMERS; i++) { 235 void __iomem *timer_base; 236 struct sp804_clkevt *clkevt; 237 238 timer_base = base + timer->timer_base[i]; 239 clkevt = &sp804_clkevt[i]; 240 clkevt->base = timer_base; 241 clkevt->load = timer_base + timer->load; 242 clkevt->load_h = timer_base + timer->load_h; 243 clkevt->value = timer_base + timer->value; 244 clkevt->value_h = timer_base + timer->value_h; 245 clkevt->ctrl = timer_base + timer->ctrl; 246 clkevt->intclr = timer_base + timer->intclr; 247 clkevt->width = timer->width; 248 } 249} 250 251static int __init sp804_of_init(struct device_node *np, struct sp804_timer *timer) 252{ 253 static bool initialized = false; 254 void __iomem *base; 255 void __iomem *timer1_base; 256 void __iomem *timer2_base; 257 int irq, ret = -EINVAL; 258 u32 irq_num = 0; 259 struct clk *clk1, *clk2; 260 const char *name = of_get_property(np, "compatible", NULL); 261 262 if (initialized) { 263 pr_debug("%pOF: skipping further SP804 timer device\n", np); 264 return 0; 265 } 266 267 base = of_iomap(np, 0); 268 if (!base) 269 return -ENXIO; 270 271 timer1_base = base + timer->timer_base[0]; 272 timer2_base = base + timer->timer_base[1]; 273 274 /* Ensure timers are disabled */ 275 writel(0, timer1_base + timer->ctrl); 276 writel(0, timer2_base + timer->ctrl); 277 278 clk1 = of_clk_get(np, 0); 279 if (IS_ERR(clk1)) 280 clk1 = NULL; 281 282 /* Get the 2nd clock if the timer has 3 timer clocks */ 283 if (of_clk_get_parent_count(np) == 3) { 284 clk2 = of_clk_get(np, 1); 285 if (IS_ERR(clk2)) { 286 pr_err("%pOFn clock not found: %d\n", np, 287 (int)PTR_ERR(clk2)); 288 clk2 = NULL; 289 } 290 } else 291 clk2 = clk1; 292 293 irq = irq_of_parse_and_map(np, 0); 294 if (irq <= 0) 295 goto err; 296 297 sp804_clkevt_init(timer, base); 298 299 of_property_read_u32(np, "arm,sp804-has-irq", &irq_num); 300 if (irq_num == 2) { 301 302 ret = sp804_clockevents_init(timer2_base, irq, clk2, name); 303 if (ret) 304 goto err; 305 306 ret = sp804_clocksource_and_sched_clock_init(timer1_base, 307 name, clk1, 1); 308 if (ret) 309 goto err; 310 } else { 311 312 ret = sp804_clockevents_init(timer1_base, irq, clk1, name); 313 if (ret) 314 goto err; 315 316 ret = sp804_clocksource_and_sched_clock_init(timer2_base, 317 name, clk2, 1); 318 if (ret) 319 goto err; 320 } 321 initialized = true; 322 323 return 0; 324err: 325 iounmap(base); 326 return ret; 327} 328 329static int __init arm_sp804_of_init(struct device_node *np) 330{ 331 return sp804_of_init(np, &arm_sp804_timer); 332} 333TIMER_OF_DECLARE(sp804, "arm,sp804", arm_sp804_of_init); 334 335static int __init hisi_sp804_of_init(struct device_node *np) 336{ 337 return sp804_of_init(np, &hisi_sp804_timer); 338} 339TIMER_OF_DECLARE(hisi_sp804, "hisilicon,sp804", hisi_sp804_of_init); 340 341static int __init integrator_cp_of_init(struct device_node *np) 342{ 343 static int init_count = 0; 344 void __iomem *base; 345 int irq, ret = -EINVAL; 346 const char *name = of_get_property(np, "compatible", NULL); 347 struct clk *clk; 348 349 base = of_iomap(np, 0); 350 if (!base) { 351 pr_err("Failed to iomap\n"); 352 return -ENXIO; 353 } 354 355 clk = of_clk_get(np, 0); 356 if (IS_ERR(clk)) { 357 pr_err("Failed to get clock\n"); 358 return PTR_ERR(clk); 359 } 360 361 /* Ensure timer is disabled */ 362 writel(0, base + arm_sp804_timer.ctrl); 363 364 if (init_count == 2 || !of_device_is_available(np)) 365 goto err; 366 367 sp804_clkevt_init(&arm_sp804_timer, base); 368 369 if (!init_count) { 370 ret = sp804_clocksource_and_sched_clock_init(base, 371 name, clk, 0); 372 if (ret) 373 goto err; 374 } else { 375 irq = irq_of_parse_and_map(np, 0); 376 if (irq <= 0) 377 goto err; 378 379 ret = sp804_clockevents_init(base, irq, clk, name); 380 if (ret) 381 goto err; 382 } 383 384 init_count++; 385 return 0; 386err: 387 iounmap(base); 388 return ret; 389} 390TIMER_OF_DECLARE(intcp, "arm,integrator-cp-timer", integrator_cp_of_init);