aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource/timer-imx-tpm.c
diff options
context:
space:
mode:
authorAnson Huang <anson.huang@nxp.com>2018-11-06 00:15:58 -0500
committerDaniel Lezcano <daniel.lezcano@linaro.org>2018-12-18 16:22:23 -0500
commit3825603a8076738d95b430d36896a760d7fc4909 (patch)
treeb69e50c0b1d05a1d6e1f83fc60b2d1b6de87f0d6 /drivers/clocksource/timer-imx-tpm.c
parentbf287607c80f24387fedb431a346dc67f25be12c (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.c136
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
35static int counter_width; 37static int counter_width;
36static int rating;
37static void __iomem *timer_base; 38static void __iomem *timer_base;
38static struct clock_event_device clockevent_tpm;
39 39
40static inline void tpm_timer_disable(void) 40static 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
83static 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
96static int tpm_set_next_event(unsigned long delta, 83static 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
140static struct clock_event_device clockevent_tpm = { 127static 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
148static int __init tpm_clockevent_init(unsigned long rate, int irq) 144static 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; 161static 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
164static int __init tpm_timer_init(struct device_node *np) 170static 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
248err_per_clk_enable: 229 return tpm_clocksource_init();
249 clk_disable_unprepare(ipg);
250err_clk_get:
251 clk_put(per);
252 clk_put(ipg);
253err_iomap:
254 iounmap(timer_base);
255 return ret;
256} 230}
257TIMER_OF_DECLARE(imx7ulp, "fsl,imx7ulp-tpm", tpm_timer_init); 231TIMER_OF_DECLARE(imx7ulp, "fsl,imx7ulp-tpm", tpm_timer_init);