1/* 2 * Clocksource driver for NXP LPC32xx/18xx/43xx timer 3 * 4 * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com> 5 * 6 * Based on: 7 * time-efm32 Copyright (C) 2013 Pengutronix 8 * mach-lpc32xx/timer.c Copyright (C) 2009 - 2010 NXP Semiconductors 9 * 10 * This file is licensed under the terms of the GNU General Public 11 * License version 2. This program is licensed "as is" without any 12 * warranty of any kind, whether express or implied. 13 * 14 */ 15 16#define pr_fmt(fmt) "%s: " fmt, __func__ 17 18#include <linux/clk.h> 19#include <linux/clockchips.h> 20#include <linux/clocksource.h> 21#include <linux/interrupt.h> 22#include <linux/irq.h> 23#include <linux/kernel.h> 24#include <linux/of.h> 25#include <linux/of_address.h> 26#include <linux/of_irq.h> 27#include <linux/sched_clock.h> 28 29#define LPC32XX_TIMER_IR 0x000 30#define LPC32XX_TIMER_IR_MR0INT BIT(0) 31#define LPC32XX_TIMER_TCR 0x004 32#define LPC32XX_TIMER_TCR_CEN BIT(0) 33#define LPC32XX_TIMER_TCR_CRST BIT(1) 34#define LPC32XX_TIMER_TC 0x008 35#define LPC32XX_TIMER_PR 0x00c 36#define LPC32XX_TIMER_MCR 0x014 37#define LPC32XX_TIMER_MCR_MR0I BIT(0) 38#define LPC32XX_TIMER_MCR_MR0R BIT(1) 39#define LPC32XX_TIMER_MCR_MR0S BIT(2) 40#define LPC32XX_TIMER_MR0 0x018 41#define LPC32XX_TIMER_CTCR 0x070 42 43struct lpc32xx_clock_event_ddata { 44 struct clock_event_device evtdev; 45 void __iomem *base; 46}; 47 48/* Needed for the sched clock */ 49static void __iomem *clocksource_timer_counter; 50 51static u64 notrace lpc32xx_read_sched_clock(void) 52{ 53 return readl(clocksource_timer_counter); 54} 55 56static int lpc32xx_clkevt_next_event(unsigned long delta, 57 struct clock_event_device *evtdev) 58{ 59 struct lpc32xx_clock_event_ddata *ddata = 60 container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev); 61 62 /* 63 * Place timer in reset and program the delta in the prescale 64 * register (PR). When the prescale counter matches the value 65 * in PR the counter register is incremented and the compare 66 * match will trigger. After setup the timer is released from 67 * reset and enabled. 68 */ 69 writel_relaxed(LPC32XX_TIMER_TCR_CRST, ddata->base + LPC32XX_TIMER_TCR); 70 writel_relaxed(delta, ddata->base + LPC32XX_TIMER_PR); 71 writel_relaxed(LPC32XX_TIMER_TCR_CEN, ddata->base + LPC32XX_TIMER_TCR); 72 73 return 0; 74} 75 76static int lpc32xx_clkevt_shutdown(struct clock_event_device *evtdev) 77{ 78 struct lpc32xx_clock_event_ddata *ddata = 79 container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev); 80 81 /* Disable the timer */ 82 writel_relaxed(0, ddata->base + LPC32XX_TIMER_TCR); 83 84 return 0; 85} 86 87static int lpc32xx_clkevt_oneshot(struct clock_event_device *evtdev) 88{ 89 /* 90 * When using oneshot, we must also disable the timer 91 * to wait for the first call to set_next_event(). 92 */ 93 return lpc32xx_clkevt_shutdown(evtdev); 94} 95 96static irqreturn_t lpc32xx_clock_event_handler(int irq, void *dev_id) 97{ 98 struct lpc32xx_clock_event_ddata *ddata = dev_id; 99 100 /* Clear match on channel 0 */ 101 writel_relaxed(LPC32XX_TIMER_IR_MR0INT, ddata->base + LPC32XX_TIMER_IR); 102 103 ddata->evtdev.event_handler(&ddata->evtdev); 104 105 return IRQ_HANDLED; 106} 107 108static struct lpc32xx_clock_event_ddata lpc32xx_clk_event_ddata = { 109 .evtdev = { 110 .name = "lpc3220 clockevent", 111 .features = CLOCK_EVT_FEAT_ONESHOT, 112 .rating = 300, 113 .set_next_event = lpc32xx_clkevt_next_event, 114 .set_state_shutdown = lpc32xx_clkevt_shutdown, 115 .set_state_oneshot = lpc32xx_clkevt_oneshot, 116 }, 117}; 118 119static int __init lpc32xx_clocksource_init(struct device_node *np) 120{ 121 void __iomem *base; 122 unsigned long rate; 123 struct clk *clk; 124 int ret; 125 126 clk = of_clk_get_by_name(np, "timerclk"); 127 if (IS_ERR(clk)) { 128 pr_err("clock get failed (%lu)\n", PTR_ERR(clk)); 129 return PTR_ERR(clk); 130 } 131 132 ret = clk_prepare_enable(clk); 133 if (ret) { 134 pr_err("clock enable failed (%d)\n", ret); 135 goto err_clk_enable; 136 } 137 138 base = of_iomap(np, 0); 139 if (!base) { 140 pr_err("unable to map registers\n"); 141 ret = -EADDRNOTAVAIL; 142 goto err_iomap; 143 } 144 145 /* 146 * Disable and reset timer then set it to free running timer 147 * mode (CTCR) with no prescaler (PR) or match operations (MCR). 148 * After setup the timer is released from reset and enabled. 149 */ 150 writel_relaxed(LPC32XX_TIMER_TCR_CRST, base + LPC32XX_TIMER_TCR); 151 writel_relaxed(0, base + LPC32XX_TIMER_PR); 152 writel_relaxed(0, base + LPC32XX_TIMER_MCR); 153 writel_relaxed(0, base + LPC32XX_TIMER_CTCR); 154 writel_relaxed(LPC32XX_TIMER_TCR_CEN, base + LPC32XX_TIMER_TCR); 155 156 rate = clk_get_rate(clk); 157 ret = clocksource_mmio_init(base + LPC32XX_TIMER_TC, "lpc3220 timer", 158 rate, 300, 32, clocksource_mmio_readl_up); 159 if (ret) { 160 pr_err("failed to init clocksource (%d)\n", ret); 161 goto err_clocksource_init; 162 } 163 164 clocksource_timer_counter = base + LPC32XX_TIMER_TC; 165 sched_clock_register(lpc32xx_read_sched_clock, 32, rate); 166 167 return 0; 168 169err_clocksource_init: 170 iounmap(base); 171err_iomap: 172 clk_disable_unprepare(clk); 173err_clk_enable: 174 clk_put(clk); 175 return ret; 176} 177 178static int __init lpc32xx_clockevent_init(struct device_node *np) 179{ 180 void __iomem *base; 181 unsigned long rate; 182 struct clk *clk; 183 int ret, irq; 184 185 clk = of_clk_get_by_name(np, "timerclk"); 186 if (IS_ERR(clk)) { 187 pr_err("clock get failed (%lu)\n", PTR_ERR(clk)); 188 return PTR_ERR(clk); 189 } 190 191 ret = clk_prepare_enable(clk); 192 if (ret) { 193 pr_err("clock enable failed (%d)\n", ret); 194 goto err_clk_enable; 195 } 196 197 base = of_iomap(np, 0); 198 if (!base) { 199 pr_err("unable to map registers\n"); 200 ret = -EADDRNOTAVAIL; 201 goto err_iomap; 202 } 203 204 irq = irq_of_parse_and_map(np, 0); 205 if (!irq) { 206 pr_err("get irq failed\n"); 207 ret = -ENOENT; 208 goto err_irq; 209 } 210 211 /* 212 * Disable timer and clear any pending interrupt (IR) on match 213 * channel 0 (MR0). Configure a compare match value of 1 on MR0 214 * and enable interrupt, reset on match and stop on match (MCR). 215 */ 216 writel_relaxed(0, base + LPC32XX_TIMER_TCR); 217 writel_relaxed(0, base + LPC32XX_TIMER_CTCR); 218 writel_relaxed(LPC32XX_TIMER_IR_MR0INT, base + LPC32XX_TIMER_IR); 219 writel_relaxed(1, base + LPC32XX_TIMER_MR0); 220 writel_relaxed(LPC32XX_TIMER_MCR_MR0I | LPC32XX_TIMER_MCR_MR0R | 221 LPC32XX_TIMER_MCR_MR0S, base + LPC32XX_TIMER_MCR); 222 223 rate = clk_get_rate(clk); 224 lpc32xx_clk_event_ddata.base = base; 225 clockevents_config_and_register(&lpc32xx_clk_event_ddata.evtdev, 226 rate, 1, -1); 227 228 ret = request_irq(irq, lpc32xx_clock_event_handler, 229 IRQF_TIMER | IRQF_IRQPOLL, "lpc3220 clockevent", 230 &lpc32xx_clk_event_ddata); 231 if (ret) { 232 pr_err("request irq failed\n"); 233 goto err_irq; 234 } 235 236 return 0; 237 238err_irq: 239 iounmap(base); 240err_iomap: 241 clk_disable_unprepare(clk); 242err_clk_enable: 243 clk_put(clk); 244 return ret; 245} 246 247/* 248 * This function asserts that we have exactly one clocksource and one 249 * clock_event_device in the end. 250 */ 251static void __init lpc32xx_timer_init(struct device_node *np) 252{ 253 static int has_clocksource, has_clockevent; 254 int ret; 255 256 if (!has_clocksource) { 257 ret = lpc32xx_clocksource_init(np); 258 if (!ret) { 259 has_clocksource = 1; 260 return; 261 } 262 } 263 264 if (!has_clockevent) { 265 ret = lpc32xx_clockevent_init(np); 266 if (!ret) { 267 has_clockevent = 1; 268 return; 269 } 270 } 271} 272CLOCKSOURCE_OF_DECLARE(lpc32xx_timer, "nxp,lpc3220-timer", lpc32xx_timer_init); 273