From: Petar Stepanovic <pstepanovic@axiado.com>
To: Naveen Kumar Rajgiri Bassappa <rbnaveenkumar@axiado.com>,
Prasad Bolisetty <pbolisetty@axiado.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Tzu-Hao Wei <twei@axiado.com>,
Karthikeyan Mitran <kmitran@axiado.com>,
Philipp Zabel <p.zabel@pengutronix.de>
Cc: linux-usb@vger.kernel.org, devicetree@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, openbmc@lists.ozlabs.org,
Petar Stepanovic <pstepanovic@axiado.com>,
Krutik Shah <krutikshah@axiado.com>
Subject: [PATCH v3 0/6] Axiado AX3000 and AX3005 USB Device Controller (UDC)
Date: Tue, 20 Oct 2026 00:18:54 -0700 [thread overview]
Message-ID: <20261020-axiado-ax3000-usb-device-controller-v3-0-3012ecfc0a93@axiado.com> (raw)
Dear maintainers,
This series continues the work of adding support for the USB device
controller (UDC) integrated into the Axiado AX3000 and AX3005 SoCs.
The controller is based on the Corigine USB 3.1 IP core, which is
dual-role capable (device and host) at the hardware level. Which role
is active depends on which driver is bound to it: this series binds
it in device role, while host role would instead use a standard xHCI
host driver - the hardware itself does not fix the role. Endpoint 0
shares the same command-ring / event-ring / per-endpoint transfer-ring
TRB hardware as every other endpoint, so the driver tracks control
transfer stages (SETUP/DATA/STATUS) explicitly instead of relying on a
dedicated hardware FIFO. Other upstream TRB/ring based UDC drivers,
such as cdns2 (whose file layout this series' structure is now modeled
on), share this same shape for the same reason.
Since v2, the driver has been restructured to follow the file layout
and conventions of drivers/usb/gadget/udc/cdns2, split into
core/gadget/ep0/ring source files with ftrace tracepoint support, and
brought in line with cdns2's static/global function ratio. See the
detailed changelog below.
The devicetree binding also picks up one item left over from the v2
review: the description now notes the underlying core is dual-role
capable (device and host), used here in device role.
Tested on an Axiado AX3005 EVK with a mass-storage + composite HID
(keyboard/mouse) gadget, including repeated bind/unbind/rebind cycles
and host-driven bus resets.
Signed-off-by: Petar Stepanovic <pstepanovic@axiado.com>
---
Changes in v3:
Devicetree binding:
- Note that the underlying Corigine core is dual-role capable (device
and host), used here in device role.
- Drop the explicit maximum-speed property declaration. Krzysztof noted
in the v2 review that compatible already implies SuperSpeed
capability,
and testing confirms the property is not required.
- Reference the generic usb.yaml schema and replace additionalProperties
with unevaluatedProperties to permit standard USB properties while
rejecting unsupported properties.
- Validated the updated binding with dt_binding_check.
Driver structure (matching drivers/usb/gadget/udc/cdns2):
- Split crg_udc.c/crg_udc.h into crg-udc-core.c, crg-udc-gadget.c,
crg-udc-ep0.c, crg-udc-ring.c and crg-udc.h, one concern per file.
- Add ftrace tracepoint support (crg-udc-trace.h/.c) covering pullup,
doorbell, TRB queueing, event processing, control requests, and
request alloc/free/giveback, plus a decode-helper header
(crg-udc-debug.h) for the PORTSC/completion-code/TRB-type strings
used by the trace TP_printk()s.
- Make internal-only functions static and normalize the remaining
exported ones to a consistent crg_udc_ prefix.
- Reorganize #include lists so each file pulls in only the headers it
actually uses, instead of funneling every kernel header the driver
needs through the shared crg-udc.h.
- Match the SPDX/license comment style used elsewhere in the tree:
a line comment for the SPDX tag, block comment for the description
and copyright.
Bug fixes:
- Restore the VBUS-detect vendor-register write on udc_start(),
udc_stop(), remove() and shutdown(). Without it the controller never
considers itself powered and enumeration is unreliable.
- Restore the DATA_STAGE_XFER/DATA_STAGE_RECV cases dropped from the
EP0 status-stage completion handler. Without them, any control read
(e.g. GET_DESCRIPTOR) never arms its STATUS stage and the host times
out waiting for it.
- Fix the transfer-ring TRB-deferral check to defer building a TRB
only when the ring is actually full, not merely because another
request is already queued on the same endpoint. The stricter check
silently broke back-to-back completions on one endpoint, such as
mass storage's CSW immediately following its data stage.
- Restore the RUN-gated completion check in the hardware command
helper, so a command issued after the controller has already been
stopped (e.g. during udc_stop()) does not spin waiting on a
completion the hardware will never post.
- Call usb_gadget_udc_reset() on a bus reset so the composite/function
drivers correctly re-run set_alt() and re-enable their endpoints
after a reset, instead of composite silently treating a repeated
SET_CONFIGURATION as a no-op. This is deferred to a workqueue rather
than called directly from the port-status interrupt path, since the
synchronous call re-enters the function drivers and would otherwise
require dropping the driver lock in the middle of event processing.
- Clear the generic usb_ep.enabled flag and endpoint descriptors during
internal endpoint teardown and controller reset, preventing stale
endpoint state across sessions and allowing endpoints to be correctly
re-enabled after a new bind or reset.
Additional fixes from Sashiko review:
- Use dma_addr_t for DMA offset calculations and validate DMA address
translation failures before programming hardware registers.
- Reserve transfer-ring capacity and publish multi-TRB descriptors
only after all TRBs have been initialized.
- Track remaining TRBs and buffer length for requests spanning
multiple transfer descriptors.
- Advance the hardware dequeue pointer before completing canceled
requests, and restore the producer cycle state when rewinding rings.
- Detach pending requests before completing them during endpoint
teardown, and complete requests that fail during deferred queueing.
- Reduce the hardware reset timeout from 500 ms to 10 ms and release
the spinlock while polling for completion.
- Protect pullup register updates with the controller spinlock.
- Update the event-ring dequeue pointer before yielding the CPU.
- Unregister the interrupt handler before freeing DMA resources.
- Link to v2: https://patch.msgid.link/20260817-axiado-ax3000-usb-device-controller-v2-0-0ef033dd0a68@axiado.com
Changes in v2:
- Drop the dual (GPL-2.0+ OR MIT) license; the driver and header are now
GPL-2.0+ only.
- Register via module_platform_driver() and add MODULE_AUTHOR/MODULE_ALIAS
instead of the hand-written module_init/module_exit pair.
- Acquire clock, reset and PHY through the driver model
(devm_clk_get_optional, devm_reset_control_get_optional_exclusive,
devm_phy_optional_get), with teardown wired up via
devm_add_action_or_reset.
- Switch to devm_request_irq() and drop the manual free_irq() paths.
- Support multiple instances using an IDA (DEFINE_IDA/ida_alloc/ida_free)
instead of a file-static device counter.
- Read match data with device_get_match_data() and move the former
compile-time feature switches to DT properties (dis-u1u2-entry-quirk,
dis-u1u2-initiation-quirk, reinit-ep0-on-bus-reset).
- Set the DMA mask via dma_set_mask_and_coherent() with a 32-bit fallback,
and convert PM to SIMPLE_DEV_PM_OPS.
- Fix endianness handling for TRBs, events and endpoint contexts using
cpu_to_le32()/le32_to_cpu(), and decode setup packets without casting.
- Locking: pass the caller's IRQ flags through the completion paths so the
interrupt state is correctly restored across the unlock/lock window around
gadget callbacks.
- Properly free all coherent DMA allocations and add
dma_mapping_error() checks after dma_map_single()
- Fix DMA directions on the GET_STATUS/SET_SEL control transfers.
- Replace open-coded register busy-wait loops with
readl_poll_timeout_atomic() so they time out instead of spinning forever,
and return proper errnos (-EBUSY/-ETIMEDOUT/-EIO) instead of -1.
- Replace the custom SETF_VAR/GETF/MAKEF_VAR shift-and-mask macros with
FIELD_PREP/FIELD_GET (include linux/bitfield.h), and use BIT()/GENMASK()
and dma_wmb()/dma_rmb().
- Use DMA_MAPPING_ERROR instead of a private DMA_ADDR_INVALID.
- Remove the U-Boot-derived VBUS cable-detect routine, the VBUS-detect
kthread and its wait queue, dead defines and struct fields, the unused
interrupt-register-array macros, the mdelay()-based reset delays and the
bulk of the dev_dbg() tracing.
- Implement the pullup(is_on == 0) path and route suspend/shutdown through
pullup(0); mark crg_udc_ep_ops const and return IRQ_NONE from the shared
IRQ handler when the interrupt is not ours.
- Use dev_err_probe() with structured goto-based unwinding in probe.
- Reword the Kconfig help text for USB_CRG_UDC to name the crg_udc module.
- Link to v1: https://lore.kernel.org/r/20260202-axiado-ax3000-usb-device-controller-v1-0-45ce0a8b014f@axiado.com
To: Naveen Kumar Rajgiri Bassappa <rbnaveenkumar@axiado.com>
To: Prasad Bolisetty <pbolisetty@axiado.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: Rob Herring <robh@kernel.org>
To: Krzysztof Kozlowski <krzk+dt@kernel.org>
To: Conor Dooley <conor+dt@kernel.org>
To: Tzu-Hao Wei <twei@axiado.com>
To: Karthikeyan Mitran <kmitran@axiado.com>
To: Philipp Zabel <p.zabel@pengutronix.de>
To: Petar Stepanovic <pstepanovic@axiado.com>
Cc: linux-usb@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
---
Petar Stepanovic (6):
dt-bindings: usb: gadget: udc: add Axiado AX3000 and AX3005 UDC
usb: gadget: udc: crg: Add hardware definitions and structs
usb: gadget: udc: crg: Add ring and transfer management
usb: gadget: udc: crg: Add endpoint 0 handling
usb: gadget: udc: crg: Add gadget and endpoint operations
usb: gadget: udc: crg: Add core driver and build integration
.../devicetree/bindings/usb/axiado,ax3000-udc.yaml | 69 +
MAINTAINERS | 9 +
drivers/usb/gadget/udc/Kconfig | 2 +
drivers/usb/gadget/udc/Makefile | 1 +
drivers/usb/gadget/udc/crg/Kconfig | 16 +
drivers/usb/gadget/udc/crg/Makefile | 9 +
drivers/usb/gadget/udc/crg/crg-udc-core.c | 706 ++++++
drivers/usb/gadget/udc/crg/crg-udc-debug.h | 143 ++
drivers/usb/gadget/udc/crg/crg-udc-ep0.c | 1106 ++++++++++
drivers/usb/gadget/udc/crg/crg-udc-gadget.c | 2299 ++++++++++++++++++++
drivers/usb/gadget/udc/crg/crg-udc-ring.c | 664 ++++++
drivers/usb/gadget/udc/crg/crg-udc-trace.c | 9 +
drivers/usb/gadget/udc/crg/crg-udc-trace.h | 164 ++
drivers/usb/gadget/udc/crg/crg-udc.h | 722 ++++++
14 files changed, 5919 insertions(+)
---
base-commit: c68641afacd9ea5707a489b30f204d5e89b324e0
change-id: 20260128-axiado-ax3000-usb-device-controller-156d3f1840c9
Best regards,
--
Petar Stepanovic <pstepanovic@axiado.com>
next reply other threads:[~2026-10-20 7:19 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-20 7:18 Petar Stepanovic [this message]
2026-10-20 7:18 ` [PATCH v3 1/6] dt-bindings: usb: gadget: udc: add Axiado AX3000 and AX3005 UDC Petar Stepanovic
2026-10-20 7:18 ` [PATCH v3 2/6] usb: gadget: udc: crg: Add hardware definitions and structs Petar Stepanovic
2026-10-20 7:18 ` [PATCH v3 3/6] usb: gadget: udc: crg: Add ring and transfer management Petar Stepanovic
2026-10-20 7:18 ` [PATCH v3 4/6] usb: gadget: udc: crg: Add endpoint 0 handling Petar Stepanovic
2026-10-20 7:18 ` [PATCH v3 5/6] usb: gadget: udc: crg: Add gadget and endpoint operations Petar Stepanovic
2026-10-20 7:19 ` [PATCH v3 6/6] usb: gadget: udc: crg: Add core driver and build integration Petar Stepanovic
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=20261020-axiado-ax3000-usb-device-controller-v3-0-3012ecfc0a93@axiado.com \
--to=pstepanovic@axiado.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=kmitran@axiado.com \
--cc=krutikshah@axiado.com \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=openbmc@lists.ozlabs.org \
--cc=p.zabel@pengutronix.de \
--cc=pbolisetty@axiado.com \
--cc=rbnaveenkumar@axiado.com \
--cc=robh@kernel.org \
--cc=twei@axiado.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
all inboxes | Powered by JetHome®