@samitouri / QOSamiQemu / commits / ad64baf49d

hw/arm: Remove the 'musicpal' machine

The 'musicpal' machine emulates the Freecom MusicPal, which was an "internet radio" released in the mid-2000s. The stock system used a 2.6.16 Linux kernel, but as far as I'm aware, support for the hardware was never upstreamed to the mainline kernel. There are a number of reasons for deprecating this board: * The hardware is now solidly obsolete * It was never supported in mainline Linux * The SoC is a Marvell one with no public datasheet * The only QEMU changes to it have been the usual tree wide updates and refactoring work * The only bug report we've ever had about it has been one of the usual "bug found by static analysis" kind But in fact we can just drop it immediately, because in commit 59754f85ed35 ("target/arm: Do memory type alignment check when translation disabled") in 2024 we broke the boot of the standard firmware image for this board. (The image's u-boot does a LDRH to an unaligned address, which is UNPREDICTABLE; we used to let it through, but that commit makes it take a Data Abort, so the image crashes before it boots the kernel.) Since nobody complained, we can deduce that nobody's actually using this machine. Remove the machine proper, and note this in the docs. Devices used only by this board will be removed in subsequent commits. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Acked-by: Jan Kiszka <jan.kiszka@web.de> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Message-id: 20260819185430.3467629-4-peter.maydell@linaro.org

Peter Maydell committed Aug 19, 2026 at 19:54 UTC ad64baf49de8af2d374906b37738e4c7fb9a795a
8 files changed +10 -1441
MAINTAINERS
-10
@@ -995,16 +995,6 @@ S: Odd Fixes
995 F: hw/arm/musca.c
996 F: docs/system/arm/musca.rst
997
998 -Musicpal
999 -M: Jan Kiszka <jan.kiszka@web.de>
1000 -M: Peter Maydell <peter.maydell@linaro.org>
1001 -L: qemu-arm@nongnu.org
1002 -S: Odd Fixes
1003 -F: hw/arm/musicpal.c
1004 -F: hw/net/mv88w8618_eth.c
1005 -F: include/hw/net/mv88w8618_eth.h
1006 -F: docs/system/arm/musicpal.rst
1007 -
998 Nuvoton NPCM7xx
999 M: Tyrone Ting <kfting@nuvoton.com>
1000 M: Hao Wu <wuhaotsh@google.com>
configs/devices/arm-softmmu/default.mak
-1
@@ -14,7 +14,6 @@
14 # CONFIG_EXYNOS4=n
15 # CONFIG_INTEGRATOR=n
16 # CONFIG_FSL_IMX31=n
17 -# CONFIG_MUSICPAL=n
17 # CONFIG_MPS3R=n
18 # CONFIG_MUSCA=n
19 # CONFIG_SX1=n
docs/about/removed-features.rst
+10
@@ -1251,6 +1251,16 @@ machine they want to use to avoid confusion. Existing users of the ``spike``
1251 machine must ensure that they're setting the ``spike`` machine in the
1252 command line (``-M spike``).
1253
1254 +Arm ``musicpal`` machine (removed in 11.2)
1255 +''''''''''''''''''''''''''''''''''''''''''
1256 +
1257 +The ``musicpal`` machine was an emulation of the Freecom MusicPal, an
1258 +"internet radio" device from the mid-2000s. This hardware was never
1259 +supported in upstream Linux, was based on a Marvell SoC with no public
1260 +documentation, and is now obsolete. We accidentally broke booting this
1261 +board in 2024, without anybody noticing; it has therefore been removed
1262 +without a deprecation period.
1263 +
1264 linux-user mode CPUs
1265 --------------------
1266
docs/system/arm/musicpal.rst deleted
-19
@@ -1,19 +0,0 @@
1 -Freecom MusicPal (``musicpal``)
2 -===============================
3 -
4 -The Freecom MusicPal internet radio emulation includes the following
5 -elements:
6 -
7 -- Marvell MV88W8618 Arm core.
8 -
9 -- 32 MB RAM, 256 KB SRAM, 8 MB flash.
10 -
11 -- Up to 2 16550 UARTs
12 -
13 -- MV88W8xx8 Ethernet controller
14 -
15 -- MV88W8618 audio controller, WM8750 CODEC and mixer
16 -
17 -- 128x64 display with brightness control
18 -
19 -- 2 buttons, 2 navigation wheels with button function
docs/system/target-arm.rst
-1
@@ -87,7 +87,6 @@ Board-specific documentation
87 arm/cubieboard
88 arm/emcraft-sf2
89 arm/exynos
90 - arm/musicpal
90 arm/kzm
91 arm/nrf
92 arm/nuvoton
hw/arm/Kconfig
-12
@@ -103,18 +103,6 @@ config MUSCA
103 config MARVELL_88W8618
104 bool
105
106 -config MUSICPAL
107 - bool
108 - default y
109 - depends on TCG && ARM
110 - select OR_IRQ
111 - select BITBANG_I2C
112 - select MARVELL_88W8618
113 - select PTIMER
114 - select PFLASH_CFI02
115 - select SERIAL_MM
116 - select WM8750
117 -
106 config NETDUINO2
107 bool
108 default y
hw/arm/meson.build
-1
@@ -6,7 +6,6 @@ arm_common_ss.add(when: 'CONFIG_EMCRAFT_SF2', if_true: files('msf2-som.c'))
6 arm_common_ss.add(when: 'CONFIG_INTEGRATOR', if_true: files('integratorcp.c'))
7 arm_common_ss.add(when: 'CONFIG_MICROBIT', if_true: files('microbit.c'))
8 arm_common_ss.add(when: 'CONFIG_MPS3R', if_true: files('mps3r.c'))
9 -arm_common_ss.add(when: 'CONFIG_MUSICPAL', if_true: [files('musicpal.c')])
9 arm_common_ss.add(when: 'CONFIG_NETDUINOPLUS2', if_true: files('netduinoplus2.c'))
10 arm_common_ss.add(when: 'CONFIG_OLIMEX_STM32_H405', if_true: files('olimex-stm32-h405.c'))
11 arm_common_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx.c', 'npcm7xx_boards.c'))
hw/arm/musicpal.c deleted
-1397
@@ -1,1397 +0,0 @@
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 "hw/core/sysbus.h"
16 -#include "migration/vmstate.h"
17 -#include "hw/arm/boot.h"
18 -#include "hw/arm/machines-qom.h"
19 -#include "net/net.h"
20 -#include "system/system.h"
21 -#include "hw/core/boards.h"
22 -#include "hw/char/serial-mm.h"
23 -#include "qemu/timer.h"
24 -#include "hw/core/ptimer.h"
25 -#include "hw/core/qdev-properties.h"
26 -#include "hw/block/flash.h"
27 -#include "standard-headers/linux/input-event-codes.h"
28 -#include "ui/console.h"
29 -#include "hw/i2c/i2c.h"
30 -#include "hw/i2c/bitbang_i2c.h"
31 -#include "hw/core/irq.h"
32 -#include "hw/core/or-irq.h"
33 -#include "hw/audio/wm8750.h"
34 -#include "system/block-backend.h"
35 -#include "system/runstate.h"
36 -#include "system/dma.h"
37 -#include "ui/pixel_ops.h"
38 -#include "qemu/cutils.h"
39 -#include "qom/object.h"
40 -#include "hw/net/mv88w8618_eth.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 bool 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 - qemu_console_update(s->con, 0, 0, 128*3, 64*3);
175 - return true;
176 -}
177 -
178 -static void lcd_invalidate(void *opaque)
179 -{
180 -}
181 -
182 -static void musicpal_lcd_gpio_brightness_in(void *opaque, int irq, int level)
183 -{
184 - musicpal_lcd_state *s = opaque;
185 - s->brightness &= ~(1 << irq);
186 - s->brightness |= level << irq;
187 -}
188 -
189 -static uint64_t musicpal_lcd_read(void *opaque, hwaddr offset,
190 - unsigned size)
191 -{
192 - musicpal_lcd_state *s = opaque;
193 -
194 - switch (offset) {
195 - case MP_LCD_IRQCTRL:
196 - return s->irqctrl;
197 -
198 - default:
199 - return 0;
200 - }
201 -}
202 -
203 -static void musicpal_lcd_write(void *opaque, hwaddr offset,
204 - uint64_t value, unsigned size)
205 -{
206 - musicpal_lcd_state *s = opaque;
207 -
208 - switch (offset) {
209 - case MP_LCD_IRQCTRL:
210 - s->irqctrl = value;
211 - break;
212 -
213 - case MP_LCD_SPICTRL:
214 - if (value == MP_LCD_SPI_DATA || value == MP_LCD_SPI_CMD) {
215 - s->mode = value;
216 - } else {
217 - s->mode = MP_LCD_SPI_INVALID;
218 - }
219 - break;
220 -
221 - case MP_LCD_INST:
222 - if (value >= MP_LCD_INST_SETPAGE0 && value <= MP_LCD_INST_SETPAGE7) {
223 - s->page = value - MP_LCD_INST_SETPAGE0;
224 - s->page_off = 0;
225 - }
226 - break;
227 -
228 - case MP_LCD_DATA:
229 - if (s->mode == MP_LCD_SPI_CMD) {
230 - if (value >= MP_LCD_INST_SETPAGE0 &&
231 - value <= MP_LCD_INST_SETPAGE7) {
232 - s->page = value - MP_LCD_INST_SETPAGE0;
233 - s->page_off = 0;
234 - }
235 - } else if (s->mode == MP_LCD_SPI_DATA) {
236 - s->video_ram[s->page*128 + s->page_off] = value;
237 - s->page_off = (s->page_off + 1) & 127;
238 - }
239 - break;
240 - }
241 -}
242 -
243 -static const MemoryRegionOps musicpal_lcd_ops = {
244 - .read = musicpal_lcd_read,
245 - .write = musicpal_lcd_write,
246 - .endianness = DEVICE_NATIVE_ENDIAN,
247 -};
248 -
249 -static const GraphicHwOps musicpal_gfx_ops = {
250 - .invalidate = lcd_invalidate,
251 - .gfx_update = lcd_refresh,
252 -};
253 -
254 -static void musicpal_lcd_realize(DeviceState *dev, Error **errp)
255 -{
256 - musicpal_lcd_state *s = MUSICPAL_LCD(dev);
257 - s->con = qemu_graphic_console_create(dev, 0, &musicpal_gfx_ops, s);
258 - qemu_console_resize(s->con, 128 * 3, 64 * 3);
259 -}
260 -
261 -static void musicpal_lcd_init(Object *obj)
262 -{
263 - SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
264 - DeviceState *dev = DEVICE(sbd);
265 - musicpal_lcd_state *s = MUSICPAL_LCD(dev);
266 -
267 - s->brightness = 7;
268 -
269 - memory_region_init_io(&s->iomem, obj, &musicpal_lcd_ops, s,
270 - "musicpal-lcd", MP_LCD_SIZE);
271 - sysbus_init_mmio(sbd, &s->iomem);
272 -
273 - qdev_init_gpio_in(dev, musicpal_lcd_gpio_brightness_in, 3);
274 -}
275 -
276 -static const VMStateDescription musicpal_lcd_vmsd = {
277 - .name = "musicpal_lcd",
278 - .version_id = 1,
279 - .minimum_version_id = 1,
280 - .fields = (const VMStateField[]) {
281 - VMSTATE_UINT32(brightness, musicpal_lcd_state),
282 - VMSTATE_UINT32(mode, musicpal_lcd_state),
283 - VMSTATE_UINT32(irqctrl, musicpal_lcd_state),
284 - VMSTATE_UINT32(page, musicpal_lcd_state),
285 - VMSTATE_UINT32(page_off, musicpal_lcd_state),
286 - VMSTATE_BUFFER(video_ram, musicpal_lcd_state),
287 - VMSTATE_END_OF_LIST()
288 - }
289 -};
290 -
291 -static void musicpal_lcd_class_init(ObjectClass *klass, const void *data)
292 -{
293 - DeviceClass *dc = DEVICE_CLASS(klass);
294 -
295 - dc->vmsd = &musicpal_lcd_vmsd;
296 - dc->realize = musicpal_lcd_realize;
297 -}
298 -
299 -static const TypeInfo musicpal_lcd_info = {
300 - .name = TYPE_MUSICPAL_LCD,
301 - .parent = TYPE_SYS_BUS_DEVICE,
302 - .instance_size = sizeof(musicpal_lcd_state),
303 - .instance_init = musicpal_lcd_init,
304 - .class_init = musicpal_lcd_class_init,
305 -};
306 -
307 -/* PIC register offsets */
308 -#define MP_PIC_STATUS 0x00
309 -#define MP_PIC_ENABLE_SET 0x08
310 -#define MP_PIC_ENABLE_CLR 0x0C
311 -
312 -#define TYPE_MV88W8618_PIC "mv88w8618_pic"
313 -OBJECT_DECLARE_SIMPLE_TYPE(mv88w8618_pic_state, MV88W8618_PIC)
314 -
315 -struct mv88w8618_pic_state {
316 - /*< private >*/
317 - SysBusDevice parent_obj;
318 - /*< public >*/
319 -
320 - MemoryRegion iomem;
321 - uint32_t level;
322 - uint32_t enabled;
323 - qemu_irq parent_irq;
324 -};
325 -
326 -static void mv88w8618_pic_update(mv88w8618_pic_state *s)
327 -{
328 - qemu_set_irq(s->parent_irq, (s->level & s->enabled));
329 -}
330 -
331 -static void mv88w8618_pic_set_irq(void *opaque, int irq, int level)
332 -{
333 - mv88w8618_pic_state *s = opaque;
334 -
335 - if (level) {
336 - s->level |= 1 << irq;
337 - } else {
338 - s->level &= ~(1 << irq);
339 - }
340 - mv88w8618_pic_update(s);
341 -}
342 -
343 -static uint64_t mv88w8618_pic_read(void *opaque, hwaddr offset,
344 - unsigned size)
345 -{
346 - mv88w8618_pic_state *s = opaque;
347 -
348 - switch (offset) {
349 - case MP_PIC_STATUS:
350 - return s->level & s->enabled;
351 -
352 - default:
353 - return 0;
354 - }
355 -}
356 -
357 -static void mv88w8618_pic_write(void *opaque, hwaddr offset,
358 - uint64_t value, unsigned size)
359 -{
360 - mv88w8618_pic_state *s = opaque;
361 -
362 - switch (offset) {
363 - case MP_PIC_ENABLE_SET:
364 - s->enabled |= value;
365 - break;
366 -
367 - case MP_PIC_ENABLE_CLR:
368 - s->enabled &= ~value;
369 - s->level &= ~value;
370 - break;
371 - }
372 - mv88w8618_pic_update(s);
373 -}
374 -
375 -static void mv88w8618_pic_reset(DeviceState *d)
376 -{
377 - mv88w8618_pic_state *s = MV88W8618_PIC(d);
378 -
379 - s->level = 0;
380 - s->enabled = 0;
381 -}
382 -
383 -static const MemoryRegionOps mv88w8618_pic_ops = {
384 - .read = mv88w8618_pic_read,
385 - .write = mv88w8618_pic_write,
386 - .endianness = DEVICE_NATIVE_ENDIAN,
387 -};
388 -
389 -static void mv88w8618_pic_init(Object *obj)
390 -{
391 - SysBusDevice *dev = SYS_BUS_DEVICE(obj);
392 - mv88w8618_pic_state *s = MV88W8618_PIC(dev);
393 -
394 - qdev_init_gpio_in(DEVICE(dev), mv88w8618_pic_set_irq, 32);
395 - sysbus_init_irq(dev, &s->parent_irq);
396 - memory_region_init_io(&s->iomem, obj, &mv88w8618_pic_ops, s,
397 - "musicpal-pic", MP_PIC_SIZE);
398 - sysbus_init_mmio(dev, &s->iomem);
399 -}
400 -
401 -static const VMStateDescription mv88w8618_pic_vmsd = {
402 - .name = "mv88w8618_pic",
403 - .version_id = 1,
404 - .minimum_version_id = 1,
405 - .fields = (const VMStateField[]) {
406 - VMSTATE_UINT32(level, mv88w8618_pic_state),
407 - VMSTATE_UINT32(enabled, mv88w8618_pic_state),
408 - VMSTATE_END_OF_LIST()
409 - }
410 -};
411 -
412 -static void mv88w8618_pic_class_init(ObjectClass *klass, const void *data)
413 -{
414 - DeviceClass *dc = DEVICE_CLASS(klass);
415 -
416 - device_class_set_legacy_reset(dc, mv88w8618_pic_reset);
417 - dc->vmsd = &mv88w8618_pic_vmsd;
418 -}
419 -
420 -static const TypeInfo mv88w8618_pic_info = {
421 - .name = TYPE_MV88W8618_PIC,
422 - .parent = TYPE_SYS_BUS_DEVICE,
423 - .instance_size = sizeof(mv88w8618_pic_state),
424 - .instance_init = mv88w8618_pic_init,
425 - .class_init = mv88w8618_pic_class_init,
426 -};
427 -
428 -/* PIT register offsets */
429 -#define MP_PIT_TIMER1_LENGTH 0x00
430 -/* ... */
431 -#define MP_PIT_TIMER4_LENGTH 0x0C
432 -#define MP_PIT_CONTROL 0x10
433 -#define MP_PIT_TIMER1_VALUE 0x14
434 -/* ... */
435 -#define MP_PIT_TIMER4_VALUE 0x20
436 -#define MP_BOARD_RESET 0x34
437 -
438 -/* Magic board reset value (probably some watchdog behind it) */
439 -#define MP_BOARD_RESET_MAGIC 0x10000
440 -
441 -typedef struct mv88w8618_timer_state {
442 - ptimer_state *ptimer;
443 - uint32_t limit;
444 - int freq;
445 - qemu_irq irq;
446 -} mv88w8618_timer_state;
447 -
448 -#define TYPE_MV88W8618_PIT "mv88w8618_pit"
449 -OBJECT_DECLARE_SIMPLE_TYPE(mv88w8618_pit_state, MV88W8618_PIT)
450 -
451 -struct mv88w8618_pit_state {
452 - /*< private >*/
453 - SysBusDevice parent_obj;
454 - /*< public >*/
455 -
456 - MemoryRegion iomem;
457 - mv88w8618_timer_state timer[4];
458 -};
459 -
460 -static void mv88w8618_timer_tick(void *opaque)
461 -{
462 - mv88w8618_timer_state *s = opaque;
463 -
464 - qemu_irq_raise(s->irq);
465 -}
466 -
467 -static void mv88w8618_timer_init(SysBusDevice *dev, mv88w8618_timer_state *s,
468 - uint32_t freq)
469 -{
470 - sysbus_init_irq(dev, &s->irq);
471 - s->freq = freq;
472 -
473 - s->ptimer = ptimer_init(mv88w8618_timer_tick, s, PTIMER_POLICY_LEGACY);
474 -}
475 -
476 -static uint64_t mv88w8618_pit_read(void *opaque, hwaddr offset,
477 - unsigned size)
478 -{
479 - mv88w8618_pit_state *s = opaque;
480 - mv88w8618_timer_state *t;
481 -
482 - switch (offset) {
483 - case MP_PIT_TIMER1_VALUE ... MP_PIT_TIMER4_VALUE:
484 - t = &s->timer[(offset-MP_PIT_TIMER1_VALUE) >> 2];
485 - return ptimer_get_count(t->ptimer);
486 -
487 - default:
488 - return 0;
489 - }
490 -}
491 -
492 -static void mv88w8618_pit_write(void *opaque, hwaddr offset,
493 - uint64_t value, unsigned size)
494 -{
495 - mv88w8618_pit_state *s = opaque;
496 - mv88w8618_timer_state *t;
497 - int i;
498 -
499 - switch (offset) {
500 - case MP_PIT_TIMER1_LENGTH ... MP_PIT_TIMER4_LENGTH:
501 - t = &s->timer[offset >> 2];
502 - t->limit = value;
503 - ptimer_transaction_begin(t->ptimer);
504 - if (t->limit > 0) {
505 - ptimer_set_limit(t->ptimer, t->limit, 1);
506 - } else {
507 - ptimer_stop(t->ptimer);
508 - }
509 - ptimer_transaction_commit(t->ptimer);
510 - break;
511 -
512 - case MP_PIT_CONTROL:
513 - for (i = 0; i < 4; i++) {
514 - t = &s->timer[i];
515 - ptimer_transaction_begin(t->ptimer);
516 - if (value & 0xf && t->limit > 0) {
517 - ptimer_set_limit(t->ptimer, t->limit, 0);
518 - ptimer_set_freq(t->ptimer, t->freq);
519 - ptimer_run(t->ptimer, 0);
520 - } else {
521 - ptimer_stop(t->ptimer);
522 - }
523 - ptimer_transaction_commit(t->ptimer);
524 - value >>= 4;
525 - }
526 - break;
527 -
528 - case MP_BOARD_RESET:
529 - if (value == MP_BOARD_RESET_MAGIC) {
530 - qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
531 - }
532 - break;
533 - }
534 -}
535 -
536 -static void mv88w8618_pit_reset(DeviceState *d)
537 -{
538 - mv88w8618_pit_state *s = MV88W8618_PIT(d);
539 - int i;
540 -
541 - for (i = 0; i < 4; i++) {
542 - mv88w8618_timer_state *t = &s->timer[i];
543 - ptimer_transaction_begin(t->ptimer);
544 - ptimer_stop(t->ptimer);
545 - ptimer_transaction_commit(t->ptimer);
546 - t->limit = 0;
547 - }
548 -}
549 -
550 -static const MemoryRegionOps mv88w8618_pit_ops = {
551 - .read = mv88w8618_pit_read,
552 - .write = mv88w8618_pit_write,
553 - .endianness = DEVICE_NATIVE_ENDIAN,
554 -};
555 -
556 -static void mv88w8618_pit_init(Object *obj)
557 -{
558 - SysBusDevice *dev = SYS_BUS_DEVICE(obj);
559 - mv88w8618_pit_state *s = MV88W8618_PIT(dev);
560 - int i;
561 -
562 - /* Letting them all run at 1 MHz is likely just a pragmatic
563 - * simplification. */
564 - for (i = 0; i < 4; i++) {
565 - mv88w8618_timer_init(dev, &s->timer[i], 1000000);
566 - }
567 -
568 - memory_region_init_io(&s->iomem, obj, &mv88w8618_pit_ops, s,
569 - "musicpal-pit", MP_PIT_SIZE);
570 - sysbus_init_mmio(dev, &s->iomem);
571 -}
572 -
573 -static void mv88w8618_pit_finalize(Object *obj)
574 -{
575 - SysBusDevice *dev = SYS_BUS_DEVICE(obj);
576 - mv88w8618_pit_state *s = MV88W8618_PIT(dev);
577 - int i;
578 -
579 - for (i = 0; i < 4; i++) {
580 - ptimer_free(s->timer[i].ptimer);
581 - }
582 -}
583 -
584 -static const VMStateDescription mv88w8618_timer_vmsd = {
585 - .name = "timer",
586 - .version_id = 1,
587 - .minimum_version_id = 1,
588 - .fields = (const VMStateField[]) {
589 - VMSTATE_PTIMER(ptimer, mv88w8618_timer_state),
590 - VMSTATE_UINT32(limit, mv88w8618_timer_state),
591 - VMSTATE_END_OF_LIST()
592 - }
593 -};
594 -
595 -static const VMStateDescription mv88w8618_pit_vmsd = {
596 - .name = "mv88w8618_pit",
597 - .version_id = 1,
598 - .minimum_version_id = 1,
599 - .fields = (const VMStateField[]) {
600 - VMSTATE_STRUCT_ARRAY(timer, mv88w8618_pit_state, 4, 1,
601 - mv88w8618_timer_vmsd, mv88w8618_timer_state),
602 - VMSTATE_END_OF_LIST()
603 - }
604 -};
605 -
606 -static void mv88w8618_pit_class_init(ObjectClass *klass, const void *data)
607 -{
608 - DeviceClass *dc = DEVICE_CLASS(klass);
609 -
610 - device_class_set_legacy_reset(dc, mv88w8618_pit_reset);
611 - dc->vmsd = &mv88w8618_pit_vmsd;
612 -}
613 -
614 -static const TypeInfo mv88w8618_pit_info = {
615 - .name = TYPE_MV88W8618_PIT,
616 - .parent = TYPE_SYS_BUS_DEVICE,
617 - .instance_size = sizeof(mv88w8618_pit_state),
618 - .instance_init = mv88w8618_pit_init,
619 - .instance_finalize = mv88w8618_pit_finalize,
620 - .class_init = mv88w8618_pit_class_init,
621 -};
622 -
623 -/* Flash config register offsets */
624 -#define MP_FLASHCFG_CFGR0 0x04
625 -
626 -#define TYPE_MV88W8618_FLASHCFG "mv88w8618_flashcfg"
627 -OBJECT_DECLARE_SIMPLE_TYPE(mv88w8618_flashcfg_state, MV88W8618_FLASHCFG)
628 -
629 -struct mv88w8618_flashcfg_state {
630 - /*< private >*/
631 - SysBusDevice parent_obj;
632 - /*< public >*/
633 -
634 - MemoryRegion iomem;
635 - uint32_t cfgr0;
636 -};
637 -
638 -static uint64_t mv88w8618_flashcfg_read(void *opaque,
639 - hwaddr offset,
640 - unsigned size)
641 -{
642 - mv88w8618_flashcfg_state *s = opaque;
643 -
644 - switch (offset) {
645 - case MP_FLASHCFG_CFGR0:
646 - return s->cfgr0;
647 -
648 - default:
649 - return 0;
650 - }
651 -}
652 -
653 -static void mv88w8618_flashcfg_write(void *opaque, hwaddr offset,
654 - uint64_t value, unsigned size)
655 -{
656 - mv88w8618_flashcfg_state *s = opaque;
657 -
658 - switch (offset) {
659 - case MP_FLASHCFG_CFGR0:
660 - s->cfgr0 = value;
661 - break;
662 - }
663 -}
664 -
665 -static const MemoryRegionOps mv88w8618_flashcfg_ops = {
666 - .read = mv88w8618_flashcfg_read,
667 - .write = mv88w8618_flashcfg_write,
668 - .endianness = DEVICE_NATIVE_ENDIAN,
669 -};
670 -
671 -static void mv88w8618_flashcfg_init(Object *obj)
672 -{
673 - SysBusDevice *dev = SYS_BUS_DEVICE(obj);
674 - mv88w8618_flashcfg_state *s = MV88W8618_FLASHCFG(dev);
675 -
676 - s->cfgr0 = 0xfffe4285; /* Default as set by U-Boot for 8 MB flash */
677 - memory_region_init_io(&s->iomem, obj, &mv88w8618_flashcfg_ops, s,
678 - "musicpal-flashcfg", MP_FLASHCFG_SIZE);
679 - sysbus_init_mmio(dev, &s->iomem);
680 -}
681 -
682 -static const VMStateDescription mv88w8618_flashcfg_vmsd = {
683 - .name = "mv88w8618_flashcfg",
684 - .version_id = 1,
685 - .minimum_version_id = 1,
686 - .fields = (const VMStateField[]) {
687 - VMSTATE_UINT32(cfgr0, mv88w8618_flashcfg_state),
688 - VMSTATE_END_OF_LIST()
689 - }
690 -};
691 -
692 -static void mv88w8618_flashcfg_class_init(ObjectClass *klass, const void *data)
693 -{
694 - DeviceClass *dc = DEVICE_CLASS(klass);
695 -
696 - dc->vmsd = &mv88w8618_flashcfg_vmsd;
697 -}
698 -
699 -static const TypeInfo mv88w8618_flashcfg_info = {
700 - .name = TYPE_MV88W8618_FLASHCFG,
701 - .parent = TYPE_SYS_BUS_DEVICE,
702 - .instance_size = sizeof(mv88w8618_flashcfg_state),
703 - .instance_init = mv88w8618_flashcfg_init,
704 - .class_init = mv88w8618_flashcfg_class_init,
705 -};
706 -
707 -/* Misc register offsets */
708 -#define MP_MISC_BOARD_REVISION 0x18
709 -
710 -#define MP_BOARD_REVISION 0x31
711 -
712 -struct MusicPalMiscState {
713 - SysBusDevice parent_obj;
714 - MemoryRegion iomem;
715 -};
716 -
717 -#define TYPE_MUSICPAL_MISC "musicpal-misc"
718 -OBJECT_DECLARE_SIMPLE_TYPE(MusicPalMiscState, MUSICPAL_MISC)
719 -
720 -static uint64_t musicpal_misc_read(void *opaque, hwaddr offset,
721 - unsigned size)
722 -{
723 - switch (offset) {
724 - case MP_MISC_BOARD_REVISION:
725 - return MP_BOARD_REVISION;
726 -
727 - default:
728 - return 0;
729 - }
730 -}
731 -
732 -static void musicpal_misc_write(void *opaque, hwaddr offset,
733 - uint64_t value, unsigned size)
734 -{
735 -}
736 -
737 -static const MemoryRegionOps musicpal_misc_ops = {
738 - .read = musicpal_misc_read,
739 - .write = musicpal_misc_write,
740 - .endianness = DEVICE_NATIVE_ENDIAN,
741 -};
742 -
743 -static void musicpal_misc_init(Object *obj)
744 -{
745 - SysBusDevice *sd = SYS_BUS_DEVICE(obj);
746 - MusicPalMiscState *s = MUSICPAL_MISC(obj);
747 -
748 - memory_region_init_io(&s->iomem, OBJECT(s), &musicpal_misc_ops, NULL,
749 - "musicpal-misc", MP_MISC_SIZE);
750 - sysbus_init_mmio(sd, &s->iomem);
751 -}
752 -
753 -static const TypeInfo musicpal_misc_info = {
754 - .name = TYPE_MUSICPAL_MISC,
755 - .parent = TYPE_SYS_BUS_DEVICE,
756 - .instance_init = musicpal_misc_init,
757 - .instance_size = sizeof(MusicPalMiscState),
758 -};
759 -
760 -/* WLAN register offsets */
761 -#define MP_WLAN_MAGIC1 0x11c
762 -#define MP_WLAN_MAGIC2 0x124
763 -
764 -static uint64_t mv88w8618_wlan_read(void *opaque, hwaddr offset,
765 - unsigned size)
766 -{
767 - switch (offset) {
768 - /* Workaround to allow loading the binary-only wlandrv.ko crap
769 - * from the original Freecom firmware. */
770 - case MP_WLAN_MAGIC1:
771 - return ~3;
772 - case MP_WLAN_MAGIC2:
773 - return -1;
774 -
775 - default:
776 - return 0;
777 - }
778 -}
779 -
780 -static void mv88w8618_wlan_write(void *opaque, hwaddr offset,
781 - uint64_t value, unsigned size)
782 -{
783 -}
784 -
785 -static const MemoryRegionOps mv88w8618_wlan_ops = {
786 - .read = mv88w8618_wlan_read,
787 - .write =mv88w8618_wlan_write,
788 - .endianness = DEVICE_NATIVE_ENDIAN,
789 -};
790 -
791 -static void mv88w8618_wlan_realize(DeviceState *dev, Error **errp)
792 -{
793 - MemoryRegion *iomem = g_new(MemoryRegion, 1);
794 -
795 - memory_region_init_io(iomem, OBJECT(dev), &mv88w8618_wlan_ops, NULL,
796 - "musicpal-wlan", MP_WLAN_SIZE);
797 - sysbus_init_mmio(SYS_BUS_DEVICE(dev), iomem);
798 -}
799 -
800 -/* GPIO register offsets */
801 -#define MP_GPIO_OE_LO 0x008
802 -#define MP_GPIO_OUT_LO 0x00c
803 -#define MP_GPIO_IN_LO 0x010
804 -#define MP_GPIO_IER_LO 0x014
805 -#define MP_GPIO_IMR_LO 0x018
806 -#define MP_GPIO_ISR_LO 0x020
807 -#define MP_GPIO_OE_HI 0x508
808 -#define MP_GPIO_OUT_HI 0x50c
809 -#define MP_GPIO_IN_HI 0x510
810 -#define MP_GPIO_IER_HI 0x514
811 -#define MP_GPIO_IMR_HI 0x518
812 -#define MP_GPIO_ISR_HI 0x520
813 -
814 -/* GPIO bits & masks */
815 -#define MP_GPIO_LCD_BRIGHTNESS 0x00070000
816 -#define MP_GPIO_I2C_DATA_BIT 29
817 -#define MP_GPIO_I2C_CLOCK_BIT 30
818 -
819 -/* LCD brightness bits in GPIO_OE_HI */
820 -#define MP_OE_LCD_BRIGHTNESS 0x0007
821 -
822 -#define TYPE_MUSICPAL_GPIO "musicpal_gpio"
823 -OBJECT_DECLARE_SIMPLE_TYPE(musicpal_gpio_state, MUSICPAL_GPIO)
824 -
825 -struct musicpal_gpio_state {
826 - /*< private >*/
827 - SysBusDevice parent_obj;
828 - /*< public >*/
829 -
830 - MemoryRegion iomem;
831 - uint32_t lcd_brightness;
832 - uint32_t out_state;
833 - uint32_t in_state;
834 - uint32_t ier;
835 - uint32_t imr;
836 - uint32_t isr;
837 - qemu_irq irq;
838 - qemu_irq out[5]; /* 3 brightness out + 2 lcd (data and clock ) */
839 -};
840 -
841 -static void musicpal_gpio_brightness_update(musicpal_gpio_state *s) {
842 - int i;
843 - uint32_t brightness;
844 -
845 - /* compute brightness ratio */
846 - switch (s->lcd_brightness) {
847 - case 0x00000007:
848 - brightness = 0;
849 - break;
850 -
851 - case 0x00020000:
852 - brightness = 1;
853 - break;
854 -
855 - case 0x00020001:
856 - brightness = 2;
857 - break;
858 -
859 - case 0x00040000:
860 - brightness = 3;
861 - break;
862 -
863 - case 0x00010006:
864 - brightness = 4;
865 - break;
866 -
867 - case 0x00020005:
868 - brightness = 5;
869 - break;
870 -
871 - case 0x00040003:
872 - brightness = 6;
873 - break;
874 -
875 - case 0x00030004:
876 - default:
877 - brightness = 7;
878 - }
879 -
880 - /* set lcd brightness GPIOs */
881 - for (i = 0; i <= 2; i++) {
882 - qemu_set_irq(s->out[i], (brightness >> i) & 1);
883 - }
884 -}
885 -
886 -static void musicpal_gpio_pin_event(void *opaque, int pin, int level)
887 -{
888 - musicpal_gpio_state *s = opaque;
889 - uint32_t mask = 1 << pin;
890 - uint32_t delta = level << pin;
891 - uint32_t old = s->in_state & mask;
892 -
893 - s->in_state &= ~mask;
894 - s->in_state |= delta;
895 -
896 - if ((old ^ delta) &&
897 - ((level && (s->imr & mask)) || (!level && (s->ier & mask)))) {
898 - s->isr = mask;
899 - qemu_irq_raise(s->irq);
900 - }
901 -}
902 -
903 -static uint64_t musicpal_gpio_read(void *opaque, hwaddr offset,
904 - unsigned size)
905 -{
906 - musicpal_gpio_state *s = opaque;
907 -
908 - switch (offset) {
909 - case MP_GPIO_OE_HI: /* used for LCD brightness control */
910 - return s->lcd_brightness & MP_OE_LCD_BRIGHTNESS;
911 -
912 - case MP_GPIO_OUT_LO:
913 - return s->out_state & 0xFFFF;
914 - case MP_GPIO_OUT_HI:
915 - return s->out_state >> 16;
916 -
917 - case MP_GPIO_IN_LO:
918 - return s->in_state & 0xFFFF;
919 - case MP_GPIO_IN_HI:
920 - return s->in_state >> 16;
921 -
922 - case MP_GPIO_IER_LO:
923 - return s->ier & 0xFFFF;
924 - case MP_GPIO_IER_HI:
925 - return s->ier >> 16;
926 -
927 - case MP_GPIO_IMR_LO:
928 - return s->imr & 0xFFFF;
929 - case MP_GPIO_IMR_HI:
930 - return s->imr >> 16;
931 -
932 - case MP_GPIO_ISR_LO:
933 - return s->isr & 0xFFFF;
934 - case MP_GPIO_ISR_HI:
935 - return s->isr >> 16;
936 -
937 - default:
938 - return 0;
939 - }
940 -}
941 -
942 -static void musicpal_gpio_write(void *opaque, hwaddr offset,
943 - uint64_t value, unsigned size)
944 -{
945 - musicpal_gpio_state *s = opaque;
946 - switch (offset) {
947 - case MP_GPIO_OE_HI: /* used for LCD brightness control */
948 - s->lcd_brightness = (s->lcd_brightness & MP_GPIO_LCD_BRIGHTNESS) |
949 - (value & MP_OE_LCD_BRIGHTNESS);
950 - musicpal_gpio_brightness_update(s);
951 - break;
952 -
953 - case MP_GPIO_OUT_LO:
954 - s->out_state = (s->out_state & 0xFFFF0000) | (value & 0xFFFF);
955 - break;
956 - case MP_GPIO_OUT_HI:
957 - s->out_state = (s->out_state & 0xFFFF) | (value << 16);
958 - s->lcd_brightness = (s->lcd_brightness & 0xFFFF) |
959 - (s->out_state & MP_GPIO_LCD_BRIGHTNESS);
960 - musicpal_gpio_brightness_update(s);
961 - qemu_set_irq(s->out[3], (s->out_state >> MP_GPIO_I2C_DATA_BIT) & 1);
962 - qemu_set_irq(s->out[4], (s->out_state >> MP_GPIO_I2C_CLOCK_BIT) & 1);
963 - break;
964 -
965 - case MP_GPIO_IER_LO:
966 - s->ier = (s->ier & 0xFFFF0000) | (value & 0xFFFF);
967 - break;
968 - case MP_GPIO_IER_HI:
969 - s->ier = (s->ier & 0xFFFF) | (value << 16);
970 - break;
971 -
972 - case MP_GPIO_IMR_LO:
973 - s->imr = (s->imr & 0xFFFF0000) | (value & 0xFFFF);
974 - break;
975 - case MP_GPIO_IMR_HI:
976 - s->imr = (s->imr & 0xFFFF) | (value << 16);
977 - break;
978 - }
979 -}
980 -
981 -static const MemoryRegionOps musicpal_gpio_ops = {
982 - .read = musicpal_gpio_read,
983 - .write = musicpal_gpio_write,
984 - .endianness = DEVICE_NATIVE_ENDIAN,
985 -};
986 -
987 -static void musicpal_gpio_reset(DeviceState *d)
988 -{
989 - musicpal_gpio_state *s = MUSICPAL_GPIO(d);
990 -
991 - s->lcd_brightness = 0;
992 - s->out_state = 0;
993 - s->in_state = 0xffffffff;
994 - s->ier = 0;
995 - s->imr = 0;
996 - s->isr = 0;
997 -}
998 -
999 -static void musicpal_gpio_init(Object *obj)
1000 -{
1001 - SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1002 - DeviceState *dev = DEVICE(sbd);
1003 - musicpal_gpio_state *s = MUSICPAL_GPIO(dev);
1004 -
1005 - sysbus_init_irq(sbd, &s->irq);
1006 -
1007 - memory_region_init_io(&s->iomem, obj, &musicpal_gpio_ops, s,
1008 - "musicpal-gpio", MP_GPIO_SIZE);
1009 - sysbus_init_mmio(sbd, &s->iomem);
1010 -
1011 - qdev_init_gpio_out(dev, s->out, ARRAY_SIZE(s->out));
1012 -
1013 - qdev_init_gpio_in(dev, musicpal_gpio_pin_event, 32);
1014 -}
1015 -
1016 -static const VMStateDescription musicpal_gpio_vmsd = {
1017 - .name = "musicpal_gpio",
1018 - .version_id = 1,
1019 - .minimum_version_id = 1,
1020 - .fields = (const VMStateField[]) {
1021 - VMSTATE_UINT32(lcd_brightness, musicpal_gpio_state),
1022 - VMSTATE_UINT32(out_state, musicpal_gpio_state),
1023 - VMSTATE_UINT32(in_state, musicpal_gpio_state),
1024 - VMSTATE_UINT32(ier, musicpal_gpio_state),
1025 - VMSTATE_UINT32(imr, musicpal_gpio_state),
1026 - VMSTATE_UINT32(isr, musicpal_gpio_state),
1027 - VMSTATE_END_OF_LIST()
1028 - }
1029 -};
1030 -
1031 -static void musicpal_gpio_class_init(ObjectClass *klass, const void *data)
1032 -{
1033 - DeviceClass *dc = DEVICE_CLASS(klass);
1034 -
1035 - device_class_set_legacy_reset(dc, musicpal_gpio_reset);
1036 - dc->vmsd = &musicpal_gpio_vmsd;
1037 -}
1038 -
1039 -static const TypeInfo musicpal_gpio_info = {
1040 - .name = TYPE_MUSICPAL_GPIO,
1041 - .parent = TYPE_SYS_BUS_DEVICE,
1042 - .instance_size = sizeof(musicpal_gpio_state),
1043 - .instance_init = musicpal_gpio_init,
1044 - .class_init = musicpal_gpio_class_init,
1045 -};
1046 -
1047 -/* Keyboard codes & masks */
1048 -#define MP_KEY_WHEEL_VOL (1 << 0)
1049 -#define MP_KEY_WHEEL_VOL_INV (1 << 1)
1050 -#define MP_KEY_WHEEL_NAV (1 << 2)
1051 -#define MP_KEY_WHEEL_NAV_INV (1 << 3)
1052 -#define MP_KEY_BTN_FAVORITS (1 << 4)
1053 -#define MP_KEY_BTN_MENU (1 << 5)
1054 -#define MP_KEY_BTN_VOLUME (1 << 6)
1055 -#define MP_KEY_BTN_NAVIGATION (1 << 7)
1056 -
1057 -#define TYPE_MUSICPAL_KEY "musicpal_key"
1058 -OBJECT_DECLARE_SIMPLE_TYPE(musicpal_key_state, MUSICPAL_KEY)
1059 -
1060 -struct musicpal_key_state {
1061 - /*< private >*/
1062 - SysBusDevice parent_obj;
1063 - /*< public >*/
1064 -
1065 - QemuInputHandlerState *hs;
1066 - uint32_t pressed_keys;
1067 - qemu_irq out[8];
1068 -};
1069 -
1070 -static void musicpal_key_event(DeviceState *dev, QemuConsole *src,
1071 - QemuInputEvent *evt)
1072 -{
1073 - musicpal_key_state *s = MUSICPAL_KEY(dev);
1074 - uint32_t event = 0;
1075 - int i;
1076 -
1077 - switch (evt->key.key) {
1078 - case KEY_UP:
1079 - event = MP_KEY_WHEEL_NAV | MP_KEY_WHEEL_NAV_INV;
1080 - break;
1081 -
1082 - case KEY_DOWN:
1083 - event = MP_KEY_WHEEL_NAV;
1084 - break;
1085 -
1086 - case KEY_LEFT:
1087 - event = MP_KEY_WHEEL_VOL | MP_KEY_WHEEL_VOL_INV;
1088 - break;
1089 -
1090 - case KEY_RIGHT:
1091 - event = MP_KEY_WHEEL_VOL;
1092 - break;
1093 -
1094 - case KEY_F:
1095 - event = MP_KEY_BTN_FAVORITS;
1096 - break;
1097 -
1098 - case KEY_TAB:
1099 - event = MP_KEY_BTN_VOLUME;
1100 - break;
1101 -
1102 - case KEY_ENTER:
1103 - event = MP_KEY_BTN_NAVIGATION;
1104 - break;
1105 -
1106 - case KEY_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 (evt->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 (evt->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], !evt->key.down);
1133 - }
1134 - }
1135 - if (evt->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 - musicpal_key_state *s = MUSICPAL_KEY(dev);
1163 -
1164 - s->hs = qemu_input_handler_register(dev, &musicpal_key_handler);
1165 -}
1166 -
1167 -static void musicpal_key_unrealize(DeviceState *dev)
1168 -{
1169 - musicpal_key_state *s = MUSICPAL_KEY(dev);
1170 -
1171 - g_clear_pointer(&s->hs, qemu_input_handler_unregister);
1172 -}
1173 -
1174 -static const VMStateDescription musicpal_key_vmsd = {
1175 - .name = "musicpal_key",
1176 - .version_id = 2,
1177 - .minimum_version_id = 2,
1178 - .fields = (const VMStateField[]) {
1179 - VMSTATE_UINT32(pressed_keys, musicpal_key_state),
1180 - VMSTATE_END_OF_LIST()
1181 - }
1182 -};
1183 -
1184 -static void musicpal_key_class_init(ObjectClass *klass, const void *data)
1185 -{
1186 - DeviceClass *dc = DEVICE_CLASS(klass);
1187 -
1188 - dc->vmsd = &musicpal_key_vmsd;
1189 - dc->realize = musicpal_key_realize;
1190 - dc->unrealize = musicpal_key_unrealize;
1191 -}
1192 -
1193 -static const TypeInfo musicpal_key_info = {
1194 - .name = TYPE_MUSICPAL_KEY,
1195 - .parent = TYPE_SYS_BUS_DEVICE,
1196 - .instance_size = sizeof(musicpal_key_state),
1197 - .instance_init = musicpal_key_init,
1198 - .class_init = musicpal_key_class_init,
1199 -};
1200 -
1201 -#define FLASH_SECTOR_SIZE (64 * KiB)
1202 -
1203 -#define TYPE_MUSICPAL_MACHINE MACHINE_TYPE_NAME("musicpal")
1204 -OBJECT_DECLARE_SIMPLE_TYPE(MusicPalMachineState, MUSICPAL_MACHINE)
1205 -
1206 -struct MusicPalMachineState {
1207 - MachineState parent;
1208 -
1209 - struct arm_boot_info bootinfo;
1210 -};
1211 -
1212 -static void musicpal_init(MachineState *machine)
1213 -{
1214 - MusicPalMachineState *mpms = MUSICPAL_MACHINE(machine);
1215 - ARMCPU *cpu;
1216 - DeviceState *dev;
1217 - DeviceState *pic;
1218 - DeviceState *uart_orgate;
1219 - DeviceState *i2c_dev;
1220 - DeviceState *lcd_dev;
1221 - DeviceState *key_dev;
1222 - I2CSlave *wm8750_dev;
1223 - SysBusDevice *s;
1224 - I2CBus *i2c;
1225 - int i;
1226 - unsigned long flash_size;
1227 - DriveInfo *dinfo;
1228 - MachineClass *mc = MACHINE_GET_CLASS(machine);
1229 - MemoryRegion *address_space_mem = get_system_memory();
1230 - MemoryRegion *sram = g_new(MemoryRegion, 1);
1231 -
1232 - /* For now we use a fixed - the original - RAM size */
1233 - if (machine->ram_size != mc->default_ram_size) {
1234 - char *sz = size_to_str(mc->default_ram_size);
1235 - error_report("Invalid RAM size, should be %s", sz);
1236 - g_free(sz);
1237 - exit(EXIT_FAILURE);
1238 - }
1239 -
1240 - cpu = ARM_CPU(cpu_create(machine->cpu_type));
1241 -
1242 - memory_region_add_subregion(address_space_mem, 0, machine->ram);
1243 -
1244 - memory_region_init_ram(sram, NULL, "musicpal.sram", MP_SRAM_SIZE,
1245 - &error_fatal);
1246 - memory_region_add_subregion(address_space_mem, MP_SRAM_BASE, sram);
1247 -
1248 - pic = sysbus_create_simple(TYPE_MV88W8618_PIC, MP_PIC_BASE,
1249 - qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
1250 - sysbus_create_varargs(TYPE_MV88W8618_PIT, MP_PIT_BASE,
1251 - qdev_get_gpio_in(pic, MP_TIMER1_IRQ),
1252 - qdev_get_gpio_in(pic, MP_TIMER2_IRQ),
1253 - qdev_get_gpio_in(pic, MP_TIMER3_IRQ),
1254 - qdev_get_gpio_in(pic, MP_TIMER4_IRQ), NULL);
1255 -
1256 - /* Logically OR both UART IRQs together */
1257 - uart_orgate = qdev_new(TYPE_OR_IRQ);
1258 - object_property_set_int(OBJECT(uart_orgate), "num-lines", 2, &error_fatal);
1259 - qdev_realize_and_unref(uart_orgate, NULL, &error_fatal);
1260 - qdev_connect_gpio_out(uart_orgate, 0,
1261 - qdev_get_gpio_in(pic, MP_UART_SHARED_IRQ));
1262 -
1263 - serial_mm_init(address_space_mem, MP_UART1_BASE, 2,
1264 - qdev_get_gpio_in(uart_orgate, 0),
1265 - 1825000, serial_hd(0), DEVICE_NATIVE_ENDIAN);
1266 - serial_mm_init(address_space_mem, MP_UART2_BASE, 2,
1267 - qdev_get_gpio_in(uart_orgate, 1),
1268 - 1825000, serial_hd(1), DEVICE_NATIVE_ENDIAN);
1269 -
1270 - /* Register flash */
1271 - dinfo = drive_get(IF_PFLASH, 0, 0);
1272 - if (dinfo) {
1273 - BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
1274 -
1275 - flash_size = blk_getlength(blk);
1276 - if (flash_size != 8 * MiB && flash_size != 16 * MiB &&
1277 - flash_size != 32 * MiB) {
1278 - error_report("Invalid flash image size");
1279 - exit(1);
1280 - }
1281 -
1282 - /*
1283 - * The original U-Boot accesses the flash at 0xFE000000 instead of
1284 - * 0xFF800000 (if there is 8 MB flash). So remap flash access if the
1285 - * image is smaller than 32 MB.
1286 - */
1287 - pflash_cfi02_register(0x100000000ULL - MP_FLASH_SIZE_MAX,
1288 - "musicpal.flash", flash_size,
1289 - blk, FLASH_SECTOR_SIZE,
1290 - MP_FLASH_SIZE_MAX / flash_size,
1291 - 2, 0x00BF, 0x236D, 0x0000, 0x0000,
1292 - 0x5555, 0x2AAA, 0);
1293 - }
1294 - sysbus_create_simple(TYPE_MV88W8618_FLASHCFG, MP_FLASHCFG_BASE, NULL);
1295 -
1296 - dev = qdev_new(TYPE_MV88W8618_ETH);
1297 - qemu_configure_nic_device(dev, true, "mv88w8618");
1298 - object_property_set_link(OBJECT(dev), "dma-memory",
1299 - OBJECT(get_system_memory()), &error_fatal);
1300 - sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
1301 - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, MP_ETH_BASE);
1302 - sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
1303 - qdev_get_gpio_in(pic, MP_ETH_IRQ));
1304 -
1305 - sysbus_create_simple("mv88w8618_wlan", MP_WLAN_BASE, NULL);
1306 -
1307 - sysbus_create_simple(TYPE_MUSICPAL_MISC, MP_MISC_BASE, NULL);
1308 -
1309 - dev = sysbus_create_simple(TYPE_MUSICPAL_GPIO, MP_GPIO_BASE,
1310 - qdev_get_gpio_in(pic, MP_GPIO_IRQ));
1311 - i2c_dev = sysbus_create_simple(TYPE_GPIO_I2C, -1, NULL);
1312 - i2c = (I2CBus *)qdev_get_child_bus(i2c_dev, "i2c");
1313 -
1314 - lcd_dev = sysbus_create_simple(TYPE_MUSICPAL_LCD, MP_LCD_BASE, NULL);
1315 - key_dev = sysbus_create_simple(TYPE_MUSICPAL_KEY, -1, NULL);
1316 -
1317 - /* I2C read data */
1318 - qdev_connect_gpio_out(i2c_dev, 0,
1319 - qdev_get_gpio_in(dev, MP_GPIO_I2C_DATA_BIT));
1320 - /* I2C data */
1321 - qdev_connect_gpio_out(dev, 3, qdev_get_gpio_in(i2c_dev, 0));
1322 - /* I2C clock */
1323 - qdev_connect_gpio_out(dev, 4, qdev_get_gpio_in(i2c_dev, 1));
1324 -
1325 - for (i = 0; i < 3; i++) {
1326 - qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(lcd_dev, i));
1327 - }
1328 - for (i = 0; i < 4; i++) {
1329 - qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 8));
1330 - }
1331 - for (i = 4; i < 8; i++) {
1332 - qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 15));
1333 - }
1334 -
1335 - wm8750_dev = i2c_slave_new(TYPE_WM8750, MP_WM_ADDR);
1336 - if (machine->audiodev) {
1337 - qdev_prop_set_string(DEVICE(wm8750_dev), "audiodev", machine->audiodev);
1338 - }
1339 - i2c_slave_realize_and_unref(wm8750_dev, i2c, &error_abort);
1340 -
1341 - dev = qdev_new(TYPE_MV88W8618_AUDIO);
1342 - s = SYS_BUS_DEVICE(dev);
1343 - object_property_set_link(OBJECT(dev), "wm8750", OBJECT(wm8750_dev),
1344 - NULL);
1345 - sysbus_realize_and_unref(s, &error_fatal);
1346 - sysbus_mmio_map(s, 0, MP_AUDIO_BASE);
1347 - sysbus_connect_irq(s, 0, qdev_get_gpio_in(pic, MP_AUDIO_IRQ));
1348 -
1349 - mpms->bootinfo.loader_start = 0x0;
1350 - mpms->bootinfo.board_id = 0x20e;
1351 - mpms->bootinfo.ram_size = MP_RAM_DEFAULT_SIZE;
1352 - arm_load_kernel(cpu, machine, &mpms->bootinfo);
1353 -}
1354 -
1355 -static void musicpal_machine_init(MachineClass *mc)
1356 -{
1357 - mc->desc = "Marvell 88w8618 / MusicPal (ARM926EJ-S)";
1358 - mc->init = musicpal_init;
1359 - mc->ignore_memory_transaction_failures = true;
1360 - mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926");
1361 - mc->default_ram_size = MP_RAM_DEFAULT_SIZE;
1362 - mc->default_ram_id = "musicpal.ram";
1363 -
1364 - machine_add_audiodev_property(mc);
1365 -}
1366 -
1367 -DEFINE_MACHINE_EXTENDED("musicpal", MACHINE, MusicPalMachineState,
1368 - musicpal_machine_init, false,
1369 - arm_machine_interfaces)
1370 -
1371 -static void mv88w8618_wlan_class_init(ObjectClass *klass, const void *data)
1372 -{
1373 - DeviceClass *dc = DEVICE_CLASS(klass);
1374 -
1375 - dc->realize = mv88w8618_wlan_realize;
1376 -}
1377 -
1378 -static const TypeInfo mv88w8618_wlan_info = {
1379 - .name = "mv88w8618_wlan",
1380 - .parent = TYPE_SYS_BUS_DEVICE,
1381 - .instance_size = sizeof(SysBusDevice),
1382 - .class_init = mv88w8618_wlan_class_init,
1383 -};
1384 -
1385 -static void musicpal_register_types(void)
1386 -{
1387 - type_register_static(&mv88w8618_pic_info);
1388 - type_register_static(&mv88w8618_pit_info);
1389 - type_register_static(&mv88w8618_flashcfg_info);
1390 - type_register_static(&mv88w8618_wlan_info);
1391 - type_register_static(&musicpal_lcd_info);
1392 - type_register_static(&musicpal_gpio_info);
1393 - type_register_static(&musicpal_key_info);
1394 - type_register_static(&musicpal_misc_info);
1395 -}
1396 -
1397 -type_init(musicpal_register_types)