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