0108-usb-mtu3-use-FORCE-RG_IDDIG-to-implement-manual-DRD-.patch 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. From 6c4995c9a8ba8841ba640201636954c84f494587 Mon Sep 17 00:00:00 2001
  2. From: Chunfeng Yun <[email protected]>
  3. Date: Fri, 13 Oct 2017 17:10:42 +0800
  4. Subject: [PATCH 108/224] usb: mtu3: use FORCE/RG_IDDIG to implement manual DRD
  5. switch
  6. In order to keep manual DRD switch independent on IDDIG interrupt,
  7. make use of FORCE/RG_IDDIG instead of IDDIG EINT interrupt to
  8. implement manual DRD switch function.
  9. Signed-off-by: Chunfeng Yun <[email protected]>
  10. Signed-off-by: Felipe Balbi <[email protected]>
  11. ---
  12. drivers/usb/mtu3/mtu3.h | 18 ++++++++----
  13. drivers/usb/mtu3/mtu3_dr.c | 61 ++++++++++++++++++++++++++++++-----------
  14. drivers/usb/mtu3/mtu3_dr.h | 6 ++++
  15. drivers/usb/mtu3/mtu3_host.c | 5 ++++
  16. drivers/usb/mtu3/mtu3_hw_regs.h | 2 ++
  17. drivers/usb/mtu3/mtu3_plat.c | 38 ++-----------------------
  18. 6 files changed, 74 insertions(+), 56 deletions(-)
  19. --- a/drivers/usb/mtu3/mtu3.h
  20. +++ b/drivers/usb/mtu3/mtu3.h
  21. @@ -115,6 +115,19 @@ enum mtu3_g_ep0_state {
  22. };
  23. /**
  24. + * MTU3_DR_FORCE_NONE: automatically switch host and periperal mode
  25. + * by IDPIN signal.
  26. + * MTU3_DR_FORCE_HOST: force to enter host mode and override OTG
  27. + * IDPIN signal.
  28. + * MTU3_DR_FORCE_DEVICE: force to enter peripheral mode.
  29. + */
  30. +enum mtu3_dr_force_mode {
  31. + MTU3_DR_FORCE_NONE = 0,
  32. + MTU3_DR_FORCE_HOST,
  33. + MTU3_DR_FORCE_DEVICE,
  34. +};
  35. +
  36. +/**
  37. * @base: the base address of fifo
  38. * @limit: the bitmap size in bits
  39. * @bitmap: fifo bitmap in unit of @MTU3_EP_FIFO_UNIT
  40. @@ -196,7 +209,6 @@ struct mtu3_gpd_ring {
  41. * xHCI driver initialization, it's necessary for system bootup
  42. * as device.
  43. * @is_u3_drd: whether port0 supports usb3.0 dual-role device or not
  44. -* @id_*: used to maually switch between host and device modes by idpin
  45. * @manual_drd_enabled: it's true when supports dual-role device by debugfs
  46. * to switch host/device modes depending on user input.
  47. */
  48. @@ -207,10 +219,6 @@ struct otg_switch_mtk {
  49. struct notifier_block id_nb;
  50. struct delayed_work extcon_reg_dwork;
  51. bool is_u3_drd;
  52. - /* dual-role switch by debugfs */
  53. - struct pinctrl *id_pinctrl;
  54. - struct pinctrl_state *id_float;
  55. - struct pinctrl_state *id_ground;
  56. bool manual_drd_enabled;
  57. };
  58. --- a/drivers/usb/mtu3/mtu3_dr.c
  59. +++ b/drivers/usb/mtu3/mtu3_dr.c
  60. @@ -261,21 +261,22 @@ static void extcon_register_dwork(struct
  61. * depending on user input.
  62. * This is useful in special cases, such as uses TYPE-A receptacle but also
  63. * wants to support dual-role mode.
  64. - * It generates cable state changes by pulling up/down IDPIN and
  65. - * notifies driver to switch mode by "extcon-usb-gpio".
  66. - * NOTE: when use MICRO receptacle, should not enable this interface.
  67. */
  68. static void ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host)
  69. {
  70. struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
  71. - if (to_host)
  72. - pinctrl_select_state(otg_sx->id_pinctrl, otg_sx->id_ground);
  73. - else
  74. - pinctrl_select_state(otg_sx->id_pinctrl, otg_sx->id_float);
  75. + if (to_host) {
  76. + ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_HOST);
  77. + ssusb_set_mailbox(otg_sx, MTU3_VBUS_OFF);
  78. + ssusb_set_mailbox(otg_sx, MTU3_ID_GROUND);
  79. + } else {
  80. + ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_DEVICE);
  81. + ssusb_set_mailbox(otg_sx, MTU3_ID_FLOAT);
  82. + ssusb_set_mailbox(otg_sx, MTU3_VBUS_VALID);
  83. + }
  84. }
  85. -
  86. static int ssusb_mode_show(struct seq_file *sf, void *unused)
  87. {
  88. struct ssusb_mtk *ssusb = sf->private;
  89. @@ -388,17 +389,45 @@ static void ssusb_debugfs_exit(struct ss
  90. debugfs_remove_recursive(ssusb->dbgfs_root);
  91. }
  92. +void ssusb_set_force_mode(struct ssusb_mtk *ssusb,
  93. + enum mtu3_dr_force_mode mode)
  94. +{
  95. + u32 value;
  96. +
  97. + value = mtu3_readl(ssusb->ippc_base, SSUSB_U2_CTRL(0));
  98. + switch (mode) {
  99. + case MTU3_DR_FORCE_DEVICE:
  100. + value |= SSUSB_U2_PORT_FORCE_IDDIG | SSUSB_U2_PORT_RG_IDDIG;
  101. + break;
  102. + case MTU3_DR_FORCE_HOST:
  103. + value |= SSUSB_U2_PORT_FORCE_IDDIG;
  104. + value &= ~SSUSB_U2_PORT_RG_IDDIG;
  105. + break;
  106. + case MTU3_DR_FORCE_NONE:
  107. + value &= ~(SSUSB_U2_PORT_FORCE_IDDIG | SSUSB_U2_PORT_RG_IDDIG);
  108. + break;
  109. + default:
  110. + return;
  111. + }
  112. + mtu3_writel(ssusb->ippc_base, SSUSB_U2_CTRL(0), value);
  113. +}
  114. +
  115. int ssusb_otg_switch_init(struct ssusb_mtk *ssusb)
  116. {
  117. struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
  118. - INIT_DELAYED_WORK(&otg_sx->extcon_reg_dwork, extcon_register_dwork);
  119. -
  120. - if (otg_sx->manual_drd_enabled)
  121. + if (otg_sx->manual_drd_enabled) {
  122. ssusb_debugfs_init(ssusb);
  123. + } else {
  124. + INIT_DELAYED_WORK(&otg_sx->extcon_reg_dwork,
  125. + extcon_register_dwork);
  126. - /* It is enough to delay 1s for waiting for host initialization */
  127. - schedule_delayed_work(&otg_sx->extcon_reg_dwork, HZ);
  128. + /*
  129. + * It is enough to delay 1s for waiting for
  130. + * host initialization
  131. + */
  132. + schedule_delayed_work(&otg_sx->extcon_reg_dwork, HZ);
  133. + }
  134. return 0;
  135. }
  136. @@ -407,8 +436,8 @@ void ssusb_otg_switch_exit(struct ssusb_
  137. {
  138. struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
  139. - cancel_delayed_work(&otg_sx->extcon_reg_dwork);
  140. -
  141. if (otg_sx->manual_drd_enabled)
  142. ssusb_debugfs_exit(ssusb);
  143. + else
  144. + cancel_delayed_work(&otg_sx->extcon_reg_dwork);
  145. }
  146. --- a/drivers/usb/mtu3/mtu3_dr.h
  147. +++ b/drivers/usb/mtu3/mtu3_dr.h
  148. @@ -87,6 +87,8 @@ static inline void ssusb_gadget_exit(str
  149. int ssusb_otg_switch_init(struct ssusb_mtk *ssusb);
  150. void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb);
  151. int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on);
  152. +void ssusb_set_force_mode(struct ssusb_mtk *ssusb,
  153. + enum mtu3_dr_force_mode mode);
  154. #else
  155. @@ -103,6 +105,10 @@ static inline int ssusb_set_vbus(struct
  156. return 0;
  157. }
  158. +static inline void
  159. +ssusb_set_force_mode(struct ssusb_mtk *ssusb, enum mtu3_dr_force_mode mode)
  160. +{}
  161. +
  162. #endif
  163. #endif /* _MTU3_DR_H_ */
  164. --- a/drivers/usb/mtu3/mtu3_host.c
  165. +++ b/drivers/usb/mtu3/mtu3_host.c
  166. @@ -189,6 +189,8 @@ int ssusb_host_disable(struct ssusb_mtk
  167. static void ssusb_host_setup(struct ssusb_mtk *ssusb)
  168. {
  169. + struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
  170. +
  171. host_ports_num_get(ssusb);
  172. /*
  173. @@ -197,6 +199,9 @@ static void ssusb_host_setup(struct ssus
  174. */
  175. ssusb_host_enable(ssusb);
  176. + if (otg_sx->manual_drd_enabled)
  177. + ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_HOST);
  178. +
  179. /* if port0 supports dual-role, works as host mode by default */
  180. ssusb_set_vbus(&ssusb->otg_switch, 1);
  181. }
  182. --- a/drivers/usb/mtu3/mtu3_hw_regs.h
  183. +++ b/drivers/usb/mtu3/mtu3_hw_regs.h
  184. @@ -472,6 +472,8 @@
  185. #define SSUSB_U3_PORT_DIS BIT(0)
  186. /* U3D_SSUSB_U2_CTRL_0P */
  187. +#define SSUSB_U2_PORT_RG_IDDIG BIT(12)
  188. +#define SSUSB_U2_PORT_FORCE_IDDIG BIT(11)
  189. #define SSUSB_U2_PORT_VBUSVALID BIT(9)
  190. #define SSUSB_U2_PORT_OTG_SEL BIT(7)
  191. #define SSUSB_U2_PORT_HOST BIT(2)
  192. --- a/drivers/usb/mtu3/mtu3_plat.c
  193. +++ b/drivers/usb/mtu3/mtu3_plat.c
  194. @@ -21,7 +21,6 @@
  195. #include <linux/module.h>
  196. #include <linux/of_address.h>
  197. #include <linux/of_irq.h>
  198. -#include <linux/pinctrl/consumer.h>
  199. #include <linux/platform_device.h>
  200. #include "mtu3.h"
  201. @@ -212,33 +211,6 @@ static void ssusb_ip_sw_reset(struct ssu
  202. mtu3_clrbits(ssusb->ippc_base, U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST);
  203. }
  204. -static int get_iddig_pinctrl(struct ssusb_mtk *ssusb)
  205. -{
  206. - struct otg_switch_mtk *otg_sx = &ssusb->otg_switch;
  207. -
  208. - otg_sx->id_pinctrl = devm_pinctrl_get(ssusb->dev);
  209. - if (IS_ERR(otg_sx->id_pinctrl)) {
  210. - dev_err(ssusb->dev, "Cannot find id pinctrl!\n");
  211. - return PTR_ERR(otg_sx->id_pinctrl);
  212. - }
  213. -
  214. - otg_sx->id_float =
  215. - pinctrl_lookup_state(otg_sx->id_pinctrl, "id_float");
  216. - if (IS_ERR(otg_sx->id_float)) {
  217. - dev_err(ssusb->dev, "Cannot find pinctrl id_float!\n");
  218. - return PTR_ERR(otg_sx->id_float);
  219. - }
  220. -
  221. - otg_sx->id_ground =
  222. - pinctrl_lookup_state(otg_sx->id_pinctrl, "id_ground");
  223. - if (IS_ERR(otg_sx->id_ground)) {
  224. - dev_err(ssusb->dev, "Cannot find pinctrl id_ground!\n");
  225. - return PTR_ERR(otg_sx->id_ground);
  226. - }
  227. -
  228. - return 0;
  229. -}
  230. -
  231. /* ignore the error if the clock does not exist */
  232. static struct clk *get_optional_clk(struct device *dev, const char *id)
  233. {
  234. @@ -349,15 +321,11 @@ static int get_ssusb_rscs(struct platfor
  235. dev_err(ssusb->dev, "couldn't get extcon device\n");
  236. return -EPROBE_DEFER;
  237. }
  238. - if (otg_sx->manual_drd_enabled) {
  239. - ret = get_iddig_pinctrl(ssusb);
  240. - if (ret)
  241. - return ret;
  242. - }
  243. }
  244. - dev_info(dev, "dr_mode: %d, is_u3_dr: %d, u3p_dis_msk:%x\n",
  245. - ssusb->dr_mode, otg_sx->is_u3_drd, ssusb->u3p_dis_msk);
  246. + dev_info(dev, "dr_mode: %d, is_u3_dr: %d, u3p_dis_msk: %x, drd: %s\n",
  247. + ssusb->dr_mode, otg_sx->is_u3_drd, ssusb->u3p_dis_msk,
  248. + otg_sx->manual_drd_enabled ? "manual" : "auto");
  249. return 0;
  250. }