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