Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

phy: exynos5-usbdrd: support HS combo phy for ExynosAutov920

Support UTMI+ combo phy for this SoC, which is somewhat similar to
what the existing Exynos850 supports. The difference is that some
register offsets and bit fields are different from Exynos850.

Add required change in phy driver to support combo HS phy for this SoC.

Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
Signed-off-by: Pritam Manohar Sutar <pritam.sutar@samsung.com>
Link: https://patch.msgid.link/20251124110453.2887437-5-pritam.sutar@samsung.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Pritam Manohar Sutar and committed by
Vinod Koul
22a401c9 fc58d462

+211
+211
drivers/phy/samsung/phy-exynos5-usbdrd.c
··· 41 41 #define EXYNOS2200_CLKRST_LINK_PCLK_SEL BIT(1) 42 42 43 43 #define EXYNOS2200_DRD_UTMI 0x10 44 + 45 + /* ExynosAutov920 bits */ 46 + #define UTMICTL_FORCE_UTMI_SUSPEND BIT(13) 47 + #define UTMICTL_FORCE_UTMI_SLEEP BIT(12) 48 + #define UTMICTL_FORCE_DPPULLDOWN BIT(9) 49 + #define UTMICTL_FORCE_DMPULLDOWN BIT(8) 50 + 44 51 #define EXYNOS2200_UTMI_FORCE_VBUSVALID BIT(1) 45 52 #define EXYNOS2200_UTMI_FORCE_BVALID BIT(0) 46 53 ··· 256 249 257 250 #define EXYNOS850_DRD_HSP_TEST 0x5c 258 251 #define HSP_TEST_SIDDQ BIT(24) 252 + 253 + #define EXYNOSAUTOV920_DRD_HSP_CLKRST 0x100 254 + #define HSPCLKRST_PHY20_SW_PORTRESET BIT(3) 255 + #define HSPCLKRST_PHY20_SW_POR BIT(1) 256 + #define HSPCLKRST_PHY20_SW_POR_SEL BIT(0) 257 + 258 + #define EXYNOSAUTOV920_DRD_HSPCTL 0x104 259 + #define HSPCTRL_VBUSVLDEXTSEL BIT(13) 260 + #define HSPCTRL_VBUSVLDEXT BIT(12) 261 + #define HSPCTRL_EN_UTMISUSPEND BIT(9) 262 + #define HSPCTRL_COMMONONN BIT(8) 263 + 264 + #define EXYNOSAUTOV920_DRD_HSP_TEST 0x10c 265 + 266 + #define EXYNOSAUTOV920_DRD_HSPPLLTUNE 0x110 267 + #define HSPPLLTUNE_FSEL GENMASK(18, 16) 259 268 260 269 /* Exynos9 - GS101 */ 261 270 #define EXYNOS850_DRD_SECPMACTL 0x48 ··· 2077 2054 .n_regulators = ARRAY_SIZE(exynos5_regulator_names), 2078 2055 }; 2079 2056 2057 + static void 2058 + exynosautov920_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd) 2059 + { 2060 + void __iomem *reg_phy = phy_drd->reg_phy; 2061 + u32 reg; 2062 + 2063 + /* 2064 + * Disable HWACG (hardware auto clock gating control). This 2065 + * forces QACTIVE signal in Q-Channel interface to HIGH level, 2066 + * to make sure the PHY clock is not gated by the hardware. 2067 + */ 2068 + reg = readl(reg_phy + EXYNOS850_DRD_LINKCTRL); 2069 + reg |= LINKCTRL_FORCE_QACT; 2070 + writel(reg, reg_phy + EXYNOS850_DRD_LINKCTRL); 2071 + 2072 + /* De-assert link reset */ 2073 + reg = readl(reg_phy + EXYNOS2200_DRD_CLKRST); 2074 + reg &= ~CLKRST_LINK_SW_RST; 2075 + writel(reg, reg_phy + EXYNOS2200_DRD_CLKRST); 2076 + 2077 + /* Set PHY POR High */ 2078 + reg = readl(reg_phy + EXYNOSAUTOV920_DRD_HSP_CLKRST); 2079 + reg |= HSPCLKRST_PHY20_SW_POR | HSPCLKRST_PHY20_SW_POR_SEL; 2080 + writel(reg, reg_phy + EXYNOSAUTOV920_DRD_HSP_CLKRST); 2081 + 2082 + /* Enable UTMI+ */ 2083 + reg = readl(reg_phy + EXYNOS2200_DRD_UTMI); 2084 + reg &= ~(UTMICTL_FORCE_UTMI_SUSPEND | UTMICTL_FORCE_UTMI_SLEEP | 2085 + UTMICTL_FORCE_DPPULLDOWN | UTMICTL_FORCE_DMPULLDOWN); 2086 + writel(reg, reg_phy + EXYNOS2200_DRD_UTMI); 2087 + 2088 + /* set phy clock & control HS phy */ 2089 + reg = readl(reg_phy + EXYNOSAUTOV920_DRD_HSPCTL); 2090 + reg |= HSPCTRL_EN_UTMISUSPEND | HSPCTRL_COMMONONN; 2091 + writel(reg, reg_phy + EXYNOSAUTOV920_DRD_HSPCTL); 2092 + 2093 + fsleep(100); 2094 + 2095 + /* Set VBUS Valid and DP-Pull up control by VBUS pad usage */ 2096 + reg = readl(reg_phy + EXYNOS850_DRD_LINKCTRL); 2097 + reg |= FIELD_PREP_CONST(LINKCTRL_BUS_FILTER_BYPASS, 0xf); 2098 + writel(reg, reg_phy + EXYNOS850_DRD_LINKCTRL); 2099 + 2100 + reg = readl(reg_phy + EXYNOS2200_DRD_UTMI); 2101 + reg |= EXYNOS2200_UTMI_FORCE_VBUSVALID | EXYNOS2200_UTMI_FORCE_BVALID; 2102 + writel(reg, reg_phy + EXYNOS2200_DRD_UTMI); 2103 + 2104 + reg = readl(reg_phy + EXYNOSAUTOV920_DRD_HSPCTL); 2105 + reg |= HSPCTRL_VBUSVLDEXTSEL | HSPCTRL_VBUSVLDEXT; 2106 + writel(reg, reg_phy + EXYNOSAUTOV920_DRD_HSPCTL); 2107 + 2108 + /* Setting FSEL for refference clock */ 2109 + reg = readl(reg_phy + EXYNOSAUTOV920_DRD_HSPPLLTUNE); 2110 + reg &= ~HSPPLLTUNE_FSEL; 2111 + 2112 + switch (phy_drd->extrefclk) { 2113 + case EXYNOS5_FSEL_50MHZ: 2114 + reg |= FIELD_PREP(HSPPLLTUNE_FSEL, 7); 2115 + break; 2116 + case EXYNOS5_FSEL_26MHZ: 2117 + reg |= FIELD_PREP(HSPPLLTUNE_FSEL, 6); 2118 + break; 2119 + case EXYNOS5_FSEL_24MHZ: 2120 + reg |= FIELD_PREP(HSPPLLTUNE_FSEL, 2); 2121 + break; 2122 + case EXYNOS5_FSEL_20MHZ: 2123 + reg |= FIELD_PREP(HSPPLLTUNE_FSEL, 1); 2124 + break; 2125 + case EXYNOS5_FSEL_19MHZ2: 2126 + reg |= FIELD_PREP(HSPPLLTUNE_FSEL, 0); 2127 + break; 2128 + default: 2129 + dev_warn(phy_drd->dev, "unsupported ref clk: %#.2x\n", 2130 + phy_drd->extrefclk); 2131 + break; 2132 + } 2133 + writel(reg, reg_phy + EXYNOSAUTOV920_DRD_HSPPLLTUNE); 2134 + 2135 + /* Enable PHY Power Mode */ 2136 + reg = readl(reg_phy + EXYNOSAUTOV920_DRD_HSP_TEST); 2137 + reg &= ~HSP_TEST_SIDDQ; 2138 + writel(reg, reg_phy + EXYNOSAUTOV920_DRD_HSP_TEST); 2139 + 2140 + /* before POR low, 10us delay is needed to Finish PHY reset */ 2141 + fsleep(10); 2142 + 2143 + /* Set PHY POR Low */ 2144 + reg = readl(reg_phy + EXYNOSAUTOV920_DRD_HSP_CLKRST); 2145 + reg |= HSPCLKRST_PHY20_SW_POR_SEL; 2146 + reg &= ~(HSPCLKRST_PHY20_SW_POR | HSPCLKRST_PHY20_SW_PORTRESET); 2147 + writel(reg, reg_phy + EXYNOSAUTOV920_DRD_HSP_CLKRST); 2148 + 2149 + /* after POR low and delay 75us, PHYCLOCK is guaranteed. */ 2150 + fsleep(75); 2151 + 2152 + /* force pipe3 signal for link */ 2153 + reg = readl(reg_phy + EXYNOS850_DRD_LINKCTRL); 2154 + reg |= LINKCTRL_FORCE_PIPE_EN; 2155 + reg &= ~LINKCTRL_FORCE_PHYSTATUS; 2156 + reg |= LINKCTRL_FORCE_RXELECIDLE; 2157 + writel(reg, reg_phy + EXYNOS850_DRD_LINKCTRL); 2158 + } 2159 + 2160 + static void 2161 + exynosautov920_usbdrd_hsphy_disable(struct exynos5_usbdrd_phy *phy_drd) 2162 + { 2163 + u32 reg; 2164 + void __iomem *reg_phy = phy_drd->reg_phy; 2165 + 2166 + /* set phy clock & control HS phy */ 2167 + reg = readl(reg_phy + EXYNOS2200_DRD_UTMI); 2168 + reg |= UTMICTL_FORCE_UTMI_SUSPEND | UTMICTL_FORCE_UTMI_SLEEP; 2169 + reg &= ~(UTMICTL_FORCE_DPPULLDOWN | UTMICTL_FORCE_DMPULLDOWN); 2170 + writel(reg, reg_phy + EXYNOS2200_DRD_UTMI); 2171 + 2172 + /* Disable PHY Power Mode */ 2173 + reg = readl(reg_phy + EXYNOSAUTOV920_DRD_HSP_TEST); 2174 + reg |= HSP_TEST_SIDDQ; 2175 + writel(reg, reg_phy + EXYNOSAUTOV920_DRD_HSP_TEST); 2176 + 2177 + /* clear force q-channel */ 2178 + reg = readl(reg_phy + EXYNOS850_DRD_LINKCTRL); 2179 + reg &= ~LINKCTRL_FORCE_QACT; 2180 + writel(reg, reg_phy + EXYNOS850_DRD_LINKCTRL); 2181 + 2182 + /* link sw reset is need for USB_DP/DM high-z in host mode */ 2183 + reg = readl(reg_phy + EXYNOS2200_DRD_CLKRST); 2184 + reg |= CLKRST_LINK_SW_RST; 2185 + writel(reg, reg_phy + EXYNOS2200_DRD_CLKRST); 2186 + fsleep(10); 2187 + reg &= ~CLKRST_LINK_SW_RST; 2188 + writel(reg, reg_phy + EXYNOS2200_DRD_CLKRST); 2189 + } 2190 + 2080 2191 static int exynosautov920_usbdrd_phy_init(struct phy *phy) 2081 2192 { 2082 2193 struct phy_usb_instance *inst = phy_get_drvdata(phy); ··· 2243 2086 return ret; 2244 2087 2245 2088 exynos850_usbdrd_phy_exit(phy); 2089 + 2090 + /* enable PHY isol */ 2091 + inst->phy_cfg->phy_isol(inst, true); 2092 + 2093 + clk_bulk_disable_unprepare(phy_drd->drv_data->n_clks, phy_drd->clks); 2094 + 2095 + return 0; 2096 + } 2097 + 2098 + static int exynosautov920_usbdrd_combo_phy_exit(struct phy *phy) 2099 + { 2100 + struct phy_usb_instance *inst = phy_get_drvdata(phy); 2101 + struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst); 2102 + int ret = 0; 2103 + 2104 + ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_clks, phy_drd->clks); 2105 + if (ret) 2106 + return ret; 2107 + 2108 + if (inst->phy_cfg->id == EXYNOS5_DRDPHY_UTMI) 2109 + exynosautov920_usbdrd_hsphy_disable(phy_drd); 2246 2110 2247 2111 /* enable PHY isol */ 2248 2112 inst->phy_cfg->phy_isol(inst, true); ··· 2322 2144 2323 2145 static const char * const exynosautov920_usb20_regulators[] = { 2324 2146 "dvdd", "vdd18", "vdd33", 2147 + }; 2148 + 2149 + static const struct phy_ops exynosautov920_usbdrd_combo_hsphy_ops = { 2150 + .init = exynosautov920_usbdrd_phy_init, 2151 + .exit = exynosautov920_usbdrd_combo_phy_exit, 2152 + .power_on = exynosautov920_usbdrd_phy_power_on, 2153 + .power_off = exynosautov920_usbdrd_phy_power_off, 2154 + .owner = THIS_MODULE, 2155 + }; 2156 + 2157 + static const struct 2158 + exynos5_usbdrd_phy_config usbdrd_hsphy_cfg_exynosautov920[] = { 2159 + { 2160 + .id = EXYNOS5_DRDPHY_UTMI, 2161 + .phy_isol = exynos5_usbdrd_phy_isol, 2162 + .phy_init = exynosautov920_usbdrd_utmi_init, 2163 + }, 2164 + }; 2165 + 2166 + static const 2167 + struct exynos5_usbdrd_phy_drvdata exynosautov920_usbdrd_combo_hsphy = { 2168 + .phy_cfg = usbdrd_hsphy_cfg_exynosautov920, 2169 + .phy_ops = &exynosautov920_usbdrd_combo_hsphy_ops, 2170 + .pmu_offset_usbdrd0_phy = EXYNOSAUTOV920_PHY_CTRL_USB20, 2171 + .clk_names = exynos5_clk_names, 2172 + .n_clks = ARRAY_SIZE(exynos5_clk_names), 2173 + .core_clk_names = exynos5_core_clk_names, 2174 + .n_core_clks = ARRAY_SIZE(exynos5_core_clk_names), 2175 + .regulator_names = exynosautov920_usb20_regulators, 2176 + .n_regulators = ARRAY_SIZE(exynosautov920_usb20_regulators), 2325 2177 }; 2326 2178 2327 2179 static const struct phy_ops exynosautov920_usbdrd_phy_ops = { ··· 2588 2380 }, { 2589 2381 .compatible = "samsung,exynos990-usbdrd-phy", 2590 2382 .data = &exynos990_usbdrd_phy 2383 + }, { 2384 + .compatible = "samsung,exynosautov920-usbdrd-combo-hsphy", 2385 + .data = &exynosautov920_usbdrd_combo_hsphy 2591 2386 }, { 2592 2387 .compatible = "samsung,exynosautov920-usbdrd-phy", 2593 2388 .data = &exynosautov920_usbdrd_phy