diff options
author | Julius Werner <jwerner@chromium.org> | 2013-09-03 15:07:31 -0700 |
---|---|---|
committer | Isaac Christensen <isaac.christensen@se-eng.com> | 2014-08-18 19:02:41 +0200 |
commit | 68aef1169239cc5d33fb36f05cd32d7e062b7743 (patch) | |
tree | 3a1436c1e348fbd6d9020ac578c8aa31cf00d86b | |
parent | 9125d88596181549f9cd7988c6dd748d54b299ee (diff) | |
download | coreboot-68aef1169239cc5d33fb36f05cd32d7e062b7743.tar.xz |
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@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/169452
Reviewed-by: Stefan Reinauer <reinauer@google.com>
(cherry picked from commit e9809ae12ef8b8bd6cd61d3f604cb9e4718cf7eb)
Signed-off-by: Isaac Christensen <isaac.christensen@se-eng.com>
Reviewed-on: http://review.coreboot.org/6642
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
-rw-r--r-- | src/cpu/samsung/exynos5250/cpu.h | 1 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5250/power.h | 5 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5250/usb.c | 110 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5250/usb.h | 77 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5420/cpu.h | 2 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5420/power.h | 10 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5420/usb.c | 129 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5420/usb.h | 84 | ||||
-rw-r--r-- | src/mainboard/google/pit/mainboard.c | 18 | ||||
-rw-r--r-- | 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 12745d3d85..85b6fae464 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 293fe3b704..df68b53dbd 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 521ea4da5a..76da1dd56e 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 c951c1fbbb..ad617da96c 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 ffc83f88e4..e3c7f1be38 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 e65c4bd976..a89ee9dca8 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 521ea4da5a..84a6f4ca4c 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 7eb317c68e..b3c2a33fd6 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 bdf2d571b2..211160d754 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 756dc15325..f906e534a3 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(); } |