Compare commits

...
4 Commits
Author SHA1 Message Date
tmakin eff4d587d2 xusb: t210: support utmi pad biasing
Based on t186 driver and downstream:
https://gitlab.com/nvidia/nv-tegra/linux-4.9/-/commit/8d05313ac9fd54a2fc373a0e789390dfa0607726
2026-09-12 12:52:17 -05:00
tmakin 366514a4be bm92t 2026-09-12 01:04:02 -05:00
tmakin f9b2980f86 gki hax 2026-09-12 01:03:55 -05:00
Bibhay Ranjan 494a158389 pinctrl: t210b01: Add SDMMC2 pinmux support
Add sdmmc2 pinmux support inorder to use
SDMMC2 controller on t210b01 platforms.

Bug 200360711

Change-Id: Ie2d3a20d10325d42dc5dbf601c9da747ff0caa66
Signed-off-by: Bibhay Ranjan <bibhayr@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1593367
Reviewed-on: https://git-master.nvidia.com/r/1648549
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-by: Pavan Kunapuli <pkunapuli@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Ashutosh Jha <ajha@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
2026-08-30 12:20:53 -05:00
4 changed files with 332 additions and 105 deletions

No files matched your search

+1 -6
View File
@@ -1,5 +1,6 @@
CONFIG_LOCALVERSION="-4k"
CONFIG_AUDIT=y
CONFIG_GENERIC_IRQ_DEBUGFS=y
CONFIG_TIME_KUNIT_TEST=m
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
@@ -9,7 +10,6 @@ CONFIG_BPF_JIT_ALWAYS_ON=y
# CONFIG_BPF_UNPRIV_DEFAULT_OFF is not set
CONFIG_BPF_LSM=y
CONFIG_PREEMPT=y
CONFIG_SCHED_CLASS_EXT=y
CONFIG_IRQ_TIME_ACCOUNTING=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
@@ -49,7 +49,6 @@ CONFIG_EXPERT=y
# CONFIG_FHANDLE is not set
# CONFIG_RSEQ is not set
CONFIG_PROFILING=y
CONFIG_RUST=y
CONFIG_ARCH_SUNXI=y
CONFIG_ARCH_HISI=y
CONFIG_ARCH_QCOM=y
@@ -440,7 +439,6 @@ CONFIG_HW_RANDOM=y
# CONFIG_HW_RANDOM_HISI is not set
# CONFIG_HW_RANDOM_HISTB is not set
CONFIG_HW_RANDOM_CCTRNG=m
# CONFIG_DEVMEM is not set
# CONFIG_DEVPORT is not set
# CONFIG_I2C_HELPER_AUTO is not set
# CONFIG_I2C_TEGRA_BPMP is not set
@@ -606,7 +604,6 @@ CONFIG_VIRTIO_BALLOON=m
CONFIG_VHOST_VSOCK=y
CONFIG_STAGING=y
CONFIG_ASHMEM=y
CONFIG_ASHMEM_RUST=y
CONFIG_COMMON_CLK_SCPI=y
# CONFIG_SUNXI_CCU is not set
CONFIG_CLK_KUNIT_TEST=m
@@ -765,8 +762,6 @@ CONFIG_STACKTRACE_BUILD_ID=y
CONFIG_DYNAMIC_DEBUG_CORE=y
CONFIG_DEBUG_INFO_DWARF5=y
CONFIG_DEBUG_INFO_COMPRESSED_ZSTD=y
CONFIG_DEBUG_INFO_BTF=y
CONFIG_MODULE_ALLOW_BTF_MISMATCH=y
CONFIG_HEADERS_INSTALL=y
# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
CONFIG_MAGIC_SYSRQ=y
+196 -88
View File
@@ -28,6 +28,8 @@
#define FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK 0x3f
#define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT 7
#define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK 0xf
#define FUSE_SKU_CALIB_HS_SQUELCH_SHIFT 29
#define FUSE_SKU_CALIB_HS_SQUELCH_MASK 0x7
#define FUSE_USB_CALIB_EXT_RPD_CTRL_SHIFT 0
#define FUSE_USB_CALIB_EXT_RPD_CTRL_MASK 0x1f
@@ -95,6 +97,7 @@
#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI (1 << 29)
#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 (1 << 27)
#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD (1 << 26)
#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_TERM_SEL (1 << 25)
#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT 0
#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK 0x3f
@@ -413,6 +416,8 @@
#define UHSIC_STROBE_RPD_C BIT(16)
#define UHSIC_STROBE_RPD_D BIT(24)
#define TEGRA_UTMI_PAD_MAX 4
struct init_data {
u8 cfg_addr;
u16 cfg_wdata;
@@ -428,6 +433,7 @@ static struct init_data tegra210b01_usb3_pll_g1_init_data[] = {
struct tegra210_xusb_fuse_calibration {
u32 hs_curr_level[4];
u32 hs_term_range_adj;
u32 hs_squelch;
u32 rpd_ctrl;
};
@@ -442,6 +448,8 @@ struct tegra210_xusb_padctl {
struct tegra_xusb_padctl base;
struct regmap *regmap;
DECLARE_BITMAP(utmi_pad_enabled, TEGRA_UTMI_PAD_MAX);
struct tegra210_xusb_fuse_calibration fuse;
struct tegra210_xusb_padctl_context context;
};
@@ -1939,6 +1947,151 @@ static int tegra210_usb2_phy_exit(struct phy *phy)
return 0;
}
static void tegra210_utmi_bias_pad_power_on(struct tegra_xusb_padctl *padctl,
struct tegra_xusb_usb2_pad *pad)
{
struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl);
struct device *dev = padctl->dev;
u32 value;
int err;
if (!bitmap_empty(priv->utmi_pad_enabled, TEGRA_UTMI_PAD_MAX))
return;
err = clk_prepare_enable(pad->clk);
if (err < 0)
dev_warn(dev, "failed to enable USB2 trk clock: %d\n", err);
value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
value &= ~(XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_MASK <<
XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_SHIFT);
value |= ((XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_VAL &
XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_MASK) <<
XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_SHIFT);
value &= ~(XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_MASK <<
XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_SHIFT);
value |= ((XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_VAL &
XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_MASK) <<
XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_SHIFT);
padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD;
value &= ~(XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK <<
XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT);
value |= ((priv->fuse.hs_squelch &
XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK) <<
XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT);
value &= ~(XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK <<
XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT);
value |= ((XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL &
XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK) <<
XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT);
padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
udelay(1);
value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL1_PD_TRK;
padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
}
static void tegra210_utmi_bias_pad_power_off(struct tegra_xusb_padctl *padctl,
struct tegra_xusb_usb2_pad *pad)
{
struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl);
u32 value;
if (!bitmap_empty(priv->utmi_pad_enabled, TEGRA_UTMI_PAD_MAX))
return;
value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
value |= XUSB_PADCTL_USB2_BIAS_PAD_CTL1_PD_TRK;
padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
}
static void tegra210_utmi_pad_power_on(struct phy *phy)
{
struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad);
struct tegra_xusb_padctl *padctl = lane->pad->padctl;
struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl);
struct tegra_xusb_usb2_port *port;
struct device *dev = padctl->dev;
unsigned int index = lane->index;
u32 value;
if (!phy)
return;
mutex_lock(&padctl->lock);
if (test_bit(index, priv->utmi_pad_enabled)) {
mutex_unlock(&padctl->lock);
return;
}
port = tegra_xusb_find_usb2_port(padctl, index);
if (!port) {
dev_err(dev, "no port found for USB2 lane %u\n", index);
mutex_unlock(&padctl->lock);
return;
}
dev_dbg(dev, "power on UTMI pad %u\n", index);
tegra210_utmi_bias_pad_power_on(padctl, pad);
udelay(2);
value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index));
value &= ~XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD;
padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index));
value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index));
value &= ~XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR;
padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index));
set_bit(index, priv->utmi_pad_enabled);
mutex_unlock(&padctl->lock);
}
static void tegra210_utmi_pad_power_down(struct phy *phy)
{
struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad);
struct tegra_xusb_padctl *padctl = lane->pad->padctl;
struct tegra210_xusb_padctl *priv = to_tegra210_xusb_padctl(padctl);
unsigned int index = lane->index;
u32 value;
if (!phy)
return;
mutex_lock(&padctl->lock);
if (!test_bit(index, priv->utmi_pad_enabled)) {
mutex_unlock(&padctl->lock);
return;
}
dev_dbg(padctl->dev, "power down UTMI pad %u\n", index);
value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index));
value |= XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD;
padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index));
value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index));
value |= XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR;
padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index));
udelay(2);
clear_bit(index, priv->utmi_pad_enabled);
tegra210_utmi_bias_pad_power_off(padctl, pad);
mutex_unlock(&padctl->lock);
}
static int tegra210_xusb_padctl_vbus_override(struct tegra_xusb_padctl *padctl,
bool status)
{
@@ -2040,13 +2193,11 @@ static int tegra210_usb2_phy_power_on(struct phy *phy)
{
struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
struct tegra_xusb_usb2_lane *usb2 = to_usb2_lane(lane);
struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad);
struct tegra_xusb_padctl *padctl = lane->pad->padctl;
struct tegra210_xusb_padctl *priv;
struct tegra_xusb_usb2_port *port;
unsigned int index = lane->index;
u32 value;
int err;
port = tegra_xusb_find_usb2_port(padctl, index);
if (!port) {
@@ -2086,21 +2237,6 @@ static int tegra210_usb2_phy_power_on(struct phy *phy)
padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
}
value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK <<
XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) |
(XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK <<
XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT));
value |= (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_VAL <<
XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT);
if (tegra_sku_info.revision < TEGRA_REVISION_A02)
value |=
(XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_VAL <<
XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT);
padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
value = padctl_readl(padctl, XUSB_PADCTL_USB2_PORT_CAP);
value &= ~XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_MASK(index);
if (port->mode == USB_DR_MODE_UNKNOWN)
@@ -2114,28 +2250,40 @@ static int tegra210_usb2_phy_power_on(struct phy *phy)
padctl_writel(padctl, value, XUSB_PADCTL_USB2_PORT_CAP);
value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index));
value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK <<
XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT) |
XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD |
XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 |
XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI);
value |= (priv->fuse.hs_curr_level[index] +
usb2->hs_curr_level_offset) <<
XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT;
value &= ~XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI;
value |= XUSB_PADCTL_USB2_OTG_PAD_CTL0_TERM_SEL;
value &= ~(XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK <<
XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT);
if (usb2->hs_curr_level_offset) {
int hs_current_level;
hs_current_level = (int) priv->fuse.hs_curr_level[index] +
usb2->hs_curr_level_offset;
if (hs_current_level < 0)
hs_current_level = 0;
if (hs_current_level > 0x3f)
hs_current_level = 0x3f;
value |= (hs_current_level &
XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK) <<
XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT;
} else {
value |= (priv->fuse.hs_curr_level[index] &
XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK) <<
XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT;
}
padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL0(index));
value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index));
value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK <<
XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) |
(XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_MASK <<
XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_SHIFT) |
XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR |
XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_OVRD |
XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_OVRD);
value |= (priv->fuse.hs_term_range_adj <<
XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) |
(priv->fuse.rpd_ctrl <<
XUSB_PADCTL_USB2_OTG_PAD_CTL1_RPD_CTRL_SHIFT);
value &= ~(XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK <<
XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT);
value |= (priv->fuse.hs_term_range_adj &
XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK) <<
XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT;
value &= ~RPD_CTRL(~0);
value |= RPD_CTRL(priv->fuse.rpd_ctrl);
padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL1(index));
value = padctl_readl(padctl,
@@ -2151,55 +2299,14 @@ static int tegra210_usb2_phy_power_on(struct phy *phy)
padctl_writel(padctl, value,
XUSB_PADCTL_USB2_BATTERY_CHRG_OTGPADX_CTL1(index));
if (pad->enable > 0) {
pad->enable++;
mutex_unlock(&padctl->lock);
return 0;
}
err = clk_prepare_enable(pad->clk);
if (err)
goto out;
value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_MASK <<
XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_SHIFT) |
(XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_MASK <<
XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_SHIFT));
value |= (XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_VAL <<
XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_START_TIMER_SHIFT) |
(XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_VAL <<
XUSB_PADCTL_USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_SHIFT);
padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD;
padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
udelay(1);
value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL1_PD_TRK;
padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL1);
udelay(50);
clk_disable_unprepare(pad->clk);
pad->enable++;
mutex_unlock(&padctl->lock);
return 0;
out:
mutex_unlock(&padctl->lock);
return err;
}
static int tegra210_usb2_phy_power_off(struct phy *phy)
{
struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
struct tegra_xusb_usb2_pad *pad = to_usb2_pad(lane->pad);
struct tegra_xusb_padctl *padctl = lane->pad->padctl;
struct tegra_xusb_usb2_port *port;
u32 value;
@@ -2239,17 +2346,6 @@ static int tegra210_usb2_phy_power_off(struct phy *phy)
padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP);
}
if (WARN_ON(pad->enable == 0))
goto out;
if (--pad->enable > 0)
goto out;
value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
value |= XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD;
padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
out:
mutex_unlock(&padctl->lock);
return 0;
}
@@ -3239,6 +3335,8 @@ static int tegra210_utmi_port_reset(struct phy *phy)
static int
tegra210_xusb_read_fuse_calibration(struct tegra210_xusb_fuse_calibration *fuse)
{
struct tegra210_xusb_padctl *priv =
container_of(fuse, struct tegra210_xusb_padctl, fuse);
unsigned int i;
u32 value;
int err;
@@ -3247,12 +3345,18 @@ tegra210_xusb_read_fuse_calibration(struct tegra210_xusb_fuse_calibration *fuse)
if (err < 0)
return err;
dev_info(priv->base.dev, "TEGRA_FUSE_SKU_CALIB_0 = 0x%x\n", value);
for (i = 0; i < ARRAY_SIZE(fuse->hs_curr_level); i++) {
fuse->hs_curr_level[i] =
(value >> FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(i)) &
FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK;
}
fuse->hs_squelch =
(value >> FUSE_SKU_CALIB_HS_SQUELCH_SHIFT)
& FUSE_SKU_CALIB_HS_SQUELCH_MASK;
fuse->hs_term_range_adj =
(value >> FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT) &
FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK;
@@ -3261,6 +3365,8 @@ tegra210_xusb_read_fuse_calibration(struct tegra210_xusb_fuse_calibration *fuse)
if (err < 0)
return err;
dev_info(priv->base.dev, "TEGRA_FUSE_USB_CALIB_EXT_0 = 0x%x\n", value);
fuse->rpd_ctrl =
(value >> FUSE_USB_CALIB_EXT_RPD_CTRL_SHIFT) &
FUSE_USB_CALIB_EXT_RPD_CTRL_MASK;
@@ -3392,6 +3498,8 @@ static const struct tegra_xusb_padctl_ops tegra210_xusb_padctl_ops = {
.hsic_set_idle = tegra210_hsic_set_idle,
.vbus_override = tegra210_xusb_padctl_vbus_override,
.utmi_port_reset = tegra210_utmi_port_reset,
.utmi_pad_power_on = tegra210_utmi_pad_power_on,
.utmi_pad_power_down = tegra210_utmi_pad_power_down,
};
static const char * const tegra210_xusb_padctl_supply_names[] = {
+106
View File
@@ -192,6 +192,19 @@ struct tegra210_pinctrl_soc {
#define TEGRA_PIN_BATT_BCL _PIN(5)
#define TEGRA_PIN_CLK_REQ _PIN(6)
#define TEGRA_PIN_SHUTDOWN _PIN(7)
#define TEGRA_PIN_SDMMC2_CLK _PIN(8)
#define TEGRA_PIN_SDMMC2_CLKB _PIN(9)
#define TEGRA_PIN_SDMMC2_CMD _PIN(10)
#define TEGRA_PIN_SDMMC2_DAT0 _PIN(11)
#define TEGRA_PIN_SDMMC2_DAT1 _PIN(12)
#define TEGRA_PIN_SDMMC2_DAT2 _PIN(13)
#define TEGRA_PIN_SDMMC2_DAT3 _PIN(14)
#define TEGRA_PIN_SDMMC2_DAT4 _PIN(15)
#define TEGRA_PIN_SDMMC2_DAT5 _PIN(16)
#define TEGRA_PIN_SDMMC2_DAT6 _PIN(17)
#define TEGRA_PIN_SDMMC2_DAT7 _PIN(18)
#define TEGRA_PIN_SDMMC2_DQS _PIN(19)
#define TEGRA_PIN_SDMMC2_DQSB _PIN(20)
static const struct pinctrl_pin_desc tegra210_pins[] = {
PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PA0, "PEX_L0_RST_N PA0"),
@@ -276,6 +289,19 @@ static const struct pinctrl_pin_desc tegra210_pins[] = {
PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PM3, "SDMMC1_DAT2 PM3"),
PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PM4, "SDMMC1_DAT1 PM4"),
PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PM5, "SDMMC1_DAT0 PM5"),
PINCTRL_PIN(TEGRA_PIN_SDMMC2_CLK, "SDMMC2_CLK"),
PINCTRL_PIN(TEGRA_PIN_SDMMC2_CLKB, "SDMMC2_CLKB"),
PINCTRL_PIN(TEGRA_PIN_SDMMC2_CMD, "SDMMC2_CMD"),
PINCTRL_PIN(TEGRA_PIN_SDMMC2_DAT0, "SDMMC2_DAT0"),
PINCTRL_PIN(TEGRA_PIN_SDMMC2_DAT1, "SDMMC2_DAT1"),
PINCTRL_PIN(TEGRA_PIN_SDMMC2_DAT2, "SDMMC2_DAT2"),
PINCTRL_PIN(TEGRA_PIN_SDMMC2_DAT3, "SDMMC2_DAT3"),
PINCTRL_PIN(TEGRA_PIN_SDMMC2_DAT4, "SDMMC2_DAT4"),
PINCTRL_PIN(TEGRA_PIN_SDMMC2_DAT5, "SDMMC2_DAT5"),
PINCTRL_PIN(TEGRA_PIN_SDMMC2_DAT6, "SDMMC2_DAT6"),
PINCTRL_PIN(TEGRA_PIN_SDMMC2_DAT7, "SDMMC2_DAT7"),
PINCTRL_PIN(TEGRA_PIN_SDMMC2_DQS, "SDMMC2_DQS"),
PINCTRL_PIN(TEGRA_PIN_SDMMC2_DQSB, "SDMMC2_DQSB"),
PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PP0, "SDMMC3_CLK PP0"),
PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PP1, "SDMMC3_CMD PP1"),
PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PP2, "SDMMC3_DAT3 PP2"),
@@ -686,6 +712,58 @@ static const unsigned sdmmc1_dat0_pm5_pins[] = {
TEGRA_PIN_SDMMC1_DAT0_PM5,
};
static const unsigned sdmmc2_clk_pins[] = {
TEGRA_PIN_SDMMC2_CLK,
};
static const unsigned sdmmc2_clkb_pins[] = {
TEGRA_PIN_SDMMC2_CLKB,
};
static const unsigned sdmmc2_cmd_pins[] = {
TEGRA_PIN_SDMMC2_CMD,
};
static const unsigned sdmmc2_dat0_pins[] = {
TEGRA_PIN_SDMMC2_DAT0,
};
static const unsigned sdmmc2_dat1_pins[] = {
TEGRA_PIN_SDMMC2_DAT1,
};
static const unsigned sdmmc2_dat2_pins[] = {
TEGRA_PIN_SDMMC2_DAT2,
};
static const unsigned sdmmc2_dat3_pins[] = {
TEGRA_PIN_SDMMC2_DAT3,
};
static const unsigned sdmmc2_dat4_pins[] = {
TEGRA_PIN_SDMMC2_DAT4,
};
static const unsigned sdmmc2_dat5_pins[] = {
TEGRA_PIN_SDMMC2_DAT5,
};
static const unsigned sdmmc2_dat6_pins[] = {
TEGRA_PIN_SDMMC2_DAT6,
};
static const unsigned sdmmc2_dat7_pins[] = {
TEGRA_PIN_SDMMC2_DAT7,
};
static const unsigned sdmmc2_dqs_pins[] = {
TEGRA_PIN_SDMMC2_DQS,
};
static const unsigned sdmmc2_dqsb_pins[] = {
TEGRA_PIN_SDMMC2_DQSB,
};
static const unsigned sdmmc3_clk_pp0_pins[] = {
TEGRA_PIN_SDMMC3_CLK_PP0,
};
@@ -1100,6 +1178,19 @@ static const unsigned drive_sdmmc1_pins[] = {
};
static const unsigned drive_sdmmc2_pins[] = {
TEGRA_PIN_SDMMC2_CLK,
TEGRA_PIN_SDMMC2_CLKB,
TEGRA_PIN_SDMMC2_CMD,
TEGRA_PIN_SDMMC2_DAT0,
TEGRA_PIN_SDMMC2_DAT1,
TEGRA_PIN_SDMMC2_DAT2,
TEGRA_PIN_SDMMC2_DAT3,
TEGRA_PIN_SDMMC2_DAT4,
TEGRA_PIN_SDMMC2_DAT5,
TEGRA_PIN_SDMMC2_DAT6,
TEGRA_PIN_SDMMC2_DAT7,
TEGRA_PIN_SDMMC2_DQS,
TEGRA_PIN_SDMMC2_DQSB,
};
static const unsigned drive_sdmmc3_pins[] = {
@@ -1162,6 +1253,7 @@ enum tegra_mux {
TEGRA_MUX_RSVD3,
TEGRA_MUX_SATA,
TEGRA_MUX_SDMMC1,
TEGRA_MUX_SDMMC2,
TEGRA_MUX_SDMMC3,
TEGRA_MUX_SHUTDOWN,
TEGRA_MUX_SOC,
@@ -1240,6 +1332,7 @@ static const char * const tegra210_functions[] = {
FUNCTION(rsvd3),
FUNCTION(sata),
FUNCTION(sdmmc1),
FUNCTION(sdmmc2),
FUNCTION(sdmmc3),
FUNCTION(shutdown),
FUNCTION(soc),
@@ -1362,6 +1455,19 @@ static struct tegra_pingroup tegra210_groups[] = {
PINGROUP(sdmmc1_dat2_pm3, SDMMC1, SPI3, RSVD2, RSVD3, 0x300c, Y, Y, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
PINGROUP(sdmmc1_dat1_pm4, SDMMC1, SPI3, RSVD2, RSVD3, 0x3010, Y, Y, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
PINGROUP(sdmmc1_dat0_pm5, SDMMC1, RSVD1, RSVD2, RSVD3, 0x3014, Y, Y, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
PINGROUP(sdmmc2_clk, SDMMC2, RSVD1, RSVD2, RSVD3, 0x32b4, Y, Y, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
PINGROUP(sdmmc2_clkb, SDMMC2, RSVD1, RSVD2, RSVD3, 0x32b8, Y, Y, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
PINGROUP(sdmmc2_cmd, SDMMC2, RSVD1, RSVD2, RSVD3, 0x32bc, Y, Y, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
PINGROUP(sdmmc2_dat0, SDMMC2, RSVD1, RSVD2, RSVD3, 0x3294, Y, Y, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
PINGROUP(sdmmc2_dat1, SDMMC2, RSVD1, RSVD2, RSVD3, 0x3298, Y, Y, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
PINGROUP(sdmmc2_dat2, SDMMC2, RSVD1, RSVD2, RSVD3, 0x329c, Y, Y, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
PINGROUP(sdmmc2_dat3, SDMMC2, RSVD1, RSVD2, RSVD3, 0x32a0, Y, Y, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
PINGROUP(sdmmc2_dat4, SDMMC2, RSVD1, RSVD2, RSVD3, 0x32a4, Y, Y, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
PINGROUP(sdmmc2_dat5, SDMMC2, RSVD1, RSVD2, RSVD3, 0x32a8, Y, Y, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
PINGROUP(sdmmc2_dat6, SDMMC2, RSVD1, RSVD2, RSVD3, 0x32ac, Y, Y, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
PINGROUP(sdmmc2_dat7, SDMMC2, RSVD1, RSVD2, RSVD3, 0x32b0, Y, Y, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
PINGROUP(sdmmc2_dqs, SDMMC2, RSVD1, RSVD2, RSVD3, 0x32c0, Y, Y, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
PINGROUP(sdmmc2_dqsb, SDMMC2, RSVD1, RSVD2, RSVD3, 0x32c4, Y, Y, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
PINGROUP(sdmmc3_clk_pp0, SDMMC3, RSVD1, RSVD2, RSVD3, 0x301c, Y, Y, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
PINGROUP(sdmmc3_cmd_pp1, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3020, Y, Y, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
PINGROUP(sdmmc3_dat0_pp5, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3024, Y, Y, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+29 -11
View File
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
#define DEBUG 1
/*
* Driver for Rohm BM92TXX USB Type-C and Power Delivery controller
*
@@ -29,6 +31,7 @@
#include <linux/interrupt.h>
#include <linux/debugfs.h>
#include <linux/extcon-provider.h>
#include <linux/mutex.h>
#include <linux/usb/role.h>
#include <linux/regulator/consumer.h>
#include <linux/uaccess.h>
@@ -394,23 +397,23 @@ enum bm92t_state_type {
DOCK_CONFIG_HANDLED
};
struct __packed pd_object {
struct pd_object {
unsigned int amp:10;
unsigned int volt:10;
unsigned int info:10;
unsigned int type:2;
};
} __packed;
struct __packed rd_object {
struct rd_object {
unsigned int max_amp:10;
unsigned int op_amp:10;
unsigned int info:6;
unsigned int usb_comms:1;
unsigned int mismatch:1;
unsigned int obj_no:4;
};
} __packed;
struct __packed vd_object {
struct vd_object {
unsigned int vid:16;
unsigned int rsvd:10;
unsigned int modal:1;
@@ -424,7 +427,7 @@ struct __packed vd_object {
unsigned int pid:16;
unsigned int prod_type;
};
} __packed;
struct bm92t_device {
int pdo_no;
@@ -465,6 +468,7 @@ struct bm92t_info {
struct extcon_dev *edev;
struct delayed_work oneshot_work;
struct delayed_work power_work;
struct mutex lock;
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_root;
@@ -1053,7 +1057,7 @@ static void bm92t_extcon_cable_set_init_state(struct work_struct *work)
struct bm92t_info *info = container_of(to_delayed_work(work),
struct bm92t_info, oneshot_work);
disable_irq(info->i2c_client->irq);
mutex_lock(&info->lock);
bm92t_set_vbus_enable(info, false);
@@ -1078,7 +1082,10 @@ static void bm92t_extcon_cable_set_init_state(struct work_struct *work)
"extcon cable is set to init state\n");
msleep(100); /* Wait a bit */
queue_work(info->event_wq, &info->work);
//queue_work(info->event_wq, &info->work);
enable_irq(info->i2c_client->irq);
mutex_unlock(&info->lock);
}
static bool bm92t_check_pdo(struct bm92t_info *info)
@@ -1330,6 +1337,8 @@ static void bm92t_event_handler(struct work_struct *work)
info = container_of(work, struct bm92t_info, work);
dev = &info->i2c_client->dev;
mutex_lock(&info->lock);
/* Read status registers at 02h, 03h and 04h */
err = bm92t_read_reg(info, ALERT_STATUS_REG,
(unsigned char *) &alert_data,
@@ -1929,6 +1938,7 @@ init_contract_out:
ret:
enable_irq(info->i2c_client->irq);
mutex_unlock(&info->lock);
}
static irqreturn_t bm92t_interrupt_handler(int irq, void *handle)
@@ -2177,7 +2187,7 @@ static ssize_t bm92t_cmd_write(struct file *file,
ret = kstrtouint(buf, 0, &val);
if (ret == 1) {
if (!ret) {
cmd = val;
bm92t_send_cmd(info, &cmd);
} else {
@@ -2209,7 +2219,7 @@ static ssize_t bm92t_usbhub_dp_sleep_write(struct file *file,
ret = kstrtouint(buf, 0, &val);
if (ret == 1) {
if (!ret) {
bm92t_usbhub_dp_sleep(info, val ? true : false);
} else {
dev_err(&info->i2c_client->dev, "Syntax is: 0 or number\n");
@@ -2489,6 +2499,8 @@ static int bm92t_probe(struct i2c_client *client)
/* Disable Source mode at boot */
bm92t_set_source_mode(info, SPDSRC12_OFF);
mutex_init(&info->lock);
INIT_WORK(&info->work, bm92t_event_handler);
INIT_DELAYED_WORK(&info->oneshot_work,
bm92t_extcon_cable_set_init_state);
@@ -2506,7 +2518,7 @@ static int bm92t_probe(struct i2c_client *client)
*/
if (request_threaded_irq(client->irq, NULL,
bm92t_interrupt_handler,
IRQF_TRIGGER_LOW | IRQF_ONESHOT, "bm92t",
IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_NO_AUTOEN, "bm92t",
info)) {
dev_err(&client->dev, "Request irq failed\n");
destroy_workqueue(info->event_wq);
@@ -2535,6 +2547,8 @@ static int bm92t_probe(struct i2c_client *client)
schedule_delayed_work(&info->oneshot_work, msecs_to_jiffies(100));
// enable_irq(client->irq);
dev_info(&client->dev, "init done\n");
return 0;
@@ -2595,6 +2609,8 @@ static int bm92t_pm_resume(struct device *dev)
disable_irq_wake(client->irq);
}
mutex_lock(&info->lock);
/*
* Toggle DP signal
* Do a toggle on resume instead of disable in suspend
@@ -2610,6 +2626,8 @@ static int bm92t_pm_resume(struct device *dev)
if (enable_led)
bm92t_usbhub_led_cfg_wait(info, 128, 0, 0, 64);
mutex_unlock(&info->lock);
return 0;
}