blob: 14b7a2b9993356f73f20f6c1eb577579f1c195c8 [file] [log] [blame]
Maxime Coqueline37e4592015-05-22 23:03:33 +02001/*
2 * Copyright (C) Maxime Coquelin 2015
3 * Author: Maxime Coquelin <mcoquelin.stm32@gmail.com>
4 * License terms: GNU General Public License (GPL), version 2
5 *
6 * Inspired by time-efm32.c from Uwe Kleine-Koenig
7 */
8
9#include <linux/kernel.h>
10#include <linux/clocksource.h>
11#include <linux/clockchips.h>
12#include <linux/irq.h>
13#include <linux/interrupt.h>
14#include <linux/of.h>
15#include <linux/of_address.h>
16#include <linux/of_irq.h>
17#include <linux/clk.h>
18#include <linux/reset.h>
Benjamin Gaignardd04af492018-01-08 14:28:51 +010019#include <linux/slab.h>
20
21#include "timer-of.h"
Maxime Coqueline37e4592015-05-22 23:03:33 +020022
23#define TIM_CR1 0x00
24#define TIM_DIER 0x0c
25#define TIM_SR 0x10
26#define TIM_EGR 0x14
27#define TIM_PSC 0x28
28#define TIM_ARR 0x2c
29
30#define TIM_CR1_CEN BIT(0)
31#define TIM_CR1_OPM BIT(3)
32#define TIM_CR1_ARPE BIT(7)
33
34#define TIM_DIER_UIE BIT(0)
35
36#define TIM_SR_UIF BIT(0)
37
38#define TIM_EGR_UG BIT(0)
39
Benjamin Gaignardd04af492018-01-08 14:28:51 +010040static int stm32_clock_event_shutdown(struct clock_event_device *clkevt)
Maxime Coqueline37e4592015-05-22 23:03:33 +020041{
Benjamin Gaignardd04af492018-01-08 14:28:51 +010042 struct timer_of *to = to_timer_of(clkevt);
Maxime Coqueline37e4592015-05-22 23:03:33 +020043
Benjamin Gaignardd04af492018-01-08 14:28:51 +010044 writel_relaxed(0, timer_of_base(to) + TIM_CR1);
45
Viresh Kumar8e8af4c2015-06-18 16:24:50 +053046 return 0;
47}
Maxime Coqueline37e4592015-05-22 23:03:33 +020048
Benjamin Gaignardd04af492018-01-08 14:28:51 +010049static int stm32_clock_event_set_periodic(struct clock_event_device *clkevt)
Viresh Kumar8e8af4c2015-06-18 16:24:50 +053050{
Benjamin Gaignardd04af492018-01-08 14:28:51 +010051 struct timer_of *to = to_timer_of(clkevt);
Viresh Kumar8e8af4c2015-06-18 16:24:50 +053052
Benjamin Gaignardd04af492018-01-08 14:28:51 +010053 writel_relaxed(timer_of_period(to), timer_of_base(to) + TIM_ARR);
54 writel_relaxed(TIM_CR1_ARPE | TIM_CR1_CEN, timer_of_base(to) + TIM_CR1);
55
Viresh Kumar8e8af4c2015-06-18 16:24:50 +053056 return 0;
Maxime Coqueline37e4592015-05-22 23:03:33 +020057}
58
59static int stm32_clock_event_set_next_event(unsigned long evt,
Benjamin Gaignardd04af492018-01-08 14:28:51 +010060 struct clock_event_device *clkevt)
Maxime Coqueline37e4592015-05-22 23:03:33 +020061{
Benjamin Gaignardd04af492018-01-08 14:28:51 +010062 struct timer_of *to = to_timer_of(clkevt);
Maxime Coqueline37e4592015-05-22 23:03:33 +020063
Benjamin Gaignardd04af492018-01-08 14:28:51 +010064 writel_relaxed(evt, timer_of_base(to) + TIM_ARR);
Maxime Coqueline37e4592015-05-22 23:03:33 +020065 writel_relaxed(TIM_CR1_ARPE | TIM_CR1_OPM | TIM_CR1_CEN,
Benjamin Gaignardd04af492018-01-08 14:28:51 +010066 timer_of_base(to) + TIM_CR1);
Maxime Coqueline37e4592015-05-22 23:03:33 +020067
68 return 0;
69}
70
71static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
72{
Benjamin Gaignardd04af492018-01-08 14:28:51 +010073 struct clock_event_device *clkevt = (struct clock_event_device *)dev_id;
74 struct timer_of *to = to_timer_of(clkevt);
Maxime Coqueline37e4592015-05-22 23:03:33 +020075
Benjamin Gaignardd04af492018-01-08 14:28:51 +010076 writel_relaxed(0, timer_of_base(to) + TIM_SR);
Maxime Coqueline37e4592015-05-22 23:03:33 +020077
Benjamin Gaignardd04af492018-01-08 14:28:51 +010078 clkevt->event_handler(clkevt);
Maxime Coqueline37e4592015-05-22 23:03:33 +020079
80 return IRQ_HANDLED;
81}
82
Benjamin Gaignardd04af492018-01-08 14:28:51 +010083static void __init stm32_clockevent_init(struct timer_of *to)
Maxime Coqueline37e4592015-05-22 23:03:33 +020084{
Benjamin Gaignardd04af492018-01-08 14:28:51 +010085 unsigned long max_delta;
86 int prescaler;
Maxime Coqueline37e4592015-05-22 23:03:33 +020087
Daniel Lezcanof2ed8ef2018-01-08 14:28:52 +010088 to->clkevt.name = to->np->full_name;
Benjamin Gaignardd04af492018-01-08 14:28:51 +010089 to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
90 to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
91 to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
92 to->clkevt.set_state_oneshot = stm32_clock_event_shutdown;
93 to->clkevt.tick_resume = stm32_clock_event_shutdown;
94 to->clkevt.set_next_event = stm32_clock_event_set_next_event;
95
96 /* Detect whether the timer is 16 or 32 bits */
97 writel_relaxed(~0U, timer_of_base(to) + TIM_ARR);
98 max_delta = readl_relaxed(timer_of_base(to) + TIM_ARR);
99 if (max_delta == ~0U) {
100 prescaler = 1;
101 to->clkevt.rating = 250;
102 } else {
103 prescaler = 1024;
104 to->clkevt.rating = 100;
105 }
106 writel_relaxed(0, timer_of_base(to) + TIM_ARR);
107
108 writel_relaxed(prescaler - 1, timer_of_base(to) + TIM_PSC);
109 writel_relaxed(TIM_EGR_UG, timer_of_base(to) + TIM_EGR);
110 writel_relaxed(0, timer_of_base(to) + TIM_SR);
111 writel_relaxed(TIM_DIER_UIE, timer_of_base(to) + TIM_DIER);
112
113 /* Adjust rate and period given the prescaler value */
114 to->of_clk.rate = DIV_ROUND_CLOSEST(to->of_clk.rate, prescaler);
115 to->of_clk.period = DIV_ROUND_UP(to->of_clk.rate, HZ);
116
117 clockevents_config_and_register(&to->clkevt,
118 timer_of_rate(to), 0x1, max_delta);
119
120 pr_info("%pOF: STM32 clockevent driver initialized (%d bits)\n",
121 to->np, max_delta == UINT_MAX ? 32 : 16);
122}
123
124static int __init stm32_timer_init(struct device_node *node)
125{
126 struct reset_control *rstc;
127 struct timer_of *to;
128 int ret;
129
130 to = kzalloc(sizeof(*to), GFP_KERNEL);
131 if (!to)
Daniel Lezcanoe0aeca32018-01-08 14:28:50 +0100132 return -ENOMEM;
133
Benjamin Gaignardd04af492018-01-08 14:28:51 +0100134 to->flags = TIMER_OF_IRQ | TIMER_OF_CLOCK | TIMER_OF_BASE;
135 to->of_irq.handler = stm32_clock_event_handler;
Maxime Coqueline37e4592015-05-22 23:03:33 +0200136
Benjamin Gaignardd04af492018-01-08 14:28:51 +0100137 ret = timer_of_init(node, to);
138 if (ret)
139 goto err;
Maxime Coqueline37e4592015-05-22 23:03:33 +0200140
Benjamin Gaignardd04af492018-01-08 14:28:51 +0100141 rstc = of_reset_control_get(node, NULL);
Maxime Coqueline37e4592015-05-22 23:03:33 +0200142 if (!IS_ERR(rstc)) {
143 reset_control_assert(rstc);
144 reset_control_deassert(rstc);
145 }
146
Benjamin Gaignardd04af492018-01-08 14:28:51 +0100147 stm32_clockevent_init(to);
148 return 0;
149err:
150 kfree(to);
Daniel Lezcano38d94c52016-06-06 23:28:17 +0200151 return ret;
Maxime Coqueline37e4592015-05-22 23:03:33 +0200152}
153
Benjamin Gaignardd04af492018-01-08 14:28:51 +0100154TIMER_OF_DECLARE(stm32, "st,stm32-timer", stm32_timer_init);