Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'clockevents/3.14' of git://git.linaro.org/people/daniel.lezcano/linux into timers/core

Pull clocksource/clockevent updates from Daniel Lezcano:

* Axel Lin removed an unused structure defining the ids for the
bcm kona driver.

* Ezequiel Garcia enabled the timer divider only when the 25MHz
timer is not used for the armada 370 XP.

* Jingoo Han removed a pointless platform data initialization for
the sh_mtu and sh_mtu2.

* Laurent Pinchart added the clk_prepare/clk_unprepare for sh_cmt.

* Linus Walleij added a useful warning in clk_of when no clocks
are found while the old behavior was to silently hang at boot time.

* Maxime Ripard added the high speed timer drivers for the
Allwinner SoCs (A10, A13, A20). He increased the rating, shared the
irq across all available cpus and fixed the clockevent's irq
initialization for the sun4i.

* Michael Opdenacker removed the usage of the IRQF_DISABLED for the
all the timers driver located in drivers/clocksource.

* Stephen Boyd switched to sched_clock_register for the
arm_global_timer, cadence_ttc, sun4i and orion timers.

Conflicts:
drivers/clocksource/clksrc-of.c

Signed-off-by: Ingo Molnar <mingo@kernel.org>

+295 -47
+22
Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt
··· 1 + Allwinner SoCs High Speed Timer Controller 2 + 3 + Required properties: 4 + 5 + - compatible : should be "allwinner,sun5i-a13-hstimer" or 6 + "allwinner,sun7i-a20-hstimer" 7 + - reg : Specifies base physical address and size of the registers. 8 + - interrupts : The interrupts of these timers (2 for the sun5i IP, 4 for the sun7i 9 + one) 10 + - clocks: phandle to the source clock (usually the AHB clock) 11 + 12 + Example: 13 + 14 + timer@01c60000 { 15 + compatible = "allwinner,sun7i-a20-hstimer"; 16 + reg = <0x01c60000 0x1000>; 17 + interrupts = <0 51 1>, 18 + <0 52 1>, 19 + <0 53 1>, 20 + <0 54 1>; 21 + clocks = <&ahb1_gates 19>; 22 + };
+7
arch/arm/boot/dts/sun5i-a10s.dtsi
··· 332 332 clock-frequency = <100000>; 333 333 status = "disabled"; 334 334 }; 335 + 336 + timer@01c60000 { 337 + compatible = "allwinner,sun5i-a13-hstimer"; 338 + reg = <0x01c60000 0x1000>; 339 + interrupts = <82>, <83>; 340 + clocks = <&ahb_gates 28>; 341 + }; 335 342 }; 336 343 };
+7
arch/arm/boot/dts/sun5i-a13.dtsi
··· 273 273 clock-frequency = <100000>; 274 274 status = "disabled"; 275 275 }; 276 + 277 + timer@01c60000 { 278 + compatible = "allwinner,sun5i-a13-hstimer"; 279 + reg = <0x01c60000 0x1000>; 280 + interrupts = <82>, <83>; 281 + clocks = <&ahb_gates 28>; 282 + }; 276 283 }; 277 284 };
+10
arch/arm/boot/dts/sun7i-a20.dtsi
··· 395 395 status = "disabled"; 396 396 }; 397 397 398 + hstimer@01c60000 { 399 + compatible = "allwinner,sun7i-a20-hstimer"; 400 + reg = <0x01c60000 0x1000>; 401 + interrupts = <0 81 1>, 402 + <0 82 1>, 403 + <0 83 1>, 404 + <0 84 1>; 405 + clocks = <&ahb_gates 28>; 406 + }; 407 + 398 408 gic: interrupt-controller@01c81000 { 399 409 compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic"; 400 410 reg = <0x01c81000 0x1000>,
+1
arch/arm/mach-sunxi/Kconfig
··· 12 12 select PINCTRL_SUNXI 13 13 select SPARSE_IRQ 14 14 select SUN4I_TIMER 15 + select SUN5I_HSTIMER
+4
drivers/clocksource/Kconfig
··· 37 37 select CLKSRC_MMIO 38 38 bool 39 39 40 + config SUN5I_HSTIMER 41 + select CLKSRC_MMIO 42 + bool 43 + 40 44 config VT8500_TIMER 41 45 bool 42 46
+1
drivers/clocksource/Makefile
··· 22 22 obj-$(CONFIG_ARCH_MXS) += mxs_timer.o 23 23 obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o 24 24 obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o 25 + obj-$(CONFIG_SUN5I_HSTIMER) += timer-sun5i.o 25 26 obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o 26 27 obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o 27 28 obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o
+2 -2
drivers/clocksource/arm_global_timer.c
··· 202 202 }; 203 203 204 204 #ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK 205 - static u32 notrace gt_sched_clock_read(void) 205 + static u64 notrace gt_sched_clock_read(void) 206 206 { 207 207 return gt_counter_read(); 208 208 } ··· 217 217 writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL); 218 218 219 219 #ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK 220 - setup_sched_clock(gt_sched_clock_read, 32, gt_clk_rate); 220 + sched_clock_register(gt_sched_clock_read, 64, gt_clk_rate); 221 221 #endif 222 222 clocksource_register_hz(&gt_clocksource, gt_clk_rate); 223 223 }
-6
drivers/clocksource/bcm_kona_timer.c
··· 98 98 return; 99 99 } 100 100 101 - static const struct of_device_id bcm_timer_ids[] __initconst = { 102 - {.compatible = "brcm,kona-timer"}, 103 - {.compatible = "bcm,kona-timer"}, /* deprecated name */ 104 - {}, 105 - }; 106 - 107 101 static void __init kona_timers_init(struct device_node *node) 108 102 { 109 103 u32 freq;
+3 -4
drivers/clocksource/cadence_ttc_timer.c
··· 158 158 TTC_COUNT_VAL_OFFSET); 159 159 } 160 160 161 - static u32 notrace ttc_sched_clock_read(void) 161 + static u64 notrace ttc_sched_clock_read(void) 162 162 { 163 163 return __raw_readl(ttc_sched_clock_val_reg); 164 164 } ··· 306 306 } 307 307 308 308 ttc_sched_clock_val_reg = base + TTC_COUNT_VAL_OFFSET; 309 - setup_sched_clock(ttc_sched_clock_read, 16, 309 + sched_clock_register(ttc_sched_clock_read, 16, 310 310 clk_get_rate(ttccs->ttc.clk) / PRESCALE); 311 311 } 312 312 ··· 388 388 __raw_writel(0x1, ttcce->ttc.base_addr + TTC_IER_OFFSET); 389 389 390 390 err = request_irq(irq, ttc_clock_event_interrupt, 391 - IRQF_DISABLED | IRQF_TIMER, 392 - ttcce->ce.name, ttcce); 391 + IRQF_TIMER, ttcce->ce.name, ttcce); 393 392 if (WARN_ON(err)) { 394 393 kfree(ttcce); 395 394 return;
+4
drivers/clocksource/clksrc-of.c
··· 28 28 struct device_node *np; 29 29 const struct of_device_id *match; 30 30 clocksource_of_init_fn init_func; 31 + unsigned clocksources = 0; 31 32 32 33 for_each_matching_node_and_match(np, __clksrc_of_table, &match) { 33 34 if (!of_device_is_available(np)) ··· 36 35 37 36 init_func = match->data; 38 37 init_func(np); 38 + clocksources++; 39 39 } 40 + if (!clocksources) 41 + pr_crit("%s: no matching clocksources found\n", __func__); 40 42 }
+1 -1
drivers/clocksource/cs5535-clockevt.c
··· 131 131 132 132 static struct irqaction mfgptirq = { 133 133 .handler = mfgpt_tick, 134 - .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER | IRQF_SHARED, 134 + .flags = IRQF_NOBALANCING | IRQF_TIMER | IRQF_SHARED, 135 135 .name = DRV_NAME, 136 136 }; 137 137
+1 -2
drivers/clocksource/dw_apb_timer.c
··· 243 243 dw_ced->irqaction.dev_id = &dw_ced->ced; 244 244 dw_ced->irqaction.irq = irq; 245 245 dw_ced->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | 246 - IRQF_NOBALANCING | 247 - IRQF_DISABLED; 246 + IRQF_NOBALANCING; 248 247 249 248 dw_ced->eoi = apbt_eoi; 250 249 err = setup_irq(irq, &dw_ced->irqaction);
+1 -1
drivers/clocksource/nomadik-mtu.c
··· 187 187 188 188 static struct irqaction nmdk_timer_irq = { 189 189 .name = "Nomadik Timer Tick", 190 - .flags = IRQF_DISABLED | IRQF_TIMER, 190 + .flags = IRQF_TIMER, 191 191 .handler = nmdk_timer_interrupt, 192 192 .dev_id = &nmdk_clkevt, 193 193 };
+1 -1
drivers/clocksource/samsung_pwm_timer.c
··· 264 264 265 265 static struct irqaction samsung_clock_event_irq = { 266 266 .name = "samsung_time_irq", 267 - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, 267 + .flags = IRQF_TIMER | IRQF_IRQPOLL, 268 268 .handler = samsung_clock_event_isr, 269 269 .dev_id = &time_event_device, 270 270 };
+17 -6
drivers/clocksource/sh_cmt.c
··· 634 634 635 635 static void sh_cmt_clock_event_suspend(struct clock_event_device *ced) 636 636 { 637 - pm_genpd_syscore_poweroff(&ced_to_sh_cmt(ced)->pdev->dev); 637 + struct sh_cmt_priv *p = ced_to_sh_cmt(ced); 638 + 639 + pm_genpd_syscore_poweroff(&p->pdev->dev); 640 + clk_unprepare(p->clk); 638 641 } 639 642 640 643 static void sh_cmt_clock_event_resume(struct clock_event_device *ced) 641 644 { 642 - pm_genpd_syscore_poweron(&ced_to_sh_cmt(ced)->pdev->dev); 645 + struct sh_cmt_priv *p = ced_to_sh_cmt(ced); 646 + 647 + clk_prepare(p->clk); 648 + pm_genpd_syscore_poweron(&p->pdev->dev); 643 649 } 644 650 645 651 static void sh_cmt_register_clockevent(struct sh_cmt_priv *p, ··· 732 726 p->irqaction.name = dev_name(&p->pdev->dev); 733 727 p->irqaction.handler = sh_cmt_interrupt; 734 728 p->irqaction.dev_id = p; 735 - p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \ 736 - IRQF_IRQPOLL | IRQF_NOBALANCING; 729 + p->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING; 737 730 738 731 /* get hold of clock */ 739 732 p->clk = clk_get(&p->pdev->dev, "cmt_fck"); ··· 741 736 ret = PTR_ERR(p->clk); 742 737 goto err2; 743 738 } 739 + 740 + ret = clk_prepare(p->clk); 741 + if (ret < 0) 742 + goto err3; 744 743 745 744 if (res2 && (resource_size(res2) == 4)) { 746 745 /* assume both CMSTR and CMCSR to be 32-bit */ ··· 782 773 cfg->clocksource_rating); 783 774 if (ret) { 784 775 dev_err(&p->pdev->dev, "registration failed\n"); 785 - goto err3; 776 + goto err4; 786 777 } 787 778 p->cs_enabled = false; 788 779 789 780 ret = setup_irq(irq, &p->irqaction); 790 781 if (ret) { 791 782 dev_err(&p->pdev->dev, "failed to request irq %d\n", irq); 792 - goto err3; 783 + goto err4; 793 784 } 794 785 795 786 platform_set_drvdata(pdev, p); 796 787 797 788 return 0; 789 + err4: 790 + clk_unprepare(p->clk); 798 791 err3: 799 792 clk_put(p->clk); 800 793 err2:
+1 -3
drivers/clocksource/sh_mtu2.c
··· 302 302 p->irqaction.handler = sh_mtu2_interrupt; 303 303 p->irqaction.dev_id = p; 304 304 p->irqaction.irq = irq; 305 - p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \ 306 - IRQF_IRQPOLL | IRQF_NOBALANCING; 305 + p->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING; 307 306 308 307 /* get hold of clock */ 309 308 p->clk = clk_get(&p->pdev->dev, "mtu2_fck"); ··· 357 358 ret = sh_mtu2_setup(p, pdev); 358 359 if (ret) { 359 360 kfree(p); 360 - platform_set_drvdata(pdev, NULL); 361 361 pm_runtime_idle(&pdev->dev); 362 362 return ret; 363 363 }
+1 -3
drivers/clocksource/sh_tmu.c
··· 462 462 p->irqaction.handler = sh_tmu_interrupt; 463 463 p->irqaction.dev_id = p; 464 464 p->irqaction.irq = irq; 465 - p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \ 466 - IRQF_IRQPOLL | IRQF_NOBALANCING; 465 + p->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING; 467 466 468 467 /* get hold of clock */ 469 468 p->clk = clk_get(&p->pdev->dev, "tmu_fck"); ··· 522 523 ret = sh_tmu_setup(p, pdev); 523 524 if (ret) { 524 525 kfree(p); 525 - platform_set_drvdata(pdev, NULL); 526 526 pm_runtime_idle(&pdev->dev); 527 527 return ret; 528 528 }
+6 -5
drivers/clocksource/sun4i_timer.c
··· 114 114 115 115 static struct clock_event_device sun4i_clockevent = { 116 116 .name = "sun4i_tick", 117 - .rating = 300, 117 + .rating = 350, 118 118 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, 119 119 .set_mode = sun4i_clkevt_mode, 120 120 .set_next_event = sun4i_clkevt_next_event, ··· 138 138 .dev_id = &sun4i_clockevent, 139 139 }; 140 140 141 - static u32 sun4i_timer_sched_read(void) 141 + static u64 notrace sun4i_timer_sched_read(void) 142 142 { 143 143 return ~readl(timer_base + TIMER_CNTVAL_REG(1)); 144 144 } ··· 170 170 TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M), 171 171 timer_base + TIMER_CTL_REG(1)); 172 172 173 - setup_sched_clock(sun4i_timer_sched_read, 32, rate); 173 + sched_clock_register(sun4i_timer_sched_read, 32, rate); 174 174 clocksource_mmio_init(timer_base + TIMER_CNTVAL_REG(1), node->name, 175 - rate, 300, 32, clocksource_mmio_readl_down); 175 + rate, 350, 32, clocksource_mmio_readl_down); 176 176 177 177 ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); 178 178 ··· 190 190 val = readl(timer_base + TIMER_IRQ_EN_REG); 191 191 writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG); 192 192 193 - sun4i_clockevent.cpumask = cpumask_of(0); 193 + sun4i_clockevent.cpumask = cpu_possible_mask; 194 + sun4i_clockevent.irq = irq; 194 195 195 196 clockevents_config_and_register(&sun4i_clockevent, rate, 196 197 TIMER_SYNC_TICKS, 0xffffffff);
+1 -1
drivers/clocksource/tegra20_timer.c
··· 149 149 150 150 static struct irqaction tegra_timer_irq = { 151 151 .name = "timer0", 152 - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_HIGH, 152 + .flags = IRQF_TIMER | IRQF_TRIGGER_HIGH, 153 153 .handler = tegra_timer_interrupt, 154 154 .dev_id = &tegra_clockevent, 155 155 };
+9 -9
drivers/clocksource/time-armada-370-xp.c
··· 76 76 static void __iomem *timer_base, *local_base; 77 77 static unsigned int timer_clk; 78 78 static bool timer25Mhz = true; 79 + static u32 enable_mask; 79 80 80 81 /* 81 82 * Number of timer ticks per jiffy. ··· 122 121 /* 123 122 * Enable the timer. 124 123 */ 125 - local_timer_ctrl_clrset(TIMER0_RELOAD_EN, 126 - TIMER0_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT)); 124 + local_timer_ctrl_clrset(TIMER0_RELOAD_EN, enable_mask); 127 125 return 0; 128 126 } 129 127 ··· 141 141 /* 142 142 * Enable timer. 143 143 */ 144 - local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | 145 - TIMER0_EN | 146 - TIMER0_DIV(TIMER_DIVIDER_SHIFT)); 144 + local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask); 147 145 } else { 148 146 /* 149 147 * Disable timer. ··· 238 240 WARN_ON(!timer_base); 239 241 local_base = of_iomap(np, 1); 240 242 241 - if (timer25Mhz) 243 + if (timer25Mhz) { 242 244 set = TIMER0_25MHZ; 243 - else 245 + enable_mask = TIMER0_EN; 246 + } else { 244 247 clr = TIMER0_25MHZ; 248 + enable_mask = TIMER0_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT); 249 + } 245 250 timer_ctrl_clrset(clr, set); 246 251 local_timer_ctrl_clrset(clr, set); 247 252 ··· 263 262 writel(0xffffffff, timer_base + TIMER0_VAL_OFF); 264 263 writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF); 265 264 266 - timer_ctrl_clrset(0, TIMER0_EN | TIMER0_RELOAD_EN | 267 - TIMER0_DIV(TIMER_DIVIDER_SHIFT)); 265 + timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask); 268 266 269 267 /* 270 268 * Set scale and timer for sched_clock.
+2 -2
drivers/clocksource/time-orion.c
··· 53 53 /* 54 54 * Free-running clocksource handling. 55 55 */ 56 - static u32 notrace orion_read_sched_clock(void) 56 + static u64 notrace orion_read_sched_clock(void) 57 57 { 58 58 return ~readl(timer_base + TIMER0_VAL); 59 59 } ··· 135 135 clocksource_mmio_init(timer_base + TIMER0_VAL, "orion_clocksource", 136 136 clk_get_rate(clk), 300, 32, 137 137 clocksource_mmio_readl_down); 138 - setup_sched_clock(orion_read_sched_clock, 32, clk_get_rate(clk)); 138 + sched_clock_register(orion_read_sched_clock, 32, clk_get_rate(clk)); 139 139 140 140 /* setup timer1 as clockevent timer */ 141 141 if (setup_irq(irq, &orion_clkevt_irq))
+192
drivers/clocksource/timer-sun5i.c
··· 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/sched_clock.h> 20 + #include <linux/of.h> 21 + #include <linux/of_address.h> 22 + #include <linux/of_irq.h> 23 + 24 + #define TIMER_IRQ_EN_REG 0x00 25 + #define TIMER_IRQ_EN(val) BIT(val) 26 + #define TIMER_IRQ_ST_REG 0x04 27 + #define TIMER_CTL_REG(val) (0x20 * (val) + 0x10) 28 + #define TIMER_CTL_ENABLE BIT(0) 29 + #define TIMER_CTL_RELOAD BIT(1) 30 + #define TIMER_CTL_CLK_PRES(val) (((val) & 0x7) << 4) 31 + #define TIMER_CTL_ONESHOT BIT(7) 32 + #define TIMER_INTVAL_LO_REG(val) (0x20 * (val) + 0x14) 33 + #define TIMER_INTVAL_HI_REG(val) (0x20 * (val) + 0x18) 34 + #define TIMER_CNTVAL_LO_REG(val) (0x20 * (val) + 0x1c) 35 + #define TIMER_CNTVAL_HI_REG(val) (0x20 * (val) + 0x20) 36 + 37 + #define TIMER_SYNC_TICKS 3 38 + 39 + static void __iomem *timer_base; 40 + static u32 ticks_per_jiffy; 41 + 42 + /* 43 + * When we disable a timer, we need to wait at least for 2 cycles of 44 + * the timer source clock. We will use for that the clocksource timer 45 + * that is already setup and runs at the same frequency than the other 46 + * timers, and we never will be disabled. 47 + */ 48 + static void sun5i_clkevt_sync(void) 49 + { 50 + u32 old = readl(timer_base + TIMER_CNTVAL_LO_REG(1)); 51 + 52 + while ((old - readl(timer_base + TIMER_CNTVAL_LO_REG(1))) < TIMER_SYNC_TICKS) 53 + cpu_relax(); 54 + } 55 + 56 + static void sun5i_clkevt_time_stop(u8 timer) 57 + { 58 + u32 val = readl(timer_base + TIMER_CTL_REG(timer)); 59 + writel(val & ~TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(timer)); 60 + 61 + sun5i_clkevt_sync(); 62 + } 63 + 64 + static void sun5i_clkevt_time_setup(u8 timer, u32 delay) 65 + { 66 + writel(delay, timer_base + TIMER_INTVAL_LO_REG(timer)); 67 + } 68 + 69 + static void sun5i_clkevt_time_start(u8 timer, bool periodic) 70 + { 71 + u32 val = readl(timer_base + TIMER_CTL_REG(timer)); 72 + 73 + if (periodic) 74 + val &= ~TIMER_CTL_ONESHOT; 75 + else 76 + val |= TIMER_CTL_ONESHOT; 77 + 78 + writel(val | TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, 79 + timer_base + TIMER_CTL_REG(timer)); 80 + } 81 + 82 + static void sun5i_clkevt_mode(enum clock_event_mode mode, 83 + struct clock_event_device *clk) 84 + { 85 + switch (mode) { 86 + case CLOCK_EVT_MODE_PERIODIC: 87 + sun5i_clkevt_time_stop(0); 88 + sun5i_clkevt_time_setup(0, ticks_per_jiffy); 89 + sun5i_clkevt_time_start(0, true); 90 + break; 91 + case CLOCK_EVT_MODE_ONESHOT: 92 + sun5i_clkevt_time_stop(0); 93 + sun5i_clkevt_time_start(0, false); 94 + break; 95 + case CLOCK_EVT_MODE_UNUSED: 96 + case CLOCK_EVT_MODE_SHUTDOWN: 97 + default: 98 + sun5i_clkevt_time_stop(0); 99 + break; 100 + } 101 + } 102 + 103 + static int sun5i_clkevt_next_event(unsigned long evt, 104 + struct clock_event_device *unused) 105 + { 106 + sun5i_clkevt_time_stop(0); 107 + sun5i_clkevt_time_setup(0, evt - TIMER_SYNC_TICKS); 108 + sun5i_clkevt_time_start(0, false); 109 + 110 + return 0; 111 + } 112 + 113 + static struct clock_event_device sun5i_clockevent = { 114 + .name = "sun5i_tick", 115 + .rating = 340, 116 + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, 117 + .set_mode = sun5i_clkevt_mode, 118 + .set_next_event = sun5i_clkevt_next_event, 119 + }; 120 + 121 + 122 + static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id) 123 + { 124 + struct clock_event_device *evt = (struct clock_event_device *)dev_id; 125 + 126 + writel(0x1, timer_base + TIMER_IRQ_ST_REG); 127 + evt->event_handler(evt); 128 + 129 + return IRQ_HANDLED; 130 + } 131 + 132 + static struct irqaction sun5i_timer_irq = { 133 + .name = "sun5i_timer0", 134 + .flags = IRQF_TIMER | IRQF_IRQPOLL, 135 + .handler = sun5i_timer_interrupt, 136 + .dev_id = &sun5i_clockevent, 137 + }; 138 + 139 + static u32 sun5i_timer_sched_read(void) 140 + { 141 + return ~readl(timer_base + TIMER_CNTVAL_LO_REG(1)); 142 + } 143 + 144 + static void __init sun5i_timer_init(struct device_node *node) 145 + { 146 + unsigned long rate; 147 + struct clk *clk; 148 + int ret, irq; 149 + u32 val; 150 + 151 + timer_base = of_iomap(node, 0); 152 + if (!timer_base) 153 + panic("Can't map registers"); 154 + 155 + irq = irq_of_parse_and_map(node, 0); 156 + if (irq <= 0) 157 + panic("Can't parse IRQ"); 158 + 159 + clk = of_clk_get(node, 0); 160 + if (IS_ERR(clk)) 161 + panic("Can't get timer clock"); 162 + clk_prepare_enable(clk); 163 + rate = clk_get_rate(clk); 164 + 165 + writel(~0, timer_base + TIMER_INTVAL_LO_REG(1)); 166 + writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, 167 + timer_base + TIMER_CTL_REG(1)); 168 + 169 + setup_sched_clock(sun5i_timer_sched_read, 32, rate); 170 + clocksource_mmio_init(timer_base + TIMER_CNTVAL_LO_REG(1), node->name, 171 + rate, 340, 32, clocksource_mmio_readl_down); 172 + 173 + ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); 174 + 175 + ret = setup_irq(irq, &sun5i_timer_irq); 176 + if (ret) 177 + pr_warn("failed to setup irq %d\n", irq); 178 + 179 + /* Enable timer0 interrupt */ 180 + val = readl(timer_base + TIMER_IRQ_EN_REG); 181 + writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG); 182 + 183 + sun5i_clockevent.cpumask = cpu_possible_mask; 184 + sun5i_clockevent.irq = irq; 185 + 186 + clockevents_config_and_register(&sun5i_clockevent, rate, 187 + TIMER_SYNC_TICKS, 0xffffffff); 188 + } 189 + CLOCKSOURCE_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer", 190 + sun5i_timer_init); 191 + CLOCKSOURCE_OF_DECLARE(sun7i_a20, "allwinner,sun7i-a20-hstimer", 192 + sun5i_timer_init);
+1 -1
drivers/clocksource/vt8500_timer.c
··· 124 124 125 125 static struct irqaction irq = { 126 126 .name = "vt8500_timer", 127 - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, 127 + .flags = IRQF_TIMER | IRQF_IRQPOLL, 128 128 .handler = vt8500_timer_interrupt, 129 129 .dev_id = &clockevent, 130 130 };