From: Michael Brown Date: Mon, 21 Jul 2025 12:44:38 +0000 (+0100) Subject: [dwusb] Add driver for DesignWare USB3 host controller X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e01e5ff7c6863a7825d58fb414181a0209dce6f9;p=thirdparty%2Fipxe.git [dwusb] Add driver for DesignWare USB3 host controller Add a basic driver for the DesignWare USB3 host controller as found in the Lichee Pi 4A. This driver covers only the DesignWare host controller hardware. On the Lichee Pi 4A, this is sufficient to get the single USB root hub port (exposed internally via the SODIMM connector) up and running. The driver does not yet handle the various GPIOs that control power and signal routing for the Lichee Pi 4A's onboard VL817 USB hub and the four physical USB-A ports. This therefore leaves the USB hub and the USB-A ports unpowered, and the USB2 root hub port routed to the physical USB-C port. Devices plugged in to the USB-A ports will not be powered up, and a device plugged in to the USB-C port will enumerate as a USB2 device. Signed-off-by: Michael Brown --- diff --git a/src/drivers/usb/dwusb.c b/src/drivers/usb/dwusb.c new file mode 100644 index 000000000..1bae2ce74 --- /dev/null +++ b/src/drivers/usb/dwusb.c @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2025 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include +#include +#include +#include +#include +#include +#include "dwusb.h" + +/** @file + * + * Synopsys DesignWare USB3 host controller driver + * + */ + +/** + * Probe devicetree device + * + * @v dt Devicetree device + * @v offset Starting node offset + * @ret rc Return status code + */ +static int dwusb_probe ( struct dt_device *dt, unsigned int offset ) { + struct xhci_device *xhci; + uint32_t gctl; + int rc; + + /* Allocate and initialise structure */ + xhci = zalloc ( sizeof ( *xhci ) ); + if ( ! xhci ) { + rc = -ENOMEM; + goto err_alloc; + } + xhci->dev = &dt->dev; + xhci->dma = &dt->dma; + + /* Map registers */ + xhci->regs = dt_ioremap ( dt, offset, 0, 0 ); + if ( ! xhci->regs ) { + rc = -ENODEV; + goto err_ioremap; + } + + /* Reset via global core control register */ + gctl = readl ( xhci->regs + DWUSB_GCTL ); + writel ( ( gctl | DWUSB_GCTL_RESET ), ( xhci->regs + DWUSB_GCTL ) ); + mdelay ( 100 ); + writel ( gctl, ( xhci->regs + DWUSB_GCTL ) ); + + /* Configure as a host controller */ + gctl &= ~DWUSB_GCTL_PRTDIR_MASK; + gctl |= DWUSB_GCTL_PRTDIR_HOST; + writel ( gctl, ( xhci->regs + DWUSB_GCTL ) ); + + /* Initialise xHCI device */ + xhci_init ( xhci ); + + /* Register xHCI device */ + if ( ( rc = xhci_register ( xhci ) ) != 0 ) { + DBGC ( xhci, "XHCI %s could not register: %s\n", + xhci->name, strerror ( rc ) ); + goto err_register; + } + + dt_set_drvdata ( dt, xhci ); + return 0; + + xhci_unregister ( xhci ); + err_register: + iounmap ( xhci->regs ); + err_ioremap: + free ( xhci ); + err_alloc: + return rc; +} + +/** + * Remove devicetree device + * + * @v dt Devicetree device + */ +static void dwusb_remove ( struct dt_device *dt ) { + struct xhci_device *xhci = dt_get_drvdata ( dt ); + + /* Unregister xHCI device */ + xhci_unregister ( xhci ); + + /* Unmap registers */ + iounmap ( xhci->regs ); + + /* Free device */ + free ( xhci ); +} + +/** DesignWare USB3 compatible model identifiers */ +static const char * dwusb_ids[] = { + "snps,dwc3", +}; + +/** DesignWare USB3 devicetree driver */ +struct dt_driver dwusb_driver __dt_driver = { + .name = "dwusb", + .ids = dwusb_ids, + .id_count = ( sizeof ( dwusb_ids ) / sizeof ( dwusb_ids[0] ) ), + .probe = dwusb_probe, + .remove = dwusb_remove, +}; diff --git a/src/drivers/usb/dwusb.h b/src/drivers/usb/dwusb.h new file mode 100644 index 000000000..523f7ba81 --- /dev/null +++ b/src/drivers/usb/dwusb.h @@ -0,0 +1,23 @@ +#ifndef _DWUSB_H +#define _DWUSB_H + +/** @file + * + * Synopsys DesignWare USB3 host controller driver + * + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include + +/** Global core control register */ +#define DWUSB_GCTL 0xc110 +#define DWUSB_GCTL_PRTDIR( x ) ( (x) << 12 ) /**< Port direction */ +#define DWUSB_GCTL_PRTDIR_HOST \ + DWUSB_GCTL_PRTDIR ( 1 ) /**< Operate as a host */ +#define DWUSB_GCTL_PRTDIR_MASK \ + DWUSB_GCTL_PRTDIR ( 3 ) /**< Port direction mask */ +#define DWUSB_GCTL_RESET 0x00000800 /**< Core soft reset */ + +#endif /* _DWUSB_H */ diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h index 0e3634f9e..7db8d5679 100644 --- a/src/include/ipxe/errfile.h +++ b/src/include/ipxe/errfile.h @@ -237,6 +237,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #define ERRFILE_devtree ( ERRFILE_DRIVER | 0x00da0000 ) #define ERRFILE_cgem ( ERRFILE_DRIVER | 0x00db0000 ) #define ERRFILE_dwmac ( ERRFILE_DRIVER | 0x00dc0000 ) +#define ERRFILE_dwusb ( ERRFILE_DRIVER | 0x00dd0000 ) #define ERRFILE_aoe ( ERRFILE_NET | 0x00000000 ) #define ERRFILE_arp ( ERRFILE_NET | 0x00010000 )