1/* 2 * Copyright (C) 2013 Pengutronix 3 * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> 4 * 5 * This program is free software; you can redistribute it and/or modify it under 6 * the terms of the GNU General Public License version 2 as published by the 7 * Free Software Foundation. 8 */ 9 10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 11 12#include <linux/kernel.h> 13#include <linux/clocksource.h> 14#include <linux/clockchips.h> 15#include <linux/irq.h> 16#include <linux/interrupt.h> 17#include <linux/of.h> 18#include <linux/of_address.h> 19#include <linux/of_irq.h> 20#include <linux/clk.h> 21 22#define TIMERn_CTRL 0x00 23#define TIMERn_CTRL_PRESC(val) (((val) & 0xf) << 24) 24#define TIMERn_CTRL_PRESC_1024 TIMERn_CTRL_PRESC(10) 25#define TIMERn_CTRL_CLKSEL(val) (((val) & 0x3) << 16) 26#define TIMERn_CTRL_CLKSEL_PRESCHFPERCLK TIMERn_CTRL_CLKSEL(0) 27#define TIMERn_CTRL_OSMEN 0x00000010 28#define TIMERn_CTRL_MODE(val) (((val) & 0x3) << 0) 29#define TIMERn_CTRL_MODE_UP TIMERn_CTRL_MODE(0) 30#define TIMERn_CTRL_MODE_DOWN TIMERn_CTRL_MODE(1) 31 32#define TIMERn_CMD 0x04 33#define TIMERn_CMD_START 0x00000001 34#define TIMERn_CMD_STOP 0x00000002 35 36#define TIMERn_IEN 0x0c 37#define TIMERn_IF 0x10 38#define TIMERn_IFS 0x14 39#define TIMERn_IFC 0x18 40#define TIMERn_IRQ_UF 0x00000002 41 42#define TIMERn_TOP 0x1c 43#define TIMERn_CNT 0x24 44 45struct efm32_clock_event_ddata { 46 struct clock_event_device evtdev; 47 void __iomem *base; 48 unsigned periodic_top; 49}; 50 51static int efm32_clock_event_shutdown(struct clock_event_device *evtdev) 52{ 53 struct efm32_clock_event_ddata *ddata = 54 container_of(evtdev, struct efm32_clock_event_ddata, evtdev); 55 56 writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); 57 return 0; 58} 59 60static int efm32_clock_event_set_oneshot(struct clock_event_device *evtdev) 61{ 62 struct efm32_clock_event_ddata *ddata = 63 container_of(evtdev, struct efm32_clock_event_ddata, evtdev); 64 65 writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); 66 writel_relaxed(TIMERn_CTRL_PRESC_1024 | 67 TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | 68 TIMERn_CTRL_OSMEN | 69 TIMERn_CTRL_MODE_DOWN, 70 ddata->base + TIMERn_CTRL); 71 return 0; 72} 73 74static int efm32_clock_event_set_periodic(struct clock_event_device *evtdev) 75{ 76 struct efm32_clock_event_ddata *ddata = 77 container_of(evtdev, struct efm32_clock_event_ddata, evtdev); 78 79 writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); 80 writel_relaxed(ddata->periodic_top, ddata->base + TIMERn_TOP); 81 writel_relaxed(TIMERn_CTRL_PRESC_1024 | 82 TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | 83 TIMERn_CTRL_MODE_DOWN, 84 ddata->base + TIMERn_CTRL); 85 writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD); 86 return 0; 87} 88 89static int efm32_clock_event_set_next_event(unsigned long evt, 90 struct clock_event_device *evtdev) 91{ 92 struct efm32_clock_event_ddata *ddata = 93 container_of(evtdev, struct efm32_clock_event_ddata, evtdev); 94 95 writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); 96 writel_relaxed(evt, ddata->base + TIMERn_CNT); 97 writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD); 98 99 return 0; 100} 101 102static irqreturn_t efm32_clock_event_handler(int irq, void *dev_id) 103{ 104 struct efm32_clock_event_ddata *ddata = dev_id; 105 106 writel_relaxed(TIMERn_IRQ_UF, ddata->base + TIMERn_IFC); 107 108 ddata->evtdev.event_handler(&ddata->evtdev); 109 110 return IRQ_HANDLED; 111} 112 113static struct efm32_clock_event_ddata clock_event_ddata = { 114 .evtdev = { 115 .name = "efm32 clockevent", 116 .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, 117 .set_state_shutdown = efm32_clock_event_shutdown, 118 .set_state_periodic = efm32_clock_event_set_periodic, 119 .set_state_oneshot = efm32_clock_event_set_oneshot, 120 .set_next_event = efm32_clock_event_set_next_event, 121 .rating = 200, 122 }, 123}; 124 125static struct irqaction efm32_clock_event_irq = { 126 .name = "efm32 clockevent", 127 .flags = IRQF_TIMER, 128 .handler = efm32_clock_event_handler, 129 .dev_id = &clock_event_ddata, 130}; 131 132static int __init efm32_clocksource_init(struct device_node *np) 133{ 134 struct clk *clk; 135 void __iomem *base; 136 unsigned long rate; 137 int ret; 138 139 clk = of_clk_get(np, 0); 140 if (IS_ERR(clk)) { 141 ret = PTR_ERR(clk); 142 pr_err("failed to get clock for clocksource (%d)\n", ret); 143 goto err_clk_get; 144 } 145 146 ret = clk_prepare_enable(clk); 147 if (ret) { 148 pr_err("failed to enable timer clock for clocksource (%d)\n", 149 ret); 150 goto err_clk_enable; 151 } 152 rate = clk_get_rate(clk); 153 154 base = of_iomap(np, 0); 155 if (!base) { 156 ret = -EADDRNOTAVAIL; 157 pr_err("failed to map registers for clocksource\n"); 158 goto err_iomap; 159 } 160 161 writel_relaxed(TIMERn_CTRL_PRESC_1024 | 162 TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | 163 TIMERn_CTRL_MODE_UP, base + TIMERn_CTRL); 164 writel_relaxed(TIMERn_CMD_START, base + TIMERn_CMD); 165 166 ret = clocksource_mmio_init(base + TIMERn_CNT, "efm32 timer", 167 DIV_ROUND_CLOSEST(rate, 1024), 200, 16, 168 clocksource_mmio_readl_up); 169 if (ret) { 170 pr_err("failed to init clocksource (%d)\n", ret); 171 goto err_clocksource_init; 172 } 173 174 return 0; 175 176err_clocksource_init: 177 178 iounmap(base); 179err_iomap: 180 181 clk_disable_unprepare(clk); 182err_clk_enable: 183 184 clk_put(clk); 185err_clk_get: 186 187 return ret; 188} 189 190static int __init efm32_clockevent_init(struct device_node *np) 191{ 192 struct clk *clk; 193 void __iomem *base; 194 unsigned long rate; 195 int irq; 196 int ret; 197 198 clk = of_clk_get(np, 0); 199 if (IS_ERR(clk)) { 200 ret = PTR_ERR(clk); 201 pr_err("failed to get clock for clockevent (%d)\n", ret); 202 goto err_clk_get; 203 } 204 205 ret = clk_prepare_enable(clk); 206 if (ret) { 207 pr_err("failed to enable timer clock for clockevent (%d)\n", 208 ret); 209 goto err_clk_enable; 210 } 211 rate = clk_get_rate(clk); 212 213 base = of_iomap(np, 0); 214 if (!base) { 215 ret = -EADDRNOTAVAIL; 216 pr_err("failed to map registers for clockevent\n"); 217 goto err_iomap; 218 } 219 220 irq = irq_of_parse_and_map(np, 0); 221 if (!irq) { 222 ret = -ENOENT; 223 pr_err("failed to get irq for clockevent\n"); 224 goto err_get_irq; 225 } 226 227 writel_relaxed(TIMERn_IRQ_UF, base + TIMERn_IEN); 228 229 clock_event_ddata.base = base; 230 clock_event_ddata.periodic_top = DIV_ROUND_CLOSEST(rate, 1024 * HZ); 231 232 clockevents_config_and_register(&clock_event_ddata.evtdev, 233 DIV_ROUND_CLOSEST(rate, 1024), 234 0xf, 0xffff); 235 236 setup_irq(irq, &efm32_clock_event_irq); 237 238 return 0; 239 240err_get_irq: 241 242 iounmap(base); 243err_iomap: 244 245 clk_disable_unprepare(clk); 246err_clk_enable: 247 248 clk_put(clk); 249err_clk_get: 250 251 return ret; 252} 253 254/* 255 * This function asserts that we have exactly one clocksource and one 256 * clock_event_device in the end. 257 */ 258static void __init efm32_timer_init(struct device_node *np) 259{ 260 static int has_clocksource, has_clockevent; 261 int ret; 262 263 if (!has_clocksource) { 264 ret = efm32_clocksource_init(np); 265 if (!ret) { 266 has_clocksource = 1; 267 return; 268 } 269 } 270 271 if (!has_clockevent) { 272 ret = efm32_clockevent_init(np); 273 if (!ret) { 274 has_clockevent = 1; 275 return; 276 } 277 } 278} 279CLOCKSOURCE_OF_DECLARE(efm32compat, "efm32,timer", efm32_timer_init); 280CLOCKSOURCE_OF_DECLARE(efm32, "energymicro,efm32-timer", efm32_timer_init); 281