timer-oxnas-rps.c (6800B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * drivers/clocksource/timer-oxnas-rps.c 4 * 5 * Copyright (C) 2009 Oxford Semiconductor Ltd 6 * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com> 7 * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com> 8 */ 9 10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 11 12#include <linux/init.h> 13#include <linux/irq.h> 14#include <linux/io.h> 15#include <linux/clk.h> 16#include <linux/slab.h> 17#include <linux/interrupt.h> 18#include <linux/of_irq.h> 19#include <linux/of_address.h> 20#include <linux/clockchips.h> 21#include <linux/sched_clock.h> 22 23/* TIMER1 used as tick 24 * TIMER2 used as clocksource 25 */ 26 27/* Registers definitions */ 28 29#define TIMER_LOAD_REG 0x0 30#define TIMER_CURR_REG 0x4 31#define TIMER_CTRL_REG 0x8 32#define TIMER_CLRINT_REG 0xC 33 34#define TIMER_BITS 24 35 36#define TIMER_MAX_VAL (BIT(TIMER_BITS) - 1) 37 38#define TIMER_PERIODIC BIT(6) 39#define TIMER_ENABLE BIT(7) 40 41#define TIMER_DIV1 (0) 42#define TIMER_DIV16 (1 << 2) 43#define TIMER_DIV256 (2 << 2) 44 45#define TIMER1_REG_OFFSET 0 46#define TIMER2_REG_OFFSET 0x20 47 48/* Clockevent & Clocksource data */ 49 50struct oxnas_rps_timer { 51 struct clock_event_device clkevent; 52 void __iomem *clksrc_base; 53 void __iomem *clkevt_base; 54 unsigned long timer_period; 55 unsigned int timer_prescaler; 56 struct clk *clk; 57 int irq; 58}; 59 60static irqreturn_t oxnas_rps_timer_irq(int irq, void *dev_id) 61{ 62 struct oxnas_rps_timer *rps = dev_id; 63 64 writel_relaxed(0, rps->clkevt_base + TIMER_CLRINT_REG); 65 66 rps->clkevent.event_handler(&rps->clkevent); 67 68 return IRQ_HANDLED; 69} 70 71static void oxnas_rps_timer_config(struct oxnas_rps_timer *rps, 72 unsigned long period, 73 unsigned int periodic) 74{ 75 uint32_t cfg = rps->timer_prescaler; 76 77 if (period) 78 cfg |= TIMER_ENABLE; 79 80 if (periodic) 81 cfg |= TIMER_PERIODIC; 82 83 writel_relaxed(period, rps->clkevt_base + TIMER_LOAD_REG); 84 writel_relaxed(cfg, rps->clkevt_base + TIMER_CTRL_REG); 85} 86 87static int oxnas_rps_timer_shutdown(struct clock_event_device *evt) 88{ 89 struct oxnas_rps_timer *rps = 90 container_of(evt, struct oxnas_rps_timer, clkevent); 91 92 oxnas_rps_timer_config(rps, 0, 0); 93 94 return 0; 95} 96 97static int oxnas_rps_timer_set_periodic(struct clock_event_device *evt) 98{ 99 struct oxnas_rps_timer *rps = 100 container_of(evt, struct oxnas_rps_timer, clkevent); 101 102 oxnas_rps_timer_config(rps, rps->timer_period, 1); 103 104 return 0; 105} 106 107static int oxnas_rps_timer_set_oneshot(struct clock_event_device *evt) 108{ 109 struct oxnas_rps_timer *rps = 110 container_of(evt, struct oxnas_rps_timer, clkevent); 111 112 oxnas_rps_timer_config(rps, rps->timer_period, 0); 113 114 return 0; 115} 116 117static int oxnas_rps_timer_next_event(unsigned long delta, 118 struct clock_event_device *evt) 119{ 120 struct oxnas_rps_timer *rps = 121 container_of(evt, struct oxnas_rps_timer, clkevent); 122 123 oxnas_rps_timer_config(rps, delta, 0); 124 125 return 0; 126} 127 128static int __init oxnas_rps_clockevent_init(struct oxnas_rps_timer *rps) 129{ 130 ulong clk_rate = clk_get_rate(rps->clk); 131 ulong timer_rate; 132 133 /* Start with prescaler 1 */ 134 rps->timer_prescaler = TIMER_DIV1; 135 rps->timer_period = DIV_ROUND_UP(clk_rate, HZ); 136 timer_rate = clk_rate; 137 138 if (rps->timer_period > TIMER_MAX_VAL) { 139 rps->timer_prescaler = TIMER_DIV16; 140 timer_rate = clk_rate / 16; 141 rps->timer_period = DIV_ROUND_UP(timer_rate, HZ); 142 } 143 if (rps->timer_period > TIMER_MAX_VAL) { 144 rps->timer_prescaler = TIMER_DIV256; 145 timer_rate = clk_rate / 256; 146 rps->timer_period = DIV_ROUND_UP(timer_rate, HZ); 147 } 148 149 rps->clkevent.name = "oxnas-rps"; 150 rps->clkevent.features = CLOCK_EVT_FEAT_PERIODIC | 151 CLOCK_EVT_FEAT_ONESHOT | 152 CLOCK_EVT_FEAT_DYNIRQ; 153 rps->clkevent.tick_resume = oxnas_rps_timer_shutdown; 154 rps->clkevent.set_state_shutdown = oxnas_rps_timer_shutdown; 155 rps->clkevent.set_state_periodic = oxnas_rps_timer_set_periodic; 156 rps->clkevent.set_state_oneshot = oxnas_rps_timer_set_oneshot; 157 rps->clkevent.set_next_event = oxnas_rps_timer_next_event; 158 rps->clkevent.rating = 200; 159 rps->clkevent.cpumask = cpu_possible_mask; 160 rps->clkevent.irq = rps->irq; 161 clockevents_config_and_register(&rps->clkevent, 162 timer_rate, 163 1, 164 TIMER_MAX_VAL); 165 166 pr_info("Registered clock event rate %luHz prescaler %x period %lu\n", 167 clk_rate, 168 rps->timer_prescaler, 169 rps->timer_period); 170 171 return 0; 172} 173 174/* Clocksource */ 175 176static void __iomem *timer_sched_base; 177 178static u64 notrace oxnas_rps_read_sched_clock(void) 179{ 180 return ~readl_relaxed(timer_sched_base); 181} 182 183static int __init oxnas_rps_clocksource_init(struct oxnas_rps_timer *rps) 184{ 185 ulong clk_rate = clk_get_rate(rps->clk); 186 int ret; 187 188 /* use prescale 16 */ 189 clk_rate = clk_rate / 16; 190 191 writel_relaxed(TIMER_MAX_VAL, rps->clksrc_base + TIMER_LOAD_REG); 192 writel_relaxed(TIMER_PERIODIC | TIMER_ENABLE | TIMER_DIV16, 193 rps->clksrc_base + TIMER_CTRL_REG); 194 195 timer_sched_base = rps->clksrc_base + TIMER_CURR_REG; 196 sched_clock_register(oxnas_rps_read_sched_clock, 197 TIMER_BITS, clk_rate); 198 ret = clocksource_mmio_init(timer_sched_base, 199 "oxnas_rps_clocksource_timer", 200 clk_rate, 250, TIMER_BITS, 201 clocksource_mmio_readl_down); 202 if (WARN_ON(ret)) { 203 pr_err("can't register clocksource\n"); 204 return ret; 205 } 206 207 pr_info("Registered clocksource rate %luHz\n", clk_rate); 208 209 return 0; 210} 211 212static int __init oxnas_rps_timer_init(struct device_node *np) 213{ 214 struct oxnas_rps_timer *rps; 215 void __iomem *base; 216 int ret; 217 218 rps = kzalloc(sizeof(*rps), GFP_KERNEL); 219 if (!rps) 220 return -ENOMEM; 221 222 rps->clk = of_clk_get(np, 0); 223 if (IS_ERR(rps->clk)) { 224 ret = PTR_ERR(rps->clk); 225 goto err_alloc; 226 } 227 228 ret = clk_prepare_enable(rps->clk); 229 if (ret) 230 goto err_clk; 231 232 base = of_iomap(np, 0); 233 if (!base) { 234 ret = -ENXIO; 235 goto err_clk_prepare; 236 } 237 238 rps->irq = irq_of_parse_and_map(np, 0); 239 if (!rps->irq) { 240 ret = -EINVAL; 241 goto err_iomap; 242 } 243 244 rps->clkevt_base = base + TIMER1_REG_OFFSET; 245 rps->clksrc_base = base + TIMER2_REG_OFFSET; 246 247 /* Disable timers */ 248 writel_relaxed(0, rps->clkevt_base + TIMER_CTRL_REG); 249 writel_relaxed(0, rps->clksrc_base + TIMER_CTRL_REG); 250 writel_relaxed(0, rps->clkevt_base + TIMER_LOAD_REG); 251 writel_relaxed(0, rps->clksrc_base + TIMER_LOAD_REG); 252 writel_relaxed(0, rps->clkevt_base + TIMER_CLRINT_REG); 253 writel_relaxed(0, rps->clksrc_base + TIMER_CLRINT_REG); 254 255 ret = request_irq(rps->irq, oxnas_rps_timer_irq, 256 IRQF_TIMER | IRQF_IRQPOLL, 257 "rps-timer", rps); 258 if (ret) 259 goto err_iomap; 260 261 ret = oxnas_rps_clocksource_init(rps); 262 if (ret) 263 goto err_irqreq; 264 265 ret = oxnas_rps_clockevent_init(rps); 266 if (ret) 267 goto err_irqreq; 268 269 return 0; 270 271err_irqreq: 272 free_irq(rps->irq, rps); 273err_iomap: 274 iounmap(base); 275err_clk_prepare: 276 clk_disable_unprepare(rps->clk); 277err_clk: 278 clk_put(rps->clk); 279err_alloc: 280 kfree(rps); 281 282 return ret; 283} 284 285TIMER_OF_DECLARE(ox810se_rps, 286 "oxsemi,ox810se-rps-timer", oxnas_rps_timer_init); 287TIMER_OF_DECLARE(ox820_rps, 288 "oxsemi,ox820-rps-timer", oxnas_rps_timer_init);