@@ -301,6 +301,97 @@ static void tegra_phy_xusb_utmi_pad_power_down(struct phy *phy)
301
301
tegra186_utmi_bias_pad_power_off (padctl );
302
302
}
303
303
304
+ static int tegra186_xusb_padctl_vbus_override (struct tegra_xusb_padctl * padctl ,
305
+ bool status )
306
+ {
307
+ u32 value ;
308
+
309
+ dev_dbg (padctl -> dev , "%s vbus override\n" , status ? "set" : "clear" );
310
+
311
+ value = padctl_readl (padctl , USB2_VBUS_ID );
312
+
313
+ if (status ) {
314
+ value |= VBUS_OVERRIDE ;
315
+ value &= ~ID_OVERRIDE (~0 );
316
+ value |= ID_OVERRIDE_FLOATING ;
317
+ } else {
318
+ value &= ~VBUS_OVERRIDE ;
319
+ }
320
+
321
+ padctl_writel (padctl , value , USB2_VBUS_ID );
322
+
323
+ return 0 ;
324
+ }
325
+
326
+ static int tegra186_xusb_padctl_id_override (struct tegra_xusb_padctl * padctl ,
327
+ bool status )
328
+ {
329
+ u32 value ;
330
+
331
+ dev_dbg (padctl -> dev , "%s id override\n" , status ? "set" : "clear" );
332
+
333
+ value = padctl_readl (padctl , USB2_VBUS_ID );
334
+
335
+ if (status ) {
336
+ if (value & VBUS_OVERRIDE ) {
337
+ value &= ~VBUS_OVERRIDE ;
338
+ padctl_writel (padctl , value , USB2_VBUS_ID );
339
+ usleep_range (1000 , 2000 );
340
+
341
+ value = padctl_readl (padctl , USB2_VBUS_ID );
342
+ }
343
+
344
+ value &= ~ID_OVERRIDE (~0 );
345
+ value |= ID_OVERRIDE_GROUNDED ;
346
+ } else {
347
+ value &= ~ID_OVERRIDE (~0 );
348
+ value |= ID_OVERRIDE_FLOATING ;
349
+ }
350
+
351
+ padctl_writel (padctl , value , USB2_VBUS_ID );
352
+
353
+ return 0 ;
354
+ }
355
+
356
+ static int tegra186_utmi_phy_set_mode (struct phy * phy , enum phy_mode mode ,
357
+ int submode )
358
+ {
359
+ struct tegra_xusb_lane * lane = phy_get_drvdata (phy );
360
+ struct tegra_xusb_padctl * padctl = lane -> pad -> padctl ;
361
+ struct tegra_xusb_usb2_port * port = tegra_xusb_find_usb2_port (padctl ,
362
+ lane -> index );
363
+ int err = 0 ;
364
+
365
+ mutex_lock (& padctl -> lock );
366
+
367
+ dev_dbg (& port -> base .dev , "%s: mode %d" , __func__ , mode );
368
+
369
+ if (mode == PHY_MODE_USB_OTG ) {
370
+ if (submode == USB_ROLE_HOST ) {
371
+ tegra186_xusb_padctl_id_override (padctl , true);
372
+
373
+ err = regulator_enable (port -> supply );
374
+ } else if (submode == USB_ROLE_DEVICE ) {
375
+ tegra186_xusb_padctl_vbus_override (padctl , true);
376
+ } else if (submode == USB_ROLE_NONE ) {
377
+ /*
378
+ * When port is peripheral only or role transitions to
379
+ * USB_ROLE_NONE from USB_ROLE_DEVICE, regulator is not
380
+ * enabled.
381
+ */
382
+ if (regulator_is_enabled (port -> supply ))
383
+ regulator_disable (port -> supply );
384
+
385
+ tegra186_xusb_padctl_id_override (padctl , false);
386
+ tegra186_xusb_padctl_vbus_override (padctl , false);
387
+ }
388
+ }
389
+
390
+ mutex_unlock (& padctl -> lock );
391
+
392
+ return err ;
393
+ }
394
+
304
395
static int tegra186_utmi_phy_power_on (struct phy * phy )
305
396
{
306
397
struct tegra_xusb_lane * lane = phy_get_drvdata (phy );
@@ -439,6 +530,7 @@ static const struct phy_ops utmi_phy_ops = {
439
530
.exit = tegra186_utmi_phy_exit ,
440
531
.power_on = tegra186_utmi_phy_power_on ,
441
532
.power_off = tegra186_utmi_phy_power_off ,
533
+ .set_mode = tegra186_utmi_phy_set_mode ,
442
534
.owner = THIS_MODULE ,
443
535
};
444
536
@@ -857,28 +949,6 @@ static void tegra186_xusb_padctl_remove(struct tegra_xusb_padctl *padctl)
857
949
{
858
950
}
859
951
860
- static int tegra186_xusb_padctl_vbus_override (struct tegra_xusb_padctl * padctl ,
861
- bool status )
862
- {
863
- u32 value ;
864
-
865
- dev_dbg (padctl -> dev , "%s vbus override\n" , status ? "set" : "clear" );
866
-
867
- value = padctl_readl (padctl , USB2_VBUS_ID );
868
-
869
- if (status ) {
870
- value |= VBUS_OVERRIDE ;
871
- value &= ~ID_OVERRIDE (~0 );
872
- value |= ID_OVERRIDE_FLOATING ;
873
- } else {
874
- value &= ~VBUS_OVERRIDE ;
875
- }
876
-
877
- padctl_writel (padctl , value , USB2_VBUS_ID );
878
-
879
- return 0 ;
880
- }
881
-
882
952
static const struct tegra_xusb_padctl_ops tegra186_xusb_padctl_ops = {
883
953
.probe = tegra186_xusb_padctl_probe ,
884
954
.remove = tegra186_xusb_padctl_remove ,
0 commit comments