drivers: usb: Add generic XHCI

Add support for the generic XHCI driver that contains no SoC
specific code. It can be used on platforms that simply work out
of the box, like on emulated platforms.

TEST: Booted on QEMU sbsa machine using the generic xhci driver.

Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Reviewed-by: Marek Vasut <marex@denx.de>
Cc: Tom Rini <trini@konsulko.com>
Cc: Marek Vasut <marex@denx.de>
This commit is contained in:
Patrick Rudolph
2024-10-23 15:19:59 +02:00
committed by Tom Rini
parent 4ac655cd1a
commit b6fbcb0a56
3 changed files with 84 additions and 0 deletions

View File

@@ -68,6 +68,14 @@ config USB_XHCI_MVEBU
SoCs, which includes Armada8K, Armada3700 and other Armada
family SoCs.
config USB_XHCI_GENERIC
bool "Generic SoC USB 3.0 support"
depends on OF_CONTROL
default n
help
Choose this option to add support for USB 3.0 driver for SoCs
that do not need platform specific code, like on emulated targets.
config USB_XHCI_OCTEON
bool "Support for Marvell Octeon family on-chip xHCI USB controller"
depends on ARCH_OCTEON

View File

@@ -50,6 +50,7 @@ obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos5.o
obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o
obj-$(CONFIG_USB_XHCI_MTK) += xhci-mtk.o
obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o
obj-$(CONFIG_USB_XHCI_GENERIC) += xhci-generic.o
obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o
obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o
obj-$(CONFIG_USB_XHCI_RCAR) += xhci-rcar.o

View File

@@ -0,0 +1,75 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2024 9elements GmbH
*
* GENERIC USB HOST xHCI Controller
*/
#include <dm.h>
#include <fdtdec.h>
#include <log.h>
#include <usb.h>
#include <asm/io.h>
#include <dm/device_compat.h>
#include <usb/xhci.h>
struct generic_xhci_plat {
fdt_addr_t hcd_base;
};
/**
* Contains pointers to register base addresses
* for the usb controller.
*/
struct generic_xhci {
struct xhci_ctrl ctrl; /* Needs to come first in this struct! */
struct usb_plat usb_plat;
struct xhci_hccr *hcd;
};
static int xhci_usb_probe(struct udevice *dev)
{
struct generic_xhci_plat *plat = dev_get_plat(dev);
struct generic_xhci *ctx = dev_get_priv(dev);
struct xhci_hcor *hcor;
int len;
ctx->hcd = (struct xhci_hccr *)phys_to_virt(plat->hcd_base);
len = HC_LENGTH(xhci_readl(&ctx->hcd->cr_capbase));
hcor = (struct xhci_hcor *)((uintptr_t)ctx->hcd + len);
return xhci_register(dev, ctx->hcd, hcor);
}
static int xhci_usb_of_to_plat(struct udevice *dev)
{
struct generic_xhci_plat *plat = dev_get_plat(dev);
/*
* Get the base address for XHCI controller from the device node
*/
plat->hcd_base = dev_read_addr(dev);
if (plat->hcd_base == FDT_ADDR_T_NONE) {
dev_dbg(dev, "Can't get the XHCI register base address\n");
return -ENXIO;
}
return 0;
}
static const struct udevice_id xhci_usb_ids[] = {
{ .compatible = "generic-xhci" },
{ }
};
U_BOOT_DRIVER(usb_xhci) = {
.name = "xhci_generic",
.id = UCLASS_USB,
.of_match = xhci_usb_ids,
.of_to_plat = xhci_usb_of_to_plat,
.probe = xhci_usb_probe,
.remove = xhci_deregister,
.ops = &xhci_usb_ops,
.plat_auto = sizeof(struct generic_xhci_plat),
.priv_auto = sizeof(struct generic_xhci),
.flags = DM_FLAG_ALLOC_PRIV_DMA,
};