162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/delay.h> 762306a36Sopenharmony_ci#include <linux/io.h> 862306a36Sopenharmony_ci#include <linux/mailbox_client.h> 962306a36Sopenharmony_ci#include <linux/module.h> 1062306a36Sopenharmony_ci#include <linux/of.h> 1162306a36Sopenharmony_ci#include <linux/phy/phy.h> 1262306a36Sopenharmony_ci#include <linux/platform_device.h> 1362306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 1462306a36Sopenharmony_ci#include <linux/reset.h> 1562306a36Sopenharmony_ci#include <linux/slab.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <soc/tegra/fuse.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include "xusb.h" 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(x) ((x) ? 15 : 0) 2262306a36Sopenharmony_ci#define FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK 0x3f 2362306a36Sopenharmony_ci#define FUSE_SKU_CALIB_HS_IREF_CAP_SHIFT 13 2462306a36Sopenharmony_ci#define FUSE_SKU_CALIB_HS_IREF_CAP_MASK 0x3 2562306a36Sopenharmony_ci#define FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_SHIFT 11 2662306a36Sopenharmony_ci#define FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_MASK 0x3 2762306a36Sopenharmony_ci#define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT 7 2862306a36Sopenharmony_ci#define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK 0xf 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP 0x008 3162306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(x) ((x) * 4) 3262306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_PORT_CAP_MASK 0x3 3362306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_DISABLED 0x0 3462306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_HOST 0x1 3562306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_DEVICE 0x2 3662306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_OTG 0x3 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP 0x014 3962306a36Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(x) (1 << (((x) * 4) + 3)) 4062306a36Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_SHIFT(x) ((x) * 4) 4162306a36Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(x) (0x7 << ((x) * 4)) 4262306a36Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(x, v) (((v) & 0x7) << ((x) * 4)) 4362306a36Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORT_MAP_MASK 0x7 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM 0x01c 4662306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26) 4762306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25) 4862306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24) 4962306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(x) (1 << (18 + (x) * 4)) 5062306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(x) \ 5162306a36Sopenharmony_ci (1 << (17 + (x) * 4)) 5262306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(x) (1 << (16 + (x) * 4)) 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040 5562306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19) 5662306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12) 5762306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1) 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044 6062306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6) 6162306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5) 6262306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4) 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(x) (0x058 + (x) * 4) 6562306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT 24 6662306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_MASK 0xff 6762306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_VAL 0x24 6862306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT 16 6962306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK 0x3f 7062306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT 8 7162306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK 0x3f 7262306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT 8 7362306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_MASK 0xffff 7462306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_VAL 0xf070 7562306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT 4 7662306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_MASK 0xf 7762306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_VAL 0xf 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(x) (0x068 + (x) * 4) 8062306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT 24 8162306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK 0x1f 8262306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT 16 8362306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK 0x7f 8462306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_VAL 0x002008ee 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL2(x) ((x) < 2 ? 0x078 + (x) * 4 : \ 8762306a36Sopenharmony_ci 0x0f8 + (x) * 4) 8862306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT 28 8962306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_MASK 0x3 9062306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_VAL 0x1 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL5(x) ((x) < 2 ? 0x090 + (x) * 4 : \ 9362306a36Sopenharmony_ci 0x11c + (x) * 4) 9462306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL5_RX_QEYE_EN (1 << 8) 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL6(x) ((x) < 2 ? 0x098 + (x) * 4 : \ 9762306a36Sopenharmony_ci 0x128 + (x) * 4) 9862306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT 24 9962306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK 0x3f 10062306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_TAP_MASK 0x1f 10162306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_AMP_MASK 0x7f 10262306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT 16 10362306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK 0xff 10462306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_G_Z 0x21 10562306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_TAP 0x32 10662306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_AMP 0x33 10762306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_CTLE_Z 0x48 10862306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_LATCH_G_Z 0xa1 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PADX_CTL0(x) (0x0a0 + (x) * 4) 11162306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI (1 << 21) 11262306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 (1 << 20) 11362306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD (1 << 19) 11462306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT 14 11562306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_MASK 0x3 11662306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_VAL(x) ((x) ? 0x0 : 0x3) 11762306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT 6 11862306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_MASK 0x3f 11962306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_VAL 0x0e 12062306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT 0 12162306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK 0x3f 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PADX_CTL1(x) (0x0ac + (x) * 4) 12462306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT 9 12562306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_MASK 0x3 12662306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT 3 12762306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK 0x7 12862306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR (1 << 2) 12962306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP (1 << 1) 13062306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP (1 << 0) 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0 0x0b8 13362306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD (1 << 12) 13462306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT 2 13562306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK 0x7 13662306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL 0x5 13762306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT 0 13862306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK 0x3 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PADX_CTL0(x) (0x0c0 + (x) * 4) 14162306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT 12 14262306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_MASK 0x7 14362306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT 8 14462306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_MASK 0x7 14562306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT 4 14662306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_MASK 0x7 14762306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT 0 14862306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_MASK 0x7 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PADX_CTL1(x) (0x0c8 + (x) * 4) 15162306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE (1 << 10) 15262306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_RPU_DATA (1 << 9) 15362306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_RPD_STROBE (1 << 8) 15462306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA (1 << 7) 15562306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI (1 << 5) 15662306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX (1 << 4) 15762306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX (1 << 3) 15862306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX (1 << 2) 15962306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN (1 << 0) 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PADX_CTL2(x) (0x0d0 + (x) * 4) 16262306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT 4 16362306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK 0x7 16462306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT 0 16562306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK 0x7 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL 0x0e0 16862306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL_STRB_TRIM_MASK 0x1f 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci#define XUSB_PADCTL_USB3_PAD_MUX 0x134 17162306a36Sopenharmony_ci#define XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(x) (1 << (1 + (x))) 17262306a36Sopenharmony_ci#define XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(x) (1 << (6 + (x))) 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138 17562306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27) 17662306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24) 17762306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT 20 17862306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_MASK 0x3 17962306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3) 18062306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1) 18162306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0) 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2 0x13c 18462306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT 20 18562306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_MASK 0xf 18662306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT 16 18762306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_MASK 0xf 18862306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TCLKOUT_EN (1 << 12) 18962306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TXCLKREF_SEL (1 << 4) 19062306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT 0 19162306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_MASK 0x7 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL3 0x140 19462306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL3_RCAL_BYPASS (1 << 7) 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148 19762306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1) 19862306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0) 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2 0x14c 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5 0x158 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6 0x15c 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_cistruct tegra124_xusb_fuse_calibration { 20762306a36Sopenharmony_ci u32 hs_curr_level[3]; 20862306a36Sopenharmony_ci u32 hs_iref_cap; 20962306a36Sopenharmony_ci u32 hs_term_range_adj; 21062306a36Sopenharmony_ci u32 hs_squelch_level; 21162306a36Sopenharmony_ci}; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_cistruct tegra124_xusb_padctl { 21462306a36Sopenharmony_ci struct tegra_xusb_padctl base; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci struct tegra124_xusb_fuse_calibration fuse; 21762306a36Sopenharmony_ci}; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_cistatic inline struct tegra124_xusb_padctl * 22062306a36Sopenharmony_cito_tegra124_xusb_padctl(struct tegra_xusb_padctl *padctl) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci return container_of(padctl, struct tegra124_xusb_padctl, base); 22362306a36Sopenharmony_ci} 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_cistatic int tegra124_xusb_padctl_enable(struct tegra_xusb_padctl *padctl) 22662306a36Sopenharmony_ci{ 22762306a36Sopenharmony_ci u32 value; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci mutex_lock(&padctl->lock); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci if (padctl->enable++ > 0) 23262306a36Sopenharmony_ci goto out; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 23562306a36Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; 23662306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci usleep_range(100, 200); 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 24162306a36Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; 24262306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci usleep_range(100, 200); 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 24762306a36Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; 24862306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ciout: 25162306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 25262306a36Sopenharmony_ci return 0; 25362306a36Sopenharmony_ci} 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_cistatic int tegra124_xusb_padctl_disable(struct tegra_xusb_padctl *padctl) 25662306a36Sopenharmony_ci{ 25762306a36Sopenharmony_ci u32 value; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci mutex_lock(&padctl->lock); 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci if (WARN_ON(padctl->enable == 0)) 26262306a36Sopenharmony_ci goto out; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci if (--padctl->enable > 0) 26562306a36Sopenharmony_ci goto out; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 26862306a36Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; 26962306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci usleep_range(100, 200); 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 27462306a36Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; 27562306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci usleep_range(100, 200); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 28062306a36Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; 28162306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ciout: 28462306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 28562306a36Sopenharmony_ci return 0; 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_cistatic int tegra124_usb3_save_context(struct tegra_xusb_padctl *padctl, 28962306a36Sopenharmony_ci unsigned int index) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci struct tegra_xusb_usb3_port *port; 29262306a36Sopenharmony_ci struct tegra_xusb_lane *lane; 29362306a36Sopenharmony_ci u32 value, offset; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci port = tegra_xusb_find_usb3_port(padctl, index); 29662306a36Sopenharmony_ci if (!port) 29762306a36Sopenharmony_ci return -ENODEV; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci port->context_saved = true; 30062306a36Sopenharmony_ci lane = port->base.lane; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci if (lane->pad == padctl->pcie) 30362306a36Sopenharmony_ci offset = XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL6(lane->index); 30462306a36Sopenharmony_ci else 30562306a36Sopenharmony_ci offset = XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci value = padctl_readl(padctl, offset); 30862306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK << 30962306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT); 31062306a36Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_TAP << 31162306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT; 31262306a36Sopenharmony_ci padctl_writel(padctl, value, offset); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci value = padctl_readl(padctl, offset) >> 31562306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT; 31662306a36Sopenharmony_ci port->tap1 = value & XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_TAP_MASK; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci value = padctl_readl(padctl, offset); 31962306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK << 32062306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT); 32162306a36Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_AMP << 32262306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT; 32362306a36Sopenharmony_ci padctl_writel(padctl, value, offset); 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci value = padctl_readl(padctl, offset) >> 32662306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT; 32762306a36Sopenharmony_ci port->amp = value & XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_AMP_MASK; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(index)); 33062306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK << 33162306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) | 33262306a36Sopenharmony_ci (XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK << 33362306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT)); 33462306a36Sopenharmony_ci value |= (port->tap1 << 33562306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) | 33662306a36Sopenharmony_ci (port->amp << 33762306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT); 33862306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(index)); 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci value = padctl_readl(padctl, offset); 34162306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK << 34262306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT); 34362306a36Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_LATCH_G_Z << 34462306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT; 34562306a36Sopenharmony_ci padctl_writel(padctl, value, offset); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci value = padctl_readl(padctl, offset); 34862306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK << 34962306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT); 35062306a36Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_G_Z << 35162306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT; 35262306a36Sopenharmony_ci padctl_writel(padctl, value, offset); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci value = padctl_readl(padctl, offset) >> 35562306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT; 35662306a36Sopenharmony_ci port->ctle_g = value & 35762306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci value = padctl_readl(padctl, offset); 36062306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK << 36162306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT); 36262306a36Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_CTLE_Z << 36362306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT; 36462306a36Sopenharmony_ci padctl_writel(padctl, value, offset); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci value = padctl_readl(padctl, offset) >> 36762306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT; 36862306a36Sopenharmony_ci port->ctle_z = value & 36962306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index)); 37262306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK << 37362306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) | 37462306a36Sopenharmony_ci (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK << 37562306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT)); 37662306a36Sopenharmony_ci value |= (port->ctle_g << 37762306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) | 37862306a36Sopenharmony_ci (port->ctle_z << 37962306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT); 38062306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index)); 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci return 0; 38362306a36Sopenharmony_ci} 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_cistatic int tegra124_hsic_set_idle(struct tegra_xusb_padctl *padctl, 38662306a36Sopenharmony_ci unsigned int index, bool idle) 38762306a36Sopenharmony_ci{ 38862306a36Sopenharmony_ci u32 value; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci if (idle) 39362306a36Sopenharmony_ci value |= XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA | 39462306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE; 39562306a36Sopenharmony_ci else 39662306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA | 39762306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci return 0; 40262306a36Sopenharmony_ci} 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci#define TEGRA124_LANE(_name, _offset, _shift, _mask, _type) \ 40562306a36Sopenharmony_ci { \ 40662306a36Sopenharmony_ci .name = _name, \ 40762306a36Sopenharmony_ci .offset = _offset, \ 40862306a36Sopenharmony_ci .shift = _shift, \ 40962306a36Sopenharmony_ci .mask = _mask, \ 41062306a36Sopenharmony_ci .num_funcs = ARRAY_SIZE(tegra124_##_type##_functions), \ 41162306a36Sopenharmony_ci .funcs = tegra124_##_type##_functions, \ 41262306a36Sopenharmony_ci } 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_cistatic const char * const tegra124_usb2_functions[] = { 41562306a36Sopenharmony_ci "snps", 41662306a36Sopenharmony_ci "xusb", 41762306a36Sopenharmony_ci "uart", 41862306a36Sopenharmony_ci}; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra124_usb2_lanes[] = { 42162306a36Sopenharmony_ci TEGRA124_LANE("usb2-0", 0x004, 0, 0x3, usb2), 42262306a36Sopenharmony_ci TEGRA124_LANE("usb2-1", 0x004, 2, 0x3, usb2), 42362306a36Sopenharmony_ci TEGRA124_LANE("usb2-2", 0x004, 4, 0x3, usb2), 42462306a36Sopenharmony_ci}; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_cistatic struct tegra_xusb_lane * 42762306a36Sopenharmony_citegra124_usb2_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 42862306a36Sopenharmony_ci unsigned int index) 42962306a36Sopenharmony_ci{ 43062306a36Sopenharmony_ci struct tegra_xusb_usb2_lane *usb2; 43162306a36Sopenharmony_ci int err; 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL); 43462306a36Sopenharmony_ci if (!usb2) 43562306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci INIT_LIST_HEAD(&usb2->base.list); 43862306a36Sopenharmony_ci usb2->base.soc = &pad->soc->lanes[index]; 43962306a36Sopenharmony_ci usb2->base.index = index; 44062306a36Sopenharmony_ci usb2->base.pad = pad; 44162306a36Sopenharmony_ci usb2->base.np = np; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci err = tegra_xusb_lane_parse_dt(&usb2->base, np); 44462306a36Sopenharmony_ci if (err < 0) { 44562306a36Sopenharmony_ci kfree(usb2); 44662306a36Sopenharmony_ci return ERR_PTR(err); 44762306a36Sopenharmony_ci } 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci return &usb2->base; 45062306a36Sopenharmony_ci} 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_cistatic void tegra124_usb2_lane_remove(struct tegra_xusb_lane *lane) 45362306a36Sopenharmony_ci{ 45462306a36Sopenharmony_ci struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci kfree(usb2); 45762306a36Sopenharmony_ci} 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra124_usb2_lane_ops = { 46062306a36Sopenharmony_ci .probe = tegra124_usb2_lane_probe, 46162306a36Sopenharmony_ci .remove = tegra124_usb2_lane_remove, 46262306a36Sopenharmony_ci}; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_cistatic int tegra124_usb2_phy_init(struct phy *phy) 46562306a36Sopenharmony_ci{ 46662306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci return tegra124_xusb_padctl_enable(lane->pad->padctl); 46962306a36Sopenharmony_ci} 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_cistatic int tegra124_usb2_phy_exit(struct phy *phy) 47262306a36Sopenharmony_ci{ 47362306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci return tegra124_xusb_padctl_disable(lane->pad->padctl); 47662306a36Sopenharmony_ci} 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_cistatic int tegra124_usb2_phy_power_on(struct phy *phy) 47962306a36Sopenharmony_ci{ 48062306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 48162306a36Sopenharmony_ci struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane); 48262306a36Sopenharmony_ci struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad); 48362306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 48462306a36Sopenharmony_ci struct tegra124_xusb_padctl *priv; 48562306a36Sopenharmony_ci struct tegra_xusb_usb2_port *port; 48662306a36Sopenharmony_ci unsigned int index = lane->index; 48762306a36Sopenharmony_ci u32 value; 48862306a36Sopenharmony_ci int err; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci port = tegra_xusb_find_usb2_port(padctl, index); 49162306a36Sopenharmony_ci if (!port) { 49262306a36Sopenharmony_ci dev_err(&phy->dev, "no port found for USB2 lane %u\n", index); 49362306a36Sopenharmony_ci return -ENODEV; 49462306a36Sopenharmony_ci } 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci priv = to_tegra124_xusb_padctl(padctl); 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 49962306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK << 50062306a36Sopenharmony_ci XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) | 50162306a36Sopenharmony_ci (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK << 50262306a36Sopenharmony_ci XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT)); 50362306a36Sopenharmony_ci value |= (priv->fuse.hs_squelch_level << 50462306a36Sopenharmony_ci XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) | 50562306a36Sopenharmony_ci (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL << 50662306a36Sopenharmony_ci XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT); 50762306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_PORT_CAP); 51062306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_USB2_PORT_CAP_PORT_CAP_MASK << 51162306a36Sopenharmony_ci XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(index)); 51262306a36Sopenharmony_ci value |= XUSB_PADCTL_USB2_PORT_CAP_HOST << 51362306a36Sopenharmony_ci XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(index); 51462306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_PORT_CAP); 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index)); 51762306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK << 51862306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT) | 51962306a36Sopenharmony_ci (XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_MASK << 52062306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT) | 52162306a36Sopenharmony_ci (XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_MASK << 52262306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT) | 52362306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD | 52462306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 | 52562306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI); 52662306a36Sopenharmony_ci value |= (priv->fuse.hs_curr_level[index] + 52762306a36Sopenharmony_ci usb2->hs_curr_level_offset) << 52862306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT; 52962306a36Sopenharmony_ci value |= XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_VAL << 53062306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT; 53162306a36Sopenharmony_ci value |= XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_VAL(index) << 53262306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT; 53362306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index)); 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index)); 53662306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK << 53762306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) | 53862306a36Sopenharmony_ci (XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_MASK << 53962306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT) | 54062306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR | 54162306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP | 54262306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP); 54362306a36Sopenharmony_ci value |= (priv->fuse.hs_term_range_adj << 54462306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) | 54562306a36Sopenharmony_ci (priv->fuse.hs_iref_cap << 54662306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT); 54762306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index)); 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci err = regulator_enable(port->supply); 55062306a36Sopenharmony_ci if (err) 55162306a36Sopenharmony_ci return err; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci mutex_lock(&pad->lock); 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci if (pad->enable++ > 0) 55662306a36Sopenharmony_ci goto out; 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 55962306a36Sopenharmony_ci value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD; 56062306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ciout: 56362306a36Sopenharmony_ci mutex_unlock(&pad->lock); 56462306a36Sopenharmony_ci return 0; 56562306a36Sopenharmony_ci} 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_cistatic int tegra124_usb2_phy_power_off(struct phy *phy) 56862306a36Sopenharmony_ci{ 56962306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 57062306a36Sopenharmony_ci struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad); 57162306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 57262306a36Sopenharmony_ci struct tegra_xusb_usb2_port *port; 57362306a36Sopenharmony_ci u32 value; 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci port = tegra_xusb_find_usb2_port(padctl, lane->index); 57662306a36Sopenharmony_ci if (!port) { 57762306a36Sopenharmony_ci dev_err(&phy->dev, "no port found for USB2 lane %u\n", 57862306a36Sopenharmony_ci lane->index); 57962306a36Sopenharmony_ci return -ENODEV; 58062306a36Sopenharmony_ci } 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci mutex_lock(&pad->lock); 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci if (WARN_ON(pad->enable == 0)) 58562306a36Sopenharmony_ci goto out; 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci if (--pad->enable > 0) 58862306a36Sopenharmony_ci goto out; 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 59162306a36Sopenharmony_ci value |= XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD; 59262306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ciout: 59562306a36Sopenharmony_ci regulator_disable(port->supply); 59662306a36Sopenharmony_ci mutex_unlock(&pad->lock); 59762306a36Sopenharmony_ci return 0; 59862306a36Sopenharmony_ci} 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_cistatic const struct phy_ops tegra124_usb2_phy_ops = { 60162306a36Sopenharmony_ci .init = tegra124_usb2_phy_init, 60262306a36Sopenharmony_ci .exit = tegra124_usb2_phy_exit, 60362306a36Sopenharmony_ci .power_on = tegra124_usb2_phy_power_on, 60462306a36Sopenharmony_ci .power_off = tegra124_usb2_phy_power_off, 60562306a36Sopenharmony_ci .owner = THIS_MODULE, 60662306a36Sopenharmony_ci}; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_cistatic struct tegra_xusb_pad * 60962306a36Sopenharmony_citegra124_usb2_pad_probe(struct tegra_xusb_padctl *padctl, 61062306a36Sopenharmony_ci const struct tegra_xusb_pad_soc *soc, 61162306a36Sopenharmony_ci struct device_node *np) 61262306a36Sopenharmony_ci{ 61362306a36Sopenharmony_ci struct tegra_xusb_usb2_pad *usb2; 61462306a36Sopenharmony_ci struct tegra_xusb_pad *pad; 61562306a36Sopenharmony_ci int err; 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL); 61862306a36Sopenharmony_ci if (!usb2) 61962306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci mutex_init(&usb2->lock); 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci pad = &usb2->base; 62462306a36Sopenharmony_ci pad->ops = &tegra124_usb2_lane_ops; 62562306a36Sopenharmony_ci pad->soc = soc; 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci err = tegra_xusb_pad_init(pad, padctl, np); 62862306a36Sopenharmony_ci if (err < 0) { 62962306a36Sopenharmony_ci kfree(usb2); 63062306a36Sopenharmony_ci goto out; 63162306a36Sopenharmony_ci } 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci err = tegra_xusb_pad_register(pad, &tegra124_usb2_phy_ops); 63462306a36Sopenharmony_ci if (err < 0) 63562306a36Sopenharmony_ci goto unregister; 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci dev_set_drvdata(&pad->dev, pad); 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci return pad; 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ciunregister: 64262306a36Sopenharmony_ci device_unregister(&pad->dev); 64362306a36Sopenharmony_ciout: 64462306a36Sopenharmony_ci return ERR_PTR(err); 64562306a36Sopenharmony_ci} 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_cistatic void tegra124_usb2_pad_remove(struct tegra_xusb_pad *pad) 64862306a36Sopenharmony_ci{ 64962306a36Sopenharmony_ci struct tegra_xusb_usb2_pad *usb2 = to_usb2_pad(pad); 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci kfree(usb2); 65262306a36Sopenharmony_ci} 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra124_usb2_ops = { 65562306a36Sopenharmony_ci .probe = tegra124_usb2_pad_probe, 65662306a36Sopenharmony_ci .remove = tegra124_usb2_pad_remove, 65762306a36Sopenharmony_ci}; 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra124_usb2_pad = { 66062306a36Sopenharmony_ci .name = "usb2", 66162306a36Sopenharmony_ci .num_lanes = ARRAY_SIZE(tegra124_usb2_lanes), 66262306a36Sopenharmony_ci .lanes = tegra124_usb2_lanes, 66362306a36Sopenharmony_ci .ops = &tegra124_usb2_ops, 66462306a36Sopenharmony_ci}; 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_cistatic const char * const tegra124_ulpi_functions[] = { 66762306a36Sopenharmony_ci "snps", 66862306a36Sopenharmony_ci "xusb", 66962306a36Sopenharmony_ci}; 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra124_ulpi_lanes[] = { 67262306a36Sopenharmony_ci TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, ulpi), 67362306a36Sopenharmony_ci}; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_cistatic struct tegra_xusb_lane * 67662306a36Sopenharmony_citegra124_ulpi_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 67762306a36Sopenharmony_ci unsigned int index) 67862306a36Sopenharmony_ci{ 67962306a36Sopenharmony_ci struct tegra_xusb_ulpi_lane *ulpi; 68062306a36Sopenharmony_ci int err; 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci ulpi = kzalloc(sizeof(*ulpi), GFP_KERNEL); 68362306a36Sopenharmony_ci if (!ulpi) 68462306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci INIT_LIST_HEAD(&ulpi->base.list); 68762306a36Sopenharmony_ci ulpi->base.soc = &pad->soc->lanes[index]; 68862306a36Sopenharmony_ci ulpi->base.index = index; 68962306a36Sopenharmony_ci ulpi->base.pad = pad; 69062306a36Sopenharmony_ci ulpi->base.np = np; 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci err = tegra_xusb_lane_parse_dt(&ulpi->base, np); 69362306a36Sopenharmony_ci if (err < 0) { 69462306a36Sopenharmony_ci kfree(ulpi); 69562306a36Sopenharmony_ci return ERR_PTR(err); 69662306a36Sopenharmony_ci } 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci return &ulpi->base; 69962306a36Sopenharmony_ci} 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_cistatic void tegra124_ulpi_lane_remove(struct tegra_xusb_lane *lane) 70262306a36Sopenharmony_ci{ 70362306a36Sopenharmony_ci struct tegra_xusb_ulpi_lane *ulpi = to_ulpi_lane(lane); 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci kfree(ulpi); 70662306a36Sopenharmony_ci} 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra124_ulpi_lane_ops = { 70962306a36Sopenharmony_ci .probe = tegra124_ulpi_lane_probe, 71062306a36Sopenharmony_ci .remove = tegra124_ulpi_lane_remove, 71162306a36Sopenharmony_ci}; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_cistatic int tegra124_ulpi_phy_init(struct phy *phy) 71462306a36Sopenharmony_ci{ 71562306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci return tegra124_xusb_padctl_enable(lane->pad->padctl); 71862306a36Sopenharmony_ci} 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_cistatic int tegra124_ulpi_phy_exit(struct phy *phy) 72162306a36Sopenharmony_ci{ 72262306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci return tegra124_xusb_padctl_disable(lane->pad->padctl); 72562306a36Sopenharmony_ci} 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_cistatic int tegra124_ulpi_phy_power_on(struct phy *phy) 72862306a36Sopenharmony_ci{ 72962306a36Sopenharmony_ci return 0; 73062306a36Sopenharmony_ci} 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_cistatic int tegra124_ulpi_phy_power_off(struct phy *phy) 73362306a36Sopenharmony_ci{ 73462306a36Sopenharmony_ci return 0; 73562306a36Sopenharmony_ci} 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_cistatic const struct phy_ops tegra124_ulpi_phy_ops = { 73862306a36Sopenharmony_ci .init = tegra124_ulpi_phy_init, 73962306a36Sopenharmony_ci .exit = tegra124_ulpi_phy_exit, 74062306a36Sopenharmony_ci .power_on = tegra124_ulpi_phy_power_on, 74162306a36Sopenharmony_ci .power_off = tegra124_ulpi_phy_power_off, 74262306a36Sopenharmony_ci .owner = THIS_MODULE, 74362306a36Sopenharmony_ci}; 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_cistatic struct tegra_xusb_pad * 74662306a36Sopenharmony_citegra124_ulpi_pad_probe(struct tegra_xusb_padctl *padctl, 74762306a36Sopenharmony_ci const struct tegra_xusb_pad_soc *soc, 74862306a36Sopenharmony_ci struct device_node *np) 74962306a36Sopenharmony_ci{ 75062306a36Sopenharmony_ci struct tegra_xusb_ulpi_pad *ulpi; 75162306a36Sopenharmony_ci struct tegra_xusb_pad *pad; 75262306a36Sopenharmony_ci int err; 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci ulpi = kzalloc(sizeof(*ulpi), GFP_KERNEL); 75562306a36Sopenharmony_ci if (!ulpi) 75662306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci pad = &ulpi->base; 75962306a36Sopenharmony_ci pad->ops = &tegra124_ulpi_lane_ops; 76062306a36Sopenharmony_ci pad->soc = soc; 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci err = tegra_xusb_pad_init(pad, padctl, np); 76362306a36Sopenharmony_ci if (err < 0) { 76462306a36Sopenharmony_ci kfree(ulpi); 76562306a36Sopenharmony_ci goto out; 76662306a36Sopenharmony_ci } 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci err = tegra_xusb_pad_register(pad, &tegra124_ulpi_phy_ops); 76962306a36Sopenharmony_ci if (err < 0) 77062306a36Sopenharmony_ci goto unregister; 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci dev_set_drvdata(&pad->dev, pad); 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci return pad; 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ciunregister: 77762306a36Sopenharmony_ci device_unregister(&pad->dev); 77862306a36Sopenharmony_ciout: 77962306a36Sopenharmony_ci return ERR_PTR(err); 78062306a36Sopenharmony_ci} 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_cistatic void tegra124_ulpi_pad_remove(struct tegra_xusb_pad *pad) 78362306a36Sopenharmony_ci{ 78462306a36Sopenharmony_ci struct tegra_xusb_ulpi_pad *ulpi = to_ulpi_pad(pad); 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci kfree(ulpi); 78762306a36Sopenharmony_ci} 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra124_ulpi_ops = { 79062306a36Sopenharmony_ci .probe = tegra124_ulpi_pad_probe, 79162306a36Sopenharmony_ci .remove = tegra124_ulpi_pad_remove, 79262306a36Sopenharmony_ci}; 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra124_ulpi_pad = { 79562306a36Sopenharmony_ci .name = "ulpi", 79662306a36Sopenharmony_ci .num_lanes = ARRAY_SIZE(tegra124_ulpi_lanes), 79762306a36Sopenharmony_ci .lanes = tegra124_ulpi_lanes, 79862306a36Sopenharmony_ci .ops = &tegra124_ulpi_ops, 79962306a36Sopenharmony_ci}; 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_cistatic const char * const tegra124_hsic_functions[] = { 80262306a36Sopenharmony_ci "snps", 80362306a36Sopenharmony_ci "xusb", 80462306a36Sopenharmony_ci}; 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra124_hsic_lanes[] = { 80762306a36Sopenharmony_ci TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, hsic), 80862306a36Sopenharmony_ci TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, hsic), 80962306a36Sopenharmony_ci}; 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_cistatic struct tegra_xusb_lane * 81262306a36Sopenharmony_citegra124_hsic_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 81362306a36Sopenharmony_ci unsigned int index) 81462306a36Sopenharmony_ci{ 81562306a36Sopenharmony_ci struct tegra_xusb_hsic_lane *hsic; 81662306a36Sopenharmony_ci int err; 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci hsic = kzalloc(sizeof(*hsic), GFP_KERNEL); 81962306a36Sopenharmony_ci if (!hsic) 82062306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci INIT_LIST_HEAD(&hsic->base.list); 82362306a36Sopenharmony_ci hsic->base.soc = &pad->soc->lanes[index]; 82462306a36Sopenharmony_ci hsic->base.index = index; 82562306a36Sopenharmony_ci hsic->base.pad = pad; 82662306a36Sopenharmony_ci hsic->base.np = np; 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci err = tegra_xusb_lane_parse_dt(&hsic->base, np); 82962306a36Sopenharmony_ci if (err < 0) { 83062306a36Sopenharmony_ci kfree(hsic); 83162306a36Sopenharmony_ci return ERR_PTR(err); 83262306a36Sopenharmony_ci } 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_ci return &hsic->base; 83562306a36Sopenharmony_ci} 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_cistatic void tegra124_hsic_lane_remove(struct tegra_xusb_lane *lane) 83862306a36Sopenharmony_ci{ 83962306a36Sopenharmony_ci struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane); 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci kfree(hsic); 84262306a36Sopenharmony_ci} 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra124_hsic_lane_ops = { 84562306a36Sopenharmony_ci .probe = tegra124_hsic_lane_probe, 84662306a36Sopenharmony_ci .remove = tegra124_hsic_lane_remove, 84762306a36Sopenharmony_ci}; 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_cistatic int tegra124_hsic_phy_init(struct phy *phy) 85062306a36Sopenharmony_ci{ 85162306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci return tegra124_xusb_padctl_enable(lane->pad->padctl); 85462306a36Sopenharmony_ci} 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_cistatic int tegra124_hsic_phy_exit(struct phy *phy) 85762306a36Sopenharmony_ci{ 85862306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci return tegra124_xusb_padctl_disable(lane->pad->padctl); 86162306a36Sopenharmony_ci} 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_cistatic int tegra124_hsic_phy_power_on(struct phy *phy) 86462306a36Sopenharmony_ci{ 86562306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 86662306a36Sopenharmony_ci struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane); 86762306a36Sopenharmony_ci struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad); 86862306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 86962306a36Sopenharmony_ci unsigned int index = lane->index; 87062306a36Sopenharmony_ci u32 value; 87162306a36Sopenharmony_ci int err; 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_ci err = regulator_enable(pad->supply); 87462306a36Sopenharmony_ci if (err) 87562306a36Sopenharmony_ci return err; 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci padctl_writel(padctl, hsic->strobe_trim, 87862306a36Sopenharmony_ci XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL); 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci if (hsic->auto_term) 88362306a36Sopenharmony_ci value |= XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN; 88462306a36Sopenharmony_ci else 88562306a36Sopenharmony_ci value &= ~XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN; 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(index)); 89062306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_MASK << 89162306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT) | 89262306a36Sopenharmony_ci (XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_MASK << 89362306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT) | 89462306a36Sopenharmony_ci (XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_MASK << 89562306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT) | 89662306a36Sopenharmony_ci (XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_MASK << 89762306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT)); 89862306a36Sopenharmony_ci value |= (hsic->tx_rtune_n << 89962306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT) | 90062306a36Sopenharmony_ci (hsic->tx_rtune_p << 90162306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT) | 90262306a36Sopenharmony_ci (hsic->tx_rslew_n << 90362306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT) | 90462306a36Sopenharmony_ci (hsic->tx_rslew_p << 90562306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT); 90662306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL0(index)); 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL2(index)); 90962306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK << 91062306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) | 91162306a36Sopenharmony_ci (XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK << 91262306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT)); 91362306a36Sopenharmony_ci value |= (hsic->rx_strobe_trim << 91462306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) | 91562306a36Sopenharmony_ci (hsic->rx_data_trim << 91662306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT); 91762306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL2(index)); 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 92062306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_HSIC_PAD_CTL1_RPD_STROBE | 92162306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_RPU_DATA | 92262306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX | 92362306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI | 92462306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX | 92562306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX); 92662306a36Sopenharmony_ci value |= XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA | 92762306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE; 92862306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci return 0; 93162306a36Sopenharmony_ci} 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_cistatic int tegra124_hsic_phy_power_off(struct phy *phy) 93462306a36Sopenharmony_ci{ 93562306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 93662306a36Sopenharmony_ci struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad); 93762306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 93862306a36Sopenharmony_ci unsigned int index = lane->index; 93962306a36Sopenharmony_ci u32 value; 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 94262306a36Sopenharmony_ci value |= XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX | 94362306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI | 94462306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX | 94562306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX; 94662306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci regulator_disable(pad->supply); 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci return 0; 95162306a36Sopenharmony_ci} 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_cistatic const struct phy_ops tegra124_hsic_phy_ops = { 95462306a36Sopenharmony_ci .init = tegra124_hsic_phy_init, 95562306a36Sopenharmony_ci .exit = tegra124_hsic_phy_exit, 95662306a36Sopenharmony_ci .power_on = tegra124_hsic_phy_power_on, 95762306a36Sopenharmony_ci .power_off = tegra124_hsic_phy_power_off, 95862306a36Sopenharmony_ci .owner = THIS_MODULE, 95962306a36Sopenharmony_ci}; 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_cistatic struct tegra_xusb_pad * 96262306a36Sopenharmony_citegra124_hsic_pad_probe(struct tegra_xusb_padctl *padctl, 96362306a36Sopenharmony_ci const struct tegra_xusb_pad_soc *soc, 96462306a36Sopenharmony_ci struct device_node *np) 96562306a36Sopenharmony_ci{ 96662306a36Sopenharmony_ci struct tegra_xusb_hsic_pad *hsic; 96762306a36Sopenharmony_ci struct tegra_xusb_pad *pad; 96862306a36Sopenharmony_ci int err; 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci hsic = kzalloc(sizeof(*hsic), GFP_KERNEL); 97162306a36Sopenharmony_ci if (!hsic) 97262306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci pad = &hsic->base; 97562306a36Sopenharmony_ci pad->ops = &tegra124_hsic_lane_ops; 97662306a36Sopenharmony_ci pad->soc = soc; 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_ci err = tegra_xusb_pad_init(pad, padctl, np); 97962306a36Sopenharmony_ci if (err < 0) { 98062306a36Sopenharmony_ci kfree(hsic); 98162306a36Sopenharmony_ci goto out; 98262306a36Sopenharmony_ci } 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_ci err = tegra_xusb_pad_register(pad, &tegra124_hsic_phy_ops); 98562306a36Sopenharmony_ci if (err < 0) 98662306a36Sopenharmony_ci goto unregister; 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci dev_set_drvdata(&pad->dev, pad); 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci return pad; 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ciunregister: 99362306a36Sopenharmony_ci device_unregister(&pad->dev); 99462306a36Sopenharmony_ciout: 99562306a36Sopenharmony_ci return ERR_PTR(err); 99662306a36Sopenharmony_ci} 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_cistatic void tegra124_hsic_pad_remove(struct tegra_xusb_pad *pad) 99962306a36Sopenharmony_ci{ 100062306a36Sopenharmony_ci struct tegra_xusb_hsic_pad *hsic = to_hsic_pad(pad); 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci kfree(hsic); 100362306a36Sopenharmony_ci} 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra124_hsic_ops = { 100662306a36Sopenharmony_ci .probe = tegra124_hsic_pad_probe, 100762306a36Sopenharmony_ci .remove = tegra124_hsic_pad_remove, 100862306a36Sopenharmony_ci}; 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra124_hsic_pad = { 101162306a36Sopenharmony_ci .name = "hsic", 101262306a36Sopenharmony_ci .num_lanes = ARRAY_SIZE(tegra124_hsic_lanes), 101362306a36Sopenharmony_ci .lanes = tegra124_hsic_lanes, 101462306a36Sopenharmony_ci .ops = &tegra124_hsic_ops, 101562306a36Sopenharmony_ci}; 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_cistatic const char * const tegra124_pcie_functions[] = { 101862306a36Sopenharmony_ci "pcie", 101962306a36Sopenharmony_ci "usb3-ss", 102062306a36Sopenharmony_ci "sata", 102162306a36Sopenharmony_ci}; 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra124_pcie_lanes[] = { 102462306a36Sopenharmony_ci TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, pcie), 102562306a36Sopenharmony_ci TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, pcie), 102662306a36Sopenharmony_ci TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, pcie), 102762306a36Sopenharmony_ci TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, pcie), 102862306a36Sopenharmony_ci TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, pcie), 102962306a36Sopenharmony_ci}; 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_cistatic struct tegra_xusb_lane * 103262306a36Sopenharmony_citegra124_pcie_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 103362306a36Sopenharmony_ci unsigned int index) 103462306a36Sopenharmony_ci{ 103562306a36Sopenharmony_ci struct tegra_xusb_pcie_lane *pcie; 103662306a36Sopenharmony_ci int err; 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci pcie = kzalloc(sizeof(*pcie), GFP_KERNEL); 103962306a36Sopenharmony_ci if (!pcie) 104062306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci INIT_LIST_HEAD(&pcie->base.list); 104362306a36Sopenharmony_ci pcie->base.soc = &pad->soc->lanes[index]; 104462306a36Sopenharmony_ci pcie->base.index = index; 104562306a36Sopenharmony_ci pcie->base.pad = pad; 104662306a36Sopenharmony_ci pcie->base.np = np; 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ci err = tegra_xusb_lane_parse_dt(&pcie->base, np); 104962306a36Sopenharmony_ci if (err < 0) { 105062306a36Sopenharmony_ci kfree(pcie); 105162306a36Sopenharmony_ci return ERR_PTR(err); 105262306a36Sopenharmony_ci } 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci return &pcie->base; 105562306a36Sopenharmony_ci} 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_cistatic void tegra124_pcie_lane_remove(struct tegra_xusb_lane *lane) 105862306a36Sopenharmony_ci{ 105962306a36Sopenharmony_ci struct tegra_xusb_pcie_lane *pcie = to_pcie_lane(lane); 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci kfree(pcie); 106262306a36Sopenharmony_ci} 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra124_pcie_lane_ops = { 106562306a36Sopenharmony_ci .probe = tegra124_pcie_lane_probe, 106662306a36Sopenharmony_ci .remove = tegra124_pcie_lane_remove, 106762306a36Sopenharmony_ci}; 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_cistatic int tegra124_pcie_phy_init(struct phy *phy) 107062306a36Sopenharmony_ci{ 107162306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci return tegra124_xusb_padctl_enable(lane->pad->padctl); 107462306a36Sopenharmony_ci} 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_cistatic int tegra124_pcie_phy_exit(struct phy *phy) 107762306a36Sopenharmony_ci{ 107862306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci return tegra124_xusb_padctl_disable(lane->pad->padctl); 108162306a36Sopenharmony_ci} 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_cistatic int tegra124_pcie_phy_power_on(struct phy *phy) 108462306a36Sopenharmony_ci{ 108562306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 108662306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 108762306a36Sopenharmony_ci unsigned long timeout; 108862306a36Sopenharmony_ci int err = -ETIMEDOUT; 108962306a36Sopenharmony_ci u32 value; 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); 109262306a36Sopenharmony_ci value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK; 109362306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); 109662306a36Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN | 109762306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN | 109862306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL; 109962306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); 110262306a36Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST; 110362306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(50); 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_ci while (time_before(jiffies, timeout)) { 110862306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); 110962306a36Sopenharmony_ci if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) { 111062306a36Sopenharmony_ci err = 0; 111162306a36Sopenharmony_ci break; 111262306a36Sopenharmony_ci } 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_ci usleep_range(100, 200); 111562306a36Sopenharmony_ci } 111662306a36Sopenharmony_ci 111762306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); 111862306a36Sopenharmony_ci value |= XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index); 111962306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_ci return err; 112262306a36Sopenharmony_ci} 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_cistatic int tegra124_pcie_phy_power_off(struct phy *phy) 112562306a36Sopenharmony_ci{ 112662306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 112762306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 112862306a36Sopenharmony_ci u32 value; 112962306a36Sopenharmony_ci 113062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); 113162306a36Sopenharmony_ci value &= ~XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index); 113262306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); 113562306a36Sopenharmony_ci value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST; 113662306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci return 0; 113962306a36Sopenharmony_ci} 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_cistatic const struct phy_ops tegra124_pcie_phy_ops = { 114262306a36Sopenharmony_ci .init = tegra124_pcie_phy_init, 114362306a36Sopenharmony_ci .exit = tegra124_pcie_phy_exit, 114462306a36Sopenharmony_ci .power_on = tegra124_pcie_phy_power_on, 114562306a36Sopenharmony_ci .power_off = tegra124_pcie_phy_power_off, 114662306a36Sopenharmony_ci .owner = THIS_MODULE, 114762306a36Sopenharmony_ci}; 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_cistatic struct tegra_xusb_pad * 115062306a36Sopenharmony_citegra124_pcie_pad_probe(struct tegra_xusb_padctl *padctl, 115162306a36Sopenharmony_ci const struct tegra_xusb_pad_soc *soc, 115262306a36Sopenharmony_ci struct device_node *np) 115362306a36Sopenharmony_ci{ 115462306a36Sopenharmony_ci struct tegra_xusb_pcie_pad *pcie; 115562306a36Sopenharmony_ci struct tegra_xusb_pad *pad; 115662306a36Sopenharmony_ci int err; 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ci pcie = kzalloc(sizeof(*pcie), GFP_KERNEL); 115962306a36Sopenharmony_ci if (!pcie) 116062306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci pad = &pcie->base; 116362306a36Sopenharmony_ci pad->ops = &tegra124_pcie_lane_ops; 116462306a36Sopenharmony_ci pad->soc = soc; 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_ci err = tegra_xusb_pad_init(pad, padctl, np); 116762306a36Sopenharmony_ci if (err < 0) { 116862306a36Sopenharmony_ci kfree(pcie); 116962306a36Sopenharmony_ci goto out; 117062306a36Sopenharmony_ci } 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ci err = tegra_xusb_pad_register(pad, &tegra124_pcie_phy_ops); 117362306a36Sopenharmony_ci if (err < 0) 117462306a36Sopenharmony_ci goto unregister; 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_ci dev_set_drvdata(&pad->dev, pad); 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_ci return pad; 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_ciunregister: 118162306a36Sopenharmony_ci device_unregister(&pad->dev); 118262306a36Sopenharmony_ciout: 118362306a36Sopenharmony_ci return ERR_PTR(err); 118462306a36Sopenharmony_ci} 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_cistatic void tegra124_pcie_pad_remove(struct tegra_xusb_pad *pad) 118762306a36Sopenharmony_ci{ 118862306a36Sopenharmony_ci struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(pad); 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_ci kfree(pcie); 119162306a36Sopenharmony_ci} 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra124_pcie_ops = { 119462306a36Sopenharmony_ci .probe = tegra124_pcie_pad_probe, 119562306a36Sopenharmony_ci .remove = tegra124_pcie_pad_remove, 119662306a36Sopenharmony_ci}; 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra124_pcie_pad = { 119962306a36Sopenharmony_ci .name = "pcie", 120062306a36Sopenharmony_ci .num_lanes = ARRAY_SIZE(tegra124_pcie_lanes), 120162306a36Sopenharmony_ci .lanes = tegra124_pcie_lanes, 120262306a36Sopenharmony_ci .ops = &tegra124_pcie_ops, 120362306a36Sopenharmony_ci}; 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra124_sata_lanes[] = { 120662306a36Sopenharmony_ci TEGRA124_LANE("sata-0", 0x134, 26, 0x3, pcie), 120762306a36Sopenharmony_ci}; 120862306a36Sopenharmony_ci 120962306a36Sopenharmony_cistatic struct tegra_xusb_lane * 121062306a36Sopenharmony_citegra124_sata_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 121162306a36Sopenharmony_ci unsigned int index) 121262306a36Sopenharmony_ci{ 121362306a36Sopenharmony_ci struct tegra_xusb_sata_lane *sata; 121462306a36Sopenharmony_ci int err; 121562306a36Sopenharmony_ci 121662306a36Sopenharmony_ci sata = kzalloc(sizeof(*sata), GFP_KERNEL); 121762306a36Sopenharmony_ci if (!sata) 121862306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci INIT_LIST_HEAD(&sata->base.list); 122162306a36Sopenharmony_ci sata->base.soc = &pad->soc->lanes[index]; 122262306a36Sopenharmony_ci sata->base.index = index; 122362306a36Sopenharmony_ci sata->base.pad = pad; 122462306a36Sopenharmony_ci sata->base.np = np; 122562306a36Sopenharmony_ci 122662306a36Sopenharmony_ci err = tegra_xusb_lane_parse_dt(&sata->base, np); 122762306a36Sopenharmony_ci if (err < 0) { 122862306a36Sopenharmony_ci kfree(sata); 122962306a36Sopenharmony_ci return ERR_PTR(err); 123062306a36Sopenharmony_ci } 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_ci return &sata->base; 123362306a36Sopenharmony_ci} 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_cistatic void tegra124_sata_lane_remove(struct tegra_xusb_lane *lane) 123662306a36Sopenharmony_ci{ 123762306a36Sopenharmony_ci struct tegra_xusb_sata_lane *sata = to_sata_lane(lane); 123862306a36Sopenharmony_ci 123962306a36Sopenharmony_ci kfree(sata); 124062306a36Sopenharmony_ci} 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra124_sata_lane_ops = { 124362306a36Sopenharmony_ci .probe = tegra124_sata_lane_probe, 124462306a36Sopenharmony_ci .remove = tegra124_sata_lane_remove, 124562306a36Sopenharmony_ci}; 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_cistatic int tegra124_sata_phy_init(struct phy *phy) 124862306a36Sopenharmony_ci{ 124962306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci return tegra124_xusb_padctl_enable(lane->pad->padctl); 125262306a36Sopenharmony_ci} 125362306a36Sopenharmony_ci 125462306a36Sopenharmony_cistatic int tegra124_sata_phy_exit(struct phy *phy) 125562306a36Sopenharmony_ci{ 125662306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_ci return tegra124_xusb_padctl_disable(lane->pad->padctl); 125962306a36Sopenharmony_ci} 126062306a36Sopenharmony_ci 126162306a36Sopenharmony_cistatic int tegra124_sata_phy_power_on(struct phy *phy) 126262306a36Sopenharmony_ci{ 126362306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 126462306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 126562306a36Sopenharmony_ci unsigned long timeout; 126662306a36Sopenharmony_ci int err = -ETIMEDOUT; 126762306a36Sopenharmony_ci u32 value; 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); 127062306a36Sopenharmony_ci value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; 127162306a36Sopenharmony_ci value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ; 127262306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 127562306a36Sopenharmony_ci value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; 127662306a36Sopenharmony_ci value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ; 127762306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 128062306a36Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE; 128162306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 128462306a36Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST; 128562306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 128662306a36Sopenharmony_ci 128762306a36Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(50); 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ci while (time_before(jiffies, timeout)) { 129062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 129162306a36Sopenharmony_ci if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) { 129262306a36Sopenharmony_ci err = 0; 129362306a36Sopenharmony_ci break; 129462306a36Sopenharmony_ci } 129562306a36Sopenharmony_ci 129662306a36Sopenharmony_ci usleep_range(100, 200); 129762306a36Sopenharmony_ci } 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); 130062306a36Sopenharmony_ci value |= XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index); 130162306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ci return err; 130462306a36Sopenharmony_ci} 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_cistatic int tegra124_sata_phy_power_off(struct phy *phy) 130762306a36Sopenharmony_ci{ 130862306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 130962306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 131062306a36Sopenharmony_ci u32 value; 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); 131362306a36Sopenharmony_ci value &= ~XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index); 131462306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); 131562306a36Sopenharmony_ci 131662306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 131762306a36Sopenharmony_ci value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST; 131862306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 131962306a36Sopenharmony_ci 132062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 132162306a36Sopenharmony_ci value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE; 132262306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 132362306a36Sopenharmony_ci 132462306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 132562306a36Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; 132662306a36Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ; 132762306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); 133062306a36Sopenharmony_ci value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; 133162306a36Sopenharmony_ci value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ; 133262306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); 133362306a36Sopenharmony_ci 133462306a36Sopenharmony_ci return 0; 133562306a36Sopenharmony_ci} 133662306a36Sopenharmony_ci 133762306a36Sopenharmony_cistatic const struct phy_ops tegra124_sata_phy_ops = { 133862306a36Sopenharmony_ci .init = tegra124_sata_phy_init, 133962306a36Sopenharmony_ci .exit = tegra124_sata_phy_exit, 134062306a36Sopenharmony_ci .power_on = tegra124_sata_phy_power_on, 134162306a36Sopenharmony_ci .power_off = tegra124_sata_phy_power_off, 134262306a36Sopenharmony_ci .owner = THIS_MODULE, 134362306a36Sopenharmony_ci}; 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_cistatic struct tegra_xusb_pad * 134662306a36Sopenharmony_citegra124_sata_pad_probe(struct tegra_xusb_padctl *padctl, 134762306a36Sopenharmony_ci const struct tegra_xusb_pad_soc *soc, 134862306a36Sopenharmony_ci struct device_node *np) 134962306a36Sopenharmony_ci{ 135062306a36Sopenharmony_ci struct tegra_xusb_sata_pad *sata; 135162306a36Sopenharmony_ci struct tegra_xusb_pad *pad; 135262306a36Sopenharmony_ci int err; 135362306a36Sopenharmony_ci 135462306a36Sopenharmony_ci sata = kzalloc(sizeof(*sata), GFP_KERNEL); 135562306a36Sopenharmony_ci if (!sata) 135662306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_ci pad = &sata->base; 135962306a36Sopenharmony_ci pad->ops = &tegra124_sata_lane_ops; 136062306a36Sopenharmony_ci pad->soc = soc; 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci err = tegra_xusb_pad_init(pad, padctl, np); 136362306a36Sopenharmony_ci if (err < 0) { 136462306a36Sopenharmony_ci kfree(sata); 136562306a36Sopenharmony_ci goto out; 136662306a36Sopenharmony_ci } 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_ci err = tegra_xusb_pad_register(pad, &tegra124_sata_phy_ops); 136962306a36Sopenharmony_ci if (err < 0) 137062306a36Sopenharmony_ci goto unregister; 137162306a36Sopenharmony_ci 137262306a36Sopenharmony_ci dev_set_drvdata(&pad->dev, pad); 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_ci return pad; 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_ciunregister: 137762306a36Sopenharmony_ci device_unregister(&pad->dev); 137862306a36Sopenharmony_ciout: 137962306a36Sopenharmony_ci return ERR_PTR(err); 138062306a36Sopenharmony_ci} 138162306a36Sopenharmony_ci 138262306a36Sopenharmony_cistatic void tegra124_sata_pad_remove(struct tegra_xusb_pad *pad) 138362306a36Sopenharmony_ci{ 138462306a36Sopenharmony_ci struct tegra_xusb_sata_pad *sata = to_sata_pad(pad); 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_ci kfree(sata); 138762306a36Sopenharmony_ci} 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra124_sata_ops = { 139062306a36Sopenharmony_ci .probe = tegra124_sata_pad_probe, 139162306a36Sopenharmony_ci .remove = tegra124_sata_pad_remove, 139262306a36Sopenharmony_ci}; 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra124_sata_pad = { 139562306a36Sopenharmony_ci .name = "sata", 139662306a36Sopenharmony_ci .num_lanes = ARRAY_SIZE(tegra124_sata_lanes), 139762306a36Sopenharmony_ci .lanes = tegra124_sata_lanes, 139862306a36Sopenharmony_ci .ops = &tegra124_sata_ops, 139962306a36Sopenharmony_ci}; 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_cistatic const struct tegra_xusb_pad_soc *tegra124_pads[] = { 140262306a36Sopenharmony_ci &tegra124_usb2_pad, 140362306a36Sopenharmony_ci &tegra124_ulpi_pad, 140462306a36Sopenharmony_ci &tegra124_hsic_pad, 140562306a36Sopenharmony_ci &tegra124_pcie_pad, 140662306a36Sopenharmony_ci &tegra124_sata_pad, 140762306a36Sopenharmony_ci}; 140862306a36Sopenharmony_ci 140962306a36Sopenharmony_cistatic int tegra124_usb2_port_enable(struct tegra_xusb_port *port) 141062306a36Sopenharmony_ci{ 141162306a36Sopenharmony_ci return 0; 141262306a36Sopenharmony_ci} 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_cistatic void tegra124_usb2_port_disable(struct tegra_xusb_port *port) 141562306a36Sopenharmony_ci{ 141662306a36Sopenharmony_ci} 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_cistatic struct tegra_xusb_lane * 141962306a36Sopenharmony_citegra124_usb2_port_map(struct tegra_xusb_port *port) 142062306a36Sopenharmony_ci{ 142162306a36Sopenharmony_ci return tegra_xusb_find_lane(port->padctl, "usb2", port->index); 142262306a36Sopenharmony_ci} 142362306a36Sopenharmony_ci 142462306a36Sopenharmony_cistatic const struct tegra_xusb_port_ops tegra124_usb2_port_ops = { 142562306a36Sopenharmony_ci .release = tegra_xusb_usb2_port_release, 142662306a36Sopenharmony_ci .remove = tegra_xusb_usb2_port_remove, 142762306a36Sopenharmony_ci .enable = tegra124_usb2_port_enable, 142862306a36Sopenharmony_ci .disable = tegra124_usb2_port_disable, 142962306a36Sopenharmony_ci .map = tegra124_usb2_port_map, 143062306a36Sopenharmony_ci}; 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_cistatic int tegra124_ulpi_port_enable(struct tegra_xusb_port *port) 143362306a36Sopenharmony_ci{ 143462306a36Sopenharmony_ci return 0; 143562306a36Sopenharmony_ci} 143662306a36Sopenharmony_ci 143762306a36Sopenharmony_cistatic void tegra124_ulpi_port_disable(struct tegra_xusb_port *port) 143862306a36Sopenharmony_ci{ 143962306a36Sopenharmony_ci} 144062306a36Sopenharmony_ci 144162306a36Sopenharmony_cistatic struct tegra_xusb_lane * 144262306a36Sopenharmony_citegra124_ulpi_port_map(struct tegra_xusb_port *port) 144362306a36Sopenharmony_ci{ 144462306a36Sopenharmony_ci return tegra_xusb_find_lane(port->padctl, "ulpi", port->index); 144562306a36Sopenharmony_ci} 144662306a36Sopenharmony_ci 144762306a36Sopenharmony_cistatic const struct tegra_xusb_port_ops tegra124_ulpi_port_ops = { 144862306a36Sopenharmony_ci .release = tegra_xusb_ulpi_port_release, 144962306a36Sopenharmony_ci .enable = tegra124_ulpi_port_enable, 145062306a36Sopenharmony_ci .disable = tegra124_ulpi_port_disable, 145162306a36Sopenharmony_ci .map = tegra124_ulpi_port_map, 145262306a36Sopenharmony_ci}; 145362306a36Sopenharmony_ci 145462306a36Sopenharmony_cistatic int tegra124_hsic_port_enable(struct tegra_xusb_port *port) 145562306a36Sopenharmony_ci{ 145662306a36Sopenharmony_ci return 0; 145762306a36Sopenharmony_ci} 145862306a36Sopenharmony_ci 145962306a36Sopenharmony_cistatic void tegra124_hsic_port_disable(struct tegra_xusb_port *port) 146062306a36Sopenharmony_ci{ 146162306a36Sopenharmony_ci} 146262306a36Sopenharmony_ci 146362306a36Sopenharmony_cistatic struct tegra_xusb_lane * 146462306a36Sopenharmony_citegra124_hsic_port_map(struct tegra_xusb_port *port) 146562306a36Sopenharmony_ci{ 146662306a36Sopenharmony_ci return tegra_xusb_find_lane(port->padctl, "hsic", port->index); 146762306a36Sopenharmony_ci} 146862306a36Sopenharmony_ci 146962306a36Sopenharmony_cistatic const struct tegra_xusb_port_ops tegra124_hsic_port_ops = { 147062306a36Sopenharmony_ci .release = tegra_xusb_hsic_port_release, 147162306a36Sopenharmony_ci .enable = tegra124_hsic_port_enable, 147262306a36Sopenharmony_ci .disable = tegra124_hsic_port_disable, 147362306a36Sopenharmony_ci .map = tegra124_hsic_port_map, 147462306a36Sopenharmony_ci}; 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_cistatic int tegra124_usb3_port_enable(struct tegra_xusb_port *port) 147762306a36Sopenharmony_ci{ 147862306a36Sopenharmony_ci struct tegra_xusb_usb3_port *usb3 = to_usb3_port(port); 147962306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = port->padctl; 148062306a36Sopenharmony_ci struct tegra_xusb_lane *lane = usb3->base.lane; 148162306a36Sopenharmony_ci unsigned int index = port->index, offset; 148262306a36Sopenharmony_ci u32 value; 148362306a36Sopenharmony_ci 148462306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); 148562306a36Sopenharmony_ci 148662306a36Sopenharmony_ci if (!usb3->internal) 148762306a36Sopenharmony_ci value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index); 148862306a36Sopenharmony_ci else 148962306a36Sopenharmony_ci value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index); 149062306a36Sopenharmony_ci 149162306a36Sopenharmony_ci value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(index); 149262306a36Sopenharmony_ci value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(index, usb3->port); 149362306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); 149462306a36Sopenharmony_ci 149562306a36Sopenharmony_ci /* 149662306a36Sopenharmony_ci * TODO: move this code into the PCIe/SATA PHY ->power_on() callbacks 149762306a36Sopenharmony_ci * and conditionalize based on mux function? This seems to work, but 149862306a36Sopenharmony_ci * might not be the exact proper sequence. 149962306a36Sopenharmony_ci */ 150062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index)); 150162306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_MASK << 150262306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT) | 150362306a36Sopenharmony_ci (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_MASK << 150462306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT) | 150562306a36Sopenharmony_ci (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_MASK << 150662306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT)); 150762306a36Sopenharmony_ci value |= (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_VAL << 150862306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT) | 150962306a36Sopenharmony_ci (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_VAL << 151062306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT) | 151162306a36Sopenharmony_ci (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_VAL << 151262306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT); 151362306a36Sopenharmony_ci 151462306a36Sopenharmony_ci if (usb3->context_saved) { 151562306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK << 151662306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) | 151762306a36Sopenharmony_ci (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK << 151862306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT)); 151962306a36Sopenharmony_ci value |= (usb3->ctle_g << 152062306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) | 152162306a36Sopenharmony_ci (usb3->ctle_z << 152262306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT); 152362306a36Sopenharmony_ci } 152462306a36Sopenharmony_ci 152562306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index)); 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ci value = XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_VAL; 152862306a36Sopenharmony_ci 152962306a36Sopenharmony_ci if (usb3->context_saved) { 153062306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK << 153162306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) | 153262306a36Sopenharmony_ci (XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK << 153362306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT)); 153462306a36Sopenharmony_ci value |= (usb3->tap1 << 153562306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) | 153662306a36Sopenharmony_ci (usb3->amp << 153762306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT); 153862306a36Sopenharmony_ci } 153962306a36Sopenharmony_ci 154062306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(index)); 154162306a36Sopenharmony_ci 154262306a36Sopenharmony_ci if (lane->pad == padctl->pcie) 154362306a36Sopenharmony_ci offset = XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL2(lane->index); 154462306a36Sopenharmony_ci else 154562306a36Sopenharmony_ci offset = XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2; 154662306a36Sopenharmony_ci 154762306a36Sopenharmony_ci value = padctl_readl(padctl, offset); 154862306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_MASK << 154962306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT); 155062306a36Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_VAL << 155162306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT; 155262306a36Sopenharmony_ci padctl_writel(padctl, value, offset); 155362306a36Sopenharmony_ci 155462306a36Sopenharmony_ci if (lane->pad == padctl->pcie) 155562306a36Sopenharmony_ci offset = XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL5(lane->index); 155662306a36Sopenharmony_ci else 155762306a36Sopenharmony_ci offset = XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5; 155862306a36Sopenharmony_ci 155962306a36Sopenharmony_ci value = padctl_readl(padctl, offset); 156062306a36Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL5_RX_QEYE_EN; 156162306a36Sopenharmony_ci padctl_writel(padctl, value, offset); 156262306a36Sopenharmony_ci 156362306a36Sopenharmony_ci /* Enable SATA PHY when SATA lane is used */ 156462306a36Sopenharmony_ci if (lane->pad == padctl->sata) { 156562306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 156662306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_MASK << 156762306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT); 156862306a36Sopenharmony_ci value |= 0x2 << 156962306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT; 157062306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 157162306a36Sopenharmony_ci 157262306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL2); 157362306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_MASK << 157462306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT) | 157562306a36Sopenharmony_ci (XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_MASK << 157662306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT) | 157762306a36Sopenharmony_ci (XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_MASK << 157862306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT) | 157962306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TCLKOUT_EN); 158062306a36Sopenharmony_ci value |= (0x7 << 158162306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT) | 158262306a36Sopenharmony_ci (0x8 << 158362306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT) | 158462306a36Sopenharmony_ci (0x8 << 158562306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT) | 158662306a36Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TXCLKREF_SEL; 158762306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL2); 158862306a36Sopenharmony_ci 158962306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL3); 159062306a36Sopenharmony_ci value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL3_RCAL_BYPASS; 159162306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL3); 159262306a36Sopenharmony_ci } 159362306a36Sopenharmony_ci 159462306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 159562306a36Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(index); 159662306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 159762306a36Sopenharmony_ci 159862306a36Sopenharmony_ci usleep_range(100, 200); 159962306a36Sopenharmony_ci 160062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 160162306a36Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(index); 160262306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_ci usleep_range(100, 200); 160562306a36Sopenharmony_ci 160662306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 160762306a36Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(index); 160862306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 160962306a36Sopenharmony_ci 161062306a36Sopenharmony_ci return 0; 161162306a36Sopenharmony_ci} 161262306a36Sopenharmony_ci 161362306a36Sopenharmony_cistatic void tegra124_usb3_port_disable(struct tegra_xusb_port *port) 161462306a36Sopenharmony_ci{ 161562306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = port->padctl; 161662306a36Sopenharmony_ci u32 value; 161762306a36Sopenharmony_ci 161862306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 161962306a36Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(port->index); 162062306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_ci usleep_range(100, 200); 162362306a36Sopenharmony_ci 162462306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 162562306a36Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(port->index); 162662306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_ci usleep_range(250, 350); 162962306a36Sopenharmony_ci 163062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 163162306a36Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(port->index); 163262306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 163362306a36Sopenharmony_ci 163462306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); 163562306a36Sopenharmony_ci value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(port->index); 163662306a36Sopenharmony_ci value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(port->index, 0x7); 163762306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); 163862306a36Sopenharmony_ci} 163962306a36Sopenharmony_ci 164062306a36Sopenharmony_cistatic const struct tegra_xusb_lane_map tegra124_usb3_map[] = { 164162306a36Sopenharmony_ci { 0, "pcie", 0 }, 164262306a36Sopenharmony_ci { 1, "pcie", 1 }, 164362306a36Sopenharmony_ci { 1, "sata", 0 }, 164462306a36Sopenharmony_ci { 0, NULL, 0 }, 164562306a36Sopenharmony_ci}; 164662306a36Sopenharmony_ci 164762306a36Sopenharmony_cistatic struct tegra_xusb_lane * 164862306a36Sopenharmony_citegra124_usb3_port_map(struct tegra_xusb_port *port) 164962306a36Sopenharmony_ci{ 165062306a36Sopenharmony_ci return tegra_xusb_port_find_lane(port, tegra124_usb3_map, "usb3-ss"); 165162306a36Sopenharmony_ci} 165262306a36Sopenharmony_ci 165362306a36Sopenharmony_cistatic const struct tegra_xusb_port_ops tegra124_usb3_port_ops = { 165462306a36Sopenharmony_ci .release = tegra_xusb_usb3_port_release, 165562306a36Sopenharmony_ci .enable = tegra124_usb3_port_enable, 165662306a36Sopenharmony_ci .disable = tegra124_usb3_port_disable, 165762306a36Sopenharmony_ci .map = tegra124_usb3_port_map, 165862306a36Sopenharmony_ci}; 165962306a36Sopenharmony_ci 166062306a36Sopenharmony_cistatic int 166162306a36Sopenharmony_citegra124_xusb_read_fuse_calibration(struct tegra124_xusb_fuse_calibration *fuse) 166262306a36Sopenharmony_ci{ 166362306a36Sopenharmony_ci unsigned int i; 166462306a36Sopenharmony_ci int err; 166562306a36Sopenharmony_ci u32 value; 166662306a36Sopenharmony_ci 166762306a36Sopenharmony_ci err = tegra_fuse_readl(TEGRA_FUSE_SKU_CALIB_0, &value); 166862306a36Sopenharmony_ci if (err < 0) 166962306a36Sopenharmony_ci return err; 167062306a36Sopenharmony_ci 167162306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(fuse->hs_curr_level); i++) { 167262306a36Sopenharmony_ci fuse->hs_curr_level[i] = 167362306a36Sopenharmony_ci (value >> FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(i)) & 167462306a36Sopenharmony_ci FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK; 167562306a36Sopenharmony_ci } 167662306a36Sopenharmony_ci fuse->hs_iref_cap = 167762306a36Sopenharmony_ci (value >> FUSE_SKU_CALIB_HS_IREF_CAP_SHIFT) & 167862306a36Sopenharmony_ci FUSE_SKU_CALIB_HS_IREF_CAP_MASK; 167962306a36Sopenharmony_ci fuse->hs_term_range_adj = 168062306a36Sopenharmony_ci (value >> FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT) & 168162306a36Sopenharmony_ci FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK; 168262306a36Sopenharmony_ci fuse->hs_squelch_level = 168362306a36Sopenharmony_ci (value >> FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_SHIFT) & 168462306a36Sopenharmony_ci FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_MASK; 168562306a36Sopenharmony_ci 168662306a36Sopenharmony_ci return 0; 168762306a36Sopenharmony_ci} 168862306a36Sopenharmony_ci 168962306a36Sopenharmony_cistatic struct tegra_xusb_padctl * 169062306a36Sopenharmony_citegra124_xusb_padctl_probe(struct device *dev, 169162306a36Sopenharmony_ci const struct tegra_xusb_padctl_soc *soc) 169262306a36Sopenharmony_ci{ 169362306a36Sopenharmony_ci struct tegra124_xusb_padctl *padctl; 169462306a36Sopenharmony_ci int err; 169562306a36Sopenharmony_ci 169662306a36Sopenharmony_ci padctl = devm_kzalloc(dev, sizeof(*padctl), GFP_KERNEL); 169762306a36Sopenharmony_ci if (!padctl) 169862306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 169962306a36Sopenharmony_ci 170062306a36Sopenharmony_ci padctl->base.dev = dev; 170162306a36Sopenharmony_ci padctl->base.soc = soc; 170262306a36Sopenharmony_ci 170362306a36Sopenharmony_ci err = tegra124_xusb_read_fuse_calibration(&padctl->fuse); 170462306a36Sopenharmony_ci if (err < 0) 170562306a36Sopenharmony_ci return ERR_PTR(err); 170662306a36Sopenharmony_ci 170762306a36Sopenharmony_ci return &padctl->base; 170862306a36Sopenharmony_ci} 170962306a36Sopenharmony_ci 171062306a36Sopenharmony_cistatic void tegra124_xusb_padctl_remove(struct tegra_xusb_padctl *padctl) 171162306a36Sopenharmony_ci{ 171262306a36Sopenharmony_ci} 171362306a36Sopenharmony_ci 171462306a36Sopenharmony_cistatic const struct tegra_xusb_padctl_ops tegra124_xusb_padctl_ops = { 171562306a36Sopenharmony_ci .probe = tegra124_xusb_padctl_probe, 171662306a36Sopenharmony_ci .remove = tegra124_xusb_padctl_remove, 171762306a36Sopenharmony_ci .usb3_save_context = tegra124_usb3_save_context, 171862306a36Sopenharmony_ci .hsic_set_idle = tegra124_hsic_set_idle, 171962306a36Sopenharmony_ci}; 172062306a36Sopenharmony_ci 172162306a36Sopenharmony_cistatic const char * const tegra124_xusb_padctl_supply_names[] = { 172262306a36Sopenharmony_ci "avdd-pll-utmip", 172362306a36Sopenharmony_ci "avdd-pll-erefe", 172462306a36Sopenharmony_ci "avdd-pex-pll", 172562306a36Sopenharmony_ci "hvdd-pex-pll-e", 172662306a36Sopenharmony_ci}; 172762306a36Sopenharmony_ci 172862306a36Sopenharmony_ciconst struct tegra_xusb_padctl_soc tegra124_xusb_padctl_soc = { 172962306a36Sopenharmony_ci .num_pads = ARRAY_SIZE(tegra124_pads), 173062306a36Sopenharmony_ci .pads = tegra124_pads, 173162306a36Sopenharmony_ci .ports = { 173262306a36Sopenharmony_ci .usb2 = { 173362306a36Sopenharmony_ci .ops = &tegra124_usb2_port_ops, 173462306a36Sopenharmony_ci .count = 3, 173562306a36Sopenharmony_ci }, 173662306a36Sopenharmony_ci .ulpi = { 173762306a36Sopenharmony_ci .ops = &tegra124_ulpi_port_ops, 173862306a36Sopenharmony_ci .count = 1, 173962306a36Sopenharmony_ci }, 174062306a36Sopenharmony_ci .hsic = { 174162306a36Sopenharmony_ci .ops = &tegra124_hsic_port_ops, 174262306a36Sopenharmony_ci .count = 2, 174362306a36Sopenharmony_ci }, 174462306a36Sopenharmony_ci .usb3 = { 174562306a36Sopenharmony_ci .ops = &tegra124_usb3_port_ops, 174662306a36Sopenharmony_ci .count = 2, 174762306a36Sopenharmony_ci }, 174862306a36Sopenharmony_ci }, 174962306a36Sopenharmony_ci .ops = &tegra124_xusb_padctl_ops, 175062306a36Sopenharmony_ci .supply_names = tegra124_xusb_padctl_supply_names, 175162306a36Sopenharmony_ci .num_supplies = ARRAY_SIZE(tegra124_xusb_padctl_supply_names), 175262306a36Sopenharmony_ci}; 175362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(tegra124_xusb_padctl_soc); 175462306a36Sopenharmony_ci 175562306a36Sopenharmony_ciMODULE_AUTHOR("Thierry Reding <treding@nvidia.com>"); 175662306a36Sopenharmony_ciMODULE_DESCRIPTION("NVIDIA Tegra 124 XUSB Pad Controller driver"); 175762306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 1758