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