06251356d2a7429852594289c7e2ca3a929f09a5
[openwrt.git] / target / linux / gemini / patches-3.18 / 160-gemini-timers.patch
1 --- a/arch/arm/mach-gemini/time.c       2015-03-25 23:06:03.188317455 +0200
2 +++ b/arch/arm/mach-gemini/time.c       2015-03-25 23:06:24.417315486 +0200
3 @@ -15,15 +15,18 @@
4  #include <asm/mach/time.h>
5  #include <linux/clockchips.h>
6  #include <linux/clocksource.h>
7 +#include <linux/sched_clock.h>
8  
9  /*
10   * Register definitions for the timers
11   */
12 -#define TIMER_COUNT(BASE_ADDR)         (BASE_ADDR  + 0x00)
13 -#define TIMER_LOAD(BASE_ADDR)          (BASE_ADDR  + 0x04)
14 -#define TIMER_MATCH1(BASE_ADDR)                (BASE_ADDR  + 0x08)
15 -#define TIMER_MATCH2(BASE_ADDR)                (BASE_ADDR  + 0x0C)
16 -#define TIMER_CR(BASE_ADDR)            (BASE_ADDR  + 0x30)
17 +#define TIMER_COUNT(BASE_ADDR)         (IO_ADDRESS(BASE_ADDR) + 0x00)
18 +#define TIMER_LOAD(BASE_ADDR)          (IO_ADDRESS(BASE_ADDR) + 0x04)
19 +#define TIMER_MATCH1(BASE_ADDR)                (IO_ADDRESS(BASE_ADDR) + 0x08)
20 +#define TIMER_MATCH2(BASE_ADDR)                (IO_ADDRESS(BASE_ADDR) + 0x0C)
21 +#define TIMER_CR(BASE_ADDR)            (IO_ADDRESS(BASE_ADDR) + 0x30)
22 +#define TIMER_INTR_STATE(BASE_ADDR)    (IO_ADDRESS(BASE_ADDR) + 0x34)
23 +#define TIMER_INTR_MASK(BASE_ADDR)     (IO_ADDRESS(BASE_ADDR) + 0x38)
24  
25  #define TIMER_1_CR_ENABLE              (1 << 0)
26  #define TIMER_1_CR_CLOCK               (1 << 1)
27 @@ -34,27 +37,38 @@
28  #define TIMER_3_CR_ENABLE              (1 << 6)
29  #define TIMER_3_CR_CLOCK               (1 << 7)
30  #define TIMER_3_CR_INT                 (1 << 8)
31 +#define TIMER_1_CR_UPDOWN              (1 << 9)
32 +#define TIMER_2_CR_UPDOWN              (1 << 10)
33 +#define TIMER_3_CR_UPDOWN              (1 << 11)
34 +
35 +#define TIMER_1_INT_MATCH1             (1 << 0)
36 +#define TIMER_1_INT_MATCH2             (1 << 1)
37 +#define TIMER_1_INT_OVERFLOW           (1 << 2)
38 +#define TIMER_2_INT_MATCH1             (1 << 3)
39 +#define TIMER_2_INT_MATCH2             (1 << 4)
40 +#define TIMER_2_INT_OVERFLOW           (1 << 5)
41 +#define TIMER_3_INT_MATCH1             (1 << 6)
42 +#define TIMER_3_INT_MATCH2             (1 << 7)
43 +#define TIMER_3_INT_OVERFLOW           (1 << 8)
44 +#define TIMER_INT_ALL_MASK             0x1ff
45  
46  static unsigned int tick_rate;
47  
48 +static u64 notrace gemini_read_sched_clock(void)
49 +{
50 +       return readl(TIMER_COUNT(GEMINI_TIMER3_BASE));
51 +}
52 +
53  static int gemini_timer_set_next_event(unsigned long cycles,
54                                        struct clock_event_device *evt)
55  {
56         u32 cr;
57  
58 -       cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
59 -
60 -       /* This may be overdoing it, feel free to test without this */
61 -       cr &= ~TIMER_2_CR_ENABLE;
62 -       cr &= ~TIMER_2_CR_INT;
63 -       writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
64 -
65 -       /* Set next event */
66 -       writel(cycles, TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE)));
67 -       writel(cycles, TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE)));
68 -       cr |= TIMER_2_CR_ENABLE;
69 -       cr |= TIMER_2_CR_INT;
70 -       writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
71 +       /* Setup the match register */
72 +       cr = readl(TIMER_COUNT(GEMINI_TIMER1_BASE));
73 +       writel(cr + cycles, TIMER_MATCH1(GEMINI_TIMER1_BASE));
74 +       if (readl(TIMER_COUNT(GEMINI_TIMER1_BASE)) - cr > cycles)
75 +               return -ETIME;
76  
77         return 0;
78  }
79 @@ -66,48 +80,68 @@
80         u32 cr;
81  
82         switch (mode) {
83 -        case CLOCK_EVT_MODE_PERIODIC:
84 -               /* Start the timer */
85 -               writel(period,
86 -                      TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE)));
87 -               writel(period,
88 -                      TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE)));
89 -               cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
90 -               cr |= TIMER_2_CR_ENABLE;
91 -               cr |= TIMER_2_CR_INT;
92 -               writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
93 +       case CLOCK_EVT_MODE_PERIODIC:
94 +               /* Stop timer and interrupt. */
95 +               cr = readl(TIMER_CR(GEMINI_TIMER_BASE));
96 +               cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT);
97 +               writel(cr, TIMER_CR(GEMINI_TIMER_BASE));
98 +
99 +               /* Setup timer to fire at 1/HZ intervals. */
100 +               cr = 0xffffffff - (period - 1);
101 +               writel(cr, TIMER_COUNT(GEMINI_TIMER1_BASE));
102 +               writel(cr, TIMER_LOAD(GEMINI_TIMER1_BASE));
103 +
104 +               /* enable interrupt on overflaw */
105 +               cr = readl(TIMER_INTR_MASK(GEMINI_TIMER_BASE));
106 +               cr &= ~(TIMER_1_INT_MATCH1 | TIMER_1_INT_MATCH2);
107 +               cr |= TIMER_1_INT_OVERFLOW;
108 +               writel(cr, TIMER_INTR_MASK(GEMINI_TIMER_BASE));
109 +
110 +               /* start the timer */
111 +               cr = readl(TIMER_CR(GEMINI_TIMER_BASE));
112 +               cr |= TIMER_1_CR_ENABLE | TIMER_1_CR_INT;
113 +               writel(cr, TIMER_CR(GEMINI_TIMER_BASE));
114                 break;
115 +
116         case CLOCK_EVT_MODE_ONESHOT:
117         case CLOCK_EVT_MODE_UNUSED:
118 -        case CLOCK_EVT_MODE_SHUTDOWN:
119 +       case CLOCK_EVT_MODE_SHUTDOWN:
120 +               /* Stop timer and interrupt. */
121 +               cr = readl(TIMER_CR(GEMINI_TIMER_BASE));
122 +               cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT);
123 +               writel(cr, TIMER_CR(GEMINI_TIMER_BASE));
124 +
125 +               /* Setup counter start from 0 */
126 +               writel(0, TIMER_COUNT(GEMINI_TIMER1_BASE));
127 +               writel(0, TIMER_LOAD(GEMINI_TIMER1_BASE));
128 +
129 +               /* enable interrupt */
130 +               cr = readl(TIMER_INTR_MASK(GEMINI_TIMER_BASE));
131 +               cr &= ~(TIMER_1_INT_OVERFLOW | TIMER_1_INT_MATCH2);
132 +               cr |= TIMER_1_INT_MATCH1;
133 +               writel(cr, TIMER_INTR_MASK(GEMINI_TIMER_BASE));
134 +
135 +               /* start the timer */
136 +               cr = readl(TIMER_CR(GEMINI_TIMER_BASE));
137 +               cr |= TIMER_1_CR_ENABLE;
138 +               writel(cr, TIMER_CR(GEMINI_TIMER_BASE));
139 +               break;
140 +
141         case CLOCK_EVT_MODE_RESUME:
142 -               /*
143 -                * Disable also for oneshot: the set_next() call will
144 -                * arm the timer instead.
145 -                */
146 -               cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
147 -               cr &= ~TIMER_2_CR_ENABLE;
148 -               cr &= ~TIMER_2_CR_INT;
149 -               writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
150                 break;
151 -       default:
152 -                break;
153         }
154  }
155  
156 -/* Use TIMER2 as clock event */
157  static struct clock_event_device gemini_clockevent = {
158 -       .name           = "TIMER2",
159 -       .rating         = 300, /* Reasonably fast and accurate clock event */
160 -       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
161 -       .set_next_event = gemini_timer_set_next_event,
162 -       .set_mode       = gemini_timer_set_mode,
163 +       .name           = "gemini_timer_1",
164 +       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
165 +       .shift          = 32,
166 +       .rating         = 300,
167 +       .set_next_event = gemini_timer_set_next_event,
168 +       .set_mode       = gemini_timer_set_mode,
169  };
170  
171 -/*
172 - * IRQ handler for the timer
173 - */
174 -static irqreturn_t gemini_timer_interrupt(int irq, void *dev_id)
175 +static irqreturn_t gemini_timer_intr(int irq, void *dev_id)
176  {
177         struct clock_event_device *evt = &gemini_clockevent;
178  
179 @@ -116,14 +150,11 @@
180  }
181  
182  static struct irqaction gemini_timer_irq = {
183 -       .name           = "Gemini Timer Tick",
184 -       .flags          = IRQF_TIMER,
185 -       .handler        = gemini_timer_interrupt,
186 +       .name           = "gemini timer 1",
187 +       .flags          = IRQF_DISABLED | IRQF_TIMER,
188 +       .handler        = gemini_timer_intr,
189  };
190  
191 -/*
192 - * Set up timer interrupt, and return the current time in seconds.
193 - */
194  void __init gemini_timer_init(void)
195  {
196         u32 reg_v;
197 @@ -151,20 +182,35 @@
198         }
199  
200         /*
201 -        * Make irqs happen for the system timer
202 +        * Reset the interrupt mask and status
203          */
204 -       setup_irq(IRQ_TIMER2, &gemini_timer_irq);
205 +       writel(TIMER_INT_ALL_MASK, TIMER_INTR_MASK(GEMINI_TIMER_BASE));
206 +       writel(0, TIMER_INTR_STATE(GEMINI_TIMER_BASE));
207 +       writel(TIMER_1_CR_UPDOWN | TIMER_3_CR_ENABLE | TIMER_3_CR_UPDOWN,
208 +               TIMER_CR(GEMINI_TIMER_BASE));
209  
210 -       /* Enable and use TIMER1 as clock source */
211 -       writel(0xffffffff, TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER1_BASE)));
212 -       writel(0xffffffff, TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER1_BASE)));
213 -       writel(TIMER_1_CR_ENABLE, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
214 -       if (clocksource_mmio_init(TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER1_BASE)),
215 -                                 "TIMER1", tick_rate, 300, 32,
216 -                                 clocksource_mmio_readl_up))
217 -               pr_err("timer: failed to initialize gemini clock source\n");
218 +       /*
219 +        * Setup free-running clocksource timer (interrupts
220 +        * disabled.)
221 +        */
222 +       writel(0, TIMER_COUNT(GEMINI_TIMER3_BASE));
223 +       writel(0, TIMER_LOAD(GEMINI_TIMER3_BASE));
224 +       writel(0, TIMER_MATCH1(GEMINI_TIMER3_BASE));
225 +       writel(0, TIMER_MATCH2(GEMINI_TIMER3_BASE));
226 +       clocksource_mmio_init(TIMER_COUNT(GEMINI_TIMER3_BASE),
227 +                       "gemini_clocksource", tick_rate,
228 +                       300, 32, clocksource_mmio_readl_up);
229 +       sched_clock_register(gemini_read_sched_clock, 32, tick_rate);
230  
231 -       /* Configure and register the clockevent */
232 +       /*
233 +        * Setup clockevent timer (interrupt-driven.)
234 +        */
235 +       writel(0, TIMER_COUNT(GEMINI_TIMER1_BASE));
236 +       writel(0, TIMER_LOAD(GEMINI_TIMER1_BASE));
237 +       writel(0, TIMER_MATCH1(GEMINI_TIMER1_BASE));
238 +       writel(0, TIMER_MATCH2(GEMINI_TIMER1_BASE));
239 +       setup_irq(IRQ_TIMER1, &gemini_timer_irq);
240 +       gemini_clockevent.cpumask = cpumask_of(0);
241         clockevents_config_and_register(&gemini_clockevent, tick_rate,
242                                         1, 0xffffffff);
243  }