diff options
author | Anson Huang <Anson.Huang@nxp.com> | 2018-03-27 23:22:38 -0400 |
---|---|---|
committer | Daniel Lezcano <daniel.lezcano@linaro.org> | 2018-03-30 16:44:11 -0400 |
commit | 0136c741ff40e03323419feec05fcd594f36a463 (patch) | |
tree | 6ebe96d799a7077e52d060f7aa96741f9df5882b | |
parent | 506a7be93ff773d5d4cf75a59f342865605b4910 (diff) |
clocksource/drivers/imx-tpm: Add different counter width support
Different TPM modules have different width counters which is 16-bit or 32-bit,
the counter width can be read from TPM_PARAM register bit[23:16], this patch
adds dynamic check for counter width to support both 16-bit and 32-bit TPM
modules.
Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
-rw-r--r-- | drivers/clocksource/timer-imx-tpm.c | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/drivers/clocksource/timer-imx-tpm.c b/drivers/clocksource/timer-imx-tpm.c index 7403e494417a..05d97a6871d8 100644 --- a/drivers/clocksource/timer-imx-tpm.c +++ b/drivers/clocksource/timer-imx-tpm.c | |||
@@ -17,9 +17,13 @@ | |||
17 | #include <linux/of_irq.h> | 17 | #include <linux/of_irq.h> |
18 | #include <linux/sched_clock.h> | 18 | #include <linux/sched_clock.h> |
19 | 19 | ||
20 | #define TPM_PARAM 0x4 | ||
21 | #define TPM_PARAM_WIDTH_SHIFT 16 | ||
22 | #define TPM_PARAM_WIDTH_MASK (0xff << 16) | ||
20 | #define TPM_SC 0x10 | 23 | #define TPM_SC 0x10 |
21 | #define TPM_SC_CMOD_INC_PER_CNT (0x1 << 3) | 24 | #define TPM_SC_CMOD_INC_PER_CNT (0x1 << 3) |
22 | #define TPM_SC_CMOD_DIV_DEFAULT 0x3 | 25 | #define TPM_SC_CMOD_DIV_DEFAULT 0x3 |
26 | #define TPM_SC_CMOD_DIV_MAX 0x7 | ||
23 | #define TPM_SC_TOF_MASK (0x1 << 7) | 27 | #define TPM_SC_TOF_MASK (0x1 << 7) |
24 | #define TPM_CNT 0x14 | 28 | #define TPM_CNT 0x14 |
25 | #define TPM_MOD 0x18 | 29 | #define TPM_MOD 0x18 |
@@ -33,6 +37,8 @@ | |||
33 | #define TPM_C0SC_CHF_MASK (0x1 << 7) | 37 | #define TPM_C0SC_CHF_MASK (0x1 << 7) |
34 | #define TPM_C0V 0x24 | 38 | #define TPM_C0V 0x24 |
35 | 39 | ||
40 | static int counter_width; | ||
41 | static int rating; | ||
36 | static void __iomem *timer_base; | 42 | static void __iomem *timer_base; |
37 | static struct clock_event_device clockevent_tpm; | 43 | static struct clock_event_device clockevent_tpm; |
38 | 44 | ||
@@ -85,10 +91,11 @@ static int __init tpm_clocksource_init(unsigned long rate) | |||
85 | tpm_delay_timer.freq = rate; | 91 | tpm_delay_timer.freq = rate; |
86 | register_current_timer_delay(&tpm_delay_timer); | 92 | register_current_timer_delay(&tpm_delay_timer); |
87 | 93 | ||
88 | sched_clock_register(tpm_read_sched_clock, 32, rate); | 94 | sched_clock_register(tpm_read_sched_clock, counter_width, rate); |
89 | 95 | ||
90 | return clocksource_mmio_init(timer_base + TPM_CNT, "imx-tpm", | 96 | return clocksource_mmio_init(timer_base + TPM_CNT, "imx-tpm", |
91 | rate, 200, 32, clocksource_mmio_readl_up); | 97 | rate, rating, counter_width, |
98 | clocksource_mmio_readl_up); | ||
92 | } | 99 | } |
93 | 100 | ||
94 | static int tpm_set_next_event(unsigned long delta, | 101 | static int tpm_set_next_event(unsigned long delta, |
@@ -141,7 +148,6 @@ static struct clock_event_device clockevent_tpm = { | |||
141 | .set_state_oneshot = tpm_set_state_oneshot, | 148 | .set_state_oneshot = tpm_set_state_oneshot, |
142 | .set_next_event = tpm_set_next_event, | 149 | .set_next_event = tpm_set_next_event, |
143 | .set_state_shutdown = tpm_set_state_shutdown, | 150 | .set_state_shutdown = tpm_set_state_shutdown, |
144 | .rating = 200, | ||
145 | }; | 151 | }; |
146 | 152 | ||
147 | static int __init tpm_clockevent_init(unsigned long rate, int irq) | 153 | static int __init tpm_clockevent_init(unsigned long rate, int irq) |
@@ -151,10 +157,11 @@ static int __init tpm_clockevent_init(unsigned long rate, int irq) | |||
151 | ret = request_irq(irq, tpm_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL, | 157 | ret = request_irq(irq, tpm_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL, |
152 | "i.MX7ULP TPM Timer", &clockevent_tpm); | 158 | "i.MX7ULP TPM Timer", &clockevent_tpm); |
153 | 159 | ||
160 | clockevent_tpm.rating = rating; | ||
154 | clockevent_tpm.cpumask = cpumask_of(0); | 161 | clockevent_tpm.cpumask = cpumask_of(0); |
155 | clockevent_tpm.irq = irq; | 162 | clockevent_tpm.irq = irq; |
156 | clockevents_config_and_register(&clockevent_tpm, | 163 | clockevents_config_and_register(&clockevent_tpm, rate, 300, |
157 | rate, 300, 0xfffffffe); | 164 | GENMASK(counter_width - 1, 1)); |
158 | 165 | ||
159 | return ret; | 166 | return ret; |
160 | } | 167 | } |
@@ -199,6 +206,11 @@ static int __init tpm_timer_init(struct device_node *np) | |||
199 | goto err_per_clk_enable; | 206 | goto err_per_clk_enable; |
200 | } | 207 | } |
201 | 208 | ||
209 | counter_width = (readl(timer_base + TPM_PARAM) & TPM_PARAM_WIDTH_MASK) | ||
210 | >> TPM_PARAM_WIDTH_SHIFT; | ||
211 | /* use rating 200 for 32-bit counter and 150 for 16-bit counter */ | ||
212 | rating = counter_width == 0x20 ? 200 : 150; | ||
213 | |||
202 | /* | 214 | /* |
203 | * Initialize tpm module to a known state | 215 | * Initialize tpm module to a known state |
204 | * 1) Counter disabled | 216 | * 1) Counter disabled |
@@ -215,12 +227,17 @@ static int __init tpm_timer_init(struct device_node *np) | |||
215 | /* CHF is W1C */ | 227 | /* CHF is W1C */ |
216 | writel(TPM_C0SC_CHF_MASK, timer_base + TPM_C0SC); | 228 | writel(TPM_C0SC_CHF_MASK, timer_base + TPM_C0SC); |
217 | 229 | ||
218 | /* increase per cnt, div 8 by default */ | 230 | /* |
219 | writel(TPM_SC_CMOD_INC_PER_CNT | TPM_SC_CMOD_DIV_DEFAULT, | 231 | * increase per cnt, |
232 | * div 8 for 32-bit counter and div 128 for 16-bit counter | ||
233 | */ | ||
234 | writel(TPM_SC_CMOD_INC_PER_CNT | | ||
235 | (counter_width == 0x20 ? | ||
236 | TPM_SC_CMOD_DIV_DEFAULT : TPM_SC_CMOD_DIV_MAX), | ||
220 | timer_base + TPM_SC); | 237 | timer_base + TPM_SC); |
221 | 238 | ||
222 | /* set MOD register to maximum for free running mode */ | 239 | /* set MOD register to maximum for free running mode */ |
223 | writel(0xffffffff, timer_base + TPM_MOD); | 240 | writel(GENMASK(counter_width - 1, 0), timer_base + TPM_MOD); |
224 | 241 | ||
225 | rate = clk_get_rate(per) >> 3; | 242 | rate = clk_get_rate(per) >> 3; |
226 | ret = tpm_clocksource_init(rate); | 243 | ret = tpm_clocksource_init(rate); |