Skip to content

Commit 28e71e2

Browse files
Linus Walleijdlezcano
authored andcommitted
clocksource/drivers/fttmr010: Refactor to handle clock
The plain Faraday FTTMR010 timer needs a clock to figure out its tick rate, and the gemini reads it directly from the system controller set-up. Split the init function and add two paths for the two compatible-strings. We only support clocking using PCLK because of lack of documentation on how EXTCLK works. The Gemini still works like before, but we can also support a generic, clock-based version. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
1 parent f5bf0ee commit 28e71e2

1 file changed

Lines changed: 73 additions & 46 deletions

File tree

drivers/clocksource/timer-fttmr010.c

Lines changed: 73 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,7 @@
1616
#include <linux/clockchips.h>
1717
#include <linux/clocksource.h>
1818
#include <linux/sched_clock.h>
19-
20-
/*
21-
* Relevant registers in the global syscon
22-
*/
23-
#define GLOBAL_STATUS 0x04
24-
#define CPU_AHB_RATIO_MASK (0x3 << 18)
25-
#define CPU_AHB_1_1 (0x0 << 18)
26-
#define CPU_AHB_3_2 (0x1 << 18)
27-
#define CPU_AHB_24_13 (0x2 << 18)
28-
#define CPU_AHB_2_1 (0x3 << 18)
29-
#define REG_TO_AHB_SPEED(reg) ((((reg) >> 15) & 0x7) * 10 + 130)
19+
#include <linux/clk.h>
3020

3121
/*
3222
* Register definitions for the timers
@@ -189,23 +179,9 @@ static struct irqaction fttmr010_timer_irq = {
189179
.handler = fttmr010_timer_interrupt,
190180
};
191181

192-
static int __init gemini_timer_of_init(struct device_node *np)
182+
static int __init fttmr010_timer_common_init(struct device_node *np)
193183
{
194-
static struct regmap *map;
195184
int irq;
196-
int ret;
197-
u32 val;
198-
199-
map = syscon_regmap_lookup_by_phandle(np, "syscon");
200-
if (IS_ERR(map)) {
201-
pr_err("Can't get regmap for syscon handle");
202-
return -ENODEV;
203-
}
204-
ret = regmap_read(map, GLOBAL_STATUS, &val);
205-
if (ret) {
206-
pr_err("Can't read syscon status register");
207-
return -ENXIO;
208-
}
209185

210186
base = of_iomap(np, 0);
211187
if (!base) {
@@ -219,26 +195,6 @@ static int __init gemini_timer_of_init(struct device_node *np)
219195
return -EINVAL;
220196
}
221197

222-
tick_rate = REG_TO_AHB_SPEED(val) * 1000000;
223-
printk(KERN_INFO "Bus: %dMHz", tick_rate / 1000000);
224-
225-
tick_rate /= 6; /* APB bus run AHB*(1/6) */
226-
227-
switch (val & CPU_AHB_RATIO_MASK) {
228-
case CPU_AHB_1_1:
229-
printk(KERN_CONT "(1/1)\n");
230-
break;
231-
case CPU_AHB_3_2:
232-
printk(KERN_CONT "(3/2)\n");
233-
break;
234-
case CPU_AHB_24_13:
235-
printk(KERN_CONT "(24/13)\n");
236-
break;
237-
case CPU_AHB_2_1:
238-
printk(KERN_CONT "(2/1)\n");
239-
break;
240-
}
241-
242198
/*
243199
* Reset the interrupt mask and status
244200
*/
@@ -273,4 +229,75 @@ static int __init gemini_timer_of_init(struct device_node *np)
273229

274230
return 0;
275231
}
232+
233+
static int __init fttmr010_timer_of_init(struct device_node *np)
234+
{
235+
/*
236+
* These implementations require a clock reference.
237+
* FIXME: we currently only support clocking using PCLK
238+
* and using EXTCLK is not supported in the driver.
239+
*/
240+
struct clk *clk;
241+
242+
clk = of_clk_get_by_name(np, "PCLK");
243+
if (IS_ERR(clk)) {
244+
pr_err("could not get PCLK");
245+
return PTR_ERR(clk);
246+
}
247+
tick_rate = clk_get_rate(clk);
248+
249+
return fttmr010_timer_common_init(np);
250+
}
251+
CLOCKSOURCE_OF_DECLARE(fttmr010, "faraday,fttmr010", fttmr010_timer_of_init);
252+
253+
/*
254+
* Gemini-specific: relevant registers in the global syscon
255+
*/
256+
#define GLOBAL_STATUS 0x04
257+
#define CPU_AHB_RATIO_MASK (0x3 << 18)
258+
#define CPU_AHB_1_1 (0x0 << 18)
259+
#define CPU_AHB_3_2 (0x1 << 18)
260+
#define CPU_AHB_24_13 (0x2 << 18)
261+
#define CPU_AHB_2_1 (0x3 << 18)
262+
#define REG_TO_AHB_SPEED(reg) ((((reg) >> 15) & 0x7) * 10 + 130)
263+
264+
static int __init gemini_timer_of_init(struct device_node *np)
265+
{
266+
static struct regmap *map;
267+
int ret;
268+
u32 val;
269+
270+
map = syscon_regmap_lookup_by_phandle(np, "syscon");
271+
if (IS_ERR(map)) {
272+
pr_err("Can't get regmap for syscon handle\n");
273+
return -ENODEV;
274+
}
275+
ret = regmap_read(map, GLOBAL_STATUS, &val);
276+
if (ret) {
277+
pr_err("Can't read syscon status register\n");
278+
return -ENXIO;
279+
}
280+
281+
tick_rate = REG_TO_AHB_SPEED(val) * 1000000;
282+
pr_info("Bus: %dMHz ", tick_rate / 1000000);
283+
284+
tick_rate /= 6; /* APB bus run AHB*(1/6) */
285+
286+
switch (val & CPU_AHB_RATIO_MASK) {
287+
case CPU_AHB_1_1:
288+
pr_cont("(1/1)\n");
289+
break;
290+
case CPU_AHB_3_2:
291+
pr_cont("(3/2)\n");
292+
break;
293+
case CPU_AHB_24_13:
294+
pr_cont("(24/13)\n");
295+
break;
296+
case CPU_AHB_2_1:
297+
pr_cont("(2/1)\n");
298+
break;
299+
}
300+
301+
return fttmr010_timer_common_init(np);
302+
}
276303
CLOCKSOURCE_OF_DECLARE(gemini, "cortina,gemini-timer", gemini_timer_of_init);

0 commit comments

Comments
 (0)