* [RFC PATCH 0/3] Add virtio-mmio support to m68k virt machine
@ 2026-03-10 13:59 Daniel Palmer
2026-03-10 13:59 ` [RFC PATCH 1/3] virtio: mmio: Allow instantiation via platform data Daniel Palmer
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Daniel Palmer @ 2026-03-10 13:59 UTC (permalink / raw)
To: visitorckw, angelo, bmeng.cn; +Cc: laurent, u-boot, Daniel Palmer
Lets start making the m68k virt machine support useful.
This allows the virtio mmio driver instances to be created with
platform data, fixes (for some value of fix) the endian issues in
virtio mmio and then adds the code for the board to create the
instances.
This is very rough. I'm not sure how to fix the endian issues or
if there are even any issues and I missed something. I got my
version of the m68k virt machine working back in 2024 and can't
remember everything.
Daniel Palmer (3):
virtio: mmio: Allow instantiation via platform data
virtio: mmio: endian *fixes* *HACK*
board: qemu: m68k: Create virtio mmio instances
arch/m68k/Kconfig | 14 +--
board/emulation/qemu-m68k/qemu-m68k.c | 46 +++++++++
drivers/virtio/virtio_mmio.c | 141 ++++++++++++++++----------
include/virtio_mmio.h | 12 +++
4 files changed, 152 insertions(+), 61 deletions(-)
create mode 100644 include/virtio_mmio.h
--
2.51.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [RFC PATCH 1/3] virtio: mmio: Allow instantiation via platform data
2026-03-10 13:59 [RFC PATCH 0/3] Add virtio-mmio support to m68k virt machine Daniel Palmer
@ 2026-03-10 13:59 ` Daniel Palmer
2026-03-10 13:59 ` [RFC PATCH 2/3] virtio: mmio: endian *fixes* *HACK* Daniel Palmer
2026-03-10 13:59 ` [RFC PATCH 3/3] board: qemu: m68k: Create virtio mmio instances Daniel Palmer
2 siblings, 0 replies; 7+ messages in thread
From: Daniel Palmer @ 2026-03-10 13:59 UTC (permalink / raw)
To: visitorckw, angelo, bmeng.cn; +Cc: laurent, u-boot, Daniel Palmer
The m68k QEMU virt machine doesn't use devicetree, yet, so
allow it to create virtio-mmio instances via platform data.
Signed-off-by: Daniel Palmer <daniel@thingy.jp>
---
drivers/virtio/virtio_mmio.c | 27 ++++++++++++++++++---------
include/virtio_mmio.h | 12 ++++++++++++
2 files changed, 30 insertions(+), 9 deletions(-)
create mode 100644 include/virtio_mmio.h
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 1cd737aca249..28b46ab66238 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -12,6 +12,7 @@
#include <virtio_types.h>
#include <virtio.h>
#include <virtio_ring.h>
+#include <virtio_mmio.h>
#include <linux/bug.h>
#include <linux/compat.h>
#include <linux/err.h>
@@ -335,21 +336,28 @@ static int virtio_mmio_notify(struct udevice *udev, struct virtqueue *vq)
static int virtio_mmio_of_to_plat(struct udevice *udev)
{
- struct virtio_mmio_priv *priv = dev_get_priv(udev);
+ struct virtio_mmio_plat *plat = dev_get_plat(udev);
+ fdt_addr_t addr;
+
+ addr = dev_read_addr(udev);
- priv->base = (void __iomem *)(ulong)dev_read_addr(udev);
- if (priv->base == (void __iomem *)FDT_ADDR_T_NONE)
+ if (addr == FDT_ADDR_T_NONE)
return -EINVAL;
+ plat->base = addr;
+
return 0;
}
static int virtio_mmio_probe(struct udevice *udev)
{
+ struct virtio_mmio_plat *plat = dev_get_plat(udev);
struct virtio_mmio_priv *priv = dev_get_priv(udev);
struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
u32 magic;
+ priv->base = (void __iomem *)plat->base;
+
/* Check magic value */
magic = readl(priv->base + VIRTIO_MMIO_MAGIC_VALUE);
if (magic != ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)) {
@@ -405,11 +413,12 @@ static const struct udevice_id virtio_mmio_ids[] = {
};
U_BOOT_DRIVER(virtio_mmio) = {
- .name = "virtio-mmio",
- .id = UCLASS_VIRTIO,
- .of_match = virtio_mmio_ids,
- .ops = &virtio_mmio_ops,
- .probe = virtio_mmio_probe,
+ .name = "virtio-mmio",
+ .id = UCLASS_VIRTIO,
+ .of_match = virtio_mmio_ids,
+ .ops = &virtio_mmio_ops,
+ .probe = virtio_mmio_probe,
.of_to_plat = virtio_mmio_of_to_plat,
- .priv_auto = sizeof(struct virtio_mmio_priv),
+ .priv_auto = sizeof(struct virtio_mmio_priv),
+ .plat_auto = sizeof(struct virtio_mmio_plat),
};
diff --git a/include/virtio_mmio.h b/include/virtio_mmio.h
new file mode 100644
index 000000000000..8c072826db55
--- /dev/null
+++ b/include/virtio_mmio.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef __VIRTIO_MMIO_H__
+#define __VIRTIO_MMIO_H__
+
+#include <linux/types.h>
+
+struct virtio_mmio_plat {
+ phys_addr_t base;
+};
+
+#endif /* __VIRTIO_MMIO_H__ */
--
2.51.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [RFC PATCH 2/3] virtio: mmio: endian *fixes* *HACK*
2026-03-10 13:59 [RFC PATCH 0/3] Add virtio-mmio support to m68k virt machine Daniel Palmer
2026-03-10 13:59 ` [RFC PATCH 1/3] virtio: mmio: Allow instantiation via platform data Daniel Palmer
@ 2026-03-10 13:59 ` Daniel Palmer
2026-03-14 8:53 ` Daniel Palmer
2026-03-10 13:59 ` [RFC PATCH 3/3] board: qemu: m68k: Create virtio mmio instances Daniel Palmer
2 siblings, 1 reply; 7+ messages in thread
From: Daniel Palmer @ 2026-03-10 13:59 UTC (permalink / raw)
To: visitorckw, angelo, bmeng.cn; +Cc: laurent, u-boot, Daniel Palmer
From: Daniel Palmer <daniel@0x0f.com>
This is an attempt to *fix* virtio mmio on the QEMU m68k virt machine.
As far as I can tell all of the registers in the virtio mmio regions
should be little endian so after reading them they need to be converted
to big endian for the code to work on them? other parts of the code
are also doing endian conversion so I'm not sure.
Or QEMU is incorrectly giving big endian register values?
---
drivers/virtio/virtio_mmio.c | 114 +++++++++++++++++++++--------------
1 file changed, 68 insertions(+), 46 deletions(-)
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 28b46ab66238..2cf85fdab4ed 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -19,6 +19,27 @@
#include <linux/io.h>
#include "virtio_mmio.h"
+static inline u32 virtio_mmio_readl(void *addr)
+{
+ return in_le32(addr);
+}
+
+static inline u16 virtio_mmio_readw(void *addr)
+{
+ return in_le16(addr);
+}
+
+static inline void virtio_mmio_writel(u32 val, void *addr)
+{
+ out_le32(addr, val);
+}
+
+static inline void virtio_mmio_writew(u32 val, void *addr)
+{
+ out_le16(addr, val);
+}
+
+
static int virtio_mmio_get_config(struct udevice *udev, unsigned int offset,
void *buf, unsigned int len)
{
@@ -44,17 +65,17 @@ static int virtio_mmio_get_config(struct udevice *udev, unsigned int offset,
memcpy(buf, &b, sizeof(b));
break;
case 2:
- w = cpu_to_le16(readw(base + offset));
+ w = cpu_to_le16(virtio_mmio_readw(base + offset));
memcpy(buf, &w, sizeof(w));
break;
case 4:
- l = cpu_to_le32(readl(base + offset));
+ l = cpu_to_le32(virtio_mmio_readl(base + offset));
memcpy(buf, &l, sizeof(l));
break;
case 8:
- l = cpu_to_le32(readl(base + offset));
+ l = cpu_to_le32(virtio_mmio_readl(base + offset));
memcpy(buf, &l, sizeof(l));
- l = cpu_to_le32(readl(base + offset + sizeof(l)));
+ l = cpu_to_le32(virtio_mmio_readl(base + offset + sizeof(l)));
memcpy(buf + sizeof(l), &l, sizeof(l));
break;
default:
@@ -90,17 +111,17 @@ static int virtio_mmio_set_config(struct udevice *udev, unsigned int offset,
break;
case 2:
memcpy(&w, buf, sizeof(w));
- writew(le16_to_cpu(w), base + offset);
+ virtio_mmio_writew(le16_to_cpu(w), base + offset);
break;
case 4:
memcpy(&l, buf, sizeof(l));
- writel(le32_to_cpu(l), base + offset);
+ virtio_mmio_writel(le32_to_cpu(l), base + offset);
break;
case 8:
memcpy(&l, buf, sizeof(l));
- writel(le32_to_cpu(l), base + offset);
+ virtio_mmio_writel(le32_to_cpu(l), base + offset);
memcpy(&l, buf + sizeof(l), sizeof(l));
- writel(le32_to_cpu(l), base + offset + sizeof(l));
+ virtio_mmio_writel(le32_to_cpu(l), base + offset + sizeof(l));
break;
default:
WARN_ON(true);
@@ -116,7 +137,7 @@ static int virtio_mmio_generation(struct udevice *udev, u32 *counter)
if (priv->version == 1)
*counter = 0;
else
- *counter = readl(priv->base + VIRTIO_MMIO_CONFIG_GENERATION);
+ *counter = virtio_mmio_readl(priv->base + VIRTIO_MMIO_CONFIG_GENERATION);
return 0;
}
@@ -125,7 +146,7 @@ static int virtio_mmio_get_status(struct udevice *udev, u8 *status)
{
struct virtio_mmio_priv *priv = dev_get_priv(udev);
- *status = readl(priv->base + VIRTIO_MMIO_STATUS) & 0xff;
+ *status = virtio_mmio_readl(priv->base + VIRTIO_MMIO_STATUS) & 0xff;
return 0;
}
@@ -137,7 +158,7 @@ static int virtio_mmio_set_status(struct udevice *udev, u8 status)
/* We should never be setting status to 0 */
WARN_ON(status == 0);
- writel(status, priv->base + VIRTIO_MMIO_STATUS);
+ virtio_mmio_writel(status, priv->base + VIRTIO_MMIO_STATUS);
return 0;
}
@@ -147,7 +168,7 @@ static int virtio_mmio_reset(struct udevice *udev)
struct virtio_mmio_priv *priv = dev_get_priv(udev);
/* 0 status means a reset */
- writel(0, priv->base + VIRTIO_MMIO_STATUS);
+ virtio_mmio_writel(0, priv->base + VIRTIO_MMIO_STATUS);
return 0;
}
@@ -156,12 +177,12 @@ static int virtio_mmio_get_features(struct udevice *udev, u64 *features)
{
struct virtio_mmio_priv *priv = dev_get_priv(udev);
- writel(1, priv->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL);
- *features = readl(priv->base + VIRTIO_MMIO_DEVICE_FEATURES);
+ virtio_mmio_writel(1, priv->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL);
+ *features = virtio_mmio_readl(priv->base + VIRTIO_MMIO_DEVICE_FEATURES);
*features <<= 32;
- writel(0, priv->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL);
- *features |= readl(priv->base + VIRTIO_MMIO_DEVICE_FEATURES);
+ virtio_mmio_writel(0, priv->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL);
+ *features |= virtio_mmio_readl(priv->base + VIRTIO_MMIO_DEVICE_FEATURES);
return 0;
}
@@ -177,12 +198,12 @@ static int virtio_mmio_set_features(struct udevice *udev)
return -EINVAL;
}
- writel(1, priv->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL);
- writel((u32)(uc_priv->features >> 32),
+ virtio_mmio_writel(1, priv->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL);
+ virtio_mmio_writel((u32)(uc_priv->features >> 32),
priv->base + VIRTIO_MMIO_DRIVER_FEATURES);
- writel(0, priv->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL);
- writel((u32)uc_priv->features,
+ virtio_mmio_writel(0, priv->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL);
+ virtio_mmio_writel((u32)uc_priv->features,
priv->base + VIRTIO_MMIO_DRIVER_FEATURES);
return 0;
@@ -197,16 +218,16 @@ static struct virtqueue *virtio_mmio_setup_vq(struct udevice *udev,
int err;
/* Select the queue we're interested in */
- writel(index, priv->base + VIRTIO_MMIO_QUEUE_SEL);
+ virtio_mmio_writel(index, priv->base + VIRTIO_MMIO_QUEUE_SEL);
/* Queue shouldn't already be set up */
- if (readl(priv->base + (priv->version == 1 ?
+ if (virtio_mmio_readl(priv->base + (priv->version == 1 ?
VIRTIO_MMIO_QUEUE_PFN : VIRTIO_MMIO_QUEUE_READY))) {
err = -ENOENT;
goto error_available;
}
- num = readl(priv->base + VIRTIO_MMIO_QUEUE_NUM_MAX);
+ num = virtio_mmio_readl(priv->base + VIRTIO_MMIO_QUEUE_NUM_MAX);
if (num == 0) {
err = -ENOENT;
goto error_new_virtqueue;
@@ -220,7 +241,7 @@ static struct virtqueue *virtio_mmio_setup_vq(struct udevice *udev,
}
/* Activate the queue */
- writel(virtqueue_get_vring_size(vq),
+ virtio_mmio_writel(virtqueue_get_vring_size(vq),
priv->base + VIRTIO_MMIO_QUEUE_NUM);
if (priv->version == 1) {
u64 q_pfn = virtqueue_get_desc_addr(vq) >> PAGE_SHIFT;
@@ -237,27 +258,27 @@ static struct virtqueue *virtio_mmio_setup_vq(struct udevice *udev,
goto error_bad_pfn;
}
- writel(PAGE_SIZE, priv->base + VIRTIO_MMIO_QUEUE_ALIGN);
- writel(q_pfn, priv->base + VIRTIO_MMIO_QUEUE_PFN);
+ virtio_mmio_writel(PAGE_SIZE, priv->base + VIRTIO_MMIO_QUEUE_ALIGN);
+ virtio_mmio_writel(q_pfn, priv->base + VIRTIO_MMIO_QUEUE_PFN);
} else {
u64 addr;
addr = virtqueue_get_desc_addr(vq);
- writel((u32)addr, priv->base + VIRTIO_MMIO_QUEUE_DESC_LOW);
- writel((u32)(addr >> 32),
+ virtio_mmio_writel((u32)addr, priv->base + VIRTIO_MMIO_QUEUE_DESC_LOW);
+ virtio_mmio_writel((u32)(addr >> 32),
priv->base + VIRTIO_MMIO_QUEUE_DESC_HIGH);
addr = virtqueue_get_avail_addr(vq);
- writel((u32)addr, priv->base + VIRTIO_MMIO_QUEUE_AVAIL_LOW);
- writel((u32)(addr >> 32),
+ virtio_mmio_writel((u32)addr, priv->base + VIRTIO_MMIO_QUEUE_AVAIL_LOW);
+ virtio_mmio_writel((u32)(addr >> 32),
priv->base + VIRTIO_MMIO_QUEUE_AVAIL_HIGH);
addr = virtqueue_get_used_addr(vq);
- writel((u32)addr, priv->base + VIRTIO_MMIO_QUEUE_USED_LOW);
- writel((u32)(addr >> 32),
+ virtio_mmio_writel((u32)addr, priv->base + VIRTIO_MMIO_QUEUE_USED_LOW);
+ virtio_mmio_writel((u32)(addr >> 32),
priv->base + VIRTIO_MMIO_QUEUE_USED_HIGH);
- writel(1, priv->base + VIRTIO_MMIO_QUEUE_READY);
+ virtio_mmio_writel(1, priv->base + VIRTIO_MMIO_QUEUE_READY);
}
return vq;
@@ -267,10 +288,10 @@ error_bad_pfn:
error_new_virtqueue:
if (priv->version == 1) {
- writel(0, priv->base + VIRTIO_MMIO_QUEUE_PFN);
+ virtio_mmio_writel(0, priv->base + VIRTIO_MMIO_QUEUE_PFN);
} else {
- writel(0, priv->base + VIRTIO_MMIO_QUEUE_READY);
- WARN_ON(readl(priv->base + VIRTIO_MMIO_QUEUE_READY));
+ virtio_mmio_writel(0, priv->base + VIRTIO_MMIO_QUEUE_READY);
+ WARN_ON(virtio_mmio_readl(priv->base + VIRTIO_MMIO_QUEUE_READY));
}
error_available:
@@ -283,12 +304,12 @@ static void virtio_mmio_del_vq(struct virtqueue *vq)
unsigned int index = vq->index;
/* Select and deactivate the queue */
- writel(index, priv->base + VIRTIO_MMIO_QUEUE_SEL);
+ virtio_mmio_writel(index, priv->base + VIRTIO_MMIO_QUEUE_SEL);
if (priv->version == 1) {
- writel(0, priv->base + VIRTIO_MMIO_QUEUE_PFN);
+ virtio_mmio_writel(0, priv->base + VIRTIO_MMIO_QUEUE_PFN);
} else {
- writel(0, priv->base + VIRTIO_MMIO_QUEUE_READY);
- WARN_ON(readl(priv->base + VIRTIO_MMIO_QUEUE_READY));
+ virtio_mmio_writel(0, priv->base + VIRTIO_MMIO_QUEUE_READY);
+ WARN_ON(virtio_mmio_readl(priv->base + VIRTIO_MMIO_QUEUE_READY));
}
vring_del_virtqueue(vq);
@@ -329,7 +350,7 @@ static int virtio_mmio_notify(struct udevice *udev, struct virtqueue *vq)
* We write the queue's selector into the notification register
* to signal the other end
*/
- writel(vq->index, priv->base + VIRTIO_MMIO_QUEUE_NOTIFY);
+ virtio_mmio_writel(vq->index, priv->base + VIRTIO_MMIO_QUEUE_NOTIFY);
return 0;
}
@@ -359,14 +380,14 @@ static int virtio_mmio_probe(struct udevice *udev)
priv->base = (void __iomem *)plat->base;
/* Check magic value */
- magic = readl(priv->base + VIRTIO_MMIO_MAGIC_VALUE);
+ magic = virtio_mmio_readl(priv->base + VIRTIO_MMIO_MAGIC_VALUE);
if (magic != ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)) {
debug("(%s): wrong magic value 0x%08x!\n", udev->name, magic);
return 0;
}
/* Check device version */
- priv->version = readl(priv->base + VIRTIO_MMIO_VERSION);
+ priv->version = virtio_mmio_readl(priv->base + VIRTIO_MMIO_VERSION);
if (priv->version < 1 || priv->version > 2) {
debug("(%s): version %d not supported!\n",
udev->name, priv->version);
@@ -374,7 +395,7 @@ static int virtio_mmio_probe(struct udevice *udev)
}
/* Check device ID */
- uc_priv->device = readl(priv->base + VIRTIO_MMIO_DEVICE_ID);
+ uc_priv->device = virtio_mmio_readl(priv->base + VIRTIO_MMIO_DEVICE_ID);
if (uc_priv->device == 0) {
/*
* virtio-mmio device with an ID 0 is a (dummy) placeholder
@@ -382,10 +403,11 @@ static int virtio_mmio_probe(struct udevice *udev)
*/
return 0;
}
- uc_priv->vendor = readl(priv->base + VIRTIO_MMIO_VENDOR_ID);
+ /* This is actually used as little endian locally? noice */
+ uc_priv->vendor = cpu_to_le32(virtio_mmio_readl(priv->base + VIRTIO_MMIO_VENDOR_ID));
if (priv->version == 1)
- writel(PAGE_SIZE, priv->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
+ virtio_mmio_writel(PAGE_SIZE, priv->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
debug("(%s): device (%d) vendor (%08x) version (%d)\n", udev->name,
uc_priv->device, uc_priv->vendor, priv->version);
--
2.51.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [RFC PATCH 3/3] board: qemu: m68k: Create virtio mmio instances
2026-03-10 13:59 [RFC PATCH 0/3] Add virtio-mmio support to m68k virt machine Daniel Palmer
2026-03-10 13:59 ` [RFC PATCH 1/3] virtio: mmio: Allow instantiation via platform data Daniel Palmer
2026-03-10 13:59 ` [RFC PATCH 2/3] virtio: mmio: endian *fixes* *HACK* Daniel Palmer
@ 2026-03-10 13:59 ` Daniel Palmer
2 siblings, 0 replies; 7+ messages in thread
From: Daniel Palmer @ 2026-03-10 13:59 UTC (permalink / raw)
To: visitorckw, angelo, bmeng.cn; +Cc: laurent, u-boot, Daniel Palmer
So that you can use virtio network, block etc create the virtio mmio
instances. There are 128 of these even if they are not all used, a
single mmio base value is passed via bootinfo.
Signed-off-by: Daniel Palmer <daniel@thingy.jp>
---
arch/m68k/Kconfig | 14 ++++----
board/emulation/qemu-m68k/qemu-m68k.c | 46 +++++++++++++++++++++++++++
2 files changed, 54 insertions(+), 6 deletions(-)
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 6ce8f577e3a1..20a112880c87 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -195,12 +195,14 @@ config TARGET_STMARK2
select M54418
config TARGET_QEMU_M68K
- bool "Support QEMU m68k virt"
- select M68040
- imply CMD_DM
- help
- This target supports the QEMU m68k virtual machine (-M virt).
- It simulates a Motorola 68040 CPU with Goldfish peripherals.
+ bool "Support QEMU m68k virt"
+ select M68040
+ select BOARD_EARLY_INIT_R
+ select VIRTIO_MMIO
+ imply CMD_DM
+ help
+ This target supports the QEMU m68k virtual machine (-M virt).
+ It simulates a Motorola 68040 CPU with Goldfish peripherals.
endchoice
diff --git a/board/emulation/qemu-m68k/qemu-m68k.c b/board/emulation/qemu-m68k/qemu-m68k.c
index d3527aee1128..2517ecf1bb8c 100644
--- a/board/emulation/qemu-m68k/qemu-m68k.c
+++ b/board/emulation/qemu-m68k/qemu-m68k.c
@@ -14,9 +14,14 @@
#include <asm/bootinfo.h>
#include <asm/global_data.h>
#include <asm/io.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
#include <dm/platdata.h>
+#include <dm/root.h>
#include <linux/errno.h>
#include <linux/sizes.h>
+#include <virtio_mmio.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -25,6 +30,37 @@ static struct goldfish_rtc_plat rtc_plat;
static struct goldfish_timer_plat timer_plat;
static struct qemu_virt_ctrl_plat reset_plat;
+#define VIRTIO_MMIO_NUM 128
+#define VIRTIO_MMIO_SZ 0x200
+
+static struct virtio_mmio_plat virtio_mmio_plat[VIRTIO_MMIO_NUM] = { 0 };
+static char virtio_mmio_names[VIRTIO_MMIO_NUM][11] = { 0 };
+static phys_addr_t virtio_mmio_base = 0;
+
+static inline int create_virtio_mmios(void)
+{
+ struct driver *drv;
+ int i, ret;
+
+ if (!virtio_mmio_base)
+ return -ENODEV;
+
+ drv = lists_driver_lookup_name("virtio-mmio");
+ if (!drv)
+ return -ENOENT;
+
+ for (i = 0; i < VIRTIO_MMIO_NUM; i++) {
+ virtio_mmio_plat[i].base = virtio_mmio_base + (VIRTIO_MMIO_SZ * i);
+ sprintf(virtio_mmio_names[i], "virtio-%d", i);
+
+ ret = device_bind(dm_root(), drv, virtio_mmio_names[i], &virtio_mmio_plat[i], ofnode_null(), NULL);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
/*
* Theoretical limit derivation:
* Max Bootinfo Size (Standard Page) = 4096 bytes
@@ -65,6 +101,9 @@ static void parse_bootinfo(void)
case BI_VIRT_CTRL_BASE:
reset_plat.reg = base;
break;
+ case BI_VIRT_VIRTIO_BASE:
+ virtio_mmio_base = base;
+ break;
case BI_MEMCHUNK:
gd->ram_size = record->data[1];
break;
@@ -80,6 +119,13 @@ int board_early_init_f(void)
return 0;
}
+int board_early_init_r(void)
+{
+ create_virtio_mmios();
+
+ return 0;
+}
+
int checkboard(void)
{
puts("Board: QEMU m68k virt\n");
--
2.51.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [RFC PATCH 2/3] virtio: mmio: endian *fixes* *HACK*
2026-03-10 13:59 ` [RFC PATCH 2/3] virtio: mmio: endian *fixes* *HACK* Daniel Palmer
@ 2026-03-14 8:53 ` Daniel Palmer
2026-04-02 19:43 ` Kuan-Wei Chiu
0 siblings, 1 reply; 7+ messages in thread
From: Daniel Palmer @ 2026-03-14 8:53 UTC (permalink / raw)
To: visitorckw, angelo, bmeng.cn; +Cc: laurent, u-boot
Hi all,
On Tue, 10 Mar 2026 at 23:01, Daniel Palmer <daniel@thingy.jp> wrote:
>
> From: Daniel Palmer <daniel@0x0f.com>
>
> This is an attempt to *fix* virtio mmio on the QEMU m68k virt machine.
> As far as I can tell all of the registers in the virtio mmio regions
> should be little endian so after reading them they need to be converted
> to big endian for the code to work on them? other parts of the code
> are also doing endian conversion so I'm not sure.
>
> Or QEMU is incorrectly giving big endian register values?
> ---
I have a patch for this in my Linux tree too so I sent that:
https://lore.kernel.org/lkml/20260314030612.1949420-1-daniel@thingy.jp/T/#mab66837bb90c30916fd0fc066245bdeb9918e96c
It would seem our versions of readl(), writel() etc are broken. For
Linux the nommu versions are broken, for u-boot it seems they are all
broken. By broken I mean they should be expecting a little endian
value from the access and then converting to the CPU endian. (I think)
Cheers,
Daniel
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH 2/3] virtio: mmio: endian *fixes* *HACK*
2026-03-14 8:53 ` Daniel Palmer
@ 2026-04-02 19:43 ` Kuan-Wei Chiu
2026-04-04 1:49 ` Daniel Palmer
0 siblings, 1 reply; 7+ messages in thread
From: Kuan-Wei Chiu @ 2026-04-02 19:43 UTC (permalink / raw)
To: Daniel Palmer; +Cc: angelo, bmeng.cn, laurent, u-boot
Hi Daniel,
On Sat, Mar 14, 2026 at 05:53:17PM +0900, Daniel Palmer wrote:
> Hi all,
>
> On Tue, 10 Mar 2026 at 23:01, Daniel Palmer <daniel@thingy.jp> wrote:
> >
> > From: Daniel Palmer <daniel@0x0f.com>
> >
> > This is an attempt to *fix* virtio mmio on the QEMU m68k virt machine.
> > As far as I can tell all of the registers in the virtio mmio regions
> > should be little endian so after reading them they need to be converted
> > to big endian for the code to work on them? other parts of the code
> > are also doing endian conversion so I'm not sure.
> >
> > Or QEMU is incorrectly giving big endian register values?
> > ---
>
> I have a patch for this in my Linux tree too so I sent that:
> https://lore.kernel.org/lkml/20260314030612.1949420-1-daniel@thingy.jp/T/#mab66837bb90c30916fd0fc066245bdeb9918e96c
> It would seem our versions of readl(), writel() etc are broken. For
> Linux the nommu versions are broken, for u-boot it seems they are all
> broken. By broken I mean they should be expecting a little endian
> value from the access and then converting to the CPU endian. (I think)
>
Sorry for the late reply.
So it sounds like we have to fix all the broken readl/writel() in both
Linux and U-Boot first.
For U-Boot, I think we need the following fix? (totally untested yet)
diff --git a/arch/m68k/include/asm/io.h b/arch/m68k/include/asm/io.h
index 35ad4a1c044..0106a57a03e 100644
--- a/arch/m68k/include/asm/io.h
+++ b/arch/m68k/include/asm/io.h
@@ -31,10 +31,10 @@
#define writew(b,addr) ((*(volatile u16 *) (addr)) = (b))
#define writel(b,addr) ((*(volatile u32 *) (addr)) = (b))
#else
-#define readw(addr) in_be16((volatile u16 *)(addr))
-#define readl(addr) in_be32((volatile u32 *)(addr))
-#define writew(b,addr) out_be16((volatile u16 *)(addr),(b))
-#define writel(b,addr) out_be32((volatile u32 *)(addr),(b))
+#define readw(addr) in_le16((volatile u16 *)(addr))
+#define readl(addr) in_le32((volatile u32 *)(addr))
+#define writew(b,addr) out_le16((volatile u16 *)(addr),(b))
+#define writel(b,addr) out_le32((volatile u32 *)(addr),(b))
#endif
/*
Regards,
Kuan-Wei
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [RFC PATCH 2/3] virtio: mmio: endian *fixes* *HACK*
2026-04-02 19:43 ` Kuan-Wei Chiu
@ 2026-04-04 1:49 ` Daniel Palmer
0 siblings, 0 replies; 7+ messages in thread
From: Daniel Palmer @ 2026-04-04 1:49 UTC (permalink / raw)
To: Kuan-Wei Chiu; +Cc: angelo, bmeng.cn, laurent, u-boot
Hi Kuan-Wei,
On Fri, 3 Apr 2026 at 04:43, Kuan-Wei Chiu <visitorckw@gmail.com> wrote:
> >
> > I have a patch for this in my Linux tree too so I sent that:
> > https://lore.kernel.org/lkml/20260314030612.1949420-1-daniel@thingy.jp/T/#mab66837bb90c30916fd0fc066245bdeb9918e96c
> > It would seem our versions of readl(), writel() etc are broken. For
> > Linux the nommu versions are broken, for u-boot it seems they are all
> > broken. By broken I mean they should be expecting a little endian
> > value from the access and then converting to the CPU endian. (I think)
> >
>
> Sorry for the late reply.
>
> So it sounds like we have to fix all the broken readl/writel() in both
> Linux and U-Boot first.
>
> For U-Boot, I think we need the following fix? (totally untested yet)
>
> diff --git a/arch/m68k/include/asm/io.h b/arch/m68k/include/asm/io.h
> index 35ad4a1c044..0106a57a03e 100644
> --- a/arch/m68k/include/asm/io.h
> +++ b/arch/m68k/include/asm/io.h
> @@ -31,10 +31,10 @@
> #define writew(b,addr) ((*(volatile u16 *) (addr)) = (b))
> #define writel(b,addr) ((*(volatile u32 *) (addr)) = (b))
> #else
> -#define readw(addr) in_be16((volatile u16 *)(addr))
> -#define readl(addr) in_be32((volatile u32 *)(addr))
> -#define writew(b,addr) out_be16((volatile u16 *)(addr),(b))
> -#define writel(b,addr) out_be32((volatile u32 *)(addr),(b))
> +#define readw(addr) in_le16((volatile u16 *)(addr))
> +#define readl(addr) in_le32((volatile u32 *)(addr))
> +#define writew(b,addr) out_le16((volatile u16 *)(addr),(b))
> +#define writel(b,addr) out_le32((volatile u32 *)(addr),(b))
> #endif
>
> /*
Doing this might fix virtio but break anything that relies on the
current behaviour. At least in Linux Coldfire has hacks in its io
macros to retain the broken behaviour for certain places but have the
correct behaviour for others (PCI I guess).
Since MMU-abled classic m68k seems to have the correct behaviour in
Linux I think we should split the u-boot io macros into Coldfire and
classic m68k and make classic m68k match Linux. That will avoid
breaking anything in coldfire that uses the io macros and depends on
the current behavior. But I guess we might need to revisit the pieces
you added for the virt machine to make sure they still work.
nommu classic m68k is broken in Linux but I intend to send a patch to
make it match MMU classic m68k.
Cheers,
Daniel
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-04-04 1:49 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-10 13:59 [RFC PATCH 0/3] Add virtio-mmio support to m68k virt machine Daniel Palmer
2026-03-10 13:59 ` [RFC PATCH 1/3] virtio: mmio: Allow instantiation via platform data Daniel Palmer
2026-03-10 13:59 ` [RFC PATCH 2/3] virtio: mmio: endian *fixes* *HACK* Daniel Palmer
2026-03-14 8:53 ` Daniel Palmer
2026-04-02 19:43 ` Kuan-Wei Chiu
2026-04-04 1:49 ` Daniel Palmer
2026-03-10 13:59 ` [RFC PATCH 3/3] board: qemu: m68k: Create virtio mmio instances Daniel Palmer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox