From: Jamin Lin <jamin_lin@aspeedtech.com>
To: "Paolo Bonzini" <pbonzini@redhat.com>,
"Peter Maydell" <peter.maydell@linaro.org>,
"Cédric Le Goater" <clg@kaod.org>,
"Steven Lee" <steven_lee@aspeedtech.com>,
"Troy Lee" <leetroy@gmail.com>,
"Kane Chen" <kane_chen@aspeedtech.com>,
"Andrew Jeffery" <andrew@codeconstruct.com.au>,
"Joel Stanley" <joel@jms.id.au>,
"open list:ARM TCG CPUs" <qemu-arm@nongnu.org>,
"open list:All patches CC here" <qemu-devel@nongnu.org>
Cc: Jamin Lin <jamin_lin@aspeedtech.com>, Troy Lee <troy_lee@aspeedtech.com>
Subject: [PATCH v1 0/3] hw/usb: Add ASPEED USB Device Controller (UDC)
Date: Fri, 3 Jul 2026 07:43:33 +0000 [thread overview]
Message-ID: <20260703074332.1049473-1-jamin_lin@aspeedtech.com> (raw)
This series adds a QEMU model for the ASPEED USB Device Controller (UDC),
driven by the Linux "aspeed_udc" gadget driver.
It is the first step of a larger plan to model USB device-side support on
ASPEED BMC/BIC SoCs, which has three goals:
1. Model the ASPEED UDC (AST2600 / AST1030). The AST2600 also has USB host
(EHCI) controllers, so this series targets the AST2600 UDC: its gadget can
be attached to the SoC's own EHCI bus, letting the guest enumerate its own
gadget and exercise the UDC end-to-end. [this series]
2. AST1030 UDC. The AST1030 has no USB host controller, so testing its UDC
needs a second QEMU instance. The plan is to redirect the UDC gadget out
of the guest using libusbredir and attach it to another QEMU that runs a
USB host (a VMM, or an AST2600 / AST2700 guest). [on-going]
3. ASPEED vHub, as a longer-term goal towards BMC KVM / Virtual Media support
in QEMU. [future]
This series implements goal 1 only.
Design
------
The UDC is modelled as two QOM objects, because a single object cannot be
both a SysBusDevice and a USBDevice:
- "aspeed.udc": the sysbus device (MMIO register map, IRQ and DMA engine)
that the guest gadget driver programs.
- "aspeed.udc-gadget": a user-creatable USB device presented on a USB host
controller's bus. It links back to its controller through the "udc"
property.
The SoC creates the controller; the gadget is added on the command line, e.g.
-device aspeed.udc-gadget,udc=/machine/soc/udc
Test result:
-----------
The default ASPEED SDK prebuilt image does not enable the UDC driver, so
build a kernel with CONFIG_USB_ASPEED_UDC=y first.
Start QEMU with the gadget attached to the on-SoC EHCI:
qemu-system-arm -machine ast2600-evb -drive file=<image>,if=mtd,format=raw \
-device aspeed.udc-gadget,udc=/machine/soc/udc -nographic
In the guest, bring up a mass-storage gadget and verify enumeration and I/O:
1. Before: only the host controllers are present
root@ast2600-default:~# lsusb
unable to initialize usb specBus 001 Device 001: ID 1d6b:0002 Linux 6.18.20-dirty-32e49fb4a22b-g32e49fb4a22b-dirty ehci_hcd EHCI Host Controller
Bus 002 Device 001: ID 1d6b:0001 Linux 6.18.20-dirty-32e49fb4a22b-g32e49fb4a22b-dirty uhci_hcd Generic UHCI Host Controller
2. Enable the gadget
root@ast2600-default:~# ./usb-storage.sh
Using UDC: 1e6a2000.usb
[ 598.582205] Mass Storage Function, version: 2009/09/11
[ 598.582635] LUN: removable file: (no medium)
USB Mass Storage gadget is enabled.
Backing file: /home/root/jamin
root@ast2600-default:~# [ 598.876395] usb 1-1: new high-speed USB device number 2 using ehci-platform
[ 599.070035] usb 1-1: New USB device found, idVendor=1d6b, idProduct=0104, bcdDevice= 1.00
[ 599.070821] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 599.071448] usb 1-1: Product: ASPEED USB Storage
[ 599.072687] usb 1-1: Manufacturer: ASPEED
[ 599.073384] usb 1-1: SerialNumber: 1234567890
[ 599.103625] usb-storage 1-1:1.0: USB Mass Storage device detected
[ 599.136326] scsi host0: usb-storage 1-1:1.0
[ 600.230921] scsi 0:0:0:0: Direct-Access Linux File-Stor Gadget 0618 PQ: 0 ANSI: 2
[ 600.243758] sd 0:0:0:0: Attached scsi generic sg0 type 0
[ 600.263452] sd 0:0:0:0: Power-on or device reset occurred
[ 600.289381] sd 0:0:0:0: [sda] 2048 512-byte logical blocks: (1.05 MB/1.00 MiB)
[ 600.297896] sd 0:0:0:0: [sda] Write Protect is off
[ 600.306379] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 600.424608] sda:
[ 600.425526] sd 0:0:0:0: [sda] Attached SCSI removable disk
3. After: the gadget enumerates on the EHCI bus
root@ast2600-default:~# lsusb
unable to initialize usb specBus 001 Device 001: ID 1d6b:0002 Linux 6.18.20-dirty-32e49fb4a22b-g32e49fb4a22b-dirty ehci_hcd EHCI Host Controller
Bus 001 Device 002: ID 1d6b:0104 ASPEED ASPEED USB Storage
Bus 002 Device 001: ID 1d6b:0001 Linux 6.18.20-dirty-32e49fb4a22b-g32e49fb4a22b-dirty uhci_hcd Generic UHCI Host Controller
4. Mount and verify data
root@ast2600-default:~# mount /dev/sda /mnt/
root@ast2600-default:~# sha256sum /mnt/testfile
3308890a1289f6a327c014537523e8ebd0833301af3d25a7c5893dc7050d2c70 /mnt/testfile
root@ast2600-default:~# umount /mnt
5. Stop the gadget -> clean disconnect
root@ast2600-default:~# ./usb-storage.sh stop
Stopping USB gadget...
[ 669.866439] usb 1-1: USB disconnect, device number 2
Stopped.
root@ast2600-default:~# [ 669.968156] sd 0:0:0:0: [sda] Synchronizing SCSI cache
[ 669.969307] sd 0:0:0:0: [sda] Synchronize Cache(10) failed: Result: hostbyte=0x01 driverbyte=DRIVER_OK
root@ast2600-default:~# lsusb
unable to initialize usb specBus 001 Device 001: ID 1d6b:0002 Linux 6.18.20-dirty-32e49fb4a22b-g32e49fb4a22b-dirty ehci_hcd EHCI Host Controller
Bus 002 Device 001: ID 1d6b:0001 Linux 6.18.20-dirty-32e49fb4a22b-g32e49fb4a22b-dirty uhci_hcd Generic UHCI Host Controller
The contents of this scripts
---------------------------
root@ast2600-default:~# cat usb-storage.sh
#!/bin/sh
set -e
G=/sys/kernel/config/usb_gadget/g1
IMG=/home/root/jamin
SIZE_MB=64
mount_configfs()
{
mountpoint -q /sys/kernel/config || mount -t configfs none /sys/kernel/config
}
get_udc()
{
ls /sys/class/udc | head -n 1
}
stop_gadget()
{
if [ ! -d "$G" ]; then
return
fi
echo "Stopping USB gadget..."
# Unbind UDC first
if [ -f "$G/UDC" ]; then
echo "" > "$G/UDC" 2>/dev/null || true
fi
# Clear backing file to release image
if [ -f "$G/functions/mass_storage.0/lun.0/file" ]; then
echo "" > "$G/functions/mass_storage.0/lun.0/file" 2>/dev/null || true
fi
# Remove function link from config
rm -f "$G/configs/c.1/mass_storage.0" 2>/dev/null || true
echo "Stopped."
}
start_gadget()
{
mount_configfs
UDC="$(get_udc)"
if [ -z "$UDC" ]; then
echo "ERROR: No UDC found in /sys/class/udc"
exit 1
fi
stop_gadget
echo "Using UDC: $UDC"
modprobe libcomposite 2>/dev/null || true
mkdir -p "$G"
cd "$G"
echo 0x1d6b > idVendor
echo 0x0104 > idProduct
echo 0x0200 > bcdUSB
echo 0x0100 > bcdDevice
mkdir -p strings/0x409
echo "1234567890" > strings/0x409/serialnumber
echo "ASPEED" > strings/0x409/manufacturer
echo "ASPEED USB Storage" > strings/0x409/product
mkdir -p configs/c.1/strings/0x409
echo "Mass Storage" > configs/c.1/strings/0x409/configuration
echo 120 > configs/c.1/MaxPower
if [ ! -f "$IMG" ]; then
echo "Creating backing image: $IMG"
dd if=/dev/zero of="$IMG" bs=1M count="$SIZE_MB"
mkfs.vfat "$IMG"
fi
mkdir -p functions/mass_storage.0
# Make sure old LUN is detached before changing attributes
echo "" > functions/mass_storage.0/lun.0/file 2>/dev/null || true
echo 0 > functions/mass_storage.0/stall
echo 0 > functions/mass_storage.0/lun.0/cdrom
echo 0 > functions/mass_storage.0/lun.0/ro
echo 1 > functions/mass_storage.0/lun.0/removable
echo "$IMG" > functions/mass_storage.0/lun.0/file
ln -sf functions/mass_storage.0 configs/c.1/mass_storage.0
echo "$UDC" > UDC
echo "USB Mass Storage gadget is enabled."
echo "Backing file: $IMG"
}
case "$1" in
start|"")
start_gadget
;;
stop)
stop_gadget
;;
restart)
stop_gadget
sleep 1
start_gadget
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac
v1:
1. Add ASPEED UDC device controller
2. Add ASPEED UDC gadget USB device
Jamin Lin (3):
hw/usb/aspeed-udc: Add ASPEED UDC device controller
hw/usb/aspeed-udc: Add ASPEED UDC gadget USB device
hw/arm/aspeed_ast2600: Wire up the UDC
hw/arm/Kconfig | 1 +
hw/arm/aspeed_ast2600.c | 13 +
hw/usb/Kconfig | 4 +
hw/usb/aspeed-udc.c | 930 ++++++++++++++++++++++++++++++++++++
hw/usb/meson.build | 1 +
hw/usb/trace-events | 16 +
include/hw/arm/aspeed_soc.h | 2 +
include/hw/usb/aspeed-udc.h | 84 ++++
8 files changed, 1051 insertions(+)
create mode 100644 hw/usb/aspeed-udc.c
create mode 100644 include/hw/usb/aspeed-udc.h
--
2.53.0
next reply other threads:[~2026-07-03 7:43 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-03 7:43 Jamin Lin [this message]
2026-07-03 7:43 ` [PATCH v1 1/3] hw/usb/aspeed-udc: Add ASPEED UDC device controller Jamin Lin
2026-07-09 21:03 ` Philippe Mathieu-Daudé
2026-07-03 7:43 ` [PATCH v1 2/3] hw/usb/aspeed-udc: Add ASPEED UDC gadget USB device Jamin Lin
2026-07-03 7:43 ` [PATCH v1 3/3] hw/arm/aspeed_ast2600: Wire up the UDC Jamin Lin
2026-07-09 21:10 ` Philippe Mathieu-Daudé
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260703074332.1049473-1-jamin_lin@aspeedtech.com \
--to=jamin_lin@aspeedtech.com \
--cc=andrew@codeconstruct.com.au \
--cc=clg@kaod.org \
--cc=joel@jms.id.au \
--cc=kane_chen@aspeedtech.com \
--cc=leetroy@gmail.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=steven_lee@aspeedtech.com \
--cc=troy_lee@aspeedtech.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox