Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
at91sam926x_time.c
Go to the documentation of this file.
1 /*
2  * at91sam926x_time.c - Periodic Interval Timer (PIT) for at91sam926x
3  *
4  * Copyright (C) 2005-2006 M. Amine SAYA, ATMEL Rousset, France
5  * Revision 2005 M. Nicolas Diremdjian, ATMEL Rousset, France
6  * Converted to ClockSource/ClockEvents by David Brownell.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12 #include <linux/interrupt.h>
13 #include <linux/irq.h>
14 #include <linux/kernel.h>
15 #include <linux/clk.h>
16 #include <linux/clockchips.h>
17 #include <linux/of.h>
18 #include <linux/of_address.h>
19 #include <linux/of_irq.h>
20 
21 #include <asm/mach/time.h>
22 
23 #include <mach/at91_pit.h>
24 
25 
26 #define PIT_CPIV(x) ((x) & AT91_PIT_CPIV)
27 #define PIT_PICNT(x) (((x) & AT91_PIT_PICNT) >> 20)
28 
29 static u32 pit_cycle; /* write-once */
30 static u32 pit_cnt; /* access only w/system irq blocked */
31 static void __iomem *pit_base_addr __read_mostly;
32 
33 static inline unsigned int pit_read(unsigned int reg_offset)
34 {
35  return __raw_readl(pit_base_addr + reg_offset);
36 }
37 
38 static inline void pit_write(unsigned int reg_offset, unsigned long value)
39 {
40  __raw_writel(value, pit_base_addr + reg_offset);
41 }
42 
43 /*
44  * Clocksource: just a monotonic counter of MCK/16 cycles.
45  * We don't care whether or not PIT irqs are enabled.
46  */
47 static cycle_t read_pit_clk(struct clocksource *cs)
48 {
49  unsigned long flags;
50  u32 elapsed;
51  u32 t;
52 
53  raw_local_irq_save(flags);
54  elapsed = pit_cnt;
55  t = pit_read(AT91_PIT_PIIR);
56  raw_local_irq_restore(flags);
57 
58  elapsed += PIT_PICNT(t) * pit_cycle;
59  elapsed += PIT_CPIV(t);
60  return elapsed;
61 }
62 
63 static struct clocksource pit_clk = {
64  .name = "pit",
65  .rating = 175,
66  .read = read_pit_clk,
68 };
69 
70 
71 /*
72  * Clockevent device: interrupts every 1/HZ (== pit_cycles * MCK/16)
73  */
74 static void
75 pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
76 {
77  switch (mode) {
78  case CLOCK_EVT_MODE_PERIODIC:
79  /* update clocksource counter */
80  pit_cnt += pit_cycle * PIT_PICNT(pit_read(AT91_PIT_PIVR));
81  pit_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN
82  | AT91_PIT_PITIEN);
83  break;
84  case CLOCK_EVT_MODE_ONESHOT:
85  BUG();
86  /* FALLTHROUGH */
87  case CLOCK_EVT_MODE_SHUTDOWN:
88  case CLOCK_EVT_MODE_UNUSED:
89  /* disable irq, leaving the clocksource active */
90  pit_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN);
91  break;
92  case CLOCK_EVT_MODE_RESUME:
93  break;
94  }
95 }
96 
97 static struct clock_event_device pit_clkevt = {
98  .name = "pit",
99  .features = CLOCK_EVT_FEAT_PERIODIC,
100  .shift = 32,
101  .rating = 100,
102  .set_mode = pit_clkevt_mode,
103 };
104 
105 
106 /*
107  * IRQ handler for the timer.
108  */
109 static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id)
110 {
111  /*
112  * irqs should be disabled here, but as the irq is shared they are only
113  * guaranteed to be off if the timer irq is registered first.
114  */
116 
117  /* The PIT interrupt may be disabled, and is shared */
118  if ((pit_clkevt.mode == CLOCK_EVT_MODE_PERIODIC)
119  && (pit_read(AT91_PIT_SR) & AT91_PIT_PITS)) {
120  unsigned nr_ticks;
121 
122  /* Get number of ticks performed before irq, and ack it */
123  nr_ticks = PIT_PICNT(pit_read(AT91_PIT_PIVR));
124  do {
125  pit_cnt += pit_cycle;
126  pit_clkevt.event_handler(&pit_clkevt);
127  nr_ticks--;
128  } while (nr_ticks);
129 
130  return IRQ_HANDLED;
131  }
132 
133  return IRQ_NONE;
134 }
135 
136 static struct irqaction at91sam926x_pit_irq = {
137  .name = "at91_tick",
139  .handler = at91sam926x_pit_interrupt,
140  .irq = NR_IRQS_LEGACY + AT91_ID_SYS,
141 };
142 
143 static void at91sam926x_pit_reset(void)
144 {
145  /* Disable timer and irqs */
146  pit_write(AT91_PIT_MR, 0);
147 
148  /* Clear any pending interrupts, wait for PIT to stop counting */
149  while (PIT_CPIV(pit_read(AT91_PIT_PIVR)) != 0)
150  cpu_relax();
151 
152  /* Start PIT but don't enable IRQ */
153  pit_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN);
154 }
155 
156 #ifdef CONFIG_OF
157 static struct of_device_id pit_timer_ids[] = {
158  { .compatible = "atmel,at91sam9260-pit" },
159  { /* sentinel */ }
160 };
161 
162 static int __init of_at91sam926x_pit_init(void)
163 {
164  struct device_node *np;
165  int ret;
166 
167  np = of_find_matching_node(NULL, pit_timer_ids);
168  if (!np)
169  goto err;
170 
171  pit_base_addr = of_iomap(np, 0);
172  if (!pit_base_addr)
173  goto node_err;
174 
175  /* Get the interrupts property */
176  ret = irq_of_parse_and_map(np, 0);
177  if (!ret) {
178  pr_crit("AT91: PIT: Unable to get IRQ from DT\n");
179  goto ioremap_err;
180  }
181  at91sam926x_pit_irq.irq = ret;
182 
183  of_node_put(np);
184 
185  return 0;
186 
187 ioremap_err:
188  iounmap(pit_base_addr);
189 node_err:
190  of_node_put(np);
191 err:
192  return -EINVAL;
193 }
194 #else
195 static int __init of_at91sam926x_pit_init(void)
196 {
197  return -EINVAL;
198 }
199 #endif
200 
201 /*
202  * Set up both clocksource and clockevent support.
203  */
204 static void __init at91sam926x_pit_init(void)
205 {
206  unsigned long pit_rate;
207  unsigned bits;
208  int ret;
209 
210  /* For device tree enabled device: initialize here */
211  of_at91sam926x_pit_init();
212 
213  /*
214  * Use our actual MCK to figure out how many MCK/16 ticks per
215  * 1/HZ period (instead of a compile-time constant LATCH).
216  */
217  pit_rate = clk_get_rate(clk_get(NULL, "mck")) / 16;
218  pit_cycle = (pit_rate + HZ/2) / HZ;
219  WARN_ON(((pit_cycle - 1) & ~AT91_PIT_PIV) != 0);
220 
221  /* Initialize and enable the timer */
222  at91sam926x_pit_reset();
223 
224  /*
225  * Register clocksource. The high order bits of PIV are unused,
226  * so this isn't a 32-bit counter unless we get clockevent irqs.
227  */
228  bits = 12 /* PICNT */ + ilog2(pit_cycle) /* PIV */;
229  pit_clk.mask = CLOCKSOURCE_MASK(bits);
230  clocksource_register_hz(&pit_clk, pit_rate);
231 
232  /* Set up irq handler */
233  ret = setup_irq(at91sam926x_pit_irq.irq, &at91sam926x_pit_irq);
234  if (ret)
235  pr_crit("AT91: PIT: Unable to setup IRQ\n");
236 
237  /* Set up and register clockevents */
238  pit_clkevt.mult = div_sc(pit_rate, NSEC_PER_SEC, pit_clkevt.shift);
239  pit_clkevt.cpumask = cpumask_of(0);
240  clockevents_register_device(&pit_clkevt);
241 }
242 
243 static void at91sam926x_pit_suspend(void)
244 {
245  /* Disable timer */
246  pit_write(AT91_PIT_MR, 0);
247 }
248 
250 {
251 #if defined(CONFIG_OF)
252  struct device_node *np =
253  of_find_matching_node(NULL, pit_timer_ids);
254 
255  if (np) {
256  of_node_put(np);
257  return;
258  }
259 #endif
260  pit_base_addr = ioremap(addr, 16);
261 
262  if (!pit_base_addr)
263  panic("Impossible to ioremap PIT\n");
264 }
265 
267  .init = at91sam926x_pit_init,
268  .suspend = at91sam926x_pit_suspend,
269  .resume = at91sam926x_pit_reset,
270 };