iPXE
dwusb.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2025 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <stdlib.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <ipxe/timer.h>
30 #include <ipxe/devtree.h>
31 #include <ipxe/fdt.h>
32 #include "dwusb.h"
33 
34 /** @file
35  *
36  * Synopsys DesignWare USB3 host controller driver
37  *
38  */
39 
40 /**
41  * Probe devicetree device
42  *
43  * @v dt Devicetree device
44  * @v offset Starting node offset
45  * @ret rc Return status code
46  */
47 static int dwusb_probe ( struct dt_device *dt, unsigned int offset ) {
48  struct xhci_device *xhci;
49  uint32_t gctl;
50  int rc;
51 
52  /* Allocate and initialise structure */
53  xhci = zalloc ( sizeof ( *xhci ) );
54  if ( ! xhci ) {
55  rc = -ENOMEM;
56  goto err_alloc;
57  }
58  xhci->dev = &dt->dev;
59  xhci->dma = &dt->dma;
60 
61  /* Map registers */
62  xhci->regs = dt_ioremap ( dt, offset, 0, 0 );
63  if ( ! xhci->regs ) {
64  rc = -ENODEV;
65  goto err_ioremap;
66  }
67 
68  /* Reset via global core control register */
69  gctl = readl ( xhci->regs + DWUSB_GCTL );
70  writel ( ( gctl | DWUSB_GCTL_RESET ), ( xhci->regs + DWUSB_GCTL ) );
71  mdelay ( 100 );
72  writel ( gctl, ( xhci->regs + DWUSB_GCTL ) );
73 
74  /* Configure as a host controller */
75  gctl &= ~DWUSB_GCTL_PRTDIR_MASK;
76  gctl |= DWUSB_GCTL_PRTDIR_HOST;
77  writel ( gctl, ( xhci->regs + DWUSB_GCTL ) );
78 
79  /* Initialise xHCI device */
80  xhci_init ( xhci );
81 
82  /* Register xHCI device */
83  if ( ( rc = xhci_register ( xhci ) ) != 0 ) {
84  DBGC ( xhci, "XHCI %s could not register: %s\n",
85  xhci->name, strerror ( rc ) );
86  goto err_register;
87  }
88 
89  dt_set_drvdata ( dt, xhci );
90  return 0;
91 
92  xhci_unregister ( xhci );
93  err_register:
94  iounmap ( xhci->regs );
95  err_ioremap:
96  free ( xhci );
97  err_alloc:
98  return rc;
99 }
100 
101 /**
102  * Remove devicetree device
103  *
104  * @v dt Devicetree device
105  */
106 static void dwusb_remove ( struct dt_device *dt ) {
107  struct xhci_device *xhci = dt_get_drvdata ( dt );
108 
109  /* Unregister xHCI device */
110  xhci_unregister ( xhci );
111 
112  /* Unmap registers */
113  iounmap ( xhci->regs );
114 
115  /* Free device */
116  free ( xhci );
117 }
118 
119 /** DesignWare USB3 compatible model identifiers */
120 static const char * dwusb_ids[] = {
121  "snps,dwc3",
122 };
123 
124 /** DesignWare USB3 devicetree driver */
125 struct dt_driver dwusb_driver __dt_driver = {
126  .name = "dwusb",
127  .ids = dwusb_ids,
128  .id_count = ( sizeof ( dwusb_ids ) / sizeof ( dwusb_ids[0] ) ),
129  .probe = dwusb_probe,
130  .remove = dwusb_remove,
131 };
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
int xhci_register(struct xhci_device *xhci)
Register xHCI controller.
Definition: xhci.c:3318
struct dt_driver dwusb_driver __dt_driver
DesignWare USB3 devicetree driver.
Definition: dwusb.c:125
An xHCI device.
Definition: xhci.h:1066
Error codes.
#define DWUSB_GCTL
Global core control register.
Definition: dwusb.h:15
#define DWUSB_GCTL_PRTDIR_MASK
Port direction mask.
Definition: dwusb.h:19
void * regs
Registers.
Definition: xhci.h:1068
A devicetree driver.
Definition: devtree.h:31
uint32_t readl(volatile uint32_t *io_addr)
Read 32-bit dword from memory-mapped device.
struct device * dev
Underlying hardware device.
Definition: xhci.h:1070
#define DBGC(...)
Definition: compiler.h:505
iPXE timers
static const char * dwusb_ids[]
DesignWare USB3 compatible model identifiers.
Definition: dwusb.c:120
struct device dev
Generic device.
Definition: devtree.h:21
int(* probe)(struct dt_device *dt, unsigned int offset)
Probe device.
Definition: devtree.h:45
#define ENOMEM
Not enough space.
Definition: errno.h:534
Synopsys DesignWare USB3 host controller driver.
void xhci_init(struct xhci_device *xhci)
Initialise device.
Definition: xhci.c:263
Devicetree bus.
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
void writel(uint32_t data, volatile uint32_t *io_addr)
Write 32-bit dword to memory-mapped device.
A devicetree device.
Definition: devtree.h:17
#define DWUSB_GCTL_RESET
Core soft reset.
Definition: dwusb.h:21
static int dwusb_probe(struct dt_device *dt, unsigned int offset)
Probe devicetree device.
Definition: dwusb.c:47
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
static void dt_set_drvdata(struct dt_device *dt, void *priv)
Set devicetree driver-private data.
Definition: devtree.h:66
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:661
const char * name
Name.
Definition: xhci.h:1074
static void dwusb_remove(struct dt_device *dt)
Remove devicetree device.
Definition: dwusb.c:106
#define ENODEV
No such device.
Definition: errno.h:509
unsigned int uint32_t
Definition: stdint.h:12
#define DWUSB_GCTL_PRTDIR_HOST
Operate as a host.
Definition: dwusb.h:17
static struct xen_remove_from_physmap * remove
Definition: xenmem.h:39
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
Definition: timer.c:78
const char * name
Driver name.
Definition: devtree.h:33
Flattened Device Tree.
void * dt_ioremap(struct dt_device *dt, unsigned int offset, unsigned int index, size_t len)
Map devicetree range.
Definition: devtree.c:52
void iounmap(volatile const void *io_addr)
Unmap I/O address.
struct dma_device * dma
DMA device.
Definition: xhci.h:1072
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
struct dma_device dma
DMA device.
Definition: devtree.h:23
String functions.
void xhci_unregister(struct xhci_device *xhci)
Unregister xHCI controller.
Definition: xhci.c:3363
static void * dt_get_drvdata(struct dt_device *dt)
Get devicetree driver-private data.
Definition: devtree.h:76