aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource
diff options
context:
space:
mode:
authorAlexandre Belloni <alexandre.belloni@free-electrons.com>2015-03-12 08:07:32 -0400
committerNicolas Ferre <nicolas.ferre@atmel.com>2015-03-16 12:03:06 -0400
commitadf2edfd6003c401ae52a360e0e67abc7deeb952 (patch)
tree8e9e0fd79fa932d18928ed0d51787fd3184e2e0a /drivers/clocksource
parentb53cdd03222391f76e82cd0c7d040816c919ab75 (diff)
clocksource: atmel-st: use syscon/regmap
The register range from the system timer is also used by the watchdog driver. Use a regmap to handle concurrent accesses. Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com> Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com> Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Diffstat (limited to 'drivers/clocksource')
-rw-r--r--drivers/clocksource/timer-atmel-st.c94
1 files changed, 35 insertions, 59 deletions
diff --git a/drivers/clocksource/timer-atmel-st.c b/drivers/clocksource/timer-atmel-st.c
index 7d062ab32674..674ef2519d6b 100644
--- a/drivers/clocksource/timer-atmel-st.c
+++ b/drivers/clocksource/timer-atmel-st.c
@@ -24,18 +24,19 @@
24#include <linux/irq.h> 24#include <linux/irq.h>
25#include <linux/clockchips.h> 25#include <linux/clockchips.h>
26#include <linux/export.h> 26#include <linux/export.h>
27#include <linux/of.h> 27#include <linux/mfd/syscon.h>
28#include <linux/of_address.h> 28#include <linux/mfd/syscon/atmel-st.h>
29#include <linux/of_irq.h> 29#include <linux/of_irq.h>
30#include <linux/regmap.h>
30 31
31#include <asm/mach/time.h> 32#include <asm/mach/time.h>
32 33
33#include <mach/at91_st.h>
34#include <mach/hardware.h> 34#include <mach/hardware.h>
35 35
36static unsigned long last_crtr; 36static unsigned long last_crtr;
37static u32 irqmask; 37static u32 irqmask;
38static struct clock_event_device clkevt; 38static struct clock_event_device clkevt;
39static struct regmap *regmap_st;
39 40
40#define RM9200_TIMER_LATCH ((AT91_SLOW_CLOCK + HZ/2) / HZ) 41#define RM9200_TIMER_LATCH ((AT91_SLOW_CLOCK + HZ/2) / HZ)
41 42
@@ -46,11 +47,11 @@ static struct clock_event_device clkevt;
46 */ 47 */
47static inline unsigned long read_CRTR(void) 48static inline unsigned long read_CRTR(void)
48{ 49{
49 unsigned long x1, x2; 50 unsigned int x1, x2;
50 51
51 x1 = at91_st_read(AT91_ST_CRTR); 52 regmap_read(regmap_st, AT91_ST_CRTR, &x1);
52 do { 53 do {
53 x2 = at91_st_read(AT91_ST_CRTR); 54 regmap_read(regmap_st, AT91_ST_CRTR, &x2);
54 if (x1 == x2) 55 if (x1 == x2)
55 break; 56 break;
56 x1 = x2; 57 x1 = x2;
@@ -63,7 +64,10 @@ static inline unsigned long read_CRTR(void)
63 */ 64 */
64static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id) 65static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
65{ 66{
66 u32 sr = at91_st_read(AT91_ST_SR) & irqmask; 67 u32 sr;
68
69 regmap_read(regmap_st, AT91_ST_SR, &sr);
70 sr &= irqmask;
67 71
68 /* 72 /*
69 * irqs should be disabled here, but as the irq is shared they are only 73 * irqs should be disabled here, but as the irq is shared they are only
@@ -115,23 +119,25 @@ static struct clocksource clk32k = {
115static void 119static void
116clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev) 120clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev)
117{ 121{
122 unsigned int val;
123
118 /* Disable and flush pending timer interrupts */ 124 /* Disable and flush pending timer interrupts */
119 at91_st_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_ALMS); 125 regmap_write(regmap_st, AT91_ST_IDR, AT91_ST_PITS | AT91_ST_ALMS);
120 at91_st_read(AT91_ST_SR); 126 regmap_read(regmap_st, AT91_ST_SR, &val);
121 127
122 last_crtr = read_CRTR(); 128 last_crtr = read_CRTR();
123 switch (mode) { 129 switch (mode) {
124 case CLOCK_EVT_MODE_PERIODIC: 130 case CLOCK_EVT_MODE_PERIODIC:
125 /* PIT for periodic irqs; fixed rate of 1/HZ */ 131 /* PIT for periodic irqs; fixed rate of 1/HZ */
126 irqmask = AT91_ST_PITS; 132 irqmask = AT91_ST_PITS;
127 at91_st_write(AT91_ST_PIMR, RM9200_TIMER_LATCH); 133 regmap_write(regmap_st, AT91_ST_PIMR, RM9200_TIMER_LATCH);
128 break; 134 break;
129 case CLOCK_EVT_MODE_ONESHOT: 135 case CLOCK_EVT_MODE_ONESHOT:
130 /* ALM for oneshot irqs, set by next_event() 136 /* ALM for oneshot irqs, set by next_event()
131 * before 32 seconds have passed 137 * before 32 seconds have passed
132 */ 138 */
133 irqmask = AT91_ST_ALMS; 139 irqmask = AT91_ST_ALMS;
134 at91_st_write(AT91_ST_RTAR, last_crtr); 140 regmap_write(regmap_st, AT91_ST_RTAR, last_crtr);
135 break; 141 break;
136 case CLOCK_EVT_MODE_SHUTDOWN: 142 case CLOCK_EVT_MODE_SHUTDOWN:
137 case CLOCK_EVT_MODE_UNUSED: 143 case CLOCK_EVT_MODE_UNUSED:
@@ -139,7 +145,7 @@ clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev)
139 irqmask = 0; 145 irqmask = 0;
140 break; 146 break;
141 } 147 }
142 at91_st_write(AT91_ST_IER, irqmask); 148 regmap_write(regmap_st, AT91_ST_IER, irqmask);
143} 149}
144 150
145static int 151static int
@@ -147,6 +153,7 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
147{ 153{
148 u32 alm; 154 u32 alm;
149 int status = 0; 155 int status = 0;
156 unsigned int val;
150 157
151 BUG_ON(delta < 2); 158 BUG_ON(delta < 2);
152 159
@@ -162,12 +169,12 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
162 alm = read_CRTR(); 169 alm = read_CRTR();
163 170
164 /* Cancel any pending alarm; flush any pending IRQ */ 171 /* Cancel any pending alarm; flush any pending IRQ */
165 at91_st_write(AT91_ST_RTAR, alm); 172 regmap_write(regmap_st, AT91_ST_RTAR, alm);
166 at91_st_read(AT91_ST_SR); 173 regmap_read(regmap_st, AT91_ST_SR, &val);
167 174
168 /* Schedule alarm by writing RTAR. */ 175 /* Schedule alarm by writing RTAR. */
169 alm += delta; 176 alm += delta;
170 at91_st_write(AT91_ST_RTAR, alm); 177 regmap_write(regmap_st, AT91_ST_RTAR, alm);
171 178
172 return status; 179 return status;
173} 180}
@@ -180,57 +187,26 @@ static struct clock_event_device clkevt = {
180 .set_mode = clkevt32k_mode, 187 .set_mode = clkevt32k_mode,
181}; 188};
182 189
183void __iomem *at91_st_base;
184EXPORT_SYMBOL_GPL(at91_st_base);
185
186static const struct of_device_id at91rm9200_st_timer_ids[] = {
187 { .compatible = "atmel,at91rm9200-st" },
188 { /* sentinel */ }
189};
190
191static int __init of_at91rm9200_st_init(void)
192{
193 struct device_node *np;
194 int ret;
195
196 np = of_find_matching_node(NULL, at91rm9200_st_timer_ids);
197 if (!np)
198 goto err;
199
200 at91_st_base = of_iomap(np, 0);
201 if (!at91_st_base)
202 goto node_err;
203
204 /* Get the interrupts property */
205 ret = irq_of_parse_and_map(np, 0);
206 if (!ret)
207 goto ioremap_err;
208 at91rm9200_timer_irq.irq = ret;
209
210 of_node_put(np);
211
212 return 0;
213
214ioremap_err:
215 iounmap(at91_st_base);
216node_err:
217 of_node_put(np);
218err:
219 return -EINVAL;
220}
221
222/* 190/*
223 * ST (system timer) module supports both clockevents and clocksource. 191 * ST (system timer) module supports both clockevents and clocksource.
224 */ 192 */
225static void __init atmel_st_timer_init(struct device_node *node) 193static void __init atmel_st_timer_init(struct device_node *node)
226{ 194{
227 /* For device tree enabled device: initialize here */ 195 unsigned int val;
228 of_at91rm9200_st_init(); 196
197 regmap_st = syscon_node_to_regmap(node);
198 if (IS_ERR(regmap_st))
199 panic(pr_fmt("Unable to get regmap\n"));
229 200
230 /* Disable all timer interrupts, and clear any pending ones */ 201 /* Disable all timer interrupts, and clear any pending ones */
231 at91_st_write(AT91_ST_IDR, 202 regmap_write(regmap_st, AT91_ST_IDR,
232 AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS); 203 AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
233 at91_st_read(AT91_ST_SR); 204 regmap_read(regmap_st, AT91_ST_SR, &val);
205
206 /* Get the interrupts property */
207 at91rm9200_timer_irq.irq = irq_of_parse_and_map(node, 0);
208 if (!at91rm9200_timer_irq.irq)
209 panic(pr_fmt("Unable to get IRQ from DT\n"));
234 210
235 /* Make IRQs happen for the system timer */ 211 /* Make IRQs happen for the system timer */
236 setup_irq(at91rm9200_timer_irq.irq, &at91rm9200_timer_irq); 212 setup_irq(at91rm9200_timer_irq.irq, &at91rm9200_timer_irq);
@@ -239,7 +215,7 @@ static void __init atmel_st_timer_init(struct device_node *node)
239 * directly for the clocksource and all clockevents, after adjusting 215 * directly for the clocksource and all clockevents, after adjusting
240 * its prescaler from the 1 Hz default. 216 * its prescaler from the 1 Hz default.
241 */ 217 */
242 at91_st_write(AT91_ST_RTMR, 1); 218 regmap_write(regmap_st, AT91_ST_RTMR, 1);
243 219
244 /* Setup timer clockevent, with minimum of two ticks (important!!) */ 220 /* Setup timer clockevent, with minimum of two ticks (important!!) */
245 clkevt.cpumask = cpumask_of(0); 221 clkevt.cpumask = cpumask_of(0);