Commit 5b35eb84 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull phy fixes from Vinod Koul:
 "Core:

   - use per-PHY lockdep keys, in order to fix a phy using internal phys

 Drivers:

   - tegra:
       - fixes for unbalanced regulator
       - decouple pad calibration fix
       - disable periodic updates

   - qualcomm:
       - error code fix for driver probe"

* tag 'phy-fix-6.16' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy:
  phy: qcom: fix error code in snps_eusb2_hsphy_probe()
  phy: use per-PHY lockdep keys
  phy: tegra: xusb: Fix unbalanced regulator disable in UTMI PHY mode
  phy: tegra: xusb: Disable periodic tracking on Tegra234
  phy: tegra: xusb: Decouple CYA_TRK_CODE_UPDATE_ON_IDLE from trk_hw_mode
parents a4e37030 b7acfeab
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -994,7 +994,8 @@ struct phy *phy_create(struct device *dev, struct device_node *node,
	}

	device_initialize(&phy->dev);
	mutex_init(&phy->mutex);
	lockdep_register_key(&phy->lockdep_key);
	mutex_init_with_key(&phy->mutex, &phy->lockdep_key);

	phy->dev.class = &phy_class;
	phy->dev.parent = dev;
@@ -1259,6 +1260,8 @@ static void phy_release(struct device *dev)
	dev_vdbg(dev, "releasing '%s'\n", dev_name(dev));
	debugfs_remove_recursive(phy->debugfs);
	regulator_put(phy->pwr);
	mutex_destroy(&phy->mutex);
	lockdep_unregister_key(&phy->lockdep_key);
	ida_free(&phy_ida, phy->id);
	kfree(phy);
}
+4 −2
Original line number Diff line number Diff line
@@ -567,9 +567,11 @@ static int snps_eusb2_hsphy_probe(struct platform_device *pdev)
		}
	}

	if (IS_ERR_OR_NULL(phy->ref_clk))
		return dev_err_probe(dev, PTR_ERR(phy->ref_clk),
	if (IS_ERR_OR_NULL(phy->ref_clk)) {
		ret = phy->ref_clk ? PTR_ERR(phy->ref_clk) : -ENOENT;
		return dev_err_probe(dev, ret,
				     "failed to get ref clk\n");
	}

	num = ARRAY_SIZE(phy->vregs);
	for (i = 0; i < num; i++)
+46 −29
Original line number Diff line number Diff line
@@ -648,15 +648,16 @@ static void tegra186_utmi_bias_pad_power_on(struct tegra_xusb_padctl *padctl)
		udelay(100);
	}

	if (padctl->soc->trk_hw_mode) {
	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL2);
		value |= USB2_TRK_HW_MODE;
	if (padctl->soc->trk_update_on_idle)
		value &= ~CYA_TRK_CODE_UPDATE_ON_IDLE;
	if (padctl->soc->trk_hw_mode)
		value |= USB2_TRK_HW_MODE;
	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL2);
	} else {

	if (!padctl->soc->trk_hw_mode)
		clk_disable_unprepare(priv->usb2_trk_clk);
}
}

static void tegra186_utmi_bias_pad_power_off(struct tegra_xusb_padctl *padctl)
{
@@ -782,13 +783,15 @@ static int tegra186_xusb_padctl_vbus_override(struct tegra_xusb_padctl *padctl,
}

static int tegra186_xusb_padctl_id_override(struct tegra_xusb_padctl *padctl,
					    bool status)
					    struct tegra_xusb_usb2_port *port, bool status)
{
	u32 value;
	u32 value, id_override;
	int err = 0;

	dev_dbg(padctl->dev, "%s id override\n", status ? "set" : "clear");

	value = padctl_readl(padctl, USB2_VBUS_ID);
	id_override = value & ID_OVERRIDE(~0);

	if (status) {
		if (value & VBUS_OVERRIDE) {
@@ -799,14 +802,34 @@ static int tegra186_xusb_padctl_id_override(struct tegra_xusb_padctl *padctl,
			value = padctl_readl(padctl, USB2_VBUS_ID);
		}

		if (id_override != ID_OVERRIDE_GROUNDED) {
			value &= ~ID_OVERRIDE(~0);
			value |= ID_OVERRIDE_GROUNDED;
			padctl_writel(padctl, value, USB2_VBUS_ID);

			err = regulator_enable(port->supply);
			if (err) {
				dev_err(padctl->dev, "Failed to enable regulator: %d\n", err);
				return err;
			}
		}
	} else {
		value &= ~ID_OVERRIDE(~0);
		value |= ID_OVERRIDE_FLOATING;
		if (id_override == ID_OVERRIDE_GROUNDED) {
			/*
			 * The regulator is disabled only when the role transitions
			 * from USB_ROLE_HOST to USB_ROLE_NONE.
			 */
			err = regulator_disable(port->supply);
			if (err) {
				dev_err(padctl->dev, "Failed to disable regulator: %d\n", err);
				return err;
			}

			value &= ~ID_OVERRIDE(~0);
			value |= ID_OVERRIDE_FLOATING;
			padctl_writel(padctl, value, USB2_VBUS_ID);
		}
	}

	return 0;
}
@@ -826,27 +849,20 @@ static int tegra186_utmi_phy_set_mode(struct phy *phy, enum phy_mode mode,

	if (mode == PHY_MODE_USB_OTG) {
		if (submode == USB_ROLE_HOST) {
			tegra186_xusb_padctl_id_override(padctl, true);

			err = regulator_enable(port->supply);
			err = tegra186_xusb_padctl_id_override(padctl, port, true);
			if (err)
				goto out;
		} else if (submode == USB_ROLE_DEVICE) {
			tegra186_xusb_padctl_vbus_override(padctl, true);
		} else if (submode == USB_ROLE_NONE) {
			/*
			 * When port is peripheral only or role transitions to
			 * USB_ROLE_NONE from USB_ROLE_DEVICE, regulator is not
			 * enabled.
			 */
			if (regulator_is_enabled(port->supply))
				regulator_disable(port->supply);

			tegra186_xusb_padctl_id_override(padctl, false);
			err = tegra186_xusb_padctl_id_override(padctl, port, false);
			if (err)
				goto out;
			tegra186_xusb_padctl_vbus_override(padctl, false);
		}
	}

out:
	mutex_unlock(&padctl->lock);

	return err;
}

@@ -1710,7 +1726,8 @@ const struct tegra_xusb_padctl_soc tegra234_xusb_padctl_soc = {
	.num_supplies = ARRAY_SIZE(tegra194_xusb_padctl_supply_names),
	.supports_gen2 = true,
	.poll_trk_completed = true,
	.trk_hw_mode = true,
	.trk_hw_mode = false,
	.trk_update_on_idle = true,
	.supports_lp_cfg_en = true,
};
EXPORT_SYMBOL_GPL(tegra234_xusb_padctl_soc);
+1 −0
Original line number Diff line number Diff line
@@ -434,6 +434,7 @@ struct tegra_xusb_padctl_soc {
	bool need_fake_usb3_port;
	bool poll_trk_completed;
	bool trk_hw_mode;
	bool trk_update_on_idle;
	bool supports_lp_cfg_en;
};

+2 −0
Original line number Diff line number Diff line
@@ -154,6 +154,7 @@ struct phy_attrs {
 * @id: id of the phy device
 * @ops: function pointers for performing phy operations
 * @mutex: mutex to protect phy_ops
 * @lockdep_key: lockdep information for this mutex
 * @init_count: used to protect when the PHY is used by multiple consumers
 * @power_count: used to protect when the PHY is used by multiple consumers
 * @attrs: used to specify PHY specific attributes
@@ -165,6 +166,7 @@ struct phy {
	int			id;
	const struct phy_ops	*ops;
	struct mutex		mutex;
	struct lock_class_key	lockdep_key;
	int			init_count;
	int			power_count;
	struct phy_attrs	attrs;