blob: 33c7c90412ba31e29ca362b0352cd91f7d790af2 [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
Daniel Lezcano70c62cf2018-01-08 14:28:53 +010083/**
84 * stm32_timer_width - Sort out the timer width (32/16)
85 * @to: a pointer to a timer-of structure
86 *
87 * Write the 32-bit max value and read/return the result. If the timer
88 * is 32 bits wide, the result will be UINT_MAX, otherwise it will
89 * be truncated by the 16-bit register to USHRT_MAX.
90 *
91 * Returns UINT_MAX if the timer is 32 bits wide, USHRT_MAX if it is a
92 * 16 bits wide.
93 */
94static u32 __init stm32_timer_width(struct timer_of *to)
95{
96 writel_relaxed(UINT_MAX, timer_of_base(to) + TIM_ARR);
97
98 return readl_relaxed(timer_of_base(to) + TIM_ARR);
99}
100
Benjamin Gaignardd04af492018-01-08 14:28:51 +0100101static void __init stm32_clockevent_init(struct timer_of *to)
Maxime Coqueline37e4592015-05-22 23:03:33 +0200102{
Daniel Lezcano70c62cf2018-01-08 14:28:53 +0100103 u32 width = 0;
Benjamin Gaignardd04af492018-01-08 14:28:51 +0100104 int prescaler;
Maxime Coqueline37e4592015-05-22 23:03:33 +0200105
Daniel Lezcanof2ed8ef2018-01-08 14:28:52 +0100106 to->clkevt.name = to->np->full_name;
Benjamin Gaignardd04af492018-01-08 14:28:51 +0100107 to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
108 to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
109 to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
110 to->clkevt.set_state_oneshot = stm32_clock_event_shutdown;
111 to->clkevt.tick_resume = stm32_clock_event_shutdown;
112 to->clkevt.set_next_event = stm32_clock_event_set_next_event;
113
Daniel Lezcano70c62cf2018-01-08 14:28:53 +0100114 width = stm32_timer_width(to);
115 if (width == UINT_MAX) {
Benjamin Gaignardd04af492018-01-08 14:28:51 +0100116 prescaler = 1;
117 to->clkevt.rating = 250;
118 } else {
119 prescaler = 1024;
120 to->clkevt.rating = 100;
121 }
122 writel_relaxed(0, timer_of_base(to) + TIM_ARR);
123
124 writel_relaxed(prescaler - 1, timer_of_base(to) + TIM_PSC);
125 writel_relaxed(TIM_EGR_UG, timer_of_base(to) + TIM_EGR);
126 writel_relaxed(0, timer_of_base(to) + TIM_SR);
127 writel_relaxed(TIM_DIER_UIE, timer_of_base(to) + TIM_DIER);
128
129 /* Adjust rate and period given the prescaler value */
130 to->of_clk.rate = DIV_ROUND_CLOSEST(to->of_clk.rate, prescaler);
131 to->of_clk.period = DIV_ROUND_UP(to->of_clk.rate, HZ);
132
133 clockevents_config_and_register(&to->clkevt,
Daniel Lezcano70c62cf2018-01-08 14:28:53 +0100134 timer_of_rate(to), 0x1, width);
Benjamin Gaignardd04af492018-01-08 14:28:51 +0100135
136 pr_info("%pOF: STM32 clockevent driver initialized (%d bits)\n",
Daniel Lezcano70c62cf2018-01-08 14:28:53 +0100137 to->np, width == UINT_MAX ? 32 : 16);
Benjamin Gaignardd04af492018-01-08 14:28:51 +0100138}
139
140static int __init stm32_timer_init(struct device_node *node)
141{
142 struct reset_control *rstc;
143 struct timer_of *to;
144 int ret;
145
146 to = kzalloc(sizeof(*to), GFP_KERNEL);
147 if (!to)
Daniel Lezcanoe0aeca32018-01-08 14:28:50 +0100148 return -ENOMEM;
149
Benjamin Gaignardd04af492018-01-08 14:28:51 +0100150 to->flags = TIMER_OF_IRQ | TIMER_OF_CLOCK | TIMER_OF_BASE;
151 to->of_irq.handler = stm32_clock_event_handler;
Maxime Coqueline37e4592015-05-22 23:03:33 +0200152
Benjamin Gaignardd04af492018-01-08 14:28:51 +0100153 ret = timer_of_init(node, to);
154 if (ret)
155 goto err;
Maxime Coqueline37e4592015-05-22 23:03:33 +0200156
Benjamin Gaignardd04af492018-01-08 14:28:51 +0100157 rstc = of_reset_control_get(node, NULL);
Maxime Coqueline37e4592015-05-22 23:03:33 +0200158 if (!IS_ERR(rstc)) {
159 reset_control_assert(rstc);
160 reset_control_deassert(rstc);
161 }
162
Benjamin Gaignardd04af492018-01-08 14:28:51 +0100163 stm32_clockevent_init(to);
164 return 0;
165err:
166 kfree(to);
Daniel Lezcano38d94c52016-06-06 23:28:17 +0200167 return ret;
Maxime Coqueline37e4592015-05-22 23:03:33 +0200168}
169
Benjamin Gaignardd04af492018-01-08 14:28:51 +0100170TIMER_OF_DECLARE(stm32, "st,stm32-timer", stm32_timer_init);