summaryrefslogtreecommitdiffstats
path: root/configs
diff options
context:
space:
mode:
Diffstat (limited to 'configs')
-rw-r--r--configs/platform-v7a/barebox-am335x-mlo.config2
-rw-r--r--configs/platform-v7a/barebox-am335x.config3
-rw-r--r--configs/platform-v7a/barebox-am335x.config.diff3
-rw-r--r--configs/platform-v7a/barebox-mx6.config3
-rw-r--r--configs/platform-v7a/barebox-mx6.config.diff3
-rw-r--r--configs/platform-v7a/barebox-rpi2.config2
-rw-r--r--configs/platform-v7a/barebox-rpi2.config.diff2
-rw-r--r--configs/platform-v7a/barebox-vexpress.config3
-rw-r--r--configs/platform-v7a/barebox-vexpress.config.diff3
-rw-r--r--configs/platform-v7a/barebox.config4
-rw-r--r--configs/platform-v7a/patches/barebox-2019.12.0/0001-ARM-rpi-Do-not-warn-when-firmware-doesn-t-pass-a-dtb.patch59
-rw-r--r--configs/platform-v7a/patches/barebox-2019.12.0/0002-usb-Make-timeout-unit-clear.patch81
-rw-r--r--configs/platform-v7a/patches/barebox-2019.12.0/0003-of-Add-of_bus_n_xxx_cells.patch117
-rw-r--r--configs/platform-v7a/patches/barebox-2019.12.0/0004-device-Introduce-dma_offset.patch126
-rw-r--r--configs/platform-v7a/patches/barebox-2019.12.0/0005-of-Read-dma_offset-from-device-tree.patch203
-rw-r--r--configs/platform-v7a/patches/barebox-2019.12.0/0006-usb-Add-usbroothubdes.h.patch146
-rw-r--r--configs/platform-v7a/patches/barebox-2019.12.0/0007-regulator-add-function-to-get-regulator-by-its-name.patch73
-rw-r--r--configs/platform-v7a/patches/barebox-2019.12.0/0008-rpi-Enable-USB-Power-domain-during-startup.patch47
-rw-r--r--configs/platform-v7a/patches/barebox-2019.12.0/0009-usb-Forward-error-code-from-usb_set_configuration.patch40
-rw-r--r--configs/platform-v7a/patches/barebox-2019.12.0/0010-usb-Add-dwc2-host-driver.patch1964
-rw-r--r--configs/platform-v7a/patches/barebox-2019.12.0/0011-ARM-bcm2835-mbox-Remove-response-valid-check.patch29
-rw-r--r--configs/platform-v7a/patches/barebox-2019.12.0/0012-gpio-Add-raspberrypi-exp-gpio-driver.patch335
-rw-r--r--configs/platform-v7a/patches/barebox-2019.12.0/0013-ARM-bcm2835-mbox-use-pr_-to-print-messages.patch137
-rw-r--r--configs/platform-v7a/patches/barebox-2019.12.0/0014-ARM-rpi_defconfig-Enable-raspberry-GPIO-exp-driver.patch23
-rw-r--r--configs/platform-v7a/patches/barebox-2019.12.0/0015-ARM-rpi-mailbox-Use-non-interruptible-timeout.patch47
-rw-r--r--configs/platform-v7a/patches/barebox-2019.12.0/0016-ARM-rpi_defconfig-Enable-more-features.patch109
-rw-r--r--configs/platform-v7a/patches/barebox-2019.12.0/0101-Release-2019.12.0-customers-pengutronix-distrokit-v7.patch22
-rw-r--r--configs/platform-v7a/patches/barebox-2019.12.0/series26
28 files changed, 3602 insertions, 10 deletions
diff --git a/configs/platform-v7a/barebox-am335x-mlo.config b/configs/platform-v7a/barebox-am335x-mlo.config
index 61a8a0c..ac33598 100644
--- a/configs/platform-v7a/barebox-am335x-mlo.config
+++ b/configs/platform-v7a/barebox-am335x-mlo.config
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Barebox/arm 2019.12.0 Configuration
+# Barebox/arm 2019.12.0-20200108-1 Configuration
#
CONFIG_ARM=y
CONFIG_ARM_USE_COMPRESSED_DTB=y
diff --git a/configs/platform-v7a/barebox-am335x.config b/configs/platform-v7a/barebox-am335x.config
index 4dc6216..ed52e1c 100644
--- a/configs/platform-v7a/barebox-am335x.config
+++ b/configs/platform-v7a/barebox-am335x.config
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Barebox/arm 2019.12.0 Configuration
+# Barebox/arm 2019.12.0-20200108-1 Configuration
#
CONFIG_ARM=y
CONFIG_ARM_LINUX=y
@@ -579,6 +579,7 @@ CONFIG_USB=y
CONFIG_USB_HOST=y
# CONFIG_USB_DWC3 is not set
CONFIG_USB_EHCI=y
+# CONFIG_USB_DWC2_HOST is not set
# CONFIG_USB_XHCI is not set
# CONFIG_USB_ULPI is not set
CONFIG_USB_STORAGE=y
diff --git a/configs/platform-v7a/barebox-am335x.config.diff b/configs/platform-v7a/barebox-am335x.config.diff
index c05292f..e2c1823 100644
--- a/configs/platform-v7a/barebox-am335x.config.diff
+++ b/configs/platform-v7a/barebox-am335x.config.diff
@@ -1,4 +1,4 @@
-6740c59d874d4e8459025d536717c542
+f04efdb7bd2dd288fed0cb3cb5c307cd
# CONFIG_AM33XX_NET_BOOT is not set
CONFIG_ARCH_AM33XX=y
# CONFIG_ARCH_BCM283X is not set
@@ -41,6 +41,7 @@ CONFIG_EEPROM_AT24=y
CONFIG_GPIO_GENERIC=y
CONFIG_GPIO_GENERIC_PLATFORM=y
CONFIG_GPIO_OMAP=y
+# CONFIG_GPIO_RASPBERRYPI_EXP is undefined
# CONFIG_GREGORIAN_CALENDER is undefined
# CONFIG_HAVE_CLK is undefined
# CONFIG_I2C_MV64XXX is undefined
diff --git a/configs/platform-v7a/barebox-mx6.config b/configs/platform-v7a/barebox-mx6.config
index 5926735..4bf336f 100644
--- a/configs/platform-v7a/barebox-mx6.config
+++ b/configs/platform-v7a/barebox-mx6.config
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Barebox/arm 2019.12.0 Configuration
+# Barebox/arm 2019.12.0-20200108-1 Configuration
#
CONFIG_ARM=y
CONFIG_ARM_LINUX=y
@@ -665,6 +665,7 @@ CONFIG_USB_IMX_CHIPIDEA=y
CONFIG_USB_IMX_PHY=y
# CONFIG_USB_DWC3 is not set
CONFIG_USB_EHCI=y
+# CONFIG_USB_DWC2_HOST is not set
# CONFIG_USB_XHCI is not set
CONFIG_USB_ULPI=y
CONFIG_USB_STORAGE=y
diff --git a/configs/platform-v7a/barebox-mx6.config.diff b/configs/platform-v7a/barebox-mx6.config.diff
index 29c1c48..5c66e25 100644
--- a/configs/platform-v7a/barebox-mx6.config.diff
+++ b/configs/platform-v7a/barebox-mx6.config.diff
@@ -1,4 +1,4 @@
-6740c59d874d4e8459025d536717c542
+f04efdb7bd2dd288fed0cb3cb5c307cd
# CONFIG_ARCH_BCM283X is not set
CONFIG_ARCH_HAS_FEC_IMX=y
CONFIG_ARCH_HAS_IMX_GPT=y
@@ -67,6 +67,7 @@ CONFIG_FS_UBIFS_COMPRESSION_LZO=y
# CONFIG_FS_UBIFS_COMPRESSION_ZLIB is not set
CONFIG_GENERIC_PHY=y
CONFIG_GPIO_IMX=y
+# CONFIG_GPIO_RASPBERRYPI_EXP is undefined
# CONFIG_HABV4 is not set
# CONFIG_HWRNG is not set
CONFIG_HW_HAS_PCI=y
diff --git a/configs/platform-v7a/barebox-rpi2.config b/configs/platform-v7a/barebox-rpi2.config
index fd3e220..400cd3d 100644
--- a/configs/platform-v7a/barebox-rpi2.config
+++ b/configs/platform-v7a/barebox-rpi2.config
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Barebox/arm 2019.12.0 Configuration
+# Barebox/arm 2019.12.0-20200108-1 Configuration
#
CONFIG_ARM=y
CONFIG_ARM_LINUX=y
diff --git a/configs/platform-v7a/barebox-rpi2.config.diff b/configs/platform-v7a/barebox-rpi2.config.diff
index f493e1d..84cfd0d 100644
--- a/configs/platform-v7a/barebox-rpi2.config.diff
+++ b/configs/platform-v7a/barebox-rpi2.config.diff
@@ -1,4 +1,4 @@
-6740c59d874d4e8459025d536717c542
+f04efdb7bd2dd288fed0cb3cb5c307cd
CONFIG_ARM_ASM_UNIFIED=y
CONFIG_BOOTM_INITRD=y
# CONFIG_CMD_I2C is undefined
diff --git a/configs/platform-v7a/barebox-vexpress.config b/configs/platform-v7a/barebox-vexpress.config
index 617fb2c..66f98b4 100644
--- a/configs/platform-v7a/barebox-vexpress.config
+++ b/configs/platform-v7a/barebox-vexpress.config
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Barebox/arm 2019.12.0 Configuration
+# Barebox/arm 2019.12.0-20200108-1 Configuration
#
CONFIG_ARM=y
CONFIG_ARM_LINUX=y
@@ -533,6 +533,7 @@ CONFIG_USB=y
CONFIG_USB_HOST=y
# CONFIG_USB_DWC3 is not set
CONFIG_USB_EHCI=y
+# CONFIG_USB_DWC2_HOST is not set
# CONFIG_USB_XHCI is not set
# CONFIG_USB_ULPI is not set
CONFIG_USB_STORAGE=y
diff --git a/configs/platform-v7a/barebox-vexpress.config.diff b/configs/platform-v7a/barebox-vexpress.config.diff
index 840a44d..294201d 100644
--- a/configs/platform-v7a/barebox-vexpress.config.diff
+++ b/configs/platform-v7a/barebox-vexpress.config.diff
@@ -1,4 +1,4 @@
-6740c59d874d4e8459025d536717c542
+f04efdb7bd2dd288fed0cb3cb5c307cd
CONFIG_AMBA_SP804=y
# CONFIG_ARCH_BCM283X is not set
CONFIG_ARCH_VEXPRESS=y
@@ -29,6 +29,7 @@ CONFIG_DRIVER_NET_SMC911X=y
# CONFIG_GPIO_PCA953X is undefined
# CONFIG_GPIO_PCF857X is undefined
# CONFIG_GPIO_PL061 is undefined
+# CONFIG_GPIO_RASPBERRYPI_EXP is undefined
# CONFIG_GPIO_SX150X is undefined
# CONFIG_I2C_ALGOBIT is undefined
# CONFIG_I2C_GPIO is undefined
diff --git a/configs/platform-v7a/barebox.config b/configs/platform-v7a/barebox.config
index 4e0d31e..ea81861 100644
--- a/configs/platform-v7a/barebox.config
+++ b/configs/platform-v7a/barebox.config
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Barebox/arm 2019.12.0 Configuration
+# Barebox/arm 2019.12.0-20200108-1 Configuration
#
CONFIG_ARM=y
CONFIG_ARM_LINUX=y
@@ -545,6 +545,7 @@ CONFIG_USB=y
CONFIG_USB_HOST=y
# CONFIG_USB_DWC3 is not set
CONFIG_USB_EHCI=y
+# CONFIG_USB_DWC2_HOST is not set
# CONFIG_USB_XHCI is not set
# CONFIG_USB_ULPI is not set
CONFIG_USB_STORAGE=y
@@ -671,6 +672,7 @@ CONFIG_GPIOLIB=y
# CONFIG_GPIO_PCA953X is not set
# CONFIG_GPIO_PCF857X is not set
# CONFIG_GPIO_PL061 is not set
+# CONFIG_GPIO_RASPBERRYPI_EXP is not set
# CONFIG_GPIO_DESIGNWARE is not set
# CONFIG_GPIO_SX150X is not set
# end of GPIO
diff --git a/configs/platform-v7a/patches/barebox-2019.12.0/0001-ARM-rpi-Do-not-warn-when-firmware-doesn-t-pass-a-dtb.patch b/configs/platform-v7a/patches/barebox-2019.12.0/0001-ARM-rpi-Do-not-warn-when-firmware-doesn-t-pass-a-dtb.patch
new file mode 100644
index 0000000..54cc301
--- /dev/null
+++ b/configs/platform-v7a/patches/barebox-2019.12.0/0001-ARM-rpi-Do-not-warn-when-firmware-doesn-t-pass-a-dtb.patch
@@ -0,0 +1,59 @@
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 18 Dec 2019 14:55:15 +0100
+Subject: [PATCH] ARM: rpi: Do not warn when firmware doesn't pass a dtb
+
+When there is no dtb placed in the boot partition then none is passed by
+the firmware to barebox. This may be intended, so do not warn about it.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ arch/arm/boards/raspberry-pi/lowlevel.c | 9 ++++++++-
+ arch/arm/boards/raspberry-pi/rpi-common.c | 11 +++++++----
+ 2 files changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/arch/arm/boards/raspberry-pi/lowlevel.c b/arch/arm/boards/raspberry-pi/lowlevel.c
+index 70f1936522e2..d58beb605255 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 dd6bbd5bdd9c..acb26f6a6491 100644
+--- a/arch/arm/boards/raspberry-pi/rpi-common.c
++++ b/arch/arm/boards/raspberry-pi/rpi-common.c
+@@ -433,13 +433,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;
+ }
+
diff --git a/configs/platform-v7a/patches/barebox-2019.12.0/0002-usb-Make-timeout-unit-clear.patch b/configs/platform-v7a/patches/barebox-2019.12.0/0002-usb-Make-timeout-unit-clear.patch
new file mode 100644
index 0000000..9fab21f
--- /dev/null
+++ b/configs/platform-v7a/patches/barebox-2019.12.0/0002-usb-Make-timeout-unit-clear.patch
@@ -0,0 +1,81 @@
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Fri, 20 Dec 2019 09:33:43 +0100
+Subject: [PATCH] usb: Make timeout unit clear
+
+The usb_*_msg() functions take a timeout parameter. Make clear which
+unit is expected by adding a _ms suffix to the variable name.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/usb/core/usb.c | 8 ++++----
+ include/usb/usb.h | 8 ++++----
+ 2 files changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index d29cd1328bbb..ad3bacf23655 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -593,7 +593,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 +615,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 +631,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 +644,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/include/usb/usb.h b/include/usb/usb.h
+index 0045608d6446..a9714ec28992 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/configs/platform-v7a/patches/barebox-2019.12.0/0003-of-Add-of_bus_n_xxx_cells.patch b/configs/platform-v7a/patches/barebox-2019.12.0/0003-of-Add-of_bus_n_xxx_cells.patch
new file mode 100644
index 0000000..8bc5926
--- /dev/null
+++ b/configs/platform-v7a/patches/barebox-2019.12.0/0003-of-Add-of_bus_n_xxx_cells.patch
@@ -0,0 +1,117 @@
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Fri, 20 Dec 2019 12:27:02 +0100
+Subject: [PATCH] of: Add of_bus_n_xxx_cells()
+
+Added straight from the Kernel.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/of/base.c | 46 ++++++++++++++++++++++++++++------------------
+ include/of.h | 12 ++++++++++++
+ 2 files changed, 40 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/of/base.c b/drivers/of/base.c
+index 98ef5fc0d421..e1d3707d01ee 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/include/of.h b/include/of.h
+index 98ddf795cbb4..fb49f40c12a0 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,
+@@ -330,11 +332,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/configs/platform-v7a/patches/barebox-2019.12.0/0004-device-Introduce-dma_offset.patch b/configs/platform-v7a/patches/barebox-2019.12.0/0004-device-Introduce-dma_offset.patch
new file mode 100644
index 0000000..d4d850a
--- /dev/null
+++ b/configs/platform-v7a/patches/barebox-2019.12.0/0004-device-Introduce-dma_offset.patch
@@ -0,0 +1,126 @@
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Fri, 20 Dec 2019 12:29:03 +0100
+Subject: [PATCH] device: Introduce dma_offset
+
+For devices that do not have a 1:1 mapping between DMA and CPU we need a
+dma_offset. This adds dma_offset to struct device_d and starts honoring
+it in ARM dma_(un)map_single(). Also we add some comments to functions
+that would normally need a device argument to make the DMA <-> CPU
+translations device specific.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ arch/arm/cpu/mmu-common.c | 33 +++++++++++++++++++++++++++++++--
+ arch/arm/cpu/mmu.c | 4 ++++
+ arch/arm/cpu/mmu_64.c | 4 ++++
+ include/driver.h | 2 ++
+ 4 files changed, 41 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/cpu/mmu-common.c b/arch/arm/cpu/mmu-common.c
+index aeefbb2daaa1..287622b20399 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 158b130b5765..1f97c28ec657 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 b45a69661e22..1851fdd1a70a 100644
+--- a/arch/arm/cpu/mmu_64.c
++++ b/arch/arm/cpu/mmu_64.c
+@@ -244,6 +244,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/include/driver.h b/include/driver.h
+index 300603fa3277..5ea3a862f2f0 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/configs/platform-v7a/patches/barebox-2019.12.0/0005-of-Read-dma_offset-from-device-tree.patch b/configs/platform-v7a/patches/barebox-2019.12.0/0005-of-Read-dma_offset-from-device-tree.patch
new file mode 100644
index 0000000..d46d44b
--- /dev/null
+++ b/configs/platform-v7a/patches/barebox-2019.12.0/0005-of-Read-dma_offset-from-device-tree.patch
@@ -0,0 +1,203 @@
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Fri, 20 Dec 2019 12:32:23 +0100
+Subject: [PATCH] of: Read dma_offset from device tree
+
+This reads the dma-ranges property from the device tree and sets
+dma_offset in the devices accordingly. The code is mostly taken
+from the Kernel as of v5.5-rc1. of_dma_configure() is trimmed down
+to the cases we want to support currently.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/of/address.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ drivers/of/platform.c | 18 +++++++++
+ include/of_address.h | 9 +++++
+ 3 files changed, 136 insertions(+)
+
+diff --git a/drivers/of/address.c b/drivers/of/address.c
+index 4e12522a0a75..2020f5b7b1ed 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/platform.c b/drivers/of/platform.c
+index d3795d799a13..b1a7eb673064 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/include/of_address.h b/include/of_address.h
+index ebf3ec2a2423..350ecaec827a 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/configs/platform-v7a/patches/barebox-2019.12.0/0006-usb-Add-usbroothubdes.h.patch b/configs/platform-v7a/patches/barebox-2019.12.0/0006-usb-Add-usbroothubdes.h.patch
new file mode 100644
index 0000000..331e7de
--- /dev/null
+++ b/configs/platform-v7a/patches/barebox-2019.12.0/0006-usb-Add-usbroothubdes.h.patch
@@ -0,0 +1,146 @@
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Thu, 19 Dec 2019 12:04:01 +0100
+Subject: [PATCH] usb: Add usbroothubdes.h
+
+Taken from U-Boot, needed for the upcoming dwc2 driver.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ include/usb/usbroothubdes.h | 128 ++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 128 insertions(+)
+ create mode 100644 include/usb/usbroothubdes.h
+
+diff --git a/include/usb/usbroothubdes.h b/include/usb/usbroothubdes.h
+new file mode 100644
+index 000000000000..e743555d8e05
+--- /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
diff --git a/configs/platform-v7a/patches/barebox-2019.12.0/0007-regulator-add-function-to-get-regulator-by-its-name.patch b/configs/platform-v7a/patches/barebox-2019.12.0/0007-regulator-add-function-to-get-regulator-by-its-name.patch
new file mode 100644
index 0000000..0ccafda
--- /dev/null
+++ b/configs/platform-v7a/patches/barebox-2019.12.0/0007-regulator-add-function-to-get-regulator-by-its-name.patch
@@ -0,0 +1,73 @@
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Thu, 19 Dec 2019 19:27:58 +0100
+Subject: [PATCH] regulator: add function to get regulator by its name
+
+Useful for getting regulators that are not correctly associated with a
+device.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/regulator/core.c | 30 +++++++++++++++++++++++++++++-
+ include/regulator.h | 1 +
+ 2 files changed, 30 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
+index 4ca035ae9476..f0de7a52e391 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/include/regulator.h b/include/regulator.h
+index 156acb82f8df..a445c5c3d10a 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/configs/platform-v7a/patches/barebox-2019.12.0/0008-rpi-Enable-USB-Power-domain-during-startup.patch b/configs/platform-v7a/patches/barebox-2019.12.0/0008-rpi-Enable-USB-Power-domain-during-startup.patch
new file mode 100644
index 0000000..a30e632
--- /dev/null
+++ b/configs/platform-v7a/patches/barebox-2019.12.0/0008-rpi-Enable-USB-Power-domain-during-startup.patch
@@ -0,0 +1,47 @@
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Thu, 19 Dec 2019 19:28:36 +0100
+Subject: [PATCH] rpi: Enable USB Power domain during startup
+
+Enable the USB Power domain during startup. The power domain is
+abstracted as a regulator in barebox, but modelled as a power domain in
+the device tree. Until this is sorted out just enable the power domain
+or regulator in the board code.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ arch/arm/boards/raspberry-pi/rpi-common.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/arch/arm/boards/raspberry-pi/rpi-common.c b/arch/arm/boards/raspberry-pi/rpi-common.c
+index acb26f6a6491..45961b52eeaa 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>
+@@ -462,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/configs/platform-v7a/patches/barebox-2019.12.0/0009-usb-Forward-error-code-from-usb_set_configuration.patch b/configs/platform-v7a/patches/barebox-2019.12.0/0009-usb-Forward-error-code-from-usb_set_configuration.patch
new file mode 100644
index 0000000..ceef0eb
--- /dev/null
+++ b/configs/platform-v7a/patches/barebox-2019.12.0/0009-usb-Forward-error-code-from-usb_set_configuration.patch
@@ -0,0 +1,40 @@
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Thu, 19 Dec 2019 19:30:15 +0100
+Subject: [PATCH] usb: Forward error code from usb_set_configuration
+
+Instead of returning -1 forward the error code and take the opportunity
+to print the error string.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/usb/core/usb.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index ad3bacf23655..1c3dcb79a847 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",
diff --git a/configs/platform-v7a/patches/barebox-2019.12.0/0010-usb-Add-dwc2-host-driver.patch b/configs/platform-v7a/patches/barebox-2019.12.0/0010-usb-Add-dwc2-host-driver.patch
new file mode 100644
index 0000000..43a6146
--- /dev/null
+++ b/configs/platform-v7a/patches/barebox-2019.12.0/0010-usb-Add-dwc2-host-driver.patch
@@ -0,0 +1,1964 @@
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Thu, 19 Dec 2019 07:21:20 +0100
+Subject: [PATCH] usb: Add dwc2 host driver
+
+This adds a driver for the dwc2 controller in host mode. The driver is
+taken from U-Boot-2019.10 and tested on a Raspberry Pi 3.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/usb/host/Kconfig | 3 +
+ drivers/usb/host/Makefile | 1 +
+ drivers/usb/host/dwc2.c | 1132 +++++++++++++++++++++++++++++++++++++++++++++
+ drivers/usb/host/dwc2.h | 778 +++++++++++++++++++++++++++++++
+ 4 files changed, 1914 insertions(+)
+ create mode 100644 drivers/usb/host/dwc2.c
+ create mode 100644 drivers/usb/host/dwc2.h
+
+diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
+index d2029bc7d729..b0f32faee998 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 0478d342720d..fa042e9a5423 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 000000000000..1df114968687
+--- /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 000000000000..bdf338f1edff
+--- /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/configs/platform-v7a/patches/barebox-2019.12.0/0011-ARM-bcm2835-mbox-Remove-response-valid-check.patch b/configs/platform-v7a/patches/barebox-2019.12.0/0011-ARM-bcm2835-mbox-Remove-response-valid-check.patch
new file mode 100644
index 0000000..3bcf32d
--- /dev/null
+++ b/configs/platform-v7a/patches/barebox-2019.12.0/0011-ARM-bcm2835-mbox-Remove-response-valid-check.patch
@@ -0,0 +1,29 @@
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Tue, 7 Jan 2020 10:45:35 +0100
+Subject: [PATCH] ARM: bcm2835 mbox: Remove response valid check
+
+Not all messages return a valid response as they do not send a response
+at all. This is at least true for the SET_GPIO_STATE and SET_GPIO_CONFIG
+messages.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ arch/arm/mach-bcm283x/mbox.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+diff --git a/arch/arm/mach-bcm283x/mbox.c b/arch/arm/mach-bcm283x/mbox.c
+index b295993359fa..4405efaffd39 100644
+--- a/arch/arm/mach-bcm283x/mbox.c
++++ b/arch/arm/mach-bcm283x/mbox.c
+@@ -137,11 +137,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/configs/platform-v7a/patches/barebox-2019.12.0/0012-gpio-Add-raspberrypi-exp-gpio-driver.patch b/configs/platform-v7a/patches/barebox-2019.12.0/0012-gpio-Add-raspberrypi-exp-gpio-driver.patch
new file mode 100644
index 0000000..dcfc4c2
--- /dev/null
+++ b/configs/platform-v7a/patches/barebox-2019.12.0/0012-gpio-Add-raspberrypi-exp-gpio-driver.patch
@@ -0,0 +1,335 @@
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Tue, 7 Jan 2020 10:55:11 +0100
+Subject: [PATCH] gpio: Add raspberrypi exp gpio driver
+
+Taken from the kernel adopted to barebox.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ arch/arm/mach-bcm283x/include/mach/mbox.h | 4 +
+ drivers/gpio/Kconfig | 7 +
+ drivers/gpio/Makefile | 1 +
+ drivers/gpio/gpio-raspberrypi-exp.c | 272 ++++++++++++++++++++++++++++++
+ 4 files changed, 284 insertions(+)
+ create mode 100644 drivers/gpio/gpio-raspberrypi-exp.c
+
+diff --git a/arch/arm/mach-bcm283x/include/mach/mbox.h b/arch/arm/mach-bcm283x/include/mach/mbox.h
+index 6db961b8076b..f10f5bc14844 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/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
+index 0f924d135f0e..7e4fc90d3934 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 bc5c500e4d27..77dcf58f640d 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 000000000000..0713e3ca5fb6
+--- /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/configs/platform-v7a/patches/barebox-2019.12.0/0013-ARM-bcm2835-mbox-use-pr_-to-print-messages.patch b/configs/platform-v7a/patches/barebox-2019.12.0/0013-ARM-bcm2835-mbox-use-pr_-to-print-messages.patch
new file mode 100644
index 0000000..f9a34d1
--- /dev/null
+++ b/configs/platform-v7a/patches/barebox-2019.12.0/0013-ARM-bcm2835-mbox-use-pr_-to-print-messages.patch
@@ -0,0 +1,137 @@
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Tue, 7 Jan 2020 10:57:32 +0100
+Subject: [PATCH] ARM: bcm2835 mbox: use pr_* to print messages
+
+To give the user an idea where the messages come from.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ arch/arm/mach-bcm283x/mbox.c | 36 +++++++++++++++++++-----------------
+ 1 file changed, 19 insertions(+), 17 deletions(-)
+
+diff --git a/arch/arm/mach-bcm283x/mbox.c b/arch/arm/mach-bcm283x/mbox.c
+index 4405efaffd39..1b1981f7cb67 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;
+ }
+
+@@ -36,7 +38,7 @@ static int bcm2835_mbox_call_raw(u32 chan, struct bcm2835_mbox_hdr *buffer,
+ if (val & BCM2835_MBOX_STATUS_RD_EMPTY)
+ break;
+ if (is_timeout(starttime, TIMEOUT)) {
+- printf("mbox: Timeout draining stale responses\n");
++ pr_err("mbox: Timeout draining stale responses\n");
+ return -ETIMEDOUT;
+ }
+ val = readl(mbox_base + MAIL0_RD);
+@@ -48,14 +50,14 @@ static int bcm2835_mbox_call_raw(u32 chan, struct bcm2835_mbox_hdr *buffer,
+ if (!(val & BCM2835_MBOX_STATUS_WR_FULL))
+ break;
+ if (is_timeout(starttime, TIMEOUT)) {
+- printf("mbox: Timeout waiting for send space\n");
++ 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);
+@@ -66,20 +68,20 @@ static int bcm2835_mbox_call_raw(u32 chan, struct bcm2835_mbox_hdr *buffer,
+ if (!(val & BCM2835_MBOX_STATUS_RD_EMPTY))
+ break;
+ if (is_timeout(starttime, TIMEOUT)) {
+- printf("mbox: Timeout waiting for response\n");
++ 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;
+ }
+
diff --git a/configs/platform-v7a/patches/barebox-2019.12.0/0014-ARM-rpi_defconfig-Enable-raspberry-GPIO-exp-driver.patch b/configs/platform-v7a/patches/barebox-2019.12.0/0014-ARM-rpi_defconfig-Enable-raspberry-GPIO-exp-driver.patch
new file mode 100644
index 0000000..5fc5645
--- /dev/null
+++ b/configs/platform-v7a/patches/barebox-2019.12.0/0014-ARM-rpi_defconfig-Enable-raspberry-GPIO-exp-driver.patch
@@ -0,0 +1,23 @@
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Tue, 7 Jan 2020 10:58:37 +0100
+Subject: [PATCH] ARM: rpi_defconfig: Enable raspberry GPIO exp driver
+
+Enable the recently introduced GPIO exp driver.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ arch/arm/configs/rpi_defconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm/configs/rpi_defconfig b/arch/arm/configs/rpi_defconfig
+index 0ae0c42b12d7..3813b837dd35 100644
+--- a/arch/arm/configs/rpi_defconfig
++++ b/arch/arm/configs/rpi_defconfig
+@@ -72,6 +72,7 @@ CONFIG_LED_GPIO=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
diff --git a/configs/platform-v7a/patches/barebox-2019.12.0/0015-ARM-rpi-mailbox-Use-non-interruptible-timeout.patch b/configs/platform-v7a/patches/barebox-2019.12.0/0015-ARM-rpi-mailbox-Use-non-interruptible-timeout.patch
new file mode 100644
index 0000000..88a7c53
--- /dev/null
+++ b/configs/platform-v7a/patches/barebox-2019.12.0/0015-ARM-rpi-mailbox-Use-non-interruptible-timeout.patch
@@ -0,0 +1,47 @@
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 8 Jan 2020 10:29:16 +0100
+Subject: [PATCH] ARM: rpi mailbox: Use non interruptible timeout
+
+This makes sure that during a mailbox transfer no other mailbox transfer
+is started. This happens on a raspberrypi3 where one GPIO on the
+firmware GPIO controller (which is controlled via mailbox) is registered
+as a heartbeat LED. With this it can happen that during a mailbox
+transfer the poller which drives the heartbeat LED is triggered in
+is_timeout() which results in corrupted transfers.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ arch/arm/mach-bcm283x/mbox.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/mach-bcm283x/mbox.c b/arch/arm/mach-bcm283x/mbox.c
+index 1b1981f7cb67..22abbb0ca586 100644
+--- a/arch/arm/mach-bcm283x/mbox.c
++++ b/arch/arm/mach-bcm283x/mbox.c
+@@ -37,7 +37,7 @@ 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)) {
++ if (is_timeout_non_interruptible(starttime, TIMEOUT)) {
+ pr_err("mbox: Timeout draining stale responses\n");
+ return -ETIMEDOUT;
+ }
+@@ -49,7 +49,7 @@ 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)) {
++ if (is_timeout_non_interruptible(starttime, TIMEOUT)) {
+ pr_err("mbox: Timeout waiting for send space\n");
+ return -ETIMEDOUT;
+ }
+@@ -67,7 +67,7 @@ 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)) {
++ if (is_timeout_non_interruptible(starttime, TIMEOUT)) {
+ pr_err("mbox: Timeout waiting for response\n");
+ return -ETIMEDOUT;
+ }
diff --git a/configs/platform-v7a/patches/barebox-2019.12.0/0016-ARM-rpi_defconfig-Enable-more-features.patch b/configs/platform-v7a/patches/barebox-2019.12.0/0016-ARM-rpi_defconfig-Enable-more-features.patch
new file mode 100644
index 0000000..5d6c1f7
--- /dev/null
+++ b/configs/platform-v7a/patches/barebox-2019.12.0/0016-ARM-rpi_defconfig-Enable-more-features.patch
@@ -0,0 +1,109 @@
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Fri, 20 Dec 2019 15:03:38 +0100
+Subject: [PATCH] ARM: rpi_defconfig: Enable more features
+
+This enabled more features for the rasperrypi boards:
+
+- DWC2 USB driver
+- Networking support
+- GPIO EXP driver
+- LED support
+- more commands
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ arch/arm/configs/rpi_defconfig | 25 +++++++++++++++++++++++--
+ 1 file changed, 23 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/configs/rpi_defconfig b/arch/arm/configs/rpi_defconfig
+index 3813b837dd35..dd5ca7585a83 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,18 +70,26 @@ 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
+@@ -76,8 +97,8 @@ 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/configs/platform-v7a/patches/barebox-2019.12.0/0101-Release-2019.12.0-customers-pengutronix-distrokit-v7.patch b/configs/platform-v7a/patches/barebox-2019.12.0/0101-Release-2019.12.0-customers-pengutronix-distrokit-v7.patch
new file mode 100644
index 0000000..94e09d0
--- /dev/null
+++ b/configs/platform-v7a/patches/barebox-2019.12.0/0101-Release-2019.12.0-customers-pengutronix-distrokit-v7.patch
@@ -0,0 +1,22 @@
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 8 Jan 2020 11:15:45 +0100
+Subject: [PATCH] Release
+ 2019.12.0/customers/pengutronix/distrokit-v7a/20200108-1
+
+---
+ Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/Makefile b/Makefile
+index 600ca36a311c..96890b4c13f6 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ VERSION = 2019
+ PATCHLEVEL = 12
+ SUBLEVEL = 0
+-EXTRAVERSION =
++EXTRAVERSION =-20200108-1
+ NAME = None
+
+ # *DOCUMENTATION*
diff --git a/configs/platform-v7a/patches/barebox-2019.12.0/series b/configs/platform-v7a/patches/barebox-2019.12.0/series
new file mode 100644
index 0000000..f5bb5c5
--- /dev/null
+++ b/configs/platform-v7a/patches/barebox-2019.12.0/series
@@ -0,0 +1,26 @@
+# umpf-base: v2019.12.0
+# umpf-name: 2019.12.0/customers/pengutronix/distrokit-v7a
+# umpf-version: 2019.12.0/customers/pengutronix/distrokit-v7a/20200108-1
+# umpf-topic: v2019.12.0/topic/raspberrypi
+# umpf-hashinfo: 3315e55b033d80c15865e0b936894ed773ce391c
+# umpf-topic-range: 48b57af0ab888bf88607d0e55ad3e79d13cc0a31..adbebd694167ede6aeb2a298918b24040c0ded97
+0001-ARM-rpi-Do-not-warn-when-firmware-doesn-t-pass-a-dtb.patch
+0002-usb-Make-timeout-unit-clear.patch
+0003-of-Add-of_bus_n_xxx_cells.patch
+0004-device-Introduce-dma_offset.patch
+0005-of-Read-dma_offset-from-device-tree.patch
+0006-usb-Add-usbroothubdes.h.patch
+0007-regulator-add-function-to-get-regulator-by-its-name.patch
+0008-rpi-Enable-USB-Power-domain-during-startup.patch
+0009-usb-Forward-error-code-from-usb_set_configuration.patch
+0010-usb-Add-dwc2-host-driver.patch
+0011-ARM-bcm2835-mbox-Remove-response-valid-check.patch
+0012-gpio-Add-raspberrypi-exp-gpio-driver.patch
+0013-ARM-bcm2835-mbox-use-pr_-to-print-messages.patch
+0014-ARM-rpi_defconfig-Enable-raspberry-GPIO-exp-driver.patch
+0015-ARM-rpi-mailbox-Use-non-interruptible-timeout.patch
+0016-ARM-rpi_defconfig-Enable-more-features.patch
+# umpf-release: 2019.12.0/customers/pengutronix/distrokit-v7a/20200108-1
+# umpf-topic-range: adbebd694167ede6aeb2a298918b24040c0ded97..0cc90c348816c16cded33c2ed48e918c9f69d8cd
+0101-Release-2019.12.0-customers-pengutronix-distrokit-v7.patch
+# umpf-end