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