diff options
Diffstat (limited to 'drivers/clocksource')
-rw-r--r-- | drivers/clocksource/Kconfig | 1 | ||||
-rw-r--r-- | drivers/clocksource/Makefile | 1 | ||||
-rw-r--r-- | drivers/clocksource/arm_arch_timer.c | 13 | ||||
-rw-r--r-- | drivers/clocksource/time-armada-370-xp.c | 55 | ||||
-rw-r--r-- | drivers/clocksource/timer-atmel-pit.c | 32 | ||||
-rw-r--r-- | drivers/clocksource/timer-integrator-ap.c | 210 | ||||
-rw-r--r-- | drivers/clocksource/timer-marco.c | 23 |
7 files changed, 288 insertions, 47 deletions
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 90420600e1eb..f657a48d20eb 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig | |||
@@ -32,6 +32,7 @@ config ARMADA_370_XP_TIMER | |||
32 | 32 | ||
33 | config MESON6_TIMER | 33 | config MESON6_TIMER |
34 | bool | 34 | bool |
35 | select CLKSRC_MMIO | ||
35 | 36 | ||
36 | config ORION_TIMER | 37 | config ORION_TIMER |
37 | select CLKSRC_OF | 38 | select CLKSRC_OF |
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 756f6f10efa0..fae0435cc23d 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile | |||
@@ -45,4 +45,5 @@ obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o | |||
45 | obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o | 45 | obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o |
46 | obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o | 46 | obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o |
47 | obj-$(CONFIG_ARCH_KEYSTONE) += timer-keystone.o | 47 | obj-$(CONFIG_ARCH_KEYSTONE) += timer-keystone.o |
48 | obj-$(CONFIG_ARCH_INTEGRATOR_AP) += timer-integrator-ap.o | ||
48 | obj-$(CONFIG_CLKSRC_VERSATILE) += versatile.o | 49 | obj-$(CONFIG_CLKSRC_VERSATILE) += versatile.o |
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 43005d4d3348..6a79fc4f900c 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c | |||
@@ -462,7 +462,10 @@ static void __init arch_counter_register(unsigned type) | |||
462 | 462 | ||
463 | /* Register the CP15 based counter if we have one */ | 463 | /* Register the CP15 based counter if we have one */ |
464 | if (type & ARCH_CP15_TIMER) { | 464 | if (type & ARCH_CP15_TIMER) { |
465 | arch_timer_read_counter = arch_counter_get_cntvct; | 465 | if (arch_timer_use_virtual) |
466 | arch_timer_read_counter = arch_counter_get_cntvct; | ||
467 | else | ||
468 | arch_timer_read_counter = arch_counter_get_cntpct; | ||
466 | } else { | 469 | } else { |
467 | arch_timer_read_counter = arch_counter_get_cntvct_mem; | 470 | arch_timer_read_counter = arch_counter_get_cntvct_mem; |
468 | 471 | ||
@@ -702,6 +705,14 @@ static void __init arch_timer_init(struct device_node *np) | |||
702 | arch_timer_detect_rate(NULL, np); | 705 | arch_timer_detect_rate(NULL, np); |
703 | 706 | ||
704 | /* | 707 | /* |
708 | * If we cannot rely on firmware initializing the timer registers then | ||
709 | * we should use the physical timers instead. | ||
710 | */ | ||
711 | if (IS_ENABLED(CONFIG_ARM) && | ||
712 | of_property_read_bool(np, "arm,cpu-registers-not-fw-configured")) | ||
713 | arch_timer_use_virtual = false; | ||
714 | |||
715 | /* | ||
705 | * If HYP mode is available, we know that the physical timer | 716 | * If HYP mode is available, we know that the physical timer |
706 | * has been configured to be accessible from PL1. Use it, so | 717 | * has been configured to be accessible from PL1. Use it, so |
707 | * that a guest can use the virtual timer instead. | 718 | * that a guest can use the virtual timer instead. |
diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c index 0451e62fac7a..0c8c5e337540 100644 --- a/drivers/clocksource/time-armada-370-xp.c +++ b/drivers/clocksource/time-armada-370-xp.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/module.h> | 43 | #include <linux/module.h> |
44 | #include <linux/sched_clock.h> | 44 | #include <linux/sched_clock.h> |
45 | #include <linux/percpu.h> | 45 | #include <linux/percpu.h> |
46 | #include <linux/syscore_ops.h> | ||
46 | 47 | ||
47 | /* | 48 | /* |
48 | * Timer block registers. | 49 | * Timer block registers. |
@@ -223,6 +224,28 @@ static struct notifier_block armada_370_xp_timer_cpu_nb = { | |||
223 | .notifier_call = armada_370_xp_timer_cpu_notify, | 224 | .notifier_call = armada_370_xp_timer_cpu_notify, |
224 | }; | 225 | }; |
225 | 226 | ||
227 | static u32 timer0_ctrl_reg, timer0_local_ctrl_reg; | ||
228 | |||
229 | static int armada_370_xp_timer_suspend(void) | ||
230 | { | ||
231 | timer0_ctrl_reg = readl(timer_base + TIMER_CTRL_OFF); | ||
232 | timer0_local_ctrl_reg = readl(local_base + TIMER_CTRL_OFF); | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static void armada_370_xp_timer_resume(void) | ||
237 | { | ||
238 | writel(0xffffffff, timer_base + TIMER0_VAL_OFF); | ||
239 | writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF); | ||
240 | writel(timer0_ctrl_reg, timer_base + TIMER_CTRL_OFF); | ||
241 | writel(timer0_local_ctrl_reg, local_base + TIMER_CTRL_OFF); | ||
242 | } | ||
243 | |||
244 | struct syscore_ops armada_370_xp_timer_syscore_ops = { | ||
245 | .suspend = armada_370_xp_timer_suspend, | ||
246 | .resume = armada_370_xp_timer_resume, | ||
247 | }; | ||
248 | |||
226 | static void __init armada_370_xp_timer_common_init(struct device_node *np) | 249 | static void __init armada_370_xp_timer_common_init(struct device_node *np) |
227 | { | 250 | { |
228 | u32 clr = 0, set = 0; | 251 | u32 clr = 0, set = 0; |
@@ -285,6 +308,8 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np) | |||
285 | /* Immediately configure the timer on the boot CPU */ | 308 | /* Immediately configure the timer on the boot CPU */ |
286 | if (!res) | 309 | if (!res) |
287 | armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt)); | 310 | armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt)); |
311 | |||
312 | register_syscore_ops(&armada_370_xp_timer_syscore_ops); | ||
288 | } | 313 | } |
289 | 314 | ||
290 | static void __init armada_xp_timer_init(struct device_node *np) | 315 | static void __init armada_xp_timer_init(struct device_node *np) |
@@ -293,6 +318,7 @@ static void __init armada_xp_timer_init(struct device_node *np) | |||
293 | 318 | ||
294 | /* The 25Mhz fixed clock is mandatory, and must always be available */ | 319 | /* The 25Mhz fixed clock is mandatory, and must always be available */ |
295 | BUG_ON(IS_ERR(clk)); | 320 | BUG_ON(IS_ERR(clk)); |
321 | clk_prepare_enable(clk); | ||
296 | timer_clk = clk_get_rate(clk); | 322 | timer_clk = clk_get_rate(clk); |
297 | 323 | ||
298 | armada_370_xp_timer_common_init(np); | 324 | armada_370_xp_timer_common_init(np); |
@@ -300,11 +326,40 @@ static void __init armada_xp_timer_init(struct device_node *np) | |||
300 | CLOCKSOURCE_OF_DECLARE(armada_xp, "marvell,armada-xp-timer", | 326 | CLOCKSOURCE_OF_DECLARE(armada_xp, "marvell,armada-xp-timer", |
301 | armada_xp_timer_init); | 327 | armada_xp_timer_init); |
302 | 328 | ||
329 | static void __init armada_375_timer_init(struct device_node *np) | ||
330 | { | ||
331 | struct clk *clk; | ||
332 | |||
333 | clk = of_clk_get_by_name(np, "fixed"); | ||
334 | if (!IS_ERR(clk)) { | ||
335 | clk_prepare_enable(clk); | ||
336 | timer_clk = clk_get_rate(clk); | ||
337 | } else { | ||
338 | |||
339 | /* | ||
340 | * This fallback is required in order to retain proper | ||
341 | * devicetree backwards compatibility. | ||
342 | */ | ||
343 | clk = of_clk_get(np, 0); | ||
344 | |||
345 | /* Must have at least a clock */ | ||
346 | BUG_ON(IS_ERR(clk)); | ||
347 | clk_prepare_enable(clk); | ||
348 | timer_clk = clk_get_rate(clk) / TIMER_DIVIDER; | ||
349 | timer25Mhz = false; | ||
350 | } | ||
351 | |||
352 | armada_370_xp_timer_common_init(np); | ||
353 | } | ||
354 | CLOCKSOURCE_OF_DECLARE(armada_375, "marvell,armada-375-timer", | ||
355 | armada_375_timer_init); | ||
356 | |||
303 | static void __init armada_370_timer_init(struct device_node *np) | 357 | static void __init armada_370_timer_init(struct device_node *np) |
304 | { | 358 | { |
305 | struct clk *clk = of_clk_get(np, 0); | 359 | struct clk *clk = of_clk_get(np, 0); |
306 | 360 | ||
307 | BUG_ON(IS_ERR(clk)); | 361 | BUG_ON(IS_ERR(clk)); |
362 | clk_prepare_enable(clk); | ||
308 | timer_clk = clk_get_rate(clk) / TIMER_DIVIDER; | 363 | timer_clk = clk_get_rate(clk) / TIMER_DIVIDER; |
309 | timer25Mhz = false; | 364 | timer25Mhz = false; |
310 | 365 | ||
diff --git a/drivers/clocksource/timer-atmel-pit.c b/drivers/clocksource/timer-atmel-pit.c index d5289098b3df..b5b4d4585c9a 100644 --- a/drivers/clocksource/timer-atmel-pit.c +++ b/drivers/clocksource/timer-atmel-pit.c | |||
@@ -262,35 +262,3 @@ static void __init at91sam926x_pit_dt_init(struct device_node *node) | |||
262 | } | 262 | } |
263 | CLOCKSOURCE_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit", | 263 | CLOCKSOURCE_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit", |
264 | at91sam926x_pit_dt_init); | 264 | at91sam926x_pit_dt_init); |
265 | |||
266 | static void __iomem *pit_base_addr; | ||
267 | |||
268 | void __init at91sam926x_pit_init(int irq) | ||
269 | { | ||
270 | struct pit_data *data; | ||
271 | |||
272 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
273 | if (!data) | ||
274 | panic(pr_fmt("Unable to allocate memory\n")); | ||
275 | |||
276 | data->base = pit_base_addr; | ||
277 | |||
278 | data->mck = clk_get(NULL, "mck"); | ||
279 | if (IS_ERR(data->mck)) | ||
280 | panic(pr_fmt("Unable to get mck clk\n")); | ||
281 | |||
282 | data->irq = irq; | ||
283 | |||
284 | at91sam926x_pit_common_init(data); | ||
285 | } | ||
286 | |||
287 | void __init at91sam926x_ioremap_pit(u32 addr) | ||
288 | { | ||
289 | if (of_have_populated_dt()) | ||
290 | return; | ||
291 | |||
292 | pit_base_addr = ioremap(addr, 16); | ||
293 | |||
294 | if (!pit_base_addr) | ||
295 | panic(pr_fmt("Impossible to ioremap PIT\n")); | ||
296 | } | ||
diff --git a/drivers/clocksource/timer-integrator-ap.c b/drivers/clocksource/timer-integrator-ap.c new file mode 100644 index 000000000000..b9efd30513d5 --- /dev/null +++ b/drivers/clocksource/timer-integrator-ap.c | |||
@@ -0,0 +1,210 @@ | |||
1 | /* | ||
2 | * Integrator/AP timer driver | ||
3 | * Copyright (C) 2000-2003 Deep Blue Solutions Ltd | ||
4 | * Copyright (c) 2014, Linaro Limited | ||
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 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/clk.h> | ||
22 | #include <linux/clocksource.h> | ||
23 | #include <linux/of_irq.h> | ||
24 | #include <linux/of_address.h> | ||
25 | #include <linux/of_platform.h> | ||
26 | #include <linux/clockchips.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/sched_clock.h> | ||
29 | #include <asm/hardware/arm_timer.h> | ||
30 | |||
31 | static void __iomem * sched_clk_base; | ||
32 | |||
33 | static u64 notrace integrator_read_sched_clock(void) | ||
34 | { | ||
35 | return -readl(sched_clk_base + TIMER_VALUE); | ||
36 | } | ||
37 | |||
38 | static void integrator_clocksource_init(unsigned long inrate, | ||
39 | void __iomem *base) | ||
40 | { | ||
41 | u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC; | ||
42 | unsigned long rate = inrate; | ||
43 | |||
44 | if (rate >= 1500000) { | ||
45 | rate /= 16; | ||
46 | ctrl |= TIMER_CTRL_DIV16; | ||
47 | } | ||
48 | |||
49 | writel(0xffff, base + TIMER_LOAD); | ||
50 | writel(ctrl, base + TIMER_CTRL); | ||
51 | |||
52 | clocksource_mmio_init(base + TIMER_VALUE, "timer2", | ||
53 | rate, 200, 16, clocksource_mmio_readl_down); | ||
54 | |||
55 | sched_clk_base = base; | ||
56 | sched_clock_register(integrator_read_sched_clock, 16, rate); | ||
57 | } | ||
58 | |||
59 | static unsigned long timer_reload; | ||
60 | static void __iomem * clkevt_base; | ||
61 | |||
62 | /* | ||
63 | * IRQ handler for the timer | ||
64 | */ | ||
65 | static irqreturn_t integrator_timer_interrupt(int irq, void *dev_id) | ||
66 | { | ||
67 | struct clock_event_device *evt = dev_id; | ||
68 | |||
69 | /* clear the interrupt */ | ||
70 | writel(1, clkevt_base + TIMER_INTCLR); | ||
71 | |||
72 | evt->event_handler(evt); | ||
73 | |||
74 | return IRQ_HANDLED; | ||
75 | } | ||
76 | |||
77 | static void clkevt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) | ||
78 | { | ||
79 | u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE; | ||
80 | |||
81 | /* Disable timer */ | ||
82 | writel(ctrl, clkevt_base + TIMER_CTRL); | ||
83 | |||
84 | switch (mode) { | ||
85 | case CLOCK_EVT_MODE_PERIODIC: | ||
86 | /* Enable the timer and start the periodic tick */ | ||
87 | writel(timer_reload, clkevt_base + TIMER_LOAD); | ||
88 | ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE; | ||
89 | writel(ctrl, clkevt_base + TIMER_CTRL); | ||
90 | break; | ||
91 | case CLOCK_EVT_MODE_ONESHOT: | ||
92 | /* Leave the timer disabled, .set_next_event will enable it */ | ||
93 | ctrl &= ~TIMER_CTRL_PERIODIC; | ||
94 | writel(ctrl, clkevt_base + TIMER_CTRL); | ||
95 | break; | ||
96 | case CLOCK_EVT_MODE_UNUSED: | ||
97 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
98 | case CLOCK_EVT_MODE_RESUME: | ||
99 | default: | ||
100 | /* Just leave in disabled state */ | ||
101 | break; | ||
102 | } | ||
103 | |||
104 | } | ||
105 | |||
106 | static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt) | ||
107 | { | ||
108 | unsigned long ctrl = readl(clkevt_base + TIMER_CTRL); | ||
109 | |||
110 | writel(ctrl & ~TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL); | ||
111 | writel(next, clkevt_base + TIMER_LOAD); | ||
112 | writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL); | ||
113 | |||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static struct clock_event_device integrator_clockevent = { | ||
118 | .name = "timer1", | ||
119 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | ||
120 | .set_mode = clkevt_set_mode, | ||
121 | .set_next_event = clkevt_set_next_event, | ||
122 | .rating = 300, | ||
123 | }; | ||
124 | |||
125 | static struct irqaction integrator_timer_irq = { | ||
126 | .name = "timer", | ||
127 | .flags = IRQF_TIMER | IRQF_IRQPOLL, | ||
128 | .handler = integrator_timer_interrupt, | ||
129 | .dev_id = &integrator_clockevent, | ||
130 | }; | ||
131 | |||
132 | static void integrator_clockevent_init(unsigned long inrate, | ||
133 | void __iomem *base, int irq) | ||
134 | { | ||
135 | unsigned long rate = inrate; | ||
136 | unsigned int ctrl = 0; | ||
137 | |||
138 | clkevt_base = base; | ||
139 | /* Calculate and program a divisor */ | ||
140 | if (rate > 0x100000 * HZ) { | ||
141 | rate /= 256; | ||
142 | ctrl |= TIMER_CTRL_DIV256; | ||
143 | } else if (rate > 0x10000 * HZ) { | ||
144 | rate /= 16; | ||
145 | ctrl |= TIMER_CTRL_DIV16; | ||
146 | } | ||
147 | timer_reload = rate / HZ; | ||
148 | writel(ctrl, clkevt_base + TIMER_CTRL); | ||
149 | |||
150 | setup_irq(irq, &integrator_timer_irq); | ||
151 | clockevents_config_and_register(&integrator_clockevent, | ||
152 | rate, | ||
153 | 1, | ||
154 | 0xffffU); | ||
155 | } | ||
156 | |||
157 | static void __init integrator_ap_timer_init_of(struct device_node *node) | ||
158 | { | ||
159 | const char *path; | ||
160 | void __iomem *base; | ||
161 | int err; | ||
162 | int irq; | ||
163 | struct clk *clk; | ||
164 | unsigned long rate; | ||
165 | struct device_node *pri_node; | ||
166 | struct device_node *sec_node; | ||
167 | |||
168 | base = of_io_request_and_map(node, 0, "integrator-timer"); | ||
169 | if (!base) | ||
170 | return; | ||
171 | |||
172 | clk = of_clk_get(node, 0); | ||
173 | if (IS_ERR(clk)) { | ||
174 | pr_err("No clock for %s\n", node->name); | ||
175 | return; | ||
176 | } | ||
177 | clk_prepare_enable(clk); | ||
178 | rate = clk_get_rate(clk); | ||
179 | writel(0, base + TIMER_CTRL); | ||
180 | |||
181 | err = of_property_read_string(of_aliases, | ||
182 | "arm,timer-primary", &path); | ||
183 | if (WARN_ON(err)) | ||
184 | return; | ||
185 | pri_node = of_find_node_by_path(path); | ||
186 | err = of_property_read_string(of_aliases, | ||
187 | "arm,timer-secondary", &path); | ||
188 | if (WARN_ON(err)) | ||
189 | return; | ||
190 | sec_node = of_find_node_by_path(path); | ||
191 | |||
192 | if (node == pri_node) { | ||
193 | /* The primary timer lacks IRQ, use as clocksource */ | ||
194 | integrator_clocksource_init(rate, base); | ||
195 | return; | ||
196 | } | ||
197 | |||
198 | if (node == sec_node) { | ||
199 | /* The secondary timer will drive the clock event */ | ||
200 | irq = irq_of_parse_and_map(node, 0); | ||
201 | integrator_clockevent_init(rate, base, irq); | ||
202 | return; | ||
203 | } | ||
204 | |||
205 | pr_info("Timer @%p unused\n", base); | ||
206 | clk_disable_unprepare(clk); | ||
207 | } | ||
208 | |||
209 | CLOCKSOURCE_OF_DECLARE(integrator_ap_timer, "arm,integrator-timer", | ||
210 | integrator_ap_timer_init_of); | ||
diff --git a/drivers/clocksource/timer-marco.c b/drivers/clocksource/timer-marco.c index caf7a2030461..361a789d4bee 100644 --- a/drivers/clocksource/timer-marco.c +++ b/drivers/clocksource/timer-marco.c | |||
@@ -20,8 +20,6 @@ | |||
20 | #include <linux/of_address.h> | 20 | #include <linux/of_address.h> |
21 | #include <linux/sched_clock.h> | 21 | #include <linux/sched_clock.h> |
22 | 22 | ||
23 | #define MARCO_CLOCK_FREQ 1000000 | ||
24 | |||
25 | #define SIRFSOC_TIMER_32COUNTER_0_CTRL 0x0000 | 23 | #define SIRFSOC_TIMER_32COUNTER_0_CTRL 0x0000 |
26 | #define SIRFSOC_TIMER_32COUNTER_1_CTRL 0x0004 | 24 | #define SIRFSOC_TIMER_32COUNTER_1_CTRL 0x0004 |
27 | #define SIRFSOC_TIMER_MATCH_0 0x0018 | 25 | #define SIRFSOC_TIMER_MATCH_0 0x0018 |
@@ -40,6 +38,8 @@ | |||
40 | 38 | ||
41 | #define SIRFSOC_TIMER_REG_CNT 6 | 39 | #define SIRFSOC_TIMER_REG_CNT 6 |
42 | 40 | ||
41 | static unsigned long marco_timer_rate; | ||
42 | |||
43 | static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = { | 43 | static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = { |
44 | SIRFSOC_TIMER_WATCHDOG_EN, | 44 | SIRFSOC_TIMER_WATCHDOG_EN, |
45 | SIRFSOC_TIMER_32COUNTER_0_CTRL, | 45 | SIRFSOC_TIMER_32COUNTER_0_CTRL, |
@@ -195,7 +195,7 @@ static int sirfsoc_local_timer_setup(struct clock_event_device *ce) | |||
195 | ce->rating = 200; | 195 | ce->rating = 200; |
196 | ce->set_mode = sirfsoc_timer_set_mode; | 196 | ce->set_mode = sirfsoc_timer_set_mode; |
197 | ce->set_next_event = sirfsoc_timer_set_next_event; | 197 | ce->set_next_event = sirfsoc_timer_set_next_event; |
198 | clockevents_calc_mult_shift(ce, MARCO_CLOCK_FREQ, 60); | 198 | clockevents_calc_mult_shift(ce, marco_timer_rate, 60); |
199 | ce->max_delta_ns = clockevent_delta2ns(-2, ce); | 199 | ce->max_delta_ns = clockevent_delta2ns(-2, ce); |
200 | ce->min_delta_ns = clockevent_delta2ns(2, ce); | 200 | ce->min_delta_ns = clockevent_delta2ns(2, ce); |
201 | ce->cpumask = cpumask_of(cpu); | 201 | ce->cpumask = cpumask_of(cpu); |
@@ -257,7 +257,6 @@ static void __init sirfsoc_clockevent_init(void) | |||
257 | /* initialize the kernel jiffy timer source */ | 257 | /* initialize the kernel jiffy timer source */ |
258 | static void __init sirfsoc_marco_timer_init(struct device_node *np) | 258 | static void __init sirfsoc_marco_timer_init(struct device_node *np) |
259 | { | 259 | { |
260 | unsigned long rate; | ||
261 | u32 timer_div; | 260 | u32 timer_div; |
262 | struct clk *clk; | 261 | struct clk *clk; |
263 | 262 | ||
@@ -266,16 +265,12 @@ static void __init sirfsoc_marco_timer_init(struct device_node *np) | |||
266 | 265 | ||
267 | BUG_ON(clk_prepare_enable(clk)); | 266 | BUG_ON(clk_prepare_enable(clk)); |
268 | 267 | ||
269 | rate = clk_get_rate(clk); | 268 | marco_timer_rate = clk_get_rate(clk); |
270 | |||
271 | BUG_ON(rate < MARCO_CLOCK_FREQ); | ||
272 | BUG_ON(rate % MARCO_CLOCK_FREQ); | ||
273 | 269 | ||
274 | /* Initialize the timer dividers */ | 270 | /* timer dividers: 0, not divided */ |
275 | timer_div = rate / MARCO_CLOCK_FREQ - 1; | 271 | writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL); |
276 | writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL); | 272 | writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL); |
277 | writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL); | 273 | writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_1_CTRL); |
278 | writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_1_CTRL); | ||
279 | 274 | ||
280 | /* Initialize timer counters to 0 */ | 275 | /* Initialize timer counters to 0 */ |
281 | writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO); | 276 | writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO); |
@@ -288,7 +283,7 @@ static void __init sirfsoc_marco_timer_init(struct device_node *np) | |||
288 | /* Clear all interrupts */ | 283 | /* Clear all interrupts */ |
289 | writel_relaxed(0xFFFF, sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS); | 284 | writel_relaxed(0xFFFF, sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS); |
290 | 285 | ||
291 | BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, MARCO_CLOCK_FREQ)); | 286 | BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, marco_timer_rate)); |
292 | 287 | ||
293 | sirfsoc_clockevent_init(); | 288 | sirfsoc_clockevent_init(); |
294 | } | 289 | } |