xref: /linux/drivers/phy/apple/atc.c (revision 9b725d5959a1d9bb670ccdb23add45f0eaafefb5)
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