summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2020-01-15 07:58:30 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2020-01-15 07:58:30 +0100
commit56c313fe1751756ba978824798f61b4abe6ac49c (patch)
tree9e98f6bee10468f8b58667e41d2f3dc3e842477a
parent38188906dce22189462cea0b23e67fd122e22dea (diff)
parent184050d9972b37557cdff40805ee04582c8e54e6 (diff)
downloadbarebox-56c313fe1751756ba978824798f61b4abe6ac49c.tar.gz
barebox-56c313fe1751756ba978824798f61b4abe6ac49c.tar.xz
Merge branch 'for-next/rpi'
-rw-r--r--arch/arm/boards/raspberry-pi/lowlevel.c9
-rw-r--r--arch/arm/boards/raspberry-pi/rpi-common.c21
-rw-r--r--arch/arm/configs/rpi_defconfig26
-rw-r--r--arch/arm/cpu/mmu-common.c33
-rw-r--r--arch/arm/cpu/mmu.c4
-rw-r--r--arch/arm/cpu/mmu_64.c4
-rw-r--r--arch/arm/mach-bcm283x/include/mach/mbox.h4
-rw-r--r--arch/arm/mach-bcm283x/mbox.c47
-rw-r--r--drivers/gpio/Kconfig7
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-raspberrypi-exp.c272
-rw-r--r--drivers/of/address.c109
-rw-r--r--drivers/of/base.c46
-rw-r--r--drivers/of/platform.c18
-rw-r--r--drivers/regulator/core.c30
-rw-r--r--drivers/usb/core/usb.c18
-rw-r--r--drivers/usb/host/Kconfig3
-rw-r--r--drivers/usb/host/Makefile1
-rw-r--r--drivers/usb/host/dwc2.c1132
-rw-r--r--drivers/usb/host/dwc2.h778
-rw-r--r--include/driver.h2
-rw-r--r--include/of.h12
-rw-r--r--include/of_address.h9
-rw-r--r--include/regulator.h1
-rw-r--r--include/usb/usb.h8
-rw-r--r--include/usb/usbroothubdes.h128
26 files changed, 2658 insertions, 65 deletions
diff --git a/arch/arm/boards/raspberry-pi/lowlevel.c b/arch/arm/boards/raspberry-pi/lowlevel.c
index 70f1936522..d58beb6052 100644
--- a/arch/arm/boards/raspberry-pi/lowlevel.c
+++ b/arch/arm/boards/raspberry-pi/lowlevel.c
@@ -11,8 +11,15 @@ static void copy_vc_fdt(void *dest, void *src, unsigned long max_size)
{
struct fdt_header *oftree_src = src;
struct fdt_header *oftree_dest = dest;
+ unsigned long size;
- unsigned long size = be32_to_cpu(oftree_src->totalsize);
+ if (!src) {
+ oftree_dest->magic = cpu_to_be32(VIDEOCORE_FDT_ERROR);
+ oftree_dest->totalsize = cpu_to_be32(0);
+ return;
+ }
+
+ size = be32_to_cpu(oftree_src->totalsize);
if (size > max_size) {
oftree_dest->magic = cpu_to_be32(VIDEOCORE_FDT_ERROR);
/* Save an error code after the magic value for easier
diff --git a/arch/arm/boards/raspberry-pi/rpi-common.c b/arch/arm/boards/raspberry-pi/rpi-common.c
index dd6bbd5bdd..45961b52ee 100644
--- a/arch/arm/boards/raspberry-pi/rpi-common.c
+++ b/arch/arm/boards/raspberry-pi/rpi-common.c
@@ -21,6 +21,7 @@
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <envfs.h>
+#include <regulator.h>
#include <malloc.h>
#include <libfile.h>
#include <gpio.h>
@@ -433,13 +434,16 @@ static void rpi_vc_fdt(void)
oftree = saved_vc_fdt;
magic = be32_to_cpu(oftree->magic);
- if (magic != FDT_MAGIC) {
- pr_err("videocore fdt saved in pbl has invalid magic\n");
- if (magic == VIDEOCORE_FDT_ERROR) {
+ if (magic == VIDEOCORE_FDT_ERROR) {
+ if (oftree->totalsize)
pr_err("there was an error copying fdt in pbl: %d\n",
be32_to_cpu(oftree->totalsize));
- }
+ return;
+ }
+
+ if (magic != FDT_MAGIC) {
+ pr_err("videocore fdt saved in pbl has invalid magic\n");
return;
}
@@ -459,11 +463,20 @@ static void rpi_vc_fdt(void)
static int rpi_devices_init(void)
{
+ struct regulator *reg;
+
rpi_model_init();
bcm2835_register_fb();
armlinux_set_architecture(MACH_TYPE_BCM2708);
rpi_env_init();
rpi_vc_fdt();
+
+ reg = regulator_get_name("bcm2835_usb");
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+
+ regulator_enable(reg);
+
return 0;
}
late_initcall(rpi_devices_init);
diff --git a/arch/arm/configs/rpi_defconfig b/arch/arm/configs/rpi_defconfig
index 0ae0c42b12..dd5ca7585a 100644
--- a/arch/arm/configs/rpi_defconfig
+++ b/arch/arm/configs/rpi_defconfig
@@ -2,6 +2,7 @@ CONFIG_ARCH_BCM283X=y
CONFIG_MACH_RPI=y
CONFIG_MACH_RPI2=y
CONFIG_MACH_RPI3=y
+CONFIG_MACH_RPI_CM3=y
CONFIG_AEABI=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
CONFIG_ARM_UNWIND=y
@@ -20,11 +21,15 @@ CONFIG_BOOTM_VERBOSE=y
CONFIG_BOOTM_INITRD=y
CONFIG_BOOTM_OFTREE=y
CONFIG_BLSPEC=y
+CONFIG_CONSOLE_ALLOW_COLOR=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/raspberry-pi/env"
+CONFIG_CMD_DMESG=y
CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
+CONFIG_CMD_IMD=y
CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_REGULATOR=y
CONFIG_CMD_GO=y
CONFIG_CMD_LOADB=y
CONFIG_CMD_LOADY=y
@@ -32,17 +37,25 @@ CONFIG_CMD_RESET=y
CONFIG_CMD_UIMAGE=y
CONFIG_CMD_PARTITION=y
CONFIG_CMD_EXPORT=y
+CONFIG_CMD_DEFAULTENV=y
+CONFIG_CMD_LOADENV=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_MAGICVAR=y
CONFIG_CMD_MAGICVAR_HELP=y
CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_CMP=y
CONFIG_CMD_FILETYPE=y
CONFIG_CMD_LN=y
CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_SHA1SUM=y
+CONFIG_CMD_SHA256SUM=y
CONFIG_CMD_UNCOMPRESS=y
CONFIG_CMD_LET=y
CONFIG_CMD_MSLEEP=y
CONFIG_CMD_SLEEP=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MIITOOL=y
+CONFIG_CMD_PING=y
CONFIG_CMD_ECHO_E=y
CONFIG_CMD_EDIT=y
CONFIG_CMD_LOGIN=y
@@ -57,26 +70,35 @@ CONFIG_CMD_MM=y
CONFIG_CMD_CLK=y
CONFIG_CMD_DETECT=y
CONFIG_CMD_GPIO=y
+CONFIG_CMD_LED=y
+CONFIG_CMD_LED_TRIGGER=y
CONFIG_CMD_WD=y
CONFIG_CMD_OF_NODE=y
CONFIG_CMD_OF_PROPERTY=y
CONFIG_CMD_OFTREE=y
CONFIG_CMD_TIME=y
+CONFIG_NET=y
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_DRIVER_SERIAL_NS16550=y
+CONFIG_NET_USB=y
+CONFIG_NET_USB_SMSC95XX=y
+CONFIG_USB_HOST=y
+CONFIG_USB_DWC2_HOST=y
CONFIG_MCI=y
CONFIG_MCI_BCM283X=y
CONFIG_MCI_BCM283X_SDHOST=y
CONFIG_LED=y
CONFIG_LED_GPIO=y
+CONFIG_LED_GPIO_OF=y
CONFIG_LED_TRIGGERS=y
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_BCM2835=y
+CONFIG_GPIO_RASPBERRYPI_EXP=y
CONFIG_PINCTRL_BCM283X=y
CONFIG_REGULATOR=y
CONFIG_FS_EXT4=y
+CONFIG_FS_TFTP=y
+CONFIG_FS_NFS=y
CONFIG_FS_FAT=y
CONFIG_FS_FAT_WRITE=y
CONFIG_FS_FAT_LFN=y
-CONFIG_DIGEST_SHA1_GENERIC=y
-CONFIG_DIGEST_SHA256_GENERIC=y
diff --git a/arch/arm/cpu/mmu-common.c b/arch/arm/cpu/mmu-common.c
index aeefbb2daa..287622b203 100644
--- a/arch/arm/cpu/mmu-common.c
+++ b/arch/arm/cpu/mmu-common.c
@@ -11,9 +11,32 @@
#include "mmu.h"
+static inline dma_addr_t cpu_to_dma(struct device_d *dev, unsigned long cpu_addr)
+{
+ dma_addr_t dma_addr = cpu_addr;
+
+ if (dev)
+ dma_addr -= dev->dma_offset;
+
+ return dma_addr;
+}
+
+static inline unsigned long dma_to_cpu(struct device_d *dev, dma_addr_t addr)
+{
+ unsigned long cpu_addr = addr;
+
+ if (dev)
+ cpu_addr += dev->dma_offset;
+
+ return cpu_addr;
+}
+
void dma_sync_single_for_cpu(dma_addr_t address, size_t size,
enum dma_data_direction dir)
{
+ /*
+ * FIXME: This function needs a device argument to support non 1:1 mappings
+ */
if (dir != DMA_TO_DEVICE)
dma_inv_range((void *)address, size);
}
@@ -25,12 +48,14 @@ dma_addr_t dma_map_single(struct device_d *dev, void *ptr, size_t size,
dma_sync_single_for_device(addr, size, dir);
- return addr;
+ return cpu_to_dma(dev, addr);
}
-void dma_unmap_single(struct device_d *dev, dma_addr_t addr, size_t size,
+void dma_unmap_single(struct device_d *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir)
{
+ unsigned long addr = dma_to_cpu(dev, dma_addr);
+
dma_sync_single_for_cpu(addr, size, dir);
}
@@ -53,6 +78,10 @@ void *dma_alloc_map(size_t size, dma_addr_t *dma_handle, unsigned flags)
void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
{
+ /*
+ * FIXME: This function needs a device argument to support non 1:1 mappings
+ */
+
return dma_alloc_map(size, dma_handle, MAP_UNCACHED);
}
diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c
index 158b130b57..1f97c28ec6 100644
--- a/arch/arm/cpu/mmu.c
+++ b/arch/arm/cpu/mmu.c
@@ -491,6 +491,10 @@ void *dma_alloc_writecombine(size_t size, dma_addr_t *dma_handle)
void dma_sync_single_for_device(dma_addr_t address, size_t size,
enum dma_data_direction dir)
{
+ /*
+ * FIXME: This function needs a device argument to support non 1:1 mappings
+ */
+
if (dir == DMA_FROM_DEVICE) {
__dma_inv_range(address, address + size);
if (outer_cache.inv_range)
diff --git a/arch/arm/cpu/mmu_64.c b/arch/arm/cpu/mmu_64.c
index f7a13014af..98cd4c754e 100644
--- a/arch/arm/cpu/mmu_64.c
+++ b/arch/arm/cpu/mmu_64.c
@@ -245,6 +245,10 @@ void dma_flush_range(void *ptr, size_t size)
void dma_sync_single_for_device(dma_addr_t address, size_t size,
enum dma_data_direction dir)
{
+ /*
+ * FIXME: This function needs a device argument to support non 1:1 mappings
+ */
+
if (dir == DMA_FROM_DEVICE)
v8_inv_dcache_range(address, address + size - 1);
else
diff --git a/arch/arm/mach-bcm283x/include/mach/mbox.h b/arch/arm/mach-bcm283x/include/mach/mbox.h
index 6db961b807..f10f5bc148 100644
--- a/arch/arm/mach-bcm283x/include/mach/mbox.h
+++ b/arch/arm/mach-bcm283x/include/mach/mbox.h
@@ -126,6 +126,10 @@ struct bcm2835_mbox_tag_hdr {
*/
#define BCM2835_MBOX_TAG_GET_BOARD_REV 0x00010002
+#define BCM2835_MBOX_TAG_GET_GPIO_STATE 0x00030041
+#define BCM2835_MBOX_TAG_SET_GPIO_STATE 0x00038041
+#define BCM2835_MBOX_TAG_GET_GPIO_CONFIG 0x00030043
+#define BCM2835_MBOX_TAG_SET_GPIO_CONFIG 0x00038043
/*
* ids
diff --git a/arch/arm/mach-bcm283x/mbox.c b/arch/arm/mach-bcm283x/mbox.c
index b295993359..22abbb0ca5 100644
--- a/arch/arm/mach-bcm283x/mbox.c
+++ b/arch/arm/mach-bcm283x/mbox.c
@@ -6,6 +6,8 @@
* SPDX-License-Identifier: GPL-2.0+
*/
+#define pr_fmt(fmt) "rpi-mbox: " fmt
+
#include <clock.h>
#include <common.h>
#include <dma.h>
@@ -26,7 +28,7 @@ static int bcm2835_mbox_call_raw(u32 chan, struct bcm2835_mbox_hdr *buffer,
u32 val;
if (send & BCM2835_CHAN_MASK) {
- printf("mbox: Illegal mbox data 0x%08x\n", send);
+ pr_err("mbox: Illegal mbox data 0x%08x\n", send);
return -EINVAL;
}
@@ -35,8 +37,8 @@ static int bcm2835_mbox_call_raw(u32 chan, struct bcm2835_mbox_hdr *buffer,
val = readl(mbox_base + MAIL0_STA);
if (val & BCM2835_MBOX_STATUS_RD_EMPTY)
break;
- if (is_timeout(starttime, TIMEOUT)) {
- printf("mbox: Timeout draining stale responses\n");
+ if (is_timeout_non_interruptible(starttime, TIMEOUT)) {
+ pr_err("mbox: Timeout draining stale responses\n");
return -ETIMEDOUT;
}
val = readl(mbox_base + MAIL0_RD);
@@ -47,15 +49,15 @@ static int bcm2835_mbox_call_raw(u32 chan, struct bcm2835_mbox_hdr *buffer,
val = readl(mbox_base + MAIL0_STA);
if (!(val & BCM2835_MBOX_STATUS_WR_FULL))
break;
- if (is_timeout(starttime, TIMEOUT)) {
- printf("mbox: Timeout waiting for send space\n");
+ if (is_timeout_non_interruptible(starttime, TIMEOUT)) {
+ pr_err("mbox: Timeout waiting for send space\n");
return -ETIMEDOUT;
}
}
/* Send the request */
val = BCM2835_MBOX_PACK(chan, send);
- debug("mbox: TX raw: 0x%08x\n", val);
+ pr_debug("mbox: TX raw: 0x%08x\n", val);
dma_sync_single_for_device((unsigned long)send, buffer->buf_size,
DMA_BIDIRECTIONAL);
writel(val, mbox_base + MAIL1_WRT);
@@ -65,21 +67,21 @@ static int bcm2835_mbox_call_raw(u32 chan, struct bcm2835_mbox_hdr *buffer,
val = readl(mbox_base + MAIL0_STA);
if (!(val & BCM2835_MBOX_STATUS_RD_EMPTY))
break;
- if (is_timeout(starttime, TIMEOUT)) {
- printf("mbox: Timeout waiting for response\n");
+ if (is_timeout_non_interruptible(starttime, TIMEOUT)) {
+ pr_err("mbox: Timeout waiting for response\n");
return -ETIMEDOUT;
}
}
/* Read the response */
val = readl(mbox_base + MAIL0_RD);
- debug("mbox: RX raw: 0x%08x\n", val);
+ pr_debug("mbox: RX raw: 0x%08x\n", val);
dma_sync_single_for_cpu((unsigned long)send, buffer->buf_size,
DMA_BIDIRECTIONAL);
/* Validate the response */
if (BCM2835_MBOX_UNPACK_CHAN(val) != chan) {
- printf("mbox: Response channel mismatch\n");
+ pr_err("mbox: Response channel mismatch\n");
return -EIO;
}
@@ -89,7 +91,7 @@ static int bcm2835_mbox_call_raw(u32 chan, struct bcm2835_mbox_hdr *buffer,
}
#ifdef DEBUG
-void dump_buf(struct bcm2835_mbox_hdr *buffer)
+static void dump_buf(struct bcm2835_mbox_hdr *buffer)
{
u32 *p;
u32 words;
@@ -98,7 +100,11 @@ void dump_buf(struct bcm2835_mbox_hdr *buffer)
p = (u32 *)buffer;
words = buffer->buf_size / 4;
for (i = 0; i < words; i++)
- printf(" 0x%04x: 0x%08x\n", i * 4, p[i]);
+ pr_debug(" 0x%04x: 0x%08x\n", i * 4, p[i]);
+}
+#else
+static void dump_buf(struct bcm2835_mbox_hdr *buffer)
+{
}
#endif
@@ -109,27 +115,23 @@ int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_hdr *buffer)
struct bcm2835_mbox_tag_hdr *tag;
int tag_index;
-#ifdef DEBUG
- printf("mbox: TX buffer\n");
+ pr_debug("mbox: TX buffer\n");
dump_buf(buffer);
-#endif
ret = bcm2835_mbox_call_raw(chan, buffer, &rbuffer);
if (ret)
return ret;
if (rbuffer != (u32)buffer) {
- printf("mbox: Response buffer mismatch\n");
+ pr_err("mbox: Response buffer mismatch\n");
return -EIO;
}
-#ifdef DEBUG
- printf("mbox: RX buffer\n");
+ pr_debug("mbox: RX buffer\n");
dump_buf(buffer);
-#endif
/* Validate overall response status */
if (buffer->code != BCM2835_MBOX_RESP_CODE_SUCCESS) {
- printf("mbox: Header response code invalid\n");
+ pr_err("mbox: Header response code invalid\n");
return -EIO;
}
@@ -137,11 +139,6 @@ int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_hdr *buffer)
tag = (void *)(buffer + 1);
tag_index = 0;
while (tag->tag) {
- if (!(tag->val_len & BCM2835_MBOX_TAG_VAL_LEN_RESPONSE)) {
- printf("mbox: Tag %d missing val_len response bit\n",
- tag_index);
- return -EIO;
- }
/*
* Clear the reponse bit so clients can just look right at the
* length field without extra processing
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 0f924d135f..7e4fc90d39 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -129,6 +129,13 @@ config GPIO_PL061
help
Say yes here to support the PrimeCell PL061 GPIO device
+config GPIO_RASPBERRYPI_EXP
+ bool "Raspberry Pi 3 GPIO Expander"
+ depends on ARCH_BCM283X
+ help
+ Turn on GPIO support for the expander on Raspberry Pi 3 boards, using
+ the firmware mailbox to communicate with VideoCore on BCM283x chips.
+
config GPIO_STMPE
depends on MFD_STMPE
bool "STMPE GPIO Expander"
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index bc5c500e4d..77dcf58f64 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_GPIO_TEGRA) += gpio-tegra.o
obj-$(CONFIG_GPIO_DESIGNWARE) += gpio-dw.o
obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o
obj-$(CONFIG_GPIO_VF610) += gpio-vf610.o
+obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o
diff --git a/drivers/gpio/gpio-raspberrypi-exp.c b/drivers/gpio/gpio-raspberrypi-exp.c
new file mode 100644
index 0000000000..0713e3ca5f
--- /dev/null
+++ b/drivers/gpio/gpio-raspberrypi-exp.c
@@ -0,0 +1,272 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Raspberry Pi 3 expander GPIO driver
+ *
+ * Uses the firmware mailbox service to communicate with the
+ * GPIO expander on the VPU.
+ *
+ * Copyright (C) 2017 Raspberry Pi Trading Ltd.
+ */
+
+#include <common.h>
+#include <gpio.h>
+#include <init.h>
+#include <mach/mbox.h>
+
+#define NUM_GPIO 8
+
+#define RPI_EXP_GPIO_BASE 128
+
+#define RPI_EXP_GPIO_DIR_IN 0
+#define RPI_EXP_GPIO_DIR_OUT 1
+
+struct rpi_exp_gpio {
+ struct gpio_chip gc;
+ struct rpi_firmware *fw;
+};
+
+/* VC4 firmware mailbox interface data structures */
+struct gpio_set_config {
+ struct bcm2835_mbox_hdr hdr; /* buf_size, code */
+ struct bcm2835_mbox_tag_hdr tag_hdr; /* tag, val_buf_size, val_len */
+ union {
+ struct {
+ u32 gpio;
+ u32 direction;
+ u32 polarity;
+ u32 term_en;
+ u32 term_pull_up;
+ u32 state;
+ } req;
+ } body;
+ u32 end_tag;
+};
+
+struct gpio_get_config {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ u32 gpio;
+ u32 direction;
+ u32 polarity;
+ u32 term_en;
+ u32 term_pull_up;
+ } req;
+ } body;
+ u32 end_tag;
+};
+
+struct gpio_get_set_state {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ u32 gpio;
+ u32 state;
+ } req;
+ } body;
+ u32 end_tag;
+};
+
+static inline struct rpi_exp_gpio *to_rpi_gpio(struct gpio_chip *gc)
+{
+ return container_of(gc, struct rpi_exp_gpio, gc);
+}
+
+static int rpi_exp_gpio_get_polarity(struct gpio_chip *gc, unsigned int off)
+{
+ struct rpi_exp_gpio *gpio;
+ int ret;
+ BCM2835_MBOX_STACK_ALIGN(struct gpio_get_config, get);
+ BCM2835_MBOX_INIT_HDR(get);
+ BCM2835_MBOX_INIT_TAG(get, GET_GPIO_CONFIG);
+
+ gpio = to_rpi_gpio(gc);
+
+ get->body.req.gpio = off + RPI_EXP_GPIO_BASE; /* GPIO to update */
+
+ ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &get->hdr);
+ if (ret || get->body.req.gpio != 0) {
+ dev_err(gc->dev, "Failed to get GPIO %u config (%d %x)\n",
+ off, ret, get->body.req.gpio);
+ return ret ? ret : -EIO;
+ }
+ return get->body.req.polarity;
+}
+
+static int rpi_exp_gpio_dir_in(struct gpio_chip *gc, unsigned int off)
+{
+ struct rpi_exp_gpio *gpio;
+ int ret;
+ BCM2835_MBOX_STACK_ALIGN(struct gpio_set_config, set_in);
+ BCM2835_MBOX_INIT_HDR(set_in);
+ BCM2835_MBOX_INIT_TAG(set_in, SET_GPIO_CONFIG);
+
+ gpio = to_rpi_gpio(gc);
+
+ set_in->body.req.gpio = off + RPI_EXP_GPIO_BASE; /* GPIO to update */
+ set_in->body.req.direction = RPI_EXP_GPIO_DIR_IN;
+ set_in->body.req.term_en = 0; /* termination disabled */
+ set_in->body.req.term_pull_up = 0; /* n/a as termination disabled */
+ set_in->body.req.state = 0; /* n/a as configured as an input */
+
+ ret = rpi_exp_gpio_get_polarity(gc, off);
+ if (ret < 0)
+ return ret;
+
+ set_in->body.req.polarity = ret; /* Retain existing setting */
+
+ ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &set_in->hdr);
+ if (ret || set_in->body.req.gpio != 0) {
+ dev_err(gc->dev, "Failed to set GPIO %u to input (%d %x)\n",
+ off, ret, set_in->body.req.gpio);
+ return ret ? ret : -EIO;
+ }
+
+ return 0;
+}
+
+static int rpi_exp_gpio_dir_out(struct gpio_chip *gc, unsigned int off, int val)
+{
+ struct rpi_exp_gpio *gpio;
+ int ret;
+ BCM2835_MBOX_STACK_ALIGN(struct gpio_set_config, set_out);
+ BCM2835_MBOX_INIT_HDR(set_out);
+ BCM2835_MBOX_INIT_TAG(set_out, SET_GPIO_CONFIG);
+
+ gpio = to_rpi_gpio(gc);
+
+ set_out->body.req.gpio = off + RPI_EXP_GPIO_BASE; /* GPIO to update */
+ set_out->body.req.direction = RPI_EXP_GPIO_DIR_OUT;
+ set_out->body.req.term_en = 0; /* n/a as an output */
+ set_out->body.req.term_pull_up = 0; /* n/a as termination disabled */
+ set_out->body.req.state = val; /* Output state */
+
+ ret = rpi_exp_gpio_get_polarity(gc, off);
+ if (ret < 0)
+ return ret;
+ set_out->body.req.polarity = ret; /* Retain existing setting */
+
+ ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &set_out->hdr);
+ if (ret || set_out->body.req.gpio != 0) {
+ dev_err(gc->dev, "Failed to set GPIO %u to output (%d %x)\n",
+ off, ret, set_out->body.req.gpio);
+ return ret ? ret : -EIO;
+ }
+ return 0;
+}
+
+static int rpi_exp_gpio_get_direction(struct gpio_chip *gc, unsigned int off)
+{
+ struct rpi_exp_gpio *gpio;
+ int ret;
+ BCM2835_MBOX_STACK_ALIGN(struct gpio_get_config, get);
+ BCM2835_MBOX_INIT_HDR(get);
+ BCM2835_MBOX_INIT_TAG(get, GET_GPIO_CONFIG);
+
+ gpio = to_rpi_gpio(gc);
+
+ get->body.req.gpio = off + RPI_EXP_GPIO_BASE; /* GPIO to update */
+
+ ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &get->hdr);
+ if (ret || get->body.req.gpio != 0) {
+ dev_err(gc->dev,
+ "Failed to get GPIO %u config (%d %x)\n", off, ret,
+ get->body.req.gpio);
+ return ret ? ret : -EIO;
+ }
+ if (get->body.req.direction)
+ return GPIOF_DIR_OUT;
+
+ return GPIOF_DIR_IN;
+}
+
+static int rpi_exp_gpio_get(struct gpio_chip *gc, unsigned int off)
+{
+ struct rpi_exp_gpio *gpio;
+ int ret;
+ BCM2835_MBOX_STACK_ALIGN(struct gpio_get_set_state, get);
+ BCM2835_MBOX_INIT_HDR(get);
+ BCM2835_MBOX_INIT_TAG(get, GET_GPIO_STATE);
+
+ gpio = to_rpi_gpio(gc);
+
+ get->body.req.gpio = off + RPI_EXP_GPIO_BASE; /* GPIO to update */
+ get->body.req.state = 0; /* storage for returned value */
+
+ ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &get->hdr);
+ if (ret || get->body.req.gpio != 0) {
+ dev_err(gc->dev,
+ "Failed to get GPIO %u state (%d %x)\n", off, ret,
+ get->body.req.gpio);
+ return ret ? ret : -EIO;
+ }
+ return !!get->body.req.state;
+}
+
+static void rpi_exp_gpio_set(struct gpio_chip *gc, unsigned int off, int val)
+{
+ struct rpi_exp_gpio *gpio;
+ int ret;
+ BCM2835_MBOX_STACK_ALIGN(struct gpio_get_set_state, set);
+ BCM2835_MBOX_INIT_HDR(set);
+ BCM2835_MBOX_INIT_TAG(set, SET_GPIO_STATE);
+
+ gpio = to_rpi_gpio(gc);
+
+ set->body.req.gpio = off + RPI_EXP_GPIO_BASE; /* GPIO to update */
+ set->body.req.state = val; /* Output state */
+
+ ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &set->hdr);
+ if (ret || set->body.req.gpio != 0)
+ dev_err(gc->dev,
+ "Failed to set GPIO %u state (%d %x)\n", off, ret,
+ set->body.req.gpio);
+}
+
+static struct gpio_ops rpi_exp_gpio_ops = {
+ .direction_input = rpi_exp_gpio_dir_in,
+ .direction_output = rpi_exp_gpio_dir_out,
+ .get_direction = rpi_exp_gpio_get_direction,
+ .get = rpi_exp_gpio_get,
+ .set = rpi_exp_gpio_set,
+};
+
+static int rpi_exp_gpio_probe(struct device_d *dev)
+{
+ struct rpi_exp_gpio *rpi_gpio;
+ int ret;
+
+ rpi_gpio = xzalloc(sizeof(*rpi_gpio));
+
+ rpi_gpio->gc.dev = dev;
+ rpi_gpio->gc.base = -1;
+ rpi_gpio->gc.ngpio = NUM_GPIO;
+ rpi_gpio->gc.ops = &rpi_exp_gpio_ops;
+
+ ret = gpiochip_add(&rpi_gpio->gc);
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "probed gpiochip with %d gpios, base %d\n",
+ rpi_gpio->gc.ngpio, rpi_gpio->gc.base);
+
+ return 0;
+}
+
+static __maybe_unused struct of_device_id rpi_exp_gpio_ids[] = {
+ {
+ .compatible = "raspberrypi,firmware-gpio",
+ }, {
+ /* sentinel */
+ },
+};
+
+static struct driver_d rpi_exp_gpio_driver = {
+ .name = "rpi-exp-gpio",
+ .probe = rpi_exp_gpio_probe,
+ .of_compatible = DRV_OF_COMPAT(rpi_exp_gpio_ids),
+};
+
+device_platform_driver(rpi_exp_gpio_driver);
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 007c5fd9d0..f0a74ec37c 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -458,6 +458,33 @@ bool of_can_translate_address(struct device_node *dev)
}
EXPORT_SYMBOL(of_can_translate_address);
+static struct device_node *__of_get_dma_parent(struct device_node *np)
+{
+ struct of_phandle_args args;
+ int ret, index;
+
+ index = of_property_match_string(np, "interconnect-names", "dma-mem");
+ if (index < 0)
+ return of_get_parent(np);
+
+ ret = of_parse_phandle_with_args(np, "interconnects",
+ "#interconnect-cells",
+ index, &args);
+ if (ret < 0)
+ return of_get_parent(np);
+
+ return args.np;
+}
+
+static struct device_node *of_get_next_dma_parent(struct device_node *np)
+{
+ struct device_node *parent;
+
+ parent = __of_get_dma_parent(np);
+
+ return parent;
+}
+
const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
unsigned int *flags)
{
@@ -586,3 +613,85 @@ void __iomem *of_iomap(struct device_node *np, int index)
return IOMEM(res.start);
}
EXPORT_SYMBOL(of_iomap);
+
+/**
+ * of_dma_get_range - Get DMA range info
+ * @np: device node to get DMA range info
+ * @dma_addr: pointer to store initial DMA address of DMA range
+ * @paddr: pointer to store initial CPU address of DMA range
+ * @size: pointer to store size of DMA range
+ *
+ * Look in bottom up direction for the first "dma-ranges" property
+ * and parse it.
+ * dma-ranges format:
+ * DMA addr (dma_addr) : naddr cells
+ * CPU addr (phys_addr_t) : pna cells
+ * size : nsize cells
+ *
+ * It returns -ENODEV if "dma-ranges" property was not found
+ * for this device in DT.
+ */
+int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 *size)
+{
+ struct device_node *node = np;
+ const __be32 *ranges = NULL;
+ int len, naddr, nsize, pna;
+ int ret = 0;
+ bool found_dma_ranges = false;
+ u64 dmaaddr;
+
+ while (node) {
+ ranges = of_get_property(node, "dma-ranges", &len);
+
+ /* Ignore empty ranges, they imply no translation required */
+ if (ranges && len > 0)
+ break;
+
+ /* Once we find 'dma-ranges', then a missing one is an error */
+ if (found_dma_ranges && !ranges) {
+ ret = -ENODEV;
+ goto out;
+ }
+ found_dma_ranges = true;
+
+ node = of_get_next_dma_parent(node);
+ }
+
+ if (!node || !ranges) {
+ pr_debug("no dma-ranges found for node(%pOF)\n", np);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ naddr = of_bus_n_addr_cells(node);
+ nsize = of_bus_n_size_cells(node);
+ pna = of_n_addr_cells(node);
+ if ((len / sizeof(__be32)) % (pna + naddr + nsize)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* dma-ranges format:
+ * DMA addr : naddr cells
+ * CPU addr : pna cells
+ * size : nsize cells
+ */
+ dmaaddr = of_read_number(ranges, naddr);
+ *paddr = of_translate_dma_address(node, ranges + naddr);
+ if (*paddr == OF_BAD_ADDR) {
+ pr_err("translation of DMA address(%llx) to CPU address failed node(%pOF)\n",
+ dmaaddr, np);
+ ret = -EINVAL;
+ goto out;
+ }
+ *dma_addr = dmaaddr;
+
+ *size = of_read_number(ranges + naddr + pna, nsize);
+
+ pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n",
+ *dma_addr, *paddr, *size);
+
+out:
+
+ return ret;
+}
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 80ceeab13b..9ede052274 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -78,36 +78,46 @@ static struct device_node *of_aliases;
#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1
#define OF_ROOT_NODE_ADDR_CELLS_DEFAULT 1
-int of_n_addr_cells(struct device_node *np)
+int of_bus_n_addr_cells(struct device_node *np)
{
- const __be32 *ip;
+ u32 cells;
+
+ for (; np; np = np->parent)
+ if (!of_property_read_u32(np, "#address-cells", &cells))
+ return cells;
- do {
- if (np->parent)
- np = np->parent;
- ip = of_get_property(np, "#address-cells", NULL);
- if (ip)
- return be32_to_cpup(ip);
- } while (np->parent);
/* No #address-cells property for the root node */
return OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
}
+
+int of_n_addr_cells(struct device_node *np)
+{
+ if (np->parent)
+ np = np->parent;
+
+ return of_bus_n_addr_cells(np);
+}
EXPORT_SYMBOL(of_n_addr_cells);
-int of_n_size_cells(struct device_node *np)
+int of_bus_n_size_cells(struct device_node *np)
{
- const __be32 *ip;
+ u32 cells;
+
+ for (; np; np = np->parent)
+ if (!of_property_read_u32(np, "#size-cells", &cells))
+ return cells;
- do {
- if (np->parent)
- np = np->parent;
- ip = of_get_property(np, "#size-cells", NULL);
- if (ip)
- return be32_to_cpup(ip);
- } while (np->parent);
/* No #size-cells property for the root node */
return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
}
+
+int of_n_size_cells(struct device_node *np)
+{
+ if (np->parent)
+ np = np->parent;
+
+ return of_bus_n_size_cells(np);
+}
EXPORT_SYMBOL(of_n_size_cells);
struct property *of_find_property(const struct device_node *np,
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index d3795d799a..b1a7eb6730 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -74,6 +74,22 @@ static void of_device_make_bus_id(struct device_d *dev)
}
}
+static void of_dma_configure(struct device_d *dev, struct device_node *np)
+{
+ u64 dma_addr, paddr, size = 0;
+ unsigned long offset;
+ int ret;
+
+ ret = of_dma_get_range(np, &dma_addr, &paddr, &size);
+ if (ret < 0) {
+ dma_addr = offset = 0;
+ } else {
+ offset = paddr - dma_addr;
+ }
+
+ dev->dma_offset = offset;
+}
+
/**
* of_platform_device_create - Alloc, initialize and register an of_device
* @np: pointer to node to create device for
@@ -148,6 +164,8 @@ struct device_d *of_platform_device_create(struct device_node *np,
dev->num_resources = num_reg;
of_device_make_bus_id(dev);
+ of_dma_configure(dev, np);
+
resinval = (-1);
debug("%s: register device %s, io=%pa\n",
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 4ca035ae94..f0de7a52e3 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -327,6 +327,34 @@ struct regulator *regulator_get(struct device_d *dev, const char *supply)
return r;
}
+static struct regulator_internal *regulator_by_name(const char *name)
+{
+ struct regulator_internal *ri;
+
+ list_for_each_entry(ri, &regulator_list, list)
+ if (ri->name && !strcmp(ri->name, name))
+ return ri;
+
+ return NULL;
+}
+
+struct regulator *regulator_get_name(const char *name)
+{
+ struct regulator_internal *ri;
+ struct regulator *r;
+
+ ri = regulator_by_name(name);
+ if (!ri)
+ return ERR_PTR(-ENODEV);
+
+ r = xzalloc(sizeof(*r));
+ r->ri = ri;
+
+ list_add_tail(&r->list, &ri->consumer_list);
+
+ return r;
+}
+
/*
* regulator_enable - enable a regulator.
* @r: the regulator to enable
@@ -379,7 +407,7 @@ static void regulator_print_one(struct regulator_internal *ri)
printf(" consumers:\n");
list_for_each_entry(r, &ri->consumer_list, list)
- printf(" %s\n", dev_name(r->dev));
+ printf(" %s\n", r->dev ? dev_name(r->dev) : "none");
}
}
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index d29cd1328b..1c3dcb79a8 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -124,7 +124,7 @@ static int usb_set_configuration(struct usb_device *dev, int configuration)
dev->toggle[1] = 0;
return 0;
} else
- return -1;
+ return res;
}
/* The routine usb_set_maxpacket_ep() is extracted from the loop of routine
@@ -412,9 +412,11 @@ int usb_new_device(struct usb_device *dev)
usb_parse_config(dev, buf, 0);
usb_set_maxpacket(dev);
/* we set the default configuration here */
- if (usb_set_configuration(dev, dev->config.desc.bConfigurationValue)) {
- printf("failed to set default configuration " \
- "len %d, status %lX\n", dev->act_len, dev->status);
+ err = usb_set_configuration(dev, dev->config.desc.bConfigurationValue);
+ if (err) {
+ printf("Setting default configuration failed with: %s\n" \
+ "len %d, status %lX\n", strerror(-err),
+ dev->act_len, dev->status);
goto err_out;
}
pr_debug("new device: Mfr=%d, Product=%d, SerialNumber=%d\n",
@@ -593,7 +595,7 @@ int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe,
int usb_control_msg(struct usb_device *dev, unsigned int pipe,
unsigned char request, unsigned char requesttype,
unsigned short value, unsigned short index,
- void *data, unsigned short size, int timeout)
+ void *data, unsigned short size, int timeout_ms)
{
struct usb_host *host = dev->host;
int ret;
@@ -615,7 +617,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe,
dev->status = USB_ST_NOT_PROC; /*not yet processed */
ret = host->submit_control_msg(dev, pipe, data, size, setup_packet,
- timeout);
+ timeout_ms);
usb_host_release(host);
@@ -631,7 +633,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe,
* synchronous behavior
*/
int usb_bulk_msg(struct usb_device *dev, unsigned int pipe,
- void *data, int len, int *actual_length, int timeout)
+ void *data, int len, int *actual_length, int timeout_ms)
{
struct usb_host *host = dev->host;
int ret;
@@ -644,7 +646,7 @@ int usb_bulk_msg(struct usb_device *dev, unsigned int pipe,
return ret;
dev->status = USB_ST_NOT_PROC; /* not yet processed */
- ret = host->submit_bulk_msg(dev, pipe, data, len, timeout);
+ ret = host->submit_bulk_msg(dev, pipe, data, len, timeout_ms);
usb_host_release(host);
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index d2029bc7d7..b0f32faee9 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -21,6 +21,9 @@ config USB_OHCI_AT91
depends on ARCH_AT91
bool "AT91 OHCI driver"
+config USB_DWC2_HOST
+ bool "DWC2 Host driver"
+
config USB_XHCI
bool "xHCI driver"
depends on HAS_DMA
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 0478d34272..fa042e9a54 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -3,5 +3,6 @@ obj-$(CONFIG_USB_EHCI_OMAP) += ehci-omap.o
obj-$(CONFIG_USB_EHCI_ATMEL) += ehci-atmel.o
obj-$(CONFIG_USB_OHCI) += ohci-hcd.o
obj-$(CONFIG_USB_OHCI_AT91) += ohci-at91.o
+obj-$(CONFIG_USB_DWC2_HOST) += dwc2.o
obj-$(CONFIG_USB_XHCI) += xhci-hcd.o xhci-hub.o
obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
new file mode 100644
index 0000000000..1df1149686
--- /dev/null
+++ b/drivers/usb/host/dwc2.c
@@ -0,0 +1,1132 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2012 Oleksandr Tymoshenko <gonzo@freebsd.org>
+ * Copyright (C) 2014 Marek Vasut <marex@denx.de>
+ */
+
+#include <common.h>
+#include <usb/usb.h>
+#include <usb/usbroothubdes.h>
+#include <malloc.h>
+#include <init.h>
+#include <io.h>
+#include <of.h>
+#include <linux/iopoll.h>
+#include <dma.h>
+
+#include "dwc2.h"
+
+/* Use only HC channel 0. */
+#define DWC2_HC_CHANNEL 0
+
+#define DWC2_STATUS_BUF_SIZE 64
+#define DWC2_DATA_BUF_SIZE (16 * 1024)
+
+#define MAX_DEVICE 16
+#define MAX_ENDPOINT 16
+
+struct dwc2_priv {
+ struct device_d *dev;
+ struct usb_host host;
+ uint8_t *dmabuf;
+
+ u8 in_data_toggle[MAX_DEVICE][MAX_ENDPOINT];
+ u8 out_data_toggle[MAX_DEVICE][MAX_ENDPOINT];
+ struct dwc2_core_regs *regs;
+ int root_hub_devnum;
+ bool ext_vbus;
+ /*
+ * The hnp/srp capability must be disabled if the platform
+ * does't support hnp/srp. Otherwise the force mode can't work.
+ */
+ bool hnp_srp_disable;
+ bool oc_disable;
+};
+
+/*
+ * Initializes the FSLSPClkSel field of the HCFG register
+ * depending on the PHY type.
+ */
+static void init_fslspclksel(struct dwc2_priv *priv)
+{
+ struct dwc2_core_regs *regs = priv->regs;
+ uint32_t phyclk;
+
+ phyclk = DWC2_HCFG_FSLSPCLKSEL_48_MHZ; /* Full speed PHY */
+
+ clrsetbits_le32(&regs->host_regs.hcfg,
+ DWC2_HCFG_FSLSPCLKSEL_MASK,
+ phyclk << DWC2_HCFG_FSLSPCLKSEL_OFFSET);
+}
+
+/*
+ * Flush a Tx FIFO.
+ *
+ * @param regs Programming view of DWC_otg controller.
+ * @param num Tx FIFO to flush.
+ */
+static void dwc_otg_flush_tx_fifo(struct dwc2_priv *priv, const int num)
+{
+ struct dwc2_core_regs *regs = priv->regs;
+ struct device_d *dev = priv->dev;
+ int ret;
+ uint32_t val;
+
+ writel(DWC2_GRSTCTL_TXFFLSH | (num << DWC2_GRSTCTL_TXFNUM_OFFSET),
+ &regs->grstctl);
+ ret = readl_poll_timeout(&regs->grstctl, val, !(val & DWC2_GRSTCTL_TXFFLSH),
+ 1000000);
+ if (ret)
+ dev_err(dev, "%s: Timeout!\n", __func__);
+
+ /* Wait for 3 PHY Clocks */
+ udelay(1);
+}
+
+/*
+ * Flush Rx FIFO.
+ *
+ * @param regs Programming view of DWC_otg controller.
+ */
+static void dwc_otg_flush_rx_fifo(struct dwc2_priv *priv)
+{
+ struct dwc2_core_regs *regs = priv->regs;
+ struct device_d *dev = priv->dev;
+ int ret;
+ uint32_t val;
+
+ writel(DWC2_GRSTCTL_RXFFLSH, &regs->grstctl);
+ ret = readl_poll_timeout(&regs->grstctl, val, !(val & DWC2_GRSTCTL_RXFFLSH),
+ 1000000);
+ if (ret)
+ dev_err(dev, "%s: Timeout!\n", __func__);
+
+ /* Wait for 3 PHY Clocks */
+ udelay(1);
+}
+
+/*
+ * Do core a soft reset of the core. Be careful with this because it
+ * resets all the internal state machines of the core.
+ */
+static void dwc_otg_core_reset(struct dwc2_priv *priv)
+{
+ struct dwc2_core_regs *regs = priv->regs;
+ struct device_d *dev = priv->dev;
+ uint32_t val;
+ int ret;
+
+ /* Wait for AHB master IDLE state. */
+ ret = readl_poll_timeout(&regs->grstctl, val, val & DWC2_GRSTCTL_AHBIDLE,
+ 1000000);
+ if (ret)
+ dev_err(dev, "%s: Timeout!\n", __func__);
+
+ /* Core Soft Reset */
+ writel(DWC2_GRSTCTL_CSFTRST, &regs->grstctl);
+ ret = readl_poll_timeout(&regs->grstctl, val, !(val & DWC2_GRSTCTL_CSFTRST),
+ 1000000);
+ if (ret)
+ dev_err(dev, "%s: Timeout!\n", __func__);
+
+ /*
+ * Wait for core to come out of reset.
+ * NOTE: This long sleep is _very_ important, otherwise the core will
+ * not stay in host mode after a connector ID change!
+ */
+ mdelay(100);
+}
+
+/*
+ * This function initializes the DWC_otg controller registers for
+ * host mode.
+ *
+ * This function flushes the Tx and Rx FIFOs and it flushes any entries in the
+ * request queues. Host channels are reset to ensure that they are ready for
+ * performing transfers.
+ *
+ * @param dev USB Device (NULL if driver model is not being used)
+ * @param regs Programming view of DWC_otg controller
+ *
+ */
+static void dwc_otg_core_host_init(struct dwc2_priv *priv)
+{
+ struct dwc2_core_regs *regs = priv->regs;
+ struct device_d *dev = priv->dev;
+ uint32_t nptxfifosize = 0;
+ uint32_t ptxfifosize = 0;
+ uint32_t hprt0 = 0;
+ uint32_t val;
+ int i, ret, num_channels;
+
+ /* Restart the Phy Clock */
+ writel(0, &regs->pcgcctl);
+
+ /* Initialize Host Configuration Register */
+ init_fslspclksel(priv);
+
+ /* Configure data FIFO sizes */
+ if (readl(&regs->ghwcfg2) & DWC2_HWCFG2_DYNAMIC_FIFO) {
+ /* Rx FIFO */
+ writel(CONFIG_DWC2_HOST_RX_FIFO_SIZE, &regs->grxfsiz);
+
+ /* Non-periodic Tx FIFO */
+ nptxfifosize |= CONFIG_DWC2_HOST_NPERIO_TX_FIFO_SIZE <<
+ DWC2_FIFOSIZE_DEPTH_OFFSET;
+ nptxfifosize |= CONFIG_DWC2_HOST_RX_FIFO_SIZE <<
+ DWC2_FIFOSIZE_STARTADDR_OFFSET;
+ writel(nptxfifosize, &regs->gnptxfsiz);
+
+ /* Periodic Tx FIFO */
+ ptxfifosize |= CONFIG_DWC2_HOST_PERIO_TX_FIFO_SIZE <<
+ DWC2_FIFOSIZE_DEPTH_OFFSET;
+ ptxfifosize |= (CONFIG_DWC2_HOST_RX_FIFO_SIZE +
+ CONFIG_DWC2_HOST_NPERIO_TX_FIFO_SIZE) <<
+ DWC2_FIFOSIZE_STARTADDR_OFFSET;
+ writel(ptxfifosize, &regs->hptxfsiz);
+ }
+
+ /* Clear Host Set HNP Enable in the OTG Control Register */
+ clrbits_le32(&regs->gotgctl, DWC2_GOTGCTL_HSTSETHNPEN);
+
+ /* Make sure the FIFOs are flushed. */
+ dwc_otg_flush_tx_fifo(priv, 0x10); /* All Tx FIFOs */
+ dwc_otg_flush_rx_fifo(priv);
+
+ /* Flush out any leftover queued requests. */
+ num_channels = readl(&regs->ghwcfg2);
+ num_channels &= DWC2_HWCFG2_NUM_HOST_CHAN_MASK;
+ num_channels >>= DWC2_HWCFG2_NUM_HOST_CHAN_OFFSET;
+ num_channels += 1;
+
+ for (i = 0; i < num_channels; i++)
+ clrsetbits_le32(&regs->hc_regs[i].hcchar,
+ DWC2_HCCHAR_CHEN | DWC2_HCCHAR_EPDIR,
+ DWC2_HCCHAR_CHDIS);
+
+ /* Halt all channels to put them into a known state. */
+ for (i = 0; i < num_channels; i++) {
+ clrsetbits_le32(&regs->hc_regs[i].hcchar,
+ DWC2_HCCHAR_EPDIR,
+ DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS);
+ ret = readl_poll_timeout(&regs->hc_regs[i].hcchar, val,
+ !(val & DWC2_HCCHAR_CHEN),
+ 1000000);
+ if (ret)
+ dev_err(dev, "%s: Timeout!\n", __func__);
+ }
+
+ /* Turn on the vbus power. */
+ if (readl(&regs->gintsts) & DWC2_GINTSTS_CURMODE_HOST) {
+ hprt0 = readl(&regs->hprt0);
+ hprt0 &= ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET);
+ hprt0 &= ~(DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG);
+ if (!(hprt0 & DWC2_HPRT0_PRTPWR)) {
+ hprt0 |= DWC2_HPRT0_PRTPWR;
+ writel(hprt0, &regs->hprt0);
+ }
+ }
+}
+
+/*
+ * This function initializes the DWC_otg controller registers and
+ * prepares the core for device mode or host mode operation.
+ *
+ * @param regs Programming view of the DWC_otg controller
+ */
+static void dwc_otg_core_init(struct dwc2_priv *priv)
+{
+ struct dwc2_core_regs *regs = priv->regs;
+ uint32_t ahbcfg = 0;
+ uint32_t usbcfg = 0;
+ uint8_t brst_sz = 32;
+
+ /* Common Initialization */
+ usbcfg = readl(&regs->gusbcfg);
+
+ /* Program the ULPI External VBUS bit if needed */
+ if (priv->ext_vbus) {
+ usbcfg |= DWC2_GUSBCFG_ULPI_EXT_VBUS_DRV;
+ if (!priv->oc_disable) {
+ usbcfg |= DWC2_GUSBCFG_ULPI_INT_VBUS_INDICATOR |
+ DWC2_GUSBCFG_INDICATOR_PASSTHROUGH;
+ }
+ } else {
+ usbcfg &= ~DWC2_GUSBCFG_ULPI_EXT_VBUS_DRV;
+ }
+
+ /* Set external TS Dline pulsing */
+ usbcfg &= ~DWC2_GUSBCFG_TERM_SEL_DL_PULSE;
+ writel(usbcfg, &regs->gusbcfg);
+
+ /* Reset the Controller */
+ dwc_otg_core_reset(priv);
+
+ /* High speed PHY. */
+
+ /*
+ * HS PHY parameters. These parameters are preserved during
+ * soft reset so only program the first time. Do a soft reset
+ * immediately after setting phyif.
+ */
+ usbcfg &= ~(DWC2_GUSBCFG_ULPI_UTMI_SEL | DWC2_GUSBCFG_PHYIF);
+ usbcfg |= CONFIG_DWC2_PHY_TYPE << DWC2_GUSBCFG_ULPI_UTMI_SEL_OFFSET;
+
+ if (usbcfg & DWC2_GUSBCFG_ULPI_UTMI_SEL) /* ULPI interface */
+ usbcfg &= ~DWC2_GUSBCFG_DDRSEL;
+
+ writel(usbcfg, &regs->gusbcfg);
+
+ /* Reset after setting the PHY parameters */
+ dwc_otg_core_reset(priv);
+
+ usbcfg = readl(&regs->gusbcfg);
+ usbcfg &= ~(DWC2_GUSBCFG_ULPI_FSLS | DWC2_GUSBCFG_ULPI_CLK_SUS_M);
+
+ if (priv->hnp_srp_disable)
+ usbcfg |= DWC2_GUSBCFG_FORCEHOSTMODE;
+
+ writel(usbcfg, &regs->gusbcfg);
+
+ /* Program the GAHBCFG Register. */
+ switch (readl(&regs->ghwcfg2) & DWC2_HWCFG2_ARCHITECTURE_MASK) {
+ case DWC2_HWCFG2_ARCHITECTURE_SLAVE_ONLY:
+ break;
+ case DWC2_HWCFG2_ARCHITECTURE_EXT_DMA:
+ while (brst_sz > 1) {
+ ahbcfg |= ahbcfg + (1 << DWC2_GAHBCFG_HBURSTLEN_OFFSET);
+ ahbcfg &= DWC2_GAHBCFG_HBURSTLEN_MASK;
+ brst_sz >>= 1;
+ }
+
+ ahbcfg |= DWC2_GAHBCFG_DMAENABLE;
+ break;
+
+ case DWC2_HWCFG2_ARCHITECTURE_INT_DMA:
+ ahbcfg |= DWC2_GAHBCFG_HBURSTLEN_INCR4;
+ ahbcfg |= DWC2_GAHBCFG_DMAENABLE;
+ break;
+ }
+
+ writel(ahbcfg, &regs->gahbcfg);
+
+ /* Program the capabilities in GUSBCFG Register */
+ usbcfg = 0;
+
+ if (!priv->hnp_srp_disable)
+ usbcfg |= DWC2_GUSBCFG_HNPCAP | DWC2_GUSBCFG_SRPCAP;
+
+ setbits_le32(&regs->gusbcfg, usbcfg);
+}
+
+/*
+ * Prepares a host channel for transferring packets to/from a specific
+ * endpoint. The HCCHARn register is set up with the characteristics specified
+ * in _hc. Host channel interrupts that may need to be serviced while this
+ * transfer is in progress are enabled.
+ *
+ * @param regs Programming view of DWC_otg controller
+ * @param hc Information needed to initialize the host channel
+ */
+static void dwc_otg_hc_init(struct dwc2_core_regs *regs, uint8_t hc_num,
+ struct usb_device *dev, uint8_t dev_addr, uint8_t ep_num,
+ uint8_t ep_is_in, uint8_t ep_type, uint16_t max_packet)
+{
+ struct dwc2_hc_regs *hc_regs = &regs->hc_regs[hc_num];
+ uint32_t hcchar = (dev_addr << DWC2_HCCHAR_DEVADDR_OFFSET) |
+ (ep_num << DWC2_HCCHAR_EPNUM_OFFSET) |
+ (ep_is_in << DWC2_HCCHAR_EPDIR_OFFSET) |
+ (ep_type << DWC2_HCCHAR_EPTYPE_OFFSET) |
+ (max_packet << DWC2_HCCHAR_MPS_OFFSET);
+
+ if (dev->speed == USB_SPEED_LOW)
+ hcchar |= DWC2_HCCHAR_LSPDDEV;
+
+ /*
+ * Program the HCCHARn register with the endpoint characteristics
+ * for the current transfer.
+ */
+ writel(hcchar, &hc_regs->hcchar);
+
+ /* Program the HCSPLIT register, default to no SPLIT */
+ writel(0, &hc_regs->hcsplt);
+}
+
+static void dwc_otg_hc_init_split(struct dwc2_hc_regs *hc_regs,
+ uint8_t hub_devnum, uint8_t hub_port)
+{
+ uint32_t hcsplt = 0;
+
+ hcsplt = DWC2_HCSPLT_SPLTENA;
+ hcsplt |= hub_devnum << DWC2_HCSPLT_HUBADDR_OFFSET;
+ hcsplt |= hub_port << DWC2_HCSPLT_PRTADDR_OFFSET;
+
+ /* Program the HCSPLIT register for SPLITs */
+ writel(hcsplt, &hc_regs->hcsplt);
+}
+
+/*
+ * DWC2 to USB API interface
+ */
+/* Direction: In ; Request: Status */
+static int dwc_otg_submit_rh_msg_in_status(struct dwc2_core_regs *regs,
+ struct usb_device *dev, void *buffer,
+ int txlen, struct devrequest *cmd)
+{
+ uint32_t hprt0 = 0;
+ uint32_t port_status = 0;
+ uint32_t port_change = 0;
+ int len = 0;
+ int stat = 0;
+
+ switch (cmd->requesttype & ~USB_DIR_IN) {
+ case 0:
+ *(uint16_t *)buffer = cpu_to_le16(1);
+ len = 2;
+ break;
+ case USB_RECIP_INTERFACE:
+ case USB_RECIP_ENDPOINT:
+ *(uint16_t *)buffer = cpu_to_le16(0);
+ len = 2;
+ break;
+ case USB_TYPE_CLASS:
+ *(uint32_t *)buffer = cpu_to_le32(0);
+ len = 4;
+ break;
+ case USB_RECIP_OTHER | USB_TYPE_CLASS:
+ hprt0 = readl(&regs->hprt0);
+ if (hprt0 & DWC2_HPRT0_PRTCONNSTS)
+ port_status |= USB_PORT_STAT_CONNECTION;
+ if (hprt0 & DWC2_HPRT0_PRTENA)
+ port_status |= USB_PORT_STAT_ENABLE;
+ if (hprt0 & DWC2_HPRT0_PRTSUSP)
+ port_status |= USB_PORT_STAT_SUSPEND;
+ if (hprt0 & DWC2_HPRT0_PRTOVRCURRACT)
+ port_status |= USB_PORT_STAT_OVERCURRENT;
+ if (hprt0 & DWC2_HPRT0_PRTRST)
+ port_status |= USB_PORT_STAT_RESET;
+ if (hprt0 & DWC2_HPRT0_PRTPWR)
+ port_status |= USB_PORT_STAT_POWER;
+
+ if ((hprt0 & DWC2_HPRT0_PRTSPD_MASK) == DWC2_HPRT0_PRTSPD_LOW)
+ port_status |= USB_PORT_STAT_LOW_SPEED;
+ else if ((hprt0 & DWC2_HPRT0_PRTSPD_MASK) ==
+ DWC2_HPRT0_PRTSPD_HIGH)
+ port_status |= USB_PORT_STAT_HIGH_SPEED;
+
+ if (hprt0 & DWC2_HPRT0_PRTENCHNG)
+ port_change |= USB_PORT_STAT_C_ENABLE;
+ if (hprt0 & DWC2_HPRT0_PRTCONNDET)
+ port_change |= USB_PORT_STAT_C_CONNECTION;
+ if (hprt0 & DWC2_HPRT0_PRTOVRCURRCHNG)
+ port_change |= USB_PORT_STAT_C_OVERCURRENT;
+
+ *(uint32_t *)buffer = cpu_to_le32(port_status |
+ (port_change << 16));
+ len = 4;
+ break;
+ default:
+ pr_err("%s: unsupported root hub command\n", __func__);
+ stat = USB_ST_STALLED;
+ }
+
+ dev->act_len = min(len, txlen);
+ dev->status = stat;
+
+ return stat;
+}
+
+/* Direction: In ; Request: Descriptor */
+static int dwc_otg_submit_rh_msg_in_descriptor(struct usb_device *dev,
+ void *buffer, int txlen,
+ struct devrequest *cmd)
+{
+ unsigned char data[32];
+ uint32_t dsc;
+ int len = 0;
+ int stat = 0;
+ uint16_t wValue = cpu_to_le16(cmd->value);
+ uint16_t wLength = cpu_to_le16(cmd->length);
+
+ switch (cmd->requesttype & ~USB_DIR_IN) {
+ case 0:
+ switch (wValue & 0xff00) {
+ case 0x0100: /* device descriptor */
+ len = min3(txlen, (int)sizeof(root_hub_dev_des), (int)wLength);
+ memcpy(buffer, root_hub_dev_des, len);
+ break;
+ case 0x0200: /* configuration descriptor */
+ len = min3(txlen, (int)sizeof(root_hub_config_des), (int)wLength);
+ memcpy(buffer, root_hub_config_des, len);
+ break;
+ case 0x0300: /* string descriptors */
+ switch (wValue & 0xff) {
+ case 0x00:
+ len = min3(txlen, (int)sizeof(root_hub_str_index0),
+ (int)wLength);
+ memcpy(buffer, root_hub_str_index0, len);
+ break;
+ case 0x01:
+ len = min3(txlen, (int)sizeof(root_hub_str_index1),
+ (int)wLength);
+ memcpy(buffer, root_hub_str_index1, len);
+ break;
+ }
+ break;
+ default:
+ stat = USB_ST_STALLED;
+ }
+ break;
+
+ case USB_TYPE_CLASS:
+ /* Root port config, set 1 port and nothing else. */
+ dsc = 0x00000001;
+
+ data[0] = 9; /* min length; */
+ data[1] = 0x29;
+ data[2] = dsc & RH_A_NDP;
+ data[3] = 0;
+ if (dsc & RH_A_PSM)
+ data[3] |= 0x1;
+ if (dsc & RH_A_NOCP)
+ data[3] |= 0x10;
+ else if (dsc & RH_A_OCPM)
+ data[3] |= 0x8;
+
+ /* corresponds to data[4-7] */
+ data[5] = (dsc & RH_A_POTPGT) >> 24;
+ data[7] = dsc & RH_B_DR;
+ if (data[2] < 7) {
+ data[8] = 0xff;
+ } else {
+ data[0] += 2;
+ data[8] = (dsc & RH_B_DR) >> 8;
+ data[9] = 0xff;
+ data[10] = data[9];
+ }
+
+ len = min3(txlen, (int)data[0], (int)wLength);
+ memcpy(buffer, data, len);
+ break;
+ default:
+ pr_err("%s: unsupported root hub command\n", __func__);
+ stat = USB_ST_STALLED;
+ }
+
+ dev->act_len = min(len, txlen);
+ dev->status = stat;
+
+ return stat;
+}
+
+/* Direction: In ; Request: Configuration */
+static int dwc_otg_submit_rh_msg_in_configuration(struct usb_device *dev,
+ void *buffer, int txlen,
+ struct devrequest *cmd)
+{
+ int len = 0;
+ int stat = 0;
+
+ switch (cmd->requesttype & ~USB_DIR_IN) {
+ case 0:
+ *(uint8_t *)buffer = 0x01;
+ len = 1;
+ break;
+ default:
+ pr_err("%s: unsupported root hub command\n", __func__);
+ stat = USB_ST_STALLED;
+ }
+
+ dev->act_len = min(len, txlen);
+ dev->status = stat;
+
+ return stat;
+}
+
+/* Direction: In */
+static int dwc_otg_submit_rh_msg_in(struct dwc2_priv *priv,
+ struct usb_device *dev, void *buffer,
+ int txlen, struct devrequest *cmd)
+{
+ switch (cmd->request) {
+ case USB_REQ_GET_STATUS:
+ return dwc_otg_submit_rh_msg_in_status(priv->regs, dev, buffer,
+ txlen, cmd);
+ case USB_REQ_GET_DESCRIPTOR:
+ return dwc_otg_submit_rh_msg_in_descriptor(dev, buffer,
+ txlen, cmd);
+ case USB_REQ_GET_CONFIGURATION:
+ return dwc_otg_submit_rh_msg_in_configuration(dev, buffer,
+ txlen, cmd);
+ default:
+ pr_err("%s: unsupported root hub command\n", __func__);
+ return USB_ST_STALLED;
+ }
+}
+
+/* Direction: Out */
+static int dwc_otg_submit_rh_msg_out(struct dwc2_priv *priv,
+ struct usb_device *dev,
+ void *buffer, int txlen,
+ struct devrequest *cmd)
+{
+ struct dwc2_core_regs *regs = priv->regs;
+ int len = 0;
+ int stat = 0;
+ uint16_t bmrtype_breq = cmd->requesttype | (cmd->request << 8);
+ uint16_t wValue = cpu_to_le16(cmd->value);
+
+ switch (bmrtype_breq & ~USB_DIR_IN) {
+ case (USB_REQ_CLEAR_FEATURE << 8) | USB_RECIP_ENDPOINT:
+ case (USB_REQ_CLEAR_FEATURE << 8) | USB_TYPE_CLASS:
+ break;
+
+ case (USB_REQ_CLEAR_FEATURE << 8) | USB_RECIP_OTHER | USB_TYPE_CLASS:
+ switch (wValue) {
+ case USB_PORT_FEAT_C_CONNECTION:
+ setbits_le32(&regs->hprt0, DWC2_HPRT0_PRTCONNDET);
+ break;
+ }
+ break;
+
+ case (USB_REQ_SET_FEATURE << 8) | USB_RECIP_OTHER | USB_TYPE_CLASS:
+ switch (wValue) {
+ case USB_PORT_FEAT_SUSPEND:
+ break;
+
+ case USB_PORT_FEAT_RESET:
+ clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_PRTENA |
+ DWC2_HPRT0_PRTCONNDET |
+ DWC2_HPRT0_PRTENCHNG |
+ DWC2_HPRT0_PRTOVRCURRCHNG,
+ DWC2_HPRT0_PRTRST);
+ mdelay(50);
+ clrbits_le32(&regs->hprt0, DWC2_HPRT0_PRTRST);
+ break;
+
+ case USB_PORT_FEAT_POWER:
+ clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_PRTENA |
+ DWC2_HPRT0_PRTCONNDET |
+ DWC2_HPRT0_PRTENCHNG |
+ DWC2_HPRT0_PRTOVRCURRCHNG,
+ DWC2_HPRT0_PRTRST);
+ break;
+
+ case USB_PORT_FEAT_ENABLE:
+ break;
+ }
+ break;
+ case (USB_REQ_SET_ADDRESS << 8):
+ priv->root_hub_devnum = wValue;
+ break;
+ case (USB_REQ_SET_CONFIGURATION << 8):
+ break;
+ default:
+ pr_err("%s: unsupported root hub command\n", __func__);
+ stat = USB_ST_STALLED;
+ }
+
+ len = min(len, txlen);
+
+ dev->act_len = len;
+ dev->status = stat;
+
+ return stat;
+}
+
+static int dwc_otg_submit_rh_msg(struct dwc2_priv *priv, struct usb_device *dev,
+ unsigned long pipe, void *buffer, int txlen,
+ struct devrequest *cmd)
+{
+ int stat = 0;
+
+ if (usb_pipeint(pipe)) {
+ pr_err("Root-Hub submit IRQ: NOT implemented\n");
+ return 0;
+ }
+
+ if (cmd->requesttype & USB_DIR_IN)
+ stat = dwc_otg_submit_rh_msg_in(priv, dev, buffer, txlen, cmd);
+ else
+ stat = dwc_otg_submit_rh_msg_out(priv, dev, buffer, txlen, cmd);
+
+ mdelay(1);
+
+ return stat;
+}
+
+static int wait_for_chhltd(struct dwc2_priv *priv, uint32_t *sub,
+ u8 *toggle, int timeout_ms)
+{
+ struct dwc2_core_regs *regs = priv->regs;
+ struct dwc2_hc_regs *hc_regs = &regs->hc_regs[DWC2_HC_CHANNEL];
+ struct device_d *dev = priv->dev;
+ int ret;
+ uint32_t hcint, hctsiz;
+ uint32_t val;
+ int timeout_us = timeout_ms * 1000;
+
+ ret = readl_poll_timeout(&hc_regs->hcint, val,
+ val & DWC2_HCINT_CHHLTD, timeout_us);
+ if (ret) {
+ clrsetbits_le32(&hc_regs->hcchar, 0, DWC2_HCCHAR_CHDIS);
+ readl_poll_timeout(&hc_regs->hcint, val,
+ val & DWC2_HCINT_CHHLTD, 10000);
+
+ return ret;
+ }
+
+ hcint = readl(&hc_regs->hcint);
+ hctsiz = readl(&hc_regs->hctsiz);
+ *sub = (hctsiz & DWC2_HCTSIZ_XFERSIZE_MASK) >>
+ DWC2_HCTSIZ_XFERSIZE_OFFSET;
+ *toggle = (hctsiz & DWC2_HCTSIZ_PID_MASK) >> DWC2_HCTSIZ_PID_OFFSET;
+
+ dev_dbg(dev, "%s: HCINT=%08x sub=%u toggle=%d\n", __func__, hcint, *sub,
+ *toggle);
+
+ if (hcint & DWC2_HCINT_XFERCOMP)
+ return 0;
+
+ if (hcint & (DWC2_HCINT_NAK | DWC2_HCINT_FRMOVRUN))
+ return -EAGAIN;
+
+ dev_dbg(dev, "%s: Error (HCINT=%08x)\n", __func__, hcint);
+
+ return -EINVAL;
+}
+
+static int dwc2_eptype[] = {
+ DWC2_HCCHAR_EPTYPE_ISOC,
+ DWC2_HCCHAR_EPTYPE_INTR,
+ DWC2_HCCHAR_EPTYPE_CONTROL,
+ DWC2_HCCHAR_EPTYPE_BULK,
+};
+
+static int transfer_chunk(struct dwc2_priv *priv, u8 *pid, int in, void *buffer,
+ int num_packets, int xfer_len, int *actual_len,
+ int odd_frame, int timeout_ms)
+{
+ struct dwc2_core_regs *regs = priv->regs;
+ struct dwc2_hc_regs *hc_regs = &regs->hc_regs[DWC2_HC_CHANNEL];
+ int ret = 0;
+ uint32_t sub = 0;
+ enum dma_data_direction dir;
+ dma_addr_t dma = 0;
+
+ dev_dbg(priv->dev, "%s: chunk: pid %d xfer_len %u pkts %u\n",
+ __func__, *pid, xfer_len, num_packets);
+
+ writel((xfer_len << DWC2_HCTSIZ_XFERSIZE_OFFSET) |
+ (num_packets << DWC2_HCTSIZ_PKTCNT_OFFSET) |
+ (*pid << DWC2_HCTSIZ_PID_OFFSET),
+ &hc_regs->hctsiz);
+
+ if (xfer_len) {
+ if (in) {
+ dir = DMA_FROM_DEVICE;
+ } else {
+ memcpy(priv->dmabuf, buffer, xfer_len);
+ dir = DMA_TO_DEVICE;
+ }
+ dma = dma_map_single(priv->dev, priv->dmabuf, xfer_len, dir);
+ }
+
+ writel(dma, &hc_regs->hcdma);
+
+ /* Clear old interrupt conditions for this host channel. */
+ writel(0x3fff, &hc_regs->hcint);
+
+ /* Set host channel enable after all other setup is complete. */
+ clrsetbits_le32(&hc_regs->hcchar, DWC2_HCCHAR_MULTICNT_MASK |
+ DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS |
+ DWC2_HCCHAR_ODDFRM,
+ (1 << DWC2_HCCHAR_MULTICNT_OFFSET) |
+ (odd_frame << DWC2_HCCHAR_ODDFRM_OFFSET) |
+ DWC2_HCCHAR_CHEN);
+
+ ret = wait_for_chhltd(priv, &sub, pid, timeout_ms);
+
+ if (xfer_len)
+ dma_unmap_single(priv->dev, dma, xfer_len, dir);
+
+ if (in) {
+ xfer_len -= sub;
+
+ memcpy(buffer, priv->dmabuf, xfer_len);
+ }
+
+ if (!ret)
+ *actual_len = xfer_len;
+
+ return ret;
+}
+
+static int usb_find_usb2_hub_address_port(struct usb_device *udev,
+ uint8_t *hub_address, uint8_t *hub_port)
+{
+ /* Find out the nearest parent which is high speed */
+ while (udev->parent->parent) {
+ if (udev->parent->speed != USB_SPEED_HIGH) {
+ udev = udev->parent;
+ } else {
+ *hub_address = udev->parent->devnum;
+ *hub_port = udev->portnr;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int chunk_msg(struct dwc2_priv *priv, struct usb_device *dev,
+ unsigned long pipe, u8 *pid, int in, void *buffer, int len,
+ int timeout_ms)
+{
+ struct dwc2_core_regs *regs = priv->regs;
+ struct dwc2_hc_regs *hc_regs = &regs->hc_regs[DWC2_HC_CHANNEL];
+ struct dwc2_host_regs *host_regs = &regs->host_regs;
+ int devnum = usb_pipedevice(pipe);
+ int ep = usb_pipeendpoint(pipe);
+ int max = usb_maxpacket(dev, pipe);
+ int eptype = dwc2_eptype[usb_pipetype(pipe)];
+ int done = 0;
+ int ret = 0;
+ int do_split = 0;
+ int complete_split = 0;
+ uint32_t xfer_len;
+ uint32_t num_packets;
+ int stop_transfer = 0;
+ uint32_t max_xfer_len;
+ int ssplit_frame_num = 0;
+
+ dev_dbg(priv->dev, "%s: msg: pipe %lx pid %d in %d len %d\n",
+ __func__, pipe, *pid, in, len);
+
+ max_xfer_len = CONFIG_DWC2_MAX_PACKET_COUNT * max;
+ if (max_xfer_len > CONFIG_DWC2_MAX_TRANSFER_SIZE)
+ max_xfer_len = CONFIG_DWC2_MAX_TRANSFER_SIZE;
+ if (max_xfer_len > DWC2_DATA_BUF_SIZE)
+ max_xfer_len = DWC2_DATA_BUF_SIZE;
+
+ /* Make sure that max_xfer_len is a multiple of max packet size. */
+ num_packets = max_xfer_len / max;
+ max_xfer_len = num_packets * max;
+
+ /* Initialize channel */
+ dwc_otg_hc_init(regs, DWC2_HC_CHANNEL, dev, devnum, ep, in,
+ eptype, max);
+
+ /* Check if the target is a FS/LS device behind a HS hub */
+ if (dev->speed != USB_SPEED_HIGH) {
+ uint8_t hub_addr;
+ uint8_t hub_port;
+ uint32_t hprt0 = readl(&regs->hprt0);
+
+ if ((hprt0 & DWC2_HPRT0_PRTSPD_MASK) == DWC2_HPRT0_PRTSPD_HIGH) {
+ ret = usb_find_usb2_hub_address_port(dev, &hub_addr,
+ &hub_port);
+ if (ret)
+ return ret;
+ dwc_otg_hc_init_split(hc_regs, hub_addr, hub_port);
+
+ do_split = 1;
+ num_packets = 1;
+ max_xfer_len = max;
+ }
+ }
+
+ do {
+ int actual_len = 0;
+ uint32_t hcint;
+ int odd_frame = 0;
+ xfer_len = len - done;
+
+ if (xfer_len > max_xfer_len)
+ xfer_len = max_xfer_len;
+ else if (xfer_len > max)
+ num_packets = (xfer_len + max - 1) / max;
+ else
+ num_packets = 1;
+
+ if (complete_split)
+ setbits_le32(&hc_regs->hcsplt, DWC2_HCSPLT_COMPSPLT);
+ else if (do_split)
+ clrbits_le32(&hc_regs->hcsplt, DWC2_HCSPLT_COMPSPLT);
+
+ if (eptype == DWC2_HCCHAR_EPTYPE_INTR) {
+ int uframe_num = readl(&host_regs->hfnum);
+ if (!(uframe_num & 0x1))
+ odd_frame = 1;
+ }
+
+ ret = transfer_chunk(priv, pid, in, (char *)buffer + done,
+ num_packets, xfer_len, &actual_len,
+ odd_frame, timeout_ms);
+
+ hcint = readl(&hc_regs->hcint);
+ if (complete_split) {
+ stop_transfer = 0;
+ if (hcint & DWC2_HCINT_NYET) {
+ int frame_num = DWC2_HFNUM_MAX_FRNUM &
+ readl(&host_regs->hfnum);
+ ret = 0;
+ if (((frame_num - ssplit_frame_num) &
+ DWC2_HFNUM_MAX_FRNUM) > 4)
+ ret = -EAGAIN;
+ } else
+ complete_split = 0;
+ } else if (do_split) {
+ if (hcint & DWC2_HCINT_ACK) {
+ ssplit_frame_num = DWC2_HFNUM_MAX_FRNUM &
+ readl(&host_regs->hfnum);
+ ret = 0;
+ complete_split = 1;
+ }
+ }
+
+ if (ret)
+ break;
+
+ if (actual_len < xfer_len)
+ stop_transfer = 1;
+
+ done += actual_len;
+
+ /*
+ * Transactions are done when when either all data is transferred or
+ * there is a short transfer. In case of a SPLIT make sure the CSPLIT
+ * is executed.
+ */
+ } while (((done < len) && !stop_transfer) || complete_split);
+
+ writel(0, &hc_regs->hcintmsk);
+ writel(0xFFFFFFFF, &hc_regs->hcint);
+
+ dev->status = 0;
+ dev->act_len = done;
+
+ return ret;
+}
+
+#define to_dwc2(ptr) container_of(ptr, struct dwc2_priv, host)
+
+static int dwc2_init_common(struct usb_host *host)
+{
+ struct dwc2_priv *priv = to_dwc2(host);
+ struct dwc2_core_regs *regs = priv->regs;
+ int i, j;
+
+ priv->ext_vbus = 0;
+
+ dwc_otg_core_init(priv);
+ dwc_otg_core_host_init(priv);
+
+ clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_PRTENA |
+ DWC2_HPRT0_PRTCONNDET | DWC2_HPRT0_PRTENCHNG |
+ DWC2_HPRT0_PRTOVRCURRCHNG,
+ DWC2_HPRT0_PRTRST);
+ mdelay(50);
+ clrbits_le32(&regs->hprt0, DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET |
+ DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG |
+ DWC2_HPRT0_PRTRST);
+
+ for (i = 0; i < MAX_DEVICE; i++) {
+ for (j = 0; j < MAX_ENDPOINT; j++) {
+ priv->in_data_toggle[i][j] = DWC2_HC_PID_DATA0;
+ priv->out_data_toggle[i][j] = DWC2_HC_PID_DATA0;
+ }
+ }
+
+ return 0;
+}
+
+static void dwc2_uninit_common(struct dwc2_core_regs *regs)
+{
+ /* Put everything in reset. */
+ clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_PRTENA |
+ DWC2_HPRT0_PRTCONNDET | DWC2_HPRT0_PRTENCHNG |
+ DWC2_HPRT0_PRTOVRCURRCHNG,
+ DWC2_HPRT0_PRTRST);
+}
+
+static int dwc2_submit_control_msg(struct usb_device *udev,
+ unsigned long pipe, void *buffer, int len,
+ struct devrequest *setup, int timeout_ms)
+{
+ struct usb_host *host = udev->host;
+ struct dwc2_priv *priv = to_dwc2(host);
+ int devnum = usb_pipedevice(pipe);
+ int ret, act_len;
+ u8 pid;
+ /* For CONTROL endpoint pid should start with DATA1 */
+ int status_direction;
+
+ if (devnum == priv->root_hub_devnum) {
+ udev->status = 0;
+ udev->speed = USB_SPEED_HIGH;
+ return dwc_otg_submit_rh_msg(priv, udev, pipe, buffer, len,
+ setup);
+ }
+
+ /* SETUP stage */
+ pid = DWC2_HC_PID_SETUP;
+ do {
+ ret = chunk_msg(priv, udev, pipe, &pid, 0, setup, 8, timeout_ms);
+ } while (ret == -EAGAIN);
+
+ if (ret)
+ return ret;
+
+ /* DATA stage */
+ act_len = 0;
+ if (buffer) {
+ pid = DWC2_HC_PID_DATA1;
+ do {
+ ret = chunk_msg(priv, udev, pipe, &pid, usb_pipein(pipe),
+ buffer, len, timeout_ms);
+ act_len += udev->act_len;
+ buffer += udev->act_len;
+ len -= udev->act_len;
+ } while (ret == -EAGAIN);
+ if (ret)
+ return ret;
+ status_direction = usb_pipeout(pipe);
+ } else {
+ /* No-data CONTROL always ends with an IN transaction */
+ status_direction = 1;
+ }
+
+ /* STATUS stage */
+ pid = DWC2_HC_PID_DATA1;
+ do {
+ ret = chunk_msg(priv, udev, pipe, &pid, status_direction,
+ NULL, 0, timeout_ms);
+ } while (ret == -EAGAIN);
+
+ if (ret)
+ return ret;
+
+ udev->act_len = act_len;
+
+ return 0;
+}
+
+static int dwc2_submit_bulk_msg(struct usb_device *udev, unsigned long pipe,
+ void *buffer, int len, int timeout_ms)
+{
+ struct usb_host *host = udev->host;
+ struct dwc2_priv *priv = to_dwc2(host);
+ int devnum = usb_pipedevice(pipe);
+ int ep = usb_pipeendpoint(pipe);
+ u8* pid;
+
+ if ((devnum >= MAX_DEVICE) || (devnum == priv->root_hub_devnum)) {
+ udev->status = 0;
+ return -EINVAL;
+ }
+
+ if (usb_pipein(pipe))
+ pid = &priv->in_data_toggle[devnum][ep];
+ else
+ pid = &priv->out_data_toggle[devnum][ep];
+
+ return chunk_msg(priv, udev, pipe, pid, usb_pipein(pipe), buffer, len,
+ timeout_ms);
+}
+
+static int dwc2_submit_int_msg(struct usb_device *udev, unsigned long pipe,
+ void *buffer, int len, int interval)
+{
+ uint64_t start;
+ int ret;
+
+ start = get_time_ns();
+
+ while (1) {
+ ret = dwc2_submit_bulk_msg(udev, pipe, buffer, len, 0);
+ if (ret != -EAGAIN)
+ return ret;
+ if (is_timeout(start, USB_CNTL_TIMEOUT * MSECOND))
+ return -ETIMEDOUT;
+ }
+}
+
+static int dwc2_detect(struct device_d *dev)
+{
+ struct dwc2_priv *priv = dev->priv;
+
+ return usb_host_detect(&priv->host);
+}
+
+static int dwc2_probe(struct device_d *dev)
+{
+ struct resource *iores;
+ struct dwc2_priv *priv;
+ struct usb_host *host;
+ struct device_node *np = dev->device_node;
+ int ret;
+ uint32_t snpsid;
+
+ priv = xzalloc(sizeof(*priv));
+
+ iores = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(iores))
+ return PTR_ERR(iores);
+
+ priv->regs = IOMEM(iores->start);
+ priv->dev = dev;
+
+ snpsid = readl(&priv->regs->gsnpsid);
+ dev_info(dev, "Core Release: %x.%03x\n",
+ snpsid >> 12 & 0xf, snpsid & 0xfff);
+
+ if ((snpsid & DWC2_SNPSID_DEVID_MASK) != DWC2_SNPSID_DEVID_VER_2xx &&
+ (snpsid & DWC2_SNPSID_DEVID_MASK) != DWC2_SNPSID_DEVID_VER_3xx) {
+ dev_info(dev, "SNPSID invalid (not DWC2 OTG device): %08x\n",
+ snpsid);
+ return -ENODEV;
+ }
+
+ priv->oc_disable = of_property_read_bool(np, "disable-over-current");
+ priv->hnp_srp_disable = of_property_read_bool(np, "hnp-srp-disable");
+ priv->dmabuf = dma_alloc(DWC2_DATA_BUF_SIZE);
+
+ host = &priv->host;
+
+ host->init = dwc2_init_common;
+ host->submit_int_msg = dwc2_submit_int_msg;
+ host->submit_control_msg = dwc2_submit_control_msg;
+ host->submit_bulk_msg = dwc2_submit_bulk_msg;
+
+ dev->priv = priv;
+ dev->detect = dwc2_detect;
+
+ ret = usb_register_host(host);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void dwc2_remove(struct device_d *dev)
+{
+ struct dwc2_priv *priv = dev->priv;
+
+ dwc2_uninit_common(priv->regs);
+}
+
+static const struct of_device_id dwc2_dt_ids[] = {
+ { .compatible = "brcm,bcm2835-usb" },
+ { .compatible = "brcm,bcm2708-usb" },
+ { .compatible = "snps,dwc2" },
+ { /* sentinel */ }
+};
+
+static struct driver_d dwc2_driver = {
+ .name = "dwc2",
+ .probe = dwc2_probe,
+ .remove = dwc2_remove,
+ .of_compatible = DRV_OF_COMPAT(dwc2_dt_ids),
+};
+device_platform_driver(dwc2_driver);
diff --git a/drivers/usb/host/dwc2.h b/drivers/usb/host/dwc2.h
new file mode 100644
index 0000000000..bdf338f1ed
--- /dev/null
+++ b/drivers/usb/host/dwc2.h
@@ -0,0 +1,778 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2014 Marek Vasut <marex@denx.de>
+ */
+
+#ifndef __DWC2_H__
+#define __DWC2_H__
+
+struct dwc2_hc_regs {
+ u32 hcchar; /* 0x00 */
+ u32 hcsplt;
+ u32 hcint;
+ u32 hcintmsk;
+ u32 hctsiz; /* 0x10 */
+ u32 hcdma;
+ u32 reserved;
+ u32 hcdmab;
+};
+
+struct dwc2_host_regs {
+ u32 hcfg; /* 0x00 */
+ u32 hfir;
+ u32 hfnum;
+ u32 _pad_0x40c;
+ u32 hptxsts; /* 0x10 */
+ u32 haint;
+ u32 haintmsk;
+ u32 hflbaddr;
+};
+
+struct dwc2_core_regs {
+ u32 gotgctl; /* 0x000 */
+ u32 gotgint;
+ u32 gahbcfg;
+ u32 gusbcfg;
+ u32 grstctl; /* 0x010 */
+ u32 gintsts;
+ u32 gintmsk;
+ u32 grxstsr;
+ u32 grxstsp; /* 0x020 */
+ u32 grxfsiz;
+ u32 gnptxfsiz;
+ u32 gnptxsts;
+ u32 gi2cctl; /* 0x030 */
+ u32 gpvndctl;
+ u32 ggpio;
+ u32 guid;
+ u32 gsnpsid; /* 0x040 */
+ u32 ghwcfg1;
+ u32 ghwcfg2;
+ u32 ghwcfg3;
+ u32 ghwcfg4; /* 0x050 */
+ u32 glpmcfg;
+ u32 _pad_0x58_0x9c[42];
+ u32 hptxfsiz; /* 0x100 */
+ u32 dptxfsiz_dieptxf[15];
+ u32 _pad_0x140_0x3fc[176];
+ struct dwc2_host_regs host_regs; /* 0x400 */
+ u32 _pad_0x420_0x43c[8];
+ u32 hprt0; /* 0x440 */
+ u32 _pad_0x444_0x4fc[47];
+ struct dwc2_hc_regs hc_regs[16]; /* 0x500 */
+ u32 _pad_0x700_0xe00[448];
+ u32 pcgcctl; /* 0xe00 */
+};
+
+#define DWC2_GOTGCTL_SESREQSCS (1 << 0)
+#define DWC2_GOTGCTL_SESREQSCS_OFFSET 0
+#define DWC2_GOTGCTL_SESREQ (1 << 1)
+#define DWC2_GOTGCTL_SESREQ_OFFSET 1
+#define DWC2_GOTGCTL_HSTNEGSCS (1 << 8)
+#define DWC2_GOTGCTL_HSTNEGSCS_OFFSET 8
+#define DWC2_GOTGCTL_HNPREQ (1 << 9)
+#define DWC2_GOTGCTL_HNPREQ_OFFSET 9
+#define DWC2_GOTGCTL_HSTSETHNPEN (1 << 10)
+#define DWC2_GOTGCTL_HSTSETHNPEN_OFFSET 10
+#define DWC2_GOTGCTL_DEVHNPEN (1 << 11)
+#define DWC2_GOTGCTL_DEVHNPEN_OFFSET 11
+#define DWC2_GOTGCTL_CONIDSTS (1 << 16)
+#define DWC2_GOTGCTL_CONIDSTS_OFFSET 16
+#define DWC2_GOTGCTL_DBNCTIME (1 << 17)
+#define DWC2_GOTGCTL_DBNCTIME_OFFSET 17
+#define DWC2_GOTGCTL_ASESVLD (1 << 18)
+#define DWC2_GOTGCTL_ASESVLD_OFFSET 18
+#define DWC2_GOTGCTL_BSESVLD (1 << 19)
+#define DWC2_GOTGCTL_BSESVLD_OFFSET 19
+#define DWC2_GOTGCTL_OTGVER (1 << 20)
+#define DWC2_GOTGCTL_OTGVER_OFFSET 20
+#define DWC2_GOTGINT_SESENDDET (1 << 2)
+#define DWC2_GOTGINT_SESENDDET_OFFSET 2
+#define DWC2_GOTGINT_SESREQSUCSTSCHNG (1 << 8)
+#define DWC2_GOTGINT_SESREQSUCSTSCHNG_OFFSET 8
+#define DWC2_GOTGINT_HSTNEGSUCSTSCHNG (1 << 9)
+#define DWC2_GOTGINT_HSTNEGSUCSTSCHNG_OFFSET 9
+#define DWC2_GOTGINT_RESERVER10_16_MASK (0x7F << 10)
+#define DWC2_GOTGINT_RESERVER10_16_OFFSET 10
+#define DWC2_GOTGINT_HSTNEGDET (1 << 17)
+#define DWC2_GOTGINT_HSTNEGDET_OFFSET 17
+#define DWC2_GOTGINT_ADEVTOUTCHNG (1 << 18)
+#define DWC2_GOTGINT_ADEVTOUTCHNG_OFFSET 18
+#define DWC2_GOTGINT_DEBDONE (1 << 19)
+#define DWC2_GOTGINT_DEBDONE_OFFSET 19
+#define DWC2_GAHBCFG_GLBLINTRMSK (1 << 0)
+#define DWC2_GAHBCFG_GLBLINTRMSK_OFFSET 0
+#define DWC2_GAHBCFG_HBURSTLEN_SINGLE (0 << 1)
+#define DWC2_GAHBCFG_HBURSTLEN_INCR (1 << 1)
+#define DWC2_GAHBCFG_HBURSTLEN_INCR4 (3 << 1)
+#define DWC2_GAHBCFG_HBURSTLEN_INCR8 (5 << 1)
+#define DWC2_GAHBCFG_HBURSTLEN_INCR16 (7 << 1)
+#define DWC2_GAHBCFG_HBURSTLEN_MASK (0xF << 1)
+#define DWC2_GAHBCFG_HBURSTLEN_OFFSET 1
+#define DWC2_GAHBCFG_DMAENABLE (1 << 5)
+#define DWC2_GAHBCFG_DMAENABLE_OFFSET 5
+#define DWC2_GAHBCFG_NPTXFEMPLVL_TXFEMPLVL (1 << 7)
+#define DWC2_GAHBCFG_NPTXFEMPLVL_TXFEMPLVL_OFFSET 7
+#define DWC2_GAHBCFG_PTXFEMPLVL (1 << 8)
+#define DWC2_GAHBCFG_PTXFEMPLVL_OFFSET 8
+#define DWC2_GUSBCFG_TOUTCAL_MASK (0x7 << 0)
+#define DWC2_GUSBCFG_TOUTCAL_OFFSET 0
+#define DWC2_GUSBCFG_PHYIF (1 << 3)
+#define DWC2_GUSBCFG_PHYIF_OFFSET 3
+#define DWC2_GUSBCFG_ULPI_UTMI_SEL (1 << 4)
+#define DWC2_GUSBCFG_ULPI_UTMI_SEL_OFFSET 4
+#define DWC2_GUSBCFG_FSINTF (1 << 5)
+#define DWC2_GUSBCFG_FSINTF_OFFSET 5
+#define DWC2_GUSBCFG_PHYSEL (1 << 6)
+#define DWC2_GUSBCFG_PHYSEL_OFFSET 6
+#define DWC2_GUSBCFG_DDRSEL (1 << 7)
+#define DWC2_GUSBCFG_DDRSEL_OFFSET 7
+#define DWC2_GUSBCFG_SRPCAP (1 << 8)
+#define DWC2_GUSBCFG_SRPCAP_OFFSET 8
+#define DWC2_GUSBCFG_HNPCAP (1 << 9)
+#define DWC2_GUSBCFG_HNPCAP_OFFSET 9
+#define DWC2_GUSBCFG_USBTRDTIM_MASK (0xF << 10)
+#define DWC2_GUSBCFG_USBTRDTIM_OFFSET 10
+#define DWC2_GUSBCFG_NPTXFRWNDEN (1 << 14)
+#define DWC2_GUSBCFG_NPTXFRWNDEN_OFFSET 14
+#define DWC2_GUSBCFG_PHYLPWRCLKSEL (1 << 15)
+#define DWC2_GUSBCFG_PHYLPWRCLKSEL_OFFSET 15
+#define DWC2_GUSBCFG_OTGUTMIFSSEL (1 << 16)
+#define DWC2_GUSBCFG_OTGUTMIFSSEL_OFFSET 16
+#define DWC2_GUSBCFG_ULPI_FSLS (1 << 17)
+#define DWC2_GUSBCFG_ULPI_FSLS_OFFSET 17
+#define DWC2_GUSBCFG_ULPI_AUTO_RES (1 << 18)
+#define DWC2_GUSBCFG_ULPI_AUTO_RES_OFFSET 18
+#define DWC2_GUSBCFG_ULPI_CLK_SUS_M (1 << 19)
+#define DWC2_GUSBCFG_ULPI_CLK_SUS_M_OFFSET 19
+#define DWC2_GUSBCFG_ULPI_EXT_VBUS_DRV (1 << 20)
+#define DWC2_GUSBCFG_ULPI_EXT_VBUS_DRV_OFFSET 20
+#define DWC2_GUSBCFG_ULPI_INT_VBUS_INDICATOR (1 << 21)
+#define DWC2_GUSBCFG_ULPI_INT_VBUS_INDICATOR_OFFSET 21
+#define DWC2_GUSBCFG_TERM_SEL_DL_PULSE (1 << 22)
+#define DWC2_GUSBCFG_TERM_SEL_DL_PULSE_OFFSET 22
+#define DWC2_GUSBCFG_INDICATOR_PASSTHROUGH (1 << 24)
+#define DWC2_GUSBCFG_INDICATOR_PASSTHROUGH_OFFSET 24
+#define DWC2_GUSBCFG_IC_USB_CAP (1 << 26)
+#define DWC2_GUSBCFG_IC_USB_CAP_OFFSET 26
+#define DWC2_GUSBCFG_IC_TRAFFIC_PULL_REMOVE (1 << 27)
+#define DWC2_GUSBCFG_IC_TRAFFIC_PULL_REMOVE_OFFSET 27
+#define DWC2_GUSBCFG_TX_END_DELAY (1 << 28)
+#define DWC2_GUSBCFG_TX_END_DELAY_OFFSET 28
+#define DWC2_GUSBCFG_FORCEHOSTMODE (1 << 29)
+#define DWC2_GUSBCFG_FORCEHOSTMODE_OFFSET 29
+#define DWC2_GUSBCFG_FORCEDEVMODE (1 << 30)
+#define DWC2_GUSBCFG_FORCEDEVMODE_OFFSET 30
+#define DWC2_GLPMCTL_LPM_CAP_EN (1 << 0)
+#define DWC2_GLPMCTL_LPM_CAP_EN_OFFSET 0
+#define DWC2_GLPMCTL_APPL_RESP (1 << 1)
+#define DWC2_GLPMCTL_APPL_RESP_OFFSET 1
+#define DWC2_GLPMCTL_HIRD_MASK (0xF << 2)
+#define DWC2_GLPMCTL_HIRD_OFFSET 2
+#define DWC2_GLPMCTL_REM_WKUP_EN (1 << 6)
+#define DWC2_GLPMCTL_REM_WKUP_EN_OFFSET 6
+#define DWC2_GLPMCTL_EN_UTMI_SLEEP (1 << 7)
+#define DWC2_GLPMCTL_EN_UTMI_SLEEP_OFFSET 7
+#define DWC2_GLPMCTL_HIRD_THRES_MASK (0x1F << 8)
+#define DWC2_GLPMCTL_HIRD_THRES_OFFSET 8
+#define DWC2_GLPMCTL_LPM_RESP_MASK (0x3 << 13)
+#define DWC2_GLPMCTL_LPM_RESP_OFFSET 13
+#define DWC2_GLPMCTL_PRT_SLEEP_STS (1 << 15)
+#define DWC2_GLPMCTL_PRT_SLEEP_STS_OFFSET 15
+#define DWC2_GLPMCTL_SLEEP_STATE_RESUMEOK (1 << 16)
+#define DWC2_GLPMCTL_SLEEP_STATE_RESUMEOK_OFFSET 16
+#define DWC2_GLPMCTL_LPM_CHAN_INDEX_MASK (0xF << 17)
+#define DWC2_GLPMCTL_LPM_CHAN_INDEX_OFFSET 17
+#define DWC2_GLPMCTL_RETRY_COUNT_MASK (0x7 << 21)
+#define DWC2_GLPMCTL_RETRY_COUNT_OFFSET 21
+#define DWC2_GLPMCTL_SEND_LPM (1 << 24)
+#define DWC2_GLPMCTL_SEND_LPM_OFFSET 24
+#define DWC2_GLPMCTL_RETRY_COUNT_STS_MASK (0x7 << 25)
+#define DWC2_GLPMCTL_RETRY_COUNT_STS_OFFSET 25
+#define DWC2_GLPMCTL_HSIC_CONNECT (1 << 30)
+#define DWC2_GLPMCTL_HSIC_CONNECT_OFFSET 30
+#define DWC2_GLPMCTL_INV_SEL_HSIC (1 << 31)
+#define DWC2_GLPMCTL_INV_SEL_HSIC_OFFSET 31
+#define DWC2_GRSTCTL_CSFTRST (1 << 0)
+#define DWC2_GRSTCTL_CSFTRST_OFFSET 0
+#define DWC2_GRSTCTL_HSFTRST (1 << 1)
+#define DWC2_GRSTCTL_HSFTRST_OFFSET 1
+#define DWC2_GRSTCTL_HSTFRM (1 << 2)
+#define DWC2_GRSTCTL_HSTFRM_OFFSET 2
+#define DWC2_GRSTCTL_INTKNQFLSH (1 << 3)
+#define DWC2_GRSTCTL_INTKNQFLSH_OFFSET 3
+#define DWC2_GRSTCTL_RXFFLSH (1 << 4)
+#define DWC2_GRSTCTL_RXFFLSH_OFFSET 4
+#define DWC2_GRSTCTL_TXFFLSH (1 << 5)
+#define DWC2_GRSTCTL_TXFFLSH_OFFSET 5
+#define DWC2_GRSTCTL_TXFNUM_MASK (0x1F << 6)
+#define DWC2_GRSTCTL_TXFNUM_OFFSET 6
+#define DWC2_GRSTCTL_DMAREQ (1 << 30)
+#define DWC2_GRSTCTL_DMAREQ_OFFSET 30
+#define DWC2_GRSTCTL_AHBIDLE (1 << 31)
+#define DWC2_GRSTCTL_AHBIDLE_OFFSET 31
+#define DWC2_GINTMSK_MODEMISMATCH (1 << 1)
+#define DWC2_GINTMSK_MODEMISMATCH_OFFSET 1
+#define DWC2_GINTMSK_OTGINTR (1 << 2)
+#define DWC2_GINTMSK_OTGINTR_OFFSET 2
+#define DWC2_GINTMSK_SOFINTR (1 << 3)
+#define DWC2_GINTMSK_SOFINTR_OFFSET 3
+#define DWC2_GINTMSK_RXSTSQLVL (1 << 4)
+#define DWC2_GINTMSK_RXSTSQLVL_OFFSET 4
+#define DWC2_GINTMSK_NPTXFEMPTY (1 << 5)
+#define DWC2_GINTMSK_NPTXFEMPTY_OFFSET 5
+#define DWC2_GINTMSK_GINNAKEFF (1 << 6)
+#define DWC2_GINTMSK_GINNAKEFF_OFFSET 6
+#define DWC2_GINTMSK_GOUTNAKEFF (1 << 7)
+#define DWC2_GINTMSK_GOUTNAKEFF_OFFSET 7
+#define DWC2_GINTMSK_I2CINTR (1 << 9)
+#define DWC2_GINTMSK_I2CINTR_OFFSET 9
+#define DWC2_GINTMSK_ERLYSUSPEND (1 << 10)
+#define DWC2_GINTMSK_ERLYSUSPEND_OFFSET 10
+#define DWC2_GINTMSK_USBSUSPEND (1 << 11)
+#define DWC2_GINTMSK_USBSUSPEND_OFFSET 11
+#define DWC2_GINTMSK_USBRESET (1 << 12)
+#define DWC2_GINTMSK_USBRESET_OFFSET 12
+#define DWC2_GINTMSK_ENUMDONE (1 << 13)
+#define DWC2_GINTMSK_ENUMDONE_OFFSET 13
+#define DWC2_GINTMSK_ISOOUTDROP (1 << 14)
+#define DWC2_GINTMSK_ISOOUTDROP_OFFSET 14
+#define DWC2_GINTMSK_EOPFRAME (1 << 15)
+#define DWC2_GINTMSK_EOPFRAME_OFFSET 15
+#define DWC2_GINTMSK_EPMISMATCH (1 << 17)
+#define DWC2_GINTMSK_EPMISMATCH_OFFSET 17
+#define DWC2_GINTMSK_INEPINTR (1 << 18)
+#define DWC2_GINTMSK_INEPINTR_OFFSET 18
+#define DWC2_GINTMSK_OUTEPINTR (1 << 19)
+#define DWC2_GINTMSK_OUTEPINTR_OFFSET 19
+#define DWC2_GINTMSK_INCOMPLISOIN (1 << 20)
+#define DWC2_GINTMSK_INCOMPLISOIN_OFFSET 20
+#define DWC2_GINTMSK_INCOMPLISOOUT (1 << 21)
+#define DWC2_GINTMSK_INCOMPLISOOUT_OFFSET 21
+#define DWC2_GINTMSK_PORTINTR (1 << 24)
+#define DWC2_GINTMSK_PORTINTR_OFFSET 24
+#define DWC2_GINTMSK_HCINTR (1 << 25)
+#define DWC2_GINTMSK_HCINTR_OFFSET 25
+#define DWC2_GINTMSK_PTXFEMPTY (1 << 26)
+#define DWC2_GINTMSK_PTXFEMPTY_OFFSET 26
+#define DWC2_GINTMSK_LPMTRANRCVD (1 << 27)
+#define DWC2_GINTMSK_LPMTRANRCVD_OFFSET 27
+#define DWC2_GINTMSK_CONIDSTSCHNG (1 << 28)
+#define DWC2_GINTMSK_CONIDSTSCHNG_OFFSET 28
+#define DWC2_GINTMSK_DISCONNECT (1 << 29)
+#define DWC2_GINTMSK_DISCONNECT_OFFSET 29
+#define DWC2_GINTMSK_SESSREQINTR (1 << 30)
+#define DWC2_GINTMSK_SESSREQINTR_OFFSET 30
+#define DWC2_GINTMSK_WKUPINTR (1 << 31)
+#define DWC2_GINTMSK_WKUPINTR_OFFSET 31
+#define DWC2_GINTSTS_CURMODE_DEVICE (0 << 0)
+#define DWC2_GINTSTS_CURMODE_HOST (1 << 0)
+#define DWC2_GINTSTS_CURMODE (1 << 0)
+#define DWC2_GINTSTS_CURMODE_OFFSET 0
+#define DWC2_GINTSTS_MODEMISMATCH (1 << 1)
+#define DWC2_GINTSTS_MODEMISMATCH_OFFSET 1
+#define DWC2_GINTSTS_OTGINTR (1 << 2)
+#define DWC2_GINTSTS_OTGINTR_OFFSET 2
+#define DWC2_GINTSTS_SOFINTR (1 << 3)
+#define DWC2_GINTSTS_SOFINTR_OFFSET 3
+#define DWC2_GINTSTS_RXSTSQLVL (1 << 4)
+#define DWC2_GINTSTS_RXSTSQLVL_OFFSET 4
+#define DWC2_GINTSTS_NPTXFEMPTY (1 << 5)
+#define DWC2_GINTSTS_NPTXFEMPTY_OFFSET 5
+#define DWC2_GINTSTS_GINNAKEFF (1 << 6)
+#define DWC2_GINTSTS_GINNAKEFF_OFFSET 6
+#define DWC2_GINTSTS_GOUTNAKEFF (1 << 7)
+#define DWC2_GINTSTS_GOUTNAKEFF_OFFSET 7
+#define DWC2_GINTSTS_I2CINTR (1 << 9)
+#define DWC2_GINTSTS_I2CINTR_OFFSET 9
+#define DWC2_GINTSTS_ERLYSUSPEND (1 << 10)
+#define DWC2_GINTSTS_ERLYSUSPEND_OFFSET 10
+#define DWC2_GINTSTS_USBSUSPEND (1 << 11)
+#define DWC2_GINTSTS_USBSUSPEND_OFFSET 11
+#define DWC2_GINTSTS_USBRESET (1 << 12)
+#define DWC2_GINTSTS_USBRESET_OFFSET 12
+#define DWC2_GINTSTS_ENUMDONE (1 << 13)
+#define DWC2_GINTSTS_ENUMDONE_OFFSET 13
+#define DWC2_GINTSTS_ISOOUTDROP (1 << 14)
+#define DWC2_GINTSTS_ISOOUTDROP_OFFSET 14
+#define DWC2_GINTSTS_EOPFRAME (1 << 15)
+#define DWC2_GINTSTS_EOPFRAME_OFFSET 15
+#define DWC2_GINTSTS_INTOKENRX (1 << 16)
+#define DWC2_GINTSTS_INTOKENRX_OFFSET 16
+#define DWC2_GINTSTS_EPMISMATCH (1 << 17)
+#define DWC2_GINTSTS_EPMISMATCH_OFFSET 17
+#define DWC2_GINTSTS_INEPINT (1 << 18)
+#define DWC2_GINTSTS_INEPINT_OFFSET 18
+#define DWC2_GINTSTS_OUTEPINTR (1 << 19)
+#define DWC2_GINTSTS_OUTEPINTR_OFFSET 19
+#define DWC2_GINTSTS_INCOMPLISOIN (1 << 20)
+#define DWC2_GINTSTS_INCOMPLISOIN_OFFSET 20
+#define DWC2_GINTSTS_INCOMPLISOOUT (1 << 21)
+#define DWC2_GINTSTS_INCOMPLISOOUT_OFFSET 21
+#define DWC2_GINTSTS_PORTINTR (1 << 24)
+#define DWC2_GINTSTS_PORTINTR_OFFSET 24
+#define DWC2_GINTSTS_HCINTR (1 << 25)
+#define DWC2_GINTSTS_HCINTR_OFFSET 25
+#define DWC2_GINTSTS_PTXFEMPTY (1 << 26)
+#define DWC2_GINTSTS_PTXFEMPTY_OFFSET 26
+#define DWC2_GINTSTS_LPMTRANRCVD (1 << 27)
+#define DWC2_GINTSTS_LPMTRANRCVD_OFFSET 27
+#define DWC2_GINTSTS_CONIDSTSCHNG (1 << 28)
+#define DWC2_GINTSTS_CONIDSTSCHNG_OFFSET 28
+#define DWC2_GINTSTS_DISCONNECT (1 << 29)
+#define DWC2_GINTSTS_DISCONNECT_OFFSET 29
+#define DWC2_GINTSTS_SESSREQINTR (1 << 30)
+#define DWC2_GINTSTS_SESSREQINTR_OFFSET 30
+#define DWC2_GINTSTS_WKUPINTR (1 << 31)
+#define DWC2_GINTSTS_WKUPINTR_OFFSET 31
+#define DWC2_GRXSTS_EPNUM_MASK (0xF << 0)
+#define DWC2_GRXSTS_EPNUM_OFFSET 0
+#define DWC2_GRXSTS_BCNT_MASK (0x7FF << 4)
+#define DWC2_GRXSTS_BCNT_OFFSET 4
+#define DWC2_GRXSTS_DPID_MASK (0x3 << 15)
+#define DWC2_GRXSTS_DPID_OFFSET 15
+#define DWC2_GRXSTS_PKTSTS_MASK (0xF << 17)
+#define DWC2_GRXSTS_PKTSTS_OFFSET 17
+#define DWC2_GRXSTS_FN_MASK (0xF << 21)
+#define DWC2_GRXSTS_FN_OFFSET 21
+#define DWC2_FIFOSIZE_STARTADDR_MASK (0xFFFF << 0)
+#define DWC2_FIFOSIZE_STARTADDR_OFFSET 0
+#define DWC2_FIFOSIZE_DEPTH_MASK (0xFFFF << 16)
+#define DWC2_FIFOSIZE_DEPTH_OFFSET 16
+#define DWC2_GNPTXSTS_NPTXFSPCAVAIL_MASK (0xFFFF << 0)
+#define DWC2_GNPTXSTS_NPTXFSPCAVAIL_OFFSET 0
+#define DWC2_GNPTXSTS_NPTXQSPCAVAIL_MASK (0xFF << 16)
+#define DWC2_GNPTXSTS_NPTXQSPCAVAIL_OFFSET 16
+#define DWC2_GNPTXSTS_NPTXQTOP_TERMINATE (1 << 24)
+#define DWC2_GNPTXSTS_NPTXQTOP_TERMINATE_OFFSET 24
+#define DWC2_GNPTXSTS_NPTXQTOP_TOKEN_MASK (0x3 << 25)
+#define DWC2_GNPTXSTS_NPTXQTOP_TOKEN_OFFSET 25
+#define DWC2_GNPTXSTS_NPTXQTOP_CHNEP_MASK (0xF << 27)
+#define DWC2_GNPTXSTS_NPTXQTOP_CHNEP_OFFSET 27
+#define DWC2_DTXFSTS_TXFSPCAVAIL_MASK (0xFFFF << 0)
+#define DWC2_DTXFSTS_TXFSPCAVAIL_OFFSET 0
+#define DWC2_GI2CCTL_RWDATA_MASK (0xFF << 0)
+#define DWC2_GI2CCTL_RWDATA_OFFSET 0
+#define DWC2_GI2CCTL_REGADDR_MASK (0xFF << 8)
+#define DWC2_GI2CCTL_REGADDR_OFFSET 8
+#define DWC2_GI2CCTL_ADDR_MASK (0x7F << 16)
+#define DWC2_GI2CCTL_ADDR_OFFSET 16
+#define DWC2_GI2CCTL_I2CEN (1 << 23)
+#define DWC2_GI2CCTL_I2CEN_OFFSET 23
+#define DWC2_GI2CCTL_ACK (1 << 24)
+#define DWC2_GI2CCTL_ACK_OFFSET 24
+#define DWC2_GI2CCTL_I2CSUSPCTL (1 << 25)
+#define DWC2_GI2CCTL_I2CSUSPCTL_OFFSET 25
+#define DWC2_GI2CCTL_I2CDEVADDR_MASK (0x3 << 26)
+#define DWC2_GI2CCTL_I2CDEVADDR_OFFSET 26
+#define DWC2_GI2CCTL_RW (1 << 30)
+#define DWC2_GI2CCTL_RW_OFFSET 30
+#define DWC2_GI2CCTL_BSYDNE (1 << 31)
+#define DWC2_GI2CCTL_BSYDNE_OFFSET 31
+#define DWC2_HWCFG1_EP_DIR0_MASK (0x3 << 0)
+#define DWC2_HWCFG1_EP_DIR0_OFFSET 0
+#define DWC2_HWCFG1_EP_DIR1_MASK (0x3 << 2)
+#define DWC2_HWCFG1_EP_DIR1_OFFSET 2
+#define DWC2_HWCFG1_EP_DIR2_MASK (0x3 << 4)
+#define DWC2_HWCFG1_EP_DIR2_OFFSET 4
+#define DWC2_HWCFG1_EP_DIR3_MASK (0x3 << 6)
+#define DWC2_HWCFG1_EP_DIR3_OFFSET 6
+#define DWC2_HWCFG1_EP_DIR4_MASK (0x3 << 8)
+#define DWC2_HWCFG1_EP_DIR4_OFFSET 8
+#define DWC2_HWCFG1_EP_DIR5_MASK (0x3 << 10)
+#define DWC2_HWCFG1_EP_DIR5_OFFSET 10
+#define DWC2_HWCFG1_EP_DIR6_MASK (0x3 << 12)
+#define DWC2_HWCFG1_EP_DIR6_OFFSET 12
+#define DWC2_HWCFG1_EP_DIR7_MASK (0x3 << 14)
+#define DWC2_HWCFG1_EP_DIR7_OFFSET 14
+#define DWC2_HWCFG1_EP_DIR8_MASK (0x3 << 16)
+#define DWC2_HWCFG1_EP_DIR8_OFFSET 16
+#define DWC2_HWCFG1_EP_DIR9_MASK (0x3 << 18)
+#define DWC2_HWCFG1_EP_DIR9_OFFSET 18
+#define DWC2_HWCFG1_EP_DIR10_MASK (0x3 << 20)
+#define DWC2_HWCFG1_EP_DIR10_OFFSET 20
+#define DWC2_HWCFG1_EP_DIR11_MASK (0x3 << 22)
+#define DWC2_HWCFG1_EP_DIR11_OFFSET 22
+#define DWC2_HWCFG1_EP_DIR12_MASK (0x3 << 24)
+#define DWC2_HWCFG1_EP_DIR12_OFFSET 24
+#define DWC2_HWCFG1_EP_DIR13_MASK (0x3 << 26)
+#define DWC2_HWCFG1_EP_DIR13_OFFSET 26
+#define DWC2_HWCFG1_EP_DIR14_MASK (0x3 << 28)
+#define DWC2_HWCFG1_EP_DIR14_OFFSET 28
+#define DWC2_HWCFG1_EP_DIR15_MASK (0x3 << 30)
+#define DWC2_HWCFG1_EP_DIR15_OFFSET 30
+#define DWC2_HWCFG2_OP_MODE_MASK (0x7 << 0)
+#define DWC2_HWCFG2_OP_MODE_OFFSET 0
+#define DWC2_HWCFG2_ARCHITECTURE_SLAVE_ONLY (0x0 << 3)
+#define DWC2_HWCFG2_ARCHITECTURE_EXT_DMA (0x1 << 3)
+#define DWC2_HWCFG2_ARCHITECTURE_INT_DMA (0x2 << 3)
+#define DWC2_HWCFG2_ARCHITECTURE_MASK (0x3 << 3)
+#define DWC2_HWCFG2_ARCHITECTURE_OFFSET 3
+#define DWC2_HWCFG2_POINT2POINT (1 << 5)
+#define DWC2_HWCFG2_POINT2POINT_OFFSET 5
+#define DWC2_HWCFG2_HS_PHY_TYPE_MASK (0x3 << 6)
+#define DWC2_HWCFG2_HS_PHY_TYPE_OFFSET 6
+#define DWC2_HWCFG2_FS_PHY_TYPE_MASK (0x3 << 8)
+#define DWC2_HWCFG2_FS_PHY_TYPE_OFFSET 8
+#define DWC2_HWCFG2_NUM_DEV_EP_MASK (0xF << 10)
+#define DWC2_HWCFG2_NUM_DEV_EP_OFFSET 10
+#define DWC2_HWCFG2_NUM_HOST_CHAN_MASK (0xF << 14)
+#define DWC2_HWCFG2_NUM_HOST_CHAN_OFFSET 14
+#define DWC2_HWCFG2_PERIO_EP_SUPPORTED (1 << 18)
+#define DWC2_HWCFG2_PERIO_EP_SUPPORTED_OFFSET 18
+#define DWC2_HWCFG2_DYNAMIC_FIFO (1 << 19)
+#define DWC2_HWCFG2_DYNAMIC_FIFO_OFFSET 19
+#define DWC2_HWCFG2_MULTI_PROC_INT (1 << 20)
+#define DWC2_HWCFG2_MULTI_PROC_INT_OFFSET 20
+#define DWC2_HWCFG2_NONPERIO_TX_Q_DEPTH_MASK (0x3 << 22)
+#define DWC2_HWCFG2_NONPERIO_TX_Q_DEPTH_OFFSET 22
+#define DWC2_HWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK (0x3 << 24)
+#define DWC2_HWCFG2_HOST_PERIO_TX_Q_DEPTH_OFFSET 24
+#define DWC2_HWCFG2_DEV_TOKEN_Q_DEPTH_MASK (0x1F << 26)
+#define DWC2_HWCFG2_DEV_TOKEN_Q_DEPTH_OFFSET 26
+#define DWC2_HWCFG3_XFER_SIZE_CNTR_WIDTH_MASK (0xF << 0)
+#define DWC2_HWCFG3_XFER_SIZE_CNTR_WIDTH_OFFSET 0
+#define DWC2_HWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK (0x7 << 4)
+#define DWC2_HWCFG3_PACKET_SIZE_CNTR_WIDTH_OFFSET 4
+#define DWC2_HWCFG3_OTG_FUNC (1 << 7)
+#define DWC2_HWCFG3_OTG_FUNC_OFFSET 7
+#define DWC2_HWCFG3_I2C (1 << 8)
+#define DWC2_HWCFG3_I2C_OFFSET 8
+#define DWC2_HWCFG3_VENDOR_CTRL_IF (1 << 9)
+#define DWC2_HWCFG3_VENDOR_CTRL_IF_OFFSET 9
+#define DWC2_HWCFG3_OPTIONAL_FEATURES (1 << 10)
+#define DWC2_HWCFG3_OPTIONAL_FEATURES_OFFSET 10
+#define DWC2_HWCFG3_SYNCH_RESET_TYPE (1 << 11)
+#define DWC2_HWCFG3_SYNCH_RESET_TYPE_OFFSET 11
+#define DWC2_HWCFG3_OTG_ENABLE_IC_USB (1 << 12)
+#define DWC2_HWCFG3_OTG_ENABLE_IC_USB_OFFSET 12
+#define DWC2_HWCFG3_OTG_ENABLE_HSIC (1 << 13)
+#define DWC2_HWCFG3_OTG_ENABLE_HSIC_OFFSET 13
+#define DWC2_HWCFG3_OTG_LPM_EN (1 << 15)
+#define DWC2_HWCFG3_OTG_LPM_EN_OFFSET 15
+#define DWC2_HWCFG3_DFIFO_DEPTH_MASK (0xFFFF << 16)
+#define DWC2_HWCFG3_DFIFO_DEPTH_OFFSET 16
+#define DWC2_HWCFG4_NUM_DEV_PERIO_IN_EP_MASK (0xF << 0)
+#define DWC2_HWCFG4_NUM_DEV_PERIO_IN_EP_OFFSET 0
+#define DWC2_HWCFG4_POWER_OPTIMIZ (1 << 4)
+#define DWC2_HWCFG4_POWER_OPTIMIZ_OFFSET 4
+#define DWC2_HWCFG4_MIN_AHB_FREQ_MASK (0x1FF << 5)
+#define DWC2_HWCFG4_MIN_AHB_FREQ_OFFSET 5
+#define DWC2_HWCFG4_UTMI_PHY_DATA_WIDTH_MASK (0x3 << 14)
+#define DWC2_HWCFG4_UTMI_PHY_DATA_WIDTH_OFFSET 14
+#define DWC2_HWCFG4_NUM_DEV_MODE_CTRL_EP_MASK (0xF << 16)
+#define DWC2_HWCFG4_NUM_DEV_MODE_CTRL_EP_OFFSET 16
+#define DWC2_HWCFG4_IDDIG_FILT_EN (1 << 20)
+#define DWC2_HWCFG4_IDDIG_FILT_EN_OFFSET 20
+#define DWC2_HWCFG4_VBUS_VALID_FILT_EN (1 << 21)
+#define DWC2_HWCFG4_VBUS_VALID_FILT_EN_OFFSET 21
+#define DWC2_HWCFG4_A_VALID_FILT_EN (1 << 22)
+#define DWC2_HWCFG4_A_VALID_FILT_EN_OFFSET 22
+#define DWC2_HWCFG4_B_VALID_FILT_EN (1 << 23)
+#define DWC2_HWCFG4_B_VALID_FILT_EN_OFFSET 23
+#define DWC2_HWCFG4_SESSION_END_FILT_EN (1 << 24)
+#define DWC2_HWCFG4_SESSION_END_FILT_EN_OFFSET 24
+#define DWC2_HWCFG4_DED_FIFO_EN (1 << 25)
+#define DWC2_HWCFG4_DED_FIFO_EN_OFFSET 25
+#define DWC2_HWCFG4_NUM_IN_EPS_MASK (0xF << 26)
+#define DWC2_HWCFG4_NUM_IN_EPS_OFFSET 26
+#define DWC2_HWCFG4_DESC_DMA (1 << 30)
+#define DWC2_HWCFG4_DESC_DMA_OFFSET 30
+#define DWC2_HWCFG4_DESC_DMA_DYN (1 << 31)
+#define DWC2_HWCFG4_DESC_DMA_DYN_OFFSET 31
+#define DWC2_HCFG_FSLSPCLKSEL_30_60_MHZ 0
+#define DWC2_HCFG_FSLSPCLKSEL_48_MHZ 1
+#define DWC2_HCFG_FSLSPCLKSEL_6_MHZ 2
+#define DWC2_HCFG_FSLSPCLKSEL_MASK (0x3 << 0)
+#define DWC2_HCFG_FSLSPCLKSEL_OFFSET 0
+#define DWC2_HCFG_FSLSSUPP (1 << 2)
+#define DWC2_HCFG_FSLSSUPP_OFFSET 2
+#define DWC2_HCFG_DESCDMA (1 << 23)
+#define DWC2_HCFG_DESCDMA_OFFSET 23
+#define DWC2_HCFG_FRLISTEN_MASK (0x3 << 24)
+#define DWC2_HCFG_FRLISTEN_OFFSET 24
+#define DWC2_HCFG_PERSCHEDENA (1 << 26)
+#define DWC2_HCFG_PERSCHEDENA_OFFSET 26
+#define DWC2_HCFG_PERSCHEDSTAT (1 << 27)
+#define DWC2_HCFG_PERSCHEDSTAT_OFFSET 27
+#define DWC2_HFIR_FRINT_MASK (0xFFFF << 0)
+#define DWC2_HFIR_FRINT_OFFSET 0
+#define DWC2_HFNUM_FRNUM_MASK (0xFFFF << 0)
+#define DWC2_HFNUM_FRNUM_OFFSET 0
+#define DWC2_HFNUM_FRREM_MASK (0xFFFF << 16)
+#define DWC2_HFNUM_FRREM_OFFSET 16
+#define DWC2_HFNUM_MAX_FRNUM 0x3FFF
+#define DWC2_HPTXSTS_PTXFSPCAVAIL_MASK (0xFFFF << 0)
+#define DWC2_HPTXSTS_PTXFSPCAVAIL_OFFSET 0
+#define DWC2_HPTXSTS_PTXQSPCAVAIL_MASK (0xFF << 16)
+#define DWC2_HPTXSTS_PTXQSPCAVAIL_OFFSET 16
+#define DWC2_HPTXSTS_PTXQTOP_TERMINATE (1 << 24)
+#define DWC2_HPTXSTS_PTXQTOP_TERMINATE_OFFSET 24
+#define DWC2_HPTXSTS_PTXQTOP_TOKEN_MASK (0x3 << 25)
+#define DWC2_HPTXSTS_PTXQTOP_TOKEN_OFFSET 25
+#define DWC2_HPTXSTS_PTXQTOP_CHNUM_MASK (0xF << 27)
+#define DWC2_HPTXSTS_PTXQTOP_CHNUM_OFFSET 27
+#define DWC2_HPTXSTS_PTXQTOP_ODD (1 << 31)
+#define DWC2_HPTXSTS_PTXQTOP_ODD_OFFSET 31
+#define DWC2_HPRT0_PRTCONNSTS (1 << 0)
+#define DWC2_HPRT0_PRTCONNSTS_OFFSET 0
+#define DWC2_HPRT0_PRTCONNDET (1 << 1)
+#define DWC2_HPRT0_PRTCONNDET_OFFSET 1
+#define DWC2_HPRT0_PRTENA (1 << 2)
+#define DWC2_HPRT0_PRTENA_OFFSET 2
+#define DWC2_HPRT0_PRTENCHNG (1 << 3)
+#define DWC2_HPRT0_PRTENCHNG_OFFSET 3
+#define DWC2_HPRT0_PRTOVRCURRACT (1 << 4)
+#define DWC2_HPRT0_PRTOVRCURRACT_OFFSET 4
+#define DWC2_HPRT0_PRTOVRCURRCHNG (1 << 5)
+#define DWC2_HPRT0_PRTOVRCURRCHNG_OFFSET 5
+#define DWC2_HPRT0_PRTRES (1 << 6)
+#define DWC2_HPRT0_PRTRES_OFFSET 6
+#define DWC2_HPRT0_PRTSUSP (1 << 7)
+#define DWC2_HPRT0_PRTSUSP_OFFSET 7
+#define DWC2_HPRT0_PRTRST (1 << 8)
+#define DWC2_HPRT0_PRTRST_OFFSET 8
+#define DWC2_HPRT0_PRTLNSTS_MASK (0x3 << 10)
+#define DWC2_HPRT0_PRTLNSTS_OFFSET 10
+#define DWC2_HPRT0_PRTPWR (1 << 12)
+#define DWC2_HPRT0_PRTPWR_OFFSET 12
+#define DWC2_HPRT0_PRTTSTCTL_MASK (0xF << 13)
+#define DWC2_HPRT0_PRTTSTCTL_OFFSET 13
+#define DWC2_HPRT0_PRTSPD_HIGH (0 << 17)
+#define DWC2_HPRT0_PRTSPD_FULL (1 << 17)
+#define DWC2_HPRT0_PRTSPD_LOW (2 << 17)
+#define DWC2_HPRT0_PRTSPD_MASK (0x3 << 17)
+#define DWC2_HPRT0_PRTSPD_OFFSET 17
+#define DWC2_HAINT_CH0 (1 << 0)
+#define DWC2_HAINT_CH0_OFFSET 0
+#define DWC2_HAINT_CH1 (1 << 1)
+#define DWC2_HAINT_CH1_OFFSET 1
+#define DWC2_HAINT_CH2 (1 << 2)
+#define DWC2_HAINT_CH2_OFFSET 2
+#define DWC2_HAINT_CH3 (1 << 3)
+#define DWC2_HAINT_CH3_OFFSET 3
+#define DWC2_HAINT_CH4 (1 << 4)
+#define DWC2_HAINT_CH4_OFFSET 4
+#define DWC2_HAINT_CH5 (1 << 5)
+#define DWC2_HAINT_CH5_OFFSET 5
+#define DWC2_HAINT_CH6 (1 << 6)
+#define DWC2_HAINT_CH6_OFFSET 6
+#define DWC2_HAINT_CH7 (1 << 7)
+#define DWC2_HAINT_CH7_OFFSET 7
+#define DWC2_HAINT_CH8 (1 << 8)
+#define DWC2_HAINT_CH8_OFFSET 8
+#define DWC2_HAINT_CH9 (1 << 9)
+#define DWC2_HAINT_CH9_OFFSET 9
+#define DWC2_HAINT_CH10 (1 << 10)
+#define DWC2_HAINT_CH10_OFFSET 10
+#define DWC2_HAINT_CH11 (1 << 11)
+#define DWC2_HAINT_CH11_OFFSET 11
+#define DWC2_HAINT_CH12 (1 << 12)
+#define DWC2_HAINT_CH12_OFFSET 12
+#define DWC2_HAINT_CH13 (1 << 13)
+#define DWC2_HAINT_CH13_OFFSET 13
+#define DWC2_HAINT_CH14 (1 << 14)
+#define DWC2_HAINT_CH14_OFFSET 14
+#define DWC2_HAINT_CH15 (1 << 15)
+#define DWC2_HAINT_CH15_OFFSET 15
+#define DWC2_HAINT_CHINT_MASK 0xffff
+#define DWC2_HAINT_CHINT_OFFSET 0
+#define DWC2_HAINTMSK_CH0 (1 << 0)
+#define DWC2_HAINTMSK_CH0_OFFSET 0
+#define DWC2_HAINTMSK_CH1 (1 << 1)
+#define DWC2_HAINTMSK_CH1_OFFSET 1
+#define DWC2_HAINTMSK_CH2 (1 << 2)
+#define DWC2_HAINTMSK_CH2_OFFSET 2
+#define DWC2_HAINTMSK_CH3 (1 << 3)
+#define DWC2_HAINTMSK_CH3_OFFSET 3
+#define DWC2_HAINTMSK_CH4 (1 << 4)
+#define DWC2_HAINTMSK_CH4_OFFSET 4
+#define DWC2_HAINTMSK_CH5 (1 << 5)
+#define DWC2_HAINTMSK_CH5_OFFSET 5
+#define DWC2_HAINTMSK_CH6 (1 << 6)
+#define DWC2_HAINTMSK_CH6_OFFSET 6
+#define DWC2_HAINTMSK_CH7 (1 << 7)
+#define DWC2_HAINTMSK_CH7_OFFSET 7
+#define DWC2_HAINTMSK_CH8 (1 << 8)
+#define DWC2_HAINTMSK_CH8_OFFSET 8
+#define DWC2_HAINTMSK_CH9 (1 << 9)
+#define DWC2_HAINTMSK_CH9_OFFSET 9
+#define DWC2_HAINTMSK_CH10 (1 << 10)
+#define DWC2_HAINTMSK_CH10_OFFSET 10
+#define DWC2_HAINTMSK_CH11 (1 << 11)
+#define DWC2_HAINTMSK_CH11_OFFSET 11
+#define DWC2_HAINTMSK_CH12 (1 << 12)
+#define DWC2_HAINTMSK_CH12_OFFSET 12
+#define DWC2_HAINTMSK_CH13 (1 << 13)
+#define DWC2_HAINTMSK_CH13_OFFSET 13
+#define DWC2_HAINTMSK_CH14 (1 << 14)
+#define DWC2_HAINTMSK_CH14_OFFSET 14
+#define DWC2_HAINTMSK_CH15 (1 << 15)
+#define DWC2_HAINTMSK_CH15_OFFSET 15
+#define DWC2_HAINTMSK_CHINT_MASK 0xffff
+#define DWC2_HAINTMSK_CHINT_OFFSET 0
+#define DWC2_HCCHAR_MPS_MASK (0x7FF << 0)
+#define DWC2_HCCHAR_MPS_OFFSET 0
+#define DWC2_HCCHAR_EPNUM_MASK (0xF << 11)
+#define DWC2_HCCHAR_EPNUM_OFFSET 11
+#define DWC2_HCCHAR_EPDIR (1 << 15)
+#define DWC2_HCCHAR_EPDIR_OFFSET 15
+#define DWC2_HCCHAR_LSPDDEV (1 << 17)
+#define DWC2_HCCHAR_LSPDDEV_OFFSET 17
+#define DWC2_HCCHAR_EPTYPE_CONTROL 0
+#define DWC2_HCCHAR_EPTYPE_ISOC 1
+#define DWC2_HCCHAR_EPTYPE_BULK 2
+#define DWC2_HCCHAR_EPTYPE_INTR 3
+#define DWC2_HCCHAR_EPTYPE_MASK (0x3 << 18)
+#define DWC2_HCCHAR_EPTYPE_OFFSET 18
+#define DWC2_HCCHAR_MULTICNT_MASK (0x3 << 20)
+#define DWC2_HCCHAR_MULTICNT_OFFSET 20
+#define DWC2_HCCHAR_DEVADDR_MASK (0x7F << 22)
+#define DWC2_HCCHAR_DEVADDR_OFFSET 22
+#define DWC2_HCCHAR_ODDFRM (1 << 29)
+#define DWC2_HCCHAR_ODDFRM_OFFSET 29
+#define DWC2_HCCHAR_CHDIS (1 << 30)
+#define DWC2_HCCHAR_CHDIS_OFFSET 30
+#define DWC2_HCCHAR_CHEN (1 << 31)
+#define DWC2_HCCHAR_CHEN_OFFSET 31
+#define DWC2_HCSPLT_PRTADDR_MASK (0x7F << 0)
+#define DWC2_HCSPLT_PRTADDR_OFFSET 0
+#define DWC2_HCSPLT_HUBADDR_MASK (0x7F << 7)
+#define DWC2_HCSPLT_HUBADDR_OFFSET 7
+#define DWC2_HCSPLT_XACTPOS_MASK (0x3 << 14)
+#define DWC2_HCSPLT_XACTPOS_OFFSET 14
+#define DWC2_HCSPLT_COMPSPLT (1 << 16)
+#define DWC2_HCSPLT_COMPSPLT_OFFSET 16
+#define DWC2_HCSPLT_SPLTENA (1 << 31)
+#define DWC2_HCSPLT_SPLTENA_OFFSET 31
+#define DWC2_HCINT_XFERCOMP (1 << 0)
+#define DWC2_HCINT_XFERCOMP_OFFSET 0
+#define DWC2_HCINT_CHHLTD (1 << 1)
+#define DWC2_HCINT_CHHLTD_OFFSET 1
+#define DWC2_HCINT_AHBERR (1 << 2)
+#define DWC2_HCINT_AHBERR_OFFSET 2
+#define DWC2_HCINT_STALL (1 << 3)
+#define DWC2_HCINT_STALL_OFFSET 3
+#define DWC2_HCINT_NAK (1 << 4)
+#define DWC2_HCINT_NAK_OFFSET 4
+#define DWC2_HCINT_ACK (1 << 5)
+#define DWC2_HCINT_ACK_OFFSET 5
+#define DWC2_HCINT_NYET (1 << 6)
+#define DWC2_HCINT_NYET_OFFSET 6
+#define DWC2_HCINT_XACTERR (1 << 7)
+#define DWC2_HCINT_XACTERR_OFFSET 7
+#define DWC2_HCINT_BBLERR (1 << 8)
+#define DWC2_HCINT_BBLERR_OFFSET 8
+#define DWC2_HCINT_FRMOVRUN (1 << 9)
+#define DWC2_HCINT_FRMOVRUN_OFFSET 9
+#define DWC2_HCINT_DATATGLERR (1 << 10)
+#define DWC2_HCINT_DATATGLERR_OFFSET 10
+#define DWC2_HCINT_BNA (1 << 11)
+#define DWC2_HCINT_BNA_OFFSET 11
+#define DWC2_HCINT_XCS_XACT (1 << 12)
+#define DWC2_HCINT_XCS_XACT_OFFSET 12
+#define DWC2_HCINT_FRM_LIST_ROLL (1 << 13)
+#define DWC2_HCINT_FRM_LIST_ROLL_OFFSET 13
+#define DWC2_HCINTMSK_XFERCOMPL (1 << 0)
+#define DWC2_HCINTMSK_XFERCOMPL_OFFSET 0
+#define DWC2_HCINTMSK_CHHLTD (1 << 1)
+#define DWC2_HCINTMSK_CHHLTD_OFFSET 1
+#define DWC2_HCINTMSK_AHBERR (1 << 2)
+#define DWC2_HCINTMSK_AHBERR_OFFSET 2
+#define DWC2_HCINTMSK_STALL (1 << 3)
+#define DWC2_HCINTMSK_STALL_OFFSET 3
+#define DWC2_HCINTMSK_NAK (1 << 4)
+#define DWC2_HCINTMSK_NAK_OFFSET 4
+#define DWC2_HCINTMSK_ACK (1 << 5)
+#define DWC2_HCINTMSK_ACK_OFFSET 5
+#define DWC2_HCINTMSK_NYET (1 << 6)
+#define DWC2_HCINTMSK_NYET_OFFSET 6
+#define DWC2_HCINTMSK_XACTERR (1 << 7)
+#define DWC2_HCINTMSK_XACTERR_OFFSET 7
+#define DWC2_HCINTMSK_BBLERR (1 << 8)
+#define DWC2_HCINTMSK_BBLERR_OFFSET 8
+#define DWC2_HCINTMSK_FRMOVRUN (1 << 9)
+#define DWC2_HCINTMSK_FRMOVRUN_OFFSET 9
+#define DWC2_HCINTMSK_DATATGLERR (1 << 10)
+#define DWC2_HCINTMSK_DATATGLERR_OFFSET 10
+#define DWC2_HCINTMSK_BNA (1 << 11)
+#define DWC2_HCINTMSK_BNA_OFFSET 11
+#define DWC2_HCINTMSK_XCS_XACT (1 << 12)
+#define DWC2_HCINTMSK_XCS_XACT_OFFSET 12
+#define DWC2_HCINTMSK_FRM_LIST_ROLL (1 << 13)
+#define DWC2_HCINTMSK_FRM_LIST_ROLL_OFFSET 13
+#define DWC2_HCTSIZ_XFERSIZE_MASK 0x7ffff
+#define DWC2_HCTSIZ_XFERSIZE_OFFSET 0
+#define DWC2_HCTSIZ_SCHINFO_MASK 0xff
+#define DWC2_HCTSIZ_SCHINFO_OFFSET 0
+#define DWC2_HCTSIZ_NTD_MASK (0xff << 8)
+#define DWC2_HCTSIZ_NTD_OFFSET 8
+#define DWC2_HCTSIZ_PKTCNT_MASK (0x3ff << 19)
+#define DWC2_HCTSIZ_PKTCNT_OFFSET 19
+#define DWC2_HCTSIZ_PID_MASK (0x3 << 29)
+#define DWC2_HCTSIZ_PID_OFFSET 29
+#define DWC2_HCTSIZ_DOPNG (1 << 31)
+#define DWC2_HCTSIZ_DOPNG_OFFSET 31
+#define DWC2_HCDMA_CTD_MASK (0xFF << 3)
+#define DWC2_HCDMA_CTD_OFFSET 3
+#define DWC2_HCDMA_DMA_ADDR_MASK (0x1FFFFF << 11)
+#define DWC2_HCDMA_DMA_ADDR_OFFSET 11
+#define DWC2_PCGCCTL_STOPPCLK (1 << 0)
+#define DWC2_PCGCCTL_STOPPCLK_OFFSET 0
+#define DWC2_PCGCCTL_GATEHCLK (1 << 1)
+#define DWC2_PCGCCTL_GATEHCLK_OFFSET 1
+#define DWC2_PCGCCTL_PWRCLMP (1 << 2)
+#define DWC2_PCGCCTL_PWRCLMP_OFFSET 2
+#define DWC2_PCGCCTL_RSTPDWNMODULE (1 << 3)
+#define DWC2_PCGCCTL_RSTPDWNMODULE_OFFSET 3
+#define DWC2_PCGCCTL_PHYSUSPENDED (1 << 4)
+#define DWC2_PCGCCTL_PHYSUSPENDED_OFFSET 4
+#define DWC2_PCGCCTL_ENBL_SLEEP_GATING (1 << 5)
+#define DWC2_PCGCCTL_ENBL_SLEEP_GATING_OFFSET 5
+#define DWC2_PCGCCTL_PHY_IN_SLEEP (1 << 6)
+#define DWC2_PCGCCTL_PHY_IN_SLEEP_OFFSET 6
+#define DWC2_PCGCCTL_DEEP_SLEEP (1 << 7)
+#define DWC2_PCGCCTL_DEEP_SLEEP_OFFSET 7
+#define DWC2_SNPSID_DEVID_VER_2xx (0x4f542 << 12)
+#define DWC2_SNPSID_DEVID_VER_3xx (0x4f543 << 12)
+#define DWC2_SNPSID_DEVID_MASK (0xfffff << 12)
+#define DWC2_SNPSID_DEVID_OFFSET 12
+
+/* Host controller specific */
+#define DWC2_HC_PID_DATA0 0
+#define DWC2_HC_PID_DATA2 1
+#define DWC2_HC_PID_DATA1 2
+#define DWC2_HC_PID_MDATA 3
+#define DWC2_HC_PID_SETUP 3
+
+/* roothub.a masks */
+#define RH_A_NDP (0xff << 0) /* number of downstream ports */
+#define RH_A_PSM (1 << 8) /* power switching mode */
+#define RH_A_NPS (1 << 9) /* no power switching */
+#define RH_A_DT (1 << 10) /* device type (mbz) */
+#define RH_A_OCPM (1 << 11) /* over current protection mode */
+#define RH_A_NOCP (1 << 12) /* no over current protection */
+#define RH_A_POTPGT (0xff << 24) /* power on to power good time */
+
+/* roothub.b masks */
+#define RH_B_DR 0x0000ffff /* device removable flags */
+#define RH_B_PPCM 0xffff0000 /* port power control mask */
+
+/* Default driver configuration */
+#define CONFIG_DWC2_MAX_CHANNELS 16 /* Max # of EPs */
+#define CONFIG_DWC2_HOST_RX_FIFO_SIZE (516 + CONFIG_DWC2_MAX_CHANNELS)
+#define CONFIG_DWC2_HOST_NPERIO_TX_FIFO_SIZE 0x100 /* nPeriodic TX FIFO */
+#define CONFIG_DWC2_HOST_PERIO_TX_FIFO_SIZE 0x200 /* Periodic TX FIFO */
+#define CONFIG_DWC2_MAX_TRANSFER_SIZE 65535
+#define CONFIG_DWC2_MAX_PACKET_COUNT 511
+
+#define DWC2_PHY_TYPE_FS 0
+#define DWC2_PHY_TYPE_UTMI 1
+#define DWC2_PHY_TYPE_ULPI 2
+#define CONFIG_DWC2_PHY_TYPE DWC2_PHY_TYPE_UTMI /* PHY type */
+#define CONFIG_DWC2_UTMI_WIDTH 8 /* UTMI bus width (8/16) */
+
+#define CONFIG_DWC2_PHY_ULPI_EXT_VBUS /* ULPI PHY controls VBUS */
+#define CONFIG_DWC2_TX_THR_LENGTH 64
+
+#endif /* __DWC2_H__ */
diff --git a/include/driver.h b/include/driver.h
index ad59ce90c3..74be1b3e8e 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -93,6 +93,8 @@ struct device_d {
u64 dma_mask;
+ unsigned long dma_offset;
+
void (*info) (struct device_d *);
/*
* For devices which take longer to probe this is called
diff --git a/include/of.h b/include/of.h
index f63a3efe13..67601ce80c 100644
--- a/include/of.h
+++ b/include/of.h
@@ -113,7 +113,9 @@ struct device_node *of_unflatten_dtb_const(const void *infdt);
struct cdev;
#ifdef CONFIG_OFTREE
+extern int of_bus_n_addr_cells(struct device_node *np);
extern int of_n_addr_cells(struct device_node *np);
+extern int of_bus_n_size_cells(struct device_node *np);
extern int of_n_size_cells(struct device_node *np);
extern struct property *of_find_property(const struct device_node *np,
@@ -328,11 +330,21 @@ static inline struct device_d *of_platform_device_create(struct device_node *np,
return NULL;
}
+static inline int of_bus_n_addr_cells(struct device_node *np)
+{
+ return 0;
+}
+
static inline int of_n_addr_cells(struct device_node *np)
{
return 0;
}
+static inline int of_bus_n_size_cells(struct device_node *np)
+{
+ return 0;
+}
+
static inline int of_n_size_cells(struct device_node *np)
{
return 0;
diff --git a/include/of_address.h b/include/of_address.h
index ebf3ec2a24..350ecaec82 100644
--- a/include/of_address.h
+++ b/include/of_address.h
@@ -56,6 +56,9 @@ extern struct device_node *of_find_matching_node_by_address(
u64 base_address);
extern void __iomem *of_iomap(struct device_node *np, int index);
+extern int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr,
+ u64 *size);
+
#else /* CONFIG_OFTREE */
static inline u64 of_translate_address(struct device_node *dev,
@@ -99,6 +102,12 @@ static inline void __iomem *of_iomap(struct device_node *np, int index)
return NULL;
}
+static inline int of_dma_get_range(struct device_node *np, u64 *dma_addr,
+ u64 *paddr, u64 *size)
+{
+ return -ENOSYS;
+}
+
#endif /* CONFIG_OFTREE */
#ifdef CONFIG_OF_PCI
diff --git a/include/regulator.h b/include/regulator.h
index 156acb82f8..a445c5c3d1 100644
--- a/include/regulator.h
+++ b/include/regulator.h
@@ -116,6 +116,7 @@ void regulators_print(void);
#ifdef CONFIG_REGULATOR
struct regulator *regulator_get(struct device_d *, const char *);
+struct regulator *regulator_get_name(const char *name);
int regulator_enable(struct regulator *);
int regulator_disable(struct regulator *);
int regulator_is_enabled_regmap(struct regulator_dev *);
diff --git a/include/usb/usb.h b/include/usb/usb.h
index d39de71aff..95dedfd5b7 100644
--- a/include/usb/usb.h
+++ b/include/usb/usb.h
@@ -140,9 +140,9 @@ struct usb_host {
int (*init)(struct usb_host *);
int (*exit)(struct usb_host *);
int (*submit_bulk_msg)(struct usb_device *dev, unsigned long pipe,
- void *buffer, int transfer_len, int timeout);
+ void *buffer, int transfer_len, int timeout_ms);
int (*submit_control_msg)(struct usb_device *dev, unsigned long pipe, void *buffer,
- int transfer_len, struct devrequest *setup, int timeout);
+ int transfer_len, struct devrequest *setup, int timeout_ms);
int (*submit_int_msg)(struct usb_device *dev, unsigned long pipe, void *buffer,
int transfer_len, int interval);
void (*usb_event_poll)(void);
@@ -167,9 +167,9 @@ int usb_set_idle(struct usb_device *dev, int ifnum, int duration,
int usb_control_msg(struct usb_device *dev, unsigned int pipe,
unsigned char request, unsigned char requesttype,
unsigned short value, unsigned short index,
- void *data, unsigned short size, int timeout);
+ void *data, unsigned short size, int timeout_ms);
int usb_bulk_msg(struct usb_device *dev, unsigned int pipe,
- void *data, int len, int *actual_length, int timeout);
+ void *data, int len, int *actual_length, int timeout_ms);
int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe,
void *buffer, int transfer_len, int interval);
int usb_maxpacket(struct usb_device *dev, unsigned long pipe);
diff --git a/include/usb/usbroothubdes.h b/include/usb/usbroothubdes.h
new file mode 100644
index 0000000000..e743555d8e
--- /dev/null
+++ b/include/usb/usbroothubdes.h
@@ -0,0 +1,128 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * USB virtual root hub descriptors
+ *
+ * (C) Copyright 2014
+ * Stephen Warren swarren@wwwdotorg.org
+ *
+ * Based on ohci-hcd.c
+ */
+
+#ifndef __USBROOTHUBDES_H__
+#define __USBROOTHUBDES_H__
+
+/* Device descriptor */
+static __u8 root_hub_dev_des[] = {
+ 0x12, /* __u8 bLength; */
+ 0x01, /* __u8 bDescriptorType; Device */
+ 0x10, /* __u16 bcdUSB; v1.1 */
+ 0x01,
+ 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 bDeviceSubClass; */
+ 0x00, /* __u8 bDeviceProtocol; */
+ 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
+ 0x00, /* __u16 idVendor; */
+ 0x00,
+ 0x00, /* __u16 idProduct; */
+ 0x00,
+ 0x00, /* __u16 bcdDevice; */
+ 0x00,
+ 0x00, /* __u8 iManufacturer; */
+ 0x01, /* __u8 iProduct; */
+ 0x00, /* __u8 iSerialNumber; */
+ 0x01, /* __u8 bNumConfigurations; */
+};
+
+/* Configuration descriptor */
+static __u8 root_hub_config_des[] = {
+ 0x09, /* __u8 bLength; */
+ 0x02, /* __u8 bDescriptorType; Configuration */
+ 0x19, /* __u16 wTotalLength; */
+ 0x00,
+ 0x01, /* __u8 bNumInterfaces; */
+ 0x01, /* __u8 bConfigurationValue; */
+ 0x00, /* __u8 iConfiguration; */
+ 0x40, /* __u8 bmAttributes;
+ * Bit 7: Bus-powered
+ * 6: Self-powered,
+ * 5 Remote-wakwup,
+ * 4..0: resvd
+ */
+ 0x00, /* __u8 MaxPower; */
+ /* interface */
+ 0x09, /* __u8 if_bLength; */
+ 0x04, /* __u8 if_bDescriptorType; Interface */
+ 0x00, /* __u8 if_bInterfaceNumber; */
+ 0x00, /* __u8 if_bAlternateSetting; */
+ 0x01, /* __u8 if_bNumEndpoints; */
+ 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 if_bInterfaceSubClass; */
+ 0x00, /* __u8 if_bInterfaceProtocol; */
+ 0x00, /* __u8 if_iInterface; */
+ /* endpoint */
+ 0x07, /* __u8 ep_bLength; */
+ 0x05, /* __u8 ep_bDescriptorType; Endpoint */
+ 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
+ 0x03, /* __u8 ep_bmAttributes; Interrupt */
+ 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
+ 0x00,
+ 0xff, /* __u8 ep_bInterval; 255 ms */
+};
+
+#ifdef WANT_USB_ROOT_HUB_HUB_DES
+static unsigned char root_hub_hub_des[] = {
+ 0x09, /* __u8 bLength; */
+ 0x29, /* __u8 bDescriptorType; Hub-descriptor */
+ 0x02, /* __u8 bNbrPorts; */
+ 0x00, /* __u16 wHubCharacteristics; */
+ 0x00,
+ 0x01, /* __u8 bPwrOn2pwrGood; 2ms */
+ 0x00, /* __u8 bHubContrCurrent; 0 mA */
+ 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */
+ 0xff, /* __u8 PortPwrCtrlMask; *** 7 ports max *** */
+};
+#endif
+
+static unsigned char root_hub_str_index0[] = {
+ 0x04, /* __u8 bLength; */
+ 0x03, /* __u8 bDescriptorType; String-descriptor */
+ 0x09, /* __u8 lang ID */
+ 0x04, /* __u8 lang ID */
+};
+
+static unsigned char root_hub_str_index1[] = {
+ 32, /* __u8 bLength; */
+ 0x03, /* __u8 bDescriptorType; String-descriptor */
+ 'U', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ '-', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'B', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'o', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'o', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 't', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ ' ', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'R', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'o', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'o', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 't', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ ' ', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'H', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'u', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'b', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+};
+
+#endif