diff options
Diffstat (limited to 'drivers/clocksource')
-rw-r--r-- | drivers/clocksource/Kconfig | 14 | ||||
-rw-r--r-- | drivers/clocksource/Makefile | 3 | ||||
-rw-r--r-- | drivers/clocksource/clps711x-timer.c | 131 | ||||
-rw-r--r-- | drivers/clocksource/exynos_mct.c | 63 | ||||
-rw-r--r-- | drivers/clocksource/mtk_timer.c | 261 | ||||
-rw-r--r-- | drivers/clocksource/pxa_timer.c | 227 | ||||
-rw-r--r-- | drivers/clocksource/sh_cmt.c | 233 | ||||
-rw-r--r-- | drivers/clocksource/sh_mtu2.c | 146 | ||||
-rw-r--r-- | drivers/clocksource/sh_tmu.c | 127 | ||||
-rw-r--r-- | drivers/clocksource/timer-marco.c | 3 | ||||
-rw-r--r-- | drivers/clocksource/timer-prima2.c | 3 |
11 files changed, 868 insertions, 343 deletions
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 065131cbfcc0..cfd6519df661 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig | |||
@@ -1,3 +1,5 @@ | |||
1 | menu "Clock Source drivers" | ||
2 | |||
1 | config CLKSRC_OF | 3 | config CLKSRC_OF |
2 | bool | 4 | bool |
3 | 5 | ||
@@ -125,6 +127,7 @@ config CLKSRC_METAG_GENERIC | |||
125 | 127 | ||
126 | config CLKSRC_EXYNOS_MCT | 128 | config CLKSRC_EXYNOS_MCT |
127 | def_bool y if ARCH_EXYNOS | 129 | def_bool y if ARCH_EXYNOS |
130 | depends on !ARM64 | ||
128 | help | 131 | help |
129 | Support for Multi Core Timer controller on Exynos SoCs. | 132 | Support for Multi Core Timer controller on Exynos SoCs. |
130 | 133 | ||
@@ -149,6 +152,11 @@ config VF_PIT_TIMER | |||
149 | config SYS_SUPPORTS_SH_CMT | 152 | config SYS_SUPPORTS_SH_CMT |
150 | bool | 153 | bool |
151 | 154 | ||
155 | config MTK_TIMER | ||
156 | select CLKSRC_OF | ||
157 | select CLKSRC_MMIO | ||
158 | bool | ||
159 | |||
152 | config SYS_SUPPORTS_SH_MTU2 | 160 | config SYS_SUPPORTS_SH_MTU2 |
153 | bool | 161 | bool |
154 | 162 | ||
@@ -173,7 +181,7 @@ config SH_TIMER_MTU2 | |||
173 | default SYS_SUPPORTS_SH_MTU2 | 181 | default SYS_SUPPORTS_SH_MTU2 |
174 | help | 182 | help |
175 | This enables build of a clockevent driver for the Multi-Function | 183 | This enables build of a clockevent driver for the Multi-Function |
176 | Timer Pulse Unit 2 (TMU2) hardware available on SoCs from Renesas. | 184 | Timer Pulse Unit 2 (MTU2) hardware available on SoCs from Renesas. |
177 | This hardware comes with 16 bit-timer registers. | 185 | This hardware comes with 16 bit-timer registers. |
178 | 186 | ||
179 | config SH_TIMER_TMU | 187 | config SH_TIMER_TMU |
@@ -187,7 +195,7 @@ config SH_TIMER_TMU | |||
187 | 195 | ||
188 | config EM_TIMER_STI | 196 | config EM_TIMER_STI |
189 | bool "Renesas STI timer driver" if COMPILE_TEST | 197 | bool "Renesas STI timer driver" if COMPILE_TEST |
190 | depends on GENERIC_CLOCKEVENTS | 198 | depends on GENERIC_CLOCKEVENTS && HAS_IOMEM |
191 | default SYS_SUPPORTS_EM_STI | 199 | default SYS_SUPPORTS_EM_STI |
192 | help | 200 | help |
193 | This enables build of a clocksource and clockevent driver for | 201 | This enables build of a clocksource and clockevent driver for |
@@ -207,3 +215,5 @@ config CLKSRC_VERSATILE | |||
207 | counter available in the "System Registers" block of | 215 | counter available in the "System Registers" block of |
208 | ARM Versatile, RealView and Versatile Express reference | 216 | ARM Versatile, RealView and Versatile Express reference |
209 | platforms. | 217 | platforms. |
218 | |||
219 | endmenu | ||
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 800b1303c236..7fd9fd1dff42 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile | |||
@@ -16,9 +16,11 @@ obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o | |||
16 | obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o | 16 | obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o |
17 | obj-$(CONFIG_ORION_TIMER) += time-orion.o | 17 | obj-$(CONFIG_ORION_TIMER) += time-orion.o |
18 | obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o | 18 | obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o |
19 | obj-$(CONFIG_ARCH_CLPS711X) += clps711x-timer.o | ||
19 | obj-$(CONFIG_ARCH_MARCO) += timer-marco.o | 20 | obj-$(CONFIG_ARCH_MARCO) += timer-marco.o |
20 | obj-$(CONFIG_ARCH_MOXART) += moxart_timer.o | 21 | obj-$(CONFIG_ARCH_MOXART) += moxart_timer.o |
21 | obj-$(CONFIG_ARCH_MXS) += mxs_timer.o | 22 | obj-$(CONFIG_ARCH_MXS) += mxs_timer.o |
23 | obj-$(CONFIG_ARCH_PXA) += pxa_timer.o | ||
22 | obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o | 24 | obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o |
23 | obj-$(CONFIG_ARCH_U300) += timer-u300.o | 25 | obj-$(CONFIG_ARCH_U300) += timer-u300.o |
24 | obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o | 26 | obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o |
@@ -34,6 +36,7 @@ obj-$(CONFIG_CLKSRC_SAMSUNG_PWM) += samsung_pwm_timer.o | |||
34 | obj-$(CONFIG_FSL_FTM_TIMER) += fsl_ftm_timer.o | 36 | obj-$(CONFIG_FSL_FTM_TIMER) += fsl_ftm_timer.o |
35 | obj-$(CONFIG_VF_PIT_TIMER) += vf_pit_timer.o | 37 | obj-$(CONFIG_VF_PIT_TIMER) += vf_pit_timer.o |
36 | obj-$(CONFIG_CLKSRC_QCOM) += qcom-timer.o | 38 | obj-$(CONFIG_CLKSRC_QCOM) += qcom-timer.o |
39 | obj-$(CONFIG_MTK_TIMER) += mtk_timer.o | ||
37 | 40 | ||
38 | obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o | 41 | obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o |
39 | obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o | 42 | obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o |
diff --git a/drivers/clocksource/clps711x-timer.c b/drivers/clocksource/clps711x-timer.c new file mode 100644 index 000000000000..d83ec1f2fddc --- /dev/null +++ b/drivers/clocksource/clps711x-timer.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * Cirrus Logic CLPS711X clocksource driver | ||
3 | * | ||
4 | * Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/clockchips.h> | ||
14 | #include <linux/clocksource.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/of_address.h> | ||
18 | #include <linux/of_irq.h> | ||
19 | #include <linux/sched_clock.h> | ||
20 | #include <linux/slab.h> | ||
21 | |||
22 | enum { | ||
23 | CLPS711X_CLKSRC_CLOCKSOURCE, | ||
24 | CLPS711X_CLKSRC_CLOCKEVENT, | ||
25 | }; | ||
26 | |||
27 | static void __iomem *tcd; | ||
28 | |||
29 | static u64 notrace clps711x_sched_clock_read(void) | ||
30 | { | ||
31 | return ~readw(tcd); | ||
32 | } | ||
33 | |||
34 | static int __init _clps711x_clksrc_init(struct clk *clock, void __iomem *base) | ||
35 | { | ||
36 | unsigned long rate; | ||
37 | |||
38 | if (!base) | ||
39 | return -ENOMEM; | ||
40 | if (IS_ERR(clock)) | ||
41 | return PTR_ERR(clock); | ||
42 | |||
43 | rate = clk_get_rate(clock); | ||
44 | |||
45 | tcd = base; | ||
46 | |||
47 | clocksource_mmio_init(tcd, "clps711x-clocksource", rate, 300, 16, | ||
48 | clocksource_mmio_readw_down); | ||
49 | |||
50 | sched_clock_register(clps711x_sched_clock_read, 16, rate); | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static irqreturn_t clps711x_timer_interrupt(int irq, void *dev_id) | ||
56 | { | ||
57 | struct clock_event_device *evt = dev_id; | ||
58 | |||
59 | evt->event_handler(evt); | ||
60 | |||
61 | return IRQ_HANDLED; | ||
62 | } | ||
63 | |||
64 | static void clps711x_clockevent_set_mode(enum clock_event_mode mode, | ||
65 | struct clock_event_device *evt) | ||
66 | { | ||
67 | } | ||
68 | |||
69 | static int __init _clps711x_clkevt_init(struct clk *clock, void __iomem *base, | ||
70 | unsigned int irq) | ||
71 | { | ||
72 | struct clock_event_device *clkevt; | ||
73 | unsigned long rate; | ||
74 | |||
75 | if (!irq) | ||
76 | return -EINVAL; | ||
77 | if (!base) | ||
78 | return -ENOMEM; | ||
79 | if (IS_ERR(clock)) | ||
80 | return PTR_ERR(clock); | ||
81 | |||
82 | clkevt = kzalloc(sizeof(*clkevt), GFP_KERNEL); | ||
83 | if (!clkevt) | ||
84 | return -ENOMEM; | ||
85 | |||
86 | rate = clk_get_rate(clock); | ||
87 | |||
88 | /* Set Timer prescaler */ | ||
89 | writew(DIV_ROUND_CLOSEST(rate, HZ), base); | ||
90 | |||
91 | clkevt->name = "clps711x-clockevent"; | ||
92 | clkevt->rating = 300; | ||
93 | clkevt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_C3STOP; | ||
94 | clkevt->set_mode = clps711x_clockevent_set_mode; | ||
95 | clkevt->cpumask = cpumask_of(0); | ||
96 | clockevents_config_and_register(clkevt, HZ, 0, 0); | ||
97 | |||
98 | return request_irq(irq, clps711x_timer_interrupt, IRQF_TIMER, | ||
99 | "clps711x-timer", clkevt); | ||
100 | } | ||
101 | |||
102 | void __init clps711x_clksrc_init(void __iomem *tc1_base, void __iomem *tc2_base, | ||
103 | unsigned int irq) | ||
104 | { | ||
105 | struct clk *tc1 = clk_get_sys("clps711x-timer.0", NULL); | ||
106 | struct clk *tc2 = clk_get_sys("clps711x-timer.1", NULL); | ||
107 | |||
108 | BUG_ON(_clps711x_clksrc_init(tc1, tc1_base)); | ||
109 | BUG_ON(_clps711x_clkevt_init(tc2, tc2_base, irq)); | ||
110 | } | ||
111 | |||
112 | #ifdef CONFIG_CLKSRC_OF | ||
113 | static void __init clps711x_timer_init(struct device_node *np) | ||
114 | { | ||
115 | unsigned int irq = irq_of_parse_and_map(np, 0); | ||
116 | struct clk *clock = of_clk_get(np, 0); | ||
117 | void __iomem *base = of_iomap(np, 0); | ||
118 | |||
119 | switch (of_alias_get_id(np, "timer")) { | ||
120 | case CLPS711X_CLKSRC_CLOCKSOURCE: | ||
121 | BUG_ON(_clps711x_clksrc_init(clock, base)); | ||
122 | break; | ||
123 | case CLPS711X_CLKSRC_CLOCKEVENT: | ||
124 | BUG_ON(_clps711x_clkevt_init(clock, base, irq)); | ||
125 | break; | ||
126 | default: | ||
127 | break; | ||
128 | } | ||
129 | } | ||
130 | CLOCKSOURCE_OF_DECLARE(clps711x, "cirrus,clps711x-timer", clps711x_timer_init); | ||
131 | #endif | ||
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index ab51bf20a3ed..9403061a2acc 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c | |||
@@ -94,7 +94,7 @@ static void exynos4_mct_write(unsigned int value, unsigned long offset) | |||
94 | u32 mask; | 94 | u32 mask; |
95 | u32 i; | 95 | u32 i; |
96 | 96 | ||
97 | __raw_writel(value, reg_base + offset); | 97 | writel_relaxed(value, reg_base + offset); |
98 | 98 | ||
99 | if (likely(offset >= EXYNOS4_MCT_L_BASE(0))) { | 99 | if (likely(offset >= EXYNOS4_MCT_L_BASE(0))) { |
100 | stat_addr = (offset & ~EXYNOS4_MCT_L_MASK) + MCT_L_WSTAT_OFFSET; | 100 | stat_addr = (offset & ~EXYNOS4_MCT_L_MASK) + MCT_L_WSTAT_OFFSET; |
@@ -144,8 +144,8 @@ static void exynos4_mct_write(unsigned int value, unsigned long offset) | |||
144 | 144 | ||
145 | /* Wait maximum 1 ms until written values are applied */ | 145 | /* Wait maximum 1 ms until written values are applied */ |
146 | for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++) | 146 | for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++) |
147 | if (__raw_readl(reg_base + stat_addr) & mask) { | 147 | if (readl_relaxed(reg_base + stat_addr) & mask) { |
148 | __raw_writel(mask, reg_base + stat_addr); | 148 | writel_relaxed(mask, reg_base + stat_addr); |
149 | return; | 149 | return; |
150 | } | 150 | } |
151 | 151 | ||
@@ -157,28 +157,51 @@ static void exynos4_mct_frc_start(void) | |||
157 | { | 157 | { |
158 | u32 reg; | 158 | u32 reg; |
159 | 159 | ||
160 | reg = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON); | 160 | reg = readl_relaxed(reg_base + EXYNOS4_MCT_G_TCON); |
161 | reg |= MCT_G_TCON_START; | 161 | reg |= MCT_G_TCON_START; |
162 | exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON); | 162 | exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON); |
163 | } | 163 | } |
164 | 164 | ||
165 | static cycle_t notrace _exynos4_frc_read(void) | 165 | /** |
166 | * exynos4_read_count_64 - Read all 64-bits of the global counter | ||
167 | * | ||
168 | * This will read all 64-bits of the global counter taking care to make sure | ||
169 | * that the upper and lower half match. Note that reading the MCT can be quite | ||
170 | * slow (hundreds of nanoseconds) so you should use the 32-bit (lower half | ||
171 | * only) version when possible. | ||
172 | * | ||
173 | * Returns the number of cycles in the global counter. | ||
174 | */ | ||
175 | static u64 exynos4_read_count_64(void) | ||
166 | { | 176 | { |
167 | unsigned int lo, hi; | 177 | unsigned int lo, hi; |
168 | u32 hi2 = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_U); | 178 | u32 hi2 = readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_U); |
169 | 179 | ||
170 | do { | 180 | do { |
171 | hi = hi2; | 181 | hi = hi2; |
172 | lo = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_L); | 182 | lo = readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_L); |
173 | hi2 = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_U); | 183 | hi2 = readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_U); |
174 | } while (hi != hi2); | 184 | } while (hi != hi2); |
175 | 185 | ||
176 | return ((cycle_t)hi << 32) | lo; | 186 | return ((cycle_t)hi << 32) | lo; |
177 | } | 187 | } |
178 | 188 | ||
189 | /** | ||
190 | * exynos4_read_count_32 - Read the lower 32-bits of the global counter | ||
191 | * | ||
192 | * This will read just the lower 32-bits of the global counter. This is marked | ||
193 | * as notrace so it can be used by the scheduler clock. | ||
194 | * | ||
195 | * Returns the number of cycles in the global counter (lower 32 bits). | ||
196 | */ | ||
197 | static u32 notrace exynos4_read_count_32(void) | ||
198 | { | ||
199 | return readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_L); | ||
200 | } | ||
201 | |||
179 | static cycle_t exynos4_frc_read(struct clocksource *cs) | 202 | static cycle_t exynos4_frc_read(struct clocksource *cs) |
180 | { | 203 | { |
181 | return _exynos4_frc_read(); | 204 | return exynos4_read_count_32(); |
182 | } | 205 | } |
183 | 206 | ||
184 | static void exynos4_frc_resume(struct clocksource *cs) | 207 | static void exynos4_frc_resume(struct clocksource *cs) |
@@ -190,21 +213,23 @@ struct clocksource mct_frc = { | |||
190 | .name = "mct-frc", | 213 | .name = "mct-frc", |
191 | .rating = 400, | 214 | .rating = 400, |
192 | .read = exynos4_frc_read, | 215 | .read = exynos4_frc_read, |
193 | .mask = CLOCKSOURCE_MASK(64), | 216 | .mask = CLOCKSOURCE_MASK(32), |
194 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 217 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
195 | .resume = exynos4_frc_resume, | 218 | .resume = exynos4_frc_resume, |
196 | }; | 219 | }; |
197 | 220 | ||
198 | static u64 notrace exynos4_read_sched_clock(void) | 221 | static u64 notrace exynos4_read_sched_clock(void) |
199 | { | 222 | { |
200 | return _exynos4_frc_read(); | 223 | return exynos4_read_count_32(); |
201 | } | 224 | } |
202 | 225 | ||
203 | static struct delay_timer exynos4_delay_timer; | 226 | static struct delay_timer exynos4_delay_timer; |
204 | 227 | ||
205 | static cycles_t exynos4_read_current_timer(void) | 228 | static cycles_t exynos4_read_current_timer(void) |
206 | { | 229 | { |
207 | return _exynos4_frc_read(); | 230 | BUILD_BUG_ON_MSG(sizeof(cycles_t) != sizeof(u32), |
231 | "cycles_t needs to move to 32-bit for ARM64 usage"); | ||
232 | return exynos4_read_count_32(); | ||
208 | } | 233 | } |
209 | 234 | ||
210 | static void __init exynos4_clocksource_init(void) | 235 | static void __init exynos4_clocksource_init(void) |
@@ -218,14 +243,14 @@ static void __init exynos4_clocksource_init(void) | |||
218 | if (clocksource_register_hz(&mct_frc, clk_rate)) | 243 | if (clocksource_register_hz(&mct_frc, clk_rate)) |
219 | panic("%s: can't register clocksource\n", mct_frc.name); | 244 | panic("%s: can't register clocksource\n", mct_frc.name); |
220 | 245 | ||
221 | sched_clock_register(exynos4_read_sched_clock, 64, clk_rate); | 246 | sched_clock_register(exynos4_read_sched_clock, 32, clk_rate); |
222 | } | 247 | } |
223 | 248 | ||
224 | static void exynos4_mct_comp0_stop(void) | 249 | static void exynos4_mct_comp0_stop(void) |
225 | { | 250 | { |
226 | unsigned int tcon; | 251 | unsigned int tcon; |
227 | 252 | ||
228 | tcon = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON); | 253 | tcon = readl_relaxed(reg_base + EXYNOS4_MCT_G_TCON); |
229 | tcon &= ~(MCT_G_TCON_COMP0_ENABLE | MCT_G_TCON_COMP0_AUTO_INC); | 254 | tcon &= ~(MCT_G_TCON_COMP0_ENABLE | MCT_G_TCON_COMP0_AUTO_INC); |
230 | 255 | ||
231 | exynos4_mct_write(tcon, EXYNOS4_MCT_G_TCON); | 256 | exynos4_mct_write(tcon, EXYNOS4_MCT_G_TCON); |
@@ -238,14 +263,14 @@ static void exynos4_mct_comp0_start(enum clock_event_mode mode, | |||
238 | unsigned int tcon; | 263 | unsigned int tcon; |
239 | cycle_t comp_cycle; | 264 | cycle_t comp_cycle; |
240 | 265 | ||
241 | tcon = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON); | 266 | tcon = readl_relaxed(reg_base + EXYNOS4_MCT_G_TCON); |
242 | 267 | ||
243 | if (mode == CLOCK_EVT_MODE_PERIODIC) { | 268 | if (mode == CLOCK_EVT_MODE_PERIODIC) { |
244 | tcon |= MCT_G_TCON_COMP0_AUTO_INC; | 269 | tcon |= MCT_G_TCON_COMP0_AUTO_INC; |
245 | exynos4_mct_write(cycles, EXYNOS4_MCT_G_COMP0_ADD_INCR); | 270 | exynos4_mct_write(cycles, EXYNOS4_MCT_G_COMP0_ADD_INCR); |
246 | } | 271 | } |
247 | 272 | ||
248 | comp_cycle = exynos4_frc_read(&mct_frc) + cycles; | 273 | comp_cycle = exynos4_read_count_64() + cycles; |
249 | exynos4_mct_write((u32)comp_cycle, EXYNOS4_MCT_G_COMP0_L); | 274 | exynos4_mct_write((u32)comp_cycle, EXYNOS4_MCT_G_COMP0_L); |
250 | exynos4_mct_write((u32)(comp_cycle >> 32), EXYNOS4_MCT_G_COMP0_U); | 275 | exynos4_mct_write((u32)(comp_cycle >> 32), EXYNOS4_MCT_G_COMP0_U); |
251 | 276 | ||
@@ -327,7 +352,7 @@ static void exynos4_mct_tick_stop(struct mct_clock_event_device *mevt) | |||
327 | unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START; | 352 | unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START; |
328 | unsigned long offset = mevt->base + MCT_L_TCON_OFFSET; | 353 | unsigned long offset = mevt->base + MCT_L_TCON_OFFSET; |
329 | 354 | ||
330 | tmp = __raw_readl(reg_base + offset); | 355 | tmp = readl_relaxed(reg_base + offset); |
331 | if (tmp & mask) { | 356 | if (tmp & mask) { |
332 | tmp &= ~mask; | 357 | tmp &= ~mask; |
333 | exynos4_mct_write(tmp, offset); | 358 | exynos4_mct_write(tmp, offset); |
@@ -349,7 +374,7 @@ static void exynos4_mct_tick_start(unsigned long cycles, | |||
349 | /* enable MCT tick interrupt */ | 374 | /* enable MCT tick interrupt */ |
350 | exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET); | 375 | exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET); |
351 | 376 | ||
352 | tmp = __raw_readl(reg_base + mevt->base + MCT_L_TCON_OFFSET); | 377 | tmp = readl_relaxed(reg_base + mevt->base + MCT_L_TCON_OFFSET); |
353 | tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START | | 378 | tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START | |
354 | MCT_L_TCON_INTERVAL_MODE; | 379 | MCT_L_TCON_INTERVAL_MODE; |
355 | exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET); | 380 | exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET); |
@@ -401,7 +426,7 @@ static int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt) | |||
401 | exynos4_mct_tick_stop(mevt); | 426 | exynos4_mct_tick_stop(mevt); |
402 | 427 | ||
403 | /* Clear the MCT tick interrupt */ | 428 | /* Clear the MCT tick interrupt */ |
404 | if (__raw_readl(reg_base + mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) { | 429 | if (readl_relaxed(reg_base + mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) { |
405 | exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET); | 430 | exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET); |
406 | return 1; | 431 | return 1; |
407 | } else { | 432 | } else { |
diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c new file mode 100644 index 000000000000..32a3d25795d3 --- /dev/null +++ b/drivers/clocksource/mtk_timer.c | |||
@@ -0,0 +1,261 @@ | |||
1 | /* | ||
2 | * Mediatek SoCs General-Purpose Timer handling. | ||
3 | * | ||
4 | * Copyright (C) 2014 Matthias Brugger | ||
5 | * | ||
6 | * Matthias Brugger <matthias.bgg@gmail.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | */ | ||
18 | |||
19 | #include <linux/clk.h> | ||
20 | #include <linux/clockchips.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/irq.h> | ||
23 | #include <linux/irqreturn.h> | ||
24 | #include <linux/of.h> | ||
25 | #include <linux/of_address.h> | ||
26 | #include <linux/of_irq.h> | ||
27 | #include <linux/slab.h> | ||
28 | |||
29 | #define GPT_IRQ_EN_REG 0x00 | ||
30 | #define GPT_IRQ_ENABLE(val) BIT((val) - 1) | ||
31 | #define GPT_IRQ_ACK_REG 0x08 | ||
32 | #define GPT_IRQ_ACK(val) BIT((val) - 1) | ||
33 | |||
34 | #define TIMER_CTRL_REG(val) (0x10 * (val)) | ||
35 | #define TIMER_CTRL_OP(val) (((val) & 0x3) << 4) | ||
36 | #define TIMER_CTRL_OP_ONESHOT (0) | ||
37 | #define TIMER_CTRL_OP_REPEAT (1) | ||
38 | #define TIMER_CTRL_OP_FREERUN (3) | ||
39 | #define TIMER_CTRL_CLEAR (2) | ||
40 | #define TIMER_CTRL_ENABLE (1) | ||
41 | #define TIMER_CTRL_DISABLE (0) | ||
42 | |||
43 | #define TIMER_CLK_REG(val) (0x04 + (0x10 * (val))) | ||
44 | #define TIMER_CLK_SRC(val) (((val) & 0x1) << 4) | ||
45 | #define TIMER_CLK_SRC_SYS13M (0) | ||
46 | #define TIMER_CLK_SRC_RTC32K (1) | ||
47 | #define TIMER_CLK_DIV1 (0x0) | ||
48 | #define TIMER_CLK_DIV2 (0x1) | ||
49 | |||
50 | #define TIMER_CNT_REG(val) (0x08 + (0x10 * (val))) | ||
51 | #define TIMER_CMP_REG(val) (0x0C + (0x10 * (val))) | ||
52 | |||
53 | #define GPT_CLK_EVT 1 | ||
54 | #define GPT_CLK_SRC 2 | ||
55 | |||
56 | struct mtk_clock_event_device { | ||
57 | void __iomem *gpt_base; | ||
58 | u32 ticks_per_jiffy; | ||
59 | struct clock_event_device dev; | ||
60 | }; | ||
61 | |||
62 | static inline struct mtk_clock_event_device *to_mtk_clk( | ||
63 | struct clock_event_device *c) | ||
64 | { | ||
65 | return container_of(c, struct mtk_clock_event_device, dev); | ||
66 | } | ||
67 | |||
68 | static void mtk_clkevt_time_stop(struct mtk_clock_event_device *evt, u8 timer) | ||
69 | { | ||
70 | u32 val; | ||
71 | |||
72 | val = readl(evt->gpt_base + TIMER_CTRL_REG(timer)); | ||
73 | writel(val & ~TIMER_CTRL_ENABLE, evt->gpt_base + | ||
74 | TIMER_CTRL_REG(timer)); | ||
75 | } | ||
76 | |||
77 | static void mtk_clkevt_time_setup(struct mtk_clock_event_device *evt, | ||
78 | unsigned long delay, u8 timer) | ||
79 | { | ||
80 | writel(delay, evt->gpt_base + TIMER_CMP_REG(timer)); | ||
81 | } | ||
82 | |||
83 | static void mtk_clkevt_time_start(struct mtk_clock_event_device *evt, | ||
84 | bool periodic, u8 timer) | ||
85 | { | ||
86 | u32 val; | ||
87 | |||
88 | /* Acknowledge interrupt */ | ||
89 | writel(GPT_IRQ_ACK(timer), evt->gpt_base + GPT_IRQ_ACK_REG); | ||
90 | |||
91 | val = readl(evt->gpt_base + TIMER_CTRL_REG(timer)); | ||
92 | |||
93 | /* Clear 2 bit timer operation mode field */ | ||
94 | val &= ~TIMER_CTRL_OP(0x3); | ||
95 | |||
96 | if (periodic) | ||
97 | val |= TIMER_CTRL_OP(TIMER_CTRL_OP_REPEAT); | ||
98 | else | ||
99 | val |= TIMER_CTRL_OP(TIMER_CTRL_OP_ONESHOT); | ||
100 | |||
101 | writel(val | TIMER_CTRL_ENABLE | TIMER_CTRL_CLEAR, | ||
102 | evt->gpt_base + TIMER_CTRL_REG(timer)); | ||
103 | } | ||
104 | |||
105 | static void mtk_clkevt_mode(enum clock_event_mode mode, | ||
106 | struct clock_event_device *clk) | ||
107 | { | ||
108 | struct mtk_clock_event_device *evt = to_mtk_clk(clk); | ||
109 | |||
110 | mtk_clkevt_time_stop(evt, GPT_CLK_EVT); | ||
111 | |||
112 | switch (mode) { | ||
113 | case CLOCK_EVT_MODE_PERIODIC: | ||
114 | mtk_clkevt_time_setup(evt, evt->ticks_per_jiffy, GPT_CLK_EVT); | ||
115 | mtk_clkevt_time_start(evt, true, GPT_CLK_EVT); | ||
116 | break; | ||
117 | case CLOCK_EVT_MODE_ONESHOT: | ||
118 | /* Timer is enabled in set_next_event */ | ||
119 | break; | ||
120 | case CLOCK_EVT_MODE_UNUSED: | ||
121 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
122 | default: | ||
123 | /* No more interrupts will occur as source is disabled */ | ||
124 | break; | ||
125 | } | ||
126 | } | ||
127 | |||
128 | static int mtk_clkevt_next_event(unsigned long event, | ||
129 | struct clock_event_device *clk) | ||
130 | { | ||
131 | struct mtk_clock_event_device *evt = to_mtk_clk(clk); | ||
132 | |||
133 | mtk_clkevt_time_stop(evt, GPT_CLK_EVT); | ||
134 | mtk_clkevt_time_setup(evt, event, GPT_CLK_EVT); | ||
135 | mtk_clkevt_time_start(evt, false, GPT_CLK_EVT); | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static irqreturn_t mtk_timer_interrupt(int irq, void *dev_id) | ||
141 | { | ||
142 | struct mtk_clock_event_device *evt = dev_id; | ||
143 | |||
144 | /* Acknowledge timer0 irq */ | ||
145 | writel(GPT_IRQ_ACK(GPT_CLK_EVT), evt->gpt_base + GPT_IRQ_ACK_REG); | ||
146 | evt->dev.event_handler(&evt->dev); | ||
147 | |||
148 | return IRQ_HANDLED; | ||
149 | } | ||
150 | |||
151 | static void mtk_timer_global_reset(struct mtk_clock_event_device *evt) | ||
152 | { | ||
153 | /* Disable all interrupts */ | ||
154 | writel(0x0, evt->gpt_base + GPT_IRQ_EN_REG); | ||
155 | /* Acknowledge all interrupts */ | ||
156 | writel(0x3f, evt->gpt_base + GPT_IRQ_ACK_REG); | ||
157 | } | ||
158 | |||
159 | static void | ||
160 | mtk_timer_setup(struct mtk_clock_event_device *evt, u8 timer, u8 option) | ||
161 | { | ||
162 | writel(TIMER_CTRL_CLEAR | TIMER_CTRL_DISABLE, | ||
163 | evt->gpt_base + TIMER_CTRL_REG(timer)); | ||
164 | |||
165 | writel(TIMER_CLK_SRC(TIMER_CLK_SRC_SYS13M) | TIMER_CLK_DIV1, | ||
166 | evt->gpt_base + TIMER_CLK_REG(timer)); | ||
167 | |||
168 | writel(0x0, evt->gpt_base + TIMER_CMP_REG(timer)); | ||
169 | |||
170 | writel(TIMER_CTRL_OP(option) | TIMER_CTRL_ENABLE, | ||
171 | evt->gpt_base + TIMER_CTRL_REG(timer)); | ||
172 | } | ||
173 | |||
174 | static void mtk_timer_enable_irq(struct mtk_clock_event_device *evt, u8 timer) | ||
175 | { | ||
176 | u32 val; | ||
177 | |||
178 | val = readl(evt->gpt_base + GPT_IRQ_EN_REG); | ||
179 | writel(val | GPT_IRQ_ENABLE(timer), | ||
180 | evt->gpt_base + GPT_IRQ_EN_REG); | ||
181 | } | ||
182 | |||
183 | static void __init mtk_timer_init(struct device_node *node) | ||
184 | { | ||
185 | struct mtk_clock_event_device *evt; | ||
186 | struct resource res; | ||
187 | unsigned long rate = 0; | ||
188 | struct clk *clk; | ||
189 | |||
190 | evt = kzalloc(sizeof(*evt), GFP_KERNEL); | ||
191 | if (!evt) { | ||
192 | pr_warn("Can't allocate mtk clock event driver struct"); | ||
193 | return; | ||
194 | } | ||
195 | |||
196 | evt->dev.name = "mtk_tick"; | ||
197 | evt->dev.rating = 300; | ||
198 | evt->dev.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; | ||
199 | evt->dev.set_mode = mtk_clkevt_mode; | ||
200 | evt->dev.set_next_event = mtk_clkevt_next_event; | ||
201 | evt->dev.cpumask = cpu_possible_mask; | ||
202 | |||
203 | evt->gpt_base = of_io_request_and_map(node, 0, "mtk-timer"); | ||
204 | if (IS_ERR(evt->gpt_base)) { | ||
205 | pr_warn("Can't get resource\n"); | ||
206 | return; | ||
207 | } | ||
208 | |||
209 | evt->dev.irq = irq_of_parse_and_map(node, 0); | ||
210 | if (evt->dev.irq <= 0) { | ||
211 | pr_warn("Can't parse IRQ"); | ||
212 | goto err_mem; | ||
213 | } | ||
214 | |||
215 | clk = of_clk_get(node, 0); | ||
216 | if (IS_ERR(clk)) { | ||
217 | pr_warn("Can't get timer clock"); | ||
218 | goto err_irq; | ||
219 | } | ||
220 | |||
221 | if (clk_prepare_enable(clk)) { | ||
222 | pr_warn("Can't prepare clock"); | ||
223 | goto err_clk_put; | ||
224 | } | ||
225 | rate = clk_get_rate(clk); | ||
226 | |||
227 | if (request_irq(evt->dev.irq, mtk_timer_interrupt, | ||
228 | IRQF_TIMER | IRQF_IRQPOLL, "mtk_timer", evt)) { | ||
229 | pr_warn("failed to setup irq %d\n", evt->dev.irq); | ||
230 | goto err_clk_disable; | ||
231 | } | ||
232 | |||
233 | evt->ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); | ||
234 | |||
235 | mtk_timer_global_reset(evt); | ||
236 | |||
237 | /* Configure clock source */ | ||
238 | mtk_timer_setup(evt, GPT_CLK_SRC, TIMER_CTRL_OP_FREERUN); | ||
239 | clocksource_mmio_init(evt->gpt_base + TIMER_CNT_REG(GPT_CLK_SRC), | ||
240 | node->name, rate, 300, 32, clocksource_mmio_readl_up); | ||
241 | |||
242 | /* Configure clock event */ | ||
243 | mtk_timer_setup(evt, GPT_CLK_EVT, TIMER_CTRL_OP_REPEAT); | ||
244 | mtk_timer_enable_irq(evt, GPT_CLK_EVT); | ||
245 | |||
246 | clockevents_config_and_register(&evt->dev, rate, 0x3, | ||
247 | 0xffffffff); | ||
248 | return; | ||
249 | |||
250 | err_clk_disable: | ||
251 | clk_disable_unprepare(clk); | ||
252 | err_clk_put: | ||
253 | clk_put(clk); | ||
254 | err_irq: | ||
255 | irq_dispose_mapping(evt->dev.irq); | ||
256 | err_mem: | ||
257 | iounmap(evt->gpt_base); | ||
258 | of_address_to_resource(node, 0, &res); | ||
259 | release_mem_region(res.start, resource_size(&res)); | ||
260 | } | ||
261 | CLOCKSOURCE_OF_DECLARE(mtk_mt6577, "mediatek,mt6577-timer", mtk_timer_init); | ||
diff --git a/drivers/clocksource/pxa_timer.c b/drivers/clocksource/pxa_timer.c new file mode 100644 index 000000000000..941f3f344e08 --- /dev/null +++ b/drivers/clocksource/pxa_timer.c | |||
@@ -0,0 +1,227 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-pxa/time.c | ||
3 | * | ||
4 | * PXA clocksource, clockevents, and OST interrupt handlers. | ||
5 | * Copyright (c) 2007 by Bill Gatliff <bgat@billgatliff.com>. | ||
6 | * | ||
7 | * Derived from Nicolas Pitre's PXA timer handler Copyright (c) 2001 | ||
8 | * by MontaVista Software, Inc. (Nico, your code rocks!) | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/clockchips.h> | ||
20 | #include <linux/of_address.h> | ||
21 | #include <linux/of_irq.h> | ||
22 | #include <linux/sched_clock.h> | ||
23 | |||
24 | #include <asm/div64.h> | ||
25 | |||
26 | #define OSMR0 0x00 /* OS Timer 0 Match Register */ | ||
27 | #define OSMR1 0x04 /* OS Timer 1 Match Register */ | ||
28 | #define OSMR2 0x08 /* OS Timer 2 Match Register */ | ||
29 | #define OSMR3 0x0C /* OS Timer 3 Match Register */ | ||
30 | |||
31 | #define OSCR 0x10 /* OS Timer Counter Register */ | ||
32 | #define OSSR 0x14 /* OS Timer Status Register */ | ||
33 | #define OWER 0x18 /* OS Timer Watchdog Enable Register */ | ||
34 | #define OIER 0x1C /* OS Timer Interrupt Enable Register */ | ||
35 | |||
36 | #define OSSR_M3 (1 << 3) /* Match status channel 3 */ | ||
37 | #define OSSR_M2 (1 << 2) /* Match status channel 2 */ | ||
38 | #define OSSR_M1 (1 << 1) /* Match status channel 1 */ | ||
39 | #define OSSR_M0 (1 << 0) /* Match status channel 0 */ | ||
40 | |||
41 | #define OIER_E0 (1 << 0) /* Interrupt enable channel 0 */ | ||
42 | |||
43 | /* | ||
44 | * This is PXA's sched_clock implementation. This has a resolution | ||
45 | * of at least 308 ns and a maximum value of 208 days. | ||
46 | * | ||
47 | * The return value is guaranteed to be monotonic in that range as | ||
48 | * long as there is always less than 582 seconds between successive | ||
49 | * calls to sched_clock() which should always be the case in practice. | ||
50 | */ | ||
51 | |||
52 | #define timer_readl(reg) readl_relaxed(timer_base + (reg)) | ||
53 | #define timer_writel(val, reg) writel_relaxed((val), timer_base + (reg)) | ||
54 | |||
55 | static void __iomem *timer_base; | ||
56 | |||
57 | static u64 notrace pxa_read_sched_clock(void) | ||
58 | { | ||
59 | return timer_readl(OSCR); | ||
60 | } | ||
61 | |||
62 | |||
63 | #define MIN_OSCR_DELTA 16 | ||
64 | |||
65 | static irqreturn_t | ||
66 | pxa_ost0_interrupt(int irq, void *dev_id) | ||
67 | { | ||
68 | struct clock_event_device *c = dev_id; | ||
69 | |||
70 | /* Disarm the compare/match, signal the event. */ | ||
71 | timer_writel(timer_readl(OIER) & ~OIER_E0, OIER); | ||
72 | timer_writel(OSSR_M0, OSSR); | ||
73 | c->event_handler(c); | ||
74 | |||
75 | return IRQ_HANDLED; | ||
76 | } | ||
77 | |||
78 | static int | ||
79 | pxa_osmr0_set_next_event(unsigned long delta, struct clock_event_device *dev) | ||
80 | { | ||
81 | unsigned long next, oscr; | ||
82 | |||
83 | timer_writel(timer_readl(OIER) | OIER_E0, OIER); | ||
84 | next = timer_readl(OSCR) + delta; | ||
85 | timer_writel(next, OSMR0); | ||
86 | oscr = timer_readl(OSCR); | ||
87 | |||
88 | return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0; | ||
89 | } | ||
90 | |||
91 | static void | ||
92 | pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev) | ||
93 | { | ||
94 | switch (mode) { | ||
95 | case CLOCK_EVT_MODE_ONESHOT: | ||
96 | timer_writel(timer_readl(OIER) & ~OIER_E0, OIER); | ||
97 | timer_writel(OSSR_M0, OSSR); | ||
98 | break; | ||
99 | |||
100 | case CLOCK_EVT_MODE_UNUSED: | ||
101 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
102 | /* initializing, released, or preparing for suspend */ | ||
103 | timer_writel(timer_readl(OIER) & ~OIER_E0, OIER); | ||
104 | timer_writel(OSSR_M0, OSSR); | ||
105 | break; | ||
106 | |||
107 | case CLOCK_EVT_MODE_RESUME: | ||
108 | case CLOCK_EVT_MODE_PERIODIC: | ||
109 | break; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | #ifdef CONFIG_PM | ||
114 | static unsigned long osmr[4], oier, oscr; | ||
115 | |||
116 | static void pxa_timer_suspend(struct clock_event_device *cedev) | ||
117 | { | ||
118 | osmr[0] = timer_readl(OSMR0); | ||
119 | osmr[1] = timer_readl(OSMR1); | ||
120 | osmr[2] = timer_readl(OSMR2); | ||
121 | osmr[3] = timer_readl(OSMR3); | ||
122 | oier = timer_readl(OIER); | ||
123 | oscr = timer_readl(OSCR); | ||
124 | } | ||
125 | |||
126 | static void pxa_timer_resume(struct clock_event_device *cedev) | ||
127 | { | ||
128 | /* | ||
129 | * Ensure that we have at least MIN_OSCR_DELTA between match | ||
130 | * register 0 and the OSCR, to guarantee that we will receive | ||
131 | * the one-shot timer interrupt. We adjust OSMR0 in preference | ||
132 | * to OSCR to guarantee that OSCR is monotonically incrementing. | ||
133 | */ | ||
134 | if (osmr[0] - oscr < MIN_OSCR_DELTA) | ||
135 | osmr[0] += MIN_OSCR_DELTA; | ||
136 | |||
137 | timer_writel(osmr[0], OSMR0); | ||
138 | timer_writel(osmr[1], OSMR1); | ||
139 | timer_writel(osmr[2], OSMR2); | ||
140 | timer_writel(osmr[3], OSMR3); | ||
141 | timer_writel(oier, OIER); | ||
142 | timer_writel(oscr, OSCR); | ||
143 | } | ||
144 | #else | ||
145 | #define pxa_timer_suspend NULL | ||
146 | #define pxa_timer_resume NULL | ||
147 | #endif | ||
148 | |||
149 | static struct clock_event_device ckevt_pxa_osmr0 = { | ||
150 | .name = "osmr0", | ||
151 | .features = CLOCK_EVT_FEAT_ONESHOT, | ||
152 | .rating = 200, | ||
153 | .set_next_event = pxa_osmr0_set_next_event, | ||
154 | .set_mode = pxa_osmr0_set_mode, | ||
155 | .suspend = pxa_timer_suspend, | ||
156 | .resume = pxa_timer_resume, | ||
157 | }; | ||
158 | |||
159 | static struct irqaction pxa_ost0_irq = { | ||
160 | .name = "ost0", | ||
161 | .flags = IRQF_TIMER | IRQF_IRQPOLL, | ||
162 | .handler = pxa_ost0_interrupt, | ||
163 | .dev_id = &ckevt_pxa_osmr0, | ||
164 | }; | ||
165 | |||
166 | static void pxa_timer_common_init(int irq, unsigned long clock_tick_rate) | ||
167 | { | ||
168 | timer_writel(0, OIER); | ||
169 | timer_writel(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR); | ||
170 | |||
171 | sched_clock_register(pxa_read_sched_clock, 32, clock_tick_rate); | ||
172 | |||
173 | ckevt_pxa_osmr0.cpumask = cpumask_of(0); | ||
174 | |||
175 | setup_irq(irq, &pxa_ost0_irq); | ||
176 | |||
177 | clocksource_mmio_init(timer_base + OSCR, "oscr0", clock_tick_rate, 200, | ||
178 | 32, clocksource_mmio_readl_up); | ||
179 | clockevents_config_and_register(&ckevt_pxa_osmr0, clock_tick_rate, | ||
180 | MIN_OSCR_DELTA * 2, 0x7fffffff); | ||
181 | } | ||
182 | |||
183 | static void __init pxa_timer_dt_init(struct device_node *np) | ||
184 | { | ||
185 | struct clk *clk; | ||
186 | int irq; | ||
187 | |||
188 | /* timer registers are shared with watchdog timer */ | ||
189 | timer_base = of_iomap(np, 0); | ||
190 | if (!timer_base) | ||
191 | panic("%s: unable to map resource\n", np->name); | ||
192 | |||
193 | clk = of_clk_get(np, 0); | ||
194 | if (IS_ERR(clk)) { | ||
195 | pr_crit("%s: unable to get clk\n", np->name); | ||
196 | return; | ||
197 | } | ||
198 | clk_prepare_enable(clk); | ||
199 | |||
200 | /* we are only interested in OS-timer0 irq */ | ||
201 | irq = irq_of_parse_and_map(np, 0); | ||
202 | if (irq <= 0) { | ||
203 | pr_crit("%s: unable to parse OS-timer0 irq\n", np->name); | ||
204 | return; | ||
205 | } | ||
206 | |||
207 | pxa_timer_common_init(irq, clk_get_rate(clk)); | ||
208 | } | ||
209 | CLOCKSOURCE_OF_DECLARE(pxa_timer, "marvell,pxa-timer", pxa_timer_dt_init); | ||
210 | |||
211 | /* | ||
212 | * Legacy timer init for non device-tree boards. | ||
213 | */ | ||
214 | void __init pxa_timer_nodt_init(int irq, void __iomem *base, | ||
215 | unsigned long clock_tick_rate) | ||
216 | { | ||
217 | struct clk *clk; | ||
218 | |||
219 | timer_base = base; | ||
220 | clk = clk_get(NULL, "OSTIMER0"); | ||
221 | if (clk && !IS_ERR(clk)) | ||
222 | clk_prepare_enable(clk); | ||
223 | else | ||
224 | pr_crit("%s: unable to get clk\n", __func__); | ||
225 | |||
226 | pxa_timer_common_init(irq, clock_tick_rate); | ||
227 | } | ||
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index dfa780396b91..2bd13b53b727 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/ioport.h> | 24 | #include <linux/ioport.h> |
25 | #include <linux/irq.h> | 25 | #include <linux/irq.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/of.h> | ||
27 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
28 | #include <linux/pm_domain.h> | 29 | #include <linux/pm_domain.h> |
29 | #include <linux/pm_runtime.h> | 30 | #include <linux/pm_runtime.h> |
@@ -114,14 +115,15 @@ struct sh_cmt_device { | |||
114 | struct platform_device *pdev; | 115 | struct platform_device *pdev; |
115 | 116 | ||
116 | const struct sh_cmt_info *info; | 117 | const struct sh_cmt_info *info; |
117 | bool legacy; | ||
118 | 118 | ||
119 | void __iomem *mapbase_ch; | ||
120 | void __iomem *mapbase; | 119 | void __iomem *mapbase; |
121 | struct clk *clk; | 120 | struct clk *clk; |
122 | 121 | ||
122 | raw_spinlock_t lock; /* Protect the shared start/stop register */ | ||
123 | |||
123 | struct sh_cmt_channel *channels; | 124 | struct sh_cmt_channel *channels; |
124 | unsigned int num_channels; | 125 | unsigned int num_channels; |
126 | unsigned int hw_channels; | ||
125 | 127 | ||
126 | bool has_clockevent; | 128 | bool has_clockevent; |
127 | bool has_clocksource; | 129 | bool has_clocksource; |
@@ -301,14 +303,12 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_channel *ch, | |||
301 | return v2; | 303 | return v2; |
302 | } | 304 | } |
303 | 305 | ||
304 | static DEFINE_RAW_SPINLOCK(sh_cmt_lock); | ||
305 | |||
306 | static void sh_cmt_start_stop_ch(struct sh_cmt_channel *ch, int start) | 306 | static void sh_cmt_start_stop_ch(struct sh_cmt_channel *ch, int start) |
307 | { | 307 | { |
308 | unsigned long flags, value; | 308 | unsigned long flags, value; |
309 | 309 | ||
310 | /* start stop register shared by multiple timer channels */ | 310 | /* start stop register shared by multiple timer channels */ |
311 | raw_spin_lock_irqsave(&sh_cmt_lock, flags); | 311 | raw_spin_lock_irqsave(&ch->cmt->lock, flags); |
312 | value = sh_cmt_read_cmstr(ch); | 312 | value = sh_cmt_read_cmstr(ch); |
313 | 313 | ||
314 | if (start) | 314 | if (start) |
@@ -317,7 +317,7 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_channel *ch, int start) | |||
317 | value &= ~(1 << ch->timer_bit); | 317 | value &= ~(1 << ch->timer_bit); |
318 | 318 | ||
319 | sh_cmt_write_cmstr(ch, value); | 319 | sh_cmt_write_cmstr(ch, value); |
320 | raw_spin_unlock_irqrestore(&sh_cmt_lock, flags); | 320 | raw_spin_unlock_irqrestore(&ch->cmt->lock, flags); |
321 | } | 321 | } |
322 | 322 | ||
323 | static int sh_cmt_enable(struct sh_cmt_channel *ch, unsigned long *rate) | 323 | static int sh_cmt_enable(struct sh_cmt_channel *ch, unsigned long *rate) |
@@ -792,7 +792,7 @@ static int sh_cmt_register_clockevent(struct sh_cmt_channel *ch, | |||
792 | int irq; | 792 | int irq; |
793 | int ret; | 793 | int ret; |
794 | 794 | ||
795 | irq = platform_get_irq(ch->cmt->pdev, ch->cmt->legacy ? 0 : ch->index); | 795 | irq = platform_get_irq(ch->cmt->pdev, ch->index); |
796 | if (irq < 0) { | 796 | if (irq < 0) { |
797 | dev_err(&ch->cmt->pdev->dev, "ch%u: failed to get irq\n", | 797 | dev_err(&ch->cmt->pdev->dev, "ch%u: failed to get irq\n", |
798 | ch->index); | 798 | ch->index); |
@@ -863,33 +863,26 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index, | |||
863 | * Compute the address of the channel control register block. For the | 863 | * Compute the address of the channel control register block. For the |
864 | * timers with a per-channel start/stop register, compute its address | 864 | * timers with a per-channel start/stop register, compute its address |
865 | * as well. | 865 | * as well. |
866 | * | ||
867 | * For legacy configuration the address has been mapped explicitly. | ||
868 | */ | 866 | */ |
869 | if (cmt->legacy) { | 867 | switch (cmt->info->model) { |
870 | ch->ioctrl = cmt->mapbase_ch; | 868 | case SH_CMT_16BIT: |
871 | } else { | 869 | ch->ioctrl = cmt->mapbase + 2 + ch->hwidx * 6; |
872 | switch (cmt->info->model) { | 870 | break; |
873 | case SH_CMT_16BIT: | 871 | case SH_CMT_32BIT: |
874 | ch->ioctrl = cmt->mapbase + 2 + ch->hwidx * 6; | 872 | case SH_CMT_48BIT: |
875 | break; | 873 | ch->ioctrl = cmt->mapbase + 0x10 + ch->hwidx * 0x10; |
876 | case SH_CMT_32BIT: | 874 | break; |
877 | case SH_CMT_48BIT: | 875 | case SH_CMT_32BIT_FAST: |
878 | ch->ioctrl = cmt->mapbase + 0x10 + ch->hwidx * 0x10; | 876 | /* |
879 | break; | 877 | * The 32-bit "fast" timer has a single channel at hwidx 5 but |
880 | case SH_CMT_32BIT_FAST: | 878 | * is located at offset 0x40 instead of 0x60 for some reason. |
881 | /* | 879 | */ |
882 | * The 32-bit "fast" timer has a single channel at hwidx | 880 | ch->ioctrl = cmt->mapbase + 0x40; |
883 | * 5 but is located at offset 0x40 instead of 0x60 for | 881 | break; |
884 | * some reason. | 882 | case SH_CMT_48BIT_GEN2: |
885 | */ | 883 | ch->iostart = cmt->mapbase + ch->hwidx * 0x100; |
886 | ch->ioctrl = cmt->mapbase + 0x40; | 884 | ch->ioctrl = ch->iostart + 0x10; |
887 | break; | 885 | break; |
888 | case SH_CMT_48BIT_GEN2: | ||
889 | ch->iostart = cmt->mapbase + ch->hwidx * 0x100; | ||
890 | ch->ioctrl = ch->iostart + 0x10; | ||
891 | break; | ||
892 | } | ||
893 | } | 886 | } |
894 | 887 | ||
895 | if (cmt->info->width == (sizeof(ch->max_match_value) * 8)) | 888 | if (cmt->info->width == (sizeof(ch->max_match_value) * 8)) |
@@ -900,12 +893,7 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index, | |||
900 | ch->match_value = ch->max_match_value; | 893 | ch->match_value = ch->max_match_value; |
901 | raw_spin_lock_init(&ch->lock); | 894 | raw_spin_lock_init(&ch->lock); |
902 | 895 | ||
903 | if (cmt->legacy) { | 896 | ch->timer_bit = cmt->info->model == SH_CMT_48BIT_GEN2 ? 0 : ch->hwidx; |
904 | ch->timer_bit = ch->hwidx; | ||
905 | } else { | ||
906 | ch->timer_bit = cmt->info->model == SH_CMT_48BIT_GEN2 | ||
907 | ? 0 : ch->hwidx; | ||
908 | } | ||
909 | 897 | ||
910 | ret = sh_cmt_register(ch, dev_name(&cmt->pdev->dev), | 898 | ret = sh_cmt_register(ch, dev_name(&cmt->pdev->dev), |
911 | clockevent, clocksource); | 899 | clockevent, clocksource); |
@@ -938,75 +926,65 @@ static int sh_cmt_map_memory(struct sh_cmt_device *cmt) | |||
938 | return 0; | 926 | return 0; |
939 | } | 927 | } |
940 | 928 | ||
941 | static int sh_cmt_map_memory_legacy(struct sh_cmt_device *cmt) | 929 | static const struct platform_device_id sh_cmt_id_table[] = { |
942 | { | 930 | { "sh-cmt-16", (kernel_ulong_t)&sh_cmt_info[SH_CMT_16BIT] }, |
943 | struct sh_timer_config *cfg = cmt->pdev->dev.platform_data; | 931 | { "sh-cmt-32", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT] }, |
944 | struct resource *res, *res2; | 932 | { "sh-cmt-32-fast", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT_FAST] }, |
945 | 933 | { "sh-cmt-48", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT] }, | |
946 | /* map memory, let mapbase_ch point to our channel */ | 934 | { "sh-cmt-48-gen2", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT_GEN2] }, |
947 | res = platform_get_resource(cmt->pdev, IORESOURCE_MEM, 0); | 935 | { } |
948 | if (!res) { | 936 | }; |
949 | dev_err(&cmt->pdev->dev, "failed to get I/O memory\n"); | 937 | MODULE_DEVICE_TABLE(platform, sh_cmt_id_table); |
950 | return -ENXIO; | ||
951 | } | ||
952 | |||
953 | cmt->mapbase_ch = ioremap_nocache(res->start, resource_size(res)); | ||
954 | if (cmt->mapbase_ch == NULL) { | ||
955 | dev_err(&cmt->pdev->dev, "failed to remap I/O memory\n"); | ||
956 | return -ENXIO; | ||
957 | } | ||
958 | |||
959 | /* optional resource for the shared timer start/stop register */ | ||
960 | res2 = platform_get_resource(cmt->pdev, IORESOURCE_MEM, 1); | ||
961 | |||
962 | /* map second resource for CMSTR */ | ||
963 | cmt->mapbase = ioremap_nocache(res2 ? res2->start : | ||
964 | res->start - cfg->channel_offset, | ||
965 | res2 ? resource_size(res2) : 2); | ||
966 | if (cmt->mapbase == NULL) { | ||
967 | dev_err(&cmt->pdev->dev, "failed to remap I/O second memory\n"); | ||
968 | iounmap(cmt->mapbase_ch); | ||
969 | return -ENXIO; | ||
970 | } | ||
971 | |||
972 | /* identify the model based on the resources */ | ||
973 | if (resource_size(res) == 6) | ||
974 | cmt->info = &sh_cmt_info[SH_CMT_16BIT]; | ||
975 | else if (res2 && (resource_size(res2) == 4)) | ||
976 | cmt->info = &sh_cmt_info[SH_CMT_48BIT_GEN2]; | ||
977 | else | ||
978 | cmt->info = &sh_cmt_info[SH_CMT_32BIT]; | ||
979 | 938 | ||
980 | return 0; | 939 | static const struct of_device_id sh_cmt_of_table[] __maybe_unused = { |
981 | } | 940 | { .compatible = "renesas,cmt-32", .data = &sh_cmt_info[SH_CMT_32BIT] }, |
941 | { .compatible = "renesas,cmt-32-fast", .data = &sh_cmt_info[SH_CMT_32BIT_FAST] }, | ||
942 | { .compatible = "renesas,cmt-48", .data = &sh_cmt_info[SH_CMT_48BIT] }, | ||
943 | { .compatible = "renesas,cmt-48-gen2", .data = &sh_cmt_info[SH_CMT_48BIT_GEN2] }, | ||
944 | { } | ||
945 | }; | ||
946 | MODULE_DEVICE_TABLE(of, sh_cmt_of_table); | ||
982 | 947 | ||
983 | static void sh_cmt_unmap_memory(struct sh_cmt_device *cmt) | 948 | static int sh_cmt_parse_dt(struct sh_cmt_device *cmt) |
984 | { | 949 | { |
985 | iounmap(cmt->mapbase); | 950 | struct device_node *np = cmt->pdev->dev.of_node; |
986 | if (cmt->mapbase_ch) | 951 | |
987 | iounmap(cmt->mapbase_ch); | 952 | return of_property_read_u32(np, "renesas,channels-mask", |
953 | &cmt->hw_channels); | ||
988 | } | 954 | } |
989 | 955 | ||
990 | static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev) | 956 | static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev) |
991 | { | 957 | { |
992 | struct sh_timer_config *cfg = pdev->dev.platform_data; | 958 | unsigned int mask; |
993 | const struct platform_device_id *id = pdev->id_entry; | 959 | unsigned int i; |
994 | unsigned int hw_channels; | ||
995 | int ret; | 960 | int ret; |
996 | 961 | ||
997 | memset(cmt, 0, sizeof(*cmt)); | 962 | memset(cmt, 0, sizeof(*cmt)); |
998 | cmt->pdev = pdev; | 963 | cmt->pdev = pdev; |
964 | raw_spin_lock_init(&cmt->lock); | ||
965 | |||
966 | if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { | ||
967 | const struct of_device_id *id; | ||
968 | |||
969 | id = of_match_node(sh_cmt_of_table, pdev->dev.of_node); | ||
970 | cmt->info = id->data; | ||
999 | 971 | ||
1000 | if (!cfg) { | 972 | ret = sh_cmt_parse_dt(cmt); |
973 | if (ret < 0) | ||
974 | return ret; | ||
975 | } else if (pdev->dev.platform_data) { | ||
976 | struct sh_timer_config *cfg = pdev->dev.platform_data; | ||
977 | const struct platform_device_id *id = pdev->id_entry; | ||
978 | |||
979 | cmt->info = (const struct sh_cmt_info *)id->driver_data; | ||
980 | cmt->hw_channels = cfg->channels_mask; | ||
981 | } else { | ||
1001 | dev_err(&cmt->pdev->dev, "missing platform data\n"); | 982 | dev_err(&cmt->pdev->dev, "missing platform data\n"); |
1002 | return -ENXIO; | 983 | return -ENXIO; |
1003 | } | 984 | } |
1004 | 985 | ||
1005 | cmt->info = (const struct sh_cmt_info *)id->driver_data; | ||
1006 | cmt->legacy = cmt->info ? false : true; | ||
1007 | |||
1008 | /* Get hold of clock. */ | 986 | /* Get hold of clock. */ |
1009 | cmt->clk = clk_get(&cmt->pdev->dev, cmt->legacy ? "cmt_fck" : "fck"); | 987 | cmt->clk = clk_get(&cmt->pdev->dev, "fck"); |
1010 | if (IS_ERR(cmt->clk)) { | 988 | if (IS_ERR(cmt->clk)) { |
1011 | dev_err(&cmt->pdev->dev, "cannot get clock\n"); | 989 | dev_err(&cmt->pdev->dev, "cannot get clock\n"); |
1012 | return PTR_ERR(cmt->clk); | 990 | return PTR_ERR(cmt->clk); |
@@ -1016,28 +994,13 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev) | |||
1016 | if (ret < 0) | 994 | if (ret < 0) |
1017 | goto err_clk_put; | 995 | goto err_clk_put; |
1018 | 996 | ||
1019 | /* | 997 | /* Map the memory resource(s). */ |
1020 | * Map the memory resource(s). We need to support both the legacy | 998 | ret = sh_cmt_map_memory(cmt); |
1021 | * platform device configuration (with one device per channel) and the | ||
1022 | * new version (with multiple channels per device). | ||
1023 | */ | ||
1024 | if (cmt->legacy) | ||
1025 | ret = sh_cmt_map_memory_legacy(cmt); | ||
1026 | else | ||
1027 | ret = sh_cmt_map_memory(cmt); | ||
1028 | |||
1029 | if (ret < 0) | 999 | if (ret < 0) |
1030 | goto err_clk_unprepare; | 1000 | goto err_clk_unprepare; |
1031 | 1001 | ||
1032 | /* Allocate and setup the channels. */ | 1002 | /* Allocate and setup the channels. */ |
1033 | if (cmt->legacy) { | 1003 | cmt->num_channels = hweight8(cmt->hw_channels); |
1034 | cmt->num_channels = 1; | ||
1035 | hw_channels = 0; | ||
1036 | } else { | ||
1037 | cmt->num_channels = hweight8(cfg->channels_mask); | ||
1038 | hw_channels = cfg->channels_mask; | ||
1039 | } | ||
1040 | |||
1041 | cmt->channels = kzalloc(cmt->num_channels * sizeof(*cmt->channels), | 1004 | cmt->channels = kzalloc(cmt->num_channels * sizeof(*cmt->channels), |
1042 | GFP_KERNEL); | 1005 | GFP_KERNEL); |
1043 | if (cmt->channels == NULL) { | 1006 | if (cmt->channels == NULL) { |
@@ -1045,35 +1008,21 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev) | |||
1045 | goto err_unmap; | 1008 | goto err_unmap; |
1046 | } | 1009 | } |
1047 | 1010 | ||
1048 | if (cmt->legacy) { | 1011 | /* |
1049 | ret = sh_cmt_setup_channel(&cmt->channels[0], | 1012 | * Use the first channel as a clock event device and the second channel |
1050 | cfg->timer_bit, cfg->timer_bit, | 1013 | * as a clock source. If only one channel is available use it for both. |
1051 | cfg->clockevent_rating != 0, | 1014 | */ |
1052 | cfg->clocksource_rating != 0, cmt); | 1015 | for (i = 0, mask = cmt->hw_channels; i < cmt->num_channels; ++i) { |
1016 | unsigned int hwidx = ffs(mask) - 1; | ||
1017 | bool clocksource = i == 1 || cmt->num_channels == 1; | ||
1018 | bool clockevent = i == 0; | ||
1019 | |||
1020 | ret = sh_cmt_setup_channel(&cmt->channels[i], i, hwidx, | ||
1021 | clockevent, clocksource, cmt); | ||
1053 | if (ret < 0) | 1022 | if (ret < 0) |
1054 | goto err_unmap; | 1023 | goto err_unmap; |
1055 | } else { | ||
1056 | unsigned int mask = hw_channels; | ||
1057 | unsigned int i; | ||
1058 | 1024 | ||
1059 | /* | 1025 | mask &= ~(1 << hwidx); |
1060 | * Use the first channel as a clock event device and the second | ||
1061 | * channel as a clock source. If only one channel is available | ||
1062 | * use it for both. | ||
1063 | */ | ||
1064 | for (i = 0; i < cmt->num_channels; ++i) { | ||
1065 | unsigned int hwidx = ffs(mask) - 1; | ||
1066 | bool clocksource = i == 1 || cmt->num_channels == 1; | ||
1067 | bool clockevent = i == 0; | ||
1068 | |||
1069 | ret = sh_cmt_setup_channel(&cmt->channels[i], i, hwidx, | ||
1070 | clockevent, clocksource, | ||
1071 | cmt); | ||
1072 | if (ret < 0) | ||
1073 | goto err_unmap; | ||
1074 | |||
1075 | mask &= ~(1 << hwidx); | ||
1076 | } | ||
1077 | } | 1026 | } |
1078 | 1027 | ||
1079 | platform_set_drvdata(pdev, cmt); | 1028 | platform_set_drvdata(pdev, cmt); |
@@ -1082,7 +1031,7 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev) | |||
1082 | 1031 | ||
1083 | err_unmap: | 1032 | err_unmap: |
1084 | kfree(cmt->channels); | 1033 | kfree(cmt->channels); |
1085 | sh_cmt_unmap_memory(cmt); | 1034 | iounmap(cmt->mapbase); |
1086 | err_clk_unprepare: | 1035 | err_clk_unprepare: |
1087 | clk_unprepare(cmt->clk); | 1036 | clk_unprepare(cmt->clk); |
1088 | err_clk_put: | 1037 | err_clk_put: |
@@ -1132,22 +1081,12 @@ static int sh_cmt_remove(struct platform_device *pdev) | |||
1132 | return -EBUSY; /* cannot unregister clockevent and clocksource */ | 1081 | return -EBUSY; /* cannot unregister clockevent and clocksource */ |
1133 | } | 1082 | } |
1134 | 1083 | ||
1135 | static const struct platform_device_id sh_cmt_id_table[] = { | ||
1136 | { "sh_cmt", 0 }, | ||
1137 | { "sh-cmt-16", (kernel_ulong_t)&sh_cmt_info[SH_CMT_16BIT] }, | ||
1138 | { "sh-cmt-32", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT] }, | ||
1139 | { "sh-cmt-32-fast", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT_FAST] }, | ||
1140 | { "sh-cmt-48", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT] }, | ||
1141 | { "sh-cmt-48-gen2", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT_GEN2] }, | ||
1142 | { } | ||
1143 | }; | ||
1144 | MODULE_DEVICE_TABLE(platform, sh_cmt_id_table); | ||
1145 | |||
1146 | static struct platform_driver sh_cmt_device_driver = { | 1084 | static struct platform_driver sh_cmt_device_driver = { |
1147 | .probe = sh_cmt_probe, | 1085 | .probe = sh_cmt_probe, |
1148 | .remove = sh_cmt_remove, | 1086 | .remove = sh_cmt_remove, |
1149 | .driver = { | 1087 | .driver = { |
1150 | .name = "sh_cmt", | 1088 | .name = "sh_cmt", |
1089 | .of_match_table = of_match_ptr(sh_cmt_of_table), | ||
1151 | }, | 1090 | }, |
1152 | .id_table = sh_cmt_id_table, | 1091 | .id_table = sh_cmt_id_table, |
1153 | }; | 1092 | }; |
diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index 188d4e092efc..3d88698cf2b8 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/ioport.h> | 23 | #include <linux/ioport.h> |
24 | #include <linux/irq.h> | 24 | #include <linux/irq.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/of.h> | ||
26 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
27 | #include <linux/pm_domain.h> | 28 | #include <linux/pm_domain.h> |
28 | #include <linux/pm_runtime.h> | 29 | #include <linux/pm_runtime.h> |
@@ -37,7 +38,6 @@ struct sh_mtu2_channel { | |||
37 | unsigned int index; | 38 | unsigned int index; |
38 | 39 | ||
39 | void __iomem *base; | 40 | void __iomem *base; |
40 | int irq; | ||
41 | 41 | ||
42 | struct clock_event_device ced; | 42 | struct clock_event_device ced; |
43 | }; | 43 | }; |
@@ -48,15 +48,14 @@ struct sh_mtu2_device { | |||
48 | void __iomem *mapbase; | 48 | void __iomem *mapbase; |
49 | struct clk *clk; | 49 | struct clk *clk; |
50 | 50 | ||
51 | raw_spinlock_t lock; /* Protect the shared registers */ | ||
52 | |||
51 | struct sh_mtu2_channel *channels; | 53 | struct sh_mtu2_channel *channels; |
52 | unsigned int num_channels; | 54 | unsigned int num_channels; |
53 | 55 | ||
54 | bool legacy; | ||
55 | bool has_clockevent; | 56 | bool has_clockevent; |
56 | }; | 57 | }; |
57 | 58 | ||
58 | static DEFINE_RAW_SPINLOCK(sh_mtu2_lock); | ||
59 | |||
60 | #define TSTR -1 /* shared register */ | 59 | #define TSTR -1 /* shared register */ |
61 | #define TCR 0 /* channel register */ | 60 | #define TCR 0 /* channel register */ |
62 | #define TMDR 1 /* channel register */ | 61 | #define TMDR 1 /* channel register */ |
@@ -162,12 +161,8 @@ static inline unsigned long sh_mtu2_read(struct sh_mtu2_channel *ch, int reg_nr) | |||
162 | { | 161 | { |
163 | unsigned long offs; | 162 | unsigned long offs; |
164 | 163 | ||
165 | if (reg_nr == TSTR) { | 164 | if (reg_nr == TSTR) |
166 | if (ch->mtu->legacy) | 165 | return ioread8(ch->mtu->mapbase + 0x280); |
167 | return ioread8(ch->mtu->mapbase); | ||
168 | else | ||
169 | return ioread8(ch->mtu->mapbase + 0x280); | ||
170 | } | ||
171 | 166 | ||
172 | offs = mtu2_reg_offs[reg_nr]; | 167 | offs = mtu2_reg_offs[reg_nr]; |
173 | 168 | ||
@@ -182,12 +177,8 @@ static inline void sh_mtu2_write(struct sh_mtu2_channel *ch, int reg_nr, | |||
182 | { | 177 | { |
183 | unsigned long offs; | 178 | unsigned long offs; |
184 | 179 | ||
185 | if (reg_nr == TSTR) { | 180 | if (reg_nr == TSTR) |
186 | if (ch->mtu->legacy) | 181 | return iowrite8(value, ch->mtu->mapbase + 0x280); |
187 | return iowrite8(value, ch->mtu->mapbase); | ||
188 | else | ||
189 | return iowrite8(value, ch->mtu->mapbase + 0x280); | ||
190 | } | ||
191 | 182 | ||
192 | offs = mtu2_reg_offs[reg_nr]; | 183 | offs = mtu2_reg_offs[reg_nr]; |
193 | 184 | ||
@@ -202,7 +193,7 @@ static void sh_mtu2_start_stop_ch(struct sh_mtu2_channel *ch, int start) | |||
202 | unsigned long flags, value; | 193 | unsigned long flags, value; |
203 | 194 | ||
204 | /* start stop register shared by multiple timer channels */ | 195 | /* start stop register shared by multiple timer channels */ |
205 | raw_spin_lock_irqsave(&sh_mtu2_lock, flags); | 196 | raw_spin_lock_irqsave(&ch->mtu->lock, flags); |
206 | value = sh_mtu2_read(ch, TSTR); | 197 | value = sh_mtu2_read(ch, TSTR); |
207 | 198 | ||
208 | if (start) | 199 | if (start) |
@@ -211,7 +202,7 @@ static void sh_mtu2_start_stop_ch(struct sh_mtu2_channel *ch, int start) | |||
211 | value &= ~(1 << ch->index); | 202 | value &= ~(1 << ch->index); |
212 | 203 | ||
213 | sh_mtu2_write(ch, TSTR, value); | 204 | sh_mtu2_write(ch, TSTR, value); |
214 | raw_spin_unlock_irqrestore(&sh_mtu2_lock, flags); | 205 | raw_spin_unlock_irqrestore(&ch->mtu->lock, flags); |
215 | } | 206 | } |
216 | 207 | ||
217 | static int sh_mtu2_enable(struct sh_mtu2_channel *ch) | 208 | static int sh_mtu2_enable(struct sh_mtu2_channel *ch) |
@@ -331,7 +322,6 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_channel *ch, | |||
331 | const char *name) | 322 | const char *name) |
332 | { | 323 | { |
333 | struct clock_event_device *ced = &ch->ced; | 324 | struct clock_event_device *ced = &ch->ced; |
334 | int ret; | ||
335 | 325 | ||
336 | ced->name = name; | 326 | ced->name = name; |
337 | ced->features = CLOCK_EVT_FEAT_PERIODIC; | 327 | ced->features = CLOCK_EVT_FEAT_PERIODIC; |
@@ -344,24 +334,12 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_channel *ch, | |||
344 | dev_info(&ch->mtu->pdev->dev, "ch%u: used for clock events\n", | 334 | dev_info(&ch->mtu->pdev->dev, "ch%u: used for clock events\n", |
345 | ch->index); | 335 | ch->index); |
346 | clockevents_register_device(ced); | 336 | clockevents_register_device(ced); |
347 | |||
348 | ret = request_irq(ch->irq, sh_mtu2_interrupt, | ||
349 | IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING, | ||
350 | dev_name(&ch->mtu->pdev->dev), ch); | ||
351 | if (ret) { | ||
352 | dev_err(&ch->mtu->pdev->dev, "ch%u: failed to request irq %d\n", | ||
353 | ch->index, ch->irq); | ||
354 | return; | ||
355 | } | ||
356 | } | 337 | } |
357 | 338 | ||
358 | static int sh_mtu2_register(struct sh_mtu2_channel *ch, const char *name, | 339 | static int sh_mtu2_register(struct sh_mtu2_channel *ch, const char *name) |
359 | bool clockevent) | ||
360 | { | 340 | { |
361 | if (clockevent) { | 341 | ch->mtu->has_clockevent = true; |
362 | ch->mtu->has_clockevent = true; | 342 | sh_mtu2_register_clockevent(ch, name); |
363 | sh_mtu2_register_clockevent(ch, name); | ||
364 | } | ||
365 | 343 | ||
366 | return 0; | 344 | return 0; |
367 | } | 345 | } |
@@ -372,40 +350,32 @@ static int sh_mtu2_setup_channel(struct sh_mtu2_channel *ch, unsigned int index, | |||
372 | static const unsigned int channel_offsets[] = { | 350 | static const unsigned int channel_offsets[] = { |
373 | 0x300, 0x380, 0x000, | 351 | 0x300, 0x380, 0x000, |
374 | }; | 352 | }; |
375 | bool clockevent; | 353 | char name[6]; |
354 | int irq; | ||
355 | int ret; | ||
376 | 356 | ||
377 | ch->mtu = mtu; | 357 | ch->mtu = mtu; |
378 | 358 | ||
379 | if (mtu->legacy) { | 359 | sprintf(name, "tgi%ua", index); |
380 | struct sh_timer_config *cfg = mtu->pdev->dev.platform_data; | 360 | irq = platform_get_irq_byname(mtu->pdev, name); |
381 | 361 | if (irq < 0) { | |
382 | clockevent = cfg->clockevent_rating != 0; | ||
383 | |||
384 | ch->irq = platform_get_irq(mtu->pdev, 0); | ||
385 | ch->base = mtu->mapbase - cfg->channel_offset; | ||
386 | ch->index = cfg->timer_bit; | ||
387 | } else { | ||
388 | char name[6]; | ||
389 | |||
390 | clockevent = true; | ||
391 | |||
392 | sprintf(name, "tgi%ua", index); | ||
393 | ch->irq = platform_get_irq_byname(mtu->pdev, name); | ||
394 | ch->base = mtu->mapbase + channel_offsets[index]; | ||
395 | ch->index = index; | ||
396 | } | ||
397 | |||
398 | if (ch->irq < 0) { | ||
399 | /* Skip channels with no declared interrupt. */ | 362 | /* Skip channels with no declared interrupt. */ |
400 | if (!mtu->legacy) | 363 | return 0; |
401 | return 0; | 364 | } |
402 | 365 | ||
403 | dev_err(&mtu->pdev->dev, "ch%u: failed to get irq\n", | 366 | ret = request_irq(irq, sh_mtu2_interrupt, |
404 | ch->index); | 367 | IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING, |
405 | return ch->irq; | 368 | dev_name(&ch->mtu->pdev->dev), ch); |
369 | if (ret) { | ||
370 | dev_err(&ch->mtu->pdev->dev, "ch%u: failed to request irq %d\n", | ||
371 | index, irq); | ||
372 | return ret; | ||
406 | } | 373 | } |
407 | 374 | ||
408 | return sh_mtu2_register(ch, dev_name(&mtu->pdev->dev), clockevent); | 375 | ch->base = mtu->mapbase + channel_offsets[index]; |
376 | ch->index = index; | ||
377 | |||
378 | return sh_mtu2_register(ch, dev_name(&mtu->pdev->dev)); | ||
409 | } | 379 | } |
410 | 380 | ||
411 | static int sh_mtu2_map_memory(struct sh_mtu2_device *mtu) | 381 | static int sh_mtu2_map_memory(struct sh_mtu2_device *mtu) |
@@ -422,46 +392,21 @@ static int sh_mtu2_map_memory(struct sh_mtu2_device *mtu) | |||
422 | if (mtu->mapbase == NULL) | 392 | if (mtu->mapbase == NULL) |
423 | return -ENXIO; | 393 | return -ENXIO; |
424 | 394 | ||
425 | /* | ||
426 | * In legacy platform device configuration (with one device per channel) | ||
427 | * the resource points to the channel base address. | ||
428 | */ | ||
429 | if (mtu->legacy) { | ||
430 | struct sh_timer_config *cfg = mtu->pdev->dev.platform_data; | ||
431 | mtu->mapbase += cfg->channel_offset; | ||
432 | } | ||
433 | |||
434 | return 0; | 395 | return 0; |
435 | } | 396 | } |
436 | 397 | ||
437 | static void sh_mtu2_unmap_memory(struct sh_mtu2_device *mtu) | ||
438 | { | ||
439 | if (mtu->legacy) { | ||
440 | struct sh_timer_config *cfg = mtu->pdev->dev.platform_data; | ||
441 | mtu->mapbase -= cfg->channel_offset; | ||
442 | } | ||
443 | |||
444 | iounmap(mtu->mapbase); | ||
445 | } | ||
446 | |||
447 | static int sh_mtu2_setup(struct sh_mtu2_device *mtu, | 398 | static int sh_mtu2_setup(struct sh_mtu2_device *mtu, |
448 | struct platform_device *pdev) | 399 | struct platform_device *pdev) |
449 | { | 400 | { |
450 | struct sh_timer_config *cfg = pdev->dev.platform_data; | ||
451 | const struct platform_device_id *id = pdev->id_entry; | ||
452 | unsigned int i; | 401 | unsigned int i; |
453 | int ret; | 402 | int ret; |
454 | 403 | ||
455 | mtu->pdev = pdev; | 404 | mtu->pdev = pdev; |
456 | mtu->legacy = id->driver_data; | ||
457 | 405 | ||
458 | if (mtu->legacy && !cfg) { | 406 | raw_spin_lock_init(&mtu->lock); |
459 | dev_err(&mtu->pdev->dev, "missing platform data\n"); | ||
460 | return -ENXIO; | ||
461 | } | ||
462 | 407 | ||
463 | /* Get hold of clock. */ | 408 | /* Get hold of clock. */ |
464 | mtu->clk = clk_get(&mtu->pdev->dev, mtu->legacy ? "mtu2_fck" : "fck"); | 409 | mtu->clk = clk_get(&mtu->pdev->dev, "fck"); |
465 | if (IS_ERR(mtu->clk)) { | 410 | if (IS_ERR(mtu->clk)) { |
466 | dev_err(&mtu->pdev->dev, "cannot get clock\n"); | 411 | dev_err(&mtu->pdev->dev, "cannot get clock\n"); |
467 | return PTR_ERR(mtu->clk); | 412 | return PTR_ERR(mtu->clk); |
@@ -479,10 +424,7 @@ static int sh_mtu2_setup(struct sh_mtu2_device *mtu, | |||
479 | } | 424 | } |
480 | 425 | ||
481 | /* Allocate and setup the channels. */ | 426 | /* Allocate and setup the channels. */ |
482 | if (mtu->legacy) | 427 | mtu->num_channels = 3; |
483 | mtu->num_channels = 1; | ||
484 | else | ||
485 | mtu->num_channels = 3; | ||
486 | 428 | ||
487 | mtu->channels = kzalloc(sizeof(*mtu->channels) * mtu->num_channels, | 429 | mtu->channels = kzalloc(sizeof(*mtu->channels) * mtu->num_channels, |
488 | GFP_KERNEL); | 430 | GFP_KERNEL); |
@@ -491,16 +433,10 @@ static int sh_mtu2_setup(struct sh_mtu2_device *mtu, | |||
491 | goto err_unmap; | 433 | goto err_unmap; |
492 | } | 434 | } |
493 | 435 | ||
494 | if (mtu->legacy) { | 436 | for (i = 0; i < mtu->num_channels; ++i) { |
495 | ret = sh_mtu2_setup_channel(&mtu->channels[0], 0, mtu); | 437 | ret = sh_mtu2_setup_channel(&mtu->channels[i], i, mtu); |
496 | if (ret < 0) | 438 | if (ret < 0) |
497 | goto err_unmap; | 439 | goto err_unmap; |
498 | } else { | ||
499 | for (i = 0; i < mtu->num_channels; ++i) { | ||
500 | ret = sh_mtu2_setup_channel(&mtu->channels[i], i, mtu); | ||
501 | if (ret < 0) | ||
502 | goto err_unmap; | ||
503 | } | ||
504 | } | 440 | } |
505 | 441 | ||
506 | platform_set_drvdata(pdev, mtu); | 442 | platform_set_drvdata(pdev, mtu); |
@@ -509,7 +445,7 @@ static int sh_mtu2_setup(struct sh_mtu2_device *mtu, | |||
509 | 445 | ||
510 | err_unmap: | 446 | err_unmap: |
511 | kfree(mtu->channels); | 447 | kfree(mtu->channels); |
512 | sh_mtu2_unmap_memory(mtu); | 448 | iounmap(mtu->mapbase); |
513 | err_clk_unprepare: | 449 | err_clk_unprepare: |
514 | clk_unprepare(mtu->clk); | 450 | clk_unprepare(mtu->clk); |
515 | err_clk_put: | 451 | err_clk_put: |
@@ -560,17 +496,23 @@ static int sh_mtu2_remove(struct platform_device *pdev) | |||
560 | } | 496 | } |
561 | 497 | ||
562 | static const struct platform_device_id sh_mtu2_id_table[] = { | 498 | static const struct platform_device_id sh_mtu2_id_table[] = { |
563 | { "sh_mtu2", 1 }, | ||
564 | { "sh-mtu2", 0 }, | 499 | { "sh-mtu2", 0 }, |
565 | { }, | 500 | { }, |
566 | }; | 501 | }; |
567 | MODULE_DEVICE_TABLE(platform, sh_mtu2_id_table); | 502 | MODULE_DEVICE_TABLE(platform, sh_mtu2_id_table); |
568 | 503 | ||
504 | static const struct of_device_id sh_mtu2_of_table[] __maybe_unused = { | ||
505 | { .compatible = "renesas,mtu2" }, | ||
506 | { } | ||
507 | }; | ||
508 | MODULE_DEVICE_TABLE(of, sh_mtu2_of_table); | ||
509 | |||
569 | static struct platform_driver sh_mtu2_device_driver = { | 510 | static struct platform_driver sh_mtu2_device_driver = { |
570 | .probe = sh_mtu2_probe, | 511 | .probe = sh_mtu2_probe, |
571 | .remove = sh_mtu2_remove, | 512 | .remove = sh_mtu2_remove, |
572 | .driver = { | 513 | .driver = { |
573 | .name = "sh_mtu2", | 514 | .name = "sh_mtu2", |
515 | .of_match_table = of_match_ptr(sh_mtu2_of_table), | ||
574 | }, | 516 | }, |
575 | .id_table = sh_mtu2_id_table, | 517 | .id_table = sh_mtu2_id_table, |
576 | }; | 518 | }; |
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 6bd17a8f3dd4..0f665b8f2461 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/ioport.h> | 24 | #include <linux/ioport.h> |
25 | #include <linux/irq.h> | 25 | #include <linux/irq.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/of.h> | ||
27 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
28 | #include <linux/pm_domain.h> | 29 | #include <linux/pm_domain.h> |
29 | #include <linux/pm_runtime.h> | 30 | #include <linux/pm_runtime.h> |
@@ -32,7 +33,6 @@ | |||
32 | #include <linux/spinlock.h> | 33 | #include <linux/spinlock.h> |
33 | 34 | ||
34 | enum sh_tmu_model { | 35 | enum sh_tmu_model { |
35 | SH_TMU_LEGACY, | ||
36 | SH_TMU, | 36 | SH_TMU, |
37 | SH_TMU_SH3, | 37 | SH_TMU_SH3, |
38 | }; | 38 | }; |
@@ -62,6 +62,8 @@ struct sh_tmu_device { | |||
62 | 62 | ||
63 | enum sh_tmu_model model; | 63 | enum sh_tmu_model model; |
64 | 64 | ||
65 | raw_spinlock_t lock; /* Protect the shared start/stop register */ | ||
66 | |||
65 | struct sh_tmu_channel *channels; | 67 | struct sh_tmu_channel *channels; |
66 | unsigned int num_channels; | 68 | unsigned int num_channels; |
67 | 69 | ||
@@ -69,8 +71,6 @@ struct sh_tmu_device { | |||
69 | bool has_clocksource; | 71 | bool has_clocksource; |
70 | }; | 72 | }; |
71 | 73 | ||
72 | static DEFINE_RAW_SPINLOCK(sh_tmu_lock); | ||
73 | |||
74 | #define TSTR -1 /* shared register */ | 74 | #define TSTR -1 /* shared register */ |
75 | #define TCOR 0 /* channel register */ | 75 | #define TCOR 0 /* channel register */ |
76 | #define TCNT 1 /* channel register */ | 76 | #define TCNT 1 /* channel register */ |
@@ -91,8 +91,6 @@ static inline unsigned long sh_tmu_read(struct sh_tmu_channel *ch, int reg_nr) | |||
91 | 91 | ||
92 | if (reg_nr == TSTR) { | 92 | if (reg_nr == TSTR) { |
93 | switch (ch->tmu->model) { | 93 | switch (ch->tmu->model) { |
94 | case SH_TMU_LEGACY: | ||
95 | return ioread8(ch->tmu->mapbase); | ||
96 | case SH_TMU_SH3: | 94 | case SH_TMU_SH3: |
97 | return ioread8(ch->tmu->mapbase + 2); | 95 | return ioread8(ch->tmu->mapbase + 2); |
98 | case SH_TMU: | 96 | case SH_TMU: |
@@ -115,8 +113,6 @@ static inline void sh_tmu_write(struct sh_tmu_channel *ch, int reg_nr, | |||
115 | 113 | ||
116 | if (reg_nr == TSTR) { | 114 | if (reg_nr == TSTR) { |
117 | switch (ch->tmu->model) { | 115 | switch (ch->tmu->model) { |
118 | case SH_TMU_LEGACY: | ||
119 | return iowrite8(value, ch->tmu->mapbase); | ||
120 | case SH_TMU_SH3: | 116 | case SH_TMU_SH3: |
121 | return iowrite8(value, ch->tmu->mapbase + 2); | 117 | return iowrite8(value, ch->tmu->mapbase + 2); |
122 | case SH_TMU: | 118 | case SH_TMU: |
@@ -137,7 +133,7 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_channel *ch, int start) | |||
137 | unsigned long flags, value; | 133 | unsigned long flags, value; |
138 | 134 | ||
139 | /* start stop register shared by multiple timer channels */ | 135 | /* start stop register shared by multiple timer channels */ |
140 | raw_spin_lock_irqsave(&sh_tmu_lock, flags); | 136 | raw_spin_lock_irqsave(&ch->tmu->lock, flags); |
141 | value = sh_tmu_read(ch, TSTR); | 137 | value = sh_tmu_read(ch, TSTR); |
142 | 138 | ||
143 | if (start) | 139 | if (start) |
@@ -146,7 +142,7 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_channel *ch, int start) | |||
146 | value &= ~(1 << ch->index); | 142 | value &= ~(1 << ch->index); |
147 | 143 | ||
148 | sh_tmu_write(ch, TSTR, value); | 144 | sh_tmu_write(ch, TSTR, value); |
149 | raw_spin_unlock_irqrestore(&sh_tmu_lock, flags); | 145 | raw_spin_unlock_irqrestore(&ch->tmu->lock, flags); |
150 | } | 146 | } |
151 | 147 | ||
152 | static int __sh_tmu_enable(struct sh_tmu_channel *ch) | 148 | static int __sh_tmu_enable(struct sh_tmu_channel *ch) |
@@ -476,27 +472,12 @@ static int sh_tmu_channel_setup(struct sh_tmu_channel *ch, unsigned int index, | |||
476 | return 0; | 472 | return 0; |
477 | 473 | ||
478 | ch->tmu = tmu; | 474 | ch->tmu = tmu; |
475 | ch->index = index; | ||
479 | 476 | ||
480 | if (tmu->model == SH_TMU_LEGACY) { | 477 | if (tmu->model == SH_TMU_SH3) |
481 | struct sh_timer_config *cfg = tmu->pdev->dev.platform_data; | 478 | ch->base = tmu->mapbase + 4 + ch->index * 12; |
482 | 479 | else | |
483 | /* | 480 | ch->base = tmu->mapbase + 8 + ch->index * 12; |
484 | * The SH3 variant (SH770x, SH7705, SH7710 and SH7720) maps | ||
485 | * channel registers blocks at base + 2 + 12 * index, while all | ||
486 | * other variants map them at base + 4 + 12 * index. We can | ||
487 | * compute the index by just dividing by 12, the 2 bytes or 4 | ||
488 | * bytes offset being hidden by the integer division. | ||
489 | */ | ||
490 | ch->index = cfg->channel_offset / 12; | ||
491 | ch->base = tmu->mapbase + cfg->channel_offset; | ||
492 | } else { | ||
493 | ch->index = index; | ||
494 | |||
495 | if (tmu->model == SH_TMU_SH3) | ||
496 | ch->base = tmu->mapbase + 4 + ch->index * 12; | ||
497 | else | ||
498 | ch->base = tmu->mapbase + 8 + ch->index * 12; | ||
499 | } | ||
500 | 481 | ||
501 | ch->irq = platform_get_irq(tmu->pdev, index); | 482 | ch->irq = platform_get_irq(tmu->pdev, index); |
502 | if (ch->irq < 0) { | 483 | if (ch->irq < 0) { |
@@ -526,46 +507,53 @@ static int sh_tmu_map_memory(struct sh_tmu_device *tmu) | |||
526 | if (tmu->mapbase == NULL) | 507 | if (tmu->mapbase == NULL) |
527 | return -ENXIO; | 508 | return -ENXIO; |
528 | 509 | ||
529 | /* | ||
530 | * In legacy platform device configuration (with one device per channel) | ||
531 | * the resource points to the channel base address. | ||
532 | */ | ||
533 | if (tmu->model == SH_TMU_LEGACY) { | ||
534 | struct sh_timer_config *cfg = tmu->pdev->dev.platform_data; | ||
535 | tmu->mapbase -= cfg->channel_offset; | ||
536 | } | ||
537 | |||
538 | return 0; | 510 | return 0; |
539 | } | 511 | } |
540 | 512 | ||
541 | static void sh_tmu_unmap_memory(struct sh_tmu_device *tmu) | 513 | static int sh_tmu_parse_dt(struct sh_tmu_device *tmu) |
542 | { | 514 | { |
543 | if (tmu->model == SH_TMU_LEGACY) { | 515 | struct device_node *np = tmu->pdev->dev.of_node; |
544 | struct sh_timer_config *cfg = tmu->pdev->dev.platform_data; | 516 | |
545 | tmu->mapbase += cfg->channel_offset; | 517 | tmu->model = SH_TMU; |
518 | tmu->num_channels = 3; | ||
519 | |||
520 | of_property_read_u32(np, "#renesas,channels", &tmu->num_channels); | ||
521 | |||
522 | if (tmu->num_channels != 2 && tmu->num_channels != 3) { | ||
523 | dev_err(&tmu->pdev->dev, "invalid number of channels %u\n", | ||
524 | tmu->num_channels); | ||
525 | return -EINVAL; | ||
546 | } | 526 | } |
547 | 527 | ||
548 | iounmap(tmu->mapbase); | 528 | return 0; |
549 | } | 529 | } |
550 | 530 | ||
551 | static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev) | 531 | static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev) |
552 | { | 532 | { |
553 | struct sh_timer_config *cfg = pdev->dev.platform_data; | ||
554 | const struct platform_device_id *id = pdev->id_entry; | ||
555 | unsigned int i; | 533 | unsigned int i; |
556 | int ret; | 534 | int ret; |
557 | 535 | ||
558 | if (!cfg) { | 536 | tmu->pdev = pdev; |
537 | |||
538 | raw_spin_lock_init(&tmu->lock); | ||
539 | |||
540 | if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { | ||
541 | ret = sh_tmu_parse_dt(tmu); | ||
542 | if (ret < 0) | ||
543 | return ret; | ||
544 | } else if (pdev->dev.platform_data) { | ||
545 | const struct platform_device_id *id = pdev->id_entry; | ||
546 | struct sh_timer_config *cfg = pdev->dev.platform_data; | ||
547 | |||
548 | tmu->model = id->driver_data; | ||
549 | tmu->num_channels = hweight8(cfg->channels_mask); | ||
550 | } else { | ||
559 | dev_err(&tmu->pdev->dev, "missing platform data\n"); | 551 | dev_err(&tmu->pdev->dev, "missing platform data\n"); |
560 | return -ENXIO; | 552 | return -ENXIO; |
561 | } | 553 | } |
562 | 554 | ||
563 | tmu->pdev = pdev; | ||
564 | tmu->model = id->driver_data; | ||
565 | |||
566 | /* Get hold of clock. */ | 555 | /* Get hold of clock. */ |
567 | tmu->clk = clk_get(&tmu->pdev->dev, | 556 | tmu->clk = clk_get(&tmu->pdev->dev, "fck"); |
568 | tmu->model == SH_TMU_LEGACY ? "tmu_fck" : "fck"); | ||
569 | if (IS_ERR(tmu->clk)) { | 557 | if (IS_ERR(tmu->clk)) { |
570 | dev_err(&tmu->pdev->dev, "cannot get clock\n"); | 558 | dev_err(&tmu->pdev->dev, "cannot get clock\n"); |
571 | return PTR_ERR(tmu->clk); | 559 | return PTR_ERR(tmu->clk); |
@@ -583,11 +571,6 @@ static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev) | |||
583 | } | 571 | } |
584 | 572 | ||
585 | /* Allocate and setup the channels. */ | 573 | /* Allocate and setup the channels. */ |
586 | if (tmu->model == SH_TMU_LEGACY) | ||
587 | tmu->num_channels = 1; | ||
588 | else | ||
589 | tmu->num_channels = hweight8(cfg->channels_mask); | ||
590 | |||
591 | tmu->channels = kzalloc(sizeof(*tmu->channels) * tmu->num_channels, | 574 | tmu->channels = kzalloc(sizeof(*tmu->channels) * tmu->num_channels, |
592 | GFP_KERNEL); | 575 | GFP_KERNEL); |
593 | if (tmu->channels == NULL) { | 576 | if (tmu->channels == NULL) { |
@@ -595,23 +578,15 @@ static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev) | |||
595 | goto err_unmap; | 578 | goto err_unmap; |
596 | } | 579 | } |
597 | 580 | ||
598 | if (tmu->model == SH_TMU_LEGACY) { | 581 | /* |
599 | ret = sh_tmu_channel_setup(&tmu->channels[0], 0, | 582 | * Use the first channel as a clock event device and the second channel |
600 | cfg->clockevent_rating != 0, | 583 | * as a clock source. |
601 | cfg->clocksource_rating != 0, tmu); | 584 | */ |
585 | for (i = 0; i < tmu->num_channels; ++i) { | ||
586 | ret = sh_tmu_channel_setup(&tmu->channels[i], i, | ||
587 | i == 0, i == 1, tmu); | ||
602 | if (ret < 0) | 588 | if (ret < 0) |
603 | goto err_unmap; | 589 | goto err_unmap; |
604 | } else { | ||
605 | /* | ||
606 | * Use the first channel as a clock event device and the second | ||
607 | * channel as a clock source. | ||
608 | */ | ||
609 | for (i = 0; i < tmu->num_channels; ++i) { | ||
610 | ret = sh_tmu_channel_setup(&tmu->channels[i], i, | ||
611 | i == 0, i == 1, tmu); | ||
612 | if (ret < 0) | ||
613 | goto err_unmap; | ||
614 | } | ||
615 | } | 590 | } |
616 | 591 | ||
617 | platform_set_drvdata(pdev, tmu); | 592 | platform_set_drvdata(pdev, tmu); |
@@ -620,7 +595,7 @@ static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev) | |||
620 | 595 | ||
621 | err_unmap: | 596 | err_unmap: |
622 | kfree(tmu->channels); | 597 | kfree(tmu->channels); |
623 | sh_tmu_unmap_memory(tmu); | 598 | iounmap(tmu->mapbase); |
624 | err_clk_unprepare: | 599 | err_clk_unprepare: |
625 | clk_unprepare(tmu->clk); | 600 | clk_unprepare(tmu->clk); |
626 | err_clk_put: | 601 | err_clk_put: |
@@ -671,18 +646,24 @@ static int sh_tmu_remove(struct platform_device *pdev) | |||
671 | } | 646 | } |
672 | 647 | ||
673 | static const struct platform_device_id sh_tmu_id_table[] = { | 648 | static const struct platform_device_id sh_tmu_id_table[] = { |
674 | { "sh_tmu", SH_TMU_LEGACY }, | ||
675 | { "sh-tmu", SH_TMU }, | 649 | { "sh-tmu", SH_TMU }, |
676 | { "sh-tmu-sh3", SH_TMU_SH3 }, | 650 | { "sh-tmu-sh3", SH_TMU_SH3 }, |
677 | { } | 651 | { } |
678 | }; | 652 | }; |
679 | MODULE_DEVICE_TABLE(platform, sh_tmu_id_table); | 653 | MODULE_DEVICE_TABLE(platform, sh_tmu_id_table); |
680 | 654 | ||
655 | static const struct of_device_id sh_tmu_of_table[] __maybe_unused = { | ||
656 | { .compatible = "renesas,tmu" }, | ||
657 | { } | ||
658 | }; | ||
659 | MODULE_DEVICE_TABLE(of, sh_tmu_of_table); | ||
660 | |||
681 | static struct platform_driver sh_tmu_device_driver = { | 661 | static struct platform_driver sh_tmu_device_driver = { |
682 | .probe = sh_tmu_probe, | 662 | .probe = sh_tmu_probe, |
683 | .remove = sh_tmu_remove, | 663 | .remove = sh_tmu_remove, |
684 | .driver = { | 664 | .driver = { |
685 | .name = "sh_tmu", | 665 | .name = "sh_tmu", |
666 | .of_match_table = of_match_ptr(sh_tmu_of_table), | ||
686 | }, | 667 | }, |
687 | .id_table = sh_tmu_id_table, | 668 | .id_table = sh_tmu_id_table, |
688 | }; | 669 | }; |
diff --git a/drivers/clocksource/timer-marco.c b/drivers/clocksource/timer-marco.c index dbd30398222a..330e93064692 100644 --- a/drivers/clocksource/timer-marco.c +++ b/drivers/clocksource/timer-marco.c | |||
@@ -260,6 +260,9 @@ static void __init sirfsoc_marco_timer_init(struct device_node *np) | |||
260 | 260 | ||
261 | clk = of_clk_get(np, 0); | 261 | clk = of_clk_get(np, 0); |
262 | BUG_ON(IS_ERR(clk)); | 262 | BUG_ON(IS_ERR(clk)); |
263 | |||
264 | BUG_ON(clk_prepare_enable(clk)); | ||
265 | |||
263 | rate = clk_get_rate(clk); | 266 | rate = clk_get_rate(clk); |
264 | 267 | ||
265 | BUG_ON(rate < MARCO_CLOCK_FREQ); | 268 | BUG_ON(rate < MARCO_CLOCK_FREQ); |
diff --git a/drivers/clocksource/timer-prima2.c b/drivers/clocksource/timer-prima2.c index a722aac7ac02..ce18d570e1cd 100644 --- a/drivers/clocksource/timer-prima2.c +++ b/drivers/clocksource/timer-prima2.c | |||
@@ -200,6 +200,9 @@ static void __init sirfsoc_prima2_timer_init(struct device_node *np) | |||
200 | 200 | ||
201 | clk = of_clk_get(np, 0); | 201 | clk = of_clk_get(np, 0); |
202 | BUG_ON(IS_ERR(clk)); | 202 | BUG_ON(IS_ERR(clk)); |
203 | |||
204 | BUG_ON(clk_prepare_enable(clk)); | ||
205 | |||
203 | rate = clk_get_rate(clk); | 206 | rate = clk_get_rate(clk); |
204 | 207 | ||
205 | BUG_ON(rate < PRIMA2_CLOCK_FREQ); | 208 | BUG_ON(rate < PRIMA2_CLOCK_FREQ); |