From 76655cb82c207b0c9904c094f7790de2f0835b67 Mon Sep 17 00:00:00 2001 From: Liangfeng Wu Date: Thu, 26 May 2016 16:06:58 +0800 Subject: [PATCH] rockchip: gru: Add USB DRD DWC3 controller support This patch adds code to initialize the two DWC3 USB host controllers, and uses them to initialize USB3.0 on the gru rk3399 board. BRANCH=none BUG=chrome-os-partner:52684 TEST=boot from USB3.0 on gru/kevin rk3399 platform Change-Id: If6a6e56f3a7c7ce8e8b098634cfc2f250a91810d Signed-off-by: Martin Roth Original-Commit-Id: 0306a9e Original-Change-Id: I796fa1133510876f75873d134ea752e1b52e40a8 Original-Signed-off-by: Liangfeng Wu Original-Signed-off-by: Douglas Anderson Original-Reviewed-on: https://chromium-review.googlesource.com/347524 Original-Commit-Ready: Brian Norris Original-Reviewed-by: Vadim Bendebury Original-Reviewed-by: Julius Werner Reviewed-on: https://review.coreboot.org/15112 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh --- src/mainboard/google/gru/mainboard.c | 8 ++ src/soc/rockchip/rk3399/Makefile.inc | 2 + .../rockchip/rk3399/include/soc/addressmap.h | 3 + src/soc/rockchip/rk3399/include/soc/usb.h | 121 ++++++++++++++++++ src/soc/rockchip/rk3399/romstage.c | 13 ++ src/soc/rockchip/rk3399/usb.c | 107 ++++++++++++++++ 6 files changed, 254 insertions(+) create mode 100644 src/soc/rockchip/rk3399/include/soc/usb.h create mode 100644 src/soc/rockchip/rk3399/usb.c diff --git a/src/mainboard/google/gru/mainboard.c b/src/mainboard/google/gru/mainboard.c index bbe0224693..e6baebe13b 100644 --- a/src/mainboard/google/gru/mainboard.c +++ b/src/mainboard/google/gru/mainboard.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "board.h" @@ -118,12 +119,19 @@ static void configure_display(void) gpio_output(GPIO(4, D, 3), 1); /* CPU3_EDP_VDDEN for P3.3V_DISP */ } +static void setup_usb(void) +{ + setup_usb_drd0_dwc3(); + setup_usb_drd1_dwc3(); +} + static void mainboard_init(device_t dev) { configure_sdmmc(); configure_emmc(); configure_codec(); configure_display(); + setup_usb(); } static void enable_backlight_booster(void) diff --git a/src/soc/rockchip/rk3399/Makefile.inc b/src/soc/rockchip/rk3399/Makefile.inc index 77958d577f..f35f706ff2 100644 --- a/src/soc/rockchip/rk3399/Makefile.inc +++ b/src/soc/rockchip/rk3399/Makefile.inc @@ -47,6 +47,7 @@ romstage-y += ../common/pwm.c romstage-y += timer.c romstage-y += romstage.c romstage-y += tsadc.c +romstage-y += usb.c romstage-y += gpio.c romstage-y += ../common/gpio.c @@ -67,6 +68,7 @@ ramstage-y += saradc.c ramstage-y += soc.c ramstage-y += timer.c ramstage-$(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) += ../common/vop.c +ramstage-y += usb.c BL31_MAKEARGS += PLAT=rk3399 ################################################################################ diff --git a/src/soc/rockchip/rk3399/include/soc/addressmap.h b/src/soc/rockchip/rk3399/include/soc/addressmap.h index 77fca9e6f7..e65674c77c 100644 --- a/src/soc/rockchip/rk3399/include/soc/addressmap.h +++ b/src/soc/rockchip/rk3399/include/soc/addressmap.h @@ -70,6 +70,9 @@ #define DDRC1_BASE_ADDR 0xffa88000 #define SERVER_MSCH1_BASE_ADDR 0xffa8c000 +#define USB_DRD0_DWC3_BASE 0xfe80c100 +#define USB_DRD1_DWC3_BASE 0xfe90c100 + #define IC_BASES { I2C0_BASE, I2C1_BASE, I2C2_BASE, I2C3_BASE, \ I2C4_BASE, I2C5_BASE, I2C6_BASE, I2C7_BASE, I2C8_BASE } diff --git a/src/soc/rockchip/rk3399/include/soc/usb.h b/src/soc/rockchip/rk3399/include/soc/usb.h new file mode 100644 index 0000000000..4276a2b596 --- /dev/null +++ b/src/soc/rockchip/rk3399/include/soc/usb.h @@ -0,0 +1,121 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2016 Rockchip, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __SOC_ROCKCHIP_RK3399_USB_H_ +#define __SOC_ROCKCHIP_RK3399_USB_H_ + +#include + +/* Global constants */ +#define DWC3_GSNPSID_MASK 0xffff0000 +#define DWC3_GSNPSID_SHIFT 16 +#define DWC3_GSNPSREV_MASK 0xffff + +/* Global Configuration Register */ +#define DWC3_GCTL_PWRDNSCALE(n) ((n) << 19) +#define DWC3_GCTL_U2RSTECN (1 << 16) +#define DWC3_GCTL_RAMCLKSEL(x) \ + (((x) & DWC3_GCTL_CLK_MASK) << 6) +#define DWC3_GCTL_CLK_BUS (0) +#define DWC3_GCTL_CLK_PIPE (1) +#define DWC3_GCTL_CLK_PIPEHALF (2) +#define DWC3_GCTL_CLK_MASK (3) +#define DWC3_GCTL_PRTCAP(n) (((n) & (3 << 12)) >> 12) +#define DWC3_GCTL_PRTCAPDIR(n) ((n) << 12) +#define DWC3_GCTL_PRTCAP_HOST 1 +#define DWC3_GCTL_PRTCAP_DEVICE 2 +#define DWC3_GCTL_PRTCAP_OTG 3 +#define DWC3_GCTL_CORESOFTRESET (1 << 11) +#define DWC3_GCTL_SCALEDOWN(n) ((n) << 4) +#define DWC3_GCTL_SCALEDOWN_MASK DWC3_GCTL_SCALEDOWN(3) +#define DWC3_GCTL_DISSCRAMBLE (1 << 3) +#define DWC3_GCTL_DSBLCLKGTNG (1 << 0) + +/* Global HWPARAMS1 Register */ +#define DWC3_GHWPARAMS1_EN_PWROPT(n) (((n) & (3 << 24)) >> 24) +#define DWC3_GHWPARAMS1_EN_PWROPT_NO 0 +#define DWC3_GHWPARAMS1_EN_PWROPT_CLK 1 + +/* Global USB2 PHY Configuration Register */ +#define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31) +#define DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS (1 << 30) +#define DWC3_GUSB2PHYCFG_USBTRDTIM(n) ((n) << 10) +#define DWC3_GUSB2PHYCFG_USB2TRDTIM_MASK DWC3_GUSB2PHYCFG_USBTRDTIM(0xf) +#define DWC3_GUSB2PHYCFG_SUSPHY (1 << 6) +#define DWC3_GUSB2PHYCFG_PHYIF(n) ((n) << 3) +#define DWC3_GUSB2PHYCFG_PHYIF_MASK DWC3_GUSB2PHYCFG_PHYIF(1) +#define USBTRDTIM_UTMI_8_BIT 9 +#define USBTRDTIM_UTMI_16_BIT 5 + +/* Global USB3 PIPE Control Register */ +#define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31) +#define DWC3_GUSB3PIPECTL_SUSPHY (1 << 17) + +struct rockchip_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; + uint32_t hwparams0; + uint32_t hwparams1; + uint32_t hwparams2; + uint32_t hwparams3; + uint32_t hwparams4; + uint32_t hwparams5; + uint32_t hwparams6; + uint32_t hwparams7; + 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 rockchip_usb_drd_dwc3 * const rockchip_usb_drd0_dwc3 = + (void *)USB_DRD0_DWC3_BASE; +static struct rockchip_usb_drd_dwc3 * const rockchip_usb_drd1_dwc3 = + (void *)USB_DRD1_DWC3_BASE; + +/* Call reset _ before setup_ */ +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 /* __SOC_ROCKCHIP_RK3399_USB_H_ */ diff --git a/src/soc/rockchip/rk3399/romstage.c b/src/soc/rockchip/rk3399/romstage.c index ae0264e828..3722813d6d 100644 --- a/src/soc/rockchip/rk3399/romstage.c +++ b/src/soc/rockchip/rk3399/romstage.c @@ -31,6 +31,7 @@ #include #include #include +#include static const uint64_t dram_size = (uint64_t)min((uint64_t)CONFIG_DRAM_SIZE_MB * MiB, MAX_DRAM_ADDRESS); @@ -72,6 +73,16 @@ static void init_dvs_outputs(void) pwm_init(i, 3333, 1904); } +static void prepare_usb(void) +{ + /* + * Do dwc3 core soft reset and phy reset. Kick these resets + * off early so they get at least 100ms to settle. + */ + reset_usb_drd0_dwc3(); + reset_usb_drd1_dwc3(); +} + void main(void) { console_init(); @@ -81,6 +92,8 @@ void main(void) /* Init DVS to conservative values. */ init_dvs_outputs(); + prepare_usb(); + sdram_init(get_sdram_config()); mmu_config_range((void *)0, (uintptr_t)dram_size, CACHED_MEM); diff --git a/src/soc/rockchip/rk3399/usb.c b/src/soc/rockchip/rk3399/usb.c new file mode 100644 index 0000000000..df0305f8c3 --- /dev/null +++ b/src/soc/rockchip/rk3399/usb.c @@ -0,0 +1,107 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2016 Rockchip, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include + +static void reset_dwc3(struct rockchip_usb_drd_dwc3 *dwc3_reg) +{ + /* Before Resetting PHY, put Core in Reset */ + setbits_le32(&dwc3_reg->ctl, DWC3_GCTL_CORESOFTRESET); + /* Assert USB3 PHY reset */ + setbits_le32(&dwc3_reg->usb3pipectl, DWC3_GUSB3PIPECTL_PHYSOFTRST); + /* Assert USB2 PHY reset */ + setbits_le32(&dwc3_reg->usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST); +} + +static void setup_dwc3(struct rockchip_usb_drd_dwc3 *dwc3_reg) +{ + u32 reg; + u32 revision; + u32 dwc3_hwparams1; + + /* Clear USB3 PHY reset */ + clrbits_le32(&dwc3_reg->usb3pipectl, DWC3_GUSB3PIPECTL_PHYSOFTRST); + /* Clear USB2 PHY reset */ + clrbits_le32(&dwc3_reg->usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST); + /* After PHYs are stable we can take Core out of reset state */ + clrbits_le32(&dwc3_reg->ctl, DWC3_GCTL_CORESOFTRESET); + + revision = read32(&dwc3_reg->snpsid); + /* This should read as U3 followed by revision number */ + if ((revision & DWC3_GSNPSID_MASK) != 0x55330000) { + printk(BIOS_ERR, "ERROR: not a DesignWare USB3 DRD Core\n"); + return; + } + + dwc3_hwparams1 = read32(&dwc3_reg->hwparams1); + + reg = read32(&dwc3_reg->ctl); + reg &= ~DWC3_GCTL_SCALEDOWN_MASK; + reg &= ~DWC3_GCTL_DISSCRAMBLE; + if (DWC3_GHWPARAMS1_EN_PWROPT(dwc3_hwparams1) == + DWC3_GHWPARAMS1_EN_PWROPT_CLK) + reg &= ~DWC3_GCTL_DSBLCLKGTNG; + else + printk(BIOS_DEBUG, "No power optimization available\n"); + + write32(&dwc3_reg->ctl, reg); + + /* We are hard-coding DWC3 core to Host Mode */ + clrsetbits_le32(&dwc3_reg->ctl, + DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG), + DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_HOST)); + /* + * Configure USB phy interface of DWC3 core. + * For Rockchip rk3399 SOC DWC3 core: + * 1. Clear U2_FREECLK_EXITS. + * 2. Select UTMI+ PHY with 16-bit interface. + * 3. Set USBTRDTIM to the corresponding value + * according to the UTMI+ PHY interface. + */ + reg = read32(&dwc3_reg->usb2phycfg); + reg &= ~(DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS | + DWC3_GUSB2PHYCFG_USB2TRDTIM_MASK | + DWC3_GUSB2PHYCFG_PHYIF_MASK); + reg |= DWC3_GUSB2PHYCFG_PHYIF(1) | + DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT); + write32(&dwc3_reg->usb2phycfg, reg); +} + +void reset_usb_drd0_dwc3(void) +{ + printk(BIOS_DEBUG, "Starting DWC3 reset for USB DRD0\n"); + reset_dwc3(rockchip_usb_drd0_dwc3); +} + +void reset_usb_drd1_dwc3(void) +{ + printk(BIOS_DEBUG, "Starting DWC3 reset for USB DRD1\n"); + reset_dwc3(rockchip_usb_drd1_dwc3); +} + +void setup_usb_drd0_dwc3(void) +{ + setup_dwc3(rockchip_usb_drd0_dwc3); + printk(BIOS_DEBUG, "DWC3 setup for USB DRD0 finished\n"); +} + +void setup_usb_drd1_dwc3(void) +{ + setup_dwc3(rockchip_usb_drd1_dwc3); + printk(BIOS_DEBUG, "DWC3 setup for USB DRD1 finished\n"); +}