aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource/timer-stm32.c
diff options
context:
space:
mode:
authorDaniel Lezcano <daniel.lezcano@linaro.org>2018-01-08 08:28:56 -0500
committerIngo Molnar <mingo@kernel.org>2018-01-08 11:57:26 -0500
commit3c84e75b1e5d8406e12b533d44f54ad84d6e3bd6 (patch)
treea94052febd2eb77cd8295716433d5275165a7f52 /drivers/clocksource/timer-stm32.c
parent8e82df381b676ae5f6c93ab4a75f56d8f61babc4 (diff)
clocksource/drivers/stm32: Factor out more of the clockevent code
In order to prepare the clocksource code, let's factor out the clockevent code, split the prescaler and timer width code into separate functions. Tested-by: Benjamin Gaignard <benjamin.gaignard@st.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Benjamin Gaignard <benjamin.gaignard@st.com> Cc: Alexandre Torgue <alexandre.torgue@st.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Maxime Coquelin <mcoquelin.stm32@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/1515418139-23276-17-git-send-email-daniel.lezcano@linaro.org [ Small edits. ] Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'drivers/clocksource/timer-stm32.c')
-rw-r--r--drivers/clocksource/timer-stm32.c107
1 files changed, 82 insertions, 25 deletions
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 882037f1d8d6..0d37f1a1994e 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -44,6 +44,42 @@
44#define TIM_PSC_MAX USHRT_MAX 44#define TIM_PSC_MAX USHRT_MAX
45#define TIM_PSC_CLKRATE 10000 45#define TIM_PSC_CLKRATE 10000
46 46
47struct stm32_timer_private {
48 int bits;
49};
50
51/**
52 * stm32_timer_of_bits_set - set accessor helper
53 * @to: a timer_of structure pointer
54 * @bits: the number of bits (16 or 32)
55 *
56 * Accessor helper to set the number of bits in the timer-of private
57 * structure.
58 *
59 */
60static void stm32_timer_of_bits_set(struct timer_of *to, int bits)
61{
62 struct stm32_timer_private *pd = to->private_data;
63
64 pd->bits = bits;
65}
66
67/**
68 * stm32_timer_of_bits_get - get accessor helper
69 * @to: a timer_of structure pointer
70 *
71 * Accessor helper to get the number of bits in the timer-of private
72 * structure.
73 *
74 * Returns an integer corresponding to the number of bits.
75 */
76static int stm32_timer_of_bits_get(struct timer_of *to)
77{
78 struct stm32_timer_private *pd = to->private_data;
79
80 return pd->bits;
81}
82
47static void stm32_clock_event_disable(struct timer_of *to) 83static void stm32_clock_event_disable(struct timer_of *to)
48{ 84{
49 writel_relaxed(0, timer_of_base(to) + TIM_DIER); 85 writel_relaxed(0, timer_of_base(to) + TIM_DIER);
@@ -124,35 +160,31 @@ static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
124 * is 32 bits wide, the result will be UINT_MAX, otherwise it will 160 * is 32 bits wide, the result will be UINT_MAX, otherwise it will
125 * be truncated by the 16-bit register to USHRT_MAX. 161 * be truncated by the 16-bit register to USHRT_MAX.
126 * 162 *
127 * Returns UINT_MAX if the timer is 32 bits wide, USHRT_MAX if it is a
128 * 16 bits wide.
129 */ 163 */
130static u32 __init stm32_timer_width(struct timer_of *to) 164static void __init stm32_timer_set_width(struct timer_of *to)
131{ 165{
166 u32 width;
167
132 writel_relaxed(UINT_MAX, timer_of_base(to) + TIM_ARR); 168 writel_relaxed(UINT_MAX, timer_of_base(to) + TIM_ARR);
133 169
134 return readl_relaxed(timer_of_base(to) + TIM_ARR); 170 width = readl_relaxed(timer_of_base(to) + TIM_ARR);
171
172 stm32_timer_of_bits_set(to, width == UINT_MAX ? 32 : 16);
135} 173}
136 174
137static void __init stm32_clockevent_init(struct timer_of *to) 175/**
176 * stm32_timer_set_prescaler - Compute and set the prescaler register
177 * @to: a pointer to a timer-of structure
178 *
179 * Depending on the timer width, compute the prescaler to always
180 * target a 10MHz timer rate for 16 bits. 32-bit timers are
181 * considered precise and long enough to not use the prescaler.
182 */
183static void __init stm32_timer_set_prescaler(struct timer_of *to)
138{ 184{
139 u32 width = 0; 185 int prescaler = 1;
140 int prescaler;
141 186
142 to->clkevt.name = to->np->full_name; 187 if (stm32_timer_of_bits_get(to) != 32) {
143 to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
144 to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
145 to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
146 to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
147 to->clkevt.set_state_oneshot = stm32_clock_event_set_oneshot;
148 to->clkevt.tick_resume = stm32_clock_event_shutdown;
149 to->clkevt.set_next_event = stm32_clock_event_set_next_event;
150
151 width = stm32_timer_width(to);
152 if (width == UINT_MAX) {
153 prescaler = 1;
154 to->clkevt.rating = 250;
155 } else {
156 prescaler = DIV_ROUND_CLOSEST(timer_of_rate(to), 188 prescaler = DIV_ROUND_CLOSEST(timer_of_rate(to),
157 TIM_PSC_CLKRATE); 189 TIM_PSC_CLKRATE);
158 /* 190 /*
@@ -161,7 +193,6 @@ static void __init stm32_clockevent_init(struct timer_of *to)
161 * this case. 193 * this case.
162 */ 194 */
163 prescaler = prescaler < TIM_PSC_MAX ? prescaler : TIM_PSC_MAX; 195 prescaler = prescaler < TIM_PSC_MAX ? prescaler : TIM_PSC_MAX;
164 to->clkevt.rating = 100;
165 } 196 }
166 197
167 writel_relaxed(prescaler - 1, timer_of_base(to) + TIM_PSC); 198 writel_relaxed(prescaler - 1, timer_of_base(to) + TIM_PSC);
@@ -171,12 +202,26 @@ static void __init stm32_clockevent_init(struct timer_of *to)
171 /* Adjust rate and period given the prescaler value */ 202 /* Adjust rate and period given the prescaler value */
172 to->of_clk.rate = DIV_ROUND_CLOSEST(to->of_clk.rate, prescaler); 203 to->of_clk.rate = DIV_ROUND_CLOSEST(to->of_clk.rate, prescaler);
173 to->of_clk.period = DIV_ROUND_UP(to->of_clk.rate, HZ); 204 to->of_clk.period = DIV_ROUND_UP(to->of_clk.rate, HZ);
205}
206
207static void __init stm32_clockevent_init(struct timer_of *to)
208{
209 u32 bits = stm32_timer_of_bits_get(to);
174 210
175 clockevents_config_and_register(&to->clkevt, 211 to->clkevt.name = to->np->full_name;
176 timer_of_rate(to), 0x1, width); 212 to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
213 to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
214 to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
215 to->clkevt.set_state_oneshot = stm32_clock_event_set_oneshot;
216 to->clkevt.tick_resume = stm32_clock_event_shutdown;
217 to->clkevt.set_next_event = stm32_clock_event_set_next_event;
218 to->clkevt.rating = bits == 32 ? 250 : 100;
219
220 clockevents_config_and_register(&to->clkevt, timer_of_rate(to), 0x1,
221 (1 << bits) - 1);
177 222
178 pr_info("%pOF: STM32 clockevent driver initialized (%d bits)\n", 223 pr_info("%pOF: STM32 clockevent driver initialized (%d bits)\n",
179 to->np, width == UINT_MAX ? 32 : 16); 224 to->np, bits);
180} 225}
181 226
182static int __init stm32_timer_init(struct device_node *node) 227static int __init stm32_timer_init(struct device_node *node)
@@ -196,14 +241,26 @@ static int __init stm32_timer_init(struct device_node *node)
196 if (ret) 241 if (ret)
197 goto err; 242 goto err;
198 243
244 to->private_data = kzalloc(sizeof(struct stm32_timer_private),
245 GFP_KERNEL);
246 if (!to->private_data)
247 goto deinit;
248
199 rstc = of_reset_control_get(node, NULL); 249 rstc = of_reset_control_get(node, NULL);
200 if (!IS_ERR(rstc)) { 250 if (!IS_ERR(rstc)) {
201 reset_control_assert(rstc); 251 reset_control_assert(rstc);
202 reset_control_deassert(rstc); 252 reset_control_deassert(rstc);
203 } 253 }
204 254
255 stm32_timer_set_width(to);
256
257 stm32_timer_set_prescaler(to);
258
205 stm32_clockevent_init(to); 259 stm32_clockevent_init(to);
206 return 0; 260 return 0;
261
262deinit:
263 timer_of_cleanup(to);
207err: 264err:
208 kfree(to); 265 kfree(to);
209 return ret; 266 return ret;