at master 11 kB view raw
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_eoi(struct dw_apb_timer *timer) 72{ 73 apbt_readl_relaxed(timer, APBTMR_N_EOI); 74} 75 76static irqreturn_t dw_apb_clockevent_irq(int irq, void *data) 77{ 78 struct clock_event_device *evt = data; 79 struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); 80 81 if (!evt->event_handler) { 82 pr_info("Spurious APBT timer interrupt %d\n", irq); 83 return IRQ_NONE; 84 } 85 86 if (dw_ced->eoi) 87 dw_ced->eoi(&dw_ced->timer); 88 89 evt->event_handler(evt); 90 return IRQ_HANDLED; 91} 92 93static void apbt_enable_int(struct dw_apb_timer *timer) 94{ 95 u32 ctrl = apbt_readl(timer, APBTMR_N_CONTROL); 96 /* clear pending intr */ 97 apbt_readl(timer, APBTMR_N_EOI); 98 ctrl &= ~APBTMR_CONTROL_INT; 99 apbt_writel(timer, ctrl, APBTMR_N_CONTROL); 100} 101 102static int apbt_shutdown(struct clock_event_device *evt) 103{ 104 struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); 105 u32 ctrl; 106 107 pr_debug("%s CPU %d state=shutdown\n", __func__, 108 cpumask_first(evt->cpumask)); 109 110 ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL); 111 ctrl &= ~APBTMR_CONTROL_ENABLE; 112 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); 113 return 0; 114} 115 116static int apbt_set_oneshot(struct clock_event_device *evt) 117{ 118 struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); 119 u32 ctrl; 120 121 pr_debug("%s CPU %d state=oneshot\n", __func__, 122 cpumask_first(evt->cpumask)); 123 124 ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL); 125 /* 126 * set free running mode, this mode will let timer reload max 127 * timeout which will give time (3min on 25MHz clock) to rearm 128 * the next event, therefore emulate the one-shot mode. 129 */ 130 ctrl &= ~APBTMR_CONTROL_ENABLE; 131 ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC; 132 133 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); 134 /* write again to set free running mode */ 135 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); 136 137 /* 138 * DW APB p. 46, load counter with all 1s before starting free 139 * running mode. 140 */ 141 apbt_writel(&dw_ced->timer, ~0, APBTMR_N_LOAD_COUNT); 142 ctrl &= ~APBTMR_CONTROL_INT; 143 ctrl |= APBTMR_CONTROL_ENABLE; 144 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); 145 return 0; 146} 147 148static int apbt_set_periodic(struct clock_event_device *evt) 149{ 150 struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); 151 unsigned long period = DIV_ROUND_UP(dw_ced->timer.freq, HZ); 152 u32 ctrl; 153 154 pr_debug("%s CPU %d state=periodic\n", __func__, 155 cpumask_first(evt->cpumask)); 156 157 ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL); 158 ctrl |= APBTMR_CONTROL_MODE_PERIODIC; 159 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); 160 /* 161 * DW APB p. 46, have to disable timer before load counter, 162 * may cause sync problem. 163 */ 164 ctrl &= ~APBTMR_CONTROL_ENABLE; 165 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); 166 udelay(1); 167 pr_debug("Setting clock period %lu for HZ %d\n", period, HZ); 168 apbt_writel(&dw_ced->timer, period, APBTMR_N_LOAD_COUNT); 169 ctrl |= APBTMR_CONTROL_ENABLE; 170 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); 171 return 0; 172} 173 174static int apbt_resume(struct clock_event_device *evt) 175{ 176 struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); 177 178 pr_debug("%s CPU %d state=resume\n", __func__, 179 cpumask_first(evt->cpumask)); 180 181 apbt_enable_int(&dw_ced->timer); 182 return 0; 183} 184 185static int apbt_next_event(unsigned long delta, 186 struct clock_event_device *evt) 187{ 188 u32 ctrl; 189 struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); 190 191 /* Disable timer */ 192 ctrl = apbt_readl_relaxed(&dw_ced->timer, APBTMR_N_CONTROL); 193 ctrl &= ~APBTMR_CONTROL_ENABLE; 194 apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); 195 /* write new count */ 196 apbt_writel_relaxed(&dw_ced->timer, delta, APBTMR_N_LOAD_COUNT); 197 ctrl |= APBTMR_CONTROL_ENABLE; 198 apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); 199 200 return 0; 201} 202 203/** 204 * dw_apb_clockevent_init() - use an APB timer as a clock_event_device 205 * 206 * @cpu: The CPU the events will be targeted at or -1 if CPU affiliation 207 * isn't required. 208 * @name: The name used for the timer and the IRQ for it. 209 * @rating: The rating to give the timer. 210 * @base: I/O base for the timer registers. 211 * @irq: The interrupt number to use for the timer. 212 * @freq: The frequency that the timer counts at. 213 * 214 * This creates a clock_event_device for using with the generic clock layer 215 * but does not start and register it. This should be done with 216 * dw_apb_clockevent_register() as the next step. If this is the first time 217 * it has been called for a timer then the IRQ will be requested, if not it 218 * just be enabled to allow CPU hotplug to avoid repeatedly requesting and 219 * releasing the IRQ. 220 */ 221struct dw_apb_clock_event_device * 222dw_apb_clockevent_init(int cpu, const char *name, unsigned rating, 223 void __iomem *base, int irq, unsigned long freq) 224{ 225 struct dw_apb_clock_event_device *dw_ced = 226 kzalloc(sizeof(*dw_ced), GFP_KERNEL); 227 int err; 228 229 if (!dw_ced) 230 return NULL; 231 232 dw_ced->timer.base = base; 233 dw_ced->timer.irq = irq; 234 dw_ced->timer.freq = freq; 235 236 clockevents_calc_mult_shift(&dw_ced->ced, freq, APBT_MIN_PERIOD); 237 dw_ced->ced.max_delta_ns = clockevent_delta2ns(0x7fffffff, 238 &dw_ced->ced); 239 dw_ced->ced.max_delta_ticks = 0x7fffffff; 240 dw_ced->ced.min_delta_ns = clockevent_delta2ns(5000, &dw_ced->ced); 241 dw_ced->ced.min_delta_ticks = 5000; 242 dw_ced->ced.cpumask = cpu < 0 ? cpu_possible_mask : cpumask_of(cpu); 243 dw_ced->ced.features = CLOCK_EVT_FEAT_PERIODIC | 244 CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_DYNIRQ; 245 dw_ced->ced.set_state_shutdown = apbt_shutdown; 246 dw_ced->ced.set_state_periodic = apbt_set_periodic; 247 dw_ced->ced.set_state_oneshot = apbt_set_oneshot; 248 dw_ced->ced.set_state_oneshot_stopped = apbt_shutdown; 249 dw_ced->ced.tick_resume = apbt_resume; 250 dw_ced->ced.set_next_event = apbt_next_event; 251 dw_ced->ced.irq = dw_ced->timer.irq; 252 dw_ced->ced.rating = rating; 253 dw_ced->ced.name = name; 254 255 dw_ced->eoi = apbt_eoi; 256 err = request_irq(irq, dw_apb_clockevent_irq, 257 IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING, 258 dw_ced->ced.name, &dw_ced->ced); 259 if (err) { 260 pr_err("failed to request timer irq\n"); 261 kfree(dw_ced); 262 dw_ced = NULL; 263 } 264 265 return dw_ced; 266} 267 268/** 269 * dw_apb_clockevent_register() - register the clock with the generic layer 270 * 271 * @dw_ced: The APB clock to register as a clock_event_device. 272 */ 273void dw_apb_clockevent_register(struct dw_apb_clock_event_device *dw_ced) 274{ 275 apbt_writel(&dw_ced->timer, 0, APBTMR_N_CONTROL); 276 clockevents_register_device(&dw_ced->ced); 277 apbt_enable_int(&dw_ced->timer); 278} 279 280/** 281 * dw_apb_clocksource_start() - start the clocksource counting. 282 * 283 * @dw_cs: The clocksource to start. 284 * 285 * This is used to start the clocksource before registration and can be used 286 * to enable calibration of timers. 287 */ 288void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs) 289{ 290 /* 291 * start count down from 0xffff_ffff. this is done by toggling the 292 * enable bit then load initial load count to ~0. 293 */ 294 u32 ctrl = apbt_readl(&dw_cs->timer, APBTMR_N_CONTROL); 295 296 ctrl &= ~APBTMR_CONTROL_ENABLE; 297 apbt_writel(&dw_cs->timer, ctrl, APBTMR_N_CONTROL); 298 apbt_writel(&dw_cs->timer, ~0, APBTMR_N_LOAD_COUNT); 299 /* enable, mask interrupt */ 300 ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC; 301 ctrl |= (APBTMR_CONTROL_ENABLE | APBTMR_CONTROL_INT); 302 apbt_writel(&dw_cs->timer, ctrl, APBTMR_N_CONTROL); 303 /* read it once to get cached counter value initialized */ 304 dw_apb_clocksource_read(dw_cs); 305} 306 307static u64 __apbt_read_clocksource(struct clocksource *cs) 308{ 309 u32 current_count; 310 struct dw_apb_clocksource *dw_cs = 311 clocksource_to_dw_apb_clocksource(cs); 312 313 current_count = apbt_readl_relaxed(&dw_cs->timer, 314 APBTMR_N_CURRENT_VALUE); 315 316 return (u64)~current_count; 317} 318 319static void apbt_restart_clocksource(struct clocksource *cs) 320{ 321 struct dw_apb_clocksource *dw_cs = 322 clocksource_to_dw_apb_clocksource(cs); 323 324 dw_apb_clocksource_start(dw_cs); 325} 326 327/** 328 * dw_apb_clocksource_init() - use an APB timer as a clocksource. 329 * 330 * @rating: The rating to give the clocksource. 331 * @name: The name for the clocksource. 332 * @base: The I/O base for the timer registers. 333 * @freq: The frequency that the timer counts at. 334 * 335 * This creates a clocksource using an APB timer but does not yet register it 336 * with the clocksource system. This should be done with 337 * dw_apb_clocksource_register() as the next step. 338 */ 339struct dw_apb_clocksource * 340dw_apb_clocksource_init(unsigned rating, const char *name, void __iomem *base, 341 unsigned long freq) 342{ 343 struct dw_apb_clocksource *dw_cs = kzalloc(sizeof(*dw_cs), GFP_KERNEL); 344 345 if (!dw_cs) 346 return NULL; 347 348 dw_cs->timer.base = base; 349 dw_cs->timer.freq = freq; 350 dw_cs->cs.name = name; 351 dw_cs->cs.rating = rating; 352 dw_cs->cs.read = __apbt_read_clocksource; 353 dw_cs->cs.mask = CLOCKSOURCE_MASK(32); 354 dw_cs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; 355 dw_cs->cs.resume = apbt_restart_clocksource; 356 357 return dw_cs; 358} 359 360/** 361 * dw_apb_clocksource_register() - register the APB clocksource. 362 * 363 * @dw_cs: The clocksource to register. 364 */ 365void dw_apb_clocksource_register(struct dw_apb_clocksource *dw_cs) 366{ 367 clocksource_register_hz(&dw_cs->cs, dw_cs->timer.freq); 368} 369 370/** 371 * dw_apb_clocksource_read() - read the current value of a clocksource. 372 * 373 * @dw_cs: The clocksource to read. 374 */ 375u64 dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs) 376{ 377 return (u64)~apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE); 378}