[coreboot-gerrit] New patch to review for coreboot: eb83a39 exynos5: Implement support for USB 3.0 DRD PHYs/controllers

Isaac Christensen (isaac.christensen@se-eng.com) gerrit at coreboot.org
Wed Aug 13 01:24:47 CEST 2014


Isaac Christensen (isaac.christensen at se-eng.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/6642

-gerrit

commit eb83a397dee76f563e72ffcbd48ebcc628754a58
Author: Julius Werner <jwerner at chromium.org>
Date:   Tue Sep 3 15:07:31 2013 -0700

    exynos5: Implement support for USB 3.0 DRD PHYs/controllers
    
    This patch adds support for the DesignWare3 USB 3.0 DRD controller and
    PHY to the Exynos5250 and Exynos5420 CPUs. It also adds code to the
    Google Snow and Pit boards to turn these controllers on where
    applicable.
    
    Change-Id: Idcca627363a69f1d65402e1acb9a62b439f077ff
    Signed-off-by: Julius Werner <jwerner at chromium.org>
    Reviewed-on: https://chromium-review.googlesource.com/169452
    Reviewed-by: Stefan Reinauer <reinauer at google.com>
    (cherry picked from commit e9809ae12ef8b8bd6cd61d3f604cb9e4718cf7eb)
    Signed-off-by: Isaac Christensen <isaac.christensen at se-eng.com>
---
 src/cpu/samsung/exynos5250/cpu.h      |   1 +
 src/cpu/samsung/exynos5250/power.h    |   5 +-
 src/cpu/samsung/exynos5250/usb.c      | 110 ++++++++++++++++++++++++++++-
 src/cpu/samsung/exynos5250/usb.h      |  77 ++++++++++++++++++--
 src/cpu/samsung/exynos5420/cpu.h      |   2 +
 src/cpu/samsung/exynos5420/power.h    |  10 +--
 src/cpu/samsung/exynos5420/usb.c      | 129 +++++++++++++++++++++++++++++++++-
 src/cpu/samsung/exynos5420/usb.h      |  84 ++++++++++++++++++++--
 src/mainboard/google/pit/mainboard.c  |  18 ++++-
 src/mainboard/google/snow/mainboard.c |  12 +++-
 10 files changed, 427 insertions(+), 21 deletions(-)

diff --git a/src/cpu/samsung/exynos5250/cpu.h b/src/cpu/samsung/exynos5250/cpu.h
index 12745d3..85b6fae 100644
--- a/src/cpu/samsung/exynos5250/cpu.h
+++ b/src/cpu/samsung/exynos5250/cpu.h
@@ -41,6 +41,7 @@
 #define EXYNOS5_GPIO_PART2_BASE		0x11400c00	/* X00..X37 */
 #define EXYNOS5_USB_DRD_XHCI_BASE	0x12000000
 #define EXYNOS5_USB_DRD_PHY_BASE	0x12100000
+#define EXYNOS5_USB_DRD_DWC3_BASE	0x1200C100
 #define EXYNOS5_USB_HOST_EHCI_BASE	0x12110000
 #define EXYNOS5_USB_HOST_PHY_BASE	0x12130000
 #define EXYNOS5_MMC_BASE		0x12200000
diff --git a/src/cpu/samsung/exynos5250/power.h b/src/cpu/samsung/exynos5250/power.h
index 293fe3b..df68b53 100644
--- a/src/cpu/samsung/exynos5250/power.h
+++ b/src/cpu/samsung/exynos5250/power.h
@@ -30,7 +30,7 @@ void power_enable_hw_thermal_trip(void);
 #define MIPI_PHY1_CONTROL_ENABLE		(1 << 0)
 #define MIPI_PHY1_CONTROL_M_RESETN		(1 << 2)
 
-#define POWER_USB_HOST_PHY_CTRL_EN		(1 << 0)
+#define POWER_USB_PHY_CTRL_EN			(1 << 0)
 #define POWER_PS_HOLD_CONTROL_DATA_HIGH		(1 << 8)
 #define POWER_ENABLE_HW_TRIP			(1UL << 31)
 
@@ -47,7 +47,8 @@ struct exynos5_power {
 	uint32_t	om_stat;		/* 0x0000 */
 	uint8_t		reserved1[0x03fc];
 	uint32_t	sw_reset;		/* 0x0400 */
-	uint8_t		reserved2[0x0304];
+	uint8_t		reserved2[0x0300];
+	uint32_t	usb_drd_phy_ctrl;	/* 0x0704 */
 	uint32_t	usb_host_phy_ctrl;	/* 0x0708 */
 	uint8_t		reserved3[0x8];
 	uint32_t	mipi_phy1_control;	/* 0x0714 */
diff --git a/src/cpu/samsung/exynos5250/usb.c b/src/cpu/samsung/exynos5250/usb.c
index 521ea4d..76da1dd 100644
--- a/src/cpu/samsung/exynos5250/usb.c
+++ b/src/cpu/samsung/exynos5250/usb.c
@@ -27,13 +27,119 @@
 #include "sysreg.h"
 #include "usb.h"
 
+static void reset_dwc3(struct exynos5_usb_drd_dwc3 *dwc3)
+{
+	setbits_le32(&dwc3->ctl, 0x1 << 11);		/* core soft reset */
+	setbits_le32(&dwc3->usb3pipectl, 0x1 << 31);	/* PHY soft reset */
+	setbits_le32(&dwc3->usb2phycfg, 0x1 << 31);	/* PHY soft reset */
+}
+
+void reset_usb_drd_dwc3()
+{
+	printk(BIOS_DEBUG, "Starting DWC3 reset for USB DRD\n");
+	reset_dwc3(exynos_usb_drd_dwc3);
+}
+
+static void setup_dwc3(struct exynos5_usb_drd_dwc3 *dwc3)
+{
+	if (!(dwc3->ctl & 0x1 << 11) ||
+	    !(dwc3->usb3pipectl & 0x1 << 31) ||
+	    !(dwc3->usb2phycfg & 0x1 << 31)) {
+		printk(BIOS_ERR, "DWC3 at %p not in reset (you need to call "
+		       "reset_usb_drd_dwc3() first)!\n", dwc3);
+	}
+
+	/* Set relevant registers to default values (clearing all reset bits) */
+
+	writel(0x1 << 24 |	/* activate PHY low power states */
+	       0x4 << 19 |	/* low power delay value */
+	       0x1 << 18 |	/* activate PHY low power delay */
+	       0x1 << 17 |	/* enable SuperSpeed PHY suspend */
+	       0x1 << 1 |	/* default Tx deemphasis value */
+	       0, &dwc3->usb3pipectl);
+
+	/* Configure PHY clock turnaround for 8-bit UTMI+, disable suspend */
+	writel(0x9 << 10 |	/* PHY clock turnaround for 8-bit UTMI+ */
+	       0x1 << 8 |	/* enable PHY sleep in L1 */
+	       0x1 << 6 |	/* enable PHY suspend */
+	       0, &dwc3->usb2phycfg);
+
+	writel(0x5dc << 19 |	/* suspend clock scale for 24MHz */
+	       0x1 << 16 |	/* retry SS three times (bugfix from U-Boot) */
+	       0x1 << 12 |	/* port capability HOST */
+	       0, &dwc3->ctl);
+}
+
+void setup_usb_drd_dwc3()
+{
+	setup_dwc3(exynos_usb_drd_dwc3);
+	printk(BIOS_DEBUG, "DWC3 setup for USB DRD finished\n");
+}
+
+static void setup_drd_phy(struct exynos5_usb_drd_phy *phy)
+{
+	/* Set all PHY registers to default values */
+
+	/* XHCI Version 1.0, Frame Length adjustment 30 MHz */
+	setbits_le32(&phy->linksystem, 0x1 << 27 | 0x20 << 1);
+
+	/* Disable OTG, ID0 and DRVVBUS, do not force sleep/suspend */
+	writel(1 << 6, &phy->utmi);
+
+	writel(0x88 << 23 |	/* spread spectrum refclk selector */
+	       0x1 << 20 |	/* enable spread spectrum */
+	       0x1 << 19 |	/* enable prescaler refclk */
+	       0x68 << 11 |	/* multiplier for 24MHz refclk */
+	       0x5 << 5 |	/* select 24MHz refclk (weird, from U-Boot) */
+	       0x1 << 4 |	/* power supply in normal operating mode */
+	       0x3 << 2 |	/* use external refclk (undocumented on 5420?)*/
+	       0x1 << 1 |	/* force port reset */
+	       0x1 << 0 |	/* normal operating mode */
+	       0, &phy->clkrst);
+
+	writel(0x9 << 26 |	/* LOS level */
+	       0x3 << 22 |	/* TX VREF tune */
+	       0x1 << 20 |	/* TX rise tune */
+	       0x1 << 18 |	/* TX res tune */
+	       0x3 << 13 |	/* TX HS X Vtune */
+	       0x3 << 9 |	/* TX FS/LS tune */
+	       0x3 << 6 |	/* SQRX tune */
+	       0x4 << 3 |	/* OTG tune */
+	       0x4 << 0 |	/* comp disc tune */
+	       0, &phy->param0);
+
+	writel(0x7f << 19 |	/* reserved */
+	       0x7f << 12 |	/* Tx launch amplitude */
+	       0x20 << 6 |	/* Tx deemphasis 6dB */
+	       0x1c << 0 |	/* Tx deemphasis 3.5dB (value from U-Boot) */
+	       0, &phy->param1);
+
+	/* disable all test features */
+	writel(0, &phy->test);
+
+	/* UTMI clock select? ("must be 0x1") */
+	writel(0x1 << 2, &phy->utmiclksel);
+
+	/* Samsung magic, undocumented (from U-Boot) */
+	writel(0x0, &phy->resume);
+
+	udelay(10);
+	clrbits_le32(&phy->clkrst, 0x1 << 1);  /* deassert port reset */
+}
+
+void setup_usb_drd_phy()
+{
+	printk(BIOS_DEBUG, "Powering up USB DRD PHY\n");
+	setbits_le32(&exynos_power->usb_drd_phy_ctrl, POWER_USB_PHY_CTRL_EN);
+	setup_drd_phy(exynos_usb_drd_phy);
+}
+
 void setup_usb_host_phy(int hsic_gpio)
 {
 	unsigned int hostphy_ctrl0;
 
 	setbits_le32(&exynos_sysreg->usb20_phy_cfg, USB20_PHY_CFG_EN);
-	setbits_le32(&exynos_power->usb_host_phy_ctrl,
-		     POWER_USB_HOST_PHY_CTRL_EN);
+	setbits_le32(&exynos_power->usb_host_phy_ctrl, POWER_USB_PHY_CTRL_EN);
 
 	printk(BIOS_DEBUG, "Powering up USB HOST PHY (%s HSIC)\n",
 			hsic_gpio ? "with" : "without");
diff --git a/src/cpu/samsung/exynos5250/usb.h b/src/cpu/samsung/exynos5250/usb.h
index c951c1f..ad617da 100644
--- a/src/cpu/samsung/exynos5250/usb.h
+++ b/src/cpu/samsung/exynos5250/usb.h
@@ -45,24 +45,93 @@
 struct exynos5_usb_host_phy {
         uint32_t usbphyctrl0;
         uint32_t usbphytune0;
-        uint32_t reserved1[2];
+        uint8_t reserved1[8];
         uint32_t hsicphyctrl1;
         uint32_t hsicphytune1;
-        uint32_t reserved2[2];
+        uint8_t reserved2[8];
         uint32_t hsicphyctrl2;
         uint32_t hsicphytune2;
-        uint32_t reserved3[2];
+        uint8_t reserved3[8];
         uint32_t ehcictrl;
         uint32_t ohcictrl;
         uint32_t usbotgsys;
-        uint32_t reserved4;
+        uint8_t reserved4[4];
         uint32_t usbotgtune;
 };
 
 static struct exynos5_usb_host_phy * const exynos_usb_host_phy =
 		(void *)EXYNOS5_USB_HOST_PHY_BASE;
 
+struct exynos5_usb_drd_phy {
+	uint8_t reserved1[4];
+	uint32_t linksystem;
+	uint32_t utmi;
+	uint32_t pipe;
+	uint32_t clkrst;
+	uint32_t reg0;
+	uint32_t reg1;
+	uint32_t param0;
+	uint32_t param1;
+	uint32_t term;
+	uint32_t test;
+	uint32_t adp;
+	uint32_t utmiclksel;
+	uint32_t resume;
+	uint8_t reserved2[8];
+	uint32_t linkhcbelt;
+	uint32_t linkport;
+};
+
+static struct exynos5_usb_drd_phy * const exynos_usb_drd_phy =
+		(void *)EXYNOS5_USB_DRD_PHY_BASE;
+
+struct exynos5_usb_drd_dwc3 {
+	uint32_t sbuscfg0;
+	uint32_t sbuscfg1;
+	uint32_t txthrcfg;
+	uint32_t rxthrcfg;
+	uint32_t ctl;
+	uint32_t evten;
+	uint32_t sts;
+	uint8_t reserved0[4];
+	uint32_t snpsid;
+	uint32_t gpio;
+	uint32_t uid;
+	uint32_t uctl;
+	uint64_t buserraddr;
+	uint64_t prtbimap;
+	uint8_t reserved1[32];
+	uint32_t dbgfifospace;
+	uint32_t dbgltssm;
+	uint32_t dbglnmcc;
+	uint32_t dbgbmu;
+	uint32_t dbglspmux;
+	uint32_t dbglsp;
+	uint32_t dbgepinfo0;
+	uint32_t dbgepinfo1;
+	uint64_t prtbimap_hs;
+	uint64_t prtbimap_fs;
+	uint8_t reserved2[112];
+	uint32_t usb2phycfg;
+	uint8_t reserved3[60];
+	uint32_t usb2i2cctl;
+	uint8_t reserved4[60];
+	uint32_t usb2phyacc;
+	uint8_t reserved5[60];
+	uint32_t usb3pipectl;
+	uint8_t reserved6[60];
+};
+
+static struct exynos5_usb_drd_dwc3 * const exynos_usb_drd_dwc3 =
+		(void *)EXYNOS5_USB_DRD_DWC3_BASE;
+
 /* Leave hsic_gpio at 0 to not enable HSIC. */
 void setup_usb_host_phy(int hsic_gpio);
 
+void setup_usb_drd_phy(void);
+
+/* Call reset_ before setup_, ensure at least 100ms pass in between. */
+void reset_usb_drd_dwc3(void);
+void setup_usb_drd_dwc3(void);
+
 #endif
diff --git a/src/cpu/samsung/exynos5420/cpu.h b/src/cpu/samsung/exynos5420/cpu.h
index ffc83f8..e3c7f1b 100644
--- a/src/cpu/samsung/exynos5420/cpu.h
+++ b/src/cpu/samsung/exynos5420/cpu.h
@@ -39,6 +39,7 @@
 #define EXYNOS5420_DMC_TZASC_0		0x10D40000
 #define EXYNOS5420_DMC_TZASC_1		0x10D50000
 #define EXYNOS5420_USB_DRD0_XHCI_BASE	0x12000000
+#define EXYNOS5420_USB_DRD0_DWC3_BASE	0x1200C100
 #define EXYNOS5420_USB_DRD0_PHY_BASE	0x12100000
 #define EXYNOS5_USB_HOST_EHCI_BASE	0x12110000
 #define EXYNOS5_USB_HOST_PHY_BASE	0x12130000
@@ -46,6 +47,7 @@
 #define EXYNOS5_MSHC_BASE		0x12240000
 #define EXYNOS5_SROMC_BASE		0x12250000
 #define EXYNOS5420_USB_DRD1_XHCI_BASE	0x12400000
+#define EXYNOS5420_USB_DRD1_DWC3_BASE	0x1240C100
 #define EXYNOS5420_USB_DRD1_PHY_BASE	0x12500000
 #define EXYNOS5_UART0_BASE		0x12C00000
 #define EXYNOS5_UART1_BASE		0x12C10000
diff --git a/src/cpu/samsung/exynos5420/power.h b/src/cpu/samsung/exynos5420/power.h
index e65c4bd..a89ee9d 100644
--- a/src/cpu/samsung/exynos5420/power.h
+++ b/src/cpu/samsung/exynos5420/power.h
@@ -30,7 +30,7 @@ void power_enable_hw_thermal_trip(void);
 #define MIPI_PHY1_CONTROL_ENABLE		(1 << 0)
 #define MIPI_PHY1_CONTROL_M_RESETN		(1 << 2)
 
-#define POWER_USB_HOST_PHY_CTRL_EN		(1 << 0)
+#define POWER_USB_PHY_CTRL_EN			(1 << 0)
 #define POWER_PS_HOLD_CONTROL_DATA_HIGH		(1 << 8)
 #define POWER_ENABLE_HW_TRIP			(1UL << 31)
 
@@ -47,9 +47,11 @@ struct exynos5_power {
 	uint32_t	om_stat;		/* 0x0000 */
 	uint8_t		reserved1[0x03fc];
 	uint32_t	sw_reset;		/* 0x0400 */
-	uint8_t		reserved2[0x0304];
-	uint32_t	usb_host_phy_ctrl;	/* 0x0708 */
-	uint8_t		reserved3[0x8];
+	uint8_t		reserved2[0x0300];
+	uint32_t	usb_drd0_phy_ctrl;	/* 0x0704 */
+	uint32_t	usb_drd1_phy_ctrl;	/* 0x0708 */
+	uint32_t	usb_host_phy_ctrl;	/* 0x070c */
+	uint8_t		reserved3[0x4];
 	uint32_t	mipi_phy1_control;	/* 0x0714 */
 	uint8_t		reserved4[0x8];
 	uint32_t	dptx_phy_control;	/* 0x0720 */
diff --git a/src/cpu/samsung/exynos5420/usb.c b/src/cpu/samsung/exynos5420/usb.c
index 521ea4d..84a6f4c 100644
--- a/src/cpu/samsung/exynos5420/usb.c
+++ b/src/cpu/samsung/exynos5420/usb.c
@@ -27,13 +27,138 @@
 #include "sysreg.h"
 #include "usb.h"
 
+static void reset_dwc3(struct exynos5_usb_drd_dwc3 *dwc3)
+{
+	setbits_le32(&dwc3->ctl, 0x1 << 11);		/* core soft reset */
+	setbits_le32(&dwc3->usb3pipectl, 0x1 << 31);	/* PHY soft reset */
+	setbits_le32(&dwc3->usb2phycfg, 0x1 << 31);	/* PHY soft reset */
+}
+
+void reset_usb_drd0_dwc3()
+{
+	printk(BIOS_DEBUG, "Starting DWC3 reset for USB DRD0\n");
+	reset_dwc3(exynos_usb_drd0_dwc3);
+}
+
+void reset_usb_drd1_dwc3()
+{
+	printk(BIOS_DEBUG, "Starting DWC3 reset for USB DRD1\n");
+	reset_dwc3(exynos_usb_drd1_dwc3);
+}
+
+static void setup_dwc3(struct exynos5_usb_drd_dwc3 *dwc3)
+{
+	if (!(dwc3->ctl & 0x1 << 11) ||
+	    !(dwc3->usb3pipectl & 0x1 << 31) ||
+	    !(dwc3->usb2phycfg & 0x1 << 31)) {
+		printk(BIOS_ERR, "DWC3 at %p not in reset (you need to call "
+		       "reset_usb_drdX_dwc3() first)!\n", dwc3);
+	}
+
+	/* Set relevant registers to default values (clearing all reset bits) */
+
+	writel(0x1 << 24 |	/* activate PHY low power states */
+	       0x4 << 19 |	/* low power delay value */
+	       0x1 << 18 |	/* activate PHY low power delay */
+	       0x1 << 17 |	/* enable SuperSpeed PHY suspend */
+	       0x1 << 1 |	/* default Tx deemphasis value */
+	       0, &dwc3->usb3pipectl);
+
+	/* Configure PHY clock turnaround for 8-bit UTMI+, disable suspend */
+	writel(0x9 << 10 |	/* PHY clock turnaround for 8-bit UTMI+ */
+	       0x1 << 8 |	/* enable PHY sleep in L1 */
+	       0x1 << 6 |	/* enable PHY suspend */
+	       0, &dwc3->usb2phycfg);
+
+	writel(0x5dc << 19 |	/* suspend clock scale for 24MHz */
+	       0x1 << 16 |	/* retry SS three times (bugfix from U-Boot) */
+	       0x1 << 12 |	/* port capability HOST */
+	       0, &dwc3->ctl);
+}
+
+void setup_usb_drd0_dwc3()
+{
+	setup_dwc3(exynos_usb_drd0_dwc3);
+	printk(BIOS_DEBUG, "DWC3 setup for USB DRD0 finished\n");
+}
+
+void setup_usb_drd1_dwc3()
+{
+	setup_dwc3(exynos_usb_drd1_dwc3);
+	printk(BIOS_DEBUG, "DWC3 setup for USB DRD1 finished\n");
+}
+
+static void setup_drd_phy(struct exynos5_usb_drd_phy *phy)
+{
+	/* Set all PHY registers to default values */
+
+	/* XHCI Version 1.0, Frame Length adjustment 30 MHz */
+	setbits_le32(&phy->linksystem, 0x1 << 27 | 0x20 << 1);
+
+	/* Disable OTG, ID0 and DRVVBUS, do not force sleep/suspend */
+	writel(1 << 6, &phy->utmi);
+
+	writel(0x88 << 23 |	/* spread spectrum refclk selector */
+	       0x1 << 20 |	/* enable spread spectrum */
+	       0x1 << 19 |	/* enable prescaler refclk */
+	       0x68 << 11 |	/* multiplier for 24MHz refclk */
+	       0x5 << 5 |	/* select 24MHz refclk (weird, from U-Boot) */
+	       0x1 << 4 |	/* power supply in normal operating mode */
+	       0x3 << 2 |	/* use external refclk (undocumented on 5420?)*/
+	       0x1 << 1 |	/* force port reset */
+	       0x1 << 0 |	/* normal operating mode */
+	       0, &phy->clkrst);
+
+	writel(0x9 << 26 |	/* LOS level */
+	       0x3 << 22 |	/* TX VREF tune */
+	       0x1 << 20 |	/* TX rise tune */
+	       0x1 << 18 |	/* TX res tune */
+	       0x3 << 13 |	/* TX HS X Vtune */
+	       0x3 << 9 |	/* TX FS/LS tune */
+	       0x3 << 6 |	/* SQRX tune */
+	       0x4 << 3 |	/* OTG tune */
+	       0x4 << 0 |	/* comp disc tune */
+	       0, &phy->param0);
+
+	writel(0x7f << 19 |	/* reserved */
+	       0x7f << 12 |	/* Tx launch amplitude */
+	       0x20 << 6 |	/* Tx deemphasis 6dB */
+	       0x1c << 0 |	/* Tx deemphasis 3.5dB (value from U-Boot) */
+	       0, &phy->param1);
+
+	/* disable all test features */
+	writel(0, &phy->test);
+
+	/* UTMI clock select? ("must be 0x1") */
+	writel(0x1 << 2, &phy->utmiclksel);
+
+	/* Samsung magic, undocumented (from U-Boot) */
+	writel(0x0, &phy->resume);
+
+	udelay(10);
+	clrbits_le32(&phy->clkrst, 0x1 << 1);  /* deassert port reset */
+}
+
+void setup_usb_drd0_phy()
+{
+	printk(BIOS_DEBUG, "Powering up USB DRD0 PHY\n");
+	setbits_le32(&exynos_power->usb_drd0_phy_ctrl, POWER_USB_PHY_CTRL_EN);
+	setup_drd_phy(exynos_usb_drd0_phy);
+}
+
+void setup_usb_drd1_phy()
+{
+	printk(BIOS_DEBUG, "Powering up USB DRD1 PHY\n");
+	setbits_le32(&exynos_power->usb_drd1_phy_ctrl, POWER_USB_PHY_CTRL_EN);
+	setup_drd_phy(exynos_usb_drd1_phy);
+}
+
 void setup_usb_host_phy(int hsic_gpio)
 {
 	unsigned int hostphy_ctrl0;
 
 	setbits_le32(&exynos_sysreg->usb20_phy_cfg, USB20_PHY_CFG_EN);
-	setbits_le32(&exynos_power->usb_host_phy_ctrl,
-		     POWER_USB_HOST_PHY_CTRL_EN);
+	setbits_le32(&exynos_power->usb_host_phy_ctrl, POWER_USB_PHY_CTRL_EN);
 
 	printk(BIOS_DEBUG, "Powering up USB HOST PHY (%s HSIC)\n",
 			hsic_gpio ? "with" : "without");
diff --git a/src/cpu/samsung/exynos5420/usb.h b/src/cpu/samsung/exynos5420/usb.h
index 7eb317c..b3c2a33 100644
--- a/src/cpu/samsung/exynos5420/usb.h
+++ b/src/cpu/samsung/exynos5420/usb.h
@@ -45,24 +45,100 @@
 struct exynos5_usb_host_phy {
         uint32_t usbphyctrl0;
         uint32_t usbphytune0;
-        uint32_t reserved1[2];
+        uint8_t reserved1[8];
         uint32_t hsicphyctrl1;
         uint32_t hsicphytune1;
-        uint32_t reserved2[2];
+        uint8_t reserved2[8];
         uint32_t hsicphyctrl2;
         uint32_t hsicphytune2;
-        uint32_t reserved3[2];
+        uint8_t reserved3[8];
         uint32_t ehcictrl;
         uint32_t ohcictrl;
         uint32_t usbotgsys;
-        uint32_t reserved4;
+        uint8_t reserved4[4];
         uint32_t usbotgtune;
 };
 
 static struct exynos5_usb_host_phy * const exynos_usb_host_phy =
 		(void *)EXYNOS5_USB_HOST_PHY_BASE;
 
+struct exynos5_usb_drd_phy {
+	uint8_t reserved1[4];
+	uint32_t linksystem;
+	uint32_t utmi;
+	uint32_t pipe;
+	uint32_t clkrst;
+	uint32_t reg0;
+	uint32_t reg1;
+	uint32_t param0;
+	uint32_t param1;
+	uint32_t term;
+	uint32_t test;
+	uint32_t adp;
+	uint32_t utmiclksel;
+	uint32_t resume;
+	uint8_t reserved2[8];
+	uint32_t linkhcbelt;
+	uint32_t linkport;
+};
+
+static struct exynos5_usb_drd_phy * const exynos_usb_drd0_phy =
+		(void *)EXYNOS5420_USB_DRD0_PHY_BASE;
+static struct exynos5_usb_drd_phy * const exynos_usb_drd1_phy =
+		(void *)EXYNOS5420_USB_DRD1_PHY_BASE;
+
+struct exynos5_usb_drd_dwc3 {
+	uint32_t sbuscfg0;
+	uint32_t sbuscfg1;
+	uint32_t txthrcfg;
+	uint32_t rxthrcfg;
+	uint32_t ctl;
+	uint32_t evten;
+	uint32_t sts;
+	uint8_t reserved0[4];
+	uint32_t snpsid;
+	uint32_t gpio;
+	uint32_t uid;
+	uint32_t uctl;
+	uint64_t buserraddr;
+	uint64_t prtbimap;
+	uint8_t reserved1[32];
+	uint32_t dbgfifospace;
+	uint32_t dbgltssm;
+	uint32_t dbglnmcc;
+	uint32_t dbgbmu;
+	uint32_t dbglspmux;
+	uint32_t dbglsp;
+	uint32_t dbgepinfo0;
+	uint32_t dbgepinfo1;
+	uint64_t prtbimap_hs;
+	uint64_t prtbimap_fs;
+	uint8_t reserved2[112];
+	uint32_t usb2phycfg;
+	uint8_t reserved3[60];
+	uint32_t usb2i2cctl;
+	uint8_t reserved4[60];
+	uint32_t usb2phyacc;
+	uint8_t reserved5[60];
+	uint32_t usb3pipectl;
+	uint8_t reserved6[60];
+};
+
+static struct exynos5_usb_drd_dwc3 * const exynos_usb_drd0_dwc3 =
+		(void *)EXYNOS5420_USB_DRD0_DWC3_BASE;
+static struct exynos5_usb_drd_dwc3 * const exynos_usb_drd1_dwc3 =
+		(void *)EXYNOS5420_USB_DRD1_DWC3_BASE;
+
 /* Leave hsic_gpio at 0 to not enable HSIC. */
 void setup_usb_host_phy(int hsic_gpio);
 
+void setup_usb_drd0_phy(void);
+void setup_usb_drd1_phy(void);
+
+/* Call reset_ before setup_, ensure at least 100ms pass in between. */
+void reset_usb_drd0_dwc3(void);
+void reset_usb_drd1_dwc3(void);
+void setup_usb_drd0_dwc3(void);
+void setup_usb_drd1_dwc3(void);
+
 #endif
diff --git a/src/mainboard/google/pit/mainboard.c b/src/mainboard/google/pit/mainboard.c
index bdf2d57..211160d 100644
--- a/src/mainboard/google/pit/mainboard.c
+++ b/src/mainboard/google/pit/mainboard.c
@@ -312,9 +312,22 @@ static enum exynos5_gpio_pin usb_drd0_vbus = GPIO_H00;
 static enum exynos5_gpio_pin usb_drd1_vbus = GPIO_H01;
 /* static enum exynos5_gpio_pin hsic_reset_l = GPIO_X24; */
 
+static void prepare_usb(void)
+{
+	/* Kick these resets off early so they get at least 100ms to settle */
+	reset_usb_drd0_dwc3();
+	reset_usb_drd1_dwc3();
+}
+
 static void setup_usb(void)
 {
 	/* HSIC and USB HOST port not needed in firmware on this board */
+	setup_usb_drd0_phy();
+	setup_usb_drd1_phy();
+
+	setup_usb_drd0_dwc3();
+	setup_usb_drd1_dwc3();
+
 	gpio_direction_output(usb_drd0_vbus, 1);
 	gpio_direction_output(usb_drd1_vbus, 1);
 }
@@ -401,6 +414,7 @@ static void mainboard_init(device_t dev)
 
 	void *fb_addr = (void *)(get_fb_base_kb() * KiB);
 
+	prepare_usb();
 	gpio_init();
 	setup_storage();
 	tmu_init(&exynos5420_tmu_info);
@@ -408,8 +422,6 @@ static void mainboard_init(device_t dev)
 	/* Clock Gating all the unused IP's to save power */
 	clock_gate();
 
-	setup_usb();
-
 	sdmmc_vdd();
 
 	set_vbe_mode_info_valid(&edid, (uintptr_t)fb_addr);
@@ -447,6 +459,8 @@ static void mainboard_init(device_t dev)
 	backlight_vdd();
 	backlight_pwm();
 	backlight_en();
+
+	setup_usb();
 }
 
 static void mainboard_enable(device_t dev)
diff --git a/src/mainboard/google/snow/mainboard.c b/src/mainboard/google/snow/mainboard.c
index 756dc15..f906e53 100644
--- a/src/mainboard/google/snow/mainboard.c
+++ b/src/mainboard/google/snow/mainboard.c
@@ -165,9 +165,17 @@ static enum exynos5_gpio_pin usb_host_vbus = GPIO_X11;
 static enum exynos5_gpio_pin usb_drd_vbus = GPIO_X27;
 /* static enum exynos5_gpio_pin hsic_reset_l = GPIO_E10; */
 
+static void prepare_usb(void)
+{
+	/* Kick this reset off early so it gets at least 100ms to settle */
+	reset_usb_drd_dwc3();
+}
+
 static void setup_usb(void)
 {
 	/* HSIC not needed in firmware on this board */
+	setup_usb_drd_phy();
+	setup_usb_drd_dwc3();
 	setup_usb_host_phy(0);
 
 	gpio_direction_output(usb_host_vbus, 1);
@@ -260,6 +268,7 @@ static void mainboard_init(device_t dev)
 	};
 	void *fb_addr = (void *)(get_fb_base_kb() * KiB);
 
+	prepare_usb();
 	gpio_init();
 	setup_storage();
 
@@ -273,7 +282,6 @@ static void mainboard_init(device_t dev)
 
 	/* Disable USB3.0 PLL to save 250mW of power */
 	disable_usb30_pll();
-	setup_usb();
 
 	sdmmc_vdd();
 
@@ -309,6 +317,8 @@ static void mainboard_init(device_t dev)
 	if (dp_tries > MAX_DP_TRIES)
 		printk(BIOS_ERR, "%s: Failed to set up displayport\n", __func__);
 
+	setup_usb();
+
 	// Uncomment to get excessive GPIO output:
 	// gpio_info();
 }



More information about the coreboot-gerrit mailing list