18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/delay.h>
78c2ecf20Sopenharmony_ci#include <linux/io.h>
88c2ecf20Sopenharmony_ci#include <linux/mailbox_client.h>
98c2ecf20Sopenharmony_ci#include <linux/module.h>
108c2ecf20Sopenharmony_ci#include <linux/of.h>
118c2ecf20Sopenharmony_ci#include <linux/phy/phy.h>
128c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
138c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h>
148c2ecf20Sopenharmony_ci#include <linux/reset.h>
158c2ecf20Sopenharmony_ci#include <linux/slab.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include <soc/tegra/fuse.h>
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#include "xusb.h"
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#define FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(x) ((x) ? 15 : 0)
228c2ecf20Sopenharmony_ci#define FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK 0x3f
238c2ecf20Sopenharmony_ci#define FUSE_SKU_CALIB_HS_IREF_CAP_SHIFT 13
248c2ecf20Sopenharmony_ci#define FUSE_SKU_CALIB_HS_IREF_CAP_MASK 0x3
258c2ecf20Sopenharmony_ci#define FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_SHIFT 11
268c2ecf20Sopenharmony_ci#define FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_MASK 0x3
278c2ecf20Sopenharmony_ci#define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT 7
288c2ecf20Sopenharmony_ci#define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK 0xf
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP 0x008
318c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(x) ((x) * 4)
328c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_PORT_CAP_MASK 0x3
338c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_DISABLED 0x0
348c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_HOST 0x1
358c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_DEVICE 0x2
368c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_OTG 0x3
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP 0x014
398c2ecf20Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(x) (1 << (((x) * 4) + 3))
408c2ecf20Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_SHIFT(x) ((x) * 4)
418c2ecf20Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(x) (0x7 << ((x) * 4))
428c2ecf20Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(x, v) (((v) & 0x7) << ((x) * 4))
438c2ecf20Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORT_MAP_MASK 0x7
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM 0x01c
468c2ecf20Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26)
478c2ecf20Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25)
488c2ecf20Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24)
498c2ecf20Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(x) (1 << (18 + (x) * 4))
508c2ecf20Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(x) \
518c2ecf20Sopenharmony_ci							(1 << (17 + (x) * 4))
528c2ecf20Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(x) (1 << (16 + (x) * 4))
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040
558c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19)
568c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12)
578c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1)
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044
608c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6)
618c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5)
628c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4)
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(x) (0x058 + (x) * 4)
658c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT 24
668c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_MASK 0xff
678c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_VAL 0x24
688c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT 16
698c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK 0x3f
708c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT 8
718c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK 0x3f
728c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT 8
738c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_MASK 0xffff
748c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_VAL 0xf070
758c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT 4
768c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_MASK 0xf
778c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_VAL 0xf
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(x) (0x068 + (x) * 4)
808c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT 24
818c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK 0x1f
828c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT 16
838c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK 0x7f
848c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_VAL 0x002008ee
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL2(x) ((x) < 2 ? 0x078 + (x) * 4 : \
878c2ecf20Sopenharmony_ci					       0x0f8 + (x) * 4)
888c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT 28
898c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_MASK 0x3
908c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_VAL 0x1
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL5(x) ((x) < 2 ? 0x090 + (x) * 4 : \
938c2ecf20Sopenharmony_ci					       0x11c + (x) * 4)
948c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL5_RX_QEYE_EN (1 << 8)
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL6(x) ((x) < 2 ? 0x098 + (x) * 4 : \
978c2ecf20Sopenharmony_ci					       0x128 + (x) * 4)
988c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT 24
998c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK 0x3f
1008c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_TAP_MASK 0x1f
1018c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_AMP_MASK 0x7f
1028c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT 16
1038c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK 0xff
1048c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_G_Z 0x21
1058c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_TAP 0x32
1068c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_AMP 0x33
1078c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_CTLE_Z 0x48
1088c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_LATCH_G_Z 0xa1
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PADX_CTL0(x) (0x0a0 + (x) * 4)
1118c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI (1 << 21)
1128c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 (1 << 20)
1138c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD (1 << 19)
1148c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT 14
1158c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_MASK 0x3
1168c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_VAL(x) ((x) ? 0x0 : 0x3)
1178c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT 6
1188c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_MASK 0x3f
1198c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_VAL 0x0e
1208c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT 0
1218c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK 0x3f
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PADX_CTL1(x) (0x0ac + (x) * 4)
1248c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT 9
1258c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_MASK 0x3
1268c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT 3
1278c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK 0x7
1288c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR (1 << 2)
1298c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP (1 << 1)
1308c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP (1 << 0)
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0 0x0b8
1338c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD (1 << 12)
1348c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT 2
1358c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK 0x7
1368c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL 0x5
1378c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT 0
1388c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK 0x3
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PADX_CTL0(x) (0x0c0 + (x) * 4)
1418c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT 12
1428c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_MASK 0x7
1438c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT 8
1448c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_MASK 0x7
1458c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT 4
1468c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_MASK 0x7
1478c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT 0
1488c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_MASK 0x7
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PADX_CTL1(x) (0x0c8 + (x) * 4)
1518c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE (1 << 10)
1528c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_RPU_DATA (1 << 9)
1538c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_RPD_STROBE (1 << 8)
1548c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA (1 << 7)
1558c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI (1 << 5)
1568c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX (1 << 4)
1578c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX (1 << 3)
1588c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX (1 << 2)
1598c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN (1 << 0)
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PADX_CTL2(x) (0x0d0 + (x) * 4)
1628c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT 4
1638c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK 0x7
1648c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT 0
1658c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK 0x7
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL 0x0e0
1688c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL_STRB_TRIM_MASK 0x1f
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB3_PAD_MUX 0x134
1718c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(x) (1 << (1 + (x)))
1728c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(x) (1 << (6 + (x)))
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138
1758c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27)
1768c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24)
1778c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT 20
1788c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_MASK 0x3
1798c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3)
1808c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1)
1818c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0)
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2 0x13c
1848c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT 20
1858c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_MASK 0xf
1868c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT 16
1878c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_MASK 0xf
1888c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TCLKOUT_EN (1 << 12)
1898c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TXCLKREF_SEL (1 << 4)
1908c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT 0
1918c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_MASK 0x7
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL3 0x140
1948c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL3_RCAL_BYPASS (1 << 7)
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148
1978c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1)
1988c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0)
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2 0x14c
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5 0x158
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6 0x15c
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_cistruct tegra124_xusb_fuse_calibration {
2078c2ecf20Sopenharmony_ci	u32 hs_curr_level[3];
2088c2ecf20Sopenharmony_ci	u32 hs_iref_cap;
2098c2ecf20Sopenharmony_ci	u32 hs_term_range_adj;
2108c2ecf20Sopenharmony_ci	u32 hs_squelch_level;
2118c2ecf20Sopenharmony_ci};
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_cistruct tegra124_xusb_padctl {
2148c2ecf20Sopenharmony_ci	struct tegra_xusb_padctl base;
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	struct tegra124_xusb_fuse_calibration fuse;
2178c2ecf20Sopenharmony_ci};
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_cistatic inline struct tegra124_xusb_padctl *
2208c2ecf20Sopenharmony_cito_tegra124_xusb_padctl(struct tegra_xusb_padctl *padctl)
2218c2ecf20Sopenharmony_ci{
2228c2ecf20Sopenharmony_ci	return container_of(padctl, struct tegra124_xusb_padctl, base);
2238c2ecf20Sopenharmony_ci}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_cistatic int tegra124_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
2268c2ecf20Sopenharmony_ci{
2278c2ecf20Sopenharmony_ci	u32 value;
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	mutex_lock(&padctl->lock);
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	if (padctl->enable++ > 0)
2328c2ecf20Sopenharmony_ci		goto out;
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
2358c2ecf20Sopenharmony_ci	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
2368c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	usleep_range(100, 200);
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
2418c2ecf20Sopenharmony_ci	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
2428c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	usleep_range(100, 200);
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
2478c2ecf20Sopenharmony_ci	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
2488c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ciout:
2518c2ecf20Sopenharmony_ci	mutex_unlock(&padctl->lock);
2528c2ecf20Sopenharmony_ci	return 0;
2538c2ecf20Sopenharmony_ci}
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_cistatic int tegra124_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
2568c2ecf20Sopenharmony_ci{
2578c2ecf20Sopenharmony_ci	u32 value;
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	mutex_lock(&padctl->lock);
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	if (WARN_ON(padctl->enable == 0))
2628c2ecf20Sopenharmony_ci		goto out;
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	if (--padctl->enable > 0)
2658c2ecf20Sopenharmony_ci		goto out;
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
2688c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
2698c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	usleep_range(100, 200);
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
2748c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
2758c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	usleep_range(100, 200);
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
2808c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
2818c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ciout:
2848c2ecf20Sopenharmony_ci	mutex_unlock(&padctl->lock);
2858c2ecf20Sopenharmony_ci	return 0;
2868c2ecf20Sopenharmony_ci}
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_cistatic int tegra124_usb3_save_context(struct tegra_xusb_padctl *padctl,
2898c2ecf20Sopenharmony_ci				      unsigned int index)
2908c2ecf20Sopenharmony_ci{
2918c2ecf20Sopenharmony_ci	struct tegra_xusb_usb3_port *port;
2928c2ecf20Sopenharmony_ci	struct tegra_xusb_lane *lane;
2938c2ecf20Sopenharmony_ci	u32 value, offset;
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	port = tegra_xusb_find_usb3_port(padctl, index);
2968c2ecf20Sopenharmony_ci	if (!port)
2978c2ecf20Sopenharmony_ci		return -ENODEV;
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	port->context_saved = true;
3008c2ecf20Sopenharmony_ci	lane = port->base.lane;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	if (lane->pad == padctl->pcie)
3038c2ecf20Sopenharmony_ci		offset = XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL6(lane->index);
3048c2ecf20Sopenharmony_ci	else
3058c2ecf20Sopenharmony_ci		offset = XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6;
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, offset);
3088c2ecf20Sopenharmony_ci	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK <<
3098c2ecf20Sopenharmony_ci		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT);
3108c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_TAP <<
3118c2ecf20Sopenharmony_ci		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT;
3128c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, offset);
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, offset) >>
3158c2ecf20Sopenharmony_ci		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT;
3168c2ecf20Sopenharmony_ci	port->tap1 = value & XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_TAP_MASK;
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, offset);
3198c2ecf20Sopenharmony_ci	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK <<
3208c2ecf20Sopenharmony_ci		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT);
3218c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_AMP <<
3228c2ecf20Sopenharmony_ci		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT;
3238c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, offset);
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, offset) >>
3268c2ecf20Sopenharmony_ci		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT;
3278c2ecf20Sopenharmony_ci	port->amp = value & XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_AMP_MASK;
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(index));
3308c2ecf20Sopenharmony_ci	value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK <<
3318c2ecf20Sopenharmony_ci		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) |
3328c2ecf20Sopenharmony_ci		   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK <<
3338c2ecf20Sopenharmony_ci		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT));
3348c2ecf20Sopenharmony_ci	value |= (port->tap1 <<
3358c2ecf20Sopenharmony_ci		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) |
3368c2ecf20Sopenharmony_ci		 (port->amp <<
3378c2ecf20Sopenharmony_ci		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT);
3388c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(index));
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, offset);
3418c2ecf20Sopenharmony_ci	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK <<
3428c2ecf20Sopenharmony_ci		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT);
3438c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_LATCH_G_Z <<
3448c2ecf20Sopenharmony_ci		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT;
3458c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, offset);
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, offset);
3488c2ecf20Sopenharmony_ci	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK <<
3498c2ecf20Sopenharmony_ci		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT);
3508c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_G_Z <<
3518c2ecf20Sopenharmony_ci		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT;
3528c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, offset);
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, offset) >>
3558c2ecf20Sopenharmony_ci		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT;
3568c2ecf20Sopenharmony_ci	port->ctle_g = value &
3578c2ecf20Sopenharmony_ci		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK;
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, offset);
3608c2ecf20Sopenharmony_ci	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK <<
3618c2ecf20Sopenharmony_ci		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT);
3628c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_CTLE_Z <<
3638c2ecf20Sopenharmony_ci		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT;
3648c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, offset);
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, offset) >>
3678c2ecf20Sopenharmony_ci		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT;
3688c2ecf20Sopenharmony_ci	port->ctle_z = value &
3698c2ecf20Sopenharmony_ci		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK;
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index));
3728c2ecf20Sopenharmony_ci	value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK <<
3738c2ecf20Sopenharmony_ci		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) |
3748c2ecf20Sopenharmony_ci		   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK <<
3758c2ecf20Sopenharmony_ci		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT));
3768c2ecf20Sopenharmony_ci	value |= (port->ctle_g <<
3778c2ecf20Sopenharmony_ci		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) |
3788c2ecf20Sopenharmony_ci		 (port->ctle_z <<
3798c2ecf20Sopenharmony_ci		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT);
3808c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index));
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	return 0;
3838c2ecf20Sopenharmony_ci}
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_cistatic int tegra124_hsic_set_idle(struct tegra_xusb_padctl *padctl,
3868c2ecf20Sopenharmony_ci				  unsigned int index, bool idle)
3878c2ecf20Sopenharmony_ci{
3888c2ecf20Sopenharmony_ci	u32 value;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index));
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	if (idle)
3938c2ecf20Sopenharmony_ci		value |= XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA |
3948c2ecf20Sopenharmony_ci			 XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE;
3958c2ecf20Sopenharmony_ci	else
3968c2ecf20Sopenharmony_ci		value &= ~(XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA |
3978c2ecf20Sopenharmony_ci			   XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE);
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index));
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	return 0;
4028c2ecf20Sopenharmony_ci}
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci#define TEGRA124_LANE(_name, _offset, _shift, _mask, _type)		\
4058c2ecf20Sopenharmony_ci	{								\
4068c2ecf20Sopenharmony_ci		.name = _name,						\
4078c2ecf20Sopenharmony_ci		.offset = _offset,					\
4088c2ecf20Sopenharmony_ci		.shift = _shift,					\
4098c2ecf20Sopenharmony_ci		.mask = _mask,						\
4108c2ecf20Sopenharmony_ci		.num_funcs = ARRAY_SIZE(tegra124_##_type##_functions),	\
4118c2ecf20Sopenharmony_ci		.funcs = tegra124_##_type##_functions,			\
4128c2ecf20Sopenharmony_ci	}
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_cistatic const char * const tegra124_usb2_functions[] = {
4158c2ecf20Sopenharmony_ci	"snps",
4168c2ecf20Sopenharmony_ci	"xusb",
4178c2ecf20Sopenharmony_ci	"uart",
4188c2ecf20Sopenharmony_ci};
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra124_usb2_lanes[] = {
4218c2ecf20Sopenharmony_ci	TEGRA124_LANE("usb2-0", 0x004,  0, 0x3, usb2),
4228c2ecf20Sopenharmony_ci	TEGRA124_LANE("usb2-1", 0x004,  2, 0x3, usb2),
4238c2ecf20Sopenharmony_ci	TEGRA124_LANE("usb2-2", 0x004,  4, 0x3, usb2),
4248c2ecf20Sopenharmony_ci};
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_cistatic struct tegra_xusb_lane *
4278c2ecf20Sopenharmony_citegra124_usb2_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np,
4288c2ecf20Sopenharmony_ci			 unsigned int index)
4298c2ecf20Sopenharmony_ci{
4308c2ecf20Sopenharmony_ci	struct tegra_xusb_usb2_lane *usb2;
4318c2ecf20Sopenharmony_ci	int err;
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL);
4348c2ecf20Sopenharmony_ci	if (!usb2)
4358c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&usb2->base.list);
4388c2ecf20Sopenharmony_ci	usb2->base.soc = &pad->soc->lanes[index];
4398c2ecf20Sopenharmony_ci	usb2->base.index = index;
4408c2ecf20Sopenharmony_ci	usb2->base.pad = pad;
4418c2ecf20Sopenharmony_ci	usb2->base.np = np;
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	err = tegra_xusb_lane_parse_dt(&usb2->base, np);
4448c2ecf20Sopenharmony_ci	if (err < 0) {
4458c2ecf20Sopenharmony_ci		kfree(usb2);
4468c2ecf20Sopenharmony_ci		return ERR_PTR(err);
4478c2ecf20Sopenharmony_ci	}
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci	return &usb2->base;
4508c2ecf20Sopenharmony_ci}
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_cistatic void tegra124_usb2_lane_remove(struct tegra_xusb_lane *lane)
4538c2ecf20Sopenharmony_ci{
4548c2ecf20Sopenharmony_ci	struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane);
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	kfree(usb2);
4578c2ecf20Sopenharmony_ci}
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra124_usb2_lane_ops = {
4608c2ecf20Sopenharmony_ci	.probe = tegra124_usb2_lane_probe,
4618c2ecf20Sopenharmony_ci	.remove = tegra124_usb2_lane_remove,
4628c2ecf20Sopenharmony_ci};
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_cistatic int tegra124_usb2_phy_init(struct phy *phy)
4658c2ecf20Sopenharmony_ci{
4668c2ecf20Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	return tegra124_xusb_padctl_enable(lane->pad->padctl);
4698c2ecf20Sopenharmony_ci}
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_cistatic int tegra124_usb2_phy_exit(struct phy *phy)
4728c2ecf20Sopenharmony_ci{
4738c2ecf20Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	return tegra124_xusb_padctl_disable(lane->pad->padctl);
4768c2ecf20Sopenharmony_ci}
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_cistatic int tegra124_usb2_phy_power_on(struct phy *phy)
4798c2ecf20Sopenharmony_ci{
4808c2ecf20Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
4818c2ecf20Sopenharmony_ci	struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane);
4828c2ecf20Sopenharmony_ci	struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad);
4838c2ecf20Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
4848c2ecf20Sopenharmony_ci	struct tegra124_xusb_padctl *priv;
4858c2ecf20Sopenharmony_ci	struct tegra_xusb_usb2_port *port;
4868c2ecf20Sopenharmony_ci	unsigned int index = lane->index;
4878c2ecf20Sopenharmony_ci	u32 value;
4888c2ecf20Sopenharmony_ci	int err;
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	port = tegra_xusb_find_usb2_port(padctl, index);
4918c2ecf20Sopenharmony_ci	if (!port) {
4928c2ecf20Sopenharmony_ci		dev_err(&phy->dev, "no port found for USB2 lane %u\n", index);
4938c2ecf20Sopenharmony_ci		return -ENODEV;
4948c2ecf20Sopenharmony_ci	}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	priv = to_tegra124_xusb_padctl(padctl);
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
4998c2ecf20Sopenharmony_ci	value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK <<
5008c2ecf20Sopenharmony_ci		    XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) |
5018c2ecf20Sopenharmony_ci		   (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK <<
5028c2ecf20Sopenharmony_ci		    XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT));
5038c2ecf20Sopenharmony_ci	value |= (priv->fuse.hs_squelch_level <<
5048c2ecf20Sopenharmony_ci		  XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) |
5058c2ecf20Sopenharmony_ci		 (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL <<
5068c2ecf20Sopenharmony_ci		  XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT);
5078c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB2_PORT_CAP);
5108c2ecf20Sopenharmony_ci	value &= ~(XUSB_PADCTL_USB2_PORT_CAP_PORT_CAP_MASK <<
5118c2ecf20Sopenharmony_ci		   XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(index));
5128c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_USB2_PORT_CAP_HOST <<
5138c2ecf20Sopenharmony_ci		XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(index);
5148c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB2_PORT_CAP);
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index));
5178c2ecf20Sopenharmony_ci	value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK <<
5188c2ecf20Sopenharmony_ci		    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT) |
5198c2ecf20Sopenharmony_ci		   (XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_MASK <<
5208c2ecf20Sopenharmony_ci		    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT) |
5218c2ecf20Sopenharmony_ci		   (XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_MASK <<
5228c2ecf20Sopenharmony_ci		    XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT) |
5238c2ecf20Sopenharmony_ci		   XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD |
5248c2ecf20Sopenharmony_ci		   XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 |
5258c2ecf20Sopenharmony_ci		   XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI);
5268c2ecf20Sopenharmony_ci	value |= (priv->fuse.hs_curr_level[index] +
5278c2ecf20Sopenharmony_ci		  usb2->hs_curr_level_offset) <<
5288c2ecf20Sopenharmony_ci		XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT;
5298c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_VAL <<
5308c2ecf20Sopenharmony_ci		XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT;
5318c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_VAL(index) <<
5328c2ecf20Sopenharmony_ci		XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT;
5338c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index));
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index));
5368c2ecf20Sopenharmony_ci	value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK <<
5378c2ecf20Sopenharmony_ci		    XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) |
5388c2ecf20Sopenharmony_ci		   (XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_MASK <<
5398c2ecf20Sopenharmony_ci		    XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT) |
5408c2ecf20Sopenharmony_ci		   XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR |
5418c2ecf20Sopenharmony_ci		   XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP |
5428c2ecf20Sopenharmony_ci		   XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP);
5438c2ecf20Sopenharmony_ci	value |= (priv->fuse.hs_term_range_adj <<
5448c2ecf20Sopenharmony_ci		  XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) |
5458c2ecf20Sopenharmony_ci		 (priv->fuse.hs_iref_cap <<
5468c2ecf20Sopenharmony_ci		  XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT);
5478c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index));
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	err = regulator_enable(port->supply);
5508c2ecf20Sopenharmony_ci	if (err)
5518c2ecf20Sopenharmony_ci		return err;
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	mutex_lock(&pad->lock);
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci	if (pad->enable++ > 0)
5568c2ecf20Sopenharmony_ci		goto out;
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
5598c2ecf20Sopenharmony_ci	value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD;
5608c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ciout:
5638c2ecf20Sopenharmony_ci	mutex_unlock(&pad->lock);
5648c2ecf20Sopenharmony_ci	return 0;
5658c2ecf20Sopenharmony_ci}
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_cistatic int tegra124_usb2_phy_power_off(struct phy *phy)
5688c2ecf20Sopenharmony_ci{
5698c2ecf20Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
5708c2ecf20Sopenharmony_ci	struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad);
5718c2ecf20Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
5728c2ecf20Sopenharmony_ci	struct tegra_xusb_usb2_port *port;
5738c2ecf20Sopenharmony_ci	u32 value;
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	port = tegra_xusb_find_usb2_port(padctl, lane->index);
5768c2ecf20Sopenharmony_ci	if (!port) {
5778c2ecf20Sopenharmony_ci		dev_err(&phy->dev, "no port found for USB2 lane %u\n",
5788c2ecf20Sopenharmony_ci			lane->index);
5798c2ecf20Sopenharmony_ci		return -ENODEV;
5808c2ecf20Sopenharmony_ci	}
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci	mutex_lock(&pad->lock);
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	if (WARN_ON(pad->enable == 0))
5858c2ecf20Sopenharmony_ci		goto out;
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci	if (--pad->enable > 0)
5888c2ecf20Sopenharmony_ci		goto out;
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
5918c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD;
5928c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ciout:
5958c2ecf20Sopenharmony_ci	regulator_disable(port->supply);
5968c2ecf20Sopenharmony_ci	mutex_unlock(&pad->lock);
5978c2ecf20Sopenharmony_ci	return 0;
5988c2ecf20Sopenharmony_ci}
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_cistatic const struct phy_ops tegra124_usb2_phy_ops = {
6018c2ecf20Sopenharmony_ci	.init = tegra124_usb2_phy_init,
6028c2ecf20Sopenharmony_ci	.exit = tegra124_usb2_phy_exit,
6038c2ecf20Sopenharmony_ci	.power_on = tegra124_usb2_phy_power_on,
6048c2ecf20Sopenharmony_ci	.power_off = tegra124_usb2_phy_power_off,
6058c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
6068c2ecf20Sopenharmony_ci};
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_cistatic struct tegra_xusb_pad *
6098c2ecf20Sopenharmony_citegra124_usb2_pad_probe(struct tegra_xusb_padctl *padctl,
6108c2ecf20Sopenharmony_ci			const struct tegra_xusb_pad_soc *soc,
6118c2ecf20Sopenharmony_ci			struct device_node *np)
6128c2ecf20Sopenharmony_ci{
6138c2ecf20Sopenharmony_ci	struct tegra_xusb_usb2_pad *usb2;
6148c2ecf20Sopenharmony_ci	struct tegra_xusb_pad *pad;
6158c2ecf20Sopenharmony_ci	int err;
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL);
6188c2ecf20Sopenharmony_ci	if (!usb2)
6198c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	mutex_init(&usb2->lock);
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci	pad = &usb2->base;
6248c2ecf20Sopenharmony_ci	pad->ops = &tegra124_usb2_lane_ops;
6258c2ecf20Sopenharmony_ci	pad->soc = soc;
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	err = tegra_xusb_pad_init(pad, padctl, np);
6288c2ecf20Sopenharmony_ci	if (err < 0) {
6298c2ecf20Sopenharmony_ci		kfree(usb2);
6308c2ecf20Sopenharmony_ci		goto out;
6318c2ecf20Sopenharmony_ci	}
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	err = tegra_xusb_pad_register(pad, &tegra124_usb2_phy_ops);
6348c2ecf20Sopenharmony_ci	if (err < 0)
6358c2ecf20Sopenharmony_ci		goto unregister;
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	dev_set_drvdata(&pad->dev, pad);
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_ci	return pad;
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ciunregister:
6428c2ecf20Sopenharmony_ci	device_unregister(&pad->dev);
6438c2ecf20Sopenharmony_ciout:
6448c2ecf20Sopenharmony_ci	return ERR_PTR(err);
6458c2ecf20Sopenharmony_ci}
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_cistatic void tegra124_usb2_pad_remove(struct tegra_xusb_pad *pad)
6488c2ecf20Sopenharmony_ci{
6498c2ecf20Sopenharmony_ci	struct tegra_xusb_usb2_pad *usb2 = to_usb2_pad(pad);
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	kfree(usb2);
6528c2ecf20Sopenharmony_ci}
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra124_usb2_ops = {
6558c2ecf20Sopenharmony_ci	.probe = tegra124_usb2_pad_probe,
6568c2ecf20Sopenharmony_ci	.remove = tegra124_usb2_pad_remove,
6578c2ecf20Sopenharmony_ci};
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra124_usb2_pad = {
6608c2ecf20Sopenharmony_ci	.name = "usb2",
6618c2ecf20Sopenharmony_ci	.num_lanes = ARRAY_SIZE(tegra124_usb2_lanes),
6628c2ecf20Sopenharmony_ci	.lanes = tegra124_usb2_lanes,
6638c2ecf20Sopenharmony_ci	.ops = &tegra124_usb2_ops,
6648c2ecf20Sopenharmony_ci};
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_cistatic const char * const tegra124_ulpi_functions[] = {
6678c2ecf20Sopenharmony_ci	"snps",
6688c2ecf20Sopenharmony_ci	"xusb",
6698c2ecf20Sopenharmony_ci};
6708c2ecf20Sopenharmony_ci
6718c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra124_ulpi_lanes[] = {
6728c2ecf20Sopenharmony_ci	TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, ulpi),
6738c2ecf20Sopenharmony_ci};
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_cistatic struct tegra_xusb_lane *
6768c2ecf20Sopenharmony_citegra124_ulpi_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np,
6778c2ecf20Sopenharmony_ci			 unsigned int index)
6788c2ecf20Sopenharmony_ci{
6798c2ecf20Sopenharmony_ci	struct tegra_xusb_ulpi_lane *ulpi;
6808c2ecf20Sopenharmony_ci	int err;
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci	ulpi = kzalloc(sizeof(*ulpi), GFP_KERNEL);
6838c2ecf20Sopenharmony_ci	if (!ulpi)
6848c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&ulpi->base.list);
6878c2ecf20Sopenharmony_ci	ulpi->base.soc = &pad->soc->lanes[index];
6888c2ecf20Sopenharmony_ci	ulpi->base.index = index;
6898c2ecf20Sopenharmony_ci	ulpi->base.pad = pad;
6908c2ecf20Sopenharmony_ci	ulpi->base.np = np;
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ci	err = tegra_xusb_lane_parse_dt(&ulpi->base, np);
6938c2ecf20Sopenharmony_ci	if (err < 0) {
6948c2ecf20Sopenharmony_ci		kfree(ulpi);
6958c2ecf20Sopenharmony_ci		return ERR_PTR(err);
6968c2ecf20Sopenharmony_ci	}
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci	return &ulpi->base;
6998c2ecf20Sopenharmony_ci}
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_cistatic void tegra124_ulpi_lane_remove(struct tegra_xusb_lane *lane)
7028c2ecf20Sopenharmony_ci{
7038c2ecf20Sopenharmony_ci	struct tegra_xusb_ulpi_lane *ulpi = to_ulpi_lane(lane);
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_ci	kfree(ulpi);
7068c2ecf20Sopenharmony_ci}
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra124_ulpi_lane_ops = {
7098c2ecf20Sopenharmony_ci	.probe = tegra124_ulpi_lane_probe,
7108c2ecf20Sopenharmony_ci	.remove = tegra124_ulpi_lane_remove,
7118c2ecf20Sopenharmony_ci};
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_cistatic int tegra124_ulpi_phy_init(struct phy *phy)
7148c2ecf20Sopenharmony_ci{
7158c2ecf20Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci	return tegra124_xusb_padctl_enable(lane->pad->padctl);
7188c2ecf20Sopenharmony_ci}
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_cistatic int tegra124_ulpi_phy_exit(struct phy *phy)
7218c2ecf20Sopenharmony_ci{
7228c2ecf20Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_ci	return tegra124_xusb_padctl_disable(lane->pad->padctl);
7258c2ecf20Sopenharmony_ci}
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_cistatic int tegra124_ulpi_phy_power_on(struct phy *phy)
7288c2ecf20Sopenharmony_ci{
7298c2ecf20Sopenharmony_ci	return 0;
7308c2ecf20Sopenharmony_ci}
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_cistatic int tegra124_ulpi_phy_power_off(struct phy *phy)
7338c2ecf20Sopenharmony_ci{
7348c2ecf20Sopenharmony_ci	return 0;
7358c2ecf20Sopenharmony_ci}
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_cistatic const struct phy_ops tegra124_ulpi_phy_ops = {
7388c2ecf20Sopenharmony_ci	.init = tegra124_ulpi_phy_init,
7398c2ecf20Sopenharmony_ci	.exit = tegra124_ulpi_phy_exit,
7408c2ecf20Sopenharmony_ci	.power_on = tegra124_ulpi_phy_power_on,
7418c2ecf20Sopenharmony_ci	.power_off = tegra124_ulpi_phy_power_off,
7428c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
7438c2ecf20Sopenharmony_ci};
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_cistatic struct tegra_xusb_pad *
7468c2ecf20Sopenharmony_citegra124_ulpi_pad_probe(struct tegra_xusb_padctl *padctl,
7478c2ecf20Sopenharmony_ci			const struct tegra_xusb_pad_soc *soc,
7488c2ecf20Sopenharmony_ci			struct device_node *np)
7498c2ecf20Sopenharmony_ci{
7508c2ecf20Sopenharmony_ci	struct tegra_xusb_ulpi_pad *ulpi;
7518c2ecf20Sopenharmony_ci	struct tegra_xusb_pad *pad;
7528c2ecf20Sopenharmony_ci	int err;
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci	ulpi = kzalloc(sizeof(*ulpi), GFP_KERNEL);
7558c2ecf20Sopenharmony_ci	if (!ulpi)
7568c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_ci	pad = &ulpi->base;
7598c2ecf20Sopenharmony_ci	pad->ops = &tegra124_ulpi_lane_ops;
7608c2ecf20Sopenharmony_ci	pad->soc = soc;
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci	err = tegra_xusb_pad_init(pad, padctl, np);
7638c2ecf20Sopenharmony_ci	if (err < 0) {
7648c2ecf20Sopenharmony_ci		kfree(ulpi);
7658c2ecf20Sopenharmony_ci		goto out;
7668c2ecf20Sopenharmony_ci	}
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci	err = tegra_xusb_pad_register(pad, &tegra124_ulpi_phy_ops);
7698c2ecf20Sopenharmony_ci	if (err < 0)
7708c2ecf20Sopenharmony_ci		goto unregister;
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_ci	dev_set_drvdata(&pad->dev, pad);
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci	return pad;
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_ciunregister:
7778c2ecf20Sopenharmony_ci	device_unregister(&pad->dev);
7788c2ecf20Sopenharmony_ciout:
7798c2ecf20Sopenharmony_ci	return ERR_PTR(err);
7808c2ecf20Sopenharmony_ci}
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_cistatic void tegra124_ulpi_pad_remove(struct tegra_xusb_pad *pad)
7838c2ecf20Sopenharmony_ci{
7848c2ecf20Sopenharmony_ci	struct tegra_xusb_ulpi_pad *ulpi = to_ulpi_pad(pad);
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_ci	kfree(ulpi);
7878c2ecf20Sopenharmony_ci}
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra124_ulpi_ops = {
7908c2ecf20Sopenharmony_ci	.probe = tegra124_ulpi_pad_probe,
7918c2ecf20Sopenharmony_ci	.remove = tegra124_ulpi_pad_remove,
7928c2ecf20Sopenharmony_ci};
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra124_ulpi_pad = {
7958c2ecf20Sopenharmony_ci	.name = "ulpi",
7968c2ecf20Sopenharmony_ci	.num_lanes = ARRAY_SIZE(tegra124_ulpi_lanes),
7978c2ecf20Sopenharmony_ci	.lanes = tegra124_ulpi_lanes,
7988c2ecf20Sopenharmony_ci	.ops = &tegra124_ulpi_ops,
7998c2ecf20Sopenharmony_ci};
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_cistatic const char * const tegra124_hsic_functions[] = {
8028c2ecf20Sopenharmony_ci	"snps",
8038c2ecf20Sopenharmony_ci	"xusb",
8048c2ecf20Sopenharmony_ci};
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra124_hsic_lanes[] = {
8078c2ecf20Sopenharmony_ci	TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, hsic),
8088c2ecf20Sopenharmony_ci	TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, hsic),
8098c2ecf20Sopenharmony_ci};
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_cistatic struct tegra_xusb_lane *
8128c2ecf20Sopenharmony_citegra124_hsic_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np,
8138c2ecf20Sopenharmony_ci			 unsigned int index)
8148c2ecf20Sopenharmony_ci{
8158c2ecf20Sopenharmony_ci	struct tegra_xusb_hsic_lane *hsic;
8168c2ecf20Sopenharmony_ci	int err;
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_ci	hsic = kzalloc(sizeof(*hsic), GFP_KERNEL);
8198c2ecf20Sopenharmony_ci	if (!hsic)
8208c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&hsic->base.list);
8238c2ecf20Sopenharmony_ci	hsic->base.soc = &pad->soc->lanes[index];
8248c2ecf20Sopenharmony_ci	hsic->base.index = index;
8258c2ecf20Sopenharmony_ci	hsic->base.pad = pad;
8268c2ecf20Sopenharmony_ci	hsic->base.np = np;
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_ci	err = tegra_xusb_lane_parse_dt(&hsic->base, np);
8298c2ecf20Sopenharmony_ci	if (err < 0) {
8308c2ecf20Sopenharmony_ci		kfree(hsic);
8318c2ecf20Sopenharmony_ci		return ERR_PTR(err);
8328c2ecf20Sopenharmony_ci	}
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_ci	return &hsic->base;
8358c2ecf20Sopenharmony_ci}
8368c2ecf20Sopenharmony_ci
8378c2ecf20Sopenharmony_cistatic void tegra124_hsic_lane_remove(struct tegra_xusb_lane *lane)
8388c2ecf20Sopenharmony_ci{
8398c2ecf20Sopenharmony_ci	struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane);
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci	kfree(hsic);
8428c2ecf20Sopenharmony_ci}
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra124_hsic_lane_ops = {
8458c2ecf20Sopenharmony_ci	.probe = tegra124_hsic_lane_probe,
8468c2ecf20Sopenharmony_ci	.remove = tegra124_hsic_lane_remove,
8478c2ecf20Sopenharmony_ci};
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_cistatic int tegra124_hsic_phy_init(struct phy *phy)
8508c2ecf20Sopenharmony_ci{
8518c2ecf20Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_ci	return tegra124_xusb_padctl_enable(lane->pad->padctl);
8548c2ecf20Sopenharmony_ci}
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_cistatic int tegra124_hsic_phy_exit(struct phy *phy)
8578c2ecf20Sopenharmony_ci{
8588c2ecf20Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci	return tegra124_xusb_padctl_disable(lane->pad->padctl);
8618c2ecf20Sopenharmony_ci}
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_cistatic int tegra124_hsic_phy_power_on(struct phy *phy)
8648c2ecf20Sopenharmony_ci{
8658c2ecf20Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
8668c2ecf20Sopenharmony_ci	struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane);
8678c2ecf20Sopenharmony_ci	struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad);
8688c2ecf20Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
8698c2ecf20Sopenharmony_ci	unsigned int index = lane->index;
8708c2ecf20Sopenharmony_ci	u32 value;
8718c2ecf20Sopenharmony_ci	int err;
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_ci	err = regulator_enable(pad->supply);
8748c2ecf20Sopenharmony_ci	if (err)
8758c2ecf20Sopenharmony_ci		return err;
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	padctl_writel(padctl, hsic->strobe_trim,
8788c2ecf20Sopenharmony_ci		      XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL);
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index));
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci	if (hsic->auto_term)
8838c2ecf20Sopenharmony_ci		value |= XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN;
8848c2ecf20Sopenharmony_ci	else
8858c2ecf20Sopenharmony_ci		value &= ~XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN;
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index));
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(index));
8908c2ecf20Sopenharmony_ci	value &= ~((XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_MASK <<
8918c2ecf20Sopenharmony_ci		    XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT) |
8928c2ecf20Sopenharmony_ci		   (XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_MASK <<
8938c2ecf20Sopenharmony_ci		    XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT) |
8948c2ecf20Sopenharmony_ci		   (XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_MASK <<
8958c2ecf20Sopenharmony_ci		    XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT) |
8968c2ecf20Sopenharmony_ci		   (XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_MASK <<
8978c2ecf20Sopenharmony_ci		    XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT));
8988c2ecf20Sopenharmony_ci	value |= (hsic->tx_rtune_n <<
8998c2ecf20Sopenharmony_ci		  XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT) |
9008c2ecf20Sopenharmony_ci		(hsic->tx_rtune_p <<
9018c2ecf20Sopenharmony_ci		  XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT) |
9028c2ecf20Sopenharmony_ci		(hsic->tx_rslew_n <<
9038c2ecf20Sopenharmony_ci		 XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT) |
9048c2ecf20Sopenharmony_ci		(hsic->tx_rslew_p <<
9058c2ecf20Sopenharmony_ci		 XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT);
9068c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL0(index));
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL2(index));
9098c2ecf20Sopenharmony_ci	value &= ~((XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK <<
9108c2ecf20Sopenharmony_ci		    XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) |
9118c2ecf20Sopenharmony_ci		   (XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK <<
9128c2ecf20Sopenharmony_ci		    XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT));
9138c2ecf20Sopenharmony_ci	value |= (hsic->rx_strobe_trim <<
9148c2ecf20Sopenharmony_ci		  XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) |
9158c2ecf20Sopenharmony_ci		(hsic->rx_data_trim <<
9168c2ecf20Sopenharmony_ci		 XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT);
9178c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL2(index));
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index));
9208c2ecf20Sopenharmony_ci	value &= ~(XUSB_PADCTL_HSIC_PAD_CTL1_RPD_STROBE |
9218c2ecf20Sopenharmony_ci		   XUSB_PADCTL_HSIC_PAD_CTL1_RPU_DATA |
9228c2ecf20Sopenharmony_ci		   XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX |
9238c2ecf20Sopenharmony_ci		   XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI |
9248c2ecf20Sopenharmony_ci		   XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX |
9258c2ecf20Sopenharmony_ci		   XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX);
9268c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA |
9278c2ecf20Sopenharmony_ci		 XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE;
9288c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index));
9298c2ecf20Sopenharmony_ci
9308c2ecf20Sopenharmony_ci	return 0;
9318c2ecf20Sopenharmony_ci}
9328c2ecf20Sopenharmony_ci
9338c2ecf20Sopenharmony_cistatic int tegra124_hsic_phy_power_off(struct phy *phy)
9348c2ecf20Sopenharmony_ci{
9358c2ecf20Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
9368c2ecf20Sopenharmony_ci	struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad);
9378c2ecf20Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
9388c2ecf20Sopenharmony_ci	unsigned int index = lane->index;
9398c2ecf20Sopenharmony_ci	u32 value;
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index));
9428c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX |
9438c2ecf20Sopenharmony_ci		 XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI |
9448c2ecf20Sopenharmony_ci		 XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX |
9458c2ecf20Sopenharmony_ci		 XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX;
9468c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index));
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_ci	regulator_disable(pad->supply);
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_ci	return 0;
9518c2ecf20Sopenharmony_ci}
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_cistatic const struct phy_ops tegra124_hsic_phy_ops = {
9548c2ecf20Sopenharmony_ci	.init = tegra124_hsic_phy_init,
9558c2ecf20Sopenharmony_ci	.exit = tegra124_hsic_phy_exit,
9568c2ecf20Sopenharmony_ci	.power_on = tegra124_hsic_phy_power_on,
9578c2ecf20Sopenharmony_ci	.power_off = tegra124_hsic_phy_power_off,
9588c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
9598c2ecf20Sopenharmony_ci};
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_cistatic struct tegra_xusb_pad *
9628c2ecf20Sopenharmony_citegra124_hsic_pad_probe(struct tegra_xusb_padctl *padctl,
9638c2ecf20Sopenharmony_ci			const struct tegra_xusb_pad_soc *soc,
9648c2ecf20Sopenharmony_ci			struct device_node *np)
9658c2ecf20Sopenharmony_ci{
9668c2ecf20Sopenharmony_ci	struct tegra_xusb_hsic_pad *hsic;
9678c2ecf20Sopenharmony_ci	struct tegra_xusb_pad *pad;
9688c2ecf20Sopenharmony_ci	int err;
9698c2ecf20Sopenharmony_ci
9708c2ecf20Sopenharmony_ci	hsic = kzalloc(sizeof(*hsic), GFP_KERNEL);
9718c2ecf20Sopenharmony_ci	if (!hsic)
9728c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci	pad = &hsic->base;
9758c2ecf20Sopenharmony_ci	pad->ops = &tegra124_hsic_lane_ops;
9768c2ecf20Sopenharmony_ci	pad->soc = soc;
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_ci	err = tegra_xusb_pad_init(pad, padctl, np);
9798c2ecf20Sopenharmony_ci	if (err < 0) {
9808c2ecf20Sopenharmony_ci		kfree(hsic);
9818c2ecf20Sopenharmony_ci		goto out;
9828c2ecf20Sopenharmony_ci	}
9838c2ecf20Sopenharmony_ci
9848c2ecf20Sopenharmony_ci	err = tegra_xusb_pad_register(pad, &tegra124_hsic_phy_ops);
9858c2ecf20Sopenharmony_ci	if (err < 0)
9868c2ecf20Sopenharmony_ci		goto unregister;
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_ci	dev_set_drvdata(&pad->dev, pad);
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_ci	return pad;
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ciunregister:
9938c2ecf20Sopenharmony_ci	device_unregister(&pad->dev);
9948c2ecf20Sopenharmony_ciout:
9958c2ecf20Sopenharmony_ci	return ERR_PTR(err);
9968c2ecf20Sopenharmony_ci}
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_cistatic void tegra124_hsic_pad_remove(struct tegra_xusb_pad *pad)
9998c2ecf20Sopenharmony_ci{
10008c2ecf20Sopenharmony_ci	struct tegra_xusb_hsic_pad *hsic = to_hsic_pad(pad);
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_ci	kfree(hsic);
10038c2ecf20Sopenharmony_ci}
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra124_hsic_ops = {
10068c2ecf20Sopenharmony_ci	.probe = tegra124_hsic_pad_probe,
10078c2ecf20Sopenharmony_ci	.remove = tegra124_hsic_pad_remove,
10088c2ecf20Sopenharmony_ci};
10098c2ecf20Sopenharmony_ci
10108c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra124_hsic_pad = {
10118c2ecf20Sopenharmony_ci	.name = "hsic",
10128c2ecf20Sopenharmony_ci	.num_lanes = ARRAY_SIZE(tegra124_hsic_lanes),
10138c2ecf20Sopenharmony_ci	.lanes = tegra124_hsic_lanes,
10148c2ecf20Sopenharmony_ci	.ops = &tegra124_hsic_ops,
10158c2ecf20Sopenharmony_ci};
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_cistatic const char * const tegra124_pcie_functions[] = {
10188c2ecf20Sopenharmony_ci	"pcie",
10198c2ecf20Sopenharmony_ci	"usb3-ss",
10208c2ecf20Sopenharmony_ci	"sata",
10218c2ecf20Sopenharmony_ci};
10228c2ecf20Sopenharmony_ci
10238c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra124_pcie_lanes[] = {
10248c2ecf20Sopenharmony_ci	TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, pcie),
10258c2ecf20Sopenharmony_ci	TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, pcie),
10268c2ecf20Sopenharmony_ci	TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, pcie),
10278c2ecf20Sopenharmony_ci	TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, pcie),
10288c2ecf20Sopenharmony_ci	TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, pcie),
10298c2ecf20Sopenharmony_ci};
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_cistatic struct tegra_xusb_lane *
10328c2ecf20Sopenharmony_citegra124_pcie_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np,
10338c2ecf20Sopenharmony_ci			 unsigned int index)
10348c2ecf20Sopenharmony_ci{
10358c2ecf20Sopenharmony_ci	struct tegra_xusb_pcie_lane *pcie;
10368c2ecf20Sopenharmony_ci	int err;
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_ci	pcie = kzalloc(sizeof(*pcie), GFP_KERNEL);
10398c2ecf20Sopenharmony_ci	if (!pcie)
10408c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
10418c2ecf20Sopenharmony_ci
10428c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&pcie->base.list);
10438c2ecf20Sopenharmony_ci	pcie->base.soc = &pad->soc->lanes[index];
10448c2ecf20Sopenharmony_ci	pcie->base.index = index;
10458c2ecf20Sopenharmony_ci	pcie->base.pad = pad;
10468c2ecf20Sopenharmony_ci	pcie->base.np = np;
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_ci	err = tegra_xusb_lane_parse_dt(&pcie->base, np);
10498c2ecf20Sopenharmony_ci	if (err < 0) {
10508c2ecf20Sopenharmony_ci		kfree(pcie);
10518c2ecf20Sopenharmony_ci		return ERR_PTR(err);
10528c2ecf20Sopenharmony_ci	}
10538c2ecf20Sopenharmony_ci
10548c2ecf20Sopenharmony_ci	return &pcie->base;
10558c2ecf20Sopenharmony_ci}
10568c2ecf20Sopenharmony_ci
10578c2ecf20Sopenharmony_cistatic void tegra124_pcie_lane_remove(struct tegra_xusb_lane *lane)
10588c2ecf20Sopenharmony_ci{
10598c2ecf20Sopenharmony_ci	struct tegra_xusb_pcie_lane *pcie = to_pcie_lane(lane);
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci	kfree(pcie);
10628c2ecf20Sopenharmony_ci}
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra124_pcie_lane_ops = {
10658c2ecf20Sopenharmony_ci	.probe = tegra124_pcie_lane_probe,
10668c2ecf20Sopenharmony_ci	.remove = tegra124_pcie_lane_remove,
10678c2ecf20Sopenharmony_ci};
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_cistatic int tegra124_pcie_phy_init(struct phy *phy)
10708c2ecf20Sopenharmony_ci{
10718c2ecf20Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
10728c2ecf20Sopenharmony_ci
10738c2ecf20Sopenharmony_ci	return tegra124_xusb_padctl_enable(lane->pad->padctl);
10748c2ecf20Sopenharmony_ci}
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_cistatic int tegra124_pcie_phy_exit(struct phy *phy)
10778c2ecf20Sopenharmony_ci{
10788c2ecf20Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci	return tegra124_xusb_padctl_disable(lane->pad->padctl);
10818c2ecf20Sopenharmony_ci}
10828c2ecf20Sopenharmony_ci
10838c2ecf20Sopenharmony_cistatic int tegra124_pcie_phy_power_on(struct phy *phy)
10848c2ecf20Sopenharmony_ci{
10858c2ecf20Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
10868c2ecf20Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
10878c2ecf20Sopenharmony_ci	unsigned long timeout;
10888c2ecf20Sopenharmony_ci	int err = -ETIMEDOUT;
10898c2ecf20Sopenharmony_ci	u32 value;
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
10928c2ecf20Sopenharmony_ci	value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK;
10938c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
10968c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN |
10978c2ecf20Sopenharmony_ci		 XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN |
10988c2ecf20Sopenharmony_ci		 XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL;
10998c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
11028c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
11038c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci	timeout = jiffies + msecs_to_jiffies(50);
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci	while (time_before(jiffies, timeout)) {
11088c2ecf20Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
11098c2ecf20Sopenharmony_ci		if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) {
11108c2ecf20Sopenharmony_ci			err = 0;
11118c2ecf20Sopenharmony_ci			break;
11128c2ecf20Sopenharmony_ci		}
11138c2ecf20Sopenharmony_ci
11148c2ecf20Sopenharmony_ci		usleep_range(100, 200);
11158c2ecf20Sopenharmony_ci	}
11168c2ecf20Sopenharmony_ci
11178c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
11188c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index);
11198c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
11208c2ecf20Sopenharmony_ci
11218c2ecf20Sopenharmony_ci	return err;
11228c2ecf20Sopenharmony_ci}
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_cistatic int tegra124_pcie_phy_power_off(struct phy *phy)
11258c2ecf20Sopenharmony_ci{
11268c2ecf20Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
11278c2ecf20Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
11288c2ecf20Sopenharmony_ci	u32 value;
11298c2ecf20Sopenharmony_ci
11308c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
11318c2ecf20Sopenharmony_ci	value &= ~XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index);
11328c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
11358c2ecf20Sopenharmony_ci	value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
11368c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
11378c2ecf20Sopenharmony_ci
11388c2ecf20Sopenharmony_ci	return 0;
11398c2ecf20Sopenharmony_ci}
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_cistatic const struct phy_ops tegra124_pcie_phy_ops = {
11428c2ecf20Sopenharmony_ci	.init = tegra124_pcie_phy_init,
11438c2ecf20Sopenharmony_ci	.exit = tegra124_pcie_phy_exit,
11448c2ecf20Sopenharmony_ci	.power_on = tegra124_pcie_phy_power_on,
11458c2ecf20Sopenharmony_ci	.power_off = tegra124_pcie_phy_power_off,
11468c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
11478c2ecf20Sopenharmony_ci};
11488c2ecf20Sopenharmony_ci
11498c2ecf20Sopenharmony_cistatic struct tegra_xusb_pad *
11508c2ecf20Sopenharmony_citegra124_pcie_pad_probe(struct tegra_xusb_padctl *padctl,
11518c2ecf20Sopenharmony_ci			const struct tegra_xusb_pad_soc *soc,
11528c2ecf20Sopenharmony_ci			struct device_node *np)
11538c2ecf20Sopenharmony_ci{
11548c2ecf20Sopenharmony_ci	struct tegra_xusb_pcie_pad *pcie;
11558c2ecf20Sopenharmony_ci	struct tegra_xusb_pad *pad;
11568c2ecf20Sopenharmony_ci	int err;
11578c2ecf20Sopenharmony_ci
11588c2ecf20Sopenharmony_ci	pcie = kzalloc(sizeof(*pcie), GFP_KERNEL);
11598c2ecf20Sopenharmony_ci	if (!pcie)
11608c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_ci	pad = &pcie->base;
11638c2ecf20Sopenharmony_ci	pad->ops = &tegra124_pcie_lane_ops;
11648c2ecf20Sopenharmony_ci	pad->soc = soc;
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ci	err = tegra_xusb_pad_init(pad, padctl, np);
11678c2ecf20Sopenharmony_ci	if (err < 0) {
11688c2ecf20Sopenharmony_ci		kfree(pcie);
11698c2ecf20Sopenharmony_ci		goto out;
11708c2ecf20Sopenharmony_ci	}
11718c2ecf20Sopenharmony_ci
11728c2ecf20Sopenharmony_ci	err = tegra_xusb_pad_register(pad, &tegra124_pcie_phy_ops);
11738c2ecf20Sopenharmony_ci	if (err < 0)
11748c2ecf20Sopenharmony_ci		goto unregister;
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_ci	dev_set_drvdata(&pad->dev, pad);
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_ci	return pad;
11798c2ecf20Sopenharmony_ci
11808c2ecf20Sopenharmony_ciunregister:
11818c2ecf20Sopenharmony_ci	device_unregister(&pad->dev);
11828c2ecf20Sopenharmony_ciout:
11838c2ecf20Sopenharmony_ci	return ERR_PTR(err);
11848c2ecf20Sopenharmony_ci}
11858c2ecf20Sopenharmony_ci
11868c2ecf20Sopenharmony_cistatic void tegra124_pcie_pad_remove(struct tegra_xusb_pad *pad)
11878c2ecf20Sopenharmony_ci{
11888c2ecf20Sopenharmony_ci	struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(pad);
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_ci	kfree(pcie);
11918c2ecf20Sopenharmony_ci}
11928c2ecf20Sopenharmony_ci
11938c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra124_pcie_ops = {
11948c2ecf20Sopenharmony_ci	.probe = tegra124_pcie_pad_probe,
11958c2ecf20Sopenharmony_ci	.remove = tegra124_pcie_pad_remove,
11968c2ecf20Sopenharmony_ci};
11978c2ecf20Sopenharmony_ci
11988c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra124_pcie_pad = {
11998c2ecf20Sopenharmony_ci	.name = "pcie",
12008c2ecf20Sopenharmony_ci	.num_lanes = ARRAY_SIZE(tegra124_pcie_lanes),
12018c2ecf20Sopenharmony_ci	.lanes = tegra124_pcie_lanes,
12028c2ecf20Sopenharmony_ci	.ops = &tegra124_pcie_ops,
12038c2ecf20Sopenharmony_ci};
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra124_sata_lanes[] = {
12068c2ecf20Sopenharmony_ci	TEGRA124_LANE("sata-0", 0x134, 26, 0x3, pcie),
12078c2ecf20Sopenharmony_ci};
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_cistatic struct tegra_xusb_lane *
12108c2ecf20Sopenharmony_citegra124_sata_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np,
12118c2ecf20Sopenharmony_ci			 unsigned int index)
12128c2ecf20Sopenharmony_ci{
12138c2ecf20Sopenharmony_ci	struct tegra_xusb_sata_lane *sata;
12148c2ecf20Sopenharmony_ci	int err;
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ci	sata = kzalloc(sizeof(*sata), GFP_KERNEL);
12178c2ecf20Sopenharmony_ci	if (!sata)
12188c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
12198c2ecf20Sopenharmony_ci
12208c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&sata->base.list);
12218c2ecf20Sopenharmony_ci	sata->base.soc = &pad->soc->lanes[index];
12228c2ecf20Sopenharmony_ci	sata->base.index = index;
12238c2ecf20Sopenharmony_ci	sata->base.pad = pad;
12248c2ecf20Sopenharmony_ci	sata->base.np = np;
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_ci	err = tegra_xusb_lane_parse_dt(&sata->base, np);
12278c2ecf20Sopenharmony_ci	if (err < 0) {
12288c2ecf20Sopenharmony_ci		kfree(sata);
12298c2ecf20Sopenharmony_ci		return ERR_PTR(err);
12308c2ecf20Sopenharmony_ci	}
12318c2ecf20Sopenharmony_ci
12328c2ecf20Sopenharmony_ci	return &sata->base;
12338c2ecf20Sopenharmony_ci}
12348c2ecf20Sopenharmony_ci
12358c2ecf20Sopenharmony_cistatic void tegra124_sata_lane_remove(struct tegra_xusb_lane *lane)
12368c2ecf20Sopenharmony_ci{
12378c2ecf20Sopenharmony_ci	struct tegra_xusb_sata_lane *sata = to_sata_lane(lane);
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci	kfree(sata);
12408c2ecf20Sopenharmony_ci}
12418c2ecf20Sopenharmony_ci
12428c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra124_sata_lane_ops = {
12438c2ecf20Sopenharmony_ci	.probe = tegra124_sata_lane_probe,
12448c2ecf20Sopenharmony_ci	.remove = tegra124_sata_lane_remove,
12458c2ecf20Sopenharmony_ci};
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_cistatic int tegra124_sata_phy_init(struct phy *phy)
12488c2ecf20Sopenharmony_ci{
12498c2ecf20Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_ci	return tegra124_xusb_padctl_enable(lane->pad->padctl);
12528c2ecf20Sopenharmony_ci}
12538c2ecf20Sopenharmony_ci
12548c2ecf20Sopenharmony_cistatic int tegra124_sata_phy_exit(struct phy *phy)
12558c2ecf20Sopenharmony_ci{
12568c2ecf20Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_ci	return tegra124_xusb_padctl_disable(lane->pad->padctl);
12598c2ecf20Sopenharmony_ci}
12608c2ecf20Sopenharmony_ci
12618c2ecf20Sopenharmony_cistatic int tegra124_sata_phy_power_on(struct phy *phy)
12628c2ecf20Sopenharmony_ci{
12638c2ecf20Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
12648c2ecf20Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
12658c2ecf20Sopenharmony_ci	unsigned long timeout;
12668c2ecf20Sopenharmony_ci	int err = -ETIMEDOUT;
12678c2ecf20Sopenharmony_ci	u32 value;
12688c2ecf20Sopenharmony_ci
12698c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
12708c2ecf20Sopenharmony_ci	value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
12718c2ecf20Sopenharmony_ci	value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
12728c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
12738c2ecf20Sopenharmony_ci
12748c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
12758c2ecf20Sopenharmony_ci	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
12768c2ecf20Sopenharmony_ci	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
12778c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
12788c2ecf20Sopenharmony_ci
12798c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
12808c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
12818c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
12848c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
12858c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
12868c2ecf20Sopenharmony_ci
12878c2ecf20Sopenharmony_ci	timeout = jiffies + msecs_to_jiffies(50);
12888c2ecf20Sopenharmony_ci
12898c2ecf20Sopenharmony_ci	while (time_before(jiffies, timeout)) {
12908c2ecf20Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
12918c2ecf20Sopenharmony_ci		if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) {
12928c2ecf20Sopenharmony_ci			err = 0;
12938c2ecf20Sopenharmony_ci			break;
12948c2ecf20Sopenharmony_ci		}
12958c2ecf20Sopenharmony_ci
12968c2ecf20Sopenharmony_ci		usleep_range(100, 200);
12978c2ecf20Sopenharmony_ci	}
12988c2ecf20Sopenharmony_ci
12998c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
13008c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index);
13018c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
13028c2ecf20Sopenharmony_ci
13038c2ecf20Sopenharmony_ci	return err;
13048c2ecf20Sopenharmony_ci}
13058c2ecf20Sopenharmony_ci
13068c2ecf20Sopenharmony_cistatic int tegra124_sata_phy_power_off(struct phy *phy)
13078c2ecf20Sopenharmony_ci{
13088c2ecf20Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
13098c2ecf20Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
13108c2ecf20Sopenharmony_ci	u32 value;
13118c2ecf20Sopenharmony_ci
13128c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
13138c2ecf20Sopenharmony_ci	value &= ~XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index);
13148c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
13158c2ecf20Sopenharmony_ci
13168c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
13178c2ecf20Sopenharmony_ci	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
13188c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
13198c2ecf20Sopenharmony_ci
13208c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
13218c2ecf20Sopenharmony_ci	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
13228c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
13258c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
13268c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
13278c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
13288c2ecf20Sopenharmony_ci
13298c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
13308c2ecf20Sopenharmony_ci	value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
13318c2ecf20Sopenharmony_ci	value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
13328c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
13338c2ecf20Sopenharmony_ci
13348c2ecf20Sopenharmony_ci	return 0;
13358c2ecf20Sopenharmony_ci}
13368c2ecf20Sopenharmony_ci
13378c2ecf20Sopenharmony_cistatic const struct phy_ops tegra124_sata_phy_ops = {
13388c2ecf20Sopenharmony_ci	.init = tegra124_sata_phy_init,
13398c2ecf20Sopenharmony_ci	.exit = tegra124_sata_phy_exit,
13408c2ecf20Sopenharmony_ci	.power_on = tegra124_sata_phy_power_on,
13418c2ecf20Sopenharmony_ci	.power_off = tegra124_sata_phy_power_off,
13428c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
13438c2ecf20Sopenharmony_ci};
13448c2ecf20Sopenharmony_ci
13458c2ecf20Sopenharmony_cistatic struct tegra_xusb_pad *
13468c2ecf20Sopenharmony_citegra124_sata_pad_probe(struct tegra_xusb_padctl *padctl,
13478c2ecf20Sopenharmony_ci			const struct tegra_xusb_pad_soc *soc,
13488c2ecf20Sopenharmony_ci			struct device_node *np)
13498c2ecf20Sopenharmony_ci{
13508c2ecf20Sopenharmony_ci	struct tegra_xusb_sata_pad *sata;
13518c2ecf20Sopenharmony_ci	struct tegra_xusb_pad *pad;
13528c2ecf20Sopenharmony_ci	int err;
13538c2ecf20Sopenharmony_ci
13548c2ecf20Sopenharmony_ci	sata = kzalloc(sizeof(*sata), GFP_KERNEL);
13558c2ecf20Sopenharmony_ci	if (!sata)
13568c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
13578c2ecf20Sopenharmony_ci
13588c2ecf20Sopenharmony_ci	pad = &sata->base;
13598c2ecf20Sopenharmony_ci	pad->ops = &tegra124_sata_lane_ops;
13608c2ecf20Sopenharmony_ci	pad->soc = soc;
13618c2ecf20Sopenharmony_ci
13628c2ecf20Sopenharmony_ci	err = tegra_xusb_pad_init(pad, padctl, np);
13638c2ecf20Sopenharmony_ci	if (err < 0) {
13648c2ecf20Sopenharmony_ci		kfree(sata);
13658c2ecf20Sopenharmony_ci		goto out;
13668c2ecf20Sopenharmony_ci	}
13678c2ecf20Sopenharmony_ci
13688c2ecf20Sopenharmony_ci	err = tegra_xusb_pad_register(pad, &tegra124_sata_phy_ops);
13698c2ecf20Sopenharmony_ci	if (err < 0)
13708c2ecf20Sopenharmony_ci		goto unregister;
13718c2ecf20Sopenharmony_ci
13728c2ecf20Sopenharmony_ci	dev_set_drvdata(&pad->dev, pad);
13738c2ecf20Sopenharmony_ci
13748c2ecf20Sopenharmony_ci	return pad;
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ciunregister:
13778c2ecf20Sopenharmony_ci	device_unregister(&pad->dev);
13788c2ecf20Sopenharmony_ciout:
13798c2ecf20Sopenharmony_ci	return ERR_PTR(err);
13808c2ecf20Sopenharmony_ci}
13818c2ecf20Sopenharmony_ci
13828c2ecf20Sopenharmony_cistatic void tegra124_sata_pad_remove(struct tegra_xusb_pad *pad)
13838c2ecf20Sopenharmony_ci{
13848c2ecf20Sopenharmony_ci	struct tegra_xusb_sata_pad *sata = to_sata_pad(pad);
13858c2ecf20Sopenharmony_ci
13868c2ecf20Sopenharmony_ci	kfree(sata);
13878c2ecf20Sopenharmony_ci}
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra124_sata_ops = {
13908c2ecf20Sopenharmony_ci	.probe = tegra124_sata_pad_probe,
13918c2ecf20Sopenharmony_ci	.remove = tegra124_sata_pad_remove,
13928c2ecf20Sopenharmony_ci};
13938c2ecf20Sopenharmony_ci
13948c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra124_sata_pad = {
13958c2ecf20Sopenharmony_ci	.name = "sata",
13968c2ecf20Sopenharmony_ci	.num_lanes = ARRAY_SIZE(tegra124_sata_lanes),
13978c2ecf20Sopenharmony_ci	.lanes = tegra124_sata_lanes,
13988c2ecf20Sopenharmony_ci	.ops = &tegra124_sata_ops,
13998c2ecf20Sopenharmony_ci};
14008c2ecf20Sopenharmony_ci
14018c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_soc *tegra124_pads[] = {
14028c2ecf20Sopenharmony_ci	&tegra124_usb2_pad,
14038c2ecf20Sopenharmony_ci	&tegra124_ulpi_pad,
14048c2ecf20Sopenharmony_ci	&tegra124_hsic_pad,
14058c2ecf20Sopenharmony_ci	&tegra124_pcie_pad,
14068c2ecf20Sopenharmony_ci	&tegra124_sata_pad,
14078c2ecf20Sopenharmony_ci};
14088c2ecf20Sopenharmony_ci
14098c2ecf20Sopenharmony_cistatic int tegra124_usb2_port_enable(struct tegra_xusb_port *port)
14108c2ecf20Sopenharmony_ci{
14118c2ecf20Sopenharmony_ci	return 0;
14128c2ecf20Sopenharmony_ci}
14138c2ecf20Sopenharmony_ci
14148c2ecf20Sopenharmony_cistatic void tegra124_usb2_port_disable(struct tegra_xusb_port *port)
14158c2ecf20Sopenharmony_ci{
14168c2ecf20Sopenharmony_ci}
14178c2ecf20Sopenharmony_ci
14188c2ecf20Sopenharmony_cistatic struct tegra_xusb_lane *
14198c2ecf20Sopenharmony_citegra124_usb2_port_map(struct tegra_xusb_port *port)
14208c2ecf20Sopenharmony_ci{
14218c2ecf20Sopenharmony_ci	return tegra_xusb_find_lane(port->padctl, "usb2", port->index);
14228c2ecf20Sopenharmony_ci}
14238c2ecf20Sopenharmony_ci
14248c2ecf20Sopenharmony_cistatic const struct tegra_xusb_port_ops tegra124_usb2_port_ops = {
14258c2ecf20Sopenharmony_ci	.release = tegra_xusb_usb2_port_release,
14268c2ecf20Sopenharmony_ci	.remove = tegra_xusb_usb2_port_remove,
14278c2ecf20Sopenharmony_ci	.enable = tegra124_usb2_port_enable,
14288c2ecf20Sopenharmony_ci	.disable = tegra124_usb2_port_disable,
14298c2ecf20Sopenharmony_ci	.map = tegra124_usb2_port_map,
14308c2ecf20Sopenharmony_ci};
14318c2ecf20Sopenharmony_ci
14328c2ecf20Sopenharmony_cistatic int tegra124_ulpi_port_enable(struct tegra_xusb_port *port)
14338c2ecf20Sopenharmony_ci{
14348c2ecf20Sopenharmony_ci	return 0;
14358c2ecf20Sopenharmony_ci}
14368c2ecf20Sopenharmony_ci
14378c2ecf20Sopenharmony_cistatic void tegra124_ulpi_port_disable(struct tegra_xusb_port *port)
14388c2ecf20Sopenharmony_ci{
14398c2ecf20Sopenharmony_ci}
14408c2ecf20Sopenharmony_ci
14418c2ecf20Sopenharmony_cistatic struct tegra_xusb_lane *
14428c2ecf20Sopenharmony_citegra124_ulpi_port_map(struct tegra_xusb_port *port)
14438c2ecf20Sopenharmony_ci{
14448c2ecf20Sopenharmony_ci	return tegra_xusb_find_lane(port->padctl, "ulpi", port->index);
14458c2ecf20Sopenharmony_ci}
14468c2ecf20Sopenharmony_ci
14478c2ecf20Sopenharmony_cistatic const struct tegra_xusb_port_ops tegra124_ulpi_port_ops = {
14488c2ecf20Sopenharmony_ci	.release = tegra_xusb_ulpi_port_release,
14498c2ecf20Sopenharmony_ci	.enable = tegra124_ulpi_port_enable,
14508c2ecf20Sopenharmony_ci	.disable = tegra124_ulpi_port_disable,
14518c2ecf20Sopenharmony_ci	.map = tegra124_ulpi_port_map,
14528c2ecf20Sopenharmony_ci};
14538c2ecf20Sopenharmony_ci
14548c2ecf20Sopenharmony_cistatic int tegra124_hsic_port_enable(struct tegra_xusb_port *port)
14558c2ecf20Sopenharmony_ci{
14568c2ecf20Sopenharmony_ci	return 0;
14578c2ecf20Sopenharmony_ci}
14588c2ecf20Sopenharmony_ci
14598c2ecf20Sopenharmony_cistatic void tegra124_hsic_port_disable(struct tegra_xusb_port *port)
14608c2ecf20Sopenharmony_ci{
14618c2ecf20Sopenharmony_ci}
14628c2ecf20Sopenharmony_ci
14638c2ecf20Sopenharmony_cistatic struct tegra_xusb_lane *
14648c2ecf20Sopenharmony_citegra124_hsic_port_map(struct tegra_xusb_port *port)
14658c2ecf20Sopenharmony_ci{
14668c2ecf20Sopenharmony_ci	return tegra_xusb_find_lane(port->padctl, "hsic", port->index);
14678c2ecf20Sopenharmony_ci}
14688c2ecf20Sopenharmony_ci
14698c2ecf20Sopenharmony_cistatic const struct tegra_xusb_port_ops tegra124_hsic_port_ops = {
14708c2ecf20Sopenharmony_ci	.release = tegra_xusb_hsic_port_release,
14718c2ecf20Sopenharmony_ci	.enable = tegra124_hsic_port_enable,
14728c2ecf20Sopenharmony_ci	.disable = tegra124_hsic_port_disable,
14738c2ecf20Sopenharmony_ci	.map = tegra124_hsic_port_map,
14748c2ecf20Sopenharmony_ci};
14758c2ecf20Sopenharmony_ci
14768c2ecf20Sopenharmony_cistatic int tegra124_usb3_port_enable(struct tegra_xusb_port *port)
14778c2ecf20Sopenharmony_ci{
14788c2ecf20Sopenharmony_ci	struct tegra_xusb_usb3_port *usb3 = to_usb3_port(port);
14798c2ecf20Sopenharmony_ci	struct tegra_xusb_padctl *padctl = port->padctl;
14808c2ecf20Sopenharmony_ci	struct tegra_xusb_lane *lane = usb3->base.lane;
14818c2ecf20Sopenharmony_ci	unsigned int index = port->index, offset;
14828c2ecf20Sopenharmony_ci	u32 value;
14838c2ecf20Sopenharmony_ci
14848c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP);
14858c2ecf20Sopenharmony_ci
14868c2ecf20Sopenharmony_ci	if (!usb3->internal)
14878c2ecf20Sopenharmony_ci		value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index);
14888c2ecf20Sopenharmony_ci	else
14898c2ecf20Sopenharmony_ci		value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index);
14908c2ecf20Sopenharmony_ci
14918c2ecf20Sopenharmony_ci	value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(index);
14928c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(index, usb3->port);
14938c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP);
14948c2ecf20Sopenharmony_ci
14958c2ecf20Sopenharmony_ci	/*
14968c2ecf20Sopenharmony_ci	 * TODO: move this code into the PCIe/SATA PHY ->power_on() callbacks
14978c2ecf20Sopenharmony_ci	 * and conditionalize based on mux function? This seems to work, but
14988c2ecf20Sopenharmony_ci	 * might not be the exact proper sequence.
14998c2ecf20Sopenharmony_ci	 */
15008c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index));
15018c2ecf20Sopenharmony_ci	value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_MASK <<
15028c2ecf20Sopenharmony_ci		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT) |
15038c2ecf20Sopenharmony_ci		   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_MASK <<
15048c2ecf20Sopenharmony_ci		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT) |
15058c2ecf20Sopenharmony_ci		   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_MASK <<
15068c2ecf20Sopenharmony_ci		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT));
15078c2ecf20Sopenharmony_ci	value |= (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_VAL <<
15088c2ecf20Sopenharmony_ci		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT) |
15098c2ecf20Sopenharmony_ci		 (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_VAL <<
15108c2ecf20Sopenharmony_ci		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT) |
15118c2ecf20Sopenharmony_ci		 (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_VAL <<
15128c2ecf20Sopenharmony_ci		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT);
15138c2ecf20Sopenharmony_ci
15148c2ecf20Sopenharmony_ci	if (usb3->context_saved) {
15158c2ecf20Sopenharmony_ci		value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK <<
15168c2ecf20Sopenharmony_ci			    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) |
15178c2ecf20Sopenharmony_ci			   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK <<
15188c2ecf20Sopenharmony_ci			    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT));
15198c2ecf20Sopenharmony_ci		value |= (usb3->ctle_g <<
15208c2ecf20Sopenharmony_ci			  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) |
15218c2ecf20Sopenharmony_ci			 (usb3->ctle_z <<
15228c2ecf20Sopenharmony_ci			  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT);
15238c2ecf20Sopenharmony_ci	}
15248c2ecf20Sopenharmony_ci
15258c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index));
15268c2ecf20Sopenharmony_ci
15278c2ecf20Sopenharmony_ci	value = XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_VAL;
15288c2ecf20Sopenharmony_ci
15298c2ecf20Sopenharmony_ci	if (usb3->context_saved) {
15308c2ecf20Sopenharmony_ci		value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK <<
15318c2ecf20Sopenharmony_ci			    XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) |
15328c2ecf20Sopenharmony_ci			   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK <<
15338c2ecf20Sopenharmony_ci			    XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT));
15348c2ecf20Sopenharmony_ci		value |= (usb3->tap1 <<
15358c2ecf20Sopenharmony_ci			  XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) |
15368c2ecf20Sopenharmony_ci			 (usb3->amp <<
15378c2ecf20Sopenharmony_ci			  XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT);
15388c2ecf20Sopenharmony_ci	}
15398c2ecf20Sopenharmony_ci
15408c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(index));
15418c2ecf20Sopenharmony_ci
15428c2ecf20Sopenharmony_ci	if (lane->pad == padctl->pcie)
15438c2ecf20Sopenharmony_ci		offset = XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL2(lane->index);
15448c2ecf20Sopenharmony_ci	else
15458c2ecf20Sopenharmony_ci		offset = XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2;
15468c2ecf20Sopenharmony_ci
15478c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, offset);
15488c2ecf20Sopenharmony_ci	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_MASK <<
15498c2ecf20Sopenharmony_ci		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT);
15508c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_VAL <<
15518c2ecf20Sopenharmony_ci		XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT;
15528c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, offset);
15538c2ecf20Sopenharmony_ci
15548c2ecf20Sopenharmony_ci	if (lane->pad == padctl->pcie)
15558c2ecf20Sopenharmony_ci		offset = XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL5(lane->index);
15568c2ecf20Sopenharmony_ci	else
15578c2ecf20Sopenharmony_ci		offset = XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5;
15588c2ecf20Sopenharmony_ci
15598c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, offset);
15608c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL5_RX_QEYE_EN;
15618c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, offset);
15628c2ecf20Sopenharmony_ci
15638c2ecf20Sopenharmony_ci	/* Enable SATA PHY when SATA lane is used */
15648c2ecf20Sopenharmony_ci	if (lane->pad == padctl->sata) {
15658c2ecf20Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
15668c2ecf20Sopenharmony_ci		value &= ~(XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_MASK <<
15678c2ecf20Sopenharmony_ci			   XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT);
15688c2ecf20Sopenharmony_ci		value |= 0x2 <<
15698c2ecf20Sopenharmony_ci			XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT;
15708c2ecf20Sopenharmony_ci		padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
15718c2ecf20Sopenharmony_ci
15728c2ecf20Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL2);
15738c2ecf20Sopenharmony_ci		value &= ~((XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_MASK <<
15748c2ecf20Sopenharmony_ci			    XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT) |
15758c2ecf20Sopenharmony_ci			   (XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_MASK <<
15768c2ecf20Sopenharmony_ci			    XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT) |
15778c2ecf20Sopenharmony_ci			   (XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_MASK <<
15788c2ecf20Sopenharmony_ci			    XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT) |
15798c2ecf20Sopenharmony_ci			   XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TCLKOUT_EN);
15808c2ecf20Sopenharmony_ci		value |= (0x7 <<
15818c2ecf20Sopenharmony_ci			  XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT) |
15828c2ecf20Sopenharmony_ci			 (0x8 <<
15838c2ecf20Sopenharmony_ci			  XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT) |
15848c2ecf20Sopenharmony_ci			 (0x8 <<
15858c2ecf20Sopenharmony_ci			  XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT) |
15868c2ecf20Sopenharmony_ci			 XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TXCLKREF_SEL;
15878c2ecf20Sopenharmony_ci		padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL2);
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL3);
15908c2ecf20Sopenharmony_ci		value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL3_RCAL_BYPASS;
15918c2ecf20Sopenharmony_ci		padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL3);
15928c2ecf20Sopenharmony_ci	}
15938c2ecf20Sopenharmony_ci
15948c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
15958c2ecf20Sopenharmony_ci	value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(index);
15968c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
15978c2ecf20Sopenharmony_ci
15988c2ecf20Sopenharmony_ci	usleep_range(100, 200);
15998c2ecf20Sopenharmony_ci
16008c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
16018c2ecf20Sopenharmony_ci	value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(index);
16028c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
16038c2ecf20Sopenharmony_ci
16048c2ecf20Sopenharmony_ci	usleep_range(100, 200);
16058c2ecf20Sopenharmony_ci
16068c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
16078c2ecf20Sopenharmony_ci	value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(index);
16088c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
16098c2ecf20Sopenharmony_ci
16108c2ecf20Sopenharmony_ci	return 0;
16118c2ecf20Sopenharmony_ci}
16128c2ecf20Sopenharmony_ci
16138c2ecf20Sopenharmony_cistatic void tegra124_usb3_port_disable(struct tegra_xusb_port *port)
16148c2ecf20Sopenharmony_ci{
16158c2ecf20Sopenharmony_ci	struct tegra_xusb_padctl *padctl = port->padctl;
16168c2ecf20Sopenharmony_ci	u32 value;
16178c2ecf20Sopenharmony_ci
16188c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
16198c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(port->index);
16208c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
16218c2ecf20Sopenharmony_ci
16228c2ecf20Sopenharmony_ci	usleep_range(100, 200);
16238c2ecf20Sopenharmony_ci
16248c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
16258c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(port->index);
16268c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
16278c2ecf20Sopenharmony_ci
16288c2ecf20Sopenharmony_ci	usleep_range(250, 350);
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
16318c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(port->index);
16328c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
16338c2ecf20Sopenharmony_ci
16348c2ecf20Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP);
16358c2ecf20Sopenharmony_ci	value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(port->index);
16368c2ecf20Sopenharmony_ci	value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(port->index, 0x7);
16378c2ecf20Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP);
16388c2ecf20Sopenharmony_ci}
16398c2ecf20Sopenharmony_ci
16408c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_map tegra124_usb3_map[] = {
16418c2ecf20Sopenharmony_ci	{ 0, "pcie", 0 },
16428c2ecf20Sopenharmony_ci	{ 1, "pcie", 1 },
16438c2ecf20Sopenharmony_ci	{ 1, "sata", 0 },
16448c2ecf20Sopenharmony_ci	{ 0, NULL,   0 },
16458c2ecf20Sopenharmony_ci};
16468c2ecf20Sopenharmony_ci
16478c2ecf20Sopenharmony_cistatic struct tegra_xusb_lane *
16488c2ecf20Sopenharmony_citegra124_usb3_port_map(struct tegra_xusb_port *port)
16498c2ecf20Sopenharmony_ci{
16508c2ecf20Sopenharmony_ci	return tegra_xusb_port_find_lane(port, tegra124_usb3_map, "usb3-ss");
16518c2ecf20Sopenharmony_ci}
16528c2ecf20Sopenharmony_ci
16538c2ecf20Sopenharmony_cistatic const struct tegra_xusb_port_ops tegra124_usb3_port_ops = {
16548c2ecf20Sopenharmony_ci	.release = tegra_xusb_usb3_port_release,
16558c2ecf20Sopenharmony_ci	.remove = tegra_xusb_usb3_port_remove,
16568c2ecf20Sopenharmony_ci	.enable = tegra124_usb3_port_enable,
16578c2ecf20Sopenharmony_ci	.disable = tegra124_usb3_port_disable,
16588c2ecf20Sopenharmony_ci	.map = tegra124_usb3_port_map,
16598c2ecf20Sopenharmony_ci};
16608c2ecf20Sopenharmony_ci
16618c2ecf20Sopenharmony_cistatic int
16628c2ecf20Sopenharmony_citegra124_xusb_read_fuse_calibration(struct tegra124_xusb_fuse_calibration *fuse)
16638c2ecf20Sopenharmony_ci{
16648c2ecf20Sopenharmony_ci	unsigned int i;
16658c2ecf20Sopenharmony_ci	int err;
16668c2ecf20Sopenharmony_ci	u32 value;
16678c2ecf20Sopenharmony_ci
16688c2ecf20Sopenharmony_ci	err = tegra_fuse_readl(TEGRA_FUSE_SKU_CALIB_0, &value);
16698c2ecf20Sopenharmony_ci	if (err < 0)
16708c2ecf20Sopenharmony_ci		return err;
16718c2ecf20Sopenharmony_ci
16728c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(fuse->hs_curr_level); i++) {
16738c2ecf20Sopenharmony_ci		fuse->hs_curr_level[i] =
16748c2ecf20Sopenharmony_ci			(value >> FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(i)) &
16758c2ecf20Sopenharmony_ci			FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK;
16768c2ecf20Sopenharmony_ci	}
16778c2ecf20Sopenharmony_ci	fuse->hs_iref_cap =
16788c2ecf20Sopenharmony_ci		(value >> FUSE_SKU_CALIB_HS_IREF_CAP_SHIFT) &
16798c2ecf20Sopenharmony_ci		FUSE_SKU_CALIB_HS_IREF_CAP_MASK;
16808c2ecf20Sopenharmony_ci	fuse->hs_term_range_adj =
16818c2ecf20Sopenharmony_ci		(value >> FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT) &
16828c2ecf20Sopenharmony_ci		FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK;
16838c2ecf20Sopenharmony_ci	fuse->hs_squelch_level =
16848c2ecf20Sopenharmony_ci		(value >> FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_SHIFT) &
16858c2ecf20Sopenharmony_ci		FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_MASK;
16868c2ecf20Sopenharmony_ci
16878c2ecf20Sopenharmony_ci	return 0;
16888c2ecf20Sopenharmony_ci}
16898c2ecf20Sopenharmony_ci
16908c2ecf20Sopenharmony_cistatic struct tegra_xusb_padctl *
16918c2ecf20Sopenharmony_citegra124_xusb_padctl_probe(struct device *dev,
16928c2ecf20Sopenharmony_ci			   const struct tegra_xusb_padctl_soc *soc)
16938c2ecf20Sopenharmony_ci{
16948c2ecf20Sopenharmony_ci	struct tegra124_xusb_padctl *padctl;
16958c2ecf20Sopenharmony_ci	int err;
16968c2ecf20Sopenharmony_ci
16978c2ecf20Sopenharmony_ci	padctl = devm_kzalloc(dev, sizeof(*padctl), GFP_KERNEL);
16988c2ecf20Sopenharmony_ci	if (!padctl)
16998c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
17008c2ecf20Sopenharmony_ci
17018c2ecf20Sopenharmony_ci	padctl->base.dev = dev;
17028c2ecf20Sopenharmony_ci	padctl->base.soc = soc;
17038c2ecf20Sopenharmony_ci
17048c2ecf20Sopenharmony_ci	err = tegra124_xusb_read_fuse_calibration(&padctl->fuse);
17058c2ecf20Sopenharmony_ci	if (err < 0)
17068c2ecf20Sopenharmony_ci		return ERR_PTR(err);
17078c2ecf20Sopenharmony_ci
17088c2ecf20Sopenharmony_ci	return &padctl->base;
17098c2ecf20Sopenharmony_ci}
17108c2ecf20Sopenharmony_ci
17118c2ecf20Sopenharmony_cistatic void tegra124_xusb_padctl_remove(struct tegra_xusb_padctl *padctl)
17128c2ecf20Sopenharmony_ci{
17138c2ecf20Sopenharmony_ci}
17148c2ecf20Sopenharmony_ci
17158c2ecf20Sopenharmony_cistatic const struct tegra_xusb_padctl_ops tegra124_xusb_padctl_ops = {
17168c2ecf20Sopenharmony_ci	.probe = tegra124_xusb_padctl_probe,
17178c2ecf20Sopenharmony_ci	.remove = tegra124_xusb_padctl_remove,
17188c2ecf20Sopenharmony_ci	.usb3_save_context = tegra124_usb3_save_context,
17198c2ecf20Sopenharmony_ci	.hsic_set_idle = tegra124_hsic_set_idle,
17208c2ecf20Sopenharmony_ci};
17218c2ecf20Sopenharmony_ci
17228c2ecf20Sopenharmony_cistatic const char * const tegra124_xusb_padctl_supply_names[] = {
17238c2ecf20Sopenharmony_ci	"avdd-pll-utmip",
17248c2ecf20Sopenharmony_ci	"avdd-pll-erefe",
17258c2ecf20Sopenharmony_ci	"avdd-pex-pll",
17268c2ecf20Sopenharmony_ci	"hvdd-pex-pll-e",
17278c2ecf20Sopenharmony_ci};
17288c2ecf20Sopenharmony_ci
17298c2ecf20Sopenharmony_ciconst struct tegra_xusb_padctl_soc tegra124_xusb_padctl_soc = {
17308c2ecf20Sopenharmony_ci	.num_pads = ARRAY_SIZE(tegra124_pads),
17318c2ecf20Sopenharmony_ci	.pads = tegra124_pads,
17328c2ecf20Sopenharmony_ci	.ports = {
17338c2ecf20Sopenharmony_ci		.usb2 = {
17348c2ecf20Sopenharmony_ci			.ops = &tegra124_usb2_port_ops,
17358c2ecf20Sopenharmony_ci			.count = 3,
17368c2ecf20Sopenharmony_ci		},
17378c2ecf20Sopenharmony_ci		.ulpi = {
17388c2ecf20Sopenharmony_ci			.ops = &tegra124_ulpi_port_ops,
17398c2ecf20Sopenharmony_ci			.count = 1,
17408c2ecf20Sopenharmony_ci		},
17418c2ecf20Sopenharmony_ci		.hsic = {
17428c2ecf20Sopenharmony_ci			.ops = &tegra124_hsic_port_ops,
17438c2ecf20Sopenharmony_ci			.count = 2,
17448c2ecf20Sopenharmony_ci		},
17458c2ecf20Sopenharmony_ci		.usb3 = {
17468c2ecf20Sopenharmony_ci			.ops = &tegra124_usb3_port_ops,
17478c2ecf20Sopenharmony_ci			.count = 2,
17488c2ecf20Sopenharmony_ci		},
17498c2ecf20Sopenharmony_ci	},
17508c2ecf20Sopenharmony_ci	.ops = &tegra124_xusb_padctl_ops,
17518c2ecf20Sopenharmony_ci	.supply_names = tegra124_xusb_padctl_supply_names,
17528c2ecf20Sopenharmony_ci	.num_supplies = ARRAY_SIZE(tegra124_xusb_padctl_supply_names),
17538c2ecf20Sopenharmony_ci};
17548c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(tegra124_xusb_padctl_soc);
17558c2ecf20Sopenharmony_ci
17568c2ecf20Sopenharmony_ciMODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
17578c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("NVIDIA Tegra 124 XUSB Pad Controller driver");
17588c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
1759