0021-usb-fotg210-udc-Implement-VBUS-session.patch 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. From 2fbbfb2c556944945639b17b13fcb1e05272b646 Mon Sep 17 00:00:00 2001
  2. From: Linus Walleij <[email protected]>
  3. Date: Wed, 18 Jan 2023 08:09:21 +0100
  4. Subject: [PATCH 21/29] usb: fotg210-udc: Implement VBUS session
  5. Implement VBUS session handling for FOTG210. This is
  6. mainly used by the UDC driver which needs to call down to
  7. the FOTG210 core and enable/disable VBUS, as this needs to be
  8. handled outside of the HCD and UDC drivers, by platform
  9. specific glue code.
  10. The Gemini has a special bit in a system register to turn
  11. VBUS on and off so we implement this in the FOTG210 core.
  12. Signed-off-by: Linus Walleij <[email protected]>
  13. Link: https://lore.kernel.org/r/[email protected]
  14. Signed-off-by: Greg Kroah-Hartman <[email protected]>
  15. ---
  16. --- a/drivers/usb/fotg210/fotg210-core.c
  17. +++ b/drivers/usb/fotg210/fotg210-core.c
  18. @@ -95,6 +95,35 @@ static int fotg210_gemini_init(struct fo
  19. return 0;
  20. }
  21. +/**
  22. + * fotg210_vbus() - Called by gadget driver to enable/disable VBUS
  23. + * @enable: true to enable VBUS, false to disable VBUS
  24. + */
  25. +void fotg210_vbus(struct fotg210 *fotg, bool enable)
  26. +{
  27. + u32 mask;
  28. + u32 val;
  29. + int ret;
  30. +
  31. + switch (fotg->port) {
  32. + case GEMINI_PORT_0:
  33. + mask = GEMINI_MISC_USB0_VBUS_ON;
  34. + val = enable ? GEMINI_MISC_USB0_VBUS_ON : 0;
  35. + break;
  36. + case GEMINI_PORT_1:
  37. + mask = GEMINI_MISC_USB1_VBUS_ON;
  38. + val = enable ? GEMINI_MISC_USB1_VBUS_ON : 0;
  39. + break;
  40. + default:
  41. + return;
  42. + }
  43. + ret = regmap_update_bits(fotg->map, GEMINI_GLOBAL_MISC_CTRL, mask, val);
  44. + if (ret)
  45. + dev_err(fotg->dev, "failed to %s VBUS\n",
  46. + enable ? "enable" : "disable");
  47. + dev_info(fotg->dev, "%s: %s VBUS\n", __func__, enable ? "enable" : "disable");
  48. +}
  49. +
  50. static int fotg210_probe(struct platform_device *pdev)
  51. {
  52. struct device *dev = &pdev->dev;
  53. --- a/drivers/usb/fotg210/fotg210-udc.c
  54. +++ b/drivers/usb/fotg210/fotg210-udc.c
  55. @@ -1095,9 +1095,26 @@ static int fotg210_udc_stop(struct usb_g
  56. return 0;
  57. }
  58. +/**
  59. + * fotg210_vbus_session - Called by external transceiver to enable/disable udc
  60. + * @_gadget: usb gadget
  61. + * @is_active: 0 if should disable UDC VBUS, 1 if should enable
  62. + *
  63. + * Returns 0
  64. + */
  65. +static int fotg210_vbus_session(struct usb_gadget *g, int is_active)
  66. +{
  67. + struct fotg210_udc *fotg210 = gadget_to_fotg210(g);
  68. +
  69. + /* Call down to core integration layer to drive or disable VBUS */
  70. + fotg210_vbus(fotg210->fotg, is_active);
  71. + return 0;
  72. +}
  73. +
  74. static const struct usb_gadget_ops fotg210_gadget_ops = {
  75. .udc_start = fotg210_udc_start,
  76. .udc_stop = fotg210_udc_stop,
  77. + .vbus_session = fotg210_vbus_session,
  78. };
  79. /**
  80. --- a/drivers/usb/fotg210/fotg210.h
  81. +++ b/drivers/usb/fotg210/fotg210.h
  82. @@ -17,6 +17,8 @@ struct fotg210 {
  83. enum gemini_port port;
  84. };
  85. +void fotg210_vbus(struct fotg210 *fotg, bool enable);
  86. +
  87. #ifdef CONFIG_USB_FOTG210_HCD
  88. int fotg210_hcd_probe(struct platform_device *pdev, struct fotg210 *fotg);
  89. int fotg210_hcd_remove(struct platform_device *pdev);