153d2a715SThierry Reding /* 253d2a715SThierry Reding * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. 353d2a715SThierry Reding * 453d2a715SThierry Reding * This program is free software; you can redistribute it and/or modify it 553d2a715SThierry Reding * under the terms and conditions of the GNU General Public License, 653d2a715SThierry Reding * version 2, as published by the Free Software Foundation. 753d2a715SThierry Reding * 853d2a715SThierry Reding * This program is distributed in the hope it will be useful, but WITHOUT 953d2a715SThierry Reding * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1053d2a715SThierry Reding * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 1153d2a715SThierry Reding * more details. 1253d2a715SThierry Reding */ 1353d2a715SThierry Reding 1453d2a715SThierry Reding #include <linux/delay.h> 1553d2a715SThierry Reding #include <linux/io.h> 1653d2a715SThierry Reding #include <linux/mailbox_client.h> 1753d2a715SThierry Reding #include <linux/module.h> 1853d2a715SThierry Reding #include <linux/of.h> 1953d2a715SThierry Reding #include <linux/phy/phy.h> 2053d2a715SThierry Reding #include <linux/platform_device.h> 2153d2a715SThierry Reding #include <linux/regulator/consumer.h> 2253d2a715SThierry Reding #include <linux/reset.h> 2353d2a715SThierry Reding #include <linux/slab.h> 2453d2a715SThierry Reding 2553d2a715SThierry Reding #include <soc/tegra/fuse.h> 2653d2a715SThierry Reding 2753d2a715SThierry Reding #include "xusb.h" 2853d2a715SThierry Reding 2953d2a715SThierry Reding #define FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(x) ((x) ? 15 : 0) 3053d2a715SThierry Reding #define FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK 0x3f 3153d2a715SThierry Reding #define FUSE_SKU_CALIB_HS_IREF_CAP_SHIFT 13 3253d2a715SThierry Reding #define FUSE_SKU_CALIB_HS_IREF_CAP_MASK 0x3 3353d2a715SThierry Reding #define FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_SHIFT 11 3453d2a715SThierry Reding #define FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_MASK 0x3 3553d2a715SThierry Reding #define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT 7 3653d2a715SThierry Reding #define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK 0xf 3753d2a715SThierry Reding 3853d2a715SThierry Reding #define XUSB_PADCTL_USB2_PORT_CAP 0x008 3953d2a715SThierry Reding #define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(x) ((x) * 4) 4053d2a715SThierry Reding #define XUSB_PADCTL_USB2_PORT_CAP_PORT_CAP_MASK 0x3 4153d2a715SThierry Reding #define XUSB_PADCTL_USB2_PORT_CAP_DISABLED 0x0 4253d2a715SThierry Reding #define XUSB_PADCTL_USB2_PORT_CAP_HOST 0x1 4353d2a715SThierry Reding #define XUSB_PADCTL_USB2_PORT_CAP_DEVICE 0x2 4453d2a715SThierry Reding #define XUSB_PADCTL_USB2_PORT_CAP_OTG 0x3 4553d2a715SThierry Reding 4653d2a715SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP 0x014 4753d2a715SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(x) (1 << (((x) * 4) + 3)) 4853d2a715SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_SHIFT(x) ((x) * 4) 4953d2a715SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(x) (0x7 << ((x) * 4)) 5053d2a715SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(x, v) (((v) & 0x7) << ((x) * 4)) 5153d2a715SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP_PORT_MAP_MASK 0x7 5253d2a715SThierry Reding 5353d2a715SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM 0x01c 5453d2a715SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26) 5553d2a715SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25) 5653d2a715SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24) 5753d2a715SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(x) (1 << (18 + (x) * 4)) 5853d2a715SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(x) \ 5953d2a715SThierry Reding (1 << (17 + (x) * 4)) 6053d2a715SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(x) (1 << (16 + (x) * 4)) 6153d2a715SThierry Reding 6253d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040 6353d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19) 6453d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12) 6553d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1) 6653d2a715SThierry Reding 6753d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044 6853d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6) 6953d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5) 7053d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4) 7153d2a715SThierry Reding 7253d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(x) (0x058 + (x) * 4) 7353d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT 24 7453d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_MASK 0xff 7553d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_VAL 0x24 7653d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT 16 7753d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK 0x3f 7853d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT 8 7953d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK 0x3f 8053d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT 8 8153d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_MASK 0xffff 8253d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_VAL 0xf070 8353d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT 4 8453d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_MASK 0xf 8553d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_VAL 0xf 8653d2a715SThierry Reding 8753d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(x) (0x068 + (x) * 4) 8853d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT 24 8953d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK 0x1f 9053d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT 16 9153d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK 0x7f 9253d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_VAL 0x002008ee 9353d2a715SThierry Reding 9453d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL2(x) ((x) < 2 ? 0x078 + (x) * 4 : \ 9553d2a715SThierry Reding 0x0f8 + (x) * 4) 9653d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT 28 9753d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_MASK 0x3 9853d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_VAL 0x1 9953d2a715SThierry Reding 10053d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL5(x) ((x) < 2 ? 0x090 + (x) * 4 : \ 10153d2a715SThierry Reding 0x11c + (x) * 4) 10253d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL5_RX_QEYE_EN (1 << 8) 10353d2a715SThierry Reding 10453d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL6(x) ((x) < 2 ? 0x098 + (x) * 4 : \ 10553d2a715SThierry Reding 0x128 + (x) * 4) 10653d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT 24 10753d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK 0x3f 10853d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_TAP_MASK 0x1f 10953d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_AMP_MASK 0x7f 11053d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT 16 11153d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK 0xff 11253d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_G_Z 0x21 11353d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_TAP 0x32 11453d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_AMP 0x33 11553d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_CTLE_Z 0x48 11653d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_LATCH_G_Z 0xa1 11753d2a715SThierry Reding 11853d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PADX_CTL0(x) (0x0a0 + (x) * 4) 11953d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI (1 << 21) 12053d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 (1 << 20) 12153d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD (1 << 19) 12253d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT 14 12353d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_MASK 0x3 12453d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_VAL(x) ((x) ? 0x0 : 0x3) 12553d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT 6 12653d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_MASK 0x3f 12753d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_VAL 0x0e 12853d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT 0 12953d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK 0x3f 13053d2a715SThierry Reding 13153d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PADX_CTL1(x) (0x0ac + (x) * 4) 13253d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT 9 13353d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_MASK 0x3 13453d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT 3 13553d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK 0x7 13653d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR (1 << 2) 13753d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP (1 << 1) 13853d2a715SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP (1 << 0) 13953d2a715SThierry Reding 14053d2a715SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0 0x0b8 14153d2a715SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD (1 << 12) 14253d2a715SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT 2 14353d2a715SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK 0x7 14453d2a715SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL 0x5 14553d2a715SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT 0 14653d2a715SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK 0x3 14753d2a715SThierry Reding 14853d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PADX_CTL0(x) (0x0c0 + (x) * 4) 14953d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT 12 15053d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_MASK 0x7 15153d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT 8 15253d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_MASK 0x7 15353d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT 4 15453d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_MASK 0x7 15553d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT 0 15653d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_MASK 0x7 15753d2a715SThierry Reding 15853d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PADX_CTL1(x) (0x0c8 + (x) * 4) 15953d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE (1 << 10) 16053d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_RPU_DATA (1 << 9) 16153d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_RPD_STROBE (1 << 8) 16253d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA (1 << 7) 16353d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI (1 << 5) 16453d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX (1 << 4) 16553d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX (1 << 3) 16653d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX (1 << 2) 16753d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN (1 << 0) 16853d2a715SThierry Reding 16953d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PADX_CTL2(x) (0x0d0 + (x) * 4) 17053d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT 4 17153d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK 0x7 17253d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT 0 17353d2a715SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK 0x7 17453d2a715SThierry Reding 17553d2a715SThierry Reding #define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL 0x0e0 17653d2a715SThierry Reding #define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL_STRB_TRIM_MASK 0x1f 17753d2a715SThierry Reding 17853d2a715SThierry Reding #define XUSB_PADCTL_USB3_PAD_MUX 0x134 17953d2a715SThierry Reding #define XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(x) (1 << (1 + (x))) 18053d2a715SThierry Reding #define XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(x) (1 << (6 + (x))) 18153d2a715SThierry Reding 18253d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138 18353d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27) 18453d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24) 18553d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT 20 18653d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_MASK 0x3 18753d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3) 18853d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1) 18953d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0) 19053d2a715SThierry Reding 19153d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2 0x13c 19253d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT 20 19353d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_MASK 0xf 19453d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT 16 19553d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_MASK 0xf 19653d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TCLKOUT_EN (1 << 12) 19753d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TXCLKREF_SEL (1 << 4) 19853d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT 0 19953d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_MASK 0x7 20053d2a715SThierry Reding 20153d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL3 0x140 20253d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_PLL_S0_CTL3_RCAL_BYPASS (1 << 7) 20353d2a715SThierry Reding 20453d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148 20553d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1) 20653d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0) 20753d2a715SThierry Reding 20853d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2 0x14c 20953d2a715SThierry Reding 21053d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5 0x158 21153d2a715SThierry Reding 21253d2a715SThierry Reding #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6 0x15c 21353d2a715SThierry Reding 21453d2a715SThierry Reding struct tegra124_xusb_fuse_calibration { 21553d2a715SThierry Reding u32 hs_curr_level[3]; 21653d2a715SThierry Reding u32 hs_iref_cap; 21753d2a715SThierry Reding u32 hs_term_range_adj; 21853d2a715SThierry Reding u32 hs_squelch_level; 21953d2a715SThierry Reding }; 22053d2a715SThierry Reding 22153d2a715SThierry Reding struct tegra124_xusb_padctl { 22253d2a715SThierry Reding struct tegra_xusb_padctl base; 22353d2a715SThierry Reding 22453d2a715SThierry Reding struct tegra124_xusb_fuse_calibration fuse; 22553d2a715SThierry Reding }; 22653d2a715SThierry Reding 22753d2a715SThierry Reding static inline struct tegra124_xusb_padctl * 22853d2a715SThierry Reding to_tegra124_xusb_padctl(struct tegra_xusb_padctl *padctl) 22953d2a715SThierry Reding { 23053d2a715SThierry Reding return container_of(padctl, struct tegra124_xusb_padctl, base); 23153d2a715SThierry Reding } 23253d2a715SThierry Reding 23353d2a715SThierry Reding static int tegra124_xusb_padctl_enable(struct tegra_xusb_padctl *padctl) 23453d2a715SThierry Reding { 23553d2a715SThierry Reding u32 value; 23653d2a715SThierry Reding 23753d2a715SThierry Reding mutex_lock(&padctl->lock); 23853d2a715SThierry Reding 23953d2a715SThierry Reding if (padctl->enable++ > 0) 24053d2a715SThierry Reding goto out; 24153d2a715SThierry Reding 24253d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 24353d2a715SThierry Reding value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; 24453d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 24553d2a715SThierry Reding 24653d2a715SThierry Reding usleep_range(100, 200); 24753d2a715SThierry Reding 24853d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 24953d2a715SThierry Reding value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; 25053d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 25153d2a715SThierry Reding 25253d2a715SThierry Reding usleep_range(100, 200); 25353d2a715SThierry Reding 25453d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 25553d2a715SThierry Reding value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; 25653d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 25753d2a715SThierry Reding 25853d2a715SThierry Reding out: 25953d2a715SThierry Reding mutex_unlock(&padctl->lock); 26053d2a715SThierry Reding return 0; 26153d2a715SThierry Reding } 26253d2a715SThierry Reding 26353d2a715SThierry Reding static int tegra124_xusb_padctl_disable(struct tegra_xusb_padctl *padctl) 26453d2a715SThierry Reding { 26553d2a715SThierry Reding u32 value; 26653d2a715SThierry Reding 26753d2a715SThierry Reding mutex_lock(&padctl->lock); 26853d2a715SThierry Reding 26953d2a715SThierry Reding if (WARN_ON(padctl->enable == 0)) 27053d2a715SThierry Reding goto out; 27153d2a715SThierry Reding 27253d2a715SThierry Reding if (--padctl->enable > 0) 27353d2a715SThierry Reding goto out; 27453d2a715SThierry Reding 27553d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 27653d2a715SThierry Reding value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; 27753d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 27853d2a715SThierry Reding 27953d2a715SThierry Reding usleep_range(100, 200); 28053d2a715SThierry Reding 28153d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 28253d2a715SThierry Reding value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; 28353d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 28453d2a715SThierry Reding 28553d2a715SThierry Reding usleep_range(100, 200); 28653d2a715SThierry Reding 28753d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 28853d2a715SThierry Reding value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; 28953d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 29053d2a715SThierry Reding 29153d2a715SThierry Reding out: 29253d2a715SThierry Reding mutex_unlock(&padctl->lock); 29353d2a715SThierry Reding return 0; 29453d2a715SThierry Reding } 29553d2a715SThierry Reding 29653d2a715SThierry Reding static int tegra124_usb3_save_context(struct tegra_xusb_padctl *padctl, 29753d2a715SThierry Reding unsigned int index) 29853d2a715SThierry Reding { 29953d2a715SThierry Reding struct tegra_xusb_usb3_port *port; 30053d2a715SThierry Reding struct tegra_xusb_lane *lane; 30153d2a715SThierry Reding u32 value, offset; 30253d2a715SThierry Reding 30353d2a715SThierry Reding port = tegra_xusb_find_usb3_port(padctl, index); 30453d2a715SThierry Reding if (!port) 30553d2a715SThierry Reding return -ENODEV; 30653d2a715SThierry Reding 30753d2a715SThierry Reding port->context_saved = true; 30853d2a715SThierry Reding lane = port->base.lane; 30953d2a715SThierry Reding 31053d2a715SThierry Reding if (lane->pad == padctl->pcie) 31153d2a715SThierry Reding offset = XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL6(lane->index); 31253d2a715SThierry Reding else 31353d2a715SThierry Reding offset = XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6; 31453d2a715SThierry Reding 31553d2a715SThierry Reding value = padctl_readl(padctl, offset); 31653d2a715SThierry Reding value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK << 31753d2a715SThierry Reding XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT); 31853d2a715SThierry Reding value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_TAP << 31953d2a715SThierry Reding XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT; 32053d2a715SThierry Reding padctl_writel(padctl, value, offset); 32153d2a715SThierry Reding 32253d2a715SThierry Reding value = padctl_readl(padctl, offset) >> 32353d2a715SThierry Reding XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT; 32453d2a715SThierry Reding port->tap1 = value & XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_TAP_MASK; 32553d2a715SThierry Reding 32653d2a715SThierry Reding value = padctl_readl(padctl, offset); 32753d2a715SThierry Reding value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK << 32853d2a715SThierry Reding XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT); 32953d2a715SThierry Reding value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_AMP << 33053d2a715SThierry Reding XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT; 33153d2a715SThierry Reding padctl_writel(padctl, value, offset); 33253d2a715SThierry Reding 33353d2a715SThierry Reding value = padctl_readl(padctl, offset) >> 33453d2a715SThierry Reding XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT; 33553d2a715SThierry Reding port->amp = value & XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_AMP_MASK; 33653d2a715SThierry Reding 33753d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(index)); 33853d2a715SThierry Reding value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK << 33953d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) | 34053d2a715SThierry Reding (XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK << 34153d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT)); 34253d2a715SThierry Reding value |= (port->tap1 << 34353d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) | 34453d2a715SThierry Reding (port->amp << 34553d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT); 34653d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(index)); 34753d2a715SThierry Reding 34853d2a715SThierry Reding value = padctl_readl(padctl, offset); 34953d2a715SThierry Reding value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK << 35053d2a715SThierry Reding XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT); 35153d2a715SThierry Reding value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_LATCH_G_Z << 35253d2a715SThierry Reding XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT; 35353d2a715SThierry Reding padctl_writel(padctl, value, offset); 35453d2a715SThierry Reding 35553d2a715SThierry Reding value = padctl_readl(padctl, offset); 35653d2a715SThierry Reding value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK << 35753d2a715SThierry Reding XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT); 35853d2a715SThierry Reding value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_G_Z << 35953d2a715SThierry Reding XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT; 36053d2a715SThierry Reding padctl_writel(padctl, value, offset); 36153d2a715SThierry Reding 36253d2a715SThierry Reding value = padctl_readl(padctl, offset) >> 36353d2a715SThierry Reding XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT; 36453d2a715SThierry Reding port->ctle_g = value & 36553d2a715SThierry Reding XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK; 36653d2a715SThierry Reding 36753d2a715SThierry Reding value = padctl_readl(padctl, offset); 36853d2a715SThierry Reding value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK << 36953d2a715SThierry Reding XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT); 37053d2a715SThierry Reding value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_CTLE_Z << 37153d2a715SThierry Reding XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT; 37253d2a715SThierry Reding padctl_writel(padctl, value, offset); 37353d2a715SThierry Reding 37453d2a715SThierry Reding value = padctl_readl(padctl, offset) >> 37553d2a715SThierry Reding XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT; 37653d2a715SThierry Reding port->ctle_z = value & 37753d2a715SThierry Reding XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK; 37853d2a715SThierry Reding 37953d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index)); 38053d2a715SThierry Reding value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK << 38153d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) | 38253d2a715SThierry Reding (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK << 38353d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT)); 38453d2a715SThierry Reding value |= (port->ctle_g << 38553d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) | 38653d2a715SThierry Reding (port->ctle_z << 38753d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT); 38853d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index)); 38953d2a715SThierry Reding 39053d2a715SThierry Reding return 0; 39153d2a715SThierry Reding } 39253d2a715SThierry Reding 39353d2a715SThierry Reding static int tegra124_hsic_set_idle(struct tegra_xusb_padctl *padctl, 39453d2a715SThierry Reding unsigned int index, bool idle) 39553d2a715SThierry Reding { 39653d2a715SThierry Reding u32 value; 39753d2a715SThierry Reding 39853d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 39953d2a715SThierry Reding 40053d2a715SThierry Reding if (idle) 40153d2a715SThierry Reding value |= XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA | 40253d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE; 40353d2a715SThierry Reding else 40453d2a715SThierry Reding value &= ~(XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA | 40553d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE); 40653d2a715SThierry Reding 40753d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 40853d2a715SThierry Reding 40953d2a715SThierry Reding return 0; 41053d2a715SThierry Reding } 41153d2a715SThierry Reding 41253d2a715SThierry Reding #define TEGRA124_LANE(_name, _offset, _shift, _mask, _type) \ 41353d2a715SThierry Reding { \ 41453d2a715SThierry Reding .name = _name, \ 41553d2a715SThierry Reding .offset = _offset, \ 41653d2a715SThierry Reding .shift = _shift, \ 41753d2a715SThierry Reding .mask = _mask, \ 41853d2a715SThierry Reding .num_funcs = ARRAY_SIZE(tegra124_##_type##_functions), \ 41953d2a715SThierry Reding .funcs = tegra124_##_type##_functions, \ 42053d2a715SThierry Reding } 42153d2a715SThierry Reding 42253d2a715SThierry Reding static const char * const tegra124_usb2_functions[] = { 42353d2a715SThierry Reding "snps", 42453d2a715SThierry Reding "xusb", 42553d2a715SThierry Reding "uart", 42653d2a715SThierry Reding }; 42753d2a715SThierry Reding 42853d2a715SThierry Reding static const struct tegra_xusb_lane_soc tegra124_usb2_lanes[] = { 42953d2a715SThierry Reding TEGRA124_LANE("usb2-0", 0x004, 0, 0x3, usb2), 43053d2a715SThierry Reding TEGRA124_LANE("usb2-1", 0x004, 2, 0x3, usb2), 43153d2a715SThierry Reding TEGRA124_LANE("usb2-2", 0x004, 4, 0x3, usb2), 43253d2a715SThierry Reding }; 43353d2a715SThierry Reding 43453d2a715SThierry Reding static struct tegra_xusb_lane * 43553d2a715SThierry Reding tegra124_usb2_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 43653d2a715SThierry Reding unsigned int index) 43753d2a715SThierry Reding { 43853d2a715SThierry Reding struct tegra_xusb_usb2_lane *usb2; 43953d2a715SThierry Reding int err; 44053d2a715SThierry Reding 44153d2a715SThierry Reding usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL); 44253d2a715SThierry Reding if (!usb2) 44353d2a715SThierry Reding return ERR_PTR(-ENOMEM); 44453d2a715SThierry Reding 44553d2a715SThierry Reding INIT_LIST_HEAD(&usb2->base.list); 44653d2a715SThierry Reding usb2->base.soc = &pad->soc->lanes[index]; 44753d2a715SThierry Reding usb2->base.index = index; 44853d2a715SThierry Reding usb2->base.pad = pad; 44953d2a715SThierry Reding usb2->base.np = np; 45053d2a715SThierry Reding 45153d2a715SThierry Reding err = tegra_xusb_lane_parse_dt(&usb2->base, np); 45253d2a715SThierry Reding if (err < 0) { 45353d2a715SThierry Reding kfree(usb2); 45453d2a715SThierry Reding return ERR_PTR(err); 45553d2a715SThierry Reding } 45653d2a715SThierry Reding 45753d2a715SThierry Reding return &usb2->base; 45853d2a715SThierry Reding } 45953d2a715SThierry Reding 46053d2a715SThierry Reding static void tegra124_usb2_lane_remove(struct tegra_xusb_lane *lane) 46153d2a715SThierry Reding { 46253d2a715SThierry Reding struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane); 46353d2a715SThierry Reding 46453d2a715SThierry Reding kfree(usb2); 46553d2a715SThierry Reding } 46653d2a715SThierry Reding 46753d2a715SThierry Reding static const struct tegra_xusb_lane_ops tegra124_usb2_lane_ops = { 46853d2a715SThierry Reding .probe = tegra124_usb2_lane_probe, 46953d2a715SThierry Reding .remove = tegra124_usb2_lane_remove, 47053d2a715SThierry Reding }; 47153d2a715SThierry Reding 47253d2a715SThierry Reding static int tegra124_usb2_phy_init(struct phy *phy) 47353d2a715SThierry Reding { 47453d2a715SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 47553d2a715SThierry Reding 47653d2a715SThierry Reding return tegra124_xusb_padctl_enable(lane->pad->padctl); 47753d2a715SThierry Reding } 47853d2a715SThierry Reding 47953d2a715SThierry Reding static int tegra124_usb2_phy_exit(struct phy *phy) 48053d2a715SThierry Reding { 48153d2a715SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 48253d2a715SThierry Reding 48353d2a715SThierry Reding return tegra124_xusb_padctl_disable(lane->pad->padctl); 48453d2a715SThierry Reding } 48553d2a715SThierry Reding 48653d2a715SThierry Reding static int tegra124_usb2_phy_power_on(struct phy *phy) 48753d2a715SThierry Reding { 48853d2a715SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 48953d2a715SThierry Reding struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane); 49053d2a715SThierry Reding struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad); 49153d2a715SThierry Reding struct tegra_xusb_padctl *padctl = lane->pad->padctl; 49253d2a715SThierry Reding struct tegra124_xusb_padctl *priv; 49353d2a715SThierry Reding struct tegra_xusb_usb2_port *port; 49453d2a715SThierry Reding unsigned int index = lane->index; 49553d2a715SThierry Reding u32 value; 49653d2a715SThierry Reding int err; 49753d2a715SThierry Reding 49853d2a715SThierry Reding port = tegra_xusb_find_usb2_port(padctl, index); 49953d2a715SThierry Reding if (!port) { 50053d2a715SThierry Reding dev_err(&phy->dev, "no port found for USB2 lane %u\n", index); 50153d2a715SThierry Reding return -ENODEV; 50253d2a715SThierry Reding } 50353d2a715SThierry Reding 50453d2a715SThierry Reding priv = to_tegra124_xusb_padctl(padctl); 50553d2a715SThierry Reding 50653d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 50753d2a715SThierry Reding value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK << 50853d2a715SThierry Reding XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) | 50953d2a715SThierry Reding (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK << 51053d2a715SThierry Reding XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT)); 51153d2a715SThierry Reding value |= (priv->fuse.hs_squelch_level << 51253d2a715SThierry Reding XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) | 51353d2a715SThierry Reding (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL << 51453d2a715SThierry Reding XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT); 51553d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 51653d2a715SThierry Reding 51753d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB2_PORT_CAP); 51853d2a715SThierry Reding value &= ~(XUSB_PADCTL_USB2_PORT_CAP_PORT_CAP_MASK << 51953d2a715SThierry Reding XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(index)); 52053d2a715SThierry Reding value |= XUSB_PADCTL_USB2_PORT_CAP_HOST << 52153d2a715SThierry Reding XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(index); 52253d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB2_PORT_CAP); 52353d2a715SThierry Reding 52453d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index)); 52553d2a715SThierry Reding value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK << 52653d2a715SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT) | 52753d2a715SThierry Reding (XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_MASK << 52853d2a715SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT) | 52953d2a715SThierry Reding (XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_MASK << 53053d2a715SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT) | 53153d2a715SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD | 53253d2a715SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 | 53353d2a715SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI); 53453d2a715SThierry Reding value |= (priv->fuse.hs_curr_level[index] + 53553d2a715SThierry Reding usb2->hs_curr_level_offset) << 53653d2a715SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT; 53753d2a715SThierry Reding value |= XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_VAL << 53853d2a715SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT; 53953d2a715SThierry Reding value |= XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_VAL(index) << 54053d2a715SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT; 54153d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index)); 54253d2a715SThierry Reding 54353d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index)); 54453d2a715SThierry Reding value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK << 54553d2a715SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) | 54653d2a715SThierry Reding (XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_MASK << 54753d2a715SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT) | 54853d2a715SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR | 54953d2a715SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP | 55053d2a715SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP); 55153d2a715SThierry Reding value |= (priv->fuse.hs_term_range_adj << 55253d2a715SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) | 55353d2a715SThierry Reding (priv->fuse.hs_iref_cap << 55453d2a715SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT); 55553d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index)); 55653d2a715SThierry Reding 55753d2a715SThierry Reding err = regulator_enable(port->supply); 55853d2a715SThierry Reding if (err) 55953d2a715SThierry Reding return err; 56053d2a715SThierry Reding 56153d2a715SThierry Reding mutex_lock(&pad->lock); 56253d2a715SThierry Reding 56353d2a715SThierry Reding if (pad->enable++ > 0) 56453d2a715SThierry Reding goto out; 56553d2a715SThierry Reding 56653d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 56753d2a715SThierry Reding value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD; 56853d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 56953d2a715SThierry Reding 57053d2a715SThierry Reding out: 57153d2a715SThierry Reding mutex_unlock(&pad->lock); 57253d2a715SThierry Reding return 0; 57353d2a715SThierry Reding } 57453d2a715SThierry Reding 57553d2a715SThierry Reding static int tegra124_usb2_phy_power_off(struct phy *phy) 57653d2a715SThierry Reding { 57753d2a715SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 57853d2a715SThierry Reding struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad); 57953d2a715SThierry Reding struct tegra_xusb_padctl *padctl = lane->pad->padctl; 58053d2a715SThierry Reding struct tegra_xusb_usb2_port *port; 58153d2a715SThierry Reding u32 value; 58253d2a715SThierry Reding 58353d2a715SThierry Reding port = tegra_xusb_find_usb2_port(padctl, lane->index); 58453d2a715SThierry Reding if (!port) { 58553d2a715SThierry Reding dev_err(&phy->dev, "no port found for USB2 lane %u\n", 58653d2a715SThierry Reding lane->index); 58753d2a715SThierry Reding return -ENODEV; 58853d2a715SThierry Reding } 58953d2a715SThierry Reding 59053d2a715SThierry Reding mutex_lock(&pad->lock); 59153d2a715SThierry Reding 59253d2a715SThierry Reding if (WARN_ON(pad->enable == 0)) 59353d2a715SThierry Reding goto out; 59453d2a715SThierry Reding 59553d2a715SThierry Reding if (--pad->enable > 0) 59653d2a715SThierry Reding goto out; 59753d2a715SThierry Reding 59853d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 59953d2a715SThierry Reding value |= XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD; 60053d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 60153d2a715SThierry Reding 60253d2a715SThierry Reding out: 60353d2a715SThierry Reding regulator_disable(port->supply); 60453d2a715SThierry Reding mutex_unlock(&pad->lock); 60553d2a715SThierry Reding return 0; 60653d2a715SThierry Reding } 60753d2a715SThierry Reding 60853d2a715SThierry Reding static const struct phy_ops tegra124_usb2_phy_ops = { 60953d2a715SThierry Reding .init = tegra124_usb2_phy_init, 61053d2a715SThierry Reding .exit = tegra124_usb2_phy_exit, 61153d2a715SThierry Reding .power_on = tegra124_usb2_phy_power_on, 61253d2a715SThierry Reding .power_off = tegra124_usb2_phy_power_off, 61353d2a715SThierry Reding .owner = THIS_MODULE, 61453d2a715SThierry Reding }; 61553d2a715SThierry Reding 61653d2a715SThierry Reding static struct tegra_xusb_pad * 61753d2a715SThierry Reding tegra124_usb2_pad_probe(struct tegra_xusb_padctl *padctl, 61853d2a715SThierry Reding const struct tegra_xusb_pad_soc *soc, 61953d2a715SThierry Reding struct device_node *np) 62053d2a715SThierry Reding { 62153d2a715SThierry Reding struct tegra_xusb_usb2_pad *usb2; 62253d2a715SThierry Reding struct tegra_xusb_pad *pad; 62353d2a715SThierry Reding int err; 62453d2a715SThierry Reding 62553d2a715SThierry Reding usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL); 62653d2a715SThierry Reding if (!usb2) 62753d2a715SThierry Reding return ERR_PTR(-ENOMEM); 62853d2a715SThierry Reding 62953d2a715SThierry Reding mutex_init(&usb2->lock); 63053d2a715SThierry Reding 63153d2a715SThierry Reding pad = &usb2->base; 63253d2a715SThierry Reding pad->ops = &tegra124_usb2_lane_ops; 63353d2a715SThierry Reding pad->soc = soc; 63453d2a715SThierry Reding 63553d2a715SThierry Reding err = tegra_xusb_pad_init(pad, padctl, np); 63653d2a715SThierry Reding if (err < 0) { 63753d2a715SThierry Reding kfree(usb2); 63853d2a715SThierry Reding goto out; 63953d2a715SThierry Reding } 64053d2a715SThierry Reding 64153d2a715SThierry Reding err = tegra_xusb_pad_register(pad, &tegra124_usb2_phy_ops); 64253d2a715SThierry Reding if (err < 0) 64353d2a715SThierry Reding goto unregister; 64453d2a715SThierry Reding 64553d2a715SThierry Reding dev_set_drvdata(&pad->dev, pad); 64653d2a715SThierry Reding 64753d2a715SThierry Reding return pad; 64853d2a715SThierry Reding 64953d2a715SThierry Reding unregister: 65053d2a715SThierry Reding device_unregister(&pad->dev); 65153d2a715SThierry Reding out: 65253d2a715SThierry Reding return ERR_PTR(err); 65353d2a715SThierry Reding } 65453d2a715SThierry Reding 65553d2a715SThierry Reding static void tegra124_usb2_pad_remove(struct tegra_xusb_pad *pad) 65653d2a715SThierry Reding { 65753d2a715SThierry Reding struct tegra_xusb_usb2_pad *usb2 = to_usb2_pad(pad); 65853d2a715SThierry Reding 65953d2a715SThierry Reding kfree(usb2); 66053d2a715SThierry Reding } 66153d2a715SThierry Reding 66253d2a715SThierry Reding static const struct tegra_xusb_pad_ops tegra124_usb2_ops = { 66353d2a715SThierry Reding .probe = tegra124_usb2_pad_probe, 66453d2a715SThierry Reding .remove = tegra124_usb2_pad_remove, 66553d2a715SThierry Reding }; 66653d2a715SThierry Reding 66753d2a715SThierry Reding static const struct tegra_xusb_pad_soc tegra124_usb2_pad = { 66853d2a715SThierry Reding .name = "usb2", 66953d2a715SThierry Reding .num_lanes = ARRAY_SIZE(tegra124_usb2_lanes), 67053d2a715SThierry Reding .lanes = tegra124_usb2_lanes, 67153d2a715SThierry Reding .ops = &tegra124_usb2_ops, 67253d2a715SThierry Reding }; 67353d2a715SThierry Reding 67453d2a715SThierry Reding static const char * const tegra124_ulpi_functions[] = { 67553d2a715SThierry Reding "snps", 67653d2a715SThierry Reding "xusb", 67753d2a715SThierry Reding }; 67853d2a715SThierry Reding 67953d2a715SThierry Reding static const struct tegra_xusb_lane_soc tegra124_ulpi_lanes[] = { 68053d2a715SThierry Reding TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, ulpi), 68153d2a715SThierry Reding }; 68253d2a715SThierry Reding 68353d2a715SThierry Reding static struct tegra_xusb_lane * 68453d2a715SThierry Reding tegra124_ulpi_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 68553d2a715SThierry Reding unsigned int index) 68653d2a715SThierry Reding { 68753d2a715SThierry Reding struct tegra_xusb_ulpi_lane *ulpi; 68853d2a715SThierry Reding int err; 68953d2a715SThierry Reding 69053d2a715SThierry Reding ulpi = kzalloc(sizeof(*ulpi), GFP_KERNEL); 69153d2a715SThierry Reding if (!ulpi) 69253d2a715SThierry Reding return ERR_PTR(-ENOMEM); 69353d2a715SThierry Reding 69453d2a715SThierry Reding INIT_LIST_HEAD(&ulpi->base.list); 69553d2a715SThierry Reding ulpi->base.soc = &pad->soc->lanes[index]; 69653d2a715SThierry Reding ulpi->base.index = index; 69753d2a715SThierry Reding ulpi->base.pad = pad; 69853d2a715SThierry Reding ulpi->base.np = np; 69953d2a715SThierry Reding 70053d2a715SThierry Reding err = tegra_xusb_lane_parse_dt(&ulpi->base, np); 70153d2a715SThierry Reding if (err < 0) { 70253d2a715SThierry Reding kfree(ulpi); 70353d2a715SThierry Reding return ERR_PTR(err); 70453d2a715SThierry Reding } 70553d2a715SThierry Reding 70653d2a715SThierry Reding return &ulpi->base; 70753d2a715SThierry Reding } 70853d2a715SThierry Reding 70953d2a715SThierry Reding static void tegra124_ulpi_lane_remove(struct tegra_xusb_lane *lane) 71053d2a715SThierry Reding { 71153d2a715SThierry Reding struct tegra_xusb_ulpi_lane *ulpi = to_ulpi_lane(lane); 71253d2a715SThierry Reding 71353d2a715SThierry Reding kfree(ulpi); 71453d2a715SThierry Reding } 71553d2a715SThierry Reding 71653d2a715SThierry Reding static const struct tegra_xusb_lane_ops tegra124_ulpi_lane_ops = { 71753d2a715SThierry Reding .probe = tegra124_ulpi_lane_probe, 71853d2a715SThierry Reding .remove = tegra124_ulpi_lane_remove, 71953d2a715SThierry Reding }; 72053d2a715SThierry Reding 72153d2a715SThierry Reding static int tegra124_ulpi_phy_init(struct phy *phy) 72253d2a715SThierry Reding { 72353d2a715SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 72453d2a715SThierry Reding 72553d2a715SThierry Reding return tegra124_xusb_padctl_enable(lane->pad->padctl); 72653d2a715SThierry Reding } 72753d2a715SThierry Reding 72853d2a715SThierry Reding static int tegra124_ulpi_phy_exit(struct phy *phy) 72953d2a715SThierry Reding { 73053d2a715SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 73153d2a715SThierry Reding 73253d2a715SThierry Reding return tegra124_xusb_padctl_disable(lane->pad->padctl); 73353d2a715SThierry Reding } 73453d2a715SThierry Reding 73553d2a715SThierry Reding static int tegra124_ulpi_phy_power_on(struct phy *phy) 73653d2a715SThierry Reding { 73753d2a715SThierry Reding return 0; 73853d2a715SThierry Reding } 73953d2a715SThierry Reding 74053d2a715SThierry Reding static int tegra124_ulpi_phy_power_off(struct phy *phy) 74153d2a715SThierry Reding { 74253d2a715SThierry Reding return 0; 74353d2a715SThierry Reding } 74453d2a715SThierry Reding 74553d2a715SThierry Reding static const struct phy_ops tegra124_ulpi_phy_ops = { 74653d2a715SThierry Reding .init = tegra124_ulpi_phy_init, 74753d2a715SThierry Reding .exit = tegra124_ulpi_phy_exit, 74853d2a715SThierry Reding .power_on = tegra124_ulpi_phy_power_on, 74953d2a715SThierry Reding .power_off = tegra124_ulpi_phy_power_off, 75053d2a715SThierry Reding .owner = THIS_MODULE, 75153d2a715SThierry Reding }; 75253d2a715SThierry Reding 75353d2a715SThierry Reding static struct tegra_xusb_pad * 75453d2a715SThierry Reding tegra124_ulpi_pad_probe(struct tegra_xusb_padctl *padctl, 75553d2a715SThierry Reding const struct tegra_xusb_pad_soc *soc, 75653d2a715SThierry Reding struct device_node *np) 75753d2a715SThierry Reding { 75853d2a715SThierry Reding struct tegra_xusb_ulpi_pad *ulpi; 75953d2a715SThierry Reding struct tegra_xusb_pad *pad; 76053d2a715SThierry Reding int err; 76153d2a715SThierry Reding 76253d2a715SThierry Reding ulpi = kzalloc(sizeof(*ulpi), GFP_KERNEL); 76353d2a715SThierry Reding if (!ulpi) 76453d2a715SThierry Reding return ERR_PTR(-ENOMEM); 76553d2a715SThierry Reding 76653d2a715SThierry Reding pad = &ulpi->base; 76753d2a715SThierry Reding pad->ops = &tegra124_ulpi_lane_ops; 76853d2a715SThierry Reding pad->soc = soc; 76953d2a715SThierry Reding 77053d2a715SThierry Reding err = tegra_xusb_pad_init(pad, padctl, np); 77153d2a715SThierry Reding if (err < 0) { 77253d2a715SThierry Reding kfree(ulpi); 77353d2a715SThierry Reding goto out; 77453d2a715SThierry Reding } 77553d2a715SThierry Reding 77653d2a715SThierry Reding err = tegra_xusb_pad_register(pad, &tegra124_ulpi_phy_ops); 77753d2a715SThierry Reding if (err < 0) 77853d2a715SThierry Reding goto unregister; 77953d2a715SThierry Reding 78053d2a715SThierry Reding dev_set_drvdata(&pad->dev, pad); 78153d2a715SThierry Reding 78253d2a715SThierry Reding return pad; 78353d2a715SThierry Reding 78453d2a715SThierry Reding unregister: 78553d2a715SThierry Reding device_unregister(&pad->dev); 78653d2a715SThierry Reding out: 78753d2a715SThierry Reding return ERR_PTR(err); 78853d2a715SThierry Reding } 78953d2a715SThierry Reding 79053d2a715SThierry Reding static void tegra124_ulpi_pad_remove(struct tegra_xusb_pad *pad) 79153d2a715SThierry Reding { 79253d2a715SThierry Reding struct tegra_xusb_ulpi_pad *ulpi = to_ulpi_pad(pad); 79353d2a715SThierry Reding 79453d2a715SThierry Reding kfree(ulpi); 79553d2a715SThierry Reding } 79653d2a715SThierry Reding 79753d2a715SThierry Reding static const struct tegra_xusb_pad_ops tegra124_ulpi_ops = { 79853d2a715SThierry Reding .probe = tegra124_ulpi_pad_probe, 79953d2a715SThierry Reding .remove = tegra124_ulpi_pad_remove, 80053d2a715SThierry Reding }; 80153d2a715SThierry Reding 80253d2a715SThierry Reding static const struct tegra_xusb_pad_soc tegra124_ulpi_pad = { 80353d2a715SThierry Reding .name = "ulpi", 80453d2a715SThierry Reding .num_lanes = ARRAY_SIZE(tegra124_ulpi_lanes), 80553d2a715SThierry Reding .lanes = tegra124_ulpi_lanes, 80653d2a715SThierry Reding .ops = &tegra124_ulpi_ops, 80753d2a715SThierry Reding }; 80853d2a715SThierry Reding 80953d2a715SThierry Reding static const char * const tegra124_hsic_functions[] = { 81053d2a715SThierry Reding "snps", 81153d2a715SThierry Reding "xusb", 81253d2a715SThierry Reding }; 81353d2a715SThierry Reding 81453d2a715SThierry Reding static const struct tegra_xusb_lane_soc tegra124_hsic_lanes[] = { 81553d2a715SThierry Reding TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, hsic), 81653d2a715SThierry Reding TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, hsic), 81753d2a715SThierry Reding }; 81853d2a715SThierry Reding 81953d2a715SThierry Reding static struct tegra_xusb_lane * 82053d2a715SThierry Reding tegra124_hsic_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 82153d2a715SThierry Reding unsigned int index) 82253d2a715SThierry Reding { 82353d2a715SThierry Reding struct tegra_xusb_hsic_lane *hsic; 82453d2a715SThierry Reding int err; 82553d2a715SThierry Reding 82653d2a715SThierry Reding hsic = kzalloc(sizeof(*hsic), GFP_KERNEL); 82753d2a715SThierry Reding if (!hsic) 82853d2a715SThierry Reding return ERR_PTR(-ENOMEM); 82953d2a715SThierry Reding 83053d2a715SThierry Reding INIT_LIST_HEAD(&hsic->base.list); 83153d2a715SThierry Reding hsic->base.soc = &pad->soc->lanes[index]; 83253d2a715SThierry Reding hsic->base.index = index; 83353d2a715SThierry Reding hsic->base.pad = pad; 83453d2a715SThierry Reding hsic->base.np = np; 83553d2a715SThierry Reding 83653d2a715SThierry Reding err = tegra_xusb_lane_parse_dt(&hsic->base, np); 83753d2a715SThierry Reding if (err < 0) { 83853d2a715SThierry Reding kfree(hsic); 83953d2a715SThierry Reding return ERR_PTR(err); 84053d2a715SThierry Reding } 84153d2a715SThierry Reding 84253d2a715SThierry Reding return &hsic->base; 84353d2a715SThierry Reding } 84453d2a715SThierry Reding 84553d2a715SThierry Reding static void tegra124_hsic_lane_remove(struct tegra_xusb_lane *lane) 84653d2a715SThierry Reding { 84753d2a715SThierry Reding struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane); 84853d2a715SThierry Reding 84953d2a715SThierry Reding kfree(hsic); 85053d2a715SThierry Reding } 85153d2a715SThierry Reding 85253d2a715SThierry Reding static const struct tegra_xusb_lane_ops tegra124_hsic_lane_ops = { 85353d2a715SThierry Reding .probe = tegra124_hsic_lane_probe, 85453d2a715SThierry Reding .remove = tegra124_hsic_lane_remove, 85553d2a715SThierry Reding }; 85653d2a715SThierry Reding 85753d2a715SThierry Reding static int tegra124_hsic_phy_init(struct phy *phy) 85853d2a715SThierry Reding { 85953d2a715SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 86053d2a715SThierry Reding 86153d2a715SThierry Reding return tegra124_xusb_padctl_enable(lane->pad->padctl); 86253d2a715SThierry Reding } 86353d2a715SThierry Reding 86453d2a715SThierry Reding static int tegra124_hsic_phy_exit(struct phy *phy) 86553d2a715SThierry Reding { 86653d2a715SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 86753d2a715SThierry Reding 86853d2a715SThierry Reding return tegra124_xusb_padctl_disable(lane->pad->padctl); 86953d2a715SThierry Reding } 87053d2a715SThierry Reding 87153d2a715SThierry Reding static int tegra124_hsic_phy_power_on(struct phy *phy) 87253d2a715SThierry Reding { 87353d2a715SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 87453d2a715SThierry Reding struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane); 87553d2a715SThierry Reding struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad); 87653d2a715SThierry Reding struct tegra_xusb_padctl *padctl = lane->pad->padctl; 87753d2a715SThierry Reding unsigned int index = lane->index; 87853d2a715SThierry Reding u32 value; 87953d2a715SThierry Reding int err; 88053d2a715SThierry Reding 88153d2a715SThierry Reding err = regulator_enable(pad->supply); 88253d2a715SThierry Reding if (err) 88353d2a715SThierry Reding return err; 88453d2a715SThierry Reding 88553d2a715SThierry Reding padctl_writel(padctl, hsic->strobe_trim, 88653d2a715SThierry Reding XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL); 88753d2a715SThierry Reding 88853d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 88953d2a715SThierry Reding 89053d2a715SThierry Reding if (hsic->auto_term) 89153d2a715SThierry Reding value |= XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN; 89253d2a715SThierry Reding else 89353d2a715SThierry Reding value &= ~XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN; 89453d2a715SThierry Reding 89553d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 89653d2a715SThierry Reding 89753d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(index)); 89853d2a715SThierry Reding value &= ~((XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_MASK << 89953d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT) | 90053d2a715SThierry Reding (XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_MASK << 90153d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT) | 90253d2a715SThierry Reding (XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_MASK << 90353d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT) | 90453d2a715SThierry Reding (XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_MASK << 90553d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT)); 90653d2a715SThierry Reding value |= (hsic->tx_rtune_n << 90753d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT) | 90853d2a715SThierry Reding (hsic->tx_rtune_p << 90953d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT) | 91053d2a715SThierry Reding (hsic->tx_rslew_n << 91153d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT) | 91253d2a715SThierry Reding (hsic->tx_rslew_p << 91353d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT); 91453d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL0(index)); 91553d2a715SThierry Reding 91653d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL2(index)); 91753d2a715SThierry Reding value &= ~((XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK << 91853d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) | 91953d2a715SThierry Reding (XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK << 92053d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT)); 92153d2a715SThierry Reding value |= (hsic->rx_strobe_trim << 92253d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) | 92353d2a715SThierry Reding (hsic->rx_data_trim << 92453d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT); 92553d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL2(index)); 92653d2a715SThierry Reding 92753d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 92853d2a715SThierry Reding value &= ~(XUSB_PADCTL_HSIC_PAD_CTL1_RPD_STROBE | 92953d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL1_RPU_DATA | 93053d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX | 93153d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI | 93253d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX | 93353d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX); 93453d2a715SThierry Reding value |= XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA | 93553d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE; 93653d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 93753d2a715SThierry Reding 93853d2a715SThierry Reding return 0; 93953d2a715SThierry Reding } 94053d2a715SThierry Reding 94153d2a715SThierry Reding static int tegra124_hsic_phy_power_off(struct phy *phy) 94253d2a715SThierry Reding { 94353d2a715SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 94453d2a715SThierry Reding struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad); 94553d2a715SThierry Reding struct tegra_xusb_padctl *padctl = lane->pad->padctl; 94653d2a715SThierry Reding unsigned int index = lane->index; 94753d2a715SThierry Reding u32 value; 94853d2a715SThierry Reding 94953d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 95053d2a715SThierry Reding value |= XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX | 95153d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI | 95253d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX | 95353d2a715SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX; 95453d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 95553d2a715SThierry Reding 95653d2a715SThierry Reding regulator_disable(pad->supply); 95753d2a715SThierry Reding 95853d2a715SThierry Reding return 0; 95953d2a715SThierry Reding } 96053d2a715SThierry Reding 96153d2a715SThierry Reding static const struct phy_ops tegra124_hsic_phy_ops = { 96253d2a715SThierry Reding .init = tegra124_hsic_phy_init, 96353d2a715SThierry Reding .exit = tegra124_hsic_phy_exit, 96453d2a715SThierry Reding .power_on = tegra124_hsic_phy_power_on, 96553d2a715SThierry Reding .power_off = tegra124_hsic_phy_power_off, 96653d2a715SThierry Reding .owner = THIS_MODULE, 96753d2a715SThierry Reding }; 96853d2a715SThierry Reding 96953d2a715SThierry Reding static struct tegra_xusb_pad * 97053d2a715SThierry Reding tegra124_hsic_pad_probe(struct tegra_xusb_padctl *padctl, 97153d2a715SThierry Reding const struct tegra_xusb_pad_soc *soc, 97253d2a715SThierry Reding struct device_node *np) 97353d2a715SThierry Reding { 97453d2a715SThierry Reding struct tegra_xusb_hsic_pad *hsic; 97553d2a715SThierry Reding struct tegra_xusb_pad *pad; 97653d2a715SThierry Reding int err; 97753d2a715SThierry Reding 97853d2a715SThierry Reding hsic = kzalloc(sizeof(*hsic), GFP_KERNEL); 97953d2a715SThierry Reding if (!hsic) 98053d2a715SThierry Reding return ERR_PTR(-ENOMEM); 98153d2a715SThierry Reding 98253d2a715SThierry Reding pad = &hsic->base; 98353d2a715SThierry Reding pad->ops = &tegra124_hsic_lane_ops; 98453d2a715SThierry Reding pad->soc = soc; 98553d2a715SThierry Reding 98653d2a715SThierry Reding err = tegra_xusb_pad_init(pad, padctl, np); 98753d2a715SThierry Reding if (err < 0) { 98853d2a715SThierry Reding kfree(hsic); 98953d2a715SThierry Reding goto out; 99053d2a715SThierry Reding } 99153d2a715SThierry Reding 99253d2a715SThierry Reding err = tegra_xusb_pad_register(pad, &tegra124_hsic_phy_ops); 99353d2a715SThierry Reding if (err < 0) 99453d2a715SThierry Reding goto unregister; 99553d2a715SThierry Reding 99653d2a715SThierry Reding dev_set_drvdata(&pad->dev, pad); 99753d2a715SThierry Reding 99853d2a715SThierry Reding return pad; 99953d2a715SThierry Reding 100053d2a715SThierry Reding unregister: 100153d2a715SThierry Reding device_unregister(&pad->dev); 100253d2a715SThierry Reding out: 100353d2a715SThierry Reding return ERR_PTR(err); 100453d2a715SThierry Reding } 100553d2a715SThierry Reding 100653d2a715SThierry Reding static void tegra124_hsic_pad_remove(struct tegra_xusb_pad *pad) 100753d2a715SThierry Reding { 100853d2a715SThierry Reding struct tegra_xusb_hsic_pad *hsic = to_hsic_pad(pad); 100953d2a715SThierry Reding 101053d2a715SThierry Reding kfree(hsic); 101153d2a715SThierry Reding } 101253d2a715SThierry Reding 101353d2a715SThierry Reding static const struct tegra_xusb_pad_ops tegra124_hsic_ops = { 101453d2a715SThierry Reding .probe = tegra124_hsic_pad_probe, 101553d2a715SThierry Reding .remove = tegra124_hsic_pad_remove, 101653d2a715SThierry Reding }; 101753d2a715SThierry Reding 101853d2a715SThierry Reding static const struct tegra_xusb_pad_soc tegra124_hsic_pad = { 101953d2a715SThierry Reding .name = "hsic", 102053d2a715SThierry Reding .num_lanes = ARRAY_SIZE(tegra124_hsic_lanes), 102153d2a715SThierry Reding .lanes = tegra124_hsic_lanes, 102253d2a715SThierry Reding .ops = &tegra124_hsic_ops, 102353d2a715SThierry Reding }; 102453d2a715SThierry Reding 102553d2a715SThierry Reding static const char * const tegra124_pcie_functions[] = { 102653d2a715SThierry Reding "pcie", 102753d2a715SThierry Reding "usb3-ss", 102853d2a715SThierry Reding "sata", 102953d2a715SThierry Reding }; 103053d2a715SThierry Reding 103153d2a715SThierry Reding static const struct tegra_xusb_lane_soc tegra124_pcie_lanes[] = { 103253d2a715SThierry Reding TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, pcie), 103353d2a715SThierry Reding TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, pcie), 103453d2a715SThierry Reding TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, pcie), 103553d2a715SThierry Reding TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, pcie), 103653d2a715SThierry Reding TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, pcie), 103753d2a715SThierry Reding }; 103853d2a715SThierry Reding 103953d2a715SThierry Reding static struct tegra_xusb_lane * 104053d2a715SThierry Reding tegra124_pcie_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 104153d2a715SThierry Reding unsigned int index) 104253d2a715SThierry Reding { 104353d2a715SThierry Reding struct tegra_xusb_pcie_lane *pcie; 104453d2a715SThierry Reding int err; 104553d2a715SThierry Reding 104653d2a715SThierry Reding pcie = kzalloc(sizeof(*pcie), GFP_KERNEL); 104753d2a715SThierry Reding if (!pcie) 104853d2a715SThierry Reding return ERR_PTR(-ENOMEM); 104953d2a715SThierry Reding 105053d2a715SThierry Reding INIT_LIST_HEAD(&pcie->base.list); 105153d2a715SThierry Reding pcie->base.soc = &pad->soc->lanes[index]; 105253d2a715SThierry Reding pcie->base.index = index; 105353d2a715SThierry Reding pcie->base.pad = pad; 105453d2a715SThierry Reding pcie->base.np = np; 105553d2a715SThierry Reding 105653d2a715SThierry Reding err = tegra_xusb_lane_parse_dt(&pcie->base, np); 105753d2a715SThierry Reding if (err < 0) { 105853d2a715SThierry Reding kfree(pcie); 105953d2a715SThierry Reding return ERR_PTR(err); 106053d2a715SThierry Reding } 106153d2a715SThierry Reding 106253d2a715SThierry Reding return &pcie->base; 106353d2a715SThierry Reding } 106453d2a715SThierry Reding 106553d2a715SThierry Reding static void tegra124_pcie_lane_remove(struct tegra_xusb_lane *lane) 106653d2a715SThierry Reding { 106753d2a715SThierry Reding struct tegra_xusb_pcie_lane *pcie = to_pcie_lane(lane); 106853d2a715SThierry Reding 106953d2a715SThierry Reding kfree(pcie); 107053d2a715SThierry Reding } 107153d2a715SThierry Reding 107253d2a715SThierry Reding static const struct tegra_xusb_lane_ops tegra124_pcie_lane_ops = { 107353d2a715SThierry Reding .probe = tegra124_pcie_lane_probe, 107453d2a715SThierry Reding .remove = tegra124_pcie_lane_remove, 107553d2a715SThierry Reding }; 107653d2a715SThierry Reding 107753d2a715SThierry Reding static int tegra124_pcie_phy_init(struct phy *phy) 107853d2a715SThierry Reding { 107953d2a715SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 108053d2a715SThierry Reding 108153d2a715SThierry Reding return tegra124_xusb_padctl_enable(lane->pad->padctl); 108253d2a715SThierry Reding } 108353d2a715SThierry Reding 108453d2a715SThierry Reding static int tegra124_pcie_phy_exit(struct phy *phy) 108553d2a715SThierry Reding { 108653d2a715SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 108753d2a715SThierry Reding 108853d2a715SThierry Reding return tegra124_xusb_padctl_disable(lane->pad->padctl); 108953d2a715SThierry Reding } 109053d2a715SThierry Reding 109153d2a715SThierry Reding static int tegra124_pcie_phy_power_on(struct phy *phy) 109253d2a715SThierry Reding { 109353d2a715SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 109453d2a715SThierry Reding struct tegra_xusb_padctl *padctl = lane->pad->padctl; 109553d2a715SThierry Reding unsigned long timeout; 109653d2a715SThierry Reding int err = -ETIMEDOUT; 109753d2a715SThierry Reding u32 value; 109853d2a715SThierry Reding 109953d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); 110053d2a715SThierry Reding value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK; 110153d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); 110253d2a715SThierry Reding 110353d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); 110453d2a715SThierry Reding value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN | 110553d2a715SThierry Reding XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN | 110653d2a715SThierry Reding XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL; 110753d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); 110853d2a715SThierry Reding 110953d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); 111053d2a715SThierry Reding value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST; 111153d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); 111253d2a715SThierry Reding 111353d2a715SThierry Reding timeout = jiffies + msecs_to_jiffies(50); 111453d2a715SThierry Reding 111553d2a715SThierry Reding while (time_before(jiffies, timeout)) { 111653d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); 111753d2a715SThierry Reding if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) { 111853d2a715SThierry Reding err = 0; 111953d2a715SThierry Reding break; 112053d2a715SThierry Reding } 112153d2a715SThierry Reding 112253d2a715SThierry Reding usleep_range(100, 200); 112353d2a715SThierry Reding } 112453d2a715SThierry Reding 112553d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); 112653d2a715SThierry Reding value |= XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index); 112753d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); 112853d2a715SThierry Reding 112953d2a715SThierry Reding return err; 113053d2a715SThierry Reding } 113153d2a715SThierry Reding 113253d2a715SThierry Reding static int tegra124_pcie_phy_power_off(struct phy *phy) 113353d2a715SThierry Reding { 113453d2a715SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 113553d2a715SThierry Reding struct tegra_xusb_padctl *padctl = lane->pad->padctl; 113653d2a715SThierry Reding u32 value; 113753d2a715SThierry Reding 113853d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); 113953d2a715SThierry Reding value &= ~XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index); 114053d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); 114153d2a715SThierry Reding 114253d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); 114353d2a715SThierry Reding value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST; 114453d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); 114553d2a715SThierry Reding 114653d2a715SThierry Reding return 0; 114753d2a715SThierry Reding } 114853d2a715SThierry Reding 114953d2a715SThierry Reding static const struct phy_ops tegra124_pcie_phy_ops = { 115053d2a715SThierry Reding .init = tegra124_pcie_phy_init, 115153d2a715SThierry Reding .exit = tegra124_pcie_phy_exit, 115253d2a715SThierry Reding .power_on = tegra124_pcie_phy_power_on, 115353d2a715SThierry Reding .power_off = tegra124_pcie_phy_power_off, 115453d2a715SThierry Reding .owner = THIS_MODULE, 115553d2a715SThierry Reding }; 115653d2a715SThierry Reding 115753d2a715SThierry Reding static struct tegra_xusb_pad * 115853d2a715SThierry Reding tegra124_pcie_pad_probe(struct tegra_xusb_padctl *padctl, 115953d2a715SThierry Reding const struct tegra_xusb_pad_soc *soc, 116053d2a715SThierry Reding struct device_node *np) 116153d2a715SThierry Reding { 116253d2a715SThierry Reding struct tegra_xusb_pcie_pad *pcie; 116353d2a715SThierry Reding struct tegra_xusb_pad *pad; 116453d2a715SThierry Reding int err; 116553d2a715SThierry Reding 116653d2a715SThierry Reding pcie = kzalloc(sizeof(*pcie), GFP_KERNEL); 116753d2a715SThierry Reding if (!pcie) 116853d2a715SThierry Reding return ERR_PTR(-ENOMEM); 116953d2a715SThierry Reding 117053d2a715SThierry Reding pad = &pcie->base; 117153d2a715SThierry Reding pad->ops = &tegra124_pcie_lane_ops; 117253d2a715SThierry Reding pad->soc = soc; 117353d2a715SThierry Reding 117453d2a715SThierry Reding err = tegra_xusb_pad_init(pad, padctl, np); 117553d2a715SThierry Reding if (err < 0) { 117653d2a715SThierry Reding kfree(pcie); 117753d2a715SThierry Reding goto out; 117853d2a715SThierry Reding } 117953d2a715SThierry Reding 118053d2a715SThierry Reding err = tegra_xusb_pad_register(pad, &tegra124_pcie_phy_ops); 118153d2a715SThierry Reding if (err < 0) 118253d2a715SThierry Reding goto unregister; 118353d2a715SThierry Reding 118453d2a715SThierry Reding dev_set_drvdata(&pad->dev, pad); 118553d2a715SThierry Reding 118653d2a715SThierry Reding return pad; 118753d2a715SThierry Reding 118853d2a715SThierry Reding unregister: 118953d2a715SThierry Reding device_unregister(&pad->dev); 119053d2a715SThierry Reding out: 119153d2a715SThierry Reding return ERR_PTR(err); 119253d2a715SThierry Reding } 119353d2a715SThierry Reding 119453d2a715SThierry Reding static void tegra124_pcie_pad_remove(struct tegra_xusb_pad *pad) 119553d2a715SThierry Reding { 119653d2a715SThierry Reding struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(pad); 119753d2a715SThierry Reding 119853d2a715SThierry Reding kfree(pcie); 119953d2a715SThierry Reding } 120053d2a715SThierry Reding 120153d2a715SThierry Reding static const struct tegra_xusb_pad_ops tegra124_pcie_ops = { 120253d2a715SThierry Reding .probe = tegra124_pcie_pad_probe, 120353d2a715SThierry Reding .remove = tegra124_pcie_pad_remove, 120453d2a715SThierry Reding }; 120553d2a715SThierry Reding 120653d2a715SThierry Reding static const struct tegra_xusb_pad_soc tegra124_pcie_pad = { 120753d2a715SThierry Reding .name = "pcie", 120853d2a715SThierry Reding .num_lanes = ARRAY_SIZE(tegra124_pcie_lanes), 120953d2a715SThierry Reding .lanes = tegra124_pcie_lanes, 121053d2a715SThierry Reding .ops = &tegra124_pcie_ops, 121153d2a715SThierry Reding }; 121253d2a715SThierry Reding 121353d2a715SThierry Reding static const struct tegra_xusb_lane_soc tegra124_sata_lanes[] = { 121453d2a715SThierry Reding TEGRA124_LANE("sata-0", 0x134, 26, 0x3, pcie), 121553d2a715SThierry Reding }; 121653d2a715SThierry Reding 121753d2a715SThierry Reding static struct tegra_xusb_lane * 121853d2a715SThierry Reding tegra124_sata_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 121953d2a715SThierry Reding unsigned int index) 122053d2a715SThierry Reding { 122153d2a715SThierry Reding struct tegra_xusb_sata_lane *sata; 122253d2a715SThierry Reding int err; 122353d2a715SThierry Reding 122453d2a715SThierry Reding sata = kzalloc(sizeof(*sata), GFP_KERNEL); 122553d2a715SThierry Reding if (!sata) 122653d2a715SThierry Reding return ERR_PTR(-ENOMEM); 122753d2a715SThierry Reding 122853d2a715SThierry Reding INIT_LIST_HEAD(&sata->base.list); 122953d2a715SThierry Reding sata->base.soc = &pad->soc->lanes[index]; 123053d2a715SThierry Reding sata->base.index = index; 123153d2a715SThierry Reding sata->base.pad = pad; 123253d2a715SThierry Reding sata->base.np = np; 123353d2a715SThierry Reding 123453d2a715SThierry Reding err = tegra_xusb_lane_parse_dt(&sata->base, np); 123553d2a715SThierry Reding if (err < 0) { 123653d2a715SThierry Reding kfree(sata); 123753d2a715SThierry Reding return ERR_PTR(err); 123853d2a715SThierry Reding } 123953d2a715SThierry Reding 124053d2a715SThierry Reding return &sata->base; 124153d2a715SThierry Reding } 124253d2a715SThierry Reding 124353d2a715SThierry Reding static void tegra124_sata_lane_remove(struct tegra_xusb_lane *lane) 124453d2a715SThierry Reding { 124553d2a715SThierry Reding struct tegra_xusb_sata_lane *sata = to_sata_lane(lane); 124653d2a715SThierry Reding 124753d2a715SThierry Reding kfree(sata); 124853d2a715SThierry Reding } 124953d2a715SThierry Reding 125053d2a715SThierry Reding static const struct tegra_xusb_lane_ops tegra124_sata_lane_ops = { 125153d2a715SThierry Reding .probe = tegra124_sata_lane_probe, 125253d2a715SThierry Reding .remove = tegra124_sata_lane_remove, 125353d2a715SThierry Reding }; 125453d2a715SThierry Reding 125553d2a715SThierry Reding static int tegra124_sata_phy_init(struct phy *phy) 125653d2a715SThierry Reding { 125753d2a715SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 125853d2a715SThierry Reding 125953d2a715SThierry Reding return tegra124_xusb_padctl_enable(lane->pad->padctl); 126053d2a715SThierry Reding } 126153d2a715SThierry Reding 126253d2a715SThierry Reding static int tegra124_sata_phy_exit(struct phy *phy) 126353d2a715SThierry Reding { 126453d2a715SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 126553d2a715SThierry Reding 126653d2a715SThierry Reding return tegra124_xusb_padctl_disable(lane->pad->padctl); 126753d2a715SThierry Reding } 126853d2a715SThierry Reding 126953d2a715SThierry Reding static int tegra124_sata_phy_power_on(struct phy *phy) 127053d2a715SThierry Reding { 127153d2a715SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 127253d2a715SThierry Reding struct tegra_xusb_padctl *padctl = lane->pad->padctl; 127353d2a715SThierry Reding unsigned long timeout; 127453d2a715SThierry Reding int err = -ETIMEDOUT; 127553d2a715SThierry Reding u32 value; 127653d2a715SThierry Reding 127753d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); 127853d2a715SThierry Reding value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; 127953d2a715SThierry Reding value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ; 128053d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); 128153d2a715SThierry Reding 128253d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 128353d2a715SThierry Reding value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; 128453d2a715SThierry Reding value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ; 128553d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 128653d2a715SThierry Reding 128753d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 128853d2a715SThierry Reding value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE; 128953d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 129053d2a715SThierry Reding 129153d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 129253d2a715SThierry Reding value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST; 129353d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 129453d2a715SThierry Reding 129553d2a715SThierry Reding timeout = jiffies + msecs_to_jiffies(50); 129653d2a715SThierry Reding 129753d2a715SThierry Reding while (time_before(jiffies, timeout)) { 129853d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 129953d2a715SThierry Reding if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) { 130053d2a715SThierry Reding err = 0; 130153d2a715SThierry Reding break; 130253d2a715SThierry Reding } 130353d2a715SThierry Reding 130453d2a715SThierry Reding usleep_range(100, 200); 130553d2a715SThierry Reding } 130653d2a715SThierry Reding 130753d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); 130853d2a715SThierry Reding value |= XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index); 130953d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); 131053d2a715SThierry Reding 131153d2a715SThierry Reding return err; 131253d2a715SThierry Reding } 131353d2a715SThierry Reding 131453d2a715SThierry Reding static int tegra124_sata_phy_power_off(struct phy *phy) 131553d2a715SThierry Reding { 131653d2a715SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 131753d2a715SThierry Reding struct tegra_xusb_padctl *padctl = lane->pad->padctl; 131853d2a715SThierry Reding u32 value; 131953d2a715SThierry Reding 132053d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); 132153d2a715SThierry Reding value &= ~XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index); 132253d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); 132353d2a715SThierry Reding 132453d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 132553d2a715SThierry Reding value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST; 132653d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 132753d2a715SThierry Reding 132853d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 132953d2a715SThierry Reding value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE; 133053d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 133153d2a715SThierry Reding 133253d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 133353d2a715SThierry Reding value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; 133453d2a715SThierry Reding value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ; 133553d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 133653d2a715SThierry Reding 133753d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); 133853d2a715SThierry Reding value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; 133953d2a715SThierry Reding value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ; 134053d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); 134153d2a715SThierry Reding 134253d2a715SThierry Reding return 0; 134353d2a715SThierry Reding } 134453d2a715SThierry Reding 134553d2a715SThierry Reding static const struct phy_ops tegra124_sata_phy_ops = { 134653d2a715SThierry Reding .init = tegra124_sata_phy_init, 134753d2a715SThierry Reding .exit = tegra124_sata_phy_exit, 134853d2a715SThierry Reding .power_on = tegra124_sata_phy_power_on, 134953d2a715SThierry Reding .power_off = tegra124_sata_phy_power_off, 135053d2a715SThierry Reding .owner = THIS_MODULE, 135153d2a715SThierry Reding }; 135253d2a715SThierry Reding 135353d2a715SThierry Reding static struct tegra_xusb_pad * 135453d2a715SThierry Reding tegra124_sata_pad_probe(struct tegra_xusb_padctl *padctl, 135553d2a715SThierry Reding const struct tegra_xusb_pad_soc *soc, 135653d2a715SThierry Reding struct device_node *np) 135753d2a715SThierry Reding { 135853d2a715SThierry Reding struct tegra_xusb_sata_pad *sata; 135953d2a715SThierry Reding struct tegra_xusb_pad *pad; 136053d2a715SThierry Reding int err; 136153d2a715SThierry Reding 136253d2a715SThierry Reding sata = kzalloc(sizeof(*sata), GFP_KERNEL); 136353d2a715SThierry Reding if (!sata) 136453d2a715SThierry Reding return ERR_PTR(-ENOMEM); 136553d2a715SThierry Reding 136653d2a715SThierry Reding pad = &sata->base; 136753d2a715SThierry Reding pad->ops = &tegra124_sata_lane_ops; 136853d2a715SThierry Reding pad->soc = soc; 136953d2a715SThierry Reding 137053d2a715SThierry Reding err = tegra_xusb_pad_init(pad, padctl, np); 137153d2a715SThierry Reding if (err < 0) { 137253d2a715SThierry Reding kfree(sata); 137353d2a715SThierry Reding goto out; 137453d2a715SThierry Reding } 137553d2a715SThierry Reding 137653d2a715SThierry Reding err = tegra_xusb_pad_register(pad, &tegra124_sata_phy_ops); 137753d2a715SThierry Reding if (err < 0) 137853d2a715SThierry Reding goto unregister; 137953d2a715SThierry Reding 138053d2a715SThierry Reding dev_set_drvdata(&pad->dev, pad); 138153d2a715SThierry Reding 138253d2a715SThierry Reding return pad; 138353d2a715SThierry Reding 138453d2a715SThierry Reding unregister: 138553d2a715SThierry Reding device_unregister(&pad->dev); 138653d2a715SThierry Reding out: 138753d2a715SThierry Reding return ERR_PTR(err); 138853d2a715SThierry Reding } 138953d2a715SThierry Reding 139053d2a715SThierry Reding static void tegra124_sata_pad_remove(struct tegra_xusb_pad *pad) 139153d2a715SThierry Reding { 139253d2a715SThierry Reding struct tegra_xusb_sata_pad *sata = to_sata_pad(pad); 139353d2a715SThierry Reding 139453d2a715SThierry Reding kfree(sata); 139553d2a715SThierry Reding } 139653d2a715SThierry Reding 139753d2a715SThierry Reding static const struct tegra_xusb_pad_ops tegra124_sata_ops = { 139853d2a715SThierry Reding .probe = tegra124_sata_pad_probe, 139953d2a715SThierry Reding .remove = tegra124_sata_pad_remove, 140053d2a715SThierry Reding }; 140153d2a715SThierry Reding 140253d2a715SThierry Reding static const struct tegra_xusb_pad_soc tegra124_sata_pad = { 140353d2a715SThierry Reding .name = "sata", 140453d2a715SThierry Reding .num_lanes = ARRAY_SIZE(tegra124_sata_lanes), 140553d2a715SThierry Reding .lanes = tegra124_sata_lanes, 140653d2a715SThierry Reding .ops = &tegra124_sata_ops, 140753d2a715SThierry Reding }; 140853d2a715SThierry Reding 140953d2a715SThierry Reding static const struct tegra_xusb_pad_soc *tegra124_pads[] = { 141053d2a715SThierry Reding &tegra124_usb2_pad, 141153d2a715SThierry Reding &tegra124_ulpi_pad, 141253d2a715SThierry Reding &tegra124_hsic_pad, 141353d2a715SThierry Reding &tegra124_pcie_pad, 141453d2a715SThierry Reding &tegra124_sata_pad, 141553d2a715SThierry Reding }; 141653d2a715SThierry Reding 141753d2a715SThierry Reding static int tegra124_usb2_port_enable(struct tegra_xusb_port *port) 141853d2a715SThierry Reding { 141953d2a715SThierry Reding return 0; 142053d2a715SThierry Reding } 142153d2a715SThierry Reding 142253d2a715SThierry Reding static void tegra124_usb2_port_disable(struct tegra_xusb_port *port) 142353d2a715SThierry Reding { 142453d2a715SThierry Reding } 142553d2a715SThierry Reding 142653d2a715SThierry Reding static struct tegra_xusb_lane * 142753d2a715SThierry Reding tegra124_usb2_port_map(struct tegra_xusb_port *port) 142853d2a715SThierry Reding { 142953d2a715SThierry Reding return tegra_xusb_find_lane(port->padctl, "usb2", port->index); 143053d2a715SThierry Reding } 143153d2a715SThierry Reding 143253d2a715SThierry Reding static const struct tegra_xusb_port_ops tegra124_usb2_port_ops = { 143353d2a715SThierry Reding .enable = tegra124_usb2_port_enable, 143453d2a715SThierry Reding .disable = tegra124_usb2_port_disable, 143553d2a715SThierry Reding .map = tegra124_usb2_port_map, 143653d2a715SThierry Reding }; 143753d2a715SThierry Reding 143853d2a715SThierry Reding static int tegra124_ulpi_port_enable(struct tegra_xusb_port *port) 143953d2a715SThierry Reding { 144053d2a715SThierry Reding return 0; 144153d2a715SThierry Reding } 144253d2a715SThierry Reding 144353d2a715SThierry Reding static void tegra124_ulpi_port_disable(struct tegra_xusb_port *port) 144453d2a715SThierry Reding { 144553d2a715SThierry Reding } 144653d2a715SThierry Reding 144753d2a715SThierry Reding static struct tegra_xusb_lane * 144853d2a715SThierry Reding tegra124_ulpi_port_map(struct tegra_xusb_port *port) 144953d2a715SThierry Reding { 145053d2a715SThierry Reding return tegra_xusb_find_lane(port->padctl, "ulpi", port->index); 145153d2a715SThierry Reding } 145253d2a715SThierry Reding 145353d2a715SThierry Reding static const struct tegra_xusb_port_ops tegra124_ulpi_port_ops = { 145453d2a715SThierry Reding .enable = tegra124_ulpi_port_enable, 145553d2a715SThierry Reding .disable = tegra124_ulpi_port_disable, 145653d2a715SThierry Reding .map = tegra124_ulpi_port_map, 145753d2a715SThierry Reding }; 145853d2a715SThierry Reding 145953d2a715SThierry Reding static int tegra124_hsic_port_enable(struct tegra_xusb_port *port) 146053d2a715SThierry Reding { 146153d2a715SThierry Reding return 0; 146253d2a715SThierry Reding } 146353d2a715SThierry Reding 146453d2a715SThierry Reding static void tegra124_hsic_port_disable(struct tegra_xusb_port *port) 146553d2a715SThierry Reding { 146653d2a715SThierry Reding } 146753d2a715SThierry Reding 146853d2a715SThierry Reding static struct tegra_xusb_lane * 146953d2a715SThierry Reding tegra124_hsic_port_map(struct tegra_xusb_port *port) 147053d2a715SThierry Reding { 147153d2a715SThierry Reding return tegra_xusb_find_lane(port->padctl, "hsic", port->index); 147253d2a715SThierry Reding } 147353d2a715SThierry Reding 147453d2a715SThierry Reding static const struct tegra_xusb_port_ops tegra124_hsic_port_ops = { 147553d2a715SThierry Reding .enable = tegra124_hsic_port_enable, 147653d2a715SThierry Reding .disable = tegra124_hsic_port_disable, 147753d2a715SThierry Reding .map = tegra124_hsic_port_map, 147853d2a715SThierry Reding }; 147953d2a715SThierry Reding 148053d2a715SThierry Reding static int tegra124_usb3_port_enable(struct tegra_xusb_port *port) 148153d2a715SThierry Reding { 148253d2a715SThierry Reding struct tegra_xusb_usb3_port *usb3 = to_usb3_port(port); 148353d2a715SThierry Reding struct tegra_xusb_padctl *padctl = port->padctl; 148453d2a715SThierry Reding struct tegra_xusb_lane *lane = usb3->base.lane; 148553d2a715SThierry Reding unsigned int index = port->index, offset; 148653d2a715SThierry Reding u32 value; 148753d2a715SThierry Reding 148853d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); 148953d2a715SThierry Reding 149053d2a715SThierry Reding if (!usb3->internal) 149153d2a715SThierry Reding value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index); 149253d2a715SThierry Reding else 149353d2a715SThierry Reding value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index); 149453d2a715SThierry Reding 149553d2a715SThierry Reding value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(index); 149653d2a715SThierry Reding value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(index, usb3->port); 149753d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); 149853d2a715SThierry Reding 149953d2a715SThierry Reding /* 150053d2a715SThierry Reding * TODO: move this code into the PCIe/SATA PHY ->power_on() callbacks 150153d2a715SThierry Reding * and conditionalize based on mux function? This seems to work, but 150253d2a715SThierry Reding * might not be the exact proper sequence. 150353d2a715SThierry Reding */ 150453d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index)); 150553d2a715SThierry Reding value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_MASK << 150653d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT) | 150753d2a715SThierry Reding (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_MASK << 150853d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT) | 150953d2a715SThierry Reding (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_MASK << 151053d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT)); 151153d2a715SThierry Reding value |= (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_VAL << 151253d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT) | 151353d2a715SThierry Reding (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_VAL << 151453d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT) | 151553d2a715SThierry Reding (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_VAL << 151653d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT); 151753d2a715SThierry Reding 151853d2a715SThierry Reding if (usb3->context_saved) { 151953d2a715SThierry Reding value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK << 152053d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) | 152153d2a715SThierry Reding (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK << 152253d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT)); 152353d2a715SThierry Reding value |= (usb3->ctle_g << 152453d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) | 152553d2a715SThierry Reding (usb3->ctle_z << 152653d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT); 152753d2a715SThierry Reding } 152853d2a715SThierry Reding 152953d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index)); 153053d2a715SThierry Reding 153153d2a715SThierry Reding value = XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_VAL; 153253d2a715SThierry Reding 153353d2a715SThierry Reding if (usb3->context_saved) { 153453d2a715SThierry Reding value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK << 153553d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) | 153653d2a715SThierry Reding (XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK << 153753d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT)); 153853d2a715SThierry Reding value |= (usb3->tap1 << 153953d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) | 154053d2a715SThierry Reding (usb3->amp << 154153d2a715SThierry Reding XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT); 154253d2a715SThierry Reding } 154353d2a715SThierry Reding 154453d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(index)); 154553d2a715SThierry Reding 154653d2a715SThierry Reding if (lane->pad == padctl->pcie) 154753d2a715SThierry Reding offset = XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL2(lane->index); 154853d2a715SThierry Reding else 154953d2a715SThierry Reding offset = XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2; 155053d2a715SThierry Reding 155153d2a715SThierry Reding value = padctl_readl(padctl, offset); 155253d2a715SThierry Reding value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_MASK << 155353d2a715SThierry Reding XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT); 155453d2a715SThierry Reding value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_VAL << 155553d2a715SThierry Reding XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT; 155653d2a715SThierry Reding padctl_writel(padctl, value, offset); 155753d2a715SThierry Reding 155853d2a715SThierry Reding if (lane->pad == padctl->pcie) 155953d2a715SThierry Reding offset = XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL5(lane->index); 156053d2a715SThierry Reding else 156153d2a715SThierry Reding offset = XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5; 156253d2a715SThierry Reding 156353d2a715SThierry Reding value = padctl_readl(padctl, offset); 156453d2a715SThierry Reding value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL5_RX_QEYE_EN; 156553d2a715SThierry Reding padctl_writel(padctl, value, offset); 156653d2a715SThierry Reding 156753d2a715SThierry Reding /* Enable SATA PHY when SATA lane is used */ 156853d2a715SThierry Reding if (lane->pad == padctl->sata) { 156953d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 157053d2a715SThierry Reding value &= ~(XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_MASK << 157153d2a715SThierry Reding XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT); 157253d2a715SThierry Reding value |= 0x2 << 157353d2a715SThierry Reding XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT; 157453d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); 157553d2a715SThierry Reding 157653d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL2); 157753d2a715SThierry Reding value &= ~((XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_MASK << 157853d2a715SThierry Reding XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT) | 157953d2a715SThierry Reding (XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_MASK << 158053d2a715SThierry Reding XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT) | 158153d2a715SThierry Reding (XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_MASK << 158253d2a715SThierry Reding XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT) | 158353d2a715SThierry Reding XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TCLKOUT_EN); 158453d2a715SThierry Reding value |= (0x7 << 158553d2a715SThierry Reding XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT) | 158653d2a715SThierry Reding (0x8 << 158753d2a715SThierry Reding XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT) | 158853d2a715SThierry Reding (0x8 << 158953d2a715SThierry Reding XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT) | 159053d2a715SThierry Reding XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TXCLKREF_SEL; 159153d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL2); 159253d2a715SThierry Reding 159353d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL3); 159453d2a715SThierry Reding value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL3_RCAL_BYPASS; 159553d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL3); 159653d2a715SThierry Reding } 159753d2a715SThierry Reding 159853d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 159953d2a715SThierry Reding value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(index); 160053d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 160153d2a715SThierry Reding 160253d2a715SThierry Reding usleep_range(100, 200); 160353d2a715SThierry Reding 160453d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 160553d2a715SThierry Reding value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(index); 160653d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 160753d2a715SThierry Reding 160853d2a715SThierry Reding usleep_range(100, 200); 160953d2a715SThierry Reding 161053d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 161153d2a715SThierry Reding value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(index); 161253d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 161353d2a715SThierry Reding 1614e4d5973fSVivek Gautam return 0; 161553d2a715SThierry Reding } 161653d2a715SThierry Reding 161753d2a715SThierry Reding static void tegra124_usb3_port_disable(struct tegra_xusb_port *port) 161853d2a715SThierry Reding { 161953d2a715SThierry Reding struct tegra_xusb_padctl *padctl = port->padctl; 162053d2a715SThierry Reding u32 value; 162153d2a715SThierry Reding 162253d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 162353d2a715SThierry Reding value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(port->index); 162453d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 162553d2a715SThierry Reding 162653d2a715SThierry Reding usleep_range(100, 200); 162753d2a715SThierry Reding 162853d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 162953d2a715SThierry Reding value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(port->index); 163053d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 163153d2a715SThierry Reding 163253d2a715SThierry Reding usleep_range(250, 350); 163353d2a715SThierry Reding 163453d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); 163553d2a715SThierry Reding value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(port->index); 163653d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); 163753d2a715SThierry Reding 163853d2a715SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); 163953d2a715SThierry Reding value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(port->index); 164053d2a715SThierry Reding value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(port->index, 0x7); 164153d2a715SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); 164253d2a715SThierry Reding } 164353d2a715SThierry Reding 164453d2a715SThierry Reding static const struct tegra_xusb_lane_map tegra124_usb3_map[] = { 164553d2a715SThierry Reding { 0, "pcie", 0 }, 164653d2a715SThierry Reding { 1, "pcie", 1 }, 164753d2a715SThierry Reding { 1, "sata", 0 }, 164853d2a715SThierry Reding { 0, NULL, 0 }, 164953d2a715SThierry Reding }; 165053d2a715SThierry Reding 165153d2a715SThierry Reding static struct tegra_xusb_lane * 165253d2a715SThierry Reding tegra124_usb3_port_map(struct tegra_xusb_port *port) 165353d2a715SThierry Reding { 165453d2a715SThierry Reding return tegra_xusb_port_find_lane(port, tegra124_usb3_map, "usb3-ss"); 165553d2a715SThierry Reding } 165653d2a715SThierry Reding 165753d2a715SThierry Reding static const struct tegra_xusb_port_ops tegra124_usb3_port_ops = { 165853d2a715SThierry Reding .enable = tegra124_usb3_port_enable, 165953d2a715SThierry Reding .disable = tegra124_usb3_port_disable, 166053d2a715SThierry Reding .map = tegra124_usb3_port_map, 166153d2a715SThierry Reding }; 166253d2a715SThierry Reding 166353d2a715SThierry Reding static int 166453d2a715SThierry Reding tegra124_xusb_read_fuse_calibration(struct tegra124_xusb_fuse_calibration *fuse) 166553d2a715SThierry Reding { 166653d2a715SThierry Reding unsigned int i; 166753d2a715SThierry Reding int err; 166853d2a715SThierry Reding u32 value; 166953d2a715SThierry Reding 167053d2a715SThierry Reding err = tegra_fuse_readl(TEGRA_FUSE_SKU_CALIB_0, &value); 167153d2a715SThierry Reding if (err < 0) 167253d2a715SThierry Reding return err; 167353d2a715SThierry Reding 167453d2a715SThierry Reding for (i = 0; i < ARRAY_SIZE(fuse->hs_curr_level); i++) { 167553d2a715SThierry Reding fuse->hs_curr_level[i] = 167653d2a715SThierry Reding (value >> FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(i)) & 167753d2a715SThierry Reding FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK; 167853d2a715SThierry Reding } 167953d2a715SThierry Reding fuse->hs_iref_cap = 168053d2a715SThierry Reding (value >> FUSE_SKU_CALIB_HS_IREF_CAP_SHIFT) & 168153d2a715SThierry Reding FUSE_SKU_CALIB_HS_IREF_CAP_MASK; 168253d2a715SThierry Reding fuse->hs_term_range_adj = 168353d2a715SThierry Reding (value >> FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT) & 168453d2a715SThierry Reding FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK; 168553d2a715SThierry Reding fuse->hs_squelch_level = 168653d2a715SThierry Reding (value >> FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_SHIFT) & 168753d2a715SThierry Reding FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_MASK; 168853d2a715SThierry Reding 168953d2a715SThierry Reding return 0; 169053d2a715SThierry Reding } 169153d2a715SThierry Reding 169253d2a715SThierry Reding static struct tegra_xusb_padctl * 169353d2a715SThierry Reding tegra124_xusb_padctl_probe(struct device *dev, 169453d2a715SThierry Reding const struct tegra_xusb_padctl_soc *soc) 169553d2a715SThierry Reding { 169653d2a715SThierry Reding struct tegra124_xusb_padctl *padctl; 169753d2a715SThierry Reding int err; 169853d2a715SThierry Reding 169953d2a715SThierry Reding padctl = devm_kzalloc(dev, sizeof(*padctl), GFP_KERNEL); 170053d2a715SThierry Reding if (!padctl) 170153d2a715SThierry Reding return ERR_PTR(-ENOMEM); 170253d2a715SThierry Reding 170353d2a715SThierry Reding padctl->base.dev = dev; 170453d2a715SThierry Reding padctl->base.soc = soc; 170553d2a715SThierry Reding 170653d2a715SThierry Reding err = tegra124_xusb_read_fuse_calibration(&padctl->fuse); 170753d2a715SThierry Reding if (err < 0) 170853d2a715SThierry Reding return ERR_PTR(err); 170953d2a715SThierry Reding 171053d2a715SThierry Reding return &padctl->base; 171153d2a715SThierry Reding } 171253d2a715SThierry Reding 171353d2a715SThierry Reding static void tegra124_xusb_padctl_remove(struct tegra_xusb_padctl *padctl) 171453d2a715SThierry Reding { 171553d2a715SThierry Reding } 171653d2a715SThierry Reding 171753d2a715SThierry Reding static const struct tegra_xusb_padctl_ops tegra124_xusb_padctl_ops = { 171853d2a715SThierry Reding .probe = tegra124_xusb_padctl_probe, 171953d2a715SThierry Reding .remove = tegra124_xusb_padctl_remove, 172053d2a715SThierry Reding .usb3_save_context = tegra124_usb3_save_context, 172153d2a715SThierry Reding .hsic_set_idle = tegra124_hsic_set_idle, 172253d2a715SThierry Reding }; 172353d2a715SThierry Reding 1724aa5452f5SThierry Reding static const char * const tegra124_xusb_padctl_supply_names[] = { 1725aa5452f5SThierry Reding "avdd-pll-utmip", 1726aa5452f5SThierry Reding "avdd-pll-erefe", 1727aa5452f5SThierry Reding "avdd-pex-pll", 1728aa5452f5SThierry Reding "hvdd-pex-pll-e", 1729aa5452f5SThierry Reding }; 1730aa5452f5SThierry Reding 173153d2a715SThierry Reding const struct tegra_xusb_padctl_soc tegra124_xusb_padctl_soc = { 173253d2a715SThierry Reding .num_pads = ARRAY_SIZE(tegra124_pads), 173353d2a715SThierry Reding .pads = tegra124_pads, 173453d2a715SThierry Reding .ports = { 173553d2a715SThierry Reding .usb2 = { 173653d2a715SThierry Reding .ops = &tegra124_usb2_port_ops, 173753d2a715SThierry Reding .count = 3, 173853d2a715SThierry Reding }, 173953d2a715SThierry Reding .ulpi = { 174053d2a715SThierry Reding .ops = &tegra124_ulpi_port_ops, 174153d2a715SThierry Reding .count = 1, 174253d2a715SThierry Reding }, 174353d2a715SThierry Reding .hsic = { 174453d2a715SThierry Reding .ops = &tegra124_hsic_port_ops, 174553d2a715SThierry Reding .count = 2, 174653d2a715SThierry Reding }, 174753d2a715SThierry Reding .usb3 = { 174853d2a715SThierry Reding .ops = &tegra124_usb3_port_ops, 174953d2a715SThierry Reding .count = 2, 175053d2a715SThierry Reding }, 175153d2a715SThierry Reding }, 175253d2a715SThierry Reding .ops = &tegra124_xusb_padctl_ops, 1753aa5452f5SThierry Reding .supply_names = tegra124_xusb_padctl_supply_names, 1754aa5452f5SThierry Reding .num_supplies = ARRAY_SIZE(tegra124_xusb_padctl_supply_names), 175553d2a715SThierry Reding }; 175653d2a715SThierry Reding EXPORT_SYMBOL_GPL(tegra124_xusb_padctl_soc); 175753d2a715SThierry Reding 175853d2a715SThierry Reding MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>"); 175953d2a715SThierry Reding MODULE_DESCRIPTION("NVIDIA Tegra 124 XUSB Pad Controller driver"); 176053d2a715SThierry Reding MODULE_LICENSE("GPL v2"); 1761