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