xref: /linux/drivers/phy/tegra/xusb-tegra210.c (revision 2025cf9e193de05b0654570dd639acb49ebd3adf)
1*2025cf9eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
287d66f28SThierry Reding /*
387d66f28SThierry Reding  * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
487d66f28SThierry Reding  * Copyright (C) 2015 Google, Inc.
587d66f28SThierry Reding  */
687d66f28SThierry Reding 
787d66f28SThierry Reding #include <linux/clk.h>
887d66f28SThierry Reding #include <linux/clk/tegra.h>
987d66f28SThierry Reding #include <linux/delay.h>
1087d66f28SThierry Reding #include <linux/io.h>
1187d66f28SThierry Reding #include <linux/mailbox_client.h>
1287d66f28SThierry Reding #include <linux/module.h>
1387d66f28SThierry Reding #include <linux/of.h>
1487d66f28SThierry Reding #include <linux/phy/phy.h>
1587d66f28SThierry Reding #include <linux/platform_device.h>
1687d66f28SThierry Reding #include <linux/regulator/consumer.h>
1787d66f28SThierry Reding #include <linux/reset.h>
1887d66f28SThierry Reding #include <linux/slab.h>
1987d66f28SThierry Reding 
2087d66f28SThierry Reding #include <soc/tegra/fuse.h>
2187d66f28SThierry Reding 
2287d66f28SThierry Reding #include "xusb.h"
2387d66f28SThierry Reding 
2487d66f28SThierry Reding #define FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(x) \
2587d66f28SThierry Reding 					((x) ? (11 + ((x) - 1) * 6) : 0)
2687d66f28SThierry Reding #define FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK 0x3f
2787d66f28SThierry Reding #define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT 7
2887d66f28SThierry Reding #define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK 0xf
2987d66f28SThierry Reding 
3087d66f28SThierry Reding #define FUSE_USB_CALIB_EXT_RPD_CTRL_SHIFT 0
3187d66f28SThierry Reding #define FUSE_USB_CALIB_EXT_RPD_CTRL_MASK 0x1f
3287d66f28SThierry Reding 
3387d66f28SThierry Reding #define XUSB_PADCTL_USB2_PAD_MUX 0x004
3487d66f28SThierry Reding #define XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_SHIFT 16
3587d66f28SThierry Reding #define XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_MASK 0x3
3687d66f28SThierry Reding #define XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_XUSB 0x1
3787d66f28SThierry Reding #define XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_SHIFT 18
3887d66f28SThierry Reding #define XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_MASK 0x3
3987d66f28SThierry Reding #define XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_XUSB 0x1
4087d66f28SThierry Reding 
4187d66f28SThierry Reding #define XUSB_PADCTL_USB2_PORT_CAP 0x008
4287d66f28SThierry Reding #define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_HOST(x) (0x1 << ((x) * 4))
4387d66f28SThierry Reding #define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_MASK(x) (0x3 << ((x) * 4))
4487d66f28SThierry Reding 
4587d66f28SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP 0x014
4687d66f28SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(x) (1 << (((x) * 5) + 4))
4787d66f28SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_SHIFT(x) ((x) * 5)
4887d66f28SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(x) (0x7 << ((x) * 5))
4987d66f28SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(x, v) (((v) & 0x7) << ((x) * 5))
5087d66f28SThierry Reding 
5187d66f28SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM1 0x024
5287d66f28SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN (1 << 31)
5387d66f28SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 30)
5487d66f28SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN (1 << 29)
5587d66f28SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN(x) (1 << (2 + (x) * 3))
5687d66f28SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(x) \
5787d66f28SThierry Reding 							(1 << (1 + (x) * 3))
5887d66f28SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(x) (1 << ((x) * 3))
5987d66f28SThierry Reding 
6087d66f28SThierry Reding #define XUSB_PADCTL_USB3_PAD_MUX 0x028
6187d66f28SThierry Reding #define XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(x) (1 << (1 + (x)))
6287d66f28SThierry Reding #define XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(x) (1 << (8 + (x)))
6387d66f28SThierry Reding 
6487d66f28SThierry Reding #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(x) (0x084 + (x) * 0x40)
6587d66f28SThierry Reding #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_SHIFT 7
6687d66f28SThierry Reding #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_MASK 0x3
6787d66f28SThierry Reding #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_FIX18 (1 << 6)
6887d66f28SThierry Reding 
6987d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PADX_CTL0(x) (0x088 + (x) * 0x40)
7087d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI (1 << 29)
7187d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 (1 << 27)
7287d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD (1 << 26)
7387d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT 0
7487d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK 0x3f
7587d66f28SThierry Reding 
7687d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PADX_CTL1(x) (0x08c + (x) * 0x40)
7787d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_SHIFT 26
7887d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_MASK 0x1f
7987d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT 3
8087d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK 0xf
8187d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR (1 << 2)
8287d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_OVRD (1 << 1)
8387d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_OVRD (1 << 0)
8487d66f28SThierry Reding 
8587d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0 0x284
8687d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD (1 << 11)
8787d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT 3
8887d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK 0x7
8987d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL 0x7
9087d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT 0
9187d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK 0x7
9287d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_VAL 0x2
9387d66f28SThierry Reding 
9487d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1 0x288
9587d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_PD_TRK (1 << 26)
9687d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_SHIFT 19
9787d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_MASK 0x7f
9887d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_VAL 0x0a
9987d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_SHIFT 12
10087d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_MASK 0x7f
10187d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_VAL 0x1e
10287d66f28SThierry Reding 
10387d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PADX_CTL0(x) (0x300 + (x) * 0x20)
10487d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE (1 << 18)
10587d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA1 (1 << 17)
10687d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA0 (1 << 16)
10787d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_RPD_STROBE (1 << 15)
10887d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA1 (1 << 14)
10987d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA0 (1 << 13)
11087d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_STROBE (1 << 9)
11187d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA1 (1 << 8)
11287d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA0 (1 << 7)
11387d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_STROBE (1 << 6)
11487d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA1 (1 << 5)
11587d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA0 (1 << 4)
11687d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_STROBE (1 << 3)
11787d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA1 (1 << 2)
11887d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA0 (1 << 1)
11987d66f28SThierry Reding 
12087d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PADX_CTL1(x) (0x304 + (x) * 0x20)
12187d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_SHIFT 0
12287d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_MASK 0xf
12387d66f28SThierry Reding 
12487d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PADX_CTL2(x) (0x308 + (x) * 0x20)
12587d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT 8
12687d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK 0xf
12787d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT 0
12887d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK 0xff
12987d66f28SThierry Reding 
13087d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_TRK_CTL 0x340
13187d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_TRK_CTL_PD_TRK (1 << 19)
13287d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_SHIFT 12
13387d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_MASK 0x7f
13487d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_VAL 0x0a
13587d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_SHIFT 5
13687d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_MASK 0x7f
13787d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_VAL 0x1e
13887d66f28SThierry Reding 
13987d66f28SThierry Reding #define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL 0x344
14087d66f28SThierry Reding 
14187d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_P0_CTL1 0x360
14287d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT 20
14387d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_MASK 0xff
14487d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_USB_VAL 0x19
14587d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SATA_VAL 0x1e
14687d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_SHIFT 16
14787d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_MASK 0x3
14887d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_LOCKDET_STATUS (1 << 15)
14987d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD (1 << 4)
15087d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_ENABLE (1 << 3)
15187d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_SHIFT 1
15287d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_MASK 0x3
15387d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_IDDQ (1 << 0)
15487d66f28SThierry Reding 
15587d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_P0_CTL2 0x364
15687d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT 4
15787d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_MASK 0xffffff
15887d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_VAL 0x136
15987d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD (1 << 2)
16087d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE (1 << 1)
16187d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN (1 << 0)
16287d66f28SThierry Reding 
16387d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_P0_CTL4 0x36c
164e7f4da4cSThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL4_XDIGCLK_EN (1 << 19)
16587d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_EN (1 << 15)
16687d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT 12
16787d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_MASK 0x3
16887d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_USB_VAL 0x2
16987d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SATA_VAL 0x0
17087d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL4_REFCLKBUF_EN (1 << 8)
17187d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_SHIFT 4
17287d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_MASK 0xf
17387d66f28SThierry Reding 
17487d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_P0_CTL5 0x370
17587d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT 16
17687d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_MASK 0xff
17787d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_VAL 0x2a
17887d66f28SThierry Reding 
17987d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_P0_CTL8 0x37c
18087d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE (1 << 31)
18187d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD (1 << 15)
18287d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN (1 << 13)
18387d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN (1 << 12)
18487d66f28SThierry Reding 
18587d66f28SThierry Reding #define XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL1(x) (0x460 + (x) * 0x40)
18687d66f28SThierry Reding #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_SHIFT 20
18787d66f28SThierry Reding #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_MASK 0x3
18887d66f28SThierry Reding #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_VAL 0x1
18987d66f28SThierry Reding #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_TERM_EN BIT(18)
19087d66f28SThierry Reding #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_MODE_OVRD BIT(13)
19187d66f28SThierry Reding 
19287d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_S0_CTL1 0x860
19387d66f28SThierry Reding 
19487d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_S0_CTL2 0x864
19587d66f28SThierry Reding 
19687d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_S0_CTL4 0x86c
19787d66f28SThierry Reding 
19887d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_S0_CTL5 0x870
19987d66f28SThierry Reding 
20087d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_S0_CTL8 0x87c
20187d66f28SThierry Reding 
20287d66f28SThierry Reding #define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL1 0x960
20387d66f28SThierry Reding 
20487d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(x) (0xa60 + (x) * 0x40)
20587d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT 16
20687d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_MASK 0x3
20787d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_VAL 0x2
20887d66f28SThierry Reding 
20987d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PADX_ECTL2(x) (0xa64 + (x) * 0x40)
21087d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_SHIFT 0
21187d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_MASK 0xffff
21287d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_VAL 0x00fc
21387d66f28SThierry Reding 
21487d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PADX_ECTL3(x) (0xa68 + (x) * 0x40)
21587d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL3_RX_DFE_VAL 0xc0077f1f
21687d66f28SThierry Reding 
21787d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PADX_ECTL4(x) (0xa6c + (x) * 0x40)
21887d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_SHIFT 16
21987d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_MASK 0xffff
22087d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_VAL 0x01c7
22187d66f28SThierry Reding 
22287d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PADX_ECTL6(x) (0xa74 + (x) * 0x40)
22387d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL6_RX_EQ_CTRL_H_VAL 0xfcf01368
22487d66f28SThierry Reding 
22587d66f28SThierry Reding struct tegra210_xusb_fuse_calibration {
22687d66f28SThierry Reding 	u32 hs_curr_level[4];
22787d66f28SThierry Reding 	u32 hs_term_range_adj;
22887d66f28SThierry Reding 	u32 rpd_ctrl;
22987d66f28SThierry Reding };
23087d66f28SThierry Reding 
23187d66f28SThierry Reding struct tegra210_xusb_padctl {
23287d66f28SThierry Reding 	struct tegra_xusb_padctl base;
23387d66f28SThierry Reding 
23487d66f28SThierry Reding 	struct tegra210_xusb_fuse_calibration fuse;
23587d66f28SThierry Reding };
23687d66f28SThierry Reding 
23787d66f28SThierry Reding static inline struct tegra210_xusb_padctl *
23887d66f28SThierry Reding to_tegra210_xusb_padctl(struct tegra_xusb_padctl *padctl)
23987d66f28SThierry Reding {
24087d66f28SThierry Reding 	return container_of(padctl, struct tegra210_xusb_padctl, base);
24187d66f28SThierry Reding }
24287d66f28SThierry Reding 
24387d66f28SThierry Reding /* must be called under padctl->lock */
24487d66f28SThierry Reding static int tegra210_pex_uphy_enable(struct tegra_xusb_padctl *padctl)
24587d66f28SThierry Reding {
24687d66f28SThierry Reding 	struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(padctl->pcie);
24787d66f28SThierry Reding 	unsigned long timeout;
24887d66f28SThierry Reding 	u32 value;
24987d66f28SThierry Reding 	int err;
25087d66f28SThierry Reding 
25187d66f28SThierry Reding 	if (pcie->enable > 0) {
25287d66f28SThierry Reding 		pcie->enable++;
25387d66f28SThierry Reding 		return 0;
25487d66f28SThierry Reding 	}
25587d66f28SThierry Reding 
25687d66f28SThierry Reding 	err = clk_prepare_enable(pcie->pll);
25787d66f28SThierry Reding 	if (err < 0)
25887d66f28SThierry Reding 		return err;
25987d66f28SThierry Reding 
26087d66f28SThierry Reding 	err = reset_control_deassert(pcie->rst);
26187d66f28SThierry Reding 	if (err < 0)
26287d66f28SThierry Reding 		goto disable;
26387d66f28SThierry Reding 
26487d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
26587d66f28SThierry Reding 	value &= ~(XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_MASK <<
26687d66f28SThierry Reding 		   XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT);
26787d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_VAL <<
26887d66f28SThierry Reding 		 XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT;
26987d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
27087d66f28SThierry Reding 
27187d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL5);
27287d66f28SThierry Reding 	value &= ~(XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_MASK <<
27387d66f28SThierry Reding 		   XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT);
27487d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_VAL <<
27587d66f28SThierry Reding 		 XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT;
27687d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL5);
27787d66f28SThierry Reding 
27887d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
27987d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD;
28087d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
28187d66f28SThierry Reding 
28287d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
28387d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD;
28487d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
28587d66f28SThierry Reding 
28687d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
28787d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD;
28887d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
28987d66f28SThierry Reding 
29087d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL4);
29187d66f28SThierry Reding 	value &= ~((XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_MASK <<
29287d66f28SThierry Reding 		    XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT) |
29387d66f28SThierry Reding 		   (XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_MASK <<
29487d66f28SThierry Reding 		    XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_SHIFT));
29587d66f28SThierry Reding 	value |= (XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_USB_VAL <<
29687d66f28SThierry Reding 		  XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT) |
29787d66f28SThierry Reding 		 XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_EN;
29887d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL4);
29987d66f28SThierry Reding 
30087d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
30187d66f28SThierry Reding 	value &= ~((XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_MASK <<
30287d66f28SThierry Reding 		    XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_SHIFT) |
30387d66f28SThierry Reding 		   (XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_MASK <<
30487d66f28SThierry Reding 		    XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT));
30587d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_USB_VAL <<
30687d66f28SThierry Reding 		 XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT;
30787d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
30887d66f28SThierry Reding 
30987d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
31087d66f28SThierry Reding 	value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_IDDQ;
31187d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
31287d66f28SThierry Reding 
31387d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
31487d66f28SThierry Reding 	value &= ~(XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_MASK <<
31587d66f28SThierry Reding 		   XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_SHIFT);
31687d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
31787d66f28SThierry Reding 
31887d66f28SThierry Reding 	usleep_range(10, 20);
31987d66f28SThierry Reding 
32087d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL4);
32187d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_PLL_CTL4_REFCLKBUF_EN;
32287d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL4);
32387d66f28SThierry Reding 
32487d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
32587d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN;
32687d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
32787d66f28SThierry Reding 
32887d66f28SThierry Reding 	timeout = jiffies + msecs_to_jiffies(100);
32987d66f28SThierry Reding 
33087d66f28SThierry Reding 	while (time_before(jiffies, timeout)) {
33187d66f28SThierry Reding 		value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
33287d66f28SThierry Reding 		if (value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE)
33387d66f28SThierry Reding 			break;
33487d66f28SThierry Reding 
33587d66f28SThierry Reding 		usleep_range(10, 20);
33687d66f28SThierry Reding 	}
33787d66f28SThierry Reding 
33887d66f28SThierry Reding 	if (time_after_eq(jiffies, timeout)) {
33987d66f28SThierry Reding 		err = -ETIMEDOUT;
34087d66f28SThierry Reding 		goto reset;
34187d66f28SThierry Reding 	}
34287d66f28SThierry Reding 
34387d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
34487d66f28SThierry Reding 	value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN;
34587d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
34687d66f28SThierry Reding 
34787d66f28SThierry Reding 	timeout = jiffies + msecs_to_jiffies(100);
34887d66f28SThierry Reding 
34987d66f28SThierry Reding 	while (time_before(jiffies, timeout)) {
35087d66f28SThierry Reding 		value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
35187d66f28SThierry Reding 		if (!(value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE))
35287d66f28SThierry Reding 			break;
35387d66f28SThierry Reding 
35487d66f28SThierry Reding 		usleep_range(10, 20);
35587d66f28SThierry Reding 	}
35687d66f28SThierry Reding 
35787d66f28SThierry Reding 	if (time_after_eq(jiffies, timeout)) {
35887d66f28SThierry Reding 		err = -ETIMEDOUT;
35987d66f28SThierry Reding 		goto reset;
36087d66f28SThierry Reding 	}
36187d66f28SThierry Reding 
36287d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
36387d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_PLL_CTL1_ENABLE;
36487d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
36587d66f28SThierry Reding 
36687d66f28SThierry Reding 	timeout = jiffies + msecs_to_jiffies(100);
36787d66f28SThierry Reding 
36887d66f28SThierry Reding 	while (time_before(jiffies, timeout)) {
36987d66f28SThierry Reding 		value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
37087d66f28SThierry Reding 		if (value & XUSB_PADCTL_UPHY_PLL_CTL1_LOCKDET_STATUS)
37187d66f28SThierry Reding 			break;
37287d66f28SThierry Reding 
37387d66f28SThierry Reding 		usleep_range(10, 20);
37487d66f28SThierry Reding 	}
37587d66f28SThierry Reding 
37687d66f28SThierry Reding 	if (time_after_eq(jiffies, timeout)) {
37787d66f28SThierry Reding 		err = -ETIMEDOUT;
37887d66f28SThierry Reding 		goto reset;
37987d66f28SThierry Reding 	}
38087d66f28SThierry Reding 
38187d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
38287d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN |
38387d66f28SThierry Reding 		 XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN;
38487d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
38587d66f28SThierry Reding 
38687d66f28SThierry Reding 	timeout = jiffies + msecs_to_jiffies(100);
38787d66f28SThierry Reding 
38887d66f28SThierry Reding 	while (time_before(jiffies, timeout)) {
38987d66f28SThierry Reding 		value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
39087d66f28SThierry Reding 		if (value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE)
39187d66f28SThierry Reding 			break;
39287d66f28SThierry Reding 
39387d66f28SThierry Reding 		usleep_range(10, 20);
39487d66f28SThierry Reding 	}
39587d66f28SThierry Reding 
39687d66f28SThierry Reding 	if (time_after_eq(jiffies, timeout)) {
39787d66f28SThierry Reding 		err = -ETIMEDOUT;
39887d66f28SThierry Reding 		goto reset;
39987d66f28SThierry Reding 	}
40087d66f28SThierry Reding 
40187d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
40287d66f28SThierry Reding 	value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN;
40387d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
40487d66f28SThierry Reding 
40587d66f28SThierry Reding 	timeout = jiffies + msecs_to_jiffies(100);
40687d66f28SThierry Reding 
40787d66f28SThierry Reding 	while (time_before(jiffies, timeout)) {
40887d66f28SThierry Reding 		value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
40987d66f28SThierry Reding 		if (!(value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE))
41087d66f28SThierry Reding 			break;
41187d66f28SThierry Reding 
41287d66f28SThierry Reding 		usleep_range(10, 20);
41387d66f28SThierry Reding 	}
41487d66f28SThierry Reding 
41587d66f28SThierry Reding 	if (time_after_eq(jiffies, timeout)) {
41687d66f28SThierry Reding 		err = -ETIMEDOUT;
41787d66f28SThierry Reding 		goto reset;
41887d66f28SThierry Reding 	}
41987d66f28SThierry Reding 
42087d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
42187d66f28SThierry Reding 	value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN;
42287d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
42387d66f28SThierry Reding 
42487d66f28SThierry Reding 	tegra210_xusb_pll_hw_control_enable();
42587d66f28SThierry Reding 
42687d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
42787d66f28SThierry Reding 	value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD;
42887d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
42987d66f28SThierry Reding 
43087d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
43187d66f28SThierry Reding 	value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD;
43287d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
43387d66f28SThierry Reding 
43487d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
43587d66f28SThierry Reding 	value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD;
43687d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
43787d66f28SThierry Reding 
43887d66f28SThierry Reding 	usleep_range(10, 20);
43987d66f28SThierry Reding 
44087d66f28SThierry Reding 	tegra210_xusb_pll_hw_sequence_start();
44187d66f28SThierry Reding 
44287d66f28SThierry Reding 	pcie->enable++;
44387d66f28SThierry Reding 
44487d66f28SThierry Reding 	return 0;
44587d66f28SThierry Reding 
44687d66f28SThierry Reding reset:
44787d66f28SThierry Reding 	reset_control_assert(pcie->rst);
44887d66f28SThierry Reding disable:
44987d66f28SThierry Reding 	clk_disable_unprepare(pcie->pll);
45087d66f28SThierry Reding 	return err;
45187d66f28SThierry Reding }
45287d66f28SThierry Reding 
45387d66f28SThierry Reding static void tegra210_pex_uphy_disable(struct tegra_xusb_padctl *padctl)
45487d66f28SThierry Reding {
45587d66f28SThierry Reding 	struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(padctl->pcie);
45687d66f28SThierry Reding 
45787d66f28SThierry Reding 	mutex_lock(&padctl->lock);
45887d66f28SThierry Reding 
45987d66f28SThierry Reding 	if (WARN_ON(pcie->enable == 0))
46087d66f28SThierry Reding 		goto unlock;
46187d66f28SThierry Reding 
46287d66f28SThierry Reding 	if (--pcie->enable > 0)
46387d66f28SThierry Reding 		goto unlock;
46487d66f28SThierry Reding 
46587d66f28SThierry Reding 	reset_control_assert(pcie->rst);
46687d66f28SThierry Reding 	clk_disable_unprepare(pcie->pll);
46787d66f28SThierry Reding 
46887d66f28SThierry Reding unlock:
46987d66f28SThierry Reding 	mutex_unlock(&padctl->lock);
47087d66f28SThierry Reding }
47187d66f28SThierry Reding 
47287d66f28SThierry Reding /* must be called under padctl->lock */
47387d66f28SThierry Reding static int tegra210_sata_uphy_enable(struct tegra_xusb_padctl *padctl, bool usb)
47487d66f28SThierry Reding {
47587d66f28SThierry Reding 	struct tegra_xusb_sata_pad *sata = to_sata_pad(padctl->sata);
47687d66f28SThierry Reding 	unsigned long timeout;
47787d66f28SThierry Reding 	u32 value;
47887d66f28SThierry Reding 	int err;
47987d66f28SThierry Reding 
48087d66f28SThierry Reding 	if (sata->enable > 0) {
48187d66f28SThierry Reding 		sata->enable++;
48287d66f28SThierry Reding 		return 0;
48387d66f28SThierry Reding 	}
48487d66f28SThierry Reding 
48587d66f28SThierry Reding 	err = clk_prepare_enable(sata->pll);
48687d66f28SThierry Reding 	if (err < 0)
48787d66f28SThierry Reding 		return err;
48887d66f28SThierry Reding 
48987d66f28SThierry Reding 	err = reset_control_deassert(sata->rst);
49087d66f28SThierry Reding 	if (err < 0)
49187d66f28SThierry Reding 		goto disable;
49287d66f28SThierry Reding 
49387d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
49487d66f28SThierry Reding 	value &= ~(XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_MASK <<
49587d66f28SThierry Reding 		   XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT);
49687d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_VAL <<
49787d66f28SThierry Reding 		 XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT;
49887d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
49987d66f28SThierry Reding 
50087d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL5);
50187d66f28SThierry Reding 	value &= ~(XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_MASK <<
50287d66f28SThierry Reding 		   XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT);
50387d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_VAL <<
50487d66f28SThierry Reding 		 XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT;
50587d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL5);
50687d66f28SThierry Reding 
50787d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
50887d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD;
50987d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
51087d66f28SThierry Reding 
51187d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
51287d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD;
51387d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
51487d66f28SThierry Reding 
51587d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
51687d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD;
51787d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
51887d66f28SThierry Reding 
51987d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL4);
52087d66f28SThierry Reding 	value &= ~((XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_MASK <<
52187d66f28SThierry Reding 		    XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT) |
52287d66f28SThierry Reding 		   (XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_MASK <<
52387d66f28SThierry Reding 		    XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_SHIFT));
52487d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_EN;
52587d66f28SThierry Reding 
52687d66f28SThierry Reding 	if (usb)
52787d66f28SThierry Reding 		value |= (XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_USB_VAL <<
52887d66f28SThierry Reding 			  XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT);
52987d66f28SThierry Reding 	else
53087d66f28SThierry Reding 		value |= (XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SATA_VAL <<
53187d66f28SThierry Reding 			  XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT);
53287d66f28SThierry Reding 
533e7f4da4cSThierry Reding 	value &= ~XUSB_PADCTL_UPHY_PLL_CTL4_XDIGCLK_EN;
53487d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL4);
53587d66f28SThierry Reding 
53687d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
53787d66f28SThierry Reding 	value &= ~((XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_MASK <<
53887d66f28SThierry Reding 		    XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_SHIFT) |
53987d66f28SThierry Reding 		   (XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_MASK <<
54087d66f28SThierry Reding 		    XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT));
54187d66f28SThierry Reding 
54287d66f28SThierry Reding 	if (usb)
54387d66f28SThierry Reding 		value |= XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_USB_VAL <<
54487d66f28SThierry Reding 			 XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT;
54587d66f28SThierry Reding 	else
54687d66f28SThierry Reding 		value |= XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SATA_VAL <<
54787d66f28SThierry Reding 			 XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT;
54887d66f28SThierry Reding 
54987d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
55087d66f28SThierry Reding 
55187d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
55287d66f28SThierry Reding 	value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_IDDQ;
55387d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
55487d66f28SThierry Reding 
55587d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
55687d66f28SThierry Reding 	value &= ~(XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_MASK <<
55787d66f28SThierry Reding 		   XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_SHIFT);
55887d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
55987d66f28SThierry Reding 
56087d66f28SThierry Reding 	usleep_range(10, 20);
56187d66f28SThierry Reding 
56287d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL4);
56387d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_PLL_CTL4_REFCLKBUF_EN;
56487d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL4);
56587d66f28SThierry Reding 
56687d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
56787d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN;
56887d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
56987d66f28SThierry Reding 
57087d66f28SThierry Reding 	timeout = jiffies + msecs_to_jiffies(100);
57187d66f28SThierry Reding 
57287d66f28SThierry Reding 	while (time_before(jiffies, timeout)) {
57387d66f28SThierry Reding 		value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
57487d66f28SThierry Reding 		if (value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE)
57587d66f28SThierry Reding 			break;
57687d66f28SThierry Reding 
57787d66f28SThierry Reding 		usleep_range(10, 20);
57887d66f28SThierry Reding 	}
57987d66f28SThierry Reding 
58087d66f28SThierry Reding 	if (time_after_eq(jiffies, timeout)) {
58187d66f28SThierry Reding 		err = -ETIMEDOUT;
58287d66f28SThierry Reding 		goto reset;
58387d66f28SThierry Reding 	}
58487d66f28SThierry Reding 
58587d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
58687d66f28SThierry Reding 	value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN;
58787d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
58887d66f28SThierry Reding 
58987d66f28SThierry Reding 	timeout = jiffies + msecs_to_jiffies(100);
59087d66f28SThierry Reding 
59187d66f28SThierry Reding 	while (time_before(jiffies, timeout)) {
59287d66f28SThierry Reding 		value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
59387d66f28SThierry Reding 		if (!(value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE))
59487d66f28SThierry Reding 			break;
59587d66f28SThierry Reding 
59687d66f28SThierry Reding 		usleep_range(10, 20);
59787d66f28SThierry Reding 	}
59887d66f28SThierry Reding 
59987d66f28SThierry Reding 	if (time_after_eq(jiffies, timeout)) {
60087d66f28SThierry Reding 		err = -ETIMEDOUT;
60187d66f28SThierry Reding 		goto reset;
60287d66f28SThierry Reding 	}
60387d66f28SThierry Reding 
60487d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
60587d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_PLL_CTL1_ENABLE;
60687d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
60787d66f28SThierry Reding 
60887d66f28SThierry Reding 	timeout = jiffies + msecs_to_jiffies(100);
60987d66f28SThierry Reding 
61087d66f28SThierry Reding 	while (time_before(jiffies, timeout)) {
61187d66f28SThierry Reding 		value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
61287d66f28SThierry Reding 		if (value & XUSB_PADCTL_UPHY_PLL_CTL1_LOCKDET_STATUS)
61387d66f28SThierry Reding 			break;
61487d66f28SThierry Reding 
61587d66f28SThierry Reding 		usleep_range(10, 20);
61687d66f28SThierry Reding 	}
61787d66f28SThierry Reding 
61887d66f28SThierry Reding 	if (time_after_eq(jiffies, timeout)) {
61987d66f28SThierry Reding 		err = -ETIMEDOUT;
62087d66f28SThierry Reding 		goto reset;
62187d66f28SThierry Reding 	}
62287d66f28SThierry Reding 
62387d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
62487d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN |
62587d66f28SThierry Reding 		 XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN;
62687d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
62787d66f28SThierry Reding 
62887d66f28SThierry Reding 	timeout = jiffies + msecs_to_jiffies(100);
62987d66f28SThierry Reding 
63087d66f28SThierry Reding 	while (time_before(jiffies, timeout)) {
63187d66f28SThierry Reding 		value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
63287d66f28SThierry Reding 		if (value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE)
63387d66f28SThierry Reding 			break;
63487d66f28SThierry Reding 
63587d66f28SThierry Reding 		usleep_range(10, 20);
63687d66f28SThierry Reding 	}
63787d66f28SThierry Reding 
63887d66f28SThierry Reding 	if (time_after_eq(jiffies, timeout)) {
63987d66f28SThierry Reding 		err = -ETIMEDOUT;
64087d66f28SThierry Reding 		goto reset;
64187d66f28SThierry Reding 	}
64287d66f28SThierry Reding 
64387d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
64487d66f28SThierry Reding 	value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN;
64587d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
64687d66f28SThierry Reding 
64787d66f28SThierry Reding 	timeout = jiffies + msecs_to_jiffies(100);
64887d66f28SThierry Reding 
64987d66f28SThierry Reding 	while (time_before(jiffies, timeout)) {
65087d66f28SThierry Reding 		value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
65187d66f28SThierry Reding 		if (!(value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE))
65287d66f28SThierry Reding 			break;
65387d66f28SThierry Reding 
65487d66f28SThierry Reding 		usleep_range(10, 20);
65587d66f28SThierry Reding 	}
65687d66f28SThierry Reding 
65787d66f28SThierry Reding 	if (time_after_eq(jiffies, timeout)) {
65887d66f28SThierry Reding 		err = -ETIMEDOUT;
65987d66f28SThierry Reding 		goto reset;
66087d66f28SThierry Reding 	}
66187d66f28SThierry Reding 
66287d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
66387d66f28SThierry Reding 	value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN;
66487d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
66587d66f28SThierry Reding 
66687d66f28SThierry Reding 	tegra210_sata_pll_hw_control_enable();
66787d66f28SThierry Reding 
66887d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
66987d66f28SThierry Reding 	value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD;
67087d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
67187d66f28SThierry Reding 
67287d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
67387d66f28SThierry Reding 	value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD;
67487d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
67587d66f28SThierry Reding 
67687d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
67787d66f28SThierry Reding 	value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD;
67887d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
67987d66f28SThierry Reding 
68087d66f28SThierry Reding 	usleep_range(10, 20);
68187d66f28SThierry Reding 
68287d66f28SThierry Reding 	tegra210_sata_pll_hw_sequence_start();
68387d66f28SThierry Reding 
68487d66f28SThierry Reding 	sata->enable++;
68587d66f28SThierry Reding 
68687d66f28SThierry Reding 	return 0;
68787d66f28SThierry Reding 
68887d66f28SThierry Reding reset:
68987d66f28SThierry Reding 	reset_control_assert(sata->rst);
69087d66f28SThierry Reding disable:
69187d66f28SThierry Reding 	clk_disable_unprepare(sata->pll);
69287d66f28SThierry Reding 	return err;
69387d66f28SThierry Reding }
69487d66f28SThierry Reding 
69587d66f28SThierry Reding static void tegra210_sata_uphy_disable(struct tegra_xusb_padctl *padctl)
69687d66f28SThierry Reding {
69787d66f28SThierry Reding 	struct tegra_xusb_sata_pad *sata = to_sata_pad(padctl->sata);
69887d66f28SThierry Reding 
69987d66f28SThierry Reding 	mutex_lock(&padctl->lock);
70087d66f28SThierry Reding 
70187d66f28SThierry Reding 	if (WARN_ON(sata->enable == 0))
70287d66f28SThierry Reding 		goto unlock;
70387d66f28SThierry Reding 
70487d66f28SThierry Reding 	if (--sata->enable > 0)
70587d66f28SThierry Reding 		goto unlock;
70687d66f28SThierry Reding 
70787d66f28SThierry Reding 	reset_control_assert(sata->rst);
70887d66f28SThierry Reding 	clk_disable_unprepare(sata->pll);
70987d66f28SThierry Reding 
71087d66f28SThierry Reding unlock:
71187d66f28SThierry Reding 	mutex_unlock(&padctl->lock);
71287d66f28SThierry Reding }
71387d66f28SThierry Reding 
71487d66f28SThierry Reding static int tegra210_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
71587d66f28SThierry Reding {
71687d66f28SThierry Reding 	u32 value;
71787d66f28SThierry Reding 
71887d66f28SThierry Reding 	mutex_lock(&padctl->lock);
71987d66f28SThierry Reding 
72087d66f28SThierry Reding 	if (padctl->enable++ > 0)
72187d66f28SThierry Reding 		goto out;
72287d66f28SThierry Reding 
72387d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
72487d66f28SThierry Reding 	value &= ~XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN;
72587d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
72687d66f28SThierry Reding 
72787d66f28SThierry Reding 	usleep_range(100, 200);
72887d66f28SThierry Reding 
72987d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
73087d66f28SThierry Reding 	value &= ~XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY;
73187d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
73287d66f28SThierry Reding 
73387d66f28SThierry Reding 	usleep_range(100, 200);
73487d66f28SThierry Reding 
73587d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
73687d66f28SThierry Reding 	value &= ~XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN;
73787d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
73887d66f28SThierry Reding 
73987d66f28SThierry Reding out:
74087d66f28SThierry Reding 	mutex_unlock(&padctl->lock);
74187d66f28SThierry Reding 	return 0;
74287d66f28SThierry Reding }
74387d66f28SThierry Reding 
74487d66f28SThierry Reding static int tegra210_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
74587d66f28SThierry Reding {
74687d66f28SThierry Reding 	u32 value;
74787d66f28SThierry Reding 
74887d66f28SThierry Reding 	mutex_lock(&padctl->lock);
74987d66f28SThierry Reding 
75087d66f28SThierry Reding 	if (WARN_ON(padctl->enable == 0))
75187d66f28SThierry Reding 		goto out;
75287d66f28SThierry Reding 
75387d66f28SThierry Reding 	if (--padctl->enable > 0)
75487d66f28SThierry Reding 		goto out;
75587d66f28SThierry Reding 
75687d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
75787d66f28SThierry Reding 	value |= XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN;
75887d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
75987d66f28SThierry Reding 
76087d66f28SThierry Reding 	usleep_range(100, 200);
76187d66f28SThierry Reding 
76287d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
76387d66f28SThierry Reding 	value |= XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY;
76487d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
76587d66f28SThierry Reding 
76687d66f28SThierry Reding 	usleep_range(100, 200);
76787d66f28SThierry Reding 
76887d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
76987d66f28SThierry Reding 	value |= XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN;
77087d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
77187d66f28SThierry Reding 
77287d66f28SThierry Reding out:
77387d66f28SThierry Reding 	mutex_unlock(&padctl->lock);
77487d66f28SThierry Reding 	return 0;
77587d66f28SThierry Reding }
77687d66f28SThierry Reding 
77787d66f28SThierry Reding static int tegra210_hsic_set_idle(struct tegra_xusb_padctl *padctl,
77887d66f28SThierry Reding 				  unsigned int index, bool idle)
77987d66f28SThierry Reding {
78087d66f28SThierry Reding 	u32 value;
78187d66f28SThierry Reding 
78287d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(index));
78387d66f28SThierry Reding 
78487d66f28SThierry Reding 	value &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA0 |
78587d66f28SThierry Reding 		   XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA1 |
78687d66f28SThierry Reding 		   XUSB_PADCTL_HSIC_PAD_CTL0_RPD_STROBE);
78787d66f28SThierry Reding 
78887d66f28SThierry Reding 	if (idle)
78987d66f28SThierry Reding 		value |= XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA0 |
79087d66f28SThierry Reding 			 XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA1 |
79187d66f28SThierry Reding 			 XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE;
79287d66f28SThierry Reding 	else
79387d66f28SThierry Reding 		value &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA0 |
79487d66f28SThierry Reding 			   XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA1 |
79587d66f28SThierry Reding 			   XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE);
79687d66f28SThierry Reding 
79787d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL0(index));
79887d66f28SThierry Reding 
79987d66f28SThierry Reding 	return 0;
80087d66f28SThierry Reding }
80187d66f28SThierry Reding 
80287d66f28SThierry Reding static int tegra210_usb3_set_lfps_detect(struct tegra_xusb_padctl *padctl,
80387d66f28SThierry Reding 					 unsigned int index, bool enable)
80487d66f28SThierry Reding {
80587d66f28SThierry Reding 	struct tegra_xusb_port *port;
80687d66f28SThierry Reding 	struct tegra_xusb_lane *lane;
80787d66f28SThierry Reding 	u32 value, offset;
80887d66f28SThierry Reding 
80987d66f28SThierry Reding 	port = tegra_xusb_find_port(padctl, "usb3", index);
81087d66f28SThierry Reding 	if (!port)
81187d66f28SThierry Reding 		return -ENODEV;
81287d66f28SThierry Reding 
81387d66f28SThierry Reding 	lane = port->lane;
81487d66f28SThierry Reding 
81587d66f28SThierry Reding 	if (lane->pad == padctl->pcie)
81687d66f28SThierry Reding 		offset = XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL1(lane->index);
81787d66f28SThierry Reding 	else
81887d66f28SThierry Reding 		offset = XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL1;
81987d66f28SThierry Reding 
82087d66f28SThierry Reding 	value = padctl_readl(padctl, offset);
82187d66f28SThierry Reding 
82287d66f28SThierry Reding 	value &= ~((XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_MASK <<
82387d66f28SThierry Reding 		    XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_SHIFT) |
82487d66f28SThierry Reding 		   XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_TERM_EN |
82587d66f28SThierry Reding 		   XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_MODE_OVRD);
82687d66f28SThierry Reding 
82787d66f28SThierry Reding 	if (!enable) {
82887d66f28SThierry Reding 		value |= (XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_VAL <<
82987d66f28SThierry Reding 			  XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_SHIFT) |
83087d66f28SThierry Reding 			 XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_TERM_EN |
83187d66f28SThierry Reding 			 XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_MODE_OVRD;
83287d66f28SThierry Reding 	}
83387d66f28SThierry Reding 
83487d66f28SThierry Reding 	padctl_writel(padctl, value, offset);
83587d66f28SThierry Reding 
83687d66f28SThierry Reding 	return 0;
83787d66f28SThierry Reding }
83887d66f28SThierry Reding 
83987d66f28SThierry Reding #define TEGRA210_LANE(_name, _offset, _shift, _mask, _type)		\
84087d66f28SThierry Reding 	{								\
84187d66f28SThierry Reding 		.name = _name,						\
84287d66f28SThierry Reding 		.offset = _offset,					\
84387d66f28SThierry Reding 		.shift = _shift,					\
84487d66f28SThierry Reding 		.mask = _mask,						\
84587d66f28SThierry Reding 		.num_funcs = ARRAY_SIZE(tegra210_##_type##_functions),	\
84687d66f28SThierry Reding 		.funcs = tegra210_##_type##_functions,			\
84787d66f28SThierry Reding 	}
84887d66f28SThierry Reding 
84987d66f28SThierry Reding static const char *tegra210_usb2_functions[] = {
85087d66f28SThierry Reding 	"snps",
85187d66f28SThierry Reding 	"xusb",
85287d66f28SThierry Reding 	"uart"
85387d66f28SThierry Reding };
85487d66f28SThierry Reding 
85587d66f28SThierry Reding static const struct tegra_xusb_lane_soc tegra210_usb2_lanes[] = {
85687d66f28SThierry Reding 	TEGRA210_LANE("usb2-0", 0x004,  0, 0x3, usb2),
85787d66f28SThierry Reding 	TEGRA210_LANE("usb2-1", 0x004,  2, 0x3, usb2),
85887d66f28SThierry Reding 	TEGRA210_LANE("usb2-2", 0x004,  4, 0x3, usb2),
85987d66f28SThierry Reding 	TEGRA210_LANE("usb2-3", 0x004,  6, 0x3, usb2),
86087d66f28SThierry Reding };
86187d66f28SThierry Reding 
86287d66f28SThierry Reding static struct tegra_xusb_lane *
86387d66f28SThierry Reding tegra210_usb2_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np,
86487d66f28SThierry Reding 			 unsigned int index)
86587d66f28SThierry Reding {
86687d66f28SThierry Reding 	struct tegra_xusb_usb2_lane *usb2;
86787d66f28SThierry Reding 	int err;
86887d66f28SThierry Reding 
86987d66f28SThierry Reding 	usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL);
87087d66f28SThierry Reding 	if (!usb2)
87187d66f28SThierry Reding 		return ERR_PTR(-ENOMEM);
87287d66f28SThierry Reding 
87387d66f28SThierry Reding 	INIT_LIST_HEAD(&usb2->base.list);
87487d66f28SThierry Reding 	usb2->base.soc = &pad->soc->lanes[index];
87587d66f28SThierry Reding 	usb2->base.index = index;
87687d66f28SThierry Reding 	usb2->base.pad = pad;
87787d66f28SThierry Reding 	usb2->base.np = np;
87887d66f28SThierry Reding 
87987d66f28SThierry Reding 	err = tegra_xusb_lane_parse_dt(&usb2->base, np);
88087d66f28SThierry Reding 	if (err < 0) {
88187d66f28SThierry Reding 		kfree(usb2);
88287d66f28SThierry Reding 		return ERR_PTR(err);
88387d66f28SThierry Reding 	}
88487d66f28SThierry Reding 
88587d66f28SThierry Reding 	return &usb2->base;
88687d66f28SThierry Reding }
88787d66f28SThierry Reding 
88887d66f28SThierry Reding static void tegra210_usb2_lane_remove(struct tegra_xusb_lane *lane)
88987d66f28SThierry Reding {
89087d66f28SThierry Reding 	struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane);
89187d66f28SThierry Reding 
89287d66f28SThierry Reding 	kfree(usb2);
89387d66f28SThierry Reding }
89487d66f28SThierry Reding 
89587d66f28SThierry Reding static const struct tegra_xusb_lane_ops tegra210_usb2_lane_ops = {
89687d66f28SThierry Reding 	.probe = tegra210_usb2_lane_probe,
89787d66f28SThierry Reding 	.remove = tegra210_usb2_lane_remove,
89887d66f28SThierry Reding };
89987d66f28SThierry Reding 
90087d66f28SThierry Reding static int tegra210_usb2_phy_init(struct phy *phy)
90187d66f28SThierry Reding {
90287d66f28SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
90387d66f28SThierry Reding 	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
90487d66f28SThierry Reding 	u32 value;
90587d66f28SThierry Reding 
90687d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB2_PAD_MUX);
90787d66f28SThierry Reding 	value &= ~(XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_MASK <<
90887d66f28SThierry Reding 		   XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_SHIFT);
90987d66f28SThierry Reding 	value |= XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_XUSB <<
91087d66f28SThierry Reding 		 XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_SHIFT;
91187d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB2_PAD_MUX);
91287d66f28SThierry Reding 
91387d66f28SThierry Reding 	return tegra210_xusb_padctl_enable(padctl);
91487d66f28SThierry Reding }
91587d66f28SThierry Reding 
91687d66f28SThierry Reding static int tegra210_usb2_phy_exit(struct phy *phy)
91787d66f28SThierry Reding {
91887d66f28SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
91987d66f28SThierry Reding 
92087d66f28SThierry Reding 	return tegra210_xusb_padctl_disable(lane->pad->padctl);
92187d66f28SThierry Reding }
92287d66f28SThierry Reding 
92387d66f28SThierry Reding static int tegra210_usb2_phy_power_on(struct phy *phy)
92487d66f28SThierry Reding {
92587d66f28SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
92687d66f28SThierry Reding 	struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane);
92787d66f28SThierry Reding 	struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad);
92887d66f28SThierry Reding 	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
92987d66f28SThierry Reding 	struct tegra210_xusb_padctl *priv;
93087d66f28SThierry Reding 	struct tegra_xusb_usb2_port *port;
93187d66f28SThierry Reding 	unsigned int index = lane->index;
93287d66f28SThierry Reding 	u32 value;
93387d66f28SThierry Reding 	int err;
93487d66f28SThierry Reding 
93587d66f28SThierry Reding 	port = tegra_xusb_find_usb2_port(padctl, index);
93687d66f28SThierry Reding 	if (!port) {
93787d66f28SThierry Reding 		dev_err(&phy->dev, "no port found for USB2 lane %u\n", index);
93887d66f28SThierry Reding 		return -ENODEV;
93987d66f28SThierry Reding 	}
94087d66f28SThierry Reding 
94187d66f28SThierry Reding 	priv = to_tegra210_xusb_padctl(padctl);
94287d66f28SThierry Reding 
94387d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
94487d66f28SThierry Reding 	value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK <<
94587d66f28SThierry Reding 		    XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) |
94687d66f28SThierry Reding 		   (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK <<
94787d66f28SThierry Reding 		    XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT));
94887d66f28SThierry Reding 	value |= (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL <<
94987d66f28SThierry Reding 		  XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT);
95087d66f28SThierry Reding 
95187d66f28SThierry Reding 	if (tegra_sku_info.revision < TEGRA_REVISION_A02)
95287d66f28SThierry Reding 		value |=
95387d66f28SThierry Reding 			(XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_VAL <<
95487d66f28SThierry Reding 			XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT);
95587d66f28SThierry Reding 
95687d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
95787d66f28SThierry Reding 
95887d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB2_PORT_CAP);
95987d66f28SThierry Reding 	value &= ~XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_MASK(index);
96087d66f28SThierry Reding 	value |= XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_HOST(index);
96187d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB2_PORT_CAP);
96287d66f28SThierry Reding 
96387d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index));
96487d66f28SThierry Reding 	value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK <<
96587d66f28SThierry Reding 		    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT) |
96687d66f28SThierry Reding 		   XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD |
96787d66f28SThierry Reding 		   XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 |
96887d66f28SThierry Reding 		   XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI);
96987d66f28SThierry Reding 	value |= (priv->fuse.hs_curr_level[index] +
97087d66f28SThierry Reding 		  usb2->hs_curr_level_offset) <<
97187d66f28SThierry Reding 		 XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT;
97287d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index));
97387d66f28SThierry Reding 
97487d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index));
97587d66f28SThierry Reding 	value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK <<
97687d66f28SThierry Reding 		    XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) |
97787d66f28SThierry Reding 		   (XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_MASK <<
97887d66f28SThierry Reding 		    XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_SHIFT) |
97987d66f28SThierry Reding 		   XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR |
98087d66f28SThierry Reding 		   XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_OVRD |
98187d66f28SThierry Reding 		   XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_OVRD);
98287d66f28SThierry Reding 	value |= (priv->fuse.hs_term_range_adj <<
98387d66f28SThierry Reding 		  XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) |
98487d66f28SThierry Reding 		 (priv->fuse.rpd_ctrl <<
98587d66f28SThierry Reding 		  XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_SHIFT);
98687d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index));
98787d66f28SThierry Reding 
98887d66f28SThierry Reding 	value = padctl_readl(padctl,
98987d66f28SThierry Reding 			     XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(index));
99087d66f28SThierry Reding 	value &= ~(XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_MASK <<
99187d66f28SThierry Reding 		   XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_SHIFT);
99287d66f28SThierry Reding 	value |= XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_FIX18;
99387d66f28SThierry Reding 	padctl_writel(padctl, value,
99487d66f28SThierry Reding 		      XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(index));
99587d66f28SThierry Reding 
99687d66f28SThierry Reding 	err = regulator_enable(port->supply);
99787d66f28SThierry Reding 	if (err)
99887d66f28SThierry Reding 		return err;
99987d66f28SThierry Reding 
100087d66f28SThierry Reding 	mutex_lock(&padctl->lock);
100187d66f28SThierry Reding 
100287d66f28SThierry Reding 	if (pad->enable > 0) {
100387d66f28SThierry Reding 		pad->enable++;
100487d66f28SThierry Reding 		mutex_unlock(&padctl->lock);
100587d66f28SThierry Reding 		return 0;
100687d66f28SThierry Reding 	}
100787d66f28SThierry Reding 
100887d66f28SThierry Reding 	err = clk_prepare_enable(pad->clk);
100987d66f28SThierry Reding 	if (err)
101087d66f28SThierry Reding 		goto disable_regulator;
101187d66f28SThierry Reding 
101287d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
101387d66f28SThierry Reding 	value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_MASK <<
101487d66f28SThierry Reding 		    XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_SHIFT) |
101587d66f28SThierry Reding 		   (XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_MASK <<
101687d66f28SThierry Reding 		    XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_SHIFT));
101787d66f28SThierry Reding 	value |= (XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_VAL <<
101887d66f28SThierry Reding 		  XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_SHIFT) |
101987d66f28SThierry Reding 		 (XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_VAL <<
102087d66f28SThierry Reding 		  XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_SHIFT);
102187d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
102287d66f28SThierry Reding 
102387d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
102487d66f28SThierry Reding 	value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD;
102587d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
102687d66f28SThierry Reding 
102787d66f28SThierry Reding 	udelay(1);
102887d66f28SThierry Reding 
102987d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
103087d66f28SThierry Reding 	value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL1_PD_TRK;
103187d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
103287d66f28SThierry Reding 
103387d66f28SThierry Reding 	udelay(50);
103487d66f28SThierry Reding 
103587d66f28SThierry Reding 	clk_disable_unprepare(pad->clk);
103687d66f28SThierry Reding 
103787d66f28SThierry Reding 	pad->enable++;
103887d66f28SThierry Reding 	mutex_unlock(&padctl->lock);
103987d66f28SThierry Reding 
104087d66f28SThierry Reding 	return 0;
104187d66f28SThierry Reding 
104287d66f28SThierry Reding disable_regulator:
104387d66f28SThierry Reding 	regulator_disable(port->supply);
104487d66f28SThierry Reding 	mutex_unlock(&padctl->lock);
104587d66f28SThierry Reding 	return err;
104687d66f28SThierry Reding }
104787d66f28SThierry Reding 
104887d66f28SThierry Reding static int tegra210_usb2_phy_power_off(struct phy *phy)
104987d66f28SThierry Reding {
105087d66f28SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
105187d66f28SThierry Reding 	struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad);
105287d66f28SThierry Reding 	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
105387d66f28SThierry Reding 	struct tegra_xusb_usb2_port *port;
105487d66f28SThierry Reding 	u32 value;
105587d66f28SThierry Reding 
105687d66f28SThierry Reding 	port = tegra_xusb_find_usb2_port(padctl, lane->index);
105787d66f28SThierry Reding 	if (!port) {
105887d66f28SThierry Reding 		dev_err(&phy->dev, "no port found for USB2 lane %u\n",
105987d66f28SThierry Reding 			lane->index);
106087d66f28SThierry Reding 		return -ENODEV;
106187d66f28SThierry Reding 	}
106287d66f28SThierry Reding 
106387d66f28SThierry Reding 	mutex_lock(&padctl->lock);
106487d66f28SThierry Reding 
106587d66f28SThierry Reding 	if (WARN_ON(pad->enable == 0))
106687d66f28SThierry Reding 		goto out;
106787d66f28SThierry Reding 
106887d66f28SThierry Reding 	if (--pad->enable > 0)
106987d66f28SThierry Reding 		goto out;
107087d66f28SThierry Reding 
107187d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
107287d66f28SThierry Reding 	value |= XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD;
107387d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
107487d66f28SThierry Reding 
107587d66f28SThierry Reding out:
107687d66f28SThierry Reding 	regulator_disable(port->supply);
107787d66f28SThierry Reding 	mutex_unlock(&padctl->lock);
107887d66f28SThierry Reding 	return 0;
107987d66f28SThierry Reding }
108087d66f28SThierry Reding 
108187d66f28SThierry Reding static const struct phy_ops tegra210_usb2_phy_ops = {
108287d66f28SThierry Reding 	.init = tegra210_usb2_phy_init,
108387d66f28SThierry Reding 	.exit = tegra210_usb2_phy_exit,
108487d66f28SThierry Reding 	.power_on = tegra210_usb2_phy_power_on,
108587d66f28SThierry Reding 	.power_off = tegra210_usb2_phy_power_off,
108687d66f28SThierry Reding 	.owner = THIS_MODULE,
108787d66f28SThierry Reding };
108887d66f28SThierry Reding 
108987d66f28SThierry Reding static struct tegra_xusb_pad *
109087d66f28SThierry Reding tegra210_usb2_pad_probe(struct tegra_xusb_padctl *padctl,
109187d66f28SThierry Reding 			const struct tegra_xusb_pad_soc *soc,
109287d66f28SThierry Reding 			struct device_node *np)
109387d66f28SThierry Reding {
109487d66f28SThierry Reding 	struct tegra_xusb_usb2_pad *usb2;
109587d66f28SThierry Reding 	struct tegra_xusb_pad *pad;
109687d66f28SThierry Reding 	int err;
109787d66f28SThierry Reding 
109887d66f28SThierry Reding 	usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL);
109987d66f28SThierry Reding 	if (!usb2)
110087d66f28SThierry Reding 		return ERR_PTR(-ENOMEM);
110187d66f28SThierry Reding 
110287d66f28SThierry Reding 	pad = &usb2->base;
110387d66f28SThierry Reding 	pad->ops = &tegra210_usb2_lane_ops;
110487d66f28SThierry Reding 	pad->soc = soc;
110587d66f28SThierry Reding 
110687d66f28SThierry Reding 	err = tegra_xusb_pad_init(pad, padctl, np);
110787d66f28SThierry Reding 	if (err < 0) {
110887d66f28SThierry Reding 		kfree(usb2);
110987d66f28SThierry Reding 		goto out;
111087d66f28SThierry Reding 	}
111187d66f28SThierry Reding 
111287d66f28SThierry Reding 	usb2->clk = devm_clk_get(&pad->dev, "trk");
111387d66f28SThierry Reding 	if (IS_ERR(usb2->clk)) {
111487d66f28SThierry Reding 		err = PTR_ERR(usb2->clk);
111587d66f28SThierry Reding 		dev_err(&pad->dev, "failed to get trk clock: %d\n", err);
111687d66f28SThierry Reding 		goto unregister;
111787d66f28SThierry Reding 	}
111887d66f28SThierry Reding 
111987d66f28SThierry Reding 	err = tegra_xusb_pad_register(pad, &tegra210_usb2_phy_ops);
112087d66f28SThierry Reding 	if (err < 0)
112187d66f28SThierry Reding 		goto unregister;
112287d66f28SThierry Reding 
112387d66f28SThierry Reding 	dev_set_drvdata(&pad->dev, pad);
112487d66f28SThierry Reding 
112587d66f28SThierry Reding 	return pad;
112687d66f28SThierry Reding 
112787d66f28SThierry Reding unregister:
112887d66f28SThierry Reding 	device_unregister(&pad->dev);
112987d66f28SThierry Reding out:
113087d66f28SThierry Reding 	return ERR_PTR(err);
113187d66f28SThierry Reding }
113287d66f28SThierry Reding 
113387d66f28SThierry Reding static void tegra210_usb2_pad_remove(struct tegra_xusb_pad *pad)
113487d66f28SThierry Reding {
113587d66f28SThierry Reding 	struct tegra_xusb_usb2_pad *usb2 = to_usb2_pad(pad);
113687d66f28SThierry Reding 
113787d66f28SThierry Reding 	kfree(usb2);
113887d66f28SThierry Reding }
113987d66f28SThierry Reding 
114087d66f28SThierry Reding static const struct tegra_xusb_pad_ops tegra210_usb2_ops = {
114187d66f28SThierry Reding 	.probe = tegra210_usb2_pad_probe,
114287d66f28SThierry Reding 	.remove = tegra210_usb2_pad_remove,
114387d66f28SThierry Reding };
114487d66f28SThierry Reding 
114587d66f28SThierry Reding static const struct tegra_xusb_pad_soc tegra210_usb2_pad = {
114687d66f28SThierry Reding 	.name = "usb2",
114787d66f28SThierry Reding 	.num_lanes = ARRAY_SIZE(tegra210_usb2_lanes),
114887d66f28SThierry Reding 	.lanes = tegra210_usb2_lanes,
114987d66f28SThierry Reding 	.ops = &tegra210_usb2_ops,
115087d66f28SThierry Reding };
115187d66f28SThierry Reding 
115287d66f28SThierry Reding static const char *tegra210_hsic_functions[] = {
115387d66f28SThierry Reding 	"snps",
115487d66f28SThierry Reding 	"xusb",
115587d66f28SThierry Reding };
115687d66f28SThierry Reding 
115787d66f28SThierry Reding static const struct tegra_xusb_lane_soc tegra210_hsic_lanes[] = {
115887d66f28SThierry Reding 	TEGRA210_LANE("hsic-0", 0x004, 14, 0x1, hsic),
115987d66f28SThierry Reding };
116087d66f28SThierry Reding 
116187d66f28SThierry Reding static struct tegra_xusb_lane *
116287d66f28SThierry Reding tegra210_hsic_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np,
116387d66f28SThierry Reding 			 unsigned int index)
116487d66f28SThierry Reding {
116587d66f28SThierry Reding 	struct tegra_xusb_hsic_lane *hsic;
116687d66f28SThierry Reding 	int err;
116787d66f28SThierry Reding 
116887d66f28SThierry Reding 	hsic = kzalloc(sizeof(*hsic), GFP_KERNEL);
116987d66f28SThierry Reding 	if (!hsic)
117087d66f28SThierry Reding 		return ERR_PTR(-ENOMEM);
117187d66f28SThierry Reding 
117287d66f28SThierry Reding 	INIT_LIST_HEAD(&hsic->base.list);
117387d66f28SThierry Reding 	hsic->base.soc = &pad->soc->lanes[index];
117487d66f28SThierry Reding 	hsic->base.index = index;
117587d66f28SThierry Reding 	hsic->base.pad = pad;
117687d66f28SThierry Reding 	hsic->base.np = np;
117787d66f28SThierry Reding 
117887d66f28SThierry Reding 	err = tegra_xusb_lane_parse_dt(&hsic->base, np);
117987d66f28SThierry Reding 	if (err < 0) {
118087d66f28SThierry Reding 		kfree(hsic);
118187d66f28SThierry Reding 		return ERR_PTR(err);
118287d66f28SThierry Reding 	}
118387d66f28SThierry Reding 
118487d66f28SThierry Reding 	return &hsic->base;
118587d66f28SThierry Reding }
118687d66f28SThierry Reding 
118787d66f28SThierry Reding static void tegra210_hsic_lane_remove(struct tegra_xusb_lane *lane)
118887d66f28SThierry Reding {
118987d66f28SThierry Reding 	struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane);
119087d66f28SThierry Reding 
119187d66f28SThierry Reding 	kfree(hsic);
119287d66f28SThierry Reding }
119387d66f28SThierry Reding 
119487d66f28SThierry Reding static const struct tegra_xusb_lane_ops tegra210_hsic_lane_ops = {
119587d66f28SThierry Reding 	.probe = tegra210_hsic_lane_probe,
119687d66f28SThierry Reding 	.remove = tegra210_hsic_lane_remove,
119787d66f28SThierry Reding };
119887d66f28SThierry Reding 
119987d66f28SThierry Reding static int tegra210_hsic_phy_init(struct phy *phy)
120087d66f28SThierry Reding {
120187d66f28SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
120287d66f28SThierry Reding 	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
120387d66f28SThierry Reding 	u32 value;
120487d66f28SThierry Reding 
120587d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB2_PAD_MUX);
120687d66f28SThierry Reding 	value &= ~(XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_MASK <<
120787d66f28SThierry Reding 		   XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_SHIFT);
120887d66f28SThierry Reding 	value |= XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_XUSB <<
120987d66f28SThierry Reding 		 XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_SHIFT;
121087d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB2_PAD_MUX);
121187d66f28SThierry Reding 
121287d66f28SThierry Reding 	return tegra210_xusb_padctl_enable(padctl);
121387d66f28SThierry Reding }
121487d66f28SThierry Reding 
121587d66f28SThierry Reding static int tegra210_hsic_phy_exit(struct phy *phy)
121687d66f28SThierry Reding {
121787d66f28SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
121887d66f28SThierry Reding 
121987d66f28SThierry Reding 	return tegra210_xusb_padctl_disable(lane->pad->padctl);
122087d66f28SThierry Reding }
122187d66f28SThierry Reding 
122287d66f28SThierry Reding static int tegra210_hsic_phy_power_on(struct phy *phy)
122387d66f28SThierry Reding {
122487d66f28SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
122587d66f28SThierry Reding 	struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane);
122687d66f28SThierry Reding 	struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad);
122787d66f28SThierry Reding 	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
122887d66f28SThierry Reding 	struct tegra210_xusb_padctl *priv;
122987d66f28SThierry Reding 	unsigned int index = lane->index;
123087d66f28SThierry Reding 	u32 value;
123187d66f28SThierry Reding 	int err;
123287d66f28SThierry Reding 
123387d66f28SThierry Reding 	priv = to_tegra210_xusb_padctl(padctl);
123487d66f28SThierry Reding 
123587d66f28SThierry Reding 	err = regulator_enable(pad->supply);
123687d66f28SThierry Reding 	if (err)
123787d66f28SThierry Reding 		return err;
123887d66f28SThierry Reding 
123987d66f28SThierry Reding 	padctl_writel(padctl, hsic->strobe_trim,
124087d66f28SThierry Reding 		      XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL);
124187d66f28SThierry Reding 
124287d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index));
124387d66f28SThierry Reding 	value &= ~(XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_MASK <<
124487d66f28SThierry Reding 		   XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_SHIFT);
124587d66f28SThierry Reding 	value |= (hsic->tx_rtune_p <<
124687d66f28SThierry Reding 		  XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_SHIFT);
124787d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index));
124887d66f28SThierry Reding 
124987d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL2(index));
125087d66f28SThierry Reding 	value &= ~((XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK <<
125187d66f28SThierry Reding 		    XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) |
125287d66f28SThierry Reding 		   (XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK <<
125387d66f28SThierry Reding 		    XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT));
125487d66f28SThierry Reding 	value |= (hsic->rx_strobe_trim <<
125587d66f28SThierry Reding 		  XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) |
125687d66f28SThierry Reding 		 (hsic->rx_data_trim <<
125787d66f28SThierry Reding 		  XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT);
125887d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL2(index));
125987d66f28SThierry Reding 
126087d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(index));
126187d66f28SThierry Reding 	value &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA0 |
126287d66f28SThierry Reding 		   XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA1 |
126387d66f28SThierry Reding 		   XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE |
126487d66f28SThierry Reding 		   XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA0 |
126587d66f28SThierry Reding 		   XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA1 |
126687d66f28SThierry Reding 		   XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_STROBE |
126787d66f28SThierry Reding 		   XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA0 |
126887d66f28SThierry Reding 		   XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA1 |
126987d66f28SThierry Reding 		   XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_STROBE |
127087d66f28SThierry Reding 		   XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA0 |
127187d66f28SThierry Reding 		   XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA1 |
127287d66f28SThierry Reding 		   XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_STROBE);
127387d66f28SThierry Reding 	value |= XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA0 |
127487d66f28SThierry Reding 		 XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA1 |
127587d66f28SThierry Reding 		 XUSB_PADCTL_HSIC_PAD_CTL0_RPD_STROBE;
127687d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL0(index));
127787d66f28SThierry Reding 
127887d66f28SThierry Reding 	err = clk_prepare_enable(pad->clk);
127987d66f28SThierry Reding 	if (err)
128087d66f28SThierry Reding 		goto disable;
128187d66f28SThierry Reding 
128287d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PAD_TRK_CTL);
128387d66f28SThierry Reding 	value &= ~((XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_MASK <<
128487d66f28SThierry Reding 		    XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_SHIFT) |
128587d66f28SThierry Reding 		   (XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_MASK <<
128687d66f28SThierry Reding 		    XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_SHIFT));
128787d66f28SThierry Reding 	value |= (XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_VAL <<
128887d66f28SThierry Reding 		  XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_SHIFT) |
128987d66f28SThierry Reding 		 (XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_VAL <<
129087d66f28SThierry Reding 		  XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_SHIFT);
129187d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PAD_TRK_CTL);
129287d66f28SThierry Reding 
129387d66f28SThierry Reding 	udelay(1);
129487d66f28SThierry Reding 
129587d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PAD_TRK_CTL);
129687d66f28SThierry Reding 	value &= ~XUSB_PADCTL_HSIC_PAD_TRK_CTL_PD_TRK;
129787d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PAD_TRK_CTL);
129887d66f28SThierry Reding 
129987d66f28SThierry Reding 	udelay(50);
130087d66f28SThierry Reding 
130187d66f28SThierry Reding 	clk_disable_unprepare(pad->clk);
130287d66f28SThierry Reding 
130387d66f28SThierry Reding 	return 0;
130487d66f28SThierry Reding 
130587d66f28SThierry Reding disable:
130687d66f28SThierry Reding 	regulator_disable(pad->supply);
130787d66f28SThierry Reding 	return err;
130887d66f28SThierry Reding }
130987d66f28SThierry Reding 
131087d66f28SThierry Reding static int tegra210_hsic_phy_power_off(struct phy *phy)
131187d66f28SThierry Reding {
131287d66f28SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
131387d66f28SThierry Reding 	struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad);
131487d66f28SThierry Reding 	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
131587d66f28SThierry Reding 	unsigned int index = lane->index;
131687d66f28SThierry Reding 	u32 value;
131787d66f28SThierry Reding 
131887d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(index));
131987d66f28SThierry Reding 	value |= XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA0 |
132087d66f28SThierry Reding 		 XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA1 |
132187d66f28SThierry Reding 		 XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_STROBE |
132287d66f28SThierry Reding 		 XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA0 |
132387d66f28SThierry Reding 		 XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA1 |
132487d66f28SThierry Reding 		 XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_STROBE |
132587d66f28SThierry Reding 		 XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA0 |
132687d66f28SThierry Reding 		 XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA1 |
132787d66f28SThierry Reding 		 XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_STROBE;
132887d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index));
132987d66f28SThierry Reding 
133087d66f28SThierry Reding 	regulator_disable(pad->supply);
133187d66f28SThierry Reding 
133287d66f28SThierry Reding 	return 0;
133387d66f28SThierry Reding }
133487d66f28SThierry Reding 
133587d66f28SThierry Reding static const struct phy_ops tegra210_hsic_phy_ops = {
133687d66f28SThierry Reding 	.init = tegra210_hsic_phy_init,
133787d66f28SThierry Reding 	.exit = tegra210_hsic_phy_exit,
133887d66f28SThierry Reding 	.power_on = tegra210_hsic_phy_power_on,
133987d66f28SThierry Reding 	.power_off = tegra210_hsic_phy_power_off,
134087d66f28SThierry Reding 	.owner = THIS_MODULE,
134187d66f28SThierry Reding };
134287d66f28SThierry Reding 
134387d66f28SThierry Reding static struct tegra_xusb_pad *
134487d66f28SThierry Reding tegra210_hsic_pad_probe(struct tegra_xusb_padctl *padctl,
134587d66f28SThierry Reding 			const struct tegra_xusb_pad_soc *soc,
134687d66f28SThierry Reding 			struct device_node *np)
134787d66f28SThierry Reding {
134887d66f28SThierry Reding 	struct tegra_xusb_hsic_pad *hsic;
134987d66f28SThierry Reding 	struct tegra_xusb_pad *pad;
135087d66f28SThierry Reding 	int err;
135187d66f28SThierry Reding 
135287d66f28SThierry Reding 	hsic = kzalloc(sizeof(*hsic), GFP_KERNEL);
135387d66f28SThierry Reding 	if (!hsic)
135487d66f28SThierry Reding 		return ERR_PTR(-ENOMEM);
135587d66f28SThierry Reding 
135687d66f28SThierry Reding 	pad = &hsic->base;
135787d66f28SThierry Reding 	pad->ops = &tegra210_hsic_lane_ops;
135887d66f28SThierry Reding 	pad->soc = soc;
135987d66f28SThierry Reding 
136087d66f28SThierry Reding 	err = tegra_xusb_pad_init(pad, padctl, np);
136187d66f28SThierry Reding 	if (err < 0) {
136287d66f28SThierry Reding 		kfree(hsic);
136387d66f28SThierry Reding 		goto out;
136487d66f28SThierry Reding 	}
136587d66f28SThierry Reding 
136687d66f28SThierry Reding 	hsic->clk = devm_clk_get(&pad->dev, "trk");
136787d66f28SThierry Reding 	if (IS_ERR(hsic->clk)) {
136887d66f28SThierry Reding 		err = PTR_ERR(hsic->clk);
136987d66f28SThierry Reding 		dev_err(&pad->dev, "failed to get trk clock: %d\n", err);
137087d66f28SThierry Reding 		goto unregister;
137187d66f28SThierry Reding 	}
137287d66f28SThierry Reding 
137387d66f28SThierry Reding 	err = tegra_xusb_pad_register(pad, &tegra210_hsic_phy_ops);
137487d66f28SThierry Reding 	if (err < 0)
137587d66f28SThierry Reding 		goto unregister;
137687d66f28SThierry Reding 
137787d66f28SThierry Reding 	dev_set_drvdata(&pad->dev, pad);
137887d66f28SThierry Reding 
137987d66f28SThierry Reding 	return pad;
138087d66f28SThierry Reding 
138187d66f28SThierry Reding unregister:
138287d66f28SThierry Reding 	device_unregister(&pad->dev);
138387d66f28SThierry Reding out:
138487d66f28SThierry Reding 	return ERR_PTR(err);
138587d66f28SThierry Reding }
138687d66f28SThierry Reding 
138787d66f28SThierry Reding static void tegra210_hsic_pad_remove(struct tegra_xusb_pad *pad)
138887d66f28SThierry Reding {
138987d66f28SThierry Reding 	struct tegra_xusb_hsic_pad *hsic = to_hsic_pad(pad);
139087d66f28SThierry Reding 
139187d66f28SThierry Reding 	kfree(hsic);
139287d66f28SThierry Reding }
139387d66f28SThierry Reding 
139487d66f28SThierry Reding static const struct tegra_xusb_pad_ops tegra210_hsic_ops = {
139587d66f28SThierry Reding 	.probe = tegra210_hsic_pad_probe,
139687d66f28SThierry Reding 	.remove = tegra210_hsic_pad_remove,
139787d66f28SThierry Reding };
139887d66f28SThierry Reding 
139987d66f28SThierry Reding static const struct tegra_xusb_pad_soc tegra210_hsic_pad = {
140087d66f28SThierry Reding 	.name = "hsic",
140187d66f28SThierry Reding 	.num_lanes = ARRAY_SIZE(tegra210_hsic_lanes),
140287d66f28SThierry Reding 	.lanes = tegra210_hsic_lanes,
140387d66f28SThierry Reding 	.ops = &tegra210_hsic_ops,
140487d66f28SThierry Reding };
140587d66f28SThierry Reding 
140687d66f28SThierry Reding static const char *tegra210_pcie_functions[] = {
140787d66f28SThierry Reding 	"pcie-x1",
140887d66f28SThierry Reding 	"usb3-ss",
140987d66f28SThierry Reding 	"sata",
141087d66f28SThierry Reding 	"pcie-x4",
141187d66f28SThierry Reding };
141287d66f28SThierry Reding 
141387d66f28SThierry Reding static const struct tegra_xusb_lane_soc tegra210_pcie_lanes[] = {
141487d66f28SThierry Reding 	TEGRA210_LANE("pcie-0", 0x028, 12, 0x3, pcie),
141587d66f28SThierry Reding 	TEGRA210_LANE("pcie-1", 0x028, 14, 0x3, pcie),
141687d66f28SThierry Reding 	TEGRA210_LANE("pcie-2", 0x028, 16, 0x3, pcie),
141787d66f28SThierry Reding 	TEGRA210_LANE("pcie-3", 0x028, 18, 0x3, pcie),
141887d66f28SThierry Reding 	TEGRA210_LANE("pcie-4", 0x028, 20, 0x3, pcie),
141987d66f28SThierry Reding 	TEGRA210_LANE("pcie-5", 0x028, 22, 0x3, pcie),
142087d66f28SThierry Reding 	TEGRA210_LANE("pcie-6", 0x028, 24, 0x3, pcie),
142187d66f28SThierry Reding };
142287d66f28SThierry Reding 
142387d66f28SThierry Reding static struct tegra_xusb_lane *
142487d66f28SThierry Reding tegra210_pcie_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np,
142587d66f28SThierry Reding 			 unsigned int index)
142687d66f28SThierry Reding {
142787d66f28SThierry Reding 	struct tegra_xusb_pcie_lane *pcie;
142887d66f28SThierry Reding 	int err;
142987d66f28SThierry Reding 
143087d66f28SThierry Reding 	pcie = kzalloc(sizeof(*pcie), GFP_KERNEL);
143187d66f28SThierry Reding 	if (!pcie)
143287d66f28SThierry Reding 		return ERR_PTR(-ENOMEM);
143387d66f28SThierry Reding 
143487d66f28SThierry Reding 	INIT_LIST_HEAD(&pcie->base.list);
143587d66f28SThierry Reding 	pcie->base.soc = &pad->soc->lanes[index];
143687d66f28SThierry Reding 	pcie->base.index = index;
143787d66f28SThierry Reding 	pcie->base.pad = pad;
143887d66f28SThierry Reding 	pcie->base.np = np;
143987d66f28SThierry Reding 
144087d66f28SThierry Reding 	err = tegra_xusb_lane_parse_dt(&pcie->base, np);
144187d66f28SThierry Reding 	if (err < 0) {
144287d66f28SThierry Reding 		kfree(pcie);
144387d66f28SThierry Reding 		return ERR_PTR(err);
144487d66f28SThierry Reding 	}
144587d66f28SThierry Reding 
144687d66f28SThierry Reding 	return &pcie->base;
144787d66f28SThierry Reding }
144887d66f28SThierry Reding 
144987d66f28SThierry Reding static void tegra210_pcie_lane_remove(struct tegra_xusb_lane *lane)
145087d66f28SThierry Reding {
145187d66f28SThierry Reding 	struct tegra_xusb_pcie_lane *pcie = to_pcie_lane(lane);
145287d66f28SThierry Reding 
145387d66f28SThierry Reding 	kfree(pcie);
145487d66f28SThierry Reding }
145587d66f28SThierry Reding 
145687d66f28SThierry Reding static const struct tegra_xusb_lane_ops tegra210_pcie_lane_ops = {
145787d66f28SThierry Reding 	.probe = tegra210_pcie_lane_probe,
145887d66f28SThierry Reding 	.remove = tegra210_pcie_lane_remove,
145987d66f28SThierry Reding };
146087d66f28SThierry Reding 
146187d66f28SThierry Reding static int tegra210_pcie_phy_init(struct phy *phy)
146287d66f28SThierry Reding {
146387d66f28SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
146487d66f28SThierry Reding 
146587d66f28SThierry Reding 	return tegra210_xusb_padctl_enable(lane->pad->padctl);
146687d66f28SThierry Reding }
146787d66f28SThierry Reding 
146887d66f28SThierry Reding static int tegra210_pcie_phy_exit(struct phy *phy)
146987d66f28SThierry Reding {
147087d66f28SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
147187d66f28SThierry Reding 
147287d66f28SThierry Reding 	return tegra210_xusb_padctl_disable(lane->pad->padctl);
147387d66f28SThierry Reding }
147487d66f28SThierry Reding 
147587d66f28SThierry Reding static int tegra210_pcie_phy_power_on(struct phy *phy)
147687d66f28SThierry Reding {
147787d66f28SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
147887d66f28SThierry Reding 	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
147987d66f28SThierry Reding 	u32 value;
148087d66f28SThierry Reding 	int err;
148187d66f28SThierry Reding 
148287d66f28SThierry Reding 	mutex_lock(&padctl->lock);
148387d66f28SThierry Reding 
148487d66f28SThierry Reding 	err = tegra210_pex_uphy_enable(padctl);
148587d66f28SThierry Reding 	if (err < 0)
148687d66f28SThierry Reding 		goto unlock;
148787d66f28SThierry Reding 
148887d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
148987d66f28SThierry Reding 	value |= XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index);
149087d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
149187d66f28SThierry Reding 
149287d66f28SThierry Reding unlock:
149387d66f28SThierry Reding 	mutex_unlock(&padctl->lock);
149487d66f28SThierry Reding 	return err;
149587d66f28SThierry Reding }
149687d66f28SThierry Reding 
149787d66f28SThierry Reding static int tegra210_pcie_phy_power_off(struct phy *phy)
149887d66f28SThierry Reding {
149987d66f28SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
150087d66f28SThierry Reding 	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
150187d66f28SThierry Reding 	u32 value;
150287d66f28SThierry Reding 
150387d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
150487d66f28SThierry Reding 	value &= ~XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index);
150587d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
150687d66f28SThierry Reding 
150787d66f28SThierry Reding 	tegra210_pex_uphy_disable(padctl);
150887d66f28SThierry Reding 
150987d66f28SThierry Reding 	return 0;
151087d66f28SThierry Reding }
151187d66f28SThierry Reding 
151287d66f28SThierry Reding static const struct phy_ops tegra210_pcie_phy_ops = {
151387d66f28SThierry Reding 	.init = tegra210_pcie_phy_init,
151487d66f28SThierry Reding 	.exit = tegra210_pcie_phy_exit,
151587d66f28SThierry Reding 	.power_on = tegra210_pcie_phy_power_on,
151687d66f28SThierry Reding 	.power_off = tegra210_pcie_phy_power_off,
151787d66f28SThierry Reding 	.owner = THIS_MODULE,
151887d66f28SThierry Reding };
151987d66f28SThierry Reding 
152087d66f28SThierry Reding static struct tegra_xusb_pad *
152187d66f28SThierry Reding tegra210_pcie_pad_probe(struct tegra_xusb_padctl *padctl,
152287d66f28SThierry Reding 			const struct tegra_xusb_pad_soc *soc,
152387d66f28SThierry Reding 			struct device_node *np)
152487d66f28SThierry Reding {
152587d66f28SThierry Reding 	struct tegra_xusb_pcie_pad *pcie;
152687d66f28SThierry Reding 	struct tegra_xusb_pad *pad;
152787d66f28SThierry Reding 	int err;
152887d66f28SThierry Reding 
152987d66f28SThierry Reding 	pcie = kzalloc(sizeof(*pcie), GFP_KERNEL);
153087d66f28SThierry Reding 	if (!pcie)
153187d66f28SThierry Reding 		return ERR_PTR(-ENOMEM);
153287d66f28SThierry Reding 
153387d66f28SThierry Reding 	pad = &pcie->base;
153487d66f28SThierry Reding 	pad->ops = &tegra210_pcie_lane_ops;
153587d66f28SThierry Reding 	pad->soc = soc;
153687d66f28SThierry Reding 
153787d66f28SThierry Reding 	err = tegra_xusb_pad_init(pad, padctl, np);
153887d66f28SThierry Reding 	if (err < 0) {
153987d66f28SThierry Reding 		kfree(pcie);
154087d66f28SThierry Reding 		goto out;
154187d66f28SThierry Reding 	}
154287d66f28SThierry Reding 
154387d66f28SThierry Reding 	pcie->pll = devm_clk_get(&pad->dev, "pll");
154487d66f28SThierry Reding 	if (IS_ERR(pcie->pll)) {
154587d66f28SThierry Reding 		err = PTR_ERR(pcie->pll);
154687d66f28SThierry Reding 		dev_err(&pad->dev, "failed to get PLL: %d\n", err);
154787d66f28SThierry Reding 		goto unregister;
154887d66f28SThierry Reding 	}
154987d66f28SThierry Reding 
155087d66f28SThierry Reding 	pcie->rst = devm_reset_control_get(&pad->dev, "phy");
155187d66f28SThierry Reding 	if (IS_ERR(pcie->rst)) {
155287d66f28SThierry Reding 		err = PTR_ERR(pcie->rst);
155387d66f28SThierry Reding 		dev_err(&pad->dev, "failed to get PCIe pad reset: %d\n", err);
155487d66f28SThierry Reding 		goto unregister;
155587d66f28SThierry Reding 	}
155687d66f28SThierry Reding 
155787d66f28SThierry Reding 	err = tegra_xusb_pad_register(pad, &tegra210_pcie_phy_ops);
155887d66f28SThierry Reding 	if (err < 0)
155987d66f28SThierry Reding 		goto unregister;
156087d66f28SThierry Reding 
156187d66f28SThierry Reding 	dev_set_drvdata(&pad->dev, pad);
156287d66f28SThierry Reding 
156387d66f28SThierry Reding 	return pad;
156487d66f28SThierry Reding 
156587d66f28SThierry Reding unregister:
156687d66f28SThierry Reding 	device_unregister(&pad->dev);
156787d66f28SThierry Reding out:
156887d66f28SThierry Reding 	return ERR_PTR(err);
156987d66f28SThierry Reding }
157087d66f28SThierry Reding 
157187d66f28SThierry Reding static void tegra210_pcie_pad_remove(struct tegra_xusb_pad *pad)
157287d66f28SThierry Reding {
157387d66f28SThierry Reding 	struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(pad);
157487d66f28SThierry Reding 
157587d66f28SThierry Reding 	kfree(pcie);
157687d66f28SThierry Reding }
157787d66f28SThierry Reding 
157887d66f28SThierry Reding static const struct tegra_xusb_pad_ops tegra210_pcie_ops = {
157987d66f28SThierry Reding 	.probe = tegra210_pcie_pad_probe,
158087d66f28SThierry Reding 	.remove = tegra210_pcie_pad_remove,
158187d66f28SThierry Reding };
158287d66f28SThierry Reding 
158387d66f28SThierry Reding static const struct tegra_xusb_pad_soc tegra210_pcie_pad = {
158487d66f28SThierry Reding 	.name = "pcie",
158587d66f28SThierry Reding 	.num_lanes = ARRAY_SIZE(tegra210_pcie_lanes),
158687d66f28SThierry Reding 	.lanes = tegra210_pcie_lanes,
158787d66f28SThierry Reding 	.ops = &tegra210_pcie_ops,
158887d66f28SThierry Reding };
158987d66f28SThierry Reding 
159087d66f28SThierry Reding static const struct tegra_xusb_lane_soc tegra210_sata_lanes[] = {
159187d66f28SThierry Reding 	TEGRA210_LANE("sata-0", 0x028, 30, 0x3, pcie),
159287d66f28SThierry Reding };
159387d66f28SThierry Reding 
159487d66f28SThierry Reding static struct tegra_xusb_lane *
159587d66f28SThierry Reding tegra210_sata_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np,
159687d66f28SThierry Reding 			 unsigned int index)
159787d66f28SThierry Reding {
159887d66f28SThierry Reding 	struct tegra_xusb_sata_lane *sata;
159987d66f28SThierry Reding 	int err;
160087d66f28SThierry Reding 
160187d66f28SThierry Reding 	sata = kzalloc(sizeof(*sata), GFP_KERNEL);
160287d66f28SThierry Reding 	if (!sata)
160387d66f28SThierry Reding 		return ERR_PTR(-ENOMEM);
160487d66f28SThierry Reding 
160587d66f28SThierry Reding 	INIT_LIST_HEAD(&sata->base.list);
160687d66f28SThierry Reding 	sata->base.soc = &pad->soc->lanes[index];
160787d66f28SThierry Reding 	sata->base.index = index;
160887d66f28SThierry Reding 	sata->base.pad = pad;
160987d66f28SThierry Reding 	sata->base.np = np;
161087d66f28SThierry Reding 
161187d66f28SThierry Reding 	err = tegra_xusb_lane_parse_dt(&sata->base, np);
161287d66f28SThierry Reding 	if (err < 0) {
161387d66f28SThierry Reding 		kfree(sata);
161487d66f28SThierry Reding 		return ERR_PTR(err);
161587d66f28SThierry Reding 	}
161687d66f28SThierry Reding 
161787d66f28SThierry Reding 	return &sata->base;
161887d66f28SThierry Reding }
161987d66f28SThierry Reding 
162087d66f28SThierry Reding static void tegra210_sata_lane_remove(struct tegra_xusb_lane *lane)
162187d66f28SThierry Reding {
162287d66f28SThierry Reding 	struct tegra_xusb_sata_lane *sata = to_sata_lane(lane);
162387d66f28SThierry Reding 
162487d66f28SThierry Reding 	kfree(sata);
162587d66f28SThierry Reding }
162687d66f28SThierry Reding 
162787d66f28SThierry Reding static const struct tegra_xusb_lane_ops tegra210_sata_lane_ops = {
162887d66f28SThierry Reding 	.probe = tegra210_sata_lane_probe,
162987d66f28SThierry Reding 	.remove = tegra210_sata_lane_remove,
163087d66f28SThierry Reding };
163187d66f28SThierry Reding 
163287d66f28SThierry Reding static int tegra210_sata_phy_init(struct phy *phy)
163387d66f28SThierry Reding {
163487d66f28SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
163587d66f28SThierry Reding 
163687d66f28SThierry Reding 	return tegra210_xusb_padctl_enable(lane->pad->padctl);
163787d66f28SThierry Reding }
163887d66f28SThierry Reding 
163987d66f28SThierry Reding static int tegra210_sata_phy_exit(struct phy *phy)
164087d66f28SThierry Reding {
164187d66f28SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
164287d66f28SThierry Reding 
164387d66f28SThierry Reding 	return tegra210_xusb_padctl_disable(lane->pad->padctl);
164487d66f28SThierry Reding }
164587d66f28SThierry Reding 
164687d66f28SThierry Reding static int tegra210_sata_phy_power_on(struct phy *phy)
164787d66f28SThierry Reding {
164887d66f28SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
164987d66f28SThierry Reding 	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
165087d66f28SThierry Reding 	u32 value;
165187d66f28SThierry Reding 	int err;
165287d66f28SThierry Reding 
165387d66f28SThierry Reding 	mutex_lock(&padctl->lock);
165487d66f28SThierry Reding 
165587d66f28SThierry Reding 	err = tegra210_sata_uphy_enable(padctl, false);
165687d66f28SThierry Reding 	if (err < 0)
165787d66f28SThierry Reding 		goto unlock;
165887d66f28SThierry Reding 
165987d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
166087d66f28SThierry Reding 	value |= XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index);
166187d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
166287d66f28SThierry Reding 
166387d66f28SThierry Reding unlock:
166487d66f28SThierry Reding 	mutex_unlock(&padctl->lock);
166587d66f28SThierry Reding 	return err;
166687d66f28SThierry Reding }
166787d66f28SThierry Reding 
166887d66f28SThierry Reding static int tegra210_sata_phy_power_off(struct phy *phy)
166987d66f28SThierry Reding {
167087d66f28SThierry Reding 	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
167187d66f28SThierry Reding 	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
167287d66f28SThierry Reding 	u32 value;
167387d66f28SThierry Reding 
167487d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
167587d66f28SThierry Reding 	value &= ~XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index);
167687d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
167787d66f28SThierry Reding 
167887d66f28SThierry Reding 	tegra210_sata_uphy_disable(lane->pad->padctl);
167987d66f28SThierry Reding 
168087d66f28SThierry Reding 	return 0;
168187d66f28SThierry Reding }
168287d66f28SThierry Reding 
168387d66f28SThierry Reding static const struct phy_ops tegra210_sata_phy_ops = {
168487d66f28SThierry Reding 	.init = tegra210_sata_phy_init,
168587d66f28SThierry Reding 	.exit = tegra210_sata_phy_exit,
168687d66f28SThierry Reding 	.power_on = tegra210_sata_phy_power_on,
168787d66f28SThierry Reding 	.power_off = tegra210_sata_phy_power_off,
168887d66f28SThierry Reding 	.owner = THIS_MODULE,
168987d66f28SThierry Reding };
169087d66f28SThierry Reding 
169187d66f28SThierry Reding static struct tegra_xusb_pad *
169287d66f28SThierry Reding tegra210_sata_pad_probe(struct tegra_xusb_padctl *padctl,
169387d66f28SThierry Reding 			const struct tegra_xusb_pad_soc *soc,
169487d66f28SThierry Reding 			struct device_node *np)
169587d66f28SThierry Reding {
169687d66f28SThierry Reding 	struct tegra_xusb_sata_pad *sata;
169787d66f28SThierry Reding 	struct tegra_xusb_pad *pad;
169887d66f28SThierry Reding 	int err;
169987d66f28SThierry Reding 
170087d66f28SThierry Reding 	sata = kzalloc(sizeof(*sata), GFP_KERNEL);
170187d66f28SThierry Reding 	if (!sata)
170287d66f28SThierry Reding 		return ERR_PTR(-ENOMEM);
170387d66f28SThierry Reding 
170487d66f28SThierry Reding 	pad = &sata->base;
170587d66f28SThierry Reding 	pad->ops = &tegra210_sata_lane_ops;
170687d66f28SThierry Reding 	pad->soc = soc;
170787d66f28SThierry Reding 
170887d66f28SThierry Reding 	err = tegra_xusb_pad_init(pad, padctl, np);
170987d66f28SThierry Reding 	if (err < 0) {
171087d66f28SThierry Reding 		kfree(sata);
171187d66f28SThierry Reding 		goto out;
171287d66f28SThierry Reding 	}
171387d66f28SThierry Reding 
171487d66f28SThierry Reding 	sata->rst = devm_reset_control_get(&pad->dev, "phy");
171587d66f28SThierry Reding 	if (IS_ERR(sata->rst)) {
171687d66f28SThierry Reding 		err = PTR_ERR(sata->rst);
171787d66f28SThierry Reding 		dev_err(&pad->dev, "failed to get SATA pad reset: %d\n", err);
171887d66f28SThierry Reding 		goto unregister;
171987d66f28SThierry Reding 	}
172087d66f28SThierry Reding 
172187d66f28SThierry Reding 	err = tegra_xusb_pad_register(pad, &tegra210_sata_phy_ops);
172287d66f28SThierry Reding 	if (err < 0)
172387d66f28SThierry Reding 		goto unregister;
172487d66f28SThierry Reding 
172587d66f28SThierry Reding 	dev_set_drvdata(&pad->dev, pad);
172687d66f28SThierry Reding 
172787d66f28SThierry Reding 	return pad;
172887d66f28SThierry Reding 
172987d66f28SThierry Reding unregister:
173087d66f28SThierry Reding 	device_unregister(&pad->dev);
173187d66f28SThierry Reding out:
173287d66f28SThierry Reding 	return ERR_PTR(err);
173387d66f28SThierry Reding }
173487d66f28SThierry Reding 
173587d66f28SThierry Reding static void tegra210_sata_pad_remove(struct tegra_xusb_pad *pad)
173687d66f28SThierry Reding {
173787d66f28SThierry Reding 	struct tegra_xusb_sata_pad *sata = to_sata_pad(pad);
173887d66f28SThierry Reding 
173987d66f28SThierry Reding 	kfree(sata);
174087d66f28SThierry Reding }
174187d66f28SThierry Reding 
174287d66f28SThierry Reding static const struct tegra_xusb_pad_ops tegra210_sata_ops = {
174387d66f28SThierry Reding 	.probe = tegra210_sata_pad_probe,
174487d66f28SThierry Reding 	.remove = tegra210_sata_pad_remove,
174587d66f28SThierry Reding };
174687d66f28SThierry Reding 
174787d66f28SThierry Reding static const struct tegra_xusb_pad_soc tegra210_sata_pad = {
174887d66f28SThierry Reding 	.name = "sata",
174987d66f28SThierry Reding 	.num_lanes = ARRAY_SIZE(tegra210_sata_lanes),
175087d66f28SThierry Reding 	.lanes = tegra210_sata_lanes,
175187d66f28SThierry Reding 	.ops = &tegra210_sata_ops,
175287d66f28SThierry Reding };
175387d66f28SThierry Reding 
175487d66f28SThierry Reding static const struct tegra_xusb_pad_soc * const tegra210_pads[] = {
175587d66f28SThierry Reding 	&tegra210_usb2_pad,
175687d66f28SThierry Reding 	&tegra210_hsic_pad,
175787d66f28SThierry Reding 	&tegra210_pcie_pad,
175887d66f28SThierry Reding 	&tegra210_sata_pad,
175987d66f28SThierry Reding };
176087d66f28SThierry Reding 
176187d66f28SThierry Reding static int tegra210_usb2_port_enable(struct tegra_xusb_port *port)
176287d66f28SThierry Reding {
176387d66f28SThierry Reding 	return 0;
176487d66f28SThierry Reding }
176587d66f28SThierry Reding 
176687d66f28SThierry Reding static void tegra210_usb2_port_disable(struct tegra_xusb_port *port)
176787d66f28SThierry Reding {
176887d66f28SThierry Reding }
176987d66f28SThierry Reding 
177087d66f28SThierry Reding static struct tegra_xusb_lane *
177187d66f28SThierry Reding tegra210_usb2_port_map(struct tegra_xusb_port *port)
177287d66f28SThierry Reding {
177387d66f28SThierry Reding 	return tegra_xusb_find_lane(port->padctl, "usb2", port->index);
177487d66f28SThierry Reding }
177587d66f28SThierry Reding 
177687d66f28SThierry Reding static const struct tegra_xusb_port_ops tegra210_usb2_port_ops = {
177787d66f28SThierry Reding 	.enable = tegra210_usb2_port_enable,
177887d66f28SThierry Reding 	.disable = tegra210_usb2_port_disable,
177987d66f28SThierry Reding 	.map = tegra210_usb2_port_map,
178087d66f28SThierry Reding };
178187d66f28SThierry Reding 
178287d66f28SThierry Reding static int tegra210_hsic_port_enable(struct tegra_xusb_port *port)
178387d66f28SThierry Reding {
178487d66f28SThierry Reding 	return 0;
178587d66f28SThierry Reding }
178687d66f28SThierry Reding 
178787d66f28SThierry Reding static void tegra210_hsic_port_disable(struct tegra_xusb_port *port)
178887d66f28SThierry Reding {
178987d66f28SThierry Reding }
179087d66f28SThierry Reding 
179187d66f28SThierry Reding static struct tegra_xusb_lane *
179287d66f28SThierry Reding tegra210_hsic_port_map(struct tegra_xusb_port *port)
179387d66f28SThierry Reding {
179487d66f28SThierry Reding 	return tegra_xusb_find_lane(port->padctl, "hsic", port->index);
179587d66f28SThierry Reding }
179687d66f28SThierry Reding 
179787d66f28SThierry Reding static const struct tegra_xusb_port_ops tegra210_hsic_port_ops = {
179887d66f28SThierry Reding 	.enable = tegra210_hsic_port_enable,
179987d66f28SThierry Reding 	.disable = tegra210_hsic_port_disable,
180087d66f28SThierry Reding 	.map = tegra210_hsic_port_map,
180187d66f28SThierry Reding };
180287d66f28SThierry Reding 
180387d66f28SThierry Reding static int tegra210_usb3_port_enable(struct tegra_xusb_port *port)
180487d66f28SThierry Reding {
180587d66f28SThierry Reding 	struct tegra_xusb_usb3_port *usb3 = to_usb3_port(port);
180687d66f28SThierry Reding 	struct tegra_xusb_padctl *padctl = port->padctl;
180787d66f28SThierry Reding 	struct tegra_xusb_lane *lane = usb3->base.lane;
180887d66f28SThierry Reding 	unsigned int index = port->index;
180987d66f28SThierry Reding 	u32 value;
181087d66f28SThierry Reding 	int err;
181187d66f28SThierry Reding 
181287d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP);
181387d66f28SThierry Reding 
181487d66f28SThierry Reding 	if (!usb3->internal)
181587d66f28SThierry Reding 		value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index);
181687d66f28SThierry Reding 	else
181787d66f28SThierry Reding 		value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index);
181887d66f28SThierry Reding 
181987d66f28SThierry Reding 	value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(index);
182087d66f28SThierry Reding 	value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(index, usb3->port);
182187d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP);
182287d66f28SThierry Reding 
182387d66f28SThierry Reding 	/*
182487d66f28SThierry Reding 	 * TODO: move this code into the PCIe/SATA PHY ->power_on() callbacks
182587d66f28SThierry Reding 	 * and conditionalize based on mux function? This seems to work, but
182687d66f28SThierry Reding 	 * might not be the exact proper sequence.
182787d66f28SThierry Reding 	 */
182887d66f28SThierry Reding 	err = regulator_enable(usb3->supply);
182987d66f28SThierry Reding 	if (err < 0)
183087d66f28SThierry Reding 		return err;
183187d66f28SThierry Reding 
183287d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(index));
183387d66f28SThierry Reding 	value &= ~(XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_MASK <<
183487d66f28SThierry Reding 		   XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT);
183587d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_VAL <<
183687d66f28SThierry Reding 		 XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT;
183787d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(index));
183887d66f28SThierry Reding 
183987d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_USB3_PADX_ECTL2(index));
184087d66f28SThierry Reding 	value &= ~(XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_MASK <<
184187d66f28SThierry Reding 		   XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_SHIFT);
184287d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_VAL <<
184387d66f28SThierry Reding 		 XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_SHIFT;
184487d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_USB3_PADX_ECTL2(index));
184587d66f28SThierry Reding 
184687d66f28SThierry Reding 	padctl_writel(padctl, XUSB_PADCTL_UPHY_USB3_PAD_ECTL3_RX_DFE_VAL,
184787d66f28SThierry Reding 		      XUSB_PADCTL_UPHY_USB3_PADX_ECTL3(index));
184887d66f28SThierry Reding 
184987d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_USB3_PADX_ECTL4(index));
185087d66f28SThierry Reding 	value &= ~(XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_MASK <<
185187d66f28SThierry Reding 		   XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_SHIFT);
185287d66f28SThierry Reding 	value |= XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_VAL <<
185387d66f28SThierry Reding 		 XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_SHIFT;
185487d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_USB3_PADX_ECTL4(index));
185587d66f28SThierry Reding 
185687d66f28SThierry Reding 	padctl_writel(padctl, XUSB_PADCTL_UPHY_USB3_PAD_ECTL6_RX_EQ_CTRL_H_VAL,
185787d66f28SThierry Reding 		      XUSB_PADCTL_UPHY_USB3_PADX_ECTL6(index));
185887d66f28SThierry Reding 
185987d66f28SThierry Reding 	if (lane->pad == padctl->sata)
186087d66f28SThierry Reding 		err = tegra210_sata_uphy_enable(padctl, true);
186187d66f28SThierry Reding 	else
186287d66f28SThierry Reding 		err = tegra210_pex_uphy_enable(padctl);
186387d66f28SThierry Reding 
186487d66f28SThierry Reding 	if (err) {
186587d66f28SThierry Reding 		dev_err(&port->dev, "%s: failed to enable UPHY: %d\n",
186687d66f28SThierry Reding 			__func__, err);
186787d66f28SThierry Reding 		return err;
186887d66f28SThierry Reding 	}
186987d66f28SThierry Reding 
187087d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
187187d66f28SThierry Reding 	value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN(index);
187287d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
187387d66f28SThierry Reding 
187487d66f28SThierry Reding 	usleep_range(100, 200);
187587d66f28SThierry Reding 
187687d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
187787d66f28SThierry Reding 	value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(index);
187887d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
187987d66f28SThierry Reding 
188087d66f28SThierry Reding 	usleep_range(100, 200);
188187d66f28SThierry Reding 
188287d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
188387d66f28SThierry Reding 	value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(index);
188487d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
188587d66f28SThierry Reding 
188687d66f28SThierry Reding 	return 0;
188787d66f28SThierry Reding }
188887d66f28SThierry Reding 
188987d66f28SThierry Reding static void tegra210_usb3_port_disable(struct tegra_xusb_port *port)
189087d66f28SThierry Reding {
189187d66f28SThierry Reding 	struct tegra_xusb_usb3_port *usb3 = to_usb3_port(port);
189287d66f28SThierry Reding 	struct tegra_xusb_padctl *padctl = port->padctl;
189387d66f28SThierry Reding 	struct tegra_xusb_lane *lane = port->lane;
189487d66f28SThierry Reding 	unsigned int index = port->index;
189587d66f28SThierry Reding 	u32 value;
189687d66f28SThierry Reding 
189787d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
189887d66f28SThierry Reding 	value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(index);
189987d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
190087d66f28SThierry Reding 
190187d66f28SThierry Reding 	usleep_range(100, 200);
190287d66f28SThierry Reding 
190387d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
190487d66f28SThierry Reding 	value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(index);
190587d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
190687d66f28SThierry Reding 
190787d66f28SThierry Reding 	usleep_range(250, 350);
190887d66f28SThierry Reding 
190987d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
191087d66f28SThierry Reding 	value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN(index);
191187d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
191287d66f28SThierry Reding 
191387d66f28SThierry Reding 	if (lane->pad == padctl->sata)
191487d66f28SThierry Reding 		tegra210_sata_uphy_disable(padctl);
191587d66f28SThierry Reding 	else
191687d66f28SThierry Reding 		tegra210_pex_uphy_disable(padctl);
191787d66f28SThierry Reding 
191887d66f28SThierry Reding 	regulator_disable(usb3->supply);
191987d66f28SThierry Reding 
192087d66f28SThierry Reding 	value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP);
192187d66f28SThierry Reding 	value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(index);
192287d66f28SThierry Reding 	value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(index, 0x7);
192387d66f28SThierry Reding 	padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP);
192487d66f28SThierry Reding }
192587d66f28SThierry Reding 
192687d66f28SThierry Reding static const struct tegra_xusb_lane_map tegra210_usb3_map[] = {
192787d66f28SThierry Reding 	{ 0, "pcie", 6 },
192887d66f28SThierry Reding 	{ 1, "pcie", 5 },
192987d66f28SThierry Reding 	{ 2, "pcie", 0 },
193087d66f28SThierry Reding 	{ 2, "pcie", 3 },
193187d66f28SThierry Reding 	{ 3, "pcie", 4 },
193287d66f28SThierry Reding 	{ 3, "pcie", 4 },
193387d66f28SThierry Reding 	{ 0, NULL,   0 }
193487d66f28SThierry Reding };
193587d66f28SThierry Reding 
193687d66f28SThierry Reding static struct tegra_xusb_lane *
193787d66f28SThierry Reding tegra210_usb3_port_map(struct tegra_xusb_port *port)
193887d66f28SThierry Reding {
193987d66f28SThierry Reding 	return tegra_xusb_port_find_lane(port, tegra210_usb3_map, "usb3-ss");
194087d66f28SThierry Reding }
194187d66f28SThierry Reding 
194287d66f28SThierry Reding static const struct tegra_xusb_port_ops tegra210_usb3_port_ops = {
194387d66f28SThierry Reding 	.enable = tegra210_usb3_port_enable,
194487d66f28SThierry Reding 	.disable = tegra210_usb3_port_disable,
194587d66f28SThierry Reding 	.map = tegra210_usb3_port_map,
194687d66f28SThierry Reding };
194787d66f28SThierry Reding 
194887d66f28SThierry Reding static int
194987d66f28SThierry Reding tegra210_xusb_read_fuse_calibration(struct tegra210_xusb_fuse_calibration *fuse)
195087d66f28SThierry Reding {
195187d66f28SThierry Reding 	unsigned int i;
195287d66f28SThierry Reding 	u32 value;
195387d66f28SThierry Reding 	int err;
195487d66f28SThierry Reding 
195587d66f28SThierry Reding 	err = tegra_fuse_readl(TEGRA_FUSE_SKU_CALIB_0, &value);
195687d66f28SThierry Reding 	if (err < 0)
195787d66f28SThierry Reding 		return err;
195887d66f28SThierry Reding 
195987d66f28SThierry Reding 	for (i = 0; i < ARRAY_SIZE(fuse->hs_curr_level); i++) {
196087d66f28SThierry Reding 		fuse->hs_curr_level[i] =
196187d66f28SThierry Reding 			(value >> FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(i)) &
196287d66f28SThierry Reding 			FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK;
196387d66f28SThierry Reding 	}
196487d66f28SThierry Reding 
196587d66f28SThierry Reding 	fuse->hs_term_range_adj =
196687d66f28SThierry Reding 		(value >> FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT) &
196787d66f28SThierry Reding 		FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK;
196887d66f28SThierry Reding 
196987d66f28SThierry Reding 	err = tegra_fuse_readl(TEGRA_FUSE_USB_CALIB_EXT_0, &value);
197087d66f28SThierry Reding 	if (err < 0)
197187d66f28SThierry Reding 		return err;
197287d66f28SThierry Reding 
197387d66f28SThierry Reding 	fuse->rpd_ctrl =
197487d66f28SThierry Reding 		(value >> FUSE_USB_CALIB_EXT_RPD_CTRL_SHIFT) &
197587d66f28SThierry Reding 		FUSE_USB_CALIB_EXT_RPD_CTRL_MASK;
197687d66f28SThierry Reding 
197787d66f28SThierry Reding 	return 0;
197887d66f28SThierry Reding }
197987d66f28SThierry Reding 
198087d66f28SThierry Reding static struct tegra_xusb_padctl *
198187d66f28SThierry Reding tegra210_xusb_padctl_probe(struct device *dev,
198287d66f28SThierry Reding 			   const struct tegra_xusb_padctl_soc *soc)
198387d66f28SThierry Reding {
198487d66f28SThierry Reding 	struct tegra210_xusb_padctl *padctl;
198587d66f28SThierry Reding 	int err;
198687d66f28SThierry Reding 
198787d66f28SThierry Reding 	padctl = devm_kzalloc(dev, sizeof(*padctl), GFP_KERNEL);
198887d66f28SThierry Reding 	if (!padctl)
198987d66f28SThierry Reding 		return ERR_PTR(-ENOMEM);
199087d66f28SThierry Reding 
199187d66f28SThierry Reding 	padctl->base.dev = dev;
199287d66f28SThierry Reding 	padctl->base.soc = soc;
199387d66f28SThierry Reding 
199487d66f28SThierry Reding 	err = tegra210_xusb_read_fuse_calibration(&padctl->fuse);
199587d66f28SThierry Reding 	if (err < 0)
199687d66f28SThierry Reding 		return ERR_PTR(err);
199787d66f28SThierry Reding 
199887d66f28SThierry Reding 	return &padctl->base;
199987d66f28SThierry Reding }
200087d66f28SThierry Reding 
200187d66f28SThierry Reding static void tegra210_xusb_padctl_remove(struct tegra_xusb_padctl *padctl)
200287d66f28SThierry Reding {
200387d66f28SThierry Reding }
200487d66f28SThierry Reding 
200587d66f28SThierry Reding static const struct tegra_xusb_padctl_ops tegra210_xusb_padctl_ops = {
200687d66f28SThierry Reding 	.probe = tegra210_xusb_padctl_probe,
200787d66f28SThierry Reding 	.remove = tegra210_xusb_padctl_remove,
200887d66f28SThierry Reding 	.usb3_set_lfps_detect = tegra210_usb3_set_lfps_detect,
200987d66f28SThierry Reding 	.hsic_set_idle = tegra210_hsic_set_idle,
201087d66f28SThierry Reding };
201187d66f28SThierry Reding 
201287d66f28SThierry Reding const struct tegra_xusb_padctl_soc tegra210_xusb_padctl_soc = {
201387d66f28SThierry Reding 	.num_pads = ARRAY_SIZE(tegra210_pads),
201487d66f28SThierry Reding 	.pads = tegra210_pads,
201587d66f28SThierry Reding 	.ports = {
201687d66f28SThierry Reding 		.usb2 = {
201787d66f28SThierry Reding 			.ops = &tegra210_usb2_port_ops,
201887d66f28SThierry Reding 			.count = 4,
201987d66f28SThierry Reding 		},
202087d66f28SThierry Reding 		.hsic = {
202187d66f28SThierry Reding 			.ops = &tegra210_hsic_port_ops,
202287d66f28SThierry Reding 			.count = 1,
202387d66f28SThierry Reding 		},
202487d66f28SThierry Reding 		.usb3 = {
202587d66f28SThierry Reding 			.ops = &tegra210_usb3_port_ops,
202687d66f28SThierry Reding 			.count = 4,
202787d66f28SThierry Reding 		},
202887d66f28SThierry Reding 	},
202987d66f28SThierry Reding 	.ops = &tegra210_xusb_padctl_ops,
203087d66f28SThierry Reding };
203187d66f28SThierry Reding EXPORT_SYMBOL_GPL(tegra210_xusb_padctl_soc);
203287d66f28SThierry Reding 
203387d66f28SThierry Reding MODULE_AUTHOR("Andrew Bresticker <abrestic@chromium.org>");
203487d66f28SThierry Reding MODULE_DESCRIPTION("NVIDIA Tegra 210 XUSB Pad Controller driver");
203587d66f28SThierry Reding MODULE_LICENSE("GPL v2");
2036