162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2014-2020, NVIDIA CORPORATION. All rights reserved. 462306a36Sopenharmony_ci * Copyright (C) 2015 Google, Inc. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/clk.h> 862306a36Sopenharmony_ci#include <linux/clk/tegra.h> 962306a36Sopenharmony_ci#include <linux/delay.h> 1062306a36Sopenharmony_ci#include <linux/io.h> 1162306a36Sopenharmony_ci#include <linux/mailbox_client.h> 1262306a36Sopenharmony_ci#include <linux/module.h> 1362306a36Sopenharmony_ci#include <linux/of.h> 1462306a36Sopenharmony_ci#include <linux/of_platform.h> 1562306a36Sopenharmony_ci#include <linux/phy/phy.h> 1662306a36Sopenharmony_ci#include <linux/platform_device.h> 1762306a36Sopenharmony_ci#include <linux/regmap.h> 1862306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 1962306a36Sopenharmony_ci#include <linux/reset.h> 2062306a36Sopenharmony_ci#include <linux/slab.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include <soc/tegra/fuse.h> 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include "xusb.h" 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(x) \ 2762306a36Sopenharmony_ci ((x) ? (11 + ((x) - 1) * 6) : 0) 2862306a36Sopenharmony_ci#define FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK 0x3f 2962306a36Sopenharmony_ci#define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT 7 3062306a36Sopenharmony_ci#define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK 0xf 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#define FUSE_USB_CALIB_EXT_RPD_CTRL_SHIFT 0 3362306a36Sopenharmony_ci#define FUSE_USB_CALIB_EXT_RPD_CTRL_MASK 0x1f 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PAD_MUX 0x004 3662306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_SHIFT 16 3762306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_MASK 0x3 3862306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_XUSB 0x1 3962306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_SHIFT 18 4062306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_MASK 0x3 4162306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_XUSB 0x1 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP 0x008 4462306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_DISABLED(x) (0x0 << ((x) * 4)) 4562306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_HOST(x) (0x1 << ((x) * 4)) 4662306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_DEVICE(x) (0x2 << ((x) * 4)) 4762306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_OTG(x) (0x3 << ((x) * 4)) 4862306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_MASK(x) (0x3 << ((x) * 4)) 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP 0x014 5162306a36Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(x) (1 << (((x) * 5) + 4)) 5262306a36Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_SHIFT(x) ((x) * 5) 5362306a36Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(x) (0x7 << ((x) * 5)) 5462306a36Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(x, v) (((v) & 0x7) << ((x) * 5)) 5562306a36Sopenharmony_ci#define XUSB_PADCTL_SS_PORT_MAP_PORT_DISABLED 0x7 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM_0 0x20 5862306a36Sopenharmony_ci#define USB2_PORT_WAKE_INTERRUPT_ENABLE(x) BIT((x)) 5962306a36Sopenharmony_ci#define USB2_PORT_WAKEUP_EVENT(x) BIT((x) + 7) 6062306a36Sopenharmony_ci#define SS_PORT_WAKE_INTERRUPT_ENABLE(x) BIT((x) + 14) 6162306a36Sopenharmony_ci#define SS_PORT_WAKEUP_EVENT(x) BIT((x) + 21) 6262306a36Sopenharmony_ci#define USB2_HSIC_PORT_WAKE_INTERRUPT_ENABLE(x) BIT((x) + 28) 6362306a36Sopenharmony_ci#define USB2_HSIC_PORT_WAKEUP_EVENT(x) BIT((x) + 30) 6462306a36Sopenharmony_ci#define ALL_WAKE_EVENTS ( \ 6562306a36Sopenharmony_ci USB2_PORT_WAKEUP_EVENT(0) | USB2_PORT_WAKEUP_EVENT(1) | \ 6662306a36Sopenharmony_ci USB2_PORT_WAKEUP_EVENT(2) | USB2_PORT_WAKEUP_EVENT(3) | \ 6762306a36Sopenharmony_ci SS_PORT_WAKEUP_EVENT(0) | SS_PORT_WAKEUP_EVENT(1) | \ 6862306a36Sopenharmony_ci SS_PORT_WAKEUP_EVENT(2) | SS_PORT_WAKEUP_EVENT(3) | \ 6962306a36Sopenharmony_ci USB2_HSIC_PORT_WAKEUP_EVENT(0)) 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM1 0x024 7262306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN (1 << 31) 7362306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 30) 7462306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN (1 << 29) 7562306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN(x) (1 << (2 + (x) * 3)) 7662306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(x) \ 7762306a36Sopenharmony_ci (1 << (1 + (x) * 3)) 7862306a36Sopenharmony_ci#define XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(x) (1 << ((x) * 3)) 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci#define XUSB_PADCTL_USB3_PAD_MUX 0x028 8162306a36Sopenharmony_ci#define XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(x) (1 << (1 + (x))) 8262306a36Sopenharmony_ci#define XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(x) (1 << (8 + (x))) 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL0(x) (0x080 + (x) * 0x40) 8562306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL0_ZIP (1 << 18) 8662306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL0_ZIN (1 << 22) 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(x) (0x084 + (x) * 0x40) 8962306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_SHIFT 7 9062306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_MASK 0x3 9162306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_VAL 0x1 9262306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_FIX18 (1 << 6) 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PADX_CTL0(x) (0x088 + (x) * 0x40) 9562306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI (1 << 29) 9662306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 (1 << 27) 9762306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD (1 << 26) 9862306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT 0 9962306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK 0x3f 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PADX_CTL1(x) (0x08c + (x) * 0x40) 10262306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_SHIFT 26 10362306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_MASK 0x1f 10462306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT 3 10562306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK 0xf 10662306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR (1 << 2) 10762306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_OVRD (1 << 1) 10862306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_OVRD (1 << 0) 10962306a36Sopenharmony_ci#define RPD_CTRL(x) (((x) & 0x1f) << 26) 11062306a36Sopenharmony_ci#define RPD_CTRL_VALUE(x) (((x) >> 26) & 0x1f) 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0 0x284 11362306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD (1 << 11) 11462306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT 3 11562306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK 0x7 11662306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL 0x7 11762306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT 0 11862306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK 0x7 11962306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_VAL 0x2 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL1 0x288 12262306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_PD_TRK (1 << 26) 12362306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_SHIFT 19 12462306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_MASK 0x7f 12562306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_VAL 0x0a 12662306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_SHIFT 12 12762306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_MASK 0x7f 12862306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_VAL 0x1e 12962306a36Sopenharmony_ci#define TCTRL_VALUE(x) (((x) & 0x3f) >> 0) 13062306a36Sopenharmony_ci#define PCTRL_VALUE(x) (((x) >> 6) & 0x3f) 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PADX_CTL0(x) (0x300 + (x) * 0x20) 13362306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE (1 << 18) 13462306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA1 (1 << 17) 13562306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA0 (1 << 16) 13662306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_RPD_STROBE (1 << 15) 13762306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA1 (1 << 14) 13862306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA0 (1 << 13) 13962306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_STROBE (1 << 9) 14062306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA1 (1 << 8) 14162306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA0 (1 << 7) 14262306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_STROBE (1 << 6) 14362306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA1 (1 << 5) 14462306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA0 (1 << 4) 14562306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_STROBE (1 << 3) 14662306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA1 (1 << 2) 14762306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA0 (1 << 1) 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PADX_CTL1(x) (0x304 + (x) * 0x20) 15062306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_SHIFT 0 15162306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_MASK 0xf 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PADX_CTL2(x) (0x308 + (x) * 0x20) 15462306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT 8 15562306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK 0xf 15662306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT 0 15762306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK 0xff 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_TRK_CTL 0x340 16062306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_TRK_CTL_PD_TRK (1 << 19) 16162306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_SHIFT 12 16262306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_MASK 0x7f 16362306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_VAL 0x0a 16462306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_SHIFT 5 16562306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_MASK 0x7f 16662306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_VAL 0x1e 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci#define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL 0x344 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_P0_CTL1 0x360 17162306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT 20 17262306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_MASK 0xff 17362306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_USB_VAL 0x19 17462306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SATA_VAL 0x1e 17562306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_SHIFT 16 17662306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_MASK 0x3 17762306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_LOCKDET_STATUS (1 << 15) 17862306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD (1 << 4) 17962306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_ENABLE (1 << 3) 18062306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_SHIFT 1 18162306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_MASK 0x3 18262306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL1_IDDQ (1 << 0) 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_P0_CTL2 0x364 18562306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT 4 18662306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_MASK 0xffffff 18762306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_VAL 0x136 18862306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD (1 << 2) 18962306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE (1 << 1) 19062306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN (1 << 0) 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_P0_CTL4 0x36c 19362306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL4_XDIGCLK_EN (1 << 19) 19462306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_EN (1 << 15) 19562306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT 12 19662306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_MASK 0x3 19762306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_USB_VAL 0x2 19862306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SATA_VAL 0x0 19962306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL4_REFCLKBUF_EN (1 << 8) 20062306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_SHIFT 4 20162306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_MASK 0xf 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_P0_CTL5 0x370 20462306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT 16 20562306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_MASK 0xff 20662306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_VAL 0x2a 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_P0_CTL8 0x37c 20962306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE (1 << 31) 21062306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD (1 << 15) 21162306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN (1 << 13) 21262306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN (1 << 12) 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL1(x) (0x460 + (x) * 0x40) 21562306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_SHIFT 20 21662306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_MASK 0x3 21762306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_VAL 0x1 21862306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_TERM_EN BIT(18) 21962306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_MODE_OVRD BIT(13) 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(x) (0x464 + (x) * 0x40) 22262306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ BIT(0) 22362306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ_OVRD BIT(1) 22462306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_MASK GENMASK(5, 4) 22562306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_VAL GENMASK(5, 4) 22662306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_PWR_OVRD BIT(24) 22762306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ BIT(8) 22862306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ_OVRD BIT(9) 22962306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_MASK GENMASK(13, 12) 23062306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_VAL GENMASK(13, 12) 23162306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_PWR_OVRD BIT(25) 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_S0_CTL1 0x860 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_S0_CTL2 0x864 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_S0_CTL4 0x86c 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_S0_CTL5 0x870 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_PLL_S0_CTL8 0x87c 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL1 0x960 24462306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL2 0x964 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(x) (0xa60 + (x) * 0x40) 24762306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT 16 24862306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_MASK 0x3 24962306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_VAL 0x2 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PADX_ECTL2(x) (0xa64 + (x) * 0x40) 25262306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_SHIFT 0 25362306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_MASK 0xffff 25462306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_VAL 0x00fc 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PADX_ECTL3(x) (0xa68 + (x) * 0x40) 25762306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL3_RX_DFE_VAL 0xc0077f1f 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PADX_ECTL4(x) (0xa6c + (x) * 0x40) 26062306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_SHIFT 16 26162306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_MASK 0xffff 26262306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_VAL 0x01c7 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PADX_ECTL6(x) (0xa74 + (x) * 0x40) 26562306a36Sopenharmony_ci#define XUSB_PADCTL_UPHY_USB3_PAD_ECTL6_RX_EQ_CTRL_H_VAL 0xfcf01368 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_VBUS_ID 0xc60 26862306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON (1 << 14) 26962306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT 18 27062306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK 0xf 27162306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING 8 27262306a36Sopenharmony_ci#define XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_GROUNDED 0 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci/* USB2 SLEEPWALK registers */ 27562306a36Sopenharmony_ci#define UTMIP(_port, _offset1, _offset2) \ 27662306a36Sopenharmony_ci (((_port) <= 2) ? (_offset1) : (_offset2)) 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci#define PMC_UTMIP_UHSIC_SLEEP_CFG(x) UTMIP(x, 0x1fc, 0x4d0) 27962306a36Sopenharmony_ci#define UTMIP_MASTER_ENABLE(x) UTMIP(x, BIT(8 * (x)), BIT(0)) 28062306a36Sopenharmony_ci#define UTMIP_FSLS_USE_PMC(x) UTMIP(x, BIT(8 * (x) + 1), \ 28162306a36Sopenharmony_ci BIT(1)) 28262306a36Sopenharmony_ci#define UTMIP_PCTRL_USE_PMC(x) UTMIP(x, BIT(8 * (x) + 2), \ 28362306a36Sopenharmony_ci BIT(2)) 28462306a36Sopenharmony_ci#define UTMIP_TCTRL_USE_PMC(x) UTMIP(x, BIT(8 * (x) + 3), \ 28562306a36Sopenharmony_ci BIT(3)) 28662306a36Sopenharmony_ci#define UTMIP_WAKE_VAL(_port, _value) (((_value) & 0xf) << \ 28762306a36Sopenharmony_ci (UTMIP(_port, 8 * (_port) + 4, 4))) 28862306a36Sopenharmony_ci#define UTMIP_WAKE_VAL_NONE(_port) UTMIP_WAKE_VAL(_port, 12) 28962306a36Sopenharmony_ci#define UTMIP_WAKE_VAL_ANY(_port) UTMIP_WAKE_VAL(_port, 15) 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci#define PMC_UTMIP_UHSIC_SLEEP_CFG1 (0x4d0) 29262306a36Sopenharmony_ci#define UTMIP_RPU_SWITC_LOW_USE_PMC_PX(x) BIT((x) + 8) 29362306a36Sopenharmony_ci#define UTMIP_RPD_CTRL_USE_PMC_PX(x) BIT((x) + 16) 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci#define PMC_UTMIP_MASTER_CONFIG (0x274) 29662306a36Sopenharmony_ci#define UTMIP_PWR(x) UTMIP(x, BIT(x), BIT(4)) 29762306a36Sopenharmony_ci#define UHSIC_PWR BIT(3) 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci#define PMC_USB_DEBOUNCE_DEL (0xec) 30062306a36Sopenharmony_ci#define DEBOUNCE_VAL(x) (((x) & 0xffff) << 0) 30162306a36Sopenharmony_ci#define UTMIP_LINE_DEB_CNT(x) (((x) & 0xf) << 16) 30262306a36Sopenharmony_ci#define UHSIC_LINE_DEB_CNT(x) (((x) & 0xf) << 20) 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci#define PMC_UTMIP_UHSIC_FAKE(x) UTMIP(x, 0x218, 0x294) 30562306a36Sopenharmony_ci#define UTMIP_FAKE_USBOP_VAL(x) UTMIP(x, BIT(4 * (x)), BIT(8)) 30662306a36Sopenharmony_ci#define UTMIP_FAKE_USBON_VAL(x) UTMIP(x, BIT(4 * (x) + 1), \ 30762306a36Sopenharmony_ci BIT(9)) 30862306a36Sopenharmony_ci#define UTMIP_FAKE_USBOP_EN(x) UTMIP(x, BIT(4 * (x) + 2), \ 30962306a36Sopenharmony_ci BIT(10)) 31062306a36Sopenharmony_ci#define UTMIP_FAKE_USBON_EN(x) UTMIP(x, BIT(4 * (x) + 3), \ 31162306a36Sopenharmony_ci BIT(11)) 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci#define PMC_UTMIP_UHSIC_SLEEPWALK_CFG(x) UTMIP(x, 0x200, 0x288) 31462306a36Sopenharmony_ci#define UTMIP_LINEVAL_WALK_EN(x) UTMIP(x, BIT(8 * (x) + 7), \ 31562306a36Sopenharmony_ci BIT(15)) 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci#define PMC_USB_AO (0xf0) 31862306a36Sopenharmony_ci#define USBOP_VAL_PD(x) UTMIP(x, BIT(4 * (x)), BIT(20)) 31962306a36Sopenharmony_ci#define USBON_VAL_PD(x) UTMIP(x, BIT(4 * (x) + 1), \ 32062306a36Sopenharmony_ci BIT(21)) 32162306a36Sopenharmony_ci#define STROBE_VAL_PD BIT(12) 32262306a36Sopenharmony_ci#define DATA0_VAL_PD BIT(13) 32362306a36Sopenharmony_ci#define DATA1_VAL_PD BIT(24) 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci#define PMC_UTMIP_UHSIC_SAVED_STATE(x) UTMIP(x, 0x1f0, 0x280) 32662306a36Sopenharmony_ci#define SPEED(_port, _value) (((_value) & 0x3) << \ 32762306a36Sopenharmony_ci (UTMIP(_port, 8 * (_port), 8))) 32862306a36Sopenharmony_ci#define UTMI_HS(_port) SPEED(_port, 0) 32962306a36Sopenharmony_ci#define UTMI_FS(_port) SPEED(_port, 1) 33062306a36Sopenharmony_ci#define UTMI_LS(_port) SPEED(_port, 2) 33162306a36Sopenharmony_ci#define UTMI_RST(_port) SPEED(_port, 3) 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci#define PMC_UTMIP_UHSIC_TRIGGERS (0x1ec) 33462306a36Sopenharmony_ci#define UTMIP_CLR_WALK_PTR(x) UTMIP(x, BIT(x), BIT(16)) 33562306a36Sopenharmony_ci#define UTMIP_CAP_CFG(x) UTMIP(x, BIT((x) + 4), BIT(17)) 33662306a36Sopenharmony_ci#define UTMIP_CLR_WAKE_ALARM(x) UTMIP(x, BIT((x) + 12), \ 33762306a36Sopenharmony_ci BIT(19)) 33862306a36Sopenharmony_ci#define UHSIC_CLR_WALK_PTR BIT(3) 33962306a36Sopenharmony_ci#define UHSIC_CLR_WAKE_ALARM BIT(15) 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci#define PMC_UTMIP_SLEEPWALK_PX(x) UTMIP(x, 0x204 + (4 * (x)), \ 34262306a36Sopenharmony_ci 0x4e0) 34362306a36Sopenharmony_ci/* phase A */ 34462306a36Sopenharmony_ci#define UTMIP_USBOP_RPD_A BIT(0) 34562306a36Sopenharmony_ci#define UTMIP_USBON_RPD_A BIT(1) 34662306a36Sopenharmony_ci#define UTMIP_AP_A BIT(4) 34762306a36Sopenharmony_ci#define UTMIP_AN_A BIT(5) 34862306a36Sopenharmony_ci#define UTMIP_HIGHZ_A BIT(6) 34962306a36Sopenharmony_ci/* phase B */ 35062306a36Sopenharmony_ci#define UTMIP_USBOP_RPD_B BIT(8) 35162306a36Sopenharmony_ci#define UTMIP_USBON_RPD_B BIT(9) 35262306a36Sopenharmony_ci#define UTMIP_AP_B BIT(12) 35362306a36Sopenharmony_ci#define UTMIP_AN_B BIT(13) 35462306a36Sopenharmony_ci#define UTMIP_HIGHZ_B BIT(14) 35562306a36Sopenharmony_ci/* phase C */ 35662306a36Sopenharmony_ci#define UTMIP_USBOP_RPD_C BIT(16) 35762306a36Sopenharmony_ci#define UTMIP_USBON_RPD_C BIT(17) 35862306a36Sopenharmony_ci#define UTMIP_AP_C BIT(20) 35962306a36Sopenharmony_ci#define UTMIP_AN_C BIT(21) 36062306a36Sopenharmony_ci#define UTMIP_HIGHZ_C BIT(22) 36162306a36Sopenharmony_ci/* phase D */ 36262306a36Sopenharmony_ci#define UTMIP_USBOP_RPD_D BIT(24) 36362306a36Sopenharmony_ci#define UTMIP_USBON_RPD_D BIT(25) 36462306a36Sopenharmony_ci#define UTMIP_AP_D BIT(28) 36562306a36Sopenharmony_ci#define UTMIP_AN_D BIT(29) 36662306a36Sopenharmony_ci#define UTMIP_HIGHZ_D BIT(30) 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci#define PMC_UTMIP_UHSIC_LINE_WAKEUP (0x26c) 36962306a36Sopenharmony_ci#define UTMIP_LINE_WAKEUP_EN(x) UTMIP(x, BIT(x), BIT(4)) 37062306a36Sopenharmony_ci#define UHSIC_LINE_WAKEUP_EN BIT(3) 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci#define PMC_UTMIP_TERM_PAD_CFG (0x1f8) 37362306a36Sopenharmony_ci#define PCTRL_VAL(x) (((x) & 0x3f) << 1) 37462306a36Sopenharmony_ci#define TCTRL_VAL(x) (((x) & 0x3f) << 7) 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci#define PMC_UTMIP_PAD_CFGX(x) (0x4c0 + (4 * (x))) 37762306a36Sopenharmony_ci#define RPD_CTRL_PX(x) (((x) & 0x1f) << 22) 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci#define PMC_UHSIC_SLEEP_CFG PMC_UTMIP_UHSIC_SLEEP_CFG(0) 38062306a36Sopenharmony_ci#define UHSIC_MASTER_ENABLE BIT(24) 38162306a36Sopenharmony_ci#define UHSIC_WAKE_VAL(_value) (((_value) & 0xf) << 28) 38262306a36Sopenharmony_ci#define UHSIC_WAKE_VAL_SD10 UHSIC_WAKE_VAL(2) 38362306a36Sopenharmony_ci#define UHSIC_WAKE_VAL_NONE UHSIC_WAKE_VAL(12) 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci#define PMC_UHSIC_FAKE PMC_UTMIP_UHSIC_FAKE(0) 38662306a36Sopenharmony_ci#define UHSIC_FAKE_STROBE_VAL BIT(12) 38762306a36Sopenharmony_ci#define UHSIC_FAKE_DATA_VAL BIT(13) 38862306a36Sopenharmony_ci#define UHSIC_FAKE_STROBE_EN BIT(14) 38962306a36Sopenharmony_ci#define UHSIC_FAKE_DATA_EN BIT(15) 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci#define PMC_UHSIC_SAVED_STATE PMC_UTMIP_UHSIC_SAVED_STATE(0) 39262306a36Sopenharmony_ci#define UHSIC_MODE(_value) (((_value) & 0x1) << 24) 39362306a36Sopenharmony_ci#define UHSIC_HS UHSIC_MODE(0) 39462306a36Sopenharmony_ci#define UHSIC_RST UHSIC_MODE(1) 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci#define PMC_UHSIC_SLEEPWALK_CFG PMC_UTMIP_UHSIC_SLEEPWALK_CFG(0) 39762306a36Sopenharmony_ci#define UHSIC_WAKE_WALK_EN BIT(30) 39862306a36Sopenharmony_ci#define UHSIC_LINEVAL_WALK_EN BIT(31) 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci#define PMC_UHSIC_SLEEPWALK_P0 (0x210) 40162306a36Sopenharmony_ci#define UHSIC_DATA0_RPD_A BIT(1) 40262306a36Sopenharmony_ci#define UHSIC_DATA0_RPU_B BIT(11) 40362306a36Sopenharmony_ci#define UHSIC_DATA0_RPU_C BIT(19) 40462306a36Sopenharmony_ci#define UHSIC_DATA0_RPU_D BIT(27) 40562306a36Sopenharmony_ci#define UHSIC_STROBE_RPU_A BIT(2) 40662306a36Sopenharmony_ci#define UHSIC_STROBE_RPD_B BIT(8) 40762306a36Sopenharmony_ci#define UHSIC_STROBE_RPD_C BIT(16) 40862306a36Sopenharmony_ci#define UHSIC_STROBE_RPD_D BIT(24) 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_cistruct tegra210_xusb_fuse_calibration { 41162306a36Sopenharmony_ci u32 hs_curr_level[4]; 41262306a36Sopenharmony_ci u32 hs_term_range_adj; 41362306a36Sopenharmony_ci u32 rpd_ctrl; 41462306a36Sopenharmony_ci}; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_cistruct tegra210_xusb_padctl_context { 41762306a36Sopenharmony_ci u32 usb2_pad_mux; 41862306a36Sopenharmony_ci u32 usb2_port_cap; 41962306a36Sopenharmony_ci u32 ss_port_map; 42062306a36Sopenharmony_ci u32 usb3_pad_mux; 42162306a36Sopenharmony_ci}; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_cistruct tegra210_xusb_padctl { 42462306a36Sopenharmony_ci struct tegra_xusb_padctl base; 42562306a36Sopenharmony_ci struct regmap *regmap; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci struct tegra210_xusb_fuse_calibration fuse; 42862306a36Sopenharmony_ci struct tegra210_xusb_padctl_context context; 42962306a36Sopenharmony_ci}; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_cistatic inline struct tegra210_xusb_padctl * 43262306a36Sopenharmony_cito_tegra210_xusb_padctl(struct tegra_xusb_padctl *padctl) 43362306a36Sopenharmony_ci{ 43462306a36Sopenharmony_ci return container_of(padctl, struct tegra210_xusb_padctl, base); 43562306a36Sopenharmony_ci} 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_cistatic const struct tegra_xusb_lane_map tegra210_usb3_map[] = { 43862306a36Sopenharmony_ci { 0, "pcie", 6 }, 43962306a36Sopenharmony_ci { 1, "pcie", 5 }, 44062306a36Sopenharmony_ci { 2, "pcie", 0 }, 44162306a36Sopenharmony_ci { 2, "pcie", 3 }, 44262306a36Sopenharmony_ci { 3, "pcie", 4 }, 44362306a36Sopenharmony_ci { 3, "sata", 0 }, 44462306a36Sopenharmony_ci { 0, NULL, 0 } 44562306a36Sopenharmony_ci}; 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_cistatic int tegra210_usb3_lane_map(struct tegra_xusb_lane *lane) 44862306a36Sopenharmony_ci{ 44962306a36Sopenharmony_ci const struct tegra_xusb_lane_map *map; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci for (map = tegra210_usb3_map; map->type; map++) { 45262306a36Sopenharmony_ci if (map->index == lane->index && 45362306a36Sopenharmony_ci strcmp(map->type, lane->pad->soc->name) == 0) { 45462306a36Sopenharmony_ci dev_dbg(lane->pad->padctl->dev, "lane = %s map to port = usb3-%d\n", 45562306a36Sopenharmony_ci lane->pad->soc->lanes[lane->index].name, map->port); 45662306a36Sopenharmony_ci return map->port; 45762306a36Sopenharmony_ci } 45862306a36Sopenharmony_ci } 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci return -EINVAL; 46162306a36Sopenharmony_ci} 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci/* must be called under padctl->lock */ 46462306a36Sopenharmony_cistatic int tegra210_pex_uphy_enable(struct tegra_xusb_padctl *padctl) 46562306a36Sopenharmony_ci{ 46662306a36Sopenharmony_ci struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(padctl->pcie); 46762306a36Sopenharmony_ci unsigned long timeout; 46862306a36Sopenharmony_ci u32 value; 46962306a36Sopenharmony_ci unsigned int i; 47062306a36Sopenharmony_ci int err; 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci if (pcie->enable) 47362306a36Sopenharmony_ci return 0; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci err = clk_prepare_enable(pcie->pll); 47662306a36Sopenharmony_ci if (err < 0) 47762306a36Sopenharmony_ci return err; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci if (tegra210_plle_hw_sequence_is_enabled()) 48062306a36Sopenharmony_ci goto skip_pll_init; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci err = reset_control_deassert(pcie->rst); 48362306a36Sopenharmony_ci if (err < 0) 48462306a36Sopenharmony_ci goto disable; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 48762306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_MASK << 48862306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT); 48962306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_VAL << 49062306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT; 49162306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL5); 49462306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_MASK << 49562306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT); 49662306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_VAL << 49762306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT; 49862306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL5); 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 50162306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD; 50262306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 50562306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD; 50662306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 50962306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD; 51062306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL4); 51362306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_MASK << 51462306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT) | 51562306a36Sopenharmony_ci (XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_MASK << 51662306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_SHIFT)); 51762306a36Sopenharmony_ci value |= (XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_USB_VAL << 51862306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT) | 51962306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_EN; 52062306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL4); 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 52362306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_MASK << 52462306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_SHIFT) | 52562306a36Sopenharmony_ci (XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_MASK << 52662306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT)); 52762306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_USB_VAL << 52862306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT; 52962306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 53262306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_IDDQ; 53362306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 53662306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_MASK << 53762306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_SHIFT); 53862306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci usleep_range(10, 20); 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL4); 54362306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL4_REFCLKBUF_EN; 54462306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL4); 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 54762306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN; 54862306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(100); 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci while (time_before(jiffies, timeout)) { 55362306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 55462306a36Sopenharmony_ci if (value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE) 55562306a36Sopenharmony_ci break; 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci usleep_range(10, 20); 55862306a36Sopenharmony_ci } 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci if (time_after_eq(jiffies, timeout)) { 56162306a36Sopenharmony_ci err = -ETIMEDOUT; 56262306a36Sopenharmony_ci goto reset; 56362306a36Sopenharmony_ci } 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 56662306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN; 56762306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(100); 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci while (time_before(jiffies, timeout)) { 57262306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 57362306a36Sopenharmony_ci if (!(value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE)) 57462306a36Sopenharmony_ci break; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci usleep_range(10, 20); 57762306a36Sopenharmony_ci } 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci if (time_after_eq(jiffies, timeout)) { 58062306a36Sopenharmony_ci err = -ETIMEDOUT; 58162306a36Sopenharmony_ci goto reset; 58262306a36Sopenharmony_ci } 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 58562306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL1_ENABLE; 58662306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(100); 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci while (time_before(jiffies, timeout)) { 59162306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 59262306a36Sopenharmony_ci if (value & XUSB_PADCTL_UPHY_PLL_CTL1_LOCKDET_STATUS) 59362306a36Sopenharmony_ci break; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci usleep_range(10, 20); 59662306a36Sopenharmony_ci } 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci if (time_after_eq(jiffies, timeout)) { 59962306a36Sopenharmony_ci err = -ETIMEDOUT; 60062306a36Sopenharmony_ci goto reset; 60162306a36Sopenharmony_ci } 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 60462306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN | 60562306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN; 60662306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(100); 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci while (time_before(jiffies, timeout)) { 61162306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 61262306a36Sopenharmony_ci if (value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE) 61362306a36Sopenharmony_ci break; 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci usleep_range(10, 20); 61662306a36Sopenharmony_ci } 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci if (time_after_eq(jiffies, timeout)) { 61962306a36Sopenharmony_ci err = -ETIMEDOUT; 62062306a36Sopenharmony_ci goto reset; 62162306a36Sopenharmony_ci } 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 62462306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN; 62562306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(100); 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci while (time_before(jiffies, timeout)) { 63062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 63162306a36Sopenharmony_ci if (!(value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE)) 63262306a36Sopenharmony_ci break; 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci usleep_range(10, 20); 63562306a36Sopenharmony_ci } 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci if (time_after_eq(jiffies, timeout)) { 63862306a36Sopenharmony_ci err = -ETIMEDOUT; 63962306a36Sopenharmony_ci goto reset; 64062306a36Sopenharmony_ci } 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 64362306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN; 64462306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci tegra210_xusb_pll_hw_control_enable(); 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 64962306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD; 65062306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1); 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 65362306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD; 65462306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2); 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 65762306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD; 65862306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8); 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci usleep_range(10, 20); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci tegra210_xusb_pll_hw_sequence_start(); 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ciskip_pll_init: 66562306a36Sopenharmony_ci pcie->enable = true; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci for (i = 0; i < padctl->pcie->soc->num_lanes; i++) { 66862306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); 66962306a36Sopenharmony_ci value |= XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(i); 67062306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); 67162306a36Sopenharmony_ci } 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci return 0; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_cireset: 67662306a36Sopenharmony_ci reset_control_assert(pcie->rst); 67762306a36Sopenharmony_cidisable: 67862306a36Sopenharmony_ci clk_disable_unprepare(pcie->pll); 67962306a36Sopenharmony_ci return err; 68062306a36Sopenharmony_ci} 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_cistatic void tegra210_pex_uphy_disable(struct tegra_xusb_padctl *padctl) 68362306a36Sopenharmony_ci{ 68462306a36Sopenharmony_ci struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(padctl->pcie); 68562306a36Sopenharmony_ci u32 value; 68662306a36Sopenharmony_ci unsigned int i; 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci if (WARN_ON(!pcie->enable)) 68962306a36Sopenharmony_ci return; 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci pcie->enable = false; 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci for (i = 0; i < padctl->pcie->soc->num_lanes; i++) { 69462306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); 69562306a36Sopenharmony_ci value &= ~XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(i); 69662306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); 69762306a36Sopenharmony_ci } 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci clk_disable_unprepare(pcie->pll); 70062306a36Sopenharmony_ci} 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci/* must be called under padctl->lock */ 70362306a36Sopenharmony_cistatic int tegra210_sata_uphy_enable(struct tegra_xusb_padctl *padctl) 70462306a36Sopenharmony_ci{ 70562306a36Sopenharmony_ci struct tegra_xusb_sata_pad *sata = to_sata_pad(padctl->sata); 70662306a36Sopenharmony_ci struct tegra_xusb_lane *lane = tegra_xusb_find_lane(padctl, "sata", 0); 70762306a36Sopenharmony_ci unsigned long timeout; 70862306a36Sopenharmony_ci u32 value; 70962306a36Sopenharmony_ci unsigned int i; 71062306a36Sopenharmony_ci int err; 71162306a36Sopenharmony_ci bool usb; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci if (sata->enable) 71462306a36Sopenharmony_ci return 0; 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci if (IS_ERR(lane)) 71762306a36Sopenharmony_ci return 0; 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci if (tegra210_plle_hw_sequence_is_enabled()) 72062306a36Sopenharmony_ci goto skip_pll_init; 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci usb = tegra_xusb_lane_check(lane, "usb3-ss"); 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci err = clk_prepare_enable(sata->pll); 72562306a36Sopenharmony_ci if (err < 0) 72662306a36Sopenharmony_ci return err; 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci err = reset_control_deassert(sata->rst); 72962306a36Sopenharmony_ci if (err < 0) 73062306a36Sopenharmony_ci goto disable; 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 73362306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_MASK << 73462306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT); 73562306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_VAL << 73662306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT; 73762306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL5); 74062306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_MASK << 74162306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT); 74262306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_VAL << 74362306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT; 74462306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL5); 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 74762306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD; 74862306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 75162306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD; 75262306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 75562306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD; 75662306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL4); 75962306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_MASK << 76062306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT) | 76162306a36Sopenharmony_ci (XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_MASK << 76262306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_SHIFT)); 76362306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_EN; 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci if (usb) 76662306a36Sopenharmony_ci value |= (XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_USB_VAL << 76762306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT); 76862306a36Sopenharmony_ci else 76962306a36Sopenharmony_ci value |= (XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SATA_VAL << 77062306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT); 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_PLL_CTL4_XDIGCLK_EN; 77362306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL4); 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 77662306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_MASK << 77762306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_SHIFT) | 77862306a36Sopenharmony_ci (XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_MASK << 77962306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT)); 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci if (usb) 78262306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_USB_VAL << 78362306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT; 78462306a36Sopenharmony_ci else 78562306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SATA_VAL << 78662306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT; 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 79162306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_IDDQ; 79262306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 79562306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_MASK << 79662306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_SHIFT); 79762306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci usleep_range(10, 20); 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL4); 80262306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL4_REFCLKBUF_EN; 80362306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL4); 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 80662306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN; 80762306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(100); 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci while (time_before(jiffies, timeout)) { 81262306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 81362306a36Sopenharmony_ci if (value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE) 81462306a36Sopenharmony_ci break; 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci usleep_range(10, 20); 81762306a36Sopenharmony_ci } 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci if (time_after_eq(jiffies, timeout)) { 82062306a36Sopenharmony_ci err = -ETIMEDOUT; 82162306a36Sopenharmony_ci goto reset; 82262306a36Sopenharmony_ci } 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 82562306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN; 82662306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(100); 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci while (time_before(jiffies, timeout)) { 83162306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 83262306a36Sopenharmony_ci if (!(value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE)) 83362306a36Sopenharmony_ci break; 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci usleep_range(10, 20); 83662306a36Sopenharmony_ci } 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci if (time_after_eq(jiffies, timeout)) { 83962306a36Sopenharmony_ci err = -ETIMEDOUT; 84062306a36Sopenharmony_ci goto reset; 84162306a36Sopenharmony_ci } 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 84462306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL1_ENABLE; 84562306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(100); 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci while (time_before(jiffies, timeout)) { 85062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 85162306a36Sopenharmony_ci if (value & XUSB_PADCTL_UPHY_PLL_CTL1_LOCKDET_STATUS) 85262306a36Sopenharmony_ci break; 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci usleep_range(10, 20); 85562306a36Sopenharmony_ci } 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci if (time_after_eq(jiffies, timeout)) { 85862306a36Sopenharmony_ci err = -ETIMEDOUT; 85962306a36Sopenharmony_ci goto reset; 86062306a36Sopenharmony_ci } 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 86362306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN | 86462306a36Sopenharmony_ci XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN; 86562306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(100); 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci while (time_before(jiffies, timeout)) { 87062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 87162306a36Sopenharmony_ci if (value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE) 87262306a36Sopenharmony_ci break; 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci usleep_range(10, 20); 87562306a36Sopenharmony_ci } 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci if (time_after_eq(jiffies, timeout)) { 87862306a36Sopenharmony_ci err = -ETIMEDOUT; 87962306a36Sopenharmony_ci goto reset; 88062306a36Sopenharmony_ci } 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 88362306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN; 88462306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(100); 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ci while (time_before(jiffies, timeout)) { 88962306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 89062306a36Sopenharmony_ci if (!(value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE)) 89162306a36Sopenharmony_ci break; 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci usleep_range(10, 20); 89462306a36Sopenharmony_ci } 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci if (time_after_eq(jiffies, timeout)) { 89762306a36Sopenharmony_ci err = -ETIMEDOUT; 89862306a36Sopenharmony_ci goto reset; 89962306a36Sopenharmony_ci } 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 90262306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN; 90362306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci tegra210_sata_pll_hw_control_enable(); 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 90862306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD; 90962306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL1); 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 91262306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD; 91362306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL2); 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 91662306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD; 91762306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_S0_CTL8); 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci usleep_range(10, 20); 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci tegra210_sata_pll_hw_sequence_start(); 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ciskip_pll_init: 92462306a36Sopenharmony_ci sata->enable = true; 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_ci for (i = 0; i < padctl->sata->soc->num_lanes; i++) { 92762306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); 92862306a36Sopenharmony_ci value |= XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(i); 92962306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); 93062306a36Sopenharmony_ci } 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_ci return 0; 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_cireset: 93562306a36Sopenharmony_ci reset_control_assert(sata->rst); 93662306a36Sopenharmony_cidisable: 93762306a36Sopenharmony_ci clk_disable_unprepare(sata->pll); 93862306a36Sopenharmony_ci return err; 93962306a36Sopenharmony_ci} 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_cistatic void tegra210_sata_uphy_disable(struct tegra_xusb_padctl *padctl) 94262306a36Sopenharmony_ci{ 94362306a36Sopenharmony_ci struct tegra_xusb_sata_pad *sata = to_sata_pad(padctl->sata); 94462306a36Sopenharmony_ci u32 value; 94562306a36Sopenharmony_ci unsigned int i; 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_ci if (WARN_ON(!sata->enable)) 94862306a36Sopenharmony_ci return; 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci sata->enable = false; 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci for (i = 0; i < padctl->sata->soc->num_lanes; i++) { 95362306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); 95462306a36Sopenharmony_ci value &= ~XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(i); 95562306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX); 95662306a36Sopenharmony_ci } 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci clk_disable_unprepare(sata->pll); 95962306a36Sopenharmony_ci} 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_cistatic void tegra210_aux_mux_lp0_clamp_disable(struct tegra_xusb_padctl *padctl) 96262306a36Sopenharmony_ci{ 96362306a36Sopenharmony_ci u32 value; 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 96662306a36Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN; 96762306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci usleep_range(100, 200); 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 97262306a36Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY; 97362306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci usleep_range(100, 200); 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 97862306a36Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN; 97962306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 98062306a36Sopenharmony_ci} 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_cistatic void tegra210_aux_mux_lp0_clamp_enable(struct tegra_xusb_padctl *padctl) 98362306a36Sopenharmony_ci{ 98462306a36Sopenharmony_ci u32 value; 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 98762306a36Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN; 98862306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci usleep_range(100, 200); 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 99362306a36Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY; 99462306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci usleep_range(100, 200); 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 99962306a36Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN; 100062306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 100162306a36Sopenharmony_ci} 100262306a36Sopenharmony_ci 100362306a36Sopenharmony_cistatic int tegra210_uphy_init(struct tegra_xusb_padctl *padctl) 100462306a36Sopenharmony_ci{ 100562306a36Sopenharmony_ci if (padctl->pcie) 100662306a36Sopenharmony_ci tegra210_pex_uphy_enable(padctl); 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_ci if (padctl->sata) 100962306a36Sopenharmony_ci tegra210_sata_uphy_enable(padctl); 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci if (!tegra210_plle_hw_sequence_is_enabled()) 101262306a36Sopenharmony_ci tegra210_plle_hw_sequence_start(); 101362306a36Sopenharmony_ci else 101462306a36Sopenharmony_ci dev_dbg(padctl->dev, "PLLE is already in HW control\n"); 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci tegra210_aux_mux_lp0_clamp_disable(padctl); 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_ci return 0; 101962306a36Sopenharmony_ci} 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_cistatic void __maybe_unused 102262306a36Sopenharmony_citegra210_uphy_deinit(struct tegra_xusb_padctl *padctl) 102362306a36Sopenharmony_ci{ 102462306a36Sopenharmony_ci tegra210_aux_mux_lp0_clamp_enable(padctl); 102562306a36Sopenharmony_ci 102662306a36Sopenharmony_ci if (padctl->sata) 102762306a36Sopenharmony_ci tegra210_sata_uphy_disable(padctl); 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci if (padctl->pcie) 103062306a36Sopenharmony_ci tegra210_pex_uphy_disable(padctl); 103162306a36Sopenharmony_ci} 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_cistatic int tegra210_hsic_set_idle(struct tegra_xusb_padctl *padctl, 103462306a36Sopenharmony_ci unsigned int index, bool idle) 103562306a36Sopenharmony_ci{ 103662306a36Sopenharmony_ci u32 value; 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(index)); 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA0 | 104162306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA1 | 104262306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_RPD_STROBE); 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci if (idle) 104562306a36Sopenharmony_ci value |= XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA0 | 104662306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA1 | 104762306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE; 104862306a36Sopenharmony_ci else 104962306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA0 | 105062306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA1 | 105162306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE); 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL0(index)); 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_ci return 0; 105662306a36Sopenharmony_ci} 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_cistatic int tegra210_usb3_enable_phy_sleepwalk(struct tegra_xusb_lane *lane, 105962306a36Sopenharmony_ci enum usb_device_speed speed) 106062306a36Sopenharmony_ci{ 106162306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 106262306a36Sopenharmony_ci int port = tegra210_usb3_lane_map(lane); 106362306a36Sopenharmony_ci struct device *dev = padctl->dev; 106462306a36Sopenharmony_ci u32 value; 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci if (port < 0) { 106762306a36Sopenharmony_ci dev_err(dev, "invalid usb3 port number\n"); 106862306a36Sopenharmony_ci return -EINVAL; 106962306a36Sopenharmony_ci } 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci mutex_lock(&padctl->lock); 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 107462306a36Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(port); 107562306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci usleep_range(100, 200); 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 108062306a36Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(port); 108162306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci usleep_range(250, 350); 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_ci return 0; 108862306a36Sopenharmony_ci} 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_cistatic int tegra210_usb3_disable_phy_sleepwalk(struct tegra_xusb_lane *lane) 109162306a36Sopenharmony_ci{ 109262306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 109362306a36Sopenharmony_ci int port = tegra210_usb3_lane_map(lane); 109462306a36Sopenharmony_ci struct device *dev = padctl->dev; 109562306a36Sopenharmony_ci u32 value; 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci if (port < 0) { 109862306a36Sopenharmony_ci dev_err(dev, "invalid usb3 port number\n"); 109962306a36Sopenharmony_ci return -EINVAL; 110062306a36Sopenharmony_ci } 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_ci mutex_lock(&padctl->lock); 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 110562306a36Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(port); 110662306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci usleep_range(100, 200); 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 111162306a36Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(port); 111262306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ci return 0; 111762306a36Sopenharmony_ci} 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_cistatic int tegra210_usb3_enable_phy_wake(struct tegra_xusb_lane *lane) 112062306a36Sopenharmony_ci{ 112162306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 112262306a36Sopenharmony_ci int port = tegra210_usb3_lane_map(lane); 112362306a36Sopenharmony_ci struct device *dev = padctl->dev; 112462306a36Sopenharmony_ci u32 value; 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci if (port < 0) { 112762306a36Sopenharmony_ci dev_err(dev, "invalid usb3 port number\n"); 112862306a36Sopenharmony_ci return -EINVAL; 112962306a36Sopenharmony_ci } 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci mutex_lock(&padctl->lock); 113262306a36Sopenharmony_ci 113362306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); 113462306a36Sopenharmony_ci value &= ~ALL_WAKE_EVENTS; 113562306a36Sopenharmony_ci value |= SS_PORT_WAKEUP_EVENT(port); 113662306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci usleep_range(10, 20); 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); 114162306a36Sopenharmony_ci value &= ~ALL_WAKE_EVENTS; 114262306a36Sopenharmony_ci value |= SS_PORT_WAKE_INTERRUPT_ENABLE(port); 114362306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci return 0; 114862306a36Sopenharmony_ci} 114962306a36Sopenharmony_ci 115062306a36Sopenharmony_cistatic int tegra210_usb3_disable_phy_wake(struct tegra_xusb_lane *lane) 115162306a36Sopenharmony_ci{ 115262306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 115362306a36Sopenharmony_ci int port = tegra210_usb3_lane_map(lane); 115462306a36Sopenharmony_ci struct device *dev = padctl->dev; 115562306a36Sopenharmony_ci u32 value; 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ci if (port < 0) { 115862306a36Sopenharmony_ci dev_err(dev, "invalid usb3 port number\n"); 115962306a36Sopenharmony_ci return -EINVAL; 116062306a36Sopenharmony_ci } 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci mutex_lock(&padctl->lock); 116362306a36Sopenharmony_ci 116462306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); 116562306a36Sopenharmony_ci value &= ~ALL_WAKE_EVENTS; 116662306a36Sopenharmony_ci value &= ~SS_PORT_WAKE_INTERRUPT_ENABLE(port); 116762306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci usleep_range(10, 20); 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); 117262306a36Sopenharmony_ci value &= ~ALL_WAKE_EVENTS; 117362306a36Sopenharmony_ci value |= SS_PORT_WAKEUP_EVENT(port); 117462306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_ci return 0; 117962306a36Sopenharmony_ci} 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_cistatic bool tegra210_usb3_phy_remote_wake_detected(struct tegra_xusb_lane *lane) 118262306a36Sopenharmony_ci{ 118362306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 118462306a36Sopenharmony_ci int index = tegra210_usb3_lane_map(lane); 118562306a36Sopenharmony_ci u32 value; 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci if (index < 0) 118862306a36Sopenharmony_ci return false; 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); 119162306a36Sopenharmony_ci if ((value & SS_PORT_WAKE_INTERRUPT_ENABLE(index)) && (value & SS_PORT_WAKEUP_EVENT(index))) 119262306a36Sopenharmony_ci return true; 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci return false; 119562306a36Sopenharmony_ci} 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_cistatic int tegra210_utmi_enable_phy_wake(struct tegra_xusb_lane *lane) 119862306a36Sopenharmony_ci{ 119962306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 120062306a36Sopenharmony_ci unsigned int index = lane->index; 120162306a36Sopenharmony_ci u32 value; 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci mutex_lock(&padctl->lock); 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); 120662306a36Sopenharmony_ci value &= ~ALL_WAKE_EVENTS; 120762306a36Sopenharmony_ci value |= USB2_PORT_WAKEUP_EVENT(index); 120862306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci usleep_range(10, 20); 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); 121362306a36Sopenharmony_ci value &= ~ALL_WAKE_EVENTS; 121462306a36Sopenharmony_ci value |= USB2_PORT_WAKE_INTERRUPT_ENABLE(index); 121562306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci return 0; 122062306a36Sopenharmony_ci} 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_cistatic int tegra210_utmi_disable_phy_wake(struct tegra_xusb_lane *lane) 122362306a36Sopenharmony_ci{ 122462306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 122562306a36Sopenharmony_ci unsigned int index = lane->index; 122662306a36Sopenharmony_ci u32 value; 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci mutex_lock(&padctl->lock); 122962306a36Sopenharmony_ci 123062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); 123162306a36Sopenharmony_ci value &= ~ALL_WAKE_EVENTS; 123262306a36Sopenharmony_ci value &= ~USB2_PORT_WAKE_INTERRUPT_ENABLE(index); 123362306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_ci usleep_range(10, 20); 123662306a36Sopenharmony_ci 123762306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); 123862306a36Sopenharmony_ci value &= ~ALL_WAKE_EVENTS; 123962306a36Sopenharmony_ci value |= USB2_PORT_WAKEUP_EVENT(index); 124062306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci return 0; 124562306a36Sopenharmony_ci} 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_cistatic bool tegra210_utmi_phy_remote_wake_detected(struct tegra_xusb_lane *lane) 124862306a36Sopenharmony_ci{ 124962306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 125062306a36Sopenharmony_ci unsigned int index = lane->index; 125162306a36Sopenharmony_ci u32 value; 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); 125462306a36Sopenharmony_ci if ((value & USB2_PORT_WAKE_INTERRUPT_ENABLE(index)) && 125562306a36Sopenharmony_ci (value & USB2_PORT_WAKEUP_EVENT(index))) 125662306a36Sopenharmony_ci return true; 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_ci return false; 125962306a36Sopenharmony_ci} 126062306a36Sopenharmony_ci 126162306a36Sopenharmony_cistatic int tegra210_hsic_enable_phy_wake(struct tegra_xusb_lane *lane) 126262306a36Sopenharmony_ci{ 126362306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 126462306a36Sopenharmony_ci unsigned int index = lane->index; 126562306a36Sopenharmony_ci u32 value; 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_ci mutex_lock(&padctl->lock); 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); 127062306a36Sopenharmony_ci value &= ~ALL_WAKE_EVENTS; 127162306a36Sopenharmony_ci value |= USB2_HSIC_PORT_WAKEUP_EVENT(index); 127262306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci usleep_range(10, 20); 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); 127762306a36Sopenharmony_ci value &= ~ALL_WAKE_EVENTS; 127862306a36Sopenharmony_ci value |= USB2_HSIC_PORT_WAKE_INTERRUPT_ENABLE(index); 127962306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); 128062306a36Sopenharmony_ci 128162306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci return 0; 128462306a36Sopenharmony_ci} 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_cistatic int tegra210_hsic_disable_phy_wake(struct tegra_xusb_lane *lane) 128762306a36Sopenharmony_ci{ 128862306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 128962306a36Sopenharmony_ci unsigned int index = lane->index; 129062306a36Sopenharmony_ci u32 value; 129162306a36Sopenharmony_ci 129262306a36Sopenharmony_ci mutex_lock(&padctl->lock); 129362306a36Sopenharmony_ci 129462306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); 129562306a36Sopenharmony_ci value &= ~ALL_WAKE_EVENTS; 129662306a36Sopenharmony_ci value &= ~USB2_HSIC_PORT_WAKE_INTERRUPT_ENABLE(index); 129762306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_ci usleep_range(10, 20); 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); 130262306a36Sopenharmony_ci value &= ~ALL_WAKE_EVENTS; 130362306a36Sopenharmony_ci value |= USB2_HSIC_PORT_WAKEUP_EVENT(index); 130462306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM_0); 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci return 0; 130962306a36Sopenharmony_ci} 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_cistatic bool tegra210_hsic_phy_remote_wake_detected(struct tegra_xusb_lane *lane) 131262306a36Sopenharmony_ci{ 131362306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 131462306a36Sopenharmony_ci unsigned int index = lane->index; 131562306a36Sopenharmony_ci u32 value; 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM_0); 131862306a36Sopenharmony_ci if ((value & USB2_HSIC_PORT_WAKE_INTERRUPT_ENABLE(index)) && 131962306a36Sopenharmony_ci (value & USB2_HSIC_PORT_WAKEUP_EVENT(index))) 132062306a36Sopenharmony_ci return true; 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci return false; 132362306a36Sopenharmony_ci} 132462306a36Sopenharmony_ci 132562306a36Sopenharmony_ci#define padctl_pmc_readl(_priv, _offset) \ 132662306a36Sopenharmony_ci({ \ 132762306a36Sopenharmony_ci u32 value; \ 132862306a36Sopenharmony_ci WARN(regmap_read(_priv->regmap, _offset, &value), "read %s failed\n", #_offset);\ 132962306a36Sopenharmony_ci value; \ 133062306a36Sopenharmony_ci}) 133162306a36Sopenharmony_ci 133262306a36Sopenharmony_ci#define padctl_pmc_writel(_priv, _value, _offset) \ 133362306a36Sopenharmony_ci WARN(regmap_write(_priv->regmap, _offset, _value), "write %s failed\n", #_offset) 133462306a36Sopenharmony_ci 133562306a36Sopenharmony_cistatic int tegra210_pmc_utmi_enable_phy_sleepwalk(struct tegra_xusb_lane *lane, 133662306a36Sopenharmony_ci enum usb_device_speed speed) 133762306a36Sopenharmony_ci{ 133862306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 133962306a36Sopenharmony_ci struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl); 134062306a36Sopenharmony_ci unsigned int port = lane->index; 134162306a36Sopenharmony_ci u32 value, tctrl, pctrl, rpd_ctrl; 134262306a36Sopenharmony_ci 134362306a36Sopenharmony_ci if (!priv->regmap) 134462306a36Sopenharmony_ci return -EOPNOTSUPP; 134562306a36Sopenharmony_ci 134662306a36Sopenharmony_ci if (speed > USB_SPEED_HIGH) 134762306a36Sopenharmony_ci return -EINVAL; 134862306a36Sopenharmony_ci 134962306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); 135062306a36Sopenharmony_ci tctrl = TCTRL_VALUE(value); 135162306a36Sopenharmony_ci pctrl = PCTRL_VALUE(value); 135262306a36Sopenharmony_ci 135362306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(port)); 135462306a36Sopenharmony_ci rpd_ctrl = RPD_CTRL_VALUE(value); 135562306a36Sopenharmony_ci 135662306a36Sopenharmony_ci /* ensure sleepwalk logic is disabled */ 135762306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); 135862306a36Sopenharmony_ci value &= ~UTMIP_MASTER_ENABLE(port); 135962306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); 136062306a36Sopenharmony_ci 136162306a36Sopenharmony_ci /* ensure sleepwalk logics are in low power mode */ 136262306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_MASTER_CONFIG); 136362306a36Sopenharmony_ci value |= UTMIP_PWR(port); 136462306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_MASTER_CONFIG); 136562306a36Sopenharmony_ci 136662306a36Sopenharmony_ci /* set debounce time */ 136762306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_USB_DEBOUNCE_DEL); 136862306a36Sopenharmony_ci value &= ~UTMIP_LINE_DEB_CNT(~0); 136962306a36Sopenharmony_ci value |= UTMIP_LINE_DEB_CNT(0x1); 137062306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_USB_DEBOUNCE_DEL); 137162306a36Sopenharmony_ci 137262306a36Sopenharmony_ci /* ensure fake events of sleepwalk logic are desiabled */ 137362306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_FAKE(port)); 137462306a36Sopenharmony_ci value &= ~(UTMIP_FAKE_USBOP_VAL(port) | UTMIP_FAKE_USBON_VAL(port) | 137562306a36Sopenharmony_ci UTMIP_FAKE_USBOP_EN(port) | UTMIP_FAKE_USBON_EN(port)); 137662306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_FAKE(port)); 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_ci /* ensure wake events of sleepwalk logic are not latched */ 137962306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_LINE_WAKEUP); 138062306a36Sopenharmony_ci value &= ~UTMIP_LINE_WAKEUP_EN(port); 138162306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_LINE_WAKEUP); 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_ci /* disable wake event triggers of sleepwalk logic */ 138462306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); 138562306a36Sopenharmony_ci value &= ~UTMIP_WAKE_VAL(port, ~0); 138662306a36Sopenharmony_ci value |= UTMIP_WAKE_VAL_NONE(port); 138762306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci /* power down the line state detectors of the pad */ 139062306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_USB_AO); 139162306a36Sopenharmony_ci value |= (USBOP_VAL_PD(port) | USBON_VAL_PD(port)); 139262306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_USB_AO); 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci /* save state per speed */ 139562306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SAVED_STATE(port)); 139662306a36Sopenharmony_ci value &= ~SPEED(port, ~0); 139762306a36Sopenharmony_ci 139862306a36Sopenharmony_ci switch (speed) { 139962306a36Sopenharmony_ci case USB_SPEED_HIGH: 140062306a36Sopenharmony_ci value |= UTMI_HS(port); 140162306a36Sopenharmony_ci break; 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_ci case USB_SPEED_FULL: 140462306a36Sopenharmony_ci value |= UTMI_FS(port); 140562306a36Sopenharmony_ci break; 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_ci case USB_SPEED_LOW: 140862306a36Sopenharmony_ci value |= UTMI_LS(port); 140962306a36Sopenharmony_ci break; 141062306a36Sopenharmony_ci 141162306a36Sopenharmony_ci default: 141262306a36Sopenharmony_ci value |= UTMI_RST(port); 141362306a36Sopenharmony_ci break; 141462306a36Sopenharmony_ci } 141562306a36Sopenharmony_ci 141662306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SAVED_STATE(port)); 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_ci /* enable the trigger of the sleepwalk logic */ 141962306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEPWALK_CFG(port)); 142062306a36Sopenharmony_ci value |= UTMIP_LINEVAL_WALK_EN(port); 142162306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEPWALK_CFG(port)); 142262306a36Sopenharmony_ci 142362306a36Sopenharmony_ci /* 142462306a36Sopenharmony_ci * Reset the walk pointer and clear the alarm of the sleepwalk logic, 142562306a36Sopenharmony_ci * as well as capture the configuration of the USB2.0 pad. 142662306a36Sopenharmony_ci */ 142762306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_TRIGGERS); 142862306a36Sopenharmony_ci value |= UTMIP_CLR_WALK_PTR(port) | UTMIP_CLR_WAKE_ALARM(port) | UTMIP_CAP_CFG(port); 142962306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_TRIGGERS); 143062306a36Sopenharmony_ci 143162306a36Sopenharmony_ci /* program electrical parameters read from XUSB PADCTL */ 143262306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_TERM_PAD_CFG); 143362306a36Sopenharmony_ci value &= ~(TCTRL_VAL(~0) | PCTRL_VAL(~0)); 143462306a36Sopenharmony_ci value |= (TCTRL_VAL(tctrl) | PCTRL_VAL(pctrl)); 143562306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_TERM_PAD_CFG); 143662306a36Sopenharmony_ci 143762306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_PAD_CFGX(port)); 143862306a36Sopenharmony_ci value &= ~RPD_CTRL_PX(~0); 143962306a36Sopenharmony_ci value |= RPD_CTRL_PX(rpd_ctrl); 144062306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_PAD_CFGX(port)); 144162306a36Sopenharmony_ci 144262306a36Sopenharmony_ci /* 144362306a36Sopenharmony_ci * Set up the pull-ups and pull-downs of the signals during the four 144462306a36Sopenharmony_ci * stages of sleepwalk. If a device is connected, program sleepwalk 144562306a36Sopenharmony_ci * logic to maintain a J and keep driving K upon seeing remote wake. 144662306a36Sopenharmony_ci */ 144762306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_SLEEPWALK_PX(port)); 144862306a36Sopenharmony_ci value = UTMIP_USBOP_RPD_A | UTMIP_USBOP_RPD_B | UTMIP_USBOP_RPD_C | UTMIP_USBOP_RPD_D; 144962306a36Sopenharmony_ci value |= UTMIP_USBON_RPD_A | UTMIP_USBON_RPD_B | UTMIP_USBON_RPD_C | UTMIP_USBON_RPD_D; 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_ci switch (speed) { 145262306a36Sopenharmony_ci case USB_SPEED_HIGH: 145362306a36Sopenharmony_ci case USB_SPEED_FULL: 145462306a36Sopenharmony_ci /* J state: D+/D- = high/low, K state: D+/D- = low/high */ 145562306a36Sopenharmony_ci value |= UTMIP_HIGHZ_A; 145662306a36Sopenharmony_ci value |= UTMIP_AP_A; 145762306a36Sopenharmony_ci value |= UTMIP_AN_B | UTMIP_AN_C | UTMIP_AN_D; 145862306a36Sopenharmony_ci break; 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ci case USB_SPEED_LOW: 146162306a36Sopenharmony_ci /* J state: D+/D- = low/high, K state: D+/D- = high/low */ 146262306a36Sopenharmony_ci value |= UTMIP_HIGHZ_A; 146362306a36Sopenharmony_ci value |= UTMIP_AN_A; 146462306a36Sopenharmony_ci value |= UTMIP_AP_B | UTMIP_AP_C | UTMIP_AP_D; 146562306a36Sopenharmony_ci break; 146662306a36Sopenharmony_ci 146762306a36Sopenharmony_ci default: 146862306a36Sopenharmony_ci value |= UTMIP_HIGHZ_A | UTMIP_HIGHZ_B | UTMIP_HIGHZ_C | UTMIP_HIGHZ_D; 146962306a36Sopenharmony_ci break; 147062306a36Sopenharmony_ci } 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_SLEEPWALK_PX(port)); 147362306a36Sopenharmony_ci 147462306a36Sopenharmony_ci /* power up the line state detectors of the pad */ 147562306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_USB_AO); 147662306a36Sopenharmony_ci value &= ~(USBOP_VAL_PD(port) | USBON_VAL_PD(port)); 147762306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_USB_AO); 147862306a36Sopenharmony_ci 147962306a36Sopenharmony_ci usleep_range(50, 100); 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_ci /* switch the electric control of the USB2.0 pad to PMC */ 148262306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); 148362306a36Sopenharmony_ci value |= UTMIP_FSLS_USE_PMC(port) | UTMIP_PCTRL_USE_PMC(port) | UTMIP_TCTRL_USE_PMC(port); 148462306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); 148562306a36Sopenharmony_ci 148662306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG1); 148762306a36Sopenharmony_ci value |= UTMIP_RPD_CTRL_USE_PMC_PX(port) | UTMIP_RPU_SWITC_LOW_USE_PMC_PX(port); 148862306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG1); 148962306a36Sopenharmony_ci 149062306a36Sopenharmony_ci /* set the wake signaling trigger events */ 149162306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); 149262306a36Sopenharmony_ci value &= ~UTMIP_WAKE_VAL(port, ~0); 149362306a36Sopenharmony_ci value |= UTMIP_WAKE_VAL_ANY(port); 149462306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); 149562306a36Sopenharmony_ci 149662306a36Sopenharmony_ci /* enable the wake detection */ 149762306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); 149862306a36Sopenharmony_ci value |= UTMIP_MASTER_ENABLE(port); 149962306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); 150062306a36Sopenharmony_ci 150162306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_LINE_WAKEUP); 150262306a36Sopenharmony_ci value |= UTMIP_LINE_WAKEUP_EN(port); 150362306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_LINE_WAKEUP); 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci return 0; 150662306a36Sopenharmony_ci} 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_cistatic int tegra210_pmc_utmi_disable_phy_sleepwalk(struct tegra_xusb_lane *lane) 150962306a36Sopenharmony_ci{ 151062306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 151162306a36Sopenharmony_ci struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl); 151262306a36Sopenharmony_ci unsigned int port = lane->index; 151362306a36Sopenharmony_ci u32 value; 151462306a36Sopenharmony_ci 151562306a36Sopenharmony_ci if (!priv->regmap) 151662306a36Sopenharmony_ci return -EOPNOTSUPP; 151762306a36Sopenharmony_ci 151862306a36Sopenharmony_ci /* disable the wake detection */ 151962306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); 152062306a36Sopenharmony_ci value &= ~UTMIP_MASTER_ENABLE(port); 152162306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); 152262306a36Sopenharmony_ci 152362306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_LINE_WAKEUP); 152462306a36Sopenharmony_ci value &= ~UTMIP_LINE_WAKEUP_EN(port); 152562306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_LINE_WAKEUP); 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ci /* switch the electric control of the USB2.0 pad to XUSB or USB2 */ 152862306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); 152962306a36Sopenharmony_ci value &= ~(UTMIP_FSLS_USE_PMC(port) | UTMIP_PCTRL_USE_PMC(port) | 153062306a36Sopenharmony_ci UTMIP_TCTRL_USE_PMC(port)); 153162306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); 153262306a36Sopenharmony_ci 153362306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG1); 153462306a36Sopenharmony_ci value &= ~(UTMIP_RPD_CTRL_USE_PMC_PX(port) | UTMIP_RPU_SWITC_LOW_USE_PMC_PX(port)); 153562306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG1); 153662306a36Sopenharmony_ci 153762306a36Sopenharmony_ci /* disable wake event triggers of sleepwalk logic */ 153862306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); 153962306a36Sopenharmony_ci value &= ~UTMIP_WAKE_VAL(port, ~0); 154062306a36Sopenharmony_ci value |= UTMIP_WAKE_VAL_NONE(port); 154162306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_SLEEP_CFG(port)); 154262306a36Sopenharmony_ci 154362306a36Sopenharmony_ci /* power down the line state detectors of the port */ 154462306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_USB_AO); 154562306a36Sopenharmony_ci value |= (USBOP_VAL_PD(port) | USBON_VAL_PD(port)); 154662306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_USB_AO); 154762306a36Sopenharmony_ci 154862306a36Sopenharmony_ci /* clear alarm of the sleepwalk logic */ 154962306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_TRIGGERS); 155062306a36Sopenharmony_ci value |= UTMIP_CLR_WAKE_ALARM(port); 155162306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_TRIGGERS); 155262306a36Sopenharmony_ci 155362306a36Sopenharmony_ci return 0; 155462306a36Sopenharmony_ci} 155562306a36Sopenharmony_ci 155662306a36Sopenharmony_cistatic int tegra210_pmc_hsic_enable_phy_sleepwalk(struct tegra_xusb_lane *lane, 155762306a36Sopenharmony_ci enum usb_device_speed speed) 155862306a36Sopenharmony_ci{ 155962306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 156062306a36Sopenharmony_ci struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl); 156162306a36Sopenharmony_ci u32 value; 156262306a36Sopenharmony_ci 156362306a36Sopenharmony_ci if (!priv->regmap) 156462306a36Sopenharmony_ci return -EOPNOTSUPP; 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_ci /* ensure sleepwalk logic is disabled */ 156762306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEP_CFG); 156862306a36Sopenharmony_ci value &= ~UHSIC_MASTER_ENABLE; 156962306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEP_CFG); 157062306a36Sopenharmony_ci 157162306a36Sopenharmony_ci /* ensure sleepwalk logics are in low power mode */ 157262306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_MASTER_CONFIG); 157362306a36Sopenharmony_ci value |= UHSIC_PWR; 157462306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_MASTER_CONFIG); 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_ci /* set debounce time */ 157762306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_USB_DEBOUNCE_DEL); 157862306a36Sopenharmony_ci value &= ~UHSIC_LINE_DEB_CNT(~0); 157962306a36Sopenharmony_ci value |= UHSIC_LINE_DEB_CNT(0x1); 158062306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_USB_DEBOUNCE_DEL); 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_ci /* ensure fake events of sleepwalk logic are desiabled */ 158362306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UHSIC_FAKE); 158462306a36Sopenharmony_ci value &= ~(UHSIC_FAKE_STROBE_VAL | UHSIC_FAKE_DATA_VAL | 158562306a36Sopenharmony_ci UHSIC_FAKE_STROBE_EN | UHSIC_FAKE_DATA_EN); 158662306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UHSIC_FAKE); 158762306a36Sopenharmony_ci 158862306a36Sopenharmony_ci /* ensure wake events of sleepwalk logic are not latched */ 158962306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_LINE_WAKEUP); 159062306a36Sopenharmony_ci value &= ~UHSIC_LINE_WAKEUP_EN; 159162306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_LINE_WAKEUP); 159262306a36Sopenharmony_ci 159362306a36Sopenharmony_ci /* disable wake event triggers of sleepwalk logic */ 159462306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEP_CFG); 159562306a36Sopenharmony_ci value &= ~UHSIC_WAKE_VAL(~0); 159662306a36Sopenharmony_ci value |= UHSIC_WAKE_VAL_NONE; 159762306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEP_CFG); 159862306a36Sopenharmony_ci 159962306a36Sopenharmony_ci /* power down the line state detectors of the port */ 160062306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_USB_AO); 160162306a36Sopenharmony_ci value |= STROBE_VAL_PD | DATA0_VAL_PD | DATA1_VAL_PD; 160262306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_USB_AO); 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_ci /* save state, HSIC always comes up as HS */ 160562306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UHSIC_SAVED_STATE); 160662306a36Sopenharmony_ci value &= ~UHSIC_MODE(~0); 160762306a36Sopenharmony_ci value |= UHSIC_HS; 160862306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UHSIC_SAVED_STATE); 160962306a36Sopenharmony_ci 161062306a36Sopenharmony_ci /* enable the trigger of the sleepwalk logic */ 161162306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEPWALK_CFG); 161262306a36Sopenharmony_ci value |= UHSIC_WAKE_WALK_EN | UHSIC_LINEVAL_WALK_EN; 161362306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEPWALK_CFG); 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_ci /* 161662306a36Sopenharmony_ci * Reset the walk pointer and clear the alarm of the sleepwalk logic, 161762306a36Sopenharmony_ci * as well as capture the configuration of the USB2.0 port. 161862306a36Sopenharmony_ci */ 161962306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_TRIGGERS); 162062306a36Sopenharmony_ci value |= UHSIC_CLR_WALK_PTR | UHSIC_CLR_WAKE_ALARM; 162162306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_TRIGGERS); 162262306a36Sopenharmony_ci 162362306a36Sopenharmony_ci /* 162462306a36Sopenharmony_ci * Set up the pull-ups and pull-downs of the signals during the four 162562306a36Sopenharmony_ci * stages of sleepwalk. Maintain a HSIC IDLE and keep driving HSIC 162662306a36Sopenharmony_ci * RESUME upon remote wake. 162762306a36Sopenharmony_ci */ 162862306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEPWALK_P0); 162962306a36Sopenharmony_ci value = UHSIC_DATA0_RPD_A | UHSIC_DATA0_RPU_B | UHSIC_DATA0_RPU_C | UHSIC_DATA0_RPU_D | 163062306a36Sopenharmony_ci UHSIC_STROBE_RPU_A | UHSIC_STROBE_RPD_B | UHSIC_STROBE_RPD_C | UHSIC_STROBE_RPD_D; 163162306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEPWALK_P0); 163262306a36Sopenharmony_ci 163362306a36Sopenharmony_ci /* power up the line state detectors of the port */ 163462306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_USB_AO); 163562306a36Sopenharmony_ci value &= ~(STROBE_VAL_PD | DATA0_VAL_PD | DATA1_VAL_PD); 163662306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_USB_AO); 163762306a36Sopenharmony_ci 163862306a36Sopenharmony_ci usleep_range(50, 100); 163962306a36Sopenharmony_ci 164062306a36Sopenharmony_ci /* set the wake signaling trigger events */ 164162306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEP_CFG); 164262306a36Sopenharmony_ci value &= ~UHSIC_WAKE_VAL(~0); 164362306a36Sopenharmony_ci value |= UHSIC_WAKE_VAL_SD10; 164462306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEP_CFG); 164562306a36Sopenharmony_ci 164662306a36Sopenharmony_ci /* enable the wake detection */ 164762306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEP_CFG); 164862306a36Sopenharmony_ci value |= UHSIC_MASTER_ENABLE; 164962306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEP_CFG); 165062306a36Sopenharmony_ci 165162306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_LINE_WAKEUP); 165262306a36Sopenharmony_ci value |= UHSIC_LINE_WAKEUP_EN; 165362306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_LINE_WAKEUP); 165462306a36Sopenharmony_ci 165562306a36Sopenharmony_ci return 0; 165662306a36Sopenharmony_ci} 165762306a36Sopenharmony_ci 165862306a36Sopenharmony_cistatic int tegra210_pmc_hsic_disable_phy_sleepwalk(struct tegra_xusb_lane *lane) 165962306a36Sopenharmony_ci{ 166062306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 166162306a36Sopenharmony_ci struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl); 166262306a36Sopenharmony_ci u32 value; 166362306a36Sopenharmony_ci 166462306a36Sopenharmony_ci if (!priv->regmap) 166562306a36Sopenharmony_ci return -EOPNOTSUPP; 166662306a36Sopenharmony_ci 166762306a36Sopenharmony_ci /* disable the wake detection */ 166862306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEP_CFG); 166962306a36Sopenharmony_ci value &= ~UHSIC_MASTER_ENABLE; 167062306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEP_CFG); 167162306a36Sopenharmony_ci 167262306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_LINE_WAKEUP); 167362306a36Sopenharmony_ci value &= ~UHSIC_LINE_WAKEUP_EN; 167462306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_LINE_WAKEUP); 167562306a36Sopenharmony_ci 167662306a36Sopenharmony_ci /* disable wake event triggers of sleepwalk logic */ 167762306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UHSIC_SLEEP_CFG); 167862306a36Sopenharmony_ci value &= ~UHSIC_WAKE_VAL(~0); 167962306a36Sopenharmony_ci value |= UHSIC_WAKE_VAL_NONE; 168062306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UHSIC_SLEEP_CFG); 168162306a36Sopenharmony_ci 168262306a36Sopenharmony_ci /* power down the line state detectors of the port */ 168362306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_USB_AO); 168462306a36Sopenharmony_ci value |= STROBE_VAL_PD | DATA0_VAL_PD | DATA1_VAL_PD; 168562306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_USB_AO); 168662306a36Sopenharmony_ci 168762306a36Sopenharmony_ci /* clear alarm of the sleepwalk logic */ 168862306a36Sopenharmony_ci value = padctl_pmc_readl(priv, PMC_UTMIP_UHSIC_TRIGGERS); 168962306a36Sopenharmony_ci value |= UHSIC_CLR_WAKE_ALARM; 169062306a36Sopenharmony_ci padctl_pmc_writel(priv, value, PMC_UTMIP_UHSIC_TRIGGERS); 169162306a36Sopenharmony_ci 169262306a36Sopenharmony_ci return 0; 169362306a36Sopenharmony_ci} 169462306a36Sopenharmony_ci 169562306a36Sopenharmony_cistatic int tegra210_usb3_set_lfps_detect(struct tegra_xusb_padctl *padctl, 169662306a36Sopenharmony_ci unsigned int index, bool enable) 169762306a36Sopenharmony_ci{ 169862306a36Sopenharmony_ci struct tegra_xusb_port *port; 169962306a36Sopenharmony_ci struct tegra_xusb_lane *lane; 170062306a36Sopenharmony_ci u32 value, offset; 170162306a36Sopenharmony_ci 170262306a36Sopenharmony_ci port = tegra_xusb_find_port(padctl, "usb3", index); 170362306a36Sopenharmony_ci if (!port) 170462306a36Sopenharmony_ci return -ENODEV; 170562306a36Sopenharmony_ci 170662306a36Sopenharmony_ci lane = port->lane; 170762306a36Sopenharmony_ci 170862306a36Sopenharmony_ci if (lane->pad == padctl->pcie) 170962306a36Sopenharmony_ci offset = XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL1(lane->index); 171062306a36Sopenharmony_ci else 171162306a36Sopenharmony_ci offset = XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL1; 171262306a36Sopenharmony_ci 171362306a36Sopenharmony_ci value = padctl_readl(padctl, offset); 171462306a36Sopenharmony_ci 171562306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_MASK << 171662306a36Sopenharmony_ci XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_SHIFT) | 171762306a36Sopenharmony_ci XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_TERM_EN | 171862306a36Sopenharmony_ci XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_MODE_OVRD); 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ci if (!enable) { 172162306a36Sopenharmony_ci value |= (XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_VAL << 172262306a36Sopenharmony_ci XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_IDLE_MODE_SHIFT) | 172362306a36Sopenharmony_ci XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_TERM_EN | 172462306a36Sopenharmony_ci XUSB_PADCTL_UPHY_MISC_PAD_CTL1_AUX_RX_MODE_OVRD; 172562306a36Sopenharmony_ci } 172662306a36Sopenharmony_ci 172762306a36Sopenharmony_ci padctl_writel(padctl, value, offset); 172862306a36Sopenharmony_ci 172962306a36Sopenharmony_ci return 0; 173062306a36Sopenharmony_ci} 173162306a36Sopenharmony_ci 173262306a36Sopenharmony_ci#define TEGRA210_LANE(_name, _offset, _shift, _mask, _type) \ 173362306a36Sopenharmony_ci { \ 173462306a36Sopenharmony_ci .name = _name, \ 173562306a36Sopenharmony_ci .offset = _offset, \ 173662306a36Sopenharmony_ci .shift = _shift, \ 173762306a36Sopenharmony_ci .mask = _mask, \ 173862306a36Sopenharmony_ci .num_funcs = ARRAY_SIZE(tegra210_##_type##_functions), \ 173962306a36Sopenharmony_ci .funcs = tegra210_##_type##_functions, \ 174062306a36Sopenharmony_ci } 174162306a36Sopenharmony_ci 174262306a36Sopenharmony_cistatic const char *tegra210_usb2_functions[] = { 174362306a36Sopenharmony_ci "snps", 174462306a36Sopenharmony_ci "xusb", 174562306a36Sopenharmony_ci "uart" 174662306a36Sopenharmony_ci}; 174762306a36Sopenharmony_ci 174862306a36Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra210_usb2_lanes[] = { 174962306a36Sopenharmony_ci TEGRA210_LANE("usb2-0", 0x004, 0, 0x3, usb2), 175062306a36Sopenharmony_ci TEGRA210_LANE("usb2-1", 0x004, 2, 0x3, usb2), 175162306a36Sopenharmony_ci TEGRA210_LANE("usb2-2", 0x004, 4, 0x3, usb2), 175262306a36Sopenharmony_ci TEGRA210_LANE("usb2-3", 0x004, 6, 0x3, usb2), 175362306a36Sopenharmony_ci}; 175462306a36Sopenharmony_ci 175562306a36Sopenharmony_cistatic struct tegra_xusb_lane * 175662306a36Sopenharmony_citegra210_usb2_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 175762306a36Sopenharmony_ci unsigned int index) 175862306a36Sopenharmony_ci{ 175962306a36Sopenharmony_ci struct tegra_xusb_usb2_lane *usb2; 176062306a36Sopenharmony_ci int err; 176162306a36Sopenharmony_ci 176262306a36Sopenharmony_ci usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL); 176362306a36Sopenharmony_ci if (!usb2) 176462306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 176562306a36Sopenharmony_ci 176662306a36Sopenharmony_ci INIT_LIST_HEAD(&usb2->base.list); 176762306a36Sopenharmony_ci usb2->base.soc = &pad->soc->lanes[index]; 176862306a36Sopenharmony_ci usb2->base.index = index; 176962306a36Sopenharmony_ci usb2->base.pad = pad; 177062306a36Sopenharmony_ci usb2->base.np = np; 177162306a36Sopenharmony_ci 177262306a36Sopenharmony_ci err = tegra_xusb_lane_parse_dt(&usb2->base, np); 177362306a36Sopenharmony_ci if (err < 0) { 177462306a36Sopenharmony_ci kfree(usb2); 177562306a36Sopenharmony_ci return ERR_PTR(err); 177662306a36Sopenharmony_ci } 177762306a36Sopenharmony_ci 177862306a36Sopenharmony_ci return &usb2->base; 177962306a36Sopenharmony_ci} 178062306a36Sopenharmony_ci 178162306a36Sopenharmony_cistatic void tegra210_usb2_lane_remove(struct tegra_xusb_lane *lane) 178262306a36Sopenharmony_ci{ 178362306a36Sopenharmony_ci struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane); 178462306a36Sopenharmony_ci 178562306a36Sopenharmony_ci kfree(usb2); 178662306a36Sopenharmony_ci} 178762306a36Sopenharmony_ci 178862306a36Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra210_usb2_lane_ops = { 178962306a36Sopenharmony_ci .probe = tegra210_usb2_lane_probe, 179062306a36Sopenharmony_ci .remove = tegra210_usb2_lane_remove, 179162306a36Sopenharmony_ci .enable_phy_sleepwalk = tegra210_pmc_utmi_enable_phy_sleepwalk, 179262306a36Sopenharmony_ci .disable_phy_sleepwalk = tegra210_pmc_utmi_disable_phy_sleepwalk, 179362306a36Sopenharmony_ci .enable_phy_wake = tegra210_utmi_enable_phy_wake, 179462306a36Sopenharmony_ci .disable_phy_wake = tegra210_utmi_disable_phy_wake, 179562306a36Sopenharmony_ci .remote_wake_detected = tegra210_utmi_phy_remote_wake_detected, 179662306a36Sopenharmony_ci}; 179762306a36Sopenharmony_ci 179862306a36Sopenharmony_cistatic int tegra210_usb2_phy_init(struct phy *phy) 179962306a36Sopenharmony_ci{ 180062306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 180162306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 180262306a36Sopenharmony_ci unsigned int index = lane->index; 180362306a36Sopenharmony_ci struct tegra_xusb_usb2_port *port; 180462306a36Sopenharmony_ci int err; 180562306a36Sopenharmony_ci u32 value; 180662306a36Sopenharmony_ci 180762306a36Sopenharmony_ci port = tegra_xusb_find_usb2_port(padctl, index); 180862306a36Sopenharmony_ci if (!port) { 180962306a36Sopenharmony_ci dev_err(&phy->dev, "no port found for USB2 lane %u\n", index); 181062306a36Sopenharmony_ci return -ENODEV; 181162306a36Sopenharmony_ci } 181262306a36Sopenharmony_ci 181362306a36Sopenharmony_ci if (port->supply && port->mode == USB_DR_MODE_HOST) { 181462306a36Sopenharmony_ci err = regulator_enable(port->supply); 181562306a36Sopenharmony_ci if (err) 181662306a36Sopenharmony_ci return err; 181762306a36Sopenharmony_ci } 181862306a36Sopenharmony_ci 181962306a36Sopenharmony_ci mutex_lock(&padctl->lock); 182062306a36Sopenharmony_ci 182162306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_PAD_MUX); 182262306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_MASK << 182362306a36Sopenharmony_ci XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_SHIFT); 182462306a36Sopenharmony_ci value |= XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_XUSB << 182562306a36Sopenharmony_ci XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_SHIFT; 182662306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_PAD_MUX); 182762306a36Sopenharmony_ci 182862306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 182962306a36Sopenharmony_ci 183062306a36Sopenharmony_ci return 0; 183162306a36Sopenharmony_ci} 183262306a36Sopenharmony_ci 183362306a36Sopenharmony_cistatic int tegra210_usb2_phy_exit(struct phy *phy) 183462306a36Sopenharmony_ci{ 183562306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 183662306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 183762306a36Sopenharmony_ci struct tegra_xusb_usb2_port *port; 183862306a36Sopenharmony_ci int err; 183962306a36Sopenharmony_ci 184062306a36Sopenharmony_ci port = tegra_xusb_find_usb2_port(padctl, lane->index); 184162306a36Sopenharmony_ci if (!port) { 184262306a36Sopenharmony_ci dev_err(&phy->dev, "no port found for USB2 lane %u\n", lane->index); 184362306a36Sopenharmony_ci return -ENODEV; 184462306a36Sopenharmony_ci } 184562306a36Sopenharmony_ci 184662306a36Sopenharmony_ci if (port->supply && port->mode == USB_DR_MODE_HOST) { 184762306a36Sopenharmony_ci err = regulator_disable(port->supply); 184862306a36Sopenharmony_ci if (err) 184962306a36Sopenharmony_ci return err; 185062306a36Sopenharmony_ci } 185162306a36Sopenharmony_ci 185262306a36Sopenharmony_ci return 0; 185362306a36Sopenharmony_ci} 185462306a36Sopenharmony_ci 185562306a36Sopenharmony_cistatic int tegra210_xusb_padctl_vbus_override(struct tegra_xusb_padctl *padctl, 185662306a36Sopenharmony_ci bool status) 185762306a36Sopenharmony_ci{ 185862306a36Sopenharmony_ci u32 value; 185962306a36Sopenharmony_ci 186062306a36Sopenharmony_ci dev_dbg(padctl->dev, "%s vbus override\n", status ? "set" : "clear"); 186162306a36Sopenharmony_ci 186262306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_VBUS_ID); 186362306a36Sopenharmony_ci 186462306a36Sopenharmony_ci if (status) { 186562306a36Sopenharmony_ci value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON; 186662306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK << 186762306a36Sopenharmony_ci XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT); 186862306a36Sopenharmony_ci value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING << 186962306a36Sopenharmony_ci XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT; 187062306a36Sopenharmony_ci } else { 187162306a36Sopenharmony_ci value &= ~XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON; 187262306a36Sopenharmony_ci } 187362306a36Sopenharmony_ci 187462306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_VBUS_ID); 187562306a36Sopenharmony_ci 187662306a36Sopenharmony_ci return 0; 187762306a36Sopenharmony_ci} 187862306a36Sopenharmony_ci 187962306a36Sopenharmony_cistatic int tegra210_xusb_padctl_id_override(struct tegra_xusb_padctl *padctl, 188062306a36Sopenharmony_ci bool status) 188162306a36Sopenharmony_ci{ 188262306a36Sopenharmony_ci u32 value; 188362306a36Sopenharmony_ci 188462306a36Sopenharmony_ci dev_dbg(padctl->dev, "%s id override\n", status ? "set" : "clear"); 188562306a36Sopenharmony_ci 188662306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_VBUS_ID); 188762306a36Sopenharmony_ci 188862306a36Sopenharmony_ci if (status) { 188962306a36Sopenharmony_ci if (value & XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON) { 189062306a36Sopenharmony_ci value &= ~XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_VBUS_ON; 189162306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_VBUS_ID); 189262306a36Sopenharmony_ci usleep_range(1000, 2000); 189362306a36Sopenharmony_ci 189462306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_VBUS_ID); 189562306a36Sopenharmony_ci } 189662306a36Sopenharmony_ci 189762306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK << 189862306a36Sopenharmony_ci XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT); 189962306a36Sopenharmony_ci value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_GROUNDED << 190062306a36Sopenharmony_ci XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT; 190162306a36Sopenharmony_ci } else { 190262306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_MASK << 190362306a36Sopenharmony_ci XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT); 190462306a36Sopenharmony_ci value |= XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_FLOATING << 190562306a36Sopenharmony_ci XUSB_PADCTL_USB2_VBUS_ID_OVERRIDE_SHIFT; 190662306a36Sopenharmony_ci } 190762306a36Sopenharmony_ci 190862306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_VBUS_ID); 190962306a36Sopenharmony_ci 191062306a36Sopenharmony_ci return 0; 191162306a36Sopenharmony_ci} 191262306a36Sopenharmony_ci 191362306a36Sopenharmony_cistatic int tegra210_usb2_phy_set_mode(struct phy *phy, enum phy_mode mode, 191462306a36Sopenharmony_ci int submode) 191562306a36Sopenharmony_ci{ 191662306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 191762306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 191862306a36Sopenharmony_ci struct tegra_xusb_usb2_port *port = tegra_xusb_find_usb2_port(padctl, 191962306a36Sopenharmony_ci lane->index); 192062306a36Sopenharmony_ci int err = 0; 192162306a36Sopenharmony_ci 192262306a36Sopenharmony_ci mutex_lock(&padctl->lock); 192362306a36Sopenharmony_ci 192462306a36Sopenharmony_ci dev_dbg(&port->base.dev, "%s: mode %d", __func__, mode); 192562306a36Sopenharmony_ci 192662306a36Sopenharmony_ci if (mode == PHY_MODE_USB_OTG) { 192762306a36Sopenharmony_ci if (submode == USB_ROLE_HOST) { 192862306a36Sopenharmony_ci tegra210_xusb_padctl_id_override(padctl, true); 192962306a36Sopenharmony_ci 193062306a36Sopenharmony_ci err = regulator_enable(port->supply); 193162306a36Sopenharmony_ci } else if (submode == USB_ROLE_DEVICE) { 193262306a36Sopenharmony_ci tegra210_xusb_padctl_vbus_override(padctl, true); 193362306a36Sopenharmony_ci } else if (submode == USB_ROLE_NONE) { 193462306a36Sopenharmony_ci /* 193562306a36Sopenharmony_ci * When port is peripheral only or role transitions to 193662306a36Sopenharmony_ci * USB_ROLE_NONE from USB_ROLE_DEVICE, regulator is not 193762306a36Sopenharmony_ci * be enabled. 193862306a36Sopenharmony_ci */ 193962306a36Sopenharmony_ci if (regulator_is_enabled(port->supply)) 194062306a36Sopenharmony_ci regulator_disable(port->supply); 194162306a36Sopenharmony_ci 194262306a36Sopenharmony_ci tegra210_xusb_padctl_id_override(padctl, false); 194362306a36Sopenharmony_ci tegra210_xusb_padctl_vbus_override(padctl, false); 194462306a36Sopenharmony_ci } 194562306a36Sopenharmony_ci } 194662306a36Sopenharmony_ci 194762306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 194862306a36Sopenharmony_ci 194962306a36Sopenharmony_ci return err; 195062306a36Sopenharmony_ci} 195162306a36Sopenharmony_ci 195262306a36Sopenharmony_cistatic int tegra210_usb2_phy_power_on(struct phy *phy) 195362306a36Sopenharmony_ci{ 195462306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 195562306a36Sopenharmony_ci struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane); 195662306a36Sopenharmony_ci struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad); 195762306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 195862306a36Sopenharmony_ci struct tegra210_xusb_padctl *priv; 195962306a36Sopenharmony_ci struct tegra_xusb_usb2_port *port; 196062306a36Sopenharmony_ci unsigned int index = lane->index; 196162306a36Sopenharmony_ci u32 value; 196262306a36Sopenharmony_ci int err; 196362306a36Sopenharmony_ci 196462306a36Sopenharmony_ci port = tegra_xusb_find_usb2_port(padctl, index); 196562306a36Sopenharmony_ci if (!port) { 196662306a36Sopenharmony_ci dev_err(&phy->dev, "no port found for USB2 lane %u\n", index); 196762306a36Sopenharmony_ci return -ENODEV; 196862306a36Sopenharmony_ci } 196962306a36Sopenharmony_ci 197062306a36Sopenharmony_ci priv = to_tegra210_xusb_padctl(padctl); 197162306a36Sopenharmony_ci 197262306a36Sopenharmony_ci mutex_lock(&padctl->lock); 197362306a36Sopenharmony_ci 197462306a36Sopenharmony_ci if (port->usb3_port_fake != -1) { 197562306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); 197662306a36Sopenharmony_ci value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK( 197762306a36Sopenharmony_ci port->usb3_port_fake); 197862306a36Sopenharmony_ci value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP( 197962306a36Sopenharmony_ci port->usb3_port_fake, index); 198062306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); 198162306a36Sopenharmony_ci 198262306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 198362306a36Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN( 198462306a36Sopenharmony_ci port->usb3_port_fake); 198562306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 198662306a36Sopenharmony_ci 198762306a36Sopenharmony_ci usleep_range(100, 200); 198862306a36Sopenharmony_ci 198962306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 199062306a36Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY( 199162306a36Sopenharmony_ci port->usb3_port_fake); 199262306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 199362306a36Sopenharmony_ci 199462306a36Sopenharmony_ci usleep_range(100, 200); 199562306a36Sopenharmony_ci 199662306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 199762306a36Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN( 199862306a36Sopenharmony_ci port->usb3_port_fake); 199962306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 200062306a36Sopenharmony_ci } 200162306a36Sopenharmony_ci 200262306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 200362306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK << 200462306a36Sopenharmony_ci XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) | 200562306a36Sopenharmony_ci (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK << 200662306a36Sopenharmony_ci XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT)); 200762306a36Sopenharmony_ci value |= (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL << 200862306a36Sopenharmony_ci XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT); 200962306a36Sopenharmony_ci 201062306a36Sopenharmony_ci if (tegra_sku_info.revision < TEGRA_REVISION_A02) 201162306a36Sopenharmony_ci value |= 201262306a36Sopenharmony_ci (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_VAL << 201362306a36Sopenharmony_ci XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT); 201462306a36Sopenharmony_ci 201562306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 201662306a36Sopenharmony_ci 201762306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_PORT_CAP); 201862306a36Sopenharmony_ci value &= ~XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_MASK(index); 201962306a36Sopenharmony_ci if (port->mode == USB_DR_MODE_UNKNOWN) 202062306a36Sopenharmony_ci value |= XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_DISABLED(index); 202162306a36Sopenharmony_ci else if (port->mode == USB_DR_MODE_PERIPHERAL) 202262306a36Sopenharmony_ci value |= XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_DEVICE(index); 202362306a36Sopenharmony_ci else if (port->mode == USB_DR_MODE_HOST) 202462306a36Sopenharmony_ci value |= XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_HOST(index); 202562306a36Sopenharmony_ci else if (port->mode == USB_DR_MODE_OTG) 202662306a36Sopenharmony_ci value |= XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_OTG(index); 202762306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_PORT_CAP); 202862306a36Sopenharmony_ci 202962306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index)); 203062306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK << 203162306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT) | 203262306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD | 203362306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 | 203462306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI); 203562306a36Sopenharmony_ci value |= (priv->fuse.hs_curr_level[index] + 203662306a36Sopenharmony_ci usb2->hs_curr_level_offset) << 203762306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT; 203862306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index)); 203962306a36Sopenharmony_ci 204062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index)); 204162306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK << 204262306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) | 204362306a36Sopenharmony_ci (XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_MASK << 204462306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_SHIFT) | 204562306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR | 204662306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_OVRD | 204762306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_OVRD); 204862306a36Sopenharmony_ci value |= (priv->fuse.hs_term_range_adj << 204962306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) | 205062306a36Sopenharmony_ci (priv->fuse.rpd_ctrl << 205162306a36Sopenharmony_ci XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_SHIFT); 205262306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index)); 205362306a36Sopenharmony_ci 205462306a36Sopenharmony_ci value = padctl_readl(padctl, 205562306a36Sopenharmony_ci XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(index)); 205662306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_MASK << 205762306a36Sopenharmony_ci XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_SHIFT); 205862306a36Sopenharmony_ci if (port->mode == USB_DR_MODE_HOST) 205962306a36Sopenharmony_ci value |= XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_FIX18; 206062306a36Sopenharmony_ci else 206162306a36Sopenharmony_ci value |= 206262306a36Sopenharmony_ci XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_VAL << 206362306a36Sopenharmony_ci XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL1_VREG_LEV_SHIFT; 206462306a36Sopenharmony_ci padctl_writel(padctl, value, 206562306a36Sopenharmony_ci XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(index)); 206662306a36Sopenharmony_ci 206762306a36Sopenharmony_ci if (pad->enable > 0) { 206862306a36Sopenharmony_ci pad->enable++; 206962306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 207062306a36Sopenharmony_ci return 0; 207162306a36Sopenharmony_ci } 207262306a36Sopenharmony_ci 207362306a36Sopenharmony_ci err = clk_prepare_enable(pad->clk); 207462306a36Sopenharmony_ci if (err) 207562306a36Sopenharmony_ci goto out; 207662306a36Sopenharmony_ci 207762306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); 207862306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_MASK << 207962306a36Sopenharmony_ci XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_SHIFT) | 208062306a36Sopenharmony_ci (XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_MASK << 208162306a36Sopenharmony_ci XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_SHIFT)); 208262306a36Sopenharmony_ci value |= (XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_VAL << 208362306a36Sopenharmony_ci XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_SHIFT) | 208462306a36Sopenharmony_ci (XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_VAL << 208562306a36Sopenharmony_ci XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_SHIFT); 208662306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); 208762306a36Sopenharmony_ci 208862306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 208962306a36Sopenharmony_ci value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD; 209062306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 209162306a36Sopenharmony_ci 209262306a36Sopenharmony_ci udelay(1); 209362306a36Sopenharmony_ci 209462306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); 209562306a36Sopenharmony_ci value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL1_PD_TRK; 209662306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL1); 209762306a36Sopenharmony_ci 209862306a36Sopenharmony_ci udelay(50); 209962306a36Sopenharmony_ci 210062306a36Sopenharmony_ci clk_disable_unprepare(pad->clk); 210162306a36Sopenharmony_ci 210262306a36Sopenharmony_ci pad->enable++; 210362306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 210462306a36Sopenharmony_ci 210562306a36Sopenharmony_ci return 0; 210662306a36Sopenharmony_ci 210762306a36Sopenharmony_ciout: 210862306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 210962306a36Sopenharmony_ci return err; 211062306a36Sopenharmony_ci} 211162306a36Sopenharmony_ci 211262306a36Sopenharmony_cistatic int tegra210_usb2_phy_power_off(struct phy *phy) 211362306a36Sopenharmony_ci{ 211462306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 211562306a36Sopenharmony_ci struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad); 211662306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 211762306a36Sopenharmony_ci struct tegra_xusb_usb2_port *port; 211862306a36Sopenharmony_ci u32 value; 211962306a36Sopenharmony_ci 212062306a36Sopenharmony_ci port = tegra_xusb_find_usb2_port(padctl, lane->index); 212162306a36Sopenharmony_ci if (!port) { 212262306a36Sopenharmony_ci dev_err(&phy->dev, "no port found for USB2 lane %u\n", 212362306a36Sopenharmony_ci lane->index); 212462306a36Sopenharmony_ci return -ENODEV; 212562306a36Sopenharmony_ci } 212662306a36Sopenharmony_ci 212762306a36Sopenharmony_ci mutex_lock(&padctl->lock); 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_ci if (port->usb3_port_fake != -1) { 213062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 213162306a36Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY( 213262306a36Sopenharmony_ci port->usb3_port_fake); 213362306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 213462306a36Sopenharmony_ci 213562306a36Sopenharmony_ci usleep_range(100, 200); 213662306a36Sopenharmony_ci 213762306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 213862306a36Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN( 213962306a36Sopenharmony_ci port->usb3_port_fake); 214062306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 214162306a36Sopenharmony_ci 214262306a36Sopenharmony_ci usleep_range(250, 350); 214362306a36Sopenharmony_ci 214462306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 214562306a36Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN( 214662306a36Sopenharmony_ci port->usb3_port_fake); 214762306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 214862306a36Sopenharmony_ci 214962306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); 215062306a36Sopenharmony_ci value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(port->usb3_port_fake, 215162306a36Sopenharmony_ci XUSB_PADCTL_SS_PORT_MAP_PORT_DISABLED); 215262306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); 215362306a36Sopenharmony_ci } 215462306a36Sopenharmony_ci 215562306a36Sopenharmony_ci if (WARN_ON(pad->enable == 0)) 215662306a36Sopenharmony_ci goto out; 215762306a36Sopenharmony_ci 215862306a36Sopenharmony_ci if (--pad->enable > 0) 215962306a36Sopenharmony_ci goto out; 216062306a36Sopenharmony_ci 216162306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 216262306a36Sopenharmony_ci value |= XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD; 216362306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); 216462306a36Sopenharmony_ci 216562306a36Sopenharmony_ciout: 216662306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 216762306a36Sopenharmony_ci return 0; 216862306a36Sopenharmony_ci} 216962306a36Sopenharmony_ci 217062306a36Sopenharmony_cistatic const struct phy_ops tegra210_usb2_phy_ops = { 217162306a36Sopenharmony_ci .init = tegra210_usb2_phy_init, 217262306a36Sopenharmony_ci .exit = tegra210_usb2_phy_exit, 217362306a36Sopenharmony_ci .power_on = tegra210_usb2_phy_power_on, 217462306a36Sopenharmony_ci .power_off = tegra210_usb2_phy_power_off, 217562306a36Sopenharmony_ci .set_mode = tegra210_usb2_phy_set_mode, 217662306a36Sopenharmony_ci .owner = THIS_MODULE, 217762306a36Sopenharmony_ci}; 217862306a36Sopenharmony_ci 217962306a36Sopenharmony_cistatic struct tegra_xusb_pad * 218062306a36Sopenharmony_citegra210_usb2_pad_probe(struct tegra_xusb_padctl *padctl, 218162306a36Sopenharmony_ci const struct tegra_xusb_pad_soc *soc, 218262306a36Sopenharmony_ci struct device_node *np) 218362306a36Sopenharmony_ci{ 218462306a36Sopenharmony_ci struct tegra_xusb_usb2_pad *usb2; 218562306a36Sopenharmony_ci struct tegra_xusb_pad *pad; 218662306a36Sopenharmony_ci int err; 218762306a36Sopenharmony_ci 218862306a36Sopenharmony_ci usb2 = kzalloc(sizeof(*usb2), GFP_KERNEL); 218962306a36Sopenharmony_ci if (!usb2) 219062306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 219162306a36Sopenharmony_ci 219262306a36Sopenharmony_ci pad = &usb2->base; 219362306a36Sopenharmony_ci pad->ops = &tegra210_usb2_lane_ops; 219462306a36Sopenharmony_ci pad->soc = soc; 219562306a36Sopenharmony_ci 219662306a36Sopenharmony_ci err = tegra_xusb_pad_init(pad, padctl, np); 219762306a36Sopenharmony_ci if (err < 0) { 219862306a36Sopenharmony_ci kfree(usb2); 219962306a36Sopenharmony_ci goto out; 220062306a36Sopenharmony_ci } 220162306a36Sopenharmony_ci 220262306a36Sopenharmony_ci usb2->clk = devm_clk_get(&pad->dev, "trk"); 220362306a36Sopenharmony_ci if (IS_ERR(usb2->clk)) { 220462306a36Sopenharmony_ci err = PTR_ERR(usb2->clk); 220562306a36Sopenharmony_ci dev_err(&pad->dev, "failed to get trk clock: %d\n", err); 220662306a36Sopenharmony_ci goto unregister; 220762306a36Sopenharmony_ci } 220862306a36Sopenharmony_ci 220962306a36Sopenharmony_ci err = tegra_xusb_pad_register(pad, &tegra210_usb2_phy_ops); 221062306a36Sopenharmony_ci if (err < 0) 221162306a36Sopenharmony_ci goto unregister; 221262306a36Sopenharmony_ci 221362306a36Sopenharmony_ci dev_set_drvdata(&pad->dev, pad); 221462306a36Sopenharmony_ci 221562306a36Sopenharmony_ci return pad; 221662306a36Sopenharmony_ci 221762306a36Sopenharmony_ciunregister: 221862306a36Sopenharmony_ci device_unregister(&pad->dev); 221962306a36Sopenharmony_ciout: 222062306a36Sopenharmony_ci return ERR_PTR(err); 222162306a36Sopenharmony_ci} 222262306a36Sopenharmony_ci 222362306a36Sopenharmony_cistatic void tegra210_usb2_pad_remove(struct tegra_xusb_pad *pad) 222462306a36Sopenharmony_ci{ 222562306a36Sopenharmony_ci struct tegra_xusb_usb2_pad *usb2 = to_usb2_pad(pad); 222662306a36Sopenharmony_ci 222762306a36Sopenharmony_ci kfree(usb2); 222862306a36Sopenharmony_ci} 222962306a36Sopenharmony_ci 223062306a36Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra210_usb2_ops = { 223162306a36Sopenharmony_ci .probe = tegra210_usb2_pad_probe, 223262306a36Sopenharmony_ci .remove = tegra210_usb2_pad_remove, 223362306a36Sopenharmony_ci}; 223462306a36Sopenharmony_ci 223562306a36Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra210_usb2_pad = { 223662306a36Sopenharmony_ci .name = "usb2", 223762306a36Sopenharmony_ci .num_lanes = ARRAY_SIZE(tegra210_usb2_lanes), 223862306a36Sopenharmony_ci .lanes = tegra210_usb2_lanes, 223962306a36Sopenharmony_ci .ops = &tegra210_usb2_ops, 224062306a36Sopenharmony_ci}; 224162306a36Sopenharmony_ci 224262306a36Sopenharmony_cistatic const char *tegra210_hsic_functions[] = { 224362306a36Sopenharmony_ci "snps", 224462306a36Sopenharmony_ci "xusb", 224562306a36Sopenharmony_ci}; 224662306a36Sopenharmony_ci 224762306a36Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra210_hsic_lanes[] = { 224862306a36Sopenharmony_ci TEGRA210_LANE("hsic-0", 0x004, 14, 0x1, hsic), 224962306a36Sopenharmony_ci}; 225062306a36Sopenharmony_ci 225162306a36Sopenharmony_cistatic struct tegra_xusb_lane * 225262306a36Sopenharmony_citegra210_hsic_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 225362306a36Sopenharmony_ci unsigned int index) 225462306a36Sopenharmony_ci{ 225562306a36Sopenharmony_ci struct tegra_xusb_hsic_lane *hsic; 225662306a36Sopenharmony_ci int err; 225762306a36Sopenharmony_ci 225862306a36Sopenharmony_ci hsic = kzalloc(sizeof(*hsic), GFP_KERNEL); 225962306a36Sopenharmony_ci if (!hsic) 226062306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 226162306a36Sopenharmony_ci 226262306a36Sopenharmony_ci INIT_LIST_HEAD(&hsic->base.list); 226362306a36Sopenharmony_ci hsic->base.soc = &pad->soc->lanes[index]; 226462306a36Sopenharmony_ci hsic->base.index = index; 226562306a36Sopenharmony_ci hsic->base.pad = pad; 226662306a36Sopenharmony_ci hsic->base.np = np; 226762306a36Sopenharmony_ci 226862306a36Sopenharmony_ci err = tegra_xusb_lane_parse_dt(&hsic->base, np); 226962306a36Sopenharmony_ci if (err < 0) { 227062306a36Sopenharmony_ci kfree(hsic); 227162306a36Sopenharmony_ci return ERR_PTR(err); 227262306a36Sopenharmony_ci } 227362306a36Sopenharmony_ci 227462306a36Sopenharmony_ci return &hsic->base; 227562306a36Sopenharmony_ci} 227662306a36Sopenharmony_ci 227762306a36Sopenharmony_cistatic void tegra210_hsic_lane_remove(struct tegra_xusb_lane *lane) 227862306a36Sopenharmony_ci{ 227962306a36Sopenharmony_ci struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane); 228062306a36Sopenharmony_ci 228162306a36Sopenharmony_ci kfree(hsic); 228262306a36Sopenharmony_ci} 228362306a36Sopenharmony_ci 228462306a36Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra210_hsic_lane_ops = { 228562306a36Sopenharmony_ci .probe = tegra210_hsic_lane_probe, 228662306a36Sopenharmony_ci .remove = tegra210_hsic_lane_remove, 228762306a36Sopenharmony_ci .enable_phy_sleepwalk = tegra210_pmc_hsic_enable_phy_sleepwalk, 228862306a36Sopenharmony_ci .disable_phy_sleepwalk = tegra210_pmc_hsic_disable_phy_sleepwalk, 228962306a36Sopenharmony_ci .enable_phy_wake = tegra210_hsic_enable_phy_wake, 229062306a36Sopenharmony_ci .disable_phy_wake = tegra210_hsic_disable_phy_wake, 229162306a36Sopenharmony_ci .remote_wake_detected = tegra210_hsic_phy_remote_wake_detected, 229262306a36Sopenharmony_ci}; 229362306a36Sopenharmony_ci 229462306a36Sopenharmony_cistatic int tegra210_hsic_phy_init(struct phy *phy) 229562306a36Sopenharmony_ci{ 229662306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 229762306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 229862306a36Sopenharmony_ci u32 value; 229962306a36Sopenharmony_ci 230062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_USB2_PAD_MUX); 230162306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_MASK << 230262306a36Sopenharmony_ci XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_SHIFT); 230362306a36Sopenharmony_ci value |= XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_XUSB << 230462306a36Sopenharmony_ci XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_SHIFT; 230562306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_USB2_PAD_MUX); 230662306a36Sopenharmony_ci 230762306a36Sopenharmony_ci return 0; 230862306a36Sopenharmony_ci} 230962306a36Sopenharmony_ci 231062306a36Sopenharmony_cistatic int tegra210_hsic_phy_exit(struct phy *phy) 231162306a36Sopenharmony_ci{ 231262306a36Sopenharmony_ci return 0; 231362306a36Sopenharmony_ci} 231462306a36Sopenharmony_ci 231562306a36Sopenharmony_cistatic int tegra210_hsic_phy_power_on(struct phy *phy) 231662306a36Sopenharmony_ci{ 231762306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 231862306a36Sopenharmony_ci struct tegra_xusb_hsic_lane *hsic = to_hsic_lane(lane); 231962306a36Sopenharmony_ci struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad); 232062306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 232162306a36Sopenharmony_ci unsigned int index = lane->index; 232262306a36Sopenharmony_ci u32 value; 232362306a36Sopenharmony_ci int err; 232462306a36Sopenharmony_ci 232562306a36Sopenharmony_ci err = regulator_enable(pad->supply); 232662306a36Sopenharmony_ci if (err) 232762306a36Sopenharmony_ci return err; 232862306a36Sopenharmony_ci 232962306a36Sopenharmony_ci padctl_writel(padctl, hsic->strobe_trim, 233062306a36Sopenharmony_ci XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL); 233162306a36Sopenharmony_ci 233262306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 233362306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_MASK << 233462306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_SHIFT); 233562306a36Sopenharmony_ci value |= (hsic->tx_rtune_p << 233662306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL1_TX_RTUNEP_SHIFT); 233762306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 233862306a36Sopenharmony_ci 233962306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL2(index)); 234062306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK << 234162306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) | 234262306a36Sopenharmony_ci (XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK << 234362306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT)); 234462306a36Sopenharmony_ci value |= (hsic->rx_strobe_trim << 234562306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT) | 234662306a36Sopenharmony_ci (hsic->rx_data_trim << 234762306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT); 234862306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL2(index)); 234962306a36Sopenharmony_ci 235062306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(index)); 235162306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA0 | 235262306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_RPU_DATA1 | 235362306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_RPU_STROBE | 235462306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA0 | 235562306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA1 | 235662306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_STROBE | 235762306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA0 | 235862306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA1 | 235962306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_STROBE | 236062306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA0 | 236162306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA1 | 236262306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_STROBE); 236362306a36Sopenharmony_ci value |= XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA0 | 236462306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_RPD_DATA1 | 236562306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_RPD_STROBE; 236662306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL0(index)); 236762306a36Sopenharmony_ci 236862306a36Sopenharmony_ci err = clk_prepare_enable(pad->clk); 236962306a36Sopenharmony_ci if (err) 237062306a36Sopenharmony_ci goto disable; 237162306a36Sopenharmony_ci 237262306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PAD_TRK_CTL); 237362306a36Sopenharmony_ci value &= ~((XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_MASK << 237462306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_SHIFT) | 237562306a36Sopenharmony_ci (XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_MASK << 237662306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_SHIFT)); 237762306a36Sopenharmony_ci value |= (XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_VAL << 237862306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_START_TIMER_SHIFT) | 237962306a36Sopenharmony_ci (XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_VAL << 238062306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_TRK_CTL_TRK_DONE_RESET_TIMER_SHIFT); 238162306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PAD_TRK_CTL); 238262306a36Sopenharmony_ci 238362306a36Sopenharmony_ci udelay(1); 238462306a36Sopenharmony_ci 238562306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PAD_TRK_CTL); 238662306a36Sopenharmony_ci value &= ~XUSB_PADCTL_HSIC_PAD_TRK_CTL_PD_TRK; 238762306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PAD_TRK_CTL); 238862306a36Sopenharmony_ci 238962306a36Sopenharmony_ci udelay(50); 239062306a36Sopenharmony_ci 239162306a36Sopenharmony_ci clk_disable_unprepare(pad->clk); 239262306a36Sopenharmony_ci 239362306a36Sopenharmony_ci return 0; 239462306a36Sopenharmony_ci 239562306a36Sopenharmony_cidisable: 239662306a36Sopenharmony_ci regulator_disable(pad->supply); 239762306a36Sopenharmony_ci return err; 239862306a36Sopenharmony_ci} 239962306a36Sopenharmony_ci 240062306a36Sopenharmony_cistatic int tegra210_hsic_phy_power_off(struct phy *phy) 240162306a36Sopenharmony_ci{ 240262306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 240362306a36Sopenharmony_ci struct tegra_xusb_hsic_pad *pad = to_hsic_pad(lane->pad); 240462306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 240562306a36Sopenharmony_ci unsigned int index = lane->index; 240662306a36Sopenharmony_ci u32 value; 240762306a36Sopenharmony_ci 240862306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(index)); 240962306a36Sopenharmony_ci value |= XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA0 | 241062306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_DATA1 | 241162306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_PD_RX_STROBE | 241262306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA0 | 241362306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_DATA1 | 241462306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_PD_ZI_STROBE | 241562306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA0 | 241662306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_DATA1 | 241762306a36Sopenharmony_ci XUSB_PADCTL_HSIC_PAD_CTL0_PD_TX_STROBE; 241862306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(index)); 241962306a36Sopenharmony_ci 242062306a36Sopenharmony_ci regulator_disable(pad->supply); 242162306a36Sopenharmony_ci 242262306a36Sopenharmony_ci return 0; 242362306a36Sopenharmony_ci} 242462306a36Sopenharmony_ci 242562306a36Sopenharmony_cistatic const struct phy_ops tegra210_hsic_phy_ops = { 242662306a36Sopenharmony_ci .init = tegra210_hsic_phy_init, 242762306a36Sopenharmony_ci .exit = tegra210_hsic_phy_exit, 242862306a36Sopenharmony_ci .power_on = tegra210_hsic_phy_power_on, 242962306a36Sopenharmony_ci .power_off = tegra210_hsic_phy_power_off, 243062306a36Sopenharmony_ci .owner = THIS_MODULE, 243162306a36Sopenharmony_ci}; 243262306a36Sopenharmony_ci 243362306a36Sopenharmony_cistatic struct tegra_xusb_pad * 243462306a36Sopenharmony_citegra210_hsic_pad_probe(struct tegra_xusb_padctl *padctl, 243562306a36Sopenharmony_ci const struct tegra_xusb_pad_soc *soc, 243662306a36Sopenharmony_ci struct device_node *np) 243762306a36Sopenharmony_ci{ 243862306a36Sopenharmony_ci struct tegra_xusb_hsic_pad *hsic; 243962306a36Sopenharmony_ci struct tegra_xusb_pad *pad; 244062306a36Sopenharmony_ci int err; 244162306a36Sopenharmony_ci 244262306a36Sopenharmony_ci hsic = kzalloc(sizeof(*hsic), GFP_KERNEL); 244362306a36Sopenharmony_ci if (!hsic) 244462306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 244562306a36Sopenharmony_ci 244662306a36Sopenharmony_ci pad = &hsic->base; 244762306a36Sopenharmony_ci pad->ops = &tegra210_hsic_lane_ops; 244862306a36Sopenharmony_ci pad->soc = soc; 244962306a36Sopenharmony_ci 245062306a36Sopenharmony_ci err = tegra_xusb_pad_init(pad, padctl, np); 245162306a36Sopenharmony_ci if (err < 0) { 245262306a36Sopenharmony_ci kfree(hsic); 245362306a36Sopenharmony_ci goto out; 245462306a36Sopenharmony_ci } 245562306a36Sopenharmony_ci 245662306a36Sopenharmony_ci hsic->clk = devm_clk_get(&pad->dev, "trk"); 245762306a36Sopenharmony_ci if (IS_ERR(hsic->clk)) { 245862306a36Sopenharmony_ci err = PTR_ERR(hsic->clk); 245962306a36Sopenharmony_ci dev_err(&pad->dev, "failed to get trk clock: %d\n", err); 246062306a36Sopenharmony_ci goto unregister; 246162306a36Sopenharmony_ci } 246262306a36Sopenharmony_ci 246362306a36Sopenharmony_ci err = tegra_xusb_pad_register(pad, &tegra210_hsic_phy_ops); 246462306a36Sopenharmony_ci if (err < 0) 246562306a36Sopenharmony_ci goto unregister; 246662306a36Sopenharmony_ci 246762306a36Sopenharmony_ci dev_set_drvdata(&pad->dev, pad); 246862306a36Sopenharmony_ci 246962306a36Sopenharmony_ci return pad; 247062306a36Sopenharmony_ci 247162306a36Sopenharmony_ciunregister: 247262306a36Sopenharmony_ci device_unregister(&pad->dev); 247362306a36Sopenharmony_ciout: 247462306a36Sopenharmony_ci return ERR_PTR(err); 247562306a36Sopenharmony_ci} 247662306a36Sopenharmony_ci 247762306a36Sopenharmony_cistatic void tegra210_hsic_pad_remove(struct tegra_xusb_pad *pad) 247862306a36Sopenharmony_ci{ 247962306a36Sopenharmony_ci struct tegra_xusb_hsic_pad *hsic = to_hsic_pad(pad); 248062306a36Sopenharmony_ci 248162306a36Sopenharmony_ci kfree(hsic); 248262306a36Sopenharmony_ci} 248362306a36Sopenharmony_ci 248462306a36Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra210_hsic_ops = { 248562306a36Sopenharmony_ci .probe = tegra210_hsic_pad_probe, 248662306a36Sopenharmony_ci .remove = tegra210_hsic_pad_remove, 248762306a36Sopenharmony_ci}; 248862306a36Sopenharmony_ci 248962306a36Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra210_hsic_pad = { 249062306a36Sopenharmony_ci .name = "hsic", 249162306a36Sopenharmony_ci .num_lanes = ARRAY_SIZE(tegra210_hsic_lanes), 249262306a36Sopenharmony_ci .lanes = tegra210_hsic_lanes, 249362306a36Sopenharmony_ci .ops = &tegra210_hsic_ops, 249462306a36Sopenharmony_ci}; 249562306a36Sopenharmony_ci 249662306a36Sopenharmony_cistatic void tegra210_uphy_lane_iddq_enable(struct tegra_xusb_lane *lane) 249762306a36Sopenharmony_ci{ 249862306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 249962306a36Sopenharmony_ci u32 value; 250062306a36Sopenharmony_ci 250162306a36Sopenharmony_ci value = padctl_readl(padctl, lane->soc->regs.misc_ctl2); 250262306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ_OVRD; 250362306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ_OVRD; 250462306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_PWR_OVRD; 250562306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_PWR_OVRD; 250662306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ; 250762306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_MASK; 250862306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_VAL; 250962306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ; 251062306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_MASK; 251162306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_VAL; 251262306a36Sopenharmony_ci padctl_writel(padctl, value, lane->soc->regs.misc_ctl2); 251362306a36Sopenharmony_ci} 251462306a36Sopenharmony_ci 251562306a36Sopenharmony_cistatic void tegra210_uphy_lane_iddq_disable(struct tegra_xusb_lane *lane) 251662306a36Sopenharmony_ci{ 251762306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 251862306a36Sopenharmony_ci u32 value; 251962306a36Sopenharmony_ci 252062306a36Sopenharmony_ci value = padctl_readl(padctl, lane->soc->regs.misc_ctl2); 252162306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ_OVRD; 252262306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ_OVRD; 252362306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_PWR_OVRD; 252462306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_PWR_OVRD; 252562306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_IDDQ; 252662306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_MASK; 252762306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_TX_SLEEP_VAL; 252862306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_IDDQ; 252962306a36Sopenharmony_ci value &= ~XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_MASK; 253062306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_MISC_PAD_CTL2_RX_SLEEP_VAL; 253162306a36Sopenharmony_ci padctl_writel(padctl, value, lane->soc->regs.misc_ctl2); 253262306a36Sopenharmony_ci} 253362306a36Sopenharmony_ci 253462306a36Sopenharmony_ci#define TEGRA210_UPHY_LANE(_name, _offset, _shift, _mask, _type, _misc) \ 253562306a36Sopenharmony_ci { \ 253662306a36Sopenharmony_ci .name = _name, \ 253762306a36Sopenharmony_ci .offset = _offset, \ 253862306a36Sopenharmony_ci .shift = _shift, \ 253962306a36Sopenharmony_ci .mask = _mask, \ 254062306a36Sopenharmony_ci .num_funcs = ARRAY_SIZE(tegra210_##_type##_functions), \ 254162306a36Sopenharmony_ci .funcs = tegra210_##_type##_functions, \ 254262306a36Sopenharmony_ci .regs.misc_ctl2 = _misc, \ 254362306a36Sopenharmony_ci } 254462306a36Sopenharmony_ci 254562306a36Sopenharmony_cistatic const char *tegra210_pcie_functions[] = { 254662306a36Sopenharmony_ci "pcie-x1", 254762306a36Sopenharmony_ci "usb3-ss", 254862306a36Sopenharmony_ci "sata", 254962306a36Sopenharmony_ci "pcie-x4", 255062306a36Sopenharmony_ci}; 255162306a36Sopenharmony_ci 255262306a36Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra210_pcie_lanes[] = { 255362306a36Sopenharmony_ci TEGRA210_UPHY_LANE("pcie-0", 0x028, 12, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(0)), 255462306a36Sopenharmony_ci TEGRA210_UPHY_LANE("pcie-1", 0x028, 14, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(1)), 255562306a36Sopenharmony_ci TEGRA210_UPHY_LANE("pcie-2", 0x028, 16, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(2)), 255662306a36Sopenharmony_ci TEGRA210_UPHY_LANE("pcie-3", 0x028, 18, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(3)), 255762306a36Sopenharmony_ci TEGRA210_UPHY_LANE("pcie-4", 0x028, 20, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(4)), 255862306a36Sopenharmony_ci TEGRA210_UPHY_LANE("pcie-5", 0x028, 22, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(5)), 255962306a36Sopenharmony_ci TEGRA210_UPHY_LANE("pcie-6", 0x028, 24, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_PX_CTL2(6)), 256062306a36Sopenharmony_ci}; 256162306a36Sopenharmony_ci 256262306a36Sopenharmony_cistatic struct tegra_xusb_usb3_port * 256362306a36Sopenharmony_citegra210_lane_to_usb3_port(struct tegra_xusb_lane *lane) 256462306a36Sopenharmony_ci{ 256562306a36Sopenharmony_ci int port; 256662306a36Sopenharmony_ci 256762306a36Sopenharmony_ci if (!lane || !lane->pad || !lane->pad->padctl) 256862306a36Sopenharmony_ci return NULL; 256962306a36Sopenharmony_ci 257062306a36Sopenharmony_ci port = tegra210_usb3_lane_map(lane); 257162306a36Sopenharmony_ci if (port < 0) 257262306a36Sopenharmony_ci return NULL; 257362306a36Sopenharmony_ci 257462306a36Sopenharmony_ci return tegra_xusb_find_usb3_port(lane->pad->padctl, port); 257562306a36Sopenharmony_ci} 257662306a36Sopenharmony_ci 257762306a36Sopenharmony_cistatic int tegra210_usb3_phy_power_on(struct phy *phy) 257862306a36Sopenharmony_ci{ 257962306a36Sopenharmony_ci struct device *dev = &phy->dev; 258062306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 258162306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 258262306a36Sopenharmony_ci struct tegra_xusb_usb3_port *usb3 = tegra210_lane_to_usb3_port(lane); 258362306a36Sopenharmony_ci unsigned int index; 258462306a36Sopenharmony_ci u32 value; 258562306a36Sopenharmony_ci 258662306a36Sopenharmony_ci if (!usb3) { 258762306a36Sopenharmony_ci dev_err(dev, "no USB3 port found for lane %u\n", lane->index); 258862306a36Sopenharmony_ci return -ENODEV; 258962306a36Sopenharmony_ci } 259062306a36Sopenharmony_ci 259162306a36Sopenharmony_ci index = usb3->base.index; 259262306a36Sopenharmony_ci 259362306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); 259462306a36Sopenharmony_ci 259562306a36Sopenharmony_ci if (!usb3->internal) 259662306a36Sopenharmony_ci value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index); 259762306a36Sopenharmony_ci else 259862306a36Sopenharmony_ci value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index); 259962306a36Sopenharmony_ci 260062306a36Sopenharmony_ci value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(index); 260162306a36Sopenharmony_ci value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(index, usb3->port); 260262306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); 260362306a36Sopenharmony_ci 260462306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(index)); 260562306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_MASK << 260662306a36Sopenharmony_ci XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT); 260762306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_VAL << 260862306a36Sopenharmony_ci XUSB_PADCTL_UPHY_USB3_PAD_ECTL1_TX_TERM_CTRL_SHIFT; 260962306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_USB3_PADX_ECTL1(index)); 261062306a36Sopenharmony_ci 261162306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_USB3_PADX_ECTL2(index)); 261262306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_MASK << 261362306a36Sopenharmony_ci XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_SHIFT); 261462306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_VAL << 261562306a36Sopenharmony_ci XUSB_PADCTL_UPHY_USB3_PAD_ECTL2_RX_CTLE_SHIFT; 261662306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_USB3_PADX_ECTL2(index)); 261762306a36Sopenharmony_ci 261862306a36Sopenharmony_ci padctl_writel(padctl, XUSB_PADCTL_UPHY_USB3_PAD_ECTL3_RX_DFE_VAL, 261962306a36Sopenharmony_ci XUSB_PADCTL_UPHY_USB3_PADX_ECTL3(index)); 262062306a36Sopenharmony_ci 262162306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_UPHY_USB3_PADX_ECTL4(index)); 262262306a36Sopenharmony_ci value &= ~(XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_MASK << 262362306a36Sopenharmony_ci XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_SHIFT); 262462306a36Sopenharmony_ci value |= XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_VAL << 262562306a36Sopenharmony_ci XUSB_PADCTL_UPHY_USB3_PAD_ECTL4_RX_CDR_CTRL_SHIFT; 262662306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_UPHY_USB3_PADX_ECTL4(index)); 262762306a36Sopenharmony_ci 262862306a36Sopenharmony_ci padctl_writel(padctl, XUSB_PADCTL_UPHY_USB3_PAD_ECTL6_RX_EQ_CTRL_H_VAL, 262962306a36Sopenharmony_ci XUSB_PADCTL_UPHY_USB3_PADX_ECTL6(index)); 263062306a36Sopenharmony_ci 263162306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 263262306a36Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN(index); 263362306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 263462306a36Sopenharmony_ci 263562306a36Sopenharmony_ci usleep_range(100, 200); 263662306a36Sopenharmony_ci 263762306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 263862306a36Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(index); 263962306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 264062306a36Sopenharmony_ci 264162306a36Sopenharmony_ci usleep_range(100, 200); 264262306a36Sopenharmony_ci 264362306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 264462306a36Sopenharmony_ci value &= ~XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(index); 264562306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 264662306a36Sopenharmony_ci 264762306a36Sopenharmony_ci return 0; 264862306a36Sopenharmony_ci} 264962306a36Sopenharmony_ci 265062306a36Sopenharmony_cistatic int tegra210_usb3_phy_power_off(struct phy *phy) 265162306a36Sopenharmony_ci{ 265262306a36Sopenharmony_ci struct device *dev = &phy->dev; 265362306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 265462306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 265562306a36Sopenharmony_ci struct tegra_xusb_usb3_port *usb3 = tegra210_lane_to_usb3_port(lane); 265662306a36Sopenharmony_ci unsigned int index; 265762306a36Sopenharmony_ci u32 value; 265862306a36Sopenharmony_ci 265962306a36Sopenharmony_ci if (!usb3) { 266062306a36Sopenharmony_ci dev_err(dev, "no USB3 port found for lane %u\n", lane->index); 266162306a36Sopenharmony_ci return -ENODEV; 266262306a36Sopenharmony_ci } 266362306a36Sopenharmony_ci 266462306a36Sopenharmony_ci index = usb3->base.index; 266562306a36Sopenharmony_ci 266662306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 266762306a36Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN_EARLY(index); 266862306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 266962306a36Sopenharmony_ci 267062306a36Sopenharmony_ci usleep_range(100, 200); 267162306a36Sopenharmony_ci 267262306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 267362306a36Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_CLAMP_EN(index); 267462306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 267562306a36Sopenharmony_ci 267662306a36Sopenharmony_ci usleep_range(250, 350); 267762306a36Sopenharmony_ci 267862306a36Sopenharmony_ci value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1); 267962306a36Sopenharmony_ci value |= XUSB_PADCTL_ELPG_PROGRAM1_SSPX_ELPG_VCORE_DOWN(index); 268062306a36Sopenharmony_ci padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1); 268162306a36Sopenharmony_ci 268262306a36Sopenharmony_ci return 0; 268362306a36Sopenharmony_ci} 268462306a36Sopenharmony_cistatic struct tegra_xusb_lane * 268562306a36Sopenharmony_citegra210_pcie_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 268662306a36Sopenharmony_ci unsigned int index) 268762306a36Sopenharmony_ci{ 268862306a36Sopenharmony_ci struct tegra_xusb_pcie_lane *pcie; 268962306a36Sopenharmony_ci int err; 269062306a36Sopenharmony_ci 269162306a36Sopenharmony_ci pcie = kzalloc(sizeof(*pcie), GFP_KERNEL); 269262306a36Sopenharmony_ci if (!pcie) 269362306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 269462306a36Sopenharmony_ci 269562306a36Sopenharmony_ci INIT_LIST_HEAD(&pcie->base.list); 269662306a36Sopenharmony_ci pcie->base.soc = &pad->soc->lanes[index]; 269762306a36Sopenharmony_ci pcie->base.index = index; 269862306a36Sopenharmony_ci pcie->base.pad = pad; 269962306a36Sopenharmony_ci pcie->base.np = np; 270062306a36Sopenharmony_ci 270162306a36Sopenharmony_ci err = tegra_xusb_lane_parse_dt(&pcie->base, np); 270262306a36Sopenharmony_ci if (err < 0) { 270362306a36Sopenharmony_ci kfree(pcie); 270462306a36Sopenharmony_ci return ERR_PTR(err); 270562306a36Sopenharmony_ci } 270662306a36Sopenharmony_ci 270762306a36Sopenharmony_ci return &pcie->base; 270862306a36Sopenharmony_ci} 270962306a36Sopenharmony_ci 271062306a36Sopenharmony_cistatic void tegra210_pcie_lane_remove(struct tegra_xusb_lane *lane) 271162306a36Sopenharmony_ci{ 271262306a36Sopenharmony_ci struct tegra_xusb_pcie_lane *pcie = to_pcie_lane(lane); 271362306a36Sopenharmony_ci 271462306a36Sopenharmony_ci kfree(pcie); 271562306a36Sopenharmony_ci} 271662306a36Sopenharmony_ci 271762306a36Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra210_pcie_lane_ops = { 271862306a36Sopenharmony_ci .probe = tegra210_pcie_lane_probe, 271962306a36Sopenharmony_ci .remove = tegra210_pcie_lane_remove, 272062306a36Sopenharmony_ci .iddq_enable = tegra210_uphy_lane_iddq_enable, 272162306a36Sopenharmony_ci .iddq_disable = tegra210_uphy_lane_iddq_disable, 272262306a36Sopenharmony_ci .enable_phy_sleepwalk = tegra210_usb3_enable_phy_sleepwalk, 272362306a36Sopenharmony_ci .disable_phy_sleepwalk = tegra210_usb3_disable_phy_sleepwalk, 272462306a36Sopenharmony_ci .enable_phy_wake = tegra210_usb3_enable_phy_wake, 272562306a36Sopenharmony_ci .disable_phy_wake = tegra210_usb3_disable_phy_wake, 272662306a36Sopenharmony_ci .remote_wake_detected = tegra210_usb3_phy_remote_wake_detected, 272762306a36Sopenharmony_ci}; 272862306a36Sopenharmony_ci 272962306a36Sopenharmony_cistatic int tegra210_pcie_phy_init(struct phy *phy) 273062306a36Sopenharmony_ci{ 273162306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 273262306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 273362306a36Sopenharmony_ci 273462306a36Sopenharmony_ci mutex_lock(&padctl->lock); 273562306a36Sopenharmony_ci 273662306a36Sopenharmony_ci tegra210_uphy_init(padctl); 273762306a36Sopenharmony_ci 273862306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 273962306a36Sopenharmony_ci 274062306a36Sopenharmony_ci return 0; 274162306a36Sopenharmony_ci} 274262306a36Sopenharmony_ci 274362306a36Sopenharmony_cistatic int tegra210_pcie_phy_power_on(struct phy *phy) 274462306a36Sopenharmony_ci{ 274562306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 274662306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 274762306a36Sopenharmony_ci int err = 0; 274862306a36Sopenharmony_ci 274962306a36Sopenharmony_ci mutex_lock(&padctl->lock); 275062306a36Sopenharmony_ci 275162306a36Sopenharmony_ci if (tegra_xusb_lane_check(lane, "usb3-ss")) 275262306a36Sopenharmony_ci err = tegra210_usb3_phy_power_on(phy); 275362306a36Sopenharmony_ci 275462306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 275562306a36Sopenharmony_ci return err; 275662306a36Sopenharmony_ci} 275762306a36Sopenharmony_ci 275862306a36Sopenharmony_cistatic int tegra210_pcie_phy_power_off(struct phy *phy) 275962306a36Sopenharmony_ci{ 276062306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 276162306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 276262306a36Sopenharmony_ci int err = 0; 276362306a36Sopenharmony_ci 276462306a36Sopenharmony_ci mutex_lock(&padctl->lock); 276562306a36Sopenharmony_ci 276662306a36Sopenharmony_ci if (tegra_xusb_lane_check(lane, "usb3-ss")) 276762306a36Sopenharmony_ci err = tegra210_usb3_phy_power_off(phy); 276862306a36Sopenharmony_ci 276962306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 277062306a36Sopenharmony_ci return err; 277162306a36Sopenharmony_ci} 277262306a36Sopenharmony_ci 277362306a36Sopenharmony_cistatic const struct phy_ops tegra210_pcie_phy_ops = { 277462306a36Sopenharmony_ci .init = tegra210_pcie_phy_init, 277562306a36Sopenharmony_ci .power_on = tegra210_pcie_phy_power_on, 277662306a36Sopenharmony_ci .power_off = tegra210_pcie_phy_power_off, 277762306a36Sopenharmony_ci .owner = THIS_MODULE, 277862306a36Sopenharmony_ci}; 277962306a36Sopenharmony_ci 278062306a36Sopenharmony_cistatic struct tegra_xusb_pad * 278162306a36Sopenharmony_citegra210_pcie_pad_probe(struct tegra_xusb_padctl *padctl, 278262306a36Sopenharmony_ci const struct tegra_xusb_pad_soc *soc, 278362306a36Sopenharmony_ci struct device_node *np) 278462306a36Sopenharmony_ci{ 278562306a36Sopenharmony_ci struct tegra_xusb_pcie_pad *pcie; 278662306a36Sopenharmony_ci struct tegra_xusb_pad *pad; 278762306a36Sopenharmony_ci int err; 278862306a36Sopenharmony_ci 278962306a36Sopenharmony_ci pcie = kzalloc(sizeof(*pcie), GFP_KERNEL); 279062306a36Sopenharmony_ci if (!pcie) 279162306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 279262306a36Sopenharmony_ci 279362306a36Sopenharmony_ci pad = &pcie->base; 279462306a36Sopenharmony_ci pad->ops = &tegra210_pcie_lane_ops; 279562306a36Sopenharmony_ci pad->soc = soc; 279662306a36Sopenharmony_ci 279762306a36Sopenharmony_ci err = tegra_xusb_pad_init(pad, padctl, np); 279862306a36Sopenharmony_ci if (err < 0) { 279962306a36Sopenharmony_ci kfree(pcie); 280062306a36Sopenharmony_ci goto out; 280162306a36Sopenharmony_ci } 280262306a36Sopenharmony_ci 280362306a36Sopenharmony_ci pcie->pll = devm_clk_get(&pad->dev, "pll"); 280462306a36Sopenharmony_ci if (IS_ERR(pcie->pll)) { 280562306a36Sopenharmony_ci err = PTR_ERR(pcie->pll); 280662306a36Sopenharmony_ci dev_err(&pad->dev, "failed to get PLL: %d\n", err); 280762306a36Sopenharmony_ci goto unregister; 280862306a36Sopenharmony_ci } 280962306a36Sopenharmony_ci 281062306a36Sopenharmony_ci pcie->rst = devm_reset_control_get(&pad->dev, "phy"); 281162306a36Sopenharmony_ci if (IS_ERR(pcie->rst)) { 281262306a36Sopenharmony_ci err = PTR_ERR(pcie->rst); 281362306a36Sopenharmony_ci dev_err(&pad->dev, "failed to get PCIe pad reset: %d\n", err); 281462306a36Sopenharmony_ci goto unregister; 281562306a36Sopenharmony_ci } 281662306a36Sopenharmony_ci 281762306a36Sopenharmony_ci err = tegra_xusb_pad_register(pad, &tegra210_pcie_phy_ops); 281862306a36Sopenharmony_ci if (err < 0) 281962306a36Sopenharmony_ci goto unregister; 282062306a36Sopenharmony_ci 282162306a36Sopenharmony_ci dev_set_drvdata(&pad->dev, pad); 282262306a36Sopenharmony_ci 282362306a36Sopenharmony_ci return pad; 282462306a36Sopenharmony_ci 282562306a36Sopenharmony_ciunregister: 282662306a36Sopenharmony_ci device_unregister(&pad->dev); 282762306a36Sopenharmony_ciout: 282862306a36Sopenharmony_ci return ERR_PTR(err); 282962306a36Sopenharmony_ci} 283062306a36Sopenharmony_ci 283162306a36Sopenharmony_cistatic void tegra210_pcie_pad_remove(struct tegra_xusb_pad *pad) 283262306a36Sopenharmony_ci{ 283362306a36Sopenharmony_ci struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(pad); 283462306a36Sopenharmony_ci 283562306a36Sopenharmony_ci kfree(pcie); 283662306a36Sopenharmony_ci} 283762306a36Sopenharmony_ci 283862306a36Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra210_pcie_ops = { 283962306a36Sopenharmony_ci .probe = tegra210_pcie_pad_probe, 284062306a36Sopenharmony_ci .remove = tegra210_pcie_pad_remove, 284162306a36Sopenharmony_ci}; 284262306a36Sopenharmony_ci 284362306a36Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra210_pcie_pad = { 284462306a36Sopenharmony_ci .name = "pcie", 284562306a36Sopenharmony_ci .num_lanes = ARRAY_SIZE(tegra210_pcie_lanes), 284662306a36Sopenharmony_ci .lanes = tegra210_pcie_lanes, 284762306a36Sopenharmony_ci .ops = &tegra210_pcie_ops, 284862306a36Sopenharmony_ci}; 284962306a36Sopenharmony_ci 285062306a36Sopenharmony_cistatic const struct tegra_xusb_lane_soc tegra210_sata_lanes[] = { 285162306a36Sopenharmony_ci TEGRA210_UPHY_LANE("sata-0", 0x028, 30, 0x3, pcie, XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL2), 285262306a36Sopenharmony_ci}; 285362306a36Sopenharmony_ci 285462306a36Sopenharmony_cistatic struct tegra_xusb_lane * 285562306a36Sopenharmony_citegra210_sata_lane_probe(struct tegra_xusb_pad *pad, struct device_node *np, 285662306a36Sopenharmony_ci unsigned int index) 285762306a36Sopenharmony_ci{ 285862306a36Sopenharmony_ci struct tegra_xusb_sata_lane *sata; 285962306a36Sopenharmony_ci int err; 286062306a36Sopenharmony_ci 286162306a36Sopenharmony_ci sata = kzalloc(sizeof(*sata), GFP_KERNEL); 286262306a36Sopenharmony_ci if (!sata) 286362306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 286462306a36Sopenharmony_ci 286562306a36Sopenharmony_ci INIT_LIST_HEAD(&sata->base.list); 286662306a36Sopenharmony_ci sata->base.soc = &pad->soc->lanes[index]; 286762306a36Sopenharmony_ci sata->base.index = index; 286862306a36Sopenharmony_ci sata->base.pad = pad; 286962306a36Sopenharmony_ci sata->base.np = np; 287062306a36Sopenharmony_ci 287162306a36Sopenharmony_ci err = tegra_xusb_lane_parse_dt(&sata->base, np); 287262306a36Sopenharmony_ci if (err < 0) { 287362306a36Sopenharmony_ci kfree(sata); 287462306a36Sopenharmony_ci return ERR_PTR(err); 287562306a36Sopenharmony_ci } 287662306a36Sopenharmony_ci 287762306a36Sopenharmony_ci return &sata->base; 287862306a36Sopenharmony_ci} 287962306a36Sopenharmony_ci 288062306a36Sopenharmony_cistatic void tegra210_sata_lane_remove(struct tegra_xusb_lane *lane) 288162306a36Sopenharmony_ci{ 288262306a36Sopenharmony_ci struct tegra_xusb_sata_lane *sata = to_sata_lane(lane); 288362306a36Sopenharmony_ci 288462306a36Sopenharmony_ci kfree(sata); 288562306a36Sopenharmony_ci} 288662306a36Sopenharmony_ci 288762306a36Sopenharmony_cistatic const struct tegra_xusb_lane_ops tegra210_sata_lane_ops = { 288862306a36Sopenharmony_ci .probe = tegra210_sata_lane_probe, 288962306a36Sopenharmony_ci .remove = tegra210_sata_lane_remove, 289062306a36Sopenharmony_ci .iddq_enable = tegra210_uphy_lane_iddq_enable, 289162306a36Sopenharmony_ci .iddq_disable = tegra210_uphy_lane_iddq_disable, 289262306a36Sopenharmony_ci .enable_phy_sleepwalk = tegra210_usb3_enable_phy_sleepwalk, 289362306a36Sopenharmony_ci .disable_phy_sleepwalk = tegra210_usb3_disable_phy_sleepwalk, 289462306a36Sopenharmony_ci .enable_phy_wake = tegra210_usb3_enable_phy_wake, 289562306a36Sopenharmony_ci .disable_phy_wake = tegra210_usb3_disable_phy_wake, 289662306a36Sopenharmony_ci .remote_wake_detected = tegra210_usb3_phy_remote_wake_detected, 289762306a36Sopenharmony_ci}; 289862306a36Sopenharmony_ci 289962306a36Sopenharmony_cistatic int tegra210_sata_phy_init(struct phy *phy) 290062306a36Sopenharmony_ci{ 290162306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 290262306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 290362306a36Sopenharmony_ci 290462306a36Sopenharmony_ci mutex_lock(&padctl->lock); 290562306a36Sopenharmony_ci 290662306a36Sopenharmony_ci tegra210_uphy_init(padctl); 290762306a36Sopenharmony_ci 290862306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 290962306a36Sopenharmony_ci return 0; 291062306a36Sopenharmony_ci} 291162306a36Sopenharmony_ci 291262306a36Sopenharmony_cistatic int tegra210_sata_phy_power_on(struct phy *phy) 291362306a36Sopenharmony_ci{ 291462306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 291562306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 291662306a36Sopenharmony_ci int err = 0; 291762306a36Sopenharmony_ci 291862306a36Sopenharmony_ci mutex_lock(&padctl->lock); 291962306a36Sopenharmony_ci 292062306a36Sopenharmony_ci if (tegra_xusb_lane_check(lane, "usb3-ss")) 292162306a36Sopenharmony_ci err = tegra210_usb3_phy_power_on(phy); 292262306a36Sopenharmony_ci 292362306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 292462306a36Sopenharmony_ci return err; 292562306a36Sopenharmony_ci} 292662306a36Sopenharmony_ci 292762306a36Sopenharmony_cistatic int tegra210_sata_phy_power_off(struct phy *phy) 292862306a36Sopenharmony_ci{ 292962306a36Sopenharmony_ci struct tegra_xusb_lane *lane = phy_get_drvdata(phy); 293062306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl = lane->pad->padctl; 293162306a36Sopenharmony_ci int err = 0; 293262306a36Sopenharmony_ci 293362306a36Sopenharmony_ci mutex_lock(&padctl->lock); 293462306a36Sopenharmony_ci 293562306a36Sopenharmony_ci if (tegra_xusb_lane_check(lane, "usb3-ss")) 293662306a36Sopenharmony_ci err = tegra210_usb3_phy_power_off(phy); 293762306a36Sopenharmony_ci 293862306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 293962306a36Sopenharmony_ci return err; 294062306a36Sopenharmony_ci} 294162306a36Sopenharmony_ci 294262306a36Sopenharmony_cistatic const struct phy_ops tegra210_sata_phy_ops = { 294362306a36Sopenharmony_ci .init = tegra210_sata_phy_init, 294462306a36Sopenharmony_ci .power_on = tegra210_sata_phy_power_on, 294562306a36Sopenharmony_ci .power_off = tegra210_sata_phy_power_off, 294662306a36Sopenharmony_ci .owner = THIS_MODULE, 294762306a36Sopenharmony_ci}; 294862306a36Sopenharmony_ci 294962306a36Sopenharmony_cistatic struct tegra_xusb_pad * 295062306a36Sopenharmony_citegra210_sata_pad_probe(struct tegra_xusb_padctl *padctl, 295162306a36Sopenharmony_ci const struct tegra_xusb_pad_soc *soc, 295262306a36Sopenharmony_ci struct device_node *np) 295362306a36Sopenharmony_ci{ 295462306a36Sopenharmony_ci struct tegra_xusb_sata_pad *sata; 295562306a36Sopenharmony_ci struct tegra_xusb_pad *pad; 295662306a36Sopenharmony_ci int err; 295762306a36Sopenharmony_ci 295862306a36Sopenharmony_ci sata = kzalloc(sizeof(*sata), GFP_KERNEL); 295962306a36Sopenharmony_ci if (!sata) 296062306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 296162306a36Sopenharmony_ci 296262306a36Sopenharmony_ci pad = &sata->base; 296362306a36Sopenharmony_ci pad->ops = &tegra210_sata_lane_ops; 296462306a36Sopenharmony_ci pad->soc = soc; 296562306a36Sopenharmony_ci 296662306a36Sopenharmony_ci err = tegra_xusb_pad_init(pad, padctl, np); 296762306a36Sopenharmony_ci if (err < 0) { 296862306a36Sopenharmony_ci kfree(sata); 296962306a36Sopenharmony_ci goto out; 297062306a36Sopenharmony_ci } 297162306a36Sopenharmony_ci 297262306a36Sopenharmony_ci sata->rst = devm_reset_control_get(&pad->dev, "phy"); 297362306a36Sopenharmony_ci if (IS_ERR(sata->rst)) { 297462306a36Sopenharmony_ci err = PTR_ERR(sata->rst); 297562306a36Sopenharmony_ci dev_err(&pad->dev, "failed to get SATA pad reset: %d\n", err); 297662306a36Sopenharmony_ci goto unregister; 297762306a36Sopenharmony_ci } 297862306a36Sopenharmony_ci 297962306a36Sopenharmony_ci err = tegra_xusb_pad_register(pad, &tegra210_sata_phy_ops); 298062306a36Sopenharmony_ci if (err < 0) 298162306a36Sopenharmony_ci goto unregister; 298262306a36Sopenharmony_ci 298362306a36Sopenharmony_ci dev_set_drvdata(&pad->dev, pad); 298462306a36Sopenharmony_ci 298562306a36Sopenharmony_ci return pad; 298662306a36Sopenharmony_ci 298762306a36Sopenharmony_ciunregister: 298862306a36Sopenharmony_ci device_unregister(&pad->dev); 298962306a36Sopenharmony_ciout: 299062306a36Sopenharmony_ci return ERR_PTR(err); 299162306a36Sopenharmony_ci} 299262306a36Sopenharmony_ci 299362306a36Sopenharmony_cistatic void tegra210_sata_pad_remove(struct tegra_xusb_pad *pad) 299462306a36Sopenharmony_ci{ 299562306a36Sopenharmony_ci struct tegra_xusb_sata_pad *sata = to_sata_pad(pad); 299662306a36Sopenharmony_ci 299762306a36Sopenharmony_ci kfree(sata); 299862306a36Sopenharmony_ci} 299962306a36Sopenharmony_ci 300062306a36Sopenharmony_cistatic const struct tegra_xusb_pad_ops tegra210_sata_ops = { 300162306a36Sopenharmony_ci .probe = tegra210_sata_pad_probe, 300262306a36Sopenharmony_ci .remove = tegra210_sata_pad_remove, 300362306a36Sopenharmony_ci}; 300462306a36Sopenharmony_ci 300562306a36Sopenharmony_cistatic const struct tegra_xusb_pad_soc tegra210_sata_pad = { 300662306a36Sopenharmony_ci .name = "sata", 300762306a36Sopenharmony_ci .num_lanes = ARRAY_SIZE(tegra210_sata_lanes), 300862306a36Sopenharmony_ci .lanes = tegra210_sata_lanes, 300962306a36Sopenharmony_ci .ops = &tegra210_sata_ops, 301062306a36Sopenharmony_ci}; 301162306a36Sopenharmony_ci 301262306a36Sopenharmony_cistatic const struct tegra_xusb_pad_soc * const tegra210_pads[] = { 301362306a36Sopenharmony_ci &tegra210_usb2_pad, 301462306a36Sopenharmony_ci &tegra210_hsic_pad, 301562306a36Sopenharmony_ci &tegra210_pcie_pad, 301662306a36Sopenharmony_ci &tegra210_sata_pad, 301762306a36Sopenharmony_ci}; 301862306a36Sopenharmony_ci 301962306a36Sopenharmony_cistatic int tegra210_usb2_port_enable(struct tegra_xusb_port *port) 302062306a36Sopenharmony_ci{ 302162306a36Sopenharmony_ci return 0; 302262306a36Sopenharmony_ci} 302362306a36Sopenharmony_ci 302462306a36Sopenharmony_cistatic void tegra210_usb2_port_disable(struct tegra_xusb_port *port) 302562306a36Sopenharmony_ci{ 302662306a36Sopenharmony_ci} 302762306a36Sopenharmony_ci 302862306a36Sopenharmony_cistatic struct tegra_xusb_lane * 302962306a36Sopenharmony_citegra210_usb2_port_map(struct tegra_xusb_port *port) 303062306a36Sopenharmony_ci{ 303162306a36Sopenharmony_ci return tegra_xusb_find_lane(port->padctl, "usb2", port->index); 303262306a36Sopenharmony_ci} 303362306a36Sopenharmony_ci 303462306a36Sopenharmony_cistatic const struct tegra_xusb_port_ops tegra210_usb2_port_ops = { 303562306a36Sopenharmony_ci .release = tegra_xusb_usb2_port_release, 303662306a36Sopenharmony_ci .remove = tegra_xusb_usb2_port_remove, 303762306a36Sopenharmony_ci .enable = tegra210_usb2_port_enable, 303862306a36Sopenharmony_ci .disable = tegra210_usb2_port_disable, 303962306a36Sopenharmony_ci .map = tegra210_usb2_port_map, 304062306a36Sopenharmony_ci}; 304162306a36Sopenharmony_ci 304262306a36Sopenharmony_cistatic int tegra210_hsic_port_enable(struct tegra_xusb_port *port) 304362306a36Sopenharmony_ci{ 304462306a36Sopenharmony_ci return 0; 304562306a36Sopenharmony_ci} 304662306a36Sopenharmony_ci 304762306a36Sopenharmony_cistatic void tegra210_hsic_port_disable(struct tegra_xusb_port *port) 304862306a36Sopenharmony_ci{ 304962306a36Sopenharmony_ci} 305062306a36Sopenharmony_ci 305162306a36Sopenharmony_cistatic struct tegra_xusb_lane * 305262306a36Sopenharmony_citegra210_hsic_port_map(struct tegra_xusb_port *port) 305362306a36Sopenharmony_ci{ 305462306a36Sopenharmony_ci return tegra_xusb_find_lane(port->padctl, "hsic", port->index); 305562306a36Sopenharmony_ci} 305662306a36Sopenharmony_ci 305762306a36Sopenharmony_cistatic const struct tegra_xusb_port_ops tegra210_hsic_port_ops = { 305862306a36Sopenharmony_ci .release = tegra_xusb_hsic_port_release, 305962306a36Sopenharmony_ci .enable = tegra210_hsic_port_enable, 306062306a36Sopenharmony_ci .disable = tegra210_hsic_port_disable, 306162306a36Sopenharmony_ci .map = tegra210_hsic_port_map, 306262306a36Sopenharmony_ci}; 306362306a36Sopenharmony_ci 306462306a36Sopenharmony_cistatic int tegra210_usb3_port_enable(struct tegra_xusb_port *port) 306562306a36Sopenharmony_ci{ 306662306a36Sopenharmony_ci return 0; 306762306a36Sopenharmony_ci} 306862306a36Sopenharmony_ci 306962306a36Sopenharmony_cistatic void tegra210_usb3_port_disable(struct tegra_xusb_port *port) 307062306a36Sopenharmony_ci{ 307162306a36Sopenharmony_ci} 307262306a36Sopenharmony_ci 307362306a36Sopenharmony_cistatic struct tegra_xusb_lane * 307462306a36Sopenharmony_citegra210_usb3_port_map(struct tegra_xusb_port *port) 307562306a36Sopenharmony_ci{ 307662306a36Sopenharmony_ci return tegra_xusb_port_find_lane(port, tegra210_usb3_map, "usb3-ss"); 307762306a36Sopenharmony_ci} 307862306a36Sopenharmony_ci 307962306a36Sopenharmony_cistatic const struct tegra_xusb_port_ops tegra210_usb3_port_ops = { 308062306a36Sopenharmony_ci .release = tegra_xusb_usb3_port_release, 308162306a36Sopenharmony_ci .enable = tegra210_usb3_port_enable, 308262306a36Sopenharmony_ci .disable = tegra210_usb3_port_disable, 308362306a36Sopenharmony_ci .map = tegra210_usb3_port_map, 308462306a36Sopenharmony_ci}; 308562306a36Sopenharmony_ci 308662306a36Sopenharmony_cistatic int tegra210_utmi_port_reset(struct phy *phy) 308762306a36Sopenharmony_ci{ 308862306a36Sopenharmony_ci struct tegra_xusb_padctl *padctl; 308962306a36Sopenharmony_ci struct tegra_xusb_lane *lane; 309062306a36Sopenharmony_ci u32 value; 309162306a36Sopenharmony_ci 309262306a36Sopenharmony_ci lane = phy_get_drvdata(phy); 309362306a36Sopenharmony_ci padctl = lane->pad->padctl; 309462306a36Sopenharmony_ci 309562306a36Sopenharmony_ci value = padctl_readl(padctl, 309662306a36Sopenharmony_ci XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL0(lane->index)); 309762306a36Sopenharmony_ci 309862306a36Sopenharmony_ci if ((value & XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL0_ZIP) || 309962306a36Sopenharmony_ci (value & XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPAD_CTL0_ZIN)) { 310062306a36Sopenharmony_ci tegra210_xusb_padctl_vbus_override(padctl, false); 310162306a36Sopenharmony_ci tegra210_xusb_padctl_vbus_override(padctl, true); 310262306a36Sopenharmony_ci return 1; 310362306a36Sopenharmony_ci } 310462306a36Sopenharmony_ci 310562306a36Sopenharmony_ci return 0; 310662306a36Sopenharmony_ci} 310762306a36Sopenharmony_ci 310862306a36Sopenharmony_cistatic int 310962306a36Sopenharmony_citegra210_xusb_read_fuse_calibration(struct tegra210_xusb_fuse_calibration *fuse) 311062306a36Sopenharmony_ci{ 311162306a36Sopenharmony_ci unsigned int i; 311262306a36Sopenharmony_ci u32 value; 311362306a36Sopenharmony_ci int err; 311462306a36Sopenharmony_ci 311562306a36Sopenharmony_ci err = tegra_fuse_readl(TEGRA_FUSE_SKU_CALIB_0, &value); 311662306a36Sopenharmony_ci if (err < 0) 311762306a36Sopenharmony_ci return err; 311862306a36Sopenharmony_ci 311962306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(fuse->hs_curr_level); i++) { 312062306a36Sopenharmony_ci fuse->hs_curr_level[i] = 312162306a36Sopenharmony_ci (value >> FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(i)) & 312262306a36Sopenharmony_ci FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK; 312362306a36Sopenharmony_ci } 312462306a36Sopenharmony_ci 312562306a36Sopenharmony_ci fuse->hs_term_range_adj = 312662306a36Sopenharmony_ci (value >> FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT) & 312762306a36Sopenharmony_ci FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK; 312862306a36Sopenharmony_ci 312962306a36Sopenharmony_ci err = tegra_fuse_readl(TEGRA_FUSE_USB_CALIB_EXT_0, &value); 313062306a36Sopenharmony_ci if (err < 0) 313162306a36Sopenharmony_ci return err; 313262306a36Sopenharmony_ci 313362306a36Sopenharmony_ci fuse->rpd_ctrl = 313462306a36Sopenharmony_ci (value >> FUSE_USB_CALIB_EXT_RPD_CTRL_SHIFT) & 313562306a36Sopenharmony_ci FUSE_USB_CALIB_EXT_RPD_CTRL_MASK; 313662306a36Sopenharmony_ci 313762306a36Sopenharmony_ci return 0; 313862306a36Sopenharmony_ci} 313962306a36Sopenharmony_ci 314062306a36Sopenharmony_cistatic struct tegra_xusb_padctl * 314162306a36Sopenharmony_citegra210_xusb_padctl_probe(struct device *dev, 314262306a36Sopenharmony_ci const struct tegra_xusb_padctl_soc *soc) 314362306a36Sopenharmony_ci{ 314462306a36Sopenharmony_ci struct tegra210_xusb_padctl *padctl; 314562306a36Sopenharmony_ci struct platform_device *pdev; 314662306a36Sopenharmony_ci struct device_node *np; 314762306a36Sopenharmony_ci int err; 314862306a36Sopenharmony_ci 314962306a36Sopenharmony_ci padctl = devm_kzalloc(dev, sizeof(*padctl), GFP_KERNEL); 315062306a36Sopenharmony_ci if (!padctl) 315162306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 315262306a36Sopenharmony_ci 315362306a36Sopenharmony_ci padctl->base.dev = dev; 315462306a36Sopenharmony_ci padctl->base.soc = soc; 315562306a36Sopenharmony_ci 315662306a36Sopenharmony_ci err = tegra210_xusb_read_fuse_calibration(&padctl->fuse); 315762306a36Sopenharmony_ci if (err < 0) 315862306a36Sopenharmony_ci return ERR_PTR(err); 315962306a36Sopenharmony_ci 316062306a36Sopenharmony_ci np = of_parse_phandle(dev->of_node, "nvidia,pmc", 0); 316162306a36Sopenharmony_ci if (!np) { 316262306a36Sopenharmony_ci dev_warn(dev, "nvidia,pmc property is missing\n"); 316362306a36Sopenharmony_ci goto out; 316462306a36Sopenharmony_ci } 316562306a36Sopenharmony_ci 316662306a36Sopenharmony_ci pdev = of_find_device_by_node(np); 316762306a36Sopenharmony_ci if (!pdev) { 316862306a36Sopenharmony_ci dev_warn(dev, "PMC device is not available\n"); 316962306a36Sopenharmony_ci goto out; 317062306a36Sopenharmony_ci } 317162306a36Sopenharmony_ci 317262306a36Sopenharmony_ci if (!platform_get_drvdata(pdev)) 317362306a36Sopenharmony_ci return ERR_PTR(-EPROBE_DEFER); 317462306a36Sopenharmony_ci 317562306a36Sopenharmony_ci padctl->regmap = dev_get_regmap(&pdev->dev, "usb_sleepwalk"); 317662306a36Sopenharmony_ci if (!padctl->regmap) 317762306a36Sopenharmony_ci dev_info(dev, "failed to find PMC regmap\n"); 317862306a36Sopenharmony_ci 317962306a36Sopenharmony_ciout: 318062306a36Sopenharmony_ci return &padctl->base; 318162306a36Sopenharmony_ci} 318262306a36Sopenharmony_ci 318362306a36Sopenharmony_cistatic void tegra210_xusb_padctl_remove(struct tegra_xusb_padctl *padctl) 318462306a36Sopenharmony_ci{ 318562306a36Sopenharmony_ci} 318662306a36Sopenharmony_ci 318762306a36Sopenharmony_cistatic void tegra210_xusb_padctl_save(struct tegra_xusb_padctl *padctl) 318862306a36Sopenharmony_ci{ 318962306a36Sopenharmony_ci struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl); 319062306a36Sopenharmony_ci 319162306a36Sopenharmony_ci priv->context.usb2_pad_mux = 319262306a36Sopenharmony_ci padctl_readl(padctl, XUSB_PADCTL_USB2_PAD_MUX); 319362306a36Sopenharmony_ci priv->context.usb2_port_cap = 319462306a36Sopenharmony_ci padctl_readl(padctl, XUSB_PADCTL_USB2_PORT_CAP); 319562306a36Sopenharmony_ci priv->context.ss_port_map = 319662306a36Sopenharmony_ci padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); 319762306a36Sopenharmony_ci priv->context.usb3_pad_mux = 319862306a36Sopenharmony_ci padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX); 319962306a36Sopenharmony_ci} 320062306a36Sopenharmony_ci 320162306a36Sopenharmony_cistatic void tegra210_xusb_padctl_restore(struct tegra_xusb_padctl *padctl) 320262306a36Sopenharmony_ci{ 320362306a36Sopenharmony_ci struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl); 320462306a36Sopenharmony_ci struct tegra_xusb_lane *lane; 320562306a36Sopenharmony_ci 320662306a36Sopenharmony_ci padctl_writel(padctl, priv->context.usb2_pad_mux, 320762306a36Sopenharmony_ci XUSB_PADCTL_USB2_PAD_MUX); 320862306a36Sopenharmony_ci padctl_writel(padctl, priv->context.usb2_port_cap, 320962306a36Sopenharmony_ci XUSB_PADCTL_USB2_PORT_CAP); 321062306a36Sopenharmony_ci padctl_writel(padctl, priv->context.ss_port_map, 321162306a36Sopenharmony_ci XUSB_PADCTL_SS_PORT_MAP); 321262306a36Sopenharmony_ci 321362306a36Sopenharmony_ci list_for_each_entry(lane, &padctl->lanes, list) { 321462306a36Sopenharmony_ci if (lane->pad->ops->iddq_enable) 321562306a36Sopenharmony_ci tegra210_uphy_lane_iddq_enable(lane); 321662306a36Sopenharmony_ci } 321762306a36Sopenharmony_ci 321862306a36Sopenharmony_ci padctl_writel(padctl, priv->context.usb3_pad_mux, 321962306a36Sopenharmony_ci XUSB_PADCTL_USB3_PAD_MUX); 322062306a36Sopenharmony_ci 322162306a36Sopenharmony_ci list_for_each_entry(lane, &padctl->lanes, list) { 322262306a36Sopenharmony_ci if (lane->pad->ops->iddq_disable) 322362306a36Sopenharmony_ci tegra210_uphy_lane_iddq_disable(lane); 322462306a36Sopenharmony_ci } 322562306a36Sopenharmony_ci} 322662306a36Sopenharmony_ci 322762306a36Sopenharmony_cistatic int tegra210_xusb_padctl_suspend_noirq(struct tegra_xusb_padctl *padctl) 322862306a36Sopenharmony_ci{ 322962306a36Sopenharmony_ci mutex_lock(&padctl->lock); 323062306a36Sopenharmony_ci 323162306a36Sopenharmony_ci tegra210_uphy_deinit(padctl); 323262306a36Sopenharmony_ci 323362306a36Sopenharmony_ci tegra210_xusb_padctl_save(padctl); 323462306a36Sopenharmony_ci 323562306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 323662306a36Sopenharmony_ci return 0; 323762306a36Sopenharmony_ci} 323862306a36Sopenharmony_ci 323962306a36Sopenharmony_cistatic int tegra210_xusb_padctl_resume_noirq(struct tegra_xusb_padctl *padctl) 324062306a36Sopenharmony_ci{ 324162306a36Sopenharmony_ci mutex_lock(&padctl->lock); 324262306a36Sopenharmony_ci 324362306a36Sopenharmony_ci tegra210_xusb_padctl_restore(padctl); 324462306a36Sopenharmony_ci 324562306a36Sopenharmony_ci tegra210_uphy_init(padctl); 324662306a36Sopenharmony_ci 324762306a36Sopenharmony_ci mutex_unlock(&padctl->lock); 324862306a36Sopenharmony_ci return 0; 324962306a36Sopenharmony_ci} 325062306a36Sopenharmony_ci 325162306a36Sopenharmony_cistatic const struct tegra_xusb_padctl_ops tegra210_xusb_padctl_ops = { 325262306a36Sopenharmony_ci .probe = tegra210_xusb_padctl_probe, 325362306a36Sopenharmony_ci .remove = tegra210_xusb_padctl_remove, 325462306a36Sopenharmony_ci .suspend_noirq = tegra210_xusb_padctl_suspend_noirq, 325562306a36Sopenharmony_ci .resume_noirq = tegra210_xusb_padctl_resume_noirq, 325662306a36Sopenharmony_ci .usb3_set_lfps_detect = tegra210_usb3_set_lfps_detect, 325762306a36Sopenharmony_ci .hsic_set_idle = tegra210_hsic_set_idle, 325862306a36Sopenharmony_ci .vbus_override = tegra210_xusb_padctl_vbus_override, 325962306a36Sopenharmony_ci .utmi_port_reset = tegra210_utmi_port_reset, 326062306a36Sopenharmony_ci}; 326162306a36Sopenharmony_ci 326262306a36Sopenharmony_cistatic const char * const tegra210_xusb_padctl_supply_names[] = { 326362306a36Sopenharmony_ci "avdd-pll-utmip", 326462306a36Sopenharmony_ci "avdd-pll-uerefe", 326562306a36Sopenharmony_ci "dvdd-pex-pll", 326662306a36Sopenharmony_ci "hvdd-pex-pll-e", 326762306a36Sopenharmony_ci}; 326862306a36Sopenharmony_ci 326962306a36Sopenharmony_ciconst struct tegra_xusb_padctl_soc tegra210_xusb_padctl_soc = { 327062306a36Sopenharmony_ci .num_pads = ARRAY_SIZE(tegra210_pads), 327162306a36Sopenharmony_ci .pads = tegra210_pads, 327262306a36Sopenharmony_ci .ports = { 327362306a36Sopenharmony_ci .usb2 = { 327462306a36Sopenharmony_ci .ops = &tegra210_usb2_port_ops, 327562306a36Sopenharmony_ci .count = 4, 327662306a36Sopenharmony_ci }, 327762306a36Sopenharmony_ci .hsic = { 327862306a36Sopenharmony_ci .ops = &tegra210_hsic_port_ops, 327962306a36Sopenharmony_ci .count = 1, 328062306a36Sopenharmony_ci }, 328162306a36Sopenharmony_ci .usb3 = { 328262306a36Sopenharmony_ci .ops = &tegra210_usb3_port_ops, 328362306a36Sopenharmony_ci .count = 4, 328462306a36Sopenharmony_ci }, 328562306a36Sopenharmony_ci }, 328662306a36Sopenharmony_ci .ops = &tegra210_xusb_padctl_ops, 328762306a36Sopenharmony_ci .supply_names = tegra210_xusb_padctl_supply_names, 328862306a36Sopenharmony_ci .num_supplies = ARRAY_SIZE(tegra210_xusb_padctl_supply_names), 328962306a36Sopenharmony_ci .need_fake_usb3_port = true, 329062306a36Sopenharmony_ci}; 329162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(tegra210_xusb_padctl_soc); 329262306a36Sopenharmony_ci 329362306a36Sopenharmony_ciMODULE_AUTHOR("Andrew Bresticker <abrestic@chromium.org>"); 329462306a36Sopenharmony_ciMODULE_DESCRIPTION("NVIDIA Tegra 210 XUSB Pad Controller driver"); 329562306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 3296