lasips2: add named input gpio to handle incoming port IRQs
[qemu/armbru.git] / hw / input / lasips2.c
blob013d891af695bac1550aafbdc1906e1e6cdb1f84
1 /*
2 * QEMU HP Lasi PS/2 interface emulation
4 * Copyright (c) 2019 Sven Schnelle
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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.
24 #include "qemu/osdep.h"
25 #include "qemu/log.h"
26 #include "hw/qdev-properties.h"
27 #include "hw/sysbus.h"
28 #include "hw/input/ps2.h"
29 #include "hw/input/lasips2.h"
30 #include "exec/hwaddr.h"
31 #include "trace.h"
32 #include "exec/address-spaces.h"
33 #include "migration/vmstate.h"
34 #include "hw/irq.h"
35 #include "qapi/error.h"
38 static const VMStateDescription vmstate_lasips2 = {
39 .name = "lasips2",
40 .version_id = 0,
41 .minimum_version_id = 0,
42 .fields = (VMStateField[]) {
43 VMSTATE_UINT8(kbd_port.parent_obj.control, LASIPS2State),
44 VMSTATE_UINT8(kbd_port.parent_obj.id, LASIPS2State),
45 VMSTATE_BOOL(kbd_port.parent_obj.birq, LASIPS2State),
46 VMSTATE_UINT8(mouse_port.parent_obj.control, LASIPS2State),
47 VMSTATE_UINT8(mouse_port.parent_obj.id, LASIPS2State),
48 VMSTATE_BOOL(mouse_port.parent_obj.birq, LASIPS2State),
49 VMSTATE_END_OF_LIST()
53 typedef enum {
54 REG_PS2_ID = 0,
55 REG_PS2_RCVDATA = 4,
56 REG_PS2_CONTROL = 8,
57 REG_PS2_STATUS = 12,
58 } lasips2_read_reg_t;
60 typedef enum {
61 REG_PS2_RESET = 0,
62 REG_PS2_XMTDATA = 4,
63 } lasips2_write_reg_t;
65 typedef enum {
66 LASIPS2_CONTROL_ENABLE = 0x01,
67 LASIPS2_CONTROL_LOOPBACK = 0x02,
68 LASIPS2_CONTROL_DIAG = 0x20,
69 LASIPS2_CONTROL_DATDIR = 0x40,
70 LASIPS2_CONTROL_CLKDIR = 0x80,
71 } lasips2_control_reg_t;
73 typedef enum {
74 LASIPS2_STATUS_RBNE = 0x01,
75 LASIPS2_STATUS_TBNE = 0x02,
76 LASIPS2_STATUS_TERR = 0x04,
77 LASIPS2_STATUS_PERR = 0x08,
78 LASIPS2_STATUS_CMPINTR = 0x10,
79 LASIPS2_STATUS_DATSHD = 0x40,
80 LASIPS2_STATUS_CLKSHD = 0x80,
81 } lasips2_status_reg_t;
83 static const char *lasips2_read_reg_name(uint64_t addr)
85 switch (addr & 0xc) {
86 case REG_PS2_ID:
87 return " PS2_ID";
89 case REG_PS2_RCVDATA:
90 return " PS2_RCVDATA";
92 case REG_PS2_CONTROL:
93 return " PS2_CONTROL";
95 case REG_PS2_STATUS:
96 return " PS2_STATUS";
98 default:
99 return "";
103 static const char *lasips2_write_reg_name(uint64_t addr)
105 switch (addr & 0x0c) {
106 case REG_PS2_RESET:
107 return " PS2_RESET";
109 case REG_PS2_XMTDATA:
110 return " PS2_XMTDATA";
112 case REG_PS2_CONTROL:
113 return " PS2_CONTROL";
115 default:
116 return "";
120 static void lasips2_update_irq(LASIPS2State *s)
122 trace_lasips2_intr(s->kbd_port.parent_obj.birq |
123 s->mouse_port.parent_obj.birq);
124 qemu_set_irq(s->irq, s->kbd_port.parent_obj.birq |
125 s->mouse_port.parent_obj.birq);
128 static void lasips2_set_irq(void *opaque, int n, int level)
130 LASIPS2State *s = LASIPS2(opaque);
132 if (level) {
133 s->int_status |= BIT(n);
134 } else {
135 s->int_status &= ~BIT(n);
138 lasips2_update_irq(s);
141 static void lasips2_reg_write(void *opaque, hwaddr addr, uint64_t val,
142 unsigned size)
144 LASIPS2Port *port = opaque;
146 trace_lasips2_reg_write(size, port->id, addr,
147 lasips2_write_reg_name(addr), val);
149 switch (addr & 0xc) {
150 case REG_PS2_CONTROL:
151 port->control = val;
152 break;
154 case REG_PS2_XMTDATA:
155 if (port->control & LASIPS2_CONTROL_LOOPBACK) {
156 port->buf = val;
157 port->birq = true;
158 port->loopback_rbne = true;
159 lasips2_update_irq(port->parent);
160 break;
163 if (port->id) {
164 ps2_write_mouse(PS2_MOUSE_DEVICE(port->ps2dev), val);
165 } else {
166 ps2_write_keyboard(PS2_KBD_DEVICE(port->ps2dev), val);
168 break;
170 case REG_PS2_RESET:
171 break;
173 default:
174 qemu_log_mask(LOG_UNIMP, "%s: unknown register 0x%02" HWADDR_PRIx "\n",
175 __func__, addr);
176 break;
180 static uint64_t lasips2_reg_read(void *opaque, hwaddr addr, unsigned size)
182 LASIPS2Port *port = opaque;
183 uint64_t ret = 0;
185 switch (addr & 0xc) {
186 case REG_PS2_ID:
187 ret = port->id;
188 break;
190 case REG_PS2_RCVDATA:
191 if (port->control & LASIPS2_CONTROL_LOOPBACK) {
192 port->birq = false;
193 port->loopback_rbne = false;
194 lasips2_update_irq(port->parent);
195 ret = port->buf;
196 break;
199 ret = ps2_read_data(port->ps2dev);
200 break;
202 case REG_PS2_CONTROL:
203 ret = port->control;
204 break;
206 case REG_PS2_STATUS:
207 ret = LASIPS2_STATUS_DATSHD | LASIPS2_STATUS_CLKSHD;
209 if (port->control & LASIPS2_CONTROL_DIAG) {
210 if (!(port->control & LASIPS2_CONTROL_DATDIR)) {
211 ret &= ~LASIPS2_STATUS_DATSHD;
214 if (!(port->control & LASIPS2_CONTROL_CLKDIR)) {
215 ret &= ~LASIPS2_STATUS_CLKSHD;
219 if (port->control & LASIPS2_CONTROL_LOOPBACK) {
220 if (port->loopback_rbne) {
221 ret |= LASIPS2_STATUS_RBNE;
223 } else {
224 if (!ps2_queue_empty(port->ps2dev)) {
225 ret |= LASIPS2_STATUS_RBNE;
229 if (port->parent->kbd_port.parent_obj.birq ||
230 port->parent->mouse_port.parent_obj.birq) {
231 ret |= LASIPS2_STATUS_CMPINTR;
233 break;
235 default:
236 qemu_log_mask(LOG_UNIMP, "%s: unknown register 0x%02" HWADDR_PRIx "\n",
237 __func__, addr);
238 break;
241 trace_lasips2_reg_read(size, port->id, addr,
242 lasips2_read_reg_name(addr), ret);
243 return ret;
246 static const MemoryRegionOps lasips2_reg_ops = {
247 .read = lasips2_reg_read,
248 .write = lasips2_reg_write,
249 .impl = {
250 .min_access_size = 1,
251 .max_access_size = 4,
253 .endianness = DEVICE_NATIVE_ENDIAN,
256 static void lasips2_set_kbd_irq(void *opaque, int n, int level)
258 LASIPS2State *s = LASIPS2(opaque);
259 LASIPS2Port *port = LASIPS2_PORT(&s->kbd_port);
261 port->birq = level;
262 lasips2_update_irq(port->parent);
265 static void lasips2_set_mouse_irq(void *opaque, int n, int level)
267 LASIPS2State *s = LASIPS2(opaque);
268 LASIPS2Port *port = LASIPS2_PORT(&s->mouse_port);
270 port->birq = level;
271 lasips2_update_irq(port->parent);
274 static void lasips2_realize(DeviceState *dev, Error **errp)
276 LASIPS2State *s = LASIPS2(dev);
277 LASIPS2Port *lp;
279 lp = LASIPS2_PORT(&s->kbd_port);
280 if (!(qdev_realize(DEVICE(lp), NULL, errp))) {
281 return;
284 qdev_connect_gpio_out(DEVICE(lp->ps2dev), PS2_DEVICE_IRQ,
285 qdev_get_gpio_in_named(dev, "ps2-kbd-input-irq",
286 0));
288 lp = LASIPS2_PORT(&s->mouse_port);
289 if (!(qdev_realize(DEVICE(lp), NULL, errp))) {
290 return;
293 qdev_connect_gpio_out(DEVICE(lp->ps2dev), PS2_DEVICE_IRQ,
294 qdev_get_gpio_in_named(dev, "ps2-mouse-input-irq",
295 0));
298 static void lasips2_init(Object *obj)
300 LASIPS2State *s = LASIPS2(obj);
301 LASIPS2Port *lp;
303 object_initialize_child(obj, "lasips2-kbd-port", &s->kbd_port,
304 TYPE_LASIPS2_KBD_PORT);
305 object_initialize_child(obj, "lasips2-mouse-port", &s->mouse_port,
306 TYPE_LASIPS2_MOUSE_PORT);
308 lp = LASIPS2_PORT(&s->kbd_port);
309 sysbus_init_mmio(SYS_BUS_DEVICE(obj), &lp->reg);
310 lp = LASIPS2_PORT(&s->mouse_port);
311 sysbus_init_mmio(SYS_BUS_DEVICE(obj), &lp->reg);
313 sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
315 qdev_init_gpio_in_named(DEVICE(obj), lasips2_set_kbd_irq,
316 "ps2-kbd-input-irq", 1);
317 qdev_init_gpio_in_named(DEVICE(obj), lasips2_set_mouse_irq,
318 "ps2-mouse-input-irq", 1);
319 qdev_init_gpio_in_named(DEVICE(obj), lasips2_set_irq,
320 "lasips2-port-input-irq", 2);
323 static void lasips2_class_init(ObjectClass *klass, void *data)
325 DeviceClass *dc = DEVICE_CLASS(klass);
327 dc->realize = lasips2_realize;
328 dc->vmsd = &vmstate_lasips2;
329 set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
332 static const TypeInfo lasips2_info = {
333 .name = TYPE_LASIPS2,
334 .parent = TYPE_SYS_BUS_DEVICE,
335 .instance_init = lasips2_init,
336 .instance_size = sizeof(LASIPS2State),
337 .class_init = lasips2_class_init,
340 static void lasips2_port_set_irq(void *opaque, int n, int level)
342 LASIPS2Port *s = LASIPS2_PORT(opaque);
344 qemu_set_irq(s->irq, level);
347 static void lasips2_port_realize(DeviceState *dev, Error **errp)
349 LASIPS2Port *s = LASIPS2_PORT(dev);
351 qdev_connect_gpio_out(DEVICE(s->ps2dev), PS2_DEVICE_IRQ,
352 qdev_get_gpio_in_named(dev, "ps2-input-irq", 0));
355 static void lasips2_port_init(Object *obj)
357 LASIPS2Port *s = LASIPS2_PORT(obj);
359 qdev_init_gpio_out(DEVICE(obj), &s->irq, 1);
360 qdev_init_gpio_in_named(DEVICE(obj), lasips2_port_set_irq,
361 "ps2-input-irq", 1);
364 static void lasips2_port_class_init(ObjectClass *klass, void *data)
366 DeviceClass *dc = DEVICE_CLASS(klass);
368 dc->realize = lasips2_port_realize;
371 static const TypeInfo lasips2_port_info = {
372 .name = TYPE_LASIPS2_PORT,
373 .parent = TYPE_DEVICE,
374 .instance_init = lasips2_port_init,
375 .instance_size = sizeof(LASIPS2Port),
376 .class_init = lasips2_port_class_init,
377 .class_size = sizeof(LASIPS2PortDeviceClass),
378 .abstract = true,
381 static void lasips2_kbd_port_realize(DeviceState *dev, Error **errp)
383 LASIPS2Port *lp = LASIPS2_PORT(dev);
385 lp->ps2dev = ps2_kbd_init();
388 static void lasips2_kbd_port_init(Object *obj)
390 LASIPS2KbdPort *s = LASIPS2_KBD_PORT(obj);
391 LASIPS2Port *lp = LASIPS2_PORT(obj);
393 memory_region_init_io(&lp->reg, obj, &lasips2_reg_ops, lp, "lasips2-kbd",
394 0x100);
395 lp->id = 0;
396 lp->parent = container_of(s, LASIPS2State, kbd_port);
399 static void lasips2_kbd_port_class_init(ObjectClass *klass, void *data)
401 DeviceClass *dc = DEVICE_CLASS(klass);
402 LASIPS2PortDeviceClass *lpdc = LASIPS2_PORT_CLASS(klass);
404 device_class_set_parent_realize(dc, lasips2_kbd_port_realize,
405 &lpdc->parent_realize);
408 static const TypeInfo lasips2_kbd_port_info = {
409 .name = TYPE_LASIPS2_KBD_PORT,
410 .parent = TYPE_LASIPS2_PORT,
411 .instance_size = sizeof(LASIPS2KbdPort),
412 .instance_init = lasips2_kbd_port_init,
413 .class_init = lasips2_kbd_port_class_init,
416 static void lasips2_mouse_port_realize(DeviceState *dev, Error **errp)
418 LASIPS2Port *lp = LASIPS2_PORT(dev);
420 lp->ps2dev = ps2_mouse_init();
423 static void lasips2_mouse_port_init(Object *obj)
425 LASIPS2MousePort *s = LASIPS2_MOUSE_PORT(obj);
426 LASIPS2Port *lp = LASIPS2_PORT(obj);
428 memory_region_init_io(&lp->reg, obj, &lasips2_reg_ops, lp, "lasips2-mouse",
429 0x100);
430 lp->id = 1;
431 lp->parent = container_of(s, LASIPS2State, mouse_port);
434 static void lasips2_mouse_port_class_init(ObjectClass *klass, void *data)
436 DeviceClass *dc = DEVICE_CLASS(klass);
437 LASIPS2PortDeviceClass *lpdc = LASIPS2_PORT_CLASS(klass);
439 device_class_set_parent_realize(dc, lasips2_mouse_port_realize,
440 &lpdc->parent_realize);
443 static const TypeInfo lasips2_mouse_port_info = {
444 .name = TYPE_LASIPS2_MOUSE_PORT,
445 .parent = TYPE_LASIPS2_PORT,
446 .instance_size = sizeof(LASIPS2MousePort),
447 .instance_init = lasips2_mouse_port_init,
448 .class_init = lasips2_mouse_port_class_init,
451 static void lasips2_register_types(void)
453 type_register_static(&lasips2_info);
454 type_register_static(&lasips2_port_info);
455 type_register_static(&lasips2_kbd_port_info);
456 type_register_static(&lasips2_mouse_port_info);
459 type_init(lasips2_register_types)