All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] arm: Remove the 'musicpal' machine
@ 2026-08-19 18:54 Peter Maydell
  2026-08-19 18:54 ` [PATCH 1/5] tests/qtest/pflash-cfi02-test: Don't use musicpal machine for testing Peter Maydell
                   ` (5 more replies)
  0 siblings, 6 replies; 18+ messages in thread
From: Peter Maydell @ 2026-08-19 18:54 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Pierrick Bouvier, Philippe Mathieu-Daudé, Jan Kiszka

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
 * We have no test image for it that we can distribute
 * The only bug report we've ever had about it has been one of
   the usual "bug found by static analysis" kind (#4135)

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.

This patchset first fixes up a couple of places (notably the
pflash_cfi02 tests) that were using or referring to the musicpal
board; then it removes the board, followed by the devices used only by
that board.

Strictly speaking it's possible that somebody is using this machine
with some other image that doesn't have the same "does an unaligned
LDRH" problem the stock firmware image does; but it seems unlikely
to me. We can take the standard "deprecate for two releases, then
drop" route if people prefer that.

I do also have a patch which reverts the "take a Data Abort on
unaligned access" change for v5 and v6-with-SCTLR.U=0 CPUs, which I'll
post separately.

thanks
-- PMM

Peter Maydell (5):
  tests/qtest/pflash-cfi02-test: Don't use musicpal machine for testing
  hw/arm: Remove spurious WM8750 dependency from Realview Kconfig
  hw/arm: Remove the 'musicpal' machine
  hw: Remove Marvell 88W8618 devices
  hw/audio: Remove wm8750 I2C audio device

 MAINTAINERS                             |   10 -
 configs/devices/arm-softmmu/default.mak |    1 -
 docs/about/removed-features.rst         |   10 +
 docs/system/arm/musicpal.rst            |   19 -
 docs/system/target-arm.rst              |    1 -
 hw/arm/Kconfig                          |   16 -
 hw/arm/meson.build                      |    1 -
 hw/arm/musicpal.c                       | 1388 -----------------------
 hw/audio/Kconfig                        |    4 -
 hw/audio/marvell_88w8618.c              |  315 -----
 hw/audio/meson.build                    |    2 -
 hw/audio/wm8750.c                       |  738 ------------
 hw/net/meson.build                      |    1 -
 hw/net/mv88w8618_eth.c                  |  403 -------
 include/hw/audio/wm8750.h               |   30 -
 include/hw/net/mv88w8618_eth.h          |   13 -
 tests/qtest/meson.build                 |    6 +-
 tests/qtest/pflash-cfi02-test.c         |   38 +-
 18 files changed, 36 insertions(+), 2960 deletions(-)
 delete mode 100644 docs/system/arm/musicpal.rst
 delete mode 100644 hw/arm/musicpal.c
 delete mode 100644 hw/audio/marvell_88w8618.c
 delete mode 100644 hw/audio/wm8750.c
 delete mode 100644 hw/net/mv88w8618_eth.c
 delete mode 100644 include/hw/audio/wm8750.h
 delete mode 100644 include/hw/net/mv88w8618_eth.h

-- 
2.43.0



^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 1/5] tests/qtest/pflash-cfi02-test: Don't use musicpal machine for testing
  2026-08-19 18:54 [PATCH 0/5] arm: Remove the 'musicpal' machine Peter Maydell
@ 2026-08-19 18:54 ` Peter Maydell
  2026-08-20 11:13   ` Philippe Mathieu-Daudé
  2026-08-19 18:54 ` [PATCH 2/5] hw/arm: Remove spurious WM8750 dependency from Realview Kconfig Peter Maydell
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 18+ messages in thread
From: Peter Maydell @ 2026-08-19 18:54 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Pierrick Bouvier, Philippe Mathieu-Daudé, Jan Kiszka

We currently use the musicpal machine for testing the pflash-cfi02
device.  We'd like to remove that machine, so switch the tests to the
sh4 r2d board type instead.

We use r2d because it happens to have the same "2 bank" config that
musicpal did.  (Of our other options, xilinx-zynq-a9 has only a
1-bank setup so wouldn't allow the same range of testing, and the
canon-a1100 board both doesn't support specifying a flash drive via
-drive if=pflash, plus it seems likely it too might be a candidate
for deprecate-and-drop.)

The r2d flash device is not quite the same config as the musicpal
one: it has a different base address and size, and different
ID values. So we need to update the test to match.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 tests/qtest/meson.build         |  6 +++---
 tests/qtest/pflash-cfi02-test.c | 38 ++++++++++++++++++++-------------
 2 files changed, 26 insertions(+), 18 deletions(-)

diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index f7c7d06620..1f0f04e36c 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -196,7 +196,9 @@ qtests_ppc64 = \
   (config_all_devices.has_key('CONFIG_USB_XHCI_NEC') ? ['usb-hcd-xhci-test'] : []) +         \
   qtests_pci + ['migration-test', 'cpu-plug-test', 'drive_del-test']
 
-qtests_sh4 = (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : [])
+qtests_sh4 = (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \
+  (config_all_devices.has_key('CONFIG_PFLASH_CFI02') and
+   config_all_devices.has_key('CONFIG_R2D') ? ['pflash-cfi02-test'] : [])
 qtests_sh4eb = (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : [])
 
 qtests_sparc = ['prom-env-test', 'm48t59-test', 'boot-serial-test'] + \
@@ -243,8 +245,6 @@ qtests_arm = \
   (config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \
   (config_all_devices.has_key('CONFIG_STELLARIS') or
    config_all_devices.has_key('CONFIG_MPS2') ? ['cmsdk-apb-watchdog-test'] : []) + \
-  (config_all_devices.has_key('CONFIG_PFLASH_CFI02') and
-   config_all_devices.has_key('CONFIG_MUSICPAL') ? ['pflash-cfi02-test'] : []) + \
   (config_all_devices.has_key('CONFIG_ASPEED_SOC') ? qtests_aspeed : []) + \
   (config_all_devices.has_key('CONFIG_NPCM7XX') ? qtests_npcm7xx : []) + \
   (config_all_devices.has_key('CONFIG_GENERIC_LOADER') ? ['hexloader-test'] : []) + \
diff --git a/tests/qtest/pflash-cfi02-test.c b/tests/qtest/pflash-cfi02-test.c
index 8c073efcb4..fe630c9c16 100644
--- a/tests/qtest/pflash-cfi02-test.c
+++ b/tests/qtest/pflash-cfi02-test.c
@@ -11,17 +11,25 @@
 #include "libqtest.h"
 
 /*
- * To test the pflash_cfi02 device, we run QEMU with the musicpal machine with
+ * To test the pflash_cfi02 device, we run QEMU with the sh4 r2d machine with
  * a pflash drive. This enables us to test some flash configurations, but not
  * all. In particular, we're limited to a 16-bit wide flash device.
  */
 
-#define MP_FLASH_SIZE_MAX (32 * 1024 * 1024)
-#define BASE_ADDR (0x100000000ULL - MP_FLASH_SIZE_MAX)
+/*
+ * These need to match the flash size and address in r2d.c.
+ * If the flash size changes then the sector_len[] and nb_blocs[]
+ * values in configuration[] below will need to be updated to match.
+ */
+#define BASE_ADDR 0x00000000
 
-#define UNIFORM_FLASH_SIZE (8 * 1024 * 1024)
+#define UNIFORM_FLASH_SIZE (16 * 1024 * 1024)
 #define UNIFORM_FLASH_SECTOR_SIZE (64 * 1024)
 
+/* These must match the id0, id1 args to pflash_cfi02_register() in r2d.c */
+#define FLASH_ID0 0x0001
+#define FLASH_ID1 0x227E
+
 /* Use a newtype to keep flash addresses separate from byte addresses. */
 typedef struct {
     uint64_t addr;
@@ -260,7 +268,7 @@ static void test_geometry(const void *opaque)
 {
     const FlashConfig *config = opaque;
     QTestState *qtest;
-    qtest = qtest_initf("-M musicpal"
+    qtest = qtest_initf("-M r2d"
                         " -drive if=pflash,file=%s,format=raw,copy-on-read=on"
                         /* Device geometry properties. */
                         " -global driver=cfi.pflash02,"
@@ -295,16 +303,16 @@ static void test_geometry(const void *opaque)
     /* Check the IDs. */
     unlock(c);
     flash_cmd(c, UNLOCK0_ADDR, AUTOSELECT_CMD);
-    g_assert_cmphex(flash_query(c, FLASH_ADDR(0)), ==, replicate(c, 0xBF));
+    g_assert_cmphex(flash_query(c, FLASH_ADDR(0)), ==, replicate(c, FLASH_ID0));
     if (c->bank_width >= 2) {
         /*
-         * XXX: The ID returned by the musicpal flash chip is 16 bits which
+         * XXX: The ID returned by the r2d flash chip is 16 bits which
          * wouldn't happen with an 8-bit device. It would probably be best to
          * prohibit addresses larger than the device width in pflash_cfi02.c,
          * but then we couldn't test smaller device widths at all.
          */
         g_assert_cmphex(flash_query(c, FLASH_ADDR(1)), ==,
-                        replicate(c, 0x236D));
+                        replicate(c, FLASH_ID1));
     }
     reset(c);
 
@@ -436,7 +444,7 @@ static void test_geometry(const void *opaque)
     flash_cmd(c, FLASH_ADDR(0x5555), UNLOCK0_CMD);
     flash_cmd(c, FLASH_ADDR(0x2AAA), UNLOCK1_CMD);
     flash_cmd(c, FLASH_ADDR(0x5555), AUTOSELECT_CMD);
-    g_assert_cmphex(flash_query(c, FLASH_ADDR(0)), ==, replicate(c, 0xBF));
+    g_assert_cmphex(flash_query(c, FLASH_ADDR(0)), ==, replicate(c, FLASH_ID0));
     reset(c);
 
     /*
@@ -580,7 +588,7 @@ static void test_cfi_in_autoselect(const void *opaque)
 {
     const FlashConfig *config = opaque;
     QTestState *qtest;
-    qtest = qtest_initf("-M musicpal"
+    qtest = qtest_initf("-M r2d"
                         " -drive if=pflash,file=%s,format=raw,copy-on-read=on",
                         image_path);
     FlashConfig explicit_config = expand_config_defaults(config);
@@ -590,7 +598,7 @@ static void test_cfi_in_autoselect(const void *opaque)
     /* 1. Enter autoselect. */
     unlock(c);
     flash_cmd(c, UNLOCK0_ADDR, AUTOSELECT_CMD);
-    g_assert_cmphex(flash_query(c, FLASH_ADDR(0)), ==, replicate(c, 0xBF));
+    g_assert_cmphex(flash_query(c, FLASH_ADDR(0)), ==, replicate(c, FLASH_ID0));
 
     /* 2. Enter CFI. */
     flash_cmd(c, CFI_ADDR, CFI_CMD);
@@ -600,7 +608,7 @@ static void test_cfi_in_autoselect(const void *opaque)
 
     /* 3. Exit CFI. */
     reset(c);
-    g_assert_cmphex(flash_query(c, FLASH_ADDR(0)), ==, replicate(c, 0xBF));
+    g_assert_cmphex(flash_query(c, FLASH_ADDR(0)), ==, replicate(c, FLASH_ID0));
 
     qtest_quit(qtest);
 }
@@ -613,7 +621,7 @@ static void cleanup(void *opaque)
 
 /*
  * XXX: Tests are limited to bank_width = 2 for now because that's what
- * hw/arm/musicpal.c has.
+ * hw/sh4/r2d.c has.
  */
 static const FlashConfig configuration[] = {
     /* One x16 device. */
@@ -624,13 +632,13 @@ static const FlashConfig configuration[] = {
     {
         .bank_width = 2,
         .nb_blocs = { 127, 1, 2, 1 },
-        .sector_len = { 0x10000, 0x08000, 0x02000, 0x04000 },
+        .sector_len = { 0x20000, 0x10000, 0x04000, 0x08000 },
     },
     /* Nonuniform sectors (bottom boot). */
     {
         .bank_width = 2,
         .nb_blocs = { 1, 2, 1, 127 },
-        .sector_len = { 0x04000, 0x02000, 0x08000, 0x10000 },
+        .sector_len = { 0x08000, 0x04000, 0x10000, 0x20000 },
     },
 };
 
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 2/5] hw/arm: Remove spurious WM8750 dependency from Realview Kconfig
  2026-08-19 18:54 [PATCH 0/5] arm: Remove the 'musicpal' machine Peter Maydell
  2026-08-19 18:54 ` [PATCH 1/5] tests/qtest/pflash-cfi02-test: Don't use musicpal machine for testing Peter Maydell
@ 2026-08-19 18:54 ` Peter Maydell
  2026-08-19 19:37   ` Richard Henderson
  2026-08-20 10:55   ` Philippe Mathieu-Daudé
  2026-08-19 18:54 ` [PATCH 3/5] hw/arm: Remove the 'musicpal' machine Peter Maydell
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 18+ messages in thread
From: Peter Maydell @ 2026-08-19 18:54 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Pierrick Bouvier, Philippe Mathieu-Daudé, Jan Kiszka

The REALVIEW Kconfig stanza has a "select WM8750"; however the board
itself doesn't actually use this i2c audio device: its audio is
provided by the pl041 (which connects to an LM4549). Remove the
spurious dependency.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/arm/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 260d2f0751..5e9a0bd8dc 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -155,7 +155,6 @@ config REALVIEW
     select ARM11MPCORE
     select ARM_TIMER
     select VERSATILE_PCI
-    select WM8750 # audio codec
     select LSI_SCSI_PCI
     select PCI
     select PL011 # UART
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 3/5] hw/arm: Remove the 'musicpal' machine
  2026-08-19 18:54 [PATCH 0/5] arm: Remove the 'musicpal' machine Peter Maydell
  2026-08-19 18:54 ` [PATCH 1/5] tests/qtest/pflash-cfi02-test: Don't use musicpal machine for testing Peter Maydell
  2026-08-19 18:54 ` [PATCH 2/5] hw/arm: Remove spurious WM8750 dependency from Realview Kconfig Peter Maydell
@ 2026-08-19 18:54 ` Peter Maydell
  2026-08-19 19:35   ` Richard Henderson
  2026-08-20 10:55   ` Philippe Mathieu-Daudé
  2026-08-19 18:54 ` [PATCH 4/5] hw: Remove Marvell 88W8618 devices Peter Maydell
                   ` (2 subsequent siblings)
  5 siblings, 2 replies; 18+ messages in thread
From: Peter Maydell @ 2026-08-19 18:54 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Pierrick Bouvier, Philippe Mathieu-Daudé, Jan Kiszka

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>
---
 MAINTAINERS                             |   10 -
 configs/devices/arm-softmmu/default.mak |    1 -
 docs/about/removed-features.rst         |   10 +
 docs/system/arm/musicpal.rst            |   19 -
 docs/system/target-arm.rst              |    1 -
 hw/arm/Kconfig                          |   12 -
 hw/arm/meson.build                      |    1 -
 hw/arm/musicpal.c                       | 1388 -----------------------
 8 files changed, 10 insertions(+), 1432 deletions(-)
 delete mode 100644 docs/system/arm/musicpal.rst
 delete mode 100644 hw/arm/musicpal.c

diff --git a/MAINTAINERS b/MAINTAINERS
index b51f5c3e60..ac6b049399 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -993,16 +993,6 @@ S: Odd Fixes
 F: hw/arm/musca.c
 F: docs/system/arm/musca.rst
 
-Musicpal
-M: Jan Kiszka <jan.kiszka@web.de>
-M: Peter Maydell <peter.maydell@linaro.org>
-L: qemu-arm@nongnu.org
-S: Odd Fixes
-F: hw/arm/musicpal.c
-F: hw/net/mv88w8618_eth.c
-F: include/hw/net/mv88w8618_eth.h
-F: docs/system/arm/musicpal.rst
-
 Nuvoton NPCM7xx
 M: Tyrone Ting <kfting@nuvoton.com>
 M: Hao Wu <wuhaotsh@google.com>
diff --git a/configs/devices/arm-softmmu/default.mak b/configs/devices/arm-softmmu/default.mak
index 71cf164511..22caa6a63e 100644
--- a/configs/devices/arm-softmmu/default.mak
+++ b/configs/devices/arm-softmmu/default.mak
@@ -14,7 +14,6 @@
 # CONFIG_EXYNOS4=n
 # CONFIG_INTEGRATOR=n
 # CONFIG_FSL_IMX31=n
-# CONFIG_MUSICPAL=n
 # CONFIG_MPS3R=n
 # CONFIG_MUSCA=n
 # CONFIG_SX1=n
diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst
index 0735b4ea1d..6a9944a0c7 100644
--- a/docs/about/removed-features.rst
+++ b/docs/about/removed-features.rst
@@ -1251,6 +1251,16 @@ machine they want to use to avoid confusion.  Existing users of the ``spike``
 machine must ensure that they're setting the ``spike`` machine in the
 command line (``-M spike``).
 
+Arm ``musicpal`` machine (removed in 11.2)
+''''''''''''''''''''''''''''''''''''''''''
+
+The ``musicpal`` machine was an emulation of the Freecom MusicPal, an
+"internet radio" device from the mid-2000s. This hardware was never
+supported in upstream Linux, was based on a Marvell SoC with no public
+documentation, and is now obsolete. We accidentally broke booting this
+board in 2024, without anybody noticing; it has therefore been removed
+without a deprecation period.
+
 linux-user mode CPUs
 --------------------
 
diff --git a/docs/system/arm/musicpal.rst b/docs/system/arm/musicpal.rst
deleted file mode 100644
index 9de380edf8..0000000000
--- a/docs/system/arm/musicpal.rst
+++ /dev/null
@@ -1,19 +0,0 @@
-Freecom MusicPal (``musicpal``)
-===============================
-
-The Freecom MusicPal internet radio emulation includes the following
-elements:
-
--  Marvell MV88W8618 Arm core.
-
--  32 MB RAM, 256 KB SRAM, 8 MB flash.
-
--  Up to 2 16550 UARTs
-
--  MV88W8xx8 Ethernet controller
-
--  MV88W8618 audio controller, WM8750 CODEC and mixer
-
--  128x64 display with brightness control
-
--  2 buttons, 2 navigation wheels with button function
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
index e34492402f..260cd7e4d6 100644
--- a/docs/system/target-arm.rst
+++ b/docs/system/target-arm.rst
@@ -87,7 +87,6 @@ Board-specific documentation
    arm/cubieboard
    arm/emcraft-sf2
    arm/exynos
-   arm/musicpal
    arm/kzm
    arm/nrf
    arm/nuvoton
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 5e9a0bd8dc..57db2a2fdf 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -103,18 +103,6 @@ config MUSCA
 config MARVELL_88W8618
     bool
 
-config MUSICPAL
-    bool
-    default y
-    depends on TCG && ARM
-    select OR_IRQ
-    select BITBANG_I2C
-    select MARVELL_88W8618
-    select PTIMER
-    select PFLASH_CFI02
-    select SERIAL_MM
-    select WM8750
-
 config NETDUINO2
     bool
     default y
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index 8ee5307a91..78acb04c8b 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -6,7 +6,6 @@ arm_common_ss.add(when: 'CONFIG_EMCRAFT_SF2', if_true: files('msf2-som.c'))
 arm_common_ss.add(when: 'CONFIG_INTEGRATOR', if_true: files('integratorcp.c'))
 arm_common_ss.add(when: 'CONFIG_MICROBIT', if_true: files('microbit.c'))
 arm_common_ss.add(when: 'CONFIG_MPS3R', if_true: files('mps3r.c'))
-arm_common_ss.add(when: 'CONFIG_MUSICPAL', if_true: [files('musicpal.c')])
 arm_common_ss.add(when: 'CONFIG_NETDUINOPLUS2', if_true: files('netduinoplus2.c'))
 arm_common_ss.add(when: 'CONFIG_OLIMEX_STM32_H405', if_true: files('olimex-stm32-h405.c'))
 arm_common_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx.c', 'npcm7xx_boards.c'))
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
deleted file mode 100644
index 69e83bdd97..0000000000
--- a/hw/arm/musicpal.c
+++ /dev/null
@@ -1,1388 +0,0 @@
-/*
- * Marvell MV88W8618 / Freecom MusicPal emulation.
- *
- * Copyright (c) 2008 Jan Kiszka
- *
- * This code is licensed under the GNU GPL v2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "qemu/osdep.h"
-#include "qemu/units.h"
-#include "qapi/error.h"
-#include "hw/core/sysbus.h"
-#include "migration/vmstate.h"
-#include "hw/arm/boot.h"
-#include "hw/arm/machines-qom.h"
-#include "net/net.h"
-#include "system/system.h"
-#include "hw/core/boards.h"
-#include "hw/char/serial-mm.h"
-#include "qemu/timer.h"
-#include "hw/core/ptimer.h"
-#include "hw/core/qdev-properties.h"
-#include "hw/block/flash.h"
-#include "standard-headers/linux/input-event-codes.h"
-#include "ui/console.h"
-#include "hw/i2c/i2c.h"
-#include "hw/i2c/bitbang_i2c.h"
-#include "hw/core/irq.h"
-#include "hw/core/or-irq.h"
-#include "hw/audio/wm8750.h"
-#include "system/block-backend.h"
-#include "system/runstate.h"
-#include "system/dma.h"
-#include "ui/pixel_ops.h"
-#include "qemu/cutils.h"
-#include "qom/object.h"
-#include "hw/net/mv88w8618_eth.h"
-#include "qemu/error-report.h"
-#include "target/arm/cpu-qom.h"
-
-#define MP_MISC_BASE            0x80002000
-#define MP_MISC_SIZE            0x00001000
-
-#define MP_ETH_BASE             0x80008000
-
-#define MP_WLAN_BASE            0x8000C000
-#define MP_WLAN_SIZE            0x00000800
-
-#define MP_UART1_BASE           0x8000C840
-#define MP_UART2_BASE           0x8000C940
-
-#define MP_GPIO_BASE            0x8000D000
-#define MP_GPIO_SIZE            0x00001000
-
-#define MP_FLASHCFG_BASE        0x90006000
-#define MP_FLASHCFG_SIZE        0x00001000
-
-#define MP_AUDIO_BASE           0x90007000
-
-#define MP_PIC_BASE             0x90008000
-#define MP_PIC_SIZE             0x00001000
-
-#define MP_PIT_BASE             0x90009000
-#define MP_PIT_SIZE             0x00001000
-
-#define MP_LCD_BASE             0x9000c000
-#define MP_LCD_SIZE             0x00001000
-
-#define MP_SRAM_BASE            0xC0000000
-#define MP_SRAM_SIZE            0x00020000
-
-#define MP_RAM_DEFAULT_SIZE     32*1024*1024
-#define MP_FLASH_SIZE_MAX       32*1024*1024
-
-#define MP_TIMER1_IRQ           4
-#define MP_TIMER2_IRQ           5
-#define MP_TIMER3_IRQ           6
-#define MP_TIMER4_IRQ           7
-#define MP_EHCI_IRQ             8
-#define MP_ETH_IRQ              9
-#define MP_UART_SHARED_IRQ      11
-#define MP_GPIO_IRQ             12
-#define MP_RTC_IRQ              28
-#define MP_AUDIO_IRQ            30
-
-/* Wolfson 8750 I2C address */
-#define MP_WM_ADDR              0x1A
-
-/* LCD register offsets */
-#define MP_LCD_IRQCTRL          0x180
-#define MP_LCD_IRQSTAT          0x184
-#define MP_LCD_SPICTRL          0x1ac
-#define MP_LCD_INST             0x1bc
-#define MP_LCD_DATA             0x1c0
-
-/* Mode magics */
-#define MP_LCD_SPI_DATA         0x00100011
-#define MP_LCD_SPI_CMD          0x00104011
-#define MP_LCD_SPI_INVALID      0x00000000
-
-/* Commands */
-#define MP_LCD_INST_SETPAGE0    0xB0
-/* ... */
-#define MP_LCD_INST_SETPAGE7    0xB7
-
-#define MP_LCD_TEXTCOLOR        0xe0e0ff /* RRGGBB */
-
-#define TYPE_MUSICPAL_LCD "musicpal_lcd"
-OBJECT_DECLARE_SIMPLE_TYPE(musicpal_lcd_state, MUSICPAL_LCD)
-
-struct musicpal_lcd_state {
-    /*< private >*/
-    SysBusDevice parent_obj;
-    /*< public >*/
-
-    MemoryRegion iomem;
-    uint32_t brightness;
-    uint32_t mode;
-    uint32_t irqctrl;
-    uint32_t page;
-    uint32_t page_off;
-    QemuConsole *con;
-    uint8_t video_ram[128*64/8];
-};
-
-static uint8_t scale_lcd_color(musicpal_lcd_state *s, uint8_t col)
-{
-    switch (s->brightness) {
-    case 7:
-        return col;
-    case 0:
-        return 0;
-    default:
-        return (col * s->brightness) / 7;
-    }
-}
-
-static inline void set_lcd_pixel32(musicpal_lcd_state *s,
-                                   int x, int y, uint32_t col)
-{
-    int dx, dy;
-    DisplaySurface *surface = qemu_console_surface(s->con);
-    uint32_t *pixel =
-        &((uint32_t *) surface_data(surface))[(y * 128 * 3 + x) * 3];
-
-    for (dy = 0; dy < 3; dy++, pixel += 127 * 3) {
-        for (dx = 0; dx < 3; dx++, pixel++) {
-            *pixel = col;
-        }
-    }
-}
-
-static bool lcd_refresh(void *opaque)
-{
-    musicpal_lcd_state *s = opaque;
-    int x, y, col;
-
-    col = rgb_to_pixel32(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff),
-                         scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff),
-                         scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff));
-    for (x = 0; x < 128; x++) {
-        for (y = 0; y < 64; y++) {
-            if (s->video_ram[x + (y / 8) * 128] & (1 << (y % 8))) {
-                set_lcd_pixel32(s, x, y, col);
-            } else {
-                set_lcd_pixel32(s, x, y, 0);
-            }
-        }
-    }
-
-    qemu_console_update(s->con, 0, 0, 128*3, 64*3);
-    return true;
-}
-
-static void lcd_invalidate(void *opaque)
-{
-}
-
-static void musicpal_lcd_gpio_brightness_in(void *opaque, int irq, int level)
-{
-    musicpal_lcd_state *s = opaque;
-    s->brightness &= ~(1 << irq);
-    s->brightness |= level << irq;
-}
-
-static uint64_t musicpal_lcd_read(void *opaque, hwaddr offset,
-                                  unsigned size)
-{
-    musicpal_lcd_state *s = opaque;
-
-    switch (offset) {
-    case MP_LCD_IRQCTRL:
-        return s->irqctrl;
-
-    default:
-        return 0;
-    }
-}
-
-static void musicpal_lcd_write(void *opaque, hwaddr offset,
-                               uint64_t value, unsigned size)
-{
-    musicpal_lcd_state *s = opaque;
-
-    switch (offset) {
-    case MP_LCD_IRQCTRL:
-        s->irqctrl = value;
-        break;
-
-    case MP_LCD_SPICTRL:
-        if (value == MP_LCD_SPI_DATA || value == MP_LCD_SPI_CMD) {
-            s->mode = value;
-        } else {
-            s->mode = MP_LCD_SPI_INVALID;
-        }
-        break;
-
-    case MP_LCD_INST:
-        if (value >= MP_LCD_INST_SETPAGE0 && value <= MP_LCD_INST_SETPAGE7) {
-            s->page = value - MP_LCD_INST_SETPAGE0;
-            s->page_off = 0;
-        }
-        break;
-
-    case MP_LCD_DATA:
-        if (s->mode == MP_LCD_SPI_CMD) {
-            if (value >= MP_LCD_INST_SETPAGE0 &&
-                value <= MP_LCD_INST_SETPAGE7) {
-                s->page = value - MP_LCD_INST_SETPAGE0;
-                s->page_off = 0;
-            }
-        } else if (s->mode == MP_LCD_SPI_DATA) {
-            s->video_ram[s->page*128 + s->page_off] = value;
-            s->page_off = (s->page_off + 1) & 127;
-        }
-        break;
-    }
-}
-
-static const MemoryRegionOps musicpal_lcd_ops = {
-    .read = musicpal_lcd_read,
-    .write = musicpal_lcd_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const GraphicHwOps musicpal_gfx_ops = {
-    .invalidate  = lcd_invalidate,
-    .gfx_update  = lcd_refresh,
-};
-
-static void musicpal_lcd_realize(DeviceState *dev, Error **errp)
-{
-    musicpal_lcd_state *s = MUSICPAL_LCD(dev);
-    s->con = qemu_graphic_console_create(dev, 0, &musicpal_gfx_ops, s);
-    qemu_console_resize(s->con, 128 * 3, 64 * 3);
-}
-
-static void musicpal_lcd_init(Object *obj)
-{
-    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
-    DeviceState *dev = DEVICE(sbd);
-    musicpal_lcd_state *s = MUSICPAL_LCD(dev);
-
-    s->brightness = 7;
-
-    memory_region_init_io(&s->iomem, obj, &musicpal_lcd_ops, s,
-                          "musicpal-lcd", MP_LCD_SIZE);
-    sysbus_init_mmio(sbd, &s->iomem);
-
-    qdev_init_gpio_in(dev, musicpal_lcd_gpio_brightness_in, 3);
-}
-
-static const VMStateDescription musicpal_lcd_vmsd = {
-    .name = "musicpal_lcd",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (const VMStateField[]) {
-        VMSTATE_UINT32(brightness, musicpal_lcd_state),
-        VMSTATE_UINT32(mode, musicpal_lcd_state),
-        VMSTATE_UINT32(irqctrl, musicpal_lcd_state),
-        VMSTATE_UINT32(page, musicpal_lcd_state),
-        VMSTATE_UINT32(page_off, musicpal_lcd_state),
-        VMSTATE_BUFFER(video_ram, musicpal_lcd_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void musicpal_lcd_class_init(ObjectClass *klass, const void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    dc->vmsd = &musicpal_lcd_vmsd;
-    dc->realize = musicpal_lcd_realize;
-}
-
-static const TypeInfo musicpal_lcd_info = {
-    .name          = TYPE_MUSICPAL_LCD,
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(musicpal_lcd_state),
-    .instance_init = musicpal_lcd_init,
-    .class_init    = musicpal_lcd_class_init,
-};
-
-/* PIC register offsets */
-#define MP_PIC_STATUS           0x00
-#define MP_PIC_ENABLE_SET       0x08
-#define MP_PIC_ENABLE_CLR       0x0C
-
-#define TYPE_MV88W8618_PIC "mv88w8618_pic"
-OBJECT_DECLARE_SIMPLE_TYPE(mv88w8618_pic_state, MV88W8618_PIC)
-
-struct mv88w8618_pic_state {
-    /*< private >*/
-    SysBusDevice parent_obj;
-    /*< public >*/
-
-    MemoryRegion iomem;
-    uint32_t level;
-    uint32_t enabled;
-    qemu_irq parent_irq;
-};
-
-static void mv88w8618_pic_update(mv88w8618_pic_state *s)
-{
-    qemu_set_irq(s->parent_irq, (s->level & s->enabled));
-}
-
-static void mv88w8618_pic_set_irq(void *opaque, int irq, int level)
-{
-    mv88w8618_pic_state *s = opaque;
-
-    if (level) {
-        s->level |= 1 << irq;
-    } else {
-        s->level &= ~(1 << irq);
-    }
-    mv88w8618_pic_update(s);
-}
-
-static uint64_t mv88w8618_pic_read(void *opaque, hwaddr offset,
-                                   unsigned size)
-{
-    mv88w8618_pic_state *s = opaque;
-
-    switch (offset) {
-    case MP_PIC_STATUS:
-        return s->level & s->enabled;
-
-    default:
-        return 0;
-    }
-}
-
-static void mv88w8618_pic_write(void *opaque, hwaddr offset,
-                                uint64_t value, unsigned size)
-{
-    mv88w8618_pic_state *s = opaque;
-
-    switch (offset) {
-    case MP_PIC_ENABLE_SET:
-        s->enabled |= value;
-        break;
-
-    case MP_PIC_ENABLE_CLR:
-        s->enabled &= ~value;
-        s->level &= ~value;
-        break;
-    }
-    mv88w8618_pic_update(s);
-}
-
-static void mv88w8618_pic_reset(DeviceState *d)
-{
-    mv88w8618_pic_state *s = MV88W8618_PIC(d);
-
-    s->level = 0;
-    s->enabled = 0;
-}
-
-static const MemoryRegionOps mv88w8618_pic_ops = {
-    .read = mv88w8618_pic_read,
-    .write = mv88w8618_pic_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void mv88w8618_pic_init(Object *obj)
-{
-    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
-    mv88w8618_pic_state *s = MV88W8618_PIC(dev);
-
-    qdev_init_gpio_in(DEVICE(dev), mv88w8618_pic_set_irq, 32);
-    sysbus_init_irq(dev, &s->parent_irq);
-    memory_region_init_io(&s->iomem, obj, &mv88w8618_pic_ops, s,
-                          "musicpal-pic", MP_PIC_SIZE);
-    sysbus_init_mmio(dev, &s->iomem);
-}
-
-static const VMStateDescription mv88w8618_pic_vmsd = {
-    .name = "mv88w8618_pic",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (const VMStateField[]) {
-        VMSTATE_UINT32(level, mv88w8618_pic_state),
-        VMSTATE_UINT32(enabled, mv88w8618_pic_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void mv88w8618_pic_class_init(ObjectClass *klass, const void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    device_class_set_legacy_reset(dc, mv88w8618_pic_reset);
-    dc->vmsd = &mv88w8618_pic_vmsd;
-}
-
-static const TypeInfo mv88w8618_pic_info = {
-    .name          = TYPE_MV88W8618_PIC,
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(mv88w8618_pic_state),
-    .instance_init = mv88w8618_pic_init,
-    .class_init    = mv88w8618_pic_class_init,
-};
-
-/* PIT register offsets */
-#define MP_PIT_TIMER1_LENGTH    0x00
-/* ... */
-#define MP_PIT_TIMER4_LENGTH    0x0C
-#define MP_PIT_CONTROL          0x10
-#define MP_PIT_TIMER1_VALUE     0x14
-/* ... */
-#define MP_PIT_TIMER4_VALUE     0x20
-#define MP_BOARD_RESET          0x34
-
-/* Magic board reset value (probably some watchdog behind it) */
-#define MP_BOARD_RESET_MAGIC    0x10000
-
-typedef struct mv88w8618_timer_state {
-    ptimer_state *ptimer;
-    uint32_t limit;
-    int freq;
-    qemu_irq irq;
-} mv88w8618_timer_state;
-
-#define TYPE_MV88W8618_PIT "mv88w8618_pit"
-OBJECT_DECLARE_SIMPLE_TYPE(mv88w8618_pit_state, MV88W8618_PIT)
-
-struct mv88w8618_pit_state {
-    /*< private >*/
-    SysBusDevice parent_obj;
-    /*< public >*/
-
-    MemoryRegion iomem;
-    mv88w8618_timer_state timer[4];
-};
-
-static void mv88w8618_timer_tick(void *opaque)
-{
-    mv88w8618_timer_state *s = opaque;
-
-    qemu_irq_raise(s->irq);
-}
-
-static void mv88w8618_timer_init(SysBusDevice *dev, mv88w8618_timer_state *s,
-                                 uint32_t freq)
-{
-    sysbus_init_irq(dev, &s->irq);
-    s->freq = freq;
-
-    s->ptimer = ptimer_init(mv88w8618_timer_tick, s, PTIMER_POLICY_LEGACY);
-}
-
-static uint64_t mv88w8618_pit_read(void *opaque, hwaddr offset,
-                                   unsigned size)
-{
-    mv88w8618_pit_state *s = opaque;
-    mv88w8618_timer_state *t;
-
-    switch (offset) {
-    case MP_PIT_TIMER1_VALUE ... MP_PIT_TIMER4_VALUE:
-        t = &s->timer[(offset-MP_PIT_TIMER1_VALUE) >> 2];
-        return ptimer_get_count(t->ptimer);
-
-    default:
-        return 0;
-    }
-}
-
-static void mv88w8618_pit_write(void *opaque, hwaddr offset,
-                                uint64_t value, unsigned size)
-{
-    mv88w8618_pit_state *s = opaque;
-    mv88w8618_timer_state *t;
-    int i;
-
-    switch (offset) {
-    case MP_PIT_TIMER1_LENGTH ... MP_PIT_TIMER4_LENGTH:
-        t = &s->timer[offset >> 2];
-        t->limit = value;
-        ptimer_transaction_begin(t->ptimer);
-        if (t->limit > 0) {
-            ptimer_set_limit(t->ptimer, t->limit, 1);
-        } else {
-            ptimer_stop(t->ptimer);
-        }
-        ptimer_transaction_commit(t->ptimer);
-        break;
-
-    case MP_PIT_CONTROL:
-        for (i = 0; i < 4; i++) {
-            t = &s->timer[i];
-            ptimer_transaction_begin(t->ptimer);
-            if (value & 0xf && t->limit > 0) {
-                ptimer_set_limit(t->ptimer, t->limit, 0);
-                ptimer_set_freq(t->ptimer, t->freq);
-                ptimer_run(t->ptimer, 0);
-            } else {
-                ptimer_stop(t->ptimer);
-            }
-            ptimer_transaction_commit(t->ptimer);
-            value >>= 4;
-        }
-        break;
-
-    case MP_BOARD_RESET:
-        if (value == MP_BOARD_RESET_MAGIC) {
-            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
-        }
-        break;
-    }
-}
-
-static void mv88w8618_pit_reset(DeviceState *d)
-{
-    mv88w8618_pit_state *s = MV88W8618_PIT(d);
-    int i;
-
-    for (i = 0; i < 4; i++) {
-        mv88w8618_timer_state *t = &s->timer[i];
-        ptimer_transaction_begin(t->ptimer);
-        ptimer_stop(t->ptimer);
-        ptimer_transaction_commit(t->ptimer);
-        t->limit = 0;
-    }
-}
-
-static const MemoryRegionOps mv88w8618_pit_ops = {
-    .read = mv88w8618_pit_read,
-    .write = mv88w8618_pit_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void mv88w8618_pit_init(Object *obj)
-{
-    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
-    mv88w8618_pit_state *s = MV88W8618_PIT(dev);
-    int i;
-
-    /* Letting them all run at 1 MHz is likely just a pragmatic
-     * simplification. */
-    for (i = 0; i < 4; i++) {
-        mv88w8618_timer_init(dev, &s->timer[i], 1000000);
-    }
-
-    memory_region_init_io(&s->iomem, obj, &mv88w8618_pit_ops, s,
-                          "musicpal-pit", MP_PIT_SIZE);
-    sysbus_init_mmio(dev, &s->iomem);
-}
-
-static void mv88w8618_pit_finalize(Object *obj)
-{
-    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
-    mv88w8618_pit_state *s = MV88W8618_PIT(dev);
-    int i;
-
-    for (i = 0; i < 4; i++) {
-        ptimer_free(s->timer[i].ptimer);
-    }
-}
-
-static const VMStateDescription mv88w8618_timer_vmsd = {
-    .name = "timer",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (const VMStateField[]) {
-        VMSTATE_PTIMER(ptimer, mv88w8618_timer_state),
-        VMSTATE_UINT32(limit, mv88w8618_timer_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static const VMStateDescription mv88w8618_pit_vmsd = {
-    .name = "mv88w8618_pit",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (const VMStateField[]) {
-        VMSTATE_STRUCT_ARRAY(timer, mv88w8618_pit_state, 4, 1,
-                             mv88w8618_timer_vmsd, mv88w8618_timer_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void mv88w8618_pit_class_init(ObjectClass *klass, const void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    device_class_set_legacy_reset(dc, mv88w8618_pit_reset);
-    dc->vmsd = &mv88w8618_pit_vmsd;
-}
-
-static const TypeInfo mv88w8618_pit_info = {
-    .name          = TYPE_MV88W8618_PIT,
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(mv88w8618_pit_state),
-    .instance_init = mv88w8618_pit_init,
-    .instance_finalize = mv88w8618_pit_finalize,
-    .class_init    = mv88w8618_pit_class_init,
-};
-
-/* Flash config register offsets */
-#define MP_FLASHCFG_CFGR0    0x04
-
-#define TYPE_MV88W8618_FLASHCFG "mv88w8618_flashcfg"
-OBJECT_DECLARE_SIMPLE_TYPE(mv88w8618_flashcfg_state, MV88W8618_FLASHCFG)
-
-struct mv88w8618_flashcfg_state {
-    /*< private >*/
-    SysBusDevice parent_obj;
-    /*< public >*/
-
-    MemoryRegion iomem;
-    uint32_t cfgr0;
-};
-
-static uint64_t mv88w8618_flashcfg_read(void *opaque,
-                                        hwaddr offset,
-                                        unsigned size)
-{
-    mv88w8618_flashcfg_state *s = opaque;
-
-    switch (offset) {
-    case MP_FLASHCFG_CFGR0:
-        return s->cfgr0;
-
-    default:
-        return 0;
-    }
-}
-
-static void mv88w8618_flashcfg_write(void *opaque, hwaddr offset,
-                                     uint64_t value, unsigned size)
-{
-    mv88w8618_flashcfg_state *s = opaque;
-
-    switch (offset) {
-    case MP_FLASHCFG_CFGR0:
-        s->cfgr0 = value;
-        break;
-    }
-}
-
-static const MemoryRegionOps mv88w8618_flashcfg_ops = {
-    .read = mv88w8618_flashcfg_read,
-    .write = mv88w8618_flashcfg_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void mv88w8618_flashcfg_init(Object *obj)
-{
-    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
-    mv88w8618_flashcfg_state *s = MV88W8618_FLASHCFG(dev);
-
-    s->cfgr0 = 0xfffe4285; /* Default as set by U-Boot for 8 MB flash */
-    memory_region_init_io(&s->iomem, obj, &mv88w8618_flashcfg_ops, s,
-                          "musicpal-flashcfg", MP_FLASHCFG_SIZE);
-    sysbus_init_mmio(dev, &s->iomem);
-}
-
-static const VMStateDescription mv88w8618_flashcfg_vmsd = {
-    .name = "mv88w8618_flashcfg",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (const VMStateField[]) {
-        VMSTATE_UINT32(cfgr0, mv88w8618_flashcfg_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void mv88w8618_flashcfg_class_init(ObjectClass *klass, const void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    dc->vmsd = &mv88w8618_flashcfg_vmsd;
-}
-
-static const TypeInfo mv88w8618_flashcfg_info = {
-    .name          = TYPE_MV88W8618_FLASHCFG,
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(mv88w8618_flashcfg_state),
-    .instance_init = mv88w8618_flashcfg_init,
-    .class_init    = mv88w8618_flashcfg_class_init,
-};
-
-/* Misc register offsets */
-#define MP_MISC_BOARD_REVISION  0x18
-
-#define MP_BOARD_REVISION       0x31
-
-struct MusicPalMiscState {
-    SysBusDevice parent_obj;
-    MemoryRegion iomem;
-};
-
-#define TYPE_MUSICPAL_MISC "musicpal-misc"
-OBJECT_DECLARE_SIMPLE_TYPE(MusicPalMiscState, MUSICPAL_MISC)
-
-static uint64_t musicpal_misc_read(void *opaque, hwaddr offset,
-                                   unsigned size)
-{
-    switch (offset) {
-    case MP_MISC_BOARD_REVISION:
-        return MP_BOARD_REVISION;
-
-    default:
-        return 0;
-    }
-}
-
-static void musicpal_misc_write(void *opaque, hwaddr offset,
-                                uint64_t value, unsigned size)
-{
-}
-
-static const MemoryRegionOps musicpal_misc_ops = {
-    .read = musicpal_misc_read,
-    .write = musicpal_misc_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void musicpal_misc_init(Object *obj)
-{
-    SysBusDevice *sd = SYS_BUS_DEVICE(obj);
-    MusicPalMiscState *s = MUSICPAL_MISC(obj);
-
-    memory_region_init_io(&s->iomem, OBJECT(s), &musicpal_misc_ops, NULL,
-                          "musicpal-misc", MP_MISC_SIZE);
-    sysbus_init_mmio(sd, &s->iomem);
-}
-
-static const TypeInfo musicpal_misc_info = {
-    .name = TYPE_MUSICPAL_MISC,
-    .parent = TYPE_SYS_BUS_DEVICE,
-    .instance_init = musicpal_misc_init,
-    .instance_size = sizeof(MusicPalMiscState),
-};
-
-/* WLAN register offsets */
-#define MP_WLAN_MAGIC1          0x11c
-#define MP_WLAN_MAGIC2          0x124
-
-static uint64_t mv88w8618_wlan_read(void *opaque, hwaddr offset,
-                                    unsigned size)
-{
-    switch (offset) {
-    /* Workaround to allow loading the binary-only wlandrv.ko crap
-     * from the original Freecom firmware. */
-    case MP_WLAN_MAGIC1:
-        return ~3;
-    case MP_WLAN_MAGIC2:
-        return -1;
-
-    default:
-        return 0;
-    }
-}
-
-static void mv88w8618_wlan_write(void *opaque, hwaddr offset,
-                                 uint64_t value, unsigned size)
-{
-}
-
-static const MemoryRegionOps mv88w8618_wlan_ops = {
-    .read = mv88w8618_wlan_read,
-    .write =mv88w8618_wlan_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void mv88w8618_wlan_realize(DeviceState *dev, Error **errp)
-{
-    MemoryRegion *iomem = g_new(MemoryRegion, 1);
-
-    memory_region_init_io(iomem, OBJECT(dev), &mv88w8618_wlan_ops, NULL,
-                          "musicpal-wlan", MP_WLAN_SIZE);
-    sysbus_init_mmio(SYS_BUS_DEVICE(dev), iomem);
-}
-
-/* GPIO register offsets */
-#define MP_GPIO_OE_LO           0x008
-#define MP_GPIO_OUT_LO          0x00c
-#define MP_GPIO_IN_LO           0x010
-#define MP_GPIO_IER_LO          0x014
-#define MP_GPIO_IMR_LO          0x018
-#define MP_GPIO_ISR_LO          0x020
-#define MP_GPIO_OE_HI           0x508
-#define MP_GPIO_OUT_HI          0x50c
-#define MP_GPIO_IN_HI           0x510
-#define MP_GPIO_IER_HI          0x514
-#define MP_GPIO_IMR_HI          0x518
-#define MP_GPIO_ISR_HI          0x520
-
-/* GPIO bits & masks */
-#define MP_GPIO_LCD_BRIGHTNESS  0x00070000
-#define MP_GPIO_I2C_DATA_BIT    29
-#define MP_GPIO_I2C_CLOCK_BIT   30
-
-/* LCD brightness bits in GPIO_OE_HI */
-#define MP_OE_LCD_BRIGHTNESS    0x0007
-
-#define TYPE_MUSICPAL_GPIO "musicpal_gpio"
-OBJECT_DECLARE_SIMPLE_TYPE(musicpal_gpio_state, MUSICPAL_GPIO)
-
-struct musicpal_gpio_state {
-    /*< private >*/
-    SysBusDevice parent_obj;
-    /*< public >*/
-
-    MemoryRegion iomem;
-    uint32_t lcd_brightness;
-    uint32_t out_state;
-    uint32_t in_state;
-    uint32_t ier;
-    uint32_t imr;
-    uint32_t isr;
-    qemu_irq irq;
-    qemu_irq out[5]; /* 3 brightness out + 2 lcd (data and clock ) */
-};
-
-static void musicpal_gpio_brightness_update(musicpal_gpio_state *s) {
-    int i;
-    uint32_t brightness;
-
-    /* compute brightness ratio */
-    switch (s->lcd_brightness) {
-    case 0x00000007:
-        brightness = 0;
-        break;
-
-    case 0x00020000:
-        brightness = 1;
-        break;
-
-    case 0x00020001:
-        brightness = 2;
-        break;
-
-    case 0x00040000:
-        brightness = 3;
-        break;
-
-    case 0x00010006:
-        brightness = 4;
-        break;
-
-    case 0x00020005:
-        brightness = 5;
-        break;
-
-    case 0x00040003:
-        brightness = 6;
-        break;
-
-    case 0x00030004:
-    default:
-        brightness = 7;
-    }
-
-    /* set lcd brightness GPIOs  */
-    for (i = 0; i <= 2; i++) {
-        qemu_set_irq(s->out[i], (brightness >> i) & 1);
-    }
-}
-
-static void musicpal_gpio_pin_event(void *opaque, int pin, int level)
-{
-    musicpal_gpio_state *s = opaque;
-    uint32_t mask = 1 << pin;
-    uint32_t delta = level << pin;
-    uint32_t old = s->in_state & mask;
-
-    s->in_state &= ~mask;
-    s->in_state |= delta;
-
-    if ((old ^ delta) &&
-        ((level && (s->imr & mask)) || (!level && (s->ier & mask)))) {
-        s->isr = mask;
-        qemu_irq_raise(s->irq);
-    }
-}
-
-static uint64_t musicpal_gpio_read(void *opaque, hwaddr offset,
-                                   unsigned size)
-{
-    musicpal_gpio_state *s = opaque;
-
-    switch (offset) {
-    case MP_GPIO_OE_HI: /* used for LCD brightness control */
-        return s->lcd_brightness & MP_OE_LCD_BRIGHTNESS;
-
-    case MP_GPIO_OUT_LO:
-        return s->out_state & 0xFFFF;
-    case MP_GPIO_OUT_HI:
-        return s->out_state >> 16;
-
-    case MP_GPIO_IN_LO:
-        return s->in_state & 0xFFFF;
-    case MP_GPIO_IN_HI:
-        return s->in_state >> 16;
-
-    case MP_GPIO_IER_LO:
-        return s->ier & 0xFFFF;
-    case MP_GPIO_IER_HI:
-        return s->ier >> 16;
-
-    case MP_GPIO_IMR_LO:
-        return s->imr & 0xFFFF;
-    case MP_GPIO_IMR_HI:
-        return s->imr >> 16;
-
-    case MP_GPIO_ISR_LO:
-        return s->isr & 0xFFFF;
-    case MP_GPIO_ISR_HI:
-        return s->isr >> 16;
-
-    default:
-        return 0;
-    }
-}
-
-static void musicpal_gpio_write(void *opaque, hwaddr offset,
-                                uint64_t value, unsigned size)
-{
-    musicpal_gpio_state *s = opaque;
-    switch (offset) {
-    case MP_GPIO_OE_HI: /* used for LCD brightness control */
-        s->lcd_brightness = (s->lcd_brightness & MP_GPIO_LCD_BRIGHTNESS) |
-                         (value & MP_OE_LCD_BRIGHTNESS);
-        musicpal_gpio_brightness_update(s);
-        break;
-
-    case MP_GPIO_OUT_LO:
-        s->out_state = (s->out_state & 0xFFFF0000) | (value & 0xFFFF);
-        break;
-    case MP_GPIO_OUT_HI:
-        s->out_state = (s->out_state & 0xFFFF) | (value << 16);
-        s->lcd_brightness = (s->lcd_brightness & 0xFFFF) |
-                            (s->out_state & MP_GPIO_LCD_BRIGHTNESS);
-        musicpal_gpio_brightness_update(s);
-        qemu_set_irq(s->out[3], (s->out_state >> MP_GPIO_I2C_DATA_BIT) & 1);
-        qemu_set_irq(s->out[4], (s->out_state >> MP_GPIO_I2C_CLOCK_BIT) & 1);
-        break;
-
-    case MP_GPIO_IER_LO:
-        s->ier = (s->ier & 0xFFFF0000) | (value & 0xFFFF);
-        break;
-    case MP_GPIO_IER_HI:
-        s->ier = (s->ier & 0xFFFF) | (value << 16);
-        break;
-
-    case MP_GPIO_IMR_LO:
-        s->imr = (s->imr & 0xFFFF0000) | (value & 0xFFFF);
-        break;
-    case MP_GPIO_IMR_HI:
-        s->imr = (s->imr & 0xFFFF) | (value << 16);
-        break;
-    }
-}
-
-static const MemoryRegionOps musicpal_gpio_ops = {
-    .read = musicpal_gpio_read,
-    .write = musicpal_gpio_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void musicpal_gpio_reset(DeviceState *d)
-{
-    musicpal_gpio_state *s = MUSICPAL_GPIO(d);
-
-    s->lcd_brightness = 0;
-    s->out_state = 0;
-    s->in_state = 0xffffffff;
-    s->ier = 0;
-    s->imr = 0;
-    s->isr = 0;
-}
-
-static void musicpal_gpio_init(Object *obj)
-{
-    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
-    DeviceState *dev = DEVICE(sbd);
-    musicpal_gpio_state *s = MUSICPAL_GPIO(dev);
-
-    sysbus_init_irq(sbd, &s->irq);
-
-    memory_region_init_io(&s->iomem, obj, &musicpal_gpio_ops, s,
-                          "musicpal-gpio", MP_GPIO_SIZE);
-    sysbus_init_mmio(sbd, &s->iomem);
-
-    qdev_init_gpio_out(dev, s->out, ARRAY_SIZE(s->out));
-
-    qdev_init_gpio_in(dev, musicpal_gpio_pin_event, 32);
-}
-
-static const VMStateDescription musicpal_gpio_vmsd = {
-    .name = "musicpal_gpio",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (const VMStateField[]) {
-        VMSTATE_UINT32(lcd_brightness, musicpal_gpio_state),
-        VMSTATE_UINT32(out_state, musicpal_gpio_state),
-        VMSTATE_UINT32(in_state, musicpal_gpio_state),
-        VMSTATE_UINT32(ier, musicpal_gpio_state),
-        VMSTATE_UINT32(imr, musicpal_gpio_state),
-        VMSTATE_UINT32(isr, musicpal_gpio_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void musicpal_gpio_class_init(ObjectClass *klass, const void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    device_class_set_legacy_reset(dc, musicpal_gpio_reset);
-    dc->vmsd = &musicpal_gpio_vmsd;
-}
-
-static const TypeInfo musicpal_gpio_info = {
-    .name          = TYPE_MUSICPAL_GPIO,
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(musicpal_gpio_state),
-    .instance_init = musicpal_gpio_init,
-    .class_init    = musicpal_gpio_class_init,
-};
-
-/* Keyboard codes & masks */
-#define MP_KEY_WHEEL_VOL       (1 << 0)
-#define MP_KEY_WHEEL_VOL_INV   (1 << 1)
-#define MP_KEY_WHEEL_NAV       (1 << 2)
-#define MP_KEY_WHEEL_NAV_INV   (1 << 3)
-#define MP_KEY_BTN_FAVORITS    (1 << 4)
-#define MP_KEY_BTN_MENU        (1 << 5)
-#define MP_KEY_BTN_VOLUME      (1 << 6)
-#define MP_KEY_BTN_NAVIGATION  (1 << 7)
-
-#define TYPE_MUSICPAL_KEY "musicpal_key"
-OBJECT_DECLARE_SIMPLE_TYPE(musicpal_key_state, MUSICPAL_KEY)
-
-struct musicpal_key_state {
-    /*< private >*/
-    SysBusDevice parent_obj;
-    /*< public >*/
-
-    QemuInputHandlerState *hs;
-    uint32_t pressed_keys;
-    qemu_irq out[8];
-};
-
-static void musicpal_key_event(DeviceState *dev, QemuConsole *src,
-                               QemuInputEvent *evt)
-{
-    musicpal_key_state *s = MUSICPAL_KEY(dev);
-    uint32_t event = 0;
-    int i;
-
-    switch (evt->key.key) {
-    case KEY_UP:
-        event = MP_KEY_WHEEL_NAV | MP_KEY_WHEEL_NAV_INV;
-        break;
-
-    case KEY_DOWN:
-        event = MP_KEY_WHEEL_NAV;
-        break;
-
-    case KEY_LEFT:
-        event = MP_KEY_WHEEL_VOL | MP_KEY_WHEEL_VOL_INV;
-        break;
-
-    case KEY_RIGHT:
-        event = MP_KEY_WHEEL_VOL;
-        break;
-
-    case KEY_F:
-        event = MP_KEY_BTN_FAVORITS;
-        break;
-
-    case KEY_TAB:
-        event = MP_KEY_BTN_VOLUME;
-        break;
-
-    case KEY_ENTER:
-        event = MP_KEY_BTN_NAVIGATION;
-        break;
-
-    case KEY_M:
-        event = MP_KEY_BTN_MENU;
-        break;
-    }
-
-    /*
-     * We allow repeated wheel-events when the arrow keys are held down,
-     * but do not repeat already-pressed buttons for the other key inputs.
-     */
-    if (!(event & (MP_KEY_WHEEL_NAV | MP_KEY_WHEEL_VOL))) {
-        if (evt->key.down && (s->pressed_keys & event)) {
-            event = 0;
-        }
-    }
-
-    if (event) {
-        /* Raise GPIO pin first if repeating a key */
-        if (evt->key.down && (s->pressed_keys & event)) {
-            for (i = 0; i <= 7; i++) {
-                if (event & (1 << i)) {
-                    qemu_set_irq(s->out[i], 1);
-                }
-            }
-        }
-        for (i = 0; i <= 7; i++) {
-            if (event & (1 << i)) {
-                qemu_set_irq(s->out[i], !evt->key.down);
-            }
-        }
-        if (evt->key.down) {
-            s->pressed_keys |= event;
-        } else {
-            s->pressed_keys &= ~event;
-        }
-    }
-}
-
-static void musicpal_key_init(Object *obj)
-{
-    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
-    DeviceState *dev = DEVICE(sbd);
-    musicpal_key_state *s = MUSICPAL_KEY(dev);
-
-    s->pressed_keys = 0;
-
-    qdev_init_gpio_out(dev, s->out, ARRAY_SIZE(s->out));
-}
-
-static const QemuInputHandler musicpal_key_handler = {
-    .name = "musicpal_key",
-    .mask = INPUT_EVENT_MASK_KEY,
-    .event = musicpal_key_event,
-};
-
-static void musicpal_key_realize(DeviceState *dev, Error **errp)
-{
-    musicpal_key_state *s = MUSICPAL_KEY(dev);
-
-    s->hs = qemu_input_handler_register(dev, &musicpal_key_handler);
-}
-
-static void musicpal_key_unrealize(DeviceState *dev)
-{
-    musicpal_key_state *s = MUSICPAL_KEY(dev);
-
-    g_clear_pointer(&s->hs, qemu_input_handler_unregister);
-}
-
-static const VMStateDescription musicpal_key_vmsd = {
-    .name = "musicpal_key",
-    .version_id = 2,
-    .minimum_version_id = 2,
-    .fields = (const VMStateField[]) {
-        VMSTATE_UINT32(pressed_keys, musicpal_key_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void musicpal_key_class_init(ObjectClass *klass, const void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    dc->vmsd = &musicpal_key_vmsd;
-    dc->realize = musicpal_key_realize;
-    dc->unrealize = musicpal_key_unrealize;
-}
-
-static const TypeInfo musicpal_key_info = {
-    .name          = TYPE_MUSICPAL_KEY,
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(musicpal_key_state),
-    .instance_init = musicpal_key_init,
-    .class_init    = musicpal_key_class_init,
-};
-
-#define FLASH_SECTOR_SIZE   (64 * KiB)
-
-static struct arm_boot_info musicpal_binfo = {
-    .loader_start = 0x0,
-    .board_id = 0x20e,
-};
-
-static void musicpal_init(MachineState *machine)
-{
-    ARMCPU *cpu;
-    DeviceState *dev;
-    DeviceState *pic;
-    DeviceState *uart_orgate;
-    DeviceState *i2c_dev;
-    DeviceState *lcd_dev;
-    DeviceState *key_dev;
-    I2CSlave *wm8750_dev;
-    SysBusDevice *s;
-    I2CBus *i2c;
-    int i;
-    unsigned long flash_size;
-    DriveInfo *dinfo;
-    MachineClass *mc = MACHINE_GET_CLASS(machine);
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *sram = g_new(MemoryRegion, 1);
-
-    /* For now we use a fixed - the original - RAM size */
-    if (machine->ram_size != mc->default_ram_size) {
-        char *sz = size_to_str(mc->default_ram_size);
-        error_report("Invalid RAM size, should be %s", sz);
-        g_free(sz);
-        exit(EXIT_FAILURE);
-    }
-
-    cpu = ARM_CPU(cpu_create(machine->cpu_type));
-
-    memory_region_add_subregion(address_space_mem, 0, machine->ram);
-
-    memory_region_init_ram(sram, NULL, "musicpal.sram", MP_SRAM_SIZE,
-                           &error_fatal);
-    memory_region_add_subregion(address_space_mem, MP_SRAM_BASE, sram);
-
-    pic = sysbus_create_simple(TYPE_MV88W8618_PIC, MP_PIC_BASE,
-                               qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
-    sysbus_create_varargs(TYPE_MV88W8618_PIT, MP_PIT_BASE,
-                          qdev_get_gpio_in(pic, MP_TIMER1_IRQ),
-                          qdev_get_gpio_in(pic, MP_TIMER2_IRQ),
-                          qdev_get_gpio_in(pic, MP_TIMER3_IRQ),
-                          qdev_get_gpio_in(pic, MP_TIMER4_IRQ), NULL);
-
-    /* Logically OR both UART IRQs together */
-    uart_orgate = qdev_new(TYPE_OR_IRQ);
-    object_property_set_int(OBJECT(uart_orgate), "num-lines", 2, &error_fatal);
-    qdev_realize_and_unref(uart_orgate, NULL, &error_fatal);
-    qdev_connect_gpio_out(uart_orgate, 0,
-                          qdev_get_gpio_in(pic, MP_UART_SHARED_IRQ));
-
-    serial_mm_init(address_space_mem, MP_UART1_BASE, 2,
-                   qdev_get_gpio_in(uart_orgate, 0),
-                   1825000, serial_hd(0), DEVICE_NATIVE_ENDIAN);
-    serial_mm_init(address_space_mem, MP_UART2_BASE, 2,
-                   qdev_get_gpio_in(uart_orgate, 1),
-                   1825000, serial_hd(1), DEVICE_NATIVE_ENDIAN);
-
-    /* Register flash */
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    if (dinfo) {
-        BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
-
-        flash_size = blk_getlength(blk);
-        if (flash_size != 8 * MiB && flash_size != 16 * MiB &&
-            flash_size != 32 * MiB) {
-            error_report("Invalid flash image size");
-            exit(1);
-        }
-
-        /*
-         * The original U-Boot accesses the flash at 0xFE000000 instead of
-         * 0xFF800000 (if there is 8 MB flash). So remap flash access if the
-         * image is smaller than 32 MB.
-         */
-        pflash_cfi02_register(0x100000000ULL - MP_FLASH_SIZE_MAX,
-                              "musicpal.flash", flash_size,
-                              blk, FLASH_SECTOR_SIZE,
-                              MP_FLASH_SIZE_MAX / flash_size,
-                              2, 0x00BF, 0x236D, 0x0000, 0x0000,
-                              0x5555, 0x2AAA, 0);
-    }
-    sysbus_create_simple(TYPE_MV88W8618_FLASHCFG, MP_FLASHCFG_BASE, NULL);
-
-    dev = qdev_new(TYPE_MV88W8618_ETH);
-    qemu_configure_nic_device(dev, true, "mv88w8618");
-    object_property_set_link(OBJECT(dev), "dma-memory",
-                             OBJECT(get_system_memory()), &error_fatal);
-    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, MP_ETH_BASE);
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
-                       qdev_get_gpio_in(pic, MP_ETH_IRQ));
-
-    sysbus_create_simple("mv88w8618_wlan", MP_WLAN_BASE, NULL);
-
-    sysbus_create_simple(TYPE_MUSICPAL_MISC, MP_MISC_BASE, NULL);
-
-    dev = sysbus_create_simple(TYPE_MUSICPAL_GPIO, MP_GPIO_BASE,
-                               qdev_get_gpio_in(pic, MP_GPIO_IRQ));
-    i2c_dev = sysbus_create_simple(TYPE_GPIO_I2C, -1, NULL);
-    i2c = (I2CBus *)qdev_get_child_bus(i2c_dev, "i2c");
-
-    lcd_dev = sysbus_create_simple(TYPE_MUSICPAL_LCD, MP_LCD_BASE, NULL);
-    key_dev = sysbus_create_simple(TYPE_MUSICPAL_KEY, -1, NULL);
-
-    /* I2C read data */
-    qdev_connect_gpio_out(i2c_dev, 0,
-                          qdev_get_gpio_in(dev, MP_GPIO_I2C_DATA_BIT));
-    /* I2C data */
-    qdev_connect_gpio_out(dev, 3, qdev_get_gpio_in(i2c_dev, 0));
-    /* I2C clock */
-    qdev_connect_gpio_out(dev, 4, qdev_get_gpio_in(i2c_dev, 1));
-
-    for (i = 0; i < 3; i++) {
-        qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(lcd_dev, i));
-    }
-    for (i = 0; i < 4; i++) {
-        qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 8));
-    }
-    for (i = 4; i < 8; i++) {
-        qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 15));
-    }
-
-    wm8750_dev = i2c_slave_new(TYPE_WM8750, MP_WM_ADDR);
-    if (machine->audiodev) {
-        qdev_prop_set_string(DEVICE(wm8750_dev), "audiodev", machine->audiodev);
-    }
-    i2c_slave_realize_and_unref(wm8750_dev, i2c, &error_abort);
-
-    dev = qdev_new(TYPE_MV88W8618_AUDIO);
-    s = SYS_BUS_DEVICE(dev);
-    object_property_set_link(OBJECT(dev), "wm8750", OBJECT(wm8750_dev),
-                             NULL);
-    sysbus_realize_and_unref(s, &error_fatal);
-    sysbus_mmio_map(s, 0, MP_AUDIO_BASE);
-    sysbus_connect_irq(s, 0, qdev_get_gpio_in(pic, MP_AUDIO_IRQ));
-
-    musicpal_binfo.ram_size = MP_RAM_DEFAULT_SIZE;
-    arm_load_kernel(cpu, machine, &musicpal_binfo);
-}
-
-static void musicpal_machine_init(MachineClass *mc)
-{
-    mc->desc = "Marvell 88w8618 / MusicPal (ARM926EJ-S)";
-    mc->init = musicpal_init;
-    mc->ignore_memory_transaction_failures = true;
-    mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926");
-    mc->default_ram_size = MP_RAM_DEFAULT_SIZE;
-    mc->default_ram_id = "musicpal.ram";
-
-    machine_add_audiodev_property(mc);
-}
-
-DEFINE_MACHINE_ARM("musicpal", musicpal_machine_init)
-
-static void mv88w8618_wlan_class_init(ObjectClass *klass, const void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    dc->realize = mv88w8618_wlan_realize;
-}
-
-static const TypeInfo mv88w8618_wlan_info = {
-    .name          = "mv88w8618_wlan",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(SysBusDevice),
-    .class_init    = mv88w8618_wlan_class_init,
-};
-
-static void musicpal_register_types(void)
-{
-    type_register_static(&mv88w8618_pic_info);
-    type_register_static(&mv88w8618_pit_info);
-    type_register_static(&mv88w8618_flashcfg_info);
-    type_register_static(&mv88w8618_wlan_info);
-    type_register_static(&musicpal_lcd_info);
-    type_register_static(&musicpal_gpio_info);
-    type_register_static(&musicpal_key_info);
-    type_register_static(&musicpal_misc_info);
-}
-
-type_init(musicpal_register_types)
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 4/5] hw: Remove Marvell 88W8618 devices
  2026-08-19 18:54 [PATCH 0/5] arm: Remove the 'musicpal' machine Peter Maydell
                   ` (2 preceding siblings ...)
  2026-08-19 18:54 ` [PATCH 3/5] hw/arm: Remove the 'musicpal' machine Peter Maydell
@ 2026-08-19 18:54 ` Peter Maydell
  2026-08-19 19:35   ` Richard Henderson
  2026-08-20 10:59   ` Philippe Mathieu-Daudé
  2026-08-19 18:54 ` [PATCH 5/5] hw/audio: Remove wm8750 I2C audio device Peter Maydell
  2026-08-20 10:13 ` [PATCH 0/5] arm: Remove the 'musicpal' machine Jan Kiszka
  5 siblings, 2 replies; 18+ messages in thread
From: Peter Maydell @ 2026-08-19 18:54 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Pierrick Bouvier, Philippe Mathieu-Daudé, Jan Kiszka

The mv88w8618 ethernet and audio devices were used only by the
now-removed musicpal machine, so can also be deleted.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/arm/Kconfig                 |   3 -
 hw/audio/marvell_88w8618.c     | 315 --------------------------
 hw/audio/meson.build           |   1 -
 hw/net/meson.build             |   1 -
 hw/net/mv88w8618_eth.c         | 403 ---------------------------------
 include/hw/net/mv88w8618_eth.h |  13 --
 6 files changed, 736 deletions(-)
 delete mode 100644 hw/audio/marvell_88w8618.c
 delete mode 100644 hw/net/mv88w8618_eth.c
 delete mode 100644 include/hw/net/mv88w8618_eth.h

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 57db2a2fdf..5db7ce057f 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -100,9 +100,6 @@ config MUSCA
     select SPLIT_IRQ
     select UNIMP
 
-config MARVELL_88W8618
-    bool
-
 config NETDUINO2
     bool
     default y
diff --git a/hw/audio/marvell_88w8618.c b/hw/audio/marvell_88w8618.c
deleted file mode 100644
index 061d076dad..0000000000
--- a/hw/audio/marvell_88w8618.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Marvell 88w8618 audio emulation extracted from
- * Marvell MV88w8618 / Freecom MusicPal emulation.
- *
- * Copyright (c) 2008 Jan Kiszka
- *
- * This code is licensed under the GNU GPL v2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "qemu/osdep.h"
-#include "hw/core/sysbus.h"
-#include "exec/cpu-common.h"
-#include "migration/vmstate.h"
-#include "hw/core/irq.h"
-#include "hw/core/qdev-properties.h"
-#include "hw/audio/wm8750.h"
-#include "qemu/audio.h"
-#include "qapi/error.h"
-#include "qemu/module.h"
-#include "qom/object.h"
-#include "system/physmem.h"
-
-#define MP_AUDIO_SIZE           0x00001000
-
-/* Audio register offsets */
-#define MP_AUDIO_PLAYBACK_MODE  0x00
-#define MP_AUDIO_CLOCK_DIV      0x18
-#define MP_AUDIO_IRQ_STATUS     0x20
-#define MP_AUDIO_IRQ_ENABLE     0x24
-#define MP_AUDIO_TX_START_LO    0x28
-#define MP_AUDIO_TX_THRESHOLD   0x2C
-#define MP_AUDIO_TX_STATUS      0x38
-#define MP_AUDIO_TX_START_HI    0x40
-
-/* Status register and IRQ enable bits */
-#define MP_AUDIO_TX_HALF        (1 << 6)
-#define MP_AUDIO_TX_FULL        (1 << 7)
-
-/* Playback mode bits */
-#define MP_AUDIO_16BIT_SAMPLE   (1 << 0)
-#define MP_AUDIO_PLAYBACK_EN    (1 << 7)
-#define MP_AUDIO_CLOCK_24MHZ    (1 << 9)
-#define MP_AUDIO_MONO           (1 << 14)
-
-OBJECT_DECLARE_SIMPLE_TYPE(mv88w8618_audio_state, MV88W8618_AUDIO)
-
-struct mv88w8618_audio_state {
-    SysBusDevice parent_obj;
-
-    MemoryRegion iomem;
-    qemu_irq irq;
-    uint32_t playback_mode;
-    uint32_t status;
-    uint32_t irq_enable;
-    uint32_t phys_buf;
-    uint32_t target_buffer;
-    uint32_t threshold;
-    uint32_t play_pos;
-    uint32_t last_free;
-    uint32_t clock_div;
-    void *wm;
-};
-
-static void mv88w8618_audio_callback(void *opaque, int free_out, int free_in)
-{
-    mv88w8618_audio_state *s = opaque;
-    int16_t *codec_buffer;
-    QEMU_UNINITIALIZED int8_t buf[4096];
-    int8_t *mem_buffer;
-    int pos, block_size;
-
-    if (!(s->playback_mode & MP_AUDIO_PLAYBACK_EN)) {
-        return;
-    }
-    if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE) {
-        free_out <<= 1;
-    }
-    if (!(s->playback_mode & MP_AUDIO_MONO)) {
-        free_out <<= 1;
-    }
-    block_size = s->threshold / 2;
-    if (free_out - s->last_free < block_size) {
-        return;
-    }
-    if (block_size > 4096) {
-        return;
-    }
-    physical_memory_read(s->target_buffer + s->play_pos, buf, block_size);
-    mem_buffer = buf;
-    if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE) {
-        if (s->playback_mode & MP_AUDIO_MONO) {
-            codec_buffer = wm8750_dac_buffer(s->wm, block_size >> 1);
-            for (pos = 0; pos < block_size; pos += 2) {
-                *codec_buffer++ = *(int16_t *)mem_buffer;
-                *codec_buffer++ = *(int16_t *)mem_buffer;
-                mem_buffer += 2;
-            }
-        } else {
-            memcpy(wm8750_dac_buffer(s->wm, block_size >> 2),
-                   (uint32_t *)mem_buffer, block_size);
-        }
-    } else {
-        if (s->playback_mode & MP_AUDIO_MONO) {
-            codec_buffer = wm8750_dac_buffer(s->wm, block_size);
-            for (pos = 0; pos < block_size; pos++) {
-                *codec_buffer++ = cpu_to_le16(256 * *mem_buffer);
-                *codec_buffer++ = cpu_to_le16(256 * *mem_buffer++);
-            }
-        } else {
-            codec_buffer = wm8750_dac_buffer(s->wm, block_size >> 1);
-            for (pos = 0; pos < block_size; pos += 2) {
-                *codec_buffer++ = cpu_to_le16(256 * *mem_buffer++);
-                *codec_buffer++ = cpu_to_le16(256 * *mem_buffer++);
-            }
-        }
-    }
-    wm8750_dac_commit(s->wm);
-
-    s->last_free = free_out - block_size;
-
-    if (s->play_pos == 0) {
-        s->status |= MP_AUDIO_TX_HALF;
-        s->play_pos = block_size;
-    } else {
-        s->status |= MP_AUDIO_TX_FULL;
-        s->play_pos = 0;
-    }
-
-    if (s->status & s->irq_enable) {
-        qemu_irq_raise(s->irq);
-    }
-}
-
-static void mv88w8618_audio_clock_update(mv88w8618_audio_state *s)
-{
-    int rate;
-
-    if (s->playback_mode & MP_AUDIO_CLOCK_24MHZ) {
-        rate = 24576000 / 64; /* 24.576MHz */
-    } else {
-        rate = 11289600 / 64; /* 11.2896MHz */
-    }
-    rate /= ((s->clock_div >> 8) & 0xff) + 1;
-
-    wm8750_set_bclk_in(s->wm, rate);
-}
-
-static uint64_t mv88w8618_audio_read(void *opaque, hwaddr offset,
-                                    unsigned size)
-{
-    mv88w8618_audio_state *s = opaque;
-
-    switch (offset) {
-    case MP_AUDIO_PLAYBACK_MODE:
-        return s->playback_mode;
-
-    case MP_AUDIO_CLOCK_DIV:
-        return s->clock_div;
-
-    case MP_AUDIO_IRQ_STATUS:
-        return s->status;
-
-    case MP_AUDIO_IRQ_ENABLE:
-        return s->irq_enable;
-
-    case MP_AUDIO_TX_STATUS:
-        return s->play_pos >> 2;
-
-    default:
-        return 0;
-    }
-}
-
-static void mv88w8618_audio_write(void *opaque, hwaddr offset,
-                                  uint64_t value, unsigned size)
-{
-    mv88w8618_audio_state *s = opaque;
-
-    switch (offset) {
-    case MP_AUDIO_PLAYBACK_MODE:
-        if (value & MP_AUDIO_PLAYBACK_EN &&
-            !(s->playback_mode & MP_AUDIO_PLAYBACK_EN)) {
-            s->status = 0;
-            s->last_free = 0;
-            s->play_pos = 0;
-        }
-        s->playback_mode = value;
-        mv88w8618_audio_clock_update(s);
-        break;
-
-    case MP_AUDIO_CLOCK_DIV:
-        s->clock_div = value;
-        s->last_free = 0;
-        s->play_pos = 0;
-        mv88w8618_audio_clock_update(s);
-        break;
-
-    case MP_AUDIO_IRQ_STATUS:
-        s->status &= ~value;
-        break;
-
-    case MP_AUDIO_IRQ_ENABLE:
-        s->irq_enable = value;
-        if (s->status & s->irq_enable) {
-            qemu_irq_raise(s->irq);
-        }
-        break;
-
-    case MP_AUDIO_TX_START_LO:
-        s->phys_buf = (s->phys_buf & 0xFFFF0000) | (value & 0xFFFF);
-        s->target_buffer = s->phys_buf;
-        s->play_pos = 0;
-        s->last_free = 0;
-        break;
-
-    case MP_AUDIO_TX_THRESHOLD:
-        s->threshold = (value + 1) * 4;
-        break;
-
-    case MP_AUDIO_TX_START_HI:
-        s->phys_buf = (s->phys_buf & 0xFFFF) | (value << 16);
-        s->target_buffer = s->phys_buf;
-        s->play_pos = 0;
-        s->last_free = 0;
-        break;
-    }
-}
-
-static void mv88w8618_audio_reset(DeviceState *d)
-{
-    mv88w8618_audio_state *s = MV88W8618_AUDIO(d);
-
-    s->playback_mode = 0;
-    s->status = 0;
-    s->irq_enable = 0;
-    s->clock_div = 0;
-    s->threshold = 0;
-    s->phys_buf = 0;
-}
-
-static const MemoryRegionOps mv88w8618_audio_ops = {
-    .read = mv88w8618_audio_read,
-    .write = mv88w8618_audio_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void mv88w8618_audio_init(Object *obj)
-{
-    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
-    mv88w8618_audio_state *s = MV88W8618_AUDIO(dev);
-
-    sysbus_init_irq(dev, &s->irq);
-
-    memory_region_init_io(&s->iomem, obj, &mv88w8618_audio_ops, s,
-                          "audio", MP_AUDIO_SIZE);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    object_property_add_link(OBJECT(dev), "wm8750", TYPE_WM8750,
-                             (Object **) &s->wm,
-                             qdev_prop_allow_set_link_before_realize,
-                             0);
-}
-
-static void mv88w8618_audio_realize(DeviceState *dev, Error **errp)
-{
-    mv88w8618_audio_state *s = MV88W8618_AUDIO(dev);
-
-    wm8750_data_req_set(s->wm, mv88w8618_audio_callback, s);
-}
-
-static const VMStateDescription mv88w8618_audio_vmsd = {
-    .name = "mv88w8618_audio",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (const VMStateField[]) {
-        VMSTATE_UINT32(playback_mode, mv88w8618_audio_state),
-        VMSTATE_UINT32(status, mv88w8618_audio_state),
-        VMSTATE_UINT32(irq_enable, mv88w8618_audio_state),
-        VMSTATE_UINT32(phys_buf, mv88w8618_audio_state),
-        VMSTATE_UINT32(target_buffer, mv88w8618_audio_state),
-        VMSTATE_UINT32(threshold, mv88w8618_audio_state),
-        VMSTATE_UINT32(play_pos, mv88w8618_audio_state),
-        VMSTATE_UINT32(last_free, mv88w8618_audio_state),
-        VMSTATE_UINT32(clock_div, mv88w8618_audio_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void mv88w8618_audio_class_init(ObjectClass *klass, const void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    dc->realize = mv88w8618_audio_realize;
-    device_class_set_legacy_reset(dc, mv88w8618_audio_reset);
-    dc->vmsd = &mv88w8618_audio_vmsd;
-    dc->user_creatable = false;
-}
-
-static const TypeInfo mv88w8618_audio_info = {
-    .name          = TYPE_MV88W8618_AUDIO,
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(mv88w8618_audio_state),
-    .instance_init = mv88w8618_audio_init,
-    .class_init    = mv88w8618_audio_class_init,
-};
-
-static void mv88w8618_register_types(void)
-{
-    type_register_static(&mv88w8618_audio_info);
-}
-
-type_init(mv88w8618_register_types)
diff --git a/hw/audio/meson.build b/hw/audio/meson.build
index 2154cbdb57..c977679e23 100644
--- a/hw/audio/meson.build
+++ b/hw/audio/meson.build
@@ -7,7 +7,6 @@ system_ss.add(when: 'CONFIG_CS4231A', if_true: files('cs4231a.c'))
 system_ss.add(when: 'CONFIG_ES1370', if_true: files('es1370.c'))
 system_ss.add(when: 'CONFIG_GUS', if_true: files('gus.c', 'gusemu_hal.c', 'gusemu_mixer.c'))
 system_ss.add(when: 'CONFIG_HDA', if_true: files('intel-hda.c', 'hda-codec.c'))
-system_ss.add(when: 'CONFIG_MARVELL_88W8618', if_true: files('marvell_88w8618.c'))
 system_ss.add(when: 'CONFIG_PCSPK', if_true: files('pcspk.c'))
 system_ss.add(when: 'CONFIG_PL041', if_true: files('pl041.c', 'lm4549.c'))
 system_ss.add(when: 'CONFIG_SB16', if_true: files('sb16.c'))
diff --git a/hw/net/meson.build b/hw/net/meson.build
index 84f142df22..b4c95b58fa 100644
--- a/hw/net/meson.build
+++ b/hw/net/meson.build
@@ -27,7 +27,6 @@ system_ss.add(when: 'CONFIG_ALLWINNER_EMAC', if_true: files('allwinner_emac.c'))
 system_ss.add(when: 'CONFIG_ALLWINNER_SUN8I_EMAC', if_true: files('allwinner-sun8i-emac.c'))
 system_ss.add(when: 'CONFIG_IMX_FEC', if_true: files('imx_fec.c'))
 system_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-emac.c'))
-system_ss.add(when: 'CONFIG_MARVELL_88W8618', if_true: files('mv88w8618_eth.c'))
 
 system_ss.add(when: 'CONFIG_CADENCE', if_true: files('cadence_gem.c'))
 system_ss.add(when: 'CONFIG_STELLARIS_ENET', if_true: files('stellaris_enet.c'))
diff --git a/hw/net/mv88w8618_eth.c b/hw/net/mv88w8618_eth.c
deleted file mode 100644
index 1fcfbe912e..0000000000
--- a/hw/net/mv88w8618_eth.c
+++ /dev/null
@@ -1,403 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Marvell MV88W8618 / Freecom MusicPal emulation.
- *
- * Copyright (c) 2008 Jan Kiszka
- */
-
-#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "hw/core/qdev-properties.h"
-#include "hw/core/sysbus.h"
-#include "hw/core/irq.h"
-#include "hw/net/mv88w8618_eth.h"
-#include "migration/vmstate.h"
-#include "system/dma.h"
-#include "net/net.h"
-
-#define MP_ETH_SIZE             0x00001000
-
-/* Ethernet register offsets */
-#define MP_ETH_SMIR             0x010
-#define MP_ETH_PCXR             0x408
-#define MP_ETH_SDCMR            0x448
-#define MP_ETH_ICR              0x450
-#define MP_ETH_IMR              0x458
-#define MP_ETH_FRDP0            0x480
-#define MP_ETH_FRDP1            0x484
-#define MP_ETH_FRDP2            0x488
-#define MP_ETH_FRDP3            0x48C
-#define MP_ETH_CRDP0            0x4A0
-#define MP_ETH_CRDP1            0x4A4
-#define MP_ETH_CRDP2            0x4A8
-#define MP_ETH_CRDP3            0x4AC
-#define MP_ETH_CTDP0            0x4E0
-#define MP_ETH_CTDP1            0x4E4
-
-/* MII PHY access */
-#define MP_ETH_SMIR_DATA        0x0000FFFF
-#define MP_ETH_SMIR_ADDR        0x03FF0000
-#define MP_ETH_SMIR_OPCODE      (1 << 26) /* Read value */
-#define MP_ETH_SMIR_RDVALID     (1 << 27)
-
-/* PHY registers */
-#define MP_ETH_PHY1_BMSR        0x00210000
-#define MP_ETH_PHY1_PHYSID1     0x00410000
-#define MP_ETH_PHY1_PHYSID2     0x00610000
-
-#define MP_PHY_BMSR_LINK        0x0004
-#define MP_PHY_BMSR_AUTONEG     0x0008
-
-#define MP_PHY_88E3015          0x01410E20
-
-/* TX descriptor status */
-#define MP_ETH_TX_OWN           (1U << 31)
-
-/* RX descriptor status */
-#define MP_ETH_RX_OWN           (1U << 31)
-
-/* Interrupt cause/mask bits */
-#define MP_ETH_IRQ_RX_BIT       0
-#define MP_ETH_IRQ_RX           (1 << MP_ETH_IRQ_RX_BIT)
-#define MP_ETH_IRQ_TXHI_BIT     2
-#define MP_ETH_IRQ_TXLO_BIT     3
-
-/* Port config bits */
-#define MP_ETH_PCXR_2BSM_BIT    28 /* 2-byte incoming suffix */
-
-/* SDMA command bits */
-#define MP_ETH_CMD_TXHI         (1 << 23)
-#define MP_ETH_CMD_TXLO         (1 << 22)
-
-typedef struct mv88w8618_tx_desc {
-    uint32_t cmdstat;
-    uint16_t res;
-    uint16_t bytes;
-    uint32_t buffer;
-    uint32_t next;
-} mv88w8618_tx_desc;
-
-typedef struct mv88w8618_rx_desc {
-    uint32_t cmdstat;
-    uint16_t bytes;
-    uint16_t buffer_size;
-    uint32_t buffer;
-    uint32_t next;
-} mv88w8618_rx_desc;
-
-OBJECT_DECLARE_SIMPLE_TYPE(mv88w8618_eth_state, MV88W8618_ETH)
-
-struct mv88w8618_eth_state {
-    /*< private >*/
-    SysBusDevice parent_obj;
-    /*< public >*/
-
-    MemoryRegion iomem;
-    qemu_irq irq;
-    MemoryRegion *dma_mr;
-    AddressSpace dma_as;
-    uint32_t smir;
-    uint32_t icr;
-    uint32_t imr;
-    int mmio_index;
-    uint32_t vlan_header;
-    uint32_t tx_queue[2];
-    uint32_t rx_queue[4];
-    uint32_t frx_queue[4];
-    uint32_t cur_rx[4];
-    NICState *nic;
-    NICConf conf;
-};
-
-static void eth_rx_desc_put(AddressSpace *dma_as, uint32_t addr,
-                            mv88w8618_rx_desc *desc)
-{
-    cpu_to_le32s(&desc->cmdstat);
-    cpu_to_le16s(&desc->bytes);
-    cpu_to_le16s(&desc->buffer_size);
-    cpu_to_le32s(&desc->buffer);
-    cpu_to_le32s(&desc->next);
-    dma_memory_write(dma_as, addr, desc, sizeof(*desc), MEMTXATTRS_UNSPECIFIED);
-}
-
-static void eth_rx_desc_get(AddressSpace *dma_as, uint32_t addr,
-                            mv88w8618_rx_desc *desc)
-{
-    dma_memory_read(dma_as, addr, desc, sizeof(*desc), MEMTXATTRS_UNSPECIFIED);
-    le32_to_cpus(&desc->cmdstat);
-    le16_to_cpus(&desc->bytes);
-    le16_to_cpus(&desc->buffer_size);
-    le32_to_cpus(&desc->buffer);
-    le32_to_cpus(&desc->next);
-}
-
-static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size)
-{
-    mv88w8618_eth_state *s = qemu_get_nic_opaque(nc);
-    uint32_t desc_addr;
-    mv88w8618_rx_desc desc;
-    int i;
-
-    for (i = 0; i < 4; i++) {
-        desc_addr = s->cur_rx[i];
-        if (!desc_addr) {
-            continue;
-        }
-        do {
-            eth_rx_desc_get(&s->dma_as, desc_addr, &desc);
-            if ((desc.cmdstat & MP_ETH_RX_OWN) && desc.buffer_size >= size) {
-                dma_memory_write(&s->dma_as, desc.buffer + s->vlan_header,
-                                 buf, size, MEMTXATTRS_UNSPECIFIED);
-                desc.bytes = size + s->vlan_header;
-                desc.cmdstat &= ~MP_ETH_RX_OWN;
-                s->cur_rx[i] = desc.next;
-
-                s->icr |= MP_ETH_IRQ_RX;
-                if (s->icr & s->imr) {
-                    qemu_irq_raise(s->irq);
-                }
-                eth_rx_desc_put(&s->dma_as, desc_addr, &desc);
-                return size;
-            }
-            desc_addr = desc.next;
-        } while (desc_addr != s->rx_queue[i]);
-    }
-    return size;
-}
-
-static void eth_tx_desc_put(AddressSpace *dma_as, uint32_t addr,
-                            mv88w8618_tx_desc *desc)
-{
-    cpu_to_le32s(&desc->cmdstat);
-    cpu_to_le16s(&desc->res);
-    cpu_to_le16s(&desc->bytes);
-    cpu_to_le32s(&desc->buffer);
-    cpu_to_le32s(&desc->next);
-    dma_memory_write(dma_as, addr, desc, sizeof(*desc), MEMTXATTRS_UNSPECIFIED);
-}
-
-static void eth_tx_desc_get(AddressSpace *dma_as, uint32_t addr,
-                            mv88w8618_tx_desc *desc)
-{
-    dma_memory_read(dma_as, addr, desc, sizeof(*desc), MEMTXATTRS_UNSPECIFIED);
-    le32_to_cpus(&desc->cmdstat);
-    le16_to_cpus(&desc->res);
-    le16_to_cpus(&desc->bytes);
-    le32_to_cpus(&desc->buffer);
-    le32_to_cpus(&desc->next);
-}
-
-static void eth_send(mv88w8618_eth_state *s, int queue_index)
-{
-    uint32_t desc_addr = s->tx_queue[queue_index];
-    mv88w8618_tx_desc desc;
-    uint32_t next_desc;
-    uint8_t buf[2048];
-    int len;
-
-    do {
-        eth_tx_desc_get(&s->dma_as, desc_addr, &desc);
-        next_desc = desc.next;
-        if (desc.cmdstat & MP_ETH_TX_OWN) {
-            len = desc.bytes;
-            if (len < 2048) {
-                dma_memory_read(&s->dma_as, desc.buffer, buf, len,
-                                MEMTXATTRS_UNSPECIFIED);
-                qemu_send_packet(qemu_get_queue(s->nic), buf, len);
-            }
-            desc.cmdstat &= ~MP_ETH_TX_OWN;
-            s->icr |= 1 << (MP_ETH_IRQ_TXLO_BIT - queue_index);
-            eth_tx_desc_put(&s->dma_as, desc_addr, &desc);
-        }
-        desc_addr = next_desc;
-    } while (desc_addr != s->tx_queue[queue_index]);
-}
-
-static uint64_t mv88w8618_eth_read(void *opaque, hwaddr offset,
-                                   unsigned size)
-{
-    mv88w8618_eth_state *s = opaque;
-
-    switch (offset) {
-    case MP_ETH_SMIR:
-        if (s->smir & MP_ETH_SMIR_OPCODE) {
-            switch (s->smir & MP_ETH_SMIR_ADDR) {
-            case MP_ETH_PHY1_BMSR:
-                return MP_PHY_BMSR_LINK | MP_PHY_BMSR_AUTONEG |
-                       MP_ETH_SMIR_RDVALID;
-            case MP_ETH_PHY1_PHYSID1:
-                return (MP_PHY_88E3015 >> 16) | MP_ETH_SMIR_RDVALID;
-            case MP_ETH_PHY1_PHYSID2:
-                return (MP_PHY_88E3015 & 0xFFFF) | MP_ETH_SMIR_RDVALID;
-            default:
-                return MP_ETH_SMIR_RDVALID;
-            }
-        }
-        return 0;
-
-    case MP_ETH_ICR:
-        return s->icr;
-
-    case MP_ETH_IMR:
-        return s->imr;
-
-    case MP_ETH_FRDP0 ... MP_ETH_FRDP3:
-        return s->frx_queue[(offset - MP_ETH_FRDP0) / 4];
-
-    case MP_ETH_CRDP0 ... MP_ETH_CRDP3:
-        return s->rx_queue[(offset - MP_ETH_CRDP0) / 4];
-
-    case MP_ETH_CTDP0 ... MP_ETH_CTDP1:
-        return s->tx_queue[(offset - MP_ETH_CTDP0) / 4];
-
-    default:
-        return 0;
-    }
-}
-
-static void mv88w8618_eth_write(void *opaque, hwaddr offset,
-                                uint64_t value, unsigned size)
-{
-    mv88w8618_eth_state *s = opaque;
-
-    switch (offset) {
-    case MP_ETH_SMIR:
-        s->smir = value;
-        break;
-
-    case MP_ETH_PCXR:
-        s->vlan_header = ((value >> MP_ETH_PCXR_2BSM_BIT) & 1) * 2;
-        break;
-
-    case MP_ETH_SDCMR:
-        if (value & MP_ETH_CMD_TXHI) {
-            eth_send(s, 1);
-        }
-        if (value & MP_ETH_CMD_TXLO) {
-            eth_send(s, 0);
-        }
-        if (value & (MP_ETH_CMD_TXHI | MP_ETH_CMD_TXLO) && s->icr & s->imr) {
-            qemu_irq_raise(s->irq);
-        }
-        break;
-
-    case MP_ETH_ICR:
-        s->icr &= value;
-        break;
-
-    case MP_ETH_IMR:
-        s->imr = value;
-        if (s->icr & s->imr) {
-            qemu_irq_raise(s->irq);
-        }
-        break;
-
-    case MP_ETH_FRDP0 ... MP_ETH_FRDP3:
-        s->frx_queue[(offset - MP_ETH_FRDP0) / 4] = value;
-        break;
-
-    case MP_ETH_CRDP0 ... MP_ETH_CRDP3:
-        s->rx_queue[(offset - MP_ETH_CRDP0) / 4] =
-            s->cur_rx[(offset - MP_ETH_CRDP0) / 4] = value;
-        break;
-
-    case MP_ETH_CTDP0 ... MP_ETH_CTDP1:
-        s->tx_queue[(offset - MP_ETH_CTDP0) / 4] = value;
-        break;
-    }
-}
-
-static const MemoryRegionOps mv88w8618_eth_ops = {
-    .read = mv88w8618_eth_read,
-    .write = mv88w8618_eth_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void eth_cleanup(NetClientState *nc)
-{
-    mv88w8618_eth_state *s = qemu_get_nic_opaque(nc);
-
-    s->nic = NULL;
-}
-
-static NetClientInfo net_mv88w8618_info = {
-    .type = NET_CLIENT_DRIVER_NIC,
-    .size = sizeof(NICState),
-    .receive = eth_receive,
-    .cleanup = eth_cleanup,
-};
-
-static void mv88w8618_eth_init(Object *obj)
-{
-    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
-    DeviceState *dev = DEVICE(sbd);
-    mv88w8618_eth_state *s = MV88W8618_ETH(dev);
-
-    sysbus_init_irq(sbd, &s->irq);
-    memory_region_init_io(&s->iomem, obj, &mv88w8618_eth_ops, s,
-                          "mv88w8618-eth", MP_ETH_SIZE);
-    sysbus_init_mmio(sbd, &s->iomem);
-}
-
-static void mv88w8618_eth_realize(DeviceState *dev, Error **errp)
-{
-    mv88w8618_eth_state *s = MV88W8618_ETH(dev);
-
-    if (!s->dma_mr) {
-        error_setg(errp, TYPE_MV88W8618_ETH " 'dma-memory' link not set");
-        return;
-    }
-
-    address_space_init(&s->dma_as, s->dma_mr, "emac-dma");
-    s->nic = qemu_new_nic(&net_mv88w8618_info, &s->conf,
-                          object_get_typename(OBJECT(dev)), dev->id,
-                          &dev->mem_reentrancy_guard, s);
-}
-
-static const VMStateDescription mv88w8618_eth_vmsd = {
-    .name = "mv88w8618_eth",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (const VMStateField[]) {
-        VMSTATE_UINT32(smir, mv88w8618_eth_state),
-        VMSTATE_UINT32(icr, mv88w8618_eth_state),
-        VMSTATE_UINT32(imr, mv88w8618_eth_state),
-        VMSTATE_UINT32(vlan_header, mv88w8618_eth_state),
-        VMSTATE_UINT32_ARRAY(tx_queue, mv88w8618_eth_state, 2),
-        VMSTATE_UINT32_ARRAY(rx_queue, mv88w8618_eth_state, 4),
-        VMSTATE_UINT32_ARRAY(frx_queue, mv88w8618_eth_state, 4),
-        VMSTATE_UINT32_ARRAY(cur_rx, mv88w8618_eth_state, 4),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static const Property mv88w8618_eth_properties[] = {
-    DEFINE_NIC_PROPERTIES(mv88w8618_eth_state, conf),
-    DEFINE_PROP_LINK("dma-memory", mv88w8618_eth_state, dma_mr,
-                     TYPE_MEMORY_REGION, MemoryRegion *),
-};
-
-static void mv88w8618_eth_class_init(ObjectClass *klass, const void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    dc->vmsd = &mv88w8618_eth_vmsd;
-    device_class_set_props(dc, mv88w8618_eth_properties);
-    dc->realize = mv88w8618_eth_realize;
-}
-
-static const TypeInfo mv88w8618_eth_info = {
-    .name          = TYPE_MV88W8618_ETH,
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(mv88w8618_eth_state),
-    .instance_init = mv88w8618_eth_init,
-    .class_init    = mv88w8618_eth_class_init,
-};
-
-static void musicpal_register_types(void)
-{
-    type_register_static(&mv88w8618_eth_info);
-}
-
-type_init(musicpal_register_types)
-
diff --git a/include/hw/net/mv88w8618_eth.h b/include/hw/net/mv88w8618_eth.h
deleted file mode 100644
index 41074940ec..0000000000
--- a/include/hw/net/mv88w8618_eth.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Marvell MV88W8618 / Freecom MusicPal emulation.
- *
- * Copyright (c) 2008-2021 QEMU contributors
- */
-
-#ifndef HW_NET_MV88W8618_ETH_H
-#define HW_NET_MV88W8618_ETH_H
-
-#define TYPE_MV88W8618_ETH "mv88w8618_eth"
-
-#endif
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 5/5] hw/audio: Remove wm8750 I2C audio device
  2026-08-19 18:54 [PATCH 0/5] arm: Remove the 'musicpal' machine Peter Maydell
                   ` (3 preceding siblings ...)
  2026-08-19 18:54 ` [PATCH 4/5] hw: Remove Marvell 88W8618 devices Peter Maydell
@ 2026-08-19 18:54 ` Peter Maydell
  2026-08-19 19:36   ` Richard Henderson
  2026-08-20 11:15   ` Philippe Mathieu-Daudé
  2026-08-20 10:13 ` [PATCH 0/5] arm: Remove the 'musicpal' machine Jan Kiszka
  5 siblings, 2 replies; 18+ messages in thread
From: Peter Maydell @ 2026-08-19 18:54 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Pierrick Bouvier, Philippe Mathieu-Daudé, Jan Kiszka

The wm8750 audio I2C device was used only by the audio device on the
SoC used in the now-removed musicpal machine.  Since it has no users,
we can delete it entirely.

Although the wm8750 is an I2C device that could technically have been
created on the command line, it isn't possible to do this usefully
because the device only works when C code calls functions like
wm8750_data_req_set() and wm8750_dac_buffer().

This resolves the problem noted in issue #4135 that there's a buffer
overflow in the interaction between the marvell_88w8618 audio device
and the wm8750, by removing the offending code entirely.

Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4135
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/audio/Kconfig          |   4 -
 hw/audio/meson.build      |   1 -
 hw/audio/wm8750.c         | 738 --------------------------------------
 include/hw/audio/wm8750.h |  30 --
 4 files changed, 773 deletions(-)
 delete mode 100644 hw/audio/wm8750.c
 delete mode 100644 include/hw/audio/wm8750.h

diff --git a/hw/audio/Kconfig b/hw/audio/Kconfig
index daf060e1be..ed93fa2698 100644
--- a/hw/audio/Kconfig
+++ b/hw/audio/Kconfig
@@ -38,10 +38,6 @@ config PCSPK
     default y
     depends on I8254
 
-config WM8750
-    bool
-    depends on I2C
-
 config PL041
     bool
 
diff --git a/hw/audio/meson.build b/hw/audio/meson.build
index c977679e23..3312bcec10 100644
--- a/hw/audio/meson.build
+++ b/hw/audio/meson.build
@@ -11,6 +11,5 @@ system_ss.add(when: 'CONFIG_PCSPK', if_true: files('pcspk.c'))
 system_ss.add(when: 'CONFIG_PL041', if_true: files('pl041.c', 'lm4549.c'))
 system_ss.add(when: 'CONFIG_SB16', if_true: files('sb16.c'))
 system_ss.add(when: 'CONFIG_VT82C686', if_true: files('via-ac97.c'))
-system_ss.add(when: 'CONFIG_WM8750', if_true: files('wm8750.c'))
 system_ss.add(when: ['CONFIG_VIRTIO_SND', 'CONFIG_VIRTIO'], if_true: files('virtio-snd.c'))
 system_ss.add(when: ['CONFIG_VIRTIO_SND', 'CONFIG_VIRTIO', 'CONFIG_VIRTIO_PCI'], if_true: files('virtio-snd-pci.c'))
diff --git a/hw/audio/wm8750.c b/hw/audio/wm8750.c
deleted file mode 100644
index e2507b0269..0000000000
--- a/hw/audio/wm8750.c
+++ /dev/null
@@ -1,738 +0,0 @@
-/*
- * WM8750 audio CODEC.
- *
- * Copyright (c) 2006 Openedhand Ltd.
- * Written by Andrzej Zaborowski <balrog@zabor.org>
- *
- * This file is licensed under GNU GPL.
- */
-
-#include "qemu/osdep.h"
-#include "hw/i2c/i2c.h"
-#include "migration/vmstate.h"
-#include "qemu/module.h"
-#include "hw/audio/wm8750.h"
-#include "qemu/audio.h"
-#include "qom/object.h"
-
-#define IN_PORT_N	3
-#define OUT_PORT_N	3
-
-#define CODEC		"wm8750"
-
-typedef struct {
-    int adc;
-    int adc_hz;
-    int dac;
-    int dac_hz;
-} WMRate;
-
-OBJECT_DECLARE_SIMPLE_TYPE(WM8750State, WM8750)
-
-struct WM8750State {
-    I2CSlave parent_obj;
-
-    uint8_t i2c_data[2];
-    int i2c_len;
-    AudioBackend *audio_be;
-    SWVoiceIn *adc_voice[IN_PORT_N];
-    SWVoiceOut *dac_voice[OUT_PORT_N];
-    int enable;
-    void (*data_req)(void *, int, int);
-    void *opaque;
-    uint8_t data_in[4096];
-    uint8_t data_out[4096];
-    int idx_in, req_in;
-    int idx_out, req_out;
-
-    SWVoiceOut **out[2];
-    uint8_t outvol[7], outmute[2];
-    SWVoiceIn **in[2];
-    uint8_t invol[4], inmute[2];
-
-    uint8_t diff[2], pol, ds, monomix[2], alc, mute;
-    uint8_t path[4], mpath[2], power, format;
-    const WMRate *rate;
-    uint8_t rate_vmstate;
-    int adc_hz, dac_hz, ext_adc_hz, ext_dac_hz, master;
-};
-
-/* pow(10.0, -i / 20.0) * 255, i = 0..42 */
-static const uint8_t wm8750_vol_db_table[] = {
-    255, 227, 203, 181, 161, 143, 128, 114, 102, 90, 81, 72, 64, 57, 51, 45,
-    40, 36, 32, 29, 26, 23, 20, 18, 16, 14, 13, 11, 10, 9, 8, 7, 6, 6, 5, 5,
-    4, 4, 3, 3, 3, 2, 2
-};
-
-#define WM8750_OUTVOL_TRANSFORM(x)	wm8750_vol_db_table[(0x7f - x) / 3]
-#define WM8750_INVOL_TRANSFORM(x)	(x << 2)
-
-static inline void wm8750_in_load(WM8750State *s)
-{
-    if (s->idx_in + s->req_in <= sizeof(s->data_in))
-        return;
-    s->idx_in = MAX(0, (int) sizeof(s->data_in) - s->req_in);
-    audio_be_read(s->audio_be, *s->in[0], s->data_in + s->idx_in,
-             sizeof(s->data_in) - s->idx_in);
-}
-
-static inline void wm8750_out_flush(WM8750State *s)
-{
-    int sent = 0;
-    while (sent < s->idx_out)
-        sent += audio_be_write(s->audio_be, *s->out[0],
-                               s->data_out + sent, s->idx_out - sent)
-                ?: s->idx_out;
-    s->idx_out = 0;
-}
-
-static void wm8750_audio_in_cb(void *opaque, int avail_b)
-{
-    WM8750State *s = (WM8750State *) opaque;
-    s->req_in = avail_b;
-    s->data_req(s->opaque, s->req_out >> 2, avail_b >> 2);
-}
-
-static void wm8750_audio_out_cb(void *opaque, int free_b)
-{
-    WM8750State *s = (WM8750State *) opaque;
-
-    if (s->idx_out >= free_b) {
-        s->idx_out = free_b;
-        s->req_out = 0;
-        wm8750_out_flush(s);
-    } else
-        s->req_out = free_b - s->idx_out;
-
-    s->data_req(s->opaque, s->req_out >> 2, s->req_in >> 2);
-}
-
-static const WMRate wm_rate_table[] = {
-    {  256, 48000,  256, 48000 },	/* SR: 00000 */
-    {  384, 48000,  384, 48000 },	/* SR: 00001 */
-    {  256, 48000, 1536,  8000 },	/* SR: 00010 */
-    {  384, 48000, 2304,  8000 },	/* SR: 00011 */
-    { 1536,  8000,  256, 48000 },	/* SR: 00100 */
-    { 2304,  8000,  384, 48000 },	/* SR: 00101 */
-    { 1536,  8000, 1536,  8000 },	/* SR: 00110 */
-    { 2304,  8000, 2304,  8000 },	/* SR: 00111 */
-    { 1024, 12000, 1024, 12000 },	/* SR: 01000 */
-    { 1526, 12000, 1536, 12000 },	/* SR: 01001 */
-    {  768, 16000,  768, 16000 },	/* SR: 01010 */
-    { 1152, 16000, 1152, 16000 },	/* SR: 01011 */
-    {  384, 32000,  384, 32000 },	/* SR: 01100 */
-    {  576, 32000,  576, 32000 },	/* SR: 01101 */
-    {  128, 96000,  128, 96000 },	/* SR: 01110 */
-    {  192, 96000,  192, 96000 },	/* SR: 01111 */
-    {  256, 44100,  256, 44100 },	/* SR: 10000 */
-    {  384, 44100,  384, 44100 },	/* SR: 10001 */
-    {  256, 44100, 1408,  8018 },	/* SR: 10010 */
-    {  384, 44100, 2112,  8018 },	/* SR: 10011 */
-    { 1408,  8018,  256, 44100 },	/* SR: 10100 */
-    { 2112,  8018,  384, 44100 },	/* SR: 10101 */
-    { 1408,  8018, 1408,  8018 },	/* SR: 10110 */
-    { 2112,  8018, 2112,  8018 },	/* SR: 10111 */
-    { 1024, 11025, 1024, 11025 },	/* SR: 11000 */
-    { 1536, 11025, 1536, 11025 },	/* SR: 11001 */
-    {  512, 22050,  512, 22050 },	/* SR: 11010 */
-    {  768, 22050,  768, 22050 },	/* SR: 11011 */
-    {  512, 24000,  512, 24000 },	/* SR: 11100 */
-    {  768, 24000,  768, 24000 },	/* SR: 11101 */
-    {  128, 88200,  128, 88200 },	/* SR: 11110 */
-    {  192, 88200,  192, 88200 },	/* SR: 11111 */
-};
-
-static void wm8750_vol_update(WM8750State *s)
-{
-    /* FIXME: multiply all volumes by s->invol[2], s->invol[3] */
-
-    audio_be_set_volume_in_lr(s->audio_be, s->adc_voice[0], s->mute,
-                    s->inmute[0] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[0]),
-                    s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1]));
-    audio_be_set_volume_in_lr(s->audio_be, s->adc_voice[1], s->mute,
-                    s->inmute[0] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[0]),
-                    s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1]));
-    audio_be_set_volume_in_lr(s->audio_be, s->adc_voice[2], s->mute,
-                    s->inmute[0] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[0]),
-                    s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1]));
-
-    /* FIXME: multiply all volumes by s->outvol[0], s->outvol[1] */
-
-    /* Speaker: LOUT2VOL ROUT2VOL */
-    audio_be_set_volume_out_lr(s->audio_be, s->dac_voice[0], s->mute,
-                    s->outmute[0] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[4]),
-                    s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[5]));
-
-    /* Headphone: LOUT1VOL ROUT1VOL */
-    audio_be_set_volume_out_lr(s->audio_be, s->dac_voice[1], s->mute,
-                    s->outmute[0] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[2]),
-                    s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[3]));
-
-    /* MONOOUT: MONOVOL MONOVOL */
-    audio_be_set_volume_out_lr(s->audio_be, s->dac_voice[2], s->mute,
-                    s->outmute[0] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[6]),
-                    s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[6]));
-}
-
-static void wm8750_set_format(WM8750State *s)
-{
-    int i;
-    struct audsettings in_fmt;
-    struct audsettings out_fmt;
-
-    wm8750_out_flush(s);
-
-    if (s->in[0] && *s->in[0])
-        audio_be_set_active_in(s->audio_be, *s->in[0], 0);
-    if (s->out[0] && *s->out[0])
-        audio_be_set_active_out(s->audio_be, *s->out[0], 0);
-
-    for (i = 0; i < IN_PORT_N; i ++)
-        if (s->adc_voice[i]) {
-            audio_be_close_in(s->audio_be, s->adc_voice[i]);
-            s->adc_voice[i] = NULL;
-        }
-    for (i = 0; i < OUT_PORT_N; i ++)
-        if (s->dac_voice[i]) {
-            audio_be_close_out(s->audio_be, s->dac_voice[i]);
-            s->dac_voice[i] = NULL;
-        }
-
-    if (!s->enable)
-        return;
-
-    /* Setup input */
-    in_fmt.big_endian = false;
-    in_fmt.nchannels = 2;
-    in_fmt.freq = s->adc_hz;
-    in_fmt.fmt = AUDIO_FORMAT_S16;
-
-    s->adc_voice[0] = audio_be_open_in(s->audio_be, s->adc_voice[0],
-                    CODEC ".input1", s, wm8750_audio_in_cb, &in_fmt);
-    s->adc_voice[1] = audio_be_open_in(s->audio_be, s->adc_voice[1],
-                    CODEC ".input2", s, wm8750_audio_in_cb, &in_fmt);
-    s->adc_voice[2] = audio_be_open_in(s->audio_be, s->adc_voice[2],
-                    CODEC ".input3", s, wm8750_audio_in_cb, &in_fmt);
-
-    /* Setup output */
-    out_fmt.big_endian = false;
-    out_fmt.nchannels = 2;
-    out_fmt.freq = s->dac_hz;
-    out_fmt.fmt = AUDIO_FORMAT_S16;
-
-    s->dac_voice[0] = audio_be_open_out(s->audio_be, s->dac_voice[0],
-                    CODEC ".speaker", s, wm8750_audio_out_cb, &out_fmt);
-    s->dac_voice[1] = audio_be_open_out(s->audio_be, s->dac_voice[1],
-                    CODEC ".headphone", s, wm8750_audio_out_cb, &out_fmt);
-    /* MONOMIX is also in stereo for simplicity */
-    s->dac_voice[2] = audio_be_open_out(s->audio_be, s->dac_voice[2],
-                    CODEC ".monomix", s, wm8750_audio_out_cb, &out_fmt);
-    /* no sense emulating OUT3 which is a mix of other outputs */
-
-    wm8750_vol_update(s);
-
-    /* We should connect the left and right channels to their
-     * respective inputs/outputs but we have completely no need
-     * for mixing or combining paths to different ports, so we
-     * connect both channels to where the left channel is routed.  */
-    if (s->in[0] && *s->in[0])
-        audio_be_set_active_in(s->audio_be, *s->in[0], 1);
-    if (s->out[0] && *s->out[0])
-        audio_be_set_active_out(s->audio_be, *s->out[0], 1);
-}
-
-static void wm8750_clk_update(WM8750State *s, int ext)
-{
-    if (s->master || !s->ext_dac_hz)
-        s->dac_hz = s->rate->dac_hz;
-    else
-        s->dac_hz = s->ext_dac_hz;
-
-    if (s->master || !s->ext_adc_hz)
-        s->adc_hz = s->rate->adc_hz;
-    else
-        s->adc_hz = s->ext_adc_hz;
-
-    if (s->master || (!s->ext_dac_hz && !s->ext_adc_hz)) {
-        if (!ext)
-            wm8750_set_format(s);
-    } else {
-        if (ext)
-            wm8750_set_format(s);
-    }
-}
-
-static void wm8750_reset(I2CSlave *i2c)
-{
-    WM8750State *s = WM8750(i2c);
-
-    s->rate = &wm_rate_table[0];
-    s->enable = 0;
-    wm8750_clk_update(s, 1);
-    s->diff[0] = 0;
-    s->diff[1] = 0;
-    s->ds = 0;
-    s->alc = 0;
-    s->in[0] = &s->adc_voice[0];
-    s->invol[0] = 0x17;
-    s->invol[1] = 0x17;
-    s->invol[2] = 0xc3;
-    s->invol[3] = 0xc3;
-    s->out[0] = &s->dac_voice[0];
-    s->outvol[0] = 0xff;
-    s->outvol[1] = 0xff;
-    s->outvol[2] = 0x79;
-    s->outvol[3] = 0x79;
-    s->outvol[4] = 0x79;
-    s->outvol[5] = 0x79;
-    s->outvol[6] = 0x79;
-    s->inmute[0] = 0;
-    s->inmute[1] = 0;
-    s->outmute[0] = 0;
-    s->outmute[1] = 0;
-    s->mute = 1;
-    s->path[0] = 0;
-    s->path[1] = 0;
-    s->path[2] = 0;
-    s->path[3] = 0;
-    s->mpath[0] = 0;
-    s->mpath[1] = 0;
-    s->format = 0x0a;
-    s->idx_in = sizeof(s->data_in);
-    s->req_in = 0;
-    s->idx_out = 0;
-    s->req_out = 0;
-    wm8750_vol_update(s);
-    s->i2c_len = 0;
-}
-
-static int wm8750_event(I2CSlave *i2c, enum i2c_event event)
-{
-    WM8750State *s = WM8750(i2c);
-
-    switch (event) {
-    case I2C_START_SEND:
-        s->i2c_len = 0;
-        break;
-    case I2C_FINISH:
-#ifdef VERBOSE
-        if (s->i2c_len < 2)
-            printf("%s: message too short (%i bytes)\n",
-                            __func__, s->i2c_len);
-#endif
-        break;
-    default:
-        break;
-    }
-
-    return 0;
-}
-
-#define WM8750_LINVOL	0x00
-#define WM8750_RINVOL	0x01
-#define WM8750_LOUT1V	0x02
-#define WM8750_ROUT1V	0x03
-#define WM8750_ADCDAC	0x05
-#define WM8750_IFACE	0x07
-#define WM8750_SRATE	0x08
-#define WM8750_LDAC	0x0a
-#define WM8750_RDAC	0x0b
-#define WM8750_BASS	0x0c
-#define WM8750_TREBLE	0x0d
-#define WM8750_RESET	0x0f
-#define WM8750_3D	0x10
-#define WM8750_ALC1	0x11
-#define WM8750_ALC2	0x12
-#define WM8750_ALC3	0x13
-#define WM8750_NGATE	0x14
-#define WM8750_LADC	0x15
-#define WM8750_RADC	0x16
-#define WM8750_ADCTL1	0x17
-#define WM8750_ADCTL2	0x18
-#define WM8750_PWR1	0x19
-#define WM8750_PWR2	0x1a
-#define WM8750_ADCTL3	0x1b
-#define WM8750_ADCIN	0x1f
-#define WM8750_LADCIN	0x20
-#define WM8750_RADCIN	0x21
-#define WM8750_LOUTM1	0x22
-#define WM8750_LOUTM2	0x23
-#define WM8750_ROUTM1	0x24
-#define WM8750_ROUTM2	0x25
-#define WM8750_MOUTM1	0x26
-#define WM8750_MOUTM2	0x27
-#define WM8750_LOUT2V	0x28
-#define WM8750_ROUT2V	0x29
-#define WM8750_MOUTV	0x2a
-
-static int wm8750_tx(I2CSlave *i2c, uint8_t data)
-{
-    WM8750State *s = WM8750(i2c);
-    uint8_t cmd;
-    uint16_t value;
-
-    if (s->i2c_len >= 2) {
-#ifdef VERBOSE
-        printf("%s: long message (%i bytes)\n", __func__, s->i2c_len);
-#endif
-        return 1;
-    }
-    s->i2c_data[s->i2c_len ++] = data;
-    if (s->i2c_len != 2)
-        return 0;
-
-    cmd = s->i2c_data[0] >> 1;
-    value = ((s->i2c_data[0] << 8) | s->i2c_data[1]) & 0x1ff;
-
-    switch (cmd) {
-    case WM8750_LADCIN:	/* ADC Signal Path Control (Left) */
-        s->diff[0] = (((value >> 6) & 3) == 3);	/* LINSEL */
-        if (s->diff[0])
-            s->in[0] = &s->adc_voice[0 + s->ds * 1];
-        else
-            s->in[0] = &s->adc_voice[((value >> 6) & 3) * 1 + 0];
-        break;
-
-    case WM8750_RADCIN:	/* ADC Signal Path Control (Right) */
-        s->diff[1] = (((value >> 6) & 3) == 3);	/* RINSEL */
-        if (s->diff[1])
-            s->in[1] = &s->adc_voice[0 + s->ds * 1];
-        else
-            s->in[1] = &s->adc_voice[((value >> 6) & 3) * 1 + 0];
-        break;
-
-    case WM8750_ADCIN:	/* ADC Input Mode */
-        s->ds = (value >> 8) & 1;	/* DS */
-        if (s->diff[0])
-            s->in[0] = &s->adc_voice[0 + s->ds * 1];
-        if (s->diff[1])
-            s->in[1] = &s->adc_voice[0 + s->ds * 1];
-        s->monomix[0] = (value >> 6) & 3;	/* MONOMIX */
-        break;
-
-    case WM8750_ADCTL1:	/* Additional Control (1) */
-        s->monomix[1] = (value >> 1) & 1;	/* DMONOMIX */
-        break;
-
-    case WM8750_PWR1:	/* Power Management (1) */
-        s->enable = ((value >> 6) & 7) == 3;	/* VMIDSEL, VREF */
-        wm8750_set_format(s);
-        break;
-
-    case WM8750_LINVOL:	/* Left Channel PGA */
-        s->invol[0] = value & 0x3f;		/* LINVOL */
-        s->inmute[0] = (value >> 7) & 1;	/* LINMUTE */
-        wm8750_vol_update(s);
-        break;
-
-    case WM8750_RINVOL:	/* Right Channel PGA */
-        s->invol[1] = value & 0x3f;		/* RINVOL */
-        s->inmute[1] = (value >> 7) & 1;	/* RINMUTE */
-        wm8750_vol_update(s);
-        break;
-
-    case WM8750_ADCDAC:	/* ADC and DAC Control */
-        s->pol = (value >> 5) & 3;		/* ADCPOL */
-        s->mute = (value >> 3) & 1;		/* DACMU */
-        wm8750_vol_update(s);
-        break;
-
-    case WM8750_ADCTL3:	/* Additional Control (3) */
-        break;
-
-    case WM8750_LADC:	/* Left ADC Digital Volume */
-        s->invol[2] = value & 0xff;		/* LADCVOL */
-        wm8750_vol_update(s);
-        break;
-
-    case WM8750_RADC:	/* Right ADC Digital Volume */
-        s->invol[3] = value & 0xff;		/* RADCVOL */
-        wm8750_vol_update(s);
-        break;
-
-    case WM8750_ALC1:	/* ALC Control (1) */
-        s->alc = (value >> 7) & 3;		/* ALCSEL */
-        break;
-
-    case WM8750_NGATE:	/* Noise Gate Control */
-    case WM8750_3D:	/* 3D enhance */
-        break;
-
-    case WM8750_LDAC:	/* Left Channel Digital Volume */
-        s->outvol[0] = value & 0xff;		/* LDACVOL */
-        wm8750_vol_update(s);
-        break;
-
-    case WM8750_RDAC:	/* Right Channel Digital Volume */
-        s->outvol[1] = value & 0xff;		/* RDACVOL */
-        wm8750_vol_update(s);
-        break;
-
-    case WM8750_BASS:	/* Bass Control */
-        break;
-
-    case WM8750_LOUTM1:	/* Left Mixer Control (1) */
-        s->path[0] = (value >> 8) & 1;		/* LD2LO */
-        /* TODO: mute/unmute respective paths */
-        wm8750_vol_update(s);
-        break;
-
-    case WM8750_LOUTM2:	/* Left Mixer Control (2) */
-        s->path[1] = (value >> 8) & 1;		/* RD2LO */
-        /* TODO: mute/unmute respective paths */
-        wm8750_vol_update(s);
-        break;
-
-    case WM8750_ROUTM1:	/* Right Mixer Control (1) */
-        s->path[2] = (value >> 8) & 1;		/* LD2RO */
-        /* TODO: mute/unmute respective paths */
-        wm8750_vol_update(s);
-        break;
-
-    case WM8750_ROUTM2:	/* Right Mixer Control (2) */
-        s->path[3] = (value >> 8) & 1;		/* RD2RO */
-        /* TODO: mute/unmute respective paths */
-        wm8750_vol_update(s);
-        break;
-
-    case WM8750_MOUTM1:	/* Mono Mixer Control (1) */
-        s->mpath[0] = (value >> 8) & 1;		/* LD2MO */
-        /* TODO: mute/unmute respective paths */
-        wm8750_vol_update(s);
-        break;
-
-    case WM8750_MOUTM2:	/* Mono Mixer Control (2) */
-        s->mpath[1] = (value >> 8) & 1;		/* RD2MO */
-        /* TODO: mute/unmute respective paths */
-        wm8750_vol_update(s);
-        break;
-
-    case WM8750_LOUT1V:	/* LOUT1 Volume */
-        s->outvol[2] = value & 0x7f;		/* LOUT1VOL */
-        wm8750_vol_update(s);
-        break;
-
-    case WM8750_LOUT2V:	/* LOUT2 Volume */
-        s->outvol[4] = value & 0x7f;		/* LOUT2VOL */
-        wm8750_vol_update(s);
-        break;
-
-    case WM8750_ROUT1V:	/* ROUT1 Volume */
-        s->outvol[3] = value & 0x7f;		/* ROUT1VOL */
-        wm8750_vol_update(s);
-        break;
-
-    case WM8750_ROUT2V:	/* ROUT2 Volume */
-        s->outvol[5] = value & 0x7f;		/* ROUT2VOL */
-        wm8750_vol_update(s);
-        break;
-
-    case WM8750_MOUTV:	/* MONOOUT Volume */
-        s->outvol[6] = value & 0x7f;		/* MONOOUTVOL */
-        wm8750_vol_update(s);
-        break;
-
-    case WM8750_ADCTL2:	/* Additional Control (2) */
-        break;
-
-    case WM8750_PWR2:	/* Power Management (2) */
-        s->power = value & 0x7e;
-        /* TODO: mute/unmute respective paths */
-        wm8750_vol_update(s);
-        break;
-
-    case WM8750_IFACE:	/* Digital Audio Interface Format */
-        s->format = value;
-        s->master = (value >> 6) & 1;			/* MS */
-        wm8750_clk_update(s, s->master);
-        break;
-
-    case WM8750_SRATE:	/* Clocking and Sample Rate Control */
-        s->rate = &wm_rate_table[(value >> 1) & 0x1f];
-        wm8750_clk_update(s, 0);
-        break;
-
-    case WM8750_RESET:	/* Reset */
-        wm8750_reset(I2C_SLAVE(s));
-        break;
-
-#ifdef VERBOSE
-    default:
-        printf("%s: unknown register %02x\n", __func__, cmd);
-#endif
-    }
-
-    return 0;
-}
-
-static uint8_t wm8750_rx(I2CSlave *i2c)
-{
-    return 0x00;
-}
-
-static int wm8750_pre_save(void *opaque)
-{
-    WM8750State *s = opaque;
-
-    s->rate_vmstate = s->rate - wm_rate_table;
-
-    return 0;
-}
-
-static int wm8750_post_load(void *opaque, int version_id)
-{
-    WM8750State *s = opaque;
-
-    s->rate = &wm_rate_table[s->rate_vmstate & 0x1f];
-    return 0;
-}
-
-static const VMStateDescription vmstate_wm8750 = {
-    .name = CODEC,
-    .version_id = 0,
-    .minimum_version_id = 0,
-    .pre_save = wm8750_pre_save,
-    .post_load = wm8750_post_load,
-    .fields = (const VMStateField[]) {
-        VMSTATE_UINT8_ARRAY(i2c_data, WM8750State, 2),
-        VMSTATE_INT32(i2c_len, WM8750State),
-        VMSTATE_INT32(enable, WM8750State),
-        VMSTATE_INT32(idx_in, WM8750State),
-        VMSTATE_INT32(req_in, WM8750State),
-        VMSTATE_INT32(idx_out, WM8750State),
-        VMSTATE_INT32(req_out, WM8750State),
-        VMSTATE_UINT8_ARRAY(outvol, WM8750State, 7),
-        VMSTATE_UINT8_ARRAY(outmute, WM8750State, 2),
-        VMSTATE_UINT8_ARRAY(invol, WM8750State, 4),
-        VMSTATE_UINT8_ARRAY(inmute, WM8750State, 2),
-        VMSTATE_UINT8_ARRAY(diff, WM8750State, 2),
-        VMSTATE_UINT8(pol, WM8750State),
-        VMSTATE_UINT8(ds, WM8750State),
-        VMSTATE_UINT8_ARRAY(monomix, WM8750State, 2),
-        VMSTATE_UINT8(alc, WM8750State),
-        VMSTATE_UINT8(mute, WM8750State),
-        VMSTATE_UINT8_ARRAY(path, WM8750State, 4),
-        VMSTATE_UINT8_ARRAY(mpath, WM8750State, 2),
-        VMSTATE_UINT8(format, WM8750State),
-        VMSTATE_UINT8(power, WM8750State),
-        VMSTATE_UINT8(rate_vmstate, WM8750State),
-        VMSTATE_I2C_SLAVE(parent_obj, WM8750State),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void wm8750_realize(DeviceState *dev, Error **errp)
-{
-    WM8750State *s = WM8750(dev);
-
-    if (!audio_be_check(&s->audio_be, errp)) {
-        return;
-    }
-
-    wm8750_reset(I2C_SLAVE(s));
-}
-
-#if 0
-static void wm8750_fini(I2CSlave *i2c)
-{
-    WM8750State *s = WM8750(i2c);
-
-    wm8750_reset(I2C_SLAVE(s));
-    g_free(s);
-}
-#endif
-
-void wm8750_data_req_set(DeviceState *dev, data_req_cb *data_req, void *opaque)
-{
-    WM8750State *s = WM8750(dev);
-
-    s->data_req = data_req;
-    s->opaque = opaque;
-}
-
-void wm8750_dac_dat(void *opaque, uint32_t sample)
-{
-    WM8750State *s = (WM8750State *) opaque;
-
-    *(uint32_t *) &s->data_out[s->idx_out] = sample;
-    s->req_out -= 4;
-    s->idx_out += 4;
-    if (s->idx_out >= sizeof(s->data_out) || s->req_out <= 0)
-        wm8750_out_flush(s);
-}
-
-void *wm8750_dac_buffer(void *opaque, int samples)
-{
-    WM8750State *s = (WM8750State *) opaque;
-    /* XXX: Should check if there are <i>samples</i> free samples available */
-    void *ret = s->data_out + s->idx_out;
-
-    s->idx_out += samples << 2;
-    s->req_out -= samples << 2;
-    return ret;
-}
-
-void wm8750_dac_commit(void *opaque)
-{
-    WM8750State *s = (WM8750State *) opaque;
-
-    wm8750_out_flush(s);
-}
-
-uint32_t wm8750_adc_dat(void *opaque)
-{
-    WM8750State *s = (WM8750State *) opaque;
-    uint32_t *data;
-
-    if (s->idx_in >= sizeof(s->data_in)) {
-        wm8750_in_load(s);
-        if (s->idx_in >= sizeof(s->data_in)) {
-            return 0x80008000; /* silence in AUDIO_FORMAT_S16 sample format */
-        }
-    }
-
-    data = (uint32_t *) &s->data_in[s->idx_in];
-    s->req_in -= 4;
-    s->idx_in += 4;
-    return *data;
-}
-
-void wm8750_set_bclk_in(void *opaque, int new_hz)
-{
-    WM8750State *s = (WM8750State *) opaque;
-
-    s->ext_adc_hz = new_hz;
-    s->ext_dac_hz = new_hz;
-    wm8750_clk_update(s, 1);
-}
-
-static const Property wm8750_properties[] = {
-    DEFINE_AUDIO_PROPERTIES(WM8750State, audio_be),
-};
-
-static void wm8750_class_init(ObjectClass *klass, const void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    I2CSlaveClass *sc = I2C_SLAVE_CLASS(klass);
-
-    dc->realize = wm8750_realize;
-    sc->event = wm8750_event;
-    sc->recv = wm8750_rx;
-    sc->send = wm8750_tx;
-    dc->vmsd = &vmstate_wm8750;
-    device_class_set_props(dc, wm8750_properties);
-}
-
-static const TypeInfo wm8750_info = {
-    .name          = TYPE_WM8750,
-    .parent        = TYPE_I2C_SLAVE,
-    .instance_size = sizeof(WM8750State),
-    .class_init    = wm8750_class_init,
-};
-
-static void wm8750_register_types(void)
-{
-    type_register_static(&wm8750_info);
-}
-
-type_init(wm8750_register_types)
diff --git a/include/hw/audio/wm8750.h b/include/hw/audio/wm8750.h
deleted file mode 100644
index f7bafd5e38..0000000000
--- a/include/hw/audio/wm8750.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2 or later, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef HW_DAC_WM8750_H
-#define HW_DAC_WM8750_H
-
-
-#define TYPE_WM8750 "wm8750"
-#define TYPE_MV88W8618_AUDIO "mv88w8618_audio"
-
-typedef void data_req_cb(void *opaque, int free_out, int free_in);
-
-void wm8750_data_req_set(DeviceState *dev, data_req_cb *data_req, void *opaque);
-void wm8750_dac_dat(void *opaque, uint32_t sample);
-uint32_t wm8750_adc_dat(void *opaque);
-void *wm8750_dac_buffer(void *opaque, int samples);
-void wm8750_dac_commit(void *opaque);
-void wm8750_set_bclk_in(void *opaque, int new_hz);
-
-#endif
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH 3/5] hw/arm: Remove the 'musicpal' machine
  2026-08-19 18:54 ` [PATCH 3/5] hw/arm: Remove the 'musicpal' machine Peter Maydell
@ 2026-08-19 19:35   ` Richard Henderson
  2026-08-20 10:55   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 18+ messages in thread
From: Richard Henderson @ 2026-08-19 19:35 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Pierrick Bouvier, Philippe Mathieu-Daudé, Jan Kiszka

On 8/19/26 11:54, Peter Maydell wrote:
> 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>
> ---
>   MAINTAINERS                             |   10 -
>   configs/devices/arm-softmmu/default.mak |    1 -
>   docs/about/removed-features.rst         |   10 +
>   docs/system/arm/musicpal.rst            |   19 -
>   docs/system/target-arm.rst              |    1 -
>   hw/arm/Kconfig                          |   12 -
>   hw/arm/meson.build                      |    1 -
>   hw/arm/musicpal.c                       | 1388 -----------------------
>   8 files changed, 10 insertions(+), 1432 deletions(-)
>   delete mode 100644 docs/system/arm/musicpal.rst
>   delete mode 100644 hw/arm/musicpal.c

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/5] hw: Remove Marvell 88W8618 devices
  2026-08-19 18:54 ` [PATCH 4/5] hw: Remove Marvell 88W8618 devices Peter Maydell
@ 2026-08-19 19:35   ` Richard Henderson
  2026-08-20 10:59   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 18+ messages in thread
From: Richard Henderson @ 2026-08-19 19:35 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Pierrick Bouvier, Philippe Mathieu-Daudé, Jan Kiszka

On 8/19/26 11:54, Peter Maydell wrote:
> The mv88w8618 ethernet and audio devices were used only by the
> now-removed musicpal machine, so can also be deleted.
> 
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
>   hw/arm/Kconfig                 |   3 -
>   hw/audio/marvell_88w8618.c     | 315 --------------------------
>   hw/audio/meson.build           |   1 -
>   hw/net/meson.build             |   1 -
>   hw/net/mv88w8618_eth.c         | 403 ---------------------------------
>   include/hw/net/mv88w8618_eth.h |  13 --
>   6 files changed, 736 deletions(-)
>   delete mode 100644 hw/audio/marvell_88w8618.c
>   delete mode 100644 hw/net/mv88w8618_eth.c
>   delete mode 100644 include/hw/net/mv88w8618_eth.h

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 5/5] hw/audio: Remove wm8750 I2C audio device
  2026-08-19 18:54 ` [PATCH 5/5] hw/audio: Remove wm8750 I2C audio device Peter Maydell
@ 2026-08-19 19:36   ` Richard Henderson
  2026-08-20 11:15   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 18+ messages in thread
From: Richard Henderson @ 2026-08-19 19:36 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Pierrick Bouvier, Philippe Mathieu-Daudé, Jan Kiszka

On 8/19/26 11:54, Peter Maydell wrote:
> The wm8750 audio I2C device was used only by the audio device on the
> SoC used in the now-removed musicpal machine.  Since it has no users,
> we can delete it entirely.
> 
> Although the wm8750 is an I2C device that could technically have been
> created on the command line, it isn't possible to do this usefully
> because the device only works when C code calls functions like
> wm8750_data_req_set() and wm8750_dac_buffer().
> 
> This resolves the problem noted in issue #4135 that there's a buffer
> overflow in the interaction between the marvell_88w8618 audio device
> and the wm8750, by removing the offending code entirely.
> 
> Resolves:https://gitlab.com/qemu-project/qemu/-/work_items/4135
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
>   hw/audio/Kconfig          |   4 -
>   hw/audio/meson.build      |   1 -
>   hw/audio/wm8750.c         | 738 --------------------------------------
>   include/hw/audio/wm8750.h |  30 --
>   4 files changed, 773 deletions(-)
>   delete mode 100644 hw/audio/wm8750.c
>   delete mode 100644 include/hw/audio/wm8750.h

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/5] hw/arm: Remove spurious WM8750 dependency from Realview Kconfig
  2026-08-19 18:54 ` [PATCH 2/5] hw/arm: Remove spurious WM8750 dependency from Realview Kconfig Peter Maydell
@ 2026-08-19 19:37   ` Richard Henderson
  2026-08-20 10:55   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 18+ messages in thread
From: Richard Henderson @ 2026-08-19 19:37 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Pierrick Bouvier, Philippe Mathieu-Daudé, Jan Kiszka

On 8/19/26 11:54, Peter Maydell wrote:
> The REALVIEW Kconfig stanza has a "select WM8750"; however the board
> itself doesn't actually use this i2c audio device: its audio is
> provided by the pl041 (which connects to an LM4549). Remove the
> spurious dependency.
> 
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
>   hw/arm/Kconfig | 1 -
>   1 file changed, 1 deletion(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 0/5] arm: Remove the 'musicpal' machine
  2026-08-19 18:54 [PATCH 0/5] arm: Remove the 'musicpal' machine Peter Maydell
                   ` (4 preceding siblings ...)
  2026-08-19 18:54 ` [PATCH 5/5] hw/audio: Remove wm8750 I2C audio device Peter Maydell
@ 2026-08-20 10:13 ` Jan Kiszka
  5 siblings, 0 replies; 18+ messages in thread
From: Jan Kiszka @ 2026-08-20 10:13 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Pierrick Bouvier, Philippe Mathieu-Daudé

On 19.08.26 20:54, Peter Maydell wrote:
> 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.

Right. I once talked to the developer at Freecom behind the software,
but they were already in maintenance mode and apparently had neither the
power nor the will to influence Marvell on this.

> 
> 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
>  * We have no test image for it that we can distribute
>  * The only bug report we've ever had about it has been one of
>    the usual "bug found by static analysis" kind (#4135)
> 
> 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.
> 
> This patchset first fixes up a couple of places (notably the
> pflash_cfi02 tests) that were using or referring to the musicpal
> board; then it removes the board, followed by the devices used only by
> that board.
> 
> Strictly speaking it's possible that somebody is using this machine
> with some other image that doesn't have the same "does an unaligned
> LDRH" problem the stock firmware image does; but it seems unlikely
> to me. We can take the standard "deprecate for two releases, then
> drop" route if people prefer that.
> 
> I do also have a patch which reverts the "take a Data Abort on
> unaligned access" change for v5 and v6-with-SCTLR.U=0 CPUs, which I'll
> post separately.
> 
> thanks
> -- PMM
> 
> Peter Maydell (5):
>   tests/qtest/pflash-cfi02-test: Don't use musicpal machine for testing
>   hw/arm: Remove spurious WM8750 dependency from Realview Kconfig
>   hw/arm: Remove the 'musicpal' machine
>   hw: Remove Marvell 88W8618 devices
>   hw/audio: Remove wm8750 I2C audio device
> 
>  MAINTAINERS                             |   10 -
>  configs/devices/arm-softmmu/default.mak |    1 -
>  docs/about/removed-features.rst         |   10 +
>  docs/system/arm/musicpal.rst            |   19 -
>  docs/system/target-arm.rst              |    1 -
>  hw/arm/Kconfig                          |   16 -
>  hw/arm/meson.build                      |    1 -
>  hw/arm/musicpal.c                       | 1388 -----------------------
>  hw/audio/Kconfig                        |    4 -
>  hw/audio/marvell_88w8618.c              |  315 -----
>  hw/audio/meson.build                    |    2 -
>  hw/audio/wm8750.c                       |  738 ------------
>  hw/net/meson.build                      |    1 -
>  hw/net/mv88w8618_eth.c                  |  403 -------
>  include/hw/audio/wm8750.h               |   30 -
>  include/hw/net/mv88w8618_eth.h          |   13 -
>  tests/qtest/meson.build                 |    6 +-
>  tests/qtest/pflash-cfi02-test.c         |   38 +-
>  18 files changed, 36 insertions(+), 2960 deletions(-)
>  delete mode 100644 docs/system/arm/musicpal.rst
>  delete mode 100644 hw/arm/musicpal.c
>  delete mode 100644 hw/audio/marvell_88w8618.c
>  delete mode 100644 hw/audio/wm8750.c
>  delete mode 100644 hw/net/mv88w8618_eth.c
>  delete mode 100644 include/hw/audio/wm8750.h
>  delete mode 100644 include/hw/net/mv88w8618_eth.h
> 

RIP - no problems with this. At least it was allowed to turn 18 years
in-tree. ;)

Acked-by: Jan Kiszka <jan.kiszka@web.de>

Fun fact: My real device that once motivated this reverse-engineered
machine model is still alive and basically working. Its hard-coded
web-radio service is dead by now, but manually entered streams still
work. Only the power supply had to be replace a while ago.

Jan



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/5] hw/arm: Remove spurious WM8750 dependency from Realview Kconfig
  2026-08-19 18:54 ` [PATCH 2/5] hw/arm: Remove spurious WM8750 dependency from Realview Kconfig Peter Maydell
  2026-08-19 19:37   ` Richard Henderson
@ 2026-08-20 10:55   ` Philippe Mathieu-Daudé
  2026-08-21  8:32     ` Peter Maydell
  1 sibling, 1 reply; 18+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-20 10:55 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Pierrick Bouvier, Philippe Mathieu-Daudé, Jan Kiszka

On 19/8/26 20:54, Peter Maydell wrote:
> The REALVIEW Kconfig stanza has a "select WM8750"; however the board
> itself doesn't actually use this i2c audio device: its audio is
> provided by the pl041 (which connects to an LM4549). Remove the
> spurious dependency.
> 

Is it worth Cc'ing stable?

Cc: qemu-stable@nongnu.org
Fixes: 79e93e24de8 ("hw/arm: Express dependencies of realview, versatile 
and vexpress with Kconfig")

Anyway,
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>

> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>   hw/arm/Kconfig | 1 -
>   1 file changed, 1 deletion(-)
> 
> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> index 260d2f0751..5e9a0bd8dc 100644
> --- a/hw/arm/Kconfig
> +++ b/hw/arm/Kconfig
> @@ -155,7 +155,6 @@ config REALVIEW
>       select ARM11MPCORE
>       select ARM_TIMER
>       select VERSATILE_PCI
> -    select WM8750 # audio codec
>       select LSI_SCSI_PCI
>       select PCI
>       select PL011 # UART



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 3/5] hw/arm: Remove the 'musicpal' machine
  2026-08-19 18:54 ` [PATCH 3/5] hw/arm: Remove the 'musicpal' machine Peter Maydell
  2026-08-19 19:35   ` Richard Henderson
@ 2026-08-20 10:55   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 18+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-20 10:55 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Pierrick Bouvier, Philippe Mathieu-Daudé, Jan Kiszka

On 19/8/26 20:54, Peter Maydell wrote:
> 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>
> ---
>   MAINTAINERS                             |   10 -
>   configs/devices/arm-softmmu/default.mak |    1 -
>   docs/about/removed-features.rst         |   10 +
>   docs/system/arm/musicpal.rst            |   19 -
>   docs/system/target-arm.rst              |    1 -
>   hw/arm/Kconfig                          |   12 -
>   hw/arm/meson.build                      |    1 -
>   hw/arm/musicpal.c                       | 1388 -----------------------
>   8 files changed, 10 insertions(+), 1432 deletions(-)
>   delete mode 100644 docs/system/arm/musicpal.rst
>   delete mode 100644 hw/arm/musicpal.c

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/5] hw: Remove Marvell 88W8618 devices
  2026-08-19 18:54 ` [PATCH 4/5] hw: Remove Marvell 88W8618 devices Peter Maydell
  2026-08-19 19:35   ` Richard Henderson
@ 2026-08-20 10:59   ` Philippe Mathieu-Daudé
  2026-08-21  8:37     ` Peter Maydell
  1 sibling, 1 reply; 18+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-20 10:59 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Pierrick Bouvier, Philippe Mathieu-Daudé, Jan Kiszka

On 19/8/26 20:54, Peter Maydell wrote:
> The mv88w8618 ethernet and audio devices were used only by the
> now-removed musicpal machine, so can also be deleted.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>   hw/arm/Kconfig                 |   3 -
>   hw/audio/marvell_88w8618.c     | 315 --------------------------
>   hw/audio/meson.build           |   1 -
>   hw/net/meson.build             |   1 -
>   hw/net/mv88w8618_eth.c         | 403 ---------------------------------
>   include/hw/net/mv88w8618_eth.h |  13 --
>   6 files changed, 736 deletions(-)
>   delete mode 100644 hw/audio/marvell_88w8618.c
>   delete mode 100644 hw/net/mv88w8618_eth.c
>   delete mode 100644 include/hw/net/mv88w8618_eth.h


> -static void mv88w8618_audio_callback(void *opaque, int free_out, int free_in)
> -{
> -    mv88w8618_audio_state *s = opaque;
> -    int16_t *codec_buffer;
> -    QEMU_UNINITIALIZED int8_t buf[4096];
> -    int8_t *mem_buffer;
> -    int pos, block_size;
> -
> -    if (!(s->playback_mode & MP_AUDIO_PLAYBACK_EN)) {
> -        return;
> -    }
> -    if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE) {
> -        free_out <<= 1;
> -    }
> -    if (!(s->playback_mode & MP_AUDIO_MONO)) {
> -        free_out <<= 1;
> -    }
> -    block_size = s->threshold / 2;
> -    if (free_out - s->last_free < block_size) {
> -        return;
> -    }
> -    if (block_size > 4096) {
> -        return;
> -    }
> -    physical_memory_read(s->target_buffer + s->play_pos, buf, block_size);
> -    mem_buffer = buf;
> -    if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE) {
> -        if (s->playback_mode & MP_AUDIO_MONO) {
> -            codec_buffer = wm8750_dac_buffer(s->wm, block_size >> 1);
> -            for (pos = 0; pos < block_size; pos += 2) {
> -                *codec_buffer++ = *(int16_t *)mem_buffer;
> -                *codec_buffer++ = *(int16_t *)mem_buffer;

There seems to be an endianness bug here.

> -                mem_buffer += 2;
> -            }
> -        } else {
> -            memcpy(wm8750_dac_buffer(s->wm, block_size >> 2),
> -                   (uint32_t *)mem_buffer, block_size);
> -        }
> -    } else {
> -        if (s->playback_mode & MP_AUDIO_MONO) {
> -            codec_buffer = wm8750_dac_buffer(s->wm, block_size);
> -            for (pos = 0; pos < block_size; pos++) {
> -                *codec_buffer++ = cpu_to_le16(256 * *mem_buffer);
> -                *codec_buffer++ = cpu_to_le16(256 * *mem_buffer++);
> -            }
> -        } else {
> -            codec_buffer = wm8750_dac_buffer(s->wm, block_size >> 1);
> -            for (pos = 0; pos < block_size; pos += 2) {
> -                *codec_buffer++ = cpu_to_le16(256 * *mem_buffer++);
> -                *codec_buffer++ = cpu_to_le16(256 * *mem_buffer++);
> -            }
> -        }
> -    }
> -    wm8750_dac_commit(s->wm);
> -
> -    s->last_free = free_out - block_size;
> -
> -    if (s->play_pos == 0) {
> -        s->status |= MP_AUDIO_TX_HALF;
> -        s->play_pos = block_size;
> -    } else {
> -        s->status |= MP_AUDIO_TX_FULL;
> -        s->play_pos = 0;
> -    }
> -
> -    if (s->status & s->irq_enable) {
> -        qemu_irq_raise(s->irq);
> -    }
> -}
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/5] tests/qtest/pflash-cfi02-test: Don't use musicpal machine for testing
  2026-08-19 18:54 ` [PATCH 1/5] tests/qtest/pflash-cfi02-test: Don't use musicpal machine for testing Peter Maydell
@ 2026-08-20 11:13   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 18+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-20 11:13 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Pierrick Bouvier, Philippe Mathieu-Daudé, Jan Kiszka

On 19/8/26 20:54, Peter Maydell wrote:
> We currently use the musicpal machine for testing the pflash-cfi02
> device.  We'd like to remove that machine, so switch the tests to the
> sh4 r2d board type instead.
> 
> We use r2d because it happens to have the same "2 bank" config that
> musicpal did.  (Of our other options, xilinx-zynq-a9 has only a
> 1-bank setup so wouldn't allow the same range of testing, and the
> canon-a1100 board both doesn't support specifying a flash drive via
> -drive if=pflash, plus it seems likely it too might be a candidate
> for deprecate-and-drop.)
> 
> The r2d flash device is not quite the same config as the musicpal
> one: it has a different base address and size, and different
> ID values. So we need to update the test to match.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>   tests/qtest/meson.build         |  6 +++---
>   tests/qtest/pflash-cfi02-test.c | 38 ++++++++++++++++++++-------------
>   2 files changed, 26 insertions(+), 18 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 5/5] hw/audio: Remove wm8750 I2C audio device
  2026-08-19 18:54 ` [PATCH 5/5] hw/audio: Remove wm8750 I2C audio device Peter Maydell
  2026-08-19 19:36   ` Richard Henderson
@ 2026-08-20 11:15   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 18+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-20 11:15 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Pierrick Bouvier, Philippe Mathieu-Daudé, Jan Kiszka

On 19/8/26 20:54, Peter Maydell wrote:
> The wm8750 audio I2C device was used only by the audio device on the
> SoC used in the now-removed musicpal machine.  Since it has no users,
> we can delete it entirely.
> 
> Although the wm8750 is an I2C device that could technically have been
> created on the command line, it isn't possible to do this usefully
> because the device only works when C code calls functions like
> wm8750_data_req_set() and wm8750_dac_buffer().
> 
> This resolves the problem noted in issue #4135 that there's a buffer
> overflow in the interaction between the marvell_88w8618 audio device
> and the wm8750, by removing the offending code entirely.
> 
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4135
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>   hw/audio/Kconfig          |   4 -
>   hw/audio/meson.build      |   1 -
>   hw/audio/wm8750.c         | 738 --------------------------------------
>   include/hw/audio/wm8750.h |  30 --
>   4 files changed, 773 deletions(-)
>   delete mode 100644 hw/audio/wm8750.c
>   delete mode 100644 include/hw/audio/wm8750.h

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/5] hw/arm: Remove spurious WM8750 dependency from Realview Kconfig
  2026-08-20 10:55   ` Philippe Mathieu-Daudé
@ 2026-08-21  8:32     ` Peter Maydell
  0 siblings, 0 replies; 18+ messages in thread
From: Peter Maydell @ 2026-08-21  8:32 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: qemu-arm, qemu-devel, Pierrick Bouvier,
	Philippe Mathieu-Daudé, Jan Kiszka

On Thu, 20 Aug 2026 at 11:55, Philippe Mathieu-Daudé
<philmd@oss.qualcomm.com> wrote:
>
> On 19/8/26 20:54, Peter Maydell wrote:
> > The REALVIEW Kconfig stanza has a "select WM8750"; however the board
> > itself doesn't actually use this i2c audio device: its audio is
> > provided by the pl041 (which connects to an LM4549). Remove the
> > spurious dependency.
> >
>
> Is it worth Cc'ing stable?

I don't think so -- the dependency is harmless and has been there
for years. We only need to drop it so we can delete the WM8750 code.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/5] hw: Remove Marvell 88W8618 devices
  2026-08-20 10:59   ` Philippe Mathieu-Daudé
@ 2026-08-21  8:37     ` Peter Maydell
  0 siblings, 0 replies; 18+ messages in thread
From: Peter Maydell @ 2026-08-21  8:37 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: qemu-arm, qemu-devel, Pierrick Bouvier,
	Philippe Mathieu-Daudé, Jan Kiszka

On Thu, 20 Aug 2026 at 11:59, Philippe Mathieu-Daudé
<philmd@oss.qualcomm.com> wrote:
>
> On 19/8/26 20:54, Peter Maydell wrote:
> > The mv88w8618 ethernet and audio devices were used only by the
> > now-removed musicpal machine, so can also be deleted.
> >
> > Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> > ---
> >   hw/arm/Kconfig                 |   3 -
> >   hw/audio/marvell_88w8618.c     | 315 --------------------------
> >   hw/audio/meson.build           |   1 -
> >   hw/net/meson.build             |   1 -
> >   hw/net/mv88w8618_eth.c         | 403 ---------------------------------
> >   include/hw/net/mv88w8618_eth.h |  13 --
> >   6 files changed, 736 deletions(-)
> >   delete mode 100644 hw/audio/marvell_88w8618.c
> >   delete mode 100644 hw/net/mv88w8618_eth.c
> >   delete mode 100644 include/hw/net/mv88w8618_eth.h
>
>
> > -static void mv88w8618_audio_callback(void *opaque, int free_out, int free_in)
> > -{
> > -    mv88w8618_audio_state *s = opaque;
> > -    int16_t *codec_buffer;
> > -    QEMU_UNINITIALIZED int8_t buf[4096];
> > -    int8_t *mem_buffer;
> > -    int pos, block_size;
> > -
> > -    if (!(s->playback_mode & MP_AUDIO_PLAYBACK_EN)) {
> > -        return;
> > -    }
> > -    if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE) {
> > -        free_out <<= 1;
> > -    }
> > -    if (!(s->playback_mode & MP_AUDIO_MONO)) {
> > -        free_out <<= 1;
> > -    }
> > -    block_size = s->threshold / 2;
> > -    if (free_out - s->last_free < block_size) {
> > -        return;
> > -    }
> > -    if (block_size > 4096) {
> > -        return;
> > -    }
> > -    physical_memory_read(s->target_buffer + s->play_pos, buf, block_size);
> > -    mem_buffer = buf;
> > -    if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE) {
> > -        if (s->playback_mode & MP_AUDIO_MONO) {
> > -            codec_buffer = wm8750_dac_buffer(s->wm, block_size >> 1);
> > -            for (pos = 0; pos < block_size; pos += 2) {
> > -                *codec_buffer++ = *(int16_t *)mem_buffer;
> > -                *codec_buffer++ = *(int16_t *)mem_buffer;
>
> There seems to be an endianness bug here.

Not that it matters, since the code is being deleted, but I don't
think there is. In guest memory the sample data is 16-bit little
endian values; in this code path we copy it directly into the
DAC buffer. The wm8750 code then copies from the DAC buffer to
the audio backend, and it has created the backend with formats
with big_endian == false. This matches up with the 8-bit-sample
codepaths in this function, where because we calculate a
(host-order) 16-bit sample value from the guest's 8-bit sample
we need to use cpu_to_le16() to write the LE16 data into the DAC
buffer.

> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2026-08-21  8:38 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-19 18:54 [PATCH 0/5] arm: Remove the 'musicpal' machine Peter Maydell
2026-08-19 18:54 ` [PATCH 1/5] tests/qtest/pflash-cfi02-test: Don't use musicpal machine for testing Peter Maydell
2026-08-20 11:13   ` Philippe Mathieu-Daudé
2026-08-19 18:54 ` [PATCH 2/5] hw/arm: Remove spurious WM8750 dependency from Realview Kconfig Peter Maydell
2026-08-19 19:37   ` Richard Henderson
2026-08-20 10:55   ` Philippe Mathieu-Daudé
2026-08-21  8:32     ` Peter Maydell
2026-08-19 18:54 ` [PATCH 3/5] hw/arm: Remove the 'musicpal' machine Peter Maydell
2026-08-19 19:35   ` Richard Henderson
2026-08-20 10:55   ` Philippe Mathieu-Daudé
2026-08-19 18:54 ` [PATCH 4/5] hw: Remove Marvell 88W8618 devices Peter Maydell
2026-08-19 19:35   ` Richard Henderson
2026-08-20 10:59   ` Philippe Mathieu-Daudé
2026-08-21  8:37     ` Peter Maydell
2026-08-19 18:54 ` [PATCH 5/5] hw/audio: Remove wm8750 I2C audio device Peter Maydell
2026-08-19 19:36   ` Richard Henderson
2026-08-20 11:15   ` Philippe Mathieu-Daudé
2026-08-20 10:13 ` [PATCH 0/5] arm: Remove the 'musicpal' machine Jan Kiszka

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.