diff options
author | Anson Huang <anson.huang@nxp.com> | 2018-11-06 00:15:58 -0500 |
---|---|---|
committer | Daniel Lezcano <daniel.lezcano@linaro.org> | 2018-12-18 16:22:23 -0500 |
commit | 3825603a8076738d95b430d36896a760d7fc4909 (patch) | |
tree | b69e50c0b1d05a1d6e1f83fc60b2d1b6de87f0d6 /drivers/clocksource/timer-imx-tpm.c | |
parent | bf287607c80f24387fedb431a346dc67f25be12c (diff) |
clocksource/drivers/timer-imx-tpm: Convert the driver to timer-of
Convert the driver to use the timer_of helpers. This allows to handle
timer base, clock and irq using common timer_of driver and it
simplifies the code.
Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Diffstat (limited to 'drivers/clocksource/timer-imx-tpm.c')
-rw-r--r-- | drivers/clocksource/timer-imx-tpm.c | 136 |
1 files changed, 55 insertions, 81 deletions
diff --git a/drivers/clocksource/timer-imx-tpm.c b/drivers/clocksource/timer-imx-tpm.c index b7aa2b817078..c3dd4d2f2a6e 100644 --- a/drivers/clocksource/timer-imx-tpm.c +++ b/drivers/clocksource/timer-imx-tpm.c | |||
@@ -12,6 +12,8 @@ | |||
12 | #include <linux/of_irq.h> | 12 | #include <linux/of_irq.h> |
13 | #include <linux/sched_clock.h> | 13 | #include <linux/sched_clock.h> |
14 | 14 | ||
15 | #include "timer-of.h" | ||
16 | |||
15 | #define TPM_PARAM 0x4 | 17 | #define TPM_PARAM 0x4 |
16 | #define TPM_PARAM_WIDTH_SHIFT 16 | 18 | #define TPM_PARAM_WIDTH_SHIFT 16 |
17 | #define TPM_PARAM_WIDTH_MASK (0xff << 16) | 19 | #define TPM_PARAM_WIDTH_MASK (0xff << 16) |
@@ -33,9 +35,7 @@ | |||
33 | #define TPM_C0V 0x24 | 35 | #define TPM_C0V 0x24 |
34 | 36 | ||
35 | static int counter_width; | 37 | static int counter_width; |
36 | static int rating; | ||
37 | static void __iomem *timer_base; | 38 | static void __iomem *timer_base; |
38 | static struct clock_event_device clockevent_tpm; | ||
39 | 39 | ||
40 | static inline void tpm_timer_disable(void) | 40 | static inline void tpm_timer_disable(void) |
41 | { | 41 | { |
@@ -80,19 +80,6 @@ static u64 notrace tpm_read_sched_clock(void) | |||
80 | return tpm_read_counter(); | 80 | return tpm_read_counter(); |
81 | } | 81 | } |
82 | 82 | ||
83 | static int __init tpm_clocksource_init(unsigned long rate) | ||
84 | { | ||
85 | tpm_delay_timer.read_current_timer = &tpm_read_current_timer; | ||
86 | tpm_delay_timer.freq = rate; | ||
87 | register_current_timer_delay(&tpm_delay_timer); | ||
88 | |||
89 | sched_clock_register(tpm_read_sched_clock, counter_width, rate); | ||
90 | |||
91 | return clocksource_mmio_init(timer_base + TPM_CNT, "imx-tpm", | ||
92 | rate, rating, counter_width, | ||
93 | clocksource_mmio_readl_up); | ||
94 | } | ||
95 | |||
96 | static int tpm_set_next_event(unsigned long delta, | 83 | static int tpm_set_next_event(unsigned long delta, |
97 | struct clock_event_device *evt) | 84 | struct clock_event_device *evt) |
98 | { | 85 | { |
@@ -137,74 +124,77 @@ static irqreturn_t tpm_timer_interrupt(int irq, void *dev_id) | |||
137 | return IRQ_HANDLED; | 124 | return IRQ_HANDLED; |
138 | } | 125 | } |
139 | 126 | ||
140 | static struct clock_event_device clockevent_tpm = { | 127 | static struct timer_of to_tpm = { |
141 | .name = "i.MX7ULP TPM Timer", | 128 | .flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK, |
142 | .features = CLOCK_EVT_FEAT_ONESHOT, | 129 | .clkevt = { |
143 | .set_state_oneshot = tpm_set_state_oneshot, | 130 | .name = "i.MX7ULP TPM Timer", |
144 | .set_next_event = tpm_set_next_event, | 131 | .rating = 200, |
145 | .set_state_shutdown = tpm_set_state_shutdown, | 132 | .features = CLOCK_EVT_FEAT_ONESHOT, |
133 | .set_state_shutdown = tpm_set_state_shutdown, | ||
134 | .set_state_oneshot = tpm_set_state_oneshot, | ||
135 | .set_next_event = tpm_set_next_event, | ||
136 | .cpumask = cpu_possible_mask, | ||
137 | }, | ||
138 | .of_irq = { | ||
139 | .handler = tpm_timer_interrupt, | ||
140 | .flags = IRQF_TIMER | IRQF_IRQPOLL, | ||
141 | }, | ||
146 | }; | 142 | }; |
147 | 143 | ||
148 | static int __init tpm_clockevent_init(unsigned long rate, int irq) | 144 | static int __init tpm_clocksource_init(void) |
149 | { | 145 | { |
150 | int ret; | 146 | tpm_delay_timer.read_current_timer = &tpm_read_current_timer; |
147 | tpm_delay_timer.freq = timer_of_rate(&to_tpm) >> 3; | ||
148 | register_current_timer_delay(&tpm_delay_timer); | ||
151 | 149 | ||
152 | ret = request_irq(irq, tpm_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL, | 150 | sched_clock_register(tpm_read_sched_clock, counter_width, |
153 | "i.MX7ULP TPM Timer", &clockevent_tpm); | 151 | timer_of_rate(&to_tpm) >> 3); |
154 | 152 | ||
155 | clockevent_tpm.rating = rating; | 153 | return clocksource_mmio_init(timer_base + TPM_CNT, |
156 | clockevent_tpm.cpumask = cpumask_of(0); | 154 | "imx-tpm", |
157 | clockevent_tpm.irq = irq; | 155 | timer_of_rate(&to_tpm) >> 3, |
158 | clockevents_config_and_register(&clockevent_tpm, rate, 300, | 156 | to_tpm.clkevt.rating, |
159 | GENMASK(counter_width - 1, 1)); | 157 | counter_width, |
158 | clocksource_mmio_readl_up); | ||
159 | } | ||
160 | 160 | ||
161 | return ret; | 161 | static void __init tpm_clockevent_init(void) |
162 | { | ||
163 | clockevents_config_and_register(&to_tpm.clkevt, | ||
164 | timer_of_rate(&to_tpm) >> 3, | ||
165 | 300, | ||
166 | GENMASK(counter_width - 1, | ||
167 | 1)); | ||
162 | } | 168 | } |
163 | 169 | ||
164 | static int __init tpm_timer_init(struct device_node *np) | 170 | static int __init tpm_timer_init(struct device_node *np) |
165 | { | 171 | { |
166 | struct clk *ipg, *per; | 172 | struct clk *ipg; |
167 | int irq, ret; | 173 | int ret; |
168 | u32 rate; | ||
169 | |||
170 | timer_base = of_iomap(np, 0); | ||
171 | if (!timer_base) { | ||
172 | pr_err("tpm: failed to get base address\n"); | ||
173 | return -ENXIO; | ||
174 | } | ||
175 | |||
176 | irq = irq_of_parse_and_map(np, 0); | ||
177 | if (!irq) { | ||
178 | pr_err("tpm: failed to get irq\n"); | ||
179 | ret = -ENOENT; | ||
180 | goto err_iomap; | ||
181 | } | ||
182 | 174 | ||
183 | ipg = of_clk_get_by_name(np, "ipg"); | 175 | ipg = of_clk_get_by_name(np, "ipg"); |
184 | per = of_clk_get_by_name(np, "per"); | 176 | if (IS_ERR(ipg)) { |
185 | if (IS_ERR(ipg) || IS_ERR(per)) { | 177 | pr_err("tpm: failed to get ipg clk\n"); |
186 | pr_err("tpm: failed to get ipg or per clk\n"); | 178 | return -ENODEV; |
187 | ret = -ENODEV; | ||
188 | goto err_clk_get; | ||
189 | } | 179 | } |
190 | |||
191 | /* enable clk before accessing registers */ | 180 | /* enable clk before accessing registers */ |
192 | ret = clk_prepare_enable(ipg); | 181 | ret = clk_prepare_enable(ipg); |
193 | if (ret) { | 182 | if (ret) { |
194 | pr_err("tpm: ipg clock enable failed (%d)\n", ret); | 183 | pr_err("tpm: ipg clock enable failed (%d)\n", ret); |
195 | goto err_clk_get; | 184 | clk_put(ipg); |
185 | return ret; | ||
196 | } | 186 | } |
197 | 187 | ||
198 | ret = clk_prepare_enable(per); | 188 | ret = timer_of_init(np, &to_tpm); |
199 | if (ret) { | 189 | if (ret) |
200 | pr_err("tpm: per clock enable failed (%d)\n", ret); | 190 | return ret; |
201 | goto err_per_clk_enable; | 191 | |
202 | } | 192 | timer_base = timer_of_base(&to_tpm); |
203 | 193 | ||
204 | counter_width = (readl(timer_base + TPM_PARAM) & TPM_PARAM_WIDTH_MASK) | 194 | counter_width = (readl(timer_base + TPM_PARAM) |
205 | >> TPM_PARAM_WIDTH_SHIFT; | 195 | & TPM_PARAM_WIDTH_MASK) >> TPM_PARAM_WIDTH_SHIFT; |
206 | /* use rating 200 for 32-bit counter and 150 for 16-bit counter */ | 196 | /* use rating 200 for 32-bit counter and 150 for 16-bit counter */ |
207 | rating = counter_width == 0x20 ? 200 : 150; | 197 | to_tpm.clkevt.rating = counter_width == 0x20 ? 200 : 150; |
208 | 198 | ||
209 | /* | 199 | /* |
210 | * Initialize tpm module to a known state | 200 | * Initialize tpm module to a known state |
@@ -229,29 +219,13 @@ static int __init tpm_timer_init(struct device_node *np) | |||
229 | writel(TPM_SC_CMOD_INC_PER_CNT | | 219 | writel(TPM_SC_CMOD_INC_PER_CNT | |
230 | (counter_width == 0x20 ? | 220 | (counter_width == 0x20 ? |
231 | TPM_SC_CMOD_DIV_DEFAULT : TPM_SC_CMOD_DIV_MAX), | 221 | TPM_SC_CMOD_DIV_DEFAULT : TPM_SC_CMOD_DIV_MAX), |
232 | timer_base + TPM_SC); | 222 | timer_base + TPM_SC); |
233 | 223 | ||
234 | /* set MOD register to maximum for free running mode */ | 224 | /* set MOD register to maximum for free running mode */ |
235 | writel(GENMASK(counter_width - 1, 0), timer_base + TPM_MOD); | 225 | writel(GENMASK(counter_width - 1, 0), timer_base + TPM_MOD); |
236 | 226 | ||
237 | rate = clk_get_rate(per) >> 3; | 227 | tpm_clockevent_init(); |
238 | ret = tpm_clocksource_init(rate); | ||
239 | if (ret) | ||
240 | goto err_per_clk_enable; | ||
241 | |||
242 | ret = tpm_clockevent_init(rate, irq); | ||
243 | if (ret) | ||
244 | goto err_per_clk_enable; | ||
245 | |||
246 | return 0; | ||
247 | 228 | ||
248 | err_per_clk_enable: | 229 | return tpm_clocksource_init(); |
249 | clk_disable_unprepare(ipg); | ||
250 | err_clk_get: | ||
251 | clk_put(per); | ||
252 | clk_put(ipg); | ||
253 | err_iomap: | ||
254 | iounmap(timer_base); | ||
255 | return ret; | ||
256 | } | 230 | } |
257 | TIMER_OF_DECLARE(imx7ulp, "fsl,imx7ulp-tpm", tpm_timer_init); | 231 | TIMER_OF_DECLARE(imx7ulp, "fsl,imx7ulp-tpm", tpm_timer_init); |