18e98ca1eSSven Peter // SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause 28e98ca1eSSven Peter /* 38e98ca1eSSven Peter * Apple Type-C PHY driver 48e98ca1eSSven Peter * 58e98ca1eSSven Peter * The Apple Type-C PHY (ATCPHY) is a combined PHY for USB 2.0, USB 3.x, 68e98ca1eSSven Peter * USB4/Thunderbolt, and DisplayPort connectivity via Type-C ports found in 78e98ca1eSSven Peter * Apple Silicon SoCs. 88e98ca1eSSven Peter * 98e98ca1eSSven Peter * The PHY handles muxing between these different protocols and also provides the 108e98ca1eSSven Peter * reset controller for the attached DWC3 USB controller. 118e98ca1eSSven Peter * 128e98ca1eSSven Peter * No documentation for this PHY is available and its operation has been 138e98ca1eSSven Peter * reverse engineered by observing the XNU's MMIO access using a thin hypervisor 148e98ca1eSSven Peter * and correlating register access to XNU's very verbose debug output. Most 158e98ca1eSSven Peter * register names comes from this debug output as well. 168e98ca1eSSven Peter * 178e98ca1eSSven Peter * In order to correctly setup the high speed lanes for the various modes 188e98ca1eSSven Peter * calibration values copied from Apple's firmware by our bootloader m1n1 are 198e98ca1eSSven Peter * required. Without these only USB2 operation is possible. 208e98ca1eSSven Peter * 218e98ca1eSSven Peter * Copyright (C) The Asahi Linux Contributors 228e98ca1eSSven Peter * Author: Sven Peter <sven@kernel.org> 238e98ca1eSSven Peter */ 248e98ca1eSSven Peter 258e98ca1eSSven Peter #include <dt-bindings/phy/phy.h> 268e98ca1eSSven Peter #include <linux/bitfield.h> 278e98ca1eSSven Peter #include <linux/cleanup.h> 288e98ca1eSSven Peter #include <linux/delay.h> 298e98ca1eSSven Peter #include <linux/iopoll.h> 308e98ca1eSSven Peter #include <linux/lockdep.h> 318e98ca1eSSven Peter #include <linux/module.h> 328e98ca1eSSven Peter #include <linux/mutex.h> 338e98ca1eSSven Peter #include <linux/of.h> 348e98ca1eSSven Peter #include <linux/of_device.h> 358e98ca1eSSven Peter #include <linux/phy/phy.h> 368e98ca1eSSven Peter #include <linux/platform_device.h> 378e98ca1eSSven Peter #include <linux/reset-controller.h> 388e98ca1eSSven Peter #include <linux/soc/apple/tunable.h> 398e98ca1eSSven Peter #include <linux/types.h> 408e98ca1eSSven Peter #include <linux/usb/pd.h> 418e98ca1eSSven Peter #include <linux/usb/typec.h> 428e98ca1eSSven Peter #include <linux/usb/typec_altmode.h> 438e98ca1eSSven Peter #include <linux/usb/typec_dp.h> 448e98ca1eSSven Peter #include <linux/usb/typec_mux.h> 458e98ca1eSSven Peter #include <linux/usb/typec_tbt.h> 468e98ca1eSSven Peter 478e98ca1eSSven Peter #define AUSPLL_FSM_CTRL 0x1014 488e98ca1eSSven Peter 498e98ca1eSSven Peter #define AUSPLL_APB_CMD_OVERRIDE 0x2000 508e98ca1eSSven Peter #define AUSPLL_APB_CMD_OVERRIDE_REQ BIT(0) 518e98ca1eSSven Peter #define AUSPLL_APB_CMD_OVERRIDE_ACK BIT(1) 528e98ca1eSSven Peter #define AUSPLL_APB_CMD_OVERRIDE_UNK28 BIT(28) 538e98ca1eSSven Peter #define AUSPLL_APB_CMD_OVERRIDE_CMD GENMASK(27, 3) 548e98ca1eSSven Peter 558e98ca1eSSven Peter #define AUSPLL_FREQ_DESC_A 0x2080 568e98ca1eSSven Peter #define AUSPLL_FD_FREQ_COUNT_TARGET GENMASK(9, 0) 578e98ca1eSSven Peter #define AUSPLL_FD_FBDIVN_HALF BIT(10) 588e98ca1eSSven Peter #define AUSPLL_FD_REV_DIVN GENMASK(13, 11) 598e98ca1eSSven Peter #define AUSPLL_FD_KI_MAN GENMASK(17, 14) 608e98ca1eSSven Peter #define AUSPLL_FD_KI_EXP GENMASK(21, 18) 618e98ca1eSSven Peter #define AUSPLL_FD_KP_MAN GENMASK(25, 22) 628e98ca1eSSven Peter #define AUSPLL_FD_KP_EXP GENMASK(29, 26) 638e98ca1eSSven Peter #define AUSPLL_FD_KPKI_SCALE_HBW GENMASK(31, 30) 648e98ca1eSSven Peter 658e98ca1eSSven Peter #define AUSPLL_FREQ_DESC_B 0x2084 668e98ca1eSSven Peter #define AUSPLL_FD_FBDIVN_FRAC_DEN GENMASK(13, 0) 678e98ca1eSSven Peter #define AUSPLL_FD_FBDIVN_FRAC_NUM GENMASK(27, 14) 688e98ca1eSSven Peter 698e98ca1eSSven Peter #define AUSPLL_FREQ_DESC_C 0x2088 708e98ca1eSSven Peter #define AUSPLL_FD_SDM_SSC_STEP GENMASK(7, 0) 718e98ca1eSSven Peter #define AUSPLL_FD_SDM_SSC_EN BIT(8) 728e98ca1eSSven Peter #define AUSPLL_FD_PCLK_DIV_SEL GENMASK(13, 9) 738e98ca1eSSven Peter #define AUSPLL_FD_LFSDM_DIV GENMASK(15, 14) 748e98ca1eSSven Peter #define AUSPLL_FD_LFCLK_CTRL GENMASK(19, 16) 758e98ca1eSSven Peter #define AUSPLL_FD_VCLK_OP_DIVN GENMASK(21, 20) 768e98ca1eSSven Peter #define AUSPLL_FD_VCLK_PRE_DIVN BIT(22) 778e98ca1eSSven Peter 788e98ca1eSSven Peter #define AUSPLL_DCO_EFUSE_SPARE 0x222c 798e98ca1eSSven Peter #define AUSPLL_RODCO_ENCAP_EFUSE GENMASK(10, 9) 808e98ca1eSSven Peter #define AUSPLL_RODCO_BIAS_ADJUST_EFUSE GENMASK(14, 12) 818e98ca1eSSven Peter 828e98ca1eSSven Peter #define AUSPLL_FRACN_CAN 0x22a4 838e98ca1eSSven Peter #define AUSPLL_DLL_START_CAPCODE GENMASK(18, 17) 848e98ca1eSSven Peter 858e98ca1eSSven Peter #define AUSPLL_CLKOUT_MASTER 0x2200 868e98ca1eSSven Peter #define AUSPLL_CLKOUT_MASTER_PCLK_DRVR_EN BIT(2) 878e98ca1eSSven Peter #define AUSPLL_CLKOUT_MASTER_PCLK2_DRVR_EN BIT(4) 888e98ca1eSSven Peter #define AUSPLL_CLKOUT_MASTER_REFBUFCLK_DRVR_EN BIT(6) 898e98ca1eSSven Peter 908e98ca1eSSven Peter #define AUSPLL_CLKOUT_DIV 0x2208 918e98ca1eSSven Peter #define AUSPLL_CLKOUT_PLLA_REFBUFCLK_DI GENMASK(20, 16) 928e98ca1eSSven Peter 938e98ca1eSSven Peter #define AUSPLL_BGR 0x2214 948e98ca1eSSven Peter #define AUSPLL_BGR_CTRL_AVAIL BIT(0) 958e98ca1eSSven Peter 968e98ca1eSSven Peter #define AUSPLL_CLKOUT_DTC_VREG 0x2220 978e98ca1eSSven Peter #define AUSPLL_DTC_VREG_ADJUST GENMASK(16, 14) 988e98ca1eSSven Peter #define AUSPLL_DTC_VREG_BYPASS BIT(7) 998e98ca1eSSven Peter 1008e98ca1eSSven Peter #define AUSPLL_FREQ_CFG 0x2224 1018e98ca1eSSven Peter #define AUSPLL_FREQ_REFCLK GENMASK(1, 0) 1028e98ca1eSSven Peter 1038e98ca1eSSven Peter #define AUS_COMMON_SHIM_BLK_VREG 0x0a04 1048e98ca1eSSven Peter #define AUS_VREG_TRIM GENMASK(6, 2) 1058e98ca1eSSven Peter 1068e98ca1eSSven Peter #define AUS_UNK_A20 0x0a20 1078e98ca1eSSven Peter #define AUS_UNK_A20_TX_CAL_CODE GENMASK(23, 20) 1088e98ca1eSSven Peter 1098e98ca1eSSven Peter #define ACIOPHY_CMN_SHM_STS_REG0 0x0a74 1108e98ca1eSSven Peter #define ACIOPHY_CMN_SHM_STS_REG0_CMD_READY BIT(0) 1118e98ca1eSSven Peter 1128e98ca1eSSven Peter #define CIO3PLL_CLK_CTRL 0x2a00 1138e98ca1eSSven Peter #define CIO3PLL_CLK_PCLK_EN BIT(1) 1148e98ca1eSSven Peter #define CIO3PLL_CLK_REFCLK_EN BIT(5) 1158e98ca1eSSven Peter 1168e98ca1eSSven Peter #define CIO3PLL_DCO_NCTRL 0x2a38 1178e98ca1eSSven Peter #define CIO3PLL_DCO_COARSEBIN_EFUSE0 GENMASK(6, 0) 1188e98ca1eSSven Peter #define CIO3PLL_DCO_COARSEBIN_EFUSE1 GENMASK(23, 17) 1198e98ca1eSSven Peter 1208e98ca1eSSven Peter #define CIO3PLL_FRACN_CAN 0x2aa4 1218e98ca1eSSven Peter #define CIO3PLL_DLL_CAL_START_CAPCODE GENMASK(18, 17) 1228e98ca1eSSven Peter 1238e98ca1eSSven Peter #define CIO3PLL_DTC_VREG 0x2a20 1248e98ca1eSSven Peter #define CIO3PLL_DTC_VREG_ADJUST GENMASK(16, 14) 1258e98ca1eSSven Peter 1268e98ca1eSSven Peter #define ACIOPHY_CFG0 0x08 1278e98ca1eSSven Peter #define ACIOPHY_CFG0_COMMON_BIG_OV BIT(1) 1288e98ca1eSSven Peter #define ACIOPHY_CFG0_COMMON_SMALL_OV BIT(3) 1298e98ca1eSSven Peter #define ACIOPHY_CFG0_COMMON_CLAMP_OV BIT(5) 1308e98ca1eSSven Peter #define ACIOPHY_CFG0_RX_SMALL_OV GENMASK(9, 8) 1318e98ca1eSSven Peter #define ACIOPHY_CFG0_RX_BIG_OV GENMASK(13, 12) 1328e98ca1eSSven Peter #define ACIOPHY_CFG0_RX_CLAMP_OV GENMASK(17, 16) 1338e98ca1eSSven Peter 1348e98ca1eSSven Peter #define ACIOPHY_CROSSBAR 0x4c 1358e98ca1eSSven Peter #define ACIOPHY_CROSSBAR_PROTOCOL GENMASK(4, 0) 1368e98ca1eSSven Peter #define ACIOPHY_CROSSBAR_PROTOCOL_USB4 0x0 1378e98ca1eSSven Peter #define ACIOPHY_CROSSBAR_PROTOCOL_USB4_SWAPPED 0x1 1388e98ca1eSSven Peter #define ACIOPHY_CROSSBAR_PROTOCOL_USB3 0xa 1398e98ca1eSSven Peter #define ACIOPHY_CROSSBAR_PROTOCOL_USB3_SWAPPED 0xb 1408e98ca1eSSven Peter #define ACIOPHY_CROSSBAR_PROTOCOL_USB3_DP 0x10 1418e98ca1eSSven Peter #define ACIOPHY_CROSSBAR_PROTOCOL_USB3_DP_SWAPPED 0x11 1428e98ca1eSSven Peter #define ACIOPHY_CROSSBAR_PROTOCOL_DP 0x14 1438e98ca1eSSven Peter #define ACIOPHY_CROSSBAR_DP_SINGLE_PMA GENMASK(16, 5) 1448e98ca1eSSven Peter #define ACIOPHY_CROSSBAR_DP_SINGLE_PMA_NONE 0x0000 1458e98ca1eSSven Peter #define ACIOPHY_CROSSBAR_DP_SINGLE_PMA_UNK100 0x100 1468e98ca1eSSven Peter #define ACIOPHY_CROSSBAR_DP_SINGLE_PMA_UNK008 0x008 1478e98ca1eSSven Peter #define ACIOPHY_CROSSBAR_DP_BOTH_PMA BIT(17) 1488e98ca1eSSven Peter 1498e98ca1eSSven Peter #define ACIOPHY_LANE_MODE 0x48 1508e98ca1eSSven Peter #define ACIOPHY_LANE_MODE_RX0 GENMASK(2, 0) 1518e98ca1eSSven Peter #define ACIOPHY_LANE_MODE_TX0 GENMASK(5, 3) 1528e98ca1eSSven Peter #define ACIOPHY_LANE_MODE_RX1 GENMASK(8, 6) 1538e98ca1eSSven Peter #define ACIOPHY_LANE_MODE_TX1 GENMASK(11, 9) 1548e98ca1eSSven Peter 1558e98ca1eSSven Peter enum atcphy_lane_mode { 1568e98ca1eSSven Peter ACIOPHY_LANE_MODE_USB4 = 0, 1578e98ca1eSSven Peter ACIOPHY_LANE_MODE_USB3 = 1, 1588e98ca1eSSven Peter ACIOPHY_LANE_MODE_DP = 2, 1598e98ca1eSSven Peter ACIOPHY_LANE_MODE_OFF = 3, 1608e98ca1eSSven Peter }; 1618e98ca1eSSven Peter 1628e98ca1eSSven Peter #define ACIOPHY_TOP_BIST_CIOPHY_CFG1 0x84 1638e98ca1eSSven Peter #define ACIOPHY_TOP_BIST_CIOPHY_CFG1_CLK_EN BIT(27) 1648e98ca1eSSven Peter #define ACIOPHY_TOP_BIST_CIOPHY_CFG1_BIST_EN BIT(28) 1658e98ca1eSSven Peter 1668e98ca1eSSven Peter #define ACIOPHY_TOP_BIST_OV_CFG 0x8c 1678e98ca1eSSven Peter #define ACIOPHY_TOP_BIST_OV_CFG_LN0_RESET_N_OV BIT(13) 1688e98ca1eSSven Peter #define ACIOPHY_TOP_BIST_OV_CFG_LN0_PWR_DOWN_OV BIT(25) 1698e98ca1eSSven Peter 1708e98ca1eSSven Peter #define ACIOPHY_TOP_BIST_READ_CTRL 0x90 1718e98ca1eSSven Peter #define ACIOPHY_TOP_BIST_READ_CTRL_LN0_PHY_STATUS_RE BIT(2) 1728e98ca1eSSven Peter 1738e98ca1eSSven Peter #define ACIOPHY_TOP_PHY_STAT 0x9c 1748e98ca1eSSven Peter #define ACIOPHY_TOP_PHY_STAT_LN0_UNK0 BIT(0) 1758e98ca1eSSven Peter #define ACIOPHY_TOP_PHY_STAT_LN0_UNK23 BIT(23) 1768e98ca1eSSven Peter 1778e98ca1eSSven Peter #define ACIOPHY_TOP_BIST_PHY_CFG0 0xa8 1788e98ca1eSSven Peter #define ACIOPHY_TOP_BIST_PHY_CFG0_LN0_RESET_N BIT(0) 1798e98ca1eSSven Peter 1808e98ca1eSSven Peter #define ACIOPHY_TOP_BIST_PHY_CFG1 0xac 1818e98ca1eSSven Peter #define ACIOPHY_TOP_BIST_PHY_CFG1_LN0_PWR_DOWN GENMASK(13, 10) 1828e98ca1eSSven Peter 1838e98ca1eSSven Peter #define ACIOPHY_SLEEP_CTRL 0x1b0 1848e98ca1eSSven Peter #define ACIOPHY_SLEEP_CTRL_TX_BIG_OV GENMASK(3, 2) 1858e98ca1eSSven Peter #define ACIOPHY_SLEEP_CTRL_TX_SMALL_OV GENMASK(7, 6) 1868e98ca1eSSven Peter #define ACIOPHY_SLEEP_CTRL_TX_CLAMP_OV GENMASK(11, 10) 1878e98ca1eSSven Peter 1888e98ca1eSSven Peter #define ACIOPHY_PLL_PCTL_FSM_CTRL1 0x1014 1898e98ca1eSSven Peter #define ACIOPHY_PLL_APB_REQ_OV_SEL GENMASK(21, 13) 1908e98ca1eSSven Peter #define ACIOPHY_PLL_COMMON_CTRL 0x1028 1918e98ca1eSSven Peter #define ACIOPHY_PLL_WAIT_FOR_CMN_READY_BEFORE_RESET_EXIT BIT(24) 1928e98ca1eSSven Peter 1938e98ca1eSSven Peter #define ATCPHY_POWER_CTRL 0x20000 1948e98ca1eSSven Peter #define ATCPHY_POWER_STAT 0x20004 1958e98ca1eSSven Peter #define ATCPHY_POWER_SLEEP_SMALL BIT(0) 1968e98ca1eSSven Peter #define ATCPHY_POWER_SLEEP_BIG BIT(1) 1978e98ca1eSSven Peter #define ATCPHY_POWER_CLAMP_EN BIT(2) 1988e98ca1eSSven Peter #define ATCPHY_POWER_APB_RESET_N BIT(3) 1998e98ca1eSSven Peter #define ATCPHY_POWER_PHY_RESET_N BIT(4) 2008e98ca1eSSven Peter 2018e98ca1eSSven Peter #define ATCPHY_MISC 0x20008 2028e98ca1eSSven Peter #define ATCPHY_MISC_RESET_N BIT(0) 2038e98ca1eSSven Peter #define ATCPHY_MISC_LANE_SWAP BIT(2) 2048e98ca1eSSven Peter 2058e98ca1eSSven Peter #define ACIOPHY_LANE_DP_CFG_BLK_TX_DP_CTRL0 0x7000 2068e98ca1eSSven Peter #define DP_PMA_BYTECLK_RESET BIT(0) 2078e98ca1eSSven Peter #define DP_MAC_DIV20_CLK_SEL BIT(1) 2088e98ca1eSSven Peter #define DPTXPHY_PMA_LANE_RESET_N BIT(2) 2098e98ca1eSSven Peter #define DPTXPHY_PMA_LANE_RESET_N_OV BIT(3) 2108e98ca1eSSven Peter #define DPTX_PCLK1_SELECT GENMASK(6, 4) 2118e98ca1eSSven Peter #define DPTX_PCLK2_SELECT GENMASK(9, 7) 2128e98ca1eSSven Peter #define DPRX_PCLK_SELECT GENMASK(12, 10) 2138e98ca1eSSven Peter #define DPTX_PCLK1_ENABLE BIT(13) 2148e98ca1eSSven Peter #define DPTX_PCLK2_ENABLE BIT(14) 2158e98ca1eSSven Peter #define DPRX_PCLK_ENABLE BIT(15) 2168e98ca1eSSven Peter 2178e98ca1eSSven Peter #define ACIOPHY_DP_PCLK_STAT 0x7044 2188e98ca1eSSven Peter #define ACIOPHY_AUSPLL_LOCK BIT(3) 2198e98ca1eSSven Peter 2208e98ca1eSSven Peter #define LN0_AUSPMA_RX_TOP 0x9000 2218e98ca1eSSven Peter #define LN0_AUSPMA_RX_EQ 0xA000 2228e98ca1eSSven Peter #define LN0_AUSPMA_RX_SHM 0xB000 2238e98ca1eSSven Peter #define LN0_AUSPMA_TX_TOP 0xC000 2248e98ca1eSSven Peter #define LN0_AUSPMA_TX_SHM 0xD000 2258e98ca1eSSven Peter 2268e98ca1eSSven Peter #define LN1_AUSPMA_RX_TOP 0x10000 2278e98ca1eSSven Peter #define LN1_AUSPMA_RX_EQ 0x11000 2288e98ca1eSSven Peter #define LN1_AUSPMA_RX_SHM 0x12000 2298e98ca1eSSven Peter #define LN1_AUSPMA_TX_TOP 0x13000 2308e98ca1eSSven Peter #define LN1_AUSPMA_TX_SHM 0x14000 2318e98ca1eSSven Peter 2328e98ca1eSSven Peter #define LN_AUSPMA_RX_TOP_PMAFSM 0x0010 2338e98ca1eSSven Peter #define LN_AUSPMA_RX_TOP_PMAFSM_PCS_OV BIT(0) 2348e98ca1eSSven Peter #define LN_AUSPMA_RX_TOP_PMAFSM_PCS_REQ BIT(9) 2358e98ca1eSSven Peter 2368e98ca1eSSven Peter #define LN_AUSPMA_RX_TOP_TJ_CFG_RX_TXMODE 0x00F0 2378e98ca1eSSven Peter #define LN_RX_TXMODE BIT(0) 2388e98ca1eSSven Peter 2398e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_RXA_CTLE_CTRL0 0x00 2408e98ca1eSSven Peter #define LN_TX_CLK_EN BIT(20) 2418e98ca1eSSven Peter #define LN_TX_CLK_EN_OV BIT(21) 2428e98ca1eSSven Peter 2438e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_RXA_AFE_CTRL1 0x04 2448e98ca1eSSven Peter #define LN_RX_DIV20_RESET_N_OV BIT(29) 2458e98ca1eSSven Peter #define LN_RX_DIV20_RESET_N BIT(30) 2468e98ca1eSSven Peter 2478e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_RXA_UNK_CTRL2 0x08 2488e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_RXA_UNK_CTRL3 0x0C 2498e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_RXA_UNK_CTRL4 0x10 2508e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_RXA_UNK_CTRL5 0x14 2518e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_RXA_UNK_CTRL6 0x18 2528e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_RXA_UNK_CTRL7 0x1C 2538e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_RXA_UNK_CTRL8 0x20 2548e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_RXA_UNK_CTRL9 0x24 2558e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL10 0x28 2568e98ca1eSSven Peter #define LN_DTVREG_ADJUST GENMASK(31, 27) 2578e98ca1eSSven Peter 2588e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL11 0x2C 2598e98ca1eSSven Peter #define LN_DTVREG_BIG_EN BIT(23) 2608e98ca1eSSven Peter #define LN_DTVREG_BIG_EN_OV BIT(24) 2618e98ca1eSSven Peter #define LN_DTVREG_SML_EN BIT(25) 2628e98ca1eSSven Peter #define LN_DTVREG_SML_EN_OV BIT(26) 2638e98ca1eSSven Peter 2648e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL12 0x30 2658e98ca1eSSven Peter #define LN_TX_BYTECLK_RESET_SYNC_CLR BIT(22) 2668e98ca1eSSven Peter #define LN_TX_BYTECLK_RESET_SYNC_CLR_OV BIT(23) 2678e98ca1eSSven Peter #define LN_TX_BYTECLK_RESET_SYNC_EN BIT(24) 2688e98ca1eSSven Peter #define LN_TX_BYTECLK_RESET_SYNC_EN_OV BIT(25) 2698e98ca1eSSven Peter #define LN_TX_HRCLK_SEL BIT(28) 2708e98ca1eSSven Peter #define LN_TX_HRCLK_SEL_OV BIT(29) 2718e98ca1eSSven Peter #define LN_TX_PBIAS_EN BIT(30) 2728e98ca1eSSven Peter #define LN_TX_PBIAS_EN_OV BIT(31) 2738e98ca1eSSven Peter 2748e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL13 0x34 2758e98ca1eSSven Peter #define LN_TX_PRE_EN BIT(0) 2768e98ca1eSSven Peter #define LN_TX_PRE_EN_OV BIT(1) 2778e98ca1eSSven Peter #define LN_TX_PST1_EN BIT(2) 2788e98ca1eSSven Peter #define LN_TX_PST1_EN_OV BIT(3) 2798e98ca1eSSven Peter #define LN_DTVREG_ADJUST_OV BIT(15) 2808e98ca1eSSven Peter 2818e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_UNK_CTRL14A 0x38 2828e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_UNK_CTRL14B 0x3C 2838e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_UNK_CTRL15A 0x40 2848e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_UNK_CTRL15B 0x44 2858e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_RXA_SAVOS_CTRL16 0x48 2868e98ca1eSSven Peter #define LN_RXTERM_EN BIT(21) 2878e98ca1eSSven Peter #define LN_RXTERM_EN_OV BIT(22) 2888e98ca1eSSven Peter #define LN_RXTERM_PULLUP_LEAK_EN BIT(23) 2898e98ca1eSSven Peter #define LN_RXTERM_PULLUP_LEAK_EN_OV BIT(24) 2908e98ca1eSSven Peter #define LN_TX_CAL_CODE GENMASK(29, 25) 2918e98ca1eSSven Peter #define LN_TX_CAL_CODE_OV BIT(30) 2928e98ca1eSSven Peter 2938e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL17 0x4C 2948e98ca1eSSven Peter #define LN_TX_MARGIN GENMASK(19, 15) 2958e98ca1eSSven Peter #define LN_TX_MARGIN_OV BIT(20) 2968e98ca1eSSven Peter #define LN_TX_MARGIN_LSB BIT(21) 2978e98ca1eSSven Peter #define LN_TX_MARGIN_LSB_OV BIT(22) 2988e98ca1eSSven Peter #define LN_TX_MARGIN_P1 GENMASK(26, 23) 2998e98ca1eSSven Peter #define LN_TX_MARGIN_P1_OV BIT(27) 3008e98ca1eSSven Peter #define LN_TX_MARGIN_P1_LSB GENMASK(29, 28) 3018e98ca1eSSven Peter #define LN_TX_MARGIN_P1_LSB_OV BIT(30) 3028e98ca1eSSven Peter 3038e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL18 0x50 3048e98ca1eSSven Peter #define LN_TX_P1_CODE GENMASK(3, 0) 3058e98ca1eSSven Peter #define LN_TX_P1_CODE_OV BIT(4) 3068e98ca1eSSven Peter #define LN_TX_P1_LSB_CODE GENMASK(6, 5) 3078e98ca1eSSven Peter #define LN_TX_P1_LSB_CODE_OV BIT(7) 3088e98ca1eSSven Peter #define LN_TX_MARGIN_PRE GENMASK(10, 8) 3098e98ca1eSSven Peter #define LN_TX_MARGIN_PRE_OV BIT(11) 3108e98ca1eSSven Peter #define LN_TX_MARGIN_PRE_LSB GENMASK(13, 12) 3118e98ca1eSSven Peter #define LN_TX_MARGIN_PRE_LSB_OV BIT(14) 3128e98ca1eSSven Peter #define LN_TX_PRE_LSB_CODE GENMASK(16, 15) 3138e98ca1eSSven Peter #define LN_TX_PRE_LSB_CODE_OV BIT(17) 3148e98ca1eSSven Peter #define LN_TX_PRE_CODE GENMASK(21, 18) 3158e98ca1eSSven Peter #define LN_TX_PRE_CODE_OV BIT(22) 3168e98ca1eSSven Peter 3178e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_RXA_TERM_CTRL19 0x54 3188e98ca1eSSven Peter #define LN_TX_TEST_EN BIT(21) 3198e98ca1eSSven Peter #define LN_TX_TEST_EN_OV BIT(22) 3208e98ca1eSSven Peter #define LN_TX_EN BIT(23) 3218e98ca1eSSven Peter #define LN_TX_EN_OV BIT(24) 3228e98ca1eSSven Peter #define LN_TX_CLK_DLY_CTRL_TAPGEN GENMASK(27, 25) 3238e98ca1eSSven Peter #define LN_TX_CLK_DIV2_EN BIT(28) 3248e98ca1eSSven Peter #define LN_TX_CLK_DIV2_EN_OV BIT(29) 3258e98ca1eSSven Peter #define LN_TX_CLK_DIV2_RST BIT(30) 3268e98ca1eSSven Peter #define LN_TX_CLK_DIV2_RST_OV BIT(31) 3278e98ca1eSSven Peter 3288e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_RXA_UNK_CTRL20 0x58 3298e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_RXA_UNK_CTRL21 0x5C 3308e98ca1eSSven Peter #define LN_AUSPMA_RX_SHM_TJ_RXA_VREF_CTRL22 0x60 3318e98ca1eSSven Peter #define LN_VREF_ADJUST_GRAY GENMASK(11, 7) 3328e98ca1eSSven Peter #define LN_VREF_ADJUST_GRAY_OV BIT(12) 3338e98ca1eSSven Peter #define LN_VREF_BIAS_SEL GENMASK(14, 13) 3348e98ca1eSSven Peter #define LN_VREF_BIAS_SEL_OV BIT(15) 3358e98ca1eSSven Peter #define LN_VREF_BOOST_EN BIT(16) 3368e98ca1eSSven Peter #define LN_VREF_BOOST_EN_OV BIT(17) 3378e98ca1eSSven Peter #define LN_VREF_EN BIT(18) 3388e98ca1eSSven Peter #define LN_VREF_EN_OV BIT(19) 3398e98ca1eSSven Peter #define LN_VREF_LPBKIN_DATA GENMASK(29, 28) 3408e98ca1eSSven Peter #define LN_VREF_TEST_RXLPBKDT_EN BIT(30) 3418e98ca1eSSven Peter #define LN_VREF_TEST_RXLPBKDT_EN_OV BIT(31) 3428e98ca1eSSven Peter 3438e98ca1eSSven Peter #define LN_AUSPMA_TX_SHM_TXA_CFG_MAIN_REG0 0x00 3448e98ca1eSSven Peter #define LN_BYTECLK_RESET_SYNC_EN_OV BIT(2) 3458e98ca1eSSven Peter #define LN_BYTECLK_RESET_SYNC_EN BIT(3) 3468e98ca1eSSven Peter #define LN_BYTECLK_RESET_SYNC_CLR_OV BIT(4) 3478e98ca1eSSven Peter #define LN_BYTECLK_RESET_SYNC_CLR BIT(5) 3488e98ca1eSSven Peter #define LN_BYTECLK_RESET_SYNC_SEL_OV BIT(6) 3498e98ca1eSSven Peter 3508e98ca1eSSven Peter #define LN_AUSPMA_TX_SHM_TXA_CFG_MAIN_REG1 0x04 3518e98ca1eSSven Peter #define LN_TXA_DIV2_EN_OV BIT(8) 3528e98ca1eSSven Peter #define LN_TXA_DIV2_EN BIT(9) 3538e98ca1eSSven Peter #define LN_TXA_DIV2_RESET_OV BIT(10) 3548e98ca1eSSven Peter #define LN_TXA_DIV2_RESET BIT(11) 3558e98ca1eSSven Peter #define LN_TXA_CLK_EN_OV BIT(22) 3568e98ca1eSSven Peter #define LN_TXA_CLK_EN BIT(23) 3578e98ca1eSSven Peter 3588e98ca1eSSven Peter #define LN_AUSPMA_TX_SHM_TXA_IMP_REG0 0x08 3598e98ca1eSSven Peter #define LN_TXA_CAL_CTRL_OV BIT(0) 3608e98ca1eSSven Peter #define LN_TXA_CAL_CTRL GENMASK(18, 1) 3618e98ca1eSSven Peter #define LN_TXA_CAL_CTRL_BASE_OV BIT(19) 3628e98ca1eSSven Peter #define LN_TXA_CAL_CTRL_BASE GENMASK(23, 20) 3638e98ca1eSSven Peter #define LN_TXA_HIZ_OV BIT(29) 3648e98ca1eSSven Peter #define LN_TXA_HIZ BIT(30) 3658e98ca1eSSven Peter 3668e98ca1eSSven Peter #define LN_AUSPMA_TX_SHM_TXA_IMP_REG1 0x0C 3678e98ca1eSSven Peter #define LN_AUSPMA_TX_SHM_TXA_IMP_REG2 0x10 3688e98ca1eSSven Peter #define LN_TXA_MARGIN_OV BIT(0) 3698e98ca1eSSven Peter #define LN_TXA_MARGIN GENMASK(18, 1) 3708e98ca1eSSven Peter #define LN_TXA_MARGIN_2R_OV BIT(19) 3718e98ca1eSSven Peter #define LN_TXA_MARGIN_2R BIT(20) 3728e98ca1eSSven Peter 3738e98ca1eSSven Peter #define LN_AUSPMA_TX_SHM_TXA_IMP_REG3 0x14 3748e98ca1eSSven Peter #define LN_TXA_MARGIN_POST_OV BIT(0) 3758e98ca1eSSven Peter #define LN_TXA_MARGIN_POST GENMASK(10, 1) 3768e98ca1eSSven Peter #define LN_TXA_MARGIN_POST_2R_OV BIT(11) 3778e98ca1eSSven Peter #define LN_TXA_MARGIN_POST_2R BIT(12) 3788e98ca1eSSven Peter #define LN_TXA_MARGIN_POST_4R_OV BIT(13) 3798e98ca1eSSven Peter #define LN_TXA_MARGIN_POST_4R BIT(14) 3808e98ca1eSSven Peter #define LN_TXA_MARGIN_PRE_OV BIT(15) 3818e98ca1eSSven Peter #define LN_TXA_MARGIN_PRE GENMASK(21, 16) 3828e98ca1eSSven Peter #define LN_TXA_MARGIN_PRE_2R_OV BIT(22) 3838e98ca1eSSven Peter #define LN_TXA_MARGIN_PRE_2R BIT(23) 3848e98ca1eSSven Peter #define LN_TXA_MARGIN_PRE_4R_OV BIT(24) 3858e98ca1eSSven Peter #define LN_TXA_MARGIN_PRE_4R BIT(25) 3868e98ca1eSSven Peter 3878e98ca1eSSven Peter #define LN_AUSPMA_TX_SHM_TXA_UNK_REG0 0x18 3888e98ca1eSSven Peter #define LN_AUSPMA_TX_SHM_TXA_UNK_REG1 0x1C 3898e98ca1eSSven Peter #define LN_AUSPMA_TX_SHM_TXA_UNK_REG2 0x20 3908e98ca1eSSven Peter 3918e98ca1eSSven Peter #define LN_AUSPMA_TX_SHM_TXA_LDOCLK 0x24 3928e98ca1eSSven Peter #define LN_LDOCLK_BYPASS_SML_OV BIT(8) 3938e98ca1eSSven Peter #define LN_LDOCLK_BYPASS_SML BIT(9) 3948e98ca1eSSven Peter #define LN_LDOCLK_BYPASS_BIG_OV BIT(10) 3958e98ca1eSSven Peter #define LN_LDOCLK_BYPASS_BIG BIT(11) 3968e98ca1eSSven Peter #define LN_LDOCLK_EN_SML_OV BIT(12) 3978e98ca1eSSven Peter #define LN_LDOCLK_EN_SML BIT(13) 3988e98ca1eSSven Peter #define LN_LDOCLK_EN_BIG_OV BIT(14) 3998e98ca1eSSven Peter #define LN_LDOCLK_EN_BIG BIT(15) 4008e98ca1eSSven Peter 4018e98ca1eSSven Peter /* LPDPTX registers */ 4028e98ca1eSSven Peter #define LPDPTX_AUX_CFG_BLK_AUX_CTRL 0x0000 4038e98ca1eSSven Peter #define LPDPTX_BLK_AUX_CTRL_PWRDN BIT(4) 4048e98ca1eSSven Peter #define LPDPTX_BLK_AUX_RXOFFSET GENMASK(25, 22) 4058e98ca1eSSven Peter 4068e98ca1eSSven Peter #define LPDPTX_AUX_CFG_BLK_AUX_LDO_CTRL 0x0008 4078e98ca1eSSven Peter 4088e98ca1eSSven Peter #define LPDPTX_AUX_CFG_BLK_AUX_MARGIN 0x000c 4098e98ca1eSSven Peter #define LPDPTX_MARGIN_RCAL_RXOFFSET_EN BIT(5) 4108e98ca1eSSven Peter #define LPDPTX_AUX_MARGIN_RCAL_TXSWING GENMASK(10, 6) 4118e98ca1eSSven Peter 4128e98ca1eSSven Peter #define LPDPTX_AUX_SHM_CFG_BLK_AUX_CTRL_REG0 0x0204 4138e98ca1eSSven Peter #define LPDPTX_CFG_PMA_AUX_SEL_LF_DATA BIT(15) 4148e98ca1eSSven Peter 4158e98ca1eSSven Peter #define LPDPTX_AUX_SHM_CFG_BLK_AUX_CTRL_REG1 0x0208 4168e98ca1eSSven Peter #define LPDPTX_CFG_PMA_PHYS_ADJ GENMASK(22, 20) 4178e98ca1eSSven Peter #define LPDPTX_CFG_PMA_PHYS_ADJ_OV BIT(19) 4188e98ca1eSSven Peter 4198e98ca1eSSven Peter #define LPDPTX_AUX_CONTROL 0x4000 4208e98ca1eSSven Peter #define LPDPTX_AUX_PWN_DOWN 0x10 4218e98ca1eSSven Peter #define LPDPTX_AUX_CLAMP_EN 0x04 4228e98ca1eSSven Peter #define LPDPTX_SLEEP_B_BIG_IN 0x02 4238e98ca1eSSven Peter #define LPDPTX_SLEEP_B_SML_IN 0x01 4248e98ca1eSSven Peter #define LPDPTX_TXTERM_CODEMSB 0x400 4258e98ca1eSSven Peter #define LPDPTX_TXTERM_CODE GENMASK(9, 5) 4268e98ca1eSSven Peter 4278e98ca1eSSven Peter /* pipehandler registers */ 4288e98ca1eSSven Peter #define PIPEHANDLER_OVERRIDE 0x00 4298e98ca1eSSven Peter #define PIPEHANDLER_OVERRIDE_RXVALID BIT(0) 4308e98ca1eSSven Peter #define PIPEHANDLER_OVERRIDE_RXDETECT BIT(2) 4318e98ca1eSSven Peter 4328e98ca1eSSven Peter #define PIPEHANDLER_OVERRIDE_VALUES 0x04 4338e98ca1eSSven Peter #define PIPEHANDLER_OVERRIDE_VAL_RXDETECT0 BIT(1) 4348e98ca1eSSven Peter #define PIPEHANDLER_OVERRIDE_VAL_RXDETECT1 BIT(2) 4358e98ca1eSSven Peter #define PIPEHANDLER_OVERRIDE_VAL_PHY_STATUS BIT(4) 4368e98ca1eSSven Peter 4378e98ca1eSSven Peter #define PIPEHANDLER_MUX_CTRL 0x0c 4388e98ca1eSSven Peter #define PIPEHANDLER_MUX_CTRL_CLK GENMASK(5, 3) 4398e98ca1eSSven Peter #define PIPEHANDLER_MUX_CTRL_DATA GENMASK(2, 0) 4408e98ca1eSSven Peter #define PIPEHANDLER_MUX_CTRL_CLK_OFF 0 4418e98ca1eSSven Peter #define PIPEHANDLER_MUX_CTRL_CLK_USB3 1 4428e98ca1eSSven Peter #define PIPEHANDLER_MUX_CTRL_CLK_USB4 2 4438e98ca1eSSven Peter #define PIPEHANDLER_MUX_CTRL_CLK_DUMMY 4 4448e98ca1eSSven Peter 4458e98ca1eSSven Peter #define PIPEHANDLER_MUX_CTRL_DATA_USB3 0 4468e98ca1eSSven Peter #define PIPEHANDLER_MUX_CTRL_DATA_USB4 1 4478e98ca1eSSven Peter #define PIPEHANDLER_MUX_CTRL_DATA_DUMMY 2 4488e98ca1eSSven Peter 4498e98ca1eSSven Peter #define PIPEHANDLER_LOCK_REQ 0x10 4508e98ca1eSSven Peter #define PIPEHANDLER_LOCK_ACK 0x14 4518e98ca1eSSven Peter #define PIPEHANDLER_LOCK_EN BIT(0) 4528e98ca1eSSven Peter 4538e98ca1eSSven Peter #define PIPEHANDLER_AON_GEN 0x1C 4548e98ca1eSSven Peter #define PIPEHANDLER_AON_GEN_DWC3_FORCE_CLAMP_EN BIT(4) 4558e98ca1eSSven Peter #define PIPEHANDLER_AON_GEN_DWC3_RESET_N BIT(0) 4568e98ca1eSSven Peter 4578e98ca1eSSven Peter #define PIPEHANDLER_NONSELECTED_OVERRIDE 0x20 4588e98ca1eSSven Peter #define PIPEHANDLER_NATIVE_RESET BIT(12) 4598e98ca1eSSven Peter #define PIPEHANDLER_DUMMY_PHY_EN BIT(15) 4608e98ca1eSSven Peter #define PIPEHANDLER_NATIVE_POWER_DOWN GENMASK(3, 0) 4618e98ca1eSSven Peter 4628e98ca1eSSven Peter #define PIPEHANDLER_LOCK_ACK_TIMEOUT_US 1000 4638e98ca1eSSven Peter 4648e98ca1eSSven Peter /* USB2 PHY regs */ 4658e98ca1eSSven Peter #define USB2PHY_USBCTL 0x00 4668e98ca1eSSven Peter #define USB2PHY_USBCTL_RUN 2 4678e98ca1eSSven Peter #define USB2PHY_USBCTL_ISOLATION 4 4688e98ca1eSSven Peter 4698e98ca1eSSven Peter #define USB2PHY_CTL 0x04 4708e98ca1eSSven Peter #define USB2PHY_CTL_RESET BIT(0) 4718e98ca1eSSven Peter #define USB2PHY_CTL_PORT_RESET BIT(1) 4728e98ca1eSSven Peter #define USB2PHY_CTL_APB_RESET_N BIT(2) 4738e98ca1eSSven Peter #define USB2PHY_CTL_SIDDQ BIT(3) 4748e98ca1eSSven Peter 4758e98ca1eSSven Peter #define USB2PHY_SIG 0x08 4768e98ca1eSSven Peter #define USB2PHY_SIG_VBUSDET_FORCE_VAL BIT(0) 4778e98ca1eSSven Peter #define USB2PHY_SIG_VBUSDET_FORCE_EN BIT(1) 4788e98ca1eSSven Peter #define USB2PHY_SIG_VBUSVLDEXT_FORCE_VAL BIT(2) 4798e98ca1eSSven Peter #define USB2PHY_SIG_VBUSVLDEXT_FORCE_EN BIT(3) 4808e98ca1eSSven Peter #define USB2PHY_SIG_HOST (7 << 12) 4818e98ca1eSSven Peter 4828e98ca1eSSven Peter #define USB2PHY_MISCTUNE 0x1c 4838e98ca1eSSven Peter #define USB2PHY_MISCTUNE_APBCLK_GATE_OFF BIT(29) 4848e98ca1eSSven Peter #define USB2PHY_MISCTUNE_REFCLK_GATE_OFF BIT(30) 4858e98ca1eSSven Peter 4868e98ca1eSSven Peter enum atcphy_dp_link_rate { 4878e98ca1eSSven Peter ATCPHY_DP_LINK_RATE_RBR, 4888e98ca1eSSven Peter ATCPHY_DP_LINK_RATE_HBR, 4898e98ca1eSSven Peter ATCPHY_DP_LINK_RATE_HBR2, 4908e98ca1eSSven Peter ATCPHY_DP_LINK_RATE_HBR3, 4918e98ca1eSSven Peter }; 4928e98ca1eSSven Peter 4938e98ca1eSSven Peter /** 4948e98ca1eSSven Peter * enum atcphy_pipehandler_state - States of the PIPE mux interface ("pipehandler") 4958e98ca1eSSven Peter * @ATCPHY_PIPEHANDLER_STATE_DUMMY: "Dummy PHY" (disables USB3, USB2 only) 4968e98ca1eSSven Peter * @ATCPHY_PIPEHANDLER_STATE_USB3: USB3 directly connected to the Type-C port 4978e98ca1eSSven Peter * @ATCPHY_PIPEHANDLER_STATE_USB4: USB3 tunneled via USB4/Thunderbolt 4988e98ca1eSSven Peter * 4998e98ca1eSSven Peter * DWC3's USB3 PIPE interface is connected to a multiplexer inside this PHY 5008e98ca1eSSven Peter * which can switch between a dummy state (which effectively disables any USB3 5018e98ca1eSSven Peter * support and falls back to USB2 only operation via the separate ULPI interface), 5028e98ca1eSSven Peter * a USB3 state (for regular USB3 or USB3+DisplayPort operation) and a USB4 state 5038e98ca1eSSven Peter * (for USB3 tunneled via USB4/Thunderbolt). 5048e98ca1eSSven Peter */ 5058e98ca1eSSven Peter enum atcphy_pipehandler_state { 5068e98ca1eSSven Peter ATCPHY_PIPEHANDLER_STATE_DUMMY, 5078e98ca1eSSven Peter ATCPHY_PIPEHANDLER_STATE_USB3, 5088e98ca1eSSven Peter ATCPHY_PIPEHANDLER_STATE_USB4, 5098e98ca1eSSven Peter }; 5108e98ca1eSSven Peter 5118e98ca1eSSven Peter /** 5128e98ca1eSSven Peter * enum atcphy_mode - Operating modes of the PHY 5138e98ca1eSSven Peter * @APPLE_ATCPHY_MODE_OFF: all PHYs powered off 5148e98ca1eSSven Peter * @APPLE_ATCPHY_MODE_USB2: Nothing on the four SS lanes (i.e. USB2 only on D-/+) 5158e98ca1eSSven Peter * @APPLE_ATCPHY_MODE_USB3: USB3 on two lanes, nothing on the other two 5168e98ca1eSSven Peter * @APPLE_ATCPHY_MODE_USB3_DP: USB3 on two lanes and DisplayPort on the other two 5178e98ca1eSSven Peter * @APPLE_ATCPHY_MODE_TBT: Thunderbolt on all lanes 5188e98ca1eSSven Peter * @APPLE_ATCPHY_MODE_USB4: USB4 on all lanes 5198e98ca1eSSven Peter * @APPLE_ATCPHY_MODE_DP: DisplayPort on all lanes 5208e98ca1eSSven Peter */ 5218e98ca1eSSven Peter enum atcphy_mode { 5228e98ca1eSSven Peter APPLE_ATCPHY_MODE_OFF, 5238e98ca1eSSven Peter APPLE_ATCPHY_MODE_USB2, 5248e98ca1eSSven Peter APPLE_ATCPHY_MODE_USB3, 5258e98ca1eSSven Peter APPLE_ATCPHY_MODE_USB3_DP, 5268e98ca1eSSven Peter APPLE_ATCPHY_MODE_TBT, 5278e98ca1eSSven Peter APPLE_ATCPHY_MODE_USB4, 5288e98ca1eSSven Peter APPLE_ATCPHY_MODE_DP, 5298e98ca1eSSven Peter }; 5308e98ca1eSSven Peter 5318e98ca1eSSven Peter enum atcphy_lane { 5328e98ca1eSSven Peter APPLE_ATCPHY_LANE_0, 5338e98ca1eSSven Peter APPLE_ATCPHY_LANE_1, 5348e98ca1eSSven Peter }; 5358e98ca1eSSven Peter 5368e98ca1eSSven Peter /* Link rate configuration, field names are taken from XNU debug output or register names */ 5378e98ca1eSSven Peter struct atcphy_dp_link_rate_configuration { 5388e98ca1eSSven Peter u16 freqinit_count_target; 5398e98ca1eSSven Peter u16 fbdivn_frac_den; 5408e98ca1eSSven Peter u16 fbdivn_frac_num; 5418e98ca1eSSven Peter u16 pclk_div_sel; 5428e98ca1eSSven Peter u8 lfclk_ctrl; 5438e98ca1eSSven Peter u8 vclk_op_divn; 5448e98ca1eSSven Peter bool plla_clkout_vreg_bypass; 5458e98ca1eSSven Peter bool txa_ldoclk_bypass; 5468e98ca1eSSven Peter bool txa_div2_en; 5478e98ca1eSSven Peter }; 5488e98ca1eSSven Peter 5498e98ca1eSSven Peter /* Crossbar and lane configuration */ 5508e98ca1eSSven Peter struct atcphy_mode_configuration { 5518e98ca1eSSven Peter u32 crossbar; 5528e98ca1eSSven Peter u32 crossbar_dp_single_pma; 5538e98ca1eSSven Peter bool crossbar_dp_both_pma; 5548e98ca1eSSven Peter enum atcphy_lane_mode lane_mode[2]; 5558e98ca1eSSven Peter bool dp_lane[2]; 5568e98ca1eSSven Peter bool set_swap; 5578e98ca1eSSven Peter }; 5588e98ca1eSSven Peter 5598e98ca1eSSven Peter /** 5608e98ca1eSSven Peter * struct apple_atcphy - Apple Type-C PHY device struct 5618e98ca1eSSven Peter * @np: Device node pointer 5628e98ca1eSSven Peter * @dev: Device pointer 5638e98ca1eSSven Peter * @tunables: Firmware-provided tunable parameters 5648e98ca1eSSven Peter * @tunables.axi2af: AXI to AF interface tunables 5658e98ca1eSSven Peter * @tunables.common: Common tunables for all lanes 5668e98ca1eSSven Peter * @tunables.lane_usb3: USB3 lane-specific tunables 5678e98ca1eSSven Peter * @tunables.lane_dp: DisplayPort lane-specific tunables 5688e98ca1eSSven Peter * @tunables.lane_usb4: USB4 lane-specific tunables 5698e98ca1eSSven Peter * @mode: Current PHY operating mode 5708e98ca1eSSven Peter * @swap_lanes: True if lanes must be swapped due to cable orientation 5718e98ca1eSSven Peter * @dp_link_rate: DisplayPort link rate 5728e98ca1eSSven Peter * @pipehandler_up: True if the PIPE mux ("pipehandler") is set to USB3 or USB4 mode 5738e98ca1eSSven Peter * @regs: Memory-mapped registers 5748e98ca1eSSven Peter * @regs.core: Core registers 5758e98ca1eSSven Peter * @regs.axi2af: AXI to Apple Fabric interface registers 5768e98ca1eSSven Peter * @regs.usb2phy: USB2 PHY registers 5778e98ca1eSSven Peter * @regs.pipehandler: USB3 PIPE interface ("pipehandler") registers 5788e98ca1eSSven Peter * @regs.lpdptx: DisplayPort registers 5798e98ca1eSSven Peter * @res: Resources for memory-mapped registers, used to verify that tunables aren't out of bounds 5808e98ca1eSSven Peter * @res.core: Core register resource 5818e98ca1eSSven Peter * @res.axi2af: AXI to Apple Fabric interface resource 5828e98ca1eSSven Peter * @phys: PHY instances 5838e98ca1eSSven Peter * @phys.usb2: USB2 PHY instance 5848e98ca1eSSven Peter * @phys.usb3: USB3 PHY instance 5858e98ca1eSSven Peter * @phys.dp: DisplayPort PHY instance 5868e98ca1eSSven Peter * @phy_provider: PHY provider instance 5878e98ca1eSSven Peter * @rcdev: Reset controller device 5888e98ca1eSSven Peter * @sw: Type-C switch instance 5898e98ca1eSSven Peter * @mux: Type-C mux instance 5908e98ca1eSSven Peter * @lock: Mutex for synchronizing register access across PHY, Type-C switch/mux and reset controller 5918e98ca1eSSven Peter */ 5928e98ca1eSSven Peter struct apple_atcphy { 5938e98ca1eSSven Peter struct device_node *np; 5948e98ca1eSSven Peter struct device *dev; 5958e98ca1eSSven Peter 5968e98ca1eSSven Peter struct { 5978e98ca1eSSven Peter struct apple_tunable *axi2af; 5988e98ca1eSSven Peter struct apple_tunable *common[2]; 5998e98ca1eSSven Peter struct apple_tunable *lane_usb3[2]; 6008e98ca1eSSven Peter struct apple_tunable *lane_dp[2]; 6018e98ca1eSSven Peter struct apple_tunable *lane_usb4[2]; 6028e98ca1eSSven Peter } tunables; 6038e98ca1eSSven Peter 6048e98ca1eSSven Peter enum atcphy_mode mode; 6058e98ca1eSSven Peter bool swap_lanes; 6068e98ca1eSSven Peter int dp_link_rate; 6078e98ca1eSSven Peter bool pipehandler_up; 6088e98ca1eSSven Peter 6098e98ca1eSSven Peter struct { 6108e98ca1eSSven Peter void __iomem *core; 6118e98ca1eSSven Peter void __iomem *axi2af; 6128e98ca1eSSven Peter void __iomem *usb2phy; 6138e98ca1eSSven Peter void __iomem *pipehandler; 6148e98ca1eSSven Peter void __iomem *lpdptx; 6158e98ca1eSSven Peter } regs; 6168e98ca1eSSven Peter 6178e98ca1eSSven Peter struct { 6188e98ca1eSSven Peter struct resource *core; 6198e98ca1eSSven Peter struct resource *axi2af; 6208e98ca1eSSven Peter } res; 6218e98ca1eSSven Peter 6228e98ca1eSSven Peter struct { 6238e98ca1eSSven Peter struct phy *usb2; 6248e98ca1eSSven Peter struct phy *usb3; 6258e98ca1eSSven Peter struct phy *dp; 6268e98ca1eSSven Peter } phys; 6278e98ca1eSSven Peter struct phy_provider *phy_provider; 6288e98ca1eSSven Peter 6298e98ca1eSSven Peter struct reset_controller_dev rcdev; 6308e98ca1eSSven Peter 6318e98ca1eSSven Peter struct typec_switch *sw; 6328e98ca1eSSven Peter struct typec_mux *mux; 6338e98ca1eSSven Peter 6348e98ca1eSSven Peter struct mutex lock; 6358e98ca1eSSven Peter }; 6368e98ca1eSSven Peter 6378e98ca1eSSven Peter static const struct { 6388e98ca1eSSven Peter const struct atcphy_mode_configuration normal; 6398e98ca1eSSven Peter const struct atcphy_mode_configuration swapped; 6408e98ca1eSSven Peter bool enable_dp_aux; 6418e98ca1eSSven Peter enum atcphy_pipehandler_state pipehandler_state; 6428e98ca1eSSven Peter } atcphy_modes[] = { 6438e98ca1eSSven Peter [APPLE_ATCPHY_MODE_OFF] = { 6448e98ca1eSSven Peter .normal = { 6458e98ca1eSSven Peter .crossbar = ACIOPHY_CROSSBAR_PROTOCOL_USB3, 6468e98ca1eSSven Peter .crossbar_dp_single_pma = ACIOPHY_CROSSBAR_DP_SINGLE_PMA_NONE, 6478e98ca1eSSven Peter .crossbar_dp_both_pma = false, 6488e98ca1eSSven Peter .lane_mode = {ACIOPHY_LANE_MODE_OFF, ACIOPHY_LANE_MODE_OFF}, 6498e98ca1eSSven Peter .dp_lane = {false, false}, 6508e98ca1eSSven Peter .set_swap = false, 6518e98ca1eSSven Peter }, 6528e98ca1eSSven Peter .swapped = { 6538e98ca1eSSven Peter .crossbar = ACIOPHY_CROSSBAR_PROTOCOL_USB3_SWAPPED, 6548e98ca1eSSven Peter .crossbar_dp_single_pma = ACIOPHY_CROSSBAR_DP_SINGLE_PMA_NONE, 6558e98ca1eSSven Peter .crossbar_dp_both_pma = false, 6568e98ca1eSSven Peter .lane_mode = {ACIOPHY_LANE_MODE_OFF, ACIOPHY_LANE_MODE_OFF}, 6578e98ca1eSSven Peter .dp_lane = {false, false}, 6588e98ca1eSSven Peter .set_swap = false, /* doesn't matter since the SS lanes are off */ 6598e98ca1eSSven Peter }, 6608e98ca1eSSven Peter .enable_dp_aux = false, 6618e98ca1eSSven Peter .pipehandler_state = ATCPHY_PIPEHANDLER_STATE_DUMMY, 6628e98ca1eSSven Peter }, 6638e98ca1eSSven Peter [APPLE_ATCPHY_MODE_USB2] = { 6648e98ca1eSSven Peter .normal = { 6658e98ca1eSSven Peter .crossbar = ACIOPHY_CROSSBAR_PROTOCOL_USB3, 6668e98ca1eSSven Peter .crossbar_dp_single_pma = ACIOPHY_CROSSBAR_DP_SINGLE_PMA_NONE, 6678e98ca1eSSven Peter .crossbar_dp_both_pma = false, 6688e98ca1eSSven Peter .lane_mode = {ACIOPHY_LANE_MODE_OFF, ACIOPHY_LANE_MODE_OFF}, 6698e98ca1eSSven Peter .dp_lane = {false, false}, 6708e98ca1eSSven Peter .set_swap = false, 6718e98ca1eSSven Peter }, 6728e98ca1eSSven Peter .swapped = { 6738e98ca1eSSven Peter .crossbar = ACIOPHY_CROSSBAR_PROTOCOL_USB3_SWAPPED, 6748e98ca1eSSven Peter .crossbar_dp_single_pma = ACIOPHY_CROSSBAR_DP_SINGLE_PMA_NONE, 6758e98ca1eSSven Peter .crossbar_dp_both_pma = false, 6768e98ca1eSSven Peter .lane_mode = {ACIOPHY_LANE_MODE_OFF, ACIOPHY_LANE_MODE_OFF}, 6778e98ca1eSSven Peter .dp_lane = {false, false}, 6788e98ca1eSSven Peter .set_swap = false, /* doesn't matter since the SS lanes are off */ 6798e98ca1eSSven Peter }, 6808e98ca1eSSven Peter .enable_dp_aux = false, 6818e98ca1eSSven Peter .pipehandler_state = ATCPHY_PIPEHANDLER_STATE_DUMMY, 6828e98ca1eSSven Peter }, 6838e98ca1eSSven Peter [APPLE_ATCPHY_MODE_USB3] = { 6848e98ca1eSSven Peter /* 6858e98ca1eSSven Peter * Setting up the lanes as DP/USB3 is intentional here, USB3/USB3 does not work 6868e98ca1eSSven Peter * and isn't required since this PHY does not support 20GBps mode anyway. 6878e98ca1eSSven Peter * The only difference to APPLE_ATCPHY_MODE_USB3_DP is that DP Aux is not enabled. 6888e98ca1eSSven Peter */ 6898e98ca1eSSven Peter .normal = { 6908e98ca1eSSven Peter .crossbar = ACIOPHY_CROSSBAR_PROTOCOL_USB3_DP, 6918e98ca1eSSven Peter .crossbar_dp_single_pma = ACIOPHY_CROSSBAR_DP_SINGLE_PMA_UNK008, 6928e98ca1eSSven Peter .crossbar_dp_both_pma = false, 6938e98ca1eSSven Peter .lane_mode = {ACIOPHY_LANE_MODE_USB3, ACIOPHY_LANE_MODE_DP}, 6948e98ca1eSSven Peter .dp_lane = {false, true}, 6958e98ca1eSSven Peter .set_swap = false, 6968e98ca1eSSven Peter }, 6978e98ca1eSSven Peter .swapped = { 6988e98ca1eSSven Peter .crossbar = ACIOPHY_CROSSBAR_PROTOCOL_USB3_DP_SWAPPED, 6998e98ca1eSSven Peter .crossbar_dp_single_pma = ACIOPHY_CROSSBAR_DP_SINGLE_PMA_UNK008, 7008e98ca1eSSven Peter .crossbar_dp_both_pma = false, 7018e98ca1eSSven Peter .lane_mode = {ACIOPHY_LANE_MODE_DP, ACIOPHY_LANE_MODE_USB3}, 7028e98ca1eSSven Peter .dp_lane = {true, false}, 7038e98ca1eSSven Peter .set_swap = true, 7048e98ca1eSSven Peter }, 7058e98ca1eSSven Peter .enable_dp_aux = false, 7068e98ca1eSSven Peter .pipehandler_state = ATCPHY_PIPEHANDLER_STATE_USB3, 7078e98ca1eSSven Peter }, 7088e98ca1eSSven Peter [APPLE_ATCPHY_MODE_USB3_DP] = { 7098e98ca1eSSven Peter .normal = { 7108e98ca1eSSven Peter .crossbar = ACIOPHY_CROSSBAR_PROTOCOL_USB3_DP, 7118e98ca1eSSven Peter .crossbar_dp_single_pma = ACIOPHY_CROSSBAR_DP_SINGLE_PMA_UNK008, 7128e98ca1eSSven Peter .crossbar_dp_both_pma = false, 7138e98ca1eSSven Peter .lane_mode = {ACIOPHY_LANE_MODE_USB3, ACIOPHY_LANE_MODE_DP}, 7148e98ca1eSSven Peter .dp_lane = {false, true}, 7158e98ca1eSSven Peter .set_swap = false, 7168e98ca1eSSven Peter }, 7178e98ca1eSSven Peter .swapped = { 7188e98ca1eSSven Peter .crossbar = ACIOPHY_CROSSBAR_PROTOCOL_USB3_DP_SWAPPED, 7198e98ca1eSSven Peter .crossbar_dp_single_pma = ACIOPHY_CROSSBAR_DP_SINGLE_PMA_UNK008, 7208e98ca1eSSven Peter .crossbar_dp_both_pma = false, 7218e98ca1eSSven Peter .lane_mode = {ACIOPHY_LANE_MODE_DP, ACIOPHY_LANE_MODE_USB3}, 7228e98ca1eSSven Peter .dp_lane = {true, false}, 7238e98ca1eSSven Peter .set_swap = true, 7248e98ca1eSSven Peter }, 7258e98ca1eSSven Peter .enable_dp_aux = true, 7268e98ca1eSSven Peter .pipehandler_state = ATCPHY_PIPEHANDLER_STATE_USB3, 7278e98ca1eSSven Peter }, 7288e98ca1eSSven Peter [APPLE_ATCPHY_MODE_TBT] = { 7298e98ca1eSSven Peter .normal = { 7308e98ca1eSSven Peter .crossbar = ACIOPHY_CROSSBAR_PROTOCOL_USB4, 7318e98ca1eSSven Peter .crossbar_dp_single_pma = ACIOPHY_CROSSBAR_DP_SINGLE_PMA_NONE, 7328e98ca1eSSven Peter .crossbar_dp_both_pma = false, 7338e98ca1eSSven Peter .lane_mode = {ACIOPHY_LANE_MODE_USB4, ACIOPHY_LANE_MODE_USB4}, 7348e98ca1eSSven Peter .dp_lane = {false, false}, 7358e98ca1eSSven Peter .set_swap = false, 7368e98ca1eSSven Peter }, 7378e98ca1eSSven Peter .swapped = { 7388e98ca1eSSven Peter .crossbar = ACIOPHY_CROSSBAR_PROTOCOL_USB4_SWAPPED, 7398e98ca1eSSven Peter .crossbar_dp_single_pma = ACIOPHY_CROSSBAR_DP_SINGLE_PMA_NONE, 7408e98ca1eSSven Peter .crossbar_dp_both_pma = false, 7418e98ca1eSSven Peter .lane_mode = {ACIOPHY_LANE_MODE_USB4, ACIOPHY_LANE_MODE_USB4}, 7428e98ca1eSSven Peter .dp_lane = {false, false}, 7438e98ca1eSSven Peter .set_swap = false, /* intentionally false */ 7448e98ca1eSSven Peter }, 7458e98ca1eSSven Peter .enable_dp_aux = false, 7468e98ca1eSSven Peter .pipehandler_state = ATCPHY_PIPEHANDLER_STATE_DUMMY, 7478e98ca1eSSven Peter }, 7488e98ca1eSSven Peter [APPLE_ATCPHY_MODE_USB4] = { 7498e98ca1eSSven Peter .normal = { 7508e98ca1eSSven Peter .crossbar = ACIOPHY_CROSSBAR_PROTOCOL_USB4, 7518e98ca1eSSven Peter .crossbar_dp_single_pma = ACIOPHY_CROSSBAR_DP_SINGLE_PMA_NONE, 7528e98ca1eSSven Peter .crossbar_dp_both_pma = false, 7538e98ca1eSSven Peter .lane_mode = {ACIOPHY_LANE_MODE_USB4, ACIOPHY_LANE_MODE_USB4}, 7548e98ca1eSSven Peter .dp_lane = {false, false}, 7558e98ca1eSSven Peter .set_swap = false, 7568e98ca1eSSven Peter }, 7578e98ca1eSSven Peter .swapped = { 7588e98ca1eSSven Peter .crossbar = ACIOPHY_CROSSBAR_PROTOCOL_USB4_SWAPPED, 7598e98ca1eSSven Peter .crossbar_dp_single_pma = ACIOPHY_CROSSBAR_DP_SINGLE_PMA_NONE, 7608e98ca1eSSven Peter .crossbar_dp_both_pma = false, 7618e98ca1eSSven Peter .lane_mode = {ACIOPHY_LANE_MODE_USB4, ACIOPHY_LANE_MODE_USB4}, 7628e98ca1eSSven Peter .dp_lane = {false, false}, 7638e98ca1eSSven Peter .set_swap = false, /* intentionally false */ 7648e98ca1eSSven Peter }, 7658e98ca1eSSven Peter .enable_dp_aux = false, 7668e98ca1eSSven Peter .pipehandler_state = ATCPHY_PIPEHANDLER_STATE_USB4, 7678e98ca1eSSven Peter }, 7688e98ca1eSSven Peter [APPLE_ATCPHY_MODE_DP] = { 7698e98ca1eSSven Peter .normal = { 7708e98ca1eSSven Peter .crossbar = ACIOPHY_CROSSBAR_PROTOCOL_DP, 7718e98ca1eSSven Peter .crossbar_dp_single_pma = ACIOPHY_CROSSBAR_DP_SINGLE_PMA_UNK100, 7728e98ca1eSSven Peter .crossbar_dp_both_pma = true, 7738e98ca1eSSven Peter .lane_mode = {ACIOPHY_LANE_MODE_DP, ACIOPHY_LANE_MODE_DP}, 7748e98ca1eSSven Peter .dp_lane = {true, true}, 7758e98ca1eSSven Peter .set_swap = false, 7768e98ca1eSSven Peter }, 7778e98ca1eSSven Peter .swapped = { 7788e98ca1eSSven Peter .crossbar = ACIOPHY_CROSSBAR_PROTOCOL_DP, 7798e98ca1eSSven Peter .crossbar_dp_single_pma = ACIOPHY_CROSSBAR_DP_SINGLE_PMA_UNK008, 7808e98ca1eSSven Peter .crossbar_dp_both_pma = false, /* intentionally false */ 7818e98ca1eSSven Peter .lane_mode = {ACIOPHY_LANE_MODE_DP, ACIOPHY_LANE_MODE_DP}, 7828e98ca1eSSven Peter .dp_lane = {true, true}, 7838e98ca1eSSven Peter .set_swap = false, /* intentionally false */ 7848e98ca1eSSven Peter }, 7858e98ca1eSSven Peter .enable_dp_aux = true, 7868e98ca1eSSven Peter .pipehandler_state = ATCPHY_PIPEHANDLER_STATE_DUMMY, 7878e98ca1eSSven Peter }, 7888e98ca1eSSven Peter }; 7898e98ca1eSSven Peter 7908e98ca1eSSven Peter static const struct atcphy_dp_link_rate_configuration dp_lr_config[] = { 7918e98ca1eSSven Peter [ATCPHY_DP_LINK_RATE_RBR] = { 7928e98ca1eSSven Peter .freqinit_count_target = 0x21c, 7938e98ca1eSSven Peter .fbdivn_frac_den = 0x0, 7948e98ca1eSSven Peter .fbdivn_frac_num = 0x0, 7958e98ca1eSSven Peter .pclk_div_sel = 0x13, 7968e98ca1eSSven Peter .lfclk_ctrl = 0x5, 7978e98ca1eSSven Peter .vclk_op_divn = 0x2, 7988e98ca1eSSven Peter .plla_clkout_vreg_bypass = true, 7998e98ca1eSSven Peter .txa_ldoclk_bypass = true, 8008e98ca1eSSven Peter .txa_div2_en = true, 8018e98ca1eSSven Peter }, 8028e98ca1eSSven Peter [ATCPHY_DP_LINK_RATE_HBR] = { 8038e98ca1eSSven Peter .freqinit_count_target = 0x1c2, 8048e98ca1eSSven Peter .fbdivn_frac_den = 0x3ffe, 8058e98ca1eSSven Peter .fbdivn_frac_num = 0x1fff, 8068e98ca1eSSven Peter .pclk_div_sel = 0x9, 8078e98ca1eSSven Peter .lfclk_ctrl = 0x5, 8088e98ca1eSSven Peter .vclk_op_divn = 0x2, 8098e98ca1eSSven Peter .plla_clkout_vreg_bypass = true, 8108e98ca1eSSven Peter .txa_ldoclk_bypass = true, 8118e98ca1eSSven Peter .txa_div2_en = false, 8128e98ca1eSSven Peter }, 8138e98ca1eSSven Peter [ATCPHY_DP_LINK_RATE_HBR2] = { 8148e98ca1eSSven Peter .freqinit_count_target = 0x1c2, 8158e98ca1eSSven Peter .fbdivn_frac_den = 0x3ffe, 8168e98ca1eSSven Peter .fbdivn_frac_num = 0x1fff, 8178e98ca1eSSven Peter .pclk_div_sel = 0x4, 8188e98ca1eSSven Peter .lfclk_ctrl = 0x5, 8198e98ca1eSSven Peter .vclk_op_divn = 0x0, 8208e98ca1eSSven Peter .plla_clkout_vreg_bypass = true, 8218e98ca1eSSven Peter .txa_ldoclk_bypass = true, 8228e98ca1eSSven Peter .txa_div2_en = false, 8238e98ca1eSSven Peter }, 8248e98ca1eSSven Peter [ATCPHY_DP_LINK_RATE_HBR3] = { 8258e98ca1eSSven Peter .freqinit_count_target = 0x2a3, 8268e98ca1eSSven Peter .fbdivn_frac_den = 0x3ffc, 8278e98ca1eSSven Peter .fbdivn_frac_num = 0x2ffd, 8288e98ca1eSSven Peter .pclk_div_sel = 0x4, 8298e98ca1eSSven Peter .lfclk_ctrl = 0x6, 8308e98ca1eSSven Peter .vclk_op_divn = 0x0, 8318e98ca1eSSven Peter .plla_clkout_vreg_bypass = false, 8328e98ca1eSSven Peter .txa_ldoclk_bypass = false, 8338e98ca1eSSven Peter .txa_div2_en = false, 8348e98ca1eSSven Peter }, 8358e98ca1eSSven Peter }; 8368e98ca1eSSven Peter 8378e98ca1eSSven Peter static inline void mask32(void __iomem *reg, u32 mask, u32 set) 8388e98ca1eSSven Peter { 8398e98ca1eSSven Peter u32 value = readl(reg); 8408e98ca1eSSven Peter 8418e98ca1eSSven Peter value &= ~mask; 8428e98ca1eSSven Peter value |= set; 8438e98ca1eSSven Peter writel(value, reg); 8448e98ca1eSSven Peter } 8458e98ca1eSSven Peter 8468e98ca1eSSven Peter static inline void core_mask32(struct apple_atcphy *atcphy, u32 reg, u32 mask, u32 set) 8478e98ca1eSSven Peter { 8488e98ca1eSSven Peter mask32(atcphy->regs.core + reg, mask, set); 8498e98ca1eSSven Peter } 8508e98ca1eSSven Peter 8518e98ca1eSSven Peter static inline void set32(void __iomem *reg, u32 set) 8528e98ca1eSSven Peter { 8538e98ca1eSSven Peter mask32(reg, 0, set); 8548e98ca1eSSven Peter } 8558e98ca1eSSven Peter 8568e98ca1eSSven Peter static inline void core_set32(struct apple_atcphy *atcphy, u32 reg, u32 set) 8578e98ca1eSSven Peter { 8588e98ca1eSSven Peter core_mask32(atcphy, reg, 0, set); 8598e98ca1eSSven Peter } 8608e98ca1eSSven Peter 8618e98ca1eSSven Peter static inline void clear32(void __iomem *reg, u32 clear) 8628e98ca1eSSven Peter { 8638e98ca1eSSven Peter mask32(reg, clear, 0); 8648e98ca1eSSven Peter } 8658e98ca1eSSven Peter 8668e98ca1eSSven Peter static inline void core_clear32(struct apple_atcphy *atcphy, u32 reg, u32 clear) 8678e98ca1eSSven Peter { 8688e98ca1eSSven Peter core_mask32(atcphy, reg, clear, 0); 8698e98ca1eSSven Peter } 8708e98ca1eSSven Peter 8718e98ca1eSSven Peter static const struct atcphy_mode_configuration *atcphy_get_mode_config(struct apple_atcphy *atcphy, 8728e98ca1eSSven Peter enum atcphy_mode mode) 8738e98ca1eSSven Peter { 8748e98ca1eSSven Peter if (atcphy->swap_lanes) 8758e98ca1eSSven Peter return &atcphy_modes[mode].swapped; 8768e98ca1eSSven Peter else 8778e98ca1eSSven Peter return &atcphy_modes[mode].normal; 8788e98ca1eSSven Peter } 8798e98ca1eSSven Peter 8808e98ca1eSSven Peter static void atcphy_apply_tunables(struct apple_atcphy *atcphy, enum atcphy_mode mode) 8818e98ca1eSSven Peter { 8828e98ca1eSSven Peter const int lane0 = atcphy->swap_lanes ? 1 : 0; 8838e98ca1eSSven Peter const int lane1 = atcphy->swap_lanes ? 0 : 1; 8848e98ca1eSSven Peter 8858e98ca1eSSven Peter apple_tunable_apply(atcphy->regs.core, atcphy->tunables.common[0]); 8868e98ca1eSSven Peter apple_tunable_apply(atcphy->regs.axi2af, atcphy->tunables.axi2af); 8878e98ca1eSSven Peter apple_tunable_apply(atcphy->regs.core, atcphy->tunables.common[1]); 8888e98ca1eSSven Peter 8898e98ca1eSSven Peter switch (mode) { 8908e98ca1eSSven Peter /* 8918e98ca1eSSven Peter * USB 3.2 Gen 2x2 / SuperSpeed 20Gbps is not supported by this hardware and applying USB3 8928e98ca1eSSven Peter * tunables to both lanes does not result in a working PHY configuration. Thus, both 8938e98ca1eSSven Peter * USB3-only and USB3/DP get the same tunable setup here. 8948e98ca1eSSven Peter */ 8958e98ca1eSSven Peter case APPLE_ATCPHY_MODE_USB3: 8968e98ca1eSSven Peter case APPLE_ATCPHY_MODE_USB3_DP: 8978e98ca1eSSven Peter apple_tunable_apply(atcphy->regs.core, atcphy->tunables.lane_usb3[lane0]); 8988e98ca1eSSven Peter apple_tunable_apply(atcphy->regs.core, atcphy->tunables.lane_dp[lane1]); 8998e98ca1eSSven Peter break; 9008e98ca1eSSven Peter 9018e98ca1eSSven Peter case APPLE_ATCPHY_MODE_DP: 9028e98ca1eSSven Peter apple_tunable_apply(atcphy->regs.core, atcphy->tunables.lane_dp[lane0]); 9038e98ca1eSSven Peter apple_tunable_apply(atcphy->regs.core, atcphy->tunables.lane_dp[lane1]); 9048e98ca1eSSven Peter break; 9058e98ca1eSSven Peter 9068e98ca1eSSven Peter /* 9078e98ca1eSSven Peter * Even though the various Thunderbolt versions and USB4 are different protocols they need 9088e98ca1eSSven Peter * the same tunables. The actual protocol-specific setup happens inside the Thunderbolt/USB4 9098e98ca1eSSven Peter * native host interface. 9108e98ca1eSSven Peter */ 9118e98ca1eSSven Peter case APPLE_ATCPHY_MODE_TBT: 9128e98ca1eSSven Peter case APPLE_ATCPHY_MODE_USB4: 9138e98ca1eSSven Peter apple_tunable_apply(atcphy->regs.core, atcphy->tunables.lane_usb4[lane0]); 9148e98ca1eSSven Peter apple_tunable_apply(atcphy->regs.core, atcphy->tunables.lane_usb4[lane1]); 9158e98ca1eSSven Peter break; 9168e98ca1eSSven Peter 9178e98ca1eSSven Peter case APPLE_ATCPHY_MODE_OFF: 9188e98ca1eSSven Peter case APPLE_ATCPHY_MODE_USB2: 9198e98ca1eSSven Peter break; 9208e98ca1eSSven Peter } 9218e98ca1eSSven Peter } 9228e98ca1eSSven Peter 9238e98ca1eSSven Peter static int atcphy_pipehandler_lock(struct apple_atcphy *atcphy) 9248e98ca1eSSven Peter { 9258e98ca1eSSven Peter int ret; 9268e98ca1eSSven Peter u32 reg; 9278e98ca1eSSven Peter 9288e98ca1eSSven Peter if (readl(atcphy->regs.pipehandler + PIPEHANDLER_LOCK_REQ) & PIPEHANDLER_LOCK_EN) { 9298e98ca1eSSven Peter dev_warn(atcphy->dev, "Pipehandler already locked\n"); 9308e98ca1eSSven Peter return 0; 9318e98ca1eSSven Peter } 9328e98ca1eSSven Peter 9338e98ca1eSSven Peter set32(atcphy->regs.pipehandler + PIPEHANDLER_LOCK_REQ, PIPEHANDLER_LOCK_EN); 9348e98ca1eSSven Peter 9358e98ca1eSSven Peter ret = readl_poll_timeout(atcphy->regs.pipehandler + PIPEHANDLER_LOCK_ACK, reg, 9368e98ca1eSSven Peter reg & PIPEHANDLER_LOCK_EN, 10, PIPEHANDLER_LOCK_ACK_TIMEOUT_US); 9378e98ca1eSSven Peter if (ret) { 9388e98ca1eSSven Peter clear32(atcphy->regs.pipehandler + PIPEHANDLER_LOCK_REQ, 1); 9398e98ca1eSSven Peter dev_warn(atcphy->dev, "Pipehandler lock not acked.\n"); 9408e98ca1eSSven Peter } 9418e98ca1eSSven Peter 9428e98ca1eSSven Peter return ret; 9438e98ca1eSSven Peter } 9448e98ca1eSSven Peter 9458e98ca1eSSven Peter static int atcphy_pipehandler_unlock(struct apple_atcphy *atcphy) 9468e98ca1eSSven Peter { 9478e98ca1eSSven Peter int ret; 9488e98ca1eSSven Peter u32 reg; 9498e98ca1eSSven Peter 9508e98ca1eSSven Peter clear32(atcphy->regs.pipehandler + PIPEHANDLER_LOCK_REQ, PIPEHANDLER_LOCK_EN); 9518e98ca1eSSven Peter ret = readl_poll_timeout(atcphy->regs.pipehandler + PIPEHANDLER_LOCK_ACK, reg, 9528e98ca1eSSven Peter !(reg & PIPEHANDLER_LOCK_EN), 10, PIPEHANDLER_LOCK_ACK_TIMEOUT_US); 9538e98ca1eSSven Peter if (ret) 9548e98ca1eSSven Peter dev_warn(atcphy->dev, "Pipehandler lock release not acked.\n"); 9558e98ca1eSSven Peter 9568e98ca1eSSven Peter return ret; 9578e98ca1eSSven Peter } 9588e98ca1eSSven Peter 9598e98ca1eSSven Peter static int atcphy_pipehandler_check(struct apple_atcphy *atcphy) 9608e98ca1eSSven Peter { 9618e98ca1eSSven Peter int ret; 9628e98ca1eSSven Peter 9638e98ca1eSSven Peter lockdep_assert_held(&atcphy->lock); 9648e98ca1eSSven Peter 9658e98ca1eSSven Peter if (readl(atcphy->regs.pipehandler + PIPEHANDLER_LOCK_ACK) & PIPEHANDLER_LOCK_EN) { 9668e98ca1eSSven Peter dev_warn(atcphy->dev, "Pipehandler already locked\n"); 9678e98ca1eSSven Peter 9688e98ca1eSSven Peter ret = atcphy_pipehandler_unlock(atcphy); 9698e98ca1eSSven Peter if (ret) { 9708e98ca1eSSven Peter dev_err(atcphy->dev, "Failed to unlock pipehandler\n"); 9718e98ca1eSSven Peter return ret; 9728e98ca1eSSven Peter } 9738e98ca1eSSven Peter } 9748e98ca1eSSven Peter 9758e98ca1eSSven Peter return 0; 9768e98ca1eSSven Peter } 9778e98ca1eSSven Peter 9788e98ca1eSSven Peter static int atcphy_configure_pipehandler_usb3(struct apple_atcphy *atcphy, bool host) 9798e98ca1eSSven Peter { 9808e98ca1eSSven Peter int ret; 9818e98ca1eSSven Peter u32 reg; 9828e98ca1eSSven Peter 9838e98ca1eSSven Peter ret = atcphy_pipehandler_check(atcphy); 9848e98ca1eSSven Peter if (ret) 9858e98ca1eSSven Peter return ret; 9868e98ca1eSSven Peter 9878e98ca1eSSven Peter /* 9888e98ca1eSSven Peter * Only host mode requires this unknown BIST sequence to work correctly, possibly due to 9898e98ca1eSSven Peter * some hardware quirk. Guest mode breaks if we try to apply this sequence. 9908e98ca1eSSven Peter */ 9918e98ca1eSSven Peter if (host) { 9928e98ca1eSSven Peter /* Force disable link detection */ 9938e98ca1eSSven Peter clear32(atcphy->regs.pipehandler + PIPEHANDLER_OVERRIDE_VALUES, 9948e98ca1eSSven Peter PIPEHANDLER_OVERRIDE_VAL_RXDETECT0 | PIPEHANDLER_OVERRIDE_VAL_RXDETECT1); 9958e98ca1eSSven Peter set32(atcphy->regs.pipehandler + PIPEHANDLER_OVERRIDE, 9968e98ca1eSSven Peter PIPEHANDLER_OVERRIDE_RXVALID); 9978e98ca1eSSven Peter set32(atcphy->regs.pipehandler + PIPEHANDLER_OVERRIDE, 9988e98ca1eSSven Peter PIPEHANDLER_OVERRIDE_RXDETECT); 9998e98ca1eSSven Peter 10008e98ca1eSSven Peter ret = atcphy_pipehandler_lock(atcphy); 10018e98ca1eSSven Peter if (ret) { 10028e98ca1eSSven Peter dev_err(atcphy->dev, "Failed to lock pipehandler"); 10038e98ca1eSSven Peter return ret; 10048e98ca1eSSven Peter } 10058e98ca1eSSven Peter 10068e98ca1eSSven Peter /* BIST dance */ 10078e98ca1eSSven Peter core_set32(atcphy, ACIOPHY_TOP_BIST_PHY_CFG0, 10088e98ca1eSSven Peter ACIOPHY_TOP_BIST_PHY_CFG0_LN0_RESET_N); 10098e98ca1eSSven Peter core_set32(atcphy, ACIOPHY_TOP_BIST_OV_CFG, ACIOPHY_TOP_BIST_OV_CFG_LN0_RESET_N_OV); 10108e98ca1eSSven Peter ret = readl_poll_timeout(atcphy->regs.core + ACIOPHY_TOP_PHY_STAT, reg, 10118e98ca1eSSven Peter !(reg & ACIOPHY_TOP_PHY_STAT_LN0_UNK23), 10, 10000); 10128e98ca1eSSven Peter if (ret) 10138e98ca1eSSven Peter dev_warn(atcphy->dev, 10148e98ca1eSSven Peter "Timed out waiting for ACIOPHY_TOP_PHY_STAT_LN0_UNK23\n"); 10158e98ca1eSSven Peter 10168e98ca1eSSven Peter core_set32(atcphy, ACIOPHY_TOP_BIST_READ_CTRL, 10178e98ca1eSSven Peter ACIOPHY_TOP_BIST_READ_CTRL_LN0_PHY_STATUS_RE); 10188e98ca1eSSven Peter core_clear32(atcphy, ACIOPHY_TOP_BIST_READ_CTRL, 10198e98ca1eSSven Peter ACIOPHY_TOP_BIST_READ_CTRL_LN0_PHY_STATUS_RE); 10208e98ca1eSSven Peter 10218e98ca1eSSven Peter core_mask32(atcphy, ACIOPHY_TOP_BIST_PHY_CFG1, 10228e98ca1eSSven Peter ACIOPHY_TOP_BIST_PHY_CFG1_LN0_PWR_DOWN, 10238e98ca1eSSven Peter FIELD_PREP(ACIOPHY_TOP_BIST_PHY_CFG1_LN0_PWR_DOWN, 3)); 10248e98ca1eSSven Peter 10258e98ca1eSSven Peter core_set32(atcphy, ACIOPHY_TOP_BIST_OV_CFG, 10268e98ca1eSSven Peter ACIOPHY_TOP_BIST_OV_CFG_LN0_PWR_DOWN_OV); 10278e98ca1eSSven Peter core_set32(atcphy, ACIOPHY_TOP_BIST_CIOPHY_CFG1, 10288e98ca1eSSven Peter ACIOPHY_TOP_BIST_CIOPHY_CFG1_CLK_EN); 10298e98ca1eSSven Peter core_set32(atcphy, ACIOPHY_TOP_BIST_CIOPHY_CFG1, 10308e98ca1eSSven Peter ACIOPHY_TOP_BIST_CIOPHY_CFG1_BIST_EN); 10318e98ca1eSSven Peter writel(0, atcphy->regs.core + ACIOPHY_TOP_BIST_CIOPHY_CFG1); 10328e98ca1eSSven Peter 10338e98ca1eSSven Peter ret = readl_poll_timeout(atcphy->regs.core + ACIOPHY_TOP_PHY_STAT, reg, 10348e98ca1eSSven Peter (reg & ACIOPHY_TOP_PHY_STAT_LN0_UNK0), 10, 10000); 10358e98ca1eSSven Peter if (ret) 10368e98ca1eSSven Peter dev_warn(atcphy->dev, 10378e98ca1eSSven Peter "timed out waiting for ACIOPHY_TOP_PHY_STAT_LN0_UNK0\n"); 10388e98ca1eSSven Peter 10398e98ca1eSSven Peter ret = readl_poll_timeout(atcphy->regs.core + ACIOPHY_TOP_PHY_STAT, reg, 10408e98ca1eSSven Peter !(reg & ACIOPHY_TOP_PHY_STAT_LN0_UNK23), 10, 10000); 10418e98ca1eSSven Peter if (ret) 10428e98ca1eSSven Peter dev_warn(atcphy->dev, 10438e98ca1eSSven Peter "timed out waiting for ACIOPHY_TOP_PHY_STAT_LN0_UNK23\n"); 10448e98ca1eSSven Peter 10458e98ca1eSSven Peter /* Clear reset for non-selected USB3 PHY (?) */ 10468e98ca1eSSven Peter mask32(atcphy->regs.pipehandler + PIPEHANDLER_NONSELECTED_OVERRIDE, 10478e98ca1eSSven Peter PIPEHANDLER_NATIVE_POWER_DOWN, FIELD_PREP(PIPEHANDLER_NATIVE_POWER_DOWN, 3)); 10488e98ca1eSSven Peter clear32(atcphy->regs.pipehandler + PIPEHANDLER_NONSELECTED_OVERRIDE, 10498e98ca1eSSven Peter PIPEHANDLER_NATIVE_RESET); 10508e98ca1eSSven Peter 10518e98ca1eSSven Peter /* More BIST stuff (?) */ 10528e98ca1eSSven Peter writel(0, atcphy->regs.core + ACIOPHY_TOP_BIST_OV_CFG); 10538e98ca1eSSven Peter core_set32(atcphy, ACIOPHY_TOP_BIST_CIOPHY_CFG1, 10548e98ca1eSSven Peter ACIOPHY_TOP_BIST_CIOPHY_CFG1_CLK_EN); 10558e98ca1eSSven Peter core_set32(atcphy, ACIOPHY_TOP_BIST_CIOPHY_CFG1, 10568e98ca1eSSven Peter ACIOPHY_TOP_BIST_CIOPHY_CFG1_BIST_EN); 10578e98ca1eSSven Peter } 10588e98ca1eSSven Peter 10598e98ca1eSSven Peter /* Configure PIPE mux to USB3 PHY */ 10608e98ca1eSSven Peter mask32(atcphy->regs.pipehandler + PIPEHANDLER_MUX_CTRL, PIPEHANDLER_MUX_CTRL_CLK, 10618e98ca1eSSven Peter FIELD_PREP(PIPEHANDLER_MUX_CTRL_CLK, PIPEHANDLER_MUX_CTRL_CLK_OFF)); 10628e98ca1eSSven Peter udelay(10); 10638e98ca1eSSven Peter mask32(atcphy->regs.pipehandler + PIPEHANDLER_MUX_CTRL, PIPEHANDLER_MUX_CTRL_DATA, 10648e98ca1eSSven Peter FIELD_PREP(PIPEHANDLER_MUX_CTRL_DATA, PIPEHANDLER_MUX_CTRL_DATA_USB3)); 10658e98ca1eSSven Peter udelay(10); 10668e98ca1eSSven Peter mask32(atcphy->regs.pipehandler + PIPEHANDLER_MUX_CTRL, PIPEHANDLER_MUX_CTRL_CLK, 10678e98ca1eSSven Peter FIELD_PREP(PIPEHANDLER_MUX_CTRL_CLK, PIPEHANDLER_MUX_CTRL_CLK_USB3)); 10688e98ca1eSSven Peter udelay(10); 10698e98ca1eSSven Peter 10708e98ca1eSSven Peter /* Remove link detection override */ 10718e98ca1eSSven Peter clear32(atcphy->regs.pipehandler + PIPEHANDLER_OVERRIDE, PIPEHANDLER_OVERRIDE_RXVALID); 10728e98ca1eSSven Peter clear32(atcphy->regs.pipehandler + PIPEHANDLER_OVERRIDE, PIPEHANDLER_OVERRIDE_RXDETECT); 10738e98ca1eSSven Peter 10748e98ca1eSSven Peter /* Pipehandler was only locked when the BIST sequence was applied for host mode */ 10758e98ca1eSSven Peter if (host) { 10768e98ca1eSSven Peter ret = atcphy_pipehandler_unlock(atcphy); 10778e98ca1eSSven Peter if (ret) 10788e98ca1eSSven Peter dev_warn(atcphy->dev, "Failed to unlock pipehandler"); 10798e98ca1eSSven Peter } 10808e98ca1eSSven Peter 10818e98ca1eSSven Peter return 0; 10828e98ca1eSSven Peter } 10838e98ca1eSSven Peter 10848e98ca1eSSven Peter static int atcphy_configure_pipehandler_dummy(struct apple_atcphy *atcphy) 10858e98ca1eSSven Peter { 10868e98ca1eSSven Peter int ret; 10878e98ca1eSSven Peter 10888e98ca1eSSven Peter ret = atcphy_pipehandler_check(atcphy); 10898e98ca1eSSven Peter if (ret) 10908e98ca1eSSven Peter return ret; 10918e98ca1eSSven Peter 10928e98ca1eSSven Peter /* Force disable link detection */ 10938e98ca1eSSven Peter clear32(atcphy->regs.pipehandler + PIPEHANDLER_OVERRIDE_VALUES, 10948e98ca1eSSven Peter PIPEHANDLER_OVERRIDE_VAL_RXDETECT0 | PIPEHANDLER_OVERRIDE_VAL_RXDETECT1); 10958e98ca1eSSven Peter set32(atcphy->regs.pipehandler + PIPEHANDLER_OVERRIDE, PIPEHANDLER_OVERRIDE_RXVALID); 10968e98ca1eSSven Peter set32(atcphy->regs.pipehandler + PIPEHANDLER_OVERRIDE, PIPEHANDLER_OVERRIDE_RXDETECT); 10978e98ca1eSSven Peter 10988e98ca1eSSven Peter ret = atcphy_pipehandler_lock(atcphy); 10998e98ca1eSSven Peter if (ret) 11008e98ca1eSSven Peter dev_warn(atcphy->dev, "Failed to lock pipehandler"); 11018e98ca1eSSven Peter 11028e98ca1eSSven Peter /* Switch to dummy PHY */ 11038e98ca1eSSven Peter mask32(atcphy->regs.pipehandler + PIPEHANDLER_MUX_CTRL, PIPEHANDLER_MUX_CTRL_CLK, 11048e98ca1eSSven Peter FIELD_PREP(PIPEHANDLER_MUX_CTRL_CLK, PIPEHANDLER_MUX_CTRL_CLK_OFF)); 11058e98ca1eSSven Peter udelay(10); 11068e98ca1eSSven Peter mask32(atcphy->regs.pipehandler + PIPEHANDLER_MUX_CTRL, PIPEHANDLER_MUX_CTRL_DATA, 11078e98ca1eSSven Peter FIELD_PREP(PIPEHANDLER_MUX_CTRL_DATA, PIPEHANDLER_MUX_CTRL_DATA_DUMMY)); 11088e98ca1eSSven Peter udelay(10); 11098e98ca1eSSven Peter mask32(atcphy->regs.pipehandler + PIPEHANDLER_MUX_CTRL, PIPEHANDLER_MUX_CTRL_CLK, 11108e98ca1eSSven Peter FIELD_PREP(PIPEHANDLER_MUX_CTRL_CLK, PIPEHANDLER_MUX_CTRL_CLK_DUMMY)); 11118e98ca1eSSven Peter udelay(10); 11128e98ca1eSSven Peter 11138e98ca1eSSven Peter ret = atcphy_pipehandler_unlock(atcphy); 11148e98ca1eSSven Peter if (ret) 11158e98ca1eSSven Peter dev_warn(atcphy->dev, "Failed to unlock pipehandler"); 11168e98ca1eSSven Peter 11178e98ca1eSSven Peter mask32(atcphy->regs.pipehandler + PIPEHANDLER_NONSELECTED_OVERRIDE, 11188e98ca1eSSven Peter PIPEHANDLER_NATIVE_POWER_DOWN, FIELD_PREP(PIPEHANDLER_NATIVE_POWER_DOWN, 2)); 11198e98ca1eSSven Peter set32(atcphy->regs.pipehandler + PIPEHANDLER_NONSELECTED_OVERRIDE, 11208e98ca1eSSven Peter PIPEHANDLER_NATIVE_RESET); 11218e98ca1eSSven Peter 11228e98ca1eSSven Peter return 0; 11238e98ca1eSSven Peter } 11248e98ca1eSSven Peter 11258e98ca1eSSven Peter static int atcphy_configure_pipehandler(struct apple_atcphy *atcphy, bool host) 11268e98ca1eSSven Peter { 11278e98ca1eSSven Peter int ret; 11288e98ca1eSSven Peter 11298e98ca1eSSven Peter lockdep_assert_held(&atcphy->lock); 11308e98ca1eSSven Peter 11318e98ca1eSSven Peter switch (atcphy_modes[atcphy->mode].pipehandler_state) { 11328e98ca1eSSven Peter case ATCPHY_PIPEHANDLER_STATE_USB3: 11338e98ca1eSSven Peter ret = atcphy_configure_pipehandler_usb3(atcphy, host); 11348e98ca1eSSven Peter atcphy->pipehandler_up = true; 11358e98ca1eSSven Peter break; 11368e98ca1eSSven Peter case ATCPHY_PIPEHANDLER_STATE_USB4: 11378e98ca1eSSven Peter dev_warn(atcphy->dev, 11388e98ca1eSSven Peter "ATCPHY_PIPEHANDLER_STATE_USB4 not implemented; falling back to USB2\n"); 11398e98ca1eSSven Peter ret = atcphy_configure_pipehandler_dummy(atcphy); 11408e98ca1eSSven Peter atcphy->pipehandler_up = false; 11418e98ca1eSSven Peter break; 11428e98ca1eSSven Peter default: 11438e98ca1eSSven Peter ret = -EINVAL; 11448e98ca1eSSven Peter } 11458e98ca1eSSven Peter 11468e98ca1eSSven Peter return ret; 11478e98ca1eSSven Peter } 11488e98ca1eSSven Peter 11498e98ca1eSSven Peter static void atcphy_setup_pipehandler(struct apple_atcphy *atcphy) 11508e98ca1eSSven Peter { 11518e98ca1eSSven Peter lockdep_assert_held(&atcphy->lock); 11528e98ca1eSSven Peter 11538e98ca1eSSven Peter mask32(atcphy->regs.pipehandler + PIPEHANDLER_MUX_CTRL, PIPEHANDLER_MUX_CTRL_CLK, 11548e98ca1eSSven Peter FIELD_PREP(PIPEHANDLER_MUX_CTRL_CLK, PIPEHANDLER_MUX_CTRL_CLK_OFF)); 11558e98ca1eSSven Peter udelay(10); 11568e98ca1eSSven Peter mask32(atcphy->regs.pipehandler + PIPEHANDLER_MUX_CTRL, PIPEHANDLER_MUX_CTRL_DATA, 11578e98ca1eSSven Peter FIELD_PREP(PIPEHANDLER_MUX_CTRL_DATA, PIPEHANDLER_MUX_CTRL_DATA_DUMMY)); 11588e98ca1eSSven Peter udelay(10); 11598e98ca1eSSven Peter mask32(atcphy->regs.pipehandler + PIPEHANDLER_MUX_CTRL, PIPEHANDLER_MUX_CTRL_CLK, 11608e98ca1eSSven Peter FIELD_PREP(PIPEHANDLER_MUX_CTRL_CLK, PIPEHANDLER_MUX_CTRL_CLK_DUMMY)); 11618e98ca1eSSven Peter udelay(10); 11628e98ca1eSSven Peter } 11638e98ca1eSSven Peter 11648e98ca1eSSven Peter static void atcphy_configure_lanes(struct apple_atcphy *atcphy, enum atcphy_mode mode) 11658e98ca1eSSven Peter { 11668e98ca1eSSven Peter const struct atcphy_mode_configuration *mode_cfg = atcphy_get_mode_config(atcphy, mode); 11678e98ca1eSSven Peter 11688e98ca1eSSven Peter core_mask32(atcphy, ACIOPHY_LANE_MODE, ACIOPHY_LANE_MODE_RX0, 11698e98ca1eSSven Peter FIELD_PREP(ACIOPHY_LANE_MODE_RX0, mode_cfg->lane_mode[0])); 11708e98ca1eSSven Peter core_mask32(atcphy, ACIOPHY_LANE_MODE, ACIOPHY_LANE_MODE_TX0, 11718e98ca1eSSven Peter FIELD_PREP(ACIOPHY_LANE_MODE_TX0, mode_cfg->lane_mode[0])); 11728e98ca1eSSven Peter core_mask32(atcphy, ACIOPHY_LANE_MODE, ACIOPHY_LANE_MODE_RX1, 11738e98ca1eSSven Peter FIELD_PREP(ACIOPHY_LANE_MODE_RX1, mode_cfg->lane_mode[1])); 11748e98ca1eSSven Peter core_mask32(atcphy, ACIOPHY_LANE_MODE, ACIOPHY_LANE_MODE_TX1, 11758e98ca1eSSven Peter FIELD_PREP(ACIOPHY_LANE_MODE_TX1, mode_cfg->lane_mode[1])); 11768e98ca1eSSven Peter core_mask32(atcphy, ACIOPHY_CROSSBAR, ACIOPHY_CROSSBAR_PROTOCOL, 11778e98ca1eSSven Peter FIELD_PREP(ACIOPHY_CROSSBAR_PROTOCOL, mode_cfg->crossbar)); 11788e98ca1eSSven Peter 11798e98ca1eSSven Peter if (mode_cfg->set_swap) 11808e98ca1eSSven Peter core_set32(atcphy, ATCPHY_MISC, ATCPHY_MISC_LANE_SWAP); 11818e98ca1eSSven Peter else 11828e98ca1eSSven Peter core_clear32(atcphy, ATCPHY_MISC, ATCPHY_MISC_LANE_SWAP); 11838e98ca1eSSven Peter 11848e98ca1eSSven Peter core_mask32(atcphy, ACIOPHY_CROSSBAR, ACIOPHY_CROSSBAR_DP_SINGLE_PMA, 11858e98ca1eSSven Peter FIELD_PREP(ACIOPHY_CROSSBAR_DP_SINGLE_PMA, mode_cfg->crossbar_dp_single_pma)); 11868e98ca1eSSven Peter if (mode_cfg->crossbar_dp_both_pma) 11878e98ca1eSSven Peter core_set32(atcphy, ACIOPHY_CROSSBAR, ACIOPHY_CROSSBAR_DP_BOTH_PMA); 11888e98ca1eSSven Peter else 11898e98ca1eSSven Peter core_clear32(atcphy, ACIOPHY_CROSSBAR, ACIOPHY_CROSSBAR_DP_BOTH_PMA); 11908e98ca1eSSven Peter 11918e98ca1eSSven Peter if (mode_cfg->dp_lane[0]) { 11928e98ca1eSSven Peter core_set32(atcphy, LN0_AUSPMA_RX_TOP + LN_AUSPMA_RX_TOP_PMAFSM, 11938e98ca1eSSven Peter LN_AUSPMA_RX_TOP_PMAFSM_PCS_OV); 11948e98ca1eSSven Peter udelay(10); 11958e98ca1eSSven Peter core_clear32(atcphy, LN0_AUSPMA_RX_TOP + LN_AUSPMA_RX_TOP_PMAFSM, 11968e98ca1eSSven Peter LN_AUSPMA_RX_TOP_PMAFSM_PCS_REQ); 11978e98ca1eSSven Peter } else { 11988e98ca1eSSven Peter core_clear32(atcphy, LN0_AUSPMA_RX_TOP + LN_AUSPMA_RX_TOP_PMAFSM, 11998e98ca1eSSven Peter LN_AUSPMA_RX_TOP_PMAFSM_PCS_OV); 12008e98ca1eSSven Peter udelay(10); 12018e98ca1eSSven Peter } 12028e98ca1eSSven Peter 12038e98ca1eSSven Peter if (mode_cfg->dp_lane[1]) { 12048e98ca1eSSven Peter core_set32(atcphy, LN1_AUSPMA_RX_TOP + LN_AUSPMA_RX_TOP_PMAFSM, 12058e98ca1eSSven Peter LN_AUSPMA_RX_TOP_PMAFSM_PCS_OV); 12068e98ca1eSSven Peter udelay(10); 12078e98ca1eSSven Peter core_clear32(atcphy, LN1_AUSPMA_RX_TOP + LN_AUSPMA_RX_TOP_PMAFSM, 12088e98ca1eSSven Peter LN_AUSPMA_RX_TOP_PMAFSM_PCS_REQ); 12098e98ca1eSSven Peter } else { 12108e98ca1eSSven Peter core_clear32(atcphy, LN1_AUSPMA_RX_TOP + LN_AUSPMA_RX_TOP_PMAFSM, 12118e98ca1eSSven Peter LN_AUSPMA_RX_TOP_PMAFSM_PCS_OV); 12128e98ca1eSSven Peter udelay(10); 12138e98ca1eSSven Peter } 12148e98ca1eSSven Peter } 12158e98ca1eSSven Peter 12168e98ca1eSSven Peter static void atcphy_enable_dp_aux(struct apple_atcphy *atcphy) 12178e98ca1eSSven Peter { 12188e98ca1eSSven Peter core_set32(atcphy, ACIOPHY_LANE_DP_CFG_BLK_TX_DP_CTRL0, DPTXPHY_PMA_LANE_RESET_N); 12198e98ca1eSSven Peter core_set32(atcphy, ACIOPHY_LANE_DP_CFG_BLK_TX_DP_CTRL0, DPTXPHY_PMA_LANE_RESET_N_OV); 12208e98ca1eSSven Peter 12218e98ca1eSSven Peter core_mask32(atcphy, ACIOPHY_LANE_DP_CFG_BLK_TX_DP_CTRL0, DPRX_PCLK_SELECT, 12228e98ca1eSSven Peter FIELD_PREP(DPRX_PCLK_SELECT, 1)); 12238e98ca1eSSven Peter core_set32(atcphy, ACIOPHY_LANE_DP_CFG_BLK_TX_DP_CTRL0, DPRX_PCLK_ENABLE); 12248e98ca1eSSven Peter 12258e98ca1eSSven Peter core_mask32(atcphy, ACIOPHY_LANE_DP_CFG_BLK_TX_DP_CTRL0, DPTX_PCLK1_SELECT, 12268e98ca1eSSven Peter FIELD_PREP(DPTX_PCLK1_SELECT, 1)); 12278e98ca1eSSven Peter core_set32(atcphy, ACIOPHY_LANE_DP_CFG_BLK_TX_DP_CTRL0, DPTX_PCLK1_ENABLE); 12288e98ca1eSSven Peter 12298e98ca1eSSven Peter core_mask32(atcphy, ACIOPHY_LANE_DP_CFG_BLK_TX_DP_CTRL0, DPTX_PCLK2_SELECT, 12308e98ca1eSSven Peter FIELD_PREP(DPTX_PCLK2_SELECT, 1)); 12318e98ca1eSSven Peter core_set32(atcphy, ACIOPHY_LANE_DP_CFG_BLK_TX_DP_CTRL0, DPTX_PCLK2_ENABLE); 12328e98ca1eSSven Peter 12338e98ca1eSSven Peter core_set32(atcphy, ACIOPHY_PLL_COMMON_CTRL, 12348e98ca1eSSven Peter ACIOPHY_PLL_WAIT_FOR_CMN_READY_BEFORE_RESET_EXIT); 12358e98ca1eSSven Peter 12368e98ca1eSSven Peter set32(atcphy->regs.lpdptx + LPDPTX_AUX_CONTROL, LPDPTX_AUX_CLAMP_EN); 12378e98ca1eSSven Peter set32(atcphy->regs.lpdptx + LPDPTX_AUX_CONTROL, LPDPTX_SLEEP_B_SML_IN); 12388e98ca1eSSven Peter udelay(10); 12398e98ca1eSSven Peter set32(atcphy->regs.lpdptx + LPDPTX_AUX_CONTROL, LPDPTX_SLEEP_B_BIG_IN); 12408e98ca1eSSven Peter udelay(10); 12418e98ca1eSSven Peter clear32(atcphy->regs.lpdptx + LPDPTX_AUX_CONTROL, LPDPTX_AUX_CLAMP_EN); 12428e98ca1eSSven Peter clear32(atcphy->regs.lpdptx + LPDPTX_AUX_CONTROL, LPDPTX_AUX_PWN_DOWN); 12438e98ca1eSSven Peter clear32(atcphy->regs.lpdptx + LPDPTX_AUX_CONTROL, LPDPTX_TXTERM_CODEMSB); 12448e98ca1eSSven Peter mask32(atcphy->regs.lpdptx + LPDPTX_AUX_CONTROL, LPDPTX_TXTERM_CODE, 12458e98ca1eSSven Peter FIELD_PREP(LPDPTX_TXTERM_CODE, 0x16)); 12468e98ca1eSSven Peter 12478e98ca1eSSven Peter set32(atcphy->regs.lpdptx + LPDPTX_AUX_CFG_BLK_AUX_LDO_CTRL, 0x1c00); 12488e98ca1eSSven Peter mask32(atcphy->regs.lpdptx + LPDPTX_AUX_SHM_CFG_BLK_AUX_CTRL_REG1, LPDPTX_CFG_PMA_PHYS_ADJ, 12498e98ca1eSSven Peter FIELD_PREP(LPDPTX_CFG_PMA_PHYS_ADJ, 5)); 12508e98ca1eSSven Peter set32(atcphy->regs.lpdptx + LPDPTX_AUX_SHM_CFG_BLK_AUX_CTRL_REG1, 12518e98ca1eSSven Peter LPDPTX_CFG_PMA_PHYS_ADJ_OV); 12528e98ca1eSSven Peter 12538e98ca1eSSven Peter clear32(atcphy->regs.lpdptx + LPDPTX_AUX_CFG_BLK_AUX_MARGIN, 12548e98ca1eSSven Peter LPDPTX_MARGIN_RCAL_RXOFFSET_EN); 12558e98ca1eSSven Peter 12568e98ca1eSSven Peter clear32(atcphy->regs.lpdptx + LPDPTX_AUX_CFG_BLK_AUX_CTRL, LPDPTX_BLK_AUX_CTRL_PWRDN); 12578e98ca1eSSven Peter set32(atcphy->regs.lpdptx + LPDPTX_AUX_SHM_CFG_BLK_AUX_CTRL_REG0, 12588e98ca1eSSven Peter LPDPTX_CFG_PMA_AUX_SEL_LF_DATA); 12598e98ca1eSSven Peter mask32(atcphy->regs.lpdptx + LPDPTX_AUX_CFG_BLK_AUX_CTRL, LPDPTX_BLK_AUX_RXOFFSET, 12608e98ca1eSSven Peter FIELD_PREP(LPDPTX_BLK_AUX_RXOFFSET, 3)); 12618e98ca1eSSven Peter 12628e98ca1eSSven Peter mask32(atcphy->regs.lpdptx + LPDPTX_AUX_CFG_BLK_AUX_MARGIN, LPDPTX_AUX_MARGIN_RCAL_TXSWING, 12638e98ca1eSSven Peter FIELD_PREP(LPDPTX_AUX_MARGIN_RCAL_TXSWING, 12)); 12648e98ca1eSSven Peter 12658e98ca1eSSven Peter atcphy->dp_link_rate = -1; 12668e98ca1eSSven Peter } 12678e98ca1eSSven Peter 12688e98ca1eSSven Peter static void atcphy_disable_dp_aux(struct apple_atcphy *atcphy) 12698e98ca1eSSven Peter { 12708e98ca1eSSven Peter set32(atcphy->regs.lpdptx + LPDPTX_AUX_CONTROL, LPDPTX_AUX_PWN_DOWN); 12718e98ca1eSSven Peter set32(atcphy->regs.lpdptx + LPDPTX_AUX_CFG_BLK_AUX_CTRL, LPDPTX_BLK_AUX_CTRL_PWRDN); 12728e98ca1eSSven Peter set32(atcphy->regs.lpdptx + LPDPTX_AUX_CONTROL, LPDPTX_AUX_CLAMP_EN); 12738e98ca1eSSven Peter clear32(atcphy->regs.lpdptx + LPDPTX_AUX_CONTROL, LPDPTX_SLEEP_B_SML_IN); 12748e98ca1eSSven Peter udelay(10); 12758e98ca1eSSven Peter clear32(atcphy->regs.lpdptx + LPDPTX_AUX_CONTROL, LPDPTX_SLEEP_B_BIG_IN); 12768e98ca1eSSven Peter udelay(10); 12778e98ca1eSSven Peter 12788e98ca1eSSven Peter core_clear32(atcphy, ACIOPHY_LANE_DP_CFG_BLK_TX_DP_CTRL0, DPTXPHY_PMA_LANE_RESET_N); 12798e98ca1eSSven Peter core_clear32(atcphy, ACIOPHY_LANE_DP_CFG_BLK_TX_DP_CTRL0, DPRX_PCLK_ENABLE); 12808e98ca1eSSven Peter core_clear32(atcphy, ACIOPHY_LANE_DP_CFG_BLK_TX_DP_CTRL0, DPTX_PCLK1_ENABLE); 12818e98ca1eSSven Peter core_clear32(atcphy, ACIOPHY_LANE_DP_CFG_BLK_TX_DP_CTRL0, DPTX_PCLK2_ENABLE); 12828e98ca1eSSven Peter } 12838e98ca1eSSven Peter 12848e98ca1eSSven Peter static int atcphy_dp_configure_lane(struct apple_atcphy *atcphy, enum atcphy_lane lane, 12858e98ca1eSSven Peter const struct atcphy_dp_link_rate_configuration *cfg) 12868e98ca1eSSven Peter { 12878e98ca1eSSven Peter void __iomem *tx_shm, *rx_shm, *rx_top; 12888e98ca1eSSven Peter unsigned int tx_cal_code; 12898e98ca1eSSven Peter 12908e98ca1eSSven Peter lockdep_assert_held(&atcphy->lock); 12918e98ca1eSSven Peter 12928e98ca1eSSven Peter switch (lane) { 12938e98ca1eSSven Peter case APPLE_ATCPHY_LANE_0: 12948e98ca1eSSven Peter tx_shm = atcphy->regs.core + LN0_AUSPMA_TX_SHM; 12958e98ca1eSSven Peter rx_shm = atcphy->regs.core + LN0_AUSPMA_RX_SHM; 12968e98ca1eSSven Peter rx_top = atcphy->regs.core + LN0_AUSPMA_RX_TOP; 12978e98ca1eSSven Peter break; 12988e98ca1eSSven Peter case APPLE_ATCPHY_LANE_1: 12998e98ca1eSSven Peter tx_shm = atcphy->regs.core + LN1_AUSPMA_TX_SHM; 13008e98ca1eSSven Peter rx_shm = atcphy->regs.core + LN1_AUSPMA_RX_SHM; 13018e98ca1eSSven Peter rx_top = atcphy->regs.core + LN1_AUSPMA_RX_TOP; 13028e98ca1eSSven Peter break; 13038e98ca1eSSven Peter default: 13048e98ca1eSSven Peter return -EINVAL; 13058e98ca1eSSven Peter } 13068e98ca1eSSven Peter 13078e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_LDOCLK, LN_LDOCLK_EN_SML); 13088e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_LDOCLK, LN_LDOCLK_EN_SML_OV); 13098e98ca1eSSven Peter udelay(10); 13108e98ca1eSSven Peter 13118e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_LDOCLK, LN_LDOCLK_EN_BIG); 13128e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_LDOCLK, LN_LDOCLK_EN_BIG_OV); 13138e98ca1eSSven Peter udelay(10); 13148e98ca1eSSven Peter 13158e98ca1eSSven Peter if (cfg->txa_ldoclk_bypass) { 13168e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_LDOCLK, LN_LDOCLK_BYPASS_SML); 13178e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_LDOCLK, LN_LDOCLK_BYPASS_SML_OV); 13188e98ca1eSSven Peter udelay(10); 13198e98ca1eSSven Peter 13208e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_LDOCLK, LN_LDOCLK_BYPASS_BIG); 13218e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_LDOCLK, LN_LDOCLK_BYPASS_BIG_OV); 13228e98ca1eSSven Peter udelay(10); 13238e98ca1eSSven Peter } else { 13248e98ca1eSSven Peter clear32(tx_shm + LN_AUSPMA_TX_SHM_TXA_LDOCLK, LN_LDOCLK_BYPASS_SML); 13258e98ca1eSSven Peter clear32(tx_shm + LN_AUSPMA_TX_SHM_TXA_LDOCLK, LN_LDOCLK_BYPASS_SML_OV); 13268e98ca1eSSven Peter udelay(10); 13278e98ca1eSSven Peter 13288e98ca1eSSven Peter clear32(tx_shm + LN_AUSPMA_TX_SHM_TXA_LDOCLK, LN_LDOCLK_BYPASS_BIG); 13298e98ca1eSSven Peter clear32(tx_shm + LN_AUSPMA_TX_SHM_TXA_LDOCLK, LN_LDOCLK_BYPASS_BIG_OV); 13308e98ca1eSSven Peter udelay(10); 13318e98ca1eSSven Peter } 13328e98ca1eSSven Peter 13338e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_CFG_MAIN_REG0, LN_BYTECLK_RESET_SYNC_SEL_OV); 13348e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_CFG_MAIN_REG0, LN_BYTECLK_RESET_SYNC_EN); 13358e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_CFG_MAIN_REG0, LN_BYTECLK_RESET_SYNC_EN_OV); 13368e98ca1eSSven Peter clear32(tx_shm + LN_AUSPMA_TX_SHM_TXA_CFG_MAIN_REG0, LN_BYTECLK_RESET_SYNC_CLR); 13378e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_CFG_MAIN_REG0, LN_BYTECLK_RESET_SYNC_CLR_OV); 13388e98ca1eSSven Peter 13398e98ca1eSSven Peter if (cfg->txa_div2_en) 13408e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_CFG_MAIN_REG1, LN_TXA_DIV2_EN); 13418e98ca1eSSven Peter else 13428e98ca1eSSven Peter clear32(tx_shm + LN_AUSPMA_TX_SHM_TXA_CFG_MAIN_REG1, LN_TXA_DIV2_EN); 13438e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_CFG_MAIN_REG1, LN_TXA_DIV2_EN_OV); 13448e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_CFG_MAIN_REG1, LN_TXA_CLK_EN); 13458e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_CFG_MAIN_REG1, LN_TXA_CLK_EN_OV); 13468e98ca1eSSven Peter clear32(tx_shm + LN_AUSPMA_TX_SHM_TXA_CFG_MAIN_REG1, LN_TXA_DIV2_RESET); 13478e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_CFG_MAIN_REG1, LN_TXA_DIV2_RESET_OV); 13488e98ca1eSSven Peter 13498e98ca1eSSven Peter mask32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG0, LN_TXA_CAL_CTRL_BASE, 13508e98ca1eSSven Peter FIELD_PREP(LN_TXA_CAL_CTRL_BASE, 0xf)); 13518e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG0, LN_TXA_CAL_CTRL_BASE_OV); 13528e98ca1eSSven Peter 13538e98ca1eSSven Peter tx_cal_code = FIELD_GET(AUS_UNK_A20_TX_CAL_CODE, readl(atcphy->regs.core + AUS_UNK_A20)); 13548e98ca1eSSven Peter mask32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG0, LN_TXA_CAL_CTRL, 13558e98ca1eSSven Peter FIELD_PREP(LN_TXA_CAL_CTRL, (1 << tx_cal_code) - 1)); 13568e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG0, LN_TXA_CAL_CTRL_OV); 13578e98ca1eSSven Peter 13588e98ca1eSSven Peter clear32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG2, LN_TXA_MARGIN); 13598e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG2, LN_TXA_MARGIN_OV); 13608e98ca1eSSven Peter clear32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG2, LN_TXA_MARGIN_2R); 13618e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG2, LN_TXA_MARGIN_2R_OV); 13628e98ca1eSSven Peter 13638e98ca1eSSven Peter clear32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG3, LN_TXA_MARGIN_POST); 13648e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG3, LN_TXA_MARGIN_POST_OV); 13658e98ca1eSSven Peter clear32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG3, LN_TXA_MARGIN_POST_2R); 13668e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG3, LN_TXA_MARGIN_POST_2R_OV); 13678e98ca1eSSven Peter clear32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG3, LN_TXA_MARGIN_POST_4R); 13688e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG3, LN_TXA_MARGIN_POST_4R_OV); 13698e98ca1eSSven Peter clear32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG3, LN_TXA_MARGIN_PRE); 13708e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG3, LN_TXA_MARGIN_PRE_OV); 13718e98ca1eSSven Peter clear32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG3, LN_TXA_MARGIN_PRE_2R); 13728e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG3, LN_TXA_MARGIN_PRE_2R_OV); 13738e98ca1eSSven Peter clear32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG3, LN_TXA_MARGIN_PRE_4R); 13748e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG3, LN_TXA_MARGIN_PRE_4R_OV); 13758e98ca1eSSven Peter 13768e98ca1eSSven Peter clear32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG0, LN_TXA_HIZ); 13778e98ca1eSSven Peter set32(tx_shm + LN_AUSPMA_TX_SHM_TXA_IMP_REG0, LN_TXA_HIZ_OV); 13788e98ca1eSSven Peter 13798e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_AFE_CTRL1, LN_RX_DIV20_RESET_N); 13808e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_AFE_CTRL1, LN_RX_DIV20_RESET_N_OV); 13818e98ca1eSSven Peter udelay(10); 13828e98ca1eSSven Peter 13838e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_AFE_CTRL1, LN_RX_DIV20_RESET_N); 13848e98ca1eSSven Peter 13858e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL12, LN_TX_BYTECLK_RESET_SYNC_EN); 13868e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL12, LN_TX_BYTECLK_RESET_SYNC_EN_OV); 13878e98ca1eSSven Peter 13888e98ca1eSSven Peter mask32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_SAVOS_CTRL16, LN_TX_CAL_CODE, 13898e98ca1eSSven Peter FIELD_PREP(LN_TX_CAL_CODE, tx_cal_code)); 13908e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_SAVOS_CTRL16, LN_TX_CAL_CODE_OV); 13918e98ca1eSSven Peter 13928e98ca1eSSven Peter mask32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TERM_CTRL19, LN_TX_CLK_DLY_CTRL_TAPGEN, 13938e98ca1eSSven Peter FIELD_PREP(LN_TX_CLK_DLY_CTRL_TAPGEN, 3)); 13948e98ca1eSSven Peter 13958e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL10, LN_DTVREG_ADJUST); 13968e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL13, LN_DTVREG_ADJUST_OV); 13978e98ca1eSSven Peter 13988e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_SAVOS_CTRL16, LN_RXTERM_EN); 13998e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_SAVOS_CTRL16, LN_RXTERM_EN_OV); 14008e98ca1eSSven Peter 14018e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TERM_CTRL19, LN_TX_TEST_EN); 14028e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TERM_CTRL19, LN_TX_TEST_EN_OV); 14038e98ca1eSSven Peter 14048e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_VREF_CTRL22, LN_VREF_TEST_RXLPBKDT_EN); 14058e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_VREF_CTRL22, LN_VREF_TEST_RXLPBKDT_EN_OV); 14068e98ca1eSSven Peter mask32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_VREF_CTRL22, LN_VREF_LPBKIN_DATA, 14078e98ca1eSSven Peter FIELD_PREP(LN_VREF_LPBKIN_DATA, 3)); 14088e98ca1eSSven Peter mask32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_VREF_CTRL22, LN_VREF_BIAS_SEL, 14098e98ca1eSSven Peter FIELD_PREP(LN_VREF_BIAS_SEL, 2)); 14108e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_VREF_CTRL22, LN_VREF_BIAS_SEL_OV); 14118e98ca1eSSven Peter mask32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_VREF_CTRL22, LN_VREF_ADJUST_GRAY, 14128e98ca1eSSven Peter FIELD_PREP(LN_VREF_ADJUST_GRAY, 0x18)); 14138e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_VREF_CTRL22, LN_VREF_ADJUST_GRAY_OV); 14148e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_VREF_CTRL22, LN_VREF_EN); 14158e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_VREF_CTRL22, LN_VREF_EN_OV); 14168e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_VREF_CTRL22, LN_VREF_BOOST_EN); 14178e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_VREF_CTRL22, LN_VREF_BOOST_EN_OV); 14188e98ca1eSSven Peter udelay(10); 14198e98ca1eSSven Peter 14208e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_VREF_CTRL22, LN_VREF_BOOST_EN); 14218e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_VREF_CTRL22, LN_VREF_BOOST_EN_OV); 14228e98ca1eSSven Peter udelay(10); 14238e98ca1eSSven Peter 14248e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL13, LN_TX_PRE_EN); 14258e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL13, LN_TX_PRE_EN_OV); 14268e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL13, LN_TX_PST1_EN); 14278e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL13, LN_TX_PST1_EN_OV); 14288e98ca1eSSven Peter 14298e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL12, LN_TX_PBIAS_EN); 14308e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL12, LN_TX_PBIAS_EN_OV); 14318e98ca1eSSven Peter 14328e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_SAVOS_CTRL16, LN_RXTERM_PULLUP_LEAK_EN); 14338e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_SAVOS_CTRL16, LN_RXTERM_PULLUP_LEAK_EN_OV); 14348e98ca1eSSven Peter 14358e98ca1eSSven Peter set32(rx_top + LN_AUSPMA_RX_TOP_TJ_CFG_RX_TXMODE, LN_RX_TXMODE); 14368e98ca1eSSven Peter 14378e98ca1eSSven Peter if (cfg->txa_div2_en) 14388e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TERM_CTRL19, LN_TX_CLK_DIV2_EN); 14398e98ca1eSSven Peter else 14408e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TERM_CTRL19, LN_TX_CLK_DIV2_EN); 14418e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TERM_CTRL19, LN_TX_CLK_DIV2_EN_OV); 14428e98ca1eSSven Peter 14438e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TERM_CTRL19, LN_TX_CLK_DIV2_RST); 14448e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TERM_CTRL19, LN_TX_CLK_DIV2_RST_OV); 14458e98ca1eSSven Peter 14468e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL12, LN_TX_HRCLK_SEL); 14478e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL12, LN_TX_HRCLK_SEL_OV); 14488e98ca1eSSven Peter 14498e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL17, LN_TX_MARGIN); 14508e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL17, LN_TX_MARGIN_OV); 14518e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL17, LN_TX_MARGIN_LSB); 14528e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL17, LN_TX_MARGIN_LSB_OV); 14538e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL17, LN_TX_MARGIN_P1); 14548e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL17, LN_TX_MARGIN_P1_OV); 14558e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL17, LN_TX_MARGIN_P1_LSB); 14568e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL17, LN_TX_MARGIN_P1_LSB_OV); 14578e98ca1eSSven Peter 14588e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL18, LN_TX_P1_CODE); 14598e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL18, LN_TX_P1_CODE_OV); 14608e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL18, LN_TX_P1_LSB_CODE); 14618e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL18, LN_TX_P1_LSB_CODE_OV); 14628e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL18, LN_TX_MARGIN_PRE); 14638e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL18, LN_TX_MARGIN_PRE_OV); 14648e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL18, LN_TX_MARGIN_PRE_LSB); 14658e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL18, LN_TX_MARGIN_PRE_LSB_OV); 14668e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL18, LN_TX_PRE_LSB_CODE); 14678e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL18, LN_TX_PRE_LSB_CODE_OV); 14688e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL18, LN_TX_PRE_CODE); 14698e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TX_CTRL18, LN_TX_PRE_CODE_OV); 14708e98ca1eSSven Peter 14718e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL11, LN_DTVREG_SML_EN); 14728e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL11, LN_DTVREG_SML_EN_OV); 14738e98ca1eSSven Peter udelay(10); 14748e98ca1eSSven Peter 14758e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL11, LN_DTVREG_BIG_EN); 14768e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL11, LN_DTVREG_BIG_EN_OV); 14778e98ca1eSSven Peter udelay(10); 14788e98ca1eSSven Peter 14798e98ca1eSSven Peter mask32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL10, LN_DTVREG_ADJUST, 14808e98ca1eSSven Peter FIELD_PREP(LN_DTVREG_ADJUST, 0xa)); 14818e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL13, LN_DTVREG_ADJUST_OV); 14828e98ca1eSSven Peter udelay(10); 14838e98ca1eSSven Peter 14848e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TERM_CTRL19, LN_TX_EN); 14858e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_TERM_CTRL19, LN_TX_EN_OV); 14868e98ca1eSSven Peter udelay(10); 14878e98ca1eSSven Peter 14888e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_CTLE_CTRL0, LN_TX_CLK_EN); 14898e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_CTLE_CTRL0, LN_TX_CLK_EN_OV); 14908e98ca1eSSven Peter 14918e98ca1eSSven Peter clear32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL12, LN_TX_BYTECLK_RESET_SYNC_CLR); 14928e98ca1eSSven Peter set32(rx_shm + LN_AUSPMA_RX_SHM_TJ_RXA_DFE_CTRL12, LN_TX_BYTECLK_RESET_SYNC_CLR_OV); 14938e98ca1eSSven Peter 14948e98ca1eSSven Peter return 0; 14958e98ca1eSSven Peter } 14968e98ca1eSSven Peter 14978e98ca1eSSven Peter static int atcphy_auspll_apb_command(struct apple_atcphy *atcphy, u32 command) 14988e98ca1eSSven Peter { 14998e98ca1eSSven Peter int ret; 15008e98ca1eSSven Peter u32 reg; 15018e98ca1eSSven Peter 15028e98ca1eSSven Peter reg = readl(atcphy->regs.core + AUSPLL_APB_CMD_OVERRIDE); 15038e98ca1eSSven Peter reg &= ~AUSPLL_APB_CMD_OVERRIDE_CMD; 15048e98ca1eSSven Peter reg |= FIELD_PREP(AUSPLL_APB_CMD_OVERRIDE_CMD, command); 15058e98ca1eSSven Peter reg |= AUSPLL_APB_CMD_OVERRIDE_REQ; 15068e98ca1eSSven Peter reg |= AUSPLL_APB_CMD_OVERRIDE_UNK28; 15078e98ca1eSSven Peter writel(reg, atcphy->regs.core + AUSPLL_APB_CMD_OVERRIDE); 15088e98ca1eSSven Peter 15098e98ca1eSSven Peter ret = readl_poll_timeout(atcphy->regs.core + AUSPLL_APB_CMD_OVERRIDE, reg, 15108e98ca1eSSven Peter (reg & AUSPLL_APB_CMD_OVERRIDE_ACK), 10, 10000); 15118e98ca1eSSven Peter if (ret) 15128e98ca1eSSven Peter dev_warn(atcphy->dev, "AUSPLL APB command was not acked\n"); 15138e98ca1eSSven Peter 15148e98ca1eSSven Peter core_clear32(atcphy, AUSPLL_APB_CMD_OVERRIDE, AUSPLL_APB_CMD_OVERRIDE_REQ); 15158e98ca1eSSven Peter 15168e98ca1eSSven Peter return 0; 15178e98ca1eSSven Peter } 15188e98ca1eSSven Peter 15198e98ca1eSSven Peter static int atcphy_dp_configure(struct apple_atcphy *atcphy, enum atcphy_dp_link_rate lr) 15208e98ca1eSSven Peter { 15218e98ca1eSSven Peter const struct atcphy_dp_link_rate_configuration *cfg; 15228e98ca1eSSven Peter const struct atcphy_mode_configuration *mode_cfg; 15238e98ca1eSSven Peter int ret; 15248e98ca1eSSven Peter u32 reg; 15258e98ca1eSSven Peter 15268e98ca1eSSven Peter guard(mutex)(&atcphy->lock); 15278e98ca1eSSven Peter mode_cfg = atcphy_get_mode_config(atcphy, atcphy->mode); 15288e98ca1eSSven Peter cfg = &dp_lr_config[lr]; 15298e98ca1eSSven Peter 15308e98ca1eSSven Peter if (atcphy->dp_link_rate == lr) 15318e98ca1eSSven Peter return 0; 15328e98ca1eSSven Peter 15338e98ca1eSSven Peter ret = readl_poll_timeout(atcphy->regs.core + ACIOPHY_CMN_SHM_STS_REG0, reg, 15348e98ca1eSSven Peter (reg & ACIOPHY_CMN_SHM_STS_REG0_CMD_READY), 10, 10000); 15358e98ca1eSSven Peter if (ret) { 15368e98ca1eSSven Peter dev_err(atcphy->dev, "ACIOPHY_CMN_SHM_STS_REG0_CMD_READY not set.\n"); 15378e98ca1eSSven Peter return ret; 15388e98ca1eSSven Peter } 15398e98ca1eSSven Peter 15408e98ca1eSSven Peter core_clear32(atcphy, AUSPLL_FREQ_CFG, AUSPLL_FREQ_REFCLK); 15418e98ca1eSSven Peter 15428e98ca1eSSven Peter core_mask32(atcphy, AUSPLL_FREQ_DESC_A, AUSPLL_FD_FREQ_COUNT_TARGET, 15438e98ca1eSSven Peter FIELD_PREP(AUSPLL_FD_FREQ_COUNT_TARGET, cfg->freqinit_count_target)); 15448e98ca1eSSven Peter core_clear32(atcphy, AUSPLL_FREQ_DESC_A, AUSPLL_FD_FBDIVN_HALF); 15458e98ca1eSSven Peter core_clear32(atcphy, AUSPLL_FREQ_DESC_A, AUSPLL_FD_REV_DIVN); 15468e98ca1eSSven Peter core_mask32(atcphy, AUSPLL_FREQ_DESC_A, AUSPLL_FD_KI_MAN, FIELD_PREP(AUSPLL_FD_KI_MAN, 8)); 15478e98ca1eSSven Peter core_mask32(atcphy, AUSPLL_FREQ_DESC_A, AUSPLL_FD_KI_EXP, FIELD_PREP(AUSPLL_FD_KI_EXP, 3)); 15488e98ca1eSSven Peter core_mask32(atcphy, AUSPLL_FREQ_DESC_A, AUSPLL_FD_KP_MAN, FIELD_PREP(AUSPLL_FD_KP_MAN, 8)); 15498e98ca1eSSven Peter core_mask32(atcphy, AUSPLL_FREQ_DESC_A, AUSPLL_FD_KP_EXP, FIELD_PREP(AUSPLL_FD_KP_EXP, 7)); 15508e98ca1eSSven Peter core_clear32(atcphy, AUSPLL_FREQ_DESC_A, AUSPLL_FD_KPKI_SCALE_HBW); 15518e98ca1eSSven Peter 15528e98ca1eSSven Peter core_mask32(atcphy, AUSPLL_FREQ_DESC_B, AUSPLL_FD_FBDIVN_FRAC_DEN, 15538e98ca1eSSven Peter FIELD_PREP(AUSPLL_FD_FBDIVN_FRAC_DEN, cfg->fbdivn_frac_den)); 15548e98ca1eSSven Peter core_mask32(atcphy, AUSPLL_FREQ_DESC_B, AUSPLL_FD_FBDIVN_FRAC_NUM, 15558e98ca1eSSven Peter FIELD_PREP(AUSPLL_FD_FBDIVN_FRAC_NUM, cfg->fbdivn_frac_num)); 15568e98ca1eSSven Peter 15578e98ca1eSSven Peter core_clear32(atcphy, AUSPLL_FREQ_DESC_C, AUSPLL_FD_SDM_SSC_STEP); 15588e98ca1eSSven Peter core_clear32(atcphy, AUSPLL_FREQ_DESC_C, AUSPLL_FD_SDM_SSC_EN); 15598e98ca1eSSven Peter core_mask32(atcphy, AUSPLL_FREQ_DESC_C, AUSPLL_FD_PCLK_DIV_SEL, 15608e98ca1eSSven Peter FIELD_PREP(AUSPLL_FD_PCLK_DIV_SEL, cfg->pclk_div_sel)); 15618e98ca1eSSven Peter core_mask32(atcphy, AUSPLL_FREQ_DESC_C, AUSPLL_FD_LFSDM_DIV, 15628e98ca1eSSven Peter FIELD_PREP(AUSPLL_FD_LFSDM_DIV, 1)); 15638e98ca1eSSven Peter core_mask32(atcphy, AUSPLL_FREQ_DESC_C, AUSPLL_FD_LFCLK_CTRL, 15648e98ca1eSSven Peter FIELD_PREP(AUSPLL_FD_LFCLK_CTRL, cfg->lfclk_ctrl)); 15658e98ca1eSSven Peter core_mask32(atcphy, AUSPLL_FREQ_DESC_C, AUSPLL_FD_VCLK_OP_DIVN, 15668e98ca1eSSven Peter FIELD_PREP(AUSPLL_FD_VCLK_OP_DIVN, cfg->vclk_op_divn)); 15678e98ca1eSSven Peter core_set32(atcphy, AUSPLL_FREQ_DESC_C, AUSPLL_FD_VCLK_PRE_DIVN); 15688e98ca1eSSven Peter 15698e98ca1eSSven Peter core_mask32(atcphy, AUSPLL_CLKOUT_DIV, AUSPLL_CLKOUT_PLLA_REFBUFCLK_DI, 15708e98ca1eSSven Peter FIELD_PREP(AUSPLL_CLKOUT_PLLA_REFBUFCLK_DI, 7)); 15718e98ca1eSSven Peter 15728e98ca1eSSven Peter if (cfg->plla_clkout_vreg_bypass) 15738e98ca1eSSven Peter core_set32(atcphy, AUSPLL_CLKOUT_DTC_VREG, AUSPLL_DTC_VREG_BYPASS); 15748e98ca1eSSven Peter else 15758e98ca1eSSven Peter core_clear32(atcphy, AUSPLL_CLKOUT_DTC_VREG, AUSPLL_DTC_VREG_BYPASS); 15768e98ca1eSSven Peter 15778e98ca1eSSven Peter core_set32(atcphy, AUSPLL_BGR, AUSPLL_BGR_CTRL_AVAIL); 15788e98ca1eSSven Peter 15798e98ca1eSSven Peter core_set32(atcphy, AUSPLL_CLKOUT_MASTER, AUSPLL_CLKOUT_MASTER_PCLK_DRVR_EN); 15808e98ca1eSSven Peter core_set32(atcphy, AUSPLL_CLKOUT_MASTER, AUSPLL_CLKOUT_MASTER_PCLK2_DRVR_EN); 15818e98ca1eSSven Peter core_set32(atcphy, AUSPLL_CLKOUT_MASTER, AUSPLL_CLKOUT_MASTER_REFBUFCLK_DRVR_EN); 15828e98ca1eSSven Peter 15838e98ca1eSSven Peter ret = atcphy_auspll_apb_command(atcphy, 0); 15848e98ca1eSSven Peter if (ret) 15858e98ca1eSSven Peter return ret; 15868e98ca1eSSven Peter 15878e98ca1eSSven Peter ret = readl_poll_timeout(atcphy->regs.core + ACIOPHY_DP_PCLK_STAT, reg, 15888e98ca1eSSven Peter (reg & ACIOPHY_AUSPLL_LOCK), 10, 10000); 15898e98ca1eSSven Peter if (ret) { 15908e98ca1eSSven Peter dev_err(atcphy->dev, "ACIOPHY_DP_PCLK did not lock.\n"); 15918e98ca1eSSven Peter return ret; 15928e98ca1eSSven Peter } 15938e98ca1eSSven Peter 15948e98ca1eSSven Peter ret = atcphy_auspll_apb_command(atcphy, 0x2800); 15958e98ca1eSSven Peter if (ret) 15968e98ca1eSSven Peter return ret; 15978e98ca1eSSven Peter 15988e98ca1eSSven Peter if (mode_cfg->dp_lane[0]) { 15998e98ca1eSSven Peter ret = atcphy_dp_configure_lane(atcphy, APPLE_ATCPHY_LANE_0, cfg); 16008e98ca1eSSven Peter if (ret) 16018e98ca1eSSven Peter return ret; 16028e98ca1eSSven Peter } 16038e98ca1eSSven Peter 16048e98ca1eSSven Peter if (mode_cfg->dp_lane[1]) { 16058e98ca1eSSven Peter ret = atcphy_dp_configure_lane(atcphy, APPLE_ATCPHY_LANE_1, cfg); 16068e98ca1eSSven Peter if (ret) 16078e98ca1eSSven Peter return ret; 16088e98ca1eSSven Peter } 16098e98ca1eSSven Peter 16108e98ca1eSSven Peter core_clear32(atcphy, ACIOPHY_LANE_DP_CFG_BLK_TX_DP_CTRL0, DP_PMA_BYTECLK_RESET); 16118e98ca1eSSven Peter core_clear32(atcphy, ACIOPHY_LANE_DP_CFG_BLK_TX_DP_CTRL0, DP_MAC_DIV20_CLK_SEL); 16128e98ca1eSSven Peter 16138e98ca1eSSven Peter atcphy->dp_link_rate = lr; 16148e98ca1eSSven Peter return 0; 16158e98ca1eSSven Peter } 16168e98ca1eSSven Peter 16178e98ca1eSSven Peter static void atcphy_usb2_power_off(struct apple_atcphy *atcphy) 16188e98ca1eSSven Peter { 16198e98ca1eSSven Peter /* Disable the PHY, this clears USB2PHY_USBCTL_RUN */ 16208e98ca1eSSven Peter writel(USB2PHY_USBCTL_ISOLATION, atcphy->regs.usb2phy + USB2PHY_USBCTL); 16218e98ca1eSSven Peter udelay(10); 16228e98ca1eSSven Peter 16238e98ca1eSSven Peter /* Switch the PHY to low power mode */ 16248e98ca1eSSven Peter set32(atcphy->regs.usb2phy + USB2PHY_CTL, USB2PHY_CTL_SIDDQ); 16258e98ca1eSSven Peter udelay(10); 16268e98ca1eSSven Peter 16278e98ca1eSSven Peter /* Enable all resets */ 16288e98ca1eSSven Peter set32(atcphy->regs.usb2phy + USB2PHY_CTL, USB2PHY_CTL_PORT_RESET); 16298e98ca1eSSven Peter udelay(10); 16308e98ca1eSSven Peter set32(atcphy->regs.usb2phy + USB2PHY_CTL, USB2PHY_CTL_RESET); 16318e98ca1eSSven Peter udelay(10); 16328e98ca1eSSven Peter clear32(atcphy->regs.usb2phy + USB2PHY_CTL, USB2PHY_CTL_APB_RESET_N); 16338e98ca1eSSven Peter udelay(10); 16348e98ca1eSSven Peter set32(atcphy->regs.usb2phy + USB2PHY_MISCTUNE, USB2PHY_MISCTUNE_APBCLK_GATE_OFF); 16358e98ca1eSSven Peter set32(atcphy->regs.usb2phy + USB2PHY_MISCTUNE, USB2PHY_MISCTUNE_REFCLK_GATE_OFF); 16368e98ca1eSSven Peter } 16378e98ca1eSSven Peter 16388e98ca1eSSven Peter static int atcphy_power_off(struct apple_atcphy *atcphy) 16398e98ca1eSSven Peter { 16408e98ca1eSSven Peter u32 reg; 16418e98ca1eSSven Peter int ret; 16428e98ca1eSSven Peter 16438e98ca1eSSven Peter atcphy_disable_dp_aux(atcphy); 16448e98ca1eSSven Peter 16458e98ca1eSSven Peter /* Enable all reset lines */ 16468e98ca1eSSven Peter core_clear32(atcphy, ATCPHY_POWER_CTRL, ATCPHY_POWER_PHY_RESET_N); 16478e98ca1eSSven Peter core_set32(atcphy, ATCPHY_POWER_CTRL, ATCPHY_POWER_CLAMP_EN); 16488e98ca1eSSven Peter core_clear32(atcphy, ATCPHY_MISC, ATCPHY_MISC_RESET_N | ATCPHY_MISC_LANE_SWAP); 16498e98ca1eSSven Peter core_clear32(atcphy, ATCPHY_POWER_CTRL, ATCPHY_POWER_APB_RESET_N); 16508e98ca1eSSven Peter 16518e98ca1eSSven Peter core_clear32(atcphy, ATCPHY_POWER_CTRL, ATCPHY_POWER_SLEEP_BIG); 16528e98ca1eSSven Peter ret = readl_poll_timeout(atcphy->regs.core + ATCPHY_POWER_STAT, reg, 16538e98ca1eSSven Peter !(reg & ATCPHY_POWER_SLEEP_BIG), 10, 1000); 16548e98ca1eSSven Peter if (ret) { 16558e98ca1eSSven Peter dev_err(atcphy->dev, "Failed to sleep atcphy \"big\"\n"); 16568e98ca1eSSven Peter return ret; 16578e98ca1eSSven Peter } 16588e98ca1eSSven Peter 16598e98ca1eSSven Peter core_clear32(atcphy, ATCPHY_POWER_CTRL, ATCPHY_POWER_SLEEP_SMALL); 16608e98ca1eSSven Peter ret = readl_poll_timeout(atcphy->regs.core + ATCPHY_POWER_STAT, reg, 16618e98ca1eSSven Peter !(reg & ATCPHY_POWER_SLEEP_SMALL), 10, 1000); 16628e98ca1eSSven Peter if (ret) { 16638e98ca1eSSven Peter dev_err(atcphy->dev, "Failed to sleep atcphy \"small\"\n"); 16648e98ca1eSSven Peter return ret; 16658e98ca1eSSven Peter } 16668e98ca1eSSven Peter 16678e98ca1eSSven Peter return 0; 16688e98ca1eSSven Peter } 16698e98ca1eSSven Peter 16708e98ca1eSSven Peter static void atcphy_usb2_power_on(struct apple_atcphy *atcphy) 16718e98ca1eSSven Peter { 16728e98ca1eSSven Peter set32(atcphy->regs.usb2phy + USB2PHY_SIG, 16738e98ca1eSSven Peter USB2PHY_SIG_VBUSDET_FORCE_VAL | USB2PHY_SIG_VBUSDET_FORCE_EN | 16748e98ca1eSSven Peter USB2PHY_SIG_VBUSVLDEXT_FORCE_VAL | USB2PHY_SIG_VBUSVLDEXT_FORCE_EN); 16758e98ca1eSSven Peter udelay(10); 16768e98ca1eSSven Peter 16778e98ca1eSSven Peter /* Take the PHY out of its low power state */ 16788e98ca1eSSven Peter clear32(atcphy->regs.usb2phy + USB2PHY_CTL, USB2PHY_CTL_SIDDQ); 16798e98ca1eSSven Peter udelay(10); 16808e98ca1eSSven Peter 16818e98ca1eSSven Peter /* Release reset */ 16828e98ca1eSSven Peter clear32(atcphy->regs.usb2phy + USB2PHY_CTL, USB2PHY_CTL_RESET); 16838e98ca1eSSven Peter udelay(10); 16848e98ca1eSSven Peter clear32(atcphy->regs.usb2phy + USB2PHY_CTL, USB2PHY_CTL_PORT_RESET); 16858e98ca1eSSven Peter udelay(10); 16868e98ca1eSSven Peter set32(atcphy->regs.usb2phy + USB2PHY_CTL, USB2PHY_CTL_APB_RESET_N); 16878e98ca1eSSven Peter udelay(10); 16888e98ca1eSSven Peter clear32(atcphy->regs.usb2phy + USB2PHY_MISCTUNE, USB2PHY_MISCTUNE_APBCLK_GATE_OFF); 16898e98ca1eSSven Peter clear32(atcphy->regs.usb2phy + USB2PHY_MISCTUNE, USB2PHY_MISCTUNE_REFCLK_GATE_OFF); 16908e98ca1eSSven Peter 16918e98ca1eSSven Peter /* Enable the PHY */ 16928e98ca1eSSven Peter writel(USB2PHY_USBCTL_RUN, atcphy->regs.usb2phy + USB2PHY_USBCTL); 16938e98ca1eSSven Peter } 16948e98ca1eSSven Peter 16958e98ca1eSSven Peter static int atcphy_power_on(struct apple_atcphy *atcphy) 16968e98ca1eSSven Peter { 16978e98ca1eSSven Peter u32 reg; 16988e98ca1eSSven Peter int ret; 16998e98ca1eSSven Peter 17008e98ca1eSSven Peter atcphy_usb2_power_on(atcphy); 17018e98ca1eSSven Peter 17028e98ca1eSSven Peter core_set32(atcphy, ATCPHY_MISC, ATCPHY_MISC_RESET_N); 17038e98ca1eSSven Peter 17048e98ca1eSSven Peter core_set32(atcphy, ATCPHY_POWER_CTRL, ATCPHY_POWER_SLEEP_SMALL); 17058e98ca1eSSven Peter ret = readl_poll_timeout(atcphy->regs.core + ATCPHY_POWER_STAT, reg, 17068e98ca1eSSven Peter reg & ATCPHY_POWER_SLEEP_SMALL, 100, 100000); 17078e98ca1eSSven Peter if (ret) { 17088e98ca1eSSven Peter dev_err(atcphy->dev, "failed to wakeup atcphy \"small\"\n"); 17098e98ca1eSSven Peter return ret; 17108e98ca1eSSven Peter } 17118e98ca1eSSven Peter 17128e98ca1eSSven Peter core_set32(atcphy, ATCPHY_POWER_CTRL, ATCPHY_POWER_SLEEP_BIG); 17138e98ca1eSSven Peter ret = readl_poll_timeout(atcphy->regs.core + ATCPHY_POWER_STAT, reg, 17148e98ca1eSSven Peter reg & ATCPHY_POWER_SLEEP_BIG, 100, 100000); 17158e98ca1eSSven Peter if (ret) { 17168e98ca1eSSven Peter dev_err(atcphy->dev, "failed to wakeup atcphy \"big\"\n"); 17178e98ca1eSSven Peter return ret; 17188e98ca1eSSven Peter } 17198e98ca1eSSven Peter 17208e98ca1eSSven Peter core_clear32(atcphy, ATCPHY_POWER_CTRL, ATCPHY_POWER_CLAMP_EN); 17218e98ca1eSSven Peter core_set32(atcphy, ATCPHY_POWER_CTRL, ATCPHY_POWER_APB_RESET_N); 17228e98ca1eSSven Peter 17238e98ca1eSSven Peter return 0; 17248e98ca1eSSven Peter } 17258e98ca1eSSven Peter 17268e98ca1eSSven Peter static int atcphy_configure(struct apple_atcphy *atcphy, enum atcphy_mode mode) 17278e98ca1eSSven Peter { 17288e98ca1eSSven Peter int ret = 0; 17298e98ca1eSSven Peter 17308e98ca1eSSven Peter lockdep_assert_held(&atcphy->lock); 17318e98ca1eSSven Peter 17328e98ca1eSSven Peter if (mode == APPLE_ATCPHY_MODE_OFF) { 17338e98ca1eSSven Peter ret = atcphy_power_off(atcphy); 17348e98ca1eSSven Peter atcphy->mode = mode; 17358e98ca1eSSven Peter return ret; 17368e98ca1eSSven Peter } 17378e98ca1eSSven Peter 17388e98ca1eSSven Peter ret = atcphy_power_on(atcphy); 17398e98ca1eSSven Peter if (ret) 17408e98ca1eSSven Peter return ret; 17418e98ca1eSSven Peter 17428e98ca1eSSven Peter atcphy_apply_tunables(atcphy, mode); 17438e98ca1eSSven Peter 17448e98ca1eSSven Peter core_set32(atcphy, AUSPLL_FSM_CTRL, 0x1fe000); 17458e98ca1eSSven Peter core_set32(atcphy, AUSPLL_APB_CMD_OVERRIDE, AUSPLL_APB_CMD_OVERRIDE_UNK28); 17468e98ca1eSSven Peter 17478e98ca1eSSven Peter set32(atcphy->regs.core + ACIOPHY_CFG0, ACIOPHY_CFG0_COMMON_SMALL_OV); 17488e98ca1eSSven Peter udelay(10); 17498e98ca1eSSven Peter set32(atcphy->regs.core + ACIOPHY_CFG0, ACIOPHY_CFG0_COMMON_BIG_OV); 17508e98ca1eSSven Peter udelay(10); 17518e98ca1eSSven Peter set32(atcphy->regs.core + ACIOPHY_CFG0, ACIOPHY_CFG0_COMMON_CLAMP_OV); 17528e98ca1eSSven Peter udelay(10); 17538e98ca1eSSven Peter 17548e98ca1eSSven Peter mask32(atcphy->regs.core + ACIOPHY_SLEEP_CTRL, ACIOPHY_SLEEP_CTRL_TX_SMALL_OV, 17558e98ca1eSSven Peter FIELD_PREP(ACIOPHY_SLEEP_CTRL_TX_SMALL_OV, 3)); 17568e98ca1eSSven Peter udelay(10); 17578e98ca1eSSven Peter mask32(atcphy->regs.core + ACIOPHY_SLEEP_CTRL, ACIOPHY_SLEEP_CTRL_TX_BIG_OV, 17588e98ca1eSSven Peter FIELD_PREP(ACIOPHY_SLEEP_CTRL_TX_BIG_OV, 3)); 17598e98ca1eSSven Peter udelay(10); 17608e98ca1eSSven Peter mask32(atcphy->regs.core + ACIOPHY_SLEEP_CTRL, ACIOPHY_SLEEP_CTRL_TX_CLAMP_OV, 17618e98ca1eSSven Peter FIELD_PREP(ACIOPHY_SLEEP_CTRL_TX_CLAMP_OV, 3)); 17628e98ca1eSSven Peter udelay(10); 17638e98ca1eSSven Peter 17648e98ca1eSSven Peter mask32(atcphy->regs.core + ACIOPHY_CFG0, ACIOPHY_CFG0_RX_BIG_OV, 17658e98ca1eSSven Peter FIELD_PREP(ACIOPHY_CFG0_RX_BIG_OV, 3)); 17668e98ca1eSSven Peter udelay(10); 17678e98ca1eSSven Peter mask32(atcphy->regs.core + ACIOPHY_CFG0, ACIOPHY_CFG0_RX_SMALL_OV, 17688e98ca1eSSven Peter FIELD_PREP(ACIOPHY_CFG0_RX_SMALL_OV, 3)); 17698e98ca1eSSven Peter udelay(10); 17708e98ca1eSSven Peter mask32(atcphy->regs.core + ACIOPHY_CFG0, ACIOPHY_CFG0_RX_CLAMP_OV, 17718e98ca1eSSven Peter FIELD_PREP(ACIOPHY_CFG0_RX_CLAMP_OV, 3)); 17728e98ca1eSSven Peter udelay(10); 17738e98ca1eSSven Peter 17748e98ca1eSSven Peter /* Setup AUX channel if DP altmode is requested */ 17758e98ca1eSSven Peter if (atcphy_modes[mode].enable_dp_aux) 17768e98ca1eSSven Peter atcphy_enable_dp_aux(atcphy); 17778e98ca1eSSven Peter 17788e98ca1eSSven Peter /* Enable clocks and configure lanes */ 17798e98ca1eSSven Peter core_set32(atcphy, CIO3PLL_CLK_CTRL, CIO3PLL_CLK_PCLK_EN); 17808e98ca1eSSven Peter core_set32(atcphy, CIO3PLL_CLK_CTRL, CIO3PLL_CLK_REFCLK_EN); 17818e98ca1eSSven Peter atcphy_configure_lanes(atcphy, mode); 17828e98ca1eSSven Peter 17838e98ca1eSSven Peter /* Take the USB3 PHY out of reset */ 17848e98ca1eSSven Peter core_set32(atcphy, ATCPHY_POWER_CTRL, ATCPHY_POWER_PHY_RESET_N); 17858e98ca1eSSven Peter 17868e98ca1eSSven Peter atcphy->mode = mode; 17878e98ca1eSSven Peter 17888e98ca1eSSven Peter return 0; 17898e98ca1eSSven Peter } 17908e98ca1eSSven Peter 17918e98ca1eSSven Peter static int atcphy_usb2_set_mode(struct phy *phy, enum phy_mode mode, int submode) 17928e98ca1eSSven Peter { 17938e98ca1eSSven Peter struct apple_atcphy *atcphy = phy_get_drvdata(phy); 17948e98ca1eSSven Peter 17958e98ca1eSSven Peter guard(mutex)(&atcphy->lock); 17968e98ca1eSSven Peter 17978e98ca1eSSven Peter switch (mode) { 17988e98ca1eSSven Peter case PHY_MODE_USB_HOST: 17998e98ca1eSSven Peter set32(atcphy->regs.usb2phy + USB2PHY_SIG, USB2PHY_SIG_HOST); 18008e98ca1eSSven Peter break; 18018e98ca1eSSven Peter case PHY_MODE_USB_DEVICE: 18028e98ca1eSSven Peter clear32(atcphy->regs.usb2phy + USB2PHY_SIG, USB2PHY_SIG_HOST); 18038e98ca1eSSven Peter break; 18048e98ca1eSSven Peter default: 18058e98ca1eSSven Peter return -EINVAL; 18068e98ca1eSSven Peter } 18078e98ca1eSSven Peter 18088e98ca1eSSven Peter return 0; 18098e98ca1eSSven Peter } 18108e98ca1eSSven Peter 18118e98ca1eSSven Peter static const struct phy_ops apple_atc_usb2_phy_ops = { 18128e98ca1eSSven Peter .owner = THIS_MODULE, 18138e98ca1eSSven Peter .set_mode = atcphy_usb2_set_mode, 18148e98ca1eSSven Peter }; 18158e98ca1eSSven Peter 18168e98ca1eSSven Peter static int atcphy_usb3_power_off(struct phy *phy) 18178e98ca1eSSven Peter { 18188e98ca1eSSven Peter struct apple_atcphy *atcphy = phy_get_drvdata(phy); 18198e98ca1eSSven Peter int ret; 18208e98ca1eSSven Peter 18218e98ca1eSSven Peter guard(mutex)(&atcphy->lock); 18228e98ca1eSSven Peter 18238e98ca1eSSven Peter ret = atcphy_configure_pipehandler_dummy(atcphy); 18248e98ca1eSSven Peter if (ret) 18258e98ca1eSSven Peter dev_warn(atcphy->dev, "Failed to switch pipe to dummy: %d", ret); 18268e98ca1eSSven Peter 18278e98ca1eSSven Peter atcphy->pipehandler_up = false; 18288e98ca1eSSven Peter 18298e98ca1eSSven Peter if (atcphy->mode != APPLE_ATCPHY_MODE_OFF) 18308e98ca1eSSven Peter atcphy_configure(atcphy, APPLE_ATCPHY_MODE_OFF); 18318e98ca1eSSven Peter 18328e98ca1eSSven Peter return 0; 18338e98ca1eSSven Peter } 18348e98ca1eSSven Peter 18358e98ca1eSSven Peter static int atcphy_usb3_set_mode(struct phy *phy, enum phy_mode mode, int submode) 18368e98ca1eSSven Peter { 18378e98ca1eSSven Peter struct apple_atcphy *atcphy = phy_get_drvdata(phy); 18388e98ca1eSSven Peter 18398e98ca1eSSven Peter guard(mutex)(&atcphy->lock); 18408e98ca1eSSven Peter 18418e98ca1eSSven Peter /* 18428e98ca1eSSven Peter * We may get multiple calls to set_mode (for host mode e.g. at least one from the dwc3 glue 18438e98ca1eSSven Peter * driver and then another one from the generic xhci code) but must only configure the 18448e98ca1eSSven Peter * PIPE handler once. 18458e98ca1eSSven Peter */ 18468e98ca1eSSven Peter if (atcphy->pipehandler_up) 18478e98ca1eSSven Peter return 0; 18488e98ca1eSSven Peter 18498e98ca1eSSven Peter switch (mode) { 18508e98ca1eSSven Peter case PHY_MODE_USB_HOST: 18518e98ca1eSSven Peter return atcphy_configure_pipehandler(atcphy, true); 18528e98ca1eSSven Peter case PHY_MODE_USB_DEVICE: 18538e98ca1eSSven Peter return atcphy_configure_pipehandler(atcphy, false); 18548e98ca1eSSven Peter default: 18558e98ca1eSSven Peter return -EINVAL; 18568e98ca1eSSven Peter } 18578e98ca1eSSven Peter } 18588e98ca1eSSven Peter 18598e98ca1eSSven Peter static const struct phy_ops apple_atc_usb3_phy_ops = { 18608e98ca1eSSven Peter .owner = THIS_MODULE, 18618e98ca1eSSven Peter .power_off = atcphy_usb3_power_off, 18628e98ca1eSSven Peter .set_mode = atcphy_usb3_set_mode, 18638e98ca1eSSven Peter }; 18648e98ca1eSSven Peter 18658e98ca1eSSven Peter static int atcphy_dpphy_set_mode(struct phy *phy, enum phy_mode mode, int submode) 18668e98ca1eSSven Peter { 18678e98ca1eSSven Peter /* Nothing to do here since the setup already happened in mux_set */ 18688e98ca1eSSven Peter if (mode == PHY_MODE_DP && submode == 0) 18698e98ca1eSSven Peter return 0; 18708e98ca1eSSven Peter return -EINVAL; 18718e98ca1eSSven Peter } 18728e98ca1eSSven Peter 18738e98ca1eSSven Peter static int atcphy_dpphy_validate(struct phy *phy, enum phy_mode mode, int submode, 18748e98ca1eSSven Peter union phy_configure_opts *opts_) 18758e98ca1eSSven Peter { 18768e98ca1eSSven Peter struct phy_configure_opts_dp *opts = &opts_->dp; 18778e98ca1eSSven Peter struct apple_atcphy *atcphy = phy_get_drvdata(phy); 18788e98ca1eSSven Peter 18798e98ca1eSSven Peter if (mode != PHY_MODE_DP) 18808e98ca1eSSven Peter return -EINVAL; 18818e98ca1eSSven Peter if (submode != 0) 18828e98ca1eSSven Peter return -EINVAL; 18838e98ca1eSSven Peter 18848e98ca1eSSven Peter switch (atcphy->mode) { 18858e98ca1eSSven Peter case APPLE_ATCPHY_MODE_USB3_DP: 18868e98ca1eSSven Peter opts->lanes = 2; 18878e98ca1eSSven Peter break; 18888e98ca1eSSven Peter case APPLE_ATCPHY_MODE_DP: 18898e98ca1eSSven Peter opts->lanes = 4; 18908e98ca1eSSven Peter break; 18918e98ca1eSSven Peter default: 18928e98ca1eSSven Peter opts->lanes = 0; 18938e98ca1eSSven Peter } 18948e98ca1eSSven Peter 18958e98ca1eSSven Peter return 0; 18968e98ca1eSSven Peter } 18978e98ca1eSSven Peter 18988e98ca1eSSven Peter static int atcphy_dpphy_configure(struct phy *phy, union phy_configure_opts *opts_) 18998e98ca1eSSven Peter { 19008e98ca1eSSven Peter struct phy_configure_opts_dp *opts = &opts_->dp; 19018e98ca1eSSven Peter struct apple_atcphy *atcphy = phy_get_drvdata(phy); 19028e98ca1eSSven Peter enum atcphy_dp_link_rate link_rate; 19038e98ca1eSSven Peter 19048e98ca1eSSven Peter if (opts->set_voltages) 19058e98ca1eSSven Peter return -EINVAL; 19068e98ca1eSSven Peter if (opts->set_lanes) 19078e98ca1eSSven Peter return -EINVAL; 19088e98ca1eSSven Peter 19098e98ca1eSSven Peter if (opts->set_rate) { 19108e98ca1eSSven Peter switch (opts->link_rate) { 19118e98ca1eSSven Peter case 1620: 19128e98ca1eSSven Peter link_rate = ATCPHY_DP_LINK_RATE_RBR; 19138e98ca1eSSven Peter break; 19148e98ca1eSSven Peter case 2700: 19158e98ca1eSSven Peter link_rate = ATCPHY_DP_LINK_RATE_HBR; 19168e98ca1eSSven Peter break; 19178e98ca1eSSven Peter case 5400: 19188e98ca1eSSven Peter link_rate = ATCPHY_DP_LINK_RATE_HBR2; 19198e98ca1eSSven Peter break; 19208e98ca1eSSven Peter case 8100: 19218e98ca1eSSven Peter link_rate = ATCPHY_DP_LINK_RATE_HBR3; 19228e98ca1eSSven Peter break; 19238e98ca1eSSven Peter case 0: 19248e98ca1eSSven Peter return 0; 19258e98ca1eSSven Peter default: 19268e98ca1eSSven Peter dev_err(atcphy->dev, "Unsupported link rate: %d\n", opts->link_rate); 19278e98ca1eSSven Peter return -EINVAL; 19288e98ca1eSSven Peter } 19298e98ca1eSSven Peter 19308e98ca1eSSven Peter return atcphy_dp_configure(atcphy, link_rate); 19318e98ca1eSSven Peter } 19328e98ca1eSSven Peter 19338e98ca1eSSven Peter return 0; 19348e98ca1eSSven Peter } 19358e98ca1eSSven Peter 19368e98ca1eSSven Peter static const struct phy_ops apple_atc_dp_phy_ops = { 19378e98ca1eSSven Peter .owner = THIS_MODULE, 19388e98ca1eSSven Peter .configure = atcphy_dpphy_configure, 19398e98ca1eSSven Peter .validate = atcphy_dpphy_validate, 19408e98ca1eSSven Peter .set_mode = atcphy_dpphy_set_mode, 19418e98ca1eSSven Peter }; 19428e98ca1eSSven Peter 19438e98ca1eSSven Peter static struct phy *atcphy_xlate(struct device *dev, const struct of_phandle_args *args) 19448e98ca1eSSven Peter { 19458e98ca1eSSven Peter struct apple_atcphy *atcphy = dev_get_drvdata(dev); 19468e98ca1eSSven Peter 19478e98ca1eSSven Peter switch (args->args[0]) { 19488e98ca1eSSven Peter case PHY_TYPE_USB2: 19498e98ca1eSSven Peter return atcphy->phys.usb2; 19508e98ca1eSSven Peter case PHY_TYPE_USB3: 19518e98ca1eSSven Peter return atcphy->phys.usb3; 19528e98ca1eSSven Peter case PHY_TYPE_DP: 19538e98ca1eSSven Peter return atcphy->phys.dp; 19548e98ca1eSSven Peter } 19558e98ca1eSSven Peter return ERR_PTR(-ENODEV); 19568e98ca1eSSven Peter } 19578e98ca1eSSven Peter 19588e98ca1eSSven Peter static int atcphy_probe_phy(struct apple_atcphy *atcphy) 19598e98ca1eSSven Peter { 19608e98ca1eSSven Peter struct { 19618e98ca1eSSven Peter struct phy **phy; 19628e98ca1eSSven Peter const struct phy_ops *ops; 19638e98ca1eSSven Peter } phys[] = { 19648e98ca1eSSven Peter { &atcphy->phys.usb2, &apple_atc_usb2_phy_ops }, 19658e98ca1eSSven Peter { &atcphy->phys.usb3, &apple_atc_usb3_phy_ops }, 19668e98ca1eSSven Peter { &atcphy->phys.dp, &apple_atc_dp_phy_ops }, 19678e98ca1eSSven Peter }; 19688e98ca1eSSven Peter 19698e98ca1eSSven Peter for (int i = 0; i < ARRAY_SIZE(phys); i++) { 19708e98ca1eSSven Peter *phys[i].phy = devm_phy_create(atcphy->dev, NULL, phys[i].ops); 19718e98ca1eSSven Peter if (IS_ERR(*phys[i].phy)) 19728e98ca1eSSven Peter return PTR_ERR(*phys[i].phy); 19738e98ca1eSSven Peter phy_set_drvdata(*phys[i].phy, atcphy); 19748e98ca1eSSven Peter } 19758e98ca1eSSven Peter 19768e98ca1eSSven Peter atcphy->phy_provider = devm_of_phy_provider_register(atcphy->dev, atcphy_xlate); 19778e98ca1eSSven Peter if (IS_ERR(atcphy->phy_provider)) 19788e98ca1eSSven Peter return PTR_ERR(atcphy->phy_provider); 19798e98ca1eSSven Peter return 0; 19808e98ca1eSSven Peter } 19818e98ca1eSSven Peter 19828e98ca1eSSven Peter static void _atcphy_dwc3_reset_assert(struct apple_atcphy *atcphy) 19838e98ca1eSSven Peter { 19848e98ca1eSSven Peter lockdep_assert_held(&atcphy->lock); 19858e98ca1eSSven Peter 19868e98ca1eSSven Peter clear32(atcphy->regs.pipehandler + PIPEHANDLER_AON_GEN, PIPEHANDLER_AON_GEN_DWC3_RESET_N); 19878e98ca1eSSven Peter set32(atcphy->regs.pipehandler + PIPEHANDLER_AON_GEN, 19888e98ca1eSSven Peter PIPEHANDLER_AON_GEN_DWC3_FORCE_CLAMP_EN); 19898e98ca1eSSven Peter } 19908e98ca1eSSven Peter 19918e98ca1eSSven Peter static int atcphy_dwc3_reset_assert(struct reset_controller_dev *rcdev, unsigned long id) 19928e98ca1eSSven Peter { 19938e98ca1eSSven Peter struct apple_atcphy *atcphy = container_of(rcdev, struct apple_atcphy, rcdev); 19948e98ca1eSSven Peter int ret; 19958e98ca1eSSven Peter 19968e98ca1eSSven Peter guard(mutex)(&atcphy->lock); 19978e98ca1eSSven Peter 19988e98ca1eSSven Peter _atcphy_dwc3_reset_assert(atcphy); 19998e98ca1eSSven Peter 20008e98ca1eSSven Peter if (atcphy->pipehandler_up) { 20018e98ca1eSSven Peter ret = atcphy_configure_pipehandler_dummy(atcphy); 20028e98ca1eSSven Peter if (ret) 20038e98ca1eSSven Peter dev_warn(atcphy->dev, "Failed to switch PIPE to dummy: %d\n", ret); 20048e98ca1eSSven Peter else 20058e98ca1eSSven Peter atcphy->pipehandler_up = false; 20068e98ca1eSSven Peter } 20078e98ca1eSSven Peter 20088e98ca1eSSven Peter atcphy_usb2_power_off(atcphy); 20098e98ca1eSSven Peter 20108e98ca1eSSven Peter return 0; 20118e98ca1eSSven Peter } 20128e98ca1eSSven Peter 20138e98ca1eSSven Peter static int atcphy_dwc3_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) 20148e98ca1eSSven Peter { 20158e98ca1eSSven Peter struct apple_atcphy *atcphy = container_of(rcdev, struct apple_atcphy, rcdev); 20168e98ca1eSSven Peter 20178e98ca1eSSven Peter guard(mutex)(&atcphy->lock); 20188e98ca1eSSven Peter 20198e98ca1eSSven Peter clear32(atcphy->regs.pipehandler + PIPEHANDLER_AON_GEN, 20208e98ca1eSSven Peter PIPEHANDLER_AON_GEN_DWC3_FORCE_CLAMP_EN); 20218e98ca1eSSven Peter set32(atcphy->regs.pipehandler + PIPEHANDLER_AON_GEN, PIPEHANDLER_AON_GEN_DWC3_RESET_N); 20228e98ca1eSSven Peter 20238e98ca1eSSven Peter return 0; 20248e98ca1eSSven Peter } 20258e98ca1eSSven Peter 20268e98ca1eSSven Peter const struct reset_control_ops atcphy_dwc3_reset_ops = { 20278e98ca1eSSven Peter .assert = atcphy_dwc3_reset_assert, 20288e98ca1eSSven Peter .deassert = atcphy_dwc3_reset_deassert, 20298e98ca1eSSven Peter }; 20308e98ca1eSSven Peter 20318e98ca1eSSven Peter static int atcphy_reset_xlate(struct reset_controller_dev *rcdev, 20328e98ca1eSSven Peter const struct of_phandle_args *reset_spec) 20338e98ca1eSSven Peter { 20348e98ca1eSSven Peter return 0; 20358e98ca1eSSven Peter } 20368e98ca1eSSven Peter 20378e98ca1eSSven Peter static int atcphy_probe_rcdev(struct apple_atcphy *atcphy) 20388e98ca1eSSven Peter { 20398e98ca1eSSven Peter atcphy->rcdev.owner = THIS_MODULE; 20408e98ca1eSSven Peter atcphy->rcdev.nr_resets = 1; 20418e98ca1eSSven Peter atcphy->rcdev.ops = &atcphy_dwc3_reset_ops; 20428e98ca1eSSven Peter atcphy->rcdev.of_node = atcphy->dev->of_node; 20438e98ca1eSSven Peter atcphy->rcdev.of_reset_n_cells = 0; 20448e98ca1eSSven Peter atcphy->rcdev.of_xlate = atcphy_reset_xlate; 20458e98ca1eSSven Peter 20468e98ca1eSSven Peter return devm_reset_controller_register(atcphy->dev, &atcphy->rcdev); 20478e98ca1eSSven Peter } 20488e98ca1eSSven Peter 20498e98ca1eSSven Peter static int atcphy_sw_set(struct typec_switch_dev *sw, enum typec_orientation orientation) 20508e98ca1eSSven Peter { 20518e98ca1eSSven Peter struct apple_atcphy *atcphy = typec_switch_get_drvdata(sw); 20528e98ca1eSSven Peter 20538e98ca1eSSven Peter guard(mutex)(&atcphy->lock); 20548e98ca1eSSven Peter 20558e98ca1eSSven Peter switch (orientation) { 20568e98ca1eSSven Peter case TYPEC_ORIENTATION_NONE: 20578e98ca1eSSven Peter break; 20588e98ca1eSSven Peter case TYPEC_ORIENTATION_NORMAL: 20598e98ca1eSSven Peter atcphy->swap_lanes = false; 20608e98ca1eSSven Peter break; 20618e98ca1eSSven Peter case TYPEC_ORIENTATION_REVERSE: 20628e98ca1eSSven Peter atcphy->swap_lanes = true; 20638e98ca1eSSven Peter break; 20648e98ca1eSSven Peter } 20658e98ca1eSSven Peter 20668e98ca1eSSven Peter return 0; 20678e98ca1eSSven Peter } 20688e98ca1eSSven Peter 20698e98ca1eSSven Peter static int atcphy_probe_switch(struct apple_atcphy *atcphy) 20708e98ca1eSSven Peter { 20718e98ca1eSSven Peter struct typec_switch_desc sw_desc = { 20728e98ca1eSSven Peter .drvdata = atcphy, 20738e98ca1eSSven Peter .fwnode = atcphy->dev->fwnode, 20748e98ca1eSSven Peter .set = atcphy_sw_set, 20758e98ca1eSSven Peter }; 20768e98ca1eSSven Peter 20778e98ca1eSSven Peter return PTR_ERR_OR_ZERO(typec_switch_register(atcphy->dev, &sw_desc)); 20788e98ca1eSSven Peter } 20798e98ca1eSSven Peter 20808e98ca1eSSven Peter static int atcphy_mux_set(struct typec_mux_dev *mux, struct typec_mux_state *state) 20818e98ca1eSSven Peter { 20828e98ca1eSSven Peter struct apple_atcphy *atcphy = typec_mux_get_drvdata(mux); 20838e98ca1eSSven Peter enum atcphy_mode target_mode; 20848e98ca1eSSven Peter 20858e98ca1eSSven Peter guard(mutex)(&atcphy->lock); 20868e98ca1eSSven Peter 20878e98ca1eSSven Peter if (state->mode == TYPEC_STATE_SAFE) { 20888e98ca1eSSven Peter target_mode = APPLE_ATCPHY_MODE_OFF; 20898e98ca1eSSven Peter } else if (state->mode == TYPEC_STATE_USB) { 20908e98ca1eSSven Peter target_mode = APPLE_ATCPHY_MODE_USB3; 20918e98ca1eSSven Peter } else if (!state->alt && state->mode == TYPEC_MODE_USB4) { 20928e98ca1eSSven Peter struct enter_usb_data *data = state->data; 20938e98ca1eSSven Peter u32 eudo_usb_mode = FIELD_GET(EUDO_USB_MODE_MASK, data->eudo); 20948e98ca1eSSven Peter 20958e98ca1eSSven Peter switch (eudo_usb_mode) { 20968e98ca1eSSven Peter case EUDO_USB_MODE_USB2: 20978e98ca1eSSven Peter target_mode = APPLE_ATCPHY_MODE_USB2; 20988e98ca1eSSven Peter break; 20998e98ca1eSSven Peter case EUDO_USB_MODE_USB3: 21008e98ca1eSSven Peter target_mode = APPLE_ATCPHY_MODE_USB3; 21018e98ca1eSSven Peter break; 21028e98ca1eSSven Peter case EUDO_USB_MODE_USB4: 21038e98ca1eSSven Peter target_mode = APPLE_ATCPHY_MODE_USB4; 21048e98ca1eSSven Peter break; 21058e98ca1eSSven Peter default: 21068e98ca1eSSven Peter dev_warn(atcphy->dev, "Unsupported EUDO USB mode: 0x%x.\n", eudo_usb_mode); 21078e98ca1eSSven Peter target_mode = APPLE_ATCPHY_MODE_OFF; 21088e98ca1eSSven Peter } 21098e98ca1eSSven Peter } else if (state->alt && state->alt->svid == USB_TYPEC_TBT_SID) { 21108e98ca1eSSven Peter target_mode = APPLE_ATCPHY_MODE_TBT; 21118e98ca1eSSven Peter } else if (state->alt && state->alt->svid == USB_TYPEC_DP_SID) { 21128e98ca1eSSven Peter switch (state->mode) { 21138e98ca1eSSven Peter case TYPEC_DP_STATE_C: 21148e98ca1eSSven Peter case TYPEC_DP_STATE_E: 21158e98ca1eSSven Peter target_mode = APPLE_ATCPHY_MODE_DP; 21168e98ca1eSSven Peter break; 21178e98ca1eSSven Peter case TYPEC_DP_STATE_D: 21188e98ca1eSSven Peter target_mode = APPLE_ATCPHY_MODE_USB3_DP; 21198e98ca1eSSven Peter break; 21208e98ca1eSSven Peter default: 21218e98ca1eSSven Peter dev_err(atcphy->dev, 21228e98ca1eSSven Peter "Unsupported DP pin assignment: 0x%lx, your connected device will not work.\n", 21238e98ca1eSSven Peter state->mode); 21248e98ca1eSSven Peter target_mode = APPLE_ATCPHY_MODE_OFF; 21258e98ca1eSSven Peter } 21268e98ca1eSSven Peter } else if (state->alt) { 21278e98ca1eSSven Peter dev_err(atcphy->dev, 21288e98ca1eSSven Peter "Unknown alternate mode SVID: 0x%x, your connected device will not work.\n", 21298e98ca1eSSven Peter state->alt->svid); 21308e98ca1eSSven Peter target_mode = APPLE_ATCPHY_MODE_OFF; 21318e98ca1eSSven Peter } else { 21328e98ca1eSSven Peter dev_err(atcphy->dev, "Unknown mode: 0x%lx, your connected device will not work.\n", 21338e98ca1eSSven Peter state->mode); 21348e98ca1eSSven Peter target_mode = APPLE_ATCPHY_MODE_OFF; 21358e98ca1eSSven Peter } 21368e98ca1eSSven Peter 21378e98ca1eSSven Peter if (atcphy->mode == target_mode) 21388e98ca1eSSven Peter return 0; 21398e98ca1eSSven Peter 21408e98ca1eSSven Peter /* 21418e98ca1eSSven Peter * If the pipehandler is still/already up here there's a bug somewhere so make sure to 21428e98ca1eSSven Peter * complain loudly. We can still try to switch modes and hope for the best though, 21438e98ca1eSSven Peter * in the worst case the hardware will fall back to USB2-only. 21448e98ca1eSSven Peter */ 21458e98ca1eSSven Peter WARN_ON_ONCE(atcphy->pipehandler_up); 21468e98ca1eSSven Peter return atcphy_configure(atcphy, target_mode); 21478e98ca1eSSven Peter } 21488e98ca1eSSven Peter 21498e98ca1eSSven Peter static int atcphy_probe_mux(struct apple_atcphy *atcphy) 21508e98ca1eSSven Peter { 21518e98ca1eSSven Peter struct typec_mux_desc mux_desc = { 21528e98ca1eSSven Peter .drvdata = atcphy, 21538e98ca1eSSven Peter .fwnode = atcphy->dev->fwnode, 21548e98ca1eSSven Peter .set = atcphy_mux_set, 21558e98ca1eSSven Peter }; 21568e98ca1eSSven Peter 21578e98ca1eSSven Peter return PTR_ERR_OR_ZERO(typec_mux_register(atcphy->dev, &mux_desc)); 21588e98ca1eSSven Peter } 21598e98ca1eSSven Peter 21608e98ca1eSSven Peter static int atcphy_load_tunables(struct apple_atcphy *atcphy) 21618e98ca1eSSven Peter { 21628e98ca1eSSven Peter struct { 21638e98ca1eSSven Peter const char *dt_name; 21648e98ca1eSSven Peter struct apple_tunable **tunable; 21658e98ca1eSSven Peter struct resource *res; 21668e98ca1eSSven Peter } tunables[] = { 21678e98ca1eSSven Peter { "apple,tunable-axi2af", &atcphy->tunables.axi2af, atcphy->res.axi2af }, 21688e98ca1eSSven Peter { "apple,tunable-common-a", &atcphy->tunables.common[0], atcphy->res.core }, 21698e98ca1eSSven Peter { "apple,tunable-common-b", &atcphy->tunables.common[1], atcphy->res.core }, 21708e98ca1eSSven Peter { "apple,tunable-lane0-usb", &atcphy->tunables.lane_usb3[0], atcphy->res.core }, 21718e98ca1eSSven Peter { "apple,tunable-lane1-usb", &atcphy->tunables.lane_usb3[1], atcphy->res.core }, 21728e98ca1eSSven Peter { "apple,tunable-lane0-cio", &atcphy->tunables.lane_usb4[0], atcphy->res.core }, 21738e98ca1eSSven Peter { "apple,tunable-lane1-cio", &atcphy->tunables.lane_usb4[1], atcphy->res.core }, 21748e98ca1eSSven Peter { "apple,tunable-lane0-dp", &atcphy->tunables.lane_dp[0], atcphy->res.core }, 21758e98ca1eSSven Peter { "apple,tunable-lane1-dp", &atcphy->tunables.lane_dp[1], atcphy->res.core }, 21768e98ca1eSSven Peter }; 21778e98ca1eSSven Peter 21788e98ca1eSSven Peter for (int i = 0; i < ARRAY_SIZE(tunables); i++) { 21798e98ca1eSSven Peter *tunables[i].tunable = devm_apple_tunable_parse( 21808e98ca1eSSven Peter atcphy->dev, atcphy->np, tunables[i].dt_name, tunables[i].res); 21817d55b44eSSven Peter if (IS_ERR(*tunables[i].tunable)) { 21828e98ca1eSSven Peter dev_err(atcphy->dev, "Failed to read tunable %s: %ld\n", 21837d55b44eSSven Peter tunables[i].dt_name, PTR_ERR(*tunables[i].tunable)); 21847d55b44eSSven Peter return PTR_ERR(*tunables[i].tunable); 21858e98ca1eSSven Peter } 21868e98ca1eSSven Peter } 21878e98ca1eSSven Peter 21888e98ca1eSSven Peter return 0; 21898e98ca1eSSven Peter } 21908e98ca1eSSven Peter 21918e98ca1eSSven Peter static int atcphy_map_resources(struct platform_device *pdev, struct apple_atcphy *atcphy) 21928e98ca1eSSven Peter { 21938e98ca1eSSven Peter struct { 21948e98ca1eSSven Peter const char *name; 21958e98ca1eSSven Peter void __iomem **addr; 21968e98ca1eSSven Peter struct resource **res; 21978e98ca1eSSven Peter } resources[] = { 21988e98ca1eSSven Peter { "core", &atcphy->regs.core, &atcphy->res.core }, 21998e98ca1eSSven Peter { "lpdptx", &atcphy->regs.lpdptx, NULL }, 22008e98ca1eSSven Peter { "axi2af", &atcphy->regs.axi2af, &atcphy->res.axi2af }, 22018e98ca1eSSven Peter { "usb2phy", &atcphy->regs.usb2phy, NULL }, 22028e98ca1eSSven Peter { "pipehandler", &atcphy->regs.pipehandler, NULL }, 22038e98ca1eSSven Peter }; 22048e98ca1eSSven Peter struct resource *res; 22058e98ca1eSSven Peter 22068e98ca1eSSven Peter for (int i = 0; i < ARRAY_SIZE(resources); i++) { 22078e98ca1eSSven Peter res = platform_get_resource_byname(pdev, IORESOURCE_MEM, resources[i].name); 22088e98ca1eSSven Peter *resources[i].addr = devm_ioremap_resource(&pdev->dev, res); 22098e98ca1eSSven Peter if (IS_ERR(resources[i].addr)) 22108e98ca1eSSven Peter return dev_err_probe(atcphy->dev, PTR_ERR(resources[i].addr), 22118e98ca1eSSven Peter "Unable to map %s regs", resources[i].name); 22128e98ca1eSSven Peter 22138e98ca1eSSven Peter if (resources[i].res) 22148e98ca1eSSven Peter *resources[i].res = res; 22158e98ca1eSSven Peter } 22168e98ca1eSSven Peter 22178e98ca1eSSven Peter return 0; 22188e98ca1eSSven Peter } 22198e98ca1eSSven Peter 22208e98ca1eSSven Peter static int atcphy_probe_finalize(struct apple_atcphy *atcphy) 22218e98ca1eSSven Peter { 22228e98ca1eSSven Peter int ret; 22238e98ca1eSSven Peter 22248e98ca1eSSven Peter guard(mutex)(&atcphy->lock); 22258e98ca1eSSven Peter 22268e98ca1eSSven Peter /* Reset dwc3 on probe, let dwc3 (consumer) deassert it */ 22278e98ca1eSSven Peter _atcphy_dwc3_reset_assert(atcphy); 22288e98ca1eSSven Peter 22298e98ca1eSSven Peter /* Reset atcphy to clear any state potentially left by the bootloader */ 2230*bc148defSSven Peter atcphy_usb2_power_off(atcphy); 22318e98ca1eSSven Peter atcphy_power_off(atcphy); 22328e98ca1eSSven Peter atcphy_setup_pipehandler(atcphy); 22338e98ca1eSSven Peter 22348e98ca1eSSven Peter ret = atcphy_probe_rcdev(atcphy); 22358e98ca1eSSven Peter if (ret) 22368e98ca1eSSven Peter return dev_err_probe(atcphy->dev, ret, "Probing rcdev failed"); 22378e98ca1eSSven Peter ret = atcphy_probe_mux(atcphy); 22388e98ca1eSSven Peter if (ret) 22398e98ca1eSSven Peter return dev_err_probe(atcphy->dev, ret, "Probing mux failed"); 22408e98ca1eSSven Peter ret = atcphy_probe_switch(atcphy); 22418e98ca1eSSven Peter if (ret) 22428e98ca1eSSven Peter return dev_err_probe(atcphy->dev, ret, "Probing switch failed"); 22438e98ca1eSSven Peter ret = atcphy_probe_phy(atcphy); 22448e98ca1eSSven Peter if (ret) 22458e98ca1eSSven Peter return dev_err_probe(atcphy->dev, ret, "Probing phy failed"); 22468e98ca1eSSven Peter 22478e98ca1eSSven Peter return 0; 22488e98ca1eSSven Peter } 22498e98ca1eSSven Peter 22508e98ca1eSSven Peter static int atcphy_probe(struct platform_device *pdev) 22518e98ca1eSSven Peter { 22528e98ca1eSSven Peter struct apple_atcphy *atcphy; 22538e98ca1eSSven Peter struct device *dev = &pdev->dev; 22548e98ca1eSSven Peter int ret; 22558e98ca1eSSven Peter 22568e98ca1eSSven Peter atcphy = devm_kzalloc(&pdev->dev, sizeof(*atcphy), GFP_KERNEL); 22578e98ca1eSSven Peter if (!atcphy) 22588e98ca1eSSven Peter return -ENOMEM; 22598e98ca1eSSven Peter 22608e98ca1eSSven Peter atcphy->dev = dev; 22618e98ca1eSSven Peter atcphy->np = dev->of_node; 22628e98ca1eSSven Peter mutex_init(&atcphy->lock); 22638e98ca1eSSven Peter platform_set_drvdata(pdev, atcphy); 22648e98ca1eSSven Peter 22658e98ca1eSSven Peter ret = atcphy_map_resources(pdev, atcphy); 22668e98ca1eSSven Peter if (ret) 22678e98ca1eSSven Peter return ret; 22688e98ca1eSSven Peter ret = atcphy_load_tunables(atcphy); 22698e98ca1eSSven Peter if (ret) 22708e98ca1eSSven Peter return ret; 22718e98ca1eSSven Peter 22728e98ca1eSSven Peter atcphy->mode = APPLE_ATCPHY_MODE_OFF; 22738e98ca1eSSven Peter atcphy->pipehandler_up = false; 22748e98ca1eSSven Peter 22758e98ca1eSSven Peter return atcphy_probe_finalize(atcphy); 22768e98ca1eSSven Peter } 22778e98ca1eSSven Peter 22788e98ca1eSSven Peter static const struct of_device_id atcphy_match[] = { 22798e98ca1eSSven Peter { .compatible = "apple,t8103-atcphy" }, 22808e98ca1eSSven Peter {}, 22818e98ca1eSSven Peter }; 22828e98ca1eSSven Peter MODULE_DEVICE_TABLE(of, atcphy_match); 22838e98ca1eSSven Peter 22848e98ca1eSSven Peter static struct platform_driver atcphy_driver = { 22858e98ca1eSSven Peter .driver = { 22868e98ca1eSSven Peter .name = "phy-apple-atc", 22878e98ca1eSSven Peter .of_match_table = atcphy_match, 22888e98ca1eSSven Peter }, 22898e98ca1eSSven Peter .probe = atcphy_probe, 22908e98ca1eSSven Peter }; 22918e98ca1eSSven Peter module_platform_driver(atcphy_driver); 22928e98ca1eSSven Peter 22938e98ca1eSSven Peter MODULE_AUTHOR("Sven Peter <sven@kernel.org>"); 22948e98ca1eSSven Peter MODULE_DESCRIPTION("Apple Type-C PHY driver"); 22958e98ca1eSSven Peter MODULE_LICENSE("GPL"); 2296