1/* 2 * Allwinner SoCs hstimer driver. 3 * 4 * Copyright (C) 2013 Maxime Ripard 5 * 6 * Maxime Ripard <maxime.ripard@free-electrons.com> 7 * 8 * This file is licensed under the terms of the GNU General Public 9 * License version 2. This program is licensed "as is" without any 10 * warranty of any kind, whether express or implied. 11 */ 12 13#include <linux/clk.h> 14#include <linux/clockchips.h> 15#include <linux/delay.h> 16#include <linux/interrupt.h> 17#include <linux/irq.h> 18#include <linux/irqreturn.h> 19#include <linux/reset.h> 20#include <linux/slab.h> 21#include <linux/of.h> 22#include <linux/of_address.h> 23#include <linux/of_irq.h> 24 25#define TIMER_IRQ_EN_REG 0x00 26#define TIMER_IRQ_EN(val) BIT(val) 27#define TIMER_IRQ_ST_REG 0x04 28#define TIMER_CTL_REG(val) (0x20 * (val) + 0x10) 29#define TIMER_CTL_ENABLE BIT(0) 30#define TIMER_CTL_RELOAD BIT(1) 31#define TIMER_CTL_CLK_PRES(val) (((val) & 0x7) << 4) 32#define TIMER_CTL_ONESHOT BIT(7) 33#define TIMER_INTVAL_LO_REG(val) (0x20 * (val) + 0x14) 34#define TIMER_INTVAL_HI_REG(val) (0x20 * (val) + 0x18) 35#define TIMER_CNTVAL_LO_REG(val) (0x20 * (val) + 0x1c) 36#define TIMER_CNTVAL_HI_REG(val) (0x20 * (val) + 0x20) 37 38#define TIMER_SYNC_TICKS 3 39 40struct sun5i_timer { 41 void __iomem *base; 42 struct clk *clk; 43 struct notifier_block clk_rate_cb; 44 u32 ticks_per_jiffy; 45}; 46 47#define to_sun5i_timer(x) \ 48 container_of(x, struct sun5i_timer, clk_rate_cb) 49 50struct sun5i_timer_clksrc { 51 struct sun5i_timer timer; 52 struct clocksource clksrc; 53}; 54 55#define to_sun5i_timer_clksrc(x) \ 56 container_of(x, struct sun5i_timer_clksrc, clksrc) 57 58struct sun5i_timer_clkevt { 59 struct sun5i_timer timer; 60 struct clock_event_device clkevt; 61}; 62 63#define to_sun5i_timer_clkevt(x) \ 64 container_of(x, struct sun5i_timer_clkevt, clkevt) 65 66/* 67 * When we disable a timer, we need to wait at least for 2 cycles of 68 * the timer source clock. We will use for that the clocksource timer 69 * that is already setup and runs at the same frequency than the other 70 * timers, and we never will be disabled. 71 */ 72static void sun5i_clkevt_sync(struct sun5i_timer_clkevt *ce) 73{ 74 u32 old = readl(ce->timer.base + TIMER_CNTVAL_LO_REG(1)); 75 76 while ((old - readl(ce->timer.base + TIMER_CNTVAL_LO_REG(1))) < TIMER_SYNC_TICKS) 77 cpu_relax(); 78} 79 80static void sun5i_clkevt_time_stop(struct sun5i_timer_clkevt *ce, u8 timer) 81{ 82 u32 val = readl(ce->timer.base + TIMER_CTL_REG(timer)); 83 writel(val & ~TIMER_CTL_ENABLE, ce->timer.base + TIMER_CTL_REG(timer)); 84 85 sun5i_clkevt_sync(ce); 86} 87 88static void sun5i_clkevt_time_setup(struct sun5i_timer_clkevt *ce, u8 timer, u32 delay) 89{ 90 writel(delay, ce->timer.base + TIMER_INTVAL_LO_REG(timer)); 91} 92 93static void sun5i_clkevt_time_start(struct sun5i_timer_clkevt *ce, u8 timer, bool periodic) 94{ 95 u32 val = readl(ce->timer.base + TIMER_CTL_REG(timer)); 96 97 if (periodic) 98 val &= ~TIMER_CTL_ONESHOT; 99 else 100 val |= TIMER_CTL_ONESHOT; 101 102 writel(val | TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, 103 ce->timer.base + TIMER_CTL_REG(timer)); 104} 105 106static void sun5i_clkevt_mode(enum clock_event_mode mode, 107 struct clock_event_device *clkevt) 108{ 109 struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt); 110 111 switch (mode) { 112 case CLOCK_EVT_MODE_PERIODIC: 113 sun5i_clkevt_time_stop(ce, 0); 114 sun5i_clkevt_time_setup(ce, 0, ce->timer.ticks_per_jiffy); 115 sun5i_clkevt_time_start(ce, 0, true); 116 break; 117 case CLOCK_EVT_MODE_ONESHOT: 118 sun5i_clkevt_time_stop(ce, 0); 119 sun5i_clkevt_time_start(ce, 0, false); 120 break; 121 case CLOCK_EVT_MODE_UNUSED: 122 case CLOCK_EVT_MODE_SHUTDOWN: 123 default: 124 sun5i_clkevt_time_stop(ce, 0); 125 break; 126 } 127} 128 129static int sun5i_clkevt_next_event(unsigned long evt, 130 struct clock_event_device *clkevt) 131{ 132 struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt); 133 134 sun5i_clkevt_time_stop(ce, 0); 135 sun5i_clkevt_time_setup(ce, 0, evt - TIMER_SYNC_TICKS); 136 sun5i_clkevt_time_start(ce, 0, false); 137 138 return 0; 139} 140 141static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id) 142{ 143 struct sun5i_timer_clkevt *ce = (struct sun5i_timer_clkevt *)dev_id; 144 145 writel(0x1, ce->timer.base + TIMER_IRQ_ST_REG); 146 ce->clkevt.event_handler(&ce->clkevt); 147 148 return IRQ_HANDLED; 149} 150 151static cycle_t sun5i_clksrc_read(struct clocksource *clksrc) 152{ 153 struct sun5i_timer_clksrc *cs = to_sun5i_timer_clksrc(clksrc); 154 155 return ~readl(cs->timer.base + TIMER_CNTVAL_LO_REG(1)); 156} 157 158static int sun5i_rate_cb_clksrc(struct notifier_block *nb, 159 unsigned long event, void *data) 160{ 161 struct clk_notifier_data *ndata = data; 162 struct sun5i_timer *timer = to_sun5i_timer(nb); 163 struct sun5i_timer_clksrc *cs = container_of(timer, struct sun5i_timer_clksrc, timer); 164 165 switch (event) { 166 case PRE_RATE_CHANGE: 167 clocksource_unregister(&cs->clksrc); 168 break; 169 170 case POST_RATE_CHANGE: 171 clocksource_register_hz(&cs->clksrc, ndata->new_rate); 172 break; 173 174 default: 175 break; 176 } 177 178 return NOTIFY_DONE; 179} 180 181static int __init sun5i_setup_clocksource(struct device_node *node, 182 void __iomem *base, 183 struct clk *clk, int irq) 184{ 185 struct sun5i_timer_clksrc *cs; 186 unsigned long rate; 187 int ret; 188 189 cs = kzalloc(sizeof(*cs), GFP_KERNEL); 190 if (!cs) 191 return -ENOMEM; 192 193 ret = clk_prepare_enable(clk); 194 if (ret) { 195 pr_err("Couldn't enable parent clock\n"); 196 goto err_free; 197 } 198 199 rate = clk_get_rate(clk); 200 201 cs->timer.base = base; 202 cs->timer.clk = clk; 203 cs->timer.clk_rate_cb.notifier_call = sun5i_rate_cb_clksrc; 204 cs->timer.clk_rate_cb.next = NULL; 205 206 ret = clk_notifier_register(clk, &cs->timer.clk_rate_cb); 207 if (ret) { 208 pr_err("Unable to register clock notifier.\n"); 209 goto err_disable_clk; 210 } 211 212 writel(~0, base + TIMER_INTVAL_LO_REG(1)); 213 writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, 214 base + TIMER_CTL_REG(1)); 215 216 cs->clksrc.name = node->name; 217 cs->clksrc.rating = 340; 218 cs->clksrc.read = sun5i_clksrc_read; 219 cs->clksrc.mask = CLOCKSOURCE_MASK(32); 220 cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS; 221 222 ret = clocksource_register_hz(&cs->clksrc, rate); 223 if (ret) { 224 pr_err("Couldn't register clock source.\n"); 225 goto err_remove_notifier; 226 } 227 228 return 0; 229 230err_remove_notifier: 231 clk_notifier_unregister(clk, &cs->timer.clk_rate_cb); 232err_disable_clk: 233 clk_disable_unprepare(clk); 234err_free: 235 kfree(cs); 236 return ret; 237} 238 239static int sun5i_rate_cb_clkevt(struct notifier_block *nb, 240 unsigned long event, void *data) 241{ 242 struct clk_notifier_data *ndata = data; 243 struct sun5i_timer *timer = to_sun5i_timer(nb); 244 struct sun5i_timer_clkevt *ce = container_of(timer, struct sun5i_timer_clkevt, timer); 245 246 if (event == POST_RATE_CHANGE) { 247 clockevents_update_freq(&ce->clkevt, ndata->new_rate); 248 ce->timer.ticks_per_jiffy = DIV_ROUND_UP(ndata->new_rate, HZ); 249 } 250 251 return NOTIFY_DONE; 252} 253 254static int __init sun5i_setup_clockevent(struct device_node *node, void __iomem *base, 255 struct clk *clk, int irq) 256{ 257 struct sun5i_timer_clkevt *ce; 258 unsigned long rate; 259 int ret; 260 u32 val; 261 262 ce = kzalloc(sizeof(*ce), GFP_KERNEL); 263 if (!ce) 264 return -ENOMEM; 265 266 ret = clk_prepare_enable(clk); 267 if (ret) { 268 pr_err("Couldn't enable parent clock\n"); 269 goto err_free; 270 } 271 272 rate = clk_get_rate(clk); 273 274 ce->timer.base = base; 275 ce->timer.ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); 276 ce->timer.clk = clk; 277 ce->timer.clk_rate_cb.notifier_call = sun5i_rate_cb_clkevt; 278 ce->timer.clk_rate_cb.next = NULL; 279 280 ret = clk_notifier_register(clk, &ce->timer.clk_rate_cb); 281 if (ret) { 282 pr_err("Unable to register clock notifier.\n"); 283 goto err_disable_clk; 284 } 285 286 ce->clkevt.name = node->name; 287 ce->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; 288 ce->clkevt.set_next_event = sun5i_clkevt_next_event; 289 ce->clkevt.set_mode = sun5i_clkevt_mode; 290 ce->clkevt.rating = 340; 291 ce->clkevt.irq = irq; 292 ce->clkevt.cpumask = cpu_possible_mask; 293 294 /* Enable timer0 interrupt */ 295 val = readl(base + TIMER_IRQ_EN_REG); 296 writel(val | TIMER_IRQ_EN(0), base + TIMER_IRQ_EN_REG); 297 298 clockevents_config_and_register(&ce->clkevt, rate, 299 TIMER_SYNC_TICKS, 0xffffffff); 300 301 ret = request_irq(irq, sun5i_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL, 302 "sun5i_timer0", ce); 303 if (ret) { 304 pr_err("Unable to register interrupt\n"); 305 goto err_remove_notifier; 306 } 307 308 return 0; 309 310err_remove_notifier: 311 clk_notifier_unregister(clk, &ce->timer.clk_rate_cb); 312err_disable_clk: 313 clk_disable_unprepare(clk); 314err_free: 315 kfree(ce); 316 return ret; 317} 318 319static void __init sun5i_timer_init(struct device_node *node) 320{ 321 struct reset_control *rstc; 322 void __iomem *timer_base; 323 struct clk *clk; 324 int irq; 325 326 timer_base = of_io_request_and_map(node, 0, of_node_full_name(node)); 327 if (!timer_base) 328 panic("Can't map registers"); 329 330 irq = irq_of_parse_and_map(node, 0); 331 if (irq <= 0) 332 panic("Can't parse IRQ"); 333 334 clk = of_clk_get(node, 0); 335 if (IS_ERR(clk)) 336 panic("Can't get timer clock"); 337 338 rstc = of_reset_control_get(node, NULL); 339 if (!IS_ERR(rstc)) 340 reset_control_deassert(rstc); 341 342 sun5i_setup_clocksource(node, timer_base, clk, irq); 343 sun5i_setup_clockevent(node, timer_base, clk, irq); 344} 345CLOCKSOURCE_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer", 346 sun5i_timer_init); 347CLOCKSOURCE_OF_DECLARE(sun7i_a20, "allwinner,sun7i-a20-hstimer", 348 sun5i_timer_init); 349