xref: /qemu/hw/misc/lasi.c (revision 440b2174)
1 /*
2  * HP-PARISC Lasi chipset emulation.
3  *
4  * (C) 2019 by Helge Deller <deller@gmx.de>
5  *
6  * This work is licensed under the GNU GPL license version 2 or later.
7  *
8  * Documentation available at:
9  * https://parisc.wiki.kernel.org/images-parisc/7/79/Lasi_ers.pdf
10  */
11 
12 #include "qemu/osdep.h"
13 #include "qemu/units.h"
14 #include "qemu/log.h"
15 #include "qapi/error.h"
16 #include "trace.h"
17 #include "hw/irq.h"
18 #include "sysemu/sysemu.h"
19 #include "sysemu/runstate.h"
20 #include "migration/vmstate.h"
21 #include "qom/object.h"
22 #include "hw/misc/lasi.h"
23 
24 
25 static bool lasi_chip_mem_valid(void *opaque, hwaddr addr,
26                                 unsigned size, bool is_write,
27                                 MemTxAttrs attrs)
28 {
29     bool ret = false;
30 
31     switch (addr) {
32     case LASI_IRR:
33     case LASI_IMR:
34     case LASI_IPR:
35     case LASI_ICR:
36     case LASI_IAR:
37 
38     case LASI_LPT:
39     case LASI_UART:
40     case LASI_LAN:
41     case LASI_RTC:
42 
43     case LASI_PCR ... LASI_AMR:
44         ret = true;
45     }
46 
47     trace_lasi_chip_mem_valid(addr, ret);
48     return ret;
49 }
50 
51 static MemTxResult lasi_chip_read_with_attrs(void *opaque, hwaddr addr,
52                                              uint64_t *data, unsigned size,
53                                              MemTxAttrs attrs)
54 {
55     LasiState *s = opaque;
56     MemTxResult ret = MEMTX_OK;
57     uint32_t val;
58 
59     switch (addr) {
60     case LASI_IRR:
61         val = s->irr;
62         break;
63     case LASI_IMR:
64         val = s->imr;
65         break;
66     case LASI_IPR:
67         val = s->ipr;
68         /* Any read to IPR clears the register.  */
69         s->ipr = 0;
70         break;
71     case LASI_ICR:
72         val = s->icr & ICR_BUS_ERROR_BIT; /* bus_error */
73         break;
74     case LASI_IAR:
75         val = s->iar;
76         break;
77 
78     case LASI_LPT:
79     case LASI_UART:
80     case LASI_LAN:
81         val = 0;
82         break;
83     case LASI_RTC:
84         val = time(NULL);
85         val += s->rtc_ref;
86         break;
87 
88     case LASI_PCR:
89     case LASI_VER:      /* only version 0 existed. */
90     case LASI_IORESET:
91         val = 0;
92         break;
93     case LASI_ERRLOG:
94         val = s->errlog;
95         break;
96     case LASI_AMR:
97         val = s->amr;
98         break;
99 
100     default:
101         /* Controlled by lasi_chip_mem_valid above. */
102         g_assert_not_reached();
103     }
104 
105     trace_lasi_chip_read(addr, val);
106 
107     *data = val;
108     return ret;
109 }
110 
111 static MemTxResult lasi_chip_write_with_attrs(void *opaque, hwaddr addr,
112                                               uint64_t val, unsigned size,
113                                               MemTxAttrs attrs)
114 {
115     LasiState *s = opaque;
116 
117     trace_lasi_chip_write(addr, val);
118 
119     switch (addr) {
120     case LASI_IRR:
121         /* read-only.  */
122         break;
123     case LASI_IMR:
124         s->imr = val;
125         if (((val & LASI_IRQ_BITS) != val) && (val != 0xffffffff)) {
126             qemu_log_mask(LOG_GUEST_ERROR,
127                 "LASI: tried to set invalid %lx IMR value.\n",
128                 (unsigned long) val);
129         }
130         break;
131     case LASI_IPR:
132         /* Any write to IPR clears the register. */
133         s->ipr = 0;
134         break;
135     case LASI_ICR:
136         s->icr = val;
137         /* if (val & ICR_TOC_BIT) issue_toc(); */
138         break;
139     case LASI_IAR:
140         s->iar = val;
141         break;
142 
143     case LASI_LPT:
144         /* XXX: reset parallel port */
145         break;
146     case LASI_UART:
147         /* XXX: reset serial port */
148         break;
149     case LASI_LAN:
150         /* XXX: reset LAN card */
151         break;
152     case LASI_RTC:
153         s->rtc_ref = val - time(NULL);
154         break;
155 
156     case LASI_PCR:
157         if (val == 0x02) { /* immediately power off */
158             qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
159         }
160         break;
161     case LASI_ERRLOG:
162         s->errlog = val;
163         break;
164     case LASI_VER:
165         /* read-only.  */
166         break;
167     case LASI_IORESET:
168         break;  /* XXX: TODO: Reset various devices. */
169     case LASI_AMR:
170         s->amr = val;
171         break;
172 
173     default:
174         /* Controlled by lasi_chip_mem_valid above. */
175         g_assert_not_reached();
176     }
177     return MEMTX_OK;
178 }
179 
180 static const MemoryRegionOps lasi_chip_ops = {
181     .read_with_attrs = lasi_chip_read_with_attrs,
182     .write_with_attrs = lasi_chip_write_with_attrs,
183     .endianness = DEVICE_BIG_ENDIAN,
184     .valid = {
185         .min_access_size = 1,
186         .max_access_size = 4,
187         .accepts = lasi_chip_mem_valid,
188     },
189     .impl = {
190         .min_access_size = 1,
191         .max_access_size = 4,
192     },
193 };
194 
195 static const VMStateDescription vmstate_lasi = {
196     .name = "Lasi",
197     .version_id = 2,
198     .minimum_version_id = 1,
199     .fields = (const VMStateField[]) {
200         VMSTATE_UINT32(irr, LasiState),
201         VMSTATE_UINT32(imr, LasiState),
202         VMSTATE_UINT32(ipr, LasiState),
203         VMSTATE_UINT32(icr, LasiState),
204         VMSTATE_UINT32(iar, LasiState),
205         VMSTATE_UINT32(errlog, LasiState),
206         VMSTATE_UINT32(amr, LasiState),
207         VMSTATE_UINT32_V(rtc_ref, LasiState, 2),
208         VMSTATE_END_OF_LIST()
209     }
210 };
211 
212 
213 static void lasi_set_irq(void *opaque, int irq, int level)
214 {
215     LasiState *s = opaque;
216     uint32_t bit = 1u << irq;
217 
218     if (level) {
219         s->ipr |= bit;
220         if (bit & s->imr) {
221             uint32_t iar = s->iar;
222             s->irr |= bit;
223             if ((s->icr & ICR_BUS_ERROR_BIT) == 0) {
224                 stl_be_phys(&address_space_memory, iar & -32, iar & 31);
225             }
226         }
227     }
228 }
229 
230 static void lasi_reset(DeviceState *dev)
231 {
232     LasiState *s = LASI_CHIP(dev);
233 
234     s->iar = 0xFFFB0000 + 3; /* CPU_HPA + 3 */
235 
236     /* Real time clock (RTC), it's only one 32-bit counter @9000 */
237     s->rtc_ref = 0;
238 }
239 
240 static void lasi_init(Object *obj)
241 {
242     LasiState *s = LASI_CHIP(obj);
243     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
244 
245     memory_region_init_io(&s->this_mem, OBJECT(s), &lasi_chip_ops,
246                           s, "lasi", 0x100000);
247 
248     sysbus_init_mmio(sbd, &s->this_mem);
249 
250     qdev_init_gpio_in(DEVICE(obj), lasi_set_irq, LASI_IRQS);
251 }
252 
253 static void lasi_class_init(ObjectClass *klass, void *data)
254 {
255     DeviceClass *dc = DEVICE_CLASS(klass);
256 
257     dc->reset = lasi_reset;
258     dc->vmsd = &vmstate_lasi;
259 }
260 
261 static const TypeInfo lasi_pcihost_info = {
262     .name          = TYPE_LASI_CHIP,
263     .parent        = TYPE_SYS_BUS_DEVICE,
264     .instance_init = lasi_init,
265     .instance_size = sizeof(LasiState),
266     .class_init    = lasi_class_init,
267 };
268 
269 static void lasi_register_types(void)
270 {
271     type_register_static(&lasi_pcihost_info);
272 }
273 
274 type_init(lasi_register_types)
275