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 void efm32_clock_event_set_mode(enum clock_event_mode mode, 52 struct clock_event_device *evtdev) 53{ 54 struct efm32_clock_event_ddata *ddata = 55 container_of(evtdev, struct efm32_clock_event_ddata, evtdev); 56 57 switch (mode) { 58 case CLOCK_EVT_MODE_PERIODIC: 59 writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); 60 writel_relaxed(ddata->periodic_top, ddata->base + TIMERn_TOP); 61 writel_relaxed(TIMERn_CTRL_PRESC_1024 | 62 TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | 63 TIMERn_CTRL_MODE_DOWN, 64 ddata->base + TIMERn_CTRL); 65 writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD); 66 break; 67 68 case CLOCK_EVT_MODE_ONESHOT: 69 writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); 70 writel_relaxed(TIMERn_CTRL_PRESC_1024 | 71 TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | 72 TIMERn_CTRL_OSMEN | 73 TIMERn_CTRL_MODE_DOWN, 74 ddata->base + TIMERn_CTRL); 75 break; 76 77 case CLOCK_EVT_MODE_UNUSED: 78 case CLOCK_EVT_MODE_SHUTDOWN: 79 writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); 80 break; 81 82 case CLOCK_EVT_MODE_RESUME: 83 break; 84 } 85} 86 87static int efm32_clock_event_set_next_event(unsigned long evt, 88 struct clock_event_device *evtdev) 89{ 90 struct efm32_clock_event_ddata *ddata = 91 container_of(evtdev, struct efm32_clock_event_ddata, evtdev); 92 93 writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); 94 writel_relaxed(evt, ddata->base + TIMERn_CNT); 95 writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD); 96 97 return 0; 98} 99 100static irqreturn_t efm32_clock_event_handler(int irq, void *dev_id) 101{ 102 struct efm32_clock_event_ddata *ddata = dev_id; 103 104 writel_relaxed(TIMERn_IRQ_UF, ddata->base + TIMERn_IFC); 105 106 ddata->evtdev.event_handler(&ddata->evtdev); 107 108 return IRQ_HANDLED; 109} 110 111static struct efm32_clock_event_ddata clock_event_ddata = { 112 .evtdev = { 113 .name = "efm32 clockevent", 114 .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, 115 .set_mode = efm32_clock_event_set_mode, 116 .set_next_event = efm32_clock_event_set_next_event, 117 .rating = 200, 118 }, 119}; 120 121static struct irqaction efm32_clock_event_irq = { 122 .name = "efm32 clockevent", 123 .flags = IRQF_TIMER, 124 .handler = efm32_clock_event_handler, 125 .dev_id = &clock_event_ddata, 126}; 127 128static int __init efm32_clocksource_init(struct device_node *np) 129{ 130 struct clk *clk; 131 void __iomem *base; 132 unsigned long rate; 133 int ret; 134 135 clk = of_clk_get(np, 0); 136 if (IS_ERR(clk)) { 137 ret = PTR_ERR(clk); 138 pr_err("failed to get clock for clocksource (%d)\n", ret); 139 goto err_clk_get; 140 } 141 142 ret = clk_prepare_enable(clk); 143 if (ret) { 144 pr_err("failed to enable timer clock for clocksource (%d)\n", 145 ret); 146 goto err_clk_enable; 147 } 148 rate = clk_get_rate(clk); 149 150 base = of_iomap(np, 0); 151 if (!base) { 152 ret = -EADDRNOTAVAIL; 153 pr_err("failed to map registers for clocksource\n"); 154 goto err_iomap; 155 } 156 157 writel_relaxed(TIMERn_CTRL_PRESC_1024 | 158 TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | 159 TIMERn_CTRL_MODE_UP, base + TIMERn_CTRL); 160 writel_relaxed(TIMERn_CMD_START, base + TIMERn_CMD); 161 162 ret = clocksource_mmio_init(base + TIMERn_CNT, "efm32 timer", 163 DIV_ROUND_CLOSEST(rate, 1024), 200, 16, 164 clocksource_mmio_readl_up); 165 if (ret) { 166 pr_err("failed to init clocksource (%d)\n", ret); 167 goto err_clocksource_init; 168 } 169 170 return 0; 171 172err_clocksource_init: 173 174 iounmap(base); 175err_iomap: 176 177 clk_disable_unprepare(clk); 178err_clk_enable: 179 180 clk_put(clk); 181err_clk_get: 182 183 return ret; 184} 185 186static int __init efm32_clockevent_init(struct device_node *np) 187{ 188 struct clk *clk; 189 void __iomem *base; 190 unsigned long rate; 191 int irq; 192 int ret; 193 194 clk = of_clk_get(np, 0); 195 if (IS_ERR(clk)) { 196 ret = PTR_ERR(clk); 197 pr_err("failed to get clock for clockevent (%d)\n", ret); 198 goto err_clk_get; 199 } 200 201 ret = clk_prepare_enable(clk); 202 if (ret) { 203 pr_err("failed to enable timer clock for clockevent (%d)\n", 204 ret); 205 goto err_clk_enable; 206 } 207 rate = clk_get_rate(clk); 208 209 base = of_iomap(np, 0); 210 if (!base) { 211 ret = -EADDRNOTAVAIL; 212 pr_err("failed to map registers for clockevent\n"); 213 goto err_iomap; 214 } 215 216 irq = irq_of_parse_and_map(np, 0); 217 if (!irq) { 218 ret = -ENOENT; 219 pr_err("failed to get irq for clockevent\n"); 220 goto err_get_irq; 221 } 222 223 writel_relaxed(TIMERn_IRQ_UF, base + TIMERn_IEN); 224 225 clock_event_ddata.base = base; 226 clock_event_ddata.periodic_top = DIV_ROUND_CLOSEST(rate, 1024 * HZ); 227 228 clockevents_config_and_register(&clock_event_ddata.evtdev, 229 DIV_ROUND_CLOSEST(rate, 1024), 230 0xf, 0xffff); 231 232 setup_irq(irq, &efm32_clock_event_irq); 233 234 return 0; 235 236err_get_irq: 237 238 iounmap(base); 239err_iomap: 240 241 clk_disable_unprepare(clk); 242err_clk_enable: 243 244 clk_put(clk); 245err_clk_get: 246 247 return ret; 248} 249 250/* 251 * This function asserts that we have exactly one clocksource and one 252 * clock_event_device in the end. 253 */ 254static void __init efm32_timer_init(struct device_node *np) 255{ 256 static int has_clocksource, has_clockevent; 257 int ret; 258 259 if (!has_clocksource) { 260 ret = efm32_clocksource_init(np); 261 if (!ret) { 262 has_clocksource = 1; 263 return; 264 } 265 } 266 267 if (!has_clockevent) { 268 ret = efm32_clockevent_init(np); 269 if (!ret) { 270 has_clockevent = 1; 271 return; 272 } 273 } 274} 275CLOCKSOURCE_OF_DECLARE(efm32compat, "efm32,timer", efm32_timer_init); 276CLOCKSOURCE_OF_DECLARE(efm32, "energymicro,efm32-timer", efm32_timer_init); 277