167905540SMaxime Ripard /* 267905540SMaxime Ripard * Allwinner SoCs hstimer driver. 367905540SMaxime Ripard * 467905540SMaxime Ripard * Copyright (C) 2013 Maxime Ripard 567905540SMaxime Ripard * 667905540SMaxime Ripard * Maxime Ripard <maxime.ripard@free-electrons.com> 767905540SMaxime Ripard * 867905540SMaxime Ripard * This file is licensed under the terms of the GNU General Public 967905540SMaxime Ripard * License version 2. This program is licensed "as is" without any 1067905540SMaxime Ripard * warranty of any kind, whether express or implied. 1167905540SMaxime Ripard */ 1267905540SMaxime Ripard 1367905540SMaxime Ripard #include <linux/clk.h> 1467905540SMaxime Ripard #include <linux/clockchips.h> 1567905540SMaxime Ripard #include <linux/delay.h> 1667905540SMaxime Ripard #include <linux/interrupt.h> 1767905540SMaxime Ripard #include <linux/irq.h> 1867905540SMaxime Ripard #include <linux/irqreturn.h> 19e50a00beSMaxime Ripard #include <linux/reset.h> 20*4a59058fSMaxime Ripard #include <linux/slab.h> 2167905540SMaxime Ripard #include <linux/of.h> 2267905540SMaxime Ripard #include <linux/of_address.h> 2367905540SMaxime Ripard #include <linux/of_irq.h> 2467905540SMaxime Ripard 2567905540SMaxime Ripard #define TIMER_IRQ_EN_REG 0x00 2667905540SMaxime Ripard #define TIMER_IRQ_EN(val) BIT(val) 2767905540SMaxime Ripard #define TIMER_IRQ_ST_REG 0x04 2867905540SMaxime Ripard #define TIMER_CTL_REG(val) (0x20 * (val) + 0x10) 2967905540SMaxime Ripard #define TIMER_CTL_ENABLE BIT(0) 3067905540SMaxime Ripard #define TIMER_CTL_RELOAD BIT(1) 3167905540SMaxime Ripard #define TIMER_CTL_CLK_PRES(val) (((val) & 0x7) << 4) 3267905540SMaxime Ripard #define TIMER_CTL_ONESHOT BIT(7) 3367905540SMaxime Ripard #define TIMER_INTVAL_LO_REG(val) (0x20 * (val) + 0x14) 3467905540SMaxime Ripard #define TIMER_INTVAL_HI_REG(val) (0x20 * (val) + 0x18) 3567905540SMaxime Ripard #define TIMER_CNTVAL_LO_REG(val) (0x20 * (val) + 0x1c) 3667905540SMaxime Ripard #define TIMER_CNTVAL_HI_REG(val) (0x20 * (val) + 0x20) 3767905540SMaxime Ripard 3867905540SMaxime Ripard #define TIMER_SYNC_TICKS 3 3967905540SMaxime Ripard 40*4a59058fSMaxime Ripard struct sun5i_timer { 41*4a59058fSMaxime Ripard void __iomem *base; 42*4a59058fSMaxime Ripard struct clk *clk; 43*4a59058fSMaxime Ripard u32 ticks_per_jiffy; 44*4a59058fSMaxime Ripard }; 45*4a59058fSMaxime Ripard 46*4a59058fSMaxime Ripard struct sun5i_timer_clksrc { 47*4a59058fSMaxime Ripard struct sun5i_timer timer; 48*4a59058fSMaxime Ripard struct clocksource clksrc; 49*4a59058fSMaxime Ripard }; 50*4a59058fSMaxime Ripard 51*4a59058fSMaxime Ripard #define to_sun5i_timer_clksrc(x) \ 52*4a59058fSMaxime Ripard container_of(x, struct sun5i_timer_clksrc, clksrc) 53*4a59058fSMaxime Ripard 54*4a59058fSMaxime Ripard struct sun5i_timer_clkevt { 55*4a59058fSMaxime Ripard struct sun5i_timer timer; 56*4a59058fSMaxime Ripard struct clock_event_device clkevt; 57*4a59058fSMaxime Ripard }; 58*4a59058fSMaxime Ripard 59*4a59058fSMaxime Ripard #define to_sun5i_timer_clkevt(x) \ 60*4a59058fSMaxime Ripard container_of(x, struct sun5i_timer_clkevt, clkevt) 6167905540SMaxime Ripard 6267905540SMaxime Ripard /* 6367905540SMaxime Ripard * When we disable a timer, we need to wait at least for 2 cycles of 6467905540SMaxime Ripard * the timer source clock. We will use for that the clocksource timer 6567905540SMaxime Ripard * that is already setup and runs at the same frequency than the other 6667905540SMaxime Ripard * timers, and we never will be disabled. 6767905540SMaxime Ripard */ 68*4a59058fSMaxime Ripard static void sun5i_clkevt_sync(struct sun5i_timer_clkevt *ce) 6967905540SMaxime Ripard { 70*4a59058fSMaxime Ripard u32 old = readl(ce->timer.base + TIMER_CNTVAL_LO_REG(1)); 7167905540SMaxime Ripard 72*4a59058fSMaxime Ripard while ((old - readl(ce->timer.base + TIMER_CNTVAL_LO_REG(1))) < TIMER_SYNC_TICKS) 7367905540SMaxime Ripard cpu_relax(); 7467905540SMaxime Ripard } 7567905540SMaxime Ripard 76*4a59058fSMaxime Ripard static void sun5i_clkevt_time_stop(struct sun5i_timer_clkevt *ce, u8 timer) 7767905540SMaxime Ripard { 78*4a59058fSMaxime Ripard u32 val = readl(ce->timer.base + TIMER_CTL_REG(timer)); 79*4a59058fSMaxime Ripard writel(val & ~TIMER_CTL_ENABLE, ce->timer.base + TIMER_CTL_REG(timer)); 8067905540SMaxime Ripard 81*4a59058fSMaxime Ripard sun5i_clkevt_sync(ce); 8267905540SMaxime Ripard } 8367905540SMaxime Ripard 84*4a59058fSMaxime Ripard static void sun5i_clkevt_time_setup(struct sun5i_timer_clkevt *ce, u8 timer, u32 delay) 8567905540SMaxime Ripard { 86*4a59058fSMaxime Ripard writel(delay, ce->timer.base + TIMER_INTVAL_LO_REG(timer)); 8767905540SMaxime Ripard } 8867905540SMaxime Ripard 89*4a59058fSMaxime Ripard static void sun5i_clkevt_time_start(struct sun5i_timer_clkevt *ce, u8 timer, bool periodic) 9067905540SMaxime Ripard { 91*4a59058fSMaxime Ripard u32 val = readl(ce->timer.base + TIMER_CTL_REG(timer)); 9267905540SMaxime Ripard 9367905540SMaxime Ripard if (periodic) 9467905540SMaxime Ripard val &= ~TIMER_CTL_ONESHOT; 9567905540SMaxime Ripard else 9667905540SMaxime Ripard val |= TIMER_CTL_ONESHOT; 9767905540SMaxime Ripard 9867905540SMaxime Ripard writel(val | TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, 99*4a59058fSMaxime Ripard ce->timer.base + TIMER_CTL_REG(timer)); 10067905540SMaxime Ripard } 10167905540SMaxime Ripard 10267905540SMaxime Ripard static void sun5i_clkevt_mode(enum clock_event_mode mode, 103*4a59058fSMaxime Ripard struct clock_event_device *clkevt) 10467905540SMaxime Ripard { 105*4a59058fSMaxime Ripard struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt); 106*4a59058fSMaxime Ripard 10767905540SMaxime Ripard switch (mode) { 10867905540SMaxime Ripard case CLOCK_EVT_MODE_PERIODIC: 109*4a59058fSMaxime Ripard sun5i_clkevt_time_stop(ce, 0); 110*4a59058fSMaxime Ripard sun5i_clkevt_time_setup(ce, 0, ce->timer.ticks_per_jiffy); 111*4a59058fSMaxime Ripard sun5i_clkevt_time_start(ce, 0, true); 11267905540SMaxime Ripard break; 11367905540SMaxime Ripard case CLOCK_EVT_MODE_ONESHOT: 114*4a59058fSMaxime Ripard sun5i_clkevt_time_stop(ce, 0); 115*4a59058fSMaxime Ripard sun5i_clkevt_time_start(ce, 0, false); 11667905540SMaxime Ripard break; 11767905540SMaxime Ripard case CLOCK_EVT_MODE_UNUSED: 11867905540SMaxime Ripard case CLOCK_EVT_MODE_SHUTDOWN: 11967905540SMaxime Ripard default: 120*4a59058fSMaxime Ripard sun5i_clkevt_time_stop(ce, 0); 12167905540SMaxime Ripard break; 12267905540SMaxime Ripard } 12367905540SMaxime Ripard } 12467905540SMaxime Ripard 12567905540SMaxime Ripard static int sun5i_clkevt_next_event(unsigned long evt, 126*4a59058fSMaxime Ripard struct clock_event_device *clkevt) 12767905540SMaxime Ripard { 128*4a59058fSMaxime Ripard struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt); 129*4a59058fSMaxime Ripard 130*4a59058fSMaxime Ripard sun5i_clkevt_time_stop(ce, 0); 131*4a59058fSMaxime Ripard sun5i_clkevt_time_setup(ce, 0, evt - TIMER_SYNC_TICKS); 132*4a59058fSMaxime Ripard sun5i_clkevt_time_start(ce, 0, false); 13367905540SMaxime Ripard 13467905540SMaxime Ripard return 0; 13567905540SMaxime Ripard } 13667905540SMaxime Ripard 13767905540SMaxime Ripard static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id) 13867905540SMaxime Ripard { 139*4a59058fSMaxime Ripard struct sun5i_timer_clkevt *ce = (struct sun5i_timer_clkevt *)dev_id; 14067905540SMaxime Ripard 141*4a59058fSMaxime Ripard writel(0x1, ce->timer.base + TIMER_IRQ_ST_REG); 142*4a59058fSMaxime Ripard ce->clkevt.event_handler(&ce->clkevt); 14367905540SMaxime Ripard 14467905540SMaxime Ripard return IRQ_HANDLED; 14567905540SMaxime Ripard } 14667905540SMaxime Ripard 147*4a59058fSMaxime Ripard static cycle_t sun5i_clksrc_read(struct clocksource *clksrc) 148*4a59058fSMaxime Ripard { 149*4a59058fSMaxime Ripard struct sun5i_timer_clksrc *cs = to_sun5i_timer_clksrc(clksrc); 150*4a59058fSMaxime Ripard 151*4a59058fSMaxime Ripard return ~readl(cs->timer.base + TIMER_CNTVAL_LO_REG(1)); 152*4a59058fSMaxime Ripard } 153*4a59058fSMaxime Ripard 154*4a59058fSMaxime Ripard static int __init sun5i_setup_clocksource(struct device_node *node, 155*4a59058fSMaxime Ripard void __iomem *base, 156*4a59058fSMaxime Ripard struct clk *clk, int irq) 157*4a59058fSMaxime Ripard { 158*4a59058fSMaxime Ripard struct sun5i_timer_clksrc *cs; 159*4a59058fSMaxime Ripard unsigned long rate; 160*4a59058fSMaxime Ripard int ret; 161*4a59058fSMaxime Ripard 162*4a59058fSMaxime Ripard cs = kzalloc(sizeof(*cs), GFP_KERNEL); 163*4a59058fSMaxime Ripard if (!cs) 164*4a59058fSMaxime Ripard return -ENOMEM; 165*4a59058fSMaxime Ripard 166*4a59058fSMaxime Ripard ret = clk_prepare_enable(clk); 167*4a59058fSMaxime Ripard if (ret) { 168*4a59058fSMaxime Ripard pr_err("Couldn't enable parent clock\n"); 169*4a59058fSMaxime Ripard goto err_free; 170*4a59058fSMaxime Ripard } 171*4a59058fSMaxime Ripard 172*4a59058fSMaxime Ripard rate = clk_get_rate(clk); 173*4a59058fSMaxime Ripard 174*4a59058fSMaxime Ripard cs->timer.base = base; 175*4a59058fSMaxime Ripard cs->timer.clk = clk; 176*4a59058fSMaxime Ripard 177*4a59058fSMaxime Ripard writel(~0, base + TIMER_INTVAL_LO_REG(1)); 178*4a59058fSMaxime Ripard writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, 179*4a59058fSMaxime Ripard base + TIMER_CTL_REG(1)); 180*4a59058fSMaxime Ripard 181*4a59058fSMaxime Ripard cs->clksrc.name = node->name; 182*4a59058fSMaxime Ripard cs->clksrc.rating = 340; 183*4a59058fSMaxime Ripard cs->clksrc.read = sun5i_clksrc_read; 184*4a59058fSMaxime Ripard cs->clksrc.mask = CLOCKSOURCE_MASK(32); 185*4a59058fSMaxime Ripard cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS; 186*4a59058fSMaxime Ripard 187*4a59058fSMaxime Ripard ret = clocksource_register_hz(&cs->clksrc, rate); 188*4a59058fSMaxime Ripard if (ret) { 189*4a59058fSMaxime Ripard pr_err("Couldn't register clock source.\n"); 190*4a59058fSMaxime Ripard goto err_disable_clk; 191*4a59058fSMaxime Ripard } 192*4a59058fSMaxime Ripard 193*4a59058fSMaxime Ripard return 0; 194*4a59058fSMaxime Ripard 195*4a59058fSMaxime Ripard err_disable_clk: 196*4a59058fSMaxime Ripard clk_disable_unprepare(clk); 197*4a59058fSMaxime Ripard err_free: 198*4a59058fSMaxime Ripard kfree(cs); 199*4a59058fSMaxime Ripard return ret; 200*4a59058fSMaxime Ripard } 201*4a59058fSMaxime Ripard 202*4a59058fSMaxime Ripard static int __init sun5i_setup_clockevent(struct device_node *node, void __iomem *base, 203*4a59058fSMaxime Ripard struct clk *clk, int irq) 204*4a59058fSMaxime Ripard { 205*4a59058fSMaxime Ripard struct sun5i_timer_clkevt *ce; 206*4a59058fSMaxime Ripard unsigned long rate; 207*4a59058fSMaxime Ripard int ret; 208*4a59058fSMaxime Ripard u32 val; 209*4a59058fSMaxime Ripard 210*4a59058fSMaxime Ripard ce = kzalloc(sizeof(*ce), GFP_KERNEL); 211*4a59058fSMaxime Ripard if (!ce) 212*4a59058fSMaxime Ripard return -ENOMEM; 213*4a59058fSMaxime Ripard 214*4a59058fSMaxime Ripard ret = clk_prepare_enable(clk); 215*4a59058fSMaxime Ripard if (ret) { 216*4a59058fSMaxime Ripard pr_err("Couldn't enable parent clock\n"); 217*4a59058fSMaxime Ripard goto err_free; 218*4a59058fSMaxime Ripard } 219*4a59058fSMaxime Ripard 220*4a59058fSMaxime Ripard rate = clk_get_rate(clk); 221*4a59058fSMaxime Ripard 222*4a59058fSMaxime Ripard ce->timer.base = base; 223*4a59058fSMaxime Ripard ce->timer.ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); 224*4a59058fSMaxime Ripard ce->timer.clk = clk; 225*4a59058fSMaxime Ripard 226*4a59058fSMaxime Ripard ce->clkevt.name = node->name; 227*4a59058fSMaxime Ripard ce->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; 228*4a59058fSMaxime Ripard ce->clkevt.set_next_event = sun5i_clkevt_next_event; 229*4a59058fSMaxime Ripard ce->clkevt.set_mode = sun5i_clkevt_mode; 230*4a59058fSMaxime Ripard ce->clkevt.rating = 340; 231*4a59058fSMaxime Ripard ce->clkevt.irq = irq; 232*4a59058fSMaxime Ripard ce->clkevt.cpumask = cpu_possible_mask; 233*4a59058fSMaxime Ripard 234*4a59058fSMaxime Ripard /* Enable timer0 interrupt */ 235*4a59058fSMaxime Ripard val = readl(base + TIMER_IRQ_EN_REG); 236*4a59058fSMaxime Ripard writel(val | TIMER_IRQ_EN(0), base + TIMER_IRQ_EN_REG); 237*4a59058fSMaxime Ripard 238*4a59058fSMaxime Ripard clockevents_config_and_register(&ce->clkevt, rate, 239*4a59058fSMaxime Ripard TIMER_SYNC_TICKS, 0xffffffff); 240*4a59058fSMaxime Ripard 241*4a59058fSMaxime Ripard ret = request_irq(irq, sun5i_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL, 242*4a59058fSMaxime Ripard "sun5i_timer0", ce); 243*4a59058fSMaxime Ripard if (ret) { 244*4a59058fSMaxime Ripard pr_err("Unable to register interrupt\n"); 245*4a59058fSMaxime Ripard goto err_disable_clk; 246*4a59058fSMaxime Ripard } 247*4a59058fSMaxime Ripard 248*4a59058fSMaxime Ripard return 0; 249*4a59058fSMaxime Ripard 250*4a59058fSMaxime Ripard err_disable_clk: 251*4a59058fSMaxime Ripard clk_disable_unprepare(clk); 252*4a59058fSMaxime Ripard err_free: 253*4a59058fSMaxime Ripard kfree(ce); 254*4a59058fSMaxime Ripard return ret; 255*4a59058fSMaxime Ripard } 256*4a59058fSMaxime Ripard 25767905540SMaxime Ripard static void __init sun5i_timer_init(struct device_node *node) 25867905540SMaxime Ripard { 259e50a00beSMaxime Ripard struct reset_control *rstc; 260*4a59058fSMaxime Ripard void __iomem *timer_base; 26167905540SMaxime Ripard struct clk *clk; 262*4a59058fSMaxime Ripard int irq; 26367905540SMaxime Ripard 264a45860d0SMaxime Ripard timer_base = of_io_request_and_map(node, 0, of_node_full_name(node)); 26567905540SMaxime Ripard if (!timer_base) 26667905540SMaxime Ripard panic("Can't map registers"); 26767905540SMaxime Ripard 26867905540SMaxime Ripard irq = irq_of_parse_and_map(node, 0); 26967905540SMaxime Ripard if (irq <= 0) 27067905540SMaxime Ripard panic("Can't parse IRQ"); 27167905540SMaxime Ripard 27267905540SMaxime Ripard clk = of_clk_get(node, 0); 27367905540SMaxime Ripard if (IS_ERR(clk)) 27467905540SMaxime Ripard panic("Can't get timer clock"); 27567905540SMaxime Ripard 276e50a00beSMaxime Ripard rstc = of_reset_control_get(node, NULL); 277e50a00beSMaxime Ripard if (!IS_ERR(rstc)) 278e50a00beSMaxime Ripard reset_control_deassert(rstc); 279e50a00beSMaxime Ripard 280*4a59058fSMaxime Ripard sun5i_setup_clocksource(node, timer_base, clk, irq); 281*4a59058fSMaxime Ripard sun5i_setup_clockevent(node, timer_base, clk, irq); 28267905540SMaxime Ripard } 28367905540SMaxime Ripard CLOCKSOURCE_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer", 28467905540SMaxime Ripard sun5i_timer_init); 28567905540SMaxime Ripard CLOCKSOURCE_OF_DECLARE(sun7i_a20, "allwinner,sun7i-a20-hstimer", 28667905540SMaxime Ripard sun5i_timer_init); 287