From 7f899da901b001a973a1971d539d77bde2b68b05 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 5 Jul 2021 13:29:01 +0100 Subject: [PATCH 1/9] phy: sun50i-usb3: Add a driver for the H6 USB3 PHY This driver is needed for XHCI to work on the Allwinner H6 SoC. The driver is copied from Linux v5.10. Reviewed-by: Andre Przywara Signed-off-by: Samuel Holland Signed-off-by: Andre Przywara --- drivers/phy/allwinner/Kconfig | 8 ++ drivers/phy/allwinner/Makefile | 1 + drivers/phy/allwinner/phy-sun50i-usb3.c | 171 ++++++++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 drivers/phy/allwinner/phy-sun50i-usb3.c diff --git a/drivers/phy/allwinner/Kconfig b/drivers/phy/allwinner/Kconfig index dba3bae61c..6bfb79cbca 100644 --- a/drivers/phy/allwinner/Kconfig +++ b/drivers/phy/allwinner/Kconfig @@ -11,3 +11,11 @@ config PHY_SUN4I_USB This driver controls the entire USB PHY block, both the USB OTG parts, as well as the 2 regular USB 2 host PHYs. + +config PHY_SUN50I_USB3 + bool "Allwinner sun50i USB3 PHY driver" + depends on ARCH_SUNXI + select PHY + help + Enable this to support the USB3 transceiver that is part of + Allwinner sun50i SoCs. diff --git a/drivers/phy/allwinner/Makefile b/drivers/phy/allwinner/Makefile index e709fca643..f2b60ce1a6 100644 --- a/drivers/phy/allwinner/Makefile +++ b/drivers/phy/allwinner/Makefile @@ -4,3 +4,4 @@ # obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o +obj-$(CONFIG_PHY_SUN50I_USB3) += phy-sun50i-usb3.o diff --git a/drivers/phy/allwinner/phy-sun50i-usb3.c b/drivers/phy/allwinner/phy-sun50i-usb3.c new file mode 100644 index 0000000000..e5a3d2d92e --- /dev/null +++ b/drivers/phy/allwinner/phy-sun50i-usb3.c @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Allwinner sun50i(H6) USB 3.0 phy driver + * + * Copyright (C) 2020 Samuel Holland + * + * Based on the Linux driver, which is: + * + * Copyright (C) 2017 Icenowy Zheng + * + * Based on phy-sun9i-usb.c, which is: + * + * Copyright (C) 2014-2015 Chen-Yu Tsai + * + * Based on code from Allwinner BSP, which is: + * + * Copyright (c) 2010-2015 Allwinner Technology Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Interface Status and Control Registers */ +#define SUNXI_ISCR 0x00 +#define SUNXI_PIPE_CLOCK_CONTROL 0x14 +#define SUNXI_PHY_TUNE_LOW 0x18 +#define SUNXI_PHY_TUNE_HIGH 0x1c +#define SUNXI_PHY_EXTERNAL_CONTROL 0x20 + +/* USB2.0 Interface Status and Control Register */ +#define SUNXI_ISCR_FORCE_VBUS (3 << 12) + +/* PIPE Clock Control Register */ +#define SUNXI_PCC_PIPE_CLK_OPEN (1 << 6) + +/* PHY External Control Register */ +#define SUNXI_PEC_EXTERN_VBUS (3 << 1) +#define SUNXI_PEC_SSC_EN (1 << 24) +#define SUNXI_PEC_REF_SSP_EN (1 << 26) + +/* PHY Tune High Register */ +#define SUNXI_TX_DEEMPH_3P5DB(n) ((n) << 19) +#define SUNXI_TX_DEEMPH_3P5DB_MASK GENMASK(24, 19) +#define SUNXI_TX_DEEMPH_6DB(n) ((n) << 13) +#define SUNXI_TX_DEEMPH_6GB_MASK GENMASK(18, 13) +#define SUNXI_TX_SWING_FULL(n) ((n) << 6) +#define SUNXI_TX_SWING_FULL_MASK GENMASK(12, 6) +#define SUNXI_LOS_BIAS(n) ((n) << 3) +#define SUNXI_LOS_BIAS_MASK GENMASK(5, 3) +#define SUNXI_TXVBOOSTLVL(n) ((n) << 0) +#define SUNXI_TXVBOOSTLVL_MASK GENMASK(2, 0) + +struct sun50i_usb3_phy_priv { + void __iomem *regs; + struct reset_ctl reset; + struct clk clk; +}; + +static void sun50i_usb3_phy_open(struct sun50i_usb3_phy_priv *phy) +{ + u32 val; + + val = readl(phy->regs + SUNXI_PHY_EXTERNAL_CONTROL); + val |= SUNXI_PEC_EXTERN_VBUS; + val |= SUNXI_PEC_SSC_EN | SUNXI_PEC_REF_SSP_EN; + writel(val, phy->regs + SUNXI_PHY_EXTERNAL_CONTROL); + + val = readl(phy->regs + SUNXI_PIPE_CLOCK_CONTROL); + val |= SUNXI_PCC_PIPE_CLK_OPEN; + writel(val, phy->regs + SUNXI_PIPE_CLOCK_CONTROL); + + val = readl(phy->regs + SUNXI_ISCR); + val |= SUNXI_ISCR_FORCE_VBUS; + writel(val, phy->regs + SUNXI_ISCR); + + /* + * All the magic numbers written to the PHY_TUNE_{LOW_HIGH} + * registers are directly taken from the BSP USB3 driver from + * Allwiner. + */ + writel(0x0047fc87, phy->regs + SUNXI_PHY_TUNE_LOW); + + val = readl(phy->regs + SUNXI_PHY_TUNE_HIGH); + val &= ~(SUNXI_TXVBOOSTLVL_MASK | SUNXI_LOS_BIAS_MASK | + SUNXI_TX_SWING_FULL_MASK | SUNXI_TX_DEEMPH_6GB_MASK | + SUNXI_TX_DEEMPH_3P5DB_MASK); + val |= SUNXI_TXVBOOSTLVL(0x7); + val |= SUNXI_LOS_BIAS(0x7); + val |= SUNXI_TX_SWING_FULL(0x55); + val |= SUNXI_TX_DEEMPH_6DB(0x20); + val |= SUNXI_TX_DEEMPH_3P5DB(0x15); + writel(val, phy->regs + SUNXI_PHY_TUNE_HIGH); +} + +static int sun50i_usb3_phy_init(struct phy *phy) +{ + struct sun50i_usb3_phy_priv *priv = dev_get_priv(phy->dev); + int ret; + + ret = clk_prepare_enable(&priv->clk); + if (ret) + return ret; + + ret = reset_deassert(&priv->reset); + if (ret) { + clk_disable_unprepare(&priv->clk); + return ret; + } + + sun50i_usb3_phy_open(priv); + + return 0; +} + +static int sun50i_usb3_phy_exit(struct phy *phy) +{ + struct sun50i_usb3_phy_priv *priv = dev_get_priv(phy->dev); + + reset_assert(&priv->reset); + clk_disable_unprepare(&priv->clk); + + return 0; +} + +static const struct phy_ops sun50i_usb3_phy_ops = { + .init = sun50i_usb3_phy_init, + .exit = sun50i_usb3_phy_exit, +}; + +static int sun50i_usb3_phy_probe(struct udevice *dev) +{ + struct sun50i_usb3_phy_priv *priv = dev_get_priv(dev); + int ret; + + ret = clk_get_by_index(dev, 0, &priv->clk); + if (ret) { + dev_err(dev, "failed to get phy clock\n"); + return ret; + } + + ret = reset_get_by_index(dev, 0, &priv->reset); + if (ret) { + dev_err(dev, "failed to get reset control\n"); + return ret; + } + + priv->regs = (void __iomem *)dev_read_addr(dev); + if (IS_ERR(priv->regs)) + return PTR_ERR(priv->regs); + + return 0; +} + +static const struct udevice_id sun50i_usb3_phy_ids[] = { + { .compatible = "allwinner,sun50i-h6-usb3-phy" }, + { }, +}; + +U_BOOT_DRIVER(sun50i_usb3_phy) = { + .name = "sun50i-usb3-phy", + .id = UCLASS_PHY, + .of_match = sun50i_usb3_phy_ids, + .ops = &sun50i_usb3_phy_ops, + .probe = sun50i_usb3_phy_probe, + .priv_auto = sizeof(struct sun50i_usb3_phy_priv), +}; From 70a98caf194dba204861575d207f9172549a5f35 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 5 Jul 2021 13:29:02 +0100 Subject: [PATCH 2/9] usb: xhci-pci: Move reset logic out of XHCI core Resetting an XHCI controller inside xhci_register undoes any register setup performed by the platform driver. And at least on the Allwinner H6, resetting the XHCI controller also resets the PHY, which prevents the controller from working. That means the controller must be taken out of reset before initializing the PHY, which must be done before calling xhci_register. The logic in the XHCI core was added to support the Raspberry Pi 4 (although this was not mentioned in the commit log!), which uses the xhci-pci platform driver. Move the reset logic to the platform driver, where it belongs, and where it cannot interfere with other platform drivers. This also fixes a failure to call reset_free if xhci_register failed. Fixes: 0b80371b350e ("usb: xhci: Add reset controller support") Signed-off-by: Samuel Holland Reviewed-by: Bin Meng Signed-off-by: Andre Przywara --- drivers/usb/host/xhci-mem.c | 2 -- drivers/usb/host/xhci-pci.c | 52 ++++++++++++++++++++++++++++++++++--- drivers/usb/host/xhci.c | 35 ------------------------- include/usb/xhci.h | 2 -- 4 files changed, 48 insertions(+), 43 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 1c11c2e7e0..0d9da62bab 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -180,8 +180,6 @@ void xhci_cleanup(struct xhci_ctrl *ctrl) xhci_free_virt_devices(ctrl); free(ctrl->erst.entries); free(ctrl->dcbaa); - if (reset_valid(&ctrl->reset)) - reset_free(&ctrl->reset); memset(ctrl, '\0', sizeof(struct xhci_ctrl)); } diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index aaa243f291..630bc20be1 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -7,12 +7,18 @@ #include #include +#include #include #include #include +#include #include #include +struct xhci_pci_plat { + struct reset_ctl reset; +}; + static int xhci_pci_init(struct udevice *dev, struct xhci_hccr **ret_hccr, struct xhci_hcor **ret_hcor) { @@ -45,15 +51,53 @@ static int xhci_pci_init(struct udevice *dev, struct xhci_hccr **ret_hccr, static int xhci_pci_probe(struct udevice *dev) { + struct xhci_pci_plat *plat = dev_get_plat(dev); struct xhci_hccr *hccr; struct xhci_hcor *hcor; int ret; + ret = reset_get_by_index(dev, 0, &plat->reset); + if (ret && ret != -ENOENT && ret != -ENOTSUPP) { + dev_err(dev, "failed to get reset\n"); + return ret; + } + + if (reset_valid(&plat->reset)) { + ret = reset_assert(&plat->reset); + if (ret) + goto err_reset; + + ret = reset_deassert(&plat->reset); + if (ret) + goto err_reset; + } + ret = xhci_pci_init(dev, &hccr, &hcor); if (ret) - return ret; + goto err_reset; - return xhci_register(dev, hccr, hcor); + ret = xhci_register(dev, hccr, hcor); + if (ret) + goto err_reset; + + return 0; + +err_reset: + if (reset_valid(&plat->reset)) + reset_free(&plat->reset); + + return ret; +} + +static int xhci_pci_remove(struct udevice *dev) +{ + struct xhci_pci_plat *plat = dev_get_plat(dev); + + xhci_deregister(dev); + if (reset_valid(&plat->reset)) + reset_free(&plat->reset); + + return 0; } static const struct udevice_id xhci_pci_ids[] = { @@ -65,10 +109,10 @@ U_BOOT_DRIVER(xhci_pci) = { .name = "xhci_pci", .id = UCLASS_USB, .probe = xhci_pci_probe, - .remove = xhci_deregister, + .remove = xhci_pci_remove, .of_match = xhci_pci_ids, .ops = &xhci_usb_ops, - .plat_auto = sizeof(struct usb_plat), + .plat_auto = sizeof(struct xhci_pci_plat), .priv_auto = sizeof(struct xhci_ctrl), .flags = DM_FLAG_OS_PREPARE | DM_FLAG_ALLOC_PRIV_DMA, }; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index d27ac01c83..452dacc0af 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -188,37 +188,6 @@ static int xhci_start(struct xhci_hcor *hcor) return ret; } -#if CONFIG_IS_ENABLED(DM_USB) -/** - * Resets XHCI Hardware - * - * @param ctrl pointer to host controller - * @return 0 if OK, or a negative error code. - */ -static int xhci_reset_hw(struct xhci_ctrl *ctrl) -{ - int ret; - - ret = reset_get_by_index(ctrl->dev, 0, &ctrl->reset); - if (ret && ret != -ENOENT && ret != -ENOTSUPP) { - dev_err(ctrl->dev, "failed to get reset\n"); - return ret; - } - - if (reset_valid(&ctrl->reset)) { - ret = reset_assert(&ctrl->reset); - if (ret) - return ret; - - ret = reset_deassert(&ctrl->reset); - if (ret) - return ret; - } - - return 0; -} -#endif - /** * Resets the XHCI Controller * @@ -1534,10 +1503,6 @@ int xhci_register(struct udevice *dev, struct xhci_hccr *hccr, ctrl->dev = dev; - ret = xhci_reset_hw(ctrl); - if (ret) - goto err; - /* * XHCI needs to issue a Address device command to setup * proper device context structures, before it can interact diff --git a/include/usb/xhci.h b/include/usb/xhci.h index 8d95e213b0..01e63cf0fc 100644 --- a/include/usb/xhci.h +++ b/include/usb/xhci.h @@ -17,7 +17,6 @@ #define HOST_XHCI_H_ #include -#include #include #include #include @@ -1200,7 +1199,6 @@ struct xhci_ctrl { #if CONFIG_IS_ENABLED(DM_USB) struct udevice *dev; #endif - struct reset_ctl reset; struct xhci_hccr *hccr; /* R/O registers, not need for volatile */ struct xhci_hcor *hcor; struct xhci_doorbell_array *dba; From 91ce84a56b3419fc7b8bd75575d470c0d22ae2b0 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 5 Jul 2021 13:29:03 +0100 Subject: [PATCH 3/9] usb: xhci-dwc3: Add support for clocks/resets Some platforms, like the Allwinner H6, do not have a separate glue layer around the dwc3. Instead, they rely on the clocks/resets/phys referenced from the dwc3 DT node itself. Add support for enabling the clocks/resets referenced from the dwc3 DT node. Signed-off-by: Samuel Holland Signed-off-by: Andre Przywara --- drivers/usb/host/xhci-dwc3.c | 56 ++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c index 3e0ae80cec..5b12d1358e 100644 --- a/drivers/usb/host/xhci-dwc3.c +++ b/drivers/usb/host/xhci-dwc3.c @@ -7,10 +7,12 @@ * Author: Ramneek Mehresh */ +#include #include #include #include #include +#include #include #include #include @@ -21,7 +23,9 @@ #include struct xhci_dwc3_plat { + struct clk_bulk clks; struct phy_bulk phys; + struct reset_ctl_bulk resets; }; void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode) @@ -111,6 +115,46 @@ void dwc3_set_fladj(struct dwc3 *dwc3_reg, u32 val) } #if CONFIG_IS_ENABLED(DM_USB) +static int xhci_dwc3_reset_init(struct udevice *dev, + struct xhci_dwc3_plat *plat) +{ + int ret; + + ret = reset_get_bulk(dev, &plat->resets); + if (ret == -ENOTSUPP || ret == -ENOENT) + return 0; + else if (ret) + return ret; + + ret = reset_deassert_bulk(&plat->resets); + if (ret) { + reset_release_bulk(&plat->resets); + return ret; + } + + return 0; +} + +static int xhci_dwc3_clk_init(struct udevice *dev, + struct xhci_dwc3_plat *plat) +{ + int ret; + + ret = clk_get_bulk(dev, &plat->clks); + if (ret == -ENOSYS || ret == -ENOENT) + return 0; + if (ret) + return ret; + + ret = clk_enable_bulk(&plat->clks); + if (ret) { + clk_release_bulk(&plat->clks); + return ret; + } + + return 0; +} + static int xhci_dwc3_probe(struct udevice *dev) { struct xhci_hcor *hcor; @@ -122,6 +166,14 @@ static int xhci_dwc3_probe(struct udevice *dev) u32 reg; int ret; + ret = xhci_dwc3_reset_init(dev, plat); + if (ret) + return ret; + + ret = xhci_dwc3_clk_init(dev, plat); + if (ret) + return ret; + hccr = (struct xhci_hccr *)((uintptr_t)dev_remap_addr(dev)); hcor = (struct xhci_hcor *)((uintptr_t)hccr + HC_LENGTH(xhci_readl(&(hccr)->cr_capbase))); @@ -171,6 +223,10 @@ static int xhci_dwc3_remove(struct udevice *dev) dwc3_shutdown_phy(dev, &plat->phys); + clk_release_bulk(&plat->clks); + + reset_release_bulk(&plat->resets); + return xhci_deregister(dev); } From 672ee240d978354882bca1ec5cdd1a7a462cc597 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 5 Jul 2021 13:29:04 +0100 Subject: [PATCH 4/9] configs: Enable USB3 on Allwinner H6 boards Pine H64 and Orange Pi 3 both provide a USB3 type A port. Enable it in U-Boot. Signed-off-by: Samuel Holland Signed-off-by: Andre Przywara --- configs/orangepi_3_defconfig | 5 +++++ configs/pine_h64_defconfig | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/configs/orangepi_3_defconfig b/configs/orangepi_3_defconfig index c243a58200..ebecf49ebd 100644 --- a/configs/orangepi_3_defconfig +++ b/configs/orangepi_3_defconfig @@ -8,5 +8,10 @@ CONFIG_MMC0_CD_PIN="PF6" CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_BLUETOOTH_DT_DEVICE_FIXUP="brcm,bcm4345c5" # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set +CONFIG_PHY_SUN50I_USB3=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_DWC3=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y +CONFIG_USB_DWC3=y +# CONFIG_USB_DWC3_GADGET is not set diff --git a/configs/pine_h64_defconfig b/configs/pine_h64_defconfig index 4e621db0c0..1928509dd7 100644 --- a/configs/pine_h64_defconfig +++ b/configs/pine_h64_defconfig @@ -12,5 +12,10 @@ CONFIG_SPL_SPI_SUNXI=y # CONFIG_PSCI_RESET is not set # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SUN8I_EMAC=y +CONFIG_PHY_SUN50I_USB3=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_DWC3=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y +CONFIG_USB_DWC3=y +# CONFIG_USB_DWC3_GADGET is not set From 950cb1f25f0bf7aaa83db41b14fc2aaab214125c Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 20 Sep 2021 15:37:22 +0200 Subject: [PATCH 5/9] usb: add support for ULPI/SERIAL/HSIC PHY modes Import usb_phy_interface enum values and DT match strings from the Linux kernel. Signed-off-by: Markus Niebel Signed-off-by: Matthias Schiffer --- drivers/usb/common/common.c | 3 +++ include/linux/usb/phy.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c index 2a47f40bba..43564c9fba 100644 --- a/drivers/usb/common/common.c +++ b/drivers/usb/common/common.c @@ -80,6 +80,9 @@ static const char *const usbphy_modes[] = { [USBPHY_INTERFACE_MODE_UNKNOWN] = "", [USBPHY_INTERFACE_MODE_UTMI] = "utmi", [USBPHY_INTERFACE_MODE_UTMIW] = "utmi_wide", + [USBPHY_INTERFACE_MODE_ULPI] = "ulpi", + [USBPHY_INTERFACE_MODE_SERIAL] = "serial", + [USBPHY_INTERFACE_MODE_HSIC] = "hsic", }; enum usb_phy_interface usb_get_phy_mode(ofnode node) diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h index 1e1217a958..14b2c7eb2e 100644 --- a/include/linux/usb/phy.h +++ b/include/linux/usb/phy.h @@ -16,6 +16,9 @@ enum usb_phy_interface { USBPHY_INTERFACE_MODE_UNKNOWN, USBPHY_INTERFACE_MODE_UTMI, USBPHY_INTERFACE_MODE_UTMIW, + USBPHY_INTERFACE_MODE_ULPI, + USBPHY_INTERFACE_MODE_SERIAL, + USBPHY_INTERFACE_MODE_HSIC, }; #if CONFIG_IS_ENABLED(DM_USB) From f2a4c890e390eb0e5d131a027a259801e8f07ff3 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 20 Sep 2021 15:37:23 +0200 Subject: [PATCH 6/9] include/configs: replace MXC_EHCI_MODE_SERIAL with PORT_PTS_SERIAL The MXC_EHCI_MODE_ definitions are redundant. Replace MXC_EHCI_MODE_SERIAL with the equivalent PORT_PTS_SERIAL. Only the zmx25 platform is affected. Signed-off-by: Markus Niebel Signed-off-by: Matthias Schiffer --- include/configs/zmx25.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/configs/zmx25.h b/include/configs/zmx25.h index 88a885463d..8b571da021 100644 --- a/include/configs/zmx25.h +++ b/include/configs/zmx25.h @@ -57,7 +57,7 @@ #define CONFIG_USB_EHCI_MXC #define CONFIG_EHCI_HCD_INIT_AFTER_RESET #define CONFIG_MXC_USB_PORT 1 -#define CONFIG_MXC_USB_PORTSC MXC_EHCI_MODE_SERIAL +#define CONFIG_MXC_USB_PORTSC PORT_PTS_SERIAL #define CONFIG_MXC_USB_FLAGS (MXC_EHCI_INTERNAL_PHY | MXC_EHCI_IPPUE_DOWN) #define CONFIG_EHCI_IS_TDI #endif /* CONFIG_CMD_USB */ From 8709228b5c61d56c21461a797b12e275bdd3c044 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 20 Sep 2021 15:37:24 +0200 Subject: [PATCH 7/9] usb: ehci-ci: remove redundant PORTSC flag definitions These definitions are unused, all boards that define portsc flags use the equivalent PORT_* definitions instead. Signed-off-by: Markus Niebel Signed-off-by: Matthias Schiffer --- include/usb/ehci-ci.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/include/usb/ehci-ci.h b/include/usb/ehci-ci.h index efb2eec5ce..bf5d26faa5 100644 --- a/include/usb/ehci-ci.h +++ b/include/usb/ehci-ci.h @@ -249,17 +249,6 @@ struct usb_ehci { * For MXC SOCs */ -/* values for portsc field */ -#define MXC_EHCI_PHY_LOW_POWER_SUSPEND (1 << 23) -#define MXC_EHCI_FORCE_FS (1 << 24) -#define MXC_EHCI_UTMI_8BIT (0 << 28) -#define MXC_EHCI_UTMI_16BIT (1 << 28) -#define MXC_EHCI_SERIAL (1 << 29) -#define MXC_EHCI_MODE_UTMI (0 << 30) -#define MXC_EHCI_MODE_PHILIPS (1 << 30) -#define MXC_EHCI_MODE_ULPI (2 << 30) -#define MXC_EHCI_MODE_SERIAL (3 << 30) - /* values for flags field */ #define MXC_EHCI_INTERFACE_DIFF_UNI (0 << 0) #define MXC_EHCI_INTERFACE_DIFF_BI (1 << 0) From 0f513c5975105a8cfdf80cc9862e4c65826ead84 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 20 Sep 2021 15:37:25 +0200 Subject: [PATCH 8/9] usb: ehci-mx6: use phy_type from device tree Allow using different PHY interfaces for multiple USB controllers. When no value is set in DT, we fall back to CONFIG_MXC_USB_PORTSC for now to stay compatible with current board configurations. This also adds support for the HSIC mode of the i.MX7. Signed-off-by: Markus Niebel Signed-off-by: Matthias Schiffer --- drivers/usb/host/ehci-mx6.c | 25 +++++++++++++++++++++++-- include/usb/ehci-ci.h | 1 + 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index c3e4170513..1bd6147c76 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "ehci.h" @@ -435,6 +436,7 @@ struct ehci_mx6_priv_data { struct clk clk; struct phy phy; enum usb_init_type init_type; + enum usb_phy_interface phy_type; #if !defined(CONFIG_PHY) int portnr; void __iomem *phy_addr; @@ -443,6 +445,24 @@ struct ehci_mx6_priv_data { #endif }; +static u32 mx6_portsc(enum usb_phy_interface phy_type) +{ + switch (phy_type) { + case USBPHY_INTERFACE_MODE_UTMI: + return PORT_PTS_UTMI; + case USBPHY_INTERFACE_MODE_UTMIW: + return PORT_PTS_UTMI | PORT_PTS_PTW; + case USBPHY_INTERFACE_MODE_ULPI: + return PORT_PTS_ULPI; + case USBPHY_INTERFACE_MODE_SERIAL: + return PORT_PTS_SERIAL; + case USBPHY_INTERFACE_MODE_HSIC: + return PORT_PTS_HSIC; + default: + return CONFIG_MXC_USB_PORTSC; + } +} + static int mx6_init_after_reset(struct ehci_ctrl *dev) { struct ehci_mx6_priv_data *priv = dev->priv; @@ -479,7 +499,7 @@ static int mx6_init_after_reset(struct ehci_ctrl *dev) return 0; setbits_le32(&ehci->usbmode, CM_HOST); - writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); + writel(mx6_portsc(priv->phy_type), &ehci->portsc); setbits_le32(&ehci->portsc, USB_EN); mdelay(10); @@ -641,6 +661,7 @@ static int ehci_usb_probe(struct udevice *dev) priv->ehci = ehci; priv->init_type = type; + priv->phy_type = usb_get_phy_mode(dev_ofnode(dev)); #if CONFIG_IS_ENABLED(CLK) ret = clk_get_by_index(dev, 0, &priv->clk); @@ -690,7 +711,7 @@ static int ehci_usb_probe(struct udevice *dev) if (priv->init_type == USB_INIT_HOST) { setbits_le32(&ehci->usbmode, CM_HOST); - writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); + writel(mx6_portsc(priv->phy_type), &ehci->portsc); setbits_le32(&ehci->portsc, USB_EN); } diff --git a/include/usb/ehci-ci.h b/include/usb/ehci-ci.h index bf5d26faa5..2cdb3146e8 100644 --- a/include/usb/ehci-ci.h +++ b/include/usb/ehci-ci.h @@ -23,6 +23,7 @@ #define PORT_PTS_ULPI (2 << 30) #define PORT_PTS_SERIAL (3 << 30) #define PORT_PTS_PTW (1 << 28) +#define PORT_PTS_HSIC (1 << 25) #define PORT_PFSC (1 << 24) /* Defined on Page 39-44 of the mpc5151 ERM */ #define PORT_PTS_PHCD (1 << 23) #define PORT_PP (1 << 12) From 53eed9adfac17921511ebf9e00c429bcb385d231 Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Thu, 16 Sep 2021 16:00:09 +0200 Subject: [PATCH 9/9] usb: xhci-dwc3: Add support for USB 3.1 controllers This adds support for the DWC_sub31 controllers such as those found on Apple's M1 SoC. This version of the controller seems to work fine with the existing driver. Signed-off-by: Mark Kettenis --- drivers/usb/host/xhci-dwc3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c index 5b12d1358e..bec0d98081 100644 --- a/drivers/usb/host/xhci-dwc3.c +++ b/drivers/usb/host/xhci-dwc3.c @@ -74,7 +74,8 @@ int dwc3_core_init(struct dwc3 *dwc3_reg) revision = readl(&dwc3_reg->g_snpsid); /* This should read as U3 followed by revision number */ - if ((revision & DWC3_GSNPSID_MASK) != 0x55330000) { + if ((revision & DWC3_GSNPSID_MASK) != 0x55330000 && + (revision & DWC3_GSNPSID_MASK) != 0x33310000) { puts("this is not a DesignWare USB3 DRD Core\n"); return -1; }