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