xref: /openbmc/qemu/hw/arm/musicpal.c (revision f4f318b4)
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 "qemu/units.h"
14 #include "qapi/error.h"
15 #include "cpu.h"
16 #include "hw/sysbus.h"
17 #include "migration/vmstate.h"
18 #include "hw/arm/boot.h"
19 #include "net/net.h"
20 #include "sysemu/sysemu.h"
21 #include "hw/boards.h"
22 #include "hw/char/serial.h"
23 #include "qemu/timer.h"
24 #include "hw/ptimer.h"
25 #include "hw/qdev-properties.h"
26 #include "hw/block/flash.h"
27 #include "ui/console.h"
28 #include "hw/i2c/i2c.h"
29 #include "hw/i2c/bitbang_i2c.h"
30 #include "hw/irq.h"
31 #include "hw/or-irq.h"
32 #include "hw/audio/wm8750.h"
33 #include "sysemu/block-backend.h"
34 #include "sysemu/runstate.h"
35 #include "sysemu/dma.h"
36 #include "ui/pixel_ops.h"
37 #include "qemu/cutils.h"
38 #include "qom/object.h"
39 #include "hw/net/mv88w8618_eth.h"
40 #include "audio/audio.h"
41 #include "qemu/error-report.h"
42 #include "target/arm/cpu-qom.h"
43 
44 #define MP_MISC_BASE            0x80002000
45 #define MP_MISC_SIZE            0x00001000
46 
47 #define MP_ETH_BASE             0x80008000
48 
49 #define MP_WLAN_BASE            0x8000C000
50 #define MP_WLAN_SIZE            0x00000800
51 
52 #define MP_UART1_BASE           0x8000C840
53 #define MP_UART2_BASE           0x8000C940
54 
55 #define MP_GPIO_BASE            0x8000D000
56 #define MP_GPIO_SIZE            0x00001000
57 
58 #define MP_FLASHCFG_BASE        0x90006000
59 #define MP_FLASHCFG_SIZE        0x00001000
60 
61 #define MP_AUDIO_BASE           0x90007000
62 
63 #define MP_PIC_BASE             0x90008000
64 #define MP_PIC_SIZE             0x00001000
65 
66 #define MP_PIT_BASE             0x90009000
67 #define MP_PIT_SIZE             0x00001000
68 
69 #define MP_LCD_BASE             0x9000c000
70 #define MP_LCD_SIZE             0x00001000
71 
72 #define MP_SRAM_BASE            0xC0000000
73 #define MP_SRAM_SIZE            0x00020000
74 
75 #define MP_RAM_DEFAULT_SIZE     32*1024*1024
76 #define MP_FLASH_SIZE_MAX       32*1024*1024
77 
78 #define MP_TIMER1_IRQ           4
79 #define MP_TIMER2_IRQ           5
80 #define MP_TIMER3_IRQ           6
81 #define MP_TIMER4_IRQ           7
82 #define MP_EHCI_IRQ             8
83 #define MP_ETH_IRQ              9
84 #define MP_UART_SHARED_IRQ      11
85 #define MP_GPIO_IRQ             12
86 #define MP_RTC_IRQ              28
87 #define MP_AUDIO_IRQ            30
88 
89 /* Wolfson 8750 I2C address */
90 #define MP_WM_ADDR              0x1A
91 
92 /* LCD register offsets */
93 #define MP_LCD_IRQCTRL          0x180
94 #define MP_LCD_IRQSTAT          0x184
95 #define MP_LCD_SPICTRL          0x1ac
96 #define MP_LCD_INST             0x1bc
97 #define MP_LCD_DATA             0x1c0
98 
99 /* Mode magics */
100 #define MP_LCD_SPI_DATA         0x00100011
101 #define MP_LCD_SPI_CMD          0x00104011
102 #define MP_LCD_SPI_INVALID      0x00000000
103 
104 /* Commands */
105 #define MP_LCD_INST_SETPAGE0    0xB0
106 /* ... */
107 #define MP_LCD_INST_SETPAGE7    0xB7
108 
109 #define MP_LCD_TEXTCOLOR        0xe0e0ff /* RRGGBB */
110 
111 #define TYPE_MUSICPAL_LCD "musicpal_lcd"
112 OBJECT_DECLARE_SIMPLE_TYPE(musicpal_lcd_state, MUSICPAL_LCD)
113 
114 struct musicpal_lcd_state {
115     /*< private >*/
116     SysBusDevice parent_obj;
117     /*< public >*/
118 
119     MemoryRegion iomem;
120     uint32_t brightness;
121     uint32_t mode;
122     uint32_t irqctrl;
123     uint32_t page;
124     uint32_t page_off;
125     QemuConsole *con;
126     uint8_t video_ram[128*64/8];
127 };
128 
129 static uint8_t scale_lcd_color(musicpal_lcd_state *s, uint8_t col)
130 {
131     switch (s->brightness) {
132     case 7:
133         return col;
134     case 0:
135         return 0;
136     default:
137         return (col * s->brightness) / 7;
138     }
139 }
140 
141 static inline void set_lcd_pixel32(musicpal_lcd_state *s,
142                                    int x, int y, uint32_t col)
143 {
144     int dx, dy;
145     DisplaySurface *surface = qemu_console_surface(s->con);
146     uint32_t *pixel =
147         &((uint32_t *) surface_data(surface))[(y * 128 * 3 + x) * 3];
148 
149     for (dy = 0; dy < 3; dy++, pixel += 127 * 3) {
150         for (dx = 0; dx < 3; dx++, pixel++) {
151             *pixel = col;
152         }
153     }
154 }
155 
156 static void lcd_refresh(void *opaque)
157 {
158     musicpal_lcd_state *s = opaque;
159     int x, y, col;
160 
161     col = rgb_to_pixel32(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff),
162                          scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff),
163                          scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff));
164     for (x = 0; x < 128; x++) {
165         for (y = 0; y < 64; y++) {
166             if (s->video_ram[x + (y / 8) * 128] & (1 << (y % 8))) {
167                 set_lcd_pixel32(s, x, y, col);
168             } else {
169                 set_lcd_pixel32(s, x, y, 0);
170             }
171         }
172     }
173 
174     dpy_gfx_update(s->con, 0, 0, 128*3, 64*3);
175 }
176 
177 static void lcd_invalidate(void *opaque)
178 {
179 }
180 
181 static void musicpal_lcd_gpio_brightness_in(void *opaque, int irq, int level)
182 {
183     musicpal_lcd_state *s = opaque;
184     s->brightness &= ~(1 << irq);
185     s->brightness |= level << irq;
186 }
187 
188 static uint64_t musicpal_lcd_read(void *opaque, hwaddr offset,
189                                   unsigned size)
190 {
191     musicpal_lcd_state *s = opaque;
192 
193     switch (offset) {
194     case MP_LCD_IRQCTRL:
195         return s->irqctrl;
196 
197     default:
198         return 0;
199     }
200 }
201 
202 static void musicpal_lcd_write(void *opaque, hwaddr offset,
203                                uint64_t value, unsigned size)
204 {
205     musicpal_lcd_state *s = opaque;
206 
207     switch (offset) {
208     case MP_LCD_IRQCTRL:
209         s->irqctrl = value;
210         break;
211 
212     case MP_LCD_SPICTRL:
213         if (value == MP_LCD_SPI_DATA || value == MP_LCD_SPI_CMD) {
214             s->mode = value;
215         } else {
216             s->mode = MP_LCD_SPI_INVALID;
217         }
218         break;
219 
220     case MP_LCD_INST:
221         if (value >= MP_LCD_INST_SETPAGE0 && value <= MP_LCD_INST_SETPAGE7) {
222             s->page = value - MP_LCD_INST_SETPAGE0;
223             s->page_off = 0;
224         }
225         break;
226 
227     case MP_LCD_DATA:
228         if (s->mode == MP_LCD_SPI_CMD) {
229             if (value >= MP_LCD_INST_SETPAGE0 &&
230                 value <= MP_LCD_INST_SETPAGE7) {
231                 s->page = value - MP_LCD_INST_SETPAGE0;
232                 s->page_off = 0;
233             }
234         } else if (s->mode == MP_LCD_SPI_DATA) {
235             s->video_ram[s->page*128 + s->page_off] = value;
236             s->page_off = (s->page_off + 1) & 127;
237         }
238         break;
239     }
240 }
241 
242 static const MemoryRegionOps musicpal_lcd_ops = {
243     .read = musicpal_lcd_read,
244     .write = musicpal_lcd_write,
245     .endianness = DEVICE_NATIVE_ENDIAN,
246 };
247 
248 static const GraphicHwOps musicpal_gfx_ops = {
249     .invalidate  = lcd_invalidate,
250     .gfx_update  = lcd_refresh,
251 };
252 
253 static void musicpal_lcd_realize(DeviceState *dev, Error **errp)
254 {
255     musicpal_lcd_state *s = MUSICPAL_LCD(dev);
256     s->con = graphic_console_init(dev, 0, &musicpal_gfx_ops, s);
257     qemu_console_resize(s->con, 128 * 3, 64 * 3);
258 }
259 
260 static void musicpal_lcd_init(Object *obj)
261 {
262     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
263     DeviceState *dev = DEVICE(sbd);
264     musicpal_lcd_state *s = MUSICPAL_LCD(dev);
265 
266     s->brightness = 7;
267 
268     memory_region_init_io(&s->iomem, obj, &musicpal_lcd_ops, s,
269                           "musicpal-lcd", MP_LCD_SIZE);
270     sysbus_init_mmio(sbd, &s->iomem);
271 
272     qdev_init_gpio_in(dev, musicpal_lcd_gpio_brightness_in, 3);
273 }
274 
275 static const VMStateDescription musicpal_lcd_vmsd = {
276     .name = "musicpal_lcd",
277     .version_id = 1,
278     .minimum_version_id = 1,
279     .fields = (const VMStateField[]) {
280         VMSTATE_UINT32(brightness, musicpal_lcd_state),
281         VMSTATE_UINT32(mode, musicpal_lcd_state),
282         VMSTATE_UINT32(irqctrl, musicpal_lcd_state),
283         VMSTATE_UINT32(page, musicpal_lcd_state),
284         VMSTATE_UINT32(page_off, musicpal_lcd_state),
285         VMSTATE_BUFFER(video_ram, musicpal_lcd_state),
286         VMSTATE_END_OF_LIST()
287     }
288 };
289 
290 static void musicpal_lcd_class_init(ObjectClass *klass, void *data)
291 {
292     DeviceClass *dc = DEVICE_CLASS(klass);
293 
294     dc->vmsd = &musicpal_lcd_vmsd;
295     dc->realize = musicpal_lcd_realize;
296 }
297 
298 static const TypeInfo musicpal_lcd_info = {
299     .name          = TYPE_MUSICPAL_LCD,
300     .parent        = TYPE_SYS_BUS_DEVICE,
301     .instance_size = sizeof(musicpal_lcd_state),
302     .instance_init = musicpal_lcd_init,
303     .class_init    = musicpal_lcd_class_init,
304 };
305 
306 /* PIC register offsets */
307 #define MP_PIC_STATUS           0x00
308 #define MP_PIC_ENABLE_SET       0x08
309 #define MP_PIC_ENABLE_CLR       0x0C
310 
311 #define TYPE_MV88W8618_PIC "mv88w8618_pic"
312 OBJECT_DECLARE_SIMPLE_TYPE(mv88w8618_pic_state, MV88W8618_PIC)
313 
314 struct mv88w8618_pic_state {
315     /*< private >*/
316     SysBusDevice parent_obj;
317     /*< public >*/
318 
319     MemoryRegion iomem;
320     uint32_t level;
321     uint32_t enabled;
322     qemu_irq parent_irq;
323 };
324 
325 static void mv88w8618_pic_update(mv88w8618_pic_state *s)
326 {
327     qemu_set_irq(s->parent_irq, (s->level & s->enabled));
328 }
329 
330 static void mv88w8618_pic_set_irq(void *opaque, int irq, int level)
331 {
332     mv88w8618_pic_state *s = opaque;
333 
334     if (level) {
335         s->level |= 1 << irq;
336     } else {
337         s->level &= ~(1 << irq);
338     }
339     mv88w8618_pic_update(s);
340 }
341 
342 static uint64_t mv88w8618_pic_read(void *opaque, hwaddr offset,
343                                    unsigned size)
344 {
345     mv88w8618_pic_state *s = opaque;
346 
347     switch (offset) {
348     case MP_PIC_STATUS:
349         return s->level & s->enabled;
350 
351     default:
352         return 0;
353     }
354 }
355 
356 static void mv88w8618_pic_write(void *opaque, hwaddr offset,
357                                 uint64_t value, unsigned size)
358 {
359     mv88w8618_pic_state *s = opaque;
360 
361     switch (offset) {
362     case MP_PIC_ENABLE_SET:
363         s->enabled |= value;
364         break;
365 
366     case MP_PIC_ENABLE_CLR:
367         s->enabled &= ~value;
368         s->level &= ~value;
369         break;
370     }
371     mv88w8618_pic_update(s);
372 }
373 
374 static void mv88w8618_pic_reset(DeviceState *d)
375 {
376     mv88w8618_pic_state *s = MV88W8618_PIC(d);
377 
378     s->level = 0;
379     s->enabled = 0;
380 }
381 
382 static const MemoryRegionOps mv88w8618_pic_ops = {
383     .read = mv88w8618_pic_read,
384     .write = mv88w8618_pic_write,
385     .endianness = DEVICE_NATIVE_ENDIAN,
386 };
387 
388 static void mv88w8618_pic_init(Object *obj)
389 {
390     SysBusDevice *dev = SYS_BUS_DEVICE(obj);
391     mv88w8618_pic_state *s = MV88W8618_PIC(dev);
392 
393     qdev_init_gpio_in(DEVICE(dev), mv88w8618_pic_set_irq, 32);
394     sysbus_init_irq(dev, &s->parent_irq);
395     memory_region_init_io(&s->iomem, obj, &mv88w8618_pic_ops, s,
396                           "musicpal-pic", MP_PIC_SIZE);
397     sysbus_init_mmio(dev, &s->iomem);
398 }
399 
400 static const VMStateDescription mv88w8618_pic_vmsd = {
401     .name = "mv88w8618_pic",
402     .version_id = 1,
403     .minimum_version_id = 1,
404     .fields = (const VMStateField[]) {
405         VMSTATE_UINT32(level, mv88w8618_pic_state),
406         VMSTATE_UINT32(enabled, mv88w8618_pic_state),
407         VMSTATE_END_OF_LIST()
408     }
409 };
410 
411 static void mv88w8618_pic_class_init(ObjectClass *klass, void *data)
412 {
413     DeviceClass *dc = DEVICE_CLASS(klass);
414 
415     dc->reset = mv88w8618_pic_reset;
416     dc->vmsd = &mv88w8618_pic_vmsd;
417 }
418 
419 static const TypeInfo mv88w8618_pic_info = {
420     .name          = TYPE_MV88W8618_PIC,
421     .parent        = TYPE_SYS_BUS_DEVICE,
422     .instance_size = sizeof(mv88w8618_pic_state),
423     .instance_init = mv88w8618_pic_init,
424     .class_init    = mv88w8618_pic_class_init,
425 };
426 
427 /* PIT register offsets */
428 #define MP_PIT_TIMER1_LENGTH    0x00
429 /* ... */
430 #define MP_PIT_TIMER4_LENGTH    0x0C
431 #define MP_PIT_CONTROL          0x10
432 #define MP_PIT_TIMER1_VALUE     0x14
433 /* ... */
434 #define MP_PIT_TIMER4_VALUE     0x20
435 #define MP_BOARD_RESET          0x34
436 
437 /* Magic board reset value (probably some watchdog behind it) */
438 #define MP_BOARD_RESET_MAGIC    0x10000
439 
440 typedef struct mv88w8618_timer_state {
441     ptimer_state *ptimer;
442     uint32_t limit;
443     int freq;
444     qemu_irq irq;
445 } mv88w8618_timer_state;
446 
447 #define TYPE_MV88W8618_PIT "mv88w8618_pit"
448 OBJECT_DECLARE_SIMPLE_TYPE(mv88w8618_pit_state, MV88W8618_PIT)
449 
450 struct mv88w8618_pit_state {
451     /*< private >*/
452     SysBusDevice parent_obj;
453     /*< public >*/
454 
455     MemoryRegion iomem;
456     mv88w8618_timer_state timer[4];
457 };
458 
459 static void mv88w8618_timer_tick(void *opaque)
460 {
461     mv88w8618_timer_state *s = opaque;
462 
463     qemu_irq_raise(s->irq);
464 }
465 
466 static void mv88w8618_timer_init(SysBusDevice *dev, mv88w8618_timer_state *s,
467                                  uint32_t freq)
468 {
469     sysbus_init_irq(dev, &s->irq);
470     s->freq = freq;
471 
472     s->ptimer = ptimer_init(mv88w8618_timer_tick, s, PTIMER_POLICY_LEGACY);
473 }
474 
475 static uint64_t mv88w8618_pit_read(void *opaque, hwaddr offset,
476                                    unsigned size)
477 {
478     mv88w8618_pit_state *s = opaque;
479     mv88w8618_timer_state *t;
480 
481     switch (offset) {
482     case MP_PIT_TIMER1_VALUE ... MP_PIT_TIMER4_VALUE:
483         t = &s->timer[(offset-MP_PIT_TIMER1_VALUE) >> 2];
484         return ptimer_get_count(t->ptimer);
485 
486     default:
487         return 0;
488     }
489 }
490 
491 static void mv88w8618_pit_write(void *opaque, hwaddr offset,
492                                 uint64_t value, unsigned size)
493 {
494     mv88w8618_pit_state *s = opaque;
495     mv88w8618_timer_state *t;
496     int i;
497 
498     switch (offset) {
499     case MP_PIT_TIMER1_LENGTH ... MP_PIT_TIMER4_LENGTH:
500         t = &s->timer[offset >> 2];
501         t->limit = value;
502         ptimer_transaction_begin(t->ptimer);
503         if (t->limit > 0) {
504             ptimer_set_limit(t->ptimer, t->limit, 1);
505         } else {
506             ptimer_stop(t->ptimer);
507         }
508         ptimer_transaction_commit(t->ptimer);
509         break;
510 
511     case MP_PIT_CONTROL:
512         for (i = 0; i < 4; i++) {
513             t = &s->timer[i];
514             ptimer_transaction_begin(t->ptimer);
515             if (value & 0xf && t->limit > 0) {
516                 ptimer_set_limit(t->ptimer, t->limit, 0);
517                 ptimer_set_freq(t->ptimer, t->freq);
518                 ptimer_run(t->ptimer, 0);
519             } else {
520                 ptimer_stop(t->ptimer);
521             }
522             ptimer_transaction_commit(t->ptimer);
523             value >>= 4;
524         }
525         break;
526 
527     case MP_BOARD_RESET:
528         if (value == MP_BOARD_RESET_MAGIC) {
529             qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
530         }
531         break;
532     }
533 }
534 
535 static void mv88w8618_pit_reset(DeviceState *d)
536 {
537     mv88w8618_pit_state *s = MV88W8618_PIT(d);
538     int i;
539 
540     for (i = 0; i < 4; i++) {
541         mv88w8618_timer_state *t = &s->timer[i];
542         ptimer_transaction_begin(t->ptimer);
543         ptimer_stop(t->ptimer);
544         ptimer_transaction_commit(t->ptimer);
545         t->limit = 0;
546     }
547 }
548 
549 static const MemoryRegionOps mv88w8618_pit_ops = {
550     .read = mv88w8618_pit_read,
551     .write = mv88w8618_pit_write,
552     .endianness = DEVICE_NATIVE_ENDIAN,
553 };
554 
555 static void mv88w8618_pit_init(Object *obj)
556 {
557     SysBusDevice *dev = SYS_BUS_DEVICE(obj);
558     mv88w8618_pit_state *s = MV88W8618_PIT(dev);
559     int i;
560 
561     /* Letting them all run at 1 MHz is likely just a pragmatic
562      * simplification. */
563     for (i = 0; i < 4; i++) {
564         mv88w8618_timer_init(dev, &s->timer[i], 1000000);
565     }
566 
567     memory_region_init_io(&s->iomem, obj, &mv88w8618_pit_ops, s,
568                           "musicpal-pit", MP_PIT_SIZE);
569     sysbus_init_mmio(dev, &s->iomem);
570 }
571 
572 static void mv88w8618_pit_finalize(Object *obj)
573 {
574     SysBusDevice *dev = SYS_BUS_DEVICE(obj);
575     mv88w8618_pit_state *s = MV88W8618_PIT(dev);
576     int i;
577 
578     for (i = 0; i < 4; i++) {
579         ptimer_free(s->timer[i].ptimer);
580     }
581 }
582 
583 static const VMStateDescription mv88w8618_timer_vmsd = {
584     .name = "timer",
585     .version_id = 1,
586     .minimum_version_id = 1,
587     .fields = (const VMStateField[]) {
588         VMSTATE_PTIMER(ptimer, mv88w8618_timer_state),
589         VMSTATE_UINT32(limit, mv88w8618_timer_state),
590         VMSTATE_END_OF_LIST()
591     }
592 };
593 
594 static const VMStateDescription mv88w8618_pit_vmsd = {
595     .name = "mv88w8618_pit",
596     .version_id = 1,
597     .minimum_version_id = 1,
598     .fields = (const VMStateField[]) {
599         VMSTATE_STRUCT_ARRAY(timer, mv88w8618_pit_state, 4, 1,
600                              mv88w8618_timer_vmsd, mv88w8618_timer_state),
601         VMSTATE_END_OF_LIST()
602     }
603 };
604 
605 static void mv88w8618_pit_class_init(ObjectClass *klass, void *data)
606 {
607     DeviceClass *dc = DEVICE_CLASS(klass);
608 
609     dc->reset = mv88w8618_pit_reset;
610     dc->vmsd = &mv88w8618_pit_vmsd;
611 }
612 
613 static const TypeInfo mv88w8618_pit_info = {
614     .name          = TYPE_MV88W8618_PIT,
615     .parent        = TYPE_SYS_BUS_DEVICE,
616     .instance_size = sizeof(mv88w8618_pit_state),
617     .instance_init = mv88w8618_pit_init,
618     .instance_finalize = mv88w8618_pit_finalize,
619     .class_init    = mv88w8618_pit_class_init,
620 };
621 
622 /* Flash config register offsets */
623 #define MP_FLASHCFG_CFGR0    0x04
624 
625 #define TYPE_MV88W8618_FLASHCFG "mv88w8618_flashcfg"
626 OBJECT_DECLARE_SIMPLE_TYPE(mv88w8618_flashcfg_state, MV88W8618_FLASHCFG)
627 
628 struct mv88w8618_flashcfg_state {
629     /*< private >*/
630     SysBusDevice parent_obj;
631     /*< public >*/
632 
633     MemoryRegion iomem;
634     uint32_t cfgr0;
635 };
636 
637 static uint64_t mv88w8618_flashcfg_read(void *opaque,
638                                         hwaddr offset,
639                                         unsigned size)
640 {
641     mv88w8618_flashcfg_state *s = opaque;
642 
643     switch (offset) {
644     case MP_FLASHCFG_CFGR0:
645         return s->cfgr0;
646 
647     default:
648         return 0;
649     }
650 }
651 
652 static void mv88w8618_flashcfg_write(void *opaque, hwaddr offset,
653                                      uint64_t value, unsigned size)
654 {
655     mv88w8618_flashcfg_state *s = opaque;
656 
657     switch (offset) {
658     case MP_FLASHCFG_CFGR0:
659         s->cfgr0 = value;
660         break;
661     }
662 }
663 
664 static const MemoryRegionOps mv88w8618_flashcfg_ops = {
665     .read = mv88w8618_flashcfg_read,
666     .write = mv88w8618_flashcfg_write,
667     .endianness = DEVICE_NATIVE_ENDIAN,
668 };
669 
670 static void mv88w8618_flashcfg_init(Object *obj)
671 {
672     SysBusDevice *dev = SYS_BUS_DEVICE(obj);
673     mv88w8618_flashcfg_state *s = MV88W8618_FLASHCFG(dev);
674 
675     s->cfgr0 = 0xfffe4285; /* Default as set by U-Boot for 8 MB flash */
676     memory_region_init_io(&s->iomem, obj, &mv88w8618_flashcfg_ops, s,
677                           "musicpal-flashcfg", MP_FLASHCFG_SIZE);
678     sysbus_init_mmio(dev, &s->iomem);
679 }
680 
681 static const VMStateDescription mv88w8618_flashcfg_vmsd = {
682     .name = "mv88w8618_flashcfg",
683     .version_id = 1,
684     .minimum_version_id = 1,
685     .fields = (const VMStateField[]) {
686         VMSTATE_UINT32(cfgr0, mv88w8618_flashcfg_state),
687         VMSTATE_END_OF_LIST()
688     }
689 };
690 
691 static void mv88w8618_flashcfg_class_init(ObjectClass *klass, void *data)
692 {
693     DeviceClass *dc = DEVICE_CLASS(klass);
694 
695     dc->vmsd = &mv88w8618_flashcfg_vmsd;
696 }
697 
698 static const TypeInfo mv88w8618_flashcfg_info = {
699     .name          = TYPE_MV88W8618_FLASHCFG,
700     .parent        = TYPE_SYS_BUS_DEVICE,
701     .instance_size = sizeof(mv88w8618_flashcfg_state),
702     .instance_init = mv88w8618_flashcfg_init,
703     .class_init    = mv88w8618_flashcfg_class_init,
704 };
705 
706 /* Misc register offsets */
707 #define MP_MISC_BOARD_REVISION  0x18
708 
709 #define MP_BOARD_REVISION       0x31
710 
711 struct MusicPalMiscState {
712     SysBusDevice parent_obj;
713     MemoryRegion iomem;
714 };
715 
716 #define TYPE_MUSICPAL_MISC "musicpal-misc"
717 OBJECT_DECLARE_SIMPLE_TYPE(MusicPalMiscState, MUSICPAL_MISC)
718 
719 static uint64_t musicpal_misc_read(void *opaque, hwaddr offset,
720                                    unsigned size)
721 {
722     switch (offset) {
723     case MP_MISC_BOARD_REVISION:
724         return MP_BOARD_REVISION;
725 
726     default:
727         return 0;
728     }
729 }
730 
731 static void musicpal_misc_write(void *opaque, hwaddr offset,
732                                 uint64_t value, unsigned size)
733 {
734 }
735 
736 static const MemoryRegionOps musicpal_misc_ops = {
737     .read = musicpal_misc_read,
738     .write = musicpal_misc_write,
739     .endianness = DEVICE_NATIVE_ENDIAN,
740 };
741 
742 static void musicpal_misc_init(Object *obj)
743 {
744     SysBusDevice *sd = SYS_BUS_DEVICE(obj);
745     MusicPalMiscState *s = MUSICPAL_MISC(obj);
746 
747     memory_region_init_io(&s->iomem, OBJECT(s), &musicpal_misc_ops, NULL,
748                           "musicpal-misc", MP_MISC_SIZE);
749     sysbus_init_mmio(sd, &s->iomem);
750 }
751 
752 static const TypeInfo musicpal_misc_info = {
753     .name = TYPE_MUSICPAL_MISC,
754     .parent = TYPE_SYS_BUS_DEVICE,
755     .instance_init = musicpal_misc_init,
756     .instance_size = sizeof(MusicPalMiscState),
757 };
758 
759 /* WLAN register offsets */
760 #define MP_WLAN_MAGIC1          0x11c
761 #define MP_WLAN_MAGIC2          0x124
762 
763 static uint64_t mv88w8618_wlan_read(void *opaque, hwaddr offset,
764                                     unsigned size)
765 {
766     switch (offset) {
767     /* Workaround to allow loading the binary-only wlandrv.ko crap
768      * from the original Freecom firmware. */
769     case MP_WLAN_MAGIC1:
770         return ~3;
771     case MP_WLAN_MAGIC2:
772         return -1;
773 
774     default:
775         return 0;
776     }
777 }
778 
779 static void mv88w8618_wlan_write(void *opaque, hwaddr offset,
780                                  uint64_t value, unsigned size)
781 {
782 }
783 
784 static const MemoryRegionOps mv88w8618_wlan_ops = {
785     .read = mv88w8618_wlan_read,
786     .write =mv88w8618_wlan_write,
787     .endianness = DEVICE_NATIVE_ENDIAN,
788 };
789 
790 static void mv88w8618_wlan_realize(DeviceState *dev, Error **errp)
791 {
792     MemoryRegion *iomem = g_new(MemoryRegion, 1);
793 
794     memory_region_init_io(iomem, OBJECT(dev), &mv88w8618_wlan_ops, NULL,
795                           "musicpal-wlan", MP_WLAN_SIZE);
796     sysbus_init_mmio(SYS_BUS_DEVICE(dev), iomem);
797 }
798 
799 /* GPIO register offsets */
800 #define MP_GPIO_OE_LO           0x008
801 #define MP_GPIO_OUT_LO          0x00c
802 #define MP_GPIO_IN_LO           0x010
803 #define MP_GPIO_IER_LO          0x014
804 #define MP_GPIO_IMR_LO          0x018
805 #define MP_GPIO_ISR_LO          0x020
806 #define MP_GPIO_OE_HI           0x508
807 #define MP_GPIO_OUT_HI          0x50c
808 #define MP_GPIO_IN_HI           0x510
809 #define MP_GPIO_IER_HI          0x514
810 #define MP_GPIO_IMR_HI          0x518
811 #define MP_GPIO_ISR_HI          0x520
812 
813 /* GPIO bits & masks */
814 #define MP_GPIO_LCD_BRIGHTNESS  0x00070000
815 #define MP_GPIO_I2C_DATA_BIT    29
816 #define MP_GPIO_I2C_CLOCK_BIT   30
817 
818 /* LCD brightness bits in GPIO_OE_HI */
819 #define MP_OE_LCD_BRIGHTNESS    0x0007
820 
821 #define TYPE_MUSICPAL_GPIO "musicpal_gpio"
822 OBJECT_DECLARE_SIMPLE_TYPE(musicpal_gpio_state, MUSICPAL_GPIO)
823 
824 struct musicpal_gpio_state {
825     /*< private >*/
826     SysBusDevice parent_obj;
827     /*< public >*/
828 
829     MemoryRegion iomem;
830     uint32_t lcd_brightness;
831     uint32_t out_state;
832     uint32_t in_state;
833     uint32_t ier;
834     uint32_t imr;
835     uint32_t isr;
836     qemu_irq irq;
837     qemu_irq out[5]; /* 3 brightness out + 2 lcd (data and clock ) */
838 };
839 
840 static void musicpal_gpio_brightness_update(musicpal_gpio_state *s) {
841     int i;
842     uint32_t brightness;
843 
844     /* compute brightness ratio */
845     switch (s->lcd_brightness) {
846     case 0x00000007:
847         brightness = 0;
848         break;
849 
850     case 0x00020000:
851         brightness = 1;
852         break;
853 
854     case 0x00020001:
855         brightness = 2;
856         break;
857 
858     case 0x00040000:
859         brightness = 3;
860         break;
861 
862     case 0x00010006:
863         brightness = 4;
864         break;
865 
866     case 0x00020005:
867         brightness = 5;
868         break;
869 
870     case 0x00040003:
871         brightness = 6;
872         break;
873 
874     case 0x00030004:
875     default:
876         brightness = 7;
877     }
878 
879     /* set lcd brightness GPIOs  */
880     for (i = 0; i <= 2; i++) {
881         qemu_set_irq(s->out[i], (brightness >> i) & 1);
882     }
883 }
884 
885 static void musicpal_gpio_pin_event(void *opaque, int pin, int level)
886 {
887     musicpal_gpio_state *s = opaque;
888     uint32_t mask = 1 << pin;
889     uint32_t delta = level << pin;
890     uint32_t old = s->in_state & mask;
891 
892     s->in_state &= ~mask;
893     s->in_state |= delta;
894 
895     if ((old ^ delta) &&
896         ((level && (s->imr & mask)) || (!level && (s->ier & mask)))) {
897         s->isr = mask;
898         qemu_irq_raise(s->irq);
899     }
900 }
901 
902 static uint64_t musicpal_gpio_read(void *opaque, hwaddr offset,
903                                    unsigned size)
904 {
905     musicpal_gpio_state *s = opaque;
906 
907     switch (offset) {
908     case MP_GPIO_OE_HI: /* used for LCD brightness control */
909         return s->lcd_brightness & MP_OE_LCD_BRIGHTNESS;
910 
911     case MP_GPIO_OUT_LO:
912         return s->out_state & 0xFFFF;
913     case MP_GPIO_OUT_HI:
914         return s->out_state >> 16;
915 
916     case MP_GPIO_IN_LO:
917         return s->in_state & 0xFFFF;
918     case MP_GPIO_IN_HI:
919         return s->in_state >> 16;
920 
921     case MP_GPIO_IER_LO:
922         return s->ier & 0xFFFF;
923     case MP_GPIO_IER_HI:
924         return s->ier >> 16;
925 
926     case MP_GPIO_IMR_LO:
927         return s->imr & 0xFFFF;
928     case MP_GPIO_IMR_HI:
929         return s->imr >> 16;
930 
931     case MP_GPIO_ISR_LO:
932         return s->isr & 0xFFFF;
933     case MP_GPIO_ISR_HI:
934         return s->isr >> 16;
935 
936     default:
937         return 0;
938     }
939 }
940 
941 static void musicpal_gpio_write(void *opaque, hwaddr offset,
942                                 uint64_t value, unsigned size)
943 {
944     musicpal_gpio_state *s = opaque;
945     switch (offset) {
946     case MP_GPIO_OE_HI: /* used for LCD brightness control */
947         s->lcd_brightness = (s->lcd_brightness & MP_GPIO_LCD_BRIGHTNESS) |
948                          (value & MP_OE_LCD_BRIGHTNESS);
949         musicpal_gpio_brightness_update(s);
950         break;
951 
952     case MP_GPIO_OUT_LO:
953         s->out_state = (s->out_state & 0xFFFF0000) | (value & 0xFFFF);
954         break;
955     case MP_GPIO_OUT_HI:
956         s->out_state = (s->out_state & 0xFFFF) | (value << 16);
957         s->lcd_brightness = (s->lcd_brightness & 0xFFFF) |
958                             (s->out_state & MP_GPIO_LCD_BRIGHTNESS);
959         musicpal_gpio_brightness_update(s);
960         qemu_set_irq(s->out[3], (s->out_state >> MP_GPIO_I2C_DATA_BIT) & 1);
961         qemu_set_irq(s->out[4], (s->out_state >> MP_GPIO_I2C_CLOCK_BIT) & 1);
962         break;
963 
964     case MP_GPIO_IER_LO:
965         s->ier = (s->ier & 0xFFFF0000) | (value & 0xFFFF);
966         break;
967     case MP_GPIO_IER_HI:
968         s->ier = (s->ier & 0xFFFF) | (value << 16);
969         break;
970 
971     case MP_GPIO_IMR_LO:
972         s->imr = (s->imr & 0xFFFF0000) | (value & 0xFFFF);
973         break;
974     case MP_GPIO_IMR_HI:
975         s->imr = (s->imr & 0xFFFF) | (value << 16);
976         break;
977     }
978 }
979 
980 static const MemoryRegionOps musicpal_gpio_ops = {
981     .read = musicpal_gpio_read,
982     .write = musicpal_gpio_write,
983     .endianness = DEVICE_NATIVE_ENDIAN,
984 };
985 
986 static void musicpal_gpio_reset(DeviceState *d)
987 {
988     musicpal_gpio_state *s = MUSICPAL_GPIO(d);
989 
990     s->lcd_brightness = 0;
991     s->out_state = 0;
992     s->in_state = 0xffffffff;
993     s->ier = 0;
994     s->imr = 0;
995     s->isr = 0;
996 }
997 
998 static void musicpal_gpio_init(Object *obj)
999 {
1000     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1001     DeviceState *dev = DEVICE(sbd);
1002     musicpal_gpio_state *s = MUSICPAL_GPIO(dev);
1003 
1004     sysbus_init_irq(sbd, &s->irq);
1005 
1006     memory_region_init_io(&s->iomem, obj, &musicpal_gpio_ops, s,
1007                           "musicpal-gpio", MP_GPIO_SIZE);
1008     sysbus_init_mmio(sbd, &s->iomem);
1009 
1010     qdev_init_gpio_out(dev, s->out, ARRAY_SIZE(s->out));
1011 
1012     qdev_init_gpio_in(dev, musicpal_gpio_pin_event, 32);
1013 }
1014 
1015 static const VMStateDescription musicpal_gpio_vmsd = {
1016     .name = "musicpal_gpio",
1017     .version_id = 1,
1018     .minimum_version_id = 1,
1019     .fields = (const VMStateField[]) {
1020         VMSTATE_UINT32(lcd_brightness, musicpal_gpio_state),
1021         VMSTATE_UINT32(out_state, musicpal_gpio_state),
1022         VMSTATE_UINT32(in_state, musicpal_gpio_state),
1023         VMSTATE_UINT32(ier, musicpal_gpio_state),
1024         VMSTATE_UINT32(imr, musicpal_gpio_state),
1025         VMSTATE_UINT32(isr, musicpal_gpio_state),
1026         VMSTATE_END_OF_LIST()
1027     }
1028 };
1029 
1030 static void musicpal_gpio_class_init(ObjectClass *klass, void *data)
1031 {
1032     DeviceClass *dc = DEVICE_CLASS(klass);
1033 
1034     dc->reset = musicpal_gpio_reset;
1035     dc->vmsd = &musicpal_gpio_vmsd;
1036 }
1037 
1038 static const TypeInfo musicpal_gpio_info = {
1039     .name          = TYPE_MUSICPAL_GPIO,
1040     .parent        = TYPE_SYS_BUS_DEVICE,
1041     .instance_size = sizeof(musicpal_gpio_state),
1042     .instance_init = musicpal_gpio_init,
1043     .class_init    = musicpal_gpio_class_init,
1044 };
1045 
1046 /* Keyboard codes & masks */
1047 #define MP_KEY_WHEEL_VOL       (1 << 0)
1048 #define MP_KEY_WHEEL_VOL_INV   (1 << 1)
1049 #define MP_KEY_WHEEL_NAV       (1 << 2)
1050 #define MP_KEY_WHEEL_NAV_INV   (1 << 3)
1051 #define MP_KEY_BTN_FAVORITS    (1 << 4)
1052 #define MP_KEY_BTN_MENU        (1 << 5)
1053 #define MP_KEY_BTN_VOLUME      (1 << 6)
1054 #define MP_KEY_BTN_NAVIGATION  (1 << 7)
1055 
1056 #define TYPE_MUSICPAL_KEY "musicpal_key"
1057 OBJECT_DECLARE_SIMPLE_TYPE(musicpal_key_state, MUSICPAL_KEY)
1058 
1059 struct musicpal_key_state {
1060     /*< private >*/
1061     SysBusDevice parent_obj;
1062     /*< public >*/
1063 
1064     uint32_t pressed_keys;
1065     qemu_irq out[8];
1066 };
1067 
1068 static void musicpal_key_event(DeviceState *dev, QemuConsole *src,
1069                                InputEvent *evt)
1070 {
1071     musicpal_key_state *s = MUSICPAL_KEY(dev);
1072     InputKeyEvent *key = evt->u.key.data;
1073     int qcode = qemu_input_key_value_to_qcode(key->key);
1074     uint32_t event = 0;
1075     int i;
1076 
1077     switch (qcode) {
1078     case Q_KEY_CODE_UP:
1079         event = MP_KEY_WHEEL_NAV | MP_KEY_WHEEL_NAV_INV;
1080         break;
1081 
1082     case Q_KEY_CODE_DOWN:
1083         event = MP_KEY_WHEEL_NAV;
1084         break;
1085 
1086     case Q_KEY_CODE_LEFT:
1087         event = MP_KEY_WHEEL_VOL | MP_KEY_WHEEL_VOL_INV;
1088         break;
1089 
1090     case Q_KEY_CODE_RIGHT:
1091         event = MP_KEY_WHEEL_VOL;
1092         break;
1093 
1094     case Q_KEY_CODE_F:
1095         event = MP_KEY_BTN_FAVORITS;
1096         break;
1097 
1098     case Q_KEY_CODE_TAB:
1099         event = MP_KEY_BTN_VOLUME;
1100         break;
1101 
1102     case Q_KEY_CODE_RET:
1103         event = MP_KEY_BTN_NAVIGATION;
1104         break;
1105 
1106     case Q_KEY_CODE_M:
1107         event = MP_KEY_BTN_MENU;
1108         break;
1109     }
1110 
1111     /*
1112      * We allow repeated wheel-events when the arrow keys are held down,
1113      * but do not repeat already-pressed buttons for the other key inputs.
1114      */
1115     if (!(event & (MP_KEY_WHEEL_NAV | MP_KEY_WHEEL_VOL))) {
1116         if (key->down && (s->pressed_keys & event)) {
1117             event = 0;
1118         }
1119     }
1120 
1121     if (event) {
1122         /* Raise GPIO pin first if repeating a key */
1123         if (key->down && (s->pressed_keys & event)) {
1124             for (i = 0; i <= 7; i++) {
1125                 if (event & (1 << i)) {
1126                     qemu_set_irq(s->out[i], 1);
1127                 }
1128             }
1129         }
1130         for (i = 0; i <= 7; i++) {
1131             if (event & (1 << i)) {
1132                 qemu_set_irq(s->out[i], !key->down);
1133             }
1134         }
1135         if (key->down) {
1136             s->pressed_keys |= event;
1137         } else {
1138             s->pressed_keys &= ~event;
1139         }
1140     }
1141 }
1142 
1143 static void musicpal_key_init(Object *obj)
1144 {
1145     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1146     DeviceState *dev = DEVICE(sbd);
1147     musicpal_key_state *s = MUSICPAL_KEY(dev);
1148 
1149     s->pressed_keys = 0;
1150 
1151     qdev_init_gpio_out(dev, s->out, ARRAY_SIZE(s->out));
1152 }
1153 
1154 static const QemuInputHandler musicpal_key_handler = {
1155     .name = "musicpal_key",
1156     .mask = INPUT_EVENT_MASK_KEY,
1157     .event = musicpal_key_event,
1158 };
1159 
1160 static void musicpal_key_realize(DeviceState *dev, Error **errp)
1161 {
1162     qemu_input_handler_register(dev, &musicpal_key_handler);
1163 }
1164 
1165 static const VMStateDescription musicpal_key_vmsd = {
1166     .name = "musicpal_key",
1167     .version_id = 2,
1168     .minimum_version_id = 2,
1169     .fields = (const VMStateField[]) {
1170         VMSTATE_UINT32(pressed_keys, musicpal_key_state),
1171         VMSTATE_END_OF_LIST()
1172     }
1173 };
1174 
1175 static void musicpal_key_class_init(ObjectClass *klass, void *data)
1176 {
1177     DeviceClass *dc = DEVICE_CLASS(klass);
1178 
1179     dc->vmsd = &musicpal_key_vmsd;
1180     dc->realize = musicpal_key_realize;
1181 }
1182 
1183 static const TypeInfo musicpal_key_info = {
1184     .name          = TYPE_MUSICPAL_KEY,
1185     .parent        = TYPE_SYS_BUS_DEVICE,
1186     .instance_size = sizeof(musicpal_key_state),
1187     .instance_init = musicpal_key_init,
1188     .class_init    = musicpal_key_class_init,
1189 };
1190 
1191 #define FLASH_SECTOR_SIZE   (64 * KiB)
1192 
1193 static struct arm_boot_info musicpal_binfo = {
1194     .loader_start = 0x0,
1195     .board_id = 0x20e,
1196 };
1197 
1198 static void musicpal_init(MachineState *machine)
1199 {
1200     ARMCPU *cpu;
1201     DeviceState *dev;
1202     DeviceState *pic;
1203     DeviceState *uart_orgate;
1204     DeviceState *i2c_dev;
1205     DeviceState *lcd_dev;
1206     DeviceState *key_dev;
1207     I2CSlave *wm8750_dev;
1208     SysBusDevice *s;
1209     I2CBus *i2c;
1210     int i;
1211     unsigned long flash_size;
1212     DriveInfo *dinfo;
1213     MachineClass *mc = MACHINE_GET_CLASS(machine);
1214     MemoryRegion *address_space_mem = get_system_memory();
1215     MemoryRegion *sram = g_new(MemoryRegion, 1);
1216 
1217     /* For now we use a fixed - the original - RAM size */
1218     if (machine->ram_size != mc->default_ram_size) {
1219         char *sz = size_to_str(mc->default_ram_size);
1220         error_report("Invalid RAM size, should be %s", sz);
1221         g_free(sz);
1222         exit(EXIT_FAILURE);
1223     }
1224 
1225     cpu = ARM_CPU(cpu_create(machine->cpu_type));
1226 
1227     memory_region_add_subregion(address_space_mem, 0, machine->ram);
1228 
1229     memory_region_init_ram(sram, NULL, "musicpal.sram", MP_SRAM_SIZE,
1230                            &error_fatal);
1231     memory_region_add_subregion(address_space_mem, MP_SRAM_BASE, sram);
1232 
1233     pic = sysbus_create_simple(TYPE_MV88W8618_PIC, MP_PIC_BASE,
1234                                qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
1235     sysbus_create_varargs(TYPE_MV88W8618_PIT, MP_PIT_BASE,
1236                           qdev_get_gpio_in(pic, MP_TIMER1_IRQ),
1237                           qdev_get_gpio_in(pic, MP_TIMER2_IRQ),
1238                           qdev_get_gpio_in(pic, MP_TIMER3_IRQ),
1239                           qdev_get_gpio_in(pic, MP_TIMER4_IRQ), NULL);
1240 
1241     /* Logically OR both UART IRQs together */
1242     uart_orgate = DEVICE(object_new(TYPE_OR_IRQ));
1243     object_property_set_int(OBJECT(uart_orgate), "num-lines", 2, &error_fatal);
1244     qdev_realize_and_unref(uart_orgate, NULL, &error_fatal);
1245     qdev_connect_gpio_out(uart_orgate, 0,
1246                           qdev_get_gpio_in(pic, MP_UART_SHARED_IRQ));
1247 
1248     serial_mm_init(address_space_mem, MP_UART1_BASE, 2,
1249                    qdev_get_gpio_in(uart_orgate, 0),
1250                    1825000, serial_hd(0), DEVICE_NATIVE_ENDIAN);
1251     serial_mm_init(address_space_mem, MP_UART2_BASE, 2,
1252                    qdev_get_gpio_in(uart_orgate, 1),
1253                    1825000, serial_hd(1), DEVICE_NATIVE_ENDIAN);
1254 
1255     /* Register flash */
1256     dinfo = drive_get(IF_PFLASH, 0, 0);
1257     if (dinfo) {
1258         BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
1259 
1260         flash_size = blk_getlength(blk);
1261         if (flash_size != 8 * MiB && flash_size != 16 * MiB &&
1262             flash_size != 32 * MiB) {
1263             error_report("Invalid flash image size");
1264             exit(1);
1265         }
1266 
1267         /*
1268          * The original U-Boot accesses the flash at 0xFE000000 instead of
1269          * 0xFF800000 (if there is 8 MB flash). So remap flash access if the
1270          * image is smaller than 32 MB.
1271          */
1272         pflash_cfi02_register(0x100000000ULL - MP_FLASH_SIZE_MAX,
1273                               "musicpal.flash", flash_size,
1274                               blk, FLASH_SECTOR_SIZE,
1275                               MP_FLASH_SIZE_MAX / flash_size,
1276                               2, 0x00BF, 0x236D, 0x0000, 0x0000,
1277                               0x5555, 0x2AAA, 0);
1278     }
1279     sysbus_create_simple(TYPE_MV88W8618_FLASHCFG, MP_FLASHCFG_BASE, NULL);
1280 
1281     qemu_check_nic_model(&nd_table[0], "mv88w8618");
1282     dev = qdev_new(TYPE_MV88W8618_ETH);
1283     qdev_set_nic_properties(dev, &nd_table[0]);
1284     object_property_set_link(OBJECT(dev), "dma-memory",
1285                              OBJECT(get_system_memory()), &error_fatal);
1286     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
1287     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, MP_ETH_BASE);
1288     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
1289                        qdev_get_gpio_in(pic, MP_ETH_IRQ));
1290 
1291     sysbus_create_simple("mv88w8618_wlan", MP_WLAN_BASE, NULL);
1292 
1293     sysbus_create_simple(TYPE_MUSICPAL_MISC, MP_MISC_BASE, NULL);
1294 
1295     dev = sysbus_create_simple(TYPE_MUSICPAL_GPIO, MP_GPIO_BASE,
1296                                qdev_get_gpio_in(pic, MP_GPIO_IRQ));
1297     i2c_dev = sysbus_create_simple(TYPE_GPIO_I2C, -1, NULL);
1298     i2c = (I2CBus *)qdev_get_child_bus(i2c_dev, "i2c");
1299 
1300     lcd_dev = sysbus_create_simple(TYPE_MUSICPAL_LCD, MP_LCD_BASE, NULL);
1301     key_dev = sysbus_create_simple(TYPE_MUSICPAL_KEY, -1, NULL);
1302 
1303     /* I2C read data */
1304     qdev_connect_gpio_out(i2c_dev, 0,
1305                           qdev_get_gpio_in(dev, MP_GPIO_I2C_DATA_BIT));
1306     /* I2C data */
1307     qdev_connect_gpio_out(dev, 3, qdev_get_gpio_in(i2c_dev, 0));
1308     /* I2C clock */
1309     qdev_connect_gpio_out(dev, 4, qdev_get_gpio_in(i2c_dev, 1));
1310 
1311     for (i = 0; i < 3; i++) {
1312         qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(lcd_dev, i));
1313     }
1314     for (i = 0; i < 4; i++) {
1315         qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 8));
1316     }
1317     for (i = 4; i < 8; i++) {
1318         qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 15));
1319     }
1320 
1321     wm8750_dev = i2c_slave_new(TYPE_WM8750, MP_WM_ADDR);
1322     if (machine->audiodev) {
1323         qdev_prop_set_string(DEVICE(wm8750_dev), "audiodev", machine->audiodev);
1324     }
1325     i2c_slave_realize_and_unref(wm8750_dev, i2c, &error_abort);
1326 
1327     dev = qdev_new(TYPE_MV88W8618_AUDIO);
1328     s = SYS_BUS_DEVICE(dev);
1329     object_property_set_link(OBJECT(dev), "wm8750", OBJECT(wm8750_dev),
1330                              NULL);
1331     sysbus_realize_and_unref(s, &error_fatal);
1332     sysbus_mmio_map(s, 0, MP_AUDIO_BASE);
1333     sysbus_connect_irq(s, 0, qdev_get_gpio_in(pic, MP_AUDIO_IRQ));
1334 
1335     musicpal_binfo.ram_size = MP_RAM_DEFAULT_SIZE;
1336     arm_load_kernel(cpu, machine, &musicpal_binfo);
1337 }
1338 
1339 static void musicpal_machine_init(MachineClass *mc)
1340 {
1341     mc->desc = "Marvell 88w8618 / MusicPal (ARM926EJ-S)";
1342     mc->init = musicpal_init;
1343     mc->ignore_memory_transaction_failures = true;
1344     mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926");
1345     mc->default_ram_size = MP_RAM_DEFAULT_SIZE;
1346     mc->default_ram_id = "musicpal.ram";
1347 
1348     machine_add_audiodev_property(mc);
1349 }
1350 
1351 DEFINE_MACHINE("musicpal", musicpal_machine_init)
1352 
1353 static void mv88w8618_wlan_class_init(ObjectClass *klass, void *data)
1354 {
1355     DeviceClass *dc = DEVICE_CLASS(klass);
1356 
1357     dc->realize = mv88w8618_wlan_realize;
1358 }
1359 
1360 static const TypeInfo mv88w8618_wlan_info = {
1361     .name          = "mv88w8618_wlan",
1362     .parent        = TYPE_SYS_BUS_DEVICE,
1363     .instance_size = sizeof(SysBusDevice),
1364     .class_init    = mv88w8618_wlan_class_init,
1365 };
1366 
1367 static void musicpal_register_types(void)
1368 {
1369     type_register_static(&mv88w8618_pic_info);
1370     type_register_static(&mv88w8618_pit_info);
1371     type_register_static(&mv88w8618_flashcfg_info);
1372     type_register_static(&mv88w8618_wlan_info);
1373     type_register_static(&musicpal_lcd_info);
1374     type_register_static(&musicpal_gpio_info);
1375     type_register_static(&musicpal_key_info);
1376     type_register_static(&musicpal_misc_info);
1377 }
1378 
1379 type_init(musicpal_register_types)
1380