From patchwork Tue Apr 28 06:27:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Wang X-Patchwork-Id: 238723 List-Id: U-Boot discussion From: frank.wang at rock-chips.com (Frank Wang) Date: Tue, 28 Apr 2020 14:27:40 +0800 Subject: [PATCH 1/8] usb: dwc3: add dis_enblslpm_quirk In-Reply-To: <20200428062747.8349-1-frank.wang@rock-chips.com> References: <20200428062747.8349-1-frank.wang@rock-chips.com> Message-ID: <20200428062747.8349-2-frank.wang@rock-chips.com> Add a quirk to clear the GUSB2PHYCFG.ENBLSLPM bit, which controls whether the PHY receives the suspend signal from the controller. Refer to commit ec791d149bca("usb: dwc3: Add dis_enblslpm_quirk") in Linux Kernel. Signed-off-by: Frank Wang Reviewed-by: Kever Yang --- drivers/usb/dwc3/core.c | 6 ++++++ drivers/usb/dwc3/core.h | 1 + include/dwc3-uboot.h | 1 + 3 files changed, 8 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 4ec3f6df6a..a80e7d54aa 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -395,6 +395,9 @@ static void dwc3_phy_setup(struct dwc3 *dwc) if (dwc->dis_u2_susphy_quirk) reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; + if (dwc->dis_enblslpm_quirk) + reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; + dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); mdelay(100); @@ -715,6 +718,7 @@ int dwc3_uboot_init(struct dwc3_device *dwc3_dev) dwc->rx_detect_poll_quirk = dwc3_dev->rx_detect_poll_quirk; dwc->dis_u3_susphy_quirk = dwc3_dev->dis_u3_susphy_quirk; dwc->dis_u2_susphy_quirk = dwc3_dev->dis_u2_susphy_quirk; + dwc->dis_enblslpm_quirk = dwc3_dev->dis_enblslpm_quirk; dwc->tx_de_emphasis_quirk = dwc3_dev->tx_de_emphasis_quirk; if (dwc3_dev->tx_de_emphasis) @@ -975,6 +979,8 @@ void dwc3_of_parse(struct dwc3 *dwc) "snps,dis_u3_susphy_quirk"); dwc->dis_u2_susphy_quirk = dev_read_bool(dev, "snps,dis_u2_susphy_quirk"); + dwc->dis_enblslpm_quirk = dev_read_bool(dev, + "snps,dis_enblslpm_quirk"); dwc->tx_de_emphasis_quirk = dev_read_bool(dev, "snps,tx_de_emphasis_quirk"); tmp = dev_read_u8_array_ptr(dev, "snps,tx_de_emphasis", 1); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 1c08a2c5b6..eabbc30f25 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -821,6 +821,7 @@ struct dwc3 { unsigned rx_detect_poll_quirk:1; unsigned dis_u3_susphy_quirk:1; unsigned dis_u2_susphy_quirk:1; + unsigned dis_enblslpm_quirk:1; unsigned tx_de_emphasis_quirk:1; unsigned tx_de_emphasis:2; diff --git a/include/dwc3-uboot.h b/include/dwc3-uboot.h index 3c9e204cf0..fd3f173c37 100644 --- a/include/dwc3-uboot.h +++ b/include/dwc3-uboot.h @@ -32,6 +32,7 @@ struct dwc3_device { unsigned rx_detect_poll_quirk; unsigned dis_u3_susphy_quirk; unsigned dis_u2_susphy_quirk; + unsigned dis_enblslpm_quirk; unsigned tx_de_emphasis_quirk; unsigned tx_de_emphasis; int index; From patchwork Tue Apr 28 06:27:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Wang X-Patchwork-Id: 238724 List-Id: U-Boot discussion From: frank.wang at rock-chips.com (Frank Wang) Date: Tue, 28 Apr 2020 14:27:41 +0800 Subject: [PATCH 2/8] usb: dwc3: add dis_u2_freeclk_exists_quirk In-Reply-To: <20200428062747.8349-1-frank.wang@rock-chips.com> References: <20200428062747.8349-1-frank.wang@rock-chips.com> Message-ID: <20200428062747.8349-3-frank.wang@rock-chips.com> Add a quirk to clear the GUSB2PHYCFG.U2_FREECLK_EXISTS bit, which specifies whether the USB2.0 PHY provides a free-running PHY clock, which is active when the clock control input is active. Refer to commit 27f83eeb6b42("usb: dwc3: add dis_u2_freeclk_exists_quirk") in Linux Rockchip Kernel. Signed-off-by: Frank Wang Reviewed-by: Kever Yang --- drivers/usb/dwc3/core.c | 6 ++++++ drivers/usb/dwc3/core.h | 2 ++ include/dwc3-uboot.h | 1 + 3 files changed, 9 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index a80e7d54aa..3c81a07dad 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -398,6 +398,9 @@ static void dwc3_phy_setup(struct dwc3 *dwc) if (dwc->dis_enblslpm_quirk) reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; + if (dwc->dis_u2_freeclk_exists_quirk) + reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS; + dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); mdelay(100); @@ -719,6 +722,7 @@ int dwc3_uboot_init(struct dwc3_device *dwc3_dev) dwc->dis_u3_susphy_quirk = dwc3_dev->dis_u3_susphy_quirk; dwc->dis_u2_susphy_quirk = dwc3_dev->dis_u2_susphy_quirk; dwc->dis_enblslpm_quirk = dwc3_dev->dis_enblslpm_quirk; + dwc->dis_u2_freeclk_exists_quirk = dwc3_dev->dis_u2_freeclk_exists_quirk; dwc->tx_de_emphasis_quirk = dwc3_dev->tx_de_emphasis_quirk; if (dwc3_dev->tx_de_emphasis) @@ -981,6 +985,8 @@ void dwc3_of_parse(struct dwc3 *dwc) "snps,dis_u2_susphy_quirk"); dwc->dis_enblslpm_quirk = dev_read_bool(dev, "snps,dis_enblslpm_quirk"); + dwc->dis_u2_freeclk_exists_quirk = dev_read_bool(dev, + "snps,dis-u2-freeclk-exists-quirk"); dwc->tx_de_emphasis_quirk = dev_read_bool(dev, "snps,tx_de_emphasis_quirk"); tmp = dev_read_u8_array_ptr(dev, "snps,tx_de_emphasis", 1); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index eabbc30f25..86a697d1bd 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -161,6 +161,7 @@ /* Global USB2 PHY Configuration Register */ #define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31) +#define DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS (1 << 30) #define DWC3_GUSB2PHYCFG_SUSPHY (1 << 6) #define DWC3_GUSB2PHYCFG_PHYIF(n) ((n) << 3) #define DWC3_GUSB2PHYCFG_PHYIF_MASK DWC3_GUSB2PHYCFG_PHYIF(1) @@ -822,6 +823,7 @@ struct dwc3 { unsigned dis_u3_susphy_quirk:1; unsigned dis_u2_susphy_quirk:1; unsigned dis_enblslpm_quirk:1; + unsigned dis_u2_freeclk_exists_quirk:1; unsigned tx_de_emphasis_quirk:1; unsigned tx_de_emphasis:2; diff --git a/include/dwc3-uboot.h b/include/dwc3-uboot.h index fd3f173c37..952ad64c35 100644 --- a/include/dwc3-uboot.h +++ b/include/dwc3-uboot.h @@ -33,6 +33,7 @@ struct dwc3_device { unsigned dis_u3_susphy_quirk; unsigned dis_u2_susphy_quirk; unsigned dis_enblslpm_quirk; + unsigned dis_u2_freeclk_exists_quirk; unsigned tx_de_emphasis_quirk; unsigned tx_de_emphasis; int index; From patchwork Tue Apr 28 06:27:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Wang X-Patchwork-Id: 238722 List-Id: U-Boot discussion From: frank.wang at rock-chips.com (Frank Wang) Date: Tue, 28 Apr 2020 14:27:42 +0800 Subject: [PATCH 3/8] usb: dwc3: amend UTMI/UTMIW phy interface setup In-Reply-To: <20200428062747.8349-1-frank.wang@rock-chips.com> References: <20200428062747.8349-1-frank.wang@rock-chips.com> Message-ID: <20200428062747.8349-4-frank.wang@rock-chips.com> Let move 8/16-bit UTMI+ interface initialization into DWC3 core init that is convenient for both DM_USB and u-boot traditional process. Signed-off-by: Frank Wang Reviewed-by: Kever Yang --- drivers/usb/common/common.c | 25 ++++++++++++++ drivers/usb/dwc3/core.c | 65 +++++++++++++++++++------------------ drivers/usb/dwc3/core.h | 5 +++ include/linux/usb/phy.h | 18 ++++++++++ 4 files changed, 82 insertions(+), 31 deletions(-) diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c index 0db281b970..48b0a9a5f1 100644 --- a/drivers/usb/common/common.c +++ b/drivers/usb/common/common.c @@ -10,6 +10,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -64,3 +65,27 @@ enum usb_device_speed usb_get_maximum_speed(ofnode node) return USB_SPEED_UNKNOWN; } + +#if CONFIG_IS_ENABLED(OF_LIVE) && CONFIG_IS_ENABLED(DM_USB) +static const char *const usbphy_modes[] = { + [USBPHY_INTERFACE_MODE_UNKNOWN] = "", + [USBPHY_INTERFACE_MODE_UTMI] = "utmi", + [USBPHY_INTERFACE_MODE_UTMIW] = "utmi_wide", +}; + +enum usb_phy_interface usb_get_phy_mode(ofnode node) +{ + const char *phy_type; + int i; + + phy_type = ofnode_get_property(node, "phy_type", NULL); + if (!phy_type) + return USBPHY_INTERFACE_MODE_UNKNOWN; + + for (i = 0; i < ARRAY_SIZE(usbphy_modes); i++) + if (!strcmp(phy_type, usbphy_modes[i])) + return i; + + return USBPHY_INTERFACE_MODE_UNKNOWN; +} +#endif diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 3c81a07dad..487be1f3b0 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -334,6 +334,34 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc) parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); } +static void dwc3_hsphy_mode_setup(struct dwc3 *dwc) +{ + enum usb_phy_interface hsphy_mode = dwc->hsphy_mode; + u32 reg; + + /* Set dwc3 usb2 phy config */ + reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); + + switch (hsphy_mode) { + case USBPHY_INTERFACE_MODE_UTMI: + reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK | + DWC3_GUSB2PHYCFG_USBTRDTIM_MASK); + reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) | + DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT); + break; + case USBPHY_INTERFACE_MODE_UTMIW: + reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK | + DWC3_GUSB2PHYCFG_USBTRDTIM_MASK); + reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_16_BIT) | + DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT); + break; + default: + break; + } + + dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); +} + /** * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core * @dwc: Pointer to our controller context structure @@ -379,6 +407,8 @@ static void dwc3_phy_setup(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); + dwc3_hsphy_mode_setup(dwc); + mdelay(100); reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); @@ -623,35 +653,6 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc) dwc3_gadget_run(dwc); } -static void dwc3_uboot_hsphy_mode(struct dwc3_device *dwc3_dev, - struct dwc3 *dwc) -{ - enum usb_phy_interface hsphy_mode = dwc3_dev->hsphy_mode; - u32 reg; - - /* Set dwc3 usb2 phy config */ - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); - - switch (hsphy_mode) { - case USBPHY_INTERFACE_MODE_UTMI: - reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK | - DWC3_GUSB2PHYCFG_USBTRDTIM_MASK); - reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) | - DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT); - break; - case USBPHY_INTERFACE_MODE_UTMIW: - reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK | - DWC3_GUSB2PHYCFG_USBTRDTIM_MASK); - reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_16_BIT) | - DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT); - break; - default: - break; - } - - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); -} - #define DWC3_ALIGN_MASK (16 - 1) /** @@ -738,6 +739,8 @@ int dwc3_uboot_init(struct dwc3_device *dwc3_dev) dwc->hird_threshold = hird_threshold | (dwc->is_utmi_l1_suspend << 4); + dwc->hsphy_mode = dwc3_dev->hsphy_mode; + dwc->index = dwc3_dev->index; dwc3_cache_hwparams(dwc); @@ -762,8 +765,6 @@ int dwc3_uboot_init(struct dwc3_device *dwc3_dev) goto err0; } - dwc3_uboot_hsphy_mode(dwc3_dev, dwc); - ret = dwc3_event_buffers_setup(dwc); if (ret) { dev_err(dwc->dev, "failed to setup event buffers\n"); @@ -951,6 +952,8 @@ void dwc3_of_parse(struct dwc3 *dwc) */ hird_threshold = 12; + dwc->hsphy_mode = usb_get_phy_mode(dev->node); + dwc->has_lpm_erratum = dev_read_bool(dev, "snps,has-lpm-erratum"); tmp = dev_read_u8_array_ptr(dev, "snps,lpm-nyet-threshold", 1); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 86a697d1bd..8552f80344 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -21,6 +21,7 @@ #include #include +#include #define DWC3_MSG_MAX 500 @@ -649,6 +650,9 @@ struct dwc3_scratchpad_array { * @maximum_speed: maximum speed requested (mainly for testing purposes) * @revision: revision register contents * @dr_mode: requested mode of operation + * @hsphy_mode: UTMI phy mode, one of following: + * - USBPHY_INTERFACE_MODE_UTMI + * - USBPHY_INTERFACE_MODE_UTMIW * @dcfg: saved contents of DCFG register * @gctl: saved contents of GCTL register * @isoch_delay: wValue from Set Isochronous Delay request; @@ -740,6 +744,7 @@ struct dwc3 { size_t regs_size; enum usb_dr_mode dr_mode; + enum usb_phy_interface hsphy_mode; /* used for suspend/resume */ u32 dcfg; diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h index 158ca9cd85..e4924ffe68 100644 --- a/include/linux/usb/phy.h +++ b/include/linux/usb/phy.h @@ -10,10 +10,28 @@ #ifndef __LINUX_USB_PHY_H #define __LINUX_USB_PHY_H +#include + enum usb_phy_interface { USBPHY_INTERFACE_MODE_UNKNOWN, USBPHY_INTERFACE_MODE_UTMI, USBPHY_INTERFACE_MODE_UTMIW, }; +#if CONFIG_IS_ENABLED(OF_LIVE) && CONFIG_IS_ENABLED(DM_USB) +/** + * usb_get_phy_mode - Get phy mode for given device_node + * @np: Pointer to the given device_node + * + * The function gets phy interface string from property 'phy_type', + * and returns the corresponding enum usb_phy_interface + */ +enum usb_phy_interface usb_get_phy_mode(ofnode node); +#else +static inline enum usb_phy_interface usb_get_phy_mode(ofnode node) +{ + return USBPHY_INTERFACE_MODE_UNKNOWN; +} +#endif + #endif /* __LINUX_USB_PHY_H */ From patchwork Tue Apr 28 06:27:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Wang X-Patchwork-Id: 238725 List-Id: U-Boot discussion From: frank.wang at rock-chips.com (Frank Wang) Date: Tue, 28 Apr 2020 14:27:43 +0800 Subject: [PATCH 4/8] usb: dwc3: add make compatible for rockchip platform In-Reply-To: <20200428062747.8349-1-frank.wang@rock-chips.com> References: <20200428062747.8349-1-frank.wang@rock-chips.com> Message-ID: <20200428062747.8349-5-frank.wang@rock-chips.com> RK3399 Type-C PHY is required that must hold whole USB3.0 OTG controller in resetting to hold pipe power state in P2 before initializing the PHY. This commit fixed it and added device compatible for rockchip platform. Signed-off-by: Frank Wang --- drivers/usb/dwc3/dwc3-generic.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index febcfc0f54..0031e8bf44 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -24,6 +24,12 @@ #include #include +struct dwc3_glue_data { + struct clk_bulk clks; + struct reset_ctl_bulk resets; + fdt_addr_t regs; +}; + struct dwc3_generic_plat { fdt_addr_t base; u32 maximum_speed; @@ -48,6 +54,7 @@ static int dwc3_generic_probe(struct udevice *dev, int rc; struct dwc3_generic_plat *plat = dev_get_platdata(dev); struct dwc3 *dwc3 = &priv->dwc3; + struct dwc3_glue_data *glue = dev_get_platdata(dev->parent); dwc3->dev = dev; dwc3->maximum_speed = plat->maximum_speed; @@ -56,10 +63,22 @@ static int dwc3_generic_probe(struct udevice *dev, dwc3_of_parse(dwc3); #endif + /* + * It must hold whole USB3.0 OTG controller in resetting to hold pipe + * power state in P2 before initializing TypeC PHY on RK3399 platform. + */ + if (device_is_compatible(dev->parent, "rockchip,rk3399-dwc3")) { + reset_assert_bulk(&glue->resets); + udelay(1); + } + rc = dwc3_setup_phy(dev, &priv->phys, &priv->num_phys); if (rc) return rc; + if (device_is_compatible(dev->parent, "rockchip,rk3399-dwc3")) + reset_deassert_bulk(&glue->resets); + priv->base = map_physmem(plat->base, DWC3_OTG_REGS_END, MAP_NOCACHE); dwc3->regs = priv->base + DWC3_GLOBALS_REGS_START; @@ -187,12 +206,6 @@ U_BOOT_DRIVER(dwc3_generic_host) = { }; #endif -struct dwc3_glue_data { - struct clk_bulk clks; - struct reset_ctl_bulk resets; - fdt_addr_t regs; -}; - struct dwc3_glue_ops { void (*select_dr_mode)(struct udevice *dev, int index, enum usb_dr_mode mode); @@ -395,6 +408,12 @@ static int dwc3_glue_probe(struct udevice *dev) if (ret) return ret; + if (glue->resets.count < 1) { + ret = dwc3_glue_reset_init(child, glue); + if (ret) + return ret; + } + while (child) { enum usb_dr_mode dr_mode; @@ -425,6 +444,8 @@ static const struct udevice_id dwc3_glue_ids[] = { { .compatible = "ti,dwc3", .data = (ulong)&ti_ops }, { .compatible = "ti,am437x-dwc3", .data = (ulong)&ti_ops }, { .compatible = "ti,am654-dwc3" }, + { .compatible = "rockchip,rk3328-dwc3" }, + { .compatible = "rockchip,rk3399-dwc3" }, { } }; From patchwork Tue Apr 28 06:31:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Wang X-Patchwork-Id: 238727 List-Id: U-Boot discussion From: frank.wang at rock-chips.com (Frank Wang) Date: Tue, 28 Apr 2020 14:31:39 +0800 Subject: [PATCH 5/8] phy: rockchip: add a new driver for type-c phy In-Reply-To: <20200428062747.8349-1-frank.wang@rock-chips.com> References: <20200428062747.8349-1-frank.wang@rock-chips.com> Message-ID: <20200428063139.8447-1-frank.wang@rock-chips.com> This implements the Type-C PHY driver for Rockchip platform with Cadence IP block. Signed-off-by: Frank Wang Signed-off-by: William Wu --- drivers/phy/Kconfig | 6 + drivers/phy/Makefile | 1 + drivers/phy/phy-rockchip-typec.c | 534 +++++++++++++++++++++++++ include/linux/usb/rockchip_phy_typec.h | 52 +++ 4 files changed, 593 insertions(+) create mode 100644 drivers/phy/phy-rockchip-typec.c create mode 100644 include/linux/usb/rockchip_phy_typec.h diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index a72f34f0d4..c8472ef245 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -90,6 +90,12 @@ config PHY_DA8XX_USB help Enable this to support the USB PHY on DA8xx SoCs. +config PHY_ROCKCHIP_TYPEC + bool "Support Rockchip TYPEC PHY Driver" + depends on PHY && ARCH_ROCKCHIP + help + Enable this to support the Rockchip USB Type-C PHY. + config PIPE3_PHY bool "Support omap's PIPE3 PHY" depends on PHY && ARCH_OMAP2PLUS diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 43ce62e08c..9ed721b1d5 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_AM654_PHY) += phy-ti-am654.o obj-$(CONFIG_STI_USB_PHY) += sti_usb_phy.o obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o obj-$(CONFIG_PHY_RCAR_GEN3) += phy-rcar-gen3.o +obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o obj-$(CONFIG_PHY_STM32_USBPHYC) += phy-stm32-usbphyc.o obj-$(CONFIG_MESON_GXL_USB_PHY) += meson-gxl-usb2.o meson-gxl-usb3.o obj-$(CONFIG_MESON_G12A_USB_PHY) += meson-g12a-usb2.o meson-g12a-usb3-pcie.o diff --git a/drivers/phy/phy-rockchip-typec.c b/drivers/phy/phy-rockchip-typec.c new file mode 100644 index 0000000000..cd0f055bd4 --- /dev/null +++ b/drivers/phy/phy-rockchip-typec.c @@ -0,0 +1,534 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Rockchip Electronics Co., Ltd + * + * Based on drivers/phy/rockchip/phy-rockchip-typec.c in Linux Kernel. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CMN_PLL0_VCOCAL_OVRD (0x83 << 2) +#define CMN_PLL0_VCOCAL_INIT (0x84 << 2) +#define CMN_PLL0_VCOCAL_ITER (0x85 << 2) +#define CMN_PLL0_LOCK_REFCNT_START (0x90 << 2) +#define CMN_PLL0_LOCK_PLLCNT_START (0x92 << 2) +#define CMN_PLL0_LOCK_PLLCNT_THR (0x93 << 2) +#define CMN_PLL0_INTDIV (0x94 << 2) +#define CMN_PLL0_FRACDIV (0x95 << 2) +#define CMN_PLL0_HIGH_THR (0x96 << 2) +#define CMN_PLL0_DSM_DIAG (0x97 << 2) +#define CMN_PLL0_SS_CTRL1 (0x98 << 2) +#define CMN_PLL0_SS_CTRL2 (0x99 << 2) +#define CMN_DIAG_PLL0_FBH_OVRD (0x1c0 << 2) +#define CMN_DIAG_PLL0_FBL_OVRD (0x1c1 << 2) +#define CMN_DIAG_PLL0_OVRD (0x1c2 << 2) +#define CMN_DIAG_PLL0_V2I_TUNE (0x1c5 << 2) +#define CMN_DIAG_PLL0_CP_TUNE (0x1c6 << 2) +#define CMN_DIAG_PLL0_LF_PROG (0x1c7 << 2) +#define CMN_DIAG_HSCLK_SEL (0x1e0 << 2) + +#define TX_TXCC_MGNFS_MULT_000(n) ((0x4050 | ((n) << 9)) << 2) +#define XCVR_DIAG_PLLDRC_CTRL(n) ((0x40e0 | ((n) << 9)) << 2) +#define XCVR_DIAG_BIDI_CTRL(n) ((0x40e8 | ((n) << 9)) << 2) +#define XCVR_DIAG_LANE_FCM_EN_MGN(n) ((0x40f2 | ((n) << 9)) << 2) +#define TX_PSC_A0(n) ((0x4100 | ((n) << 9)) << 2) +#define TX_PSC_A1(n) ((0x4101 | ((n) << 9)) << 2) +#define TX_PSC_A2(n) ((0x4102 | ((n) << 9)) << 2) +#define TX_PSC_A3(n) ((0x4103 | ((n) << 9)) << 2) +#define TX_RCVDET_CTRL(n) ((0x4120 | ((n) << 9)) << 2) +#define TX_RCVDET_EN_TMR(n) ((0x4122 | ((n) << 9)) << 2) +#define TX_RCVDET_ST_TMR(n) ((0x4123 | ((n) << 9)) << 2) +#define TX_DIAG_TX_DRV(n) ((0x41e1 | ((n) << 9)) << 2) +#define TX_DIAG_BGREF_PREDRV_DELAY (0x41e7 << 2) + +#define RX_PSC_A0(n) ((0x8000 | ((n) << 9)) << 2) +#define RX_PSC_A1(n) ((0x8001 | ((n) << 9)) << 2) +#define RX_PSC_A2(n) ((0x8002 | ((n) << 9)) << 2) +#define RX_PSC_A3(n) ((0x8003 | ((n) << 9)) << 2) +#define RX_PSC_CAL(n) ((0x8006 | ((n) << 9)) << 2) +#define RX_PSC_RDY(n) ((0x8007 | ((n) << 9)) << 2) +#define RX_SIGDET_HL_FILT_TMR(n) ((0x8090 | ((n) << 9)) << 2) +#define RX_REE_CTRL_DATA_MASK(n) ((0x81bb | ((n) << 9)) << 2) +#define RX_DIAG_SIGDET_TUNE(n) ((0x81dc | ((n) << 9)) << 2) +#define RX_DIAG_SC2C_DELAY (0x81e1 << 2) + +#define PHY_ISO_CMN_CTRL (0xc010 << 2) +#define PMA_CMN_CTRL1 (0xc800 << 2) +#define PHY_PMA_ISO_CMN_CTRL (0xc810 << 2) +#define PHY_ISOLATION_CTRL (0xc81f << 2) +#define PHY_PMA_ISO_XCVR_CTRL(n) ((0xcc11 | ((n) << 6)) << 2) +#define PHY_PMA_ISO_LINK_MODE(n) ((0xcc12 | ((n) << 6)) << 2) +#define PHY_PMA_ISO_PWRST_CTRL(n) ((0xcc13 | ((n) << 6)) << 2) +#define PHY_PMA_ISO_TX_DATA_LO(n) ((0xcc14 | ((n) << 6)) << 2) +#define PHY_PMA_ISO_TX_DATA_HI(n) ((0xcc15 | ((n) << 6)) << 2) +#define PHY_PMA_ISO_RX_DATA_LO(n) ((0xcc16 | ((n) << 6)) << 2) +#define PHY_PMA_ISO_RX_DATA_HI(n) ((0xcc17 | ((n) << 6)) << 2) + +/* + * Selects which PLL clock will be driven on the analog high speed + * clock 0: PLL 0 div 1 + * clock 1: PLL 1 div 2 + */ +#define CLK_PLL1_DIV1 0x20 +#define CLK_PLL1_DIV2 0x30 +#define CLK_PLL_MASK 0x33 + +#define CMN_READY BIT(0) +#define PHY_MODE_SET_TIMEOUT 100000 +#define MODE_DISCONNECT 0 +#define MODE_UFP_USB BIT(0) +#define MODE_DFP_USB BIT(1) +#define POWER_ON_TRIES 5 + +struct phy_reg { + u16 value; + u32 addr; +}; + +static const struct phy_reg usb3_pll_cfg[] = { + { 0xf0, CMN_PLL0_VCOCAL_INIT }, + { 0x18, CMN_PLL0_VCOCAL_ITER }, + { 0xd0, CMN_PLL0_INTDIV }, + { 0x4a4a, CMN_PLL0_FRACDIV }, + { 0x34, CMN_PLL0_HIGH_THR }, + { 0x1ee, CMN_PLL0_SS_CTRL1 }, + { 0x7f03, CMN_PLL0_SS_CTRL2 }, + { 0x20, CMN_PLL0_DSM_DIAG }, + { 0, CMN_DIAG_PLL0_OVRD }, + { 0, CMN_DIAG_PLL0_FBH_OVRD }, + { 0, CMN_DIAG_PLL0_FBL_OVRD }, + { 0x7, CMN_DIAG_PLL0_V2I_TUNE }, + { 0x45, CMN_DIAG_PLL0_CP_TUNE }, + { 0x8, CMN_DIAG_PLL0_LF_PROG }, +}; + +static void tcphy_cfg_24m(struct rockchip_typec_phy *tcphy) +{ + u32 i, rdata; + + /* + * cmn_ref_clk_sel = 3, select the 24Mhz for clk parent + * cmn_psm_clk_dig_div = 2, set the clk division to 2 + */ + writel(0x830, tcphy->base + PMA_CMN_CTRL1); + for (i = 0; i < 4; i++) { + /* + * The following PHY configuration assumes a 24 MHz reference + * clock. + */ + writel(0x90, tcphy->base + XCVR_DIAG_LANE_FCM_EN_MGN(i)); + writel(0x960, tcphy->base + TX_RCVDET_EN_TMR(i)); + writel(0x30, tcphy->base + TX_RCVDET_ST_TMR(i)); + } + + rdata = readl(tcphy->base + CMN_DIAG_HSCLK_SEL); + rdata &= ~CLK_PLL_MASK; + rdata |= CLK_PLL1_DIV2; + writel(rdata, tcphy->base + CMN_DIAG_HSCLK_SEL); +} + +static void tcphy_cfg_usb3_pll(struct rockchip_typec_phy *tcphy) +{ + u32 i; + + /* load the configuration of PLL0 */ + for (i = 0; i < ARRAY_SIZE(usb3_pll_cfg); i++) + writel(usb3_pll_cfg[i].value, + tcphy->base + usb3_pll_cfg[i].addr); +} + +static void tcphy_tx_usb3_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane) +{ + writel(0x7799, tcphy->base + TX_PSC_A0(lane)); + writel(0x7798, tcphy->base + TX_PSC_A1(lane)); + writel(0x5098, tcphy->base + TX_PSC_A2(lane)); + writel(0x5098, tcphy->base + TX_PSC_A3(lane)); + writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane)); + writel(0xbf, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane)); +} + +static void tcphy_rx_usb3_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane) +{ + writel(0xa6fd, tcphy->base + RX_PSC_A0(lane)); + writel(0xa6fd, tcphy->base + RX_PSC_A1(lane)); + writel(0xa410, tcphy->base + RX_PSC_A2(lane)); + writel(0x2410, tcphy->base + RX_PSC_A3(lane)); + writel(0x23ff, tcphy->base + RX_PSC_CAL(lane)); + writel(0x13, tcphy->base + RX_SIGDET_HL_FILT_TMR(lane)); + writel(0x03e7, tcphy->base + RX_REE_CTRL_DATA_MASK(lane)); + writel(0x1004, tcphy->base + RX_DIAG_SIGDET_TUNE(lane)); + writel(0x2010, tcphy->base + RX_PSC_RDY(lane)); + writel(0xfb, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane)); +} + +static inline int property_enable(struct rockchip_typec_phy *tcphy, + const struct usb3phy_reg *reg, bool en) +{ + u32 mask = 1 << reg->write_enable; + u32 val = en << reg->enable_bit; + + return writel((val | mask), (tcphy->grf_regs + reg->offset)); +} + +static int tcphy_cfg_usb3_to_usb2_only(struct rockchip_typec_phy *tcphy, + bool value) +{ + struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs; + + property_enable(tcphy, &cfg->usb3tousb2_en, value); + property_enable(tcphy, &cfg->usb3host_disable, value); + property_enable(tcphy, &cfg->usb3host_port, !value); + + return 0; +} + +static int tcphy_phy_init(struct rockchip_typec_phy *tcphy) +{ + struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs; + int ret; + u32 val; + + reset_deassert(&tcphy->tcphy_rst); + + property_enable(tcphy, &cfg->typec_conn_dir, tcphy->flip); + + tcphy_cfg_24m(tcphy); + + tcphy_cfg_usb3_pll(tcphy); + if (tcphy->flip) { + tcphy_tx_usb3_cfg_lane(tcphy, 3); + tcphy_rx_usb3_cfg_lane(tcphy, 2); + } else { + tcphy_tx_usb3_cfg_lane(tcphy, 0); + tcphy_rx_usb3_cfg_lane(tcphy, 1); + } + + reset_deassert(&tcphy->uphy_rst); + + ret = readx_poll_timeout(readl, tcphy->base + PMA_CMN_CTRL1, + val, val & CMN_READY, PHY_MODE_SET_TIMEOUT); + if (ret < 0) { + dev_err(tcphy->dev, "wait pma ready timeout\n"); + ret = -ETIMEDOUT; + goto err_wait_pma; + } + + reset_deassert(&tcphy->pipe_rst); + + return 0; + +err_wait_pma: + reset_assert(&tcphy->uphy_rst); + reset_assert(&tcphy->tcphy_rst); + return ret; +} + +static void tcphy_phy_deinit(struct rockchip_typec_phy *tcphy) +{ + reset_assert(&tcphy->tcphy_rst); + reset_assert(&tcphy->uphy_rst); + reset_assert(&tcphy->pipe_rst); +} + +static int tcphy_get_mode(struct rockchip_typec_phy *tcphy) +{ + u8 mode = MODE_DFP_USB | MODE_UFP_USB; + + tcphy->flip = 0; + + return mode; +} + +static int _rockchip_usb3_phy_power_on(struct rockchip_typec_phy *tcphy) +{ + struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs; + const struct usb3phy_reg *reg = &cfg->pipe_status; + int timeout, new_mode, ret = 0; + u32 val; + + mutex_lock(&tcphy->lock); + + new_mode = tcphy_get_mode(tcphy); + + if (tcphy->mode == new_mode) + goto unlock_ret; + + if (tcphy->mode == MODE_DISCONNECT) { + ret = tcphy_phy_init(tcphy); + if (ret) + goto unlock_ret; + } + + /* wait TCPHY for pipe ready */ + for (timeout = 0; timeout < 100; timeout++) { + val = readl(tcphy->grf_regs + reg->offset); + if (!(val & BIT(reg->enable_bit))) { + tcphy->mode |= new_mode & (MODE_DFP_USB | MODE_UFP_USB); + + /* enable usb3 host */ + tcphy_cfg_usb3_to_usb2_only(tcphy, false); + goto unlock_ret; + } + udelay(20); + } + + if (tcphy->mode == MODE_DISCONNECT) + tcphy_phy_deinit(tcphy); + + ret = -ETIMEDOUT; + +unlock_ret: + mutex_unlock(&tcphy->lock); + return ret; +} + +static int rockchip_usb3_phy_power_on(struct phy *phy) +{ + struct udevice *parent = dev_get_parent(phy->dev); + struct rockchip_typec_phy *tcphy = dev_get_priv(parent); + int ret; + int tries; + + for (tries = 0; tries < POWER_ON_TRIES; tries++) { + ret = _rockchip_usb3_phy_power_on(tcphy); + if (!ret) + break; + } + + if (tries && !ret) + dev_err(tcphy->dev, "Needed %d loops to turn on\n", tries); + + return ret; +} + +static int rockchip_usb3_phy_power_off(struct phy *phy) +{ + struct udevice *parent = dev_get_parent(phy->dev); + struct rockchip_typec_phy *tcphy = dev_get_priv(parent); + + mutex_lock(&tcphy->lock); + + if (tcphy->mode == MODE_DISCONNECT) + goto unlock; + + tcphy->mode = MODE_DISCONNECT; + tcphy_phy_deinit(tcphy); + +unlock: + mutex_unlock(&tcphy->lock); + return 0; +} + +static const struct phy_ops rockchip_usb3_phy_ops = { + .power_on = rockchip_usb3_phy_power_on, + .power_off = rockchip_usb3_phy_power_off, +}; + +int rockchip_u3phy_uboot_init(const char *name) +{ + struct udevice *udev; + struct rockchip_typec_phy *tcphy; + int tries; + int ret; + + ret = uclass_get_device_by_name(UCLASS_PHY, name, &udev); + if (ret) { + pr_err("%s: get usb3-phy failed: %d\n", __func__, ret); + return ret; + } + + /* Initialize OTG PHY */ + tcphy = dev_get_priv(udev); + for (tries = 0; tries < POWER_ON_TRIES; tries++) { + ret = _rockchip_usb3_phy_power_on(tcphy); + if (!ret) + break; + } + + if (tries && !ret) + pr_err("%s: needed %d loops to turn on\n", __func__, tries); + + return ret; +} + +static int tcphy_get_param(struct udevice *dev, + struct usb3phy_reg *reg, + const char *name) +{ + u32 buffer[3]; + int ret; + + ret = dev_read_u32_array(dev, name, buffer, 3); + if (ret) { + pr_err("%s: Can not parse %s\n", __func__, name); + return ret; + } + + reg->offset = buffer[0]; + reg->enable_bit = buffer[1]; + reg->write_enable = buffer[2]; + + return 0; +} + +static int tcphy_parse_dt(struct rockchip_typec_phy *tcphy, + struct udevice *dev) +{ + struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs; + int ret; + + ret = tcphy_get_param(dev, &cfg->typec_conn_dir, + "rockchip,typec-conn-dir"); + if (ret) + return ret; + + ret = tcphy_get_param(dev, &cfg->usb3tousb2_en, + "rockchip,usb3tousb2-en"); + if (ret) + return ret; + + ret = tcphy_get_param(dev, &cfg->usb3host_disable, + "rockchip,usb3-host-disable"); + if (ret) + return ret; + + ret = tcphy_get_param(dev, &cfg->usb3host_port, + "rockchip,usb3-host-port"); + if (ret) + return ret; + + ret = tcphy_get_param(dev, &cfg->external_psm, + "rockchip,external-psm"); + if (ret) + return ret; + + ret = tcphy_get_param(dev, &cfg->pipe_status, + "rockchip,pipe-status"); + if (ret) + return ret; + + tcphy->grf_regs = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + if (IS_ERR(tcphy->grf_regs)) { + dev_err(dev, "could not find grf dt node\n"); + return PTR_ERR(tcphy->grf_regs); + } + + ret = reset_get_by_name(dev, "uphy", &tcphy->uphy_rst); + if (ret) { + dev_err(dev, "no uphy_rst reset control found\n"); + return ret; + } + + ret = reset_get_by_name(dev, "uphy-pipe", &tcphy->pipe_rst); + if (ret) { + dev_err(dev, "no pipe_rst reset control found\n"); + return ret; + } + + ret = reset_get_by_name(dev, "uphy-pipe", &tcphy->tcphy_rst); + if (ret) { + dev_err(dev, "no tcphy_rst reset control found\n"); + return ret; + } + + return 0; +} + +static void typec_phy_pre_init(struct rockchip_typec_phy *tcphy) +{ + struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs; + + reset_assert(&tcphy->tcphy_rst); + reset_assert(&tcphy->uphy_rst); + reset_assert(&tcphy->pipe_rst); + + /* select external psm clock */ + property_enable(tcphy, &cfg->external_psm, 1); + property_enable(tcphy, &cfg->usb3tousb2_en, 0); + + tcphy->mode = MODE_DISCONNECT; +} + +static int rockchip_typec_phy_bind(struct udevice *parent) +{ + struct udevice *dev; + ofnode node; + const char *name; + int ret; + + dev_for_each_subnode(node, parent) { + if (!ofnode_valid(node)) { + debug("%s: %s subnode not found", __func__, parent->name); + return -ENXIO; + } + + name = ofnode_get_name(node); + debug("%s: subnode %s\n", __func__, name); + + if (!strcasecmp(name, "usb3-port")) { + ret = device_bind_driver_to_node(parent, "rockchip_typec_phy_port", + name, node, &dev); + if (ret) { + pr_err("%s: '%s' cannot bind 'rockchip_typec_phy_port'\n", + __func__, name); + return ret; + } + } + } + + return 0; +} + +static int rockchip_typec_phy_probe(struct udevice *udev) +{ + struct rockchip_typec_phy *tcphy = dev_get_priv(udev); + int ret; + + tcphy->base = (void __iomem *)dev_read_addr(udev); + if (IS_ERR(tcphy->base)) + return PTR_ERR(tcphy->base); + + ret = tcphy_parse_dt(tcphy, udev); + if (ret) + return ret; + + tcphy->dev = udev; + mutex_init(&tcphy->lock); + + typec_phy_pre_init(tcphy); + + printf("Rockchip Type-C PHY is initialized\n"); + return 0; +} + +static const struct udevice_id rockchip_typec_phy_dt_ids[] = { + { .compatible = "rockchip,rk3399-typec-phy" }, + {} +}; + +U_BOOT_DRIVER(rockchip_typec_phy_port) = { + .name = "rockchip_typec_phy_port", + .id = UCLASS_PHY, + .ops = &rockchip_usb3_phy_ops, +}; + +U_BOOT_DRIVER(rockchip_typec_phy) = { + .name = "rockchip_typec_phy", + .id = UCLASS_PHY, + .of_match = rockchip_typec_phy_dt_ids, + .probe = rockchip_typec_phy_probe, + .bind = rockchip_typec_phy_bind, + .priv_auto_alloc_size = sizeof(struct rockchip_typec_phy), +}; diff --git a/include/linux/usb/rockchip_phy_typec.h b/include/linux/usb/rockchip_phy_typec.h new file mode 100644 index 0000000000..9551f2be1e --- /dev/null +++ b/include/linux/usb/rockchip_phy_typec.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2020 Rockchip Electronics Co., Ltd + * + * Based on include/soc/rockchip/rockchip_phy_typec.h in Linux Kernel. + */ + +#ifndef __LINUX_ROCKCHIP_PHY_TYPEC_H +#define __LINUX_ROCKCHIP_PHY_TYPEC_H + +#include + +struct usb3phy_reg { + u32 offset; + u32 enable_bit; + u32 write_enable; +}; + +struct rockchip_usb3phy_port_cfg { + struct usb3phy_reg typec_conn_dir; + struct usb3phy_reg usb3tousb2_en; + struct usb3phy_reg usb3host_disable; + struct usb3phy_reg usb3host_port; + struct usb3phy_reg external_psm; + struct usb3phy_reg pipe_status; +}; + +struct rockchip_typec_phy { + struct udevice *dev; + void __iomem *base; + void __iomem *grf_regs; + struct reset_ctl uphy_rst; + struct reset_ctl pipe_rst; + struct reset_ctl tcphy_rst; + struct rockchip_usb3phy_port_cfg port_cfgs; + /* mutex to protect access to individual PHYs */ + struct mutex lock; + + bool flip; + u8 mode; +}; + +#if CONFIG_IS_ENABLED(PHY_ROCKCHIP_TYPEC) +int rockchip_u3phy_uboot_init(const char *name); +#else +static inline int rockchip_u3phy_uboot_init(const char *name) +{ + return -ENOTSUPP; +} +#endif + +#endif /* __LINUX_ROCKCHIP_PHY_TYPEC_H */ From patchwork Tue Apr 28 06:34:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Wang X-Patchwork-Id: 238728 List-Id: U-Boot discussion From: frank.wang at rock-chips.com (Frank Wang) Date: Tue, 28 Apr 2020 14:34:17 +0800 Subject: [PATCH 6/8] driver: usb: drop legacy rockchip xhci driver In-Reply-To: <20200428062747.8349-1-frank.wang@rock-chips.com> References: <20200428062747.8349-1-frank.wang@rock-chips.com> Message-ID: <20200428063417.8502-1-frank.wang@rock-chips.com> We have changed to use dwc3 generic driver for usb3.0 host, so the legacy Rockchip's xHCI driver is not needed, and drop it. Signed-off-by: Frank Wang --- drivers/usb/host/Kconfig | 9 -- drivers/usb/host/Makefile | 1 - drivers/usb/host/xhci-rockchip.c | 196 ------------------------------- 3 files changed, 206 deletions(-) delete mode 100644 drivers/usb/host/xhci-rockchip.c diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 94ac969058..94232358a0 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -47,15 +47,6 @@ config USB_XHCI_PCI help Enables support for the PCI-based xHCI controller. -config USB_XHCI_ROCKCHIP - bool "Support for Rockchip on-chip xHCI USB controller" - depends on ARCH_ROCKCHIP - depends on DM_REGULATOR - depends on DM_USB - default y - help - Enables support for the on-chip xHCI controller on Rockchip SoCs. - config USB_XHCI_RCAR bool "Renesas RCar USB 3.0 support" default y diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index b62f346094..1754714673 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -48,7 +48,6 @@ obj-$(CONFIG_USB_XHCI_BRCM) += xhci-brcm.o obj-$(CONFIG_USB_XHCI_HCD) += xhci.o xhci-mem.o xhci-ring.o obj-$(CONFIG_USB_XHCI_DWC3) += xhci-dwc3.o obj-$(CONFIG_USB_XHCI_DWC3_OF_SIMPLE) += dwc3-of-simple.o -obj-$(CONFIG_USB_XHCI_ROCKCHIP) += xhci-rockchip.o obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos5.o obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o diff --git a/drivers/usb/host/xhci-rockchip.c b/drivers/usb/host/xhci-rockchip.c deleted file mode 100644 index b67722fe45..0000000000 --- a/drivers/usb/host/xhci-rockchip.c +++ /dev/null @@ -1,196 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 2016 Rockchip, Inc. - * Authors: Daniel Meng - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -struct rockchip_xhci_platdata { - fdt_addr_t hcd_base; - struct udevice *vbus_supply; -}; - -/* - * Contains pointers to register base addresses - * for the usb controller. - */ -struct rockchip_xhci { - struct usb_platdata usb_plat; - struct xhci_ctrl ctrl; - struct xhci_hccr *hcd; - struct dwc3 *dwc3_reg; -}; - -static int xhci_usb_ofdata_to_platdata(struct udevice *dev) -{ - struct rockchip_xhci_platdata *plat = dev_get_platdata(dev); - int ret = 0; - - /* - * Get the base address for XHCI controller from the device node - */ - plat->hcd_base = dev_read_addr(dev); - if (plat->hcd_base == FDT_ADDR_T_NONE) { - pr_err("Can't get the XHCI register base address\n"); - return -ENXIO; - } - - /* Vbus regulator */ - ret = device_get_supply_regulator(dev, "vbus-supply", - &plat->vbus_supply); - if (ret) - debug("Can't get VBus regulator!\n"); - - return 0; -} - -/* - * rockchip_dwc3_phy_setup() - Configure USB PHY Interface of DWC3 Core - * @dwc: Pointer to our controller context structure - * @dev: Pointer to ulcass device - */ -static void rockchip_dwc3_phy_setup(struct dwc3 *dwc3_reg, - struct udevice *dev) -{ - u32 reg; - u32 utmi_bits; - - /* Set dwc3 usb2 phy config */ - reg = readl(&dwc3_reg->g_usb2phycfg[0]); - - if (dev_read_bool(dev, "snps,dis-enblslpm-quirk")) - reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; - - utmi_bits = dev_read_u32_default(dev, "snps,phyif-utmi-bits", -1); - if (utmi_bits == 16) { - reg |= DWC3_GUSB2PHYCFG_PHYIF; - reg &= ~DWC3_GUSB2PHYCFG_USBTRDTIM_MASK; - reg |= DWC3_GUSB2PHYCFG_USBTRDTIM_16BIT; - } else if (utmi_bits == 8) { - reg &= ~DWC3_GUSB2PHYCFG_PHYIF; - reg &= ~DWC3_GUSB2PHYCFG_USBTRDTIM_MASK; - reg |= DWC3_GUSB2PHYCFG_USBTRDTIM_8BIT; - } - - if (dev_read_bool(dev, "snps,dis-u2-freeclk-exists-quirk")) - reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS; - - if (dev_read_bool(dev, "snps,dis-u2-susphy-quirk")) - reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; - - writel(reg, &dwc3_reg->g_usb2phycfg[0]); -} - -static int rockchip_xhci_core_init(struct rockchip_xhci *rkxhci, - struct udevice *dev) -{ - int ret; - - ret = dwc3_core_init(rkxhci->dwc3_reg); - if (ret) { - pr_err("failed to initialize core\n"); - return ret; - } - - rockchip_dwc3_phy_setup(rkxhci->dwc3_reg, dev); - - /* We are hard-coding DWC3 core to Host Mode */ - dwc3_set_mode(rkxhci->dwc3_reg, DWC3_GCTL_PRTCAP_HOST); - - return 0; -} - -static int rockchip_xhci_core_exit(struct rockchip_xhci *rkxhci) -{ - return 0; -} - -static int xhci_usb_probe(struct udevice *dev) -{ - struct rockchip_xhci_platdata *plat = dev_get_platdata(dev); - struct rockchip_xhci *ctx = dev_get_priv(dev); - struct xhci_hcor *hcor; - int ret; - - ctx->hcd = (struct xhci_hccr *)plat->hcd_base; - ctx->dwc3_reg = (struct dwc3 *)((char *)(ctx->hcd) + DWC3_REG_OFFSET); - hcor = (struct xhci_hcor *)((uint64_t)ctx->hcd + - HC_LENGTH(xhci_readl(&ctx->hcd->cr_capbase))); - - if (plat->vbus_supply) { - ret = regulator_set_enable(plat->vbus_supply, true); - if (ret) { - pr_err("XHCI: failed to set VBus supply\n"); - return ret; - } - } - - ret = rockchip_xhci_core_init(ctx, dev); - if (ret) { - pr_err("XHCI: failed to initialize controller\n"); - return ret; - } - - return xhci_register(dev, ctx->hcd, hcor); -} - -static int xhci_usb_remove(struct udevice *dev) -{ - struct rockchip_xhci_platdata *plat = dev_get_platdata(dev); - struct rockchip_xhci *ctx = dev_get_priv(dev); - int ret; - - ret = xhci_deregister(dev); - if (ret) - return ret; - ret = rockchip_xhci_core_exit(ctx); - if (ret) - return ret; - - if (plat->vbus_supply) { - ret = regulator_set_enable(plat->vbus_supply, false); - if (ret) - pr_err("XHCI: failed to set VBus supply\n"); - } - - return ret; -} - -static const struct udevice_id xhci_usb_ids[] = { - { .compatible = "rockchip,rk3328-xhci" }, - { } -}; - -U_BOOT_DRIVER(usb_xhci) = { - .name = "xhci_rockchip", - .id = UCLASS_USB, - .of_match = xhci_usb_ids, - .ofdata_to_platdata = xhci_usb_ofdata_to_platdata, - .probe = xhci_usb_probe, - .remove = xhci_usb_remove, - .ops = &xhci_usb_ops, - .bind = dm_scan_fdt_dev, - .platdata_auto_alloc_size = sizeof(struct rockchip_xhci_platdata), - .priv_auto_alloc_size = sizeof(struct rockchip_xhci), - .flags = DM_FLAG_ALLOC_PRIV_DMA, -}; - -static const struct udevice_id usb_phy_ids[] = { - { .compatible = "rockchip,rk3328-usb3-phy" }, - { } -}; - -U_BOOT_DRIVER(usb_phy) = { - .name = "usb_phy_rockchip", - .of_match = usb_phy_ids, -}; From patchwork Tue Apr 28 06:34:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Wang X-Patchwork-Id: 238729 List-Id: U-Boot discussion From: frank.wang at rock-chips.com (Frank Wang) Date: Tue, 28 Apr 2020 14:34:53 +0800 Subject: [PATCH 7/8] ARM: dts: rockchip: amend dwc3 nodes to keep in line with kernel In-Reply-To: <20200428062747.8349-1-frank.wang@rock-chips.com> References: <20200428062747.8349-1-frank.wang@rock-chips.com> Message-ID: <20200428063453.8558-1-frank.wang@rock-chips.com> We have changed to use dwc3 generic driver for Rockchip SoCs so let amend dts to fix it and keep in line with Linux Kernel. Signed-off-by: Frank Wang --- arch/arm/dts/rk3399-evb.dts | 28 ++++++++++++--- arch/arm/dts/rk3399-puma.dtsi | 35 +++++++++++++++--- arch/arm/dts/rk3399-u-boot.dtsi | 11 ++++++ arch/arm/dts/rk3399.dtsi | 64 +++++++++++++++++++++------------ 4 files changed, 105 insertions(+), 33 deletions(-) diff --git a/arch/arm/dts/rk3399-evb.dts b/arch/arm/dts/rk3399-evb.dts index 4129e902a8..eccf3d40c8 100644 --- a/arch/arm/dts/rk3399-evb.dts +++ b/arch/arm/dts/rk3399-evb.dts @@ -56,6 +56,10 @@ compatible = "regulator-fixed"; regulator-name = "vcc5v0_host"; gpio = <&gpio4 25 GPIO_ACTIVE_HIGH>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + regulator-boot-on; }; vcc5v0_typec0: vcc5v0-typec0-en { @@ -164,6 +168,14 @@ status = "okay"; }; +&tcphy0 { + status = "okay"; +}; + +&tcphy1 { + status = "okay"; +}; + &uart2 { status = "okay"; }; @@ -177,20 +189,26 @@ }; &usbdrd3_0 { - vbus-supply = <&vcc5v0_typec0>; status = "okay"; }; -&usb_host1_ehci { +&usbdrd3_1 { status = "okay"; }; -&usb_host1_ohci { +&usbdrd_dwc3_0 { status = "okay"; }; -&usbdrd3_1 { - vbus-supply = <&vcc5v0_typec1>; +&usbdrd_dwc3_1 { + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { status = "okay"; }; diff --git a/arch/arm/dts/rk3399-puma.dtsi b/arch/arm/dts/rk3399-puma.dtsi index 558b6337df..ff5e6477ed 100644 --- a/arch/arm/dts/rk3399-puma.dtsi +++ b/arch/arm/dts/rk3399-puma.dtsi @@ -129,6 +129,16 @@ regulator-always-on; }; + vcc5v0_host: vcc5v0-host-regulator { + compatible = "regulator-fixed"; + enable-active-low; + gpio = <&gpio4 RK_PA3 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&host_vbus_drv>; + regulator-name = "vcc5v0_host"; + regulator-always-on; + }; + vcc5v0_sys: vcc5v0-sys { compatible = "regulator-fixed"; regulator-name = "vcc5v0_sys"; @@ -487,6 +497,14 @@ status = "okay"; }; +&tcphy0 { + status = "okay"; +}; + +&tcphy1 { + status = "okay"; +}; + &uart2 { status = "okay"; }; @@ -503,6 +521,18 @@ status = "okay"; }; +&usbdrd3_1 { + status = "okay"; +}; + +&usbdrd_dwc3_0 { + status = "okay"; +}; + +&usbdrd_dwc3_1 { + status = "okay"; +}; + &usb_host1_ehci { status = "disabled"; }; @@ -511,11 +541,6 @@ status = "disabled"; }; -&usbdrd3_1 { - status = "okay"; - tsd,usb-port-power = "usbhub_enable"; -}; - &vopb { status = "okay"; }; diff --git a/arch/arm/dts/rk3399-u-boot.dtsi b/arch/arm/dts/rk3399-u-boot.dtsi index 8b857ccfc7..e65b266604 100644 --- a/arch/arm/dts/rk3399-u-boot.dtsi +++ b/arch/arm/dts/rk3399-u-boot.dtsi @@ -98,6 +98,17 @@ u-boot,dm-pre-reloc; }; + +&u2phy0 { + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&u2phy0_otg { + u-boot,dm-pre-reloc; + status = "okay"; +}; + &vopb { u-boot,dm-pre-reloc; }; diff --git a/arch/arm/dts/rk3399.dtsi b/arch/arm/dts/rk3399.dtsi index 6b7c136ab8..4d77d88ca1 100644 --- a/arch/arm/dts/rk3399.dtsi +++ b/arch/arm/dts/rk3399.dtsi @@ -345,22 +345,21 @@ status = "disabled"; }; - usbdrd3_0: dwc3_typec0: usb at fe800000 { + usbdrd3_0: usb0 { compatible = "rockchip,rk3399-dwc3"; - #address-cells = <2>; - #size-cells = <2>; - ranges; clocks = <&cru SCLK_USB3OTG0_REF>, <&cru SCLK_USB3OTG0_SUSPEND>, - <&cru ACLK_USB3OTG0>, <&cru ACLK_USB3_RKSOC_AXI_PERF>, - <&cru ACLK_USB3>, <&cru ACLK_USB3_GRF>; + <&cru ACLK_USB3OTG0>, <&cru ACLK_USB3_GRF>; clock-names = "ref_clk", "suspend_clk", - "bus_clk", "aclk_usb3_rksoc_axi_perf", - "aclk_usb3", "grf_clk"; + "bus_clk", "grf_clk"; + power-domains = <&power RK3399_PD_USB3>; resets = <&cru SRST_A_USB3_OTG0>; reset-names = "usb3-otg"; + #address-cells = <2>; + #size-cells = <2>; + ranges; status = "disabled"; - usbdrd_dwc3_0: dwc3 { + usbdrd_dwc3_0: dwc3 at fe800000 { compatible = "snps,dwc3"; reg = <0x0 0xfe800000 0x0 0x100000>; interrupts = ; @@ -372,32 +371,33 @@ snps,dis-u2-freeclk-exists-quirk; snps,dis_u2_susphy_quirk; snps,dis-del-phy-power-chg-quirk; - snps,dis-tx-ipgap-linecheck-quirk; - power-domains = <&power RK3399_PD_USB3>; + snps,tx-ipgap-linecheck-dis-quirk; + snps,xhci-slow-suspend-quirk; + snps,xhci-trb-ent-quirk; + snps,usb3-warm-reset-on-resume-quirk; status = "disabled"; }; }; - dwc3_typec1: usbdrd3_1: usb at fe900000 { + usbdrd3_1: usb1 { compatible = "rockchip,rk3399-dwc3"; - #address-cells = <2>; - #size-cells = <2>; - ranges; clocks = <&cru SCLK_USB3OTG1_REF>, <&cru SCLK_USB3OTG1_SUSPEND>, - <&cru ACLK_USB3OTG1>, <&cru ACLK_USB3_RKSOC_AXI_PERF>, - <&cru ACLK_USB3>, <&cru ACLK_USB3_GRF>; + <&cru ACLK_USB3OTG1>, <&cru ACLK_USB3_GRF>; clock-names = "ref_clk", "suspend_clk", - "bus_clk", "aclk_usb3_rksoc_axi_perf", - "aclk_usb3", "grf_clk"; + "bus_clk", "grf_clk"; + power-domains = <&power RK3399_PD_USB3>; resets = <&cru SRST_A_USB3_OTG1>; reset-names = "usb3-otg"; + #address-cells = <2>; + #size-cells = <2>; + ranges; status = "disabled"; - usbdrd_dwc3_1: dwc3 { + usbdrd_dwc3_1: dwc3 at fe900000 { compatible = "snps,dwc3"; reg = <0x0 0xfe900000 0x0 0x100000>; interrupts = ; - dr_mode = "otg"; + dr_mode = "host"; phys = <&u2phy1_otg>, <&tcphy1_usb3>; phy-names = "usb2-phy", "usb3-phy"; phy_type = "utmi_wide"; @@ -405,8 +405,10 @@ snps,dis-u2-freeclk-exists-quirk; snps,dis_u2_susphy_quirk; snps,dis-del-phy-power-chg-quirk; - snps,dis-tx-ipgap-linecheck-quirk; - power-domains = <&power RK3399_PD_USB3>; + snps,tx-ipgap-linecheck-dis-quirk; + snps,xhci-slow-suspend-quirk; + snps,xhci-trb-ent-quirk; + snps,usb3-warm-reset-on-resume-quirk; status = "disabled"; }; }; @@ -1352,6 +1354,7 @@ tcphy0: phy at ff7c0000 { compatible = "rockchip,rk3399-typec-phy"; reg = <0x0 0xff7c0000 0x0 0x40000>; + #phy-cells = <1>; clocks = <&cru SCLK_UPHY0_TCPDCORE>, <&cru SCLK_UPHY0_TCPDPHY_REF>; clock-names = "tcpdcore", "tcpdphy-ref"; @@ -1363,6 +1366,13 @@ <&cru SRST_P_UPHY0_TCPHY>; reset-names = "uphy", "uphy-pipe", "uphy-tcphy"; rockchip,grf = <&grf>; + rockchip,typec-conn-dir = <0xe580 0 16>; + rockchip,usb3tousb2-en = <0xe580 3 19>; + rockchip,usb3-host-disable = <0x2434 0 16>; + rockchip,usb3-host-port = <0x2434 12 28>; + rockchip,external-psm = <0xe588 14 30>; + rockchip,pipe-status = <0xe5c0 0 0>; + rockchip,uphy-dp-sel = <0x6268 19 19>; status = "disabled"; tcphy0_dp: dp-port { @@ -1377,6 +1387,7 @@ tcphy1: phy at ff800000 { compatible = "rockchip,rk3399-typec-phy"; reg = <0x0 0xff800000 0x0 0x40000>; + #phy-cells = <1>; clocks = <&cru SCLK_UPHY1_TCPDCORE>, <&cru SCLK_UPHY1_TCPDPHY_REF>; clock-names = "tcpdcore", "tcpdphy-ref"; @@ -1388,6 +1399,13 @@ <&cru SRST_P_UPHY1_TCPHY>; reset-names = "uphy", "uphy-pipe", "uphy-tcphy"; rockchip,grf = <&grf>; + rockchip,typec-conn-dir = <0xe58c 0 16>; + rockchip,usb3tousb2-en = <0xe58c 3 19>; + rockchip,usb3-host-disable = <0x2444 0 16>; + rockchip,usb3-host-port = <0x2444 12 28>; + rockchip,external-psm = <0xe594 14 30>; + rockchip,pipe-status = <0xe5c0 16 16>; + rockchip,uphy-dp-sel = <0x6268 3 19>; status = "disabled"; tcphy1_dp: dp-port { From patchwork Tue Apr 28 06:35:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Wang X-Patchwork-Id: 238730 List-Id: U-Boot discussion From: frank.wang at rock-chips.com (Frank Wang) Date: Tue, 28 Apr 2020 14:35:07 +0800 Subject: [PATCH 8/8] configs: evb-rk3399: enable usb3.0 host support In-Reply-To: <20200428062747.8349-1-frank.wang@rock-chips.com> References: <20200428062747.8349-1-frank.wang@rock-chips.com> Message-ID: <20200428063507.8612-1-frank.wang@rock-chips.com> Update evb-rk3399 default config to support USB3.0 host. Signed-off-by: Frank Wang --- configs/evb-rk3399_defconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configs/evb-rk3399_defconfig b/configs/evb-rk3399_defconfig index 3f74be3b3c..d68fede479 100644 --- a/configs/evb-rk3399_defconfig +++ b/configs/evb-rk3399_defconfig @@ -18,6 +18,7 @@ CONFIG_CMD_BOOTZ=y CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_TIME=y CONFIG_SPL_OF_CONTROL=y @@ -35,6 +36,7 @@ CONFIG_SF_DEFAULT_SPEED=20000000 CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y CONFIG_GMAC_ROCKCHIP=y +CONFIG_PHY_ROCKCHIP_TYPEC=y CONFIG_PMIC_RK8XX=y CONFIG_REGULATOR_PWM=y CONFIG_REGULATOR_RK8XX=y @@ -47,6 +49,9 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_GENERIC=y +CONFIG_USB_STORAGE=y CONFIG_USB_HOST_ETHER=y CONFIG_USB_ETHER_ASIX=y CONFIG_USB_ETHER_ASIX88179=y