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 SS combo phy for ExynosAutov920

Update phy driver to enable SS combo phy for this SoC. New registers'
definitions, phy ops (init/exit), and dedicated phy driver data
structure are added for SS combo phy. Add these changes in the driver
to support SS combo 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-7-pritam.sutar@samsung.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Pritam Manohar Sutar and committed by
Vinod Koul
2fdfc1bb 05681c9c

+322 -4
+321 -4
drivers/phy/samsung/phy-exynos5-usbdrd.c
··· 273 273 #define EXYNOSAUTOV920_DRD_HSPPLLTUNE 0x110 274 274 #define HSPPLLTUNE_FSEL GENMASK(18, 16) 275 275 276 + /* ExynosAutov920 phy usb31drd port reg */ 277 + #define EXYNOSAUTOV920_USB31DRD_PHY_RST_CTRL 0x000 278 + #define PHY_RST_CTRL_PIPE_LANE0_RESET_N_OVRD_EN BIT(5) 279 + #define PHY_RST_CTRL_PIPE_LANE0_RESET_N BIT(4) 280 + #define PHY_RST_CTRL_PHY_RESET_OVRD_EN BIT(1) 281 + #define PHY_RST_CTRL_PHY_RESET BIT(0) 282 + 283 + #define EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0 0x0004 284 + #define PHY_CR_PARA_CON0_PHY0_CR_PARA_ADDR GENMASK(31, 16) 285 + #define PHY_CR_PARA_CON0_PHY0_CR_PARA_CLK BIT(8) 286 + #define PHY_CR_PARA_CON0_PHY0_CR_PARA_ACK BIT(4) 287 + #define PHY_CR_PARA_CON0_PHY0_CR_PARA_SEL BIT(0) 288 + 289 + #define EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON1 0x0008 290 + 291 + #define EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON2 0x000c 292 + #define PHY_CR_PARA_CON2_PHY0_CR_PARA_WR_EN BIT(0) 293 + #define PHY_CR_PARA_CON2_PHY0_CR_PARA_WR_DATA GENMASK(31, 16) 294 + 295 + #define EXYNOSAUTOV920_USB31DRD_PHY_CONFIG0 0x100 296 + #define PHY_CONFIG0_PHY0_PMA_PWR_STABLE BIT(14) 297 + #define PHY_CONFIG0_PHY0_PCS_PWR_STABLE BIT(13) 298 + #define PHY_CONFIG0_PHY0_ANA_PWR_EN BIT(1) 299 + 300 + #define EXYNOSAUTOV920_USB31DRD_PHY_CONFIG7 0x11c 301 + #define PHY_CONFIG7_PHY_TEST_POWERDOWN BIT(24) 302 + 303 + #define EXYNOSAUTOV920_USB31DRD_PHY_CONFIG4 0x110 304 + #define PHY_CONFIG4_PIPE_RX0_SRIS_MODE_EN BIT(2) 305 + 276 306 /* Exynos9 - GS101 */ 277 307 #define EXYNOS850_DRD_SECPMACTL 0x48 278 308 #define SECPMACTL_PMA_ROPLL_REF_CLK_SEL GENMASK(13, 12) ··· 2108 2078 }; 2109 2079 2110 2080 static void 2081 + exynosautov920_usb31drd_cr_clk(struct exynos5_usbdrd_phy *phy_drd, bool high) 2082 + { 2083 + void __iomem *reg_phy = phy_drd->reg_phy; 2084 + u32 reg; 2085 + 2086 + reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0); 2087 + if (high) 2088 + reg |= PHY_CR_PARA_CON0_PHY0_CR_PARA_CLK; 2089 + else 2090 + reg &= ~PHY_CR_PARA_CON0_PHY0_CR_PARA_CLK; 2091 + 2092 + writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0); 2093 + fsleep(1); 2094 + } 2095 + 2096 + static void 2097 + exynosautov920_usb31drd_port_phy_ready(struct exynos5_usbdrd_phy *phy_drd) 2098 + { 2099 + struct device *dev = phy_drd->dev; 2100 + void __iomem *reg_phy = phy_drd->reg_phy; 2101 + static const unsigned int timeout_us = 20000; 2102 + static const unsigned int sleep_us = 40; 2103 + u32 reg; 2104 + int err; 2105 + 2106 + /* Clear cr_para_con */ 2107 + reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0); 2108 + reg &= ~(PHY_CR_PARA_CON0_PHY0_CR_PARA_CLK | 2109 + PHY_CR_PARA_CON0_PHY0_CR_PARA_ADDR); 2110 + reg |= PHY_CR_PARA_CON0_PHY0_CR_PARA_SEL; 2111 + writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0); 2112 + writel(0x0, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON1); 2113 + writel(0x0, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON2); 2114 + 2115 + exynosautov920_usb31drd_cr_clk(phy_drd, true); 2116 + exynosautov920_usb31drd_cr_clk(phy_drd, false); 2117 + 2118 + /* 2119 + * The maximum time from phy reset de-assertion to de-assertion of 2120 + * tx/rx_ack can be as high as 5ms in fast simulation mode. 2121 + * Time to phy ready is < 20ms 2122 + */ 2123 + err = readl_poll_timeout(reg_phy + 2124 + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0, 2125 + reg, !(reg & PHY_CR_PARA_CON0_PHY0_CR_PARA_ACK), 2126 + sleep_us, timeout_us); 2127 + if (err) 2128 + dev_err(dev, "timed out waiting for rx/tx_ack: %#.8x\n", reg); 2129 + 2130 + reg &= ~PHY_CR_PARA_CON0_PHY0_CR_PARA_CLK; 2131 + writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0); 2132 + } 2133 + 2134 + static void 2135 + exynosautov920_usb31drd_cr_write(struct exynos5_usbdrd_phy *phy_drd, 2136 + u16 addr, u16 data) 2137 + { 2138 + void __iomem *reg_phy = phy_drd->reg_phy; 2139 + u32 cnt = 0; 2140 + u32 reg; 2141 + 2142 + /* Pre Clocking */ 2143 + reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0); 2144 + reg |= PHY_CR_PARA_CON0_PHY0_CR_PARA_SEL; 2145 + writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0); 2146 + 2147 + /* 2148 + * tx clks must be available prior to assertion of tx req. 2149 + * tx pstate p2 to p0 transition directly is not permitted. 2150 + * tx clk ready must be asserted synchronously on tx clk prior 2151 + * to internal transmit clk alignment sequence in the phy 2152 + * when entering from p2 to p1 to p0. 2153 + */ 2154 + do { 2155 + exynosautov920_usb31drd_cr_clk(phy_drd, true); 2156 + exynosautov920_usb31drd_cr_clk(phy_drd, false); 2157 + cnt++; 2158 + } while (cnt < 15); 2159 + 2160 + reg &= ~PHY_CR_PARA_CON0_PHY0_CR_PARA_SEL; 2161 + writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0); 2162 + 2163 + /* 2164 + * tx data path is active when tx lane is in p0 state 2165 + * and tx data en asserted. enable cr_para_wr_en. 2166 + */ 2167 + reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON2); 2168 + reg &= ~PHY_CR_PARA_CON2_PHY0_CR_PARA_WR_DATA; 2169 + reg |= FIELD_PREP(PHY_CR_PARA_CON2_PHY0_CR_PARA_WR_DATA, data) | 2170 + PHY_CR_PARA_CON2_PHY0_CR_PARA_WR_EN; 2171 + writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON2); 2172 + 2173 + /* write addr */ 2174 + reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0); 2175 + reg &= ~PHY_CR_PARA_CON0_PHY0_CR_PARA_ADDR; 2176 + reg |= FIELD_PREP(PHY_CR_PARA_CON0_PHY0_CR_PARA_ADDR, addr) | 2177 + PHY_CR_PARA_CON0_PHY0_CR_PARA_CLK | 2178 + PHY_CR_PARA_CON0_PHY0_CR_PARA_SEL; 2179 + writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0); 2180 + 2181 + /* check cr_para_ack*/ 2182 + cnt = 0; 2183 + do { 2184 + /* 2185 + * data symbols are captured by phy on rising edge of the 2186 + * tx_clk when tx data enabled. 2187 + * completion of the write cycle is acknowledged by assertion 2188 + * of the cr_para_ack. 2189 + */ 2190 + exynosautov920_usb31drd_cr_clk(phy_drd, true); 2191 + reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CR_PARA_CON0); 2192 + if ((reg & PHY_CR_PARA_CON0_PHY0_CR_PARA_ACK)) 2193 + break; 2194 + 2195 + exynosautov920_usb31drd_cr_clk(phy_drd, false); 2196 + 2197 + /* 2198 + * wait for minimum of 10 cr_para_clk cycles after phy reset 2199 + * is negated, before accessing control regs to allow for 2200 + * internal resets. 2201 + */ 2202 + cnt++; 2203 + } while (cnt < 10); 2204 + 2205 + if (cnt < 10) 2206 + exynosautov920_usb31drd_cr_clk(phy_drd, false); 2207 + } 2208 + 2209 + static void 2210 + exynosautov920_usb31drd_phy_reset(struct exynos5_usbdrd_phy *phy_drd, int val) 2211 + { 2212 + void __iomem *reg_phy = phy_drd->reg_phy; 2213 + u32 reg; 2214 + 2215 + reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_RST_CTRL); 2216 + reg &= ~PHY_RST_CTRL_PHY_RESET_OVRD_EN; 2217 + writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_RST_CTRL); 2218 + 2219 + reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_RST_CTRL); 2220 + if (val) 2221 + reg |= PHY_RST_CTRL_PHY_RESET; 2222 + else 2223 + reg &= ~PHY_RST_CTRL_PHY_RESET; 2224 + 2225 + reg |= PHY_RST_CTRL_PHY_RESET_OVRD_EN; 2226 + writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_RST_CTRL); 2227 + } 2228 + 2229 + static void 2230 + exynosautov920_usb31drd_lane0_reset(struct exynos5_usbdrd_phy *phy_drd, int val) 2231 + { 2232 + void __iomem *reg_phy = phy_drd->reg_phy; 2233 + u32 reg; 2234 + 2235 + reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_RST_CTRL); 2236 + reg |= PHY_RST_CTRL_PIPE_LANE0_RESET_N_OVRD_EN; 2237 + writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_RST_CTRL); 2238 + 2239 + reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_RST_CTRL); 2240 + if (val) 2241 + reg &= ~PHY_RST_CTRL_PIPE_LANE0_RESET_N; 2242 + else 2243 + reg |= PHY_RST_CTRL_PIPE_LANE0_RESET_N; 2244 + 2245 + reg &= ~PHY_RST_CTRL_PIPE_LANE0_RESET_N_OVRD_EN; 2246 + writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_RST_CTRL); 2247 + } 2248 + 2249 + static void 2250 + exynosautov920_usb31drd_pipe3_init(struct exynos5_usbdrd_phy *phy_drd) 2251 + { 2252 + void __iomem *reg_phy = phy_drd->reg_phy; 2253 + u32 reg; 2254 + 2255 + /* 2256 + * Phy and Pipe Lane reset assert. 2257 + * assert reset (phy_reset = 1). 2258 + * The lane-ack outputs are asserted during reset (tx_ack = rx_ack = 1) 2259 + */ 2260 + exynosautov920_usb31drd_phy_reset(phy_drd, 1); 2261 + exynosautov920_usb31drd_lane0_reset(phy_drd, 1); 2262 + 2263 + /* 2264 + * ANA Power En, PCS & PMA PWR Stable Set 2265 + * ramp-up power suppiles 2266 + */ 2267 + reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CONFIG0); 2268 + reg |= PHY_CONFIG0_PHY0_ANA_PWR_EN | PHY_CONFIG0_PHY0_PCS_PWR_STABLE | 2269 + PHY_CONFIG0_PHY0_PMA_PWR_STABLE; 2270 + writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CONFIG0); 2271 + 2272 + fsleep(10); 2273 + 2274 + /* 2275 + * phy is not functional in test_powerdown mode, test_powerdown to be 2276 + * de-asserted for normal operation 2277 + */ 2278 + reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CONFIG7); 2279 + reg &= ~PHY_CONFIG7_PHY_TEST_POWERDOWN; 2280 + writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CONFIG7); 2281 + 2282 + /* 2283 + * phy reset signal be asserted for minimum 10us after power 2284 + * supplies are ramped-up 2285 + */ 2286 + fsleep(10); 2287 + 2288 + /* 2289 + * Phy and Pipe Lane reset assert de-assert 2290 + */ 2291 + exynosautov920_usb31drd_phy_reset(phy_drd, 0); 2292 + exynosautov920_usb31drd_lane0_reset(phy_drd, 0); 2293 + 2294 + /* Pipe_rx0_sris_mode_en = 1 */ 2295 + reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CONFIG4); 2296 + reg |= PHY_CONFIG4_PIPE_RX0_SRIS_MODE_EN; 2297 + writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CONFIG4); 2298 + 2299 + /* 2300 + * wait for lane ack outputs to de-assert (tx_ack = rx_ack = 0) 2301 + * Exit from the reset state is indicated by de-assertion of *_ack 2302 + */ 2303 + exynosautov920_usb31drd_port_phy_ready(phy_drd); 2304 + 2305 + /* override values for level settings */ 2306 + exynosautov920_usb31drd_cr_write(phy_drd, 0x22, 0x00F5); 2307 + } 2308 + 2309 + static void 2310 + exynosautov920_usb31drd_ssphy_disable(struct exynos5_usbdrd_phy *phy_drd) 2311 + { 2312 + void __iomem *reg_phy = phy_drd->reg_phy; 2313 + u32 reg; 2314 + 2315 + /* 1. Assert reset (phy_reset = 1) */ 2316 + exynosautov920_usb31drd_lane0_reset(phy_drd, 1); 2317 + exynosautov920_usb31drd_phy_reset(phy_drd, 1); 2318 + 2319 + /* phy test power down */ 2320 + reg = readl(reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CONFIG7); 2321 + reg |= PHY_CONFIG7_PHY_TEST_POWERDOWN; 2322 + writel(reg, reg_phy + EXYNOSAUTOV920_USB31DRD_PHY_CONFIG7); 2323 + } 2324 + 2325 + static void 2111 2326 exynosautov920_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd) 2112 2327 { 2113 2328 void __iomem *reg_phy = phy_drd->reg_phy; ··· 2447 2172 /* after POR low and delay 75us, PHYCLOCK is guaranteed. */ 2448 2173 fsleep(75); 2449 2174 2450 - /* force pipe3 signal for link */ 2175 + /* Disable forcing pipe interface */ 2451 2176 reg = readl(reg_phy + EXYNOS850_DRD_LINKCTRL); 2452 - reg |= LINKCTRL_FORCE_PIPE_EN; 2453 - reg &= ~LINKCTRL_FORCE_PHYSTATUS; 2454 - reg |= LINKCTRL_FORCE_RXELECIDLE; 2177 + reg &= ~LINKCTRL_FORCE_PIPE_EN; 2455 2178 writel(reg, reg_phy + EXYNOS850_DRD_LINKCTRL); 2179 + 2180 + /* Pclk to pipe_clk */ 2181 + reg = readl(reg_phy + EXYNOS2200_DRD_CLKRST); 2182 + reg |= EXYNOS2200_CLKRST_LINK_PCLK_SEL; 2183 + writel(reg, reg_phy + EXYNOS2200_DRD_CLKRST); 2456 2184 } 2457 2185 2458 2186 static void ··· 2542 2264 2543 2265 if (inst->phy_cfg->id == EXYNOS5_DRDPHY_UTMI) 2544 2266 exynosautov920_usbdrd_hsphy_disable(phy_drd); 2267 + else if (inst->phy_cfg->id == EXYNOS5_DRDPHY_PIPE3) 2268 + exynosautov920_usb31drd_ssphy_disable(phy_drd); 2545 2269 2546 2270 /* enable PHY isol */ 2547 2271 inst->phy_cfg->phy_isol(inst, true); ··· 2600 2320 return 0; 2601 2321 } 2602 2322 2323 + static const char * const exynosautov920_usb30_regulators[] = { 2324 + "dvdd", "vdd18", 2325 + }; 2326 + 2603 2327 static const char * const exynosautov920_usb20_regulators[] = { 2604 2328 "dvdd", "vdd18", "vdd33", 2329 + }; 2330 + 2331 + static const struct 2332 + exynos5_usbdrd_phy_config usb31drd_phy_cfg_exynosautov920[] = { 2333 + { 2334 + .id = EXYNOS5_DRDPHY_PIPE3, 2335 + .phy_isol = exynos5_usbdrd_phy_isol, 2336 + .phy_init = exynosautov920_usb31drd_pipe3_init, 2337 + }, 2338 + }; 2339 + 2340 + static const struct phy_ops exynosautov920_usb31drd_combo_ssphy_ops = { 2341 + .init = exynosautov920_usbdrd_phy_init, 2342 + .exit = exynosautov920_usbdrd_combo_phy_exit, 2343 + .power_on = exynosautov920_usbdrd_phy_power_on, 2344 + .power_off = exynosautov920_usbdrd_phy_power_off, 2345 + .owner = THIS_MODULE, 2346 + }; 2347 + 2348 + static const 2349 + struct exynos5_usbdrd_phy_drvdata exynosautov920_usb31drd_combo_ssphy = { 2350 + .phy_cfg = usb31drd_phy_cfg_exynosautov920, 2351 + .phy_ops = &exynosautov920_usb31drd_combo_ssphy_ops, 2352 + .pmu_offset_usbdrd0_phy = EXYNOSAUTOV920_PHY_CTRL_USB31, 2353 + .clk_names = exynos5_clk_names, 2354 + .n_clks = ARRAY_SIZE(exynos5_clk_names), 2355 + .core_clk_names = exynos5_core_clk_names, 2356 + .n_core_clks = ARRAY_SIZE(exynos5_core_clk_names), 2357 + .regulator_names = exynosautov920_usb30_regulators, 2358 + .n_regulators = ARRAY_SIZE(exynosautov920_usb30_regulators), 2605 2359 }; 2606 2360 2607 2361 static const struct phy_ops exynosautov920_usbdrd_combo_hsphy_ops = { ··· 2902 2588 }, { 2903 2589 .compatible = "samsung,exynos990-usbdrd-phy", 2904 2590 .data = &exynos990_usbdrd_phy 2591 + }, { 2592 + .compatible = "samsung,exynosautov920-usb31drd-combo-ssphy", 2593 + .data = &exynosautov920_usb31drd_combo_ssphy 2905 2594 }, { 2906 2595 .compatible = "samsung,exynosautov920-usbdrd-combo-hsphy", 2907 2596 .data = &exynosautov920_usbdrd_combo_hsphy
+1
include/linux/soc/samsung/exynos-regs-pmu.h
··· 1017 1017 1018 1018 /* exynosautov920 */ 1019 1019 #define EXYNOSAUTOV920_PHY_CTRL_USB20 (0x0710) 1020 + #define EXYNOSAUTOV920_PHY_CTRL_USB31 (0x0714) 1020 1021 #endif /* __LINUX_SOC_EXYNOS_REGS_PMU_H */