From d8c80bb3b55b0821e1cf6a4814262c152ae5bc4b Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Mon, 9 Oct 2017 14:00:51 +0200 Subject: phy: exynos5-usbdrd: Calibrate LOS levels for exynos5420/5800 Adding phy calibration sequence for USB 3.0 DRD PHY present on Exynos5420/5800 systems. This calibration facilitates setting certain PHY parameters viz. the Loss-of-Signal (LOS) Detector Threshold Level, as well as Tx-Vboost-Level for Super-Speed operations. Additionally we also set proper time to wait for RxDetect measurement, for desired PHY reference clock, so as to solve issue with enumeration of few USB 3.0 devices, like Samsung SUM-TSB16S 3.0 USB drive on the controller. We are using CR_port for this purpose to send required data to override the LOS values. On testing with USB 3.0 devices on USB 3.0 port present on SMDK5420, and peach-pit boards should see following message: usb 2-1: new SuperSpeed USB device number 2 using xhci-hcd and without this patch, should see below shown message: usb 1-1: new high-speed USB device number 2 using xhci-hcd [Also removed unnecessary extra lines in the register macro definitions] Signed-off-by: Vivek Gautam [adapted to use phy_calibrate as entry point] Signed-off-by: Andrzej Pietrasiewicz Acked-by: Felipe Balbi Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/samsung/phy-exynos5-usbdrd.c | 183 +++++++++++++++++++++++++++++++ drivers/usb/dwc3/core.c | 2 + 2 files changed, 185 insertions(+) (limited to 'drivers') diff --git a/drivers/phy/samsung/phy-exynos5-usbdrd.c b/drivers/phy/samsung/phy-exynos5-usbdrd.c index 22c68f58b181..b8b226a20014 100644 --- a/drivers/phy/samsung/phy-exynos5-usbdrd.c +++ b/drivers/phy/samsung/phy-exynos5-usbdrd.c @@ -90,7 +90,17 @@ #define PHYCLKRST_COMMONONN BIT(0) #define EXYNOS5_DRD_PHYREG0 0x14 +#define PHYREG0_SSC_REF_CLK_SEL BIT(21) +#define PHYREG0_SSC_RANGE BIT(20) +#define PHYREG0_CR_WRITE BIT(19) +#define PHYREG0_CR_READ BIT(18) +#define PHYREG0_CR_DATA_IN(_x) ((_x) << 2) +#define PHYREG0_CR_CAP_DATA BIT(1) +#define PHYREG0_CR_CAP_ADDR BIT(0) + #define EXYNOS5_DRD_PHYREG1 0x18 +#define PHYREG1_CR_DATA_OUT(_x) ((_x) << 1) +#define PHYREG1_CR_ACK BIT(0) #define EXYNOS5_DRD_PHYPARAM0 0x1c @@ -119,6 +129,25 @@ #define EXYNOS5_DRD_PHYRESUME 0x34 #define EXYNOS5_DRD_LINKPORT 0x44 +/* USB 3.0 DRD PHY SS Function Control Reg; accessed by CR_PORT */ +#define EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN (0x15) +#define LOSLEVEL_OVRD_IN_LOS_BIAS_5420 (0x5 << 13) +#define LOSLEVEL_OVRD_IN_LOS_BIAS_DEFAULT (0x0 << 13) +#define LOSLEVEL_OVRD_IN_EN (0x1 << 10) +#define LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT (0x9 << 0) + +#define EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN (0x12) +#define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420 (0x5 << 13) +#define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_DEFAULT (0x4 << 13) + +#define EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG (0x1010) +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M (0x4 << 4) +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M (0x8 << 4) +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_25M_26M (0x8 << 4) +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M (0x20 << 4) +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_62M5 (0x20 << 4) +#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_96M_100M (0x40 << 4) + #define KHZ 1000 #define MHZ (KHZ * KHZ) @@ -527,6 +556,151 @@ static int exynos5_usbdrd_phy_power_off(struct phy *phy) return 0; } +static int crport_handshake(struct exynos5_usbdrd_phy *phy_drd, + u32 val, u32 cmd) +{ + u32 usec = 100; + unsigned int result; + + writel(val | cmd, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0); + + do { + result = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1); + if (result & PHYREG1_CR_ACK) + break; + + udelay(1); + } while (usec-- > 0); + + if (!usec) { + dev_err(phy_drd->dev, + "CRPORT handshake timeout1 (0x%08x)\n", val); + return -ETIME; + } + + usec = 100; + + writel(val, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0); + + do { + result = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1); + if (!(result & PHYREG1_CR_ACK)) + break; + + udelay(1); + } while (usec-- > 0); + + if (!usec) { + dev_err(phy_drd->dev, + "CRPORT handshake timeout2 (0x%08x)\n", val); + return -ETIME; + } + + return 0; +} + +static int crport_ctrl_write(struct exynos5_usbdrd_phy *phy_drd, + u32 addr, u32 data) +{ + int ret; + + /* Write Address */ + writel(PHYREG0_CR_DATA_IN(addr), + phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0); + ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(addr), + PHYREG0_CR_CAP_ADDR); + if (ret) + return ret; + + /* Write Data */ + writel(PHYREG0_CR_DATA_IN(data), + phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0); + ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data), + PHYREG0_CR_CAP_DATA); + if (ret) + return ret; + + ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data), + PHYREG0_CR_WRITE); + + return ret; +} + +/* + * Calibrate few PHY parameters using CR_PORT register to meet + * SuperSpeed requirements on Exynos5420 and Exynos5800 systems, + * which have 28nm USB 3.0 DRD PHY. + */ +static int exynos5420_usbdrd_phy_calibrate(struct exynos5_usbdrd_phy *phy_drd) +{ + unsigned int temp; + int ret = 0; + + /* + * Change los_bias to (0x5) for 28nm PHY from a + * default value (0x0); los_level is set as default + * (0x9) as also reflected in los_level[30:26] bits + * of PHYPARAM0 register. + */ + temp = LOSLEVEL_OVRD_IN_LOS_BIAS_5420 | + LOSLEVEL_OVRD_IN_EN | + LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT; + ret = crport_ctrl_write(phy_drd, + EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN, + temp); + if (ret) { + dev_err(phy_drd->dev, + "Failed setting Loss-of-Signal level for SuperSpeed\n"); + return ret; + } + + /* + * Set tx_vboost_lvl to (0x5) for 28nm PHY Tuning, + * to raise Tx signal level from its default value of (0x4) + */ + temp = TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420; + ret = crport_ctrl_write(phy_drd, + EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN, + temp); + if (ret) { + dev_err(phy_drd->dev, + "Failed setting Tx-Vboost-Level for SuperSpeed\n"); + return ret; + } + + /* + * Set proper time to wait for RxDetect measurement, for + * desired reference clock of PHY, by tuning the CR_PORT + * register LANE0.TX_DEBUG which is internal to PHY. + * This fixes issue with few USB 3.0 devices, which are + * not detected (not even generate interrupts on the bus + * on insertion) without this change. + * e.g. Samsung SUM-TSB16S 3.0 USB drive. + */ + switch (phy_drd->extrefclk) { + case EXYNOS5_FSEL_50MHZ: + temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M; + break; + case EXYNOS5_FSEL_20MHZ: + case EXYNOS5_FSEL_19MHZ2: + temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M; + break; + case EXYNOS5_FSEL_24MHZ: + default: + temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M; + break; + } + + ret = crport_ctrl_write(phy_drd, + EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG, + temp); + if (ret) + dev_err(phy_drd->dev, + "Fail to set RxDet measurement time for SuperSpeed\n"); + + return ret; +} + static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev, struct of_phandle_args *args) { @@ -538,11 +712,20 @@ static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev, return phy_drd->phys[args->args[0]].phy; } +static int exynos5_usbdrd_phy_calibrate(struct phy *phy) +{ + struct phy_usb_instance *inst = phy_get_drvdata(phy); + struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst); + + return exynos5420_usbdrd_phy_calibrate(phy_drd); +} + static const struct phy_ops exynos5_usbdrd_phy_ops = { .init = exynos5_usbdrd_phy_init, .exit = exynos5_usbdrd_phy_exit, .power_on = exynos5_usbdrd_phy_power_on, .power_off = exynos5_usbdrd_phy_power_off, + .calibrate = exynos5_usbdrd_phy_calibrate, .owner = THIS_MODULE, }; diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 07832509584f..71707a315e11 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -147,6 +147,7 @@ static void __dwc3_set_mode(struct work_struct *work) otg_set_vbus(dwc->usb2_phy->otg, true); phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST); phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST); + phy_calibrate(dwc->usb2_generic_phy); } break; case DWC3_GCTL_PRTCAP_DEVICE: @@ -945,6 +946,7 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) dev_err(dev, "failed to initialize host\n"); return ret; } + phy_calibrate(dwc->usb2_generic_phy); break; case USB_DR_MODE_OTG: INIT_WORK(&dwc->drd_work, __dwc3_set_mode); -- cgit v1.2.3 From 5e498ff117c19fd80181b5bb09ecb024b552ece8 Mon Sep 17 00:00:00 2001 From: Al Cooper Date: Wed, 27 Dec 2017 14:28:48 -0500 Subject: phy: phy-brcm-usb: Fix two DT properties to match bindings doc Change "brcm,has_xhci" and "brcm,has_eohci" device tree properties to the preferred "brcm,has-xhci" and "brcm,has-eohci". This also matches the existing device tree bindings document. Fixes: 49859e55e364 ("phy: usb: phy-brcm-usb: Add Broadcom STB USB phy driver") Signed-off-by: Al Cooper Acked-by: Florian Fainelli Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/broadcom/phy-brcm-usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/broadcom/phy-brcm-usb.c b/drivers/phy/broadcom/phy-brcm-usb.c index 195b98139e5f..d1dab36fa5b7 100644 --- a/drivers/phy/broadcom/phy-brcm-usb.c +++ b/drivers/phy/broadcom/phy-brcm-usb.c @@ -338,9 +338,9 @@ static int brcm_usb_phy_probe(struct platform_device *pdev) ARRAY_SIZE(brcm_dr_mode_to_name), mode, &priv->ini.mode); } - if (of_property_read_bool(dn, "brcm,has_xhci")) + if (of_property_read_bool(dn, "brcm,has-xhci")) priv->has_xhci = true; - if (of_property_read_bool(dn, "brcm,has_eohci")) + if (of_property_read_bool(dn, "brcm,has-eohci")) priv->has_eohci = true; err = brcm_usb_phy_dvr_init(dev, priv, dn); -- cgit v1.2.3 From 279a0cd0e02aa1e506d9acf94a7ecb530821359c Mon Sep 17 00:00:00 2001 From: Al Cooper Date: Wed, 27 Dec 2017 14:28:49 -0500 Subject: phy: phy-brcm-usb-init: Some Low Speed keyboards fail on 7271 Enable the the Low Speed Keep Alive signal on the 7271b0 by setting the LS_KEEP_ALIVE bit in the USB CTRL OBRIDGE register otherwise some Dell Low Speed keyboards fail. Also do a little cleanup of the EBRIDGE ESTOP_SCB_REQ bit. Since this is only used on one platform, remove it from the platform tables and just use "if (family == "). Fixes: 49859e55e364 ("phy: usb: phy-brcm-usb: Add Broadcom STB USB phy driver") Signed-off-by: Al Cooper Acked-by: Florian Fainelli Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/broadcom/phy-brcm-usb-init.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/broadcom/phy-brcm-usb-init.c b/drivers/phy/broadcom/phy-brcm-usb-init.c index 1e7ce0b6f299..69ea47945292 100644 --- a/drivers/phy/broadcom/phy-brcm-usb-init.c +++ b/drivers/phy/broadcom/phy-brcm-usb-init.c @@ -50,6 +50,8 @@ #define USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK 0x80000000 /* option */ #define USB_CTRL_EBRIDGE 0x0c #define USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK 0x00020000 /* option */ +#define USB_CTRL_OBRIDGE 0x10 +#define USB_CTRL_OBRIDGE_LS_KEEP_ALIVE_MASK 0x08000000 #define USB_CTRL_MDIO 0x14 #define USB_CTRL_MDIO2 0x18 #define USB_CTRL_UTMI_CTL_1 0x2c @@ -116,7 +118,6 @@ enum { USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR, USB_CTRL_SETUP_OC3_DISABLE_SELECTOR, USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_SELECTOR, - USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_SELECTOR, USB_CTRL_USB_PM_BDC_SOFT_RESETB_SELECTOR, USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR, USB_CTRL_USB_PM_USB_PWRDN_SELECTOR, @@ -203,7 +204,6 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = { USB_CTRL_SETUP_STRAP_IPP_SEL_MASK, USB_CTRL_SETUP_OC3_DISABLE_MASK, 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */ - USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK, 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */ USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK, USB_CTRL_USB_PM_USB_PWRDN_MASK, @@ -225,7 +225,6 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = { 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */ USB_CTRL_SETUP_OC3_DISABLE_MASK, USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK, - USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK, 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */ USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK, 0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */ @@ -247,7 +246,6 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = { USB_CTRL_SETUP_STRAP_IPP_SEL_MASK, USB_CTRL_SETUP_OC3_DISABLE_MASK, 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */ - USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK, USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK, USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK, USB_CTRL_USB_PM_USB_PWRDN_MASK, @@ -269,7 +267,6 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = { 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */ USB_CTRL_SETUP_OC3_DISABLE_MASK, USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK, - USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK, 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */ USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK, 0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */ @@ -291,7 +288,6 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = { 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */ USB_CTRL_SETUP_OC3_DISABLE_MASK, 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */ - USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK, 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */ USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK, USB_CTRL_USB_PM_USB_PWRDN_MASK, @@ -313,7 +309,6 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = { 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */ 0, /* USB_CTRL_SETUP_OC3_DISABLE_MASK */ USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK, - 0, /* USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK */ 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */ 0, /* USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK */ 0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */ @@ -335,7 +330,6 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = { USB_CTRL_SETUP_STRAP_IPP_SEL_MASK, USB_CTRL_SETUP_OC3_DISABLE_MASK, 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */ - 0, /* USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK */ USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK, USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK, USB_CTRL_USB_PM_USB_PWRDN_MASK, @@ -357,7 +351,6 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = { 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */ USB_CTRL_SETUP_OC3_DISABLE_MASK, USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK, - 0, /* USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK */ 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */ 0, /* USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK */ 0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */ @@ -379,7 +372,6 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = { USB_CTRL_SETUP_STRAP_IPP_SEL_MASK, USB_CTRL_SETUP_OC3_DISABLE_MASK, 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */ - USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK, USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK, USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK, USB_CTRL_USB_PM_USB_PWRDN_MASK, @@ -401,7 +393,6 @@ usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = { USB_CTRL_SETUP_STRAP_IPP_SEL_MASK, USB_CTRL_SETUP_OC3_DISABLE_MASK, 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */ - USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK, USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK, USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK, USB_CTRL_USB_PM_USB_PWRDN_MASK, @@ -952,13 +943,17 @@ void brcm_usb_init_eohci(struct brcm_usb_init_params *params) * Don't enable this so the memory controller doesn't read * into memory holes. NOTE: This bit is low true on 7366C0. */ - USB_CTRL_SET_FAMILY(params, EBRIDGE, ESTOP_SCB_REQ); + USB_CTRL_SET(ctrl, EBRIDGE, ESTOP_SCB_REQ); /* Setup the endian bits */ reg = brcmusb_readl(USB_CTRL_REG(ctrl, SETUP)); reg &= ~USB_CTRL_SETUP_ENDIAN_BITS; reg |= USB_CTRL_MASK_FAMILY(params, SETUP, ENDIAN); brcmusb_writel(reg, USB_CTRL_REG(ctrl, SETUP)); + + if (params->selected_family == BRCM_FAMILY_7271A0) + /* Enable LS keep alive fix for certain keyboards */ + USB_CTRL_SET(ctrl, OBRIDGE, LS_KEEP_ALIVE); } void brcm_usb_init_xhci(struct brcm_usb_init_params *params) -- cgit v1.2.3 From cd6f769fdea7ff7d77a6cc97658c60ca0b836d0e Mon Sep 17 00:00:00 2001 From: Al Cooper Date: Wed, 27 Dec 2017 14:28:50 -0500 Subject: phy: phy-brcm-usb-init: Power down USB 3.0 PHY when XHCI disabled Set PHY3_IDDQ_OVERRIDE in the xhci uninit routine. This will save additional power when the XHCI driver is not enabled. Fixes: 49859e55e364 ("phy: usb: phy-brcm-usb: Add Broadcom STB USB phy driver") Signed-off-by: Al Cooper Acked-by: Florian Fainelli Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/broadcom/phy-brcm-usb-init.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/phy/broadcom/phy-brcm-usb-init.c b/drivers/phy/broadcom/phy-brcm-usb-init.c index 69ea47945292..6672adcc5894 100644 --- a/drivers/phy/broadcom/phy-brcm-usb-init.c +++ b/drivers/phy/broadcom/phy-brcm-usb-init.c @@ -73,6 +73,7 @@ #define USB_CTRL_USB30_CTL1_USB3_IPP_MASK 0x20000000 /* option */ #define USB_CTRL_USB30_PCTL 0x70 #define USB_CTRL_USB30_PCTL_PHY3_SOFT_RESETB_MASK 0x00000002 +#define USB_CTRL_USB30_PCTL_PHY3_IDDQ_OVERRIDE_MASK 0x00008000 #define USB_CTRL_USB30_PCTL_PHY3_SOFT_RESETB_P1_MASK 0x00020000 #define USB_CTRL_USB_DEVICE_CTL1 0x90 #define USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK 0x00000003 /* option */ @@ -998,6 +999,7 @@ void brcm_usb_uninit_eohci(struct brcm_usb_init_params *params) void brcm_usb_uninit_xhci(struct brcm_usb_init_params *params) { brcmusb_xhci_soft_reset(params, 1); + USB_CTRL_SET(params->ctrl_regs, USB30_PCTL, PHY3_IDDQ_OVERRIDE); } void brcm_usb_set_family_map(struct brcm_usb_init_params *params) -- cgit v1.2.3 From 0aa0c12262fd848c48448c39ff6c1c097be00dd4 Mon Sep 17 00:00:00 2001 From: Al Cooper Date: Wed, 27 Dec 2017 14:28:51 -0500 Subject: phy: phy-brcm-usb-init: DRD mode can cause crash on startup This is caused by a bug in the BDC core. When the BDC core comes out of reset and it's not selected, it gets a backup clock. When the BDC core is selected, it get's the main clock. If HOST mode is then selected the BDC core has the main clock shut off but the backup clock is not restored. The failure scenario and cause are as follows: - DRD mode is active - Device mode is selected first in bootloader - When host mode is now selected, the clock to the BDC is cut off. - BDC registers are inaccessible and therefore the BDC driver crashes upon Linux boot. The fix is to have the phy driver always force a BDC reset on startup. Fixes: 49859e55e364 ("phy: usb: phy-brcm-usb: Add Broadcom STB USB phy driver") Signed-off-by: Al Cooper Acked-by: Florian Fainelli Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/broadcom/phy-brcm-usb-init.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/phy/broadcom/phy-brcm-usb-init.c b/drivers/phy/broadcom/phy-brcm-usb-init.c index 6672adcc5894..1b7febc43da9 100644 --- a/drivers/phy/broadcom/phy-brcm-usb-init.c +++ b/drivers/phy/broadcom/phy-brcm-usb-init.c @@ -918,6 +918,7 @@ void brcm_usb_init_common(struct brcm_usb_init_params *params) USB_CTRL_UNSET_FAMILY(params, USB_PM, BDC_SOFT_RESETB); break; default: + USB_CTRL_UNSET_FAMILY(params, USB_PM, BDC_SOFT_RESETB); USB_CTRL_SET_FAMILY(params, USB_PM, BDC_SOFT_RESETB); break; } -- cgit v1.2.3 From 00c0092c5f62147b7d85f0c6f1cf245a0a1ff3b6 Mon Sep 17 00:00:00 2001 From: Chunfeng Yun Date: Thu, 7 Dec 2017 19:53:34 +0800 Subject: phy: phy-mtk-tphy: use auto instead of force to bypass utmi signals When system is running, if usb2 phy is forced to bypass utmi signals, all PLL will be turned off, and it can't detect device connection anymore, so replace force mode with auto mode which can bypass utmi signals automatically if no device attached for normal flow. But keep the force mode to fix RX sensitivity degradation issue. Signed-off-by: Chunfeng Yun Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/mediatek/phy-mtk-tphy.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c index 402385f2562a..54cc44b2d289 100644 --- a/drivers/phy/mediatek/phy-mtk-tphy.c +++ b/drivers/phy/mediatek/phy-mtk-tphy.c @@ -440,9 +440,9 @@ static void u2_phy_instance_init(struct mtk_tphy *tphy, u32 index = instance->index; u32 tmp; - /* switch to USB function. (system register, force ip into usb mode) */ + /* switch to USB function, and enable usb pll */ tmp = readl(com + U3P_U2PHYDTM0); - tmp &= ~P2C_FORCE_UART_EN; + tmp &= ~(P2C_FORCE_UART_EN | P2C_FORCE_SUSPENDM); tmp |= P2C_RG_XCVRSEL_VAL(1) | P2C_RG_DATAIN_VAL(0); writel(tmp, com + U3P_U2PHYDTM0); @@ -502,10 +502,8 @@ static void u2_phy_instance_power_on(struct mtk_tphy *tphy, u32 index = instance->index; u32 tmp; - /* (force_suspendm=0) (let suspendm=1, enable usb 480MHz pll) */ tmp = readl(com + U3P_U2PHYDTM0); - tmp &= ~(P2C_FORCE_SUSPENDM | P2C_RG_XCVRSEL); - tmp &= ~(P2C_RG_DATAIN | P2C_DTM0_PART_MASK); + tmp &= ~(P2C_RG_XCVRSEL | P2C_RG_DATAIN | P2C_DTM0_PART_MASK); writel(tmp, com + U3P_U2PHYDTM0); /* OTG Enable */ @@ -540,7 +538,6 @@ static void u2_phy_instance_power_off(struct mtk_tphy *tphy, tmp = readl(com + U3P_U2PHYDTM0); tmp &= ~(P2C_RG_XCVRSEL | P2C_RG_DATAIN); - tmp |= P2C_FORCE_SUSPENDM; writel(tmp, com + U3P_U2PHYDTM0); /* OTG Disable */ @@ -548,18 +545,16 @@ static void u2_phy_instance_power_off(struct mtk_tphy *tphy, tmp &= ~PA6_RG_U2_OTG_VBUSCMP_EN; writel(tmp, com + U3P_USBPHYACR6); - /* let suspendm=0, set utmi into analog power down */ - tmp = readl(com + U3P_U2PHYDTM0); - tmp &= ~P2C_RG_SUSPENDM; - writel(tmp, com + U3P_U2PHYDTM0); - udelay(1); - tmp = readl(com + U3P_U2PHYDTM1); tmp &= ~(P2C_RG_VBUSVALID | P2C_RG_AVALID); tmp |= P2C_RG_SESSEND; writel(tmp, com + U3P_U2PHYDTM1); if (tphy->pdata->avoid_rx_sen_degradation && index) { + tmp = readl(com + U3P_U2PHYDTM0); + tmp &= ~(P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM); + writel(tmp, com + U3P_U2PHYDTM0); + tmp = readl(com + U3D_U2PHYDCR0); tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; writel(tmp, com + U3D_U2PHYDCR0); -- cgit v1.2.3 From 93a04f4f1607c55452c85c7adaee043321afb3ae Mon Sep 17 00:00:00 2001 From: Chunfeng Yun Date: Thu, 7 Dec 2017 19:53:35 +0800 Subject: phy: phy-mtk-tphy: make shared banks optional for V1 TPHY V1 TPHY for SATA doesn't have shared banks if it isn't shared with PCIe or USB, so make it optional. Signed-off-by: Chunfeng Yun Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/mediatek/phy-mtk-tphy.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c index 54cc44b2d289..11cab1d84a02 100644 --- a/drivers/phy/mediatek/phy-mtk-tphy.c +++ b/drivers/phy/mediatek/phy-mtk-tphy.c @@ -1023,9 +1023,10 @@ static int mtk_tphy_probe(struct platform_device *pdev) tphy->dev = dev; platform_set_drvdata(pdev, tphy); - if (tphy->pdata->version == MTK_PHY_V1) { + sif_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + /* SATA phy of V1 needn't it if not shared with PCIe or USB */ + if (sif_res && tphy->pdata->version == MTK_PHY_V1) { /* get banks shared by multiple phys */ - sif_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); tphy->sif_base = devm_ioremap_resource(dev, sif_res); if (IS_ERR(tphy->sif_base)) { dev_err(dev, "failed to remap sif regs\n"); -- cgit v1.2.3 From e4b227c1ca70ae779c39e5284742555b9e1cdf9f Mon Sep 17 00:00:00 2001 From: Chunfeng Yun Date: Thu, 28 Dec 2017 16:40:36 +0530 Subject: phy: phy-mtk-tphy: use of_device_get_match_data() reduce the boilerplate code to get the specific data Signed-off-by: Chunfeng Yun Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/mediatek/phy-mtk-tphy.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c index 11cab1d84a02..1e96d0740ef5 100644 --- a/drivers/phy/mediatek/phy-mtk-tphy.c +++ b/drivers/phy/mediatek/phy-mtk-tphy.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -995,7 +996,6 @@ MODULE_DEVICE_TABLE(of, mtk_tphy_id_table); static int mtk_tphy_probe(struct platform_device *pdev) { - const struct of_device_id *match; struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct device_node *child_np; @@ -1005,15 +1005,14 @@ static int mtk_tphy_probe(struct platform_device *pdev) struct resource res; int port, retval; - match = of_match_node(mtk_tphy_id_table, pdev->dev.of_node); - if (!match) - return -EINVAL; - tphy = devm_kzalloc(dev, sizeof(*tphy), GFP_KERNEL); if (!tphy) return -ENOMEM; - tphy->pdata = match->data; + tphy->pdata = of_device_get_match_data(dev); + if (!tphy->pdata) + return -EINVAL; + tphy->nphys = of_get_child_count(np); tphy->phys = devm_kcalloc(dev, tphy->nphys, sizeof(*tphy->phys), GFP_KERNEL); -- cgit v1.2.3