dw_apb_timer.c (12004B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * (C) Copyright 2009 Intel Corporation 4 * Author: Jacob Pan (jacob.jun.pan@intel.com) 5 * 6 * Shared with ARM platforms, Jamie Iles, Picochip 2011 7 * 8 * Support for the Synopsys DesignWare APB Timers. 9 */ 10#include <linux/dw_apb_timer.h> 11#include <linux/delay.h> 12#include <linux/kernel.h> 13#include <linux/interrupt.h> 14#include <linux/irq.h> 15#include <linux/io.h> 16#include <linux/slab.h> 17 18#define APBT_MIN_PERIOD 4 19#define APBT_MIN_DELTA_USEC 200 20 21#define APBTMR_N_LOAD_COUNT 0x00 22#define APBTMR_N_CURRENT_VALUE 0x04 23#define APBTMR_N_CONTROL 0x08 24#define APBTMR_N_EOI 0x0c 25#define APBTMR_N_INT_STATUS 0x10 26 27#define APBTMRS_INT_STATUS 0xa0 28#define APBTMRS_EOI 0xa4 29#define APBTMRS_RAW_INT_STATUS 0xa8 30#define APBTMRS_COMP_VERSION 0xac 31 32#define APBTMR_CONTROL_ENABLE (1 << 0) 33/* 1: periodic, 0:free running. */ 34#define APBTMR_CONTROL_MODE_PERIODIC (1 << 1) 35#define APBTMR_CONTROL_INT (1 << 2) 36 37static inline struct dw_apb_clock_event_device * 38ced_to_dw_apb_ced(struct clock_event_device *evt) 39{ 40 return container_of(evt, struct dw_apb_clock_event_device, ced); 41} 42 43static inline struct dw_apb_clocksource * 44clocksource_to_dw_apb_clocksource(struct clocksource *cs) 45{ 46 return container_of(cs, struct dw_apb_clocksource, cs); 47} 48 49static inline u32 apbt_readl(struct dw_apb_timer *timer, unsigned long offs) 50{ 51 return readl(timer->base + offs); 52} 53 54static inline void apbt_writel(struct dw_apb_timer *timer, u32 val, 55 unsigned long offs) 56{ 57 writel(val, timer->base + offs); 58} 59 60static inline u32 apbt_readl_relaxed(struct dw_apb_timer *timer, unsigned long offs) 61{ 62 return readl_relaxed(timer->base + offs); 63} 64 65static inline void apbt_writel_relaxed(struct dw_apb_timer *timer, u32 val, 66 unsigned long offs) 67{ 68 writel_relaxed(val, timer->base + offs); 69} 70 71static void apbt_disable_int(struct dw_apb_timer *timer) 72{ 73 u32 ctrl = apbt_readl(timer, APBTMR_N_CONTROL); 74 75 ctrl |= APBTMR_CONTROL_INT; 76 apbt_writel(timer, ctrl, APBTMR_N_CONTROL); 77} 78 79/** 80 * dw_apb_clockevent_pause() - stop the clock_event_device from running 81 * 82 * @dw_ced: The APB clock to stop generating events. 83 */ 84void dw_apb_clockevent_pause(struct dw_apb_clock_event_device *dw_ced) 85{ 86 disable_irq(dw_ced->timer.irq); 87 apbt_disable_int(&dw_ced->timer); 88} 89 90static void apbt_eoi(struct dw_apb_timer *timer) 91{ 92 apbt_readl_relaxed(timer, APBTMR_N_EOI); 93} 94 95static irqreturn_t dw_apb_clockevent_irq(int irq, void *data) 96{ 97 struct clock_event_device *evt = data; 98 struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); 99 100 if (!evt->event_handler) { 101 pr_info("Spurious APBT timer interrupt %d\n", irq); 102 return IRQ_NONE; 103 } 104 105 if (dw_ced->eoi) 106 dw_ced->eoi(&dw_ced->timer); 107 108 evt->event_handler(evt); 109 return IRQ_HANDLED; 110} 111 112static void apbt_enable_int(struct dw_apb_timer *timer) 113{ 114 u32 ctrl = apbt_readl(timer, APBTMR_N_CONTROL); 115 /* clear pending intr */ 116 apbt_readl(timer, APBTMR_N_EOI); 117 ctrl &= ~APBTMR_CONTROL_INT; 118 apbt_writel(timer, ctrl, APBTMR_N_CONTROL); 119} 120 121static int apbt_shutdown(struct clock_event_device *evt) 122{ 123 struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); 124 u32 ctrl; 125 126 pr_debug("%s CPU %d state=shutdown\n", __func__, 127 cpumask_first(evt->cpumask)); 128 129 ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL); 130 ctrl &= ~APBTMR_CONTROL_ENABLE; 131 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); 132 return 0; 133} 134 135static int apbt_set_oneshot(struct clock_event_device *evt) 136{ 137 struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); 138 u32 ctrl; 139 140 pr_debug("%s CPU %d state=oneshot\n", __func__, 141 cpumask_first(evt->cpumask)); 142 143 ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL); 144 /* 145 * set free running mode, this mode will let timer reload max 146 * timeout which will give time (3min on 25MHz clock) to rearm 147 * the next event, therefore emulate the one-shot mode. 148 */ 149 ctrl &= ~APBTMR_CONTROL_ENABLE; 150 ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC; 151 152 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); 153 /* write again to set free running mode */ 154 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); 155 156 /* 157 * DW APB p. 46, load counter with all 1s before starting free 158 * running mode. 159 */ 160 apbt_writel(&dw_ced->timer, ~0, APBTMR_N_LOAD_COUNT); 161 ctrl &= ~APBTMR_CONTROL_INT; 162 ctrl |= APBTMR_CONTROL_ENABLE; 163 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); 164 return 0; 165} 166 167static int apbt_set_periodic(struct clock_event_device *evt) 168{ 169 struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); 170 unsigned long period = DIV_ROUND_UP(dw_ced->timer.freq, HZ); 171 u32 ctrl; 172 173 pr_debug("%s CPU %d state=periodic\n", __func__, 174 cpumask_first(evt->cpumask)); 175 176 ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL); 177 ctrl |= APBTMR_CONTROL_MODE_PERIODIC; 178 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); 179 /* 180 * DW APB p. 46, have to disable timer before load counter, 181 * may cause sync problem. 182 */ 183 ctrl &= ~APBTMR_CONTROL_ENABLE; 184 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); 185 udelay(1); 186 pr_debug("Setting clock period %lu for HZ %d\n", period, HZ); 187 apbt_writel(&dw_ced->timer, period, APBTMR_N_LOAD_COUNT); 188 ctrl |= APBTMR_CONTROL_ENABLE; 189 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); 190 return 0; 191} 192 193static int apbt_resume(struct clock_event_device *evt) 194{ 195 struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); 196 197 pr_debug("%s CPU %d state=resume\n", __func__, 198 cpumask_first(evt->cpumask)); 199 200 apbt_enable_int(&dw_ced->timer); 201 return 0; 202} 203 204static int apbt_next_event(unsigned long delta, 205 struct clock_event_device *evt) 206{ 207 u32 ctrl; 208 struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); 209 210 /* Disable timer */ 211 ctrl = apbt_readl_relaxed(&dw_ced->timer, APBTMR_N_CONTROL); 212 ctrl &= ~APBTMR_CONTROL_ENABLE; 213 apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); 214 /* write new count */ 215 apbt_writel_relaxed(&dw_ced->timer, delta, APBTMR_N_LOAD_COUNT); 216 ctrl |= APBTMR_CONTROL_ENABLE; 217 apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); 218 219 return 0; 220} 221 222/** 223 * dw_apb_clockevent_init() - use an APB timer as a clock_event_device 224 * 225 * @cpu: The CPU the events will be targeted at or -1 if CPU affiliation 226 * isn't required. 227 * @name: The name used for the timer and the IRQ for it. 228 * @rating: The rating to give the timer. 229 * @base: I/O base for the timer registers. 230 * @irq: The interrupt number to use for the timer. 231 * @freq: The frequency that the timer counts at. 232 * 233 * This creates a clock_event_device for using with the generic clock layer 234 * but does not start and register it. This should be done with 235 * dw_apb_clockevent_register() as the next step. If this is the first time 236 * it has been called for a timer then the IRQ will be requested, if not it 237 * just be enabled to allow CPU hotplug to avoid repeatedly requesting and 238 * releasing the IRQ. 239 */ 240struct dw_apb_clock_event_device * 241dw_apb_clockevent_init(int cpu, const char *name, unsigned rating, 242 void __iomem *base, int irq, unsigned long freq) 243{ 244 struct dw_apb_clock_event_device *dw_ced = 245 kzalloc(sizeof(*dw_ced), GFP_KERNEL); 246 int err; 247 248 if (!dw_ced) 249 return NULL; 250 251 dw_ced->timer.base = base; 252 dw_ced->timer.irq = irq; 253 dw_ced->timer.freq = freq; 254 255 clockevents_calc_mult_shift(&dw_ced->ced, freq, APBT_MIN_PERIOD); 256 dw_ced->ced.max_delta_ns = clockevent_delta2ns(0x7fffffff, 257 &dw_ced->ced); 258 dw_ced->ced.max_delta_ticks = 0x7fffffff; 259 dw_ced->ced.min_delta_ns = clockevent_delta2ns(5000, &dw_ced->ced); 260 dw_ced->ced.min_delta_ticks = 5000; 261 dw_ced->ced.cpumask = cpu < 0 ? cpu_possible_mask : cpumask_of(cpu); 262 dw_ced->ced.features = CLOCK_EVT_FEAT_PERIODIC | 263 CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_DYNIRQ; 264 dw_ced->ced.set_state_shutdown = apbt_shutdown; 265 dw_ced->ced.set_state_periodic = apbt_set_periodic; 266 dw_ced->ced.set_state_oneshot = apbt_set_oneshot; 267 dw_ced->ced.set_state_oneshot_stopped = apbt_shutdown; 268 dw_ced->ced.tick_resume = apbt_resume; 269 dw_ced->ced.set_next_event = apbt_next_event; 270 dw_ced->ced.irq = dw_ced->timer.irq; 271 dw_ced->ced.rating = rating; 272 dw_ced->ced.name = name; 273 274 dw_ced->eoi = apbt_eoi; 275 err = request_irq(irq, dw_apb_clockevent_irq, 276 IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING, 277 dw_ced->ced.name, &dw_ced->ced); 278 if (err) { 279 pr_err("failed to request timer irq\n"); 280 kfree(dw_ced); 281 dw_ced = NULL; 282 } 283 284 return dw_ced; 285} 286 287/** 288 * dw_apb_clockevent_resume() - resume a clock that has been paused. 289 * 290 * @dw_ced: The APB clock to resume. 291 */ 292void dw_apb_clockevent_resume(struct dw_apb_clock_event_device *dw_ced) 293{ 294 enable_irq(dw_ced->timer.irq); 295} 296 297/** 298 * dw_apb_clockevent_stop() - stop the clock_event_device and release the IRQ. 299 * 300 * @dw_ced: The APB clock to stop generating the events. 301 */ 302void dw_apb_clockevent_stop(struct dw_apb_clock_event_device *dw_ced) 303{ 304 free_irq(dw_ced->timer.irq, &dw_ced->ced); 305} 306 307/** 308 * dw_apb_clockevent_register() - register the clock with the generic layer 309 * 310 * @dw_ced: The APB clock to register as a clock_event_device. 311 */ 312void dw_apb_clockevent_register(struct dw_apb_clock_event_device *dw_ced) 313{ 314 apbt_writel(&dw_ced->timer, 0, APBTMR_N_CONTROL); 315 clockevents_register_device(&dw_ced->ced); 316 apbt_enable_int(&dw_ced->timer); 317} 318 319/** 320 * dw_apb_clocksource_start() - start the clocksource counting. 321 * 322 * @dw_cs: The clocksource to start. 323 * 324 * This is used to start the clocksource before registration and can be used 325 * to enable calibration of timers. 326 */ 327void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs) 328{ 329 /* 330 * start count down from 0xffff_ffff. this is done by toggling the 331 * enable bit then load initial load count to ~0. 332 */ 333 u32 ctrl = apbt_readl(&dw_cs->timer, APBTMR_N_CONTROL); 334 335 ctrl &= ~APBTMR_CONTROL_ENABLE; 336 apbt_writel(&dw_cs->timer, ctrl, APBTMR_N_CONTROL); 337 apbt_writel(&dw_cs->timer, ~0, APBTMR_N_LOAD_COUNT); 338 /* enable, mask interrupt */ 339 ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC; 340 ctrl |= (APBTMR_CONTROL_ENABLE | APBTMR_CONTROL_INT); 341 apbt_writel(&dw_cs->timer, ctrl, APBTMR_N_CONTROL); 342 /* read it once to get cached counter value initialized */ 343 dw_apb_clocksource_read(dw_cs); 344} 345 346static u64 __apbt_read_clocksource(struct clocksource *cs) 347{ 348 u32 current_count; 349 struct dw_apb_clocksource *dw_cs = 350 clocksource_to_dw_apb_clocksource(cs); 351 352 current_count = apbt_readl_relaxed(&dw_cs->timer, 353 APBTMR_N_CURRENT_VALUE); 354 355 return (u64)~current_count; 356} 357 358static void apbt_restart_clocksource(struct clocksource *cs) 359{ 360 struct dw_apb_clocksource *dw_cs = 361 clocksource_to_dw_apb_clocksource(cs); 362 363 dw_apb_clocksource_start(dw_cs); 364} 365 366/** 367 * dw_apb_clocksource_init() - use an APB timer as a clocksource. 368 * 369 * @rating: The rating to give the clocksource. 370 * @name: The name for the clocksource. 371 * @base: The I/O base for the timer registers. 372 * @freq: The frequency that the timer counts at. 373 * 374 * This creates a clocksource using an APB timer but does not yet register it 375 * with the clocksource system. This should be done with 376 * dw_apb_clocksource_register() as the next step. 377 */ 378struct dw_apb_clocksource * 379dw_apb_clocksource_init(unsigned rating, const char *name, void __iomem *base, 380 unsigned long freq) 381{ 382 struct dw_apb_clocksource *dw_cs = kzalloc(sizeof(*dw_cs), GFP_KERNEL); 383 384 if (!dw_cs) 385 return NULL; 386 387 dw_cs->timer.base = base; 388 dw_cs->timer.freq = freq; 389 dw_cs->cs.name = name; 390 dw_cs->cs.rating = rating; 391 dw_cs->cs.read = __apbt_read_clocksource; 392 dw_cs->cs.mask = CLOCKSOURCE_MASK(32); 393 dw_cs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; 394 dw_cs->cs.resume = apbt_restart_clocksource; 395 396 return dw_cs; 397} 398 399/** 400 * dw_apb_clocksource_register() - register the APB clocksource. 401 * 402 * @dw_cs: The clocksource to register. 403 */ 404void dw_apb_clocksource_register(struct dw_apb_clocksource *dw_cs) 405{ 406 clocksource_register_hz(&dw_cs->cs, dw_cs->timer.freq); 407} 408 409/** 410 * dw_apb_clocksource_read() - read the current value of a clocksource. 411 * 412 * @dw_cs: The clocksource to read. 413 */ 414u64 dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs) 415{ 416 return (u64)~apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE); 417}