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

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
...@@ -115,7 +115,7 @@ struct cpcap_usb_ints_state { ...@@ -115,7 +115,7 @@ struct cpcap_usb_ints_state {
enum cpcap_gpio_mode { enum cpcap_gpio_mode {
CPCAP_DM_DP, CPCAP_DM_DP,
CPCAP_MDM_RX_TX, CPCAP_MDM_RX_TX,
CPCAP_UNKNOWN, CPCAP_UNKNOWN_DISABLED, /* Seems to disable USB lines */
CPCAP_OTG_DM_DP, CPCAP_OTG_DM_DP,
}; };
...@@ -134,6 +134,8 @@ struct cpcap_phy_ddata { ...@@ -134,6 +134,8 @@ struct cpcap_phy_ddata {
struct iio_channel *id; struct iio_channel *id;
struct regulator *vusb; struct regulator *vusb;
atomic_t active; atomic_t active;
unsigned int vbus_provider:1;
unsigned int docked:1;
}; };
static bool cpcap_usb_vbus_valid(struct cpcap_phy_ddata *ddata) 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, ...@@ -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_uart_mode(struct cpcap_phy_ddata *ddata);
static int cpcap_usb_set_usb_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) static void cpcap_usb_detect(struct work_struct *work)
{ {
struct cpcap_phy_ddata *ddata; struct cpcap_phy_ddata *ddata;
...@@ -220,16 +235,66 @@ static void cpcap_usb_detect(struct work_struct *work) ...@@ -220,16 +235,66 @@ static void cpcap_usb_detect(struct work_struct *work)
if (error) if (error)
return; return;
if (s.id_ground) { vbus = cpcap_usb_vbus_valid(ddata);
dev_dbg(ddata->dev, "id ground, USB host mode\n");
/* 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 |
CPCAP_BIT_VBUSEN_SPI,
CPCAP_BIT_VBUSEN_SPI);
if (error)
goto out_err;
return;
}
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); error = cpcap_usb_set_usb_mode(ddata);
if (error) if (error)
goto out_err; goto out_err;
error = musb_mailbox(MUSB_ID_GROUND); cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
/*
* 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;
error = cpcap_usb_set_usb_mode(ddata);
if (error) if (error)
goto out_err; goto out_err;
cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3, error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
CPCAP_BIT_VBUSSTBY_EN | CPCAP_BIT_VBUSSTBY_EN |
CPCAP_BIT_VBUSEN_SPI, CPCAP_BIT_VBUSEN_SPI,
...@@ -248,43 +313,26 @@ static void cpcap_usb_detect(struct work_struct *work) ...@@ -248,43 +313,26 @@ static void cpcap_usb_detect(struct work_struct *work)
vbus = cpcap_usb_vbus_valid(ddata); vbus = cpcap_usb_vbus_valid(ddata);
/* Otherwise assume we're connected to a USB host */
if (vbus) { if (vbus) {
/* Are we connected to a docking station with vbus? */
if (s.id_ground) {
dev_dbg(ddata->dev, "connected to a dock\n");
/* No VBUS needed with docks */
error = cpcap_usb_set_usb_mode(ddata);
if (error)
goto out_err;
error = musb_mailbox(MUSB_ID_GROUND);
if (error)
goto out_err;
return;
}
/* Otherwise assume we're connected to a USB host */
dev_dbg(ddata->dev, "connected to USB host\n"); dev_dbg(ddata->dev, "connected to USB host\n");
error = cpcap_usb_set_usb_mode(ddata); error = cpcap_usb_set_usb_mode(ddata);
if (error) if (error)
goto out_err; goto out_err;
error = musb_mailbox(MUSB_VBUS_VALID); cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_VALID);
if (error)
goto out_err;
return; return;
} }
ddata->vbus_provider = false;
ddata->docked = false;
cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_OFF);
/* Default to debug UART mode */ /* Default to debug UART mode */
error = cpcap_usb_set_uart_mode(ddata); error = cpcap_usb_set_uart_mode(ddata);
if (error) if (error)
goto out_err; goto out_err;
error = musb_mailbox(MUSB_VBUS_OFF);
if (error)
goto out_err;
dev_dbg(ddata->dev, "set UART mode\n"); dev_dbg(ddata->dev, "set UART mode\n");
return; return;
...@@ -376,7 +424,8 @@ static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata) ...@@ -376,7 +424,8 @@ static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata)
{ {
int error; 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) if (error)
goto out_err; goto out_err;
...@@ -403,6 +452,11 @@ static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata) ...@@ -403,6 +452,11 @@ static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata)
if (error) if (error)
goto out_err; goto out_err;
/* Enable UART mode */
error = cpcap_usb_gpio_set_mode(ddata, CPCAP_DM_DP);
if (error)
goto out_err;
return 0; return 0;
out_err: out_err:
...@@ -415,7 +469,8 @@ static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata) ...@@ -415,7 +469,8 @@ static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata)
{ {
int error; 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) if (error)
return error; return error;
...@@ -434,12 +489,6 @@ static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata) ...@@ -434,12 +489,6 @@ static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata)
if (error) if (error)
goto out_err; 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, error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
CPCAP_BIT_PU_SPI | CPCAP_BIT_PU_SPI |
CPCAP_BIT_DMPD_SPI | CPCAP_BIT_DMPD_SPI |
...@@ -455,6 +504,11 @@ static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata) ...@@ -455,6 +504,11 @@ static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata)
if (error) if (error)
goto out_err; goto out_err;
/* Enable USB mode */
error = cpcap_usb_gpio_set_mode(ddata, CPCAP_OTG_DM_DP);
if (error)
goto out_err;
return 0; return 0;
out_err: out_err:
...@@ -649,9 +703,7 @@ static int cpcap_usb_phy_remove(struct platform_device *pdev) ...@@ -649,9 +703,7 @@ static int cpcap_usb_phy_remove(struct platform_device *pdev)
if (error) if (error)
dev_err(ddata->dev, "could not set UART mode\n"); dev_err(ddata->dev, "could not set UART mode\n");
error = musb_mailbox(MUSB_VBUS_OFF); cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_OFF);
if (error)
dev_err(ddata->dev, "could not set mailbox\n");
usb_remove_phy(&ddata->phy); usb_remove_phy(&ddata->phy);
cancel_delayed_work_sync(&ddata->detect_work); cancel_delayed_work_sync(&ddata->detect_work);
......
...@@ -200,7 +200,7 @@ static void phy_mdm6600_status(struct work_struct *work) ...@@ -200,7 +200,7 @@ static void phy_mdm6600_status(struct work_struct *work)
struct phy_mdm6600 *ddata; struct phy_mdm6600 *ddata;
struct device *dev; struct device *dev;
DECLARE_BITMAP(values, PHY_MDM6600_NR_STATUS_LINES); 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); ddata = container_of(work, struct phy_mdm6600, status_work.work);
dev = ddata->dev; dev = ddata->dev;
...@@ -212,16 +212,11 @@ static void phy_mdm6600_status(struct work_struct *work) ...@@ -212,16 +212,11 @@ static void phy_mdm6600_status(struct work_struct *work)
if (error) if (error)
return; return;
for (i = 0; i < PHY_MDM6600_NR_STATUS_LINES; i++) { ddata->status = values[0] & ((1 << PHY_MDM6600_NR_STATUS_LINES) - 1);
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];
dev_info(dev, "modem status: %i %s\n", dev_info(dev, "modem status: %i %s\n",
ddata->status, ddata->status,
phy_mdm6600_status_name[ddata->status & 7]); phy_mdm6600_status_name[ddata->status]);
complete(&ddata->ack); complete(&ddata->ack);
} }
......
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */ /* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */
#define CLAMP_EN BIT(0) /* enables i/o clamp_n */ #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_MIN 10
#define POWER_DOWN_DELAY_US_MAX 11 #define POWER_DOWN_DELAY_US_MAX 11
......
...@@ -603,6 +603,8 @@ static long inno_hdmi_phy_rk3228_clk_round_rate(struct clk_hw *hw, ...@@ -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; const struct pre_pll_config *cfg = pre_pll_cfg_table;
rate = (rate / 1000) * 1000;
for (; cfg->pixclock != 0; cfg++) for (; cfg->pixclock != 0; cfg++)
if (cfg->pixclock == rate && !cfg->fracdiv) if (cfg->pixclock == rate && !cfg->fracdiv)
break; break;
...@@ -755,6 +757,8 @@ static long inno_hdmi_phy_rk3328_clk_round_rate(struct clk_hw *hw, ...@@ -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; const struct pre_pll_config *cfg = pre_pll_cfg_table;
rate = (rate / 1000) * 1000;
for (; cfg->pixclock != 0; cfg++) for (; cfg->pixclock != 0; cfg++)
if (cfg->pixclock == rate) if (cfg->pixclock == rate)
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment