162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2014-2020, NVIDIA CORPORATION.  All rights reserved.
462306a36Sopenharmony_ci * Copyright (C) 2015 Google, Inc.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/clk.h>
862306a36Sopenharmony_ci#include <linux/clk/tegra.h>
962306a36Sopenharmony_ci#include <linux/delay.h>
1062306a36Sopenharmony_ci#include <linux/io.h>
1162306a36Sopenharmony_ci#include <linux/mailbox_client.h>
1262306a36Sopenharmony_ci#include <linux/module.h>
1362306a36Sopenharmony_ci#include <linux/of.h>
1462306a36Sopenharmony_ci#include <linux/of_platform.h>
1562306a36Sopenharmony_ci#include <linux/phy/phy.h>
1662306a36Sopenharmony_ci#include <linux/platform_device.h>
1762306a36Sopenharmony_ci#include <linux/regmap.h>
1862306a36Sopenharmony_ci#include <linux/regulator/consumer.h>
1962306a36Sopenharmony_ci#include <linux/reset.h>
2062306a36Sopenharmony_ci#include <linux/slab.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#include <soc/tegra/fuse.h>
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#include "xusb.h"
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(x) \
2762306a36Sopenharmony_ci					((x) ? (11 + ((x) - 1) * 6) : 0)
2862306a36Sopenharmony_ci#define FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK 0x3f
2962306a36Sopenharmony_ci#define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT 7
3062306a36Sopenharmony_ci#define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK 0xf
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#define FUSE_USB_CALIB_EXT_RPD_CTRL_SHIFT 0
3362306a36Sopenharmony_ci#define FUSE_USB_CALIB_EXT_RPD_CTRL_MASK 0x1f
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PAD_MUX 0x004
3662306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_SHIFT 16
3762306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_MASK 0x3
3862306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_XUSB 0x1
3962306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_SHIFT 18
4062306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_MASK 0x3
4162306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_XUSB 0x1
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP 0x008
4462306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_DISABLED(x) (0x0 << ((x) * 4))
4562306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_HOST(x) (0x1 << ((x) * 4))
4662306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_DEVICE(x) (0x2 << ((x) * 4))
4762306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_OTG(x) (0x3 << ((x) * 4))
4862306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_MASK(x) (0x3 << ((x) * 4))
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP 0x014
5162306a36Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(x) (1 << (((x) * 5) + 4))
5262306a36Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_SHIFT(x) ((x) * 5)
5362306a36Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(x) (0x7 << ((x) * 5))
5462306a36Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(x, v) (((v) & 0x7) << ((x) * 5))
5562306a36Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORT_DISABLED 0x7
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM_0 0x20
5862306a36Sopenharmony_ci#define   USB2_PORT_WAKE_INTERRUPT_ENABLE(x)      BIT((x))
5962306a36Sopenharmony_ci#define   USB2_PORT_WAKEUP_EVENT(x)               BIT((x) + 7)
6062306a36Sopenharmony_ci#define   SS_PORT_WAKE_INTERRUPT_ENABLE(x)        BIT((x) + 14)
6162306a36Sopenharmony_ci#define   SS_PORT_WAKEUP_EVENT(x)                 BIT((x) + 21)
6262306a36Sopenharmony_ci#define   USB2_HSIC_PORT_WAKE_INTERRUPT_ENABLE(x) BIT((x) + 28)
6362306a36Sopenharmony_ci#define   USB2_HSIC_PORT_WAKEUP_EVENT(x)          BIT((x) + 30)
6462306a36Sopenharmony_ci#define   ALL_WAKE_EVENTS ( \
6562306a36Sopenharmony_ci		USB2_PORT_WAKEUP_EVENT(0) | USB2_PORT_WAKEUP_EVENT(1) | \
6662306a36Sopenharmony_ci		USB2_PORT_WAKEUP_EVENT(2) | USB2_PORT_WAKEUP_EVENT(3) | \
6762306a36Sopenharmony_ci		SS_PORT_WAKEUP_EVENT(0) | SS_PORT_WAKEUP_EVENT(1) | \
6862306a36Sopenharmony_ci		SS_PORT_WAKEUP_EVENT(2) | SS_PORT_WAKEUP_EVENT(3) | \
6962306a36Sopenharmony_ci		USB2_HSIC_PORT_WAKEUP_EVENT(0))
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM1 0x024
7262306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN (1 << 31)
7362306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 30)
7462306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN (1 << 29)
7562306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN(x) (1 << (2 + (x) * 3))
7662306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(x) \
7762306a36Sopenharmony_ci							(1 << (1 + (x) * 3))
7862306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(x) (1 << ((x) * 3))
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci#define XUSB_PADCTL_USB3_PAD_MUX 0x028
8162306a36Sopenharmony_ci#define XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(x) (1 << (1 + (x)))
8262306a36Sopenharmony_ci#define XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(x) (1 << (8 + (x)))
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL0(x) (0x080 + (x) * 0x40)
8562306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL0_ZIP (1 << 18)
8662306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL0_ZIN (1 << 22)
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(x) (0x084 + (x) * 0x40)
8962306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_SHIFT 7
9062306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_MASK 0x3
9162306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_VAL 0x1
9262306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_FIX18 (1 << 6)
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PADX_CTL0(x) (0x088 + (x) * 0x40)
9562306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI (1 << 29)
9662306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 (1 << 27)
9762306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD (1 << 26)
9862306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT 0
9962306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK 0x3f
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PADX_CTL1(x) (0x08c + (x) * 0x40)
10262306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_SHIFT 26
10362306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_MASK 0x1f
10462306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT 3
10562306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK 0xf
10662306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR (1 << 2)
10762306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_OVRD (1 << 1)
10862306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_OVRD (1 << 0)
10962306a36Sopenharmony_ci#define   RPD_CTRL(x)                      (((x) & 0x1f) << 26)
11062306a36Sopenharmony_ci#define   RPD_CTRL_VALUE(x)                (((x) >> 26) & 0x1f)
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0 0x284
11362306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD (1 << 11)
11462306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT 3
11562306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK 0x7
11662306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL 0x7
11762306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT 0
11862306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK 0x7
11962306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_VAL 0x2
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL1 0x288
12262306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_PD_TRK (1 << 26)
12362306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_SHIFT 19
12462306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_MASK 0x7f
12562306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_VAL 0x0a
12662306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_SHIFT 12
12762306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_MASK 0x7f
12862306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_VAL 0x1e
12962306a36Sopenharmony_ci#define   TCTRL_VALUE(x)                (((x) & 0x3f) >> 0)
13062306a36Sopenharmony_ci#define   PCTRL_VALUE(x)                (((x) >> 6) & 0x3f)
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PADX_CTL0(x) (0x300 + (x) * 0x20)
13362306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE (1 << 18)
13462306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA1 (1 << 17)
13562306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA0 (1 << 16)
13662306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_RPD_STROBE (1 << 15)
13762306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA1 (1 << 14)
13862306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA0 (1 << 13)
13962306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_STROBE (1 << 9)
14062306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA1 (1 << 8)
14162306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA0 (1 << 7)
14262306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_STROBE (1 << 6)
14362306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA1 (1 << 5)
14462306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA0 (1 << 4)
14562306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_STROBE (1 << 3)
14662306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA1 (1 << 2)
14762306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA0 (1 << 1)
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PADX_CTL1(x) (0x304 + (x) * 0x20)
15062306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_SHIFT 0
15162306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_MASK 0xf
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PADX_CTL2(x) (0x308 + (x) * 0x20)
15462306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT 8
15562306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK 0xf
15662306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT 0
15762306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK 0xff
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_TRK_CTL 0x340
16062306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_TRK_CTL_PD_TRK (1 << 19)
16162306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_SHIFT 12
16262306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_MASK 0x7f
16362306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_VAL 0x0a
16462306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_SHIFT 5
16562306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_MASK 0x7f
16662306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_VAL 0x1e
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL 0x344
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_P0_CTL1 0x360
17162306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT 20
17262306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_MASK 0xff
17362306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_USB_VAL 0x19
17462306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SATA_VAL 0x1e
17562306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_SHIFT 16
17662306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_MASK 0x3
17762306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_LOCKDET_STATUS (1 << 15)
17862306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD (1 << 4)
17962306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_ENABLE (1 << 3)
18062306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_SHIFT 1
18162306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_MASK 0x3
18262306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_IDDQ (1 << 0)
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_P0_CTL2 0x364
18562306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT 4
18662306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_MASK 0xffffff
18762306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_VAL 0x136
18862306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD (1 << 2)
18962306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE (1 << 1)
19062306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN (1 << 0)
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_P0_CTL4 0x36c
19362306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL4_XDIGCLK_EN (1 << 19)
19462306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_EN (1 << 15)
19562306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT 12
19662306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_MASK 0x3
19762306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_USB_VAL 0x2
19862306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SATA_VAL 0x0
19962306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL4_REFCLKBUF_EN (1 << 8)
20062306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_SHIFT 4
20162306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_MASK 0xf
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_P0_CTL5 0x370
20462306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT 16
20562306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_MASK 0xff
20662306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_VAL 0x2a
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_P0_CTL8 0x37c
20962306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE (1 << 31)
21062306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD (1 << 15)
21162306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN (1 << 13)
21262306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN (1 << 12)
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL1(x) (0x460 + (x) * 0x40)
21562306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_SHIFT 20
21662306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_MASK 0x3
21762306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_VAL 0x1
21862306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_TERM_EN BIT(18)
21962306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_MODE_OVRD BIT(13)
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(x) (0x464 + (x) * 0x40)
22262306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ BIT(0)
22362306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ_OVRD BIT(1)
22462306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_MASK GENMASK(5, 4)
22562306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_VAL GENMASK(5, 4)
22662306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_PWR_OVRD BIT(24)
22762306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ BIT(8)
22862306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ_OVRD BIT(9)
22962306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_MASK GENMASK(13, 12)
23062306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_VAL GENMASK(13, 12)
23162306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_PWR_OVRD BIT(25)
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_S0_CTL1 0x860
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_S0_CTL2 0x864
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_S0_CTL4 0x86c
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_S0_CTL5 0x870
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_S0_CTL8 0x87c
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL1 0x960
24462306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL2 0x964
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(x) (0xa60 + (x) * 0x40)
24762306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT 16
24862306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_MASK 0x3
24962306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_VAL 0x2
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PADX_ECTL2(x) (0xa64 + (x) * 0x40)
25262306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_SHIFT 0
25362306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_MASK 0xffff
25462306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_VAL 0x00fc
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PADX_ECTL3(x) (0xa68 + (x) * 0x40)
25762306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL3_RX_DFE_VAL 0xc0077f1f
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PADX_ECTL4(x) (0xa6c + (x) * 0x40)
26062306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_SHIFT 16
26162306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_MASK 0xffff
26262306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_VAL 0x01c7
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PADX_ECTL6(x) (0xa74 + (x) * 0x40)
26562306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL6_RX_EQ_CTRL_H_VAL 0xfcf01368
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_VBUS_ID 0xc60
26862306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON (1 << 14)
26962306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT 18
27062306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK 0xf
27162306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING 8
27262306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_GROUNDED 0
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci/* USB2 SLEEPWALK registers */
27562306a36Sopenharmony_ci#define UTMIP(_port, _offset1, _offset2) \
27662306a36Sopenharmony_ci		(((_port) <= 2) ? (_offset1) : (_offset2))
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci#define PMC_UTMIP_UHSIC_SLEEP_CFG(x)	UTMIP(x, 0x1fc, 0x4d0)
27962306a36Sopenharmony_ci#define   UTMIP_MASTER_ENABLE(x)		UTMIP(x, BIT(8 * (x)), BIT(0))
28062306a36Sopenharmony_ci#define   UTMIP_FSLS_USE_PMC(x)			UTMIP(x, BIT(8 * (x) + 1), \
28162306a36Sopenharmony_ci							BIT(1))
28262306a36Sopenharmony_ci#define   UTMIP_PCTRL_USE_PMC(x)		UTMIP(x, BIT(8 * (x) + 2), \
28362306a36Sopenharmony_ci							BIT(2))
28462306a36Sopenharmony_ci#define   UTMIP_TCTRL_USE_PMC(x)		UTMIP(x, BIT(8 * (x) + 3), \
28562306a36Sopenharmony_ci							BIT(3))
28662306a36Sopenharmony_ci#define   UTMIP_WAKE_VAL(_port, _value)		(((_value) & 0xf) << \
28762306a36Sopenharmony_ci					(UTMIP(_port, 8 * (_port) + 4, 4)))
28862306a36Sopenharmony_ci#define   UTMIP_WAKE_VAL_NONE(_port)		UTMIP_WAKE_VAL(_port, 12)
28962306a36Sopenharmony_ci#define   UTMIP_WAKE_VAL_ANY(_port)		UTMIP_WAKE_VAL(_port, 15)
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci#define PMC_UTMIP_UHSIC_SLEEP_CFG1	(0x4d0)
29262306a36Sopenharmony_ci#define   UTMIP_RPU_SWITC_LOW_USE_PMC_PX(x)	BIT((x) + 8)
29362306a36Sopenharmony_ci#define   UTMIP_RPD_CTRL_USE_PMC_PX(x)		BIT((x) + 16)
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci#define PMC_UTMIP_MASTER_CONFIG		(0x274)
29662306a36Sopenharmony_ci#define   UTMIP_PWR(x)				UTMIP(x, BIT(x), BIT(4))
29762306a36Sopenharmony_ci#define   UHSIC_PWR				BIT(3)
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci#define PMC_USB_DEBOUNCE_DEL		(0xec)
30062306a36Sopenharmony_ci#define   DEBOUNCE_VAL(x)			(((x) & 0xffff) << 0)
30162306a36Sopenharmony_ci#define   UTMIP_LINE_DEB_CNT(x)			(((x) & 0xf) << 16)
30262306a36Sopenharmony_ci#define   UHSIC_LINE_DEB_CNT(x)			(((x) & 0xf) << 20)
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci#define PMC_UTMIP_UHSIC_FAKE(x)		UTMIP(x, 0x218, 0x294)
30562306a36Sopenharmony_ci#define   UTMIP_FAKE_USBOP_VAL(x)		UTMIP(x, BIT(4 * (x)), BIT(8))
30662306a36Sopenharmony_ci#define   UTMIP_FAKE_USBON_VAL(x)		UTMIP(x, BIT(4 * (x) + 1), \
30762306a36Sopenharmony_ci							BIT(9))
30862306a36Sopenharmony_ci#define   UTMIP_FAKE_USBOP_EN(x)		UTMIP(x, BIT(4 * (x) + 2), \
30962306a36Sopenharmony_ci							BIT(10))
31062306a36Sopenharmony_ci#define   UTMIP_FAKE_USBON_EN(x)		UTMIP(x, BIT(4 * (x) + 3), \
31162306a36Sopenharmony_ci							BIT(11))
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci#define PMC_UTMIP_UHSIC_SLEEPWALK_CFG(x)	UTMIP(x, 0x200, 0x288)
31462306a36Sopenharmony_ci#define   UTMIP_LINEVAL_WALK_EN(x)		UTMIP(x, BIT(8 * (x) + 7), \
31562306a36Sopenharmony_ci							BIT(15))
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci#define PMC_USB_AO			(0xf0)
31862306a36Sopenharmony_ci#define   USBOP_VAL_PD(x)			UTMIP(x, BIT(4 * (x)), BIT(20))
31962306a36Sopenharmony_ci#define   USBON_VAL_PD(x)			UTMIP(x, BIT(4 * (x) + 1), \
32062306a36Sopenharmony_ci							BIT(21))
32162306a36Sopenharmony_ci#define   STROBE_VAL_PD				BIT(12)
32262306a36Sopenharmony_ci#define   DATA0_VAL_PD				BIT(13)
32362306a36Sopenharmony_ci#define   DATA1_VAL_PD				BIT(24)
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci#define PMC_UTMIP_UHSIC_SAVED_STATE(x)	UTMIP(x, 0x1f0, 0x280)
32662306a36Sopenharmony_ci#define   SPEED(_port, _value)			(((_value) & 0x3) << \
32762306a36Sopenharmony_ci						(UTMIP(_port, 8 * (_port), 8)))
32862306a36Sopenharmony_ci#define   UTMI_HS(_port)			SPEED(_port, 0)
32962306a36Sopenharmony_ci#define   UTMI_FS(_port)			SPEED(_port, 1)
33062306a36Sopenharmony_ci#define   UTMI_LS(_port)			SPEED(_port, 2)
33162306a36Sopenharmony_ci#define   UTMI_RST(_port)			SPEED(_port, 3)
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci#define PMC_UTMIP_UHSIC_TRIGGERS		(0x1ec)
33462306a36Sopenharmony_ci#define   UTMIP_CLR_WALK_PTR(x)			UTMIP(x, BIT(x), BIT(16))
33562306a36Sopenharmony_ci#define   UTMIP_CAP_CFG(x)			UTMIP(x, BIT((x) + 4), BIT(17))
33662306a36Sopenharmony_ci#define   UTMIP_CLR_WAKE_ALARM(x)		UTMIP(x, BIT((x) + 12), \
33762306a36Sopenharmony_ci							BIT(19))
33862306a36Sopenharmony_ci#define   UHSIC_CLR_WALK_PTR			BIT(3)
33962306a36Sopenharmony_ci#define   UHSIC_CLR_WAKE_ALARM			BIT(15)
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci#define PMC_UTMIP_SLEEPWALK_PX(x)	UTMIP(x, 0x204 + (4 * (x)), \
34262306a36Sopenharmony_ci							0x4e0)
34362306a36Sopenharmony_ci/* phase A */
34462306a36Sopenharmony_ci#define   UTMIP_USBOP_RPD_A			BIT(0)
34562306a36Sopenharmony_ci#define   UTMIP_USBON_RPD_A			BIT(1)
34662306a36Sopenharmony_ci#define   UTMIP_AP_A				BIT(4)
34762306a36Sopenharmony_ci#define   UTMIP_AN_A				BIT(5)
34862306a36Sopenharmony_ci#define   UTMIP_HIGHZ_A				BIT(6)
34962306a36Sopenharmony_ci/* phase B */
35062306a36Sopenharmony_ci#define   UTMIP_USBOP_RPD_B			BIT(8)
35162306a36Sopenharmony_ci#define   UTMIP_USBON_RPD_B			BIT(9)
35262306a36Sopenharmony_ci#define   UTMIP_AP_B				BIT(12)
35362306a36Sopenharmony_ci#define   UTMIP_AN_B				BIT(13)
35462306a36Sopenharmony_ci#define   UTMIP_HIGHZ_B				BIT(14)
35562306a36Sopenharmony_ci/* phase C */
35662306a36Sopenharmony_ci#define   UTMIP_USBOP_RPD_C			BIT(16)
35762306a36Sopenharmony_ci#define   UTMIP_USBON_RPD_C			BIT(17)
35862306a36Sopenharmony_ci#define   UTMIP_AP_C				BIT(20)
35962306a36Sopenharmony_ci#define   UTMIP_AN_C				BIT(21)
36062306a36Sopenharmony_ci#define   UTMIP_HIGHZ_C				BIT(22)
36162306a36Sopenharmony_ci/* phase D */
36262306a36Sopenharmony_ci#define   UTMIP_USBOP_RPD_D			BIT(24)
36362306a36Sopenharmony_ci#define   UTMIP_USBON_RPD_D			BIT(25)
36462306a36Sopenharmony_ci#define   UTMIP_AP_D				BIT(28)
36562306a36Sopenharmony_ci#define   UTMIP_AN_D				BIT(29)
36662306a36Sopenharmony_ci#define   UTMIP_HIGHZ_D				BIT(30)
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci#define PMC_UTMIP_UHSIC_LINE_WAKEUP	(0x26c)
36962306a36Sopenharmony_ci#define   UTMIP_LINE_WAKEUP_EN(x)		UTMIP(x, BIT(x), BIT(4))
37062306a36Sopenharmony_ci#define   UHSIC_LINE_WAKEUP_EN			BIT(3)
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci#define PMC_UTMIP_TERM_PAD_CFG		(0x1f8)
37362306a36Sopenharmony_ci#define   PCTRL_VAL(x)				(((x) & 0x3f) << 1)
37462306a36Sopenharmony_ci#define   TCTRL_VAL(x)				(((x) & 0x3f) << 7)
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci#define PMC_UTMIP_PAD_CFGX(x)		(0x4c0 + (4 * (x)))
37762306a36Sopenharmony_ci#define   RPD_CTRL_PX(x)			(((x) & 0x1f) << 22)
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci#define PMC_UHSIC_SLEEP_CFG	PMC_UTMIP_UHSIC_SLEEP_CFG(0)
38062306a36Sopenharmony_ci#define   UHSIC_MASTER_ENABLE			BIT(24)
38162306a36Sopenharmony_ci#define   UHSIC_WAKE_VAL(_value)		(((_value) & 0xf) << 28)
38262306a36Sopenharmony_ci#define   UHSIC_WAKE_VAL_SD10			UHSIC_WAKE_VAL(2)
38362306a36Sopenharmony_ci#define   UHSIC_WAKE_VAL_NONE			UHSIC_WAKE_VAL(12)
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci#define PMC_UHSIC_FAKE			PMC_UTMIP_UHSIC_FAKE(0)
38662306a36Sopenharmony_ci#define   UHSIC_FAKE_STROBE_VAL			BIT(12)
38762306a36Sopenharmony_ci#define   UHSIC_FAKE_DATA_VAL			BIT(13)
38862306a36Sopenharmony_ci#define   UHSIC_FAKE_STROBE_EN			BIT(14)
38962306a36Sopenharmony_ci#define   UHSIC_FAKE_DATA_EN			BIT(15)
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci#define PMC_UHSIC_SAVED_STATE		PMC_UTMIP_UHSIC_SAVED_STATE(0)
39262306a36Sopenharmony_ci#define   UHSIC_MODE(_value)			(((_value) & 0x1) << 24)
39362306a36Sopenharmony_ci#define   UHSIC_HS				UHSIC_MODE(0)
39462306a36Sopenharmony_ci#define   UHSIC_RST				UHSIC_MODE(1)
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci#define PMC_UHSIC_SLEEPWALK_CFG		PMC_UTMIP_UHSIC_SLEEPWALK_CFG(0)
39762306a36Sopenharmony_ci#define   UHSIC_WAKE_WALK_EN			BIT(30)
39862306a36Sopenharmony_ci#define   UHSIC_LINEVAL_WALK_EN			BIT(31)
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci#define PMC_UHSIC_SLEEPWALK_P0		(0x210)
40162306a36Sopenharmony_ci#define   UHSIC_DATA0_RPD_A			BIT(1)
40262306a36Sopenharmony_ci#define   UHSIC_DATA0_RPU_B			BIT(11)
40362306a36Sopenharmony_ci#define   UHSIC_DATA0_RPU_C			BIT(19)
40462306a36Sopenharmony_ci#define   UHSIC_DATA0_RPU_D			BIT(27)
40562306a36Sopenharmony_ci#define   UHSIC_STROBE_RPU_A			BIT(2)
40662306a36Sopenharmony_ci#define   UHSIC_STROBE_RPD_B			BIT(8)
40762306a36Sopenharmony_ci#define   UHSIC_STROBE_RPD_C			BIT(16)
40862306a36Sopenharmony_ci#define   UHSIC_STROBE_RPD_D			BIT(24)
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_cistruct tegra210_xusb_fuse_calibration {
41162306a36Sopenharmony_ci	u32 hs_curr_level[4];
41262306a36Sopenharmony_ci	u32 hs_term_range_adj;
41362306a36Sopenharmony_ci	u32 rpd_ctrl;
41462306a36Sopenharmony_ci};
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_cistruct tegra210_xusb_padctl_context {
41762306a36Sopenharmony_ci	u32 usb2_pad_mux;
41862306a36Sopenharmony_ci	u32 usb2_port_cap;
41962306a36Sopenharmony_ci	u32 ss_port_map;
42062306a36Sopenharmony_ci	u32 usb3_pad_mux;
42162306a36Sopenharmony_ci};
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_cistruct tegra210_xusb_padctl {
42462306a36Sopenharmony_ci	struct tegra_xusb_padctl base;
42562306a36Sopenharmony_ci	struct regmap *regmap;
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	struct tegra210_xusb_fuse_calibration fuse;
42862306a36Sopenharmony_ci	struct tegra210_xusb_padctl_context context;
42962306a36Sopenharmony_ci};
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_cistatic inline struct tegra210_xusb_padctl *
43262306a36Sopenharmony_cito_tegra210_xusb_padctl(struct tegra_xusb_padctl *padctl)
43362306a36Sopenharmony_ci{
43462306a36Sopenharmony_ci	return container_of(padctl, struct tegra210_xusb_padctl, base);
43562306a36Sopenharmony_ci}
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_cistatic const struct tegra_xusb_lane_map tegra210_usb3_map[] = {
43862306a36Sopenharmony_ci	{ 0, "pcie", 6 },
43962306a36Sopenharmony_ci	{ 1, "pcie", 5 },
44062306a36Sopenharmony_ci	{ 2, "pcie", 0 },
44162306a36Sopenharmony_ci	{ 2, "pcie", 3 },
44262306a36Sopenharmony_ci	{ 3, "pcie", 4 },
44362306a36Sopenharmony_ci	{ 3, "sata", 0 },
44462306a36Sopenharmony_ci	{ 0, NULL,   0 }
44562306a36Sopenharmony_ci};
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_cistatic int tegra210_usb3_lane_map(struct tegra_xusb_lane *lane)
44862306a36Sopenharmony_ci{
44962306a36Sopenharmony_ci	const struct tegra_xusb_lane_map *map;
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	for (map = tegra210_usb3_map; map->type; map++) {
45262306a36Sopenharmony_ci		if (map->index == lane->index &&
45362306a36Sopenharmony_ci		    strcmp(map->type, lane->pad->soc->name) == 0) {
45462306a36Sopenharmony_ci			dev_dbg(lane->pad->padctl->dev, "lane = %s map to port = usb3-%d\n",
45562306a36Sopenharmony_ci				lane->pad->soc->lanes[lane->index].name, map->port);
45662306a36Sopenharmony_ci			return map->port;
45762306a36Sopenharmony_ci		}
45862306a36Sopenharmony_ci	}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	return -EINVAL;
46162306a36Sopenharmony_ci}
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ci/* must be called under padctl->lock */
46462306a36Sopenharmony_cistatic int tegra210_pex_uphy_enable(struct tegra_xusb_padctl *padctl)
46562306a36Sopenharmony_ci{
46662306a36Sopenharmony_ci	struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(padctl->pcie);
46762306a36Sopenharmony_ci	unsigned long timeout;
46862306a36Sopenharmony_ci	u32 value;
46962306a36Sopenharmony_ci	unsigned int i;
47062306a36Sopenharmony_ci	int err;
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	if (pcie->enable)
47362306a36Sopenharmony_ci		return 0;
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci	err = clk_prepare_enable(pcie->pll);
47662306a36Sopenharmony_ci	if (err < 0)
47762306a36Sopenharmony_ci		return err;
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	if (tegra210_plle_hw_sequence_is_enabled())
48062306a36Sopenharmony_ci		goto skip_pll_init;
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	err = reset_control_deassert(pcie->rst);
48362306a36Sopenharmony_ci	if (err < 0)
48462306a36Sopenharmony_ci		goto disable;
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
48762306a36Sopenharmony_ci	value &= ~(XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_MASK <<
48862306a36Sopenharmony_ci		   XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT);
48962306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_VAL <<
49062306a36Sopenharmony_ci		 XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT;
49162306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL5);
49462306a36Sopenharmony_ci	value &= ~(XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_MASK <<
49562306a36Sopenharmony_ci		   XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT);
49662306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_VAL <<
49762306a36Sopenharmony_ci		 XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT;
49862306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL5);
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
50162306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD;
50262306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
50562306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD;
50662306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
50962306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD;
51062306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL4);
51362306a36Sopenharmony_ci	value &= ~((XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_MASK <<
51462306a36Sopenharmony_ci		    XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT) |
51562306a36Sopenharmony_ci		   (XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_MASK <<
51662306a36Sopenharmony_ci		    XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_SHIFT));
51762306a36Sopenharmony_ci	value |= (XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_USB_VAL <<
51862306a36Sopenharmony_ci		  XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT) |
51962306a36Sopenharmony_ci		 XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_EN;
52062306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL4);
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
52362306a36Sopenharmony_ci	value &= ~((XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_MASK <<
52462306a36Sopenharmony_ci		    XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_SHIFT) |
52562306a36Sopenharmony_ci		   (XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_MASK <<
52662306a36Sopenharmony_ci		    XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT));
52762306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_USB_VAL <<
52862306a36Sopenharmony_ci		 XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT;
52962306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
53262306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_IDDQ;
53362306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
53662306a36Sopenharmony_ci	value &= ~(XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_MASK <<
53762306a36Sopenharmony_ci		   XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_SHIFT);
53862306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	usleep_range(10, 20);
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL4);
54362306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_PLL_CTL4_REFCLKBUF_EN;
54462306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL4);
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
54762306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN;
54862306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	timeout = jiffies + msecs_to_jiffies(100);
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	while (time_before(jiffies, timeout)) {
55362306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
55462306a36Sopenharmony_ci		if (value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE)
55562306a36Sopenharmony_ci			break;
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci		usleep_range(10, 20);
55862306a36Sopenharmony_ci	}
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci	if (time_after_eq(jiffies, timeout)) {
56162306a36Sopenharmony_ci		err = -ETIMEDOUT;
56262306a36Sopenharmony_ci		goto reset;
56362306a36Sopenharmony_ci	}
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
56662306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN;
56762306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	timeout = jiffies + msecs_to_jiffies(100);
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	while (time_before(jiffies, timeout)) {
57262306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
57362306a36Sopenharmony_ci		if (!(value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE))
57462306a36Sopenharmony_ci			break;
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci		usleep_range(10, 20);
57762306a36Sopenharmony_ci	}
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	if (time_after_eq(jiffies, timeout)) {
58062306a36Sopenharmony_ci		err = -ETIMEDOUT;
58162306a36Sopenharmony_ci		goto reset;
58262306a36Sopenharmony_ci	}
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
58562306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_PLL_CTL1_ENABLE;
58662306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci	timeout = jiffies + msecs_to_jiffies(100);
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci	while (time_before(jiffies, timeout)) {
59162306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
59262306a36Sopenharmony_ci		if (value & XUSB_PADCTL_UPHY_PLL_CTL1_LOCKDET_STATUS)
59362306a36Sopenharmony_ci			break;
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci		usleep_range(10, 20);
59662306a36Sopenharmony_ci	}
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci	if (time_after_eq(jiffies, timeout)) {
59962306a36Sopenharmony_ci		err = -ETIMEDOUT;
60062306a36Sopenharmony_ci		goto reset;
60162306a36Sopenharmony_ci	}
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
60462306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN |
60562306a36Sopenharmony_ci		 XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN;
60662306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci	timeout = jiffies + msecs_to_jiffies(100);
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci	while (time_before(jiffies, timeout)) {
61162306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
61262306a36Sopenharmony_ci		if (value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE)
61362306a36Sopenharmony_ci			break;
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_ci		usleep_range(10, 20);
61662306a36Sopenharmony_ci	}
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	if (time_after_eq(jiffies, timeout)) {
61962306a36Sopenharmony_ci		err = -ETIMEDOUT;
62062306a36Sopenharmony_ci		goto reset;
62162306a36Sopenharmony_ci	}
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
62462306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN;
62562306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_ci	timeout = jiffies + msecs_to_jiffies(100);
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci	while (time_before(jiffies, timeout)) {
63062306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
63162306a36Sopenharmony_ci		if (!(value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE))
63262306a36Sopenharmony_ci			break;
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci		usleep_range(10, 20);
63562306a36Sopenharmony_ci	}
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ci	if (time_after_eq(jiffies, timeout)) {
63862306a36Sopenharmony_ci		err = -ETIMEDOUT;
63962306a36Sopenharmony_ci		goto reset;
64062306a36Sopenharmony_ci	}
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
64362306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN;
64462306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci	tegra210_xusb_pll_hw_control_enable();
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
64962306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD;
65062306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
65362306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD;
65462306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
65762306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD;
65862306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci	usleep_range(10, 20);
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci	tegra210_xusb_pll_hw_sequence_start();
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ciskip_pll_init:
66562306a36Sopenharmony_ci	pcie->enable = true;
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci	for (i = 0; i < padctl->pcie->soc->num_lanes; i++) {
66862306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
66962306a36Sopenharmony_ci		value |= XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(i);
67062306a36Sopenharmony_ci		padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
67162306a36Sopenharmony_ci	}
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci	return 0;
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_cireset:
67662306a36Sopenharmony_ci	reset_control_assert(pcie->rst);
67762306a36Sopenharmony_cidisable:
67862306a36Sopenharmony_ci	clk_disable_unprepare(pcie->pll);
67962306a36Sopenharmony_ci	return err;
68062306a36Sopenharmony_ci}
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_cistatic void tegra210_pex_uphy_disable(struct tegra_xusb_padctl *padctl)
68362306a36Sopenharmony_ci{
68462306a36Sopenharmony_ci	struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(padctl->pcie);
68562306a36Sopenharmony_ci	u32 value;
68662306a36Sopenharmony_ci	unsigned int i;
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_ci	if (WARN_ON(!pcie->enable))
68962306a36Sopenharmony_ci		return;
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	pcie->enable = false;
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	for (i = 0; i < padctl->pcie->soc->num_lanes; i++) {
69462306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
69562306a36Sopenharmony_ci		value &= ~XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(i);
69662306a36Sopenharmony_ci		padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
69762306a36Sopenharmony_ci	}
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci	clk_disable_unprepare(pcie->pll);
70062306a36Sopenharmony_ci}
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci/* must be called under padctl->lock */
70362306a36Sopenharmony_cistatic int tegra210_sata_uphy_enable(struct tegra_xusb_padctl *padctl)
70462306a36Sopenharmony_ci{
70562306a36Sopenharmony_ci	struct tegra_xusb_sata_pad *sata = to_sata_pad(padctl->sata);
70662306a36Sopenharmony_ci	struct tegra_xusb_lane *lane = tegra_xusb_find_lane(padctl, "sata", 0);
70762306a36Sopenharmony_ci	unsigned long timeout;
70862306a36Sopenharmony_ci	u32 value;
70962306a36Sopenharmony_ci	unsigned int i;
71062306a36Sopenharmony_ci	int err;
71162306a36Sopenharmony_ci	bool usb;
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci	if (sata->enable)
71462306a36Sopenharmony_ci		return 0;
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ci	if (IS_ERR(lane))
71762306a36Sopenharmony_ci		return 0;
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci	if (tegra210_plle_hw_sequence_is_enabled())
72062306a36Sopenharmony_ci		goto skip_pll_init;
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	usb = tegra_xusb_lane_check(lane, "usb3-ss");
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ci	err = clk_prepare_enable(sata->pll);
72562306a36Sopenharmony_ci	if (err < 0)
72662306a36Sopenharmony_ci		return err;
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_ci	err = reset_control_deassert(sata->rst);
72962306a36Sopenharmony_ci	if (err < 0)
73062306a36Sopenharmony_ci		goto disable;
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
73362306a36Sopenharmony_ci	value &= ~(XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_MASK <<
73462306a36Sopenharmony_ci		   XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT);
73562306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_VAL <<
73662306a36Sopenharmony_ci		 XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT;
73762306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL5);
74062306a36Sopenharmony_ci	value &= ~(XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_MASK <<
74162306a36Sopenharmony_ci		   XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT);
74262306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_VAL <<
74362306a36Sopenharmony_ci		 XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT;
74462306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL5);
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
74762306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD;
74862306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
74962306a36Sopenharmony_ci
75062306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
75162306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD;
75262306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
75362306a36Sopenharmony_ci
75462306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
75562306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD;
75662306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
75762306a36Sopenharmony_ci
75862306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL4);
75962306a36Sopenharmony_ci	value &= ~((XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_MASK <<
76062306a36Sopenharmony_ci		    XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT) |
76162306a36Sopenharmony_ci		   (XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_MASK <<
76262306a36Sopenharmony_ci		    XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_SHIFT));
76362306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_EN;
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_ci	if (usb)
76662306a36Sopenharmony_ci		value |= (XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_USB_VAL <<
76762306a36Sopenharmony_ci			  XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT);
76862306a36Sopenharmony_ci	else
76962306a36Sopenharmony_ci		value |= (XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SATA_VAL <<
77062306a36Sopenharmony_ci			  XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT);
77162306a36Sopenharmony_ci
77262306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_PLL_CTL4_XDIGCLK_EN;
77362306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL4);
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
77662306a36Sopenharmony_ci	value &= ~((XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_MASK <<
77762306a36Sopenharmony_ci		    XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_SHIFT) |
77862306a36Sopenharmony_ci		   (XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_MASK <<
77962306a36Sopenharmony_ci		    XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT));
78062306a36Sopenharmony_ci
78162306a36Sopenharmony_ci	if (usb)
78262306a36Sopenharmony_ci		value |= XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_USB_VAL <<
78362306a36Sopenharmony_ci			 XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT;
78462306a36Sopenharmony_ci	else
78562306a36Sopenharmony_ci		value |= XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SATA_VAL <<
78662306a36Sopenharmony_ci			 XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT;
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
79162306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_IDDQ;
79262306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
79562306a36Sopenharmony_ci	value &= ~(XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_MASK <<
79662306a36Sopenharmony_ci		   XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_SHIFT);
79762306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci	usleep_range(10, 20);
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL4);
80262306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_PLL_CTL4_REFCLKBUF_EN;
80362306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL4);
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
80662306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN;
80762306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_ci	timeout = jiffies + msecs_to_jiffies(100);
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci	while (time_before(jiffies, timeout)) {
81262306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
81362306a36Sopenharmony_ci		if (value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE)
81462306a36Sopenharmony_ci			break;
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci		usleep_range(10, 20);
81762306a36Sopenharmony_ci	}
81862306a36Sopenharmony_ci
81962306a36Sopenharmony_ci	if (time_after_eq(jiffies, timeout)) {
82062306a36Sopenharmony_ci		err = -ETIMEDOUT;
82162306a36Sopenharmony_ci		goto reset;
82262306a36Sopenharmony_ci	}
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
82562306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN;
82662306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
82762306a36Sopenharmony_ci
82862306a36Sopenharmony_ci	timeout = jiffies + msecs_to_jiffies(100);
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci	while (time_before(jiffies, timeout)) {
83162306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
83262306a36Sopenharmony_ci		if (!(value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE))
83362306a36Sopenharmony_ci			break;
83462306a36Sopenharmony_ci
83562306a36Sopenharmony_ci		usleep_range(10, 20);
83662306a36Sopenharmony_ci	}
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci	if (time_after_eq(jiffies, timeout)) {
83962306a36Sopenharmony_ci		err = -ETIMEDOUT;
84062306a36Sopenharmony_ci		goto reset;
84162306a36Sopenharmony_ci	}
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
84462306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_PLL_CTL1_ENABLE;
84562306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci	timeout = jiffies + msecs_to_jiffies(100);
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_ci	while (time_before(jiffies, timeout)) {
85062306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
85162306a36Sopenharmony_ci		if (value & XUSB_PADCTL_UPHY_PLL_CTL1_LOCKDET_STATUS)
85262306a36Sopenharmony_ci			break;
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci		usleep_range(10, 20);
85562306a36Sopenharmony_ci	}
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ci	if (time_after_eq(jiffies, timeout)) {
85862306a36Sopenharmony_ci		err = -ETIMEDOUT;
85962306a36Sopenharmony_ci		goto reset;
86062306a36Sopenharmony_ci	}
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
86362306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN |
86462306a36Sopenharmony_ci		 XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN;
86562306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci	timeout = jiffies + msecs_to_jiffies(100);
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci	while (time_before(jiffies, timeout)) {
87062306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
87162306a36Sopenharmony_ci		if (value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE)
87262306a36Sopenharmony_ci			break;
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_ci		usleep_range(10, 20);
87562306a36Sopenharmony_ci	}
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci	if (time_after_eq(jiffies, timeout)) {
87862306a36Sopenharmony_ci		err = -ETIMEDOUT;
87962306a36Sopenharmony_ci		goto reset;
88062306a36Sopenharmony_ci	}
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
88362306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN;
88462306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
88562306a36Sopenharmony_ci
88662306a36Sopenharmony_ci	timeout = jiffies + msecs_to_jiffies(100);
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_ci	while (time_before(jiffies, timeout)) {
88962306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
89062306a36Sopenharmony_ci		if (!(value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE))
89162306a36Sopenharmony_ci			break;
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci		usleep_range(10, 20);
89462306a36Sopenharmony_ci	}
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_ci	if (time_after_eq(jiffies, timeout)) {
89762306a36Sopenharmony_ci		err = -ETIMEDOUT;
89862306a36Sopenharmony_ci		goto reset;
89962306a36Sopenharmony_ci	}
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
90262306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN;
90362306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	tegra210_sata_pll_hw_control_enable();
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
90862306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD;
90962306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1);
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
91262306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD;
91362306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2);
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
91662306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD;
91762306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8);
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_ci	usleep_range(10, 20);
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci	tegra210_sata_pll_hw_sequence_start();
92262306a36Sopenharmony_ci
92362306a36Sopenharmony_ciskip_pll_init:
92462306a36Sopenharmony_ci	sata->enable = true;
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_ci	for (i = 0; i < padctl->sata->soc->num_lanes; i++) {
92762306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
92862306a36Sopenharmony_ci		value |= XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(i);
92962306a36Sopenharmony_ci		padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
93062306a36Sopenharmony_ci	}
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_ci	return 0;
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_cireset:
93562306a36Sopenharmony_ci	reset_control_assert(sata->rst);
93662306a36Sopenharmony_cidisable:
93762306a36Sopenharmony_ci	clk_disable_unprepare(sata->pll);
93862306a36Sopenharmony_ci	return err;
93962306a36Sopenharmony_ci}
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_cistatic void tegra210_sata_uphy_disable(struct tegra_xusb_padctl *padctl)
94262306a36Sopenharmony_ci{
94362306a36Sopenharmony_ci	struct tegra_xusb_sata_pad *sata = to_sata_pad(padctl->sata);
94462306a36Sopenharmony_ci	u32 value;
94562306a36Sopenharmony_ci	unsigned int i;
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_ci	if (WARN_ON(!sata->enable))
94862306a36Sopenharmony_ci		return;
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci	sata->enable = false;
95162306a36Sopenharmony_ci
95262306a36Sopenharmony_ci	for (i = 0; i < padctl->sata->soc->num_lanes; i++) {
95362306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
95462306a36Sopenharmony_ci		value &= ~XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(i);
95562306a36Sopenharmony_ci		padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
95662306a36Sopenharmony_ci	}
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_ci	clk_disable_unprepare(sata->pll);
95962306a36Sopenharmony_ci}
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_cistatic void tegra210_aux_mux_lp0_clamp_disable(struct tegra_xusb_padctl *padctl)
96262306a36Sopenharmony_ci{
96362306a36Sopenharmony_ci	u32 value;
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
96662306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN;
96762306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_ci	usleep_range(100, 200);
97062306a36Sopenharmony_ci
97162306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
97262306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY;
97362306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
97462306a36Sopenharmony_ci
97562306a36Sopenharmony_ci	usleep_range(100, 200);
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
97862306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN;
97962306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
98062306a36Sopenharmony_ci}
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_cistatic void tegra210_aux_mux_lp0_clamp_enable(struct tegra_xusb_padctl *padctl)
98362306a36Sopenharmony_ci{
98462306a36Sopenharmony_ci	u32 value;
98562306a36Sopenharmony_ci
98662306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
98762306a36Sopenharmony_ci	value |= XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN;
98862306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_ci	usleep_range(100, 200);
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
99362306a36Sopenharmony_ci	value |= XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY;
99462306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ci	usleep_range(100, 200);
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
99962306a36Sopenharmony_ci	value |= XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN;
100062306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
100162306a36Sopenharmony_ci}
100262306a36Sopenharmony_ci
100362306a36Sopenharmony_cistatic int tegra210_uphy_init(struct tegra_xusb_padctl *padctl)
100462306a36Sopenharmony_ci{
100562306a36Sopenharmony_ci	if (padctl->pcie)
100662306a36Sopenharmony_ci		tegra210_pex_uphy_enable(padctl);
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci	if (padctl->sata)
100962306a36Sopenharmony_ci		tegra210_sata_uphy_enable(padctl);
101062306a36Sopenharmony_ci
101162306a36Sopenharmony_ci	if (!tegra210_plle_hw_sequence_is_enabled())
101262306a36Sopenharmony_ci		tegra210_plle_hw_sequence_start();
101362306a36Sopenharmony_ci	else
101462306a36Sopenharmony_ci		dev_dbg(padctl->dev, "PLLE is already in HW control\n");
101562306a36Sopenharmony_ci
101662306a36Sopenharmony_ci	tegra210_aux_mux_lp0_clamp_disable(padctl);
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	return 0;
101962306a36Sopenharmony_ci}
102062306a36Sopenharmony_ci
102162306a36Sopenharmony_cistatic void __maybe_unused
102262306a36Sopenharmony_citegra210_uphy_deinit(struct tegra_xusb_padctl *padctl)
102362306a36Sopenharmony_ci{
102462306a36Sopenharmony_ci	tegra210_aux_mux_lp0_clamp_enable(padctl);
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_ci	if (padctl->sata)
102762306a36Sopenharmony_ci		tegra210_sata_uphy_disable(padctl);
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_ci	if (padctl->pcie)
103062306a36Sopenharmony_ci		tegra210_pex_uphy_disable(padctl);
103162306a36Sopenharmony_ci}
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_cistatic int tegra210_hsic_set_idle(struct tegra_xusb_padctl *padctl,
103462306a36Sopenharmony_ci				  unsigned int index, bool idle)
103562306a36Sopenharmony_ci{
103662306a36Sopenharmony_ci	u32 value;
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(index));
103962306a36Sopenharmony_ci
104062306a36Sopenharmony_ci	value &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA0 |
104162306a36Sopenharmony_ci		   XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA1 |
104262306a36Sopenharmony_ci		   XUSB_PADCTL_HSIC_PAD_CTL0_RPD_STROBE);
104362306a36Sopenharmony_ci
104462306a36Sopenharmony_ci	if (idle)
104562306a36Sopenharmony_ci		value |= XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA0 |
104662306a36Sopenharmony_ci			 XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA1 |
104762306a36Sopenharmony_ci			 XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE;
104862306a36Sopenharmony_ci	else
104962306a36Sopenharmony_ci		value &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA0 |
105062306a36Sopenharmony_ci			   XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA1 |
105162306a36Sopenharmony_ci			   XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE);
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL0(index));
105462306a36Sopenharmony_ci
105562306a36Sopenharmony_ci	return 0;
105662306a36Sopenharmony_ci}
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_cistatic int tegra210_usb3_enable_phy_sleepwalk(struct tegra_xusb_lane *lane,
105962306a36Sopenharmony_ci					      enum usb_device_speed speed)
106062306a36Sopenharmony_ci{
106162306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
106262306a36Sopenharmony_ci	int port = tegra210_usb3_lane_map(lane);
106362306a36Sopenharmony_ci	struct device *dev = padctl->dev;
106462306a36Sopenharmony_ci	u32 value;
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ci	if (port < 0) {
106762306a36Sopenharmony_ci		dev_err(dev, "invalid usb3 port number\n");
106862306a36Sopenharmony_ci		return -EINVAL;
106962306a36Sopenharmony_ci	}
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci	mutex_lock(&padctl->lock);
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
107462306a36Sopenharmony_ci	value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(port);
107562306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
107662306a36Sopenharmony_ci
107762306a36Sopenharmony_ci	usleep_range(100, 200);
107862306a36Sopenharmony_ci
107962306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
108062306a36Sopenharmony_ci	value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(port);
108162306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	usleep_range(250, 350);
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci	mutex_unlock(&padctl->lock);
108662306a36Sopenharmony_ci
108762306a36Sopenharmony_ci	return 0;
108862306a36Sopenharmony_ci}
108962306a36Sopenharmony_ci
109062306a36Sopenharmony_cistatic int tegra210_usb3_disable_phy_sleepwalk(struct tegra_xusb_lane *lane)
109162306a36Sopenharmony_ci{
109262306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
109362306a36Sopenharmony_ci	int port = tegra210_usb3_lane_map(lane);
109462306a36Sopenharmony_ci	struct device *dev = padctl->dev;
109562306a36Sopenharmony_ci	u32 value;
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_ci	if (port < 0) {
109862306a36Sopenharmony_ci		dev_err(dev, "invalid usb3 port number\n");
109962306a36Sopenharmony_ci		return -EINVAL;
110062306a36Sopenharmony_ci	}
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci	mutex_lock(&padctl->lock);
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
110562306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(port);
110662306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
110762306a36Sopenharmony_ci
110862306a36Sopenharmony_ci	usleep_range(100, 200);
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
111162306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(port);
111262306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
111362306a36Sopenharmony_ci
111462306a36Sopenharmony_ci	mutex_unlock(&padctl->lock);
111562306a36Sopenharmony_ci
111662306a36Sopenharmony_ci	return 0;
111762306a36Sopenharmony_ci}
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_cistatic int tegra210_usb3_enable_phy_wake(struct tegra_xusb_lane *lane)
112062306a36Sopenharmony_ci{
112162306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
112262306a36Sopenharmony_ci	int port = tegra210_usb3_lane_map(lane);
112362306a36Sopenharmony_ci	struct device *dev = padctl->dev;
112462306a36Sopenharmony_ci	u32 value;
112562306a36Sopenharmony_ci
112662306a36Sopenharmony_ci	if (port < 0) {
112762306a36Sopenharmony_ci		dev_err(dev, "invalid usb3 port number\n");
112862306a36Sopenharmony_ci		return -EINVAL;
112962306a36Sopenharmony_ci	}
113062306a36Sopenharmony_ci
113162306a36Sopenharmony_ci	mutex_lock(&padctl->lock);
113262306a36Sopenharmony_ci
113362306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0);
113462306a36Sopenharmony_ci	value &= ~ALL_WAKE_EVENTS;
113562306a36Sopenharmony_ci	value |= SS_PORT_WAKEUP_EVENT(port);
113662306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0);
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_ci	usleep_range(10, 20);
113962306a36Sopenharmony_ci
114062306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0);
114162306a36Sopenharmony_ci	value &= ~ALL_WAKE_EVENTS;
114262306a36Sopenharmony_ci	value |= SS_PORT_WAKE_INTERRUPT_ENABLE(port);
114362306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0);
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_ci	mutex_unlock(&padctl->lock);
114662306a36Sopenharmony_ci
114762306a36Sopenharmony_ci	return 0;
114862306a36Sopenharmony_ci}
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_cistatic int tegra210_usb3_disable_phy_wake(struct tegra_xusb_lane *lane)
115162306a36Sopenharmony_ci{
115262306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
115362306a36Sopenharmony_ci	int port = tegra210_usb3_lane_map(lane);
115462306a36Sopenharmony_ci	struct device *dev = padctl->dev;
115562306a36Sopenharmony_ci	u32 value;
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci	if (port < 0) {
115862306a36Sopenharmony_ci		dev_err(dev, "invalid usb3 port number\n");
115962306a36Sopenharmony_ci		return -EINVAL;
116062306a36Sopenharmony_ci	}
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_ci	mutex_lock(&padctl->lock);
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0);
116562306a36Sopenharmony_ci	value &= ~ALL_WAKE_EVENTS;
116662306a36Sopenharmony_ci	value &= ~SS_PORT_WAKE_INTERRUPT_ENABLE(port);
116762306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0);
116862306a36Sopenharmony_ci
116962306a36Sopenharmony_ci	usleep_range(10, 20);
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0);
117262306a36Sopenharmony_ci	value &= ~ALL_WAKE_EVENTS;
117362306a36Sopenharmony_ci	value |= SS_PORT_WAKEUP_EVENT(port);
117462306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0);
117562306a36Sopenharmony_ci
117662306a36Sopenharmony_ci	mutex_unlock(&padctl->lock);
117762306a36Sopenharmony_ci
117862306a36Sopenharmony_ci	return 0;
117962306a36Sopenharmony_ci}
118062306a36Sopenharmony_ci
118162306a36Sopenharmony_cistatic bool tegra210_usb3_phy_remote_wake_detected(struct tegra_xusb_lane *lane)
118262306a36Sopenharmony_ci{
118362306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
118462306a36Sopenharmony_ci	int index = tegra210_usb3_lane_map(lane);
118562306a36Sopenharmony_ci	u32 value;
118662306a36Sopenharmony_ci
118762306a36Sopenharmony_ci	if (index < 0)
118862306a36Sopenharmony_ci		return false;
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0);
119162306a36Sopenharmony_ci	if ((value & SS_PORT_WAKE_INTERRUPT_ENABLE(index)) && (value & SS_PORT_WAKEUP_EVENT(index)))
119262306a36Sopenharmony_ci		return true;
119362306a36Sopenharmony_ci
119462306a36Sopenharmony_ci	return false;
119562306a36Sopenharmony_ci}
119662306a36Sopenharmony_ci
119762306a36Sopenharmony_cistatic int tegra210_utmi_enable_phy_wake(struct tegra_xusb_lane *lane)
119862306a36Sopenharmony_ci{
119962306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
120062306a36Sopenharmony_ci	unsigned int index = lane->index;
120162306a36Sopenharmony_ci	u32 value;
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci	mutex_lock(&padctl->lock);
120462306a36Sopenharmony_ci
120562306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0);
120662306a36Sopenharmony_ci	value &= ~ALL_WAKE_EVENTS;
120762306a36Sopenharmony_ci	value |= USB2_PORT_WAKEUP_EVENT(index);
120862306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0);
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_ci	usleep_range(10, 20);
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0);
121362306a36Sopenharmony_ci	value &= ~ALL_WAKE_EVENTS;
121462306a36Sopenharmony_ci	value |= USB2_PORT_WAKE_INTERRUPT_ENABLE(index);
121562306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0);
121662306a36Sopenharmony_ci
121762306a36Sopenharmony_ci	mutex_unlock(&padctl->lock);
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_ci	return 0;
122062306a36Sopenharmony_ci}
122162306a36Sopenharmony_ci
122262306a36Sopenharmony_cistatic int tegra210_utmi_disable_phy_wake(struct tegra_xusb_lane *lane)
122362306a36Sopenharmony_ci{
122462306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
122562306a36Sopenharmony_ci	unsigned int index = lane->index;
122662306a36Sopenharmony_ci	u32 value;
122762306a36Sopenharmony_ci
122862306a36Sopenharmony_ci	mutex_lock(&padctl->lock);
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0);
123162306a36Sopenharmony_ci	value &= ~ALL_WAKE_EVENTS;
123262306a36Sopenharmony_ci	value &= ~USB2_PORT_WAKE_INTERRUPT_ENABLE(index);
123362306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0);
123462306a36Sopenharmony_ci
123562306a36Sopenharmony_ci	usleep_range(10, 20);
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0);
123862306a36Sopenharmony_ci	value &= ~ALL_WAKE_EVENTS;
123962306a36Sopenharmony_ci	value |= USB2_PORT_WAKEUP_EVENT(index);
124062306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0);
124162306a36Sopenharmony_ci
124262306a36Sopenharmony_ci	mutex_unlock(&padctl->lock);
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_ci	return 0;
124562306a36Sopenharmony_ci}
124662306a36Sopenharmony_ci
124762306a36Sopenharmony_cistatic bool tegra210_utmi_phy_remote_wake_detected(struct tegra_xusb_lane *lane)
124862306a36Sopenharmony_ci{
124962306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
125062306a36Sopenharmony_ci	unsigned int index = lane->index;
125162306a36Sopenharmony_ci	u32 value;
125262306a36Sopenharmony_ci
125362306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0);
125462306a36Sopenharmony_ci	if ((value & USB2_PORT_WAKE_INTERRUPT_ENABLE(index)) &&
125562306a36Sopenharmony_ci	    (value & USB2_PORT_WAKEUP_EVENT(index)))
125662306a36Sopenharmony_ci		return true;
125762306a36Sopenharmony_ci
125862306a36Sopenharmony_ci	return false;
125962306a36Sopenharmony_ci}
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_cistatic int tegra210_hsic_enable_phy_wake(struct tegra_xusb_lane *lane)
126262306a36Sopenharmony_ci{
126362306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
126462306a36Sopenharmony_ci	unsigned int index = lane->index;
126562306a36Sopenharmony_ci	u32 value;
126662306a36Sopenharmony_ci
126762306a36Sopenharmony_ci	mutex_lock(&padctl->lock);
126862306a36Sopenharmony_ci
126962306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0);
127062306a36Sopenharmony_ci	value &= ~ALL_WAKE_EVENTS;
127162306a36Sopenharmony_ci	value |= USB2_HSIC_PORT_WAKEUP_EVENT(index);
127262306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0);
127362306a36Sopenharmony_ci
127462306a36Sopenharmony_ci	usleep_range(10, 20);
127562306a36Sopenharmony_ci
127662306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0);
127762306a36Sopenharmony_ci	value &= ~ALL_WAKE_EVENTS;
127862306a36Sopenharmony_ci	value |= USB2_HSIC_PORT_WAKE_INTERRUPT_ENABLE(index);
127962306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0);
128062306a36Sopenharmony_ci
128162306a36Sopenharmony_ci	mutex_unlock(&padctl->lock);
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci	return 0;
128462306a36Sopenharmony_ci}
128562306a36Sopenharmony_ci
128662306a36Sopenharmony_cistatic int tegra210_hsic_disable_phy_wake(struct tegra_xusb_lane *lane)
128762306a36Sopenharmony_ci{
128862306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
128962306a36Sopenharmony_ci	unsigned int index = lane->index;
129062306a36Sopenharmony_ci	u32 value;
129162306a36Sopenharmony_ci
129262306a36Sopenharmony_ci	mutex_lock(&padctl->lock);
129362306a36Sopenharmony_ci
129462306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0);
129562306a36Sopenharmony_ci	value &= ~ALL_WAKE_EVENTS;
129662306a36Sopenharmony_ci	value &= ~USB2_HSIC_PORT_WAKE_INTERRUPT_ENABLE(index);
129762306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0);
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_ci	usleep_range(10, 20);
130062306a36Sopenharmony_ci
130162306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0);
130262306a36Sopenharmony_ci	value &= ~ALL_WAKE_EVENTS;
130362306a36Sopenharmony_ci	value |= USB2_HSIC_PORT_WAKEUP_EVENT(index);
130462306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0);
130562306a36Sopenharmony_ci
130662306a36Sopenharmony_ci	mutex_unlock(&padctl->lock);
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ci	return 0;
130962306a36Sopenharmony_ci}
131062306a36Sopenharmony_ci
131162306a36Sopenharmony_cistatic bool tegra210_hsic_phy_remote_wake_detected(struct tegra_xusb_lane *lane)
131262306a36Sopenharmony_ci{
131362306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
131462306a36Sopenharmony_ci	unsigned int index = lane->index;
131562306a36Sopenharmony_ci	u32 value;
131662306a36Sopenharmony_ci
131762306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0);
131862306a36Sopenharmony_ci	if ((value & USB2_HSIC_PORT_WAKE_INTERRUPT_ENABLE(index)) &&
131962306a36Sopenharmony_ci	    (value & USB2_HSIC_PORT_WAKEUP_EVENT(index)))
132062306a36Sopenharmony_ci		return true;
132162306a36Sopenharmony_ci
132262306a36Sopenharmony_ci	return false;
132362306a36Sopenharmony_ci}
132462306a36Sopenharmony_ci
132562306a36Sopenharmony_ci#define padctl_pmc_readl(_priv, _offset)						\
132662306a36Sopenharmony_ci({											\
132762306a36Sopenharmony_ci	u32 value;									\
132862306a36Sopenharmony_ci	WARN(regmap_read(_priv->regmap, _offset, &value), "read %s failed\n", #_offset);\
132962306a36Sopenharmony_ci	value;										\
133062306a36Sopenharmony_ci})
133162306a36Sopenharmony_ci
133262306a36Sopenharmony_ci#define padctl_pmc_writel(_priv, _value, _offset)					\
133362306a36Sopenharmony_ci	WARN(regmap_write(_priv->regmap, _offset, _value), "write %s failed\n", #_offset)
133462306a36Sopenharmony_ci
133562306a36Sopenharmony_cistatic int tegra210_pmc_utmi_enable_phy_sleepwalk(struct tegra_xusb_lane *lane,
133662306a36Sopenharmony_ci						  enum usb_device_speed speed)
133762306a36Sopenharmony_ci{
133862306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
133962306a36Sopenharmony_ci	struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl);
134062306a36Sopenharmony_ci	unsigned int port = lane->index;
134162306a36Sopenharmony_ci	u32 value, tctrl, pctrl, rpd_ctrl;
134262306a36Sopenharmony_ci
134362306a36Sopenharmony_ci	if (!priv->regmap)
134462306a36Sopenharmony_ci		return -EOPNOTSUPP;
134562306a36Sopenharmony_ci
134662306a36Sopenharmony_ci	if (speed > USB_SPEED_HIGH)
134762306a36Sopenharmony_ci		return -EINVAL;
134862306a36Sopenharmony_ci
134962306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
135062306a36Sopenharmony_ci	tctrl = TCTRL_VALUE(value);
135162306a36Sopenharmony_ci	pctrl = PCTRL_VALUE(value);
135262306a36Sopenharmony_ci
135362306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(port));
135462306a36Sopenharmony_ci	rpd_ctrl = RPD_CTRL_VALUE(value);
135562306a36Sopenharmony_ci
135662306a36Sopenharmony_ci	/* ensure sleepwalk logic is disabled */
135762306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port));
135862306a36Sopenharmony_ci	value &= ~UTMIP_MASTER_ENABLE(port);
135962306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port));
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_ci	/* ensure sleepwalk logics are in low power mode */
136262306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_MASTER_CONFIG);
136362306a36Sopenharmony_ci	value |= UTMIP_PWR(port);
136462306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_MASTER_CONFIG);
136562306a36Sopenharmony_ci
136662306a36Sopenharmony_ci	/* set debounce time */
136762306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_USB_DEBOUNCE_DEL);
136862306a36Sopenharmony_ci	value &= ~UTMIP_LINE_DEB_CNT(~0);
136962306a36Sopenharmony_ci	value |= UTMIP_LINE_DEB_CNT(0x1);
137062306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_USB_DEBOUNCE_DEL);
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_ci	/* ensure fake events of sleepwalk logic are desiabled */
137362306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_FAKE(port));
137462306a36Sopenharmony_ci	value &= ~(UTMIP_FAKE_USBOP_VAL(port) | UTMIP_FAKE_USBON_VAL(port) |
137562306a36Sopenharmony_ci		   UTMIP_FAKE_USBOP_EN(port) | UTMIP_FAKE_USBON_EN(port));
137662306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_FAKE(port));
137762306a36Sopenharmony_ci
137862306a36Sopenharmony_ci	/* ensure wake events of sleepwalk logic are not latched */
137962306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_LINE_WAKEUP);
138062306a36Sopenharmony_ci	value &= ~UTMIP_LINE_WAKEUP_EN(port);
138162306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_LINE_WAKEUP);
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_ci	/* disable wake event triggers of sleepwalk logic */
138462306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port));
138562306a36Sopenharmony_ci	value &= ~UTMIP_WAKE_VAL(port, ~0);
138662306a36Sopenharmony_ci	value |= UTMIP_WAKE_VAL_NONE(port);
138762306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port));
138862306a36Sopenharmony_ci
138962306a36Sopenharmony_ci	/* power down the line state detectors of the pad */
139062306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_USB_AO);
139162306a36Sopenharmony_ci	value |= (USBOP_VAL_PD(port) | USBON_VAL_PD(port));
139262306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_USB_AO);
139362306a36Sopenharmony_ci
139462306a36Sopenharmony_ci	/* save state per speed */
139562306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SAVED_STATE(port));
139662306a36Sopenharmony_ci	value &= ~SPEED(port, ~0);
139762306a36Sopenharmony_ci
139862306a36Sopenharmony_ci	switch (speed) {
139962306a36Sopenharmony_ci	case USB_SPEED_HIGH:
140062306a36Sopenharmony_ci		value |= UTMI_HS(port);
140162306a36Sopenharmony_ci		break;
140262306a36Sopenharmony_ci
140362306a36Sopenharmony_ci	case USB_SPEED_FULL:
140462306a36Sopenharmony_ci		value |= UTMI_FS(port);
140562306a36Sopenharmony_ci		break;
140662306a36Sopenharmony_ci
140762306a36Sopenharmony_ci	case USB_SPEED_LOW:
140862306a36Sopenharmony_ci		value |= UTMI_LS(port);
140962306a36Sopenharmony_ci		break;
141062306a36Sopenharmony_ci
141162306a36Sopenharmony_ci	default:
141262306a36Sopenharmony_ci		value |= UTMI_RST(port);
141362306a36Sopenharmony_ci		break;
141462306a36Sopenharmony_ci	}
141562306a36Sopenharmony_ci
141662306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SAVED_STATE(port));
141762306a36Sopenharmony_ci
141862306a36Sopenharmony_ci	/* enable the trigger of the sleepwalk logic */
141962306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEPWALK_CFG(port));
142062306a36Sopenharmony_ci	value |= UTMIP_LINEVAL_WALK_EN(port);
142162306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEPWALK_CFG(port));
142262306a36Sopenharmony_ci
142362306a36Sopenharmony_ci	/*
142462306a36Sopenharmony_ci	 * Reset the walk pointer and clear the alarm of the sleepwalk logic,
142562306a36Sopenharmony_ci	 * as well as capture the configuration of the USB2.0 pad.
142662306a36Sopenharmony_ci	 */
142762306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_TRIGGERS);
142862306a36Sopenharmony_ci	value |= UTMIP_CLR_WALK_PTR(port) | UTMIP_CLR_WAKE_ALARM(port) | UTMIP_CAP_CFG(port);
142962306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_TRIGGERS);
143062306a36Sopenharmony_ci
143162306a36Sopenharmony_ci	/* program electrical parameters read from XUSB PADCTL */
143262306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_TERM_PAD_CFG);
143362306a36Sopenharmony_ci	value &= ~(TCTRL_VAL(~0) | PCTRL_VAL(~0));
143462306a36Sopenharmony_ci	value |= (TCTRL_VAL(tctrl) | PCTRL_VAL(pctrl));
143562306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_TERM_PAD_CFG);
143662306a36Sopenharmony_ci
143762306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_PAD_CFGX(port));
143862306a36Sopenharmony_ci	value &= ~RPD_CTRL_PX(~0);
143962306a36Sopenharmony_ci	value |= RPD_CTRL_PX(rpd_ctrl);
144062306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_PAD_CFGX(port));
144162306a36Sopenharmony_ci
144262306a36Sopenharmony_ci	/*
144362306a36Sopenharmony_ci	 * Set up the pull-ups and pull-downs of the signals during the four
144462306a36Sopenharmony_ci	 * stages of sleepwalk. If a device is connected, program sleepwalk
144562306a36Sopenharmony_ci	 * logic to maintain a J and keep driving K upon seeing remote wake.
144662306a36Sopenharmony_ci	 */
144762306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_SLEEPWALK_PX(port));
144862306a36Sopenharmony_ci	value = UTMIP_USBOP_RPD_A | UTMIP_USBOP_RPD_B | UTMIP_USBOP_RPD_C | UTMIP_USBOP_RPD_D;
144962306a36Sopenharmony_ci	value |= UTMIP_USBON_RPD_A | UTMIP_USBON_RPD_B | UTMIP_USBON_RPD_C | UTMIP_USBON_RPD_D;
145062306a36Sopenharmony_ci
145162306a36Sopenharmony_ci	switch (speed) {
145262306a36Sopenharmony_ci	case USB_SPEED_HIGH:
145362306a36Sopenharmony_ci	case USB_SPEED_FULL:
145462306a36Sopenharmony_ci		/* J state: D+/D- = high/low, K state: D+/D- = low/high */
145562306a36Sopenharmony_ci		value |= UTMIP_HIGHZ_A;
145662306a36Sopenharmony_ci		value |= UTMIP_AP_A;
145762306a36Sopenharmony_ci		value |= UTMIP_AN_B | UTMIP_AN_C | UTMIP_AN_D;
145862306a36Sopenharmony_ci		break;
145962306a36Sopenharmony_ci
146062306a36Sopenharmony_ci	case USB_SPEED_LOW:
146162306a36Sopenharmony_ci		/* J state: D+/D- = low/high, K state: D+/D- = high/low */
146262306a36Sopenharmony_ci		value |= UTMIP_HIGHZ_A;
146362306a36Sopenharmony_ci		value |= UTMIP_AN_A;
146462306a36Sopenharmony_ci		value |= UTMIP_AP_B | UTMIP_AP_C | UTMIP_AP_D;
146562306a36Sopenharmony_ci		break;
146662306a36Sopenharmony_ci
146762306a36Sopenharmony_ci	default:
146862306a36Sopenharmony_ci		value |= UTMIP_HIGHZ_A | UTMIP_HIGHZ_B | UTMIP_HIGHZ_C | UTMIP_HIGHZ_D;
146962306a36Sopenharmony_ci		break;
147062306a36Sopenharmony_ci	}
147162306a36Sopenharmony_ci
147262306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_SLEEPWALK_PX(port));
147362306a36Sopenharmony_ci
147462306a36Sopenharmony_ci	/* power up the line state detectors of the pad */
147562306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_USB_AO);
147662306a36Sopenharmony_ci	value &= ~(USBOP_VAL_PD(port) | USBON_VAL_PD(port));
147762306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_USB_AO);
147862306a36Sopenharmony_ci
147962306a36Sopenharmony_ci	usleep_range(50, 100);
148062306a36Sopenharmony_ci
148162306a36Sopenharmony_ci	/* switch the electric control of the USB2.0 pad to PMC */
148262306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port));
148362306a36Sopenharmony_ci	value |= UTMIP_FSLS_USE_PMC(port) | UTMIP_PCTRL_USE_PMC(port) | UTMIP_TCTRL_USE_PMC(port);
148462306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port));
148562306a36Sopenharmony_ci
148662306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG1);
148762306a36Sopenharmony_ci	value |= UTMIP_RPD_CTRL_USE_PMC_PX(port) | UTMIP_RPU_SWITC_LOW_USE_PMC_PX(port);
148862306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG1);
148962306a36Sopenharmony_ci
149062306a36Sopenharmony_ci	/* set the wake signaling trigger events */
149162306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port));
149262306a36Sopenharmony_ci	value &= ~UTMIP_WAKE_VAL(port, ~0);
149362306a36Sopenharmony_ci	value |= UTMIP_WAKE_VAL_ANY(port);
149462306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port));
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_ci	/* enable the wake detection */
149762306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port));
149862306a36Sopenharmony_ci	value |= UTMIP_MASTER_ENABLE(port);
149962306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port));
150062306a36Sopenharmony_ci
150162306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_LINE_WAKEUP);
150262306a36Sopenharmony_ci	value |= UTMIP_LINE_WAKEUP_EN(port);
150362306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_LINE_WAKEUP);
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci	return 0;
150662306a36Sopenharmony_ci}
150762306a36Sopenharmony_ci
150862306a36Sopenharmony_cistatic int tegra210_pmc_utmi_disable_phy_sleepwalk(struct tegra_xusb_lane *lane)
150962306a36Sopenharmony_ci{
151062306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
151162306a36Sopenharmony_ci	struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl);
151262306a36Sopenharmony_ci	unsigned int port = lane->index;
151362306a36Sopenharmony_ci	u32 value;
151462306a36Sopenharmony_ci
151562306a36Sopenharmony_ci	if (!priv->regmap)
151662306a36Sopenharmony_ci		return -EOPNOTSUPP;
151762306a36Sopenharmony_ci
151862306a36Sopenharmony_ci	/* disable the wake detection */
151962306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port));
152062306a36Sopenharmony_ci	value &= ~UTMIP_MASTER_ENABLE(port);
152162306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port));
152262306a36Sopenharmony_ci
152362306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_LINE_WAKEUP);
152462306a36Sopenharmony_ci	value &= ~UTMIP_LINE_WAKEUP_EN(port);
152562306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_LINE_WAKEUP);
152662306a36Sopenharmony_ci
152762306a36Sopenharmony_ci	/* switch the electric control of the USB2.0 pad to XUSB or USB2 */
152862306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port));
152962306a36Sopenharmony_ci	value &= ~(UTMIP_FSLS_USE_PMC(port) | UTMIP_PCTRL_USE_PMC(port) |
153062306a36Sopenharmony_ci		   UTMIP_TCTRL_USE_PMC(port));
153162306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port));
153262306a36Sopenharmony_ci
153362306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG1);
153462306a36Sopenharmony_ci	value &= ~(UTMIP_RPD_CTRL_USE_PMC_PX(port) | UTMIP_RPU_SWITC_LOW_USE_PMC_PX(port));
153562306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG1);
153662306a36Sopenharmony_ci
153762306a36Sopenharmony_ci	/* disable wake event triggers of sleepwalk logic */
153862306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port));
153962306a36Sopenharmony_ci	value &= ~UTMIP_WAKE_VAL(port, ~0);
154062306a36Sopenharmony_ci	value |= UTMIP_WAKE_VAL_NONE(port);
154162306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port));
154262306a36Sopenharmony_ci
154362306a36Sopenharmony_ci	/* power down the line state detectors of the port */
154462306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_USB_AO);
154562306a36Sopenharmony_ci	value |= (USBOP_VAL_PD(port) | USBON_VAL_PD(port));
154662306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_USB_AO);
154762306a36Sopenharmony_ci
154862306a36Sopenharmony_ci	/* clear alarm of the sleepwalk logic */
154962306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_TRIGGERS);
155062306a36Sopenharmony_ci	value |= UTMIP_CLR_WAKE_ALARM(port);
155162306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_TRIGGERS);
155262306a36Sopenharmony_ci
155362306a36Sopenharmony_ci	return 0;
155462306a36Sopenharmony_ci}
155562306a36Sopenharmony_ci
155662306a36Sopenharmony_cistatic int tegra210_pmc_hsic_enable_phy_sleepwalk(struct tegra_xusb_lane *lane,
155762306a36Sopenharmony_ci						  enum usb_device_speed speed)
155862306a36Sopenharmony_ci{
155962306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
156062306a36Sopenharmony_ci	struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl);
156162306a36Sopenharmony_ci	u32 value;
156262306a36Sopenharmony_ci
156362306a36Sopenharmony_ci	if (!priv->regmap)
156462306a36Sopenharmony_ci		return -EOPNOTSUPP;
156562306a36Sopenharmony_ci
156662306a36Sopenharmony_ci	/* ensure sleepwalk logic is disabled */
156762306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEP_CFG);
156862306a36Sopenharmony_ci	value &= ~UHSIC_MASTER_ENABLE;
156962306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEP_CFG);
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_ci	/* ensure sleepwalk logics are in low power mode */
157262306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_MASTER_CONFIG);
157362306a36Sopenharmony_ci	value |= UHSIC_PWR;
157462306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_MASTER_CONFIG);
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ci	/* set debounce time */
157762306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_USB_DEBOUNCE_DEL);
157862306a36Sopenharmony_ci	value &= ~UHSIC_LINE_DEB_CNT(~0);
157962306a36Sopenharmony_ci	value |= UHSIC_LINE_DEB_CNT(0x1);
158062306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_USB_DEBOUNCE_DEL);
158162306a36Sopenharmony_ci
158262306a36Sopenharmony_ci	/* ensure fake events of sleepwalk logic are desiabled */
158362306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UHSIC_FAKE);
158462306a36Sopenharmony_ci	value &= ~(UHSIC_FAKE_STROBE_VAL | UHSIC_FAKE_DATA_VAL |
158562306a36Sopenharmony_ci		   UHSIC_FAKE_STROBE_EN | UHSIC_FAKE_DATA_EN);
158662306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UHSIC_FAKE);
158762306a36Sopenharmony_ci
158862306a36Sopenharmony_ci	/* ensure wake events of sleepwalk logic are not latched */
158962306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_LINE_WAKEUP);
159062306a36Sopenharmony_ci	value &= ~UHSIC_LINE_WAKEUP_EN;
159162306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_LINE_WAKEUP);
159262306a36Sopenharmony_ci
159362306a36Sopenharmony_ci	/* disable wake event triggers of sleepwalk logic */
159462306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEP_CFG);
159562306a36Sopenharmony_ci	value &= ~UHSIC_WAKE_VAL(~0);
159662306a36Sopenharmony_ci	value |= UHSIC_WAKE_VAL_NONE;
159762306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEP_CFG);
159862306a36Sopenharmony_ci
159962306a36Sopenharmony_ci	/* power down the line state detectors of the port */
160062306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_USB_AO);
160162306a36Sopenharmony_ci	value |= STROBE_VAL_PD | DATA0_VAL_PD | DATA1_VAL_PD;
160262306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_USB_AO);
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_ci	/* save state, HSIC always comes up as HS */
160562306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UHSIC_SAVED_STATE);
160662306a36Sopenharmony_ci	value &= ~UHSIC_MODE(~0);
160762306a36Sopenharmony_ci	value |= UHSIC_HS;
160862306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UHSIC_SAVED_STATE);
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_ci	/* enable the trigger of the sleepwalk logic */
161162306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEPWALK_CFG);
161262306a36Sopenharmony_ci	value |= UHSIC_WAKE_WALK_EN | UHSIC_LINEVAL_WALK_EN;
161362306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEPWALK_CFG);
161462306a36Sopenharmony_ci
161562306a36Sopenharmony_ci	/*
161662306a36Sopenharmony_ci	 * Reset the walk pointer and clear the alarm of the sleepwalk logic,
161762306a36Sopenharmony_ci	 * as well as capture the configuration of the USB2.0 port.
161862306a36Sopenharmony_ci	 */
161962306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_TRIGGERS);
162062306a36Sopenharmony_ci	value |= UHSIC_CLR_WALK_PTR | UHSIC_CLR_WAKE_ALARM;
162162306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_TRIGGERS);
162262306a36Sopenharmony_ci
162362306a36Sopenharmony_ci	/*
162462306a36Sopenharmony_ci	 * Set up the pull-ups and pull-downs of the signals during the four
162562306a36Sopenharmony_ci	 * stages of sleepwalk. Maintain a HSIC IDLE and keep driving HSIC
162662306a36Sopenharmony_ci	 * RESUME upon remote wake.
162762306a36Sopenharmony_ci	 */
162862306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEPWALK_P0);
162962306a36Sopenharmony_ci	value = UHSIC_DATA0_RPD_A | UHSIC_DATA0_RPU_B | UHSIC_DATA0_RPU_C | UHSIC_DATA0_RPU_D |
163062306a36Sopenharmony_ci		UHSIC_STROBE_RPU_A | UHSIC_STROBE_RPD_B | UHSIC_STROBE_RPD_C | UHSIC_STROBE_RPD_D;
163162306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEPWALK_P0);
163262306a36Sopenharmony_ci
163362306a36Sopenharmony_ci	/* power up the line state detectors of the port */
163462306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_USB_AO);
163562306a36Sopenharmony_ci	value &= ~(STROBE_VAL_PD | DATA0_VAL_PD | DATA1_VAL_PD);
163662306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_USB_AO);
163762306a36Sopenharmony_ci
163862306a36Sopenharmony_ci	usleep_range(50, 100);
163962306a36Sopenharmony_ci
164062306a36Sopenharmony_ci	/* set the wake signaling trigger events */
164162306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEP_CFG);
164262306a36Sopenharmony_ci	value &= ~UHSIC_WAKE_VAL(~0);
164362306a36Sopenharmony_ci	value |= UHSIC_WAKE_VAL_SD10;
164462306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEP_CFG);
164562306a36Sopenharmony_ci
164662306a36Sopenharmony_ci	/* enable the wake detection */
164762306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEP_CFG);
164862306a36Sopenharmony_ci	value |= UHSIC_MASTER_ENABLE;
164962306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEP_CFG);
165062306a36Sopenharmony_ci
165162306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_LINE_WAKEUP);
165262306a36Sopenharmony_ci	value |= UHSIC_LINE_WAKEUP_EN;
165362306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_LINE_WAKEUP);
165462306a36Sopenharmony_ci
165562306a36Sopenharmony_ci	return 0;
165662306a36Sopenharmony_ci}
165762306a36Sopenharmony_ci
165862306a36Sopenharmony_cistatic int tegra210_pmc_hsic_disable_phy_sleepwalk(struct tegra_xusb_lane *lane)
165962306a36Sopenharmony_ci{
166062306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
166162306a36Sopenharmony_ci	struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl);
166262306a36Sopenharmony_ci	u32 value;
166362306a36Sopenharmony_ci
166462306a36Sopenharmony_ci	if (!priv->regmap)
166562306a36Sopenharmony_ci		return -EOPNOTSUPP;
166662306a36Sopenharmony_ci
166762306a36Sopenharmony_ci	/* disable the wake detection */
166862306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEP_CFG);
166962306a36Sopenharmony_ci	value &= ~UHSIC_MASTER_ENABLE;
167062306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEP_CFG);
167162306a36Sopenharmony_ci
167262306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_LINE_WAKEUP);
167362306a36Sopenharmony_ci	value &= ~UHSIC_LINE_WAKEUP_EN;
167462306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_LINE_WAKEUP);
167562306a36Sopenharmony_ci
167662306a36Sopenharmony_ci	/* disable wake event triggers of sleepwalk logic */
167762306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEP_CFG);
167862306a36Sopenharmony_ci	value &= ~UHSIC_WAKE_VAL(~0);
167962306a36Sopenharmony_ci	value |= UHSIC_WAKE_VAL_NONE;
168062306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEP_CFG);
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_ci	/* power down the line state detectors of the port */
168362306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_USB_AO);
168462306a36Sopenharmony_ci	value |= STROBE_VAL_PD | DATA0_VAL_PD | DATA1_VAL_PD;
168562306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_USB_AO);
168662306a36Sopenharmony_ci
168762306a36Sopenharmony_ci	/* clear alarm of the sleepwalk logic */
168862306a36Sopenharmony_ci	value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_TRIGGERS);
168962306a36Sopenharmony_ci	value |= UHSIC_CLR_WAKE_ALARM;
169062306a36Sopenharmony_ci	padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_TRIGGERS);
169162306a36Sopenharmony_ci
169262306a36Sopenharmony_ci	return 0;
169362306a36Sopenharmony_ci}
169462306a36Sopenharmony_ci
169562306a36Sopenharmony_cistatic int tegra210_usb3_set_lfps_detect(struct tegra_xusb_padctl *padctl,
169662306a36Sopenharmony_ci					 unsigned int index, bool enable)
169762306a36Sopenharmony_ci{
169862306a36Sopenharmony_ci	struct tegra_xusb_port *port;
169962306a36Sopenharmony_ci	struct tegra_xusb_lane *lane;
170062306a36Sopenharmony_ci	u32 value, offset;
170162306a36Sopenharmony_ci
170262306a36Sopenharmony_ci	port = tegra_xusb_find_port(padctl, "usb3", index);
170362306a36Sopenharmony_ci	if (!port)
170462306a36Sopenharmony_ci		return -ENODEV;
170562306a36Sopenharmony_ci
170662306a36Sopenharmony_ci	lane = port->lane;
170762306a36Sopenharmony_ci
170862306a36Sopenharmony_ci	if (lane->pad == padctl->pcie)
170962306a36Sopenharmony_ci		offset = XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL1(lane->index);
171062306a36Sopenharmony_ci	else
171162306a36Sopenharmony_ci		offset = XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL1;
171262306a36Sopenharmony_ci
171362306a36Sopenharmony_ci	value = padctl_readl(padctl, offset);
171462306a36Sopenharmony_ci
171562306a36Sopenharmony_ci	value &= ~((XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_MASK <<
171662306a36Sopenharmony_ci		    XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_SHIFT) |
171762306a36Sopenharmony_ci		   XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_TERM_EN |
171862306a36Sopenharmony_ci		   XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_MODE_OVRD);
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_ci	if (!enable) {
172162306a36Sopenharmony_ci		value |= (XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_VAL <<
172262306a36Sopenharmony_ci			  XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_SHIFT) |
172362306a36Sopenharmony_ci			 XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_TERM_EN |
172462306a36Sopenharmony_ci			 XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_MODE_OVRD;
172562306a36Sopenharmony_ci	}
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_ci	padctl_writel(padctl, value, offset);
172862306a36Sopenharmony_ci
172962306a36Sopenharmony_ci	return 0;
173062306a36Sopenharmony_ci}
173162306a36Sopenharmony_ci
173262306a36Sopenharmony_ci#define TEGRA210_LANE(_name, _offset, _shift, _mask, _type)		\
173362306a36Sopenharmony_ci	{								\
173462306a36Sopenharmony_ci		.name = _name,						\
173562306a36Sopenharmony_ci		.offset = _offset,					\
173662306a36Sopenharmony_ci		.shift = _shift,					\
173762306a36Sopenharmony_ci		.mask = _mask,						\
173862306a36Sopenharmony_ci		.num_funcs = ARRAY_SIZE(tegra210_##_type##_functions),	\
173962306a36Sopenharmony_ci		.funcs = tegra210_##_type##_functions,			\
174062306a36Sopenharmony_ci	}
174162306a36Sopenharmony_ci
174262306a36Sopenharmony_cistatic const char *tegra210_usb2_functions[] = {
174362306a36Sopenharmony_ci	"snps",
174462306a36Sopenharmony_ci	"xusb",
174562306a36Sopenharmony_ci	"uart"
174662306a36Sopenharmony_ci};
174762306a36Sopenharmony_ci
174862306a36Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra210_usb2_lanes[] = {
174962306a36Sopenharmony_ci	TEGRA210_LANE("usb2-0", 0x004,  0, 0x3, usb2),
175062306a36Sopenharmony_ci	TEGRA210_LANE("usb2-1", 0x004,  2, 0x3, usb2),
175162306a36Sopenharmony_ci	TEGRA210_LANE("usb2-2", 0x004,  4, 0x3, usb2),
175262306a36Sopenharmony_ci	TEGRA210_LANE("usb2-3", 0x004,  6, 0x3, usb2),
175362306a36Sopenharmony_ci};
175462306a36Sopenharmony_ci
175562306a36Sopenharmony_cistatic struct tegra_xusb_lane *
175662306a36Sopenharmony_citegra210_usb2_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np,
175762306a36Sopenharmony_ci			 unsigned int index)
175862306a36Sopenharmony_ci{
175962306a36Sopenharmony_ci	struct tegra_xusb_usb2_lane *usb2;
176062306a36Sopenharmony_ci	int err;
176162306a36Sopenharmony_ci
176262306a36Sopenharmony_ci	usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL);
176362306a36Sopenharmony_ci	if (!usb2)
176462306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
176562306a36Sopenharmony_ci
176662306a36Sopenharmony_ci	INIT_LIST_HEAD(&usb2->base.list);
176762306a36Sopenharmony_ci	usb2->base.soc = &pad->soc->lanes[index];
176862306a36Sopenharmony_ci	usb2->base.index = index;
176962306a36Sopenharmony_ci	usb2->base.pad = pad;
177062306a36Sopenharmony_ci	usb2->base.np = np;
177162306a36Sopenharmony_ci
177262306a36Sopenharmony_ci	err = tegra_xusb_lane_parse_dt(&usb2->base, np);
177362306a36Sopenharmony_ci	if (err < 0) {
177462306a36Sopenharmony_ci		kfree(usb2);
177562306a36Sopenharmony_ci		return ERR_PTR(err);
177662306a36Sopenharmony_ci	}
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_ci	return &usb2->base;
177962306a36Sopenharmony_ci}
178062306a36Sopenharmony_ci
178162306a36Sopenharmony_cistatic void tegra210_usb2_lane_remove(struct tegra_xusb_lane *lane)
178262306a36Sopenharmony_ci{
178362306a36Sopenharmony_ci	struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane);
178462306a36Sopenharmony_ci
178562306a36Sopenharmony_ci	kfree(usb2);
178662306a36Sopenharmony_ci}
178762306a36Sopenharmony_ci
178862306a36Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra210_usb2_lane_ops = {
178962306a36Sopenharmony_ci	.probe = tegra210_usb2_lane_probe,
179062306a36Sopenharmony_ci	.remove = tegra210_usb2_lane_remove,
179162306a36Sopenharmony_ci	.enable_phy_sleepwalk = tegra210_pmc_utmi_enable_phy_sleepwalk,
179262306a36Sopenharmony_ci	.disable_phy_sleepwalk = tegra210_pmc_utmi_disable_phy_sleepwalk,
179362306a36Sopenharmony_ci	.enable_phy_wake = tegra210_utmi_enable_phy_wake,
179462306a36Sopenharmony_ci	.disable_phy_wake = tegra210_utmi_disable_phy_wake,
179562306a36Sopenharmony_ci	.remote_wake_detected = tegra210_utmi_phy_remote_wake_detected,
179662306a36Sopenharmony_ci};
179762306a36Sopenharmony_ci
179862306a36Sopenharmony_cistatic int tegra210_usb2_phy_init(struct phy *phy)
179962306a36Sopenharmony_ci{
180062306a36Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
180162306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
180262306a36Sopenharmony_ci	unsigned int index = lane->index;
180362306a36Sopenharmony_ci	struct tegra_xusb_usb2_port *port;
180462306a36Sopenharmony_ci	int err;
180562306a36Sopenharmony_ci	u32 value;
180662306a36Sopenharmony_ci
180762306a36Sopenharmony_ci	port = tegra_xusb_find_usb2_port(padctl, index);
180862306a36Sopenharmony_ci	if (!port) {
180962306a36Sopenharmony_ci		dev_err(&phy->dev, "no port found for USB2 lane %u\n", index);
181062306a36Sopenharmony_ci		return -ENODEV;
181162306a36Sopenharmony_ci	}
181262306a36Sopenharmony_ci
181362306a36Sopenharmony_ci	if (port->supply && port->mode == USB_DR_MODE_HOST) {
181462306a36Sopenharmony_ci		err = regulator_enable(port->supply);
181562306a36Sopenharmony_ci		if (err)
181662306a36Sopenharmony_ci			return err;
181762306a36Sopenharmony_ci	}
181862306a36Sopenharmony_ci
181962306a36Sopenharmony_ci	mutex_lock(&padctl->lock);
182062306a36Sopenharmony_ci
182162306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB2_PAD_MUX);
182262306a36Sopenharmony_ci	value &= ~(XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_MASK <<
182362306a36Sopenharmony_ci		   XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_SHIFT);
182462306a36Sopenharmony_ci	value |= XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_XUSB <<
182562306a36Sopenharmony_ci		 XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_SHIFT;
182662306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB2_PAD_MUX);
182762306a36Sopenharmony_ci
182862306a36Sopenharmony_ci	mutex_unlock(&padctl->lock);
182962306a36Sopenharmony_ci
183062306a36Sopenharmony_ci	return 0;
183162306a36Sopenharmony_ci}
183262306a36Sopenharmony_ci
183362306a36Sopenharmony_cistatic int tegra210_usb2_phy_exit(struct phy *phy)
183462306a36Sopenharmony_ci{
183562306a36Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
183662306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
183762306a36Sopenharmony_ci	struct tegra_xusb_usb2_port *port;
183862306a36Sopenharmony_ci	int err;
183962306a36Sopenharmony_ci
184062306a36Sopenharmony_ci	port = tegra_xusb_find_usb2_port(padctl, lane->index);
184162306a36Sopenharmony_ci	if (!port) {
184262306a36Sopenharmony_ci		dev_err(&phy->dev, "no port found for USB2 lane %u\n", lane->index);
184362306a36Sopenharmony_ci		return -ENODEV;
184462306a36Sopenharmony_ci	}
184562306a36Sopenharmony_ci
184662306a36Sopenharmony_ci	if (port->supply && port->mode == USB_DR_MODE_HOST) {
184762306a36Sopenharmony_ci		err = regulator_disable(port->supply);
184862306a36Sopenharmony_ci		if (err)
184962306a36Sopenharmony_ci			return err;
185062306a36Sopenharmony_ci	}
185162306a36Sopenharmony_ci
185262306a36Sopenharmony_ci	return 0;
185362306a36Sopenharmony_ci}
185462306a36Sopenharmony_ci
185562306a36Sopenharmony_cistatic int tegra210_xusb_padctl_vbus_override(struct tegra_xusb_padctl *padctl,
185662306a36Sopenharmony_ci					      bool status)
185762306a36Sopenharmony_ci{
185862306a36Sopenharmony_ci	u32 value;
185962306a36Sopenharmony_ci
186062306a36Sopenharmony_ci	dev_dbg(padctl->dev, "%s vbus override\n", status ? "set" : "clear");
186162306a36Sopenharmony_ci
186262306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB2_VBUS_ID);
186362306a36Sopenharmony_ci
186462306a36Sopenharmony_ci	if (status) {
186562306a36Sopenharmony_ci		value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON;
186662306a36Sopenharmony_ci		value &= ~(XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK <<
186762306a36Sopenharmony_ci			   XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT);
186862306a36Sopenharmony_ci		value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING <<
186962306a36Sopenharmony_ci			 XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT;
187062306a36Sopenharmony_ci	} else {
187162306a36Sopenharmony_ci		value &= ~XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON;
187262306a36Sopenharmony_ci	}
187362306a36Sopenharmony_ci
187462306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB2_VBUS_ID);
187562306a36Sopenharmony_ci
187662306a36Sopenharmony_ci	return 0;
187762306a36Sopenharmony_ci}
187862306a36Sopenharmony_ci
187962306a36Sopenharmony_cistatic int tegra210_xusb_padctl_id_override(struct tegra_xusb_padctl *padctl,
188062306a36Sopenharmony_ci					    bool status)
188162306a36Sopenharmony_ci{
188262306a36Sopenharmony_ci	u32 value;
188362306a36Sopenharmony_ci
188462306a36Sopenharmony_ci	dev_dbg(padctl->dev, "%s id override\n", status ? "set" : "clear");
188562306a36Sopenharmony_ci
188662306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB2_VBUS_ID);
188762306a36Sopenharmony_ci
188862306a36Sopenharmony_ci	if (status) {
188962306a36Sopenharmony_ci		if (value & XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON) {
189062306a36Sopenharmony_ci			value &= ~XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON;
189162306a36Sopenharmony_ci			padctl_writel(padctl, value, XUSB_PADCTL_USB2_VBUS_ID);
189262306a36Sopenharmony_ci			usleep_range(1000, 2000);
189362306a36Sopenharmony_ci
189462306a36Sopenharmony_ci			value = padctl_readl(padctl, XUSB_PADCTL_USB2_VBUS_ID);
189562306a36Sopenharmony_ci		}
189662306a36Sopenharmony_ci
189762306a36Sopenharmony_ci		value &= ~(XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK <<
189862306a36Sopenharmony_ci			   XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT);
189962306a36Sopenharmony_ci		value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_GROUNDED <<
190062306a36Sopenharmony_ci			 XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT;
190162306a36Sopenharmony_ci	} else {
190262306a36Sopenharmony_ci		value &= ~(XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK <<
190362306a36Sopenharmony_ci			   XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT);
190462306a36Sopenharmony_ci		value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING <<
190562306a36Sopenharmony_ci			 XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT;
190662306a36Sopenharmony_ci	}
190762306a36Sopenharmony_ci
190862306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB2_VBUS_ID);
190962306a36Sopenharmony_ci
191062306a36Sopenharmony_ci	return 0;
191162306a36Sopenharmony_ci}
191262306a36Sopenharmony_ci
191362306a36Sopenharmony_cistatic int tegra210_usb2_phy_set_mode(struct phy *phy, enum phy_mode mode,
191462306a36Sopenharmony_ci				      int submode)
191562306a36Sopenharmony_ci{
191662306a36Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
191762306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
191862306a36Sopenharmony_ci	struct tegra_xusb_usb2_port *port = tegra_xusb_find_usb2_port(padctl,
191962306a36Sopenharmony_ci								lane->index);
192062306a36Sopenharmony_ci	int err = 0;
192162306a36Sopenharmony_ci
192262306a36Sopenharmony_ci	mutex_lock(&padctl->lock);
192362306a36Sopenharmony_ci
192462306a36Sopenharmony_ci	dev_dbg(&port->base.dev, "%s: mode %d", __func__, mode);
192562306a36Sopenharmony_ci
192662306a36Sopenharmony_ci	if (mode == PHY_MODE_USB_OTG) {
192762306a36Sopenharmony_ci		if (submode == USB_ROLE_HOST) {
192862306a36Sopenharmony_ci			tegra210_xusb_padctl_id_override(padctl, true);
192962306a36Sopenharmony_ci
193062306a36Sopenharmony_ci			err = regulator_enable(port->supply);
193162306a36Sopenharmony_ci		} else if (submode == USB_ROLE_DEVICE) {
193262306a36Sopenharmony_ci			tegra210_xusb_padctl_vbus_override(padctl, true);
193362306a36Sopenharmony_ci		} else if (submode == USB_ROLE_NONE) {
193462306a36Sopenharmony_ci			/*
193562306a36Sopenharmony_ci			 * When port is peripheral only or role transitions to
193662306a36Sopenharmony_ci			 * USB_ROLE_NONE from USB_ROLE_DEVICE, regulator is not
193762306a36Sopenharmony_ci			 * be enabled.
193862306a36Sopenharmony_ci			 */
193962306a36Sopenharmony_ci			if (regulator_is_enabled(port->supply))
194062306a36Sopenharmony_ci				regulator_disable(port->supply);
194162306a36Sopenharmony_ci
194262306a36Sopenharmony_ci			tegra210_xusb_padctl_id_override(padctl, false);
194362306a36Sopenharmony_ci			tegra210_xusb_padctl_vbus_override(padctl, false);
194462306a36Sopenharmony_ci		}
194562306a36Sopenharmony_ci	}
194662306a36Sopenharmony_ci
194762306a36Sopenharmony_ci	mutex_unlock(&padctl->lock);
194862306a36Sopenharmony_ci
194962306a36Sopenharmony_ci	return err;
195062306a36Sopenharmony_ci}
195162306a36Sopenharmony_ci
195262306a36Sopenharmony_cistatic int tegra210_usb2_phy_power_on(struct phy *phy)
195362306a36Sopenharmony_ci{
195462306a36Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
195562306a36Sopenharmony_ci	struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane);
195662306a36Sopenharmony_ci	struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad);
195762306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
195862306a36Sopenharmony_ci	struct tegra210_xusb_padctl *priv;
195962306a36Sopenharmony_ci	struct tegra_xusb_usb2_port *port;
196062306a36Sopenharmony_ci	unsigned int index = lane->index;
196162306a36Sopenharmony_ci	u32 value;
196262306a36Sopenharmony_ci	int err;
196362306a36Sopenharmony_ci
196462306a36Sopenharmony_ci	port = tegra_xusb_find_usb2_port(padctl, index);
196562306a36Sopenharmony_ci	if (!port) {
196662306a36Sopenharmony_ci		dev_err(&phy->dev, "no port found for USB2 lane %u\n", index);
196762306a36Sopenharmony_ci		return -ENODEV;
196862306a36Sopenharmony_ci	}
196962306a36Sopenharmony_ci
197062306a36Sopenharmony_ci	priv = to_tegra210_xusb_padctl(padctl);
197162306a36Sopenharmony_ci
197262306a36Sopenharmony_ci	mutex_lock(&padctl->lock);
197362306a36Sopenharmony_ci
197462306a36Sopenharmony_ci	if (port->usb3_port_fake != -1) {
197562306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP);
197662306a36Sopenharmony_ci		value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(
197762306a36Sopenharmony_ci					port->usb3_port_fake);
197862306a36Sopenharmony_ci		value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(
197962306a36Sopenharmony_ci					port->usb3_port_fake, index);
198062306a36Sopenharmony_ci		padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP);
198162306a36Sopenharmony_ci
198262306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
198362306a36Sopenharmony_ci		value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN(
198462306a36Sopenharmony_ci					port->usb3_port_fake);
198562306a36Sopenharmony_ci		padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
198662306a36Sopenharmony_ci
198762306a36Sopenharmony_ci		usleep_range(100, 200);
198862306a36Sopenharmony_ci
198962306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
199062306a36Sopenharmony_ci		value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(
199162306a36Sopenharmony_ci					port->usb3_port_fake);
199262306a36Sopenharmony_ci		padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
199362306a36Sopenharmony_ci
199462306a36Sopenharmony_ci		usleep_range(100, 200);
199562306a36Sopenharmony_ci
199662306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
199762306a36Sopenharmony_ci		value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(
199862306a36Sopenharmony_ci					port->usb3_port_fake);
199962306a36Sopenharmony_ci		padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
200062306a36Sopenharmony_ci	}
200162306a36Sopenharmony_ci
200262306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
200362306a36Sopenharmony_ci	value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK <<
200462306a36Sopenharmony_ci		    XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) |
200562306a36Sopenharmony_ci		   (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK <<
200662306a36Sopenharmony_ci		    XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT));
200762306a36Sopenharmony_ci	value |= (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL <<
200862306a36Sopenharmony_ci		  XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT);
200962306a36Sopenharmony_ci
201062306a36Sopenharmony_ci	if (tegra_sku_info.revision < TEGRA_REVISION_A02)
201162306a36Sopenharmony_ci		value |=
201262306a36Sopenharmony_ci			(XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_VAL <<
201362306a36Sopenharmony_ci			XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT);
201462306a36Sopenharmony_ci
201562306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
201662306a36Sopenharmony_ci
201762306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB2_PORT_CAP);
201862306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_MASK(index);
201962306a36Sopenharmony_ci	if (port->mode == USB_DR_MODE_UNKNOWN)
202062306a36Sopenharmony_ci		value |= XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_DISABLED(index);
202162306a36Sopenharmony_ci	else if (port->mode == USB_DR_MODE_PERIPHERAL)
202262306a36Sopenharmony_ci		value |= XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_DEVICE(index);
202362306a36Sopenharmony_ci	else if (port->mode == USB_DR_MODE_HOST)
202462306a36Sopenharmony_ci		value |= XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_HOST(index);
202562306a36Sopenharmony_ci	else if (port->mode == USB_DR_MODE_OTG)
202662306a36Sopenharmony_ci		value |= XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_OTG(index);
202762306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB2_PORT_CAP);
202862306a36Sopenharmony_ci
202962306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index));
203062306a36Sopenharmony_ci	value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK <<
203162306a36Sopenharmony_ci		    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT) |
203262306a36Sopenharmony_ci		   XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD |
203362306a36Sopenharmony_ci		   XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 |
203462306a36Sopenharmony_ci		   XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI);
203562306a36Sopenharmony_ci	value |= (priv->fuse.hs_curr_level[index] +
203662306a36Sopenharmony_ci		  usb2->hs_curr_level_offset) <<
203762306a36Sopenharmony_ci		 XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT;
203862306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index));
203962306a36Sopenharmony_ci
204062306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index));
204162306a36Sopenharmony_ci	value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK <<
204262306a36Sopenharmony_ci		    XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) |
204362306a36Sopenharmony_ci		   (XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_MASK <<
204462306a36Sopenharmony_ci		    XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_SHIFT) |
204562306a36Sopenharmony_ci		   XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR |
204662306a36Sopenharmony_ci		   XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_OVRD |
204762306a36Sopenharmony_ci		   XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_OVRD);
204862306a36Sopenharmony_ci	value |= (priv->fuse.hs_term_range_adj <<
204962306a36Sopenharmony_ci		  XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) |
205062306a36Sopenharmony_ci		 (priv->fuse.rpd_ctrl <<
205162306a36Sopenharmony_ci		  XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_SHIFT);
205262306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index));
205362306a36Sopenharmony_ci
205462306a36Sopenharmony_ci	value = padctl_readl(padctl,
205562306a36Sopenharmony_ci			     XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(index));
205662306a36Sopenharmony_ci	value &= ~(XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_MASK <<
205762306a36Sopenharmony_ci		   XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_SHIFT);
205862306a36Sopenharmony_ci	if (port->mode == USB_DR_MODE_HOST)
205962306a36Sopenharmony_ci		value |= XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_FIX18;
206062306a36Sopenharmony_ci	else
206162306a36Sopenharmony_ci		value |=
206262306a36Sopenharmony_ci		      XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_VAL <<
206362306a36Sopenharmony_ci		      XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_SHIFT;
206462306a36Sopenharmony_ci	padctl_writel(padctl, value,
206562306a36Sopenharmony_ci		      XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(index));
206662306a36Sopenharmony_ci
206762306a36Sopenharmony_ci	if (pad->enable > 0) {
206862306a36Sopenharmony_ci		pad->enable++;
206962306a36Sopenharmony_ci		mutex_unlock(&padctl->lock);
207062306a36Sopenharmony_ci		return 0;
207162306a36Sopenharmony_ci	}
207262306a36Sopenharmony_ci
207362306a36Sopenharmony_ci	err = clk_prepare_enable(pad->clk);
207462306a36Sopenharmony_ci	if (err)
207562306a36Sopenharmony_ci		goto out;
207662306a36Sopenharmony_ci
207762306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
207862306a36Sopenharmony_ci	value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_MASK <<
207962306a36Sopenharmony_ci		    XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_SHIFT) |
208062306a36Sopenharmony_ci		   (XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_MASK <<
208162306a36Sopenharmony_ci		    XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_SHIFT));
208262306a36Sopenharmony_ci	value |= (XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_VAL <<
208362306a36Sopenharmony_ci		  XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_SHIFT) |
208462306a36Sopenharmony_ci		 (XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_VAL <<
208562306a36Sopenharmony_ci		  XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_SHIFT);
208662306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
208762306a36Sopenharmony_ci
208862306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
208962306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD;
209062306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
209162306a36Sopenharmony_ci
209262306a36Sopenharmony_ci	udelay(1);
209362306a36Sopenharmony_ci
209462306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
209562306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL1_PD_TRK;
209662306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
209762306a36Sopenharmony_ci
209862306a36Sopenharmony_ci	udelay(50);
209962306a36Sopenharmony_ci
210062306a36Sopenharmony_ci	clk_disable_unprepare(pad->clk);
210162306a36Sopenharmony_ci
210262306a36Sopenharmony_ci	pad->enable++;
210362306a36Sopenharmony_ci	mutex_unlock(&padctl->lock);
210462306a36Sopenharmony_ci
210562306a36Sopenharmony_ci	return 0;
210662306a36Sopenharmony_ci
210762306a36Sopenharmony_ciout:
210862306a36Sopenharmony_ci	mutex_unlock(&padctl->lock);
210962306a36Sopenharmony_ci	return err;
211062306a36Sopenharmony_ci}
211162306a36Sopenharmony_ci
211262306a36Sopenharmony_cistatic int tegra210_usb2_phy_power_off(struct phy *phy)
211362306a36Sopenharmony_ci{
211462306a36Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
211562306a36Sopenharmony_ci	struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad);
211662306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
211762306a36Sopenharmony_ci	struct tegra_xusb_usb2_port *port;
211862306a36Sopenharmony_ci	u32 value;
211962306a36Sopenharmony_ci
212062306a36Sopenharmony_ci	port = tegra_xusb_find_usb2_port(padctl, lane->index);
212162306a36Sopenharmony_ci	if (!port) {
212262306a36Sopenharmony_ci		dev_err(&phy->dev, "no port found for USB2 lane %u\n",
212362306a36Sopenharmony_ci			lane->index);
212462306a36Sopenharmony_ci		return -ENODEV;
212562306a36Sopenharmony_ci	}
212662306a36Sopenharmony_ci
212762306a36Sopenharmony_ci	mutex_lock(&padctl->lock);
212862306a36Sopenharmony_ci
212962306a36Sopenharmony_ci	if (port->usb3_port_fake != -1) {
213062306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
213162306a36Sopenharmony_ci		value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(
213262306a36Sopenharmony_ci					port->usb3_port_fake);
213362306a36Sopenharmony_ci		padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
213462306a36Sopenharmony_ci
213562306a36Sopenharmony_ci		usleep_range(100, 200);
213662306a36Sopenharmony_ci
213762306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
213862306a36Sopenharmony_ci		value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(
213962306a36Sopenharmony_ci					port->usb3_port_fake);
214062306a36Sopenharmony_ci		padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
214162306a36Sopenharmony_ci
214262306a36Sopenharmony_ci		usleep_range(250, 350);
214362306a36Sopenharmony_ci
214462306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
214562306a36Sopenharmony_ci		value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN(
214662306a36Sopenharmony_ci					port->usb3_port_fake);
214762306a36Sopenharmony_ci		padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
214862306a36Sopenharmony_ci
214962306a36Sopenharmony_ci		value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP);
215062306a36Sopenharmony_ci		value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(port->usb3_port_fake,
215162306a36Sopenharmony_ci					XUSB_PADCTL_SS_PORT_MAP_PORT_DISABLED);
215262306a36Sopenharmony_ci		padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP);
215362306a36Sopenharmony_ci	}
215462306a36Sopenharmony_ci
215562306a36Sopenharmony_ci	if (WARN_ON(pad->enable == 0))
215662306a36Sopenharmony_ci		goto out;
215762306a36Sopenharmony_ci
215862306a36Sopenharmony_ci	if (--pad->enable > 0)
215962306a36Sopenharmony_ci		goto out;
216062306a36Sopenharmony_ci
216162306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
216262306a36Sopenharmony_ci	value |= XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD;
216362306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
216462306a36Sopenharmony_ci
216562306a36Sopenharmony_ciout:
216662306a36Sopenharmony_ci	mutex_unlock(&padctl->lock);
216762306a36Sopenharmony_ci	return 0;
216862306a36Sopenharmony_ci}
216962306a36Sopenharmony_ci
217062306a36Sopenharmony_cistatic const struct phy_ops tegra210_usb2_phy_ops = {
217162306a36Sopenharmony_ci	.init = tegra210_usb2_phy_init,
217262306a36Sopenharmony_ci	.exit = tegra210_usb2_phy_exit,
217362306a36Sopenharmony_ci	.power_on = tegra210_usb2_phy_power_on,
217462306a36Sopenharmony_ci	.power_off = tegra210_usb2_phy_power_off,
217562306a36Sopenharmony_ci	.set_mode = tegra210_usb2_phy_set_mode,
217662306a36Sopenharmony_ci	.owner = THIS_MODULE,
217762306a36Sopenharmony_ci};
217862306a36Sopenharmony_ci
217962306a36Sopenharmony_cistatic struct tegra_xusb_pad *
218062306a36Sopenharmony_citegra210_usb2_pad_probe(struct tegra_xusb_padctl *padctl,
218162306a36Sopenharmony_ci			const struct tegra_xusb_pad_soc *soc,
218262306a36Sopenharmony_ci			struct device_node *np)
218362306a36Sopenharmony_ci{
218462306a36Sopenharmony_ci	struct tegra_xusb_usb2_pad *usb2;
218562306a36Sopenharmony_ci	struct tegra_xusb_pad *pad;
218662306a36Sopenharmony_ci	int err;
218762306a36Sopenharmony_ci
218862306a36Sopenharmony_ci	usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL);
218962306a36Sopenharmony_ci	if (!usb2)
219062306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
219162306a36Sopenharmony_ci
219262306a36Sopenharmony_ci	pad = &usb2->base;
219362306a36Sopenharmony_ci	pad->ops = &tegra210_usb2_lane_ops;
219462306a36Sopenharmony_ci	pad->soc = soc;
219562306a36Sopenharmony_ci
219662306a36Sopenharmony_ci	err = tegra_xusb_pad_init(pad, padctl, np);
219762306a36Sopenharmony_ci	if (err < 0) {
219862306a36Sopenharmony_ci		kfree(usb2);
219962306a36Sopenharmony_ci		goto out;
220062306a36Sopenharmony_ci	}
220162306a36Sopenharmony_ci
220262306a36Sopenharmony_ci	usb2->clk = devm_clk_get(&pad->dev, "trk");
220362306a36Sopenharmony_ci	if (IS_ERR(usb2->clk)) {
220462306a36Sopenharmony_ci		err = PTR_ERR(usb2->clk);
220562306a36Sopenharmony_ci		dev_err(&pad->dev, "failed to get trk clock: %d\n", err);
220662306a36Sopenharmony_ci		goto unregister;
220762306a36Sopenharmony_ci	}
220862306a36Sopenharmony_ci
220962306a36Sopenharmony_ci	err = tegra_xusb_pad_register(pad, &tegra210_usb2_phy_ops);
221062306a36Sopenharmony_ci	if (err < 0)
221162306a36Sopenharmony_ci		goto unregister;
221262306a36Sopenharmony_ci
221362306a36Sopenharmony_ci	dev_set_drvdata(&pad->dev, pad);
221462306a36Sopenharmony_ci
221562306a36Sopenharmony_ci	return pad;
221662306a36Sopenharmony_ci
221762306a36Sopenharmony_ciunregister:
221862306a36Sopenharmony_ci	device_unregister(&pad->dev);
221962306a36Sopenharmony_ciout:
222062306a36Sopenharmony_ci	return ERR_PTR(err);
222162306a36Sopenharmony_ci}
222262306a36Sopenharmony_ci
222362306a36Sopenharmony_cistatic void tegra210_usb2_pad_remove(struct tegra_xusb_pad *pad)
222462306a36Sopenharmony_ci{
222562306a36Sopenharmony_ci	struct tegra_xusb_usb2_pad *usb2 = to_usb2_pad(pad);
222662306a36Sopenharmony_ci
222762306a36Sopenharmony_ci	kfree(usb2);
222862306a36Sopenharmony_ci}
222962306a36Sopenharmony_ci
223062306a36Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra210_usb2_ops = {
223162306a36Sopenharmony_ci	.probe = tegra210_usb2_pad_probe,
223262306a36Sopenharmony_ci	.remove = tegra210_usb2_pad_remove,
223362306a36Sopenharmony_ci};
223462306a36Sopenharmony_ci
223562306a36Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra210_usb2_pad = {
223662306a36Sopenharmony_ci	.name = "usb2",
223762306a36Sopenharmony_ci	.num_lanes = ARRAY_SIZE(tegra210_usb2_lanes),
223862306a36Sopenharmony_ci	.lanes = tegra210_usb2_lanes,
223962306a36Sopenharmony_ci	.ops = &tegra210_usb2_ops,
224062306a36Sopenharmony_ci};
224162306a36Sopenharmony_ci
224262306a36Sopenharmony_cistatic const char *tegra210_hsic_functions[] = {
224362306a36Sopenharmony_ci	"snps",
224462306a36Sopenharmony_ci	"xusb",
224562306a36Sopenharmony_ci};
224662306a36Sopenharmony_ci
224762306a36Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra210_hsic_lanes[] = {
224862306a36Sopenharmony_ci	TEGRA210_LANE("hsic-0", 0x004, 14, 0x1, hsic),
224962306a36Sopenharmony_ci};
225062306a36Sopenharmony_ci
225162306a36Sopenharmony_cistatic struct tegra_xusb_lane *
225262306a36Sopenharmony_citegra210_hsic_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np,
225362306a36Sopenharmony_ci			 unsigned int index)
225462306a36Sopenharmony_ci{
225562306a36Sopenharmony_ci	struct tegra_xusb_hsic_lane *hsic;
225662306a36Sopenharmony_ci	int err;
225762306a36Sopenharmony_ci
225862306a36Sopenharmony_ci	hsic = kzalloc(sizeof(*hsic), GFP_KERNEL);
225962306a36Sopenharmony_ci	if (!hsic)
226062306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
226162306a36Sopenharmony_ci
226262306a36Sopenharmony_ci	INIT_LIST_HEAD(&hsic->base.list);
226362306a36Sopenharmony_ci	hsic->base.soc = &pad->soc->lanes[index];
226462306a36Sopenharmony_ci	hsic->base.index = index;
226562306a36Sopenharmony_ci	hsic->base.pad = pad;
226662306a36Sopenharmony_ci	hsic->base.np = np;
226762306a36Sopenharmony_ci
226862306a36Sopenharmony_ci	err = tegra_xusb_lane_parse_dt(&hsic->base, np);
226962306a36Sopenharmony_ci	if (err < 0) {
227062306a36Sopenharmony_ci		kfree(hsic);
227162306a36Sopenharmony_ci		return ERR_PTR(err);
227262306a36Sopenharmony_ci	}
227362306a36Sopenharmony_ci
227462306a36Sopenharmony_ci	return &hsic->base;
227562306a36Sopenharmony_ci}
227662306a36Sopenharmony_ci
227762306a36Sopenharmony_cistatic void tegra210_hsic_lane_remove(struct tegra_xusb_lane *lane)
227862306a36Sopenharmony_ci{
227962306a36Sopenharmony_ci	struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane);
228062306a36Sopenharmony_ci
228162306a36Sopenharmony_ci	kfree(hsic);
228262306a36Sopenharmony_ci}
228362306a36Sopenharmony_ci
228462306a36Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra210_hsic_lane_ops = {
228562306a36Sopenharmony_ci	.probe = tegra210_hsic_lane_probe,
228662306a36Sopenharmony_ci	.remove = tegra210_hsic_lane_remove,
228762306a36Sopenharmony_ci	.enable_phy_sleepwalk = tegra210_pmc_hsic_enable_phy_sleepwalk,
228862306a36Sopenharmony_ci	.disable_phy_sleepwalk = tegra210_pmc_hsic_disable_phy_sleepwalk,
228962306a36Sopenharmony_ci	.enable_phy_wake = tegra210_hsic_enable_phy_wake,
229062306a36Sopenharmony_ci	.disable_phy_wake = tegra210_hsic_disable_phy_wake,
229162306a36Sopenharmony_ci	.remote_wake_detected = tegra210_hsic_phy_remote_wake_detected,
229262306a36Sopenharmony_ci};
229362306a36Sopenharmony_ci
229462306a36Sopenharmony_cistatic int tegra210_hsic_phy_init(struct phy *phy)
229562306a36Sopenharmony_ci{
229662306a36Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
229762306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
229862306a36Sopenharmony_ci	u32 value;
229962306a36Sopenharmony_ci
230062306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_USB2_PAD_MUX);
230162306a36Sopenharmony_ci	value &= ~(XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_MASK <<
230262306a36Sopenharmony_ci		   XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_SHIFT);
230362306a36Sopenharmony_ci	value |= XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_XUSB <<
230462306a36Sopenharmony_ci		 XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_SHIFT;
230562306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_USB2_PAD_MUX);
230662306a36Sopenharmony_ci
230762306a36Sopenharmony_ci	return 0;
230862306a36Sopenharmony_ci}
230962306a36Sopenharmony_ci
231062306a36Sopenharmony_cistatic int tegra210_hsic_phy_exit(struct phy *phy)
231162306a36Sopenharmony_ci{
231262306a36Sopenharmony_ci	return 0;
231362306a36Sopenharmony_ci}
231462306a36Sopenharmony_ci
231562306a36Sopenharmony_cistatic int tegra210_hsic_phy_power_on(struct phy *phy)
231662306a36Sopenharmony_ci{
231762306a36Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
231862306a36Sopenharmony_ci	struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane);
231962306a36Sopenharmony_ci	struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad);
232062306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
232162306a36Sopenharmony_ci	unsigned int index = lane->index;
232262306a36Sopenharmony_ci	u32 value;
232362306a36Sopenharmony_ci	int err;
232462306a36Sopenharmony_ci
232562306a36Sopenharmony_ci	err = regulator_enable(pad->supply);
232662306a36Sopenharmony_ci	if (err)
232762306a36Sopenharmony_ci		return err;
232862306a36Sopenharmony_ci
232962306a36Sopenharmony_ci	padctl_writel(padctl, hsic->strobe_trim,
233062306a36Sopenharmony_ci		      XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL);
233162306a36Sopenharmony_ci
233262306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index));
233362306a36Sopenharmony_ci	value &= ~(XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_MASK <<
233462306a36Sopenharmony_ci		   XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_SHIFT);
233562306a36Sopenharmony_ci	value |= (hsic->tx_rtune_p <<
233662306a36Sopenharmony_ci		  XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_SHIFT);
233762306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index));
233862306a36Sopenharmony_ci
233962306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL2(index));
234062306a36Sopenharmony_ci	value &= ~((XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK <<
234162306a36Sopenharmony_ci		    XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) |
234262306a36Sopenharmony_ci		   (XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK <<
234362306a36Sopenharmony_ci		    XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT));
234462306a36Sopenharmony_ci	value |= (hsic->rx_strobe_trim <<
234562306a36Sopenharmony_ci		  XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) |
234662306a36Sopenharmony_ci		 (hsic->rx_data_trim <<
234762306a36Sopenharmony_ci		  XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT);
234862306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL2(index));
234962306a36Sopenharmony_ci
235062306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(index));
235162306a36Sopenharmony_ci	value &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA0 |
235262306a36Sopenharmony_ci		   XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA1 |
235362306a36Sopenharmony_ci		   XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE |
235462306a36Sopenharmony_ci		   XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA0 |
235562306a36Sopenharmony_ci		   XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA1 |
235662306a36Sopenharmony_ci		   XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_STROBE |
235762306a36Sopenharmony_ci		   XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA0 |
235862306a36Sopenharmony_ci		   XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA1 |
235962306a36Sopenharmony_ci		   XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_STROBE |
236062306a36Sopenharmony_ci		   XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA0 |
236162306a36Sopenharmony_ci		   XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA1 |
236262306a36Sopenharmony_ci		   XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_STROBE);
236362306a36Sopenharmony_ci	value |= XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA0 |
236462306a36Sopenharmony_ci		 XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA1 |
236562306a36Sopenharmony_ci		 XUSB_PADCTL_HSIC_PAD_CTL0_RPD_STROBE;
236662306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL0(index));
236762306a36Sopenharmony_ci
236862306a36Sopenharmony_ci	err = clk_prepare_enable(pad->clk);
236962306a36Sopenharmony_ci	if (err)
237062306a36Sopenharmony_ci		goto disable;
237162306a36Sopenharmony_ci
237262306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PAD_TRK_CTL);
237362306a36Sopenharmony_ci	value &= ~((XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_MASK <<
237462306a36Sopenharmony_ci		    XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_SHIFT) |
237562306a36Sopenharmony_ci		   (XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_MASK <<
237662306a36Sopenharmony_ci		    XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_SHIFT));
237762306a36Sopenharmony_ci	value |= (XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_VAL <<
237862306a36Sopenharmony_ci		  XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_SHIFT) |
237962306a36Sopenharmony_ci		 (XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_VAL <<
238062306a36Sopenharmony_ci		  XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_SHIFT);
238162306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PAD_TRK_CTL);
238262306a36Sopenharmony_ci
238362306a36Sopenharmony_ci	udelay(1);
238462306a36Sopenharmony_ci
238562306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PAD_TRK_CTL);
238662306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_HSIC_PAD_TRK_CTL_PD_TRK;
238762306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PAD_TRK_CTL);
238862306a36Sopenharmony_ci
238962306a36Sopenharmony_ci	udelay(50);
239062306a36Sopenharmony_ci
239162306a36Sopenharmony_ci	clk_disable_unprepare(pad->clk);
239262306a36Sopenharmony_ci
239362306a36Sopenharmony_ci	return 0;
239462306a36Sopenharmony_ci
239562306a36Sopenharmony_cidisable:
239662306a36Sopenharmony_ci	regulator_disable(pad->supply);
239762306a36Sopenharmony_ci	return err;
239862306a36Sopenharmony_ci}
239962306a36Sopenharmony_ci
240062306a36Sopenharmony_cistatic int tegra210_hsic_phy_power_off(struct phy *phy)
240162306a36Sopenharmony_ci{
240262306a36Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
240362306a36Sopenharmony_ci	struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad);
240462306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
240562306a36Sopenharmony_ci	unsigned int index = lane->index;
240662306a36Sopenharmony_ci	u32 value;
240762306a36Sopenharmony_ci
240862306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(index));
240962306a36Sopenharmony_ci	value |= XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA0 |
241062306a36Sopenharmony_ci		 XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA1 |
241162306a36Sopenharmony_ci		 XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_STROBE |
241262306a36Sopenharmony_ci		 XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA0 |
241362306a36Sopenharmony_ci		 XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA1 |
241462306a36Sopenharmony_ci		 XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_STROBE |
241562306a36Sopenharmony_ci		 XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA0 |
241662306a36Sopenharmony_ci		 XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA1 |
241762306a36Sopenharmony_ci		 XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_STROBE;
241862306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index));
241962306a36Sopenharmony_ci
242062306a36Sopenharmony_ci	regulator_disable(pad->supply);
242162306a36Sopenharmony_ci
242262306a36Sopenharmony_ci	return 0;
242362306a36Sopenharmony_ci}
242462306a36Sopenharmony_ci
242562306a36Sopenharmony_cistatic const struct phy_ops tegra210_hsic_phy_ops = {
242662306a36Sopenharmony_ci	.init = tegra210_hsic_phy_init,
242762306a36Sopenharmony_ci	.exit = tegra210_hsic_phy_exit,
242862306a36Sopenharmony_ci	.power_on = tegra210_hsic_phy_power_on,
242962306a36Sopenharmony_ci	.power_off = tegra210_hsic_phy_power_off,
243062306a36Sopenharmony_ci	.owner = THIS_MODULE,
243162306a36Sopenharmony_ci};
243262306a36Sopenharmony_ci
243362306a36Sopenharmony_cistatic struct tegra_xusb_pad *
243462306a36Sopenharmony_citegra210_hsic_pad_probe(struct tegra_xusb_padctl *padctl,
243562306a36Sopenharmony_ci			const struct tegra_xusb_pad_soc *soc,
243662306a36Sopenharmony_ci			struct device_node *np)
243762306a36Sopenharmony_ci{
243862306a36Sopenharmony_ci	struct tegra_xusb_hsic_pad *hsic;
243962306a36Sopenharmony_ci	struct tegra_xusb_pad *pad;
244062306a36Sopenharmony_ci	int err;
244162306a36Sopenharmony_ci
244262306a36Sopenharmony_ci	hsic = kzalloc(sizeof(*hsic), GFP_KERNEL);
244362306a36Sopenharmony_ci	if (!hsic)
244462306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
244562306a36Sopenharmony_ci
244662306a36Sopenharmony_ci	pad = &hsic->base;
244762306a36Sopenharmony_ci	pad->ops = &tegra210_hsic_lane_ops;
244862306a36Sopenharmony_ci	pad->soc = soc;
244962306a36Sopenharmony_ci
245062306a36Sopenharmony_ci	err = tegra_xusb_pad_init(pad, padctl, np);
245162306a36Sopenharmony_ci	if (err < 0) {
245262306a36Sopenharmony_ci		kfree(hsic);
245362306a36Sopenharmony_ci		goto out;
245462306a36Sopenharmony_ci	}
245562306a36Sopenharmony_ci
245662306a36Sopenharmony_ci	hsic->clk = devm_clk_get(&pad->dev, "trk");
245762306a36Sopenharmony_ci	if (IS_ERR(hsic->clk)) {
245862306a36Sopenharmony_ci		err = PTR_ERR(hsic->clk);
245962306a36Sopenharmony_ci		dev_err(&pad->dev, "failed to get trk clock: %d\n", err);
246062306a36Sopenharmony_ci		goto unregister;
246162306a36Sopenharmony_ci	}
246262306a36Sopenharmony_ci
246362306a36Sopenharmony_ci	err = tegra_xusb_pad_register(pad, &tegra210_hsic_phy_ops);
246462306a36Sopenharmony_ci	if (err < 0)
246562306a36Sopenharmony_ci		goto unregister;
246662306a36Sopenharmony_ci
246762306a36Sopenharmony_ci	dev_set_drvdata(&pad->dev, pad);
246862306a36Sopenharmony_ci
246962306a36Sopenharmony_ci	return pad;
247062306a36Sopenharmony_ci
247162306a36Sopenharmony_ciunregister:
247262306a36Sopenharmony_ci	device_unregister(&pad->dev);
247362306a36Sopenharmony_ciout:
247462306a36Sopenharmony_ci	return ERR_PTR(err);
247562306a36Sopenharmony_ci}
247662306a36Sopenharmony_ci
247762306a36Sopenharmony_cistatic void tegra210_hsic_pad_remove(struct tegra_xusb_pad *pad)
247862306a36Sopenharmony_ci{
247962306a36Sopenharmony_ci	struct tegra_xusb_hsic_pad *hsic = to_hsic_pad(pad);
248062306a36Sopenharmony_ci
248162306a36Sopenharmony_ci	kfree(hsic);
248262306a36Sopenharmony_ci}
248362306a36Sopenharmony_ci
248462306a36Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra210_hsic_ops = {
248562306a36Sopenharmony_ci	.probe = tegra210_hsic_pad_probe,
248662306a36Sopenharmony_ci	.remove = tegra210_hsic_pad_remove,
248762306a36Sopenharmony_ci};
248862306a36Sopenharmony_ci
248962306a36Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra210_hsic_pad = {
249062306a36Sopenharmony_ci	.name = "hsic",
249162306a36Sopenharmony_ci	.num_lanes = ARRAY_SIZE(tegra210_hsic_lanes),
249262306a36Sopenharmony_ci	.lanes = tegra210_hsic_lanes,
249362306a36Sopenharmony_ci	.ops = &tegra210_hsic_ops,
249462306a36Sopenharmony_ci};
249562306a36Sopenharmony_ci
249662306a36Sopenharmony_cistatic void tegra210_uphy_lane_iddq_enable(struct tegra_xusb_lane *lane)
249762306a36Sopenharmony_ci{
249862306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
249962306a36Sopenharmony_ci	u32 value;
250062306a36Sopenharmony_ci
250162306a36Sopenharmony_ci	value = padctl_readl(padctl, lane->soc->regs.misc_ctl2);
250262306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ_OVRD;
250362306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ_OVRD;
250462306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_PWR_OVRD;
250562306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_PWR_OVRD;
250662306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ;
250762306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_MASK;
250862306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_VAL;
250962306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ;
251062306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_MASK;
251162306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_VAL;
251262306a36Sopenharmony_ci	padctl_writel(padctl, value, lane->soc->regs.misc_ctl2);
251362306a36Sopenharmony_ci}
251462306a36Sopenharmony_ci
251562306a36Sopenharmony_cistatic void tegra210_uphy_lane_iddq_disable(struct tegra_xusb_lane *lane)
251662306a36Sopenharmony_ci{
251762306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
251862306a36Sopenharmony_ci	u32 value;
251962306a36Sopenharmony_ci
252062306a36Sopenharmony_ci	value = padctl_readl(padctl, lane->soc->regs.misc_ctl2);
252162306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ_OVRD;
252262306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ_OVRD;
252362306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_PWR_OVRD;
252462306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_PWR_OVRD;
252562306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ;
252662306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_MASK;
252762306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_VAL;
252862306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ;
252962306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_MASK;
253062306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_VAL;
253162306a36Sopenharmony_ci	padctl_writel(padctl, value, lane->soc->regs.misc_ctl2);
253262306a36Sopenharmony_ci}
253362306a36Sopenharmony_ci
253462306a36Sopenharmony_ci#define TEGRA210_UPHY_LANE(_name, _offset, _shift, _mask, _type, _misc)	\
253562306a36Sopenharmony_ci	{								\
253662306a36Sopenharmony_ci		.name = _name,						\
253762306a36Sopenharmony_ci		.offset = _offset,					\
253862306a36Sopenharmony_ci		.shift = _shift,					\
253962306a36Sopenharmony_ci		.mask = _mask,						\
254062306a36Sopenharmony_ci		.num_funcs = ARRAY_SIZE(tegra210_##_type##_functions),	\
254162306a36Sopenharmony_ci		.funcs = tegra210_##_type##_functions,			\
254262306a36Sopenharmony_ci		.regs.misc_ctl2 = _misc,				\
254362306a36Sopenharmony_ci	}
254462306a36Sopenharmony_ci
254562306a36Sopenharmony_cistatic const char *tegra210_pcie_functions[] = {
254662306a36Sopenharmony_ci	"pcie-x1",
254762306a36Sopenharmony_ci	"usb3-ss",
254862306a36Sopenharmony_ci	"sata",
254962306a36Sopenharmony_ci	"pcie-x4",
255062306a36Sopenharmony_ci};
255162306a36Sopenharmony_ci
255262306a36Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra210_pcie_lanes[] = {
255362306a36Sopenharmony_ci	TEGRA210_UPHY_LANE("pcie-0", 0x028, 12, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(0)),
255462306a36Sopenharmony_ci	TEGRA210_UPHY_LANE("pcie-1", 0x028, 14, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(1)),
255562306a36Sopenharmony_ci	TEGRA210_UPHY_LANE("pcie-2", 0x028, 16, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(2)),
255662306a36Sopenharmony_ci	TEGRA210_UPHY_LANE("pcie-3", 0x028, 18, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(3)),
255762306a36Sopenharmony_ci	TEGRA210_UPHY_LANE("pcie-4", 0x028, 20, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(4)),
255862306a36Sopenharmony_ci	TEGRA210_UPHY_LANE("pcie-5", 0x028, 22, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(5)),
255962306a36Sopenharmony_ci	TEGRA210_UPHY_LANE("pcie-6", 0x028, 24, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(6)),
256062306a36Sopenharmony_ci};
256162306a36Sopenharmony_ci
256262306a36Sopenharmony_cistatic struct tegra_xusb_usb3_port *
256362306a36Sopenharmony_citegra210_lane_to_usb3_port(struct tegra_xusb_lane *lane)
256462306a36Sopenharmony_ci{
256562306a36Sopenharmony_ci	int port;
256662306a36Sopenharmony_ci
256762306a36Sopenharmony_ci	if (!lane || !lane->pad || !lane->pad->padctl)
256862306a36Sopenharmony_ci		return NULL;
256962306a36Sopenharmony_ci
257062306a36Sopenharmony_ci	port = tegra210_usb3_lane_map(lane);
257162306a36Sopenharmony_ci	if (port < 0)
257262306a36Sopenharmony_ci		return NULL;
257362306a36Sopenharmony_ci
257462306a36Sopenharmony_ci	return tegra_xusb_find_usb3_port(lane->pad->padctl, port);
257562306a36Sopenharmony_ci}
257662306a36Sopenharmony_ci
257762306a36Sopenharmony_cistatic int tegra210_usb3_phy_power_on(struct phy *phy)
257862306a36Sopenharmony_ci{
257962306a36Sopenharmony_ci	struct device *dev = &phy->dev;
258062306a36Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
258162306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
258262306a36Sopenharmony_ci	struct tegra_xusb_usb3_port *usb3 = tegra210_lane_to_usb3_port(lane);
258362306a36Sopenharmony_ci	unsigned int index;
258462306a36Sopenharmony_ci	u32 value;
258562306a36Sopenharmony_ci
258662306a36Sopenharmony_ci	if (!usb3) {
258762306a36Sopenharmony_ci		dev_err(dev, "no USB3 port found for lane %u\n", lane->index);
258862306a36Sopenharmony_ci		return -ENODEV;
258962306a36Sopenharmony_ci	}
259062306a36Sopenharmony_ci
259162306a36Sopenharmony_ci	index = usb3->base.index;
259262306a36Sopenharmony_ci
259362306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP);
259462306a36Sopenharmony_ci
259562306a36Sopenharmony_ci	if (!usb3->internal)
259662306a36Sopenharmony_ci		value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index);
259762306a36Sopenharmony_ci	else
259862306a36Sopenharmony_ci		value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index);
259962306a36Sopenharmony_ci
260062306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(index);
260162306a36Sopenharmony_ci	value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(index, usb3->port);
260262306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP);
260362306a36Sopenharmony_ci
260462306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(index));
260562306a36Sopenharmony_ci	value &= ~(XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_MASK <<
260662306a36Sopenharmony_ci		   XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT);
260762306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_VAL <<
260862306a36Sopenharmony_ci		 XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT;
260962306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(index));
261062306a36Sopenharmony_ci
261162306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_USB3_PADX_ECTL2(index));
261262306a36Sopenharmony_ci	value &= ~(XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_MASK <<
261362306a36Sopenharmony_ci		   XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_SHIFT);
261462306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_VAL <<
261562306a36Sopenharmony_ci		 XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_SHIFT;
261662306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_USB3_PADX_ECTL2(index));
261762306a36Sopenharmony_ci
261862306a36Sopenharmony_ci	padctl_writel(padctl, XUSB_PADCTL_UPHY_USB3_PAD_ECTL3_RX_DFE_VAL,
261962306a36Sopenharmony_ci		      XUSB_PADCTL_UPHY_USB3_PADX_ECTL3(index));
262062306a36Sopenharmony_ci
262162306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_UPHY_USB3_PADX_ECTL4(index));
262262306a36Sopenharmony_ci	value &= ~(XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_MASK <<
262362306a36Sopenharmony_ci		   XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_SHIFT);
262462306a36Sopenharmony_ci	value |= XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_VAL <<
262562306a36Sopenharmony_ci		 XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_SHIFT;
262662306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_UPHY_USB3_PADX_ECTL4(index));
262762306a36Sopenharmony_ci
262862306a36Sopenharmony_ci	padctl_writel(padctl, XUSB_PADCTL_UPHY_USB3_PAD_ECTL6_RX_EQ_CTRL_H_VAL,
262962306a36Sopenharmony_ci		      XUSB_PADCTL_UPHY_USB3_PADX_ECTL6(index));
263062306a36Sopenharmony_ci
263162306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
263262306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN(index);
263362306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
263462306a36Sopenharmony_ci
263562306a36Sopenharmony_ci	usleep_range(100, 200);
263662306a36Sopenharmony_ci
263762306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
263862306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(index);
263962306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
264062306a36Sopenharmony_ci
264162306a36Sopenharmony_ci	usleep_range(100, 200);
264262306a36Sopenharmony_ci
264362306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
264462306a36Sopenharmony_ci	value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(index);
264562306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
264662306a36Sopenharmony_ci
264762306a36Sopenharmony_ci	return 0;
264862306a36Sopenharmony_ci}
264962306a36Sopenharmony_ci
265062306a36Sopenharmony_cistatic int tegra210_usb3_phy_power_off(struct phy *phy)
265162306a36Sopenharmony_ci{
265262306a36Sopenharmony_ci	struct device *dev = &phy->dev;
265362306a36Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
265462306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
265562306a36Sopenharmony_ci	struct tegra_xusb_usb3_port *usb3 = tegra210_lane_to_usb3_port(lane);
265662306a36Sopenharmony_ci	unsigned int index;
265762306a36Sopenharmony_ci	u32 value;
265862306a36Sopenharmony_ci
265962306a36Sopenharmony_ci	if (!usb3) {
266062306a36Sopenharmony_ci		dev_err(dev, "no USB3 port found for lane %u\n", lane->index);
266162306a36Sopenharmony_ci		return -ENODEV;
266262306a36Sopenharmony_ci	}
266362306a36Sopenharmony_ci
266462306a36Sopenharmony_ci	index = usb3->base.index;
266562306a36Sopenharmony_ci
266662306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
266762306a36Sopenharmony_ci	value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(index);
266862306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
266962306a36Sopenharmony_ci
267062306a36Sopenharmony_ci	usleep_range(100, 200);
267162306a36Sopenharmony_ci
267262306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
267362306a36Sopenharmony_ci	value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(index);
267462306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
267562306a36Sopenharmony_ci
267662306a36Sopenharmony_ci	usleep_range(250, 350);
267762306a36Sopenharmony_ci
267862306a36Sopenharmony_ci	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
267962306a36Sopenharmony_ci	value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN(index);
268062306a36Sopenharmony_ci	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
268162306a36Sopenharmony_ci
268262306a36Sopenharmony_ci	return 0;
268362306a36Sopenharmony_ci}
268462306a36Sopenharmony_cistatic struct tegra_xusb_lane *
268562306a36Sopenharmony_citegra210_pcie_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np,
268662306a36Sopenharmony_ci			 unsigned int index)
268762306a36Sopenharmony_ci{
268862306a36Sopenharmony_ci	struct tegra_xusb_pcie_lane *pcie;
268962306a36Sopenharmony_ci	int err;
269062306a36Sopenharmony_ci
269162306a36Sopenharmony_ci	pcie = kzalloc(sizeof(*pcie), GFP_KERNEL);
269262306a36Sopenharmony_ci	if (!pcie)
269362306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
269462306a36Sopenharmony_ci
269562306a36Sopenharmony_ci	INIT_LIST_HEAD(&pcie->base.list);
269662306a36Sopenharmony_ci	pcie->base.soc = &pad->soc->lanes[index];
269762306a36Sopenharmony_ci	pcie->base.index = index;
269862306a36Sopenharmony_ci	pcie->base.pad = pad;
269962306a36Sopenharmony_ci	pcie->base.np = np;
270062306a36Sopenharmony_ci
270162306a36Sopenharmony_ci	err = tegra_xusb_lane_parse_dt(&pcie->base, np);
270262306a36Sopenharmony_ci	if (err < 0) {
270362306a36Sopenharmony_ci		kfree(pcie);
270462306a36Sopenharmony_ci		return ERR_PTR(err);
270562306a36Sopenharmony_ci	}
270662306a36Sopenharmony_ci
270762306a36Sopenharmony_ci	return &pcie->base;
270862306a36Sopenharmony_ci}
270962306a36Sopenharmony_ci
271062306a36Sopenharmony_cistatic void tegra210_pcie_lane_remove(struct tegra_xusb_lane *lane)
271162306a36Sopenharmony_ci{
271262306a36Sopenharmony_ci	struct tegra_xusb_pcie_lane *pcie = to_pcie_lane(lane);
271362306a36Sopenharmony_ci
271462306a36Sopenharmony_ci	kfree(pcie);
271562306a36Sopenharmony_ci}
271662306a36Sopenharmony_ci
271762306a36Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra210_pcie_lane_ops = {
271862306a36Sopenharmony_ci	.probe = tegra210_pcie_lane_probe,
271962306a36Sopenharmony_ci	.remove = tegra210_pcie_lane_remove,
272062306a36Sopenharmony_ci	.iddq_enable = tegra210_uphy_lane_iddq_enable,
272162306a36Sopenharmony_ci	.iddq_disable = tegra210_uphy_lane_iddq_disable,
272262306a36Sopenharmony_ci	.enable_phy_sleepwalk = tegra210_usb3_enable_phy_sleepwalk,
272362306a36Sopenharmony_ci	.disable_phy_sleepwalk = tegra210_usb3_disable_phy_sleepwalk,
272462306a36Sopenharmony_ci	.enable_phy_wake = tegra210_usb3_enable_phy_wake,
272562306a36Sopenharmony_ci	.disable_phy_wake = tegra210_usb3_disable_phy_wake,
272662306a36Sopenharmony_ci	.remote_wake_detected = tegra210_usb3_phy_remote_wake_detected,
272762306a36Sopenharmony_ci};
272862306a36Sopenharmony_ci
272962306a36Sopenharmony_cistatic int tegra210_pcie_phy_init(struct phy *phy)
273062306a36Sopenharmony_ci{
273162306a36Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
273262306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
273362306a36Sopenharmony_ci
273462306a36Sopenharmony_ci	mutex_lock(&padctl->lock);
273562306a36Sopenharmony_ci
273662306a36Sopenharmony_ci	tegra210_uphy_init(padctl);
273762306a36Sopenharmony_ci
273862306a36Sopenharmony_ci	mutex_unlock(&padctl->lock);
273962306a36Sopenharmony_ci
274062306a36Sopenharmony_ci	return 0;
274162306a36Sopenharmony_ci}
274262306a36Sopenharmony_ci
274362306a36Sopenharmony_cistatic int tegra210_pcie_phy_power_on(struct phy *phy)
274462306a36Sopenharmony_ci{
274562306a36Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
274662306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
274762306a36Sopenharmony_ci	int err = 0;
274862306a36Sopenharmony_ci
274962306a36Sopenharmony_ci	mutex_lock(&padctl->lock);
275062306a36Sopenharmony_ci
275162306a36Sopenharmony_ci	if (tegra_xusb_lane_check(lane, "usb3-ss"))
275262306a36Sopenharmony_ci		err = tegra210_usb3_phy_power_on(phy);
275362306a36Sopenharmony_ci
275462306a36Sopenharmony_ci	mutex_unlock(&padctl->lock);
275562306a36Sopenharmony_ci	return err;
275662306a36Sopenharmony_ci}
275762306a36Sopenharmony_ci
275862306a36Sopenharmony_cistatic int tegra210_pcie_phy_power_off(struct phy *phy)
275962306a36Sopenharmony_ci{
276062306a36Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
276162306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
276262306a36Sopenharmony_ci	int err = 0;
276362306a36Sopenharmony_ci
276462306a36Sopenharmony_ci	mutex_lock(&padctl->lock);
276562306a36Sopenharmony_ci
276662306a36Sopenharmony_ci	if (tegra_xusb_lane_check(lane, "usb3-ss"))
276762306a36Sopenharmony_ci		err = tegra210_usb3_phy_power_off(phy);
276862306a36Sopenharmony_ci
276962306a36Sopenharmony_ci	mutex_unlock(&padctl->lock);
277062306a36Sopenharmony_ci	return err;
277162306a36Sopenharmony_ci}
277262306a36Sopenharmony_ci
277362306a36Sopenharmony_cistatic const struct phy_ops tegra210_pcie_phy_ops = {
277462306a36Sopenharmony_ci	.init = tegra210_pcie_phy_init,
277562306a36Sopenharmony_ci	.power_on = tegra210_pcie_phy_power_on,
277662306a36Sopenharmony_ci	.power_off = tegra210_pcie_phy_power_off,
277762306a36Sopenharmony_ci	.owner = THIS_MODULE,
277862306a36Sopenharmony_ci};
277962306a36Sopenharmony_ci
278062306a36Sopenharmony_cistatic struct tegra_xusb_pad *
278162306a36Sopenharmony_citegra210_pcie_pad_probe(struct tegra_xusb_padctl *padctl,
278262306a36Sopenharmony_ci			const struct tegra_xusb_pad_soc *soc,
278362306a36Sopenharmony_ci			struct device_node *np)
278462306a36Sopenharmony_ci{
278562306a36Sopenharmony_ci	struct tegra_xusb_pcie_pad *pcie;
278662306a36Sopenharmony_ci	struct tegra_xusb_pad *pad;
278762306a36Sopenharmony_ci	int err;
278862306a36Sopenharmony_ci
278962306a36Sopenharmony_ci	pcie = kzalloc(sizeof(*pcie), GFP_KERNEL);
279062306a36Sopenharmony_ci	if (!pcie)
279162306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
279262306a36Sopenharmony_ci
279362306a36Sopenharmony_ci	pad = &pcie->base;
279462306a36Sopenharmony_ci	pad->ops = &tegra210_pcie_lane_ops;
279562306a36Sopenharmony_ci	pad->soc = soc;
279662306a36Sopenharmony_ci
279762306a36Sopenharmony_ci	err = tegra_xusb_pad_init(pad, padctl, np);
279862306a36Sopenharmony_ci	if (err < 0) {
279962306a36Sopenharmony_ci		kfree(pcie);
280062306a36Sopenharmony_ci		goto out;
280162306a36Sopenharmony_ci	}
280262306a36Sopenharmony_ci
280362306a36Sopenharmony_ci	pcie->pll = devm_clk_get(&pad->dev, "pll");
280462306a36Sopenharmony_ci	if (IS_ERR(pcie->pll)) {
280562306a36Sopenharmony_ci		err = PTR_ERR(pcie->pll);
280662306a36Sopenharmony_ci		dev_err(&pad->dev, "failed to get PLL: %d\n", err);
280762306a36Sopenharmony_ci		goto unregister;
280862306a36Sopenharmony_ci	}
280962306a36Sopenharmony_ci
281062306a36Sopenharmony_ci	pcie->rst = devm_reset_control_get(&pad->dev, "phy");
281162306a36Sopenharmony_ci	if (IS_ERR(pcie->rst)) {
281262306a36Sopenharmony_ci		err = PTR_ERR(pcie->rst);
281362306a36Sopenharmony_ci		dev_err(&pad->dev, "failed to get PCIe pad reset: %d\n", err);
281462306a36Sopenharmony_ci		goto unregister;
281562306a36Sopenharmony_ci	}
281662306a36Sopenharmony_ci
281762306a36Sopenharmony_ci	err = tegra_xusb_pad_register(pad, &tegra210_pcie_phy_ops);
281862306a36Sopenharmony_ci	if (err < 0)
281962306a36Sopenharmony_ci		goto unregister;
282062306a36Sopenharmony_ci
282162306a36Sopenharmony_ci	dev_set_drvdata(&pad->dev, pad);
282262306a36Sopenharmony_ci
282362306a36Sopenharmony_ci	return pad;
282462306a36Sopenharmony_ci
282562306a36Sopenharmony_ciunregister:
282662306a36Sopenharmony_ci	device_unregister(&pad->dev);
282762306a36Sopenharmony_ciout:
282862306a36Sopenharmony_ci	return ERR_PTR(err);
282962306a36Sopenharmony_ci}
283062306a36Sopenharmony_ci
283162306a36Sopenharmony_cistatic void tegra210_pcie_pad_remove(struct tegra_xusb_pad *pad)
283262306a36Sopenharmony_ci{
283362306a36Sopenharmony_ci	struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(pad);
283462306a36Sopenharmony_ci
283562306a36Sopenharmony_ci	kfree(pcie);
283662306a36Sopenharmony_ci}
283762306a36Sopenharmony_ci
283862306a36Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra210_pcie_ops = {
283962306a36Sopenharmony_ci	.probe = tegra210_pcie_pad_probe,
284062306a36Sopenharmony_ci	.remove = tegra210_pcie_pad_remove,
284162306a36Sopenharmony_ci};
284262306a36Sopenharmony_ci
284362306a36Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra210_pcie_pad = {
284462306a36Sopenharmony_ci	.name = "pcie",
284562306a36Sopenharmony_ci	.num_lanes = ARRAY_SIZE(tegra210_pcie_lanes),
284662306a36Sopenharmony_ci	.lanes = tegra210_pcie_lanes,
284762306a36Sopenharmony_ci	.ops = &tegra210_pcie_ops,
284862306a36Sopenharmony_ci};
284962306a36Sopenharmony_ci
285062306a36Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra210_sata_lanes[] = {
285162306a36Sopenharmony_ci	TEGRA210_UPHY_LANE("sata-0", 0x028, 30, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL2),
285262306a36Sopenharmony_ci};
285362306a36Sopenharmony_ci
285462306a36Sopenharmony_cistatic struct tegra_xusb_lane *
285562306a36Sopenharmony_citegra210_sata_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np,
285662306a36Sopenharmony_ci			 unsigned int index)
285762306a36Sopenharmony_ci{
285862306a36Sopenharmony_ci	struct tegra_xusb_sata_lane *sata;
285962306a36Sopenharmony_ci	int err;
286062306a36Sopenharmony_ci
286162306a36Sopenharmony_ci	sata = kzalloc(sizeof(*sata), GFP_KERNEL);
286262306a36Sopenharmony_ci	if (!sata)
286362306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
286462306a36Sopenharmony_ci
286562306a36Sopenharmony_ci	INIT_LIST_HEAD(&sata->base.list);
286662306a36Sopenharmony_ci	sata->base.soc = &pad->soc->lanes[index];
286762306a36Sopenharmony_ci	sata->base.index = index;
286862306a36Sopenharmony_ci	sata->base.pad = pad;
286962306a36Sopenharmony_ci	sata->base.np = np;
287062306a36Sopenharmony_ci
287162306a36Sopenharmony_ci	err = tegra_xusb_lane_parse_dt(&sata->base, np);
287262306a36Sopenharmony_ci	if (err < 0) {
287362306a36Sopenharmony_ci		kfree(sata);
287462306a36Sopenharmony_ci		return ERR_PTR(err);
287562306a36Sopenharmony_ci	}
287662306a36Sopenharmony_ci
287762306a36Sopenharmony_ci	return &sata->base;
287862306a36Sopenharmony_ci}
287962306a36Sopenharmony_ci
288062306a36Sopenharmony_cistatic void tegra210_sata_lane_remove(struct tegra_xusb_lane *lane)
288162306a36Sopenharmony_ci{
288262306a36Sopenharmony_ci	struct tegra_xusb_sata_lane *sata = to_sata_lane(lane);
288362306a36Sopenharmony_ci
288462306a36Sopenharmony_ci	kfree(sata);
288562306a36Sopenharmony_ci}
288662306a36Sopenharmony_ci
288762306a36Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra210_sata_lane_ops = {
288862306a36Sopenharmony_ci	.probe = tegra210_sata_lane_probe,
288962306a36Sopenharmony_ci	.remove = tegra210_sata_lane_remove,
289062306a36Sopenharmony_ci	.iddq_enable = tegra210_uphy_lane_iddq_enable,
289162306a36Sopenharmony_ci	.iddq_disable = tegra210_uphy_lane_iddq_disable,
289262306a36Sopenharmony_ci	.enable_phy_sleepwalk = tegra210_usb3_enable_phy_sleepwalk,
289362306a36Sopenharmony_ci	.disable_phy_sleepwalk = tegra210_usb3_disable_phy_sleepwalk,
289462306a36Sopenharmony_ci	.enable_phy_wake = tegra210_usb3_enable_phy_wake,
289562306a36Sopenharmony_ci	.disable_phy_wake = tegra210_usb3_disable_phy_wake,
289662306a36Sopenharmony_ci	.remote_wake_detected = tegra210_usb3_phy_remote_wake_detected,
289762306a36Sopenharmony_ci};
289862306a36Sopenharmony_ci
289962306a36Sopenharmony_cistatic int tegra210_sata_phy_init(struct phy *phy)
290062306a36Sopenharmony_ci{
290162306a36Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
290262306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
290362306a36Sopenharmony_ci
290462306a36Sopenharmony_ci	mutex_lock(&padctl->lock);
290562306a36Sopenharmony_ci
290662306a36Sopenharmony_ci	tegra210_uphy_init(padctl);
290762306a36Sopenharmony_ci
290862306a36Sopenharmony_ci	mutex_unlock(&padctl->lock);
290962306a36Sopenharmony_ci	return 0;
291062306a36Sopenharmony_ci}
291162306a36Sopenharmony_ci
291262306a36Sopenharmony_cistatic int tegra210_sata_phy_power_on(struct phy *phy)
291362306a36Sopenharmony_ci{
291462306a36Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
291562306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
291662306a36Sopenharmony_ci	int err = 0;
291762306a36Sopenharmony_ci
291862306a36Sopenharmony_ci	mutex_lock(&padctl->lock);
291962306a36Sopenharmony_ci
292062306a36Sopenharmony_ci	if (tegra_xusb_lane_check(lane, "usb3-ss"))
292162306a36Sopenharmony_ci		err = tegra210_usb3_phy_power_on(phy);
292262306a36Sopenharmony_ci
292362306a36Sopenharmony_ci	mutex_unlock(&padctl->lock);
292462306a36Sopenharmony_ci	return err;
292562306a36Sopenharmony_ci}
292662306a36Sopenharmony_ci
292762306a36Sopenharmony_cistatic int tegra210_sata_phy_power_off(struct phy *phy)
292862306a36Sopenharmony_ci{
292962306a36Sopenharmony_ci	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
293062306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl = lane->pad->padctl;
293162306a36Sopenharmony_ci	int err = 0;
293262306a36Sopenharmony_ci
293362306a36Sopenharmony_ci	mutex_lock(&padctl->lock);
293462306a36Sopenharmony_ci
293562306a36Sopenharmony_ci	if (tegra_xusb_lane_check(lane, "usb3-ss"))
293662306a36Sopenharmony_ci		err = tegra210_usb3_phy_power_off(phy);
293762306a36Sopenharmony_ci
293862306a36Sopenharmony_ci	mutex_unlock(&padctl->lock);
293962306a36Sopenharmony_ci	return err;
294062306a36Sopenharmony_ci}
294162306a36Sopenharmony_ci
294262306a36Sopenharmony_cistatic const struct phy_ops tegra210_sata_phy_ops = {
294362306a36Sopenharmony_ci	.init = tegra210_sata_phy_init,
294462306a36Sopenharmony_ci	.power_on = tegra210_sata_phy_power_on,
294562306a36Sopenharmony_ci	.power_off = tegra210_sata_phy_power_off,
294662306a36Sopenharmony_ci	.owner = THIS_MODULE,
294762306a36Sopenharmony_ci};
294862306a36Sopenharmony_ci
294962306a36Sopenharmony_cistatic struct tegra_xusb_pad *
295062306a36Sopenharmony_citegra210_sata_pad_probe(struct tegra_xusb_padctl *padctl,
295162306a36Sopenharmony_ci			const struct tegra_xusb_pad_soc *soc,
295262306a36Sopenharmony_ci			struct device_node *np)
295362306a36Sopenharmony_ci{
295462306a36Sopenharmony_ci	struct tegra_xusb_sata_pad *sata;
295562306a36Sopenharmony_ci	struct tegra_xusb_pad *pad;
295662306a36Sopenharmony_ci	int err;
295762306a36Sopenharmony_ci
295862306a36Sopenharmony_ci	sata = kzalloc(sizeof(*sata), GFP_KERNEL);
295962306a36Sopenharmony_ci	if (!sata)
296062306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
296162306a36Sopenharmony_ci
296262306a36Sopenharmony_ci	pad = &sata->base;
296362306a36Sopenharmony_ci	pad->ops = &tegra210_sata_lane_ops;
296462306a36Sopenharmony_ci	pad->soc = soc;
296562306a36Sopenharmony_ci
296662306a36Sopenharmony_ci	err = tegra_xusb_pad_init(pad, padctl, np);
296762306a36Sopenharmony_ci	if (err < 0) {
296862306a36Sopenharmony_ci		kfree(sata);
296962306a36Sopenharmony_ci		goto out;
297062306a36Sopenharmony_ci	}
297162306a36Sopenharmony_ci
297262306a36Sopenharmony_ci	sata->rst = devm_reset_control_get(&pad->dev, "phy");
297362306a36Sopenharmony_ci	if (IS_ERR(sata->rst)) {
297462306a36Sopenharmony_ci		err = PTR_ERR(sata->rst);
297562306a36Sopenharmony_ci		dev_err(&pad->dev, "failed to get SATA pad reset: %d\n", err);
297662306a36Sopenharmony_ci		goto unregister;
297762306a36Sopenharmony_ci	}
297862306a36Sopenharmony_ci
297962306a36Sopenharmony_ci	err = tegra_xusb_pad_register(pad, &tegra210_sata_phy_ops);
298062306a36Sopenharmony_ci	if (err < 0)
298162306a36Sopenharmony_ci		goto unregister;
298262306a36Sopenharmony_ci
298362306a36Sopenharmony_ci	dev_set_drvdata(&pad->dev, pad);
298462306a36Sopenharmony_ci
298562306a36Sopenharmony_ci	return pad;
298662306a36Sopenharmony_ci
298762306a36Sopenharmony_ciunregister:
298862306a36Sopenharmony_ci	device_unregister(&pad->dev);
298962306a36Sopenharmony_ciout:
299062306a36Sopenharmony_ci	return ERR_PTR(err);
299162306a36Sopenharmony_ci}
299262306a36Sopenharmony_ci
299362306a36Sopenharmony_cistatic void tegra210_sata_pad_remove(struct tegra_xusb_pad *pad)
299462306a36Sopenharmony_ci{
299562306a36Sopenharmony_ci	struct tegra_xusb_sata_pad *sata = to_sata_pad(pad);
299662306a36Sopenharmony_ci
299762306a36Sopenharmony_ci	kfree(sata);
299862306a36Sopenharmony_ci}
299962306a36Sopenharmony_ci
300062306a36Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra210_sata_ops = {
300162306a36Sopenharmony_ci	.probe = tegra210_sata_pad_probe,
300262306a36Sopenharmony_ci	.remove = tegra210_sata_pad_remove,
300362306a36Sopenharmony_ci};
300462306a36Sopenharmony_ci
300562306a36Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra210_sata_pad = {
300662306a36Sopenharmony_ci	.name = "sata",
300762306a36Sopenharmony_ci	.num_lanes = ARRAY_SIZE(tegra210_sata_lanes),
300862306a36Sopenharmony_ci	.lanes = tegra210_sata_lanes,
300962306a36Sopenharmony_ci	.ops = &tegra210_sata_ops,
301062306a36Sopenharmony_ci};
301162306a36Sopenharmony_ci
301262306a36Sopenharmony_cistatic const struct tegra_xusb_pad_soc * const tegra210_pads[] = {
301362306a36Sopenharmony_ci	&tegra210_usb2_pad,
301462306a36Sopenharmony_ci	&tegra210_hsic_pad,
301562306a36Sopenharmony_ci	&tegra210_pcie_pad,
301662306a36Sopenharmony_ci	&tegra210_sata_pad,
301762306a36Sopenharmony_ci};
301862306a36Sopenharmony_ci
301962306a36Sopenharmony_cistatic int tegra210_usb2_port_enable(struct tegra_xusb_port *port)
302062306a36Sopenharmony_ci{
302162306a36Sopenharmony_ci	return 0;
302262306a36Sopenharmony_ci}
302362306a36Sopenharmony_ci
302462306a36Sopenharmony_cistatic void tegra210_usb2_port_disable(struct tegra_xusb_port *port)
302562306a36Sopenharmony_ci{
302662306a36Sopenharmony_ci}
302762306a36Sopenharmony_ci
302862306a36Sopenharmony_cistatic struct tegra_xusb_lane *
302962306a36Sopenharmony_citegra210_usb2_port_map(struct tegra_xusb_port *port)
303062306a36Sopenharmony_ci{
303162306a36Sopenharmony_ci	return tegra_xusb_find_lane(port->padctl, "usb2", port->index);
303262306a36Sopenharmony_ci}
303362306a36Sopenharmony_ci
303462306a36Sopenharmony_cistatic const struct tegra_xusb_port_ops tegra210_usb2_port_ops = {
303562306a36Sopenharmony_ci	.release = tegra_xusb_usb2_port_release,
303662306a36Sopenharmony_ci	.remove = tegra_xusb_usb2_port_remove,
303762306a36Sopenharmony_ci	.enable = tegra210_usb2_port_enable,
303862306a36Sopenharmony_ci	.disable = tegra210_usb2_port_disable,
303962306a36Sopenharmony_ci	.map = tegra210_usb2_port_map,
304062306a36Sopenharmony_ci};
304162306a36Sopenharmony_ci
304262306a36Sopenharmony_cistatic int tegra210_hsic_port_enable(struct tegra_xusb_port *port)
304362306a36Sopenharmony_ci{
304462306a36Sopenharmony_ci	return 0;
304562306a36Sopenharmony_ci}
304662306a36Sopenharmony_ci
304762306a36Sopenharmony_cistatic void tegra210_hsic_port_disable(struct tegra_xusb_port *port)
304862306a36Sopenharmony_ci{
304962306a36Sopenharmony_ci}
305062306a36Sopenharmony_ci
305162306a36Sopenharmony_cistatic struct tegra_xusb_lane *
305262306a36Sopenharmony_citegra210_hsic_port_map(struct tegra_xusb_port *port)
305362306a36Sopenharmony_ci{
305462306a36Sopenharmony_ci	return tegra_xusb_find_lane(port->padctl, "hsic", port->index);
305562306a36Sopenharmony_ci}
305662306a36Sopenharmony_ci
305762306a36Sopenharmony_cistatic const struct tegra_xusb_port_ops tegra210_hsic_port_ops = {
305862306a36Sopenharmony_ci	.release = tegra_xusb_hsic_port_release,
305962306a36Sopenharmony_ci	.enable = tegra210_hsic_port_enable,
306062306a36Sopenharmony_ci	.disable = tegra210_hsic_port_disable,
306162306a36Sopenharmony_ci	.map = tegra210_hsic_port_map,
306262306a36Sopenharmony_ci};
306362306a36Sopenharmony_ci
306462306a36Sopenharmony_cistatic int tegra210_usb3_port_enable(struct tegra_xusb_port *port)
306562306a36Sopenharmony_ci{
306662306a36Sopenharmony_ci	return 0;
306762306a36Sopenharmony_ci}
306862306a36Sopenharmony_ci
306962306a36Sopenharmony_cistatic void tegra210_usb3_port_disable(struct tegra_xusb_port *port)
307062306a36Sopenharmony_ci{
307162306a36Sopenharmony_ci}
307262306a36Sopenharmony_ci
307362306a36Sopenharmony_cistatic struct tegra_xusb_lane *
307462306a36Sopenharmony_citegra210_usb3_port_map(struct tegra_xusb_port *port)
307562306a36Sopenharmony_ci{
307662306a36Sopenharmony_ci	return tegra_xusb_port_find_lane(port, tegra210_usb3_map, "usb3-ss");
307762306a36Sopenharmony_ci}
307862306a36Sopenharmony_ci
307962306a36Sopenharmony_cistatic const struct tegra_xusb_port_ops tegra210_usb3_port_ops = {
308062306a36Sopenharmony_ci	.release = tegra_xusb_usb3_port_release,
308162306a36Sopenharmony_ci	.enable = tegra210_usb3_port_enable,
308262306a36Sopenharmony_ci	.disable = tegra210_usb3_port_disable,
308362306a36Sopenharmony_ci	.map = tegra210_usb3_port_map,
308462306a36Sopenharmony_ci};
308562306a36Sopenharmony_ci
308662306a36Sopenharmony_cistatic int tegra210_utmi_port_reset(struct phy *phy)
308762306a36Sopenharmony_ci{
308862306a36Sopenharmony_ci	struct tegra_xusb_padctl *padctl;
308962306a36Sopenharmony_ci	struct tegra_xusb_lane *lane;
309062306a36Sopenharmony_ci	u32 value;
309162306a36Sopenharmony_ci
309262306a36Sopenharmony_ci	lane = phy_get_drvdata(phy);
309362306a36Sopenharmony_ci	padctl = lane->pad->padctl;
309462306a36Sopenharmony_ci
309562306a36Sopenharmony_ci	value = padctl_readl(padctl,
309662306a36Sopenharmony_ci		     XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL0(lane->index));
309762306a36Sopenharmony_ci
309862306a36Sopenharmony_ci	if ((value & XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL0_ZIP) ||
309962306a36Sopenharmony_ci	    (value & XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL0_ZIN)) {
310062306a36Sopenharmony_ci		tegra210_xusb_padctl_vbus_override(padctl, false);
310162306a36Sopenharmony_ci		tegra210_xusb_padctl_vbus_override(padctl, true);
310262306a36Sopenharmony_ci		return 1;
310362306a36Sopenharmony_ci	}
310462306a36Sopenharmony_ci
310562306a36Sopenharmony_ci	return 0;
310662306a36Sopenharmony_ci}
310762306a36Sopenharmony_ci
310862306a36Sopenharmony_cistatic int
310962306a36Sopenharmony_citegra210_xusb_read_fuse_calibration(struct tegra210_xusb_fuse_calibration *fuse)
311062306a36Sopenharmony_ci{
311162306a36Sopenharmony_ci	unsigned int i;
311262306a36Sopenharmony_ci	u32 value;
311362306a36Sopenharmony_ci	int err;
311462306a36Sopenharmony_ci
311562306a36Sopenharmony_ci	err = tegra_fuse_readl(TEGRA_FUSE_SKU_CALIB_0, &value);
311662306a36Sopenharmony_ci	if (err < 0)
311762306a36Sopenharmony_ci		return err;
311862306a36Sopenharmony_ci
311962306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(fuse->hs_curr_level); i++) {
312062306a36Sopenharmony_ci		fuse->hs_curr_level[i] =
312162306a36Sopenharmony_ci			(value >> FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(i)) &
312262306a36Sopenharmony_ci			FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK;
312362306a36Sopenharmony_ci	}
312462306a36Sopenharmony_ci
312562306a36Sopenharmony_ci	fuse->hs_term_range_adj =
312662306a36Sopenharmony_ci		(value >> FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT) &
312762306a36Sopenharmony_ci		FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK;
312862306a36Sopenharmony_ci
312962306a36Sopenharmony_ci	err = tegra_fuse_readl(TEGRA_FUSE_USB_CALIB_EXT_0, &value);
313062306a36Sopenharmony_ci	if (err < 0)
313162306a36Sopenharmony_ci		return err;
313262306a36Sopenharmony_ci
313362306a36Sopenharmony_ci	fuse->rpd_ctrl =
313462306a36Sopenharmony_ci		(value >> FUSE_USB_CALIB_EXT_RPD_CTRL_SHIFT) &
313562306a36Sopenharmony_ci		FUSE_USB_CALIB_EXT_RPD_CTRL_MASK;
313662306a36Sopenharmony_ci
313762306a36Sopenharmony_ci	return 0;
313862306a36Sopenharmony_ci}
313962306a36Sopenharmony_ci
314062306a36Sopenharmony_cistatic struct tegra_xusb_padctl *
314162306a36Sopenharmony_citegra210_xusb_padctl_probe(struct device *dev,
314262306a36Sopenharmony_ci			   const struct tegra_xusb_padctl_soc *soc)
314362306a36Sopenharmony_ci{
314462306a36Sopenharmony_ci	struct tegra210_xusb_padctl *padctl;
314562306a36Sopenharmony_ci	struct platform_device *pdev;
314662306a36Sopenharmony_ci	struct device_node *np;
314762306a36Sopenharmony_ci	int err;
314862306a36Sopenharmony_ci
314962306a36Sopenharmony_ci	padctl = devm_kzalloc(dev, sizeof(*padctl), GFP_KERNEL);
315062306a36Sopenharmony_ci	if (!padctl)
315162306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
315262306a36Sopenharmony_ci
315362306a36Sopenharmony_ci	padctl->base.dev = dev;
315462306a36Sopenharmony_ci	padctl->base.soc = soc;
315562306a36Sopenharmony_ci
315662306a36Sopenharmony_ci	err = tegra210_xusb_read_fuse_calibration(&padctl->fuse);
315762306a36Sopenharmony_ci	if (err < 0)
315862306a36Sopenharmony_ci		return ERR_PTR(err);
315962306a36Sopenharmony_ci
316062306a36Sopenharmony_ci	np = of_parse_phandle(dev->of_node, "nvidia,pmc", 0);
316162306a36Sopenharmony_ci	if (!np) {
316262306a36Sopenharmony_ci		dev_warn(dev, "nvidia,pmc property is missing\n");
316362306a36Sopenharmony_ci		goto out;
316462306a36Sopenharmony_ci	}
316562306a36Sopenharmony_ci
316662306a36Sopenharmony_ci	pdev = of_find_device_by_node(np);
316762306a36Sopenharmony_ci	if (!pdev) {
316862306a36Sopenharmony_ci		dev_warn(dev, "PMC device is not available\n");
316962306a36Sopenharmony_ci		goto out;
317062306a36Sopenharmony_ci	}
317162306a36Sopenharmony_ci
317262306a36Sopenharmony_ci	if (!platform_get_drvdata(pdev))
317362306a36Sopenharmony_ci		return ERR_PTR(-EPROBE_DEFER);
317462306a36Sopenharmony_ci
317562306a36Sopenharmony_ci	padctl->regmap = dev_get_regmap(&pdev->dev, "usb_sleepwalk");
317662306a36Sopenharmony_ci	if (!padctl->regmap)
317762306a36Sopenharmony_ci		dev_info(dev, "failed to find PMC regmap\n");
317862306a36Sopenharmony_ci
317962306a36Sopenharmony_ciout:
318062306a36Sopenharmony_ci	return &padctl->base;
318162306a36Sopenharmony_ci}
318262306a36Sopenharmony_ci
318362306a36Sopenharmony_cistatic void tegra210_xusb_padctl_remove(struct tegra_xusb_padctl *padctl)
318462306a36Sopenharmony_ci{
318562306a36Sopenharmony_ci}
318662306a36Sopenharmony_ci
318762306a36Sopenharmony_cistatic void tegra210_xusb_padctl_save(struct tegra_xusb_padctl *padctl)
318862306a36Sopenharmony_ci{
318962306a36Sopenharmony_ci	struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl);
319062306a36Sopenharmony_ci
319162306a36Sopenharmony_ci	priv->context.usb2_pad_mux =
319262306a36Sopenharmony_ci		padctl_readl(padctl, XUSB_PADCTL_USB2_PAD_MUX);
319362306a36Sopenharmony_ci	priv->context.usb2_port_cap =
319462306a36Sopenharmony_ci		padctl_readl(padctl, XUSB_PADCTL_USB2_PORT_CAP);
319562306a36Sopenharmony_ci	priv->context.ss_port_map =
319662306a36Sopenharmony_ci		padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP);
319762306a36Sopenharmony_ci	priv->context.usb3_pad_mux =
319862306a36Sopenharmony_ci		padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
319962306a36Sopenharmony_ci}
320062306a36Sopenharmony_ci
320162306a36Sopenharmony_cistatic void tegra210_xusb_padctl_restore(struct tegra_xusb_padctl *padctl)
320262306a36Sopenharmony_ci{
320362306a36Sopenharmony_ci	struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl);
320462306a36Sopenharmony_ci	struct tegra_xusb_lane *lane;
320562306a36Sopenharmony_ci
320662306a36Sopenharmony_ci	padctl_writel(padctl, priv->context.usb2_pad_mux,
320762306a36Sopenharmony_ci		XUSB_PADCTL_USB2_PAD_MUX);
320862306a36Sopenharmony_ci	padctl_writel(padctl, priv->context.usb2_port_cap,
320962306a36Sopenharmony_ci		XUSB_PADCTL_USB2_PORT_CAP);
321062306a36Sopenharmony_ci	padctl_writel(padctl, priv->context.ss_port_map,
321162306a36Sopenharmony_ci		XUSB_PADCTL_SS_PORT_MAP);
321262306a36Sopenharmony_ci
321362306a36Sopenharmony_ci	list_for_each_entry(lane, &padctl->lanes, list) {
321462306a36Sopenharmony_ci		if (lane->pad->ops->iddq_enable)
321562306a36Sopenharmony_ci			tegra210_uphy_lane_iddq_enable(lane);
321662306a36Sopenharmony_ci	}
321762306a36Sopenharmony_ci
321862306a36Sopenharmony_ci	padctl_writel(padctl, priv->context.usb3_pad_mux,
321962306a36Sopenharmony_ci		XUSB_PADCTL_USB3_PAD_MUX);
322062306a36Sopenharmony_ci
322162306a36Sopenharmony_ci	list_for_each_entry(lane, &padctl->lanes, list) {
322262306a36Sopenharmony_ci		if (lane->pad->ops->iddq_disable)
322362306a36Sopenharmony_ci			tegra210_uphy_lane_iddq_disable(lane);
322462306a36Sopenharmony_ci	}
322562306a36Sopenharmony_ci}
322662306a36Sopenharmony_ci
322762306a36Sopenharmony_cistatic int tegra210_xusb_padctl_suspend_noirq(struct tegra_xusb_padctl *padctl)
322862306a36Sopenharmony_ci{
322962306a36Sopenharmony_ci	mutex_lock(&padctl->lock);
323062306a36Sopenharmony_ci
323162306a36Sopenharmony_ci	tegra210_uphy_deinit(padctl);
323262306a36Sopenharmony_ci
323362306a36Sopenharmony_ci	tegra210_xusb_padctl_save(padctl);
323462306a36Sopenharmony_ci
323562306a36Sopenharmony_ci	mutex_unlock(&padctl->lock);
323662306a36Sopenharmony_ci	return 0;
323762306a36Sopenharmony_ci}
323862306a36Sopenharmony_ci
323962306a36Sopenharmony_cistatic int tegra210_xusb_padctl_resume_noirq(struct tegra_xusb_padctl *padctl)
324062306a36Sopenharmony_ci{
324162306a36Sopenharmony_ci	mutex_lock(&padctl->lock);
324262306a36Sopenharmony_ci
324362306a36Sopenharmony_ci	tegra210_xusb_padctl_restore(padctl);
324462306a36Sopenharmony_ci
324562306a36Sopenharmony_ci	tegra210_uphy_init(padctl);
324662306a36Sopenharmony_ci
324762306a36Sopenharmony_ci	mutex_unlock(&padctl->lock);
324862306a36Sopenharmony_ci	return 0;
324962306a36Sopenharmony_ci}
325062306a36Sopenharmony_ci
325162306a36Sopenharmony_cistatic const struct tegra_xusb_padctl_ops tegra210_xusb_padctl_ops = {
325262306a36Sopenharmony_ci	.probe = tegra210_xusb_padctl_probe,
325362306a36Sopenharmony_ci	.remove = tegra210_xusb_padctl_remove,
325462306a36Sopenharmony_ci	.suspend_noirq = tegra210_xusb_padctl_suspend_noirq,
325562306a36Sopenharmony_ci	.resume_noirq = tegra210_xusb_padctl_resume_noirq,
325662306a36Sopenharmony_ci	.usb3_set_lfps_detect = tegra210_usb3_set_lfps_detect,
325762306a36Sopenharmony_ci	.hsic_set_idle = tegra210_hsic_set_idle,
325862306a36Sopenharmony_ci	.vbus_override = tegra210_xusb_padctl_vbus_override,
325962306a36Sopenharmony_ci	.utmi_port_reset = tegra210_utmi_port_reset,
326062306a36Sopenharmony_ci};
326162306a36Sopenharmony_ci
326262306a36Sopenharmony_cistatic const char * const tegra210_xusb_padctl_supply_names[] = {
326362306a36Sopenharmony_ci	"avdd-pll-utmip",
326462306a36Sopenharmony_ci	"avdd-pll-uerefe",
326562306a36Sopenharmony_ci	"dvdd-pex-pll",
326662306a36Sopenharmony_ci	"hvdd-pex-pll-e",
326762306a36Sopenharmony_ci};
326862306a36Sopenharmony_ci
326962306a36Sopenharmony_ciconst struct tegra_xusb_padctl_soc tegra210_xusb_padctl_soc = {
327062306a36Sopenharmony_ci	.num_pads = ARRAY_SIZE(tegra210_pads),
327162306a36Sopenharmony_ci	.pads = tegra210_pads,
327262306a36Sopenharmony_ci	.ports = {
327362306a36Sopenharmony_ci		.usb2 = {
327462306a36Sopenharmony_ci			.ops = &tegra210_usb2_port_ops,
327562306a36Sopenharmony_ci			.count = 4,
327662306a36Sopenharmony_ci		},
327762306a36Sopenharmony_ci		.hsic = {
327862306a36Sopenharmony_ci			.ops = &tegra210_hsic_port_ops,
327962306a36Sopenharmony_ci			.count = 1,
328062306a36Sopenharmony_ci		},
328162306a36Sopenharmony_ci		.usb3 = {
328262306a36Sopenharmony_ci			.ops = &tegra210_usb3_port_ops,
328362306a36Sopenharmony_ci			.count = 4,
328462306a36Sopenharmony_ci		},
328562306a36Sopenharmony_ci	},
328662306a36Sopenharmony_ci	.ops = &tegra210_xusb_padctl_ops,
328762306a36Sopenharmony_ci	.supply_names = tegra210_xusb_padctl_supply_names,
328862306a36Sopenharmony_ci	.num_supplies = ARRAY_SIZE(tegra210_xusb_padctl_supply_names),
328962306a36Sopenharmony_ci	.need_fake_usb3_port = true,
329062306a36Sopenharmony_ci};
329162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(tegra210_xusb_padctl_soc);
329262306a36Sopenharmony_ci
329362306a36Sopenharmony_ciMODULE_AUTHOR("Andrew Bresticker <abrestic@chromium.org>");
329462306a36Sopenharmony_ciMODULE_DESCRIPTION("NVIDIA Tegra 210 XUSB Pad Controller driver");
329562306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
3296