aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-at91/at91sam926x_time.c
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@free-electrons.com>2014-07-01 05:33:23 -0400
committerNicolas Ferre <nicolas.ferre@atmel.com>2014-09-03 04:55:44 -0400
commit64568d1dbd673aca3de8d2a17b9db507c5b85df7 (patch)
tree20c415ed7c7450c9d622e8817411ba49fcc4a69e /arch/arm/mach-at91/at91sam926x_time.c
parent7f282e0137bfe712655e9f8da5ade105f6918741 (diff)
ARM: at91: PIT: (Almost) remove the global variables
The timer driver is using some global variables to define some variables it has to use in most of its functions, like the base address. Use some container_of calls to have a single dynamic (and local) variable to hold this content. The only exception is in the !DT case, where the call chain to at91sam926x_ioremap_pit and then at91sam926x_pit_init as init_time makes it hard for the moment to pass the physical address of the timer. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> Acked-by: Boris BREZILLON <boris.brezillon@free-electrons.com> Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com> Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Diffstat (limited to 'arch/arm/mach-at91/at91sam926x_time.c')
-rw-r--r--arch/arm/mach-at91/at91sam926x_time.c179
1 files changed, 108 insertions, 71 deletions
diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
index e476474cb05e..9abb289dce72 100644
--- a/arch/arm/mach-at91/at91sam926x_time.c
+++ b/arch/arm/mach-at91/at91sam926x_time.c
@@ -20,6 +20,7 @@
20#include <linux/of.h> 20#include <linux/of.h>
21#include <linux/of_address.h> 21#include <linux/of_address.h>
22#include <linux/of_irq.h> 22#include <linux/of_irq.h>
23#include <linux/slab.h>
23 24
24#include <mach/hardware.h> 25#include <mach/hardware.h>
25 26
@@ -39,19 +40,35 @@
39#define PIT_CPIV(x) ((x) & AT91_PIT_CPIV) 40#define PIT_CPIV(x) ((x) & AT91_PIT_CPIV)
40#define PIT_PICNT(x) (((x) & AT91_PIT_PICNT) >> 20) 41#define PIT_PICNT(x) (((x) & AT91_PIT_PICNT) >> 20)
41 42
42static u32 pit_cycle; /* write-once */ 43struct pit_data {
43static u32 pit_cnt; /* access only w/system irq blocked */ 44 struct clock_event_device clkevt;
44static void __iomem *pit_base_addr __read_mostly; 45 struct clocksource clksrc;
45static struct clk *mck;
46 46
47static inline unsigned int pit_read(unsigned int reg_offset) 47 void __iomem *base;
48 u32 cycle;
49 u32 cnt;
50 unsigned int irq;
51 struct clk *mck;
52};
53
54static inline struct pit_data *clksrc_to_pit_data(struct clocksource *clksrc)
48{ 55{
49 return __raw_readl(pit_base_addr + reg_offset); 56 return container_of(clksrc, struct pit_data, clksrc);
50} 57}
51 58
52static inline void pit_write(unsigned int reg_offset, unsigned long value) 59static inline struct pit_data *clkevt_to_pit_data(struct clock_event_device *clkevt)
53{ 60{
54 __raw_writel(value, pit_base_addr + reg_offset); 61 return container_of(clkevt, struct pit_data, clkevt);
62}
63
64static inline unsigned int pit_read(void __iomem *base, unsigned int reg_offset)
65{
66 return __raw_readl(base + reg_offset);
67}
68
69static inline void pit_write(void __iomem *base, unsigned int reg_offset, unsigned long value)
70{
71 __raw_writel(value, base + reg_offset);
55} 72}
56 73
57/* 74/*
@@ -60,40 +77,35 @@ static inline void pit_write(unsigned int reg_offset, unsigned long value)
60 */ 77 */
61static cycle_t read_pit_clk(struct clocksource *cs) 78static cycle_t read_pit_clk(struct clocksource *cs)
62{ 79{
80 struct pit_data *data = clksrc_to_pit_data(cs);
63 unsigned long flags; 81 unsigned long flags;
64 u32 elapsed; 82 u32 elapsed;
65 u32 t; 83 u32 t;
66 84
67 raw_local_irq_save(flags); 85 raw_local_irq_save(flags);
68 elapsed = pit_cnt; 86 elapsed = data->cnt;
69 t = pit_read(AT91_PIT_PIIR); 87 t = pit_read(data->base, AT91_PIT_PIIR);
70 raw_local_irq_restore(flags); 88 raw_local_irq_restore(flags);
71 89
72 elapsed += PIT_PICNT(t) * pit_cycle; 90 elapsed += PIT_PICNT(t) * data->cycle;
73 elapsed += PIT_CPIV(t); 91 elapsed += PIT_CPIV(t);
74 return elapsed; 92 return elapsed;
75} 93}
76 94
77static struct clocksource pit_clk = {
78 .name = "pit",
79 .rating = 175,
80 .read = read_pit_clk,
81 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
82};
83
84
85/* 95/*
86 * Clockevent device: interrupts every 1/HZ (== pit_cycles * MCK/16) 96 * Clockevent device: interrupts every 1/HZ (== pit_cycles * MCK/16)
87 */ 97 */
88static void 98static void
89pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) 99pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
90{ 100{
101 struct pit_data *data = clkevt_to_pit_data(dev);
102
91 switch (mode) { 103 switch (mode) {
92 case CLOCK_EVT_MODE_PERIODIC: 104 case CLOCK_EVT_MODE_PERIODIC:
93 /* update clocksource counter */ 105 /* update clocksource counter */
94 pit_cnt += pit_cycle * PIT_PICNT(pit_read(AT91_PIT_PIVR)); 106 data->cnt += data->cycle * PIT_PICNT(pit_read(data->base, AT91_PIT_PIVR));
95 pit_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN 107 pit_write(data->base, AT91_PIT_MR,
96 | AT91_PIT_PITIEN); 108 (data->cycle - 1) | AT91_PIT_PITEN | AT91_PIT_PITIEN);
97 break; 109 break;
98 case CLOCK_EVT_MODE_ONESHOT: 110 case CLOCK_EVT_MODE_ONESHOT:
99 BUG(); 111 BUG();
@@ -101,7 +113,8 @@ pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
101 case CLOCK_EVT_MODE_SHUTDOWN: 113 case CLOCK_EVT_MODE_SHUTDOWN:
102 case CLOCK_EVT_MODE_UNUSED: 114 case CLOCK_EVT_MODE_UNUSED:
103 /* disable irq, leaving the clocksource active */ 115 /* disable irq, leaving the clocksource active */
104 pit_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN); 116 pit_write(data->base, AT91_PIT_MR,
117 (data->cycle - 1) | AT91_PIT_PITEN);
105 break; 118 break;
106 case CLOCK_EVT_MODE_RESUME: 119 case CLOCK_EVT_MODE_RESUME:
107 break; 120 break;
@@ -110,44 +123,40 @@ pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
110 123
111static void at91sam926x_pit_suspend(struct clock_event_device *cedev) 124static void at91sam926x_pit_suspend(struct clock_event_device *cedev)
112{ 125{
126 struct pit_data *data = clkevt_to_pit_data(cedev);
127
113 /* Disable timer */ 128 /* Disable timer */
114 pit_write(AT91_PIT_MR, 0); 129 pit_write(data->base, AT91_PIT_MR, 0);
115} 130}
116 131
117static void at91sam926x_pit_reset(void) 132static void at91sam926x_pit_reset(struct pit_data *data)
118{ 133{
119 /* Disable timer and irqs */ 134 /* Disable timer and irqs */
120 pit_write(AT91_PIT_MR, 0); 135 pit_write(data->base, AT91_PIT_MR, 0);
121 136
122 /* Clear any pending interrupts, wait for PIT to stop counting */ 137 /* Clear any pending interrupts, wait for PIT to stop counting */
123 while (PIT_CPIV(pit_read(AT91_PIT_PIVR)) != 0) 138 while (PIT_CPIV(pit_read(data->base, AT91_PIT_PIVR)) != 0)
124 cpu_relax(); 139 cpu_relax();
125 140
126 /* Start PIT but don't enable IRQ */ 141 /* Start PIT but don't enable IRQ */
127 pit_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN); 142 pit_write(data->base, AT91_PIT_MR,
143 (data->cycle - 1) | AT91_PIT_PITEN);
128} 144}
129 145
130static void at91sam926x_pit_resume(struct clock_event_device *cedev) 146static void at91sam926x_pit_resume(struct clock_event_device *cedev)
131{ 147{
132 at91sam926x_pit_reset(); 148 struct pit_data *data = clkevt_to_pit_data(cedev);
133}
134
135static struct clock_event_device pit_clkevt = {
136 .name = "pit",
137 .features = CLOCK_EVT_FEAT_PERIODIC,
138 .shift = 32,
139 .rating = 100,
140 .set_mode = pit_clkevt_mode,
141 .suspend = at91sam926x_pit_suspend,
142 .resume = at91sam926x_pit_resume,
143};
144 149
150 at91sam926x_pit_reset(data);
151}
145 152
146/* 153/*
147 * IRQ handler for the timer. 154 * IRQ handler for the timer.
148 */ 155 */
149static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id) 156static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id)
150{ 157{
158 struct pit_data *data = dev_id;
159
151 /* 160 /*
152 * irqs should be disabled here, but as the irq is shared they are only 161 * irqs should be disabled here, but as the irq is shared they are only
153 * guaranteed to be off if the timer irq is registered first. 162 * guaranteed to be off if the timer irq is registered first.
@@ -155,15 +164,15 @@ static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id)
155 WARN_ON_ONCE(!irqs_disabled()); 164 WARN_ON_ONCE(!irqs_disabled());
156 165
157 /* The PIT interrupt may be disabled, and is shared */ 166 /* The PIT interrupt may be disabled, and is shared */
158 if ((pit_clkevt.mode == CLOCK_EVT_MODE_PERIODIC) 167 if ((data->clkevt.mode == CLOCK_EVT_MODE_PERIODIC) &&
159 && (pit_read(AT91_PIT_SR) & AT91_PIT_PITS)) { 168 (pit_read(data->base, AT91_PIT_SR) & AT91_PIT_PITS)) {
160 unsigned nr_ticks; 169 unsigned nr_ticks;
161 170
162 /* Get number of ticks performed before irq, and ack it */ 171 /* Get number of ticks performed before irq, and ack it */
163 nr_ticks = PIT_PICNT(pit_read(AT91_PIT_PIVR)); 172 nr_ticks = PIT_PICNT(pit_read(data->base, AT91_PIT_PIVR));
164 do { 173 do {
165 pit_cnt += pit_cycle; 174 data->cnt += data->cycle;
166 pit_clkevt.event_handler(&pit_clkevt); 175 data->clkevt.event_handler(&data->clkevt);
167 nr_ticks--; 176 nr_ticks--;
168 } while (nr_ticks); 177 } while (nr_ticks);
169 178
@@ -176,7 +185,7 @@ static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id)
176/* 185/*
177 * Set up both clocksource and clockevent support. 186 * Set up both clocksource and clockevent support.
178 */ 187 */
179static void __init at91sam926x_pit_common_init(unsigned int pit_irq) 188static void __init at91sam926x_pit_common_init(struct pit_data *data)
180{ 189{
181 unsigned long pit_rate; 190 unsigned long pit_rate;
182 unsigned bits; 191 unsigned bits;
@@ -186,67 +195,95 @@ static void __init at91sam926x_pit_common_init(unsigned int pit_irq)
186 * Use our actual MCK to figure out how many MCK/16 ticks per 195 * Use our actual MCK to figure out how many MCK/16 ticks per
187 * 1/HZ period (instead of a compile-time constant LATCH). 196 * 1/HZ period (instead of a compile-time constant LATCH).
188 */ 197 */
189 pit_rate = clk_get_rate(mck) / 16; 198 pit_rate = clk_get_rate(data->mck) / 16;
190 pit_cycle = DIV_ROUND_CLOSEST(pit_rate, HZ); 199 data->cycle = DIV_ROUND_CLOSEST(pit_rate, HZ);
191 WARN_ON(((pit_cycle - 1) & ~AT91_PIT_PIV) != 0); 200 WARN_ON(((data->cycle - 1) & ~AT91_PIT_PIV) != 0);
192 201
193 /* Initialize and enable the timer */ 202 /* Initialize and enable the timer */
194 at91sam926x_pit_reset(); 203 at91sam926x_pit_reset(data);
195 204
196 /* 205 /*
197 * Register clocksource. The high order bits of PIV are unused, 206 * Register clocksource. The high order bits of PIV are unused,
198 * so this isn't a 32-bit counter unless we get clockevent irqs. 207 * so this isn't a 32-bit counter unless we get clockevent irqs.
199 */ 208 */
200 bits = 12 /* PICNT */ + ilog2(pit_cycle) /* PIV */; 209 bits = 12 /* PICNT */ + ilog2(data->cycle) /* PIV */;
201 pit_clk.mask = CLOCKSOURCE_MASK(bits); 210 data->clksrc.mask = CLOCKSOURCE_MASK(bits);
202 clocksource_register_hz(&pit_clk, pit_rate); 211 data->clksrc.name = "pit";
212 data->clksrc.rating = 175;
213 data->clksrc.read = read_pit_clk,
214 data->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS,
215 clocksource_register_hz(&data->clksrc, pit_rate);
203 216
204 /* Set up irq handler */ 217 /* Set up irq handler */
205 ret = request_irq(pit_irq, at91sam926x_pit_interrupt, 218 ret = request_irq(data->irq, at91sam926x_pit_interrupt,
206 IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL, 219 IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
207 "at91_tick", pit_base_addr); 220 "at91_tick", data);
208 if (ret) 221 if (ret)
209 panic(pr_fmt("Unable to setup IRQ\n")); 222 panic(pr_fmt("Unable to setup IRQ\n"));
210 223
211 /* Set up and register clockevents */ 224 /* Set up and register clockevents */
212 pit_clkevt.mult = div_sc(pit_rate, NSEC_PER_SEC, pit_clkevt.shift); 225 data->clkevt.name = "pit";
213 pit_clkevt.cpumask = cpumask_of(0); 226 data->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
214 clockevents_register_device(&pit_clkevt); 227 data->clkevt.shift = 32;
228 data->clkevt.mult = div_sc(pit_rate, NSEC_PER_SEC, data->clkevt.shift);
229 data->clkevt.rating = 100;
230 data->clkevt.cpumask = cpumask_of(0);
231
232 data->clkevt.set_mode = pit_clkevt_mode;
233 data->clkevt.resume = at91sam926x_pit_resume;
234 data->clkevt.suspend = at91sam926x_pit_suspend;
235 clockevents_register_device(&data->clkevt);
215} 236}
216 237
217static void __init at91sam926x_pit_dt_init(struct device_node *node) 238static void __init at91sam926x_pit_dt_init(struct device_node *node)
218{ 239{
219 unsigned int irq; 240 struct pit_data *data;
220 241
221 pit_base_addr = of_iomap(node, 0); 242 data = kzalloc(sizeof(*data), GFP_KERNEL);
222 if (!pit_base_addr) 243 if (!data)
244 panic(pr_fmt("Unable to allocate memory\n"));
245
246 data->base = of_iomap(node, 0);
247 if (!data->base)
223 panic(pr_fmt("Could not map PIT address\n")); 248 panic(pr_fmt("Could not map PIT address\n"));
224 249
225 mck = of_clk_get(node, 0); 250 data->mck = of_clk_get(node, 0);
226 if (IS_ERR(mck)) 251 if (IS_ERR(data->mck))
227 /* Fallback on clkdev for !CCF-based boards */ 252 /* Fallback on clkdev for !CCF-based boards */
228 mck = clk_get(NULL, "mck"); 253 data->mck = clk_get(NULL, "mck");
229 254
230 if (IS_ERR(mck)) 255 if (IS_ERR(data->mck))
231 panic(pr_fmt("Unable to get mck clk\n")); 256 panic(pr_fmt("Unable to get mck clk\n"));
232 257
233 /* Get the interrupts property */ 258 /* Get the interrupts property */
234 irq = irq_of_parse_and_map(node, 0); 259 data->irq = irq_of_parse_and_map(node, 0);
235 if (!irq) 260 if (!data->irq)
236 panic(pr_fmt("Unable to get IRQ from DT\n")); 261 panic(pr_fmt("Unable to get IRQ from DT\n"));
237 262
238 at91sam926x_pit_common_init(irq); 263 at91sam926x_pit_common_init(data);
239} 264}
240CLOCKSOURCE_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit", 265CLOCKSOURCE_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit",
241 at91sam926x_pit_dt_init); 266 at91sam926x_pit_dt_init);
242 267
268static void __iomem *pit_base_addr;
269
243void __init at91sam926x_pit_init(void) 270void __init at91sam926x_pit_init(void)
244{ 271{
245 mck = clk_get(NULL, "mck"); 272 struct pit_data *data;
246 if (IS_ERR(mck)) 273
274 data = kzalloc(sizeof(*data), GFP_KERNEL);
275 if (!data)
276 panic(pr_fmt("Unable to allocate memory\n"));
277
278 data->base = pit_base_addr;
279
280 data->mck = clk_get(NULL, "mck");
281 if (IS_ERR(data->mck))
247 panic(pr_fmt("Unable to get mck clk\n")); 282 panic(pr_fmt("Unable to get mck clk\n"));
248 283
249 at91sam926x_pit_common_init(NR_IRQS_LEGACY + AT91_ID_SYS); 284 data->irq = NR_IRQS_LEGACY + AT91_ID_SYS;
285
286 at91sam926x_pit_common_init(data);
250} 287}
251 288
252void __init at91sam926x_ioremap_pit(u32 addr) 289void __init at91sam926x_ioremap_pit(u32 addr)