Commit 5041a58d authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'phy-for-5.5-rc' of...

Merge tag 'phy-for-5.5-rc' of git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy into usb-linus

Kishon writes:

phy: for 5.5-rc

*) Fix error path in cpcap-usb driver when no host driver is loaded to
   avoid debug serial console from stop working
*) Fix to let USB host idle before switching to UART mode in cpcap-usb
   driver in order to avoid flakey enumeration next time
*) Prevent USB line glitches from waking up modem by enabling the USB
   lines (GPIO mux) after configuring the cpcap-usb PHY
*) Improve host vs docked mode detection in cpcap-usb PHY driver to keep
   VBUS enabled in host mode
*) Fix to prevent cpcap-usb PHY driver from enabling the PHY twice
*) Increase PHY ready timeout in qcom-qmp PHY as it takes more than 1ms
   to initialize
*) Round clock rate down to closest 1000 Hz in phy-rockchip-inno-hdmi to
   prevent wrong pixel clock to be used and result in no-signal when
   configuring a mode on RK3328

* tag 'phy-for-5.5-rc' of git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy:
  phy/rockchip: inno-hdmi: round clock rate down to closest 1000 Hz
  phy: cpcap-usb: Drop extra write to usb2 register
  phy: cpcap-usb: Improve host vs docked mode detection
  phy: cpcap-usb: Prevent USB line glitches from waking up modem
  phy: mapphone-mdm6600: Fix uninitialized status value regression
  phy: cpcap-usb: Fix flakey host idling and enumerating of devices
  phy: qcom-qmp: Increase PHY ready timeout
  phy: cpcap-usb: Fix error path when no host driver is loaded
parents c1ffba30 4f510aa1
Loading
Loading
Loading
Loading
+90 −38
Original line number Diff line number Diff line
@@ -115,7 +115,7 @@ struct cpcap_usb_ints_state {
enum cpcap_gpio_mode {
	CPCAP_DM_DP,
	CPCAP_MDM_RX_TX,
	CPCAP_UNKNOWN,
	CPCAP_UNKNOWN_DISABLED,	/* Seems to disable USB lines */
	CPCAP_OTG_DM_DP,
};

@@ -134,6 +134,8 @@ struct cpcap_phy_ddata {
	struct iio_channel *id;
	struct regulator *vusb;
	atomic_t active;
	unsigned int vbus_provider:1;
	unsigned int docked:1;
};

static bool cpcap_usb_vbus_valid(struct cpcap_phy_ddata *ddata)
@@ -207,6 +209,19 @@ static int cpcap_phy_get_ints_state(struct cpcap_phy_ddata *ddata,
static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata);
static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata);

static void cpcap_usb_try_musb_mailbox(struct cpcap_phy_ddata *ddata,
				       enum musb_vbus_id_status status)
{
	int error;

	error = musb_mailbox(status);
	if (!error)
		return;

	dev_dbg(ddata->dev, "%s: musb_mailbox failed: %i\n",
		__func__, error);
}

static void cpcap_usb_detect(struct work_struct *work)
{
	struct cpcap_phy_ddata *ddata;
@@ -220,15 +235,13 @@ static void cpcap_usb_detect(struct work_struct *work)
	if (error)
		return;

	if (s.id_ground) {
		dev_dbg(ddata->dev, "id ground, USB host mode\n");
		error = cpcap_usb_set_usb_mode(ddata);
		if (error)
			goto out_err;
	vbus = cpcap_usb_vbus_valid(ddata);

		error = musb_mailbox(MUSB_ID_GROUND);
		if (error)
			goto out_err;
	/* We need to kick the VBUS as USB A-host */
	if (s.id_ground && ddata->vbus_provider) {
		dev_dbg(ddata->dev, "still in USB A-host mode, kicking VBUS\n");

		cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);

		error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
					   CPCAP_BIT_VBUSSTBY_EN |
@@ -240,51 +253,86 @@ static void cpcap_usb_detect(struct work_struct *work)
		return;
	}

	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
				   CPCAP_BIT_VBUSSTBY_EN |
				   CPCAP_BIT_VBUSEN_SPI, 0);
	if (vbus && s.id_ground && ddata->docked) {
		dev_dbg(ddata->dev, "still docked as A-host, signal ID down\n");

		cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);

		return;
	}

	/* No VBUS needed with docks */
	if (vbus && s.id_ground && !ddata->vbus_provider) {
		dev_dbg(ddata->dev, "connected to a dock\n");

		ddata->docked = true;

		error = cpcap_usb_set_usb_mode(ddata);
		if (error)
			goto out_err;

	vbus = cpcap_usb_vbus_valid(ddata);
		cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);

	if (vbus) {
		/* Are we connected to a docking station with vbus? */
		if (s.id_ground) {
			dev_dbg(ddata->dev, "connected to a dock\n");
		/*
		 * Force check state again after musb has reoriented,
		 * otherwise devices won't enumerate after loading PHY
		 * driver.
		 */
		schedule_delayed_work(&ddata->detect_work,
				      msecs_to_jiffies(1000));

		return;
	}

	if (s.id_ground && !ddata->docked) {
		dev_dbg(ddata->dev, "id ground, USB host mode\n");

		ddata->vbus_provider = true;

			/* No VBUS needed with docks */
		error = cpcap_usb_set_usb_mode(ddata);
		if (error)
			goto out_err;
			error = musb_mailbox(MUSB_ID_GROUND);

		cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);

		error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
					   CPCAP_BIT_VBUSSTBY_EN |
					   CPCAP_BIT_VBUSEN_SPI,
					   CPCAP_BIT_VBUSEN_SPI);
		if (error)
			goto out_err;

		return;
	}

	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
				   CPCAP_BIT_VBUSSTBY_EN |
				   CPCAP_BIT_VBUSEN_SPI, 0);
	if (error)
		goto out_err;

	vbus = cpcap_usb_vbus_valid(ddata);

	/* Otherwise assume we're connected to a USB host */
	if (vbus) {
		dev_dbg(ddata->dev, "connected to USB host\n");
		error = cpcap_usb_set_usb_mode(ddata);
		if (error)
			goto out_err;
		error = musb_mailbox(MUSB_VBUS_VALID);
		if (error)
			goto out_err;
		cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_VALID);

		return;
	}

	ddata->vbus_provider = false;
	ddata->docked = false;
	cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_OFF);

	/* Default to debug UART mode */
	error = cpcap_usb_set_uart_mode(ddata);
	if (error)
		goto out_err;

	error = musb_mailbox(MUSB_VBUS_OFF);
	if (error)
		goto out_err;

	dev_dbg(ddata->dev, "set UART mode\n");

	return;
@@ -376,7 +424,8 @@ static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata)
{
	int error;

	error = cpcap_usb_gpio_set_mode(ddata, CPCAP_DM_DP);
	/* Disable lines to prevent glitches from waking up mdm6600 */
	error = cpcap_usb_gpio_set_mode(ddata, CPCAP_UNKNOWN_DISABLED);
	if (error)
		goto out_err;

@@ -403,6 +452,11 @@ static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata)
	if (error)
		goto out_err;

	/* Enable UART mode */
	error = cpcap_usb_gpio_set_mode(ddata, CPCAP_DM_DP);
	if (error)
		goto out_err;

	return 0;

out_err:
@@ -415,7 +469,8 @@ static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata)
{
	int error;

	error = cpcap_usb_gpio_set_mode(ddata, CPCAP_OTG_DM_DP);
	/* Disable lines to prevent glitches from waking up mdm6600 */
	error = cpcap_usb_gpio_set_mode(ddata, CPCAP_UNKNOWN_DISABLED);
	if (error)
		return error;

@@ -434,12 +489,6 @@ static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata)
	if (error)
		goto out_err;

	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC2,
				   CPCAP_BIT_USBXCVREN,
				   CPCAP_BIT_USBXCVREN);
	if (error)
		goto out_err;

	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
				   CPCAP_BIT_PU_SPI |
				   CPCAP_BIT_DMPD_SPI |
@@ -455,6 +504,11 @@ static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata)
	if (error)
		goto out_err;

	/* Enable USB mode */
	error = cpcap_usb_gpio_set_mode(ddata, CPCAP_OTG_DM_DP);
	if (error)
		goto out_err;

	return 0;

out_err:
@@ -649,9 +703,7 @@ static int cpcap_usb_phy_remove(struct platform_device *pdev)
	if (error)
		dev_err(ddata->dev, "could not set UART mode\n");

	error = musb_mailbox(MUSB_VBUS_OFF);
	if (error)
		dev_err(ddata->dev, "could not set mailbox\n");
	cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_OFF);

	usb_remove_phy(&ddata->phy);
	cancel_delayed_work_sync(&ddata->detect_work);
+3 −8
Original line number Diff line number Diff line
@@ -200,7 +200,7 @@ static void phy_mdm6600_status(struct work_struct *work)
	struct phy_mdm6600 *ddata;
	struct device *dev;
	DECLARE_BITMAP(values, PHY_MDM6600_NR_STATUS_LINES);
	int error, i, val = 0;
	int error;

	ddata = container_of(work, struct phy_mdm6600, status_work.work);
	dev = ddata->dev;
@@ -212,16 +212,11 @@ static void phy_mdm6600_status(struct work_struct *work)
	if (error)
		return;

	for (i = 0; i < PHY_MDM6600_NR_STATUS_LINES; i++) {
		val |= test_bit(i, values) << i;
		dev_dbg(ddata->dev, "XXX %s: i: %i values[i]: %i val: %i\n",
			__func__, i, test_bit(i, values), val);
	}
	ddata->status = values[0];
	ddata->status = values[0] & ((1 << PHY_MDM6600_NR_STATUS_LINES) - 1);

	dev_info(dev, "modem status: %i %s\n",
		 ddata->status,
		 phy_mdm6600_status_name[ddata->status & 7]);
		 phy_mdm6600_status_name[ddata->status]);
	complete(&ddata->ack);
}

+1 −1
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@
/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */
#define CLAMP_EN				BIT(0) /* enables i/o clamp_n */

#define PHY_INIT_COMPLETE_TIMEOUT		1000
#define PHY_INIT_COMPLETE_TIMEOUT		10000
#define POWER_DOWN_DELAY_US_MIN			10
#define POWER_DOWN_DELAY_US_MAX			11

+4 −0
Original line number Diff line number Diff line
@@ -603,6 +603,8 @@ static long inno_hdmi_phy_rk3228_clk_round_rate(struct clk_hw *hw,
{
	const struct pre_pll_config *cfg = pre_pll_cfg_table;

	rate = (rate / 1000) * 1000;

	for (; cfg->pixclock != 0; cfg++)
		if (cfg->pixclock == rate && !cfg->fracdiv)
			break;
@@ -755,6 +757,8 @@ static long inno_hdmi_phy_rk3328_clk_round_rate(struct clk_hw *hw,
{
	const struct pre_pll_config *cfg = pre_pll_cfg_table;

	rate = (rate / 1000) * 1000;

	for (; cfg->pixclock != 0; cfg++)
		if (cfg->pixclock == rate)
			break;