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