xref: /openbmc/qemu/hw/arm/musicpal.c (revision 14b6d44d4720681a57b5d2c58cabdfc6364f8263)
1 /*
2  * Marvell MV88W8618 / Freecom MusicPal emulation.
3  *
4  * Copyright (c) 2008 Jan Kiszka
5  *
6  * This code is licensed under the GNU GPL v2.
7  *
8  * Contributions after 2012-01-13 are licensed under the terms of the
9  * GNU GPL, version 2 or (at your option) any later version.
10  */
11 
12 #include "qemu/osdep.h"
13 #include "qapi/error.h"
14 #include "hw/sysbus.h"
15 #include "hw/arm/arm.h"
16 #include "hw/devices.h"
17 #include "net/net.h"
18 #include "sysemu/sysemu.h"
19 #include "hw/boards.h"
20 #include "hw/char/serial.h"
21 #include "qemu/timer.h"
22 #include "hw/ptimer.h"
23 #include "hw/block/flash.h"
24 #include "ui/console.h"
25 #include "hw/i2c/i2c.h"
26 #include "sysemu/block-backend.h"
27 #include "exec/address-spaces.h"
28 #include "ui/pixel_ops.h"
29 
30 #define MP_MISC_BASE            0x80002000
31 #define MP_MISC_SIZE            0x00001000
32 
33 #define MP_ETH_BASE             0x80008000
34 #define MP_ETH_SIZE             0x00001000
35 
36 #define MP_WLAN_BASE            0x8000C000
37 #define MP_WLAN_SIZE            0x00000800
38 
39 #define MP_UART1_BASE           0x8000C840
40 #define MP_UART2_BASE           0x8000C940
41 
42 #define MP_GPIO_BASE            0x8000D000
43 #define MP_GPIO_SIZE            0x00001000
44 
45 #define MP_FLASHCFG_BASE        0x90006000
46 #define MP_FLASHCFG_SIZE        0x00001000
47 
48 #define MP_AUDIO_BASE           0x90007000
49 
50 #define MP_PIC_BASE             0x90008000
51 #define MP_PIC_SIZE             0x00001000
52 
53 #define MP_PIT_BASE             0x90009000
54 #define MP_PIT_SIZE             0x00001000
55 
56 #define MP_LCD_BASE             0x9000c000
57 #define MP_LCD_SIZE             0x00001000
58 
59 #define MP_SRAM_BASE            0xC0000000
60 #define MP_SRAM_SIZE            0x00020000
61 
62 #define MP_RAM_DEFAULT_SIZE     32*1024*1024
63 #define MP_FLASH_SIZE_MAX       32*1024*1024
64 
65 #define MP_TIMER1_IRQ           4
66 #define MP_TIMER2_IRQ           5
67 #define MP_TIMER3_IRQ           6
68 #define MP_TIMER4_IRQ           7
69 #define MP_EHCI_IRQ             8
70 #define MP_ETH_IRQ              9
71 #define MP_UART1_IRQ            11
72 #define MP_UART2_IRQ            11
73 #define MP_GPIO_IRQ             12
74 #define MP_RTC_IRQ              28
75 #define MP_AUDIO_IRQ            30
76 
77 /* Wolfson 8750 I2C address */
78 #define MP_WM_ADDR              0x1A
79 
80 /* Ethernet register offsets */
81 #define MP_ETH_SMIR             0x010
82 #define MP_ETH_PCXR             0x408
83 #define MP_ETH_SDCMR            0x448
84 #define MP_ETH_ICR              0x450
85 #define MP_ETH_IMR              0x458
86 #define MP_ETH_FRDP0            0x480
87 #define MP_ETH_FRDP1            0x484
88 #define MP_ETH_FRDP2            0x488
89 #define MP_ETH_FRDP3            0x48C
90 #define MP_ETH_CRDP0            0x4A0
91 #define MP_ETH_CRDP1            0x4A4
92 #define MP_ETH_CRDP2            0x4A8
93 #define MP_ETH_CRDP3            0x4AC
94 #define MP_ETH_CTDP0            0x4E0
95 #define MP_ETH_CTDP1            0x4E4
96 
97 /* MII PHY access */
98 #define MP_ETH_SMIR_DATA        0x0000FFFF
99 #define MP_ETH_SMIR_ADDR        0x03FF0000
100 #define MP_ETH_SMIR_OPCODE      (1 << 26) /* Read value */
101 #define MP_ETH_SMIR_RDVALID     (1 << 27)
102 
103 /* PHY registers */
104 #define MP_ETH_PHY1_BMSR        0x00210000
105 #define MP_ETH_PHY1_PHYSID1     0x00410000
106 #define MP_ETH_PHY1_PHYSID2     0x00610000
107 
108 #define MP_PHY_BMSR_LINK        0x0004
109 #define MP_PHY_BMSR_AUTONEG     0x0008
110 
111 #define MP_PHY_88E3015          0x01410E20
112 
113 /* TX descriptor status */
114 #define MP_ETH_TX_OWN           (1U << 31)
115 
116 /* RX descriptor status */
117 #define MP_ETH_RX_OWN           (1U << 31)
118 
119 /* Interrupt cause/mask bits */
120 #define MP_ETH_IRQ_RX_BIT       0
121 #define MP_ETH_IRQ_RX           (1 << MP_ETH_IRQ_RX_BIT)
122 #define MP_ETH_IRQ_TXHI_BIT     2
123 #define MP_ETH_IRQ_TXLO_BIT     3
124 
125 /* Port config bits */
126 #define MP_ETH_PCXR_2BSM_BIT    28 /* 2-byte incoming suffix */
127 
128 /* SDMA command bits */
129 #define MP_ETH_CMD_TXHI         (1 << 23)
130 #define MP_ETH_CMD_TXLO         (1 << 22)
131 
132 typedef struct mv88w8618_tx_desc {
133     uint32_t cmdstat;
134     uint16_t res;
135     uint16_t bytes;
136     uint32_t buffer;
137     uint32_t next;
138 } mv88w8618_tx_desc;
139 
140 typedef struct mv88w8618_rx_desc {
141     uint32_t cmdstat;
142     uint16_t bytes;
143     uint16_t buffer_size;
144     uint32_t buffer;
145     uint32_t next;
146 } mv88w8618_rx_desc;
147 
148 #define TYPE_MV88W8618_ETH "mv88w8618_eth"
149 #define MV88W8618_ETH(obj) \
150     OBJECT_CHECK(mv88w8618_eth_state, (obj), TYPE_MV88W8618_ETH)
151 
152 typedef struct mv88w8618_eth_state {
153     /*< private >*/
154     SysBusDevice parent_obj;
155     /*< public >*/
156 
157     MemoryRegion iomem;
158     qemu_irq irq;
159     uint32_t smir;
160     uint32_t icr;
161     uint32_t imr;
162     int mmio_index;
163     uint32_t vlan_header;
164     uint32_t tx_queue[2];
165     uint32_t rx_queue[4];
166     uint32_t frx_queue[4];
167     uint32_t cur_rx[4];
168     NICState *nic;
169     NICConf conf;
170 } mv88w8618_eth_state;
171 
172 static void eth_rx_desc_put(uint32_t addr, mv88w8618_rx_desc *desc)
173 {
174     cpu_to_le32s(&desc->cmdstat);
175     cpu_to_le16s(&desc->bytes);
176     cpu_to_le16s(&desc->buffer_size);
177     cpu_to_le32s(&desc->buffer);
178     cpu_to_le32s(&desc->next);
179     cpu_physical_memory_write(addr, desc, sizeof(*desc));
180 }
181 
182 static void eth_rx_desc_get(uint32_t addr, mv88w8618_rx_desc *desc)
183 {
184     cpu_physical_memory_read(addr, desc, sizeof(*desc));
185     le32_to_cpus(&desc->cmdstat);
186     le16_to_cpus(&desc->bytes);
187     le16_to_cpus(&desc->buffer_size);
188     le32_to_cpus(&desc->buffer);
189     le32_to_cpus(&desc->next);
190 }
191 
192 static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size)
193 {
194     mv88w8618_eth_state *s = qemu_get_nic_opaque(nc);
195     uint32_t desc_addr;
196     mv88w8618_rx_desc desc;
197     int i;
198 
199     for (i = 0; i < 4; i++) {
200         desc_addr = s->cur_rx[i];
201         if (!desc_addr) {
202             continue;
203         }
204         do {
205             eth_rx_desc_get(desc_addr, &desc);
206             if ((desc.cmdstat & MP_ETH_RX_OWN) && desc.buffer_size >= size) {
207                 cpu_physical_memory_write(desc.buffer + s->vlan_header,
208                                           buf, size);
209                 desc.bytes = size + s->vlan_header;
210                 desc.cmdstat &= ~MP_ETH_RX_OWN;
211                 s->cur_rx[i] = desc.next;
212 
213                 s->icr |= MP_ETH_IRQ_RX;
214                 if (s->icr & s->imr) {
215                     qemu_irq_raise(s->irq);
216                 }
217                 eth_rx_desc_put(desc_addr, &desc);
218                 return size;
219             }
220             desc_addr = desc.next;
221         } while (desc_addr != s->rx_queue[i]);
222     }
223     return size;
224 }
225 
226 static void eth_tx_desc_put(uint32_t addr, mv88w8618_tx_desc *desc)
227 {
228     cpu_to_le32s(&desc->cmdstat);
229     cpu_to_le16s(&desc->res);
230     cpu_to_le16s(&desc->bytes);
231     cpu_to_le32s(&desc->buffer);
232     cpu_to_le32s(&desc->next);
233     cpu_physical_memory_write(addr, desc, sizeof(*desc));
234 }
235 
236 static void eth_tx_desc_get(uint32_t addr, mv88w8618_tx_desc *desc)
237 {
238     cpu_physical_memory_read(addr, desc, sizeof(*desc));
239     le32_to_cpus(&desc->cmdstat);
240     le16_to_cpus(&desc->res);
241     le16_to_cpus(&desc->bytes);
242     le32_to_cpus(&desc->buffer);
243     le32_to_cpus(&desc->next);
244 }
245 
246 static void eth_send(mv88w8618_eth_state *s, int queue_index)
247 {
248     uint32_t desc_addr = s->tx_queue[queue_index];
249     mv88w8618_tx_desc desc;
250     uint32_t next_desc;
251     uint8_t buf[2048];
252     int len;
253 
254     do {
255         eth_tx_desc_get(desc_addr, &desc);
256         next_desc = desc.next;
257         if (desc.cmdstat & MP_ETH_TX_OWN) {
258             len = desc.bytes;
259             if (len < 2048) {
260                 cpu_physical_memory_read(desc.buffer, buf, len);
261                 qemu_send_packet(qemu_get_queue(s->nic), buf, len);
262             }
263             desc.cmdstat &= ~MP_ETH_TX_OWN;
264             s->icr |= 1 << (MP_ETH_IRQ_TXLO_BIT - queue_index);
265             eth_tx_desc_put(desc_addr, &desc);
266         }
267         desc_addr = next_desc;
268     } while (desc_addr != s->tx_queue[queue_index]);
269 }
270 
271 static uint64_t mv88w8618_eth_read(void *opaque, hwaddr offset,
272                                    unsigned size)
273 {
274     mv88w8618_eth_state *s = opaque;
275 
276     switch (offset) {
277     case MP_ETH_SMIR:
278         if (s->smir & MP_ETH_SMIR_OPCODE) {
279             switch (s->smir & MP_ETH_SMIR_ADDR) {
280             case MP_ETH_PHY1_BMSR:
281                 return MP_PHY_BMSR_LINK | MP_PHY_BMSR_AUTONEG |
282                        MP_ETH_SMIR_RDVALID;
283             case MP_ETH_PHY1_PHYSID1:
284                 return (MP_PHY_88E3015 >> 16) | MP_ETH_SMIR_RDVALID;
285             case MP_ETH_PHY1_PHYSID2:
286                 return (MP_PHY_88E3015 & 0xFFFF) | MP_ETH_SMIR_RDVALID;
287             default:
288                 return MP_ETH_SMIR_RDVALID;
289             }
290         }
291         return 0;
292 
293     case MP_ETH_ICR:
294         return s->icr;
295 
296     case MP_ETH_IMR:
297         return s->imr;
298 
299     case MP_ETH_FRDP0 ... MP_ETH_FRDP3:
300         return s->frx_queue[(offset - MP_ETH_FRDP0)/4];
301 
302     case MP_ETH_CRDP0 ... MP_ETH_CRDP3:
303         return s->rx_queue[(offset - MP_ETH_CRDP0)/4];
304 
305     case MP_ETH_CTDP0 ... MP_ETH_CTDP1:
306         return s->tx_queue[(offset - MP_ETH_CTDP0)/4];
307 
308     default:
309         return 0;
310     }
311 }
312 
313 static void mv88w8618_eth_write(void *opaque, hwaddr offset,
314                                 uint64_t value, unsigned size)
315 {
316     mv88w8618_eth_state *s = opaque;
317 
318     switch (offset) {
319     case MP_ETH_SMIR:
320         s->smir = value;
321         break;
322 
323     case MP_ETH_PCXR:
324         s->vlan_header = ((value >> MP_ETH_PCXR_2BSM_BIT) & 1) * 2;
325         break;
326 
327     case MP_ETH_SDCMR:
328         if (value & MP_ETH_CMD_TXHI) {
329             eth_send(s, 1);
330         }
331         if (value & MP_ETH_CMD_TXLO) {
332             eth_send(s, 0);
333         }
334         if (value & (MP_ETH_CMD_TXHI | MP_ETH_CMD_TXLO) && s->icr & s->imr) {
335             qemu_irq_raise(s->irq);
336         }
337         break;
338 
339     case MP_ETH_ICR:
340         s->icr &= value;
341         break;
342 
343     case MP_ETH_IMR:
344         s->imr = value;
345         if (s->icr & s->imr) {
346             qemu_irq_raise(s->irq);
347         }
348         break;
349 
350     case MP_ETH_FRDP0 ... MP_ETH_FRDP3:
351         s->frx_queue[(offset - MP_ETH_FRDP0)/4] = value;
352         break;
353 
354     case MP_ETH_CRDP0 ... MP_ETH_CRDP3:
355         s->rx_queue[(offset - MP_ETH_CRDP0)/4] =
356             s->cur_rx[(offset - MP_ETH_CRDP0)/4] = value;
357         break;
358 
359     case MP_ETH_CTDP0 ... MP_ETH_CTDP1:
360         s->tx_queue[(offset - MP_ETH_CTDP0)/4] = value;
361         break;
362     }
363 }
364 
365 static const MemoryRegionOps mv88w8618_eth_ops = {
366     .read = mv88w8618_eth_read,
367     .write = mv88w8618_eth_write,
368     .endianness = DEVICE_NATIVE_ENDIAN,
369 };
370 
371 static void eth_cleanup(NetClientState *nc)
372 {
373     mv88w8618_eth_state *s = qemu_get_nic_opaque(nc);
374 
375     s->nic = NULL;
376 }
377 
378 static NetClientInfo net_mv88w8618_info = {
379     .type = NET_CLIENT_OPTIONS_KIND_NIC,
380     .size = sizeof(NICState),
381     .receive = eth_receive,
382     .cleanup = eth_cleanup,
383 };
384 
385 static int mv88w8618_eth_init(SysBusDevice *sbd)
386 {
387     DeviceState *dev = DEVICE(sbd);
388     mv88w8618_eth_state *s = MV88W8618_ETH(dev);
389 
390     sysbus_init_irq(sbd, &s->irq);
391     s->nic = qemu_new_nic(&net_mv88w8618_info, &s->conf,
392                           object_get_typename(OBJECT(dev)), dev->id, s);
393     memory_region_init_io(&s->iomem, OBJECT(s), &mv88w8618_eth_ops, s,
394                           "mv88w8618-eth", MP_ETH_SIZE);
395     sysbus_init_mmio(sbd, &s->iomem);
396     return 0;
397 }
398 
399 static const VMStateDescription mv88w8618_eth_vmsd = {
400     .name = "mv88w8618_eth",
401     .version_id = 1,
402     .minimum_version_id = 1,
403     .fields = (VMStateField[]) {
404         VMSTATE_UINT32(smir, mv88w8618_eth_state),
405         VMSTATE_UINT32(icr, mv88w8618_eth_state),
406         VMSTATE_UINT32(imr, mv88w8618_eth_state),
407         VMSTATE_UINT32(vlan_header, mv88w8618_eth_state),
408         VMSTATE_UINT32_ARRAY(tx_queue, mv88w8618_eth_state, 2),
409         VMSTATE_UINT32_ARRAY(rx_queue, mv88w8618_eth_state, 4),
410         VMSTATE_UINT32_ARRAY(frx_queue, mv88w8618_eth_state, 4),
411         VMSTATE_UINT32_ARRAY(cur_rx, mv88w8618_eth_state, 4),
412         VMSTATE_END_OF_LIST()
413     }
414 };
415 
416 static Property mv88w8618_eth_properties[] = {
417     DEFINE_NIC_PROPERTIES(mv88w8618_eth_state, conf),
418     DEFINE_PROP_END_OF_LIST(),
419 };
420 
421 static void mv88w8618_eth_class_init(ObjectClass *klass, void *data)
422 {
423     DeviceClass *dc = DEVICE_CLASS(klass);
424     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
425 
426     k->init = mv88w8618_eth_init;
427     dc->vmsd = &mv88w8618_eth_vmsd;
428     dc->props = mv88w8618_eth_properties;
429 }
430 
431 static const TypeInfo mv88w8618_eth_info = {
432     .name          = TYPE_MV88W8618_ETH,
433     .parent        = TYPE_SYS_BUS_DEVICE,
434     .instance_size = sizeof(mv88w8618_eth_state),
435     .class_init    = mv88w8618_eth_class_init,
436 };
437 
438 /* LCD register offsets */
439 #define MP_LCD_IRQCTRL          0x180
440 #define MP_LCD_IRQSTAT          0x184
441 #define MP_LCD_SPICTRL          0x1ac
442 #define MP_LCD_INST             0x1bc
443 #define MP_LCD_DATA             0x1c0
444 
445 /* Mode magics */
446 #define MP_LCD_SPI_DATA         0x00100011
447 #define MP_LCD_SPI_CMD          0x00104011
448 #define MP_LCD_SPI_INVALID      0x00000000
449 
450 /* Commmands */
451 #define MP_LCD_INST_SETPAGE0    0xB0
452 /* ... */
453 #define MP_LCD_INST_SETPAGE7    0xB7
454 
455 #define MP_LCD_TEXTCOLOR        0xe0e0ff /* RRGGBB */
456 
457 #define TYPE_MUSICPAL_LCD "musicpal_lcd"
458 #define MUSICPAL_LCD(obj) \
459     OBJECT_CHECK(musicpal_lcd_state, (obj), TYPE_MUSICPAL_LCD)
460 
461 typedef struct musicpal_lcd_state {
462     /*< private >*/
463     SysBusDevice parent_obj;
464     /*< public >*/
465 
466     MemoryRegion iomem;
467     uint32_t brightness;
468     uint32_t mode;
469     uint32_t irqctrl;
470     uint32_t page;
471     uint32_t page_off;
472     QemuConsole *con;
473     uint8_t video_ram[128*64/8];
474 } musicpal_lcd_state;
475 
476 static uint8_t scale_lcd_color(musicpal_lcd_state *s, uint8_t col)
477 {
478     switch (s->brightness) {
479     case 7:
480         return col;
481     case 0:
482         return 0;
483     default:
484         return (col * s->brightness) / 7;
485     }
486 }
487 
488 #define SET_LCD_PIXEL(depth, type) \
489 static inline void glue(set_lcd_pixel, depth) \
490         (musicpal_lcd_state *s, int x, int y, type col) \
491 { \
492     int dx, dy; \
493     DisplaySurface *surface = qemu_console_surface(s->con); \
494     type *pixel = &((type *) surface_data(surface))[(y * 128 * 3 + x) * 3]; \
495 \
496     for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \
497         for (dx = 0; dx < 3; dx++, pixel++) \
498             *pixel = col; \
499 }
500 SET_LCD_PIXEL(8, uint8_t)
501 SET_LCD_PIXEL(16, uint16_t)
502 SET_LCD_PIXEL(32, uint32_t)
503 
504 static void lcd_refresh(void *opaque)
505 {
506     musicpal_lcd_state *s = opaque;
507     DisplaySurface *surface = qemu_console_surface(s->con);
508     int x, y, col;
509 
510     switch (surface_bits_per_pixel(surface)) {
511     case 0:
512         return;
513 #define LCD_REFRESH(depth, func) \
514     case depth: \
515         col = func(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff), \
516                    scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff), \
517                    scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff)); \
518         for (x = 0; x < 128; x++) { \
519             for (y = 0; y < 64; y++) { \
520                 if (s->video_ram[x + (y/8)*128] & (1 << (y % 8))) { \
521                     glue(set_lcd_pixel, depth)(s, x, y, col); \
522                 } else { \
523                     glue(set_lcd_pixel, depth)(s, x, y, 0); \
524                 } \
525             } \
526         } \
527         break;
528     LCD_REFRESH(8, rgb_to_pixel8)
529     LCD_REFRESH(16, rgb_to_pixel16)
530     LCD_REFRESH(32, (is_surface_bgr(surface) ?
531                      rgb_to_pixel32bgr : rgb_to_pixel32))
532     default:
533         hw_error("unsupported colour depth %i\n",
534                  surface_bits_per_pixel(surface));
535     }
536 
537     dpy_gfx_update(s->con, 0, 0, 128*3, 64*3);
538 }
539 
540 static void lcd_invalidate(void *opaque)
541 {
542 }
543 
544 static void musicpal_lcd_gpio_brightness_in(void *opaque, int irq, int level)
545 {
546     musicpal_lcd_state *s = opaque;
547     s->brightness &= ~(1 << irq);
548     s->brightness |= level << irq;
549 }
550 
551 static uint64_t musicpal_lcd_read(void *opaque, hwaddr offset,
552                                   unsigned size)
553 {
554     musicpal_lcd_state *s = opaque;
555 
556     switch (offset) {
557     case MP_LCD_IRQCTRL:
558         return s->irqctrl;
559 
560     default:
561         return 0;
562     }
563 }
564 
565 static void musicpal_lcd_write(void *opaque, hwaddr offset,
566                                uint64_t value, unsigned size)
567 {
568     musicpal_lcd_state *s = opaque;
569 
570     switch (offset) {
571     case MP_LCD_IRQCTRL:
572         s->irqctrl = value;
573         break;
574 
575     case MP_LCD_SPICTRL:
576         if (value == MP_LCD_SPI_DATA || value == MP_LCD_SPI_CMD) {
577             s->mode = value;
578         } else {
579             s->mode = MP_LCD_SPI_INVALID;
580         }
581         break;
582 
583     case MP_LCD_INST:
584         if (value >= MP_LCD_INST_SETPAGE0 && value <= MP_LCD_INST_SETPAGE7) {
585             s->page = value - MP_LCD_INST_SETPAGE0;
586             s->page_off = 0;
587         }
588         break;
589 
590     case MP_LCD_DATA:
591         if (s->mode == MP_LCD_SPI_CMD) {
592             if (value >= MP_LCD_INST_SETPAGE0 &&
593                 value <= MP_LCD_INST_SETPAGE7) {
594                 s->page = value - MP_LCD_INST_SETPAGE0;
595                 s->page_off = 0;
596             }
597         } else if (s->mode == MP_LCD_SPI_DATA) {
598             s->video_ram[s->page*128 + s->page_off] = value;
599             s->page_off = (s->page_off + 1) & 127;
600         }
601         break;
602     }
603 }
604 
605 static const MemoryRegionOps musicpal_lcd_ops = {
606     .read = musicpal_lcd_read,
607     .write = musicpal_lcd_write,
608     .endianness = DEVICE_NATIVE_ENDIAN,
609 };
610 
611 static const GraphicHwOps musicpal_gfx_ops = {
612     .invalidate  = lcd_invalidate,
613     .gfx_update  = lcd_refresh,
614 };
615 
616 static int musicpal_lcd_init(SysBusDevice *sbd)
617 {
618     DeviceState *dev = DEVICE(sbd);
619     musicpal_lcd_state *s = MUSICPAL_LCD(dev);
620 
621     s->brightness = 7;
622 
623     memory_region_init_io(&s->iomem, OBJECT(s), &musicpal_lcd_ops, s,
624                           "musicpal-lcd", MP_LCD_SIZE);
625     sysbus_init_mmio(sbd, &s->iomem);
626 
627     s->con = graphic_console_init(dev, 0, &musicpal_gfx_ops, s);
628     qemu_console_resize(s->con, 128*3, 64*3);
629 
630     qdev_init_gpio_in(dev, musicpal_lcd_gpio_brightness_in, 3);
631 
632     return 0;
633 }
634 
635 static const VMStateDescription musicpal_lcd_vmsd = {
636     .name = "musicpal_lcd",
637     .version_id = 1,
638     .minimum_version_id = 1,
639     .fields = (VMStateField[]) {
640         VMSTATE_UINT32(brightness, musicpal_lcd_state),
641         VMSTATE_UINT32(mode, musicpal_lcd_state),
642         VMSTATE_UINT32(irqctrl, musicpal_lcd_state),
643         VMSTATE_UINT32(page, musicpal_lcd_state),
644         VMSTATE_UINT32(page_off, musicpal_lcd_state),
645         VMSTATE_BUFFER(video_ram, musicpal_lcd_state),
646         VMSTATE_END_OF_LIST()
647     }
648 };
649 
650 static void musicpal_lcd_class_init(ObjectClass *klass, void *data)
651 {
652     DeviceClass *dc = DEVICE_CLASS(klass);
653     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
654 
655     k->init = musicpal_lcd_init;
656     dc->vmsd = &musicpal_lcd_vmsd;
657 }
658 
659 static const TypeInfo musicpal_lcd_info = {
660     .name          = TYPE_MUSICPAL_LCD,
661     .parent        = TYPE_SYS_BUS_DEVICE,
662     .instance_size = sizeof(musicpal_lcd_state),
663     .class_init    = musicpal_lcd_class_init,
664 };
665 
666 /* PIC register offsets */
667 #define MP_PIC_STATUS           0x00
668 #define MP_PIC_ENABLE_SET       0x08
669 #define MP_PIC_ENABLE_CLR       0x0C
670 
671 #define TYPE_MV88W8618_PIC "mv88w8618_pic"
672 #define MV88W8618_PIC(obj) \
673     OBJECT_CHECK(mv88w8618_pic_state, (obj), TYPE_MV88W8618_PIC)
674 
675 typedef struct mv88w8618_pic_state {
676     /*< private >*/
677     SysBusDevice parent_obj;
678     /*< public >*/
679 
680     MemoryRegion iomem;
681     uint32_t level;
682     uint32_t enabled;
683     qemu_irq parent_irq;
684 } mv88w8618_pic_state;
685 
686 static void mv88w8618_pic_update(mv88w8618_pic_state *s)
687 {
688     qemu_set_irq(s->parent_irq, (s->level & s->enabled));
689 }
690 
691 static void mv88w8618_pic_set_irq(void *opaque, int irq, int level)
692 {
693     mv88w8618_pic_state *s = opaque;
694 
695     if (level) {
696         s->level |= 1 << irq;
697     } else {
698         s->level &= ~(1 << irq);
699     }
700     mv88w8618_pic_update(s);
701 }
702 
703 static uint64_t mv88w8618_pic_read(void *opaque, hwaddr offset,
704                                    unsigned size)
705 {
706     mv88w8618_pic_state *s = opaque;
707 
708     switch (offset) {
709     case MP_PIC_STATUS:
710         return s->level & s->enabled;
711 
712     default:
713         return 0;
714     }
715 }
716 
717 static void mv88w8618_pic_write(void *opaque, hwaddr offset,
718                                 uint64_t value, unsigned size)
719 {
720     mv88w8618_pic_state *s = opaque;
721 
722     switch (offset) {
723     case MP_PIC_ENABLE_SET:
724         s->enabled |= value;
725         break;
726 
727     case MP_PIC_ENABLE_CLR:
728         s->enabled &= ~value;
729         s->level &= ~value;
730         break;
731     }
732     mv88w8618_pic_update(s);
733 }
734 
735 static void mv88w8618_pic_reset(DeviceState *d)
736 {
737     mv88w8618_pic_state *s = MV88W8618_PIC(d);
738 
739     s->level = 0;
740     s->enabled = 0;
741 }
742 
743 static const MemoryRegionOps mv88w8618_pic_ops = {
744     .read = mv88w8618_pic_read,
745     .write = mv88w8618_pic_write,
746     .endianness = DEVICE_NATIVE_ENDIAN,
747 };
748 
749 static int mv88w8618_pic_init(SysBusDevice *dev)
750 {
751     mv88w8618_pic_state *s = MV88W8618_PIC(dev);
752 
753     qdev_init_gpio_in(DEVICE(dev), mv88w8618_pic_set_irq, 32);
754     sysbus_init_irq(dev, &s->parent_irq);
755     memory_region_init_io(&s->iomem, OBJECT(s), &mv88w8618_pic_ops, s,
756                           "musicpal-pic", MP_PIC_SIZE);
757     sysbus_init_mmio(dev, &s->iomem);
758     return 0;
759 }
760 
761 static const VMStateDescription mv88w8618_pic_vmsd = {
762     .name = "mv88w8618_pic",
763     .version_id = 1,
764     .minimum_version_id = 1,
765     .fields = (VMStateField[]) {
766         VMSTATE_UINT32(level, mv88w8618_pic_state),
767         VMSTATE_UINT32(enabled, mv88w8618_pic_state),
768         VMSTATE_END_OF_LIST()
769     }
770 };
771 
772 static void mv88w8618_pic_class_init(ObjectClass *klass, void *data)
773 {
774     DeviceClass *dc = DEVICE_CLASS(klass);
775     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
776 
777     k->init = mv88w8618_pic_init;
778     dc->reset = mv88w8618_pic_reset;
779     dc->vmsd = &mv88w8618_pic_vmsd;
780 }
781 
782 static const TypeInfo mv88w8618_pic_info = {
783     .name          = TYPE_MV88W8618_PIC,
784     .parent        = TYPE_SYS_BUS_DEVICE,
785     .instance_size = sizeof(mv88w8618_pic_state),
786     .class_init    = mv88w8618_pic_class_init,
787 };
788 
789 /* PIT register offsets */
790 #define MP_PIT_TIMER1_LENGTH    0x00
791 /* ... */
792 #define MP_PIT_TIMER4_LENGTH    0x0C
793 #define MP_PIT_CONTROL          0x10
794 #define MP_PIT_TIMER1_VALUE     0x14
795 /* ... */
796 #define MP_PIT_TIMER4_VALUE     0x20
797 #define MP_BOARD_RESET          0x34
798 
799 /* Magic board reset value (probably some watchdog behind it) */
800 #define MP_BOARD_RESET_MAGIC    0x10000
801 
802 typedef struct mv88w8618_timer_state {
803     ptimer_state *ptimer;
804     uint32_t limit;
805     int freq;
806     qemu_irq irq;
807 } mv88w8618_timer_state;
808 
809 #define TYPE_MV88W8618_PIT "mv88w8618_pit"
810 #define MV88W8618_PIT(obj) \
811     OBJECT_CHECK(mv88w8618_pit_state, (obj), TYPE_MV88W8618_PIT)
812 
813 typedef struct mv88w8618_pit_state {
814     /*< private >*/
815     SysBusDevice parent_obj;
816     /*< public >*/
817 
818     MemoryRegion iomem;
819     mv88w8618_timer_state timer[4];
820 } mv88w8618_pit_state;
821 
822 static void mv88w8618_timer_tick(void *opaque)
823 {
824     mv88w8618_timer_state *s = opaque;
825 
826     qemu_irq_raise(s->irq);
827 }
828 
829 static void mv88w8618_timer_init(SysBusDevice *dev, mv88w8618_timer_state *s,
830                                  uint32_t freq)
831 {
832     QEMUBH *bh;
833 
834     sysbus_init_irq(dev, &s->irq);
835     s->freq = freq;
836 
837     bh = qemu_bh_new(mv88w8618_timer_tick, s);
838     s->ptimer = ptimer_init(bh);
839 }
840 
841 static uint64_t mv88w8618_pit_read(void *opaque, hwaddr offset,
842                                    unsigned size)
843 {
844     mv88w8618_pit_state *s = opaque;
845     mv88w8618_timer_state *t;
846 
847     switch (offset) {
848     case MP_PIT_TIMER1_VALUE ... MP_PIT_TIMER4_VALUE:
849         t = &s->timer[(offset-MP_PIT_TIMER1_VALUE) >> 2];
850         return ptimer_get_count(t->ptimer);
851 
852     default:
853         return 0;
854     }
855 }
856 
857 static void mv88w8618_pit_write(void *opaque, hwaddr offset,
858                                 uint64_t value, unsigned size)
859 {
860     mv88w8618_pit_state *s = opaque;
861     mv88w8618_timer_state *t;
862     int i;
863 
864     switch (offset) {
865     case MP_PIT_TIMER1_LENGTH ... MP_PIT_TIMER4_LENGTH:
866         t = &s->timer[offset >> 2];
867         t->limit = value;
868         if (t->limit > 0) {
869             ptimer_set_limit(t->ptimer, t->limit, 1);
870         } else {
871             ptimer_stop(t->ptimer);
872         }
873         break;
874 
875     case MP_PIT_CONTROL:
876         for (i = 0; i < 4; i++) {
877             t = &s->timer[i];
878             if (value & 0xf && t->limit > 0) {
879                 ptimer_set_limit(t->ptimer, t->limit, 0);
880                 ptimer_set_freq(t->ptimer, t->freq);
881                 ptimer_run(t->ptimer, 0);
882             } else {
883                 ptimer_stop(t->ptimer);
884             }
885             value >>= 4;
886         }
887         break;
888 
889     case MP_BOARD_RESET:
890         if (value == MP_BOARD_RESET_MAGIC) {
891             qemu_system_reset_request();
892         }
893         break;
894     }
895 }
896 
897 static void mv88w8618_pit_reset(DeviceState *d)
898 {
899     mv88w8618_pit_state *s = MV88W8618_PIT(d);
900     int i;
901 
902     for (i = 0; i < 4; i++) {
903         ptimer_stop(s->timer[i].ptimer);
904         s->timer[i].limit = 0;
905     }
906 }
907 
908 static const MemoryRegionOps mv88w8618_pit_ops = {
909     .read = mv88w8618_pit_read,
910     .write = mv88w8618_pit_write,
911     .endianness = DEVICE_NATIVE_ENDIAN,
912 };
913 
914 static int mv88w8618_pit_init(SysBusDevice *dev)
915 {
916     mv88w8618_pit_state *s = MV88W8618_PIT(dev);
917     int i;
918 
919     /* Letting them all run at 1 MHz is likely just a pragmatic
920      * simplification. */
921     for (i = 0; i < 4; i++) {
922         mv88w8618_timer_init(dev, &s->timer[i], 1000000);
923     }
924 
925     memory_region_init_io(&s->iomem, OBJECT(s), &mv88w8618_pit_ops, s,
926                           "musicpal-pit", MP_PIT_SIZE);
927     sysbus_init_mmio(dev, &s->iomem);
928     return 0;
929 }
930 
931 static const VMStateDescription mv88w8618_timer_vmsd = {
932     .name = "timer",
933     .version_id = 1,
934     .minimum_version_id = 1,
935     .fields = (VMStateField[]) {
936         VMSTATE_PTIMER(ptimer, mv88w8618_timer_state),
937         VMSTATE_UINT32(limit, mv88w8618_timer_state),
938         VMSTATE_END_OF_LIST()
939     }
940 };
941 
942 static const VMStateDescription mv88w8618_pit_vmsd = {
943     .name = "mv88w8618_pit",
944     .version_id = 1,
945     .minimum_version_id = 1,
946     .fields = (VMStateField[]) {
947         VMSTATE_STRUCT_ARRAY(timer, mv88w8618_pit_state, 4, 1,
948                              mv88w8618_timer_vmsd, mv88w8618_timer_state),
949         VMSTATE_END_OF_LIST()
950     }
951 };
952 
953 static void mv88w8618_pit_class_init(ObjectClass *klass, void *data)
954 {
955     DeviceClass *dc = DEVICE_CLASS(klass);
956     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
957 
958     k->init = mv88w8618_pit_init;
959     dc->reset = mv88w8618_pit_reset;
960     dc->vmsd = &mv88w8618_pit_vmsd;
961 }
962 
963 static const TypeInfo mv88w8618_pit_info = {
964     .name          = TYPE_MV88W8618_PIT,
965     .parent        = TYPE_SYS_BUS_DEVICE,
966     .instance_size = sizeof(mv88w8618_pit_state),
967     .class_init    = mv88w8618_pit_class_init,
968 };
969 
970 /* Flash config register offsets */
971 #define MP_FLASHCFG_CFGR0    0x04
972 
973 #define TYPE_MV88W8618_FLASHCFG "mv88w8618_flashcfg"
974 #define MV88W8618_FLASHCFG(obj) \
975     OBJECT_CHECK(mv88w8618_flashcfg_state, (obj), TYPE_MV88W8618_FLASHCFG)
976 
977 typedef struct mv88w8618_flashcfg_state {
978     /*< private >*/
979     SysBusDevice parent_obj;
980     /*< public >*/
981 
982     MemoryRegion iomem;
983     uint32_t cfgr0;
984 } mv88w8618_flashcfg_state;
985 
986 static uint64_t mv88w8618_flashcfg_read(void *opaque,
987                                         hwaddr offset,
988                                         unsigned size)
989 {
990     mv88w8618_flashcfg_state *s = opaque;
991 
992     switch (offset) {
993     case MP_FLASHCFG_CFGR0:
994         return s->cfgr0;
995 
996     default:
997         return 0;
998     }
999 }
1000 
1001 static void mv88w8618_flashcfg_write(void *opaque, hwaddr offset,
1002                                      uint64_t value, unsigned size)
1003 {
1004     mv88w8618_flashcfg_state *s = opaque;
1005 
1006     switch (offset) {
1007     case MP_FLASHCFG_CFGR0:
1008         s->cfgr0 = value;
1009         break;
1010     }
1011 }
1012 
1013 static const MemoryRegionOps mv88w8618_flashcfg_ops = {
1014     .read = mv88w8618_flashcfg_read,
1015     .write = mv88w8618_flashcfg_write,
1016     .endianness = DEVICE_NATIVE_ENDIAN,
1017 };
1018 
1019 static int mv88w8618_flashcfg_init(SysBusDevice *dev)
1020 {
1021     mv88w8618_flashcfg_state *s = MV88W8618_FLASHCFG(dev);
1022 
1023     s->cfgr0 = 0xfffe4285; /* Default as set by U-Boot for 8 MB flash */
1024     memory_region_init_io(&s->iomem, OBJECT(s), &mv88w8618_flashcfg_ops, s,
1025                           "musicpal-flashcfg", MP_FLASHCFG_SIZE);
1026     sysbus_init_mmio(dev, &s->iomem);
1027     return 0;
1028 }
1029 
1030 static const VMStateDescription mv88w8618_flashcfg_vmsd = {
1031     .name = "mv88w8618_flashcfg",
1032     .version_id = 1,
1033     .minimum_version_id = 1,
1034     .fields = (VMStateField[]) {
1035         VMSTATE_UINT32(cfgr0, mv88w8618_flashcfg_state),
1036         VMSTATE_END_OF_LIST()
1037     }
1038 };
1039 
1040 static void mv88w8618_flashcfg_class_init(ObjectClass *klass, void *data)
1041 {
1042     DeviceClass *dc = DEVICE_CLASS(klass);
1043     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
1044 
1045     k->init = mv88w8618_flashcfg_init;
1046     dc->vmsd = &mv88w8618_flashcfg_vmsd;
1047 }
1048 
1049 static const TypeInfo mv88w8618_flashcfg_info = {
1050     .name          = TYPE_MV88W8618_FLASHCFG,
1051     .parent        = TYPE_SYS_BUS_DEVICE,
1052     .instance_size = sizeof(mv88w8618_flashcfg_state),
1053     .class_init    = mv88w8618_flashcfg_class_init,
1054 };
1055 
1056 /* Misc register offsets */
1057 #define MP_MISC_BOARD_REVISION  0x18
1058 
1059 #define MP_BOARD_REVISION       0x31
1060 
1061 typedef struct {
1062     SysBusDevice parent_obj;
1063     MemoryRegion iomem;
1064 } MusicPalMiscState;
1065 
1066 #define TYPE_MUSICPAL_MISC "musicpal-misc"
1067 #define MUSICPAL_MISC(obj) \
1068      OBJECT_CHECK(MusicPalMiscState, (obj), TYPE_MUSICPAL_MISC)
1069 
1070 static uint64_t musicpal_misc_read(void *opaque, hwaddr offset,
1071                                    unsigned size)
1072 {
1073     switch (offset) {
1074     case MP_MISC_BOARD_REVISION:
1075         return MP_BOARD_REVISION;
1076 
1077     default:
1078         return 0;
1079     }
1080 }
1081 
1082 static void musicpal_misc_write(void *opaque, hwaddr offset,
1083                                 uint64_t value, unsigned size)
1084 {
1085 }
1086 
1087 static const MemoryRegionOps musicpal_misc_ops = {
1088     .read = musicpal_misc_read,
1089     .write = musicpal_misc_write,
1090     .endianness = DEVICE_NATIVE_ENDIAN,
1091 };
1092 
1093 static void musicpal_misc_init(Object *obj)
1094 {
1095     SysBusDevice *sd = SYS_BUS_DEVICE(obj);
1096     MusicPalMiscState *s = MUSICPAL_MISC(obj);
1097 
1098     memory_region_init_io(&s->iomem, OBJECT(s), &musicpal_misc_ops, NULL,
1099                           "musicpal-misc", MP_MISC_SIZE);
1100     sysbus_init_mmio(sd, &s->iomem);
1101 }
1102 
1103 static const TypeInfo musicpal_misc_info = {
1104     .name = TYPE_MUSICPAL_MISC,
1105     .parent = TYPE_SYS_BUS_DEVICE,
1106     .instance_init = musicpal_misc_init,
1107     .instance_size = sizeof(MusicPalMiscState),
1108 };
1109 
1110 /* WLAN register offsets */
1111 #define MP_WLAN_MAGIC1          0x11c
1112 #define MP_WLAN_MAGIC2          0x124
1113 
1114 static uint64_t mv88w8618_wlan_read(void *opaque, hwaddr offset,
1115                                     unsigned size)
1116 {
1117     switch (offset) {
1118     /* Workaround to allow loading the binary-only wlandrv.ko crap
1119      * from the original Freecom firmware. */
1120     case MP_WLAN_MAGIC1:
1121         return ~3;
1122     case MP_WLAN_MAGIC2:
1123         return -1;
1124 
1125     default:
1126         return 0;
1127     }
1128 }
1129 
1130 static void mv88w8618_wlan_write(void *opaque, hwaddr offset,
1131                                  uint64_t value, unsigned size)
1132 {
1133 }
1134 
1135 static const MemoryRegionOps mv88w8618_wlan_ops = {
1136     .read = mv88w8618_wlan_read,
1137     .write =mv88w8618_wlan_write,
1138     .endianness = DEVICE_NATIVE_ENDIAN,
1139 };
1140 
1141 static int mv88w8618_wlan_init(SysBusDevice *dev)
1142 {
1143     MemoryRegion *iomem = g_new(MemoryRegion, 1);
1144 
1145     memory_region_init_io(iomem, OBJECT(dev), &mv88w8618_wlan_ops, NULL,
1146                           "musicpal-wlan", MP_WLAN_SIZE);
1147     sysbus_init_mmio(dev, iomem);
1148     return 0;
1149 }
1150 
1151 /* GPIO register offsets */
1152 #define MP_GPIO_OE_LO           0x008
1153 #define MP_GPIO_OUT_LO          0x00c
1154 #define MP_GPIO_IN_LO           0x010
1155 #define MP_GPIO_IER_LO          0x014
1156 #define MP_GPIO_IMR_LO          0x018
1157 #define MP_GPIO_ISR_LO          0x020
1158 #define MP_GPIO_OE_HI           0x508
1159 #define MP_GPIO_OUT_HI          0x50c
1160 #define MP_GPIO_IN_HI           0x510
1161 #define MP_GPIO_IER_HI          0x514
1162 #define MP_GPIO_IMR_HI          0x518
1163 #define MP_GPIO_ISR_HI          0x520
1164 
1165 /* GPIO bits & masks */
1166 #define MP_GPIO_LCD_BRIGHTNESS  0x00070000
1167 #define MP_GPIO_I2C_DATA_BIT    29
1168 #define MP_GPIO_I2C_CLOCK_BIT   30
1169 
1170 /* LCD brightness bits in GPIO_OE_HI */
1171 #define MP_OE_LCD_BRIGHTNESS    0x0007
1172 
1173 #define TYPE_MUSICPAL_GPIO "musicpal_gpio"
1174 #define MUSICPAL_GPIO(obj) \
1175     OBJECT_CHECK(musicpal_gpio_state, (obj), TYPE_MUSICPAL_GPIO)
1176 
1177 typedef struct musicpal_gpio_state {
1178     /*< private >*/
1179     SysBusDevice parent_obj;
1180     /*< public >*/
1181 
1182     MemoryRegion iomem;
1183     uint32_t lcd_brightness;
1184     uint32_t out_state;
1185     uint32_t in_state;
1186     uint32_t ier;
1187     uint32_t imr;
1188     uint32_t isr;
1189     qemu_irq irq;
1190     qemu_irq out[5]; /* 3 brightness out + 2 lcd (data and clock ) */
1191 } musicpal_gpio_state;
1192 
1193 static void musicpal_gpio_brightness_update(musicpal_gpio_state *s) {
1194     int i;
1195     uint32_t brightness;
1196 
1197     /* compute brightness ratio */
1198     switch (s->lcd_brightness) {
1199     case 0x00000007:
1200         brightness = 0;
1201         break;
1202 
1203     case 0x00020000:
1204         brightness = 1;
1205         break;
1206 
1207     case 0x00020001:
1208         brightness = 2;
1209         break;
1210 
1211     case 0x00040000:
1212         brightness = 3;
1213         break;
1214 
1215     case 0x00010006:
1216         brightness = 4;
1217         break;
1218 
1219     case 0x00020005:
1220         brightness = 5;
1221         break;
1222 
1223     case 0x00040003:
1224         brightness = 6;
1225         break;
1226 
1227     case 0x00030004:
1228     default:
1229         brightness = 7;
1230     }
1231 
1232     /* set lcd brightness GPIOs  */
1233     for (i = 0; i <= 2; i++) {
1234         qemu_set_irq(s->out[i], (brightness >> i) & 1);
1235     }
1236 }
1237 
1238 static void musicpal_gpio_pin_event(void *opaque, int pin, int level)
1239 {
1240     musicpal_gpio_state *s = opaque;
1241     uint32_t mask = 1 << pin;
1242     uint32_t delta = level << pin;
1243     uint32_t old = s->in_state & mask;
1244 
1245     s->in_state &= ~mask;
1246     s->in_state |= delta;
1247 
1248     if ((old ^ delta) &&
1249         ((level && (s->imr & mask)) || (!level && (s->ier & mask)))) {
1250         s->isr = mask;
1251         qemu_irq_raise(s->irq);
1252     }
1253 }
1254 
1255 static uint64_t musicpal_gpio_read(void *opaque, hwaddr offset,
1256                                    unsigned size)
1257 {
1258     musicpal_gpio_state *s = opaque;
1259 
1260     switch (offset) {
1261     case MP_GPIO_OE_HI: /* used for LCD brightness control */
1262         return s->lcd_brightness & MP_OE_LCD_BRIGHTNESS;
1263 
1264     case MP_GPIO_OUT_LO:
1265         return s->out_state & 0xFFFF;
1266     case MP_GPIO_OUT_HI:
1267         return s->out_state >> 16;
1268 
1269     case MP_GPIO_IN_LO:
1270         return s->in_state & 0xFFFF;
1271     case MP_GPIO_IN_HI:
1272         return s->in_state >> 16;
1273 
1274     case MP_GPIO_IER_LO:
1275         return s->ier & 0xFFFF;
1276     case MP_GPIO_IER_HI:
1277         return s->ier >> 16;
1278 
1279     case MP_GPIO_IMR_LO:
1280         return s->imr & 0xFFFF;
1281     case MP_GPIO_IMR_HI:
1282         return s->imr >> 16;
1283 
1284     case MP_GPIO_ISR_LO:
1285         return s->isr & 0xFFFF;
1286     case MP_GPIO_ISR_HI:
1287         return s->isr >> 16;
1288 
1289     default:
1290         return 0;
1291     }
1292 }
1293 
1294 static void musicpal_gpio_write(void *opaque, hwaddr offset,
1295                                 uint64_t value, unsigned size)
1296 {
1297     musicpal_gpio_state *s = opaque;
1298     switch (offset) {
1299     case MP_GPIO_OE_HI: /* used for LCD brightness control */
1300         s->lcd_brightness = (s->lcd_brightness & MP_GPIO_LCD_BRIGHTNESS) |
1301                          (value & MP_OE_LCD_BRIGHTNESS);
1302         musicpal_gpio_brightness_update(s);
1303         break;
1304 
1305     case MP_GPIO_OUT_LO:
1306         s->out_state = (s->out_state & 0xFFFF0000) | (value & 0xFFFF);
1307         break;
1308     case MP_GPIO_OUT_HI:
1309         s->out_state = (s->out_state & 0xFFFF) | (value << 16);
1310         s->lcd_brightness = (s->lcd_brightness & 0xFFFF) |
1311                             (s->out_state & MP_GPIO_LCD_BRIGHTNESS);
1312         musicpal_gpio_brightness_update(s);
1313         qemu_set_irq(s->out[3], (s->out_state >> MP_GPIO_I2C_DATA_BIT) & 1);
1314         qemu_set_irq(s->out[4], (s->out_state >> MP_GPIO_I2C_CLOCK_BIT) & 1);
1315         break;
1316 
1317     case MP_GPIO_IER_LO:
1318         s->ier = (s->ier & 0xFFFF0000) | (value & 0xFFFF);
1319         break;
1320     case MP_GPIO_IER_HI:
1321         s->ier = (s->ier & 0xFFFF) | (value << 16);
1322         break;
1323 
1324     case MP_GPIO_IMR_LO:
1325         s->imr = (s->imr & 0xFFFF0000) | (value & 0xFFFF);
1326         break;
1327     case MP_GPIO_IMR_HI:
1328         s->imr = (s->imr & 0xFFFF) | (value << 16);
1329         break;
1330     }
1331 }
1332 
1333 static const MemoryRegionOps musicpal_gpio_ops = {
1334     .read = musicpal_gpio_read,
1335     .write = musicpal_gpio_write,
1336     .endianness = DEVICE_NATIVE_ENDIAN,
1337 };
1338 
1339 static void musicpal_gpio_reset(DeviceState *d)
1340 {
1341     musicpal_gpio_state *s = MUSICPAL_GPIO(d);
1342 
1343     s->lcd_brightness = 0;
1344     s->out_state = 0;
1345     s->in_state = 0xffffffff;
1346     s->ier = 0;
1347     s->imr = 0;
1348     s->isr = 0;
1349 }
1350 
1351 static int musicpal_gpio_init(SysBusDevice *sbd)
1352 {
1353     DeviceState *dev = DEVICE(sbd);
1354     musicpal_gpio_state *s = MUSICPAL_GPIO(dev);
1355 
1356     sysbus_init_irq(sbd, &s->irq);
1357 
1358     memory_region_init_io(&s->iomem, OBJECT(s), &musicpal_gpio_ops, s,
1359                           "musicpal-gpio", MP_GPIO_SIZE);
1360     sysbus_init_mmio(sbd, &s->iomem);
1361 
1362     qdev_init_gpio_out(dev, s->out, ARRAY_SIZE(s->out));
1363 
1364     qdev_init_gpio_in(dev, musicpal_gpio_pin_event, 32);
1365 
1366     return 0;
1367 }
1368 
1369 static const VMStateDescription musicpal_gpio_vmsd = {
1370     .name = "musicpal_gpio",
1371     .version_id = 1,
1372     .minimum_version_id = 1,
1373     .fields = (VMStateField[]) {
1374         VMSTATE_UINT32(lcd_brightness, musicpal_gpio_state),
1375         VMSTATE_UINT32(out_state, musicpal_gpio_state),
1376         VMSTATE_UINT32(in_state, musicpal_gpio_state),
1377         VMSTATE_UINT32(ier, musicpal_gpio_state),
1378         VMSTATE_UINT32(imr, musicpal_gpio_state),
1379         VMSTATE_UINT32(isr, musicpal_gpio_state),
1380         VMSTATE_END_OF_LIST()
1381     }
1382 };
1383 
1384 static void musicpal_gpio_class_init(ObjectClass *klass, void *data)
1385 {
1386     DeviceClass *dc = DEVICE_CLASS(klass);
1387     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
1388 
1389     k->init = musicpal_gpio_init;
1390     dc->reset = musicpal_gpio_reset;
1391     dc->vmsd = &musicpal_gpio_vmsd;
1392 }
1393 
1394 static const TypeInfo musicpal_gpio_info = {
1395     .name          = TYPE_MUSICPAL_GPIO,
1396     .parent        = TYPE_SYS_BUS_DEVICE,
1397     .instance_size = sizeof(musicpal_gpio_state),
1398     .class_init    = musicpal_gpio_class_init,
1399 };
1400 
1401 /* Keyboard codes & masks */
1402 #define KEY_RELEASED            0x80
1403 #define KEY_CODE                0x7f
1404 
1405 #define KEYCODE_TAB             0x0f
1406 #define KEYCODE_ENTER           0x1c
1407 #define KEYCODE_F               0x21
1408 #define KEYCODE_M               0x32
1409 
1410 #define KEYCODE_EXTENDED        0xe0
1411 #define KEYCODE_UP              0x48
1412 #define KEYCODE_DOWN            0x50
1413 #define KEYCODE_LEFT            0x4b
1414 #define KEYCODE_RIGHT           0x4d
1415 
1416 #define MP_KEY_WHEEL_VOL       (1 << 0)
1417 #define MP_KEY_WHEEL_VOL_INV   (1 << 1)
1418 #define MP_KEY_WHEEL_NAV       (1 << 2)
1419 #define MP_KEY_WHEEL_NAV_INV   (1 << 3)
1420 #define MP_KEY_BTN_FAVORITS    (1 << 4)
1421 #define MP_KEY_BTN_MENU        (1 << 5)
1422 #define MP_KEY_BTN_VOLUME      (1 << 6)
1423 #define MP_KEY_BTN_NAVIGATION  (1 << 7)
1424 
1425 #define TYPE_MUSICPAL_KEY "musicpal_key"
1426 #define MUSICPAL_KEY(obj) \
1427     OBJECT_CHECK(musicpal_key_state, (obj), TYPE_MUSICPAL_KEY)
1428 
1429 typedef struct musicpal_key_state {
1430     /*< private >*/
1431     SysBusDevice parent_obj;
1432     /*< public >*/
1433 
1434     MemoryRegion iomem;
1435     uint32_t kbd_extended;
1436     uint32_t pressed_keys;
1437     qemu_irq out[8];
1438 } musicpal_key_state;
1439 
1440 static void musicpal_key_event(void *opaque, int keycode)
1441 {
1442     musicpal_key_state *s = opaque;
1443     uint32_t event = 0;
1444     int i;
1445 
1446     if (keycode == KEYCODE_EXTENDED) {
1447         s->kbd_extended = 1;
1448         return;
1449     }
1450 
1451     if (s->kbd_extended) {
1452         switch (keycode & KEY_CODE) {
1453         case KEYCODE_UP:
1454             event = MP_KEY_WHEEL_NAV | MP_KEY_WHEEL_NAV_INV;
1455             break;
1456 
1457         case KEYCODE_DOWN:
1458             event = MP_KEY_WHEEL_NAV;
1459             break;
1460 
1461         case KEYCODE_LEFT:
1462             event = MP_KEY_WHEEL_VOL | MP_KEY_WHEEL_VOL_INV;
1463             break;
1464 
1465         case KEYCODE_RIGHT:
1466             event = MP_KEY_WHEEL_VOL;
1467             break;
1468         }
1469     } else {
1470         switch (keycode & KEY_CODE) {
1471         case KEYCODE_F:
1472             event = MP_KEY_BTN_FAVORITS;
1473             break;
1474 
1475         case KEYCODE_TAB:
1476             event = MP_KEY_BTN_VOLUME;
1477             break;
1478 
1479         case KEYCODE_ENTER:
1480             event = MP_KEY_BTN_NAVIGATION;
1481             break;
1482 
1483         case KEYCODE_M:
1484             event = MP_KEY_BTN_MENU;
1485             break;
1486         }
1487         /* Do not repeat already pressed buttons */
1488         if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
1489             event = 0;
1490         }
1491     }
1492 
1493     if (event) {
1494         /* Raise GPIO pin first if repeating a key */
1495         if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
1496             for (i = 0; i <= 7; i++) {
1497                 if (event & (1 << i)) {
1498                     qemu_set_irq(s->out[i], 1);
1499                 }
1500             }
1501         }
1502         for (i = 0; i <= 7; i++) {
1503             if (event & (1 << i)) {
1504                 qemu_set_irq(s->out[i], !!(keycode & KEY_RELEASED));
1505             }
1506         }
1507         if (keycode & KEY_RELEASED) {
1508             s->pressed_keys &= ~event;
1509         } else {
1510             s->pressed_keys |= event;
1511         }
1512     }
1513 
1514     s->kbd_extended = 0;
1515 }
1516 
1517 static int musicpal_key_init(SysBusDevice *sbd)
1518 {
1519     DeviceState *dev = DEVICE(sbd);
1520     musicpal_key_state *s = MUSICPAL_KEY(dev);
1521 
1522     memory_region_init(&s->iomem, OBJECT(s), "dummy", 0);
1523     sysbus_init_mmio(sbd, &s->iomem);
1524 
1525     s->kbd_extended = 0;
1526     s->pressed_keys = 0;
1527 
1528     qdev_init_gpio_out(dev, s->out, ARRAY_SIZE(s->out));
1529 
1530     qemu_add_kbd_event_handler(musicpal_key_event, s);
1531 
1532     return 0;
1533 }
1534 
1535 static const VMStateDescription musicpal_key_vmsd = {
1536     .name = "musicpal_key",
1537     .version_id = 1,
1538     .minimum_version_id = 1,
1539     .fields = (VMStateField[]) {
1540         VMSTATE_UINT32(kbd_extended, musicpal_key_state),
1541         VMSTATE_UINT32(pressed_keys, musicpal_key_state),
1542         VMSTATE_END_OF_LIST()
1543     }
1544 };
1545 
1546 static void musicpal_key_class_init(ObjectClass *klass, void *data)
1547 {
1548     DeviceClass *dc = DEVICE_CLASS(klass);
1549     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
1550 
1551     k->init = musicpal_key_init;
1552     dc->vmsd = &musicpal_key_vmsd;
1553 }
1554 
1555 static const TypeInfo musicpal_key_info = {
1556     .name          = TYPE_MUSICPAL_KEY,
1557     .parent        = TYPE_SYS_BUS_DEVICE,
1558     .instance_size = sizeof(musicpal_key_state),
1559     .class_init    = musicpal_key_class_init,
1560 };
1561 
1562 static struct arm_boot_info musicpal_binfo = {
1563     .loader_start = 0x0,
1564     .board_id = 0x20e,
1565 };
1566 
1567 static void musicpal_init(MachineState *machine)
1568 {
1569     const char *cpu_model = machine->cpu_model;
1570     const char *kernel_filename = machine->kernel_filename;
1571     const char *kernel_cmdline = machine->kernel_cmdline;
1572     const char *initrd_filename = machine->initrd_filename;
1573     ARMCPU *cpu;
1574     qemu_irq pic[32];
1575     DeviceState *dev;
1576     DeviceState *i2c_dev;
1577     DeviceState *lcd_dev;
1578     DeviceState *key_dev;
1579     DeviceState *wm8750_dev;
1580     SysBusDevice *s;
1581     I2CBus *i2c;
1582     int i;
1583     unsigned long flash_size;
1584     DriveInfo *dinfo;
1585     MemoryRegion *address_space_mem = get_system_memory();
1586     MemoryRegion *ram = g_new(MemoryRegion, 1);
1587     MemoryRegion *sram = g_new(MemoryRegion, 1);
1588 
1589     if (!cpu_model) {
1590         cpu_model = "arm926";
1591     }
1592     cpu = cpu_arm_init(cpu_model);
1593     if (!cpu) {
1594         fprintf(stderr, "Unable to find CPU definition\n");
1595         exit(1);
1596     }
1597 
1598     /* For now we use a fixed - the original - RAM size */
1599     memory_region_allocate_system_memory(ram, NULL, "musicpal.ram",
1600                                          MP_RAM_DEFAULT_SIZE);
1601     memory_region_add_subregion(address_space_mem, 0, ram);
1602 
1603     memory_region_init_ram(sram, NULL, "musicpal.sram", MP_SRAM_SIZE,
1604                            &error_fatal);
1605     vmstate_register_ram_global(sram);
1606     memory_region_add_subregion(address_space_mem, MP_SRAM_BASE, sram);
1607 
1608     dev = sysbus_create_simple(TYPE_MV88W8618_PIC, MP_PIC_BASE,
1609                                qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
1610     for (i = 0; i < 32; i++) {
1611         pic[i] = qdev_get_gpio_in(dev, i);
1612     }
1613     sysbus_create_varargs(TYPE_MV88W8618_PIT, MP_PIT_BASE, pic[MP_TIMER1_IRQ],
1614                           pic[MP_TIMER2_IRQ], pic[MP_TIMER3_IRQ],
1615                           pic[MP_TIMER4_IRQ], NULL);
1616 
1617     if (serial_hds[0]) {
1618         serial_mm_init(address_space_mem, MP_UART1_BASE, 2, pic[MP_UART1_IRQ],
1619                        1825000, serial_hds[0], DEVICE_NATIVE_ENDIAN);
1620     }
1621     if (serial_hds[1]) {
1622         serial_mm_init(address_space_mem, MP_UART2_BASE, 2, pic[MP_UART2_IRQ],
1623                        1825000, serial_hds[1], DEVICE_NATIVE_ENDIAN);
1624     }
1625 
1626     /* Register flash */
1627     dinfo = drive_get(IF_PFLASH, 0, 0);
1628     if (dinfo) {
1629         BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
1630 
1631         flash_size = blk_getlength(blk);
1632         if (flash_size != 8*1024*1024 && flash_size != 16*1024*1024 &&
1633             flash_size != 32*1024*1024) {
1634             fprintf(stderr, "Invalid flash image size\n");
1635             exit(1);
1636         }
1637 
1638         /*
1639          * The original U-Boot accesses the flash at 0xFE000000 instead of
1640          * 0xFF800000 (if there is 8 MB flash). So remap flash access if the
1641          * image is smaller than 32 MB.
1642          */
1643 #ifdef TARGET_WORDS_BIGENDIAN
1644         pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL,
1645                               "musicpal.flash", flash_size,
1646                               blk, 0x10000, (flash_size + 0xffff) >> 16,
1647                               MP_FLASH_SIZE_MAX / flash_size,
1648                               2, 0x00BF, 0x236D, 0x0000, 0x0000,
1649                               0x5555, 0x2AAA, 1);
1650 #else
1651         pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL,
1652                               "musicpal.flash", flash_size,
1653                               blk, 0x10000, (flash_size + 0xffff) >> 16,
1654                               MP_FLASH_SIZE_MAX / flash_size,
1655                               2, 0x00BF, 0x236D, 0x0000, 0x0000,
1656                               0x5555, 0x2AAA, 0);
1657 #endif
1658 
1659     }
1660     sysbus_create_simple(TYPE_MV88W8618_FLASHCFG, MP_FLASHCFG_BASE, NULL);
1661 
1662     qemu_check_nic_model(&nd_table[0], "mv88w8618");
1663     dev = qdev_create(NULL, TYPE_MV88W8618_ETH);
1664     qdev_set_nic_properties(dev, &nd_table[0]);
1665     qdev_init_nofail(dev);
1666     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, MP_ETH_BASE);
1667     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[MP_ETH_IRQ]);
1668 
1669     sysbus_create_simple("mv88w8618_wlan", MP_WLAN_BASE, NULL);
1670 
1671     sysbus_create_simple(TYPE_MUSICPAL_MISC, MP_MISC_BASE, NULL);
1672 
1673     dev = sysbus_create_simple(TYPE_MUSICPAL_GPIO, MP_GPIO_BASE,
1674                                pic[MP_GPIO_IRQ]);
1675     i2c_dev = sysbus_create_simple("gpio_i2c", -1, NULL);
1676     i2c = (I2CBus *)qdev_get_child_bus(i2c_dev, "i2c");
1677 
1678     lcd_dev = sysbus_create_simple(TYPE_MUSICPAL_LCD, MP_LCD_BASE, NULL);
1679     key_dev = sysbus_create_simple(TYPE_MUSICPAL_KEY, -1, NULL);
1680 
1681     /* I2C read data */
1682     qdev_connect_gpio_out(i2c_dev, 0,
1683                           qdev_get_gpio_in(dev, MP_GPIO_I2C_DATA_BIT));
1684     /* I2C data */
1685     qdev_connect_gpio_out(dev, 3, qdev_get_gpio_in(i2c_dev, 0));
1686     /* I2C clock */
1687     qdev_connect_gpio_out(dev, 4, qdev_get_gpio_in(i2c_dev, 1));
1688 
1689     for (i = 0; i < 3; i++) {
1690         qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(lcd_dev, i));
1691     }
1692     for (i = 0; i < 4; i++) {
1693         qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 8));
1694     }
1695     for (i = 4; i < 8; i++) {
1696         qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 15));
1697     }
1698 
1699     wm8750_dev = i2c_create_slave(i2c, "wm8750", MP_WM_ADDR);
1700     dev = qdev_create(NULL, "mv88w8618_audio");
1701     s = SYS_BUS_DEVICE(dev);
1702     qdev_prop_set_ptr(dev, "wm8750", wm8750_dev);
1703     qdev_init_nofail(dev);
1704     sysbus_mmio_map(s, 0, MP_AUDIO_BASE);
1705     sysbus_connect_irq(s, 0, pic[MP_AUDIO_IRQ]);
1706 
1707     musicpal_binfo.ram_size = MP_RAM_DEFAULT_SIZE;
1708     musicpal_binfo.kernel_filename = kernel_filename;
1709     musicpal_binfo.kernel_cmdline = kernel_cmdline;
1710     musicpal_binfo.initrd_filename = initrd_filename;
1711     arm_load_kernel(cpu, &musicpal_binfo);
1712 }
1713 
1714 static void musicpal_machine_init(MachineClass *mc)
1715 {
1716     mc->desc = "Marvell 88w8618 / MusicPal (ARM926EJ-S)";
1717     mc->init = musicpal_init;
1718 }
1719 
1720 DEFINE_MACHINE("musicpal", musicpal_machine_init)
1721 
1722 static void mv88w8618_wlan_class_init(ObjectClass *klass, void *data)
1723 {
1724     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
1725 
1726     sdc->init = mv88w8618_wlan_init;
1727 }
1728 
1729 static const TypeInfo mv88w8618_wlan_info = {
1730     .name          = "mv88w8618_wlan",
1731     .parent        = TYPE_SYS_BUS_DEVICE,
1732     .instance_size = sizeof(SysBusDevice),
1733     .class_init    = mv88w8618_wlan_class_init,
1734 };
1735 
1736 static void musicpal_register_types(void)
1737 {
1738     type_register_static(&mv88w8618_pic_info);
1739     type_register_static(&mv88w8618_pit_info);
1740     type_register_static(&mv88w8618_flashcfg_info);
1741     type_register_static(&mv88w8618_eth_info);
1742     type_register_static(&mv88w8618_wlan_info);
1743     type_register_static(&musicpal_lcd_info);
1744     type_register_static(&musicpal_gpio_info);
1745     type_register_static(&musicpal_key_info);
1746     type_register_static(&musicpal_misc_info);
1747 }
1748 
1749 type_init(musicpal_register_types)
1750