diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2015-10-20 06:37:45 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2015-10-20 06:37:45 -0400 |
commit | 3bc2159faf897bab51e4f1144b525d21823832a6 (patch) | |
tree | 97e28296005957f4ae15b83ae0d5998ebb9f4dcf /drivers/clocksource/mtk_timer.c | |
parent | b2c280bdd6ea31be66c9b6a666e71daa49beef75 (diff) | |
parent | cb0f2538039c65f2bb64a9d427dbe9dd7d0f71a6 (diff) |
Merge branch 'clockevents/4.4' of http://git.linaro.org/people/daniel.lezcano/linux into timers/core
clockevent updates from Daniel Lezcano:
- Remove unneeded memset in em_sti, sh_cmt and h8300 because there are already
zeroed by a kzalloc (Alexey Klimov)
- Optimize code by replacing this_cpu_ptr by container_of on the exynos_mct (Alexey
Klimov)
- Get immune from a spurious interrupt when enabling the mtk_timer (Daniel Lezcano)
- Use the dynamic irq affinity to optimize wakeup and useless IPI timer on the imx
timer (Lucas Stach)
- Add new timer for Tango SoCs (Marc Gonzalez)
- Implement the timer delay for armada-370-xp (Russell King)
- Use GPT as clock source (Yingjoe Chen)
Diffstat (limited to 'drivers/clocksource/mtk_timer.c')
-rw-r--r-- | drivers/clocksource/mtk_timer.c | 26 |
1 files changed, 16 insertions, 10 deletions
diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c index 50f0641c65b6..fbfc74685e6a 100644 --- a/drivers/clocksource/mtk_timer.c +++ b/drivers/clocksource/mtk_timer.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/of.h> | 24 | #include <linux/of.h> |
25 | #include <linux/of_address.h> | 25 | #include <linux/of_address.h> |
26 | #include <linux/of_irq.h> | 26 | #include <linux/of_irq.h> |
27 | #include <linux/sched_clock.h> | ||
27 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
28 | 29 | ||
29 | #define GPT_IRQ_EN_REG 0x00 | 30 | #define GPT_IRQ_EN_REG 0x00 |
@@ -59,6 +60,13 @@ struct mtk_clock_event_device { | |||
59 | struct clock_event_device dev; | 60 | struct clock_event_device dev; |
60 | }; | 61 | }; |
61 | 62 | ||
63 | static void __iomem *gpt_sched_reg __read_mostly; | ||
64 | |||
65 | static u64 notrace mtk_read_sched_clock(void) | ||
66 | { | ||
67 | return readl_relaxed(gpt_sched_reg); | ||
68 | } | ||
69 | |||
62 | static inline struct mtk_clock_event_device *to_mtk_clk( | 70 | static inline struct mtk_clock_event_device *to_mtk_clk( |
63 | struct clock_event_device *c) | 71 | struct clock_event_device *c) |
64 | { | 72 | { |
@@ -141,14 +149,6 @@ static irqreturn_t mtk_timer_interrupt(int irq, void *dev_id) | |||
141 | return IRQ_HANDLED; | 149 | return IRQ_HANDLED; |
142 | } | 150 | } |
143 | 151 | ||
144 | static void mtk_timer_global_reset(struct mtk_clock_event_device *evt) | ||
145 | { | ||
146 | /* Disable all interrupts */ | ||
147 | writel(0x0, evt->gpt_base + GPT_IRQ_EN_REG); | ||
148 | /* Acknowledge all interrupts */ | ||
149 | writel(0x3f, evt->gpt_base + GPT_IRQ_ACK_REG); | ||
150 | } | ||
151 | |||
152 | static void | 152 | static void |
153 | mtk_timer_setup(struct mtk_clock_event_device *evt, u8 timer, u8 option) | 153 | mtk_timer_setup(struct mtk_clock_event_device *evt, u8 timer, u8 option) |
154 | { | 154 | { |
@@ -168,6 +168,12 @@ static void mtk_timer_enable_irq(struct mtk_clock_event_device *evt, u8 timer) | |||
168 | { | 168 | { |
169 | u32 val; | 169 | u32 val; |
170 | 170 | ||
171 | /* Disable all interrupts */ | ||
172 | writel(0x0, evt->gpt_base + GPT_IRQ_EN_REG); | ||
173 | |||
174 | /* Acknowledge all spurious pending interrupts */ | ||
175 | writel(0x3f, evt->gpt_base + GPT_IRQ_ACK_REG); | ||
176 | |||
171 | val = readl(evt->gpt_base + GPT_IRQ_EN_REG); | 177 | val = readl(evt->gpt_base + GPT_IRQ_EN_REG); |
172 | writel(val | GPT_IRQ_ENABLE(timer), | 178 | writel(val | GPT_IRQ_ENABLE(timer), |
173 | evt->gpt_base + GPT_IRQ_EN_REG); | 179 | evt->gpt_base + GPT_IRQ_EN_REG); |
@@ -220,8 +226,6 @@ static void __init mtk_timer_init(struct device_node *node) | |||
220 | } | 226 | } |
221 | rate = clk_get_rate(clk); | 227 | rate = clk_get_rate(clk); |
222 | 228 | ||
223 | mtk_timer_global_reset(evt); | ||
224 | |||
225 | if (request_irq(evt->dev.irq, mtk_timer_interrupt, | 229 | if (request_irq(evt->dev.irq, mtk_timer_interrupt, |
226 | IRQF_TIMER | IRQF_IRQPOLL, "mtk_timer", evt)) { | 230 | IRQF_TIMER | IRQF_IRQPOLL, "mtk_timer", evt)) { |
227 | pr_warn("failed to setup irq %d\n", evt->dev.irq); | 231 | pr_warn("failed to setup irq %d\n", evt->dev.irq); |
@@ -234,6 +238,8 @@ static void __init mtk_timer_init(struct device_node *node) | |||
234 | mtk_timer_setup(evt, GPT_CLK_SRC, TIMER_CTRL_OP_FREERUN); | 238 | mtk_timer_setup(evt, GPT_CLK_SRC, TIMER_CTRL_OP_FREERUN); |
235 | clocksource_mmio_init(evt->gpt_base + TIMER_CNT_REG(GPT_CLK_SRC), | 239 | clocksource_mmio_init(evt->gpt_base + TIMER_CNT_REG(GPT_CLK_SRC), |
236 | node->name, rate, 300, 32, clocksource_mmio_readl_up); | 240 | node->name, rate, 300, 32, clocksource_mmio_readl_up); |
241 | gpt_sched_reg = evt->gpt_base + TIMER_CNT_REG(GPT_CLK_SRC); | ||
242 | sched_clock_register(mtk_read_sched_clock, 32, rate); | ||
237 | 243 | ||
238 | /* Configure clock event */ | 244 | /* Configure clock event */ |
239 | mtk_timer_setup(evt, GPT_CLK_EVT, TIMER_CTRL_OP_REPEAT); | 245 | mtk_timer_setup(evt, GPT_CLK_EVT, TIMER_CTRL_OP_REPEAT); |