Skip to content

Commit 5041a58

Browse files
committed
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
2 parents c1ffba3 + 4f510aa commit 5041a58

File tree

4 files changed

+98
-47
lines changed

4 files changed

+98
-47
lines changed

drivers/phy/motorola/phy-cpcap-usb.c

Lines changed: 90 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ struct cpcap_usb_ints_state {
115115
enum cpcap_gpio_mode {
116116
CPCAP_DM_DP,
117117
CPCAP_MDM_RX_TX,
118-
CPCAP_UNKNOWN,
118+
CPCAP_UNKNOWN_DISABLED, /* Seems to disable USB lines */
119119
CPCAP_OTG_DM_DP,
120120
};
121121

@@ -134,6 +134,8 @@ struct cpcap_phy_ddata {
134134
struct iio_channel *id;
135135
struct regulator *vusb;
136136
atomic_t active;
137+
unsigned int vbus_provider:1;
138+
unsigned int docked:1;
137139
};
138140

139141
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,
207209
static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata);
208210
static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata);
209211

212+
static void cpcap_usb_try_musb_mailbox(struct cpcap_phy_ddata *ddata,
213+
enum musb_vbus_id_status status)
214+
{
215+
int error;
216+
217+
error = musb_mailbox(status);
218+
if (!error)
219+
return;
220+
221+
dev_dbg(ddata->dev, "%s: musb_mailbox failed: %i\n",
222+
__func__, error);
223+
}
224+
210225
static void cpcap_usb_detect(struct work_struct *work)
211226
{
212227
struct cpcap_phy_ddata *ddata;
@@ -220,16 +235,66 @@ static void cpcap_usb_detect(struct work_struct *work)
220235
if (error)
221236
return;
222237

223-
if (s.id_ground) {
224-
dev_dbg(ddata->dev, "id ground, USB host mode\n");
238+
vbus = cpcap_usb_vbus_valid(ddata);
239+
240+
/* We need to kick the VBUS as USB A-host */
241+
if (s.id_ground && ddata->vbus_provider) {
242+
dev_dbg(ddata->dev, "still in USB A-host mode, kicking VBUS\n");
243+
244+
cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
245+
246+
error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
247+
CPCAP_BIT_VBUSSTBY_EN |
248+
CPCAP_BIT_VBUSEN_SPI,
249+
CPCAP_BIT_VBUSEN_SPI);
250+
if (error)
251+
goto out_err;
252+
253+
return;
254+
}
255+
256+
if (vbus && s.id_ground && ddata->docked) {
257+
dev_dbg(ddata->dev, "still docked as A-host, signal ID down\n");
258+
259+
cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
260+
261+
return;
262+
}
263+
264+
/* No VBUS needed with docks */
265+
if (vbus && s.id_ground && !ddata->vbus_provider) {
266+
dev_dbg(ddata->dev, "connected to a dock\n");
267+
268+
ddata->docked = true;
269+
225270
error = cpcap_usb_set_usb_mode(ddata);
226271
if (error)
227272
goto out_err;
228273

229-
error = musb_mailbox(MUSB_ID_GROUND);
274+
cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
275+
276+
/*
277+
* Force check state again after musb has reoriented,
278+
* otherwise devices won't enumerate after loading PHY
279+
* driver.
280+
*/
281+
schedule_delayed_work(&ddata->detect_work,
282+
msecs_to_jiffies(1000));
283+
284+
return;
285+
}
286+
287+
if (s.id_ground && !ddata->docked) {
288+
dev_dbg(ddata->dev, "id ground, USB host mode\n");
289+
290+
ddata->vbus_provider = true;
291+
292+
error = cpcap_usb_set_usb_mode(ddata);
230293
if (error)
231294
goto out_err;
232295

296+
cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
297+
233298
error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
234299
CPCAP_BIT_VBUSSTBY_EN |
235300
CPCAP_BIT_VBUSEN_SPI,
@@ -248,43 +313,26 @@ static void cpcap_usb_detect(struct work_struct *work)
248313

249314
vbus = cpcap_usb_vbus_valid(ddata);
250315

316+
/* Otherwise assume we're connected to a USB host */
251317
if (vbus) {
252-
/* Are we connected to a docking station with vbus? */
253-
if (s.id_ground) {
254-
dev_dbg(ddata->dev, "connected to a dock\n");
255-
256-
/* No VBUS needed with docks */
257-
error = cpcap_usb_set_usb_mode(ddata);
258-
if (error)
259-
goto out_err;
260-
error = musb_mailbox(MUSB_ID_GROUND);
261-
if (error)
262-
goto out_err;
263-
264-
return;
265-
}
266-
267-
/* Otherwise assume we're connected to a USB host */
268318
dev_dbg(ddata->dev, "connected to USB host\n");
269319
error = cpcap_usb_set_usb_mode(ddata);
270320
if (error)
271321
goto out_err;
272-
error = musb_mailbox(MUSB_VBUS_VALID);
273-
if (error)
274-
goto out_err;
322+
cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_VALID);
275323

276324
return;
277325
}
278326

327+
ddata->vbus_provider = false;
328+
ddata->docked = false;
329+
cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_OFF);
330+
279331
/* Default to debug UART mode */
280332
error = cpcap_usb_set_uart_mode(ddata);
281333
if (error)
282334
goto out_err;
283335

284-
error = musb_mailbox(MUSB_VBUS_OFF);
285-
if (error)
286-
goto out_err;
287-
288336
dev_dbg(ddata->dev, "set UART mode\n");
289337

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

379-
error = cpcap_usb_gpio_set_mode(ddata, CPCAP_DM_DP);
427+
/* Disable lines to prevent glitches from waking up mdm6600 */
428+
error = cpcap_usb_gpio_set_mode(ddata, CPCAP_UNKNOWN_DISABLED);
380429
if (error)
381430
goto out_err;
382431

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

455+
/* Enable UART mode */
456+
error = cpcap_usb_gpio_set_mode(ddata, CPCAP_DM_DP);
457+
if (error)
458+
goto out_err;
459+
406460
return 0;
407461

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

418-
error = cpcap_usb_gpio_set_mode(ddata, CPCAP_OTG_DM_DP);
472+
/* Disable lines to prevent glitches from waking up mdm6600 */
473+
error = cpcap_usb_gpio_set_mode(ddata, CPCAP_UNKNOWN_DISABLED);
419474
if (error)
420475
return error;
421476

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

437-
error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC2,
438-
CPCAP_BIT_USBXCVREN,
439-
CPCAP_BIT_USBXCVREN);
440-
if (error)
441-
goto out_err;
442-
443492
error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
444493
CPCAP_BIT_PU_SPI |
445494
CPCAP_BIT_DMPD_SPI |
@@ -455,6 +504,11 @@ static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata)
455504
if (error)
456505
goto out_err;
457506

507+
/* Enable USB mode */
508+
error = cpcap_usb_gpio_set_mode(ddata, CPCAP_OTG_DM_DP);
509+
if (error)
510+
goto out_err;
511+
458512
return 0;
459513

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

652-
error = musb_mailbox(MUSB_VBUS_OFF);
653-
if (error)
654-
dev_err(ddata->dev, "could not set mailbox\n");
706+
cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_OFF);
655707

656708
usb_remove_phy(&ddata->phy);
657709
cancel_delayed_work_sync(&ddata->detect_work);

drivers/phy/motorola/phy-mapphone-mdm6600.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ static void phy_mdm6600_status(struct work_struct *work)
200200
struct phy_mdm6600 *ddata;
201201
struct device *dev;
202202
DECLARE_BITMAP(values, PHY_MDM6600_NR_STATUS_LINES);
203-
int error, i, val = 0;
203+
int error;
204204

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

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

222217
dev_info(dev, "modem status: %i %s\n",
223218
ddata->status,
224-
phy_mdm6600_status_name[ddata->status & 7]);
219+
phy_mdm6600_status_name[ddata->status]);
225220
complete(&ddata->ack);
226221
}
227222

drivers/phy/qualcomm/phy-qcom-qmp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */
6767
#define CLAMP_EN BIT(0) /* enables i/o clamp_n */
6868

69-
#define PHY_INIT_COMPLETE_TIMEOUT 1000
69+
#define PHY_INIT_COMPLETE_TIMEOUT 10000
7070
#define POWER_DOWN_DELAY_US_MIN 10
7171
#define POWER_DOWN_DELAY_US_MAX 11
7272

drivers/phy/rockchip/phy-rockchip-inno-hdmi.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,8 @@ static long inno_hdmi_phy_rk3228_clk_round_rate(struct clk_hw *hw,
603603
{
604604
const struct pre_pll_config *cfg = pre_pll_cfg_table;
605605

606+
rate = (rate / 1000) * 1000;
607+
606608
for (; cfg->pixclock != 0; cfg++)
607609
if (cfg->pixclock == rate && !cfg->fracdiv)
608610
break;
@@ -755,6 +757,8 @@ static long inno_hdmi_phy_rk3328_clk_round_rate(struct clk_hw *hw,
755757
{
756758
const struct pre_pll_config *cfg = pre_pll_cfg_table;
757759

760+
rate = (rate / 1000) * 1000;
761+
758762
for (; cfg->pixclock != 0; cfg++)
759763
if (cfg->pixclock == rate)
760764
break;

0 commit comments

Comments
 (0)