030-v4.17-0001-usb-dwc2-add-support-for-host-mode-external-vbus-sup.patch 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. From 531ef5ebea96394ddb7f554d4d88e017dde30a59 Mon Sep 17 00:00:00 2001
  2. From: Amelie Delaunay <amelie.delaunay@st.com>
  3. Date: Tue, 13 Feb 2018 09:28:12 +0100
  4. Subject: [PATCH] usb: dwc2: add support for host mode external vbus supply
  5. This patch adds a way to enable an external vbus supply in host mode,
  6. when dwc2 drvvbus signal is not used.
  7. This patch is very similar to the one done in U-Boot dwc2 driver [1]. It
  8. also adds dynamic vbus supply management depending on the role and state
  9. of the core.
  10. [1] https://lists.denx.de/pipermail/u-boot/2017-March/283434.html
  11. Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
  12. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
  13. ---
  14. drivers/usb/dwc2/core.h | 2 ++
  15. drivers/usb/dwc2/hcd.c | 26 ++++++++++++++++++++++++++
  16. 2 files changed, 28 insertions(+)
  17. --- a/drivers/usb/dwc2/core.h
  18. +++ b/drivers/usb/dwc2/core.h
  19. @@ -777,6 +777,7 @@ struct dwc2_hregs_backup {
  20. * @plat: The platform specific configuration data. This can be
  21. * removed once all SoCs support usb transceiver.
  22. * @supplies: Definition of USB power supplies
  23. + * @vbus_supply: Regulator supplying vbus.
  24. * @phyif: PHY interface width
  25. * @lock: Spinlock that protects all the driver data structures
  26. * @priv: Stores a pointer to the struct usb_hcd
  27. @@ -914,6 +915,7 @@ struct dwc2_hsotg {
  28. struct usb_phy *uphy;
  29. struct dwc2_hsotg_plat *plat;
  30. struct regulator_bulk_data supplies[DWC2_NUM_SUPPLIES];
  31. + struct regulator *vbus_supply;
  32. u32 phyif;
  33. spinlock_t lock;
  34. --- a/drivers/usb/dwc2/hcd.c
  35. +++ b/drivers/usb/dwc2/hcd.c
  36. @@ -359,6 +359,23 @@ static void dwc2_gusbcfg_init(struct dwc
  37. dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
  38. }
  39. +static int dwc2_vbus_supply_init(struct dwc2_hsotg *hsotg)
  40. +{
  41. + hsotg->vbus_supply = devm_regulator_get_optional(hsotg->dev, "vbus");
  42. + if (IS_ERR(hsotg->vbus_supply))
  43. + return 0;
  44. +
  45. + return regulator_enable(hsotg->vbus_supply);
  46. +}
  47. +
  48. +static int dwc2_vbus_supply_exit(struct dwc2_hsotg *hsotg)
  49. +{
  50. + if (hsotg->vbus_supply)
  51. + return regulator_disable(hsotg->vbus_supply);
  52. +
  53. + return 0;
  54. +}
  55. +
  56. /**
  57. * dwc2_enable_host_interrupts() - Enables the Host mode interrupts
  58. *
  59. @@ -3347,6 +3364,7 @@ static void dwc2_conn_id_status_change(s
  60. /* B-Device connector (Device Mode) */
  61. if (gotgctl & GOTGCTL_CONID_B) {
  62. + dwc2_vbus_supply_exit(hsotg);
  63. /* Wait for switch to device mode */
  64. dev_dbg(hsotg->dev, "connId B\n");
  65. if (hsotg->bus_suspended) {
  66. @@ -4456,6 +4474,9 @@ static int _dwc2_hcd_start(struct usb_hc
  67. }
  68. spin_unlock_irqrestore(&hsotg->lock, flags);
  69. +
  70. + dwc2_vbus_supply_init(hsotg);
  71. +
  72. return 0;
  73. }
  74. @@ -4483,6 +4504,8 @@ static void _dwc2_hcd_stop(struct usb_hc
  75. clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
  76. spin_unlock_irqrestore(&hsotg->lock, flags);
  77. + dwc2_vbus_supply_exit(hsotg);
  78. +
  79. usleep_range(1000, 3000);
  80. }
  81. @@ -4519,6 +4542,7 @@ static int _dwc2_hcd_suspend(struct usb_
  82. hprt0 |= HPRT0_SUSP;
  83. hprt0 &= ~HPRT0_PWR;
  84. dwc2_writel(hprt0, hsotg->regs + HPRT0);
  85. + dwc2_vbus_supply_exit(hsotg);
  86. }
  87. /* Enter hibernation */
  88. @@ -4599,6 +4623,8 @@ static int _dwc2_hcd_resume(struct usb_h
  89. spin_unlock_irqrestore(&hsotg->lock, flags);
  90. dwc2_port_resume(hsotg);
  91. } else {
  92. + dwc2_vbus_supply_init(hsotg);
  93. +
  94. /* Wait for controller to correctly update D+/D- level */
  95. usleep_range(3000, 5000);