12025cf9eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
253d2a715SThierry Reding /*
353d2a715SThierry Reding  * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
453d2a715SThierry Reding  */
553d2a715SThierry Reding 
653d2a715SThierry Reding #include <linux/delay.h>
753d2a715SThierry Reding #include <linux/io.h>
853d2a715SThierry Reding #include <linux/mailbox_client.h>
953d2a715SThierry Reding #include <linux/module.h>
1053d2a715SThierry Reding #include <linux/of.h>
1153d2a715SThierry Reding #include <linux/phy/phy.h>
1253d2a715SThierry Reding #include <linux/platform_device.h>
1353d2a715SThierry Reding #include <linux/regulator/consumer.h>
1453d2a715SThierry Reding #include <linux/reset.h>
1553d2a715SThierry Reding #include <linux/slab.h>
1653d2a715SThierry Reding 
1753d2a715SThierry Reding #include <soc/tegra/fuse.h>
1853d2a715SThierry Reding 
1953d2a715SThierry Reding #include "xusb.h"
2053d2a715SThierry Reding 
2153d2a715SThierry Reding #define FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(x) ((x) ? 15 : 0)
2253d2a715SThierry Reding #define FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK 0x3f
2353d2a715SThierry Reding #define FUSE_SKU_CALIB_HS_IREF_CAP_SHIFT 13
2453d2a715SThierry Reding #define FUSE_SKU_CALIB_HS_IREF_CAP_MASK 0x3
2553d2a715SThierry Reding #define FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_SHIFT 11
2653d2a715SThierry Reding #define FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_MASK 0x3
2753d2a715SThierry Reding #define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT 7
2853d2a715SThierry Reding #define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK 0xf
2953d2a715SThierry Reding 
3053d2a715SThierry Reding #define XUSB_PADCTL_USB2_PORT_CAP 0x008
3153d2a715SThierry Reding #define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(x) ((x) * 4)
3253d2a715SThierry Reding #define XUSB_PADCTL_USB2_PORT_CAP_PORT_CAP_MASK 0x3
3353d2a715SThierry Reding #define XUSB_PADCTL_USB2_PORT_CAP_DISABLED 0x0
3453d2a715SThierry Reding #define XUSB_PADCTL_USB2_PORT_CAP_HOST 0x1
3553d2a715SThierry Reding #define XUSB_PADCTL_USB2_PORT_CAP_DEVICE 0x2
3653d2a715SThierry Reding #define XUSB_PADCTL_USB2_PORT_CAP_OTG 0x3
3753d2a715SThierry Reding 
3853d2a715SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP 0x014
3953d2a715SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(x) (1 << (((x) * 4) + 3))
4053d2a715SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_SHIFT(x) ((x) * 4)
4153d2a715SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(x) (0x7 << ((x) * 4))
4253d2a715SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(x, v) (((v) & 0x7) << ((x) * 4))
4353d2a715SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP_PORT_MAP_MASK 0x7
4453d2a715SThierry Reding 
4553d2a715SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM 0x01c
4653d2a715SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26)
4753d2a715SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25)
4853d2a715SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24)
4953d2a715SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(x) (1 << (18 + (x) * 4))
5053d2a715SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(x) \
5153d2a715SThierry Reding 							(1 << (17 + (x) * 4))
5253d2a715SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(x) (1 << (16 + (x) * 4))
5353d2a715SThierry Reding 
5453d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040
5553d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19)
5653d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12)
5753d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1)
5853d2a715SThierry Reding 
5953d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044
6053d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6)
6153d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5)
6253d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4)
6353d2a715SThierry Reding 
6453d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(x) (0x058 + (x) * 4)
6553d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT 24
6653d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_MASK 0xff
6753d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_VAL 0x24
6853d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT 16
6953d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK 0x3f
7053d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT 8
7153d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK 0x3f
7253d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT 8
7353d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_MASK 0xffff
7453d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_VAL 0xf070
7553d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT 4
7653d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_MASK 0xf
7753d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_VAL 0xf
7853d2a715SThierry Reding 
7953d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(x) (0x068 + (x) * 4)
8053d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT 24
8153d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK 0x1f
8253d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT 16
8353d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK 0x7f
8453d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_VAL 0x002008ee
8553d2a715SThierry Reding 
8653d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL2(x) ((x) < 2 ? 0x078 + (x) * 4 : \
8753d2a715SThierry Reding 					       0x0f8 + (x) * 4)
8853d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT 28
8953d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_MASK 0x3
9053d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_VAL 0x1
9153d2a715SThierry Reding 
9253d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL5(x) ((x) < 2 ? 0x090 + (x) * 4 : \
9353d2a715SThierry Reding 					       0x11c + (x) * 4)
9453d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL5_RX_QEYE_EN (1 << 8)
9553d2a715SThierry Reding 
9653d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL6(x) ((x) < 2 ? 0x098 + (x) * 4 : \
9753d2a715SThierry Reding 					       0x128 + (x) * 4)
9853d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT 24
9953d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK 0x3f
10053d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_TAP_MASK 0x1f
10153d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_AMP_MASK 0x7f
10253d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT 16
10353d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK 0xff
10453d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_G_Z 0x21
10553d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_TAP 0x32
10653d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_AMP 0x33
10753d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_CTLE_Z 0x48
10853d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_LATCH_G_Z 0xa1
10953d2a715SThierry Reding 
11053d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PADX_CTL0(x) (0x0a0 + (x) * 4)
11153d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI (1 << 21)
11253d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 (1 << 20)
11353d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD (1 << 19)
11453d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT 14
11553d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_MASK 0x3
11653d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_VAL(x) ((x) ? 0x0 : 0x3)
11753d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT 6
11853d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_MASK 0x3f
11953d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_VAL 0x0e
12053d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT 0
12153d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK 0x3f
12253d2a715SThierry Reding 
12353d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PADX_CTL1(x) (0x0ac + (x) * 4)
12453d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT 9
12553d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_MASK 0x3
12653d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT 3
12753d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK 0x7
12853d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR (1 << 2)
12953d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP (1 << 1)
13053d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP (1 << 0)
13153d2a715SThierry Reding 
13253d2a715SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0 0x0b8
13353d2a715SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD (1 << 12)
13453d2a715SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT 2
13553d2a715SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK 0x7
13653d2a715SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL 0x5
13753d2a715SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT 0
13853d2a715SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK 0x3
13953d2a715SThierry Reding 
14053d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PADX_CTL0(x) (0x0c0 + (x) * 4)
14153d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT 12
14253d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_MASK 0x7
14353d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT 8
14453d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_MASK 0x7
14553d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT 4
14653d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_MASK 0x7
14753d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT 0
14853d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_MASK 0x7
14953d2a715SThierry Reding 
15053d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PADX_CTL1(x) (0x0c8 + (x) * 4)
15153d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE (1 << 10)
15253d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_RPU_DATA (1 << 9)
15353d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_RPD_STROBE (1 << 8)
15453d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA (1 << 7)
15553d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI (1 << 5)
15653d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX (1 << 4)
15753d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX (1 << 3)
15853d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX (1 << 2)
15953d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN (1 << 0)
16053d2a715SThierry Reding 
16153d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PADX_CTL2(x) (0x0d0 + (x) * 4)
16253d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT 4
16353d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK 0x7
16453d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT 0
16553d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK 0x7
16653d2a715SThierry Reding 
16753d2a715SThierry Reding #define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL 0x0e0
16853d2a715SThierry Reding #define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL_STRB_TRIM_MASK 0x1f
16953d2a715SThierry Reding 
17053d2a715SThierry Reding #define XUSB_PADCTL_USB3_PAD_MUX 0x134
17153d2a715SThierry Reding #define XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(x) (1 << (1 + (x)))
17253d2a715SThierry Reding #define XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(x) (1 << (6 + (x)))
17353d2a715SThierry Reding 
17453d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138
17553d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27)
17653d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24)
17753d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT 20
17853d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_MASK 0x3
17953d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3)
18053d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1)
18153d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0)
18253d2a715SThierry Reding 
18353d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2 0x13c
18453d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT 20
18553d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_MASK 0xf
18653d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT 16
18753d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_MASK 0xf
18853d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TCLKOUT_EN (1 << 12)
18953d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TXCLKREF_SEL (1 << 4)
19053d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT 0
19153d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_MASK 0x7
19253d2a715SThierry Reding 
19353d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL3 0x140
19453d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL3_RCAL_BYPASS (1 << 7)
19553d2a715SThierry Reding 
19653d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148
19753d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1)
19853d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0)
19953d2a715SThierry Reding 
20053d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2 0x14c
20153d2a715SThierry Reding 
20253d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5 0x158
20353d2a715SThierry Reding 
20453d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6 0x15c
20553d2a715SThierry Reding 
20653d2a715SThierry Reding struct tegra124_xusb_fuse_calibration {
20753d2a715SThierry Reding 	u32 hs_curr_level[3];
20853d2a715SThierry Reding 	u32 hs_iref_cap;
20953d2a715SThierry Reding 	u32 hs_term_range_adj;
21053d2a715SThierry Reding 	u32 hs_squelch_level;
21153d2a715SThierry Reding };
21253d2a715SThierry Reding 
21353d2a715SThierry Reding struct tegra124_xusb_padctl {
21453d2a715SThierry Reding 	struct tegra_xusb_padctl base;
21553d2a715SThierry Reding 
21653d2a715SThierry Reding 	struct tegra124_xusb_fuse_calibration fuse;
21753d2a715SThierry Reding };
21853d2a715SThierry Reding 
21953d2a715SThierry Reding static inline struct tegra124_xusb_padctl *
to_tegra124_xusb_padctl(struct tegra_xusb_padctl * padctl)22053d2a715SThierry Reding to_tegra124_xusb_padctl(struct tegra_xusb_padctl *padctl)
22153d2a715SThierry Reding {
22253d2a715SThierry Reding 	return container_of(padctl, struct tegra124_xusb_padctl, base);
22353d2a715SThierry Reding }
22453d2a715SThierry Reding 
tegra124_xusb_padctl_enable(struct tegra_xusb_padctl * padctl)22553d2a715SThierry Reding static int tegra124_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
22653d2a715SThierry Reding {
22753d2a715SThierry Reding 	u32 value;
22853d2a715SThierry Reding 
22953d2a715SThierry Reding 	mutex_lock(&padctl->lock);
23053d2a715SThierry Reding 
23153d2a715SThierry Reding 	if (padctl->enable++ > 0)
23253d2a715SThierry Reding 		goto out;
23353d2a715SThierry Reding 
23453d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
23553d2a715SThierry Reding 	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
23653d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
23753d2a715SThierry Reding 
23853d2a715SThierry Reding 	usleep_range(100, 200);
23953d2a715SThierry Reding 
24053d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
24153d2a715SThierry Reding 	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
24253d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
24353d2a715SThierry Reding 
24453d2a715SThierry Reding 	usleep_range(100, 200);
24553d2a715SThierry Reding 
24653d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
24753d2a715SThierry Reding 	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
24853d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
24953d2a715SThierry Reding 
25053d2a715SThierry Reding out:
25153d2a715SThierry Reding 	mutex_unlock(&padctl->lock);
25253d2a715SThierry Reding 	return 0;
25353d2a715SThierry Reding }
25453d2a715SThierry Reding 
tegra124_xusb_padctl_disable(struct tegra_xusb_padctl * padctl)25553d2a715SThierry Reding static int tegra124_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
25653d2a715SThierry Reding {
25753d2a715SThierry Reding 	u32 value;
25853d2a715SThierry Reding 
25953d2a715SThierry Reding 	mutex_lock(&padctl->lock);
26053d2a715SThierry Reding 
26153d2a715SThierry Reding 	if (WARN_ON(padctl->enable == 0))
26253d2a715SThierry Reding 		goto out;
26353d2a715SThierry Reding 
26453d2a715SThierry Reding 	if (--padctl->enable > 0)
26553d2a715SThierry Reding 		goto out;
26653d2a715SThierry Reding 
26753d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
26853d2a715SThierry Reding 	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
26953d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
27053d2a715SThierry Reding 
27153d2a715SThierry Reding 	usleep_range(100, 200);
27253d2a715SThierry Reding 
27353d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
27453d2a715SThierry Reding 	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
27553d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
27653d2a715SThierry Reding 
27753d2a715SThierry Reding 	usleep_range(100, 200);
27853d2a715SThierry Reding 
27953d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
28053d2a715SThierry Reding 	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
28153d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
28253d2a715SThierry Reding 
28353d2a715SThierry Reding out:
28453d2a715SThierry Reding 	mutex_unlock(&padctl->lock);
28553d2a715SThierry Reding 	return 0;
28653d2a715SThierry Reding }
28753d2a715SThierry Reding 
tegra124_usb3_save_context(struct tegra_xusb_padctl * padctl,unsigned int index)28853d2a715SThierry Reding static int tegra124_usb3_save_context(struct tegra_xusb_padctl *padctl,
28953d2a715SThierry Reding 				      unsigned int index)
29053d2a715SThierry Reding {
29153d2a715SThierry Reding 	struct tegra_xusb_usb3_port *port;
29253d2a715SThierry Reding 	struct tegra_xusb_lane *lane;
29353d2a715SThierry Reding 	u32 value, offset;
29453d2a715SThierry Reding 
29553d2a715SThierry Reding 	port = tegra_xusb_find_usb3_port(padctl, index);
29653d2a715SThierry Reding 	if (!port)
29753d2a715SThierry Reding 		return -ENODEV;
29853d2a715SThierry Reding 
29953d2a715SThierry Reding 	port->context_saved = true;
30053d2a715SThierry Reding 	lane = port->base.lane;
30153d2a715SThierry Reding 
30253d2a715SThierry Reding 	if (lane->pad == padctl->pcie)
30353d2a715SThierry Reding 		offset = XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL6(lane->index);
30453d2a715SThierry Reding 	else
30553d2a715SThierry Reding 		offset = XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6;
30653d2a715SThierry Reding 
30753d2a715SThierry Reding 	value = padctl_readl(padctl, offset);
30853d2a715SThierry Reding 	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK <<
30953d2a715SThierry Reding 		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT);
31053d2a715SThierry Reding 	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_TAP <<
31153d2a715SThierry Reding 		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT;
31253d2a715SThierry Reding 	padctl_writel(padctl, value, offset);
31353d2a715SThierry Reding 
31453d2a715SThierry Reding 	value = padctl_readl(padctl, offset) >>
31553d2a715SThierry Reding 		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT;
31653d2a715SThierry Reding 	port->tap1 = value & XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_TAP_MASK;
31753d2a715SThierry Reding 
31853d2a715SThierry Reding 	value = padctl_readl(padctl, offset);
31953d2a715SThierry Reding 	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK <<
32053d2a715SThierry Reding 		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT);
32153d2a715SThierry Reding 	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_AMP <<
32253d2a715SThierry Reding 		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT;
32353d2a715SThierry Reding 	padctl_writel(padctl, value, offset);
32453d2a715SThierry Reding 
32553d2a715SThierry Reding 	value = padctl_readl(padctl, offset) >>
32653d2a715SThierry Reding 		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT;
32753d2a715SThierry Reding 	port->amp = value & XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_AMP_MASK;
32853d2a715SThierry Reding 
32953d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(index));
33053d2a715SThierry Reding 	value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK <<
33153d2a715SThierry Reding 		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) |
33253d2a715SThierry Reding 		   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK <<
33353d2a715SThierry Reding 		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT));
33453d2a715SThierry Reding 	value |= (port->tap1 <<
33553d2a715SThierry Reding 		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) |
33653d2a715SThierry Reding 		 (port->amp <<
33753d2a715SThierry Reding 		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT);
33853d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(index));
33953d2a715SThierry Reding 
34053d2a715SThierry Reding 	value = padctl_readl(padctl, offset);
34153d2a715SThierry Reding 	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK <<
34253d2a715SThierry Reding 		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT);
34353d2a715SThierry Reding 	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_LATCH_G_Z <<
34453d2a715SThierry Reding 		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT;
34553d2a715SThierry Reding 	padctl_writel(padctl, value, offset);
34653d2a715SThierry Reding 
34753d2a715SThierry Reding 	value = padctl_readl(padctl, offset);
34853d2a715SThierry Reding 	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK <<
34953d2a715SThierry Reding 		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT);
35053d2a715SThierry Reding 	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_G_Z <<
35153d2a715SThierry Reding 		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT;
35253d2a715SThierry Reding 	padctl_writel(padctl, value, offset);
35353d2a715SThierry Reding 
35453d2a715SThierry Reding 	value = padctl_readl(padctl, offset) >>
35553d2a715SThierry Reding 		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT;
35653d2a715SThierry Reding 	port->ctle_g = value &
35753d2a715SThierry Reding 		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK;
35853d2a715SThierry Reding 
35953d2a715SThierry Reding 	value = padctl_readl(padctl, offset);
36053d2a715SThierry Reding 	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK <<
36153d2a715SThierry Reding 		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT);
36253d2a715SThierry Reding 	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_CTLE_Z <<
36353d2a715SThierry Reding 		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT;
36453d2a715SThierry Reding 	padctl_writel(padctl, value, offset);
36553d2a715SThierry Reding 
36653d2a715SThierry Reding 	value = padctl_readl(padctl, offset) >>
36753d2a715SThierry Reding 		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT;
36853d2a715SThierry Reding 	port->ctle_z = value &
36953d2a715SThierry Reding 		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK;
37053d2a715SThierry Reding 
37153d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index));
37253d2a715SThierry Reding 	value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK <<
37353d2a715SThierry Reding 		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) |
37453d2a715SThierry Reding 		   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK <<
37553d2a715SThierry Reding 		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT));
37653d2a715SThierry Reding 	value |= (port->ctle_g <<
37753d2a715SThierry Reding 		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) |
37853d2a715SThierry Reding 		 (port->ctle_z <<
37953d2a715SThierry Reding 		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT);
38053d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index));
38153d2a715SThierry Reding 
38253d2a715SThierry Reding 	return 0;
38353d2a715SThierry Reding }
38453d2a715SThierry Reding 
tegra124_hsic_set_idle(struct tegra_xusb_padctl * padctl,unsigned int index,bool idle)38553d2a715SThierry Reding static int tegra124_hsic_set_idle(struct tegra_xusb_padctl *padctl,
38653d2a715SThierry Reding 				  unsigned int index, bool idle)
38753d2a715SThierry Reding {
38853d2a715SThierry Reding 	u32 value;
38953d2a715SThierry Reding 
39053d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index));
39153d2a715SThierry Reding 
39253d2a715SThierry Reding 	if (idle)
39353d2a715SThierry Reding 		value |= XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA |
39453d2a715SThierry Reding 			 XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE;
39553d2a715SThierry Reding 	else
39653d2a715SThierry Reding 		value &= ~(XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA |
39753d2a715SThierry Reding 			   XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE);
39853d2a715SThierry Reding 
39953d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index));
40053d2a715SThierry Reding 
40153d2a715SThierry Reding 	return 0;
40253d2a715SThierry Reding }
40353d2a715SThierry Reding 
40453d2a715SThierry Reding #define TEGRA124_LANE(_name, _offset, _shift, _mask, _type)		\
40553d2a715SThierry Reding 	{								\
40653d2a715SThierry Reding 		.name = _name,						\
40753d2a715SThierry Reding 		.offset = _offset,					\
40853d2a715SThierry Reding 		.shift = _shift,					\
40953d2a715SThierry Reding 		.mask = _mask,						\
41053d2a715SThierry Reding 		.num_funcs = ARRAY_SIZE(tegra124_##_type##_functions),	\
41153d2a715SThierry Reding 		.funcs = tegra124_##_type##_functions,			\
41253d2a715SThierry Reding 	}
41353d2a715SThierry Reding 
41453d2a715SThierry Reding static const char * const tegra124_usb2_functions[] = {
41553d2a715SThierry Reding 	"snps",
41653d2a715SThierry Reding 	"xusb",
41753d2a715SThierry Reding 	"uart",
41853d2a715SThierry Reding };
41953d2a715SThierry Reding 
42053d2a715SThierry Reding static const struct tegra_xusb_lane_soc tegra124_usb2_lanes[] = {
42153d2a715SThierry Reding 	TEGRA124_LANE("usb2-0", 0x004,  0, 0x3, usb2),
42253d2a715SThierry Reding 	TEGRA124_LANE("usb2-1", 0x004,  2, 0x3, usb2),
42353d2a715SThierry Reding 	TEGRA124_LANE("usb2-2", 0x004,  4, 0x3, usb2),
42453d2a715SThierry Reding };
42553d2a715SThierry Reding 
42653d2a715SThierry Reding static struct tegra_xusb_lane *
tegra124_usb2_lane_probe(struct tegra_xusb_pad * pad,struct device_node * np,unsigned int index)42753d2a715SThierry Reding tegra124_usb2_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np,
42853d2a715SThierry Reding 			 unsigned int index)
42953d2a715SThierry Reding {
43053d2a715SThierry Reding 	struct tegra_xusb_usb2_lane *usb2;
43153d2a715SThierry Reding 	int err;
43253d2a715SThierry Reding 
43353d2a715SThierry Reding 	usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL);
43453d2a715SThierry Reding 	if (!usb2)
43553d2a715SThierry Reding 		return ERR_PTR(-ENOMEM);
43653d2a715SThierry Reding 
43753d2a715SThierry Reding 	INIT_LIST_HEAD(&usb2->base.list);
43853d2a715SThierry Reding 	usb2->base.soc = &pad->soc->lanes[index];
43953d2a715SThierry Reding 	usb2->base.index = index;
44053d2a715SThierry Reding 	usb2->base.pad = pad;
44153d2a715SThierry Reding 	usb2->base.np = np;
44253d2a715SThierry Reding 
44353d2a715SThierry Reding 	err = tegra_xusb_lane_parse_dt(&usb2->base, np);
44453d2a715SThierry Reding 	if (err < 0) {
44553d2a715SThierry Reding 		kfree(usb2);
44653d2a715SThierry Reding 		return ERR_PTR(err);
44753d2a715SThierry Reding 	}
44853d2a715SThierry Reding 
44953d2a715SThierry Reding 	return &usb2->base;
45053d2a715SThierry Reding }
45153d2a715SThierry Reding 
tegra124_usb2_lane_remove(struct tegra_xusb_lane * lane)45253d2a715SThierry Reding static void tegra124_usb2_lane_remove(struct tegra_xusb_lane *lane)
45353d2a715SThierry Reding {
45453d2a715SThierry Reding 	struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane);
45553d2a715SThierry Reding 
45653d2a715SThierry Reding 	kfree(usb2);
45753d2a715SThierry Reding }
45853d2a715SThierry Reding 
45953d2a715SThierry Reding static const struct tegra_xusb_lane_ops tegra124_usb2_lane_ops = {
46053d2a715SThierry Reding 	.probe = tegra124_usb2_lane_probe,
46153d2a715SThierry Reding 	.remove = tegra124_usb2_lane_remove,
46253d2a715SThierry Reding };
46353d2a715SThierry Reding 
tegra124_usb2_phy_init(struct phy * phy)46453d2a715SThierry Reding static int tegra124_usb2_phy_init(struct phy *phy)
46553d2a715SThierry Reding {
46653d2a715SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
46753d2a715SThierry Reding 
46853d2a715SThierry Reding 	return tegra124_xusb_padctl_enable(lane->pad->padctl);
46953d2a715SThierry Reding }
47053d2a715SThierry Reding 
tegra124_usb2_phy_exit(struct phy * phy)47153d2a715SThierry Reding static int tegra124_usb2_phy_exit(struct phy *phy)
47253d2a715SThierry Reding {
47353d2a715SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
47453d2a715SThierry Reding 
47553d2a715SThierry Reding 	return tegra124_xusb_padctl_disable(lane->pad->padctl);
47653d2a715SThierry Reding }
47753d2a715SThierry Reding 
tegra124_usb2_phy_power_on(struct phy * phy)47853d2a715SThierry Reding static int tegra124_usb2_phy_power_on(struct phy *phy)
47953d2a715SThierry Reding {
48053d2a715SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
48153d2a715SThierry Reding 	struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane);
48253d2a715SThierry Reding 	struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad);
48353d2a715SThierry Reding 	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
48453d2a715SThierry Reding 	struct tegra124_xusb_padctl *priv;
48553d2a715SThierry Reding 	struct tegra_xusb_usb2_port *port;
48653d2a715SThierry Reding 	unsigned int index = lane->index;
48753d2a715SThierry Reding 	u32 value;
48853d2a715SThierry Reding 	int err;
48953d2a715SThierry Reding 
49053d2a715SThierry Reding 	port = tegra_xusb_find_usb2_port(padctl, index);
49153d2a715SThierry Reding 	if (!port) {
49253d2a715SThierry Reding 		dev_err(&phy->dev, "no port found for USB2 lane %u\n", index);
49353d2a715SThierry Reding 		return -ENODEV;
49453d2a715SThierry Reding 	}
49553d2a715SThierry Reding 
49653d2a715SThierry Reding 	priv = to_tegra124_xusb_padctl(padctl);
49753d2a715SThierry Reding 
49853d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
49953d2a715SThierry Reding 	value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK <<
50053d2a715SThierry Reding 		    XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) |
50153d2a715SThierry Reding 		   (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK <<
50253d2a715SThierry Reding 		    XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT));
50353d2a715SThierry Reding 	value |= (priv->fuse.hs_squelch_level <<
50453d2a715SThierry Reding 		  XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) |
50553d2a715SThierry Reding 		 (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL <<
50653d2a715SThierry Reding 		  XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT);
50753d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
50853d2a715SThierry Reding 
50953d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB2_PORT_CAP);
51053d2a715SThierry Reding 	value &= ~(XUSB_PADCTL_USB2_PORT_CAP_PORT_CAP_MASK <<
51153d2a715SThierry Reding 		   XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(index));
51253d2a715SThierry Reding 	value |= XUSB_PADCTL_USB2_PORT_CAP_HOST <<
51353d2a715SThierry Reding 		XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(index);
51453d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB2_PORT_CAP);
51553d2a715SThierry Reding 
51653d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index));
51753d2a715SThierry Reding 	value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK <<
51853d2a715SThierry Reding 		    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT) |
51953d2a715SThierry Reding 		   (XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_MASK <<
52053d2a715SThierry Reding 		    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT) |
52153d2a715SThierry Reding 		   (XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_MASK <<
52253d2a715SThierry Reding 		    XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT) |
52353d2a715SThierry Reding 		   XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD |
52453d2a715SThierry Reding 		   XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 |
52553d2a715SThierry Reding 		   XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI);
52653d2a715SThierry Reding 	value |= (priv->fuse.hs_curr_level[index] +
52753d2a715SThierry Reding 		  usb2->hs_curr_level_offset) <<
52853d2a715SThierry Reding 		XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT;
52953d2a715SThierry Reding 	value |= XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_VAL <<
53053d2a715SThierry Reding 		XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT;
53153d2a715SThierry Reding 	value |= XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_VAL(index) <<
53253d2a715SThierry Reding 		XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT;
53353d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index));
53453d2a715SThierry Reding 
53553d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index));
53653d2a715SThierry Reding 	value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK <<
53753d2a715SThierry Reding 		    XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) |
53853d2a715SThierry Reding 		   (XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_MASK <<
53953d2a715SThierry Reding 		    XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT) |
54053d2a715SThierry Reding 		   XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR |
54153d2a715SThierry Reding 		   XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP |
54253d2a715SThierry Reding 		   XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP);
54353d2a715SThierry Reding 	value |= (priv->fuse.hs_term_range_adj <<
54453d2a715SThierry Reding 		  XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) |
54553d2a715SThierry Reding 		 (priv->fuse.hs_iref_cap <<
54653d2a715SThierry Reding 		  XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT);
54753d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index));
54853d2a715SThierry Reding 
54953d2a715SThierry Reding 	err = regulator_enable(port->supply);
55053d2a715SThierry Reding 	if (err)
55153d2a715SThierry Reding 		return err;
55253d2a715SThierry Reding 
55353d2a715SThierry Reding 	mutex_lock(&pad->lock);
55453d2a715SThierry Reding 
55553d2a715SThierry Reding 	if (pad->enable++ > 0)
55653d2a715SThierry Reding 		goto out;
55753d2a715SThierry Reding 
55853d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
55953d2a715SThierry Reding 	value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD;
56053d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
56153d2a715SThierry Reding 
56253d2a715SThierry Reding out:
56353d2a715SThierry Reding 	mutex_unlock(&pad->lock);
56453d2a715SThierry Reding 	return 0;
56553d2a715SThierry Reding }
56653d2a715SThierry Reding 
tegra124_usb2_phy_power_off(struct phy * phy)56753d2a715SThierry Reding static int tegra124_usb2_phy_power_off(struct phy *phy)
56853d2a715SThierry Reding {
56953d2a715SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
57053d2a715SThierry Reding 	struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad);
57153d2a715SThierry Reding 	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
57253d2a715SThierry Reding 	struct tegra_xusb_usb2_port *port;
57353d2a715SThierry Reding 	u32 value;
57453d2a715SThierry Reding 
57553d2a715SThierry Reding 	port = tegra_xusb_find_usb2_port(padctl, lane->index);
57653d2a715SThierry Reding 	if (!port) {
57753d2a715SThierry Reding 		dev_err(&phy->dev, "no port found for USB2 lane %u\n",
57853d2a715SThierry Reding 			lane->index);
57953d2a715SThierry Reding 		return -ENODEV;
58053d2a715SThierry Reding 	}
58153d2a715SThierry Reding 
58253d2a715SThierry Reding 	mutex_lock(&pad->lock);
58353d2a715SThierry Reding 
58453d2a715SThierry Reding 	if (WARN_ON(pad->enable == 0))
58553d2a715SThierry Reding 		goto out;
58653d2a715SThierry Reding 
58753d2a715SThierry Reding 	if (--pad->enable > 0)
58853d2a715SThierry Reding 		goto out;
58953d2a715SThierry Reding 
59053d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
59153d2a715SThierry Reding 	value |= XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD;
59253d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
59353d2a715SThierry Reding 
59453d2a715SThierry Reding out:
59553d2a715SThierry Reding 	regulator_disable(port->supply);
59653d2a715SThierry Reding 	mutex_unlock(&pad->lock);
59753d2a715SThierry Reding 	return 0;
59853d2a715SThierry Reding }
59953d2a715SThierry Reding 
60053d2a715SThierry Reding static const struct phy_ops tegra124_usb2_phy_ops = {
60153d2a715SThierry Reding 	.init = tegra124_usb2_phy_init,
60253d2a715SThierry Reding 	.exit = tegra124_usb2_phy_exit,
60353d2a715SThierry Reding 	.power_on = tegra124_usb2_phy_power_on,
60453d2a715SThierry Reding 	.power_off = tegra124_usb2_phy_power_off,
60553d2a715SThierry Reding 	.owner = THIS_MODULE,
60653d2a715SThierry Reding };
60753d2a715SThierry Reding 
60853d2a715SThierry Reding static struct tegra_xusb_pad *
tegra124_usb2_pad_probe(struct tegra_xusb_padctl * padctl,const struct tegra_xusb_pad_soc * soc,struct device_node * np)60953d2a715SThierry Reding tegra124_usb2_pad_probe(struct tegra_xusb_padctl *padctl,
61053d2a715SThierry Reding 			const struct tegra_xusb_pad_soc *soc,
61153d2a715SThierry Reding 			struct device_node *np)
61253d2a715SThierry Reding {
61353d2a715SThierry Reding 	struct tegra_xusb_usb2_pad *usb2;
61453d2a715SThierry Reding 	struct tegra_xusb_pad *pad;
61553d2a715SThierry Reding 	int err;
61653d2a715SThierry Reding 
61753d2a715SThierry Reding 	usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL);
61853d2a715SThierry Reding 	if (!usb2)
61953d2a715SThierry Reding 		return ERR_PTR(-ENOMEM);
62053d2a715SThierry Reding 
62153d2a715SThierry Reding 	mutex_init(&usb2->lock);
62253d2a715SThierry Reding 
62353d2a715SThierry Reding 	pad = &usb2->base;
62453d2a715SThierry Reding 	pad->ops = &tegra124_usb2_lane_ops;
62553d2a715SThierry Reding 	pad->soc = soc;
62653d2a715SThierry Reding 
62753d2a715SThierry Reding 	err = tegra_xusb_pad_init(pad, padctl, np);
62853d2a715SThierry Reding 	if (err < 0) {
62953d2a715SThierry Reding 		kfree(usb2);
63053d2a715SThierry Reding 		goto out;
63153d2a715SThierry Reding 	}
63253d2a715SThierry Reding 
63353d2a715SThierry Reding 	err = tegra_xusb_pad_register(pad, &tegra124_usb2_phy_ops);
63453d2a715SThierry Reding 	if (err < 0)
63553d2a715SThierry Reding 		goto unregister;
63653d2a715SThierry Reding 
63753d2a715SThierry Reding 	dev_set_drvdata(&pad->dev, pad);
63853d2a715SThierry Reding 
63953d2a715SThierry Reding 	return pad;
64053d2a715SThierry Reding 
64153d2a715SThierry Reding unregister:
64253d2a715SThierry Reding 	device_unregister(&pad->dev);
64353d2a715SThierry Reding out:
64453d2a715SThierry Reding 	return ERR_PTR(err);
64553d2a715SThierry Reding }
64653d2a715SThierry Reding 
tegra124_usb2_pad_remove(struct tegra_xusb_pad * pad)64753d2a715SThierry Reding static void tegra124_usb2_pad_remove(struct tegra_xusb_pad *pad)
64853d2a715SThierry Reding {
64953d2a715SThierry Reding 	struct tegra_xusb_usb2_pad *usb2 = to_usb2_pad(pad);
65053d2a715SThierry Reding 
65153d2a715SThierry Reding 	kfree(usb2);
65253d2a715SThierry Reding }
65353d2a715SThierry Reding 
65453d2a715SThierry Reding static const struct tegra_xusb_pad_ops tegra124_usb2_ops = {
65553d2a715SThierry Reding 	.probe = tegra124_usb2_pad_probe,
65653d2a715SThierry Reding 	.remove = tegra124_usb2_pad_remove,
65753d2a715SThierry Reding };
65853d2a715SThierry Reding 
65953d2a715SThierry Reding static const struct tegra_xusb_pad_soc tegra124_usb2_pad = {
66053d2a715SThierry Reding 	.name = "usb2",
66153d2a715SThierry Reding 	.num_lanes = ARRAY_SIZE(tegra124_usb2_lanes),
66253d2a715SThierry Reding 	.lanes = tegra124_usb2_lanes,
66353d2a715SThierry Reding 	.ops = &tegra124_usb2_ops,
66453d2a715SThierry Reding };
66553d2a715SThierry Reding 
66653d2a715SThierry Reding static const char * const tegra124_ulpi_functions[] = {
66753d2a715SThierry Reding 	"snps",
66853d2a715SThierry Reding 	"xusb",
66953d2a715SThierry Reding };
67053d2a715SThierry Reding 
67153d2a715SThierry Reding static const struct tegra_xusb_lane_soc tegra124_ulpi_lanes[] = {
67253d2a715SThierry Reding 	TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, ulpi),
67353d2a715SThierry Reding };
67453d2a715SThierry Reding 
67553d2a715SThierry Reding static struct tegra_xusb_lane *
tegra124_ulpi_lane_probe(struct tegra_xusb_pad * pad,struct device_node * np,unsigned int index)67653d2a715SThierry Reding tegra124_ulpi_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np,
67753d2a715SThierry Reding 			 unsigned int index)
67853d2a715SThierry Reding {
67953d2a715SThierry Reding 	struct tegra_xusb_ulpi_lane *ulpi;
68053d2a715SThierry Reding 	int err;
68153d2a715SThierry Reding 
68253d2a715SThierry Reding 	ulpi = kzalloc(sizeof(*ulpi), GFP_KERNEL);
68353d2a715SThierry Reding 	if (!ulpi)
68453d2a715SThierry Reding 		return ERR_PTR(-ENOMEM);
68553d2a715SThierry Reding 
68653d2a715SThierry Reding 	INIT_LIST_HEAD(&ulpi->base.list);
68753d2a715SThierry Reding 	ulpi->base.soc = &pad->soc->lanes[index];
68853d2a715SThierry Reding 	ulpi->base.index = index;
68953d2a715SThierry Reding 	ulpi->base.pad = pad;
69053d2a715SThierry Reding 	ulpi->base.np = np;
69153d2a715SThierry Reding 
69253d2a715SThierry Reding 	err = tegra_xusb_lane_parse_dt(&ulpi->base, np);
69353d2a715SThierry Reding 	if (err < 0) {
69453d2a715SThierry Reding 		kfree(ulpi);
69553d2a715SThierry Reding 		return ERR_PTR(err);
69653d2a715SThierry Reding 	}
69753d2a715SThierry Reding 
69853d2a715SThierry Reding 	return &ulpi->base;
69953d2a715SThierry Reding }
70053d2a715SThierry Reding 
tegra124_ulpi_lane_remove(struct tegra_xusb_lane * lane)70153d2a715SThierry Reding static void tegra124_ulpi_lane_remove(struct tegra_xusb_lane *lane)
70253d2a715SThierry Reding {
70353d2a715SThierry Reding 	struct tegra_xusb_ulpi_lane *ulpi = to_ulpi_lane(lane);
70453d2a715SThierry Reding 
70553d2a715SThierry Reding 	kfree(ulpi);
70653d2a715SThierry Reding }
70753d2a715SThierry Reding 
70853d2a715SThierry Reding static const struct tegra_xusb_lane_ops tegra124_ulpi_lane_ops = {
70953d2a715SThierry Reding 	.probe = tegra124_ulpi_lane_probe,
71053d2a715SThierry Reding 	.remove = tegra124_ulpi_lane_remove,
71153d2a715SThierry Reding };
71253d2a715SThierry Reding 
tegra124_ulpi_phy_init(struct phy * phy)71353d2a715SThierry Reding static int tegra124_ulpi_phy_init(struct phy *phy)
71453d2a715SThierry Reding {
71553d2a715SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
71653d2a715SThierry Reding 
71753d2a715SThierry Reding 	return tegra124_xusb_padctl_enable(lane->pad->padctl);
71853d2a715SThierry Reding }
71953d2a715SThierry Reding 
tegra124_ulpi_phy_exit(struct phy * phy)72053d2a715SThierry Reding static int tegra124_ulpi_phy_exit(struct phy *phy)
72153d2a715SThierry Reding {
72253d2a715SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
72353d2a715SThierry Reding 
72453d2a715SThierry Reding 	return tegra124_xusb_padctl_disable(lane->pad->padctl);
72553d2a715SThierry Reding }
72653d2a715SThierry Reding 
tegra124_ulpi_phy_power_on(struct phy * phy)72753d2a715SThierry Reding static int tegra124_ulpi_phy_power_on(struct phy *phy)
72853d2a715SThierry Reding {
72953d2a715SThierry Reding 	return 0;
73053d2a715SThierry Reding }
73153d2a715SThierry Reding 
tegra124_ulpi_phy_power_off(struct phy * phy)73253d2a715SThierry Reding static int tegra124_ulpi_phy_power_off(struct phy *phy)
73353d2a715SThierry Reding {
73453d2a715SThierry Reding 	return 0;
73553d2a715SThierry Reding }
73653d2a715SThierry Reding 
73753d2a715SThierry Reding static const struct phy_ops tegra124_ulpi_phy_ops = {
73853d2a715SThierry Reding 	.init = tegra124_ulpi_phy_init,
73953d2a715SThierry Reding 	.exit = tegra124_ulpi_phy_exit,
74053d2a715SThierry Reding 	.power_on = tegra124_ulpi_phy_power_on,
74153d2a715SThierry Reding 	.power_off = tegra124_ulpi_phy_power_off,
74253d2a715SThierry Reding 	.owner = THIS_MODULE,
74353d2a715SThierry Reding };
74453d2a715SThierry Reding 
74553d2a715SThierry Reding static struct tegra_xusb_pad *
tegra124_ulpi_pad_probe(struct tegra_xusb_padctl * padctl,const struct tegra_xusb_pad_soc * soc,struct device_node * np)74653d2a715SThierry Reding tegra124_ulpi_pad_probe(struct tegra_xusb_padctl *padctl,
74753d2a715SThierry Reding 			const struct tegra_xusb_pad_soc *soc,
74853d2a715SThierry Reding 			struct device_node *np)
74953d2a715SThierry Reding {
75053d2a715SThierry Reding 	struct tegra_xusb_ulpi_pad *ulpi;
75153d2a715SThierry Reding 	struct tegra_xusb_pad *pad;
75253d2a715SThierry Reding 	int err;
75353d2a715SThierry Reding 
75453d2a715SThierry Reding 	ulpi = kzalloc(sizeof(*ulpi), GFP_KERNEL);
75553d2a715SThierry Reding 	if (!ulpi)
75653d2a715SThierry Reding 		return ERR_PTR(-ENOMEM);
75753d2a715SThierry Reding 
75853d2a715SThierry Reding 	pad = &ulpi->base;
75953d2a715SThierry Reding 	pad->ops = &tegra124_ulpi_lane_ops;
76053d2a715SThierry Reding 	pad->soc = soc;
76153d2a715SThierry Reding 
76253d2a715SThierry Reding 	err = tegra_xusb_pad_init(pad, padctl, np);
76353d2a715SThierry Reding 	if (err < 0) {
76453d2a715SThierry Reding 		kfree(ulpi);
76553d2a715SThierry Reding 		goto out;
76653d2a715SThierry Reding 	}
76753d2a715SThierry Reding 
76853d2a715SThierry Reding 	err = tegra_xusb_pad_register(pad, &tegra124_ulpi_phy_ops);
76953d2a715SThierry Reding 	if (err < 0)
77053d2a715SThierry Reding 		goto unregister;
77153d2a715SThierry Reding 
77253d2a715SThierry Reding 	dev_set_drvdata(&pad->dev, pad);
77353d2a715SThierry Reding 
77453d2a715SThierry Reding 	return pad;
77553d2a715SThierry Reding 
77653d2a715SThierry Reding unregister:
77753d2a715SThierry Reding 	device_unregister(&pad->dev);
77853d2a715SThierry Reding out:
77953d2a715SThierry Reding 	return ERR_PTR(err);
78053d2a715SThierry Reding }
78153d2a715SThierry Reding 
tegra124_ulpi_pad_remove(struct tegra_xusb_pad * pad)78253d2a715SThierry Reding static void tegra124_ulpi_pad_remove(struct tegra_xusb_pad *pad)
78353d2a715SThierry Reding {
78453d2a715SThierry Reding 	struct tegra_xusb_ulpi_pad *ulpi = to_ulpi_pad(pad);
78553d2a715SThierry Reding 
78653d2a715SThierry Reding 	kfree(ulpi);
78753d2a715SThierry Reding }
78853d2a715SThierry Reding 
78953d2a715SThierry Reding static const struct tegra_xusb_pad_ops tegra124_ulpi_ops = {
79053d2a715SThierry Reding 	.probe = tegra124_ulpi_pad_probe,
79153d2a715SThierry Reding 	.remove = tegra124_ulpi_pad_remove,
79253d2a715SThierry Reding };
79353d2a715SThierry Reding 
79453d2a715SThierry Reding static const struct tegra_xusb_pad_soc tegra124_ulpi_pad = {
79553d2a715SThierry Reding 	.name = "ulpi",
79653d2a715SThierry Reding 	.num_lanes = ARRAY_SIZE(tegra124_ulpi_lanes),
79753d2a715SThierry Reding 	.lanes = tegra124_ulpi_lanes,
79853d2a715SThierry Reding 	.ops = &tegra124_ulpi_ops,
79953d2a715SThierry Reding };
80053d2a715SThierry Reding 
80153d2a715SThierry Reding static const char * const tegra124_hsic_functions[] = {
80253d2a715SThierry Reding 	"snps",
80353d2a715SThierry Reding 	"xusb",
80453d2a715SThierry Reding };
80553d2a715SThierry Reding 
80653d2a715SThierry Reding static const struct tegra_xusb_lane_soc tegra124_hsic_lanes[] = {
80753d2a715SThierry Reding 	TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, hsic),
80853d2a715SThierry Reding 	TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, hsic),
80953d2a715SThierry Reding };
81053d2a715SThierry Reding 
81153d2a715SThierry Reding static struct tegra_xusb_lane *
tegra124_hsic_lane_probe(struct tegra_xusb_pad * pad,struct device_node * np,unsigned int index)81253d2a715SThierry Reding tegra124_hsic_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np,
81353d2a715SThierry Reding 			 unsigned int index)
81453d2a715SThierry Reding {
81553d2a715SThierry Reding 	struct tegra_xusb_hsic_lane *hsic;
81653d2a715SThierry Reding 	int err;
81753d2a715SThierry Reding 
81853d2a715SThierry Reding 	hsic = kzalloc(sizeof(*hsic), GFP_KERNEL);
81953d2a715SThierry Reding 	if (!hsic)
82053d2a715SThierry Reding 		return ERR_PTR(-ENOMEM);
82153d2a715SThierry Reding 
82253d2a715SThierry Reding 	INIT_LIST_HEAD(&hsic->base.list);
82353d2a715SThierry Reding 	hsic->base.soc = &pad->soc->lanes[index];
82453d2a715SThierry Reding 	hsic->base.index = index;
82553d2a715SThierry Reding 	hsic->base.pad = pad;
82653d2a715SThierry Reding 	hsic->base.np = np;
82753d2a715SThierry Reding 
82853d2a715SThierry Reding 	err = tegra_xusb_lane_parse_dt(&hsic->base, np);
82953d2a715SThierry Reding 	if (err < 0) {
83053d2a715SThierry Reding 		kfree(hsic);
83153d2a715SThierry Reding 		return ERR_PTR(err);
83253d2a715SThierry Reding 	}
83353d2a715SThierry Reding 
83453d2a715SThierry Reding 	return &hsic->base;
83553d2a715SThierry Reding }
83653d2a715SThierry Reding 
tegra124_hsic_lane_remove(struct tegra_xusb_lane * lane)83753d2a715SThierry Reding static void tegra124_hsic_lane_remove(struct tegra_xusb_lane *lane)
83853d2a715SThierry Reding {
83953d2a715SThierry Reding 	struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane);
84053d2a715SThierry Reding 
84153d2a715SThierry Reding 	kfree(hsic);
84253d2a715SThierry Reding }
84353d2a715SThierry Reding 
84453d2a715SThierry Reding static const struct tegra_xusb_lane_ops tegra124_hsic_lane_ops = {
84553d2a715SThierry Reding 	.probe = tegra124_hsic_lane_probe,
84653d2a715SThierry Reding 	.remove = tegra124_hsic_lane_remove,
84753d2a715SThierry Reding };
84853d2a715SThierry Reding 
tegra124_hsic_phy_init(struct phy * phy)84953d2a715SThierry Reding static int tegra124_hsic_phy_init(struct phy *phy)
85053d2a715SThierry Reding {
85153d2a715SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
85253d2a715SThierry Reding 
85353d2a715SThierry Reding 	return tegra124_xusb_padctl_enable(lane->pad->padctl);
85453d2a715SThierry Reding }
85553d2a715SThierry Reding 
tegra124_hsic_phy_exit(struct phy * phy)85653d2a715SThierry Reding static int tegra124_hsic_phy_exit(struct phy *phy)
85753d2a715SThierry Reding {
85853d2a715SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
85953d2a715SThierry Reding 
86053d2a715SThierry Reding 	return tegra124_xusb_padctl_disable(lane->pad->padctl);
86153d2a715SThierry Reding }
86253d2a715SThierry Reding 
tegra124_hsic_phy_power_on(struct phy * phy)86353d2a715SThierry Reding static int tegra124_hsic_phy_power_on(struct phy *phy)
86453d2a715SThierry Reding {
86553d2a715SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
86653d2a715SThierry Reding 	struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane);
86753d2a715SThierry Reding 	struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad);
86853d2a715SThierry Reding 	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
86953d2a715SThierry Reding 	unsigned int index = lane->index;
87053d2a715SThierry Reding 	u32 value;
87153d2a715SThierry Reding 	int err;
87253d2a715SThierry Reding 
87353d2a715SThierry Reding 	err = regulator_enable(pad->supply);
87453d2a715SThierry Reding 	if (err)
87553d2a715SThierry Reding 		return err;
87653d2a715SThierry Reding 
87753d2a715SThierry Reding 	padctl_writel(padctl, hsic->strobe_trim,
87853d2a715SThierry Reding 		      XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL);
87953d2a715SThierry Reding 
88053d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index));
88153d2a715SThierry Reding 
88253d2a715SThierry Reding 	if (hsic->auto_term)
88353d2a715SThierry Reding 		value |= XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN;
88453d2a715SThierry Reding 	else
88553d2a715SThierry Reding 		value &= ~XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN;
88653d2a715SThierry Reding 
88753d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index));
88853d2a715SThierry Reding 
88953d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(index));
89053d2a715SThierry Reding 	value &= ~((XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_MASK <<
89153d2a715SThierry Reding 		    XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT) |
89253d2a715SThierry Reding 		   (XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_MASK <<
89353d2a715SThierry Reding 		    XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT) |
89453d2a715SThierry Reding 		   (XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_MASK <<
89553d2a715SThierry Reding 		    XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT) |
89653d2a715SThierry Reding 		   (XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_MASK <<
89753d2a715SThierry Reding 		    XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT));
89853d2a715SThierry Reding 	value |= (hsic->tx_rtune_n <<
89953d2a715SThierry Reding 		  XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT) |
90053d2a715SThierry Reding 		(hsic->tx_rtune_p <<
90153d2a715SThierry Reding 		  XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT) |
90253d2a715SThierry Reding 		(hsic->tx_rslew_n <<
90353d2a715SThierry Reding 		 XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT) |
90453d2a715SThierry Reding 		(hsic->tx_rslew_p <<
90553d2a715SThierry Reding 		 XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT);
90653d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL0(index));
90753d2a715SThierry Reding 
90853d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL2(index));
90953d2a715SThierry Reding 	value &= ~((XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK <<
91053d2a715SThierry Reding 		    XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) |
91153d2a715SThierry Reding 		   (XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK <<
91253d2a715SThierry Reding 		    XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT));
91353d2a715SThierry Reding 	value |= (hsic->rx_strobe_trim <<
91453d2a715SThierry Reding 		  XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) |
91553d2a715SThierry Reding 		(hsic->rx_data_trim <<
91653d2a715SThierry Reding 		 XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT);
91753d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL2(index));
91853d2a715SThierry Reding 
91953d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index));
92053d2a715SThierry Reding 	value &= ~(XUSB_PADCTL_HSIC_PAD_CTL1_RPD_STROBE |
92153d2a715SThierry Reding 		   XUSB_PADCTL_HSIC_PAD_CTL1_RPU_DATA |
92253d2a715SThierry Reding 		   XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX |
92353d2a715SThierry Reding 		   XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI |
92453d2a715SThierry Reding 		   XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX |
92553d2a715SThierry Reding 		   XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX);
92653d2a715SThierry Reding 	value |= XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA |
92753d2a715SThierry Reding 		 XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE;
92853d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index));
92953d2a715SThierry Reding 
93053d2a715SThierry Reding 	return 0;
93153d2a715SThierry Reding }
93253d2a715SThierry Reding 
tegra124_hsic_phy_power_off(struct phy * phy)93353d2a715SThierry Reding static int tegra124_hsic_phy_power_off(struct phy *phy)
93453d2a715SThierry Reding {
93553d2a715SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
93653d2a715SThierry Reding 	struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad);
93753d2a715SThierry Reding 	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
93853d2a715SThierry Reding 	unsigned int index = lane->index;
93953d2a715SThierry Reding 	u32 value;
94053d2a715SThierry Reding 
94153d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index));
94253d2a715SThierry Reding 	value |= XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX |
94353d2a715SThierry Reding 		 XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI |
94453d2a715SThierry Reding 		 XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX |
94553d2a715SThierry Reding 		 XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX;
94653d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index));
94753d2a715SThierry Reding 
94853d2a715SThierry Reding 	regulator_disable(pad->supply);
94953d2a715SThierry Reding 
95053d2a715SThierry Reding 	return 0;
95153d2a715SThierry Reding }
95253d2a715SThierry Reding 
95353d2a715SThierry Reding static const struct phy_ops tegra124_hsic_phy_ops = {
95453d2a715SThierry Reding 	.init = tegra124_hsic_phy_init,
95553d2a715SThierry Reding 	.exit = tegra124_hsic_phy_exit,
95653d2a715SThierry Reding 	.power_on = tegra124_hsic_phy_power_on,
95753d2a715SThierry Reding 	.power_off = tegra124_hsic_phy_power_off,
95853d2a715SThierry Reding 	.owner = THIS_MODULE,
95953d2a715SThierry Reding };
96053d2a715SThierry Reding 
96153d2a715SThierry Reding static struct tegra_xusb_pad *
tegra124_hsic_pad_probe(struct tegra_xusb_padctl * padctl,const struct tegra_xusb_pad_soc * soc,struct device_node * np)96253d2a715SThierry Reding tegra124_hsic_pad_probe(struct tegra_xusb_padctl *padctl,
96353d2a715SThierry Reding 			const struct tegra_xusb_pad_soc *soc,
96453d2a715SThierry Reding 			struct device_node *np)
96553d2a715SThierry Reding {
96653d2a715SThierry Reding 	struct tegra_xusb_hsic_pad *hsic;
96753d2a715SThierry Reding 	struct tegra_xusb_pad *pad;
96853d2a715SThierry Reding 	int err;
96953d2a715SThierry Reding 
97053d2a715SThierry Reding 	hsic = kzalloc(sizeof(*hsic), GFP_KERNEL);
97153d2a715SThierry Reding 	if (!hsic)
97253d2a715SThierry Reding 		return ERR_PTR(-ENOMEM);
97353d2a715SThierry Reding 
97453d2a715SThierry Reding 	pad = &hsic->base;
97553d2a715SThierry Reding 	pad->ops = &tegra124_hsic_lane_ops;
97653d2a715SThierry Reding 	pad->soc = soc;
97753d2a715SThierry Reding 
97853d2a715SThierry Reding 	err = tegra_xusb_pad_init(pad, padctl, np);
97953d2a715SThierry Reding 	if (err < 0) {
98053d2a715SThierry Reding 		kfree(hsic);
98153d2a715SThierry Reding 		goto out;
98253d2a715SThierry Reding 	}
98353d2a715SThierry Reding 
98453d2a715SThierry Reding 	err = tegra_xusb_pad_register(pad, &tegra124_hsic_phy_ops);
98553d2a715SThierry Reding 	if (err < 0)
98653d2a715SThierry Reding 		goto unregister;
98753d2a715SThierry Reding 
98853d2a715SThierry Reding 	dev_set_drvdata(&pad->dev, pad);
98953d2a715SThierry Reding 
99053d2a715SThierry Reding 	return pad;
99153d2a715SThierry Reding 
99253d2a715SThierry Reding unregister:
99353d2a715SThierry Reding 	device_unregister(&pad->dev);
99453d2a715SThierry Reding out:
99553d2a715SThierry Reding 	return ERR_PTR(err);
99653d2a715SThierry Reding }
99753d2a715SThierry Reding 
tegra124_hsic_pad_remove(struct tegra_xusb_pad * pad)99853d2a715SThierry Reding static void tegra124_hsic_pad_remove(struct tegra_xusb_pad *pad)
99953d2a715SThierry Reding {
100053d2a715SThierry Reding 	struct tegra_xusb_hsic_pad *hsic = to_hsic_pad(pad);
100153d2a715SThierry Reding 
100253d2a715SThierry Reding 	kfree(hsic);
100353d2a715SThierry Reding }
100453d2a715SThierry Reding 
100553d2a715SThierry Reding static const struct tegra_xusb_pad_ops tegra124_hsic_ops = {
100653d2a715SThierry Reding 	.probe = tegra124_hsic_pad_probe,
100753d2a715SThierry Reding 	.remove = tegra124_hsic_pad_remove,
100853d2a715SThierry Reding };
100953d2a715SThierry Reding 
101053d2a715SThierry Reding static const struct tegra_xusb_pad_soc tegra124_hsic_pad = {
101153d2a715SThierry Reding 	.name = "hsic",
101253d2a715SThierry Reding 	.num_lanes = ARRAY_SIZE(tegra124_hsic_lanes),
101353d2a715SThierry Reding 	.lanes = tegra124_hsic_lanes,
101453d2a715SThierry Reding 	.ops = &tegra124_hsic_ops,
101553d2a715SThierry Reding };
101653d2a715SThierry Reding 
101753d2a715SThierry Reding static const char * const tegra124_pcie_functions[] = {
101853d2a715SThierry Reding 	"pcie",
101953d2a715SThierry Reding 	"usb3-ss",
102053d2a715SThierry Reding 	"sata",
102153d2a715SThierry Reding };
102253d2a715SThierry Reding 
102353d2a715SThierry Reding static const struct tegra_xusb_lane_soc tegra124_pcie_lanes[] = {
102453d2a715SThierry Reding 	TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, pcie),
102553d2a715SThierry Reding 	TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, pcie),
102653d2a715SThierry Reding 	TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, pcie),
102753d2a715SThierry Reding 	TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, pcie),
102853d2a715SThierry Reding 	TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, pcie),
102953d2a715SThierry Reding };
103053d2a715SThierry Reding 
103153d2a715SThierry Reding static struct tegra_xusb_lane *
tegra124_pcie_lane_probe(struct tegra_xusb_pad * pad,struct device_node * np,unsigned int index)103253d2a715SThierry Reding tegra124_pcie_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np,
103353d2a715SThierry Reding 			 unsigned int index)
103453d2a715SThierry Reding {
103553d2a715SThierry Reding 	struct tegra_xusb_pcie_lane *pcie;
103653d2a715SThierry Reding 	int err;
103753d2a715SThierry Reding 
103853d2a715SThierry Reding 	pcie = kzalloc(sizeof(*pcie), GFP_KERNEL);
103953d2a715SThierry Reding 	if (!pcie)
104053d2a715SThierry Reding 		return ERR_PTR(-ENOMEM);
104153d2a715SThierry Reding 
104253d2a715SThierry Reding 	INIT_LIST_HEAD(&pcie->base.list);
104353d2a715SThierry Reding 	pcie->base.soc = &pad->soc->lanes[index];
104453d2a715SThierry Reding 	pcie->base.index = index;
104553d2a715SThierry Reding 	pcie->base.pad = pad;
104653d2a715SThierry Reding 	pcie->base.np = np;
104753d2a715SThierry Reding 
104853d2a715SThierry Reding 	err = tegra_xusb_lane_parse_dt(&pcie->base, np);
104953d2a715SThierry Reding 	if (err < 0) {
105053d2a715SThierry Reding 		kfree(pcie);
105153d2a715SThierry Reding 		return ERR_PTR(err);
105253d2a715SThierry Reding 	}
105353d2a715SThierry Reding 
105453d2a715SThierry Reding 	return &pcie->base;
105553d2a715SThierry Reding }
105653d2a715SThierry Reding 
tegra124_pcie_lane_remove(struct tegra_xusb_lane * lane)105753d2a715SThierry Reding static void tegra124_pcie_lane_remove(struct tegra_xusb_lane *lane)
105853d2a715SThierry Reding {
105953d2a715SThierry Reding 	struct tegra_xusb_pcie_lane *pcie = to_pcie_lane(lane);
106053d2a715SThierry Reding 
106153d2a715SThierry Reding 	kfree(pcie);
106253d2a715SThierry Reding }
106353d2a715SThierry Reding 
106453d2a715SThierry Reding static const struct tegra_xusb_lane_ops tegra124_pcie_lane_ops = {
106553d2a715SThierry Reding 	.probe = tegra124_pcie_lane_probe,
106653d2a715SThierry Reding 	.remove = tegra124_pcie_lane_remove,
106753d2a715SThierry Reding };
106853d2a715SThierry Reding 
tegra124_pcie_phy_init(struct phy * phy)106953d2a715SThierry Reding static int tegra124_pcie_phy_init(struct phy *phy)
107053d2a715SThierry Reding {
107153d2a715SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
107253d2a715SThierry Reding 
107353d2a715SThierry Reding 	return tegra124_xusb_padctl_enable(lane->pad->padctl);
107453d2a715SThierry Reding }
107553d2a715SThierry Reding 
tegra124_pcie_phy_exit(struct phy * phy)107653d2a715SThierry Reding static int tegra124_pcie_phy_exit(struct phy *phy)
107753d2a715SThierry Reding {
107853d2a715SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
107953d2a715SThierry Reding 
108053d2a715SThierry Reding 	return tegra124_xusb_padctl_disable(lane->pad->padctl);
108153d2a715SThierry Reding }
108253d2a715SThierry Reding 
tegra124_pcie_phy_power_on(struct phy * phy)108353d2a715SThierry Reding static int tegra124_pcie_phy_power_on(struct phy *phy)
108453d2a715SThierry Reding {
108553d2a715SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
108653d2a715SThierry Reding 	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
108753d2a715SThierry Reding 	unsigned long timeout;
108853d2a715SThierry Reding 	int err = -ETIMEDOUT;
108953d2a715SThierry Reding 	u32 value;
109053d2a715SThierry Reding 
109153d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
109253d2a715SThierry Reding 	value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK;
109353d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
109453d2a715SThierry Reding 
109553d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
109653d2a715SThierry Reding 	value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN |
109753d2a715SThierry Reding 		 XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN |
109853d2a715SThierry Reding 		 XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL;
109953d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
110053d2a715SThierry Reding 
110153d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
110253d2a715SThierry Reding 	value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
110353d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
110453d2a715SThierry Reding 
110553d2a715SThierry Reding 	timeout = jiffies + msecs_to_jiffies(50);
110653d2a715SThierry Reding 
110753d2a715SThierry Reding 	while (time_before(jiffies, timeout)) {
110853d2a715SThierry Reding 		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
110953d2a715SThierry Reding 		if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) {
111053d2a715SThierry Reding 			err = 0;
111153d2a715SThierry Reding 			break;
111253d2a715SThierry Reding 		}
111353d2a715SThierry Reding 
111453d2a715SThierry Reding 		usleep_range(100, 200);
111553d2a715SThierry Reding 	}
111653d2a715SThierry Reding 
111753d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
111853d2a715SThierry Reding 	value |= XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index);
111953d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
112053d2a715SThierry Reding 
112153d2a715SThierry Reding 	return err;
112253d2a715SThierry Reding }
112353d2a715SThierry Reding 
tegra124_pcie_phy_power_off(struct phy * phy)112453d2a715SThierry Reding static int tegra124_pcie_phy_power_off(struct phy *phy)
112553d2a715SThierry Reding {
112653d2a715SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
112753d2a715SThierry Reding 	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
112853d2a715SThierry Reding 	u32 value;
112953d2a715SThierry Reding 
113053d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
113153d2a715SThierry Reding 	value &= ~XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index);
113253d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
113353d2a715SThierry Reding 
113453d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
113553d2a715SThierry Reding 	value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
113653d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
113753d2a715SThierry Reding 
113853d2a715SThierry Reding 	return 0;
113953d2a715SThierry Reding }
114053d2a715SThierry Reding 
114153d2a715SThierry Reding static const struct phy_ops tegra124_pcie_phy_ops = {
114253d2a715SThierry Reding 	.init = tegra124_pcie_phy_init,
114353d2a715SThierry Reding 	.exit = tegra124_pcie_phy_exit,
114453d2a715SThierry Reding 	.power_on = tegra124_pcie_phy_power_on,
114553d2a715SThierry Reding 	.power_off = tegra124_pcie_phy_power_off,
114653d2a715SThierry Reding 	.owner = THIS_MODULE,
114753d2a715SThierry Reding };
114853d2a715SThierry Reding 
114953d2a715SThierry Reding static struct tegra_xusb_pad *
tegra124_pcie_pad_probe(struct tegra_xusb_padctl * padctl,const struct tegra_xusb_pad_soc * soc,struct device_node * np)115053d2a715SThierry Reding tegra124_pcie_pad_probe(struct tegra_xusb_padctl *padctl,
115153d2a715SThierry Reding 			const struct tegra_xusb_pad_soc *soc,
115253d2a715SThierry Reding 			struct device_node *np)
115353d2a715SThierry Reding {
115453d2a715SThierry Reding 	struct tegra_xusb_pcie_pad *pcie;
115553d2a715SThierry Reding 	struct tegra_xusb_pad *pad;
115653d2a715SThierry Reding 	int err;
115753d2a715SThierry Reding 
115853d2a715SThierry Reding 	pcie = kzalloc(sizeof(*pcie), GFP_KERNEL);
115953d2a715SThierry Reding 	if (!pcie)
116053d2a715SThierry Reding 		return ERR_PTR(-ENOMEM);
116153d2a715SThierry Reding 
116253d2a715SThierry Reding 	pad = &pcie->base;
116353d2a715SThierry Reding 	pad->ops = &tegra124_pcie_lane_ops;
116453d2a715SThierry Reding 	pad->soc = soc;
116553d2a715SThierry Reding 
116653d2a715SThierry Reding 	err = tegra_xusb_pad_init(pad, padctl, np);
116753d2a715SThierry Reding 	if (err < 0) {
116853d2a715SThierry Reding 		kfree(pcie);
116953d2a715SThierry Reding 		goto out;
117053d2a715SThierry Reding 	}
117153d2a715SThierry Reding 
117253d2a715SThierry Reding 	err = tegra_xusb_pad_register(pad, &tegra124_pcie_phy_ops);
117353d2a715SThierry Reding 	if (err < 0)
117453d2a715SThierry Reding 		goto unregister;
117553d2a715SThierry Reding 
117653d2a715SThierry Reding 	dev_set_drvdata(&pad->dev, pad);
117753d2a715SThierry Reding 
117853d2a715SThierry Reding 	return pad;
117953d2a715SThierry Reding 
118053d2a715SThierry Reding unregister:
118153d2a715SThierry Reding 	device_unregister(&pad->dev);
118253d2a715SThierry Reding out:
118353d2a715SThierry Reding 	return ERR_PTR(err);
118453d2a715SThierry Reding }
118553d2a715SThierry Reding 
tegra124_pcie_pad_remove(struct tegra_xusb_pad * pad)118653d2a715SThierry Reding static void tegra124_pcie_pad_remove(struct tegra_xusb_pad *pad)
118753d2a715SThierry Reding {
118853d2a715SThierry Reding 	struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(pad);
118953d2a715SThierry Reding 
119053d2a715SThierry Reding 	kfree(pcie);
119153d2a715SThierry Reding }
119253d2a715SThierry Reding 
119353d2a715SThierry Reding static const struct tegra_xusb_pad_ops tegra124_pcie_ops = {
119453d2a715SThierry Reding 	.probe = tegra124_pcie_pad_probe,
119553d2a715SThierry Reding 	.remove = tegra124_pcie_pad_remove,
119653d2a715SThierry Reding };
119753d2a715SThierry Reding 
119853d2a715SThierry Reding static const struct tegra_xusb_pad_soc tegra124_pcie_pad = {
119953d2a715SThierry Reding 	.name = "pcie",
120053d2a715SThierry Reding 	.num_lanes = ARRAY_SIZE(tegra124_pcie_lanes),
120153d2a715SThierry Reding 	.lanes = tegra124_pcie_lanes,
120253d2a715SThierry Reding 	.ops = &tegra124_pcie_ops,
120353d2a715SThierry Reding };
120453d2a715SThierry Reding 
120553d2a715SThierry Reding static const struct tegra_xusb_lane_soc tegra124_sata_lanes[] = {
120653d2a715SThierry Reding 	TEGRA124_LANE("sata-0", 0x134, 26, 0x3, pcie),
120753d2a715SThierry Reding };
120853d2a715SThierry Reding 
120953d2a715SThierry Reding static struct tegra_xusb_lane *
tegra124_sata_lane_probe(struct tegra_xusb_pad * pad,struct device_node * np,unsigned int index)121053d2a715SThierry Reding tegra124_sata_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np,
121153d2a715SThierry Reding 			 unsigned int index)
121253d2a715SThierry Reding {
121353d2a715SThierry Reding 	struct tegra_xusb_sata_lane *sata;
121453d2a715SThierry Reding 	int err;
121553d2a715SThierry Reding 
121653d2a715SThierry Reding 	sata = kzalloc(sizeof(*sata), GFP_KERNEL);
121753d2a715SThierry Reding 	if (!sata)
121853d2a715SThierry Reding 		return ERR_PTR(-ENOMEM);
121953d2a715SThierry Reding 
122053d2a715SThierry Reding 	INIT_LIST_HEAD(&sata->base.list);
122153d2a715SThierry Reding 	sata->base.soc = &pad->soc->lanes[index];
122253d2a715SThierry Reding 	sata->base.index = index;
122353d2a715SThierry Reding 	sata->base.pad = pad;
122453d2a715SThierry Reding 	sata->base.np = np;
122553d2a715SThierry Reding 
122653d2a715SThierry Reding 	err = tegra_xusb_lane_parse_dt(&sata->base, np);
122753d2a715SThierry Reding 	if (err < 0) {
122853d2a715SThierry Reding 		kfree(sata);
122953d2a715SThierry Reding 		return ERR_PTR(err);
123053d2a715SThierry Reding 	}
123153d2a715SThierry Reding 
123253d2a715SThierry Reding 	return &sata->base;
123353d2a715SThierry Reding }
123453d2a715SThierry Reding 
tegra124_sata_lane_remove(struct tegra_xusb_lane * lane)123553d2a715SThierry Reding static void tegra124_sata_lane_remove(struct tegra_xusb_lane *lane)
123653d2a715SThierry Reding {
123753d2a715SThierry Reding 	struct tegra_xusb_sata_lane *sata = to_sata_lane(lane);
123853d2a715SThierry Reding 
123953d2a715SThierry Reding 	kfree(sata);
124053d2a715SThierry Reding }
124153d2a715SThierry Reding 
124253d2a715SThierry Reding static const struct tegra_xusb_lane_ops tegra124_sata_lane_ops = {
124353d2a715SThierry Reding 	.probe = tegra124_sata_lane_probe,
124453d2a715SThierry Reding 	.remove = tegra124_sata_lane_remove,
124553d2a715SThierry Reding };
124653d2a715SThierry Reding 
tegra124_sata_phy_init(struct phy * phy)124753d2a715SThierry Reding static int tegra124_sata_phy_init(struct phy *phy)
124853d2a715SThierry Reding {
124953d2a715SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
125053d2a715SThierry Reding 
125153d2a715SThierry Reding 	return tegra124_xusb_padctl_enable(lane->pad->padctl);
125253d2a715SThierry Reding }
125353d2a715SThierry Reding 
tegra124_sata_phy_exit(struct phy * phy)125453d2a715SThierry Reding static int tegra124_sata_phy_exit(struct phy *phy)
125553d2a715SThierry Reding {
125653d2a715SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
125753d2a715SThierry Reding 
125853d2a715SThierry Reding 	return tegra124_xusb_padctl_disable(lane->pad->padctl);
125953d2a715SThierry Reding }
126053d2a715SThierry Reding 
tegra124_sata_phy_power_on(struct phy * phy)126153d2a715SThierry Reding static int tegra124_sata_phy_power_on(struct phy *phy)
126253d2a715SThierry Reding {
126353d2a715SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
126453d2a715SThierry Reding 	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
126553d2a715SThierry Reding 	unsigned long timeout;
126653d2a715SThierry Reding 	int err = -ETIMEDOUT;
126753d2a715SThierry Reding 	u32 value;
126853d2a715SThierry Reding 
126953d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
127053d2a715SThierry Reding 	value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
127153d2a715SThierry Reding 	value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
127253d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
127353d2a715SThierry Reding 
127453d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
127553d2a715SThierry Reding 	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
127653d2a715SThierry Reding 	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
127753d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
127853d2a715SThierry Reding 
127953d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
128053d2a715SThierry Reding 	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
128153d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
128253d2a715SThierry Reding 
128353d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
128453d2a715SThierry Reding 	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
128553d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
128653d2a715SThierry Reding 
128753d2a715SThierry Reding 	timeout = jiffies + msecs_to_jiffies(50);
128853d2a715SThierry Reding 
128953d2a715SThierry Reding 	while (time_before(jiffies, timeout)) {
129053d2a715SThierry Reding 		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
129153d2a715SThierry Reding 		if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) {
129253d2a715SThierry Reding 			err = 0;
129353d2a715SThierry Reding 			break;
129453d2a715SThierry Reding 		}
129553d2a715SThierry Reding 
129653d2a715SThierry Reding 		usleep_range(100, 200);
129753d2a715SThierry Reding 	}
129853d2a715SThierry Reding 
129953d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
130053d2a715SThierry Reding 	value |= XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index);
130153d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
130253d2a715SThierry Reding 
130353d2a715SThierry Reding 	return err;
130453d2a715SThierry Reding }
130553d2a715SThierry Reding 
tegra124_sata_phy_power_off(struct phy * phy)130653d2a715SThierry Reding static int tegra124_sata_phy_power_off(struct phy *phy)
130753d2a715SThierry Reding {
130853d2a715SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
130953d2a715SThierry Reding 	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
131053d2a715SThierry Reding 	u32 value;
131153d2a715SThierry Reding 
131253d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
131353d2a715SThierry Reding 	value &= ~XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index);
131453d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
131553d2a715SThierry Reding 
131653d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
131753d2a715SThierry Reding 	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
131853d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
131953d2a715SThierry Reding 
132053d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
132153d2a715SThierry Reding 	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
132253d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
132353d2a715SThierry Reding 
132453d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
132553d2a715SThierry Reding 	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
132653d2a715SThierry Reding 	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
132753d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
132853d2a715SThierry Reding 
132953d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
133053d2a715SThierry Reding 	value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
133153d2a715SThierry Reding 	value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
133253d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
133353d2a715SThierry Reding 
133453d2a715SThierry Reding 	return 0;
133553d2a715SThierry Reding }
133653d2a715SThierry Reding 
133753d2a715SThierry Reding static const struct phy_ops tegra124_sata_phy_ops = {
133853d2a715SThierry Reding 	.init = tegra124_sata_phy_init,
133953d2a715SThierry Reding 	.exit = tegra124_sata_phy_exit,
134053d2a715SThierry Reding 	.power_on = tegra124_sata_phy_power_on,
134153d2a715SThierry Reding 	.power_off = tegra124_sata_phy_power_off,
134253d2a715SThierry Reding 	.owner = THIS_MODULE,
134353d2a715SThierry Reding };
134453d2a715SThierry Reding 
134553d2a715SThierry Reding static struct tegra_xusb_pad *
tegra124_sata_pad_probe(struct tegra_xusb_padctl * padctl,const struct tegra_xusb_pad_soc * soc,struct device_node * np)134653d2a715SThierry Reding tegra124_sata_pad_probe(struct tegra_xusb_padctl *padctl,
134753d2a715SThierry Reding 			const struct tegra_xusb_pad_soc *soc,
134853d2a715SThierry Reding 			struct device_node *np)
134953d2a715SThierry Reding {
135053d2a715SThierry Reding 	struct tegra_xusb_sata_pad *sata;
135153d2a715SThierry Reding 	struct tegra_xusb_pad *pad;
135253d2a715SThierry Reding 	int err;
135353d2a715SThierry Reding 
135453d2a715SThierry Reding 	sata = kzalloc(sizeof(*sata), GFP_KERNEL);
135553d2a715SThierry Reding 	if (!sata)
135653d2a715SThierry Reding 		return ERR_PTR(-ENOMEM);
135753d2a715SThierry Reding 
135853d2a715SThierry Reding 	pad = &sata->base;
135953d2a715SThierry Reding 	pad->ops = &tegra124_sata_lane_ops;
136053d2a715SThierry Reding 	pad->soc = soc;
136153d2a715SThierry Reding 
136253d2a715SThierry Reding 	err = tegra_xusb_pad_init(pad, padctl, np);
136353d2a715SThierry Reding 	if (err < 0) {
136453d2a715SThierry Reding 		kfree(sata);
136553d2a715SThierry Reding 		goto out;
136653d2a715SThierry Reding 	}
136753d2a715SThierry Reding 
136853d2a715SThierry Reding 	err = tegra_xusb_pad_register(pad, &tegra124_sata_phy_ops);
136953d2a715SThierry Reding 	if (err < 0)
137053d2a715SThierry Reding 		goto unregister;
137153d2a715SThierry Reding 
137253d2a715SThierry Reding 	dev_set_drvdata(&pad->dev, pad);
137353d2a715SThierry Reding 
137453d2a715SThierry Reding 	return pad;
137553d2a715SThierry Reding 
137653d2a715SThierry Reding unregister:
137753d2a715SThierry Reding 	device_unregister(&pad->dev);
137853d2a715SThierry Reding out:
137953d2a715SThierry Reding 	return ERR_PTR(err);
138053d2a715SThierry Reding }
138153d2a715SThierry Reding 
tegra124_sata_pad_remove(struct tegra_xusb_pad * pad)138253d2a715SThierry Reding static void tegra124_sata_pad_remove(struct tegra_xusb_pad *pad)
138353d2a715SThierry Reding {
138453d2a715SThierry Reding 	struct tegra_xusb_sata_pad *sata = to_sata_pad(pad);
138553d2a715SThierry Reding 
138653d2a715SThierry Reding 	kfree(sata);
138753d2a715SThierry Reding }
138853d2a715SThierry Reding 
138953d2a715SThierry Reding static const struct tegra_xusb_pad_ops tegra124_sata_ops = {
139053d2a715SThierry Reding 	.probe = tegra124_sata_pad_probe,
139153d2a715SThierry Reding 	.remove = tegra124_sata_pad_remove,
139253d2a715SThierry Reding };
139353d2a715SThierry Reding 
139453d2a715SThierry Reding static const struct tegra_xusb_pad_soc tegra124_sata_pad = {
139553d2a715SThierry Reding 	.name = "sata",
139653d2a715SThierry Reding 	.num_lanes = ARRAY_SIZE(tegra124_sata_lanes),
139753d2a715SThierry Reding 	.lanes = tegra124_sata_lanes,
139853d2a715SThierry Reding 	.ops = &tegra124_sata_ops,
139953d2a715SThierry Reding };
140053d2a715SThierry Reding 
140153d2a715SThierry Reding static const struct tegra_xusb_pad_soc *tegra124_pads[] = {
140253d2a715SThierry Reding 	&tegra124_usb2_pad,
140353d2a715SThierry Reding 	&tegra124_ulpi_pad,
140453d2a715SThierry Reding 	&tegra124_hsic_pad,
140553d2a715SThierry Reding 	&tegra124_pcie_pad,
140653d2a715SThierry Reding 	&tegra124_sata_pad,
140753d2a715SThierry Reding };
140853d2a715SThierry Reding 
tegra124_usb2_port_enable(struct tegra_xusb_port * port)140953d2a715SThierry Reding static int tegra124_usb2_port_enable(struct tegra_xusb_port *port)
141053d2a715SThierry Reding {
141153d2a715SThierry Reding 	return 0;
141253d2a715SThierry Reding }
141353d2a715SThierry Reding 
tegra124_usb2_port_disable(struct tegra_xusb_port * port)141453d2a715SThierry Reding static void tegra124_usb2_port_disable(struct tegra_xusb_port *port)
141553d2a715SThierry Reding {
141653d2a715SThierry Reding }
141753d2a715SThierry Reding 
141853d2a715SThierry Reding static struct tegra_xusb_lane *
tegra124_usb2_port_map(struct tegra_xusb_port * port)141953d2a715SThierry Reding tegra124_usb2_port_map(struct tegra_xusb_port *port)
142053d2a715SThierry Reding {
142153d2a715SThierry Reding 	return tegra_xusb_find_lane(port->padctl, "usb2", port->index);
142253d2a715SThierry Reding }
142353d2a715SThierry Reding 
142453d2a715SThierry Reding static const struct tegra_xusb_port_ops tegra124_usb2_port_ops = {
1425e78fdbadSThierry Reding 	.release = tegra_xusb_usb2_port_release,
14262f8da84dSThierry Reding 	.remove = tegra_xusb_usb2_port_remove,
142753d2a715SThierry Reding 	.enable = tegra124_usb2_port_enable,
142853d2a715SThierry Reding 	.disable = tegra124_usb2_port_disable,
142953d2a715SThierry Reding 	.map = tegra124_usb2_port_map,
143053d2a715SThierry Reding };
143153d2a715SThierry Reding 
tegra124_ulpi_port_enable(struct tegra_xusb_port * port)143253d2a715SThierry Reding static int tegra124_ulpi_port_enable(struct tegra_xusb_port *port)
143353d2a715SThierry Reding {
143453d2a715SThierry Reding 	return 0;
143553d2a715SThierry Reding }
143653d2a715SThierry Reding 
tegra124_ulpi_port_disable(struct tegra_xusb_port * port)143753d2a715SThierry Reding static void tegra124_ulpi_port_disable(struct tegra_xusb_port *port)
143853d2a715SThierry Reding {
143953d2a715SThierry Reding }
144053d2a715SThierry Reding 
144153d2a715SThierry Reding static struct tegra_xusb_lane *
tegra124_ulpi_port_map(struct tegra_xusb_port * port)144253d2a715SThierry Reding tegra124_ulpi_port_map(struct tegra_xusb_port *port)
144353d2a715SThierry Reding {
144453d2a715SThierry Reding 	return tegra_xusb_find_lane(port->padctl, "ulpi", port->index);
144553d2a715SThierry Reding }
144653d2a715SThierry Reding 
144753d2a715SThierry Reding static const struct tegra_xusb_port_ops tegra124_ulpi_port_ops = {
1448e78fdbadSThierry Reding 	.release = tegra_xusb_ulpi_port_release,
144953d2a715SThierry Reding 	.enable = tegra124_ulpi_port_enable,
145053d2a715SThierry Reding 	.disable = tegra124_ulpi_port_disable,
145153d2a715SThierry Reding 	.map = tegra124_ulpi_port_map,
145253d2a715SThierry Reding };
145353d2a715SThierry Reding 
tegra124_hsic_port_enable(struct tegra_xusb_port * port)145453d2a715SThierry Reding static int tegra124_hsic_port_enable(struct tegra_xusb_port *port)
145553d2a715SThierry Reding {
145653d2a715SThierry Reding 	return 0;
145753d2a715SThierry Reding }
145853d2a715SThierry Reding 
tegra124_hsic_port_disable(struct tegra_xusb_port * port)145953d2a715SThierry Reding static void tegra124_hsic_port_disable(struct tegra_xusb_port *port)
146053d2a715SThierry Reding {
146153d2a715SThierry Reding }
146253d2a715SThierry Reding 
146353d2a715SThierry Reding static struct tegra_xusb_lane *
tegra124_hsic_port_map(struct tegra_xusb_port * port)146453d2a715SThierry Reding tegra124_hsic_port_map(struct tegra_xusb_port *port)
146553d2a715SThierry Reding {
146653d2a715SThierry Reding 	return tegra_xusb_find_lane(port->padctl, "hsic", port->index);
146753d2a715SThierry Reding }
146853d2a715SThierry Reding 
146953d2a715SThierry Reding static const struct tegra_xusb_port_ops tegra124_hsic_port_ops = {
1470e78fdbadSThierry Reding 	.release = tegra_xusb_hsic_port_release,
147153d2a715SThierry Reding 	.enable = tegra124_hsic_port_enable,
147253d2a715SThierry Reding 	.disable = tegra124_hsic_port_disable,
147353d2a715SThierry Reding 	.map = tegra124_hsic_port_map,
147453d2a715SThierry Reding };
147553d2a715SThierry Reding 
tegra124_usb3_port_enable(struct tegra_xusb_port * port)147653d2a715SThierry Reding static int tegra124_usb3_port_enable(struct tegra_xusb_port *port)
147753d2a715SThierry Reding {
147853d2a715SThierry Reding 	struct tegra_xusb_usb3_port *usb3 = to_usb3_port(port);
147953d2a715SThierry Reding 	struct tegra_xusb_padctl *padctl = port->padctl;
148053d2a715SThierry Reding 	struct tegra_xusb_lane *lane = usb3->base.lane;
148153d2a715SThierry Reding 	unsigned int index = port->index, offset;
148253d2a715SThierry Reding 	u32 value;
148353d2a715SThierry Reding 
148453d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP);
148553d2a715SThierry Reding 
148653d2a715SThierry Reding 	if (!usb3->internal)
148753d2a715SThierry Reding 		value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index);
148853d2a715SThierry Reding 	else
148953d2a715SThierry Reding 		value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index);
149053d2a715SThierry Reding 
149153d2a715SThierry Reding 	value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(index);
149253d2a715SThierry Reding 	value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(index, usb3->port);
149353d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP);
149453d2a715SThierry Reding 
149553d2a715SThierry Reding 	/*
149653d2a715SThierry Reding 	 * TODO: move this code into the PCIe/SATA PHY ->power_on() callbacks
149753d2a715SThierry Reding 	 * and conditionalize based on mux function? This seems to work, but
149853d2a715SThierry Reding 	 * might not be the exact proper sequence.
149953d2a715SThierry Reding 	 */
150053d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index));
150153d2a715SThierry Reding 	value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_MASK <<
150253d2a715SThierry Reding 		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT) |
150353d2a715SThierry Reding 		   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_MASK <<
150453d2a715SThierry Reding 		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT) |
150553d2a715SThierry Reding 		   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_MASK <<
150653d2a715SThierry Reding 		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT));
150753d2a715SThierry Reding 	value |= (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_VAL <<
150853d2a715SThierry Reding 		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT) |
150953d2a715SThierry Reding 		 (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_VAL <<
151053d2a715SThierry Reding 		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT) |
151153d2a715SThierry Reding 		 (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_VAL <<
151253d2a715SThierry Reding 		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT);
151353d2a715SThierry Reding 
151453d2a715SThierry Reding 	if (usb3->context_saved) {
151553d2a715SThierry Reding 		value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK <<
151653d2a715SThierry Reding 			    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) |
151753d2a715SThierry Reding 			   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK <<
151853d2a715SThierry Reding 			    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT));
151953d2a715SThierry Reding 		value |= (usb3->ctle_g <<
152053d2a715SThierry Reding 			  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) |
152153d2a715SThierry Reding 			 (usb3->ctle_z <<
152253d2a715SThierry Reding 			  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT);
152353d2a715SThierry Reding 	}
152453d2a715SThierry Reding 
152553d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index));
152653d2a715SThierry Reding 
152753d2a715SThierry Reding 	value = XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_VAL;
152853d2a715SThierry Reding 
152953d2a715SThierry Reding 	if (usb3->context_saved) {
153053d2a715SThierry Reding 		value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK <<
153153d2a715SThierry Reding 			    XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) |
153253d2a715SThierry Reding 			   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK <<
153353d2a715SThierry Reding 			    XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT));
153453d2a715SThierry Reding 		value |= (usb3->tap1 <<
153553d2a715SThierry Reding 			  XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) |
153653d2a715SThierry Reding 			 (usb3->amp <<
153753d2a715SThierry Reding 			  XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT);
153853d2a715SThierry Reding 	}
153953d2a715SThierry Reding 
154053d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(index));
154153d2a715SThierry Reding 
154253d2a715SThierry Reding 	if (lane->pad == padctl->pcie)
154353d2a715SThierry Reding 		offset = XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL2(lane->index);
154453d2a715SThierry Reding 	else
154553d2a715SThierry Reding 		offset = XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2;
154653d2a715SThierry Reding 
154753d2a715SThierry Reding 	value = padctl_readl(padctl, offset);
154853d2a715SThierry Reding 	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_MASK <<
154953d2a715SThierry Reding 		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT);
155053d2a715SThierry Reding 	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_VAL <<
155153d2a715SThierry Reding 		XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT;
155253d2a715SThierry Reding 	padctl_writel(padctl, value, offset);
155353d2a715SThierry Reding 
155453d2a715SThierry Reding 	if (lane->pad == padctl->pcie)
155553d2a715SThierry Reding 		offset = XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL5(lane->index);
155653d2a715SThierry Reding 	else
155753d2a715SThierry Reding 		offset = XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5;
155853d2a715SThierry Reding 
155953d2a715SThierry Reding 	value = padctl_readl(padctl, offset);
156053d2a715SThierry Reding 	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL5_RX_QEYE_EN;
156153d2a715SThierry Reding 	padctl_writel(padctl, value, offset);
156253d2a715SThierry Reding 
156353d2a715SThierry Reding 	/* Enable SATA PHY when SATA lane is used */
156453d2a715SThierry Reding 	if (lane->pad == padctl->sata) {
156553d2a715SThierry Reding 		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
156653d2a715SThierry Reding 		value &= ~(XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_MASK <<
156753d2a715SThierry Reding 			   XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT);
156853d2a715SThierry Reding 		value |= 0x2 <<
156953d2a715SThierry Reding 			XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT;
157053d2a715SThierry Reding 		padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
157153d2a715SThierry Reding 
157253d2a715SThierry Reding 		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL2);
157353d2a715SThierry Reding 		value &= ~((XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_MASK <<
157453d2a715SThierry Reding 			    XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT) |
157553d2a715SThierry Reding 			   (XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_MASK <<
157653d2a715SThierry Reding 			    XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT) |
157753d2a715SThierry Reding 			   (XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_MASK <<
157853d2a715SThierry Reding 			    XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT) |
157953d2a715SThierry Reding 			   XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TCLKOUT_EN);
158053d2a715SThierry Reding 		value |= (0x7 <<
158153d2a715SThierry Reding 			  XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT) |
158253d2a715SThierry Reding 			 (0x8 <<
158353d2a715SThierry Reding 			  XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT) |
158453d2a715SThierry Reding 			 (0x8 <<
158553d2a715SThierry Reding 			  XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT) |
158653d2a715SThierry Reding 			 XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TXCLKREF_SEL;
158753d2a715SThierry Reding 		padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL2);
158853d2a715SThierry Reding 
158953d2a715SThierry Reding 		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL3);
159053d2a715SThierry Reding 		value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL3_RCAL_BYPASS;
159153d2a715SThierry Reding 		padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL3);
159253d2a715SThierry Reding 	}
159353d2a715SThierry Reding 
159453d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
159553d2a715SThierry Reding 	value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(index);
159653d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
159753d2a715SThierry Reding 
159853d2a715SThierry Reding 	usleep_range(100, 200);
159953d2a715SThierry Reding 
160053d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
160153d2a715SThierry Reding 	value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(index);
160253d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
160353d2a715SThierry Reding 
160453d2a715SThierry Reding 	usleep_range(100, 200);
160553d2a715SThierry Reding 
160653d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
160753d2a715SThierry Reding 	value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(index);
160853d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
160953d2a715SThierry Reding 
1610e4d5973fSVivek Gautam 	return 0;
161153d2a715SThierry Reding }
161253d2a715SThierry Reding 
tegra124_usb3_port_disable(struct tegra_xusb_port * port)161353d2a715SThierry Reding static void tegra124_usb3_port_disable(struct tegra_xusb_port *port)
161453d2a715SThierry Reding {
161553d2a715SThierry Reding 	struct tegra_xusb_padctl *padctl = port->padctl;
161653d2a715SThierry Reding 	u32 value;
161753d2a715SThierry Reding 
161853d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
161953d2a715SThierry Reding 	value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(port->index);
162053d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
162153d2a715SThierry Reding 
162253d2a715SThierry Reding 	usleep_range(100, 200);
162353d2a715SThierry Reding 
162453d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
162553d2a715SThierry Reding 	value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(port->index);
162653d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
162753d2a715SThierry Reding 
162853d2a715SThierry Reding 	usleep_range(250, 350);
162953d2a715SThierry Reding 
163053d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
163153d2a715SThierry Reding 	value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(port->index);
163253d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
163353d2a715SThierry Reding 
163453d2a715SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP);
163553d2a715SThierry Reding 	value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(port->index);
163653d2a715SThierry Reding 	value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(port->index, 0x7);
163753d2a715SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP);
163853d2a715SThierry Reding }
163953d2a715SThierry Reding 
164053d2a715SThierry Reding static const struct tegra_xusb_lane_map tegra124_usb3_map[] = {
164153d2a715SThierry Reding 	{ 0, "pcie", 0 },
164253d2a715SThierry Reding 	{ 1, "pcie", 1 },
164353d2a715SThierry Reding 	{ 1, "sata", 0 },
164453d2a715SThierry Reding 	{ 0, NULL,   0 },
164553d2a715SThierry Reding };
164653d2a715SThierry Reding 
164753d2a715SThierry Reding static struct tegra_xusb_lane *
tegra124_usb3_port_map(struct tegra_xusb_port * port)164853d2a715SThierry Reding tegra124_usb3_port_map(struct tegra_xusb_port *port)
164953d2a715SThierry Reding {
165053d2a715SThierry Reding 	return tegra_xusb_port_find_lane(port, tegra124_usb3_map, "usb3-ss");
165153d2a715SThierry Reding }
165253d2a715SThierry Reding 
165353d2a715SThierry Reding static const struct tegra_xusb_port_ops tegra124_usb3_port_ops = {
1654e78fdbadSThierry Reding 	.release = tegra_xusb_usb3_port_release,
165553d2a715SThierry Reding 	.enable = tegra124_usb3_port_enable,
165653d2a715SThierry Reding 	.disable = tegra124_usb3_port_disable,
165753d2a715SThierry Reding 	.map = tegra124_usb3_port_map,
165853d2a715SThierry Reding };
165953d2a715SThierry Reding 
166053d2a715SThierry Reding static int
tegra124_xusb_read_fuse_calibration(struct tegra124_xusb_fuse_calibration * fuse)166153d2a715SThierry Reding tegra124_xusb_read_fuse_calibration(struct tegra124_xusb_fuse_calibration *fuse)
166253d2a715SThierry Reding {
166353d2a715SThierry Reding 	unsigned int i;
166453d2a715SThierry Reding 	int err;
166553d2a715SThierry Reding 	u32 value;
166653d2a715SThierry Reding 
166753d2a715SThierry Reding 	err = tegra_fuse_readl(TEGRA_FUSE_SKU_CALIB_0, &value);
166853d2a715SThierry Reding 	if (err < 0)
166953d2a715SThierry Reding 		return err;
167053d2a715SThierry Reding 
167153d2a715SThierry Reding 	for (i = 0; i < ARRAY_SIZE(fuse->hs_curr_level); i++) {
167253d2a715SThierry Reding 		fuse->hs_curr_level[i] =
167353d2a715SThierry Reding 			(value >> FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(i)) &
167453d2a715SThierry Reding 			FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK;
167553d2a715SThierry Reding 	}
167653d2a715SThierry Reding 	fuse->hs_iref_cap =
167753d2a715SThierry Reding 		(value >> FUSE_SKU_CALIB_HS_IREF_CAP_SHIFT) &
167853d2a715SThierry Reding 		FUSE_SKU_CALIB_HS_IREF_CAP_MASK;
167953d2a715SThierry Reding 	fuse->hs_term_range_adj =
168053d2a715SThierry Reding 		(value >> FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT) &
168153d2a715SThierry Reding 		FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK;
168253d2a715SThierry Reding 	fuse->hs_squelch_level =
168353d2a715SThierry Reding 		(value >> FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_SHIFT) &
168453d2a715SThierry Reding 		FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_MASK;
168553d2a715SThierry Reding 
168653d2a715SThierry Reding 	return 0;
168753d2a715SThierry Reding }
168853d2a715SThierry Reding 
168953d2a715SThierry Reding static struct tegra_xusb_padctl *
tegra124_xusb_padctl_probe(struct device * dev,const struct tegra_xusb_padctl_soc * soc)169053d2a715SThierry Reding tegra124_xusb_padctl_probe(struct device *dev,
169153d2a715SThierry Reding 			   const struct tegra_xusb_padctl_soc *soc)
169253d2a715SThierry Reding {
169353d2a715SThierry Reding 	struct tegra124_xusb_padctl *padctl;
169453d2a715SThierry Reding 	int err;
169553d2a715SThierry Reding 
169653d2a715SThierry Reding 	padctl = devm_kzalloc(dev, sizeof(*padctl), GFP_KERNEL);
169753d2a715SThierry Reding 	if (!padctl)
169853d2a715SThierry Reding 		return ERR_PTR(-ENOMEM);
169953d2a715SThierry Reding 
170053d2a715SThierry Reding 	padctl->base.dev = dev;
170153d2a715SThierry Reding 	padctl->base.soc = soc;
170253d2a715SThierry Reding 
170353d2a715SThierry Reding 	err = tegra124_xusb_read_fuse_calibration(&padctl->fuse);
170453d2a715SThierry Reding 	if (err < 0)
170553d2a715SThierry Reding 		return ERR_PTR(err);
170653d2a715SThierry Reding 
170753d2a715SThierry Reding 	return &padctl->base;
170853d2a715SThierry Reding }
170953d2a715SThierry Reding 
tegra124_xusb_padctl_remove(struct tegra_xusb_padctl * padctl)171053d2a715SThierry Reding static void tegra124_xusb_padctl_remove(struct tegra_xusb_padctl *padctl)
171153d2a715SThierry Reding {
171253d2a715SThierry Reding }
171353d2a715SThierry Reding 
171453d2a715SThierry Reding static const struct tegra_xusb_padctl_ops tegra124_xusb_padctl_ops = {
171553d2a715SThierry Reding 	.probe = tegra124_xusb_padctl_probe,
171653d2a715SThierry Reding 	.remove = tegra124_xusb_padctl_remove,
171753d2a715SThierry Reding 	.usb3_save_context = tegra124_usb3_save_context,
171853d2a715SThierry Reding 	.hsic_set_idle = tegra124_hsic_set_idle,
171953d2a715SThierry Reding };
172053d2a715SThierry Reding 
1721aa5452f5SThierry Reding static const char * const tegra124_xusb_padctl_supply_names[] = {
1722aa5452f5SThierry Reding 	"avdd-pll-utmip",
1723aa5452f5SThierry Reding 	"avdd-pll-erefe",
1724aa5452f5SThierry Reding 	"avdd-pex-pll",
1725aa5452f5SThierry Reding 	"hvdd-pex-pll-e",
1726aa5452f5SThierry Reding };
1727aa5452f5SThierry Reding 
172853d2a715SThierry Reding const struct tegra_xusb_padctl_soc tegra124_xusb_padctl_soc = {
172953d2a715SThierry Reding 	.num_pads = ARRAY_SIZE(tegra124_pads),
173053d2a715SThierry Reding 	.pads = tegra124_pads,
173153d2a715SThierry Reding 	.ports = {
173253d2a715SThierry Reding 		.usb2 = {
173353d2a715SThierry Reding 			.ops = &tegra124_usb2_port_ops,
173453d2a715SThierry Reding 			.count = 3,
173553d2a715SThierry Reding 		},
173653d2a715SThierry Reding 		.ulpi = {
173753d2a715SThierry Reding 			.ops = &tegra124_ulpi_port_ops,
173853d2a715SThierry Reding 			.count = 1,
173953d2a715SThierry Reding 		},
174053d2a715SThierry Reding 		.hsic = {
174153d2a715SThierry Reding 			.ops = &tegra124_hsic_port_ops,
174253d2a715SThierry Reding 			.count = 2,
174353d2a715SThierry Reding 		},
174453d2a715SThierry Reding 		.usb3 = {
174553d2a715SThierry Reding 			.ops = &tegra124_usb3_port_ops,
174653d2a715SThierry Reding 			.count = 2,
174753d2a715SThierry Reding 		},
174853d2a715SThierry Reding 	},
174953d2a715SThierry Reding 	.ops = &tegra124_xusb_padctl_ops,
1750aa5452f5SThierry Reding 	.supply_names = tegra124_xusb_padctl_supply_names,
1751aa5452f5SThierry Reding 	.num_supplies = ARRAY_SIZE(tegra124_xusb_padctl_supply_names),
175253d2a715SThierry Reding };
175353d2a715SThierry Reding EXPORT_SYMBOL_GPL(tegra124_xusb_padctl_soc);
175453d2a715SThierry Reding 
175553d2a715SThierry Reding MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
175653d2a715SThierry Reding MODULE_DESCRIPTION("NVIDIA Tegra 124 XUSB Pad Controller driver");
175753d2a715SThierry Reding MODULE_LICENSE("GPL v2");
1758