18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/delay.h> 78c2ecf20Sopenharmony_ci#include <linux/io.h> 88c2ecf20Sopenharmony_ci#include <linux/mailbox_client.h> 98c2ecf20Sopenharmony_ci#include <linux/module.h> 108c2ecf20Sopenharmony_ci#include <linux/of.h> 118c2ecf20Sopenharmony_ci#include <linux/phy/phy.h> 128c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 138c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h> 148c2ecf20Sopenharmony_ci#include <linux/reset.h> 158c2ecf20Sopenharmony_ci#include <linux/slab.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <soc/tegra/fuse.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include "xusb.h" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(x) ((x) ? 15 : 0) 228c2ecf20Sopenharmony_ci#define FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK 0x3f 238c2ecf20Sopenharmony_ci#define FUSE_SKU_CALIB_HS_IREF_CAP_SHIFT 13 248c2ecf20Sopenharmony_ci#define FUSE_SKU_CALIB_HS_IREF_CAP_MASK 0x3 258c2ecf20Sopenharmony_ci#define FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_SHIFT 11 268c2ecf20Sopenharmony_ci#define FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_MASK 0x3 278c2ecf20Sopenharmony_ci#define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT 7 288c2ecf20Sopenharmony_ci#define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK 0xf 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP 0x008 318c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(x) ((x) * 4) 328c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_PORT_CAP_MASK 0x3 338c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_DISABLED 0x0 348c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_HOST 0x1 358c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_DEVICE 0x2 368c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_OTG 0x3 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP 0x014 398c2ecf20Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(x) (1 << (((x) * 4) + 3)) 408c2ecf20Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_SHIFT(x) ((x) * 4) 418c2ecf20Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(x) (0x7 << ((x) * 4)) 428c2ecf20Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(x, v) (((v) & 0x7) << ((x) * 4)) 438c2ecf20Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORT_MAP_MASK 0x7 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM 0x01c 468c2ecf20Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26) 478c2ecf20Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25) 488c2ecf20Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24) 498c2ecf20Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(x) (1 << (18 + (x) * 4)) 508c2ecf20Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(x) \ 518c2ecf20Sopenharmony_ci (1 << (17 + (x) * 4)) 528c2ecf20Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(x) (1 << (16 + (x) * 4)) 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040 558c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19) 568c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12) 578c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1) 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044 608c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6) 618c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5) 628c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4) 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(x) (0x058 + (x) * 4) 658c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT 24 668c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_MASK 0xff 678c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_VAL 0x24 688c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT 16 698c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK 0x3f 708c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT 8 718c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK 0x3f 728c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT 8 738c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_MASK 0xffff 748c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_VAL 0xf070 758c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT 4 768c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_MASK 0xf 778c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_VAL 0xf 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(x) (0x068 + (x) * 4) 808c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT 24 818c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK 0x1f 828c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT 16 838c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK 0x7f 848c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_VAL 0x002008ee 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL2(x) ((x) < 2 ? 0x078 + (x) * 4 : \ 878c2ecf20Sopenharmony_ci 0x0f8 + (x) * 4) 888c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT 28 898c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_MASK 0x3 908c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_VAL 0x1 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL5(x) ((x) < 2 ? 0x090 + (x) * 4 : \ 938c2ecf20Sopenharmony_ci 0x11c + (x) * 4) 948c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL5_RX_QEYE_EN (1 << 8) 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL6(x) ((x) < 2 ? 0x098 + (x) * 4 : \ 978c2ecf20Sopenharmony_ci 0x128 + (x) * 4) 988c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT 24 998c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK 0x3f 1008c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_TAP_MASK 0x1f 1018c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_AMP_MASK 0x7f 1028c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT 16 1038c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK 0xff 1048c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_G_Z 0x21 1058c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_TAP 0x32 1068c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_AMP 0x33 1078c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_CTLE_Z 0x48 1088c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_LATCH_G_Z 0xa1 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PADX_CTL0(x) (0x0a0 + (x) * 4) 1118c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI (1 << 21) 1128c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 (1 << 20) 1138c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD (1 << 19) 1148c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT 14 1158c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_MASK 0x3 1168c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_VAL(x) ((x) ? 0x0 : 0x3) 1178c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT 6 1188c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_MASK 0x3f 1198c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_VAL 0x0e 1208c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT 0 1218c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK 0x3f 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PADX_CTL1(x) (0x0ac + (x) * 4) 1248c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT 9 1258c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_MASK 0x3 1268c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT 3 1278c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK 0x7 1288c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR (1 << 2) 1298c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP (1 << 1) 1308c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP (1 << 0) 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0 0x0b8 1338c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD (1 << 12) 1348c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT 2 1358c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK 0x7 1368c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL 0x5 1378c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT 0 1388c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK 0x3 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PADX_CTL0(x) (0x0c0 + (x) * 4) 1418c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT 12 1428c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_MASK 0x7 1438c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT 8 1448c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_MASK 0x7 1458c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT 4 1468c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_MASK 0x7 1478c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT 0 1488c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_MASK 0x7 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PADX_CTL1(x) (0x0c8 + (x) * 4) 1518c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE (1 << 10) 1528c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_RPU_DATA (1 << 9) 1538c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_RPD_STROBE (1 << 8) 1548c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA (1 << 7) 1558c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI (1 << 5) 1568c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX (1 << 4) 1578c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX (1 << 3) 1588c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX (1 << 2) 1598c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN (1 << 0) 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PADX_CTL2(x) (0x0d0 + (x) * 4) 1628c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT 4 1638c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK 0x7 1648c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT 0 1658c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK 0x7 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL 0x0e0 1688c2ecf20Sopenharmony_ci#define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL_STRB_TRIM_MASK 0x1f 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB3_PAD_MUX 0x134 1718c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(x) (1 << (1 + (x))) 1728c2ecf20Sopenharmony_ci#define XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(x) (1 << (6 + (x))) 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138 1758c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27) 1768c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24) 1778c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT 20 1788c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_MASK 0x3 1798c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3) 1808c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1) 1818c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0) 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2 0x13c 1848c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT 20 1858c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_MASK 0xf 1868c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT 16 1878c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_MASK 0xf 1888c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TCLKOUT_EN (1 << 12) 1898c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TXCLKREF_SEL (1 << 4) 1908c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT 0 1918c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_MASK 0x7 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL3 0x140 1948c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_PLL_S0_CTL3_RCAL_BYPASS (1 << 7) 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148 1978c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1) 1988c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0) 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2 0x14c 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5 0x158 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6 0x15c 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_cistruct tegra124_xusb_fuse_calibration { 2078c2ecf20Sopenharmony_ci u32 hs_curr_level[3]; 2088c2ecf20Sopenharmony_ci u32 hs_iref_cap; 2098c2ecf20Sopenharmony_ci u32 hs_term_range_adj; 2108c2ecf20Sopenharmony_ci u32 hs_squelch_level; 2118c2ecf20Sopenharmony_ci}; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_cistruct tegra124_xusb_padctl { 2148c2ecf20Sopenharmony_ci struct tegra_xusb_padctl base; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci struct tegra124_xusb_fuse_calibration fuse; 2178c2ecf20Sopenharmony_ci}; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_cistatic inline struct tegra124_xusb_padctl * 2208c2ecf20Sopenharmony_cito_tegra124_xusb_padctl(struct tegra_xusb_padctl *padctl) 2218c2ecf20Sopenharmony_ci{ 2228c2ecf20Sopenharmony_ci return container_of(padctl, struct tegra124_xusb_padctl, base); 2238c2ecf20Sopenharmony_ci} 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_cistatic int tegra124_xusb_padctl_enable(struct tegra_xusb_padctl *padctl) 2268c2ecf20Sopenharmony_ci{ 2278c2ecf20Sopenharmony_ci u32 value; 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci mutex_lock(&padctl->lock); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci if (padctl->enable++ > 0) 2328c2ecf20Sopenharmony_ci goto out; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 2358c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; 2368c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci usleep_range(100, 200); 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 2418c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; 2428c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci usleep_range(100, 200); 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 2478c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; 2488c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ciout: 2518c2ecf20Sopenharmony_ci mutex_unlock(&padctl->lock); 2528c2ecf20Sopenharmony_ci return 0; 2538c2ecf20Sopenharmony_ci} 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_cistatic int tegra124_xusb_padctl_disable(struct tegra_xusb_padctl *padctl) 2568c2ecf20Sopenharmony_ci{ 2578c2ecf20Sopenharmony_ci u32 value; 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci mutex_lock(&padctl->lock); 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci if (WARN_ON(padctl->enable == 0)) 2628c2ecf20Sopenharmony_ci goto out; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci if (--padctl->enable > 0) 2658c2ecf20Sopenharmony_ci goto out; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 2688c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; 2698c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci usleep_range(100, 200); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 2748c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; 2758c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci usleep_range(100, 200); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 2808c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; 2818c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ciout: 2848c2ecf20Sopenharmony_ci mutex_unlock(&padctl->lock); 2858c2ecf20Sopenharmony_ci return 0; 2868c2ecf20Sopenharmony_ci} 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_cistatic int tegra124_usb3_save_context(struct tegra_xusb_padctl *padctl, 2898c2ecf20Sopenharmony_ci unsigned int index) 2908c2ecf20Sopenharmony_ci{ 2918c2ecf20Sopenharmony_ci struct tegra_xusb_usb3_port *port; 2928c2ecf20Sopenharmony_ci struct tegra_xusb_lane *lane; 2938c2ecf20Sopenharmony_ci u32 value, offset; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci port = tegra_xusb_find_usb3_port(padctl, index); 2968c2ecf20Sopenharmony_ci if (!port) 2978c2ecf20Sopenharmony_ci return -ENODEV; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci port->context_saved = true; 3008c2ecf20Sopenharmony_ci lane = port->base.lane; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci if (lane->pad == padctl->pcie) 3038c2ecf20Sopenharmony_ci offset = XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL6(lane->index); 3048c2ecf20Sopenharmony_ci else 3058c2ecf20Sopenharmony_ci offset = XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci value = padctl_readl(padctl, offset); 3088c2ecf20Sopenharmony_ci value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK << 3098c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT); 3108c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_TAP << 3118c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT; 3128c2ecf20Sopenharmony_ci padctl_writel(padctl, value, offset); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci value = padctl_readl(padctl, offset) >> 3158c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT; 3168c2ecf20Sopenharmony_ci port->tap1 = value & XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_TAP_MASK; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci value = padctl_readl(padctl, offset); 3198c2ecf20Sopenharmony_ci value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK << 3208c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT); 3218c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_AMP << 3228c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT; 3238c2ecf20Sopenharmony_ci padctl_writel(padctl, value, offset); 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci value = padctl_readl(padctl, offset) >> 3268c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT; 3278c2ecf20Sopenharmony_ci port->amp = value & XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_AMP_MASK; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(index)); 3308c2ecf20Sopenharmony_ci value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK << 3318c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) | 3328c2ecf20Sopenharmony_ci (XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK << 3338c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT)); 3348c2ecf20Sopenharmony_ci value |= (port->tap1 << 3358c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) | 3368c2ecf20Sopenharmony_ci (port->amp << 3378c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT); 3388c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(index)); 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci value = padctl_readl(padctl, offset); 3418c2ecf20Sopenharmony_ci value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK << 3428c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT); 3438c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_LATCH_G_Z << 3448c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT; 3458c2ecf20Sopenharmony_ci padctl_writel(padctl, value, offset); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci value = padctl_readl(padctl, offset); 3488c2ecf20Sopenharmony_ci value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK << 3498c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT); 3508c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_G_Z << 3518c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT; 3528c2ecf20Sopenharmony_ci padctl_writel(padctl, value, offset); 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci value = padctl_readl(padctl, offset) >> 3558c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT; 3568c2ecf20Sopenharmony_ci port->ctle_g = value & 3578c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci value = padctl_readl(padctl, offset); 3608c2ecf20Sopenharmony_ci value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK << 3618c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT); 3628c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_CTLE_Z << 3638c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT; 3648c2ecf20Sopenharmony_ci padctl_writel(padctl, value, offset); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci value = padctl_readl(padctl, offset) >> 3678c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT; 3688c2ecf20Sopenharmony_ci port->ctle_z = value & 3698c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index)); 3728c2ecf20Sopenharmony_ci value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK << 3738c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) | 3748c2ecf20Sopenharmony_ci (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK << 3758c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT)); 3768c2ecf20Sopenharmony_ci value |= (port->ctle_g << 3778c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) | 3788c2ecf20Sopenharmony_ci (port->ctle_z << 3798c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT); 3808c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index)); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci return 0; 3838c2ecf20Sopenharmony_ci} 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_cistatic int tegra124_hsic_set_idle(struct tegra_xusb_padctl *padctl, 3868c2ecf20Sopenharmony_ci unsigned int index, bool idle) 3878c2ecf20Sopenharmony_ci{ 3888c2ecf20Sopenharmony_ci u32 value; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci if (idle) 3938c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA | 3948c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE; 3958c2ecf20Sopenharmony_ci else 3968c2ecf20Sopenharmony_ci value &= ~(XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA | 3978c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE); 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci return 0; 4028c2ecf20Sopenharmony_ci} 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci#define TEGRA124_LANE(_name, _offset, _shift, _mask, _type) \ 4058c2ecf20Sopenharmony_ci { \ 4068c2ecf20Sopenharmony_ci .name = _name, \ 4078c2ecf20Sopenharmony_ci .offset = _offset, \ 4088c2ecf20Sopenharmony_ci .shift = _shift, \ 4098c2ecf20Sopenharmony_ci .mask = _mask, \ 4108c2ecf20Sopenharmony_ci .num_funcs = ARRAY_SIZE(tegra124_##_type##_functions), \ 4118c2ecf20Sopenharmony_ci .funcs = tegra124_##_type##_functions, \ 4128c2ecf20Sopenharmony_ci } 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_cistatic const char * const tegra124_usb2_functions[] = { 4158c2ecf20Sopenharmony_ci "snps", 4168c2ecf20Sopenharmony_ci "xusb", 4178c2ecf20Sopenharmony_ci "uart", 4188c2ecf20Sopenharmony_ci}; 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra124_usb2_lanes[] = { 4218c2ecf20Sopenharmony_ci TEGRA124_LANE("usb2-0", 0x004, 0, 0x3, usb2), 4228c2ecf20Sopenharmony_ci TEGRA124_LANE("usb2-1", 0x004, 2, 0x3, usb2), 4238c2ecf20Sopenharmony_ci TEGRA124_LANE("usb2-2", 0x004, 4, 0x3, usb2), 4248c2ecf20Sopenharmony_ci}; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_cistatic struct tegra_xusb_lane * 4278c2ecf20Sopenharmony_citegra124_usb2_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 4288c2ecf20Sopenharmony_ci unsigned int index) 4298c2ecf20Sopenharmony_ci{ 4308c2ecf20Sopenharmony_ci struct tegra_xusb_usb2_lane *usb2; 4318c2ecf20Sopenharmony_ci int err; 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL); 4348c2ecf20Sopenharmony_ci if (!usb2) 4358c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&usb2->base.list); 4388c2ecf20Sopenharmony_ci usb2->base.soc = &pad->soc->lanes[index]; 4398c2ecf20Sopenharmony_ci usb2->base.index = index; 4408c2ecf20Sopenharmony_ci usb2->base.pad = pad; 4418c2ecf20Sopenharmony_ci usb2->base.np = np; 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci err = tegra_xusb_lane_parse_dt(&usb2->base, np); 4448c2ecf20Sopenharmony_ci if (err < 0) { 4458c2ecf20Sopenharmony_ci kfree(usb2); 4468c2ecf20Sopenharmony_ci return ERR_PTR(err); 4478c2ecf20Sopenharmony_ci } 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci return &usb2->base; 4508c2ecf20Sopenharmony_ci} 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_cistatic void tegra124_usb2_lane_remove(struct tegra_xusb_lane *lane) 4538c2ecf20Sopenharmony_ci{ 4548c2ecf20Sopenharmony_ci struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane); 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci kfree(usb2); 4578c2ecf20Sopenharmony_ci} 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra124_usb2_lane_ops = { 4608c2ecf20Sopenharmony_ci .probe = tegra124_usb2_lane_probe, 4618c2ecf20Sopenharmony_ci .remove = tegra124_usb2_lane_remove, 4628c2ecf20Sopenharmony_ci}; 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_cistatic int tegra124_usb2_phy_init(struct phy *phy) 4658c2ecf20Sopenharmony_ci{ 4668c2ecf20Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci return tegra124_xusb_padctl_enable(lane->pad->padctl); 4698c2ecf20Sopenharmony_ci} 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_cistatic int tegra124_usb2_phy_exit(struct phy *phy) 4728c2ecf20Sopenharmony_ci{ 4738c2ecf20Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci return tegra124_xusb_padctl_disable(lane->pad->padctl); 4768c2ecf20Sopenharmony_ci} 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_cistatic int tegra124_usb2_phy_power_on(struct phy *phy) 4798c2ecf20Sopenharmony_ci{ 4808c2ecf20Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 4818c2ecf20Sopenharmony_ci struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane); 4828c2ecf20Sopenharmony_ci struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad); 4838c2ecf20Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 4848c2ecf20Sopenharmony_ci struct tegra124_xusb_padctl *priv; 4858c2ecf20Sopenharmony_ci struct tegra_xusb_usb2_port *port; 4868c2ecf20Sopenharmony_ci unsigned int index = lane->index; 4878c2ecf20Sopenharmony_ci u32 value; 4888c2ecf20Sopenharmony_ci int err; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci port = tegra_xusb_find_usb2_port(padctl, index); 4918c2ecf20Sopenharmony_ci if (!port) { 4928c2ecf20Sopenharmony_ci dev_err(&phy->dev, "no port found for USB2 lane %u\n", index); 4938c2ecf20Sopenharmony_ci return -ENODEV; 4948c2ecf20Sopenharmony_ci } 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci priv = to_tegra124_xusb_padctl(padctl); 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 4998c2ecf20Sopenharmony_ci value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK << 5008c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) | 5018c2ecf20Sopenharmony_ci (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK << 5028c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT)); 5038c2ecf20Sopenharmony_ci value |= (priv->fuse.hs_squelch_level << 5048c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) | 5058c2ecf20Sopenharmony_ci (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL << 5068c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT); 5078c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_PORT_CAP); 5108c2ecf20Sopenharmony_ci value &= ~(XUSB_PADCTL_USB2_PORT_CAP_PORT_CAP_MASK << 5118c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(index)); 5128c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_USB2_PORT_CAP_HOST << 5138c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(index); 5148c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_PORT_CAP); 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index)); 5178c2ecf20Sopenharmony_ci value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK << 5188c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT) | 5198c2ecf20Sopenharmony_ci (XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_MASK << 5208c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT) | 5218c2ecf20Sopenharmony_ci (XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_MASK << 5228c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT) | 5238c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD | 5248c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 | 5258c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI); 5268c2ecf20Sopenharmony_ci value |= (priv->fuse.hs_curr_level[index] + 5278c2ecf20Sopenharmony_ci usb2->hs_curr_level_offset) << 5288c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT; 5298c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_VAL << 5308c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT; 5318c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_VAL(index) << 5328c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT; 5338c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index)); 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index)); 5368c2ecf20Sopenharmony_ci value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK << 5378c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) | 5388c2ecf20Sopenharmony_ci (XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_MASK << 5398c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT) | 5408c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR | 5418c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP | 5428c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP); 5438c2ecf20Sopenharmony_ci value |= (priv->fuse.hs_term_range_adj << 5448c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) | 5458c2ecf20Sopenharmony_ci (priv->fuse.hs_iref_cap << 5468c2ecf20Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT); 5478c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index)); 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci err = regulator_enable(port->supply); 5508c2ecf20Sopenharmony_ci if (err) 5518c2ecf20Sopenharmony_ci return err; 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci mutex_lock(&pad->lock); 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci if (pad->enable++ > 0) 5568c2ecf20Sopenharmony_ci goto out; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 5598c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD; 5608c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ciout: 5638c2ecf20Sopenharmony_ci mutex_unlock(&pad->lock); 5648c2ecf20Sopenharmony_ci return 0; 5658c2ecf20Sopenharmony_ci} 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_cistatic int tegra124_usb2_phy_power_off(struct phy *phy) 5688c2ecf20Sopenharmony_ci{ 5698c2ecf20Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 5708c2ecf20Sopenharmony_ci struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad); 5718c2ecf20Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 5728c2ecf20Sopenharmony_ci struct tegra_xusb_usb2_port *port; 5738c2ecf20Sopenharmony_ci u32 value; 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci port = tegra_xusb_find_usb2_port(padctl, lane->index); 5768c2ecf20Sopenharmony_ci if (!port) { 5778c2ecf20Sopenharmony_ci dev_err(&phy->dev, "no port found for USB2 lane %u\n", 5788c2ecf20Sopenharmony_ci lane->index); 5798c2ecf20Sopenharmony_ci return -ENODEV; 5808c2ecf20Sopenharmony_ci } 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci mutex_lock(&pad->lock); 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci if (WARN_ON(pad->enable == 0)) 5858c2ecf20Sopenharmony_ci goto out; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci if (--pad->enable > 0) 5888c2ecf20Sopenharmony_ci goto out; 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 5918c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD; 5928c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ciout: 5958c2ecf20Sopenharmony_ci regulator_disable(port->supply); 5968c2ecf20Sopenharmony_ci mutex_unlock(&pad->lock); 5978c2ecf20Sopenharmony_ci return 0; 5988c2ecf20Sopenharmony_ci} 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_cistatic const struct phy_ops tegra124_usb2_phy_ops = { 6018c2ecf20Sopenharmony_ci .init = tegra124_usb2_phy_init, 6028c2ecf20Sopenharmony_ci .exit = tegra124_usb2_phy_exit, 6038c2ecf20Sopenharmony_ci .power_on = tegra124_usb2_phy_power_on, 6048c2ecf20Sopenharmony_ci .power_off = tegra124_usb2_phy_power_off, 6058c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 6068c2ecf20Sopenharmony_ci}; 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_cistatic struct tegra_xusb_pad * 6098c2ecf20Sopenharmony_citegra124_usb2_pad_probe(struct tegra_xusb_padctl *padctl, 6108c2ecf20Sopenharmony_ci const struct tegra_xusb_pad_soc *soc, 6118c2ecf20Sopenharmony_ci struct device_node *np) 6128c2ecf20Sopenharmony_ci{ 6138c2ecf20Sopenharmony_ci struct tegra_xusb_usb2_pad *usb2; 6148c2ecf20Sopenharmony_ci struct tegra_xusb_pad *pad; 6158c2ecf20Sopenharmony_ci int err; 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL); 6188c2ecf20Sopenharmony_ci if (!usb2) 6198c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci mutex_init(&usb2->lock); 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci pad = &usb2->base; 6248c2ecf20Sopenharmony_ci pad->ops = &tegra124_usb2_lane_ops; 6258c2ecf20Sopenharmony_ci pad->soc = soc; 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci err = tegra_xusb_pad_init(pad, padctl, np); 6288c2ecf20Sopenharmony_ci if (err < 0) { 6298c2ecf20Sopenharmony_ci kfree(usb2); 6308c2ecf20Sopenharmony_ci goto out; 6318c2ecf20Sopenharmony_ci } 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci err = tegra_xusb_pad_register(pad, &tegra124_usb2_phy_ops); 6348c2ecf20Sopenharmony_ci if (err < 0) 6358c2ecf20Sopenharmony_ci goto unregister; 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci dev_set_drvdata(&pad->dev, pad); 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci return pad; 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ciunregister: 6428c2ecf20Sopenharmony_ci device_unregister(&pad->dev); 6438c2ecf20Sopenharmony_ciout: 6448c2ecf20Sopenharmony_ci return ERR_PTR(err); 6458c2ecf20Sopenharmony_ci} 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_cistatic void tegra124_usb2_pad_remove(struct tegra_xusb_pad *pad) 6488c2ecf20Sopenharmony_ci{ 6498c2ecf20Sopenharmony_ci struct tegra_xusb_usb2_pad *usb2 = to_usb2_pad(pad); 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci kfree(usb2); 6528c2ecf20Sopenharmony_ci} 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra124_usb2_ops = { 6558c2ecf20Sopenharmony_ci .probe = tegra124_usb2_pad_probe, 6568c2ecf20Sopenharmony_ci .remove = tegra124_usb2_pad_remove, 6578c2ecf20Sopenharmony_ci}; 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra124_usb2_pad = { 6608c2ecf20Sopenharmony_ci .name = "usb2", 6618c2ecf20Sopenharmony_ci .num_lanes = ARRAY_SIZE(tegra124_usb2_lanes), 6628c2ecf20Sopenharmony_ci .lanes = tegra124_usb2_lanes, 6638c2ecf20Sopenharmony_ci .ops = &tegra124_usb2_ops, 6648c2ecf20Sopenharmony_ci}; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_cistatic const char * const tegra124_ulpi_functions[] = { 6678c2ecf20Sopenharmony_ci "snps", 6688c2ecf20Sopenharmony_ci "xusb", 6698c2ecf20Sopenharmony_ci}; 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra124_ulpi_lanes[] = { 6728c2ecf20Sopenharmony_ci TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, ulpi), 6738c2ecf20Sopenharmony_ci}; 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_cistatic struct tegra_xusb_lane * 6768c2ecf20Sopenharmony_citegra124_ulpi_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 6778c2ecf20Sopenharmony_ci unsigned int index) 6788c2ecf20Sopenharmony_ci{ 6798c2ecf20Sopenharmony_ci struct tegra_xusb_ulpi_lane *ulpi; 6808c2ecf20Sopenharmony_ci int err; 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci ulpi = kzalloc(sizeof(*ulpi), GFP_KERNEL); 6838c2ecf20Sopenharmony_ci if (!ulpi) 6848c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ulpi->base.list); 6878c2ecf20Sopenharmony_ci ulpi->base.soc = &pad->soc->lanes[index]; 6888c2ecf20Sopenharmony_ci ulpi->base.index = index; 6898c2ecf20Sopenharmony_ci ulpi->base.pad = pad; 6908c2ecf20Sopenharmony_ci ulpi->base.np = np; 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci err = tegra_xusb_lane_parse_dt(&ulpi->base, np); 6938c2ecf20Sopenharmony_ci if (err < 0) { 6948c2ecf20Sopenharmony_ci kfree(ulpi); 6958c2ecf20Sopenharmony_ci return ERR_PTR(err); 6968c2ecf20Sopenharmony_ci } 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci return &ulpi->base; 6998c2ecf20Sopenharmony_ci} 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_cistatic void tegra124_ulpi_lane_remove(struct tegra_xusb_lane *lane) 7028c2ecf20Sopenharmony_ci{ 7038c2ecf20Sopenharmony_ci struct tegra_xusb_ulpi_lane *ulpi = to_ulpi_lane(lane); 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci kfree(ulpi); 7068c2ecf20Sopenharmony_ci} 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra124_ulpi_lane_ops = { 7098c2ecf20Sopenharmony_ci .probe = tegra124_ulpi_lane_probe, 7108c2ecf20Sopenharmony_ci .remove = tegra124_ulpi_lane_remove, 7118c2ecf20Sopenharmony_ci}; 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_cistatic int tegra124_ulpi_phy_init(struct phy *phy) 7148c2ecf20Sopenharmony_ci{ 7158c2ecf20Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci return tegra124_xusb_padctl_enable(lane->pad->padctl); 7188c2ecf20Sopenharmony_ci} 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_cistatic int tegra124_ulpi_phy_exit(struct phy *phy) 7218c2ecf20Sopenharmony_ci{ 7228c2ecf20Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci return tegra124_xusb_padctl_disable(lane->pad->padctl); 7258c2ecf20Sopenharmony_ci} 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_cistatic int tegra124_ulpi_phy_power_on(struct phy *phy) 7288c2ecf20Sopenharmony_ci{ 7298c2ecf20Sopenharmony_ci return 0; 7308c2ecf20Sopenharmony_ci} 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_cistatic int tegra124_ulpi_phy_power_off(struct phy *phy) 7338c2ecf20Sopenharmony_ci{ 7348c2ecf20Sopenharmony_ci return 0; 7358c2ecf20Sopenharmony_ci} 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_cistatic const struct phy_ops tegra124_ulpi_phy_ops = { 7388c2ecf20Sopenharmony_ci .init = tegra124_ulpi_phy_init, 7398c2ecf20Sopenharmony_ci .exit = tegra124_ulpi_phy_exit, 7408c2ecf20Sopenharmony_ci .power_on = tegra124_ulpi_phy_power_on, 7418c2ecf20Sopenharmony_ci .power_off = tegra124_ulpi_phy_power_off, 7428c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 7438c2ecf20Sopenharmony_ci}; 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_cistatic struct tegra_xusb_pad * 7468c2ecf20Sopenharmony_citegra124_ulpi_pad_probe(struct tegra_xusb_padctl *padctl, 7478c2ecf20Sopenharmony_ci const struct tegra_xusb_pad_soc *soc, 7488c2ecf20Sopenharmony_ci struct device_node *np) 7498c2ecf20Sopenharmony_ci{ 7508c2ecf20Sopenharmony_ci struct tegra_xusb_ulpi_pad *ulpi; 7518c2ecf20Sopenharmony_ci struct tegra_xusb_pad *pad; 7528c2ecf20Sopenharmony_ci int err; 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci ulpi = kzalloc(sizeof(*ulpi), GFP_KERNEL); 7558c2ecf20Sopenharmony_ci if (!ulpi) 7568c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci pad = &ulpi->base; 7598c2ecf20Sopenharmony_ci pad->ops = &tegra124_ulpi_lane_ops; 7608c2ecf20Sopenharmony_ci pad->soc = soc; 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci err = tegra_xusb_pad_init(pad, padctl, np); 7638c2ecf20Sopenharmony_ci if (err < 0) { 7648c2ecf20Sopenharmony_ci kfree(ulpi); 7658c2ecf20Sopenharmony_ci goto out; 7668c2ecf20Sopenharmony_ci } 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_ci err = tegra_xusb_pad_register(pad, &tegra124_ulpi_phy_ops); 7698c2ecf20Sopenharmony_ci if (err < 0) 7708c2ecf20Sopenharmony_ci goto unregister; 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci dev_set_drvdata(&pad->dev, pad); 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci return pad; 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ciunregister: 7778c2ecf20Sopenharmony_ci device_unregister(&pad->dev); 7788c2ecf20Sopenharmony_ciout: 7798c2ecf20Sopenharmony_ci return ERR_PTR(err); 7808c2ecf20Sopenharmony_ci} 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_cistatic void tegra124_ulpi_pad_remove(struct tegra_xusb_pad *pad) 7838c2ecf20Sopenharmony_ci{ 7848c2ecf20Sopenharmony_ci struct tegra_xusb_ulpi_pad *ulpi = to_ulpi_pad(pad); 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci kfree(ulpi); 7878c2ecf20Sopenharmony_ci} 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra124_ulpi_ops = { 7908c2ecf20Sopenharmony_ci .probe = tegra124_ulpi_pad_probe, 7918c2ecf20Sopenharmony_ci .remove = tegra124_ulpi_pad_remove, 7928c2ecf20Sopenharmony_ci}; 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra124_ulpi_pad = { 7958c2ecf20Sopenharmony_ci .name = "ulpi", 7968c2ecf20Sopenharmony_ci .num_lanes = ARRAY_SIZE(tegra124_ulpi_lanes), 7978c2ecf20Sopenharmony_ci .lanes = tegra124_ulpi_lanes, 7988c2ecf20Sopenharmony_ci .ops = &tegra124_ulpi_ops, 7998c2ecf20Sopenharmony_ci}; 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_cistatic const char * const tegra124_hsic_functions[] = { 8028c2ecf20Sopenharmony_ci "snps", 8038c2ecf20Sopenharmony_ci "xusb", 8048c2ecf20Sopenharmony_ci}; 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra124_hsic_lanes[] = { 8078c2ecf20Sopenharmony_ci TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, hsic), 8088c2ecf20Sopenharmony_ci TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, hsic), 8098c2ecf20Sopenharmony_ci}; 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_cistatic struct tegra_xusb_lane * 8128c2ecf20Sopenharmony_citegra124_hsic_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 8138c2ecf20Sopenharmony_ci unsigned int index) 8148c2ecf20Sopenharmony_ci{ 8158c2ecf20Sopenharmony_ci struct tegra_xusb_hsic_lane *hsic; 8168c2ecf20Sopenharmony_ci int err; 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci hsic = kzalloc(sizeof(*hsic), GFP_KERNEL); 8198c2ecf20Sopenharmony_ci if (!hsic) 8208c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hsic->base.list); 8238c2ecf20Sopenharmony_ci hsic->base.soc = &pad->soc->lanes[index]; 8248c2ecf20Sopenharmony_ci hsic->base.index = index; 8258c2ecf20Sopenharmony_ci hsic->base.pad = pad; 8268c2ecf20Sopenharmony_ci hsic->base.np = np; 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci err = tegra_xusb_lane_parse_dt(&hsic->base, np); 8298c2ecf20Sopenharmony_ci if (err < 0) { 8308c2ecf20Sopenharmony_ci kfree(hsic); 8318c2ecf20Sopenharmony_ci return ERR_PTR(err); 8328c2ecf20Sopenharmony_ci } 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci return &hsic->base; 8358c2ecf20Sopenharmony_ci} 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_cistatic void tegra124_hsic_lane_remove(struct tegra_xusb_lane *lane) 8388c2ecf20Sopenharmony_ci{ 8398c2ecf20Sopenharmony_ci struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane); 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci kfree(hsic); 8428c2ecf20Sopenharmony_ci} 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra124_hsic_lane_ops = { 8458c2ecf20Sopenharmony_ci .probe = tegra124_hsic_lane_probe, 8468c2ecf20Sopenharmony_ci .remove = tegra124_hsic_lane_remove, 8478c2ecf20Sopenharmony_ci}; 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_cistatic int tegra124_hsic_phy_init(struct phy *phy) 8508c2ecf20Sopenharmony_ci{ 8518c2ecf20Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci return tegra124_xusb_padctl_enable(lane->pad->padctl); 8548c2ecf20Sopenharmony_ci} 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_cistatic int tegra124_hsic_phy_exit(struct phy *phy) 8578c2ecf20Sopenharmony_ci{ 8588c2ecf20Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci return tegra124_xusb_padctl_disable(lane->pad->padctl); 8618c2ecf20Sopenharmony_ci} 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_cistatic int tegra124_hsic_phy_power_on(struct phy *phy) 8648c2ecf20Sopenharmony_ci{ 8658c2ecf20Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 8668c2ecf20Sopenharmony_ci struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane); 8678c2ecf20Sopenharmony_ci struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad); 8688c2ecf20Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 8698c2ecf20Sopenharmony_ci unsigned int index = lane->index; 8708c2ecf20Sopenharmony_ci u32 value; 8718c2ecf20Sopenharmony_ci int err; 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci err = regulator_enable(pad->supply); 8748c2ecf20Sopenharmony_ci if (err) 8758c2ecf20Sopenharmony_ci return err; 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci padctl_writel(padctl, hsic->strobe_trim, 8788c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL); 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci if (hsic->auto_term) 8838c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN; 8848c2ecf20Sopenharmony_ci else 8858c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN; 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(index)); 8908c2ecf20Sopenharmony_ci value &= ~((XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_MASK << 8918c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT) | 8928c2ecf20Sopenharmony_ci (XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_MASK << 8938c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT) | 8948c2ecf20Sopenharmony_ci (XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_MASK << 8958c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT) | 8968c2ecf20Sopenharmony_ci (XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_MASK << 8978c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT)); 8988c2ecf20Sopenharmony_ci value |= (hsic->tx_rtune_n << 8998c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT) | 9008c2ecf20Sopenharmony_ci (hsic->tx_rtune_p << 9018c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT) | 9028c2ecf20Sopenharmony_ci (hsic->tx_rslew_n << 9038c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT) | 9048c2ecf20Sopenharmony_ci (hsic->tx_rslew_p << 9058c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT); 9068c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL0(index)); 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL2(index)); 9098c2ecf20Sopenharmony_ci value &= ~((XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK << 9108c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) | 9118c2ecf20Sopenharmony_ci (XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK << 9128c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT)); 9138c2ecf20Sopenharmony_ci value |= (hsic->rx_strobe_trim << 9148c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) | 9158c2ecf20Sopenharmony_ci (hsic->rx_data_trim << 9168c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT); 9178c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL2(index)); 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 9208c2ecf20Sopenharmony_ci value &= ~(XUSB_PADCTL_HSIC_PAD_CTL1_RPD_STROBE | 9218c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_RPU_DATA | 9228c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX | 9238c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI | 9248c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX | 9258c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX); 9268c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA | 9278c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE; 9288c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_ci return 0; 9318c2ecf20Sopenharmony_ci} 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_cistatic int tegra124_hsic_phy_power_off(struct phy *phy) 9348c2ecf20Sopenharmony_ci{ 9358c2ecf20Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 9368c2ecf20Sopenharmony_ci struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad); 9378c2ecf20Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 9388c2ecf20Sopenharmony_ci unsigned int index = lane->index; 9398c2ecf20Sopenharmony_ci u32 value; 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 9428c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX | 9438c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI | 9448c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX | 9458c2ecf20Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX; 9468c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_ci regulator_disable(pad->supply); 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci return 0; 9518c2ecf20Sopenharmony_ci} 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_cistatic const struct phy_ops tegra124_hsic_phy_ops = { 9548c2ecf20Sopenharmony_ci .init = tegra124_hsic_phy_init, 9558c2ecf20Sopenharmony_ci .exit = tegra124_hsic_phy_exit, 9568c2ecf20Sopenharmony_ci .power_on = tegra124_hsic_phy_power_on, 9578c2ecf20Sopenharmony_ci .power_off = tegra124_hsic_phy_power_off, 9588c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 9598c2ecf20Sopenharmony_ci}; 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_cistatic struct tegra_xusb_pad * 9628c2ecf20Sopenharmony_citegra124_hsic_pad_probe(struct tegra_xusb_padctl *padctl, 9638c2ecf20Sopenharmony_ci const struct tegra_xusb_pad_soc *soc, 9648c2ecf20Sopenharmony_ci struct device_node *np) 9658c2ecf20Sopenharmony_ci{ 9668c2ecf20Sopenharmony_ci struct tegra_xusb_hsic_pad *hsic; 9678c2ecf20Sopenharmony_ci struct tegra_xusb_pad *pad; 9688c2ecf20Sopenharmony_ci int err; 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci hsic = kzalloc(sizeof(*hsic), GFP_KERNEL); 9718c2ecf20Sopenharmony_ci if (!hsic) 9728c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci pad = &hsic->base; 9758c2ecf20Sopenharmony_ci pad->ops = &tegra124_hsic_lane_ops; 9768c2ecf20Sopenharmony_ci pad->soc = soc; 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci err = tegra_xusb_pad_init(pad, padctl, np); 9798c2ecf20Sopenharmony_ci if (err < 0) { 9808c2ecf20Sopenharmony_ci kfree(hsic); 9818c2ecf20Sopenharmony_ci goto out; 9828c2ecf20Sopenharmony_ci } 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci err = tegra_xusb_pad_register(pad, &tegra124_hsic_phy_ops); 9858c2ecf20Sopenharmony_ci if (err < 0) 9868c2ecf20Sopenharmony_ci goto unregister; 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci dev_set_drvdata(&pad->dev, pad); 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci return pad; 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ciunregister: 9938c2ecf20Sopenharmony_ci device_unregister(&pad->dev); 9948c2ecf20Sopenharmony_ciout: 9958c2ecf20Sopenharmony_ci return ERR_PTR(err); 9968c2ecf20Sopenharmony_ci} 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_cistatic void tegra124_hsic_pad_remove(struct tegra_xusb_pad *pad) 9998c2ecf20Sopenharmony_ci{ 10008c2ecf20Sopenharmony_ci struct tegra_xusb_hsic_pad *hsic = to_hsic_pad(pad); 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci kfree(hsic); 10038c2ecf20Sopenharmony_ci} 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra124_hsic_ops = { 10068c2ecf20Sopenharmony_ci .probe = tegra124_hsic_pad_probe, 10078c2ecf20Sopenharmony_ci .remove = tegra124_hsic_pad_remove, 10088c2ecf20Sopenharmony_ci}; 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra124_hsic_pad = { 10118c2ecf20Sopenharmony_ci .name = "hsic", 10128c2ecf20Sopenharmony_ci .num_lanes = ARRAY_SIZE(tegra124_hsic_lanes), 10138c2ecf20Sopenharmony_ci .lanes = tegra124_hsic_lanes, 10148c2ecf20Sopenharmony_ci .ops = &tegra124_hsic_ops, 10158c2ecf20Sopenharmony_ci}; 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_cistatic const char * const tegra124_pcie_functions[] = { 10188c2ecf20Sopenharmony_ci "pcie", 10198c2ecf20Sopenharmony_ci "usb3-ss", 10208c2ecf20Sopenharmony_ci "sata", 10218c2ecf20Sopenharmony_ci}; 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra124_pcie_lanes[] = { 10248c2ecf20Sopenharmony_ci TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, pcie), 10258c2ecf20Sopenharmony_ci TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, pcie), 10268c2ecf20Sopenharmony_ci TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, pcie), 10278c2ecf20Sopenharmony_ci TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, pcie), 10288c2ecf20Sopenharmony_ci TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, pcie), 10298c2ecf20Sopenharmony_ci}; 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_cistatic struct tegra_xusb_lane * 10328c2ecf20Sopenharmony_citegra124_pcie_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 10338c2ecf20Sopenharmony_ci unsigned int index) 10348c2ecf20Sopenharmony_ci{ 10358c2ecf20Sopenharmony_ci struct tegra_xusb_pcie_lane *pcie; 10368c2ecf20Sopenharmony_ci int err; 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci pcie = kzalloc(sizeof(*pcie), GFP_KERNEL); 10398c2ecf20Sopenharmony_ci if (!pcie) 10408c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&pcie->base.list); 10438c2ecf20Sopenharmony_ci pcie->base.soc = &pad->soc->lanes[index]; 10448c2ecf20Sopenharmony_ci pcie->base.index = index; 10458c2ecf20Sopenharmony_ci pcie->base.pad = pad; 10468c2ecf20Sopenharmony_ci pcie->base.np = np; 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ci err = tegra_xusb_lane_parse_dt(&pcie->base, np); 10498c2ecf20Sopenharmony_ci if (err < 0) { 10508c2ecf20Sopenharmony_ci kfree(pcie); 10518c2ecf20Sopenharmony_ci return ERR_PTR(err); 10528c2ecf20Sopenharmony_ci } 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci return &pcie->base; 10558c2ecf20Sopenharmony_ci} 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_cistatic void tegra124_pcie_lane_remove(struct tegra_xusb_lane *lane) 10588c2ecf20Sopenharmony_ci{ 10598c2ecf20Sopenharmony_ci struct tegra_xusb_pcie_lane *pcie = to_pcie_lane(lane); 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci kfree(pcie); 10628c2ecf20Sopenharmony_ci} 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra124_pcie_lane_ops = { 10658c2ecf20Sopenharmony_ci .probe = tegra124_pcie_lane_probe, 10668c2ecf20Sopenharmony_ci .remove = tegra124_pcie_lane_remove, 10678c2ecf20Sopenharmony_ci}; 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_cistatic int tegra124_pcie_phy_init(struct phy *phy) 10708c2ecf20Sopenharmony_ci{ 10718c2ecf20Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 10728c2ecf20Sopenharmony_ci 10738c2ecf20Sopenharmony_ci return tegra124_xusb_padctl_enable(lane->pad->padctl); 10748c2ecf20Sopenharmony_ci} 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_cistatic int tegra124_pcie_phy_exit(struct phy *phy) 10778c2ecf20Sopenharmony_ci{ 10788c2ecf20Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci return tegra124_xusb_padctl_disable(lane->pad->padctl); 10818c2ecf20Sopenharmony_ci} 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_cistatic int tegra124_pcie_phy_power_on(struct phy *phy) 10848c2ecf20Sopenharmony_ci{ 10858c2ecf20Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 10868c2ecf20Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 10878c2ecf20Sopenharmony_ci unsigned long timeout; 10888c2ecf20Sopenharmony_ci int err = -ETIMEDOUT; 10898c2ecf20Sopenharmony_ci u32 value; 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); 10928c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK; 10938c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); 10968c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN | 10978c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN | 10988c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL; 10998c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); 11028c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST; 11038c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(50); 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci while (time_before(jiffies, timeout)) { 11088c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); 11098c2ecf20Sopenharmony_ci if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) { 11108c2ecf20Sopenharmony_ci err = 0; 11118c2ecf20Sopenharmony_ci break; 11128c2ecf20Sopenharmony_ci } 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci usleep_range(100, 200); 11158c2ecf20Sopenharmony_ci } 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); 11188c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index); 11198c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci return err; 11228c2ecf20Sopenharmony_ci} 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_cistatic int tegra124_pcie_phy_power_off(struct phy *phy) 11258c2ecf20Sopenharmony_ci{ 11268c2ecf20Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 11278c2ecf20Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 11288c2ecf20Sopenharmony_ci u32 value; 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); 11318c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index); 11328c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); 11358c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST; 11368c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_ci return 0; 11398c2ecf20Sopenharmony_ci} 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_cistatic const struct phy_ops tegra124_pcie_phy_ops = { 11428c2ecf20Sopenharmony_ci .init = tegra124_pcie_phy_init, 11438c2ecf20Sopenharmony_ci .exit = tegra124_pcie_phy_exit, 11448c2ecf20Sopenharmony_ci .power_on = tegra124_pcie_phy_power_on, 11458c2ecf20Sopenharmony_ci .power_off = tegra124_pcie_phy_power_off, 11468c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 11478c2ecf20Sopenharmony_ci}; 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_cistatic struct tegra_xusb_pad * 11508c2ecf20Sopenharmony_citegra124_pcie_pad_probe(struct tegra_xusb_padctl *padctl, 11518c2ecf20Sopenharmony_ci const struct tegra_xusb_pad_soc *soc, 11528c2ecf20Sopenharmony_ci struct device_node *np) 11538c2ecf20Sopenharmony_ci{ 11548c2ecf20Sopenharmony_ci struct tegra_xusb_pcie_pad *pcie; 11558c2ecf20Sopenharmony_ci struct tegra_xusb_pad *pad; 11568c2ecf20Sopenharmony_ci int err; 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_ci pcie = kzalloc(sizeof(*pcie), GFP_KERNEL); 11598c2ecf20Sopenharmony_ci if (!pcie) 11608c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci pad = &pcie->base; 11638c2ecf20Sopenharmony_ci pad->ops = &tegra124_pcie_lane_ops; 11648c2ecf20Sopenharmony_ci pad->soc = soc; 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci err = tegra_xusb_pad_init(pad, padctl, np); 11678c2ecf20Sopenharmony_ci if (err < 0) { 11688c2ecf20Sopenharmony_ci kfree(pcie); 11698c2ecf20Sopenharmony_ci goto out; 11708c2ecf20Sopenharmony_ci } 11718c2ecf20Sopenharmony_ci 11728c2ecf20Sopenharmony_ci err = tegra_xusb_pad_register(pad, &tegra124_pcie_phy_ops); 11738c2ecf20Sopenharmony_ci if (err < 0) 11748c2ecf20Sopenharmony_ci goto unregister; 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_ci dev_set_drvdata(&pad->dev, pad); 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_ci return pad; 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_ciunregister: 11818c2ecf20Sopenharmony_ci device_unregister(&pad->dev); 11828c2ecf20Sopenharmony_ciout: 11838c2ecf20Sopenharmony_ci return ERR_PTR(err); 11848c2ecf20Sopenharmony_ci} 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_cistatic void tegra124_pcie_pad_remove(struct tegra_xusb_pad *pad) 11878c2ecf20Sopenharmony_ci{ 11888c2ecf20Sopenharmony_ci struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(pad); 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci kfree(pcie); 11918c2ecf20Sopenharmony_ci} 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra124_pcie_ops = { 11948c2ecf20Sopenharmony_ci .probe = tegra124_pcie_pad_probe, 11958c2ecf20Sopenharmony_ci .remove = tegra124_pcie_pad_remove, 11968c2ecf20Sopenharmony_ci}; 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra124_pcie_pad = { 11998c2ecf20Sopenharmony_ci .name = "pcie", 12008c2ecf20Sopenharmony_ci .num_lanes = ARRAY_SIZE(tegra124_pcie_lanes), 12018c2ecf20Sopenharmony_ci .lanes = tegra124_pcie_lanes, 12028c2ecf20Sopenharmony_ci .ops = &tegra124_pcie_ops, 12038c2ecf20Sopenharmony_ci}; 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra124_sata_lanes[] = { 12068c2ecf20Sopenharmony_ci TEGRA124_LANE("sata-0", 0x134, 26, 0x3, pcie), 12078c2ecf20Sopenharmony_ci}; 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_cistatic struct tegra_xusb_lane * 12108c2ecf20Sopenharmony_citegra124_sata_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 12118c2ecf20Sopenharmony_ci unsigned int index) 12128c2ecf20Sopenharmony_ci{ 12138c2ecf20Sopenharmony_ci struct tegra_xusb_sata_lane *sata; 12148c2ecf20Sopenharmony_ci int err; 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci sata = kzalloc(sizeof(*sata), GFP_KERNEL); 12178c2ecf20Sopenharmony_ci if (!sata) 12188c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sata->base.list); 12218c2ecf20Sopenharmony_ci sata->base.soc = &pad->soc->lanes[index]; 12228c2ecf20Sopenharmony_ci sata->base.index = index; 12238c2ecf20Sopenharmony_ci sata->base.pad = pad; 12248c2ecf20Sopenharmony_ci sata->base.np = np; 12258c2ecf20Sopenharmony_ci 12268c2ecf20Sopenharmony_ci err = tegra_xusb_lane_parse_dt(&sata->base, np); 12278c2ecf20Sopenharmony_ci if (err < 0) { 12288c2ecf20Sopenharmony_ci kfree(sata); 12298c2ecf20Sopenharmony_ci return ERR_PTR(err); 12308c2ecf20Sopenharmony_ci } 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_ci return &sata->base; 12338c2ecf20Sopenharmony_ci} 12348c2ecf20Sopenharmony_ci 12358c2ecf20Sopenharmony_cistatic void tegra124_sata_lane_remove(struct tegra_xusb_lane *lane) 12368c2ecf20Sopenharmony_ci{ 12378c2ecf20Sopenharmony_ci struct tegra_xusb_sata_lane *sata = to_sata_lane(lane); 12388c2ecf20Sopenharmony_ci 12398c2ecf20Sopenharmony_ci kfree(sata); 12408c2ecf20Sopenharmony_ci} 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra124_sata_lane_ops = { 12438c2ecf20Sopenharmony_ci .probe = tegra124_sata_lane_probe, 12448c2ecf20Sopenharmony_ci .remove = tegra124_sata_lane_remove, 12458c2ecf20Sopenharmony_ci}; 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_cistatic int tegra124_sata_phy_init(struct phy *phy) 12488c2ecf20Sopenharmony_ci{ 12498c2ecf20Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_ci return tegra124_xusb_padctl_enable(lane->pad->padctl); 12528c2ecf20Sopenharmony_ci} 12538c2ecf20Sopenharmony_ci 12548c2ecf20Sopenharmony_cistatic int tegra124_sata_phy_exit(struct phy *phy) 12558c2ecf20Sopenharmony_ci{ 12568c2ecf20Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ci return tegra124_xusb_padctl_disable(lane->pad->padctl); 12598c2ecf20Sopenharmony_ci} 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_cistatic int tegra124_sata_phy_power_on(struct phy *phy) 12628c2ecf20Sopenharmony_ci{ 12638c2ecf20Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 12648c2ecf20Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 12658c2ecf20Sopenharmony_ci unsigned long timeout; 12668c2ecf20Sopenharmony_ci int err = -ETIMEDOUT; 12678c2ecf20Sopenharmony_ci u32 value; 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); 12708c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; 12718c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ; 12728c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); 12738c2ecf20Sopenharmony_ci 12748c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 12758c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; 12768c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ; 12778c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 12808c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE; 12818c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 12848c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST; 12858c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 12868c2ecf20Sopenharmony_ci 12878c2ecf20Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(50); 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ci while (time_before(jiffies, timeout)) { 12908c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 12918c2ecf20Sopenharmony_ci if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) { 12928c2ecf20Sopenharmony_ci err = 0; 12938c2ecf20Sopenharmony_ci break; 12948c2ecf20Sopenharmony_ci } 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_ci usleep_range(100, 200); 12978c2ecf20Sopenharmony_ci } 12988c2ecf20Sopenharmony_ci 12998c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); 13008c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index); 13018c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_ci return err; 13048c2ecf20Sopenharmony_ci} 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_cistatic int tegra124_sata_phy_power_off(struct phy *phy) 13078c2ecf20Sopenharmony_ci{ 13088c2ecf20Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 13098c2ecf20Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 13108c2ecf20Sopenharmony_ci u32 value; 13118c2ecf20Sopenharmony_ci 13128c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); 13138c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index); 13148c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 13178c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST; 13188c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 13218c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE; 13228c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 13258c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; 13268c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ; 13278c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 13288c2ecf20Sopenharmony_ci 13298c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); 13308c2ecf20Sopenharmony_ci value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; 13318c2ecf20Sopenharmony_ci value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ; 13328c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); 13338c2ecf20Sopenharmony_ci 13348c2ecf20Sopenharmony_ci return 0; 13358c2ecf20Sopenharmony_ci} 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_cistatic const struct phy_ops tegra124_sata_phy_ops = { 13388c2ecf20Sopenharmony_ci .init = tegra124_sata_phy_init, 13398c2ecf20Sopenharmony_ci .exit = tegra124_sata_phy_exit, 13408c2ecf20Sopenharmony_ci .power_on = tegra124_sata_phy_power_on, 13418c2ecf20Sopenharmony_ci .power_off = tegra124_sata_phy_power_off, 13428c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 13438c2ecf20Sopenharmony_ci}; 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_cistatic struct tegra_xusb_pad * 13468c2ecf20Sopenharmony_citegra124_sata_pad_probe(struct tegra_xusb_padctl *padctl, 13478c2ecf20Sopenharmony_ci const struct tegra_xusb_pad_soc *soc, 13488c2ecf20Sopenharmony_ci struct device_node *np) 13498c2ecf20Sopenharmony_ci{ 13508c2ecf20Sopenharmony_ci struct tegra_xusb_sata_pad *sata; 13518c2ecf20Sopenharmony_ci struct tegra_xusb_pad *pad; 13528c2ecf20Sopenharmony_ci int err; 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci sata = kzalloc(sizeof(*sata), GFP_KERNEL); 13558c2ecf20Sopenharmony_ci if (!sata) 13568c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 13578c2ecf20Sopenharmony_ci 13588c2ecf20Sopenharmony_ci pad = &sata->base; 13598c2ecf20Sopenharmony_ci pad->ops = &tegra124_sata_lane_ops; 13608c2ecf20Sopenharmony_ci pad->soc = soc; 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ci err = tegra_xusb_pad_init(pad, padctl, np); 13638c2ecf20Sopenharmony_ci if (err < 0) { 13648c2ecf20Sopenharmony_ci kfree(sata); 13658c2ecf20Sopenharmony_ci goto out; 13668c2ecf20Sopenharmony_ci } 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci err = tegra_xusb_pad_register(pad, &tegra124_sata_phy_ops); 13698c2ecf20Sopenharmony_ci if (err < 0) 13708c2ecf20Sopenharmony_ci goto unregister; 13718c2ecf20Sopenharmony_ci 13728c2ecf20Sopenharmony_ci dev_set_drvdata(&pad->dev, pad); 13738c2ecf20Sopenharmony_ci 13748c2ecf20Sopenharmony_ci return pad; 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_ciunregister: 13778c2ecf20Sopenharmony_ci device_unregister(&pad->dev); 13788c2ecf20Sopenharmony_ciout: 13798c2ecf20Sopenharmony_ci return ERR_PTR(err); 13808c2ecf20Sopenharmony_ci} 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_cistatic void tegra124_sata_pad_remove(struct tegra_xusb_pad *pad) 13838c2ecf20Sopenharmony_ci{ 13848c2ecf20Sopenharmony_ci struct tegra_xusb_sata_pad *sata = to_sata_pad(pad); 13858c2ecf20Sopenharmony_ci 13868c2ecf20Sopenharmony_ci kfree(sata); 13878c2ecf20Sopenharmony_ci} 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra124_sata_ops = { 13908c2ecf20Sopenharmony_ci .probe = tegra124_sata_pad_probe, 13918c2ecf20Sopenharmony_ci .remove = tegra124_sata_pad_remove, 13928c2ecf20Sopenharmony_ci}; 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra124_sata_pad = { 13958c2ecf20Sopenharmony_ci .name = "sata", 13968c2ecf20Sopenharmony_ci .num_lanes = ARRAY_SIZE(tegra124_sata_lanes), 13978c2ecf20Sopenharmony_ci .lanes = tegra124_sata_lanes, 13988c2ecf20Sopenharmony_ci .ops = &tegra124_sata_ops, 13998c2ecf20Sopenharmony_ci}; 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_cistatic const struct tegra_xusb_pad_soc *tegra124_pads[] = { 14028c2ecf20Sopenharmony_ci &tegra124_usb2_pad, 14038c2ecf20Sopenharmony_ci &tegra124_ulpi_pad, 14048c2ecf20Sopenharmony_ci &tegra124_hsic_pad, 14058c2ecf20Sopenharmony_ci &tegra124_pcie_pad, 14068c2ecf20Sopenharmony_ci &tegra124_sata_pad, 14078c2ecf20Sopenharmony_ci}; 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_cistatic int tegra124_usb2_port_enable(struct tegra_xusb_port *port) 14108c2ecf20Sopenharmony_ci{ 14118c2ecf20Sopenharmony_ci return 0; 14128c2ecf20Sopenharmony_ci} 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_cistatic void tegra124_usb2_port_disable(struct tegra_xusb_port *port) 14158c2ecf20Sopenharmony_ci{ 14168c2ecf20Sopenharmony_ci} 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_cistatic struct tegra_xusb_lane * 14198c2ecf20Sopenharmony_citegra124_usb2_port_map(struct tegra_xusb_port *port) 14208c2ecf20Sopenharmony_ci{ 14218c2ecf20Sopenharmony_ci return tegra_xusb_find_lane(port->padctl, "usb2", port->index); 14228c2ecf20Sopenharmony_ci} 14238c2ecf20Sopenharmony_ci 14248c2ecf20Sopenharmony_cistatic const struct tegra_xusb_port_ops tegra124_usb2_port_ops = { 14258c2ecf20Sopenharmony_ci .release = tegra_xusb_usb2_port_release, 14268c2ecf20Sopenharmony_ci .remove = tegra_xusb_usb2_port_remove, 14278c2ecf20Sopenharmony_ci .enable = tegra124_usb2_port_enable, 14288c2ecf20Sopenharmony_ci .disable = tegra124_usb2_port_disable, 14298c2ecf20Sopenharmony_ci .map = tegra124_usb2_port_map, 14308c2ecf20Sopenharmony_ci}; 14318c2ecf20Sopenharmony_ci 14328c2ecf20Sopenharmony_cistatic int tegra124_ulpi_port_enable(struct tegra_xusb_port *port) 14338c2ecf20Sopenharmony_ci{ 14348c2ecf20Sopenharmony_ci return 0; 14358c2ecf20Sopenharmony_ci} 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_cistatic void tegra124_ulpi_port_disable(struct tegra_xusb_port *port) 14388c2ecf20Sopenharmony_ci{ 14398c2ecf20Sopenharmony_ci} 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_cistatic struct tegra_xusb_lane * 14428c2ecf20Sopenharmony_citegra124_ulpi_port_map(struct tegra_xusb_port *port) 14438c2ecf20Sopenharmony_ci{ 14448c2ecf20Sopenharmony_ci return tegra_xusb_find_lane(port->padctl, "ulpi", port->index); 14458c2ecf20Sopenharmony_ci} 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_cistatic const struct tegra_xusb_port_ops tegra124_ulpi_port_ops = { 14488c2ecf20Sopenharmony_ci .release = tegra_xusb_ulpi_port_release, 14498c2ecf20Sopenharmony_ci .enable = tegra124_ulpi_port_enable, 14508c2ecf20Sopenharmony_ci .disable = tegra124_ulpi_port_disable, 14518c2ecf20Sopenharmony_ci .map = tegra124_ulpi_port_map, 14528c2ecf20Sopenharmony_ci}; 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_cistatic int tegra124_hsic_port_enable(struct tegra_xusb_port *port) 14558c2ecf20Sopenharmony_ci{ 14568c2ecf20Sopenharmony_ci return 0; 14578c2ecf20Sopenharmony_ci} 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_cistatic void tegra124_hsic_port_disable(struct tegra_xusb_port *port) 14608c2ecf20Sopenharmony_ci{ 14618c2ecf20Sopenharmony_ci} 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_cistatic struct tegra_xusb_lane * 14648c2ecf20Sopenharmony_citegra124_hsic_port_map(struct tegra_xusb_port *port) 14658c2ecf20Sopenharmony_ci{ 14668c2ecf20Sopenharmony_ci return tegra_xusb_find_lane(port->padctl, "hsic", port->index); 14678c2ecf20Sopenharmony_ci} 14688c2ecf20Sopenharmony_ci 14698c2ecf20Sopenharmony_cistatic const struct tegra_xusb_port_ops tegra124_hsic_port_ops = { 14708c2ecf20Sopenharmony_ci .release = tegra_xusb_hsic_port_release, 14718c2ecf20Sopenharmony_ci .enable = tegra124_hsic_port_enable, 14728c2ecf20Sopenharmony_ci .disable = tegra124_hsic_port_disable, 14738c2ecf20Sopenharmony_ci .map = tegra124_hsic_port_map, 14748c2ecf20Sopenharmony_ci}; 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_cistatic int tegra124_usb3_port_enable(struct tegra_xusb_port *port) 14778c2ecf20Sopenharmony_ci{ 14788c2ecf20Sopenharmony_ci struct tegra_xusb_usb3_port *usb3 = to_usb3_port(port); 14798c2ecf20Sopenharmony_ci struct tegra_xusb_padctl *padctl = port->padctl; 14808c2ecf20Sopenharmony_ci struct tegra_xusb_lane *lane = usb3->base.lane; 14818c2ecf20Sopenharmony_ci unsigned int index = port->index, offset; 14828c2ecf20Sopenharmony_ci u32 value; 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_ci if (!usb3->internal) 14878c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index); 14888c2ecf20Sopenharmony_ci else 14898c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index); 14908c2ecf20Sopenharmony_ci 14918c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(index); 14928c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(index, usb3->port); 14938c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); 14948c2ecf20Sopenharmony_ci 14958c2ecf20Sopenharmony_ci /* 14968c2ecf20Sopenharmony_ci * TODO: move this code into the PCIe/SATA PHY ->power_on() callbacks 14978c2ecf20Sopenharmony_ci * and conditionalize based on mux function? This seems to work, but 14988c2ecf20Sopenharmony_ci * might not be the exact proper sequence. 14998c2ecf20Sopenharmony_ci */ 15008c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index)); 15018c2ecf20Sopenharmony_ci value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_MASK << 15028c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT) | 15038c2ecf20Sopenharmony_ci (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_MASK << 15048c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT) | 15058c2ecf20Sopenharmony_ci (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_MASK << 15068c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT)); 15078c2ecf20Sopenharmony_ci value |= (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_VAL << 15088c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT) | 15098c2ecf20Sopenharmony_ci (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_VAL << 15108c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT) | 15118c2ecf20Sopenharmony_ci (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_VAL << 15128c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT); 15138c2ecf20Sopenharmony_ci 15148c2ecf20Sopenharmony_ci if (usb3->context_saved) { 15158c2ecf20Sopenharmony_ci value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK << 15168c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) | 15178c2ecf20Sopenharmony_ci (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK << 15188c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT)); 15198c2ecf20Sopenharmony_ci value |= (usb3->ctle_g << 15208c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) | 15218c2ecf20Sopenharmony_ci (usb3->ctle_z << 15228c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT); 15238c2ecf20Sopenharmony_ci } 15248c2ecf20Sopenharmony_ci 15258c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index)); 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_ci value = XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_VAL; 15288c2ecf20Sopenharmony_ci 15298c2ecf20Sopenharmony_ci if (usb3->context_saved) { 15308c2ecf20Sopenharmony_ci value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK << 15318c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) | 15328c2ecf20Sopenharmony_ci (XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK << 15338c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT)); 15348c2ecf20Sopenharmony_ci value |= (usb3->tap1 << 15358c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) | 15368c2ecf20Sopenharmony_ci (usb3->amp << 15378c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT); 15388c2ecf20Sopenharmony_ci } 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(index)); 15418c2ecf20Sopenharmony_ci 15428c2ecf20Sopenharmony_ci if (lane->pad == padctl->pcie) 15438c2ecf20Sopenharmony_ci offset = XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL2(lane->index); 15448c2ecf20Sopenharmony_ci else 15458c2ecf20Sopenharmony_ci offset = XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2; 15468c2ecf20Sopenharmony_ci 15478c2ecf20Sopenharmony_ci value = padctl_readl(padctl, offset); 15488c2ecf20Sopenharmony_ci value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_MASK << 15498c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT); 15508c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_VAL << 15518c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT; 15528c2ecf20Sopenharmony_ci padctl_writel(padctl, value, offset); 15538c2ecf20Sopenharmony_ci 15548c2ecf20Sopenharmony_ci if (lane->pad == padctl->pcie) 15558c2ecf20Sopenharmony_ci offset = XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL5(lane->index); 15568c2ecf20Sopenharmony_ci else 15578c2ecf20Sopenharmony_ci offset = XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5; 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_ci value = padctl_readl(padctl, offset); 15608c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL5_RX_QEYE_EN; 15618c2ecf20Sopenharmony_ci padctl_writel(padctl, value, offset); 15628c2ecf20Sopenharmony_ci 15638c2ecf20Sopenharmony_ci /* Enable SATA PHY when SATA lane is used */ 15648c2ecf20Sopenharmony_ci if (lane->pad == padctl->sata) { 15658c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 15668c2ecf20Sopenharmony_ci value &= ~(XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_MASK << 15678c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT); 15688c2ecf20Sopenharmony_ci value |= 0x2 << 15698c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT; 15708c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 15718c2ecf20Sopenharmony_ci 15728c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL2); 15738c2ecf20Sopenharmony_ci value &= ~((XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_MASK << 15748c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT) | 15758c2ecf20Sopenharmony_ci (XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_MASK << 15768c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT) | 15778c2ecf20Sopenharmony_ci (XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_MASK << 15788c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT) | 15798c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TCLKOUT_EN); 15808c2ecf20Sopenharmony_ci value |= (0x7 << 15818c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT) | 15828c2ecf20Sopenharmony_ci (0x8 << 15838c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT) | 15848c2ecf20Sopenharmony_ci (0x8 << 15858c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT) | 15868c2ecf20Sopenharmony_ci XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TXCLKREF_SEL; 15878c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL2); 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL3); 15908c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL3_RCAL_BYPASS; 15918c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL3); 15928c2ecf20Sopenharmony_ci } 15938c2ecf20Sopenharmony_ci 15948c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 15958c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(index); 15968c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_ci usleep_range(100, 200); 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 16018c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(index); 16028c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 16038c2ecf20Sopenharmony_ci 16048c2ecf20Sopenharmony_ci usleep_range(100, 200); 16058c2ecf20Sopenharmony_ci 16068c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 16078c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(index); 16088c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 16098c2ecf20Sopenharmony_ci 16108c2ecf20Sopenharmony_ci return 0; 16118c2ecf20Sopenharmony_ci} 16128c2ecf20Sopenharmony_ci 16138c2ecf20Sopenharmony_cistatic void tegra124_usb3_port_disable(struct tegra_xusb_port *port) 16148c2ecf20Sopenharmony_ci{ 16158c2ecf20Sopenharmony_ci struct tegra_xusb_padctl *padctl = port->padctl; 16168c2ecf20Sopenharmony_ci u32 value; 16178c2ecf20Sopenharmony_ci 16188c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 16198c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(port->index); 16208c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 16218c2ecf20Sopenharmony_ci 16228c2ecf20Sopenharmony_ci usleep_range(100, 200); 16238c2ecf20Sopenharmony_ci 16248c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 16258c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(port->index); 16268c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 16278c2ecf20Sopenharmony_ci 16288c2ecf20Sopenharmony_ci usleep_range(250, 350); 16298c2ecf20Sopenharmony_ci 16308c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 16318c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(port->index); 16328c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); 16358c2ecf20Sopenharmony_ci value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(port->index); 16368c2ecf20Sopenharmony_ci value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(port->index, 0x7); 16378c2ecf20Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); 16388c2ecf20Sopenharmony_ci} 16398c2ecf20Sopenharmony_ci 16408c2ecf20Sopenharmony_cistatic const struct tegra_xusb_lane_map tegra124_usb3_map[] = { 16418c2ecf20Sopenharmony_ci { 0, "pcie", 0 }, 16428c2ecf20Sopenharmony_ci { 1, "pcie", 1 }, 16438c2ecf20Sopenharmony_ci { 1, "sata", 0 }, 16448c2ecf20Sopenharmony_ci { 0, NULL, 0 }, 16458c2ecf20Sopenharmony_ci}; 16468c2ecf20Sopenharmony_ci 16478c2ecf20Sopenharmony_cistatic struct tegra_xusb_lane * 16488c2ecf20Sopenharmony_citegra124_usb3_port_map(struct tegra_xusb_port *port) 16498c2ecf20Sopenharmony_ci{ 16508c2ecf20Sopenharmony_ci return tegra_xusb_port_find_lane(port, tegra124_usb3_map, "usb3-ss"); 16518c2ecf20Sopenharmony_ci} 16528c2ecf20Sopenharmony_ci 16538c2ecf20Sopenharmony_cistatic const struct tegra_xusb_port_ops tegra124_usb3_port_ops = { 16548c2ecf20Sopenharmony_ci .release = tegra_xusb_usb3_port_release, 16558c2ecf20Sopenharmony_ci .remove = tegra_xusb_usb3_port_remove, 16568c2ecf20Sopenharmony_ci .enable = tegra124_usb3_port_enable, 16578c2ecf20Sopenharmony_ci .disable = tegra124_usb3_port_disable, 16588c2ecf20Sopenharmony_ci .map = tegra124_usb3_port_map, 16598c2ecf20Sopenharmony_ci}; 16608c2ecf20Sopenharmony_ci 16618c2ecf20Sopenharmony_cistatic int 16628c2ecf20Sopenharmony_citegra124_xusb_read_fuse_calibration(struct tegra124_xusb_fuse_calibration *fuse) 16638c2ecf20Sopenharmony_ci{ 16648c2ecf20Sopenharmony_ci unsigned int i; 16658c2ecf20Sopenharmony_ci int err; 16668c2ecf20Sopenharmony_ci u32 value; 16678c2ecf20Sopenharmony_ci 16688c2ecf20Sopenharmony_ci err = tegra_fuse_readl(TEGRA_FUSE_SKU_CALIB_0, &value); 16698c2ecf20Sopenharmony_ci if (err < 0) 16708c2ecf20Sopenharmony_ci return err; 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(fuse->hs_curr_level); i++) { 16738c2ecf20Sopenharmony_ci fuse->hs_curr_level[i] = 16748c2ecf20Sopenharmony_ci (value >> FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(i)) & 16758c2ecf20Sopenharmony_ci FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK; 16768c2ecf20Sopenharmony_ci } 16778c2ecf20Sopenharmony_ci fuse->hs_iref_cap = 16788c2ecf20Sopenharmony_ci (value >> FUSE_SKU_CALIB_HS_IREF_CAP_SHIFT) & 16798c2ecf20Sopenharmony_ci FUSE_SKU_CALIB_HS_IREF_CAP_MASK; 16808c2ecf20Sopenharmony_ci fuse->hs_term_range_adj = 16818c2ecf20Sopenharmony_ci (value >> FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT) & 16828c2ecf20Sopenharmony_ci FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK; 16838c2ecf20Sopenharmony_ci fuse->hs_squelch_level = 16848c2ecf20Sopenharmony_ci (value >> FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_SHIFT) & 16858c2ecf20Sopenharmony_ci FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_MASK; 16868c2ecf20Sopenharmony_ci 16878c2ecf20Sopenharmony_ci return 0; 16888c2ecf20Sopenharmony_ci} 16898c2ecf20Sopenharmony_ci 16908c2ecf20Sopenharmony_cistatic struct tegra_xusb_padctl * 16918c2ecf20Sopenharmony_citegra124_xusb_padctl_probe(struct device *dev, 16928c2ecf20Sopenharmony_ci const struct tegra_xusb_padctl_soc *soc) 16938c2ecf20Sopenharmony_ci{ 16948c2ecf20Sopenharmony_ci struct tegra124_xusb_padctl *padctl; 16958c2ecf20Sopenharmony_ci int err; 16968c2ecf20Sopenharmony_ci 16978c2ecf20Sopenharmony_ci padctl = devm_kzalloc(dev, sizeof(*padctl), GFP_KERNEL); 16988c2ecf20Sopenharmony_ci if (!padctl) 16998c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 17008c2ecf20Sopenharmony_ci 17018c2ecf20Sopenharmony_ci padctl->base.dev = dev; 17028c2ecf20Sopenharmony_ci padctl->base.soc = soc; 17038c2ecf20Sopenharmony_ci 17048c2ecf20Sopenharmony_ci err = tegra124_xusb_read_fuse_calibration(&padctl->fuse); 17058c2ecf20Sopenharmony_ci if (err < 0) 17068c2ecf20Sopenharmony_ci return ERR_PTR(err); 17078c2ecf20Sopenharmony_ci 17088c2ecf20Sopenharmony_ci return &padctl->base; 17098c2ecf20Sopenharmony_ci} 17108c2ecf20Sopenharmony_ci 17118c2ecf20Sopenharmony_cistatic void tegra124_xusb_padctl_remove(struct tegra_xusb_padctl *padctl) 17128c2ecf20Sopenharmony_ci{ 17138c2ecf20Sopenharmony_ci} 17148c2ecf20Sopenharmony_ci 17158c2ecf20Sopenharmony_cistatic const struct tegra_xusb_padctl_ops tegra124_xusb_padctl_ops = { 17168c2ecf20Sopenharmony_ci .probe = tegra124_xusb_padctl_probe, 17178c2ecf20Sopenharmony_ci .remove = tegra124_xusb_padctl_remove, 17188c2ecf20Sopenharmony_ci .usb3_save_context = tegra124_usb3_save_context, 17198c2ecf20Sopenharmony_ci .hsic_set_idle = tegra124_hsic_set_idle, 17208c2ecf20Sopenharmony_ci}; 17218c2ecf20Sopenharmony_ci 17228c2ecf20Sopenharmony_cistatic const char * const tegra124_xusb_padctl_supply_names[] = { 17238c2ecf20Sopenharmony_ci "avdd-pll-utmip", 17248c2ecf20Sopenharmony_ci "avdd-pll-erefe", 17258c2ecf20Sopenharmony_ci "avdd-pex-pll", 17268c2ecf20Sopenharmony_ci "hvdd-pex-pll-e", 17278c2ecf20Sopenharmony_ci}; 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_ciconst struct tegra_xusb_padctl_soc tegra124_xusb_padctl_soc = { 17308c2ecf20Sopenharmony_ci .num_pads = ARRAY_SIZE(tegra124_pads), 17318c2ecf20Sopenharmony_ci .pads = tegra124_pads, 17328c2ecf20Sopenharmony_ci .ports = { 17338c2ecf20Sopenharmony_ci .usb2 = { 17348c2ecf20Sopenharmony_ci .ops = &tegra124_usb2_port_ops, 17358c2ecf20Sopenharmony_ci .count = 3, 17368c2ecf20Sopenharmony_ci }, 17378c2ecf20Sopenharmony_ci .ulpi = { 17388c2ecf20Sopenharmony_ci .ops = &tegra124_ulpi_port_ops, 17398c2ecf20Sopenharmony_ci .count = 1, 17408c2ecf20Sopenharmony_ci }, 17418c2ecf20Sopenharmony_ci .hsic = { 17428c2ecf20Sopenharmony_ci .ops = &tegra124_hsic_port_ops, 17438c2ecf20Sopenharmony_ci .count = 2, 17448c2ecf20Sopenharmony_ci }, 17458c2ecf20Sopenharmony_ci .usb3 = { 17468c2ecf20Sopenharmony_ci .ops = &tegra124_usb3_port_ops, 17478c2ecf20Sopenharmony_ci .count = 2, 17488c2ecf20Sopenharmony_ci }, 17498c2ecf20Sopenharmony_ci }, 17508c2ecf20Sopenharmony_ci .ops = &tegra124_xusb_padctl_ops, 17518c2ecf20Sopenharmony_ci .supply_names = tegra124_xusb_padctl_supply_names, 17528c2ecf20Sopenharmony_ci .num_supplies = ARRAY_SIZE(tegra124_xusb_padctl_supply_names), 17538c2ecf20Sopenharmony_ci}; 17548c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(tegra124_xusb_padctl_soc); 17558c2ecf20Sopenharmony_ci 17568c2ecf20Sopenharmony_ciMODULE_AUTHOR("Thierry Reding <treding@nvidia.com>"); 17578c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("NVIDIA Tegra 124 XUSB Pad Controller driver"); 17588c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 1759