]> Git Repo - qemu.git/blob - hw/timer/lm32_timer.c
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-4.2-20190821' into staging
[qemu.git] / hw / timer / lm32_timer.c
1 /*
2  *  QEMU model of the LatticeMico32 timer block.
3  *
4  *  Copyright (c) 2010 Michael Walle <[email protected]>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  *
19  *
20  * Specification available at:
21  *   http://www.latticesemi.com/documents/mico32timer.pdf
22  */
23
24 #include "qemu/osdep.h"
25 #include "hw/irq.h"
26 #include "hw/sysbus.h"
27 #include "migration/vmstate.h"
28 #include "trace.h"
29 #include "qemu/timer.h"
30 #include "hw/ptimer.h"
31 #include "hw/qdev-properties.h"
32 #include "qemu/error-report.h"
33 #include "qemu/main-loop.h"
34 #include "qemu/module.h"
35
36 #define DEFAULT_FREQUENCY (50*1000000)
37
38 enum {
39     R_SR = 0,
40     R_CR,
41     R_PERIOD,
42     R_SNAPSHOT,
43     R_MAX
44 };
45
46 enum {
47     SR_TO    = (1 << 0),
48     SR_RUN   = (1 << 1),
49 };
50
51 enum {
52     CR_ITO   = (1 << 0),
53     CR_CONT  = (1 << 1),
54     CR_START = (1 << 2),
55     CR_STOP  = (1 << 3),
56 };
57
58 #define TYPE_LM32_TIMER "lm32-timer"
59 #define LM32_TIMER(obj) OBJECT_CHECK(LM32TimerState, (obj), TYPE_LM32_TIMER)
60
61 struct LM32TimerState {
62     SysBusDevice parent_obj;
63
64     MemoryRegion iomem;
65
66     QEMUBH *bh;
67     ptimer_state *ptimer;
68
69     qemu_irq irq;
70     uint32_t freq_hz;
71
72     uint32_t regs[R_MAX];
73 };
74 typedef struct LM32TimerState LM32TimerState;
75
76 static void timer_update_irq(LM32TimerState *s)
77 {
78     int state = (s->regs[R_SR] & SR_TO) && (s->regs[R_CR] & CR_ITO);
79
80     trace_lm32_timer_irq_state(state);
81     qemu_set_irq(s->irq, state);
82 }
83
84 static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size)
85 {
86     LM32TimerState *s = opaque;
87     uint32_t r = 0;
88
89     addr >>= 2;
90     switch (addr) {
91     case R_SR:
92     case R_CR:
93     case R_PERIOD:
94         r = s->regs[addr];
95         break;
96     case R_SNAPSHOT:
97         r = (uint32_t)ptimer_get_count(s->ptimer);
98         break;
99     default:
100         error_report("lm32_timer: read access to unknown register 0x"
101                 TARGET_FMT_plx, addr << 2);
102         break;
103     }
104
105     trace_lm32_timer_memory_read(addr << 2, r);
106     return r;
107 }
108
109 static void timer_write(void *opaque, hwaddr addr,
110                         uint64_t value, unsigned size)
111 {
112     LM32TimerState *s = opaque;
113
114     trace_lm32_timer_memory_write(addr, value);
115
116     addr >>= 2;
117     switch (addr) {
118     case R_SR:
119         s->regs[R_SR] &= ~SR_TO;
120         break;
121     case R_CR:
122         s->regs[R_CR] = value;
123         if (s->regs[R_CR] & CR_START) {
124             ptimer_run(s->ptimer, 1);
125         }
126         if (s->regs[R_CR] & CR_STOP) {
127             ptimer_stop(s->ptimer);
128         }
129         break;
130     case R_PERIOD:
131         s->regs[R_PERIOD] = value;
132         ptimer_set_count(s->ptimer, value);
133         break;
134     case R_SNAPSHOT:
135         error_report("lm32_timer: write access to read only register 0x"
136                 TARGET_FMT_plx, addr << 2);
137         break;
138     default:
139         error_report("lm32_timer: write access to unknown register 0x"
140                 TARGET_FMT_plx, addr << 2);
141         break;
142     }
143     timer_update_irq(s);
144 }
145
146 static const MemoryRegionOps timer_ops = {
147     .read = timer_read,
148     .write = timer_write,
149     .endianness = DEVICE_NATIVE_ENDIAN,
150     .valid = {
151         .min_access_size = 4,
152         .max_access_size = 4,
153     },
154 };
155
156 static void timer_hit(void *opaque)
157 {
158     LM32TimerState *s = opaque;
159
160     trace_lm32_timer_hit();
161
162     s->regs[R_SR] |= SR_TO;
163
164     if (s->regs[R_CR] & CR_CONT) {
165         ptimer_set_count(s->ptimer, s->regs[R_PERIOD]);
166         ptimer_run(s->ptimer, 1);
167     }
168     timer_update_irq(s);
169 }
170
171 static void timer_reset(DeviceState *d)
172 {
173     LM32TimerState *s = LM32_TIMER(d);
174     int i;
175
176     for (i = 0; i < R_MAX; i++) {
177         s->regs[i] = 0;
178     }
179     ptimer_stop(s->ptimer);
180 }
181
182 static void lm32_timer_init(Object *obj)
183 {
184     LM32TimerState *s = LM32_TIMER(obj);
185     SysBusDevice *dev = SYS_BUS_DEVICE(obj);
186
187     sysbus_init_irq(dev, &s->irq);
188
189     s->bh = qemu_bh_new(timer_hit, s);
190     s->ptimer = ptimer_init(s->bh, PTIMER_POLICY_DEFAULT);
191
192     memory_region_init_io(&s->iomem, obj, &timer_ops, s,
193                           "timer", R_MAX * 4);
194     sysbus_init_mmio(dev, &s->iomem);
195 }
196
197 static void lm32_timer_realize(DeviceState *dev, Error **errp)
198 {
199     LM32TimerState *s = LM32_TIMER(dev);
200
201     ptimer_set_freq(s->ptimer, s->freq_hz);
202 }
203
204 static const VMStateDescription vmstate_lm32_timer = {
205     .name = "lm32-timer",
206     .version_id = 1,
207     .minimum_version_id = 1,
208     .fields = (VMStateField[]) {
209         VMSTATE_PTIMER(ptimer, LM32TimerState),
210         VMSTATE_UINT32(freq_hz, LM32TimerState),
211         VMSTATE_UINT32_ARRAY(regs, LM32TimerState, R_MAX),
212         VMSTATE_END_OF_LIST()
213     }
214 };
215
216 static Property lm32_timer_properties[] = {
217     DEFINE_PROP_UINT32("frequency", LM32TimerState, freq_hz, DEFAULT_FREQUENCY),
218     DEFINE_PROP_END_OF_LIST(),
219 };
220
221 static void lm32_timer_class_init(ObjectClass *klass, void *data)
222 {
223     DeviceClass *dc = DEVICE_CLASS(klass);
224
225     dc->realize = lm32_timer_realize;
226     dc->reset = timer_reset;
227     dc->vmsd = &vmstate_lm32_timer;
228     dc->props = lm32_timer_properties;
229 }
230
231 static const TypeInfo lm32_timer_info = {
232     .name          = TYPE_LM32_TIMER,
233     .parent        = TYPE_SYS_BUS_DEVICE,
234     .instance_size = sizeof(LM32TimerState),
235     .instance_init = lm32_timer_init,
236     .class_init    = lm32_timer_class_init,
237 };
238
239 static void lm32_timer_register_types(void)
240 {
241     type_register_static(&lm32_timer_info);
242 }
243
244 type_init(lm32_timer_register_types)
This page took 0.042106 seconds and 4 git commands to generate.