12025cf9eSThomas 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 42ac25b6e9SNagarjuna Kristam #define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_DISABLED(x) (0x0 << ((x) * 4)) 4387d66f28SThierry Reding #define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_HOST(x) (0x1 << ((x) * 4)) 44ac25b6e9SNagarjuna Kristam #define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_DEVICE(x) (0x2 << ((x) * 4)) 45ac25b6e9SNagarjuna Kristam #define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_OTG(x) (0x3 << ((x) * 4)) 4687d66f28SThierry Reding #define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_MASK(x) (0x3 << ((x) * 4)) 4787d66f28SThierry Reding 4887d66f28SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP 0x014 4987d66f28SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(x) (1 << (((x) * 5) + 4)) 5087d66f28SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_SHIFT(x) ((x) * 5) 5187d66f28SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(x) (0x7 << ((x) * 5)) 5287d66f28SThierry Reding #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(x, v) (((v) & 0x7) << ((x) * 5)) 53a5be28c3SNagarjuna Kristam #define XUSB_PADCTL_SS_PORT_MAP_PORT_DISABLED 0x7 5487d66f28SThierry Reding 5587d66f28SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM1 0x024 5687d66f28SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN (1 << 31) 5787d66f28SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 30) 5887d66f28SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN (1 << 29) 5987d66f28SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN(x) (1 << (2 + (x) * 3)) 6087d66f28SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(x) \ 6187d66f28SThierry Reding (1 << (1 + (x) * 3)) 6287d66f28SThierry Reding #define XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(x) (1 << ((x) * 3)) 6387d66f28SThierry Reding 6487d66f28SThierry Reding #define XUSB_PADCTL_USB3_PAD_MUX 0x028 6587d66f28SThierry Reding #define XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(x) (1 << (1 + (x))) 6687d66f28SThierry Reding #define XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(x) (1 << (8 + (x))) 6787d66f28SThierry Reding 6890767cdfSNagarjuna Kristam #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL0(x) (0x080 + (x) * 0x40) 6990767cdfSNagarjuna Kristam #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL0_ZIP (1 << 18) 7090767cdfSNagarjuna Kristam #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL0_ZIN (1 << 22) 7190767cdfSNagarjuna Kristam 7287d66f28SThierry Reding #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(x) (0x084 + (x) * 0x40) 7387d66f28SThierry Reding #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_SHIFT 7 7487d66f28SThierry Reding #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_MASK 0x3 75ac25b6e9SNagarjuna Kristam #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_VAL 0x1 7687d66f28SThierry Reding #define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_FIX18 (1 << 6) 7787d66f28SThierry Reding 7887d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PADX_CTL0(x) (0x088 + (x) * 0x40) 7987d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI (1 << 29) 8087d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 (1 << 27) 8187d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD (1 << 26) 8287d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT 0 8387d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK 0x3f 8487d66f28SThierry Reding 8587d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PADX_CTL1(x) (0x08c + (x) * 0x40) 8687d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_SHIFT 26 8787d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_MASK 0x1f 8887d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT 3 8987d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK 0xf 9087d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR (1 << 2) 9187d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_OVRD (1 << 1) 9287d66f28SThierry Reding #define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_OVRD (1 << 0) 9387d66f28SThierry Reding 9487d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0 0x284 9587d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD (1 << 11) 9687d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT 3 9787d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK 0x7 9887d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL 0x7 9987d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT 0 10087d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK 0x7 10187d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_VAL 0x2 10287d66f28SThierry Reding 10387d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1 0x288 10487d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_PD_TRK (1 << 26) 10587d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_SHIFT 19 10687d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_MASK 0x7f 10787d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_VAL 0x0a 10887d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_SHIFT 12 10987d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_MASK 0x7f 11087d66f28SThierry Reding #define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_VAL 0x1e 11187d66f28SThierry Reding 11287d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PADX_CTL0(x) (0x300 + (x) * 0x20) 11387d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE (1 << 18) 11487d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA1 (1 << 17) 11587d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA0 (1 << 16) 11687d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_RPD_STROBE (1 << 15) 11787d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA1 (1 << 14) 11887d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA0 (1 << 13) 11987d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_STROBE (1 << 9) 12087d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA1 (1 << 8) 12187d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA0 (1 << 7) 12287d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_STROBE (1 << 6) 12387d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA1 (1 << 5) 12487d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA0 (1 << 4) 12587d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_STROBE (1 << 3) 12687d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA1 (1 << 2) 12787d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA0 (1 << 1) 12887d66f28SThierry Reding 12987d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PADX_CTL1(x) (0x304 + (x) * 0x20) 13087d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_SHIFT 0 13187d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_MASK 0xf 13287d66f28SThierry Reding 13387d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PADX_CTL2(x) (0x308 + (x) * 0x20) 13487d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT 8 13587d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK 0xf 13687d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT 0 13787d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK 0xff 13887d66f28SThierry Reding 13987d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_TRK_CTL 0x340 14087d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_TRK_CTL_PD_TRK (1 << 19) 14187d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_SHIFT 12 14287d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_MASK 0x7f 14387d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_VAL 0x0a 14487d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_SHIFT 5 14587d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_MASK 0x7f 14687d66f28SThierry Reding #define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_VAL 0x1e 14787d66f28SThierry Reding 14887d66f28SThierry Reding #define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL 0x344 14987d66f28SThierry Reding 15087d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_P0_CTL1 0x360 15187d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT 20 15287d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_MASK 0xff 15387d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_USB_VAL 0x19 15487d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SATA_VAL 0x1e 15587d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_SHIFT 16 15687d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_MASK 0x3 15787d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_LOCKDET_STATUS (1 << 15) 15887d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD (1 << 4) 15987d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_ENABLE (1 << 3) 16087d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_SHIFT 1 16187d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_MASK 0x3 16287d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL1_IDDQ (1 << 0) 16387d66f28SThierry Reding 16487d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_P0_CTL2 0x364 16587d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT 4 16687d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_MASK 0xffffff 16787d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_VAL 0x136 16887d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD (1 << 2) 16987d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE (1 << 1) 17087d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN (1 << 0) 17187d66f28SThierry Reding 17287d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_P0_CTL4 0x36c 173e7f4da4cSThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL4_XDIGCLK_EN (1 << 19) 17487d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_EN (1 << 15) 17587d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT 12 17687d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_MASK 0x3 17787d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_USB_VAL 0x2 17887d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SATA_VAL 0x0 17987d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL4_REFCLKBUF_EN (1 << 8) 18087d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_SHIFT 4 18187d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_MASK 0xf 18287d66f28SThierry Reding 18387d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_P0_CTL5 0x370 18487d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT 16 18587d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_MASK 0xff 18687d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_VAL 0x2a 18787d66f28SThierry Reding 18887d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_P0_CTL8 0x37c 18987d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE (1 << 31) 19087d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD (1 << 15) 19187d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN (1 << 13) 19287d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN (1 << 12) 19387d66f28SThierry Reding 19487d66f28SThierry Reding #define XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL1(x) (0x460 + (x) * 0x40) 19587d66f28SThierry Reding #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_SHIFT 20 19687d66f28SThierry Reding #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_MASK 0x3 19787d66f28SThierry Reding #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_VAL 0x1 19887d66f28SThierry Reding #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_TERM_EN BIT(18) 19987d66f28SThierry Reding #define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_MODE_OVRD BIT(13) 20087d66f28SThierry Reding 20187d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_S0_CTL1 0x860 20287d66f28SThierry Reding 20387d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_S0_CTL2 0x864 20487d66f28SThierry Reding 20587d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_S0_CTL4 0x86c 20687d66f28SThierry Reding 20787d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_S0_CTL5 0x870 20887d66f28SThierry Reding 20987d66f28SThierry Reding #define XUSB_PADCTL_UPHY_PLL_S0_CTL8 0x87c 21087d66f28SThierry Reding 21187d66f28SThierry Reding #define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL1 0x960 21287d66f28SThierry Reding 21387d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(x) (0xa60 + (x) * 0x40) 21487d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT 16 21587d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_MASK 0x3 21687d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_VAL 0x2 21787d66f28SThierry Reding 21887d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PADX_ECTL2(x) (0xa64 + (x) * 0x40) 21987d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_SHIFT 0 22087d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_MASK 0xffff 22187d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_VAL 0x00fc 22287d66f28SThierry Reding 22387d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PADX_ECTL3(x) (0xa68 + (x) * 0x40) 22487d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL3_RX_DFE_VAL 0xc0077f1f 22587d66f28SThierry Reding 22687d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PADX_ECTL4(x) (0xa6c + (x) * 0x40) 22787d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_SHIFT 16 22887d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_MASK 0xffff 22987d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_VAL 0x01c7 23087d66f28SThierry Reding 23187d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PADX_ECTL6(x) (0xa74 + (x) * 0x40) 23287d66f28SThierry Reding #define XUSB_PADCTL_UPHY_USB3_PAD_ECTL6_RX_EQ_CTRL_H_VAL 0xfcf01368 23387d66f28SThierry Reding 23490767cdfSNagarjuna Kristam #define XUSB_PADCTL_USB2_VBUS_ID 0xc60 23590767cdfSNagarjuna Kristam #define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON (1 << 14) 23690767cdfSNagarjuna Kristam #define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT 18 23790767cdfSNagarjuna Kristam #define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK 0xf 23890767cdfSNagarjuna Kristam #define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING 8 239*de792a6dSNagarjuna Kristam #define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_GROUNDED 0 24090767cdfSNagarjuna Kristam 24187d66f28SThierry Reding struct tegra210_xusb_fuse_calibration { 24287d66f28SThierry Reding u32 hs_curr_level[4]; 24387d66f28SThierry Reding u32 hs_term_range_adj; 24487d66f28SThierry Reding u32 rpd_ctrl; 24587d66f28SThierry Reding }; 24687d66f28SThierry Reding 24787d66f28SThierry Reding struct tegra210_xusb_padctl { 24887d66f28SThierry Reding struct tegra_xusb_padctl base; 24987d66f28SThierry Reding 25087d66f28SThierry Reding struct tegra210_xusb_fuse_calibration fuse; 25187d66f28SThierry Reding }; 25287d66f28SThierry Reding 25387d66f28SThierry Reding static inline struct tegra210_xusb_padctl * 25487d66f28SThierry Reding to_tegra210_xusb_padctl(struct tegra_xusb_padctl *padctl) 25587d66f28SThierry Reding { 25687d66f28SThierry Reding return container_of(padctl, struct tegra210_xusb_padctl, base); 25787d66f28SThierry Reding } 25887d66f28SThierry Reding 25987d66f28SThierry Reding /* must be called under padctl->lock */ 26087d66f28SThierry Reding static int tegra210_pex_uphy_enable(struct tegra_xusb_padctl *padctl) 26187d66f28SThierry Reding { 26287d66f28SThierry Reding struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(padctl->pcie); 26387d66f28SThierry Reding unsigned long timeout; 26487d66f28SThierry Reding u32 value; 26587d66f28SThierry Reding int err; 26687d66f28SThierry Reding 26787d66f28SThierry Reding if (pcie->enable > 0) { 26887d66f28SThierry Reding pcie->enable++; 26987d66f28SThierry Reding return 0; 27087d66f28SThierry Reding } 27187d66f28SThierry Reding 27287d66f28SThierry Reding err = clk_prepare_enable(pcie->pll); 27387d66f28SThierry Reding if (err < 0) 27487d66f28SThierry Reding return err; 27587d66f28SThierry Reding 27687d66f28SThierry Reding err = reset_control_deassert(pcie->rst); 27787d66f28SThierry Reding if (err < 0) 27887d66f28SThierry Reding goto disable; 27987d66f28SThierry Reding 28087d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 28187d66f28SThierry Reding value &= ~(XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_MASK << 28287d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT); 28387d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_VAL << 28487d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT; 28587d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 28687d66f28SThierry Reding 28787d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL5); 28887d66f28SThierry Reding value &= ~(XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_MASK << 28987d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT); 29087d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_VAL << 29187d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT; 29287d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL5); 29387d66f28SThierry Reding 29487d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 29587d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD; 29687d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 29787d66f28SThierry Reding 29887d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 29987d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD; 30087d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 30187d66f28SThierry Reding 30287d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 30387d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD; 30487d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 30587d66f28SThierry Reding 30687d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL4); 30787d66f28SThierry Reding value &= ~((XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_MASK << 30887d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT) | 30987d66f28SThierry Reding (XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_MASK << 31087d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_SHIFT)); 31187d66f28SThierry Reding value |= (XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_USB_VAL << 31287d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT) | 31387d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_EN; 31487d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL4); 31587d66f28SThierry Reding 31687d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 31787d66f28SThierry Reding value &= ~((XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_MASK << 31887d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_SHIFT) | 31987d66f28SThierry Reding (XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_MASK << 32087d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT)); 32187d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_USB_VAL << 32287d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT; 32387d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 32487d66f28SThierry Reding 32587d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 32687d66f28SThierry Reding value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_IDDQ; 32787d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 32887d66f28SThierry Reding 32987d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 33087d66f28SThierry Reding value &= ~(XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_MASK << 33187d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_SHIFT); 33287d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 33387d66f28SThierry Reding 33487d66f28SThierry Reding usleep_range(10, 20); 33587d66f28SThierry Reding 33687d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL4); 33787d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL4_REFCLKBUF_EN; 33887d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL4); 33987d66f28SThierry Reding 34087d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 34187d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN; 34287d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 34387d66f28SThierry Reding 34487d66f28SThierry Reding timeout = jiffies + msecs_to_jiffies(100); 34587d66f28SThierry Reding 34687d66f28SThierry Reding while (time_before(jiffies, timeout)) { 34787d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 34887d66f28SThierry Reding if (value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE) 34987d66f28SThierry Reding break; 35087d66f28SThierry Reding 35187d66f28SThierry Reding usleep_range(10, 20); 35287d66f28SThierry Reding } 35387d66f28SThierry Reding 35487d66f28SThierry Reding if (time_after_eq(jiffies, timeout)) { 35587d66f28SThierry Reding err = -ETIMEDOUT; 35687d66f28SThierry Reding goto reset; 35787d66f28SThierry Reding } 35887d66f28SThierry Reding 35987d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 36087d66f28SThierry Reding value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN; 36187d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 36287d66f28SThierry Reding 36387d66f28SThierry Reding timeout = jiffies + msecs_to_jiffies(100); 36487d66f28SThierry Reding 36587d66f28SThierry Reding while (time_before(jiffies, timeout)) { 36687d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 36787d66f28SThierry Reding if (!(value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE)) 36887d66f28SThierry Reding break; 36987d66f28SThierry Reding 37087d66f28SThierry Reding usleep_range(10, 20); 37187d66f28SThierry Reding } 37287d66f28SThierry Reding 37387d66f28SThierry Reding if (time_after_eq(jiffies, timeout)) { 37487d66f28SThierry Reding err = -ETIMEDOUT; 37587d66f28SThierry Reding goto reset; 37687d66f28SThierry Reding } 37787d66f28SThierry Reding 37887d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 37987d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL1_ENABLE; 38087d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 38187d66f28SThierry Reding 38287d66f28SThierry Reding timeout = jiffies + msecs_to_jiffies(100); 38387d66f28SThierry Reding 38487d66f28SThierry Reding while (time_before(jiffies, timeout)) { 38587d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 38687d66f28SThierry Reding if (value & XUSB_PADCTL_UPHY_PLL_CTL1_LOCKDET_STATUS) 38787d66f28SThierry Reding break; 38887d66f28SThierry Reding 38987d66f28SThierry Reding usleep_range(10, 20); 39087d66f28SThierry Reding } 39187d66f28SThierry Reding 39287d66f28SThierry Reding if (time_after_eq(jiffies, timeout)) { 39387d66f28SThierry Reding err = -ETIMEDOUT; 39487d66f28SThierry Reding goto reset; 39587d66f28SThierry Reding } 39687d66f28SThierry Reding 39787d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 39887d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN | 39987d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN; 40087d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 40187d66f28SThierry Reding 40287d66f28SThierry Reding timeout = jiffies + msecs_to_jiffies(100); 40387d66f28SThierry Reding 40487d66f28SThierry Reding while (time_before(jiffies, timeout)) { 40587d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 40687d66f28SThierry Reding if (value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE) 40787d66f28SThierry Reding break; 40887d66f28SThierry Reding 40987d66f28SThierry Reding usleep_range(10, 20); 41087d66f28SThierry Reding } 41187d66f28SThierry Reding 41287d66f28SThierry Reding if (time_after_eq(jiffies, timeout)) { 41387d66f28SThierry Reding err = -ETIMEDOUT; 41487d66f28SThierry Reding goto reset; 41587d66f28SThierry Reding } 41687d66f28SThierry Reding 41787d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 41887d66f28SThierry Reding value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN; 41987d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 42087d66f28SThierry Reding 42187d66f28SThierry Reding timeout = jiffies + msecs_to_jiffies(100); 42287d66f28SThierry Reding 42387d66f28SThierry Reding while (time_before(jiffies, timeout)) { 42487d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 42587d66f28SThierry Reding if (!(value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE)) 42687d66f28SThierry Reding break; 42787d66f28SThierry Reding 42887d66f28SThierry Reding usleep_range(10, 20); 42987d66f28SThierry Reding } 43087d66f28SThierry Reding 43187d66f28SThierry Reding if (time_after_eq(jiffies, timeout)) { 43287d66f28SThierry Reding err = -ETIMEDOUT; 43387d66f28SThierry Reding goto reset; 43487d66f28SThierry Reding } 43587d66f28SThierry Reding 43687d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 43787d66f28SThierry Reding value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN; 43887d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 43987d66f28SThierry Reding 44087d66f28SThierry Reding tegra210_xusb_pll_hw_control_enable(); 44187d66f28SThierry Reding 44287d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 44387d66f28SThierry Reding value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD; 44487d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 44587d66f28SThierry Reding 44687d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 44787d66f28SThierry Reding value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD; 44887d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 44987d66f28SThierry Reding 45087d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 45187d66f28SThierry Reding value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD; 45287d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 45387d66f28SThierry Reding 45487d66f28SThierry Reding usleep_range(10, 20); 45587d66f28SThierry Reding 45687d66f28SThierry Reding tegra210_xusb_pll_hw_sequence_start(); 45787d66f28SThierry Reding 45887d66f28SThierry Reding pcie->enable++; 45987d66f28SThierry Reding 46087d66f28SThierry Reding return 0; 46187d66f28SThierry Reding 46287d66f28SThierry Reding reset: 46387d66f28SThierry Reding reset_control_assert(pcie->rst); 46487d66f28SThierry Reding disable: 46587d66f28SThierry Reding clk_disable_unprepare(pcie->pll); 46687d66f28SThierry Reding return err; 46787d66f28SThierry Reding } 46887d66f28SThierry Reding 46987d66f28SThierry Reding static void tegra210_pex_uphy_disable(struct tegra_xusb_padctl *padctl) 47087d66f28SThierry Reding { 47187d66f28SThierry Reding struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(padctl->pcie); 47287d66f28SThierry Reding 47387d66f28SThierry Reding mutex_lock(&padctl->lock); 47487d66f28SThierry Reding 47587d66f28SThierry Reding if (WARN_ON(pcie->enable == 0)) 47687d66f28SThierry Reding goto unlock; 47787d66f28SThierry Reding 47887d66f28SThierry Reding if (--pcie->enable > 0) 47987d66f28SThierry Reding goto unlock; 48087d66f28SThierry Reding 48187d66f28SThierry Reding reset_control_assert(pcie->rst); 48287d66f28SThierry Reding clk_disable_unprepare(pcie->pll); 48387d66f28SThierry Reding 48487d66f28SThierry Reding unlock: 48587d66f28SThierry Reding mutex_unlock(&padctl->lock); 48687d66f28SThierry Reding } 48787d66f28SThierry Reding 48887d66f28SThierry Reding /* must be called under padctl->lock */ 48987d66f28SThierry Reding static int tegra210_sata_uphy_enable(struct tegra_xusb_padctl *padctl, bool usb) 49087d66f28SThierry Reding { 49187d66f28SThierry Reding struct tegra_xusb_sata_pad *sata = to_sata_pad(padctl->sata); 49287d66f28SThierry Reding unsigned long timeout; 49387d66f28SThierry Reding u32 value; 49487d66f28SThierry Reding int err; 49587d66f28SThierry Reding 49687d66f28SThierry Reding if (sata->enable > 0) { 49787d66f28SThierry Reding sata->enable++; 49887d66f28SThierry Reding return 0; 49987d66f28SThierry Reding } 50087d66f28SThierry Reding 50187d66f28SThierry Reding err = clk_prepare_enable(sata->pll); 50287d66f28SThierry Reding if (err < 0) 50387d66f28SThierry Reding return err; 50487d66f28SThierry Reding 50587d66f28SThierry Reding err = reset_control_deassert(sata->rst); 50687d66f28SThierry Reding if (err < 0) 50787d66f28SThierry Reding goto disable; 50887d66f28SThierry Reding 50987d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 51087d66f28SThierry Reding value &= ~(XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_MASK << 51187d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT); 51287d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_VAL << 51387d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT; 51487d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 51587d66f28SThierry Reding 51687d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL5); 51787d66f28SThierry Reding value &= ~(XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_MASK << 51887d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT); 51987d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_VAL << 52087d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT; 52187d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL5); 52287d66f28SThierry Reding 52387d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 52487d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD; 52587d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 52687d66f28SThierry Reding 52787d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 52887d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD; 52987d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 53087d66f28SThierry Reding 53187d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 53287d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD; 53387d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 53487d66f28SThierry Reding 53587d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL4); 53687d66f28SThierry Reding value &= ~((XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_MASK << 53787d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT) | 53887d66f28SThierry Reding (XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_MASK << 53987d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_SHIFT)); 54087d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_EN; 54187d66f28SThierry Reding 54287d66f28SThierry Reding if (usb) 54387d66f28SThierry Reding value |= (XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_USB_VAL << 54487d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT); 54587d66f28SThierry Reding else 54687d66f28SThierry Reding value |= (XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SATA_VAL << 54787d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT); 54887d66f28SThierry Reding 549e7f4da4cSThierry Reding value &= ~XUSB_PADCTL_UPHY_PLL_CTL4_XDIGCLK_EN; 55087d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL4); 55187d66f28SThierry Reding 55287d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 55387d66f28SThierry Reding value &= ~((XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_MASK << 55487d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_SHIFT) | 55587d66f28SThierry Reding (XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_MASK << 55687d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT)); 55787d66f28SThierry Reding 55887d66f28SThierry Reding if (usb) 55987d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_USB_VAL << 56087d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT; 56187d66f28SThierry Reding else 56287d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SATA_VAL << 56387d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT; 56487d66f28SThierry Reding 56587d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 56687d66f28SThierry Reding 56787d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 56887d66f28SThierry Reding value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_IDDQ; 56987d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 57087d66f28SThierry Reding 57187d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 57287d66f28SThierry Reding value &= ~(XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_MASK << 57387d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_SHIFT); 57487d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 57587d66f28SThierry Reding 57687d66f28SThierry Reding usleep_range(10, 20); 57787d66f28SThierry Reding 57887d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL4); 57987d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL4_REFCLKBUF_EN; 58087d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL4); 58187d66f28SThierry Reding 58287d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 58387d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN; 58487d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 58587d66f28SThierry Reding 58687d66f28SThierry Reding timeout = jiffies + msecs_to_jiffies(100); 58787d66f28SThierry Reding 58887d66f28SThierry Reding while (time_before(jiffies, timeout)) { 58987d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 59087d66f28SThierry Reding if (value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE) 59187d66f28SThierry Reding break; 59287d66f28SThierry Reding 59387d66f28SThierry Reding usleep_range(10, 20); 59487d66f28SThierry Reding } 59587d66f28SThierry Reding 59687d66f28SThierry Reding if (time_after_eq(jiffies, timeout)) { 59787d66f28SThierry Reding err = -ETIMEDOUT; 59887d66f28SThierry Reding goto reset; 59987d66f28SThierry Reding } 60087d66f28SThierry Reding 60187d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 60287d66f28SThierry Reding value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN; 60387d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 60487d66f28SThierry Reding 60587d66f28SThierry Reding timeout = jiffies + msecs_to_jiffies(100); 60687d66f28SThierry Reding 60787d66f28SThierry Reding while (time_before(jiffies, timeout)) { 60887d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 60987d66f28SThierry Reding if (!(value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE)) 61087d66f28SThierry Reding break; 61187d66f28SThierry Reding 61287d66f28SThierry Reding usleep_range(10, 20); 61387d66f28SThierry Reding } 61487d66f28SThierry Reding 61587d66f28SThierry Reding if (time_after_eq(jiffies, timeout)) { 61687d66f28SThierry Reding err = -ETIMEDOUT; 61787d66f28SThierry Reding goto reset; 61887d66f28SThierry Reding } 61987d66f28SThierry Reding 62087d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 62187d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL1_ENABLE; 62287d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 62387d66f28SThierry Reding 62487d66f28SThierry Reding timeout = jiffies + msecs_to_jiffies(100); 62587d66f28SThierry Reding 62687d66f28SThierry Reding while (time_before(jiffies, timeout)) { 62787d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 62887d66f28SThierry Reding if (value & XUSB_PADCTL_UPHY_PLL_CTL1_LOCKDET_STATUS) 62987d66f28SThierry Reding break; 63087d66f28SThierry Reding 63187d66f28SThierry Reding usleep_range(10, 20); 63287d66f28SThierry Reding } 63387d66f28SThierry Reding 63487d66f28SThierry Reding if (time_after_eq(jiffies, timeout)) { 63587d66f28SThierry Reding err = -ETIMEDOUT; 63687d66f28SThierry Reding goto reset; 63787d66f28SThierry Reding } 63887d66f28SThierry Reding 63987d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 64087d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN | 64187d66f28SThierry Reding XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN; 64287d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 64387d66f28SThierry Reding 64487d66f28SThierry Reding timeout = jiffies + msecs_to_jiffies(100); 64587d66f28SThierry Reding 64687d66f28SThierry Reding while (time_before(jiffies, timeout)) { 64787d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 64887d66f28SThierry Reding if (value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE) 64987d66f28SThierry Reding break; 65087d66f28SThierry Reding 65187d66f28SThierry Reding usleep_range(10, 20); 65287d66f28SThierry Reding } 65387d66f28SThierry Reding 65487d66f28SThierry Reding if (time_after_eq(jiffies, timeout)) { 65587d66f28SThierry Reding err = -ETIMEDOUT; 65687d66f28SThierry Reding goto reset; 65787d66f28SThierry Reding } 65887d66f28SThierry Reding 65987d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 66087d66f28SThierry Reding value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN; 66187d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 66287d66f28SThierry Reding 66387d66f28SThierry Reding timeout = jiffies + msecs_to_jiffies(100); 66487d66f28SThierry Reding 66587d66f28SThierry Reding while (time_before(jiffies, timeout)) { 66687d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 66787d66f28SThierry Reding if (!(value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE)) 66887d66f28SThierry Reding break; 66987d66f28SThierry Reding 67087d66f28SThierry Reding usleep_range(10, 20); 67187d66f28SThierry Reding } 67287d66f28SThierry Reding 67387d66f28SThierry Reding if (time_after_eq(jiffies, timeout)) { 67487d66f28SThierry Reding err = -ETIMEDOUT; 67587d66f28SThierry Reding goto reset; 67687d66f28SThierry Reding } 67787d66f28SThierry Reding 67887d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 67987d66f28SThierry Reding value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN; 68087d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 68187d66f28SThierry Reding 68287d66f28SThierry Reding tegra210_sata_pll_hw_control_enable(); 68387d66f28SThierry Reding 68487d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 68587d66f28SThierry Reding value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD; 68687d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 68787d66f28SThierry Reding 68887d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 68987d66f28SThierry Reding value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD; 69087d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 69187d66f28SThierry Reding 69287d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 69387d66f28SThierry Reding value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD; 69487d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 69587d66f28SThierry Reding 69687d66f28SThierry Reding usleep_range(10, 20); 69787d66f28SThierry Reding 69887d66f28SThierry Reding tegra210_sata_pll_hw_sequence_start(); 69987d66f28SThierry Reding 70087d66f28SThierry Reding sata->enable++; 70187d66f28SThierry Reding 70287d66f28SThierry Reding return 0; 70387d66f28SThierry Reding 70487d66f28SThierry Reding reset: 70587d66f28SThierry Reding reset_control_assert(sata->rst); 70687d66f28SThierry Reding disable: 70787d66f28SThierry Reding clk_disable_unprepare(sata->pll); 70887d66f28SThierry Reding return err; 70987d66f28SThierry Reding } 71087d66f28SThierry Reding 71187d66f28SThierry Reding static void tegra210_sata_uphy_disable(struct tegra_xusb_padctl *padctl) 71287d66f28SThierry Reding { 71387d66f28SThierry Reding struct tegra_xusb_sata_pad *sata = to_sata_pad(padctl->sata); 71487d66f28SThierry Reding 71587d66f28SThierry Reding mutex_lock(&padctl->lock); 71687d66f28SThierry Reding 71787d66f28SThierry Reding if (WARN_ON(sata->enable == 0)) 71887d66f28SThierry Reding goto unlock; 71987d66f28SThierry Reding 72087d66f28SThierry Reding if (--sata->enable > 0) 72187d66f28SThierry Reding goto unlock; 72287d66f28SThierry Reding 72387d66f28SThierry Reding reset_control_assert(sata->rst); 72487d66f28SThierry Reding clk_disable_unprepare(sata->pll); 72587d66f28SThierry Reding 72687d66f28SThierry Reding unlock: 72787d66f28SThierry Reding mutex_unlock(&padctl->lock); 72887d66f28SThierry Reding } 72987d66f28SThierry Reding 73087d66f28SThierry Reding static int tegra210_xusb_padctl_enable(struct tegra_xusb_padctl *padctl) 73187d66f28SThierry Reding { 73287d66f28SThierry Reding u32 value; 73387d66f28SThierry Reding 73487d66f28SThierry Reding mutex_lock(&padctl->lock); 73587d66f28SThierry Reding 73687d66f28SThierry Reding if (padctl->enable++ > 0) 73787d66f28SThierry Reding goto out; 73887d66f28SThierry Reding 73987d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 74087d66f28SThierry Reding value &= ~XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN; 74187d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 74287d66f28SThierry Reding 74387d66f28SThierry Reding usleep_range(100, 200); 74487d66f28SThierry Reding 74587d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 74687d66f28SThierry Reding value &= ~XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY; 74787d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 74887d66f28SThierry Reding 74987d66f28SThierry Reding usleep_range(100, 200); 75087d66f28SThierry Reding 75187d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 75287d66f28SThierry Reding value &= ~XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN; 75387d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 75487d66f28SThierry Reding 75587d66f28SThierry Reding out: 75687d66f28SThierry Reding mutex_unlock(&padctl->lock); 75787d66f28SThierry Reding return 0; 75887d66f28SThierry Reding } 75987d66f28SThierry Reding 76087d66f28SThierry Reding static int tegra210_xusb_padctl_disable(struct tegra_xusb_padctl *padctl) 76187d66f28SThierry Reding { 76287d66f28SThierry Reding u32 value; 76387d66f28SThierry Reding 76487d66f28SThierry Reding mutex_lock(&padctl->lock); 76587d66f28SThierry Reding 76687d66f28SThierry Reding if (WARN_ON(padctl->enable == 0)) 76787d66f28SThierry Reding goto out; 76887d66f28SThierry Reding 76987d66f28SThierry Reding if (--padctl->enable > 0) 77087d66f28SThierry Reding goto out; 77187d66f28SThierry Reding 77287d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 77387d66f28SThierry Reding value |= XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN; 77487d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 77587d66f28SThierry Reding 77687d66f28SThierry Reding usleep_range(100, 200); 77787d66f28SThierry Reding 77887d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 77987d66f28SThierry Reding value |= XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY; 78087d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 78187d66f28SThierry Reding 78287d66f28SThierry Reding usleep_range(100, 200); 78387d66f28SThierry Reding 78487d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 78587d66f28SThierry Reding value |= XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN; 78687d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 78787d66f28SThierry Reding 78887d66f28SThierry Reding out: 78987d66f28SThierry Reding mutex_unlock(&padctl->lock); 79087d66f28SThierry Reding return 0; 79187d66f28SThierry Reding } 79287d66f28SThierry Reding 79387d66f28SThierry Reding static int tegra210_hsic_set_idle(struct tegra_xusb_padctl *padctl, 79487d66f28SThierry Reding unsigned int index, bool idle) 79587d66f28SThierry Reding { 79687d66f28SThierry Reding u32 value; 79787d66f28SThierry Reding 79887d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(index)); 79987d66f28SThierry Reding 80087d66f28SThierry Reding value &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA0 | 80187d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA1 | 80287d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_RPD_STROBE); 80387d66f28SThierry Reding 80487d66f28SThierry Reding if (idle) 80587d66f28SThierry Reding value |= XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA0 | 80687d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA1 | 80787d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE; 80887d66f28SThierry Reding else 80987d66f28SThierry Reding value &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA0 | 81087d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA1 | 81187d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE); 81287d66f28SThierry Reding 81387d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL0(index)); 81487d66f28SThierry Reding 81587d66f28SThierry Reding return 0; 81687d66f28SThierry Reding } 81787d66f28SThierry Reding 81887d66f28SThierry Reding static int tegra210_usb3_set_lfps_detect(struct tegra_xusb_padctl *padctl, 81987d66f28SThierry Reding unsigned int index, bool enable) 82087d66f28SThierry Reding { 82187d66f28SThierry Reding struct tegra_xusb_port *port; 82287d66f28SThierry Reding struct tegra_xusb_lane *lane; 82387d66f28SThierry Reding u32 value, offset; 82487d66f28SThierry Reding 82587d66f28SThierry Reding port = tegra_xusb_find_port(padctl, "usb3", index); 82687d66f28SThierry Reding if (!port) 82787d66f28SThierry Reding return -ENODEV; 82887d66f28SThierry Reding 82987d66f28SThierry Reding lane = port->lane; 83087d66f28SThierry Reding 83187d66f28SThierry Reding if (lane->pad == padctl->pcie) 83287d66f28SThierry Reding offset = XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL1(lane->index); 83387d66f28SThierry Reding else 83487d66f28SThierry Reding offset = XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL1; 83587d66f28SThierry Reding 83687d66f28SThierry Reding value = padctl_readl(padctl, offset); 83787d66f28SThierry Reding 83887d66f28SThierry Reding value &= ~((XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_MASK << 83987d66f28SThierry Reding XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_SHIFT) | 84087d66f28SThierry Reding XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_TERM_EN | 84187d66f28SThierry Reding XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_MODE_OVRD); 84287d66f28SThierry Reding 84387d66f28SThierry Reding if (!enable) { 84487d66f28SThierry Reding value |= (XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_VAL << 84587d66f28SThierry Reding XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_SHIFT) | 84687d66f28SThierry Reding XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_TERM_EN | 84787d66f28SThierry Reding XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_MODE_OVRD; 84887d66f28SThierry Reding } 84987d66f28SThierry Reding 85087d66f28SThierry Reding padctl_writel(padctl, value, offset); 85187d66f28SThierry Reding 85287d66f28SThierry Reding return 0; 85387d66f28SThierry Reding } 85487d66f28SThierry Reding 85587d66f28SThierry Reding #define TEGRA210_LANE(_name, _offset, _shift, _mask, _type) \ 85687d66f28SThierry Reding { \ 85787d66f28SThierry Reding .name = _name, \ 85887d66f28SThierry Reding .offset = _offset, \ 85987d66f28SThierry Reding .shift = _shift, \ 86087d66f28SThierry Reding .mask = _mask, \ 86187d66f28SThierry Reding .num_funcs = ARRAY_SIZE(tegra210_##_type##_functions), \ 86287d66f28SThierry Reding .funcs = tegra210_##_type##_functions, \ 86387d66f28SThierry Reding } 86487d66f28SThierry Reding 86587d66f28SThierry Reding static const char *tegra210_usb2_functions[] = { 86687d66f28SThierry Reding "snps", 86787d66f28SThierry Reding "xusb", 86887d66f28SThierry Reding "uart" 86987d66f28SThierry Reding }; 87087d66f28SThierry Reding 87187d66f28SThierry Reding static const struct tegra_xusb_lane_soc tegra210_usb2_lanes[] = { 87287d66f28SThierry Reding TEGRA210_LANE("usb2-0", 0x004, 0, 0x3, usb2), 87387d66f28SThierry Reding TEGRA210_LANE("usb2-1", 0x004, 2, 0x3, usb2), 87487d66f28SThierry Reding TEGRA210_LANE("usb2-2", 0x004, 4, 0x3, usb2), 87587d66f28SThierry Reding TEGRA210_LANE("usb2-3", 0x004, 6, 0x3, usb2), 87687d66f28SThierry Reding }; 87787d66f28SThierry Reding 87887d66f28SThierry Reding static struct tegra_xusb_lane * 87987d66f28SThierry Reding tegra210_usb2_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 88087d66f28SThierry Reding unsigned int index) 88187d66f28SThierry Reding { 88287d66f28SThierry Reding struct tegra_xusb_usb2_lane *usb2; 88387d66f28SThierry Reding int err; 88487d66f28SThierry Reding 88587d66f28SThierry Reding usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL); 88687d66f28SThierry Reding if (!usb2) 88787d66f28SThierry Reding return ERR_PTR(-ENOMEM); 88887d66f28SThierry Reding 88987d66f28SThierry Reding INIT_LIST_HEAD(&usb2->base.list); 89087d66f28SThierry Reding usb2->base.soc = &pad->soc->lanes[index]; 89187d66f28SThierry Reding usb2->base.index = index; 89287d66f28SThierry Reding usb2->base.pad = pad; 89387d66f28SThierry Reding usb2->base.np = np; 89487d66f28SThierry Reding 89587d66f28SThierry Reding err = tegra_xusb_lane_parse_dt(&usb2->base, np); 89687d66f28SThierry Reding if (err < 0) { 89787d66f28SThierry Reding kfree(usb2); 89887d66f28SThierry Reding return ERR_PTR(err); 89987d66f28SThierry Reding } 90087d66f28SThierry Reding 90187d66f28SThierry Reding return &usb2->base; 90287d66f28SThierry Reding } 90387d66f28SThierry Reding 90487d66f28SThierry Reding static void tegra210_usb2_lane_remove(struct tegra_xusb_lane *lane) 90587d66f28SThierry Reding { 90687d66f28SThierry Reding struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane); 90787d66f28SThierry Reding 90887d66f28SThierry Reding kfree(usb2); 90987d66f28SThierry Reding } 91087d66f28SThierry Reding 91187d66f28SThierry Reding static const struct tegra_xusb_lane_ops tegra210_usb2_lane_ops = { 91287d66f28SThierry Reding .probe = tegra210_usb2_lane_probe, 91387d66f28SThierry Reding .remove = tegra210_usb2_lane_remove, 91487d66f28SThierry Reding }; 91587d66f28SThierry Reding 91687d66f28SThierry Reding static int tegra210_usb2_phy_init(struct phy *phy) 91787d66f28SThierry Reding { 91887d66f28SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 91987d66f28SThierry Reding struct tegra_xusb_padctl *padctl = lane->pad->padctl; 92087d66f28SThierry Reding u32 value; 92187d66f28SThierry Reding 92287d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB2_PAD_MUX); 92387d66f28SThierry Reding value &= ~(XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_MASK << 92487d66f28SThierry Reding XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_SHIFT); 92587d66f28SThierry Reding value |= XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_XUSB << 92687d66f28SThierry Reding XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_SHIFT; 92787d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB2_PAD_MUX); 92887d66f28SThierry Reding 92987d66f28SThierry Reding return tegra210_xusb_padctl_enable(padctl); 93087d66f28SThierry Reding } 93187d66f28SThierry Reding 93287d66f28SThierry Reding static int tegra210_usb2_phy_exit(struct phy *phy) 93387d66f28SThierry Reding { 93487d66f28SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 93587d66f28SThierry Reding 93687d66f28SThierry Reding return tegra210_xusb_padctl_disable(lane->pad->padctl); 93787d66f28SThierry Reding } 93887d66f28SThierry Reding 939*de792a6dSNagarjuna Kristam static int tegra210_xusb_padctl_vbus_override(struct tegra_xusb_padctl *padctl, 940*de792a6dSNagarjuna Kristam bool status) 941*de792a6dSNagarjuna Kristam { 942*de792a6dSNagarjuna Kristam u32 value; 943*de792a6dSNagarjuna Kristam 944*de792a6dSNagarjuna Kristam dev_dbg(padctl->dev, "%s vbus override\n", status ? "set" : "clear"); 945*de792a6dSNagarjuna Kristam 946*de792a6dSNagarjuna Kristam value = padctl_readl(padctl, XUSB_PADCTL_USB2_VBUS_ID); 947*de792a6dSNagarjuna Kristam 948*de792a6dSNagarjuna Kristam if (status) { 949*de792a6dSNagarjuna Kristam value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON; 950*de792a6dSNagarjuna Kristam value &= ~(XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK << 951*de792a6dSNagarjuna Kristam XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT); 952*de792a6dSNagarjuna Kristam value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING << 953*de792a6dSNagarjuna Kristam XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT; 954*de792a6dSNagarjuna Kristam } else { 955*de792a6dSNagarjuna Kristam value &= ~XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON; 956*de792a6dSNagarjuna Kristam } 957*de792a6dSNagarjuna Kristam 958*de792a6dSNagarjuna Kristam padctl_writel(padctl, value, XUSB_PADCTL_USB2_VBUS_ID); 959*de792a6dSNagarjuna Kristam 960*de792a6dSNagarjuna Kristam return 0; 961*de792a6dSNagarjuna Kristam } 962*de792a6dSNagarjuna Kristam 963*de792a6dSNagarjuna Kristam static int tegra210_xusb_padctl_id_override(struct tegra_xusb_padctl *padctl, 964*de792a6dSNagarjuna Kristam bool status) 965*de792a6dSNagarjuna Kristam { 966*de792a6dSNagarjuna Kristam u32 value; 967*de792a6dSNagarjuna Kristam 968*de792a6dSNagarjuna Kristam dev_dbg(padctl->dev, "%s id override\n", status ? "set" : "clear"); 969*de792a6dSNagarjuna Kristam 970*de792a6dSNagarjuna Kristam value = padctl_readl(padctl, XUSB_PADCTL_USB2_VBUS_ID); 971*de792a6dSNagarjuna Kristam 972*de792a6dSNagarjuna Kristam if (status) { 973*de792a6dSNagarjuna Kristam if (value & XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON) { 974*de792a6dSNagarjuna Kristam value &= ~XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON; 975*de792a6dSNagarjuna Kristam padctl_writel(padctl, value, XUSB_PADCTL_USB2_VBUS_ID); 976*de792a6dSNagarjuna Kristam usleep_range(1000, 2000); 977*de792a6dSNagarjuna Kristam 978*de792a6dSNagarjuna Kristam value = padctl_readl(padctl, XUSB_PADCTL_USB2_VBUS_ID); 979*de792a6dSNagarjuna Kristam } 980*de792a6dSNagarjuna Kristam 981*de792a6dSNagarjuna Kristam value &= ~(XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK << 982*de792a6dSNagarjuna Kristam XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT); 983*de792a6dSNagarjuna Kristam value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_GROUNDED << 984*de792a6dSNagarjuna Kristam XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT; 985*de792a6dSNagarjuna Kristam } else { 986*de792a6dSNagarjuna Kristam value &= ~(XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK << 987*de792a6dSNagarjuna Kristam XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT); 988*de792a6dSNagarjuna Kristam value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING << 989*de792a6dSNagarjuna Kristam XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT; 990*de792a6dSNagarjuna Kristam } 991*de792a6dSNagarjuna Kristam 992*de792a6dSNagarjuna Kristam padctl_writel(padctl, value, XUSB_PADCTL_USB2_VBUS_ID); 993*de792a6dSNagarjuna Kristam 994*de792a6dSNagarjuna Kristam return 0; 995*de792a6dSNagarjuna Kristam } 996*de792a6dSNagarjuna Kristam 997*de792a6dSNagarjuna Kristam static int tegra210_usb2_phy_set_mode(struct phy *phy, enum phy_mode mode, 998*de792a6dSNagarjuna Kristam int submode) 999*de792a6dSNagarjuna Kristam { 1000*de792a6dSNagarjuna Kristam struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 1001*de792a6dSNagarjuna Kristam struct tegra_xusb_padctl *padctl = lane->pad->padctl; 1002*de792a6dSNagarjuna Kristam struct tegra_xusb_usb2_port *port = tegra_xusb_find_usb2_port(padctl, 1003*de792a6dSNagarjuna Kristam lane->index); 1004*de792a6dSNagarjuna Kristam int err = 0; 1005*de792a6dSNagarjuna Kristam 1006*de792a6dSNagarjuna Kristam mutex_lock(&padctl->lock); 1007*de792a6dSNagarjuna Kristam 1008*de792a6dSNagarjuna Kristam dev_dbg(&port->base.dev, "%s: mode %d", __func__, mode); 1009*de792a6dSNagarjuna Kristam 1010*de792a6dSNagarjuna Kristam if (mode == PHY_MODE_USB_OTG) { 1011*de792a6dSNagarjuna Kristam if (submode == USB_ROLE_HOST) { 1012*de792a6dSNagarjuna Kristam tegra210_xusb_padctl_id_override(padctl, true); 1013*de792a6dSNagarjuna Kristam 1014*de792a6dSNagarjuna Kristam err = regulator_enable(port->supply); 1015*de792a6dSNagarjuna Kristam } else if (submode == USB_ROLE_DEVICE) { 1016*de792a6dSNagarjuna Kristam tegra210_xusb_padctl_vbus_override(padctl, true); 1017*de792a6dSNagarjuna Kristam } else if (submode == USB_ROLE_NONE) { 1018*de792a6dSNagarjuna Kristam /* 1019*de792a6dSNagarjuna Kristam * When port is peripheral only or role transitions to 1020*de792a6dSNagarjuna Kristam * USB_ROLE_NONE from USB_ROLE_DEVICE, regulator is not 1021*de792a6dSNagarjuna Kristam * be enabled. 1022*de792a6dSNagarjuna Kristam */ 1023*de792a6dSNagarjuna Kristam if (regulator_is_enabled(port->supply)) 1024*de792a6dSNagarjuna Kristam regulator_disable(port->supply); 1025*de792a6dSNagarjuna Kristam 1026*de792a6dSNagarjuna Kristam tegra210_xusb_padctl_id_override(padctl, false); 1027*de792a6dSNagarjuna Kristam tegra210_xusb_padctl_vbus_override(padctl, false); 1028*de792a6dSNagarjuna Kristam } 1029*de792a6dSNagarjuna Kristam } 1030*de792a6dSNagarjuna Kristam 1031*de792a6dSNagarjuna Kristam mutex_unlock(&padctl->lock); 1032*de792a6dSNagarjuna Kristam 1033*de792a6dSNagarjuna Kristam return err; 1034*de792a6dSNagarjuna Kristam } 1035*de792a6dSNagarjuna Kristam 103687d66f28SThierry Reding static int tegra210_usb2_phy_power_on(struct phy *phy) 103787d66f28SThierry Reding { 103887d66f28SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 103987d66f28SThierry Reding struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane); 104087d66f28SThierry Reding struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad); 104187d66f28SThierry Reding struct tegra_xusb_padctl *padctl = lane->pad->padctl; 104287d66f28SThierry Reding struct tegra210_xusb_padctl *priv; 104387d66f28SThierry Reding struct tegra_xusb_usb2_port *port; 104487d66f28SThierry Reding unsigned int index = lane->index; 104587d66f28SThierry Reding u32 value; 104687d66f28SThierry Reding int err; 104787d66f28SThierry Reding 104887d66f28SThierry Reding port = tegra_xusb_find_usb2_port(padctl, index); 104987d66f28SThierry Reding if (!port) { 105087d66f28SThierry Reding dev_err(&phy->dev, "no port found for USB2 lane %u\n", index); 105187d66f28SThierry Reding return -ENODEV; 105287d66f28SThierry Reding } 105387d66f28SThierry Reding 105487d66f28SThierry Reding priv = to_tegra210_xusb_padctl(padctl); 105587d66f28SThierry Reding 1056a5be28c3SNagarjuna Kristam if (port->usb3_port_fake != -1) { 1057a5be28c3SNagarjuna Kristam value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); 1058a5be28c3SNagarjuna Kristam value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK( 1059a5be28c3SNagarjuna Kristam port->usb3_port_fake); 1060a5be28c3SNagarjuna Kristam value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP( 1061a5be28c3SNagarjuna Kristam port->usb3_port_fake, index); 1062a5be28c3SNagarjuna Kristam padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); 1063a5be28c3SNagarjuna Kristam 1064a5be28c3SNagarjuna Kristam value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 1065a5be28c3SNagarjuna Kristam value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN( 1066a5be28c3SNagarjuna Kristam port->usb3_port_fake); 1067a5be28c3SNagarjuna Kristam padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 1068a5be28c3SNagarjuna Kristam 1069a5be28c3SNagarjuna Kristam usleep_range(100, 200); 1070a5be28c3SNagarjuna Kristam 1071a5be28c3SNagarjuna Kristam value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 1072a5be28c3SNagarjuna Kristam value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY( 1073a5be28c3SNagarjuna Kristam port->usb3_port_fake); 1074a5be28c3SNagarjuna Kristam padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 1075a5be28c3SNagarjuna Kristam 1076a5be28c3SNagarjuna Kristam usleep_range(100, 200); 1077a5be28c3SNagarjuna Kristam 1078a5be28c3SNagarjuna Kristam value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 1079a5be28c3SNagarjuna Kristam value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN( 1080a5be28c3SNagarjuna Kristam port->usb3_port_fake); 1081a5be28c3SNagarjuna Kristam padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 1082a5be28c3SNagarjuna Kristam } 1083a5be28c3SNagarjuna Kristam 108487d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 108587d66f28SThierry Reding value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK << 108687d66f28SThierry Reding XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) | 108787d66f28SThierry Reding (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK << 108887d66f28SThierry Reding XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT)); 108987d66f28SThierry Reding value |= (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL << 109087d66f28SThierry Reding XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT); 109187d66f28SThierry Reding 109287d66f28SThierry Reding if (tegra_sku_info.revision < TEGRA_REVISION_A02) 109387d66f28SThierry Reding value |= 109487d66f28SThierry Reding (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_VAL << 109587d66f28SThierry Reding XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT); 109687d66f28SThierry Reding 109787d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 109887d66f28SThierry Reding 109987d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB2_PORT_CAP); 110087d66f28SThierry Reding value &= ~XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_MASK(index); 1101ac25b6e9SNagarjuna Kristam if (port->mode == USB_DR_MODE_UNKNOWN) 1102ac25b6e9SNagarjuna Kristam value |= XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_DISABLED(index); 1103ac25b6e9SNagarjuna Kristam else if (port->mode == USB_DR_MODE_PERIPHERAL) 1104ac25b6e9SNagarjuna Kristam value |= XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_DEVICE(index); 1105ac25b6e9SNagarjuna Kristam else if (port->mode == USB_DR_MODE_HOST) 110687d66f28SThierry Reding value |= XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_HOST(index); 1107ac25b6e9SNagarjuna Kristam else if (port->mode == USB_DR_MODE_OTG) 1108ac25b6e9SNagarjuna Kristam value |= XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_OTG(index); 110987d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB2_PORT_CAP); 111087d66f28SThierry Reding 111187d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index)); 111287d66f28SThierry Reding value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK << 111387d66f28SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT) | 111487d66f28SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD | 111587d66f28SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 | 111687d66f28SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI); 111787d66f28SThierry Reding value |= (priv->fuse.hs_curr_level[index] + 111887d66f28SThierry Reding usb2->hs_curr_level_offset) << 111987d66f28SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT; 112087d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index)); 112187d66f28SThierry Reding 112287d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index)); 112387d66f28SThierry Reding value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK << 112487d66f28SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) | 112587d66f28SThierry Reding (XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_MASK << 112687d66f28SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_SHIFT) | 112787d66f28SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR | 112887d66f28SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_OVRD | 112987d66f28SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_OVRD); 113087d66f28SThierry Reding value |= (priv->fuse.hs_term_range_adj << 113187d66f28SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) | 113287d66f28SThierry Reding (priv->fuse.rpd_ctrl << 113387d66f28SThierry Reding XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_SHIFT); 113487d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index)); 113587d66f28SThierry Reding 113687d66f28SThierry Reding value = padctl_readl(padctl, 113787d66f28SThierry Reding XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(index)); 113887d66f28SThierry Reding value &= ~(XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_MASK << 113987d66f28SThierry Reding XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_SHIFT); 1140ac25b6e9SNagarjuna Kristam if (port->mode == USB_DR_MODE_HOST) 114187d66f28SThierry Reding value |= XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_FIX18; 1142ac25b6e9SNagarjuna Kristam else 1143ac25b6e9SNagarjuna Kristam value |= 1144ac25b6e9SNagarjuna Kristam XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_VAL << 1145ac25b6e9SNagarjuna Kristam XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_SHIFT; 114687d66f28SThierry Reding padctl_writel(padctl, value, 114787d66f28SThierry Reding XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(index)); 114887d66f28SThierry Reding 1149*de792a6dSNagarjuna Kristam if (port->supply && port->mode == USB_DR_MODE_HOST) { 115087d66f28SThierry Reding err = regulator_enable(port->supply); 115187d66f28SThierry Reding if (err) 115287d66f28SThierry Reding return err; 1153*de792a6dSNagarjuna Kristam } 115487d66f28SThierry Reding 115587d66f28SThierry Reding mutex_lock(&padctl->lock); 115687d66f28SThierry Reding 115787d66f28SThierry Reding if (pad->enable > 0) { 115887d66f28SThierry Reding pad->enable++; 115987d66f28SThierry Reding mutex_unlock(&padctl->lock); 116087d66f28SThierry Reding return 0; 116187d66f28SThierry Reding } 116287d66f28SThierry Reding 116387d66f28SThierry Reding err = clk_prepare_enable(pad->clk); 116487d66f28SThierry Reding if (err) 116587d66f28SThierry Reding goto disable_regulator; 116687d66f28SThierry Reding 116787d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); 116887d66f28SThierry Reding value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_MASK << 116987d66f28SThierry Reding XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_SHIFT) | 117087d66f28SThierry Reding (XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_MASK << 117187d66f28SThierry Reding XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_SHIFT)); 117287d66f28SThierry Reding value |= (XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_VAL << 117387d66f28SThierry Reding XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_SHIFT) | 117487d66f28SThierry Reding (XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_VAL << 117587d66f28SThierry Reding XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_SHIFT); 117687d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); 117787d66f28SThierry Reding 117887d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 117987d66f28SThierry Reding value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD; 118087d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 118187d66f28SThierry Reding 118287d66f28SThierry Reding udelay(1); 118387d66f28SThierry Reding 118487d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); 118587d66f28SThierry Reding value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL1_PD_TRK; 118687d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); 118787d66f28SThierry Reding 118887d66f28SThierry Reding udelay(50); 118987d66f28SThierry Reding 119087d66f28SThierry Reding clk_disable_unprepare(pad->clk); 119187d66f28SThierry Reding 119287d66f28SThierry Reding pad->enable++; 119387d66f28SThierry Reding mutex_unlock(&padctl->lock); 119487d66f28SThierry Reding 119587d66f28SThierry Reding return 0; 119687d66f28SThierry Reding 119787d66f28SThierry Reding disable_regulator: 119887d66f28SThierry Reding regulator_disable(port->supply); 119987d66f28SThierry Reding mutex_unlock(&padctl->lock); 120087d66f28SThierry Reding return err; 120187d66f28SThierry Reding } 120287d66f28SThierry Reding 120387d66f28SThierry Reding static int tegra210_usb2_phy_power_off(struct phy *phy) 120487d66f28SThierry Reding { 120587d66f28SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 120687d66f28SThierry Reding struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad); 120787d66f28SThierry Reding struct tegra_xusb_padctl *padctl = lane->pad->padctl; 120887d66f28SThierry Reding struct tegra_xusb_usb2_port *port; 120987d66f28SThierry Reding u32 value; 121087d66f28SThierry Reding 121187d66f28SThierry Reding port = tegra_xusb_find_usb2_port(padctl, lane->index); 121287d66f28SThierry Reding if (!port) { 121387d66f28SThierry Reding dev_err(&phy->dev, "no port found for USB2 lane %u\n", 121487d66f28SThierry Reding lane->index); 121587d66f28SThierry Reding return -ENODEV; 121687d66f28SThierry Reding } 121787d66f28SThierry Reding 121887d66f28SThierry Reding mutex_lock(&padctl->lock); 121987d66f28SThierry Reding 1220a5be28c3SNagarjuna Kristam if (port->usb3_port_fake != -1) { 1221a5be28c3SNagarjuna Kristam value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 1222a5be28c3SNagarjuna Kristam value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY( 1223a5be28c3SNagarjuna Kristam port->usb3_port_fake); 1224a5be28c3SNagarjuna Kristam padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 1225a5be28c3SNagarjuna Kristam 1226a5be28c3SNagarjuna Kristam usleep_range(100, 200); 1227a5be28c3SNagarjuna Kristam 1228a5be28c3SNagarjuna Kristam value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 1229a5be28c3SNagarjuna Kristam value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN( 1230a5be28c3SNagarjuna Kristam port->usb3_port_fake); 1231a5be28c3SNagarjuna Kristam padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 1232a5be28c3SNagarjuna Kristam 1233a5be28c3SNagarjuna Kristam usleep_range(250, 350); 1234a5be28c3SNagarjuna Kristam 1235a5be28c3SNagarjuna Kristam value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 1236a5be28c3SNagarjuna Kristam value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN( 1237a5be28c3SNagarjuna Kristam port->usb3_port_fake); 1238a5be28c3SNagarjuna Kristam padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 1239a5be28c3SNagarjuna Kristam 1240a5be28c3SNagarjuna Kristam value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); 1241a5be28c3SNagarjuna Kristam value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(port->usb3_port_fake, 1242a5be28c3SNagarjuna Kristam XUSB_PADCTL_SS_PORT_MAP_PORT_DISABLED); 1243a5be28c3SNagarjuna Kristam padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); 1244a5be28c3SNagarjuna Kristam } 1245a5be28c3SNagarjuna Kristam 124687d66f28SThierry Reding if (WARN_ON(pad->enable == 0)) 124787d66f28SThierry Reding goto out; 124887d66f28SThierry Reding 124987d66f28SThierry Reding if (--pad->enable > 0) 125087d66f28SThierry Reding goto out; 125187d66f28SThierry Reding 125287d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 125387d66f28SThierry Reding value |= XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD; 125487d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 125587d66f28SThierry Reding 125687d66f28SThierry Reding out: 125787d66f28SThierry Reding regulator_disable(port->supply); 125887d66f28SThierry Reding mutex_unlock(&padctl->lock); 125987d66f28SThierry Reding return 0; 126087d66f28SThierry Reding } 126187d66f28SThierry Reding 126287d66f28SThierry Reding static const struct phy_ops tegra210_usb2_phy_ops = { 126387d66f28SThierry Reding .init = tegra210_usb2_phy_init, 126487d66f28SThierry Reding .exit = tegra210_usb2_phy_exit, 126587d66f28SThierry Reding .power_on = tegra210_usb2_phy_power_on, 126687d66f28SThierry Reding .power_off = tegra210_usb2_phy_power_off, 1267*de792a6dSNagarjuna Kristam .set_mode = tegra210_usb2_phy_set_mode, 126887d66f28SThierry Reding .owner = THIS_MODULE, 126987d66f28SThierry Reding }; 127087d66f28SThierry Reding 127187d66f28SThierry Reding static struct tegra_xusb_pad * 127287d66f28SThierry Reding tegra210_usb2_pad_probe(struct tegra_xusb_padctl *padctl, 127387d66f28SThierry Reding const struct tegra_xusb_pad_soc *soc, 127487d66f28SThierry Reding struct device_node *np) 127587d66f28SThierry Reding { 127687d66f28SThierry Reding struct tegra_xusb_usb2_pad *usb2; 127787d66f28SThierry Reding struct tegra_xusb_pad *pad; 127887d66f28SThierry Reding int err; 127987d66f28SThierry Reding 128087d66f28SThierry Reding usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL); 128187d66f28SThierry Reding if (!usb2) 128287d66f28SThierry Reding return ERR_PTR(-ENOMEM); 128387d66f28SThierry Reding 128487d66f28SThierry Reding pad = &usb2->base; 128587d66f28SThierry Reding pad->ops = &tegra210_usb2_lane_ops; 128687d66f28SThierry Reding pad->soc = soc; 128787d66f28SThierry Reding 128887d66f28SThierry Reding err = tegra_xusb_pad_init(pad, padctl, np); 128987d66f28SThierry Reding if (err < 0) { 129087d66f28SThierry Reding kfree(usb2); 129187d66f28SThierry Reding goto out; 129287d66f28SThierry Reding } 129387d66f28SThierry Reding 129487d66f28SThierry Reding usb2->clk = devm_clk_get(&pad->dev, "trk"); 129587d66f28SThierry Reding if (IS_ERR(usb2->clk)) { 129687d66f28SThierry Reding err = PTR_ERR(usb2->clk); 129787d66f28SThierry Reding dev_err(&pad->dev, "failed to get trk clock: %d\n", err); 129887d66f28SThierry Reding goto unregister; 129987d66f28SThierry Reding } 130087d66f28SThierry Reding 130187d66f28SThierry Reding err = tegra_xusb_pad_register(pad, &tegra210_usb2_phy_ops); 130287d66f28SThierry Reding if (err < 0) 130387d66f28SThierry Reding goto unregister; 130487d66f28SThierry Reding 130587d66f28SThierry Reding dev_set_drvdata(&pad->dev, pad); 130687d66f28SThierry Reding 130787d66f28SThierry Reding return pad; 130887d66f28SThierry Reding 130987d66f28SThierry Reding unregister: 131087d66f28SThierry Reding device_unregister(&pad->dev); 131187d66f28SThierry Reding out: 131287d66f28SThierry Reding return ERR_PTR(err); 131387d66f28SThierry Reding } 131487d66f28SThierry Reding 131587d66f28SThierry Reding static void tegra210_usb2_pad_remove(struct tegra_xusb_pad *pad) 131687d66f28SThierry Reding { 131787d66f28SThierry Reding struct tegra_xusb_usb2_pad *usb2 = to_usb2_pad(pad); 131887d66f28SThierry Reding 131987d66f28SThierry Reding kfree(usb2); 132087d66f28SThierry Reding } 132187d66f28SThierry Reding 132287d66f28SThierry Reding static const struct tegra_xusb_pad_ops tegra210_usb2_ops = { 132387d66f28SThierry Reding .probe = tegra210_usb2_pad_probe, 132487d66f28SThierry Reding .remove = tegra210_usb2_pad_remove, 132587d66f28SThierry Reding }; 132687d66f28SThierry Reding 132787d66f28SThierry Reding static const struct tegra_xusb_pad_soc tegra210_usb2_pad = { 132887d66f28SThierry Reding .name = "usb2", 132987d66f28SThierry Reding .num_lanes = ARRAY_SIZE(tegra210_usb2_lanes), 133087d66f28SThierry Reding .lanes = tegra210_usb2_lanes, 133187d66f28SThierry Reding .ops = &tegra210_usb2_ops, 133287d66f28SThierry Reding }; 133387d66f28SThierry Reding 133487d66f28SThierry Reding static const char *tegra210_hsic_functions[] = { 133587d66f28SThierry Reding "snps", 133687d66f28SThierry Reding "xusb", 133787d66f28SThierry Reding }; 133887d66f28SThierry Reding 133987d66f28SThierry Reding static const struct tegra_xusb_lane_soc tegra210_hsic_lanes[] = { 134087d66f28SThierry Reding TEGRA210_LANE("hsic-0", 0x004, 14, 0x1, hsic), 134187d66f28SThierry Reding }; 134287d66f28SThierry Reding 134387d66f28SThierry Reding static struct tegra_xusb_lane * 134487d66f28SThierry Reding tegra210_hsic_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 134587d66f28SThierry Reding unsigned int index) 134687d66f28SThierry Reding { 134787d66f28SThierry Reding struct tegra_xusb_hsic_lane *hsic; 134887d66f28SThierry Reding int err; 134987d66f28SThierry Reding 135087d66f28SThierry Reding hsic = kzalloc(sizeof(*hsic), GFP_KERNEL); 135187d66f28SThierry Reding if (!hsic) 135287d66f28SThierry Reding return ERR_PTR(-ENOMEM); 135387d66f28SThierry Reding 135487d66f28SThierry Reding INIT_LIST_HEAD(&hsic->base.list); 135587d66f28SThierry Reding hsic->base.soc = &pad->soc->lanes[index]; 135687d66f28SThierry Reding hsic->base.index = index; 135787d66f28SThierry Reding hsic->base.pad = pad; 135887d66f28SThierry Reding hsic->base.np = np; 135987d66f28SThierry Reding 136087d66f28SThierry Reding err = tegra_xusb_lane_parse_dt(&hsic->base, np); 136187d66f28SThierry Reding if (err < 0) { 136287d66f28SThierry Reding kfree(hsic); 136387d66f28SThierry Reding return ERR_PTR(err); 136487d66f28SThierry Reding } 136587d66f28SThierry Reding 136687d66f28SThierry Reding return &hsic->base; 136787d66f28SThierry Reding } 136887d66f28SThierry Reding 136987d66f28SThierry Reding static void tegra210_hsic_lane_remove(struct tegra_xusb_lane *lane) 137087d66f28SThierry Reding { 137187d66f28SThierry Reding struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane); 137287d66f28SThierry Reding 137387d66f28SThierry Reding kfree(hsic); 137487d66f28SThierry Reding } 137587d66f28SThierry Reding 137687d66f28SThierry Reding static const struct tegra_xusb_lane_ops tegra210_hsic_lane_ops = { 137787d66f28SThierry Reding .probe = tegra210_hsic_lane_probe, 137887d66f28SThierry Reding .remove = tegra210_hsic_lane_remove, 137987d66f28SThierry Reding }; 138087d66f28SThierry Reding 138187d66f28SThierry Reding static int tegra210_hsic_phy_init(struct phy *phy) 138287d66f28SThierry Reding { 138387d66f28SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 138487d66f28SThierry Reding struct tegra_xusb_padctl *padctl = lane->pad->padctl; 138587d66f28SThierry Reding u32 value; 138687d66f28SThierry Reding 138787d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB2_PAD_MUX); 138887d66f28SThierry Reding value &= ~(XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_MASK << 138987d66f28SThierry Reding XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_SHIFT); 139087d66f28SThierry Reding value |= XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_XUSB << 139187d66f28SThierry Reding XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_SHIFT; 139287d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB2_PAD_MUX); 139387d66f28SThierry Reding 139487d66f28SThierry Reding return tegra210_xusb_padctl_enable(padctl); 139587d66f28SThierry Reding } 139687d66f28SThierry Reding 139787d66f28SThierry Reding static int tegra210_hsic_phy_exit(struct phy *phy) 139887d66f28SThierry Reding { 139987d66f28SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 140087d66f28SThierry Reding 140187d66f28SThierry Reding return tegra210_xusb_padctl_disable(lane->pad->padctl); 140287d66f28SThierry Reding } 140387d66f28SThierry Reding 140487d66f28SThierry Reding static int tegra210_hsic_phy_power_on(struct phy *phy) 140587d66f28SThierry Reding { 140687d66f28SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 140787d66f28SThierry Reding struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane); 140887d66f28SThierry Reding struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad); 140987d66f28SThierry Reding struct tegra_xusb_padctl *padctl = lane->pad->padctl; 141087d66f28SThierry Reding unsigned int index = lane->index; 141187d66f28SThierry Reding u32 value; 141287d66f28SThierry Reding int err; 141387d66f28SThierry Reding 141487d66f28SThierry Reding err = regulator_enable(pad->supply); 141587d66f28SThierry Reding if (err) 141687d66f28SThierry Reding return err; 141787d66f28SThierry Reding 141887d66f28SThierry Reding padctl_writel(padctl, hsic->strobe_trim, 141987d66f28SThierry Reding XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL); 142087d66f28SThierry Reding 142187d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 142287d66f28SThierry Reding value &= ~(XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_MASK << 142387d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_SHIFT); 142487d66f28SThierry Reding value |= (hsic->tx_rtune_p << 142587d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_SHIFT); 142687d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 142787d66f28SThierry Reding 142887d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL2(index)); 142987d66f28SThierry Reding value &= ~((XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK << 143087d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) | 143187d66f28SThierry Reding (XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK << 143287d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT)); 143387d66f28SThierry Reding value |= (hsic->rx_strobe_trim << 143487d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) | 143587d66f28SThierry Reding (hsic->rx_data_trim << 143687d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT); 143787d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL2(index)); 143887d66f28SThierry Reding 143987d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(index)); 144087d66f28SThierry Reding value &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA0 | 144187d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA1 | 144287d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE | 144387d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA0 | 144487d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA1 | 144587d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_STROBE | 144687d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA0 | 144787d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA1 | 144887d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_STROBE | 144987d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA0 | 145087d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA1 | 145187d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_STROBE); 145287d66f28SThierry Reding value |= XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA0 | 145387d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA1 | 145487d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_RPD_STROBE; 145587d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL0(index)); 145687d66f28SThierry Reding 145787d66f28SThierry Reding err = clk_prepare_enable(pad->clk); 145887d66f28SThierry Reding if (err) 145987d66f28SThierry Reding goto disable; 146087d66f28SThierry Reding 146187d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PAD_TRK_CTL); 146287d66f28SThierry Reding value &= ~((XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_MASK << 146387d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_SHIFT) | 146487d66f28SThierry Reding (XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_MASK << 146587d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_SHIFT)); 146687d66f28SThierry Reding value |= (XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_VAL << 146787d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_SHIFT) | 146887d66f28SThierry Reding (XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_VAL << 146987d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_SHIFT); 147087d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PAD_TRK_CTL); 147187d66f28SThierry Reding 147287d66f28SThierry Reding udelay(1); 147387d66f28SThierry Reding 147487d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PAD_TRK_CTL); 147587d66f28SThierry Reding value &= ~XUSB_PADCTL_HSIC_PAD_TRK_CTL_PD_TRK; 147687d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PAD_TRK_CTL); 147787d66f28SThierry Reding 147887d66f28SThierry Reding udelay(50); 147987d66f28SThierry Reding 148087d66f28SThierry Reding clk_disable_unprepare(pad->clk); 148187d66f28SThierry Reding 148287d66f28SThierry Reding return 0; 148387d66f28SThierry Reding 148487d66f28SThierry Reding disable: 148587d66f28SThierry Reding regulator_disable(pad->supply); 148687d66f28SThierry Reding return err; 148787d66f28SThierry Reding } 148887d66f28SThierry Reding 148987d66f28SThierry Reding static int tegra210_hsic_phy_power_off(struct phy *phy) 149087d66f28SThierry Reding { 149187d66f28SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 149287d66f28SThierry Reding struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad); 149387d66f28SThierry Reding struct tegra_xusb_padctl *padctl = lane->pad->padctl; 149487d66f28SThierry Reding unsigned int index = lane->index; 149587d66f28SThierry Reding u32 value; 149687d66f28SThierry Reding 149787d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(index)); 149887d66f28SThierry Reding value |= XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA0 | 149987d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA1 | 150087d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_STROBE | 150187d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA0 | 150287d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA1 | 150387d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_STROBE | 150487d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA0 | 150587d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA1 | 150687d66f28SThierry Reding XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_STROBE; 150787d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 150887d66f28SThierry Reding 150987d66f28SThierry Reding regulator_disable(pad->supply); 151087d66f28SThierry Reding 151187d66f28SThierry Reding return 0; 151287d66f28SThierry Reding } 151387d66f28SThierry Reding 151487d66f28SThierry Reding static const struct phy_ops tegra210_hsic_phy_ops = { 151587d66f28SThierry Reding .init = tegra210_hsic_phy_init, 151687d66f28SThierry Reding .exit = tegra210_hsic_phy_exit, 151787d66f28SThierry Reding .power_on = tegra210_hsic_phy_power_on, 151887d66f28SThierry Reding .power_off = tegra210_hsic_phy_power_off, 151987d66f28SThierry Reding .owner = THIS_MODULE, 152087d66f28SThierry Reding }; 152187d66f28SThierry Reding 152287d66f28SThierry Reding static struct tegra_xusb_pad * 152387d66f28SThierry Reding tegra210_hsic_pad_probe(struct tegra_xusb_padctl *padctl, 152487d66f28SThierry Reding const struct tegra_xusb_pad_soc *soc, 152587d66f28SThierry Reding struct device_node *np) 152687d66f28SThierry Reding { 152787d66f28SThierry Reding struct tegra_xusb_hsic_pad *hsic; 152887d66f28SThierry Reding struct tegra_xusb_pad *pad; 152987d66f28SThierry Reding int err; 153087d66f28SThierry Reding 153187d66f28SThierry Reding hsic = kzalloc(sizeof(*hsic), GFP_KERNEL); 153287d66f28SThierry Reding if (!hsic) 153387d66f28SThierry Reding return ERR_PTR(-ENOMEM); 153487d66f28SThierry Reding 153587d66f28SThierry Reding pad = &hsic->base; 153687d66f28SThierry Reding pad->ops = &tegra210_hsic_lane_ops; 153787d66f28SThierry Reding pad->soc = soc; 153887d66f28SThierry Reding 153987d66f28SThierry Reding err = tegra_xusb_pad_init(pad, padctl, np); 154087d66f28SThierry Reding if (err < 0) { 154187d66f28SThierry Reding kfree(hsic); 154287d66f28SThierry Reding goto out; 154387d66f28SThierry Reding } 154487d66f28SThierry Reding 154587d66f28SThierry Reding hsic->clk = devm_clk_get(&pad->dev, "trk"); 154687d66f28SThierry Reding if (IS_ERR(hsic->clk)) { 154787d66f28SThierry Reding err = PTR_ERR(hsic->clk); 154887d66f28SThierry Reding dev_err(&pad->dev, "failed to get trk clock: %d\n", err); 154987d66f28SThierry Reding goto unregister; 155087d66f28SThierry Reding } 155187d66f28SThierry Reding 155287d66f28SThierry Reding err = tegra_xusb_pad_register(pad, &tegra210_hsic_phy_ops); 155387d66f28SThierry Reding if (err < 0) 155487d66f28SThierry Reding goto unregister; 155587d66f28SThierry Reding 155687d66f28SThierry Reding dev_set_drvdata(&pad->dev, pad); 155787d66f28SThierry Reding 155887d66f28SThierry Reding return pad; 155987d66f28SThierry Reding 156087d66f28SThierry Reding unregister: 156187d66f28SThierry Reding device_unregister(&pad->dev); 156287d66f28SThierry Reding out: 156387d66f28SThierry Reding return ERR_PTR(err); 156487d66f28SThierry Reding } 156587d66f28SThierry Reding 156687d66f28SThierry Reding static void tegra210_hsic_pad_remove(struct tegra_xusb_pad *pad) 156787d66f28SThierry Reding { 156887d66f28SThierry Reding struct tegra_xusb_hsic_pad *hsic = to_hsic_pad(pad); 156987d66f28SThierry Reding 157087d66f28SThierry Reding kfree(hsic); 157187d66f28SThierry Reding } 157287d66f28SThierry Reding 157387d66f28SThierry Reding static const struct tegra_xusb_pad_ops tegra210_hsic_ops = { 157487d66f28SThierry Reding .probe = tegra210_hsic_pad_probe, 157587d66f28SThierry Reding .remove = tegra210_hsic_pad_remove, 157687d66f28SThierry Reding }; 157787d66f28SThierry Reding 157887d66f28SThierry Reding static const struct tegra_xusb_pad_soc tegra210_hsic_pad = { 157987d66f28SThierry Reding .name = "hsic", 158087d66f28SThierry Reding .num_lanes = ARRAY_SIZE(tegra210_hsic_lanes), 158187d66f28SThierry Reding .lanes = tegra210_hsic_lanes, 158287d66f28SThierry Reding .ops = &tegra210_hsic_ops, 158387d66f28SThierry Reding }; 158487d66f28SThierry Reding 158587d66f28SThierry Reding static const char *tegra210_pcie_functions[] = { 158687d66f28SThierry Reding "pcie-x1", 158787d66f28SThierry Reding "usb3-ss", 158887d66f28SThierry Reding "sata", 158987d66f28SThierry Reding "pcie-x4", 159087d66f28SThierry Reding }; 159187d66f28SThierry Reding 159287d66f28SThierry Reding static const struct tegra_xusb_lane_soc tegra210_pcie_lanes[] = { 159387d66f28SThierry Reding TEGRA210_LANE("pcie-0", 0x028, 12, 0x3, pcie), 159487d66f28SThierry Reding TEGRA210_LANE("pcie-1", 0x028, 14, 0x3, pcie), 159587d66f28SThierry Reding TEGRA210_LANE("pcie-2", 0x028, 16, 0x3, pcie), 159687d66f28SThierry Reding TEGRA210_LANE("pcie-3", 0x028, 18, 0x3, pcie), 159787d66f28SThierry Reding TEGRA210_LANE("pcie-4", 0x028, 20, 0x3, pcie), 159887d66f28SThierry Reding TEGRA210_LANE("pcie-5", 0x028, 22, 0x3, pcie), 159987d66f28SThierry Reding TEGRA210_LANE("pcie-6", 0x028, 24, 0x3, pcie), 160087d66f28SThierry Reding }; 160187d66f28SThierry Reding 160287d66f28SThierry Reding static struct tegra_xusb_lane * 160387d66f28SThierry Reding tegra210_pcie_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 160487d66f28SThierry Reding unsigned int index) 160587d66f28SThierry Reding { 160687d66f28SThierry Reding struct tegra_xusb_pcie_lane *pcie; 160787d66f28SThierry Reding int err; 160887d66f28SThierry Reding 160987d66f28SThierry Reding pcie = kzalloc(sizeof(*pcie), GFP_KERNEL); 161087d66f28SThierry Reding if (!pcie) 161187d66f28SThierry Reding return ERR_PTR(-ENOMEM); 161287d66f28SThierry Reding 161387d66f28SThierry Reding INIT_LIST_HEAD(&pcie->base.list); 161487d66f28SThierry Reding pcie->base.soc = &pad->soc->lanes[index]; 161587d66f28SThierry Reding pcie->base.index = index; 161687d66f28SThierry Reding pcie->base.pad = pad; 161787d66f28SThierry Reding pcie->base.np = np; 161887d66f28SThierry Reding 161987d66f28SThierry Reding err = tegra_xusb_lane_parse_dt(&pcie->base, np); 162087d66f28SThierry Reding if (err < 0) { 162187d66f28SThierry Reding kfree(pcie); 162287d66f28SThierry Reding return ERR_PTR(err); 162387d66f28SThierry Reding } 162487d66f28SThierry Reding 162587d66f28SThierry Reding return &pcie->base; 162687d66f28SThierry Reding } 162787d66f28SThierry Reding 162887d66f28SThierry Reding static void tegra210_pcie_lane_remove(struct tegra_xusb_lane *lane) 162987d66f28SThierry Reding { 163087d66f28SThierry Reding struct tegra_xusb_pcie_lane *pcie = to_pcie_lane(lane); 163187d66f28SThierry Reding 163287d66f28SThierry Reding kfree(pcie); 163387d66f28SThierry Reding } 163487d66f28SThierry Reding 163587d66f28SThierry Reding static const struct tegra_xusb_lane_ops tegra210_pcie_lane_ops = { 163687d66f28SThierry Reding .probe = tegra210_pcie_lane_probe, 163787d66f28SThierry Reding .remove = tegra210_pcie_lane_remove, 163887d66f28SThierry Reding }; 163987d66f28SThierry Reding 164087d66f28SThierry Reding static int tegra210_pcie_phy_init(struct phy *phy) 164187d66f28SThierry Reding { 164287d66f28SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 164387d66f28SThierry Reding 164487d66f28SThierry Reding return tegra210_xusb_padctl_enable(lane->pad->padctl); 164587d66f28SThierry Reding } 164687d66f28SThierry Reding 164787d66f28SThierry Reding static int tegra210_pcie_phy_exit(struct phy *phy) 164887d66f28SThierry Reding { 164987d66f28SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 165087d66f28SThierry Reding 165187d66f28SThierry Reding return tegra210_xusb_padctl_disable(lane->pad->padctl); 165287d66f28SThierry Reding } 165387d66f28SThierry Reding 165487d66f28SThierry Reding static int tegra210_pcie_phy_power_on(struct phy *phy) 165587d66f28SThierry Reding { 165687d66f28SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 165787d66f28SThierry Reding struct tegra_xusb_padctl *padctl = lane->pad->padctl; 165887d66f28SThierry Reding u32 value; 165987d66f28SThierry Reding int err; 166087d66f28SThierry Reding 166187d66f28SThierry Reding mutex_lock(&padctl->lock); 166287d66f28SThierry Reding 166387d66f28SThierry Reding err = tegra210_pex_uphy_enable(padctl); 166487d66f28SThierry Reding if (err < 0) 166587d66f28SThierry Reding goto unlock; 166687d66f28SThierry Reding 166787d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); 166887d66f28SThierry Reding value |= XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index); 166987d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); 167087d66f28SThierry Reding 167187d66f28SThierry Reding unlock: 167287d66f28SThierry Reding mutex_unlock(&padctl->lock); 167387d66f28SThierry Reding return err; 167487d66f28SThierry Reding } 167587d66f28SThierry Reding 167687d66f28SThierry Reding static int tegra210_pcie_phy_power_off(struct phy *phy) 167787d66f28SThierry Reding { 167887d66f28SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 167987d66f28SThierry Reding struct tegra_xusb_padctl *padctl = lane->pad->padctl; 168087d66f28SThierry Reding u32 value; 168187d66f28SThierry Reding 168287d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); 168387d66f28SThierry Reding value &= ~XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index); 168487d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); 168587d66f28SThierry Reding 168687d66f28SThierry Reding tegra210_pex_uphy_disable(padctl); 168787d66f28SThierry Reding 168887d66f28SThierry Reding return 0; 168987d66f28SThierry Reding } 169087d66f28SThierry Reding 169187d66f28SThierry Reding static const struct phy_ops tegra210_pcie_phy_ops = { 169287d66f28SThierry Reding .init = tegra210_pcie_phy_init, 169387d66f28SThierry Reding .exit = tegra210_pcie_phy_exit, 169487d66f28SThierry Reding .power_on = tegra210_pcie_phy_power_on, 169587d66f28SThierry Reding .power_off = tegra210_pcie_phy_power_off, 169687d66f28SThierry Reding .owner = THIS_MODULE, 169787d66f28SThierry Reding }; 169887d66f28SThierry Reding 169987d66f28SThierry Reding static struct tegra_xusb_pad * 170087d66f28SThierry Reding tegra210_pcie_pad_probe(struct tegra_xusb_padctl *padctl, 170187d66f28SThierry Reding const struct tegra_xusb_pad_soc *soc, 170287d66f28SThierry Reding struct device_node *np) 170387d66f28SThierry Reding { 170487d66f28SThierry Reding struct tegra_xusb_pcie_pad *pcie; 170587d66f28SThierry Reding struct tegra_xusb_pad *pad; 170687d66f28SThierry Reding int err; 170787d66f28SThierry Reding 170887d66f28SThierry Reding pcie = kzalloc(sizeof(*pcie), GFP_KERNEL); 170987d66f28SThierry Reding if (!pcie) 171087d66f28SThierry Reding return ERR_PTR(-ENOMEM); 171187d66f28SThierry Reding 171287d66f28SThierry Reding pad = &pcie->base; 171387d66f28SThierry Reding pad->ops = &tegra210_pcie_lane_ops; 171487d66f28SThierry Reding pad->soc = soc; 171587d66f28SThierry Reding 171687d66f28SThierry Reding err = tegra_xusb_pad_init(pad, padctl, np); 171787d66f28SThierry Reding if (err < 0) { 171887d66f28SThierry Reding kfree(pcie); 171987d66f28SThierry Reding goto out; 172087d66f28SThierry Reding } 172187d66f28SThierry Reding 172287d66f28SThierry Reding pcie->pll = devm_clk_get(&pad->dev, "pll"); 172387d66f28SThierry Reding if (IS_ERR(pcie->pll)) { 172487d66f28SThierry Reding err = PTR_ERR(pcie->pll); 172587d66f28SThierry Reding dev_err(&pad->dev, "failed to get PLL: %d\n", err); 172687d66f28SThierry Reding goto unregister; 172787d66f28SThierry Reding } 172887d66f28SThierry Reding 172987d66f28SThierry Reding pcie->rst = devm_reset_control_get(&pad->dev, "phy"); 173087d66f28SThierry Reding if (IS_ERR(pcie->rst)) { 173187d66f28SThierry Reding err = PTR_ERR(pcie->rst); 173287d66f28SThierry Reding dev_err(&pad->dev, "failed to get PCIe pad reset: %d\n", err); 173387d66f28SThierry Reding goto unregister; 173487d66f28SThierry Reding } 173587d66f28SThierry Reding 173687d66f28SThierry Reding err = tegra_xusb_pad_register(pad, &tegra210_pcie_phy_ops); 173787d66f28SThierry Reding if (err < 0) 173887d66f28SThierry Reding goto unregister; 173987d66f28SThierry Reding 174087d66f28SThierry Reding dev_set_drvdata(&pad->dev, pad); 174187d66f28SThierry Reding 174287d66f28SThierry Reding return pad; 174387d66f28SThierry Reding 174487d66f28SThierry Reding unregister: 174587d66f28SThierry Reding device_unregister(&pad->dev); 174687d66f28SThierry Reding out: 174787d66f28SThierry Reding return ERR_PTR(err); 174887d66f28SThierry Reding } 174987d66f28SThierry Reding 175087d66f28SThierry Reding static void tegra210_pcie_pad_remove(struct tegra_xusb_pad *pad) 175187d66f28SThierry Reding { 175287d66f28SThierry Reding struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(pad); 175387d66f28SThierry Reding 175487d66f28SThierry Reding kfree(pcie); 175587d66f28SThierry Reding } 175687d66f28SThierry Reding 175787d66f28SThierry Reding static const struct tegra_xusb_pad_ops tegra210_pcie_ops = { 175887d66f28SThierry Reding .probe = tegra210_pcie_pad_probe, 175987d66f28SThierry Reding .remove = tegra210_pcie_pad_remove, 176087d66f28SThierry Reding }; 176187d66f28SThierry Reding 176287d66f28SThierry Reding static const struct tegra_xusb_pad_soc tegra210_pcie_pad = { 176387d66f28SThierry Reding .name = "pcie", 176487d66f28SThierry Reding .num_lanes = ARRAY_SIZE(tegra210_pcie_lanes), 176587d66f28SThierry Reding .lanes = tegra210_pcie_lanes, 176687d66f28SThierry Reding .ops = &tegra210_pcie_ops, 176787d66f28SThierry Reding }; 176887d66f28SThierry Reding 176987d66f28SThierry Reding static const struct tegra_xusb_lane_soc tegra210_sata_lanes[] = { 177087d66f28SThierry Reding TEGRA210_LANE("sata-0", 0x028, 30, 0x3, pcie), 177187d66f28SThierry Reding }; 177287d66f28SThierry Reding 177387d66f28SThierry Reding static struct tegra_xusb_lane * 177487d66f28SThierry Reding tegra210_sata_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 177587d66f28SThierry Reding unsigned int index) 177687d66f28SThierry Reding { 177787d66f28SThierry Reding struct tegra_xusb_sata_lane *sata; 177887d66f28SThierry Reding int err; 177987d66f28SThierry Reding 178087d66f28SThierry Reding sata = kzalloc(sizeof(*sata), GFP_KERNEL); 178187d66f28SThierry Reding if (!sata) 178287d66f28SThierry Reding return ERR_PTR(-ENOMEM); 178387d66f28SThierry Reding 178487d66f28SThierry Reding INIT_LIST_HEAD(&sata->base.list); 178587d66f28SThierry Reding sata->base.soc = &pad->soc->lanes[index]; 178687d66f28SThierry Reding sata->base.index = index; 178787d66f28SThierry Reding sata->base.pad = pad; 178887d66f28SThierry Reding sata->base.np = np; 178987d66f28SThierry Reding 179087d66f28SThierry Reding err = tegra_xusb_lane_parse_dt(&sata->base, np); 179187d66f28SThierry Reding if (err < 0) { 179287d66f28SThierry Reding kfree(sata); 179387d66f28SThierry Reding return ERR_PTR(err); 179487d66f28SThierry Reding } 179587d66f28SThierry Reding 179687d66f28SThierry Reding return &sata->base; 179787d66f28SThierry Reding } 179887d66f28SThierry Reding 179987d66f28SThierry Reding static void tegra210_sata_lane_remove(struct tegra_xusb_lane *lane) 180087d66f28SThierry Reding { 180187d66f28SThierry Reding struct tegra_xusb_sata_lane *sata = to_sata_lane(lane); 180287d66f28SThierry Reding 180387d66f28SThierry Reding kfree(sata); 180487d66f28SThierry Reding } 180587d66f28SThierry Reding 180687d66f28SThierry Reding static const struct tegra_xusb_lane_ops tegra210_sata_lane_ops = { 180787d66f28SThierry Reding .probe = tegra210_sata_lane_probe, 180887d66f28SThierry Reding .remove = tegra210_sata_lane_remove, 180987d66f28SThierry Reding }; 181087d66f28SThierry Reding 181187d66f28SThierry Reding static int tegra210_sata_phy_init(struct phy *phy) 181287d66f28SThierry Reding { 181387d66f28SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 181487d66f28SThierry Reding 181587d66f28SThierry Reding return tegra210_xusb_padctl_enable(lane->pad->padctl); 181687d66f28SThierry Reding } 181787d66f28SThierry Reding 181887d66f28SThierry Reding static int tegra210_sata_phy_exit(struct phy *phy) 181987d66f28SThierry Reding { 182087d66f28SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 182187d66f28SThierry Reding 182287d66f28SThierry Reding return tegra210_xusb_padctl_disable(lane->pad->padctl); 182387d66f28SThierry Reding } 182487d66f28SThierry Reding 182587d66f28SThierry Reding static int tegra210_sata_phy_power_on(struct phy *phy) 182687d66f28SThierry Reding { 182787d66f28SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 182887d66f28SThierry Reding struct tegra_xusb_padctl *padctl = lane->pad->padctl; 182987d66f28SThierry Reding u32 value; 183087d66f28SThierry Reding int err; 183187d66f28SThierry Reding 183287d66f28SThierry Reding mutex_lock(&padctl->lock); 183387d66f28SThierry Reding 183487d66f28SThierry Reding err = tegra210_sata_uphy_enable(padctl, false); 183587d66f28SThierry Reding if (err < 0) 183687d66f28SThierry Reding goto unlock; 183787d66f28SThierry Reding 183887d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); 183987d66f28SThierry Reding value |= XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index); 184087d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); 184187d66f28SThierry Reding 184287d66f28SThierry Reding unlock: 184387d66f28SThierry Reding mutex_unlock(&padctl->lock); 184487d66f28SThierry Reding return err; 184587d66f28SThierry Reding } 184687d66f28SThierry Reding 184787d66f28SThierry Reding static int tegra210_sata_phy_power_off(struct phy *phy) 184887d66f28SThierry Reding { 184987d66f28SThierry Reding struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 185087d66f28SThierry Reding struct tegra_xusb_padctl *padctl = lane->pad->padctl; 185187d66f28SThierry Reding u32 value; 185287d66f28SThierry Reding 185387d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); 185487d66f28SThierry Reding value &= ~XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index); 185587d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); 185687d66f28SThierry Reding 185787d66f28SThierry Reding tegra210_sata_uphy_disable(lane->pad->padctl); 185887d66f28SThierry Reding 185987d66f28SThierry Reding return 0; 186087d66f28SThierry Reding } 186187d66f28SThierry Reding 186287d66f28SThierry Reding static const struct phy_ops tegra210_sata_phy_ops = { 186387d66f28SThierry Reding .init = tegra210_sata_phy_init, 186487d66f28SThierry Reding .exit = tegra210_sata_phy_exit, 186587d66f28SThierry Reding .power_on = tegra210_sata_phy_power_on, 186687d66f28SThierry Reding .power_off = tegra210_sata_phy_power_off, 186787d66f28SThierry Reding .owner = THIS_MODULE, 186887d66f28SThierry Reding }; 186987d66f28SThierry Reding 187087d66f28SThierry Reding static struct tegra_xusb_pad * 187187d66f28SThierry Reding tegra210_sata_pad_probe(struct tegra_xusb_padctl *padctl, 187287d66f28SThierry Reding const struct tegra_xusb_pad_soc *soc, 187387d66f28SThierry Reding struct device_node *np) 187487d66f28SThierry Reding { 187587d66f28SThierry Reding struct tegra_xusb_sata_pad *sata; 187687d66f28SThierry Reding struct tegra_xusb_pad *pad; 187787d66f28SThierry Reding int err; 187887d66f28SThierry Reding 187987d66f28SThierry Reding sata = kzalloc(sizeof(*sata), GFP_KERNEL); 188087d66f28SThierry Reding if (!sata) 188187d66f28SThierry Reding return ERR_PTR(-ENOMEM); 188287d66f28SThierry Reding 188387d66f28SThierry Reding pad = &sata->base; 188487d66f28SThierry Reding pad->ops = &tegra210_sata_lane_ops; 188587d66f28SThierry Reding pad->soc = soc; 188687d66f28SThierry Reding 188787d66f28SThierry Reding err = tegra_xusb_pad_init(pad, padctl, np); 188887d66f28SThierry Reding if (err < 0) { 188987d66f28SThierry Reding kfree(sata); 189087d66f28SThierry Reding goto out; 189187d66f28SThierry Reding } 189287d66f28SThierry Reding 189387d66f28SThierry Reding sata->rst = devm_reset_control_get(&pad->dev, "phy"); 189487d66f28SThierry Reding if (IS_ERR(sata->rst)) { 189587d66f28SThierry Reding err = PTR_ERR(sata->rst); 189687d66f28SThierry Reding dev_err(&pad->dev, "failed to get SATA pad reset: %d\n", err); 189787d66f28SThierry Reding goto unregister; 189887d66f28SThierry Reding } 189987d66f28SThierry Reding 190087d66f28SThierry Reding err = tegra_xusb_pad_register(pad, &tegra210_sata_phy_ops); 190187d66f28SThierry Reding if (err < 0) 190287d66f28SThierry Reding goto unregister; 190387d66f28SThierry Reding 190487d66f28SThierry Reding dev_set_drvdata(&pad->dev, pad); 190587d66f28SThierry Reding 190687d66f28SThierry Reding return pad; 190787d66f28SThierry Reding 190887d66f28SThierry Reding unregister: 190987d66f28SThierry Reding device_unregister(&pad->dev); 191087d66f28SThierry Reding out: 191187d66f28SThierry Reding return ERR_PTR(err); 191287d66f28SThierry Reding } 191387d66f28SThierry Reding 191487d66f28SThierry Reding static void tegra210_sata_pad_remove(struct tegra_xusb_pad *pad) 191587d66f28SThierry Reding { 191687d66f28SThierry Reding struct tegra_xusb_sata_pad *sata = to_sata_pad(pad); 191787d66f28SThierry Reding 191887d66f28SThierry Reding kfree(sata); 191987d66f28SThierry Reding } 192087d66f28SThierry Reding 192187d66f28SThierry Reding static const struct tegra_xusb_pad_ops tegra210_sata_ops = { 192287d66f28SThierry Reding .probe = tegra210_sata_pad_probe, 192387d66f28SThierry Reding .remove = tegra210_sata_pad_remove, 192487d66f28SThierry Reding }; 192587d66f28SThierry Reding 192687d66f28SThierry Reding static const struct tegra_xusb_pad_soc tegra210_sata_pad = { 192787d66f28SThierry Reding .name = "sata", 192887d66f28SThierry Reding .num_lanes = ARRAY_SIZE(tegra210_sata_lanes), 192987d66f28SThierry Reding .lanes = tegra210_sata_lanes, 193087d66f28SThierry Reding .ops = &tegra210_sata_ops, 193187d66f28SThierry Reding }; 193287d66f28SThierry Reding 193387d66f28SThierry Reding static const struct tegra_xusb_pad_soc * const tegra210_pads[] = { 193487d66f28SThierry Reding &tegra210_usb2_pad, 193587d66f28SThierry Reding &tegra210_hsic_pad, 193687d66f28SThierry Reding &tegra210_pcie_pad, 193787d66f28SThierry Reding &tegra210_sata_pad, 193887d66f28SThierry Reding }; 193987d66f28SThierry Reding 194087d66f28SThierry Reding static int tegra210_usb2_port_enable(struct tegra_xusb_port *port) 194187d66f28SThierry Reding { 194287d66f28SThierry Reding return 0; 194387d66f28SThierry Reding } 194487d66f28SThierry Reding 194587d66f28SThierry Reding static void tegra210_usb2_port_disable(struct tegra_xusb_port *port) 194687d66f28SThierry Reding { 194787d66f28SThierry Reding } 194887d66f28SThierry Reding 194987d66f28SThierry Reding static struct tegra_xusb_lane * 195087d66f28SThierry Reding tegra210_usb2_port_map(struct tegra_xusb_port *port) 195187d66f28SThierry Reding { 195287d66f28SThierry Reding return tegra_xusb_find_lane(port->padctl, "usb2", port->index); 195387d66f28SThierry Reding } 195487d66f28SThierry Reding 195587d66f28SThierry Reding static const struct tegra_xusb_port_ops tegra210_usb2_port_ops = { 195687d66f28SThierry Reding .enable = tegra210_usb2_port_enable, 195787d66f28SThierry Reding .disable = tegra210_usb2_port_disable, 195887d66f28SThierry Reding .map = tegra210_usb2_port_map, 195987d66f28SThierry Reding }; 196087d66f28SThierry Reding 196187d66f28SThierry Reding static int tegra210_hsic_port_enable(struct tegra_xusb_port *port) 196287d66f28SThierry Reding { 196387d66f28SThierry Reding return 0; 196487d66f28SThierry Reding } 196587d66f28SThierry Reding 196687d66f28SThierry Reding static void tegra210_hsic_port_disable(struct tegra_xusb_port *port) 196787d66f28SThierry Reding { 196887d66f28SThierry Reding } 196987d66f28SThierry Reding 197087d66f28SThierry Reding static struct tegra_xusb_lane * 197187d66f28SThierry Reding tegra210_hsic_port_map(struct tegra_xusb_port *port) 197287d66f28SThierry Reding { 197387d66f28SThierry Reding return tegra_xusb_find_lane(port->padctl, "hsic", port->index); 197487d66f28SThierry Reding } 197587d66f28SThierry Reding 197687d66f28SThierry Reding static const struct tegra_xusb_port_ops tegra210_hsic_port_ops = { 197787d66f28SThierry Reding .enable = tegra210_hsic_port_enable, 197887d66f28SThierry Reding .disable = tegra210_hsic_port_disable, 197987d66f28SThierry Reding .map = tegra210_hsic_port_map, 198087d66f28SThierry Reding }; 198187d66f28SThierry Reding 198287d66f28SThierry Reding static int tegra210_usb3_port_enable(struct tegra_xusb_port *port) 198387d66f28SThierry Reding { 198487d66f28SThierry Reding struct tegra_xusb_usb3_port *usb3 = to_usb3_port(port); 198587d66f28SThierry Reding struct tegra_xusb_padctl *padctl = port->padctl; 198687d66f28SThierry Reding struct tegra_xusb_lane *lane = usb3->base.lane; 198787d66f28SThierry Reding unsigned int index = port->index; 198887d66f28SThierry Reding u32 value; 198987d66f28SThierry Reding int err; 199087d66f28SThierry Reding 199187d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); 199287d66f28SThierry Reding 199387d66f28SThierry Reding if (!usb3->internal) 199487d66f28SThierry Reding value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index); 199587d66f28SThierry Reding else 199687d66f28SThierry Reding value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index); 199787d66f28SThierry Reding 199887d66f28SThierry Reding value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(index); 199987d66f28SThierry Reding value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(index, usb3->port); 200087d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); 200187d66f28SThierry Reding 200287d66f28SThierry Reding /* 200387d66f28SThierry Reding * TODO: move this code into the PCIe/SATA PHY ->power_on() callbacks 200487d66f28SThierry Reding * and conditionalize based on mux function? This seems to work, but 200587d66f28SThierry Reding * might not be the exact proper sequence. 200687d66f28SThierry Reding */ 200787d66f28SThierry Reding err = regulator_enable(usb3->supply); 200887d66f28SThierry Reding if (err < 0) 200987d66f28SThierry Reding return err; 201087d66f28SThierry Reding 201187d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(index)); 201287d66f28SThierry Reding value &= ~(XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_MASK << 201387d66f28SThierry Reding XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT); 201487d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_VAL << 201587d66f28SThierry Reding XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT; 201687d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(index)); 201787d66f28SThierry Reding 201887d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_USB3_PADX_ECTL2(index)); 201987d66f28SThierry Reding value &= ~(XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_MASK << 202087d66f28SThierry Reding XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_SHIFT); 202187d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_VAL << 202287d66f28SThierry Reding XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_SHIFT; 202387d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_USB3_PADX_ECTL2(index)); 202487d66f28SThierry Reding 202587d66f28SThierry Reding padctl_writel(padctl, XUSB_PADCTL_UPHY_USB3_PAD_ECTL3_RX_DFE_VAL, 202687d66f28SThierry Reding XUSB_PADCTL_UPHY_USB3_PADX_ECTL3(index)); 202787d66f28SThierry Reding 202887d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_UPHY_USB3_PADX_ECTL4(index)); 202987d66f28SThierry Reding value &= ~(XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_MASK << 203087d66f28SThierry Reding XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_SHIFT); 203187d66f28SThierry Reding value |= XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_VAL << 203287d66f28SThierry Reding XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_SHIFT; 203387d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_UPHY_USB3_PADX_ECTL4(index)); 203487d66f28SThierry Reding 203587d66f28SThierry Reding padctl_writel(padctl, XUSB_PADCTL_UPHY_USB3_PAD_ECTL6_RX_EQ_CTRL_H_VAL, 203687d66f28SThierry Reding XUSB_PADCTL_UPHY_USB3_PADX_ECTL6(index)); 203787d66f28SThierry Reding 203887d66f28SThierry Reding if (lane->pad == padctl->sata) 203987d66f28SThierry Reding err = tegra210_sata_uphy_enable(padctl, true); 204087d66f28SThierry Reding else 204187d66f28SThierry Reding err = tegra210_pex_uphy_enable(padctl); 204287d66f28SThierry Reding 204387d66f28SThierry Reding if (err) { 204487d66f28SThierry Reding dev_err(&port->dev, "%s: failed to enable UPHY: %d\n", 204587d66f28SThierry Reding __func__, err); 204687d66f28SThierry Reding return err; 204787d66f28SThierry Reding } 204887d66f28SThierry Reding 204987d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 205087d66f28SThierry Reding value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN(index); 205187d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 205287d66f28SThierry Reding 205387d66f28SThierry Reding usleep_range(100, 200); 205487d66f28SThierry Reding 205587d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 205687d66f28SThierry Reding value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(index); 205787d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 205887d66f28SThierry Reding 205987d66f28SThierry Reding usleep_range(100, 200); 206087d66f28SThierry Reding 206187d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 206287d66f28SThierry Reding value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(index); 206387d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 206487d66f28SThierry Reding 206587d66f28SThierry Reding return 0; 206687d66f28SThierry Reding } 206787d66f28SThierry Reding 206887d66f28SThierry Reding static void tegra210_usb3_port_disable(struct tegra_xusb_port *port) 206987d66f28SThierry Reding { 207087d66f28SThierry Reding struct tegra_xusb_usb3_port *usb3 = to_usb3_port(port); 207187d66f28SThierry Reding struct tegra_xusb_padctl *padctl = port->padctl; 207287d66f28SThierry Reding struct tegra_xusb_lane *lane = port->lane; 207387d66f28SThierry Reding unsigned int index = port->index; 207487d66f28SThierry Reding u32 value; 207587d66f28SThierry Reding 207687d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 207787d66f28SThierry Reding value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(index); 207887d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 207987d66f28SThierry Reding 208087d66f28SThierry Reding usleep_range(100, 200); 208187d66f28SThierry Reding 208287d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 208387d66f28SThierry Reding value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(index); 208487d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 208587d66f28SThierry Reding 208687d66f28SThierry Reding usleep_range(250, 350); 208787d66f28SThierry Reding 208887d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 208987d66f28SThierry Reding value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN(index); 209087d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 209187d66f28SThierry Reding 209287d66f28SThierry Reding if (lane->pad == padctl->sata) 209387d66f28SThierry Reding tegra210_sata_uphy_disable(padctl); 209487d66f28SThierry Reding else 209587d66f28SThierry Reding tegra210_pex_uphy_disable(padctl); 209687d66f28SThierry Reding 209787d66f28SThierry Reding regulator_disable(usb3->supply); 209887d66f28SThierry Reding 209987d66f28SThierry Reding value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); 210087d66f28SThierry Reding value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(index); 210187d66f28SThierry Reding value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(index, 0x7); 210287d66f28SThierry Reding padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); 210387d66f28SThierry Reding } 210487d66f28SThierry Reding 210587d66f28SThierry Reding static const struct tegra_xusb_lane_map tegra210_usb3_map[] = { 210687d66f28SThierry Reding { 0, "pcie", 6 }, 210787d66f28SThierry Reding { 1, "pcie", 5 }, 210887d66f28SThierry Reding { 2, "pcie", 0 }, 210987d66f28SThierry Reding { 2, "pcie", 3 }, 211087d66f28SThierry Reding { 3, "pcie", 4 }, 211187d66f28SThierry Reding { 3, "pcie", 4 }, 211287d66f28SThierry Reding { 0, NULL, 0 } 211387d66f28SThierry Reding }; 211487d66f28SThierry Reding 211587d66f28SThierry Reding static struct tegra_xusb_lane * 211687d66f28SThierry Reding tegra210_usb3_port_map(struct tegra_xusb_port *port) 211787d66f28SThierry Reding { 211887d66f28SThierry Reding return tegra_xusb_port_find_lane(port, tegra210_usb3_map, "usb3-ss"); 211987d66f28SThierry Reding } 212087d66f28SThierry Reding 212187d66f28SThierry Reding static const struct tegra_xusb_port_ops tegra210_usb3_port_ops = { 212287d66f28SThierry Reding .enable = tegra210_usb3_port_enable, 212387d66f28SThierry Reding .disable = tegra210_usb3_port_disable, 212487d66f28SThierry Reding .map = tegra210_usb3_port_map, 212587d66f28SThierry Reding }; 212687d66f28SThierry Reding 212790767cdfSNagarjuna Kristam static int tegra210_utmi_port_reset(struct phy *phy) 212890767cdfSNagarjuna Kristam { 212990767cdfSNagarjuna Kristam struct tegra_xusb_padctl *padctl; 213090767cdfSNagarjuna Kristam struct tegra_xusb_lane *lane; 213190767cdfSNagarjuna Kristam u32 value; 213290767cdfSNagarjuna Kristam 213390767cdfSNagarjuna Kristam lane = phy_get_drvdata(phy); 213490767cdfSNagarjuna Kristam padctl = lane->pad->padctl; 213590767cdfSNagarjuna Kristam 213690767cdfSNagarjuna Kristam value = padctl_readl(padctl, 213790767cdfSNagarjuna Kristam XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL0(lane->index)); 213890767cdfSNagarjuna Kristam 213990767cdfSNagarjuna Kristam if ((value & XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL0_ZIP) || 214090767cdfSNagarjuna Kristam (value & XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL0_ZIN)) { 214190767cdfSNagarjuna Kristam tegra210_xusb_padctl_vbus_override(padctl, false); 214290767cdfSNagarjuna Kristam tegra210_xusb_padctl_vbus_override(padctl, true); 214390767cdfSNagarjuna Kristam return 1; 214490767cdfSNagarjuna Kristam } 214590767cdfSNagarjuna Kristam 214690767cdfSNagarjuna Kristam return 0; 214790767cdfSNagarjuna Kristam } 214890767cdfSNagarjuna Kristam 214987d66f28SThierry Reding static int 215087d66f28SThierry Reding tegra210_xusb_read_fuse_calibration(struct tegra210_xusb_fuse_calibration *fuse) 215187d66f28SThierry Reding { 215287d66f28SThierry Reding unsigned int i; 215387d66f28SThierry Reding u32 value; 215487d66f28SThierry Reding int err; 215587d66f28SThierry Reding 215687d66f28SThierry Reding err = tegra_fuse_readl(TEGRA_FUSE_SKU_CALIB_0, &value); 215787d66f28SThierry Reding if (err < 0) 215887d66f28SThierry Reding return err; 215987d66f28SThierry Reding 216087d66f28SThierry Reding for (i = 0; i < ARRAY_SIZE(fuse->hs_curr_level); i++) { 216187d66f28SThierry Reding fuse->hs_curr_level[i] = 216287d66f28SThierry Reding (value >> FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(i)) & 216387d66f28SThierry Reding FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK; 216487d66f28SThierry Reding } 216587d66f28SThierry Reding 216687d66f28SThierry Reding fuse->hs_term_range_adj = 216787d66f28SThierry Reding (value >> FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT) & 216887d66f28SThierry Reding FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK; 216987d66f28SThierry Reding 217087d66f28SThierry Reding err = tegra_fuse_readl(TEGRA_FUSE_USB_CALIB_EXT_0, &value); 217187d66f28SThierry Reding if (err < 0) 217287d66f28SThierry Reding return err; 217387d66f28SThierry Reding 217487d66f28SThierry Reding fuse->rpd_ctrl = 217587d66f28SThierry Reding (value >> FUSE_USB_CALIB_EXT_RPD_CTRL_SHIFT) & 217687d66f28SThierry Reding FUSE_USB_CALIB_EXT_RPD_CTRL_MASK; 217787d66f28SThierry Reding 217887d66f28SThierry Reding return 0; 217987d66f28SThierry Reding } 218087d66f28SThierry Reding 218187d66f28SThierry Reding static struct tegra_xusb_padctl * 218287d66f28SThierry Reding tegra210_xusb_padctl_probe(struct device *dev, 218387d66f28SThierry Reding const struct tegra_xusb_padctl_soc *soc) 218487d66f28SThierry Reding { 218587d66f28SThierry Reding struct tegra210_xusb_padctl *padctl; 218687d66f28SThierry Reding int err; 218787d66f28SThierry Reding 218887d66f28SThierry Reding padctl = devm_kzalloc(dev, sizeof(*padctl), GFP_KERNEL); 218987d66f28SThierry Reding if (!padctl) 219087d66f28SThierry Reding return ERR_PTR(-ENOMEM); 219187d66f28SThierry Reding 219287d66f28SThierry Reding padctl->base.dev = dev; 219387d66f28SThierry Reding padctl->base.soc = soc; 219487d66f28SThierry Reding 219587d66f28SThierry Reding err = tegra210_xusb_read_fuse_calibration(&padctl->fuse); 219687d66f28SThierry Reding if (err < 0) 219787d66f28SThierry Reding return ERR_PTR(err); 219887d66f28SThierry Reding 219987d66f28SThierry Reding return &padctl->base; 220087d66f28SThierry Reding } 220187d66f28SThierry Reding 220287d66f28SThierry Reding static void tegra210_xusb_padctl_remove(struct tegra_xusb_padctl *padctl) 220387d66f28SThierry Reding { 220487d66f28SThierry Reding } 220587d66f28SThierry Reding 220687d66f28SThierry Reding static const struct tegra_xusb_padctl_ops tegra210_xusb_padctl_ops = { 220787d66f28SThierry Reding .probe = tegra210_xusb_padctl_probe, 220887d66f28SThierry Reding .remove = tegra210_xusb_padctl_remove, 220987d66f28SThierry Reding .usb3_set_lfps_detect = tegra210_usb3_set_lfps_detect, 221087d66f28SThierry Reding .hsic_set_idle = tegra210_hsic_set_idle, 221190767cdfSNagarjuna Kristam .vbus_override = tegra210_xusb_padctl_vbus_override, 221290767cdfSNagarjuna Kristam .utmi_port_reset = tegra210_utmi_port_reset, 221387d66f28SThierry Reding }; 221487d66f28SThierry Reding 2215e3888cdaSThierry Reding static const char * const tegra210_xusb_padctl_supply_names[] = { 2216e3888cdaSThierry Reding "avdd-pll-utmip", 2217e3888cdaSThierry Reding "avdd-pll-uerefe", 2218e3888cdaSThierry Reding "dvdd-pex-pll", 2219e3888cdaSThierry Reding "hvdd-pex-pll-e", 2220e3888cdaSThierry Reding }; 2221e3888cdaSThierry Reding 222287d66f28SThierry Reding const struct tegra_xusb_padctl_soc tegra210_xusb_padctl_soc = { 222387d66f28SThierry Reding .num_pads = ARRAY_SIZE(tegra210_pads), 222487d66f28SThierry Reding .pads = tegra210_pads, 222587d66f28SThierry Reding .ports = { 222687d66f28SThierry Reding .usb2 = { 222787d66f28SThierry Reding .ops = &tegra210_usb2_port_ops, 222887d66f28SThierry Reding .count = 4, 222987d66f28SThierry Reding }, 223087d66f28SThierry Reding .hsic = { 223187d66f28SThierry Reding .ops = &tegra210_hsic_port_ops, 223287d66f28SThierry Reding .count = 1, 223387d66f28SThierry Reding }, 223487d66f28SThierry Reding .usb3 = { 223587d66f28SThierry Reding .ops = &tegra210_usb3_port_ops, 223687d66f28SThierry Reding .count = 4, 223787d66f28SThierry Reding }, 223887d66f28SThierry Reding }, 223987d66f28SThierry Reding .ops = &tegra210_xusb_padctl_ops, 2240e3888cdaSThierry Reding .supply_names = tegra210_xusb_padctl_supply_names, 2241e3888cdaSThierry Reding .num_supplies = ARRAY_SIZE(tegra210_xusb_padctl_supply_names), 2242a5be28c3SNagarjuna Kristam .need_fake_usb3_port = true, 224387d66f28SThierry Reding }; 224487d66f28SThierry Reding EXPORT_SYMBOL_GPL(tegra210_xusb_padctl_soc); 224587d66f28SThierry Reding 224687d66f28SThierry Reding MODULE_AUTHOR("Andrew Bresticker <abrestic@chromium.org>"); 224787d66f28SThierry Reding MODULE_DESCRIPTION("NVIDIA Tegra 210 XUSB Pad Controller driver"); 224887d66f28SThierry Reding MODULE_LICENSE("GPL v2"); 2249