aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-picoxcell/time.c
diff options
context:
space:
mode:
authorJamie Iles <jamie@jamieiles.com>2011-07-25 12:36:42 -0400
committerJamie Iles <jamie@jamieiles.com>2011-09-26 11:11:56 -0400
commitaf75655c066621352c419646ec0775e9523dc720 (patch)
treeae3895ab4f9d8ce7823f4ef4dcbdbb8f838f3073 /arch/arm/mach-picoxcell/time.c
parentc6a389f123b9f68d605bb7e0f9b32ec1e3e14132 (diff)
picoxcell: support for Picochip picoxcell devices
picoXcell is a family of femtocell devices with an ARM application processor and picoArray DSP processor array. This patch adds support for picoXcell boards to be booted using the device tree registering the VIC's, UART's and timers. v3: - fixup vic compatible string in binding v2: - cleanup empty mach headers - convert to of_platform_populate() - simplify uncompress.h - split vic node into 2 devices - add missing __initconst attributes Signed-off-by: Jamie Iles <jamie@jamieiles.com>
Diffstat (limited to 'arch/arm/mach-picoxcell/time.c')
-rw-r--r--arch/arm/mach-picoxcell/time.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/arch/arm/mach-picoxcell/time.c b/arch/arm/mach-picoxcell/time.c
new file mode 100644
index 000000000000..90a554ff4499
--- /dev/null
+++ b/arch/arm/mach-picoxcell/time.c
@@ -0,0 +1,132 @@
1/*
2 * Copyright (c) 2011 Picochip Ltd., Jamie Iles
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * All enquiries to support@picochip.com
9 */
10#include <linux/dw_apb_timer.h>
11#include <linux/of.h>
12#include <linux/of_address.h>
13#include <linux/of_irq.h>
14#include <linux/sched.h>
15
16#include <asm/mach/time.h>
17#include <asm/sched_clock.h>
18
19#include "common.h"
20
21static void timer_get_base_and_rate(struct device_node *np,
22 void __iomem **base, u32 *rate)
23{
24 *base = of_iomap(np, 0);
25
26 if (!*base)
27 panic("Unable to map regs for %s", np->name);
28
29 if (of_property_read_u32(np, "clock-freq", rate))
30 panic("No clock-freq property for %s", np->name);
31}
32
33static void picoxcell_add_clockevent(struct device_node *event_timer)
34{
35 void __iomem *iobase;
36 struct dw_apb_clock_event_device *ced;
37 u32 irq, rate;
38
39 irq = irq_of_parse_and_map(event_timer, 0);
40 if (irq == NO_IRQ)
41 panic("No IRQ for clock event timer");
42
43 timer_get_base_and_rate(event_timer, &iobase, &rate);
44
45 ced = dw_apb_clockevent_init(0, event_timer->name, 300, iobase, irq,
46 rate);
47 if (!ced)
48 panic("Unable to initialise clockevent device");
49
50 dw_apb_clockevent_register(ced);
51}
52
53static void picoxcell_add_clocksource(struct device_node *source_timer)
54{
55 void __iomem *iobase;
56 struct dw_apb_clocksource *cs;
57 u32 rate;
58
59 timer_get_base_and_rate(source_timer, &iobase, &rate);
60
61 cs = dw_apb_clocksource_init(300, source_timer->name, iobase, rate);
62 if (!cs)
63 panic("Unable to initialise clocksource device");
64
65 dw_apb_clocksource_start(cs);
66 dw_apb_clocksource_register(cs);
67}
68
69static DEFINE_CLOCK_DATA(cd);
70static void __iomem *sched_io_base;
71
72unsigned long long notrace sched_clock(void)
73{
74 cycle_t cyc = sched_io_base ? __raw_readl(sched_io_base) : 0;
75
76 return cyc_to_sched_clock(&cd, cyc, (u32)~0);
77}
78
79static void notrace picoxcell_update_sched_clock(void)
80{
81 cycle_t cyc = sched_io_base ? __raw_readl(sched_io_base) : 0;
82
83 update_sched_clock(&cd, cyc, (u32)~0);
84}
85
86static const struct of_device_id picoxcell_rtc_ids[] __initconst = {
87 { .compatible = "picochip,pc3x2-rtc" },
88 { /* Sentinel */ },
89};
90
91static void picoxcell_init_sched_clock(void)
92{
93 struct device_node *sched_timer;
94 u32 rate;
95
96 sched_timer = of_find_matching_node(NULL, picoxcell_rtc_ids);
97 if (!sched_timer)
98 panic("No RTC for sched clock to use");
99
100 timer_get_base_and_rate(sched_timer, &sched_io_base, &rate);
101 of_node_put(sched_timer);
102
103 init_sched_clock(&cd, picoxcell_update_sched_clock, 32, rate);
104}
105
106static const struct of_device_id picoxcell_timer_ids[] __initconst = {
107 { .compatible = "picochip,pc3x2-timer" },
108 {},
109};
110
111static void __init picoxcell_timer_init(void)
112{
113 struct device_node *event_timer, *source_timer;
114
115 event_timer = of_find_matching_node(NULL, picoxcell_timer_ids);
116 if (!event_timer)
117 panic("No timer for clockevent");
118 picoxcell_add_clockevent(event_timer);
119
120 source_timer = of_find_matching_node(event_timer, picoxcell_timer_ids);
121 if (!source_timer)
122 panic("No timer for clocksource");
123 picoxcell_add_clocksource(source_timer);
124
125 of_node_put(source_timer);
126
127 picoxcell_init_sched_clock();
128}
129
130struct sys_timer picoxcell_timer = {
131 .init = picoxcell_timer_init,
132};