From: Luca Lauro via B4 Relay <devnull+famlauro93l.gmail.com@kernel.org>
To: Sascha Hauer <s.hauer@pengutronix.de>,
"open list:BAREBOX" <barebox@lists.infradead.org>
Cc: Luca Lauro <famlauro93l@gmail.com>
Subject: [PATCH v2 08/10] usb: ehci: add Marvell EHCI host controller driver
Date: Tue, 28 Jul 2026 19:43:20 +0200 [thread overview]
Message-ID: <20260728-rn102-rn104-series-v2-8-ae31f55b7bc8@gmail.com> (raw)
In-Reply-To: <20260728-rn102-rn104-series-v2-0-ae31f55b7bc8@gmail.com>
From: Luca Lauro <famlauro93l@gmail.com>
Signed-off-by: Luca Lauro <famlauro93l@gmail.com>
---
drivers/usb/host/Kconfig | 7 ++
drivers/usb/host/Makefile | 13 +--
drivers/usb/host/ehci-marvell.c | 228 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 242 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 58f276cdb4..21bf876d69 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -22,6 +22,13 @@ config USB_EHCI_ZYNQ
help
Enable support for Zynq on-chip EHCI USB controller
+config USB_EHCI_MARVELL
+ bool "Marvell USB EHCI driver"
+ depends on ARCH_MVEBU
+ depends on USB_EHCI
+ help
+ Enable support for Marvell USB EHCI controller
+
config USB_OHCI
bool "OHCI driver"
depends on !MMU && HAS_DMA
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index cbddfbe923..932581d691 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -1,8 +1,9 @@
# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_USB_EHCI) += ehci-hcd.o
-obj-$(CONFIG_USB_EHCI_OMAP) += ehci-omap.o
+obj-$(CONFIG_USB_EHCI) += ehci-hcd.o
+obj-$(CONFIG_USB_EHCI_OMAP) += ehci-omap.o
obj-$(CONFIG_USB_EHCI_ATMEL) += ehci-atmel.o
-obj-$(CONFIG_USB_EHCI_ZYNQ) += ehci-zynq.o
-obj-$(CONFIG_USB_OHCI) += ohci-hcd.o
-obj-$(CONFIG_USB_OHCI_AT91) += ohci-at91.o
-obj-$(CONFIG_USB_XHCI) += xhci.o xhci-mem.o xhci-ring.o
+obj-$(CONFIG_USB_EHCI_ZYNQ) += ehci-zynq.o
+obj-$(CONFIG_USB_EHCI_MARVELL) += ehci-marvell.o
+obj-$(CONFIG_USB_OHCI) += ohci-hcd.o
+obj-$(CONFIG_USB_OHCI_AT91) += ohci-at91.o
+obj-$(CONFIG_USB_XHCI) += xhci.o xhci-mem.o xhci-ring.o
diff --git a/drivers/usb/host/ehci-marvell.c b/drivers/usb/host/ehci-marvell.c
new file mode 100644
index 0000000000..0d0ad13c82
--- /dev/null
+++ b/drivers/usb/host/ehci-marvell.c
@@ -0,0 +1,228 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Marvell Orion / Kirkwood / Armada EHCI host controller for barebox
+ *
+ * Ported from the modern U-Boot ehci-marvell.c implementation and
+ * adapted to the barebox ehci_register() model.
+ */
+
+/*#define DEBUG*/
+
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <io.h>
+#include <of.h>
+#include <linux/usb/usb.h>
+#include <linux/usb/ehci.h>
+#include <linux/mbus.h>
+
+#include "ehci.h"
+
+#define USB_WINDOW_CTRL(i) (0x320 + ((i) << 4))
+#define USB_WINDOW_BASE(i) (0x324 + ((i) << 4))
+#define USB_TARGET_DRAM 0x0
+
+#define USB2_SBUSCFG_OFF 0x90
+
+#define USB_SBUSCFG_BAWR_OFF 0x6
+#define USB_SBUSCFG_BARD_OFF 0x3
+#define USB_SBUSCFG_AHBBRST_OFF 0x0
+
+#define USB_SBUSCFG_BAWR_ALIGN_64B 0x4
+#define USB_SBUSCFG_BARD_ALIGN_64B 0x4
+#define USB_SBUSCFG_AHBBRST_INCR16 0x7
+
+/* AC5 special window mapping (taken from U-Boot) */
+#define USB_TO_DRAM_TARGET_ID 0x2
+#define USB_TO_DRAM_ATTR_ID 0x0
+#define USB_DRAM_BASE 0x00000000
+#define USB_DRAM_SIZE 0xfff /* do not exceed the source address space */
+
+/*
+ * Private state for this Marvell EHCI instance.
+ * The driver only needs the pointer to struct ehci_host.
+ */
+struct marvell_ehci {
+ struct ehci_host *ehci;
+ void __iomem *base;
+ struct device *dev;
+ u32 dram_bus_base;
+};
+
+static void marvell_ehci_sbuscfg_fixup(void __iomem *base)
+{
+ /*
+ * SBUSCFG: Control for the AMBA system bus interface:
+ * BAWR = BARD = 4 : Align rd/wr bursts packets larger than 64 bytes
+ * AHBBRST = 7 : Align AHB burst for packets larger than 64 bytes
+ */
+ writel((USB_SBUSCFG_BAWR_ALIGN_64B << USB_SBUSCFG_BAWR_OFF) |
+ (USB_SBUSCFG_BARD_ALIGN_64B << USB_SBUSCFG_BARD_OFF) |
+ (USB_SBUSCFG_AHBBRST_INCR16 << USB_SBUSCFG_AHBBRST_OFF),
+ base + USB2_SBUSCFG_OFF);
+}
+
+/*
+ * Program the USB → DRAM decoding windows using MBUS information.
+ * For AC5, replicate the special 0x0..USB_DRAM_SIZE mapping.
+ */
+static void marvell_usb_brg_adrdec_setup(struct marvell_ehci *priv)
+{
+ const struct mbus_dram_target_info *dram;
+ void __iomem *base = priv->base;
+ int i;
+
+ dev_info(priv->dev, "USB adrdec setup: ENTER\n");
+
+ dram = mvebu_mbus_dram_info();
+ if (!dram) {
+ dev_err(priv->dev, "no MBUS DRAM info\n");
+ return;
+ }
+
+ for (i = 0; i < 4; i++) {
+ writel(0, base + USB_WINDOW_CTRL(i));
+ writel(0, base + USB_WINDOW_BASE(i));
+ }
+
+ if (priv->dev->of_node &&
+ of_device_is_compatible(priv->dev->of_node, "marvell,ac5-ehci")) {
+ /* map DRAM as seen by USB at address 0x0 (as done in U-Boot) */
+ writel((USB_DRAM_SIZE << 16) |
+ (USB_TO_DRAM_ATTR_ID << 8) |
+ (USB_TO_DRAM_TARGET_ID << 4) | 1,
+ base + USB_WINDOW_CTRL(0));
+ writel(USB_DRAM_BASE, base + USB_WINDOW_BASE(0));
+
+ dev_dbg(priv->dev,
+ "AC5 decoding windows: ctrl=0x%08x base=0x%08x\n",
+ readl(base + USB_WINDOW_CTRL(0)),
+ readl(base + USB_WINDOW_BASE(0)));
+ } else {
+ /* generic mvebu case: one window per each DRAM chip-select */
+
+ for (i = 0; i < dram->num_cs; i++) {
+ const struct mbus_dram_window *cs = dram->cs + i;
+
+ /* Write size, attributes and target id to control register */
+ writel(((cs->size - 1) & 0xffff0000) |
+ (cs->mbus_attr << 8) |
+ (dram->mbus_dram_target_id << 4) | 1,
+ base + USB_WINDOW_CTRL(i));
+
+ /* Write base address to base register */
+ writel(cs->base, base + USB_WINDOW_BASE(i));
+ }
+ }
+
+ for (i = 0; i < 4; i++) {
+ u32 ctrl = readl(base + USB_WINDOW_CTRL(i));
+ u32 winb = readl(base + USB_WINDOW_BASE(i));
+ dev_info(priv->dev, "WIN%d: CTRL=0x%08x BASE=0x%08x\n", i, ctrl, winb);
+ }
+}
+
+/*
+ * Initialization hook called by ehci-hcd.c before starting the host.
+ * Only the bridge address decoding is performed here.
+ */
+static int marvell_ehci_init(void *drvdata)
+{
+ struct marvell_ehci *priv = drvdata;
+
+ marvell_usb_brg_adrdec_setup(priv);
+
+ writel((USB_SBUSCFG_BAWR_ALIGN_64B << USB_SBUSCFG_BAWR_OFF) |
+ (USB_SBUSCFG_BARD_ALIGN_64B << USB_SBUSCFG_BARD_OFF) |
+ (USB_SBUSCFG_AHBBRST_INCR16 << USB_SBUSCFG_AHBBRST_OFF),
+ priv->base + 0x100 + 0x90);
+ mdelay(50);
+
+ /*
+ * The SBUSCFG programming (BAWR/BARD/AHBBRST) in U-Boot is only
+ * required for SoCs without hlock (e.g. Armada3700).
+ * It is currently omitted; if needed in the future, a dedicated
+ * post_init or EHCI core hook can be added.
+ */
+
+ dev_dbg(priv->dev, "marvell_ehci_init done\n");
+
+ return 0;
+}
+
+static int marvell_ehci_probe(struct device *dev)
+{
+ struct marvell_ehci *priv;
+ struct resource *iores;
+ struct ehci_data data = {};
+ void __iomem *base;
+ struct ehci_host *ehci;
+
+ priv = xzalloc(sizeof(*priv));
+ priv->dev = dev;
+ dev->priv = priv;
+
+ iores = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(iores))
+ return PTR_ERR(iores);
+
+ base = IOMEM(iores->start);
+ priv->base = base;
+
+ /*
+ * On Marvell controllers the EHCI block starts at offset 0x100
+ * from the USB base address.
+ */
+ data.hccr = base + 0x100;
+
+ u32 capbase = readl(data.hccr); /* HC_CAPBASE */
+ u8 caplength = capbase & 0xff; /* CAPLENGTH */
+
+ data.hcor = (void __iomem *)((u8 *)data.hccr + caplength);
+
+ dev_info(dev, "EHCI probe: base=%p hccr=%p hcor=%p\n",
+ base, data.hccr, data.hcor);
+
+ dev_info(dev, "EHCI CAPBASE=0x%08x CAPLENGTH=0x%02x\n",
+ capbase, caplength);
+
+ data.init = marvell_ehci_init;
+ data.drvdata = priv;
+
+ if (of_device_is_compatible(dev->of_node, "marvell,armada-3700-ehci"))
+ marvell_ehci_sbuscfg_fixup(base);
+
+ dev_dbg(dev, "marvell_ehci_probe: done\n");
+
+ ehci = ehci_register(dev, &data);
+ if (IS_ERR(ehci))
+ return PTR_ERR(ehci);
+
+ priv->ehci = ehci;
+
+ return 0;
+}
+
+static void marvell_ehci_remove(struct device *dev)
+{
+ struct marvell_ehci *priv = dev->priv;
+
+ if (priv && priv->ehci)
+ ehci_unregister(priv->ehci);
+}
+
+static const struct of_device_id marvell_ehci_dt_ids[] = {
+ { .compatible = "marvell,orion-ehci" },
+ { .compatible = "marvell,armada-3700-ehci" },
+ { .compatible = "marvell,ac5-ehci" },
+ { /* sentinel */ }
+};
+
+static struct driver marvell_ehci_driver = {
+ .name = "marvell-ehci",
+ .probe = marvell_ehci_probe,
+ .remove = marvell_ehci_remove,
+ .of_compatible = DRV_OF_COMPAT(marvell_ehci_dt_ids),
+};
+device_platform_driver(marvell_ehci_driver);
--
2.47.3
next prev parent reply other threads:[~2026-07-28 17:48 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-28 17:43 [PATCH v2 00/10] ARM: mvebu: add Netgear RN102/RN104 support and related drivers Luca Lauro via B4 Relay
2026-07-28 17:43 ` [PATCH v2 01/10] ARM: mvebu: add Netgear RN102 support Luca Lauro via B4 Relay
2026-07-28 17:43 ` [PATCH v2 02/10] ARM: mvebu: enable RN102 in mvebu_defconfig Luca Lauro via B4 Relay
2026-07-28 17:43 ` [PATCH v2 03/10] ARM: mvebu: add Netgear RN104 support Luca Lauro via B4 Relay
2026-07-28 17:43 ` [PATCH v2 04/10] ARM: mvebu: rename PUTC_LL to MVEBU_PUTC_LL Luca Lauro via B4 Relay
2026-07-28 17:43 ` [PATCH v2 05/10] drivers: fan: add fan framework and API Luca Lauro via B4 Relay
2026-07-28 17:43 ` [PATCH v2 06/10] commands: add fan control command Luca Lauro via B4 Relay
2026-07-28 17:43 ` [PATCH v2 07/10] commands: integrate fan command into Kconfig and Makefile Luca Lauro via B4 Relay
2026-07-28 17:43 ` Luca Lauro via B4 Relay [this message]
2026-07-28 17:43 ` [PATCH v2 09/10] usb: ehci: minor fixes for Marvell compatibility Luca Lauro via B4 Relay
2026-07-28 17:43 ` [PATCH v2 10/10] ata: ahci: add PCI AHCI support and Marvell-specific fixes Luca Lauro via B4 Relay
2026-07-29 14:48 ` Lucas Stach
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=20260728-rn102-rn104-series-v2-8-ae31f55b7bc8@gmail.com \
--to=devnull+famlauro93l.gmail.com@kernel.org \
--cc=barebox@lists.infradead.org \
--cc=famlauro93l@gmail.com \
--cc=s.hauer@pengutronix.de \
/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