xref: /openbmc/qemu/hw/timer/grlib_gptimer.c (revision 0fd61a2d)
1 /*
2  * QEMU GRLIB GPTimer Emulator
3  *
4  * Copyright (c) 2010-2019 AdaCore
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 
25 #include "qemu/osdep.h"
26 #include "hw/sparc/grlib.h"
27 #include "hw/sysbus.h"
28 #include "qemu/timer.h"
29 #include "hw/irq.h"
30 #include "hw/ptimer.h"
31 #include "hw/qdev-properties.h"
32 #include "qemu/module.h"
33 
34 #include "trace.h"
35 
36 #define UNIT_REG_SIZE    16     /* Size of memory mapped regs for the unit */
37 #define GPTIMER_REG_SIZE 16     /* Size of memory mapped regs for a GPTimer */
38 
39 #define GPTIMER_MAX_TIMERS 8
40 
41 /* GPTimer Config register fields */
42 #define GPTIMER_ENABLE      (1 << 0)
43 #define GPTIMER_RESTART     (1 << 1)
44 #define GPTIMER_LOAD        (1 << 2)
45 #define GPTIMER_INT_ENABLE  (1 << 3)
46 #define GPTIMER_INT_PENDING (1 << 4)
47 #define GPTIMER_CHAIN       (1 << 5) /* Not supported */
48 #define GPTIMER_DEBUG_HALT  (1 << 6) /* Not supported */
49 
50 /* Memory mapped register offsets */
51 #define SCALER_OFFSET         0x00
52 #define SCALER_RELOAD_OFFSET  0x04
53 #define CONFIG_OFFSET         0x08
54 #define COUNTER_OFFSET        0x00
55 #define COUNTER_RELOAD_OFFSET 0x04
56 #define TIMER_BASE            0x10
57 
58 #define GRLIB_GPTIMER(obj) \
59     OBJECT_CHECK(GPTimerUnit, (obj), TYPE_GRLIB_GPTIMER)
60 
61 typedef struct GPTimer     GPTimer;
62 typedef struct GPTimerUnit GPTimerUnit;
63 
64 struct GPTimer {
65     struct ptimer_state *ptimer;
66 
67     qemu_irq     irq;
68     int          id;
69     GPTimerUnit *unit;
70 
71     /* registers */
72     uint32_t counter;
73     uint32_t reload;
74     uint32_t config;
75 };
76 
77 struct GPTimerUnit {
78     SysBusDevice  parent_obj;
79 
80     MemoryRegion iomem;
81 
82     uint32_t nr_timers;         /* Number of timers available */
83     uint32_t freq_hz;           /* System frequency */
84     uint32_t irq_line;          /* Base irq line */
85 
86     GPTimer *timers;
87 
88     /* registers */
89     uint32_t scaler;
90     uint32_t reload;
91     uint32_t config;
92 };
93 
94 static void grlib_gptimer_tx_begin(GPTimer *timer)
95 {
96     ptimer_transaction_begin(timer->ptimer);
97 }
98 
99 static void grlib_gptimer_tx_commit(GPTimer *timer)
100 {
101     ptimer_transaction_commit(timer->ptimer);
102 }
103 
104 /* Must be called within grlib_gptimer_tx_begin/commit block */
105 static void grlib_gptimer_enable(GPTimer *timer)
106 {
107     assert(timer != NULL);
108 
109 
110     ptimer_stop(timer->ptimer);
111 
112     if (!(timer->config & GPTIMER_ENABLE)) {
113         /* Timer disabled */
114         trace_grlib_gptimer_disabled(timer->id, timer->config);
115         return;
116     }
117 
118     /* ptimer is triggered when the counter reach 0 but GPTimer is triggered at
119        underflow. Set count + 1 to simulate the GPTimer behavior. */
120 
121     trace_grlib_gptimer_enable(timer->id, timer->counter);
122 
123     ptimer_set_count(timer->ptimer, (uint64_t)timer->counter + 1);
124     ptimer_run(timer->ptimer, 1);
125 }
126 
127 /* Must be called within grlib_gptimer_tx_begin/commit block */
128 static void grlib_gptimer_restart(GPTimer *timer)
129 {
130     assert(timer != NULL);
131 
132     trace_grlib_gptimer_restart(timer->id, timer->reload);
133 
134     timer->counter = timer->reload;
135     grlib_gptimer_enable(timer);
136 }
137 
138 static void grlib_gptimer_set_scaler(GPTimerUnit *unit, uint32_t scaler)
139 {
140     int i = 0;
141     uint32_t value = 0;
142 
143     assert(unit != NULL);
144 
145     if (scaler > 0) {
146         value = unit->freq_hz / (scaler + 1);
147     } else {
148         value = unit->freq_hz;
149     }
150 
151     trace_grlib_gptimer_set_scaler(scaler, value);
152 
153     for (i = 0; i < unit->nr_timers; i++) {
154         ptimer_transaction_begin(unit->timers[i].ptimer);
155         ptimer_set_freq(unit->timers[i].ptimer, value);
156         ptimer_transaction_commit(unit->timers[i].ptimer);
157     }
158 }
159 
160 static void grlib_gptimer_hit(void *opaque)
161 {
162     GPTimer *timer = opaque;
163     assert(timer != NULL);
164 
165     trace_grlib_gptimer_hit(timer->id);
166 
167     /* Timer expired */
168 
169     if (timer->config & GPTIMER_INT_ENABLE) {
170         /* Set the pending bit (only unset by write in the config register) */
171         timer->config |= GPTIMER_INT_PENDING;
172         qemu_irq_pulse(timer->irq);
173     }
174 
175     if (timer->config & GPTIMER_RESTART) {
176         grlib_gptimer_restart(timer);
177     }
178 }
179 
180 static uint64_t grlib_gptimer_read(void *opaque, hwaddr addr,
181                                    unsigned size)
182 {
183     GPTimerUnit        *unit  = opaque;
184     hwaddr  timer_addr;
185     int                 id;
186     uint32_t            value = 0;
187 
188     addr &= 0xff;
189 
190     /* Unit registers */
191     switch (addr) {
192     case SCALER_OFFSET:
193         trace_grlib_gptimer_readl(-1, addr, unit->scaler);
194         return unit->scaler;
195 
196     case SCALER_RELOAD_OFFSET:
197         trace_grlib_gptimer_readl(-1, addr, unit->reload);
198         return unit->reload;
199 
200     case CONFIG_OFFSET:
201         trace_grlib_gptimer_readl(-1, addr, unit->config);
202         return unit->config;
203 
204     default:
205         break;
206     }
207 
208     timer_addr = (addr % TIMER_BASE);
209     id         = (addr - TIMER_BASE) / TIMER_BASE;
210 
211     if (id >= 0 && id < unit->nr_timers) {
212 
213         /* GPTimer registers */
214         switch (timer_addr) {
215         case COUNTER_OFFSET:
216             value = ptimer_get_count(unit->timers[id].ptimer);
217             trace_grlib_gptimer_readl(id, addr, value);
218             return value;
219 
220         case COUNTER_RELOAD_OFFSET:
221             value = unit->timers[id].reload;
222             trace_grlib_gptimer_readl(id, addr, value);
223             return value;
224 
225         case CONFIG_OFFSET:
226             trace_grlib_gptimer_readl(id, addr, unit->timers[id].config);
227             return unit->timers[id].config;
228 
229         default:
230             break;
231         }
232 
233     }
234 
235     trace_grlib_gptimer_readl(-1, addr, 0);
236     return 0;
237 }
238 
239 static void grlib_gptimer_write(void *opaque, hwaddr addr,
240                                 uint64_t value, unsigned size)
241 {
242     GPTimerUnit        *unit = opaque;
243     hwaddr  timer_addr;
244     int                 id;
245 
246     addr &= 0xff;
247 
248     /* Unit registers */
249     switch (addr) {
250     case SCALER_OFFSET:
251         value &= 0xFFFF; /* clean up the value */
252         unit->scaler = value;
253         trace_grlib_gptimer_writel(-1, addr, unit->scaler);
254         return;
255 
256     case SCALER_RELOAD_OFFSET:
257         value &= 0xFFFF; /* clean up the value */
258         unit->reload = value;
259         trace_grlib_gptimer_writel(-1, addr, unit->reload);
260         grlib_gptimer_set_scaler(unit, value);
261         return;
262 
263     case CONFIG_OFFSET:
264         /* Read Only (disable timer freeze not supported) */
265         trace_grlib_gptimer_writel(-1, addr, 0);
266         return;
267 
268     default:
269         break;
270     }
271 
272     timer_addr = (addr % TIMER_BASE);
273     id         = (addr - TIMER_BASE) / TIMER_BASE;
274 
275     if (id >= 0 && id < unit->nr_timers) {
276 
277         /* GPTimer registers */
278         switch (timer_addr) {
279         case COUNTER_OFFSET:
280             trace_grlib_gptimer_writel(id, addr, value);
281             grlib_gptimer_tx_begin(&unit->timers[id]);
282             unit->timers[id].counter = value;
283             grlib_gptimer_enable(&unit->timers[id]);
284             grlib_gptimer_tx_commit(&unit->timers[id]);
285             return;
286 
287         case COUNTER_RELOAD_OFFSET:
288             trace_grlib_gptimer_writel(id, addr, value);
289             unit->timers[id].reload = value;
290             return;
291 
292         case CONFIG_OFFSET:
293             trace_grlib_gptimer_writel(id, addr, value);
294 
295             if (value & GPTIMER_INT_PENDING) {
296                 /* clear pending bit */
297                 value &= ~GPTIMER_INT_PENDING;
298             } else {
299                 /* keep pending bit */
300                 value |= unit->timers[id].config & GPTIMER_INT_PENDING;
301             }
302 
303             unit->timers[id].config = value;
304 
305             /* gptimer_restart calls gptimer_enable, so if "enable" and "load"
306                bits are present, we just have to call restart. */
307 
308             grlib_gptimer_tx_begin(&unit->timers[id]);
309             if (value & GPTIMER_LOAD) {
310                 grlib_gptimer_restart(&unit->timers[id]);
311             } else if (value & GPTIMER_ENABLE) {
312                 grlib_gptimer_enable(&unit->timers[id]);
313             }
314 
315             /* These fields must always be read as 0 */
316             value &= ~(GPTIMER_LOAD & GPTIMER_DEBUG_HALT);
317 
318             unit->timers[id].config = value;
319             grlib_gptimer_tx_commit(&unit->timers[id]);
320             return;
321 
322         default:
323             break;
324         }
325 
326     }
327 
328     trace_grlib_gptimer_writel(-1, addr, value);
329 }
330 
331 static const MemoryRegionOps grlib_gptimer_ops = {
332     .read = grlib_gptimer_read,
333     .write = grlib_gptimer_write,
334     .endianness = DEVICE_NATIVE_ENDIAN,
335     .valid = {
336         .min_access_size = 4,
337         .max_access_size = 4,
338     },
339 };
340 
341 static void grlib_gptimer_reset(DeviceState *d)
342 {
343     GPTimerUnit *unit = GRLIB_GPTIMER(d);
344     int          i    = 0;
345 
346     assert(unit != NULL);
347 
348     unit->scaler = 0;
349     unit->reload = 0;
350 
351     unit->config  = unit->nr_timers;
352     unit->config |= unit->irq_line << 3;
353     unit->config |= 1 << 8;     /* separate interrupt */
354     unit->config |= 1 << 9;     /* Disable timer freeze */
355 
356 
357     for (i = 0; i < unit->nr_timers; i++) {
358         GPTimer *timer = &unit->timers[i];
359 
360         timer->counter = 0;
361         timer->reload = 0;
362         timer->config = 0;
363         ptimer_transaction_begin(timer->ptimer);
364         ptimer_stop(timer->ptimer);
365         ptimer_set_count(timer->ptimer, 0);
366         ptimer_set_freq(timer->ptimer, unit->freq_hz);
367         ptimer_transaction_commit(timer->ptimer);
368     }
369 }
370 
371 static void grlib_gptimer_realize(DeviceState *dev, Error **errp)
372 {
373     GPTimerUnit  *unit = GRLIB_GPTIMER(dev);
374     unsigned int  i;
375     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
376 
377     assert(unit->nr_timers > 0);
378     assert(unit->nr_timers <= GPTIMER_MAX_TIMERS);
379 
380     unit->timers = g_malloc0(sizeof unit->timers[0] * unit->nr_timers);
381 
382     for (i = 0; i < unit->nr_timers; i++) {
383         GPTimer *timer = &unit->timers[i];
384 
385         timer->unit   = unit;
386         timer->ptimer = ptimer_init(grlib_gptimer_hit, timer,
387                                     PTIMER_POLICY_DEFAULT);
388         timer->id     = i;
389 
390         /* One IRQ line for each timer */
391         sysbus_init_irq(sbd, &timer->irq);
392 
393         ptimer_transaction_begin(timer->ptimer);
394         ptimer_set_freq(timer->ptimer, unit->freq_hz);
395         ptimer_transaction_commit(timer->ptimer);
396     }
397 
398     memory_region_init_io(&unit->iomem, OBJECT(unit), &grlib_gptimer_ops,
399                           unit, "gptimer",
400                           UNIT_REG_SIZE + GPTIMER_REG_SIZE * unit->nr_timers);
401 
402     sysbus_init_mmio(sbd, &unit->iomem);
403 }
404 
405 static Property grlib_gptimer_properties[] = {
406     DEFINE_PROP_UINT32("frequency", GPTimerUnit, freq_hz,   40000000),
407     DEFINE_PROP_UINT32("irq-line",  GPTimerUnit, irq_line,  8),
408     DEFINE_PROP_UINT32("nr-timers", GPTimerUnit, nr_timers, 2),
409     DEFINE_PROP_END_OF_LIST(),
410 };
411 
412 static void grlib_gptimer_class_init(ObjectClass *klass, void *data)
413 {
414     DeviceClass *dc = DEVICE_CLASS(klass);
415 
416     dc->realize = grlib_gptimer_realize;
417     dc->reset = grlib_gptimer_reset;
418     dc->props = grlib_gptimer_properties;
419 }
420 
421 static const TypeInfo grlib_gptimer_info = {
422     .name          = TYPE_GRLIB_GPTIMER,
423     .parent        = TYPE_SYS_BUS_DEVICE,
424     .instance_size = sizeof(GPTimerUnit),
425     .class_init    = grlib_gptimer_class_init,
426 };
427 
428 static void grlib_gptimer_register_types(void)
429 {
430     type_register_static(&grlib_gptimer_info);
431 }
432 
433 type_init(grlib_gptimer_register_types)
434