diff options
author | Russell King - ARM Linux <linux@arm.linux.org.uk> | 2011-07-11 02:05:34 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2011-07-11 02:05:34 -0400 |
commit | 354a183f536a8edf6cb80ee3e3f393736e278810 (patch) | |
tree | 499ca3cad660ea38fdd95cc1fb50ecb16adafc07 /arch/arm/plat-omap | |
parent | 727e18b429e3badda12d1de74f492bfa363a2e94 (diff) |
Convert OMAPs 32kHz clocksource implementation to use the generic MMIO
clocksource support. This achieves several things:
1. It means we get rid of all these helper functions which frankly should
never have been necessary.
2. It means omap_readl() inside these helper functions does not appear in
ftrace output.
Another plus is that we avoid the overhead of calculating the address to
read each time, but a minus is that we use readl() which has a barrier.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
[tony@atomide.com: updated to use ioremap]
Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r-- | arch/arm/plat-omap/counter_32k.c | 121 |
1 files changed, 34 insertions, 87 deletions
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c index c13bc3d3eb2c..a6cbb712da51 100644 --- a/arch/arm/plat-omap/counter_32k.c +++ b/arch/arm/plat-omap/counter_32k.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
21 | #include <linux/clocksource.h> | ||
21 | 22 | ||
22 | #include <asm/sched_clock.h> | 23 | #include <asm/sched_clock.h> |
23 | 24 | ||
@@ -26,87 +27,16 @@ | |||
26 | 27 | ||
27 | #include <plat/clock.h> | 28 | #include <plat/clock.h> |
28 | 29 | ||
29 | |||
30 | /* | 30 | /* |
31 | * 32KHz clocksource ... always available, on pretty most chips except | 31 | * 32KHz clocksource ... always available, on pretty most chips except |
32 | * OMAP 730 and 1510. Other timers could be used as clocksources, with | 32 | * OMAP 730 and 1510. Other timers could be used as clocksources, with |
33 | * higher resolution in free-running counter modes (e.g. 12 MHz xtal), | 33 | * higher resolution in free-running counter modes (e.g. 12 MHz xtal), |
34 | * but systems won't necessarily want to spend resources that way. | 34 | * but systems won't necessarily want to spend resources that way. |
35 | */ | 35 | */ |
36 | static void __iomem *timer_32k_base; | ||
36 | 37 | ||
37 | #define OMAP16XX_TIMER_32K_SYNCHRONIZED 0xfffbc410 | 38 | #define OMAP16XX_TIMER_32K_SYNCHRONIZED 0xfffbc410 |
38 | 39 | ||
39 | #include <linux/clocksource.h> | ||
40 | |||
41 | /* | ||
42 | * offset_32k holds the init time counter value. It is then subtracted | ||
43 | * from every counter read to achieve a counter that counts time from the | ||
44 | * kernel boot (needed for sched_clock()). | ||
45 | */ | ||
46 | static u32 offset_32k __read_mostly; | ||
47 | |||
48 | #ifdef CONFIG_ARCH_OMAP16XX | ||
49 | static cycle_t notrace omap16xx_32k_read(struct clocksource *cs) | ||
50 | { | ||
51 | return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED) - offset_32k; | ||
52 | } | ||
53 | #else | ||
54 | #define omap16xx_32k_read NULL | ||
55 | #endif | ||
56 | |||
57 | #ifdef CONFIG_SOC_OMAP2420 | ||
58 | static cycle_t notrace omap2420_32k_read(struct clocksource *cs) | ||
59 | { | ||
60 | return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10) - offset_32k; | ||
61 | } | ||
62 | #else | ||
63 | #define omap2420_32k_read NULL | ||
64 | #endif | ||
65 | |||
66 | #ifdef CONFIG_SOC_OMAP2430 | ||
67 | static cycle_t notrace omap2430_32k_read(struct clocksource *cs) | ||
68 | { | ||
69 | return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10) - offset_32k; | ||
70 | } | ||
71 | #else | ||
72 | #define omap2430_32k_read NULL | ||
73 | #endif | ||
74 | |||
75 | #ifdef CONFIG_ARCH_OMAP3 | ||
76 | static cycle_t notrace omap34xx_32k_read(struct clocksource *cs) | ||
77 | { | ||
78 | return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10) - offset_32k; | ||
79 | } | ||
80 | #else | ||
81 | #define omap34xx_32k_read NULL | ||
82 | #endif | ||
83 | |||
84 | #ifdef CONFIG_ARCH_OMAP4 | ||
85 | static cycle_t notrace omap44xx_32k_read(struct clocksource *cs) | ||
86 | { | ||
87 | return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10) - offset_32k; | ||
88 | } | ||
89 | #else | ||
90 | #define omap44xx_32k_read NULL | ||
91 | #endif | ||
92 | |||
93 | /* | ||
94 | * Kernel assumes that sched_clock can be called early but may not have | ||
95 | * things ready yet. | ||
96 | */ | ||
97 | static cycle_t notrace omap_32k_read_dummy(struct clocksource *cs) | ||
98 | { | ||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | static struct clocksource clocksource_32k = { | ||
103 | .name = "32k_counter", | ||
104 | .rating = 250, | ||
105 | .read = omap_32k_read_dummy, | ||
106 | .mask = CLOCKSOURCE_MASK(32), | ||
107 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
108 | }; | ||
109 | |||
110 | /* | 40 | /* |
111 | * Returns current time from boot in nsecs. It's OK for this to wrap | 41 | * Returns current time from boot in nsecs. It's OK for this to wrap |
112 | * around for now, as it's just a relative time stamp. | 42 | * around for now, as it's just a relative time stamp. |
@@ -122,7 +52,7 @@ static DEFINE_CLOCK_DATA(cd); | |||
122 | 52 | ||
123 | static inline unsigned long long notrace _omap_32k_sched_clock(void) | 53 | static inline unsigned long long notrace _omap_32k_sched_clock(void) |
124 | { | 54 | { |
125 | u32 cyc = clocksource_32k.read(&clocksource_32k); | 55 | u32 cyc = timer_32k_base ? __raw_readl(timer_32k_base) : 0; |
126 | return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT); | 56 | return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT); |
127 | } | 57 | } |
128 | 58 | ||
@@ -140,7 +70,7 @@ unsigned long long notrace omap_32k_sched_clock(void) | |||
140 | 70 | ||
141 | static void notrace omap_update_sched_clock(void) | 71 | static void notrace omap_update_sched_clock(void) |
142 | { | 72 | { |
143 | u32 cyc = clocksource_32k.read(&clocksource_32k); | 73 | u32 cyc = timer_32k_base ? __raw_readl(timer_32k_base) : 0; |
144 | update_sched_clock(&cd, cyc, (u32)~0); | 74 | update_sched_clock(&cd, cyc, (u32)~0); |
145 | } | 75 | } |
146 | 76 | ||
@@ -153,6 +83,7 @@ static void notrace omap_update_sched_clock(void) | |||
153 | */ | 83 | */ |
154 | static struct timespec persistent_ts; | 84 | static struct timespec persistent_ts; |
155 | static cycles_t cycles, last_cycles; | 85 | static cycles_t cycles, last_cycles; |
86 | static unsigned int persistent_mult, persistent_shift; | ||
156 | void read_persistent_clock(struct timespec *ts) | 87 | void read_persistent_clock(struct timespec *ts) |
157 | { | 88 | { |
158 | unsigned long long nsecs; | 89 | unsigned long long nsecs; |
@@ -160,11 +91,10 @@ void read_persistent_clock(struct timespec *ts) | |||
160 | struct timespec *tsp = &persistent_ts; | 91 | struct timespec *tsp = &persistent_ts; |
161 | 92 | ||
162 | last_cycles = cycles; | 93 | last_cycles = cycles; |
163 | cycles = clocksource_32k.read(&clocksource_32k); | 94 | cycles = timer_32k_base ? __raw_readl(timer_32k_base) : 0; |
164 | delta = cycles - last_cycles; | 95 | delta = cycles - last_cycles; |
165 | 96 | ||
166 | nsecs = clocksource_cyc2ns(delta, | 97 | nsecs = clocksource_cyc2ns(delta, persistent_mult, persistent_shift); |
167 | clocksource_32k.mult, clocksource_32k.shift); | ||
168 | 98 | ||
169 | timespec_add_ns(tsp, nsecs); | 99 | timespec_add_ns(tsp, nsecs); |
170 | *ts = *tsp; | 100 | *ts = *tsp; |
@@ -176,29 +106,46 @@ int __init omap_init_clocksource_32k(void) | |||
176 | "%s: can't register clocksource!\n"; | 106 | "%s: can't register clocksource!\n"; |
177 | 107 | ||
178 | if (cpu_is_omap16xx() || cpu_class_is_omap2()) { | 108 | if (cpu_is_omap16xx() || cpu_class_is_omap2()) { |
109 | u32 pbase; | ||
110 | unsigned long size = SZ_4K; | ||
111 | void __iomem *base; | ||
179 | struct clk *sync_32k_ick; | 112 | struct clk *sync_32k_ick; |
180 | 113 | ||
181 | if (cpu_is_omap16xx()) | 114 | if (cpu_is_omap16xx()) { |
182 | clocksource_32k.read = omap16xx_32k_read; | 115 | pbase = OMAP16XX_TIMER_32K_SYNCHRONIZED; |
183 | else if (cpu_is_omap2420()) | 116 | size = SZ_1K; |
184 | clocksource_32k.read = omap2420_32k_read; | 117 | } else if (cpu_is_omap2420()) |
118 | pbase = OMAP2420_32KSYNCT_BASE + 0x10; | ||
185 | else if (cpu_is_omap2430()) | 119 | else if (cpu_is_omap2430()) |
186 | clocksource_32k.read = omap2430_32k_read; | 120 | pbase = OMAP2430_32KSYNCT_BASE + 0x10; |
187 | else if (cpu_is_omap34xx()) | 121 | else if (cpu_is_omap34xx()) |
188 | clocksource_32k.read = omap34xx_32k_read; | 122 | pbase = OMAP3430_32KSYNCT_BASE + 0x10; |
189 | else if (cpu_is_omap44xx()) | 123 | else if (cpu_is_omap44xx()) |
190 | clocksource_32k.read = omap44xx_32k_read; | 124 | pbase = OMAP4430_32KSYNCT_BASE + 0x10; |
191 | else | 125 | else |
192 | return -ENODEV; | 126 | return -ENODEV; |
193 | 127 | ||
128 | /* For this to work we must have a static mapping in io.c for this area */ | ||
129 | base = ioremap(pbase, size); | ||
130 | if (!base) | ||
131 | return -ENODEV; | ||
132 | |||
194 | sync_32k_ick = clk_get(NULL, "omap_32ksync_ick"); | 133 | sync_32k_ick = clk_get(NULL, "omap_32ksync_ick"); |
195 | if (!IS_ERR(sync_32k_ick)) | 134 | if (!IS_ERR(sync_32k_ick)) |
196 | clk_enable(sync_32k_ick); | 135 | clk_enable(sync_32k_ick); |
197 | 136 | ||
198 | offset_32k = clocksource_32k.read(&clocksource_32k); | 137 | timer_32k_base = base; |
138 | |||
139 | /* | ||
140 | * 120000 rough estimate from the calculations in | ||
141 | * __clocksource_updatefreq_scale. | ||
142 | */ | ||
143 | clocks_calc_mult_shift(&persistent_mult, &persistent_shift, | ||
144 | 32768, NSEC_PER_SEC, 120000); | ||
199 | 145 | ||
200 | if (clocksource_register_hz(&clocksource_32k, 32768)) | 146 | if (clocksource_mmio_init(base, "32k_counter", 32768, 250, 32, |
201 | printk(err, clocksource_32k.name); | 147 | clocksource_mmio_readl_up)) |
148 | printk(err, "32k_counter"); | ||
202 | 149 | ||
203 | init_fixed_sched_clock(&cd, omap_update_sched_clock, 32, | 150 | init_fixed_sched_clock(&cd, omap_update_sched_clock, 32, |
204 | 32768, SC_MULT, SC_SHIFT); | 151 | 32768, SC_MULT, SC_SHIFT); |