musb_init.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878
  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/sched.h>
  4. #include <linux/init.h>
  5. #include <linux/list.h>
  6. #include <linux/gpio.h>
  7. #include <linux/io.h>
  8. #include <linux/platform_device.h>
  9. #include <linux/dma-mapping.h>
  10. #include <linux/prefetch.h>
  11. #include <asm/cacheflush.h>
  12. #include "musb_core.h"
  13. #include "ssusb_qmu.h"
  14. #include "mu3d_hal_osal.h"
  15. #include "mu3d_hal_phy.h"
  16. #include "mu3d_hal_usb_drv.h"
  17. #include "musb_gadget.h"
  18. #ifdef CONFIG_PROJECT_PHY
  19. #include "mtk-phy-asic.h"
  20. #endif
  21. #ifdef CONFIG_OF
  22. #include <linux/of_device.h>
  23. #endif
  24. #ifdef CONFIG_USBIF_COMPLIANCE
  25. static struct musb_fifo_cfg mtu3d_cfg[] = {
  26. #else
  27. static struct musb_fifo_cfg mtu3d_cfg[] __initdata = {
  28. #endif
  29. {.hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 1024,},
  30. {.hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 1024,},
  31. {.hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 1024,},
  32. {.hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 1024,},
  33. {.hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 1024,},
  34. {.hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 1024,},
  35. {.hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 1024,},
  36. {.hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 1024,},
  37. {.hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 1024,},
  38. {.hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 1024,},
  39. {.hw_ep_num = 6, .style = FIFO_TX, .maxpacket = 1024,},
  40. {.hw_ep_num = 6, .style = FIFO_RX, .maxpacket = 1024,},
  41. {.hw_ep_num = 7, .style = FIFO_TX, .maxpacket = 1024,},
  42. {.hw_ep_num = 7, .style = FIFO_RX, .maxpacket = 1024,},
  43. {.hw_ep_num = 8, .style = FIFO_TX, .maxpacket = 1024,},
  44. {.hw_ep_num = 8, .style = FIFO_RX, .maxpacket = 1024,},
  45. };
  46. static struct musb_hdrc_config mtu3d_config = {
  47. .multipoint = false,
  48. /* FIXME:Seems no need */
  49. /* .soft_con = true, */
  50. .dma = true,
  51. .num_eps = 9, /*EP0 ~ EP8 */
  52. .dma_channels = 8,
  53. .ram_bits = 12,
  54. .fifo_cfg = mtu3d_cfg,
  55. .fifo_cfg_size = ARRAY_SIZE(mtu3d_cfg),
  56. };
  57. #ifdef CONFIG_USB_MTK_DUALMODE
  58. static struct pinctrl *pinctrl;
  59. static struct pinctrl_state *pinctrl_iddig;
  60. #endif
  61. static int mtu3d_musb_init(struct musb *musb);
  62. static int mtu3d_musb_exit(struct musb *musb);
  63. static void mtu3d_musb_enable(struct musb *musb);
  64. static void mtu3d_musb_disable(struct musb *musb);
  65. static const struct musb_platform_ops mtu3d_ops = {
  66. .init = mtu3d_musb_init,
  67. .exit = mtu3d_musb_exit,
  68. .enable = mtu3d_musb_enable,
  69. .disable = mtu3d_musb_disable
  70. };
  71. static struct musb_hdrc_platform_data mtu3d_data = {
  72. .mode = MUSB_PERIPHERAL,
  73. .config = &mtu3d_config,
  74. .platform_ops = &mtu3d_ops,
  75. };
  76. static const struct of_device_id mtu3d_of_match[] = {
  77. {
  78. .compatible = "mediatek,USB3",
  79. .data = &mtu3d_data,
  80. },
  81. {},
  82. };
  83. struct mtu3d_glue {
  84. struct device *dev;
  85. struct platform_device *musb;
  86. };
  87. #define glue_to_musb(g) platform_get_drvdata(g->musb)
  88. static void mtu3d_musb_reg_init(struct musb *musb);
  89. static int mtu3d_set_power(struct usb_phy *x, unsigned mA);
  90. static u32 sts_ltssm;
  91. #ifdef CONFIG_USBIF_COMPLIANCE
  92. void init_check_ltssm_work(void)
  93. {
  94. sts_ltssm = 0;
  95. }
  96. #endif
  97. /*
  98. * This work is to fix IOT problem.
  99. * 1. PC(Lenovo MT-M5852-B88) + USB Host PCI-e TI(TUSB7340) or Fresco,
  100. * --> PC enter SLERP/HIBERNATION --> USER wake up PC --> PC can not detect device.
  101. * 2. PC(Lenovo MT-M5852-B88) + USB Host PCI-e Fresco,
  102. * --> PC COLD reboot --> PC can not detect device.
  103. * The root cause is that device try to link host too early. XHCI host does not ready to linkup.
  104. * So create a delayed work to re-tran when device is stuck at RxDetect.
  105. */
  106. void check_ltssm_work(struct work_struct *data)
  107. {
  108. /* struct musb *musb = container_of(to_delayed_work(data), struct musb, check_ltssm_work); */
  109. #ifndef CONFIG_USBIF_COMPLIANCE
  110. os_printk(K_INFO, "%s %x\n", __func__, sts_ltssm);
  111. if (sts_ltssm == RXDET_SUCCESS_INTR) {
  112. sts_ltssm = 0;
  113. mu3d_hal_u3dev_dis();
  114. mdelay(10);
  115. mu3d_hal_u3dev_en();
  116. }
  117. #endif
  118. }
  119. #ifndef CONFIG_USBIF_COMPLIANCE
  120. /*
  121. * The workaround for IOT issue.
  122. * Lenovo PC(MT-M 5852-B88) + Asmedia U3 Host controller
  123. * The device stays at "SS" when connecting with PC.
  124. * But after restarting PC, the device would stay at "HS".
  125. */
  126. void reconnect_work(struct work_struct *data)
  127. {
  128. os_printk(K_INFO, "%s\n", __func__);
  129. /* Disable U2 detect */
  130. mu3d_hal_u3dev_dis();
  131. mu3d_hal_u2dev_disconn();
  132. mdelay(1000);
  133. mu3d_hal_u3dev_en();
  134. }
  135. #endif
  136. static inline void mtu3d_u3_ltssm_intr_handler(struct musb *musb, u32 dwLtssmValue)
  137. {
  138. static u32 soft_conn_num;
  139. if (dwLtssmValue & SS_DISABLE_INTR) {
  140. os_printk(K_INFO, "LTSSM: SS_DISABLE_INTR [%d] & Set SOFT_CONN=1\n",
  141. soft_conn_num++);
  142. /* enable U2 link. after host reset, HS/FS EP0 configuration is applied in musb_g_reset */
  143. os_clrmsk(U3D_SSUSB_U2_CTRL_0P, SSUSB_U2_PORT_PDN);
  144. os_setmsk(U3D_POWER_MANAGEMENT, SOFT_CONN);
  145. sts_ltssm = SS_DISABLE_INTR;
  146. }
  147. if (dwLtssmValue & ENTER_U0_INTR) {
  148. soft_conn_num = 0;
  149. /* do not apply U3 EP0 setting again, if the speed is already U3 */
  150. /* LTSSM may go to recovery and back to U0 */
  151. if (musb->g.speed != USB_SPEED_SUPER) {
  152. os_printk(K_INFO, "LTSSM: ENTER_U0_INTR %d\n", musb->g.speed);
  153. musb_conifg_ep0(musb);
  154. }
  155. cancel_delayed_work(&musb->check_ltssm_work);
  156. sts_ltssm = ENTER_U0_INTR;
  157. }
  158. if (dwLtssmValue & VBUS_FALL_INTR) {
  159. os_printk(K_INFO, "LTSSM: VBUS_FALL_INTR\n");
  160. mu3d_hal_pdn_ip_port(1, 1, 1, 1);
  161. mu3d_hal_u3dev_dis();
  162. }
  163. if (dwLtssmValue & VBUS_RISE_INTR) {
  164. os_printk(K_INFO, "LTSSM: VBUS_RISE_INTR\n");
  165. mu3d_hal_u3dev_en();
  166. }
  167. if (dwLtssmValue & ENTER_U3_INTR) {
  168. os_printk(K_INFO, "LTSSM: ENTER_U3_INTR\n");
  169. mu3d_hal_pdn_ip_port(0, 0, 1, 0);
  170. sts_ltssm = ENTER_U3_INTR;
  171. }
  172. #ifndef POWER_SAVING_MODE
  173. if (dwLtssmValue & U3_RESUME_INTR) {
  174. os_printk(K_INFO, "LTSSM: RESUME_INTR\n");
  175. mu3d_hal_pdn_ip_port(1, 0, 1, 0);
  176. os_writel(U3D_LINK_POWER_CONTROL, os_readl(U3D_LINK_POWER_CONTROL) | UX_EXIT);
  177. }
  178. #endif
  179. if (dwLtssmValue & EXIT_U3_INTR) {
  180. os_printk(K_INFO, "LTSSM: EXIT_U3_INTR\n");
  181. mu3d_hal_pdn_ip_port(1, 0, 1, 0);
  182. sts_ltssm = EXIT_U3_INTR;
  183. }
  184. /*7.5.12.2 Hot Reset Requirements
  185. * 1. A downstream port shall reset its Link Error Count as defined in Section 7.4.2.
  186. * 2. A downstream port shall reset its PM timers and the associated U1 and U2 timeout values to zero.
  187. * 3. The port Configuration information shall remain unchanged (refer to Section 8.4.6 for details).
  188. * 4. The port shall maintain its transmitter specifications defined in Table 6-10.
  189. * 5. The port shall maintain its low-impedance receiver termination (RRX-DC) defined in Table 6-13.
  190. */
  191. if (dwLtssmValue & HOT_RST_INTR) {
  192. DEV_INT32 link_err_cnt;
  193. DEV_INT32 timeout_val;
  194. os_printk(K_INFO, "LTSSM: HOT_RST_INTR\n");
  195. /* Clear link error count */
  196. link_err_cnt = os_readl(U3D_LINK_ERR_COUNT);
  197. os_printk(K_INFO, "LTSSM: link_err_cnt=%x\n", link_err_cnt);
  198. os_writel(U3D_LINK_ERR_COUNT, CLR_LINK_ERR_CNT);
  199. /* Clear U1 & U2 Enable */
  200. os_clrmsk(U3D_LINK_POWER_CONTROL, (SW_U1_ACCEPT_ENABLE | SW_U2_ACCEPT_ENABLE));
  201. pwr_params.bU1Enabled = 0;
  202. pwr_params.bU2Enabled = 0;
  203. /* Reset U1 & U2 timeout value */
  204. timeout_val = os_readl(U3D_LINK_UX_INACT_TIMER);
  205. os_printk(K_INFO, "LTSSM: timer_val =%x\n", timeout_val);
  206. timeout_val &= ~(U1_INACT_TIMEOUT_VALUE | DEV_U2_INACT_TIMEOUT_VALUE);
  207. os_writel(U3D_LINK_UX_INACT_TIMER, timeout_val);
  208. }
  209. if (dwLtssmValue & SS_INACTIVE_INTR) {
  210. os_printk(K_INFO, "LTSSM: SS_INACTIVE_INTR\n");
  211. sts_ltssm = SS_INACTIVE_INTR;
  212. }
  213. if (dwLtssmValue & RECOVERY_INTR) {
  214. os_printk(K_DEBUG, "LTSSM: RECOVERY_INTR\n");
  215. sts_ltssm = RECOVERY_INTR;
  216. }
  217. /* A completion of a Warm Reset shall result in the following.
  218. * 1. A downstream port shall reset its Link Error Count.
  219. * 2. Port configuration information of an upstream port shall be reset to default values. Refer to
  220. * Sections 8.4.5 and 8.4.6 for details.
  221. * 3. The PHY level variables (such as Rx equalization settings) shall be reinitialized or retrained.
  222. * 4. The LTSSM of a port shall transition to U0 through RxDetect and Polling.
  223. */
  224. if (dwLtssmValue & WARM_RST_INTR) {
  225. DEV_INT32 link_err_cnt;
  226. os_printk(K_INFO, "LTSSM: WARM_RST_INTR\n");
  227. /* Clear link error count */
  228. link_err_cnt = os_readl(U3D_LINK_ERR_COUNT);
  229. os_printk(K_INFO, "LTSSM: link_err_cnt=%x\n", link_err_cnt);
  230. os_writel(U3D_LINK_ERR_COUNT, CLR_LINK_ERR_CNT);
  231. cancel_delayed_work(&musb->check_ltssm_work);
  232. sts_ltssm = WARM_RST_INTR;
  233. }
  234. if (dwLtssmValue & ENTER_U2_INTR)
  235. os_printk(K_DEBUG, "LTSSM: ENTER_U2_INTR\n");
  236. if (dwLtssmValue & ENTER_U1_INTR)
  237. os_printk(K_DEBUG, "LTSSM: ENTER_U1_INTR\n");
  238. if (dwLtssmValue & RXDET_SUCCESS_INTR) {
  239. /*create a delay work. This work will work after 0.5sec.
  240. If LTSSM state is still at RxDet. Clear USB3_EN and set again. */
  241. os_printk(K_INFO, "LTSSM: RXDET_SUCCESS_INTR\n");
  242. sts_ltssm = RXDET_SUCCESS_INTR;
  243. schedule_delayed_work_on(0, &musb->check_ltssm_work, msecs_to_jiffies(1000));
  244. }
  245. }
  246. static inline void mtu3d_u2_common_intr_handler(u32 dwIntrUsbValue)
  247. {
  248. if (dwIntrUsbValue & DISCONN_INTR) {
  249. mu3d_hal_pdn_ip_port(1, 0, 1, 1);
  250. os_printk(K_NOTICE, "[U2 DISCONN_INTR] Set SOFT_CONN=0\n");
  251. os_clrmsk(U3D_POWER_MANAGEMENT, SOFT_CONN);
  252. /*TODO-J: ADD musb_g_disconnect(musb);?? */
  253. }
  254. if (dwIntrUsbValue & LPM_INTR) {
  255. u32 rmwake;
  256. rmwake = os_readl(U3D_POWER_MANAGEMENT);
  257. os_printk(K_NOTICE, "[U2 LPM interrupt] last rmwake is 0x%x\n", rmwake & LPM_RWP);
  258. if (!((os_readl(U3D_POWER_MANAGEMENT) & LPM_HRWE)))
  259. mu3d_hal_pdn_ip_port(0, 0, 0, 1);
  260. #ifdef CONFIG_USBIF_COMPLIANCE
  261. /* SW word around for USBIF test with Fresco FL1100 with LPM L1C enabling */
  262. #if 0
  263. if (rmwake & LPM_RWP) {
  264. os_writel(U3D_USB20_MISC_CONTROL,
  265. os_readl(U3D_USB20_MISC_CONTROL) | LPM_U3_ACK_EN);
  266. os_writel(U3D_POWER_MANAGEMENT, os_readl(U3D_POWER_MANAGEMENT) | RESUME);
  267. }
  268. #endif
  269. #endif
  270. }
  271. if (dwIntrUsbValue & LPM_RESUME_INTR) {
  272. if (!(os_readl(U3D_POWER_MANAGEMENT) & LPM_HRWE)) {
  273. mu3d_hal_pdn_ip_port(1, 0, 0, 1);
  274. os_writel(U3D_USB20_MISC_CONTROL,
  275. os_readl(U3D_USB20_MISC_CONTROL) | LPM_U3_ACK_EN);
  276. }
  277. }
  278. if (dwIntrUsbValue & SUSPEND_INTR) {
  279. os_printk(K_NOTICE, "[U2 SUSPEND_INTR]\n");
  280. mu3d_hal_pdn_ip_port(0, 0, 0, 1);
  281. }
  282. if (dwIntrUsbValue & RESUME_INTR) {
  283. os_printk(K_NOTICE, "[U2 RESUME_INTR]\n");
  284. mu3d_hal_pdn_ip_port(1, 0, 0, 1);
  285. }
  286. if (dwIntrUsbValue & RESET_INTR)
  287. os_printk(K_NOTICE, "[U2 RESET_INTR]\n");
  288. }
  289. static inline void mtu3d_link_intr_handler(struct musb *musb, u32 dwLinkIntValue)
  290. {
  291. u32 dwTemp;
  292. #ifndef CONFIG_USBIF_COMPLIANCE
  293. static u32 speed_last = SSUSB_SPEED_INACTIVE;
  294. static u32 speed = SSUSB_SPEED_INACTIVE;
  295. static struct timespec ss_timestamp = { 0, 0 };
  296. #endif
  297. dwTemp = os_readl(U3D_DEVICE_CONF) & SSUSB_DEV_SPEED;
  298. mu3d_hal_pdn_cg_en();
  299. switch (dwTemp) {
  300. case SSUSB_SPEED_FULL:
  301. os_printk(K_ALET, "USB Speed = Full Speed\n");
  302. #ifndef CONFIG_USBIF_COMPLIANCE
  303. speed_last = speed;
  304. speed = SSUSB_SPEED_FULL;
  305. #endif
  306. #ifdef CONFIG_PROJECT_PHY
  307. /* Comment from CC Chou.
  308. * When detecting HS or FS and setting RG_USB20_SW_PLLMODE=1, It is OK to enter LPM L1 with BESL=0.
  309. * When disconnecting, set RG_USB20_SW_PLLMODE=0 back.
  310. */
  311. os_setmsk(U3D_U2PHYDCR1, (0x1 << E60802_RG_USB20_SW_PLLMODE_OFST));
  312. /*BESLCK = 0 < BESLCK_U3 = 1 < BESLDCK = 15 */
  313. os_writel(U3D_USB20_LPM_PARAMETER, 0x10f0);
  314. /*
  315. * The default value of LPM_BESL_STALL and LPM_BESLD_STALL are 1.
  316. * So Does _NOT_ need to set.
  317. */
  318. /*os_setmsk(U3D_POWER_MANAGEMENT, (LPM_BESL_STALL|LPM_BESLD_STALL)); */
  319. #else
  320. /*BESLCK = 4 < BESLCK_U3 = 10 < BESLDCK = 15 */
  321. os_writel(U3D_USB20_LPM_PARAMETER, 0xa4f0);
  322. os_setmsk(U3D_POWER_MANAGEMENT, (LPM_BESL_STALL | LPM_BESLD_STALL));
  323. #endif
  324. break;
  325. case SSUSB_SPEED_HIGH:
  326. os_printk(K_ALET, "USB Speed = High Speed\n");
  327. #ifndef CONFIG_USBIF_COMPLIANCE
  328. if ((speed == SSUSB_SPEED_INACTIVE) && (speed_last == SSUSB_SPEED_SUPER)) {
  329. struct timespec tmp = get_connect_timestamp();
  330. if (timespec_compare(&ss_timestamp, &tmp) > 0) {
  331. os_printk(K_INFO, "queue reconnect work\n");
  332. schedule_delayed_work_on(0, &musb->reconnect_work, 0);
  333. }
  334. }
  335. speed_last = speed;
  336. speed = SSUSB_SPEED_HIGH;
  337. #endif
  338. #ifdef CONFIG_PROJECT_PHY
  339. /* Comment from CC Chou.
  340. * When detecting HS or FS and setting RG_USB20_SW_PLLMODE=1, It is OK to enter LPM L1 with BESL=0.
  341. * When disconnecting, set RG_USB20_SW_PLLMODE=0 back.
  342. */
  343. os_setmsk(U3D_U2PHYDCR1, (0x1 << E60802_RG_USB20_SW_PLLMODE_OFST));
  344. /*BESLCK = 0 < BESLCK_U3 = 1 < BESLDCK = 15 */
  345. os_writel(U3D_USB20_LPM_PARAMETER, 0x10f0);
  346. /*
  347. * The default value of LPM_BESL_STALL and LPM_BESLD_STALL are 1.
  348. * So Does _NOT_ need to set.
  349. */
  350. /*os_setmsk(U3D_POWER_MANAGEMENT, (LPM_BESL_STALL|LPM_BESLD_STALL)); */
  351. #else
  352. /*BESLCK = 4 < BESLCK_U3 = 10 < BESLDCK = 15 */
  353. os_writel(U3D_USB20_LPM_PARAMETER, 0xa4f0);
  354. os_setmsk(U3D_POWER_MANAGEMENT, (LPM_BESL_STALL | LPM_BESLD_STALL));
  355. #endif
  356. break;
  357. case SSUSB_SPEED_SUPER:
  358. os_printk(K_ALET, "USB Speed = Super Speed\n");
  359. #ifndef CONFIG_USBIF_COMPLIANCE
  360. speed_last = speed;
  361. speed = SSUSB_SPEED_SUPER;
  362. ss_timestamp = CURRENT_TIME;
  363. #endif
  364. break;
  365. default:
  366. os_printk(K_ALET, "USB Speed = Invalid (%x)\n", dwTemp);
  367. #ifndef CONFIG_USBIF_COMPLIANCE
  368. speed_last = speed;
  369. speed = SSUSB_SPEED_INACTIVE;
  370. #endif
  371. break;
  372. }
  373. }
  374. #ifdef SUPPORT_OTG
  375. static inline void mtu3d_otg_intr_handler(u32 dwOtgIntValue)
  376. {
  377. if (dwOtgIntValue & VBUS_CHG_INTR) {
  378. os_printk(K_NOTICE, "OTG: VBUS_CHG_INTR\n");
  379. os_setmsk(U3D_SSUSB_OTG_STS_CLR, SSUSB_VBUS_INTR_CLR);
  380. }
  381. /* this interrupt is issued when B device becomes device */
  382. if (dwOtgIntValue & SSUSB_CHG_B_ROLE_B) {
  383. os_printk(K_NOTICE, "OTG: CHG_B_ROLE_B\n");
  384. os_setmsk(U3D_SSUSB_OTG_STS_CLR, SSUSB_CHG_B_ROLE_B_CLR);
  385. /* switch DMA module to device */
  386. os_printk(K_NOTICE, "Switch DMA to device\n");
  387. os_clrmsk(U3D_SSUSB_U2_CTRL_0P, SSUSB_U2_PORT_HOST_SEL);
  388. }
  389. /* this interrupt is issued when B device becomes host */
  390. if (dwOtgIntValue & SSUSB_CHG_A_ROLE_B) {
  391. os_printk(K_NOTICE, "OTG: CHG_A_ROLE_B\n");
  392. os_setmsk(U3D_SSUSB_OTG_STS_CLR, SSUSB_CHG_A_ROLE_B_CLR);
  393. }
  394. /* this interrupt is issued when IDDIG reads B */
  395. if (dwOtgIntValue & SSUSB_ATTACH_B_ROLE) {
  396. os_printk(K_NOTICE, "OTG: CHG_ATTACH_B_ROLE\n");
  397. os_setmsk(U3D_SSUSB_OTG_STS_CLR, SSUSB_ATTACH_B_ROLE_CLR);
  398. /* switch DMA module to device */
  399. os_printk(K_NOTICE, "Switch DMA to device\n");
  400. os_clrmsk(U3D_SSUSB_U2_CTRL_0P, SSUSB_U2_PORT_HOST_SEL);
  401. }
  402. }
  403. #endif
  404. static irqreturn_t generic_interrupt(int irq, void *__hci)
  405. {
  406. unsigned long flags;
  407. irqreturn_t retval = IRQ_HANDLED;
  408. struct musb *musb = __hci;
  409. u32 dwL1Value = 0;
  410. u32 dwIntrUsbValue = 0;
  411. u32 dwDmaIntrValue = 0;
  412. u32 dwIntrEPValue = 0;
  413. u16 wIntrTxValue = 0;
  414. u16 wIntrRxValue = 0;
  415. #ifdef USE_SSUSB_QMU
  416. u32 wIntrQMUValue = 0;
  417. u32 wIntrQMUDoneValue = 0;
  418. #endif
  419. u32 dwLtssmValue = 0;
  420. u32 dwLinkIntValue = 0;
  421. #ifdef SUPPORT_OTG
  422. u32 dwOtgIntValue = 0;
  423. #endif
  424. spin_lock_irqsave(&musb->lock, flags);
  425. dwL1Value = os_readl(U3D_LV1ISR) & os_readl(U3D_LV1IER);
  426. if (dwL1Value & EP_CTRL_INTR) {
  427. u32 dwRxEpDataerrVal = os_readl(U3D_USB2_RX_EP_DATAERR_INTR);
  428. if (dwRxEpDataerrVal != 0) {
  429. /* Write 1 clear */
  430. os_writel(U3D_USB2_RX_EP_DATAERR_INTR, dwRxEpDataerrVal);
  431. os_printk(K_INFO, "===L1[%x] RxDataErr[%x]\n", dwL1Value,
  432. (dwRxEpDataerrVal >> USB2_RX_EP_DATAERR_INTR_EN_OFST
  433. && dwRxEpDataerrVal));
  434. }
  435. dwLinkIntValue = os_readl(U3D_DEV_LINK_INTR) & os_readl(U3D_DEV_LINK_INTR_ENABLE);
  436. if (dwLinkIntValue != 0) {
  437. /* Write 1 clear */
  438. os_writel(U3D_DEV_LINK_INTR, dwLinkIntValue);
  439. os_printk(K_INFO, "===L1[%x] LinkInt[%x]\n", dwL1Value, dwLinkIntValue);
  440. }
  441. }
  442. if (dwL1Value & MAC2_INTR) {
  443. dwIntrUsbValue =
  444. os_readl(U3D_COMMON_USB_INTR) & os_readl(U3D_COMMON_USB_INTR_ENABLE);
  445. /* Write 1 clear */
  446. os_writel(U3D_COMMON_USB_INTR, dwIntrUsbValue);
  447. os_printk(K_INFO, "===L1[%x] U2[%x]\n", dwL1Value, dwIntrUsbValue);
  448. }
  449. if (dwL1Value & DMA_INTR) {
  450. dwDmaIntrValue = os_readl(U3D_DMAISR) & os_readl(U3D_DMAIER);
  451. /* Write 1 clear */
  452. os_writel(U3D_DMAISR, dwDmaIntrValue);
  453. os_printk(K_INFO, "===L1[%x] DMA[%x]\n", dwL1Value, dwDmaIntrValue);
  454. }
  455. if (dwL1Value & MAC3_INTR) {
  456. dwLtssmValue = os_readl(U3D_LTSSM_INTR) & os_readl(U3D_LTSSM_INTR_ENABLE);
  457. /* Write 1 clear */
  458. os_writel(U3D_LTSSM_INTR, dwLtssmValue);
  459. os_printk(K_DEBUG, "===L1[%x] LTSSM[%x]\n", dwL1Value, dwLtssmValue);
  460. }
  461. #ifdef USE_SSUSB_QMU
  462. if (dwL1Value & QMU_INTR) {
  463. wIntrQMUValue = os_readl(U3D_QISAR1) & os_readl(U3D_QIER1);
  464. wIntrQMUDoneValue = os_readl(U3D_QISAR0) & os_readl(U3D_QIER0);
  465. /* Write 1 clear */
  466. os_writel(U3D_QISAR0, wIntrQMUDoneValue);
  467. qmu_printk(K_DEBUG, "===L1[%x] QMUDone[Tx=%x,Rx=%x] QMU[%x]===\n",
  468. dwL1Value, ((wIntrQMUDoneValue & 0xFFFF) >> 1), wIntrQMUDoneValue >> 17,
  469. wIntrQMUValue);
  470. }
  471. #endif
  472. if (dwL1Value & BMU_INTR) {
  473. dwIntrEPValue = os_readl(U3D_EPISR) & os_readl(U3D_EPIER);
  474. wIntrTxValue = dwIntrEPValue & 0xFFFF;
  475. wIntrRxValue = (dwIntrEPValue >> 16);
  476. os_writel(U3D_EPISR, dwIntrEPValue);
  477. os_printk(K_DEBUG, "===L1[%x] Tx[%x] Rx[%x]===\n",
  478. dwL1Value, wIntrTxValue, wIntrRxValue);
  479. }
  480. /*TODO: need to handle SetupEnd Interrupt!!! */
  481. /*--Handle each interrupt--*/
  482. if ((dwL1Value & (BMU_INTR | MAC2_INTR)) || dwIntrUsbValue) {
  483. musb->int_usb = dwIntrUsbValue;
  484. musb->int_tx = wIntrTxValue;
  485. musb->int_rx = wIntrRxValue;
  486. if (musb->int_usb || musb->int_tx || musb->int_rx)
  487. retval = musb_interrupt(musb);
  488. else
  489. os_printk(K_INFO, "===L1[%x] Nothing can do?? Tx[%x] Rx[%x] U2[%x]===\n",
  490. dwL1Value, wIntrTxValue, wIntrRxValue, dwIntrUsbValue);
  491. }
  492. #ifdef SUPPORT_OTG
  493. dwOtgIntValue = os_readl(U3D_SSUSB_OTG_STS) & os_readl(U3D_SSUSB_OTG_INT_EN);
  494. #endif
  495. #if defined(USE_SSUSB_QMU)
  496. if (wIntrQMUDoneValue) {
  497. if (musb->qmu_done_intr != 0) {
  498. musb->qmu_done_intr = wIntrQMUDoneValue | musb->qmu_done_intr;
  499. qmu_printk(K_DEBUG, "Has not handle yet %x\n", musb->qmu_done_intr);
  500. } else {
  501. musb->qmu_done_intr = wIntrQMUDoneValue;
  502. }
  503. tasklet_schedule(&musb->qmu_done);
  504. }
  505. if (wIntrQMUValue)
  506. qmu_exception_interrupt(musb, wIntrQMUValue);
  507. #endif
  508. if (dwLtssmValue)
  509. mtu3d_u3_ltssm_intr_handler(musb, dwLtssmValue);
  510. if (dwIntrUsbValue)
  511. mtu3d_u2_common_intr_handler(dwIntrUsbValue);
  512. if (dwLinkIntValue & SSUSB_DEV_SPEED_CHG_INTR)
  513. mtu3d_link_intr_handler(musb, dwLinkIntValue);
  514. #ifdef SUPPORT_OTG
  515. if (dwOtgIntValue)
  516. mtu3d_otg_intr_handler(dwOtgIntValue);
  517. #endif
  518. spin_unlock_irqrestore(&musb->lock, flags);
  519. return retval;
  520. }
  521. static void mtu3d_musb_enable(struct musb *musb)
  522. {
  523. os_printk(K_INFO, "%s\n", __func__);
  524. }
  525. static void mtu3d_musb_disable(struct musb *musb)
  526. {
  527. os_printk(K_INFO, "%s\n", __func__);
  528. #ifdef CONFIG_PROJECT_PHY
  529. /* Comment from CC Chou.
  530. * When detecting HS or FS and setting RG_USB20_SW_PLLMODE=1, It is OK to enter LPM L1 with BESL=0.
  531. * When disconnecting, set RG_USB20_SW_PLLMODE=0 back.
  532. */
  533. os_clrmsk(U3D_U2PHYDCR1, E60802_RG_USB20_SW_PLLMODE);
  534. #endif
  535. }
  536. static int mtu3d_musb_init(struct musb *musb)
  537. {
  538. os_printk(K_DEBUG, "%s\n", __func__);
  539. musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
  540. if (IS_ERR_OR_NULL(musb->xceiv))
  541. goto unregister;
  542. mtu3d_musb_reg_init(musb);
  543. if (is_peripheral_enabled(musb))
  544. musb->xceiv->set_power = mtu3d_set_power;
  545. musb->isr = generic_interrupt;
  546. return 0;
  547. unregister:
  548. return -ENODEV;
  549. }
  550. static int mtu3d_set_power(struct usb_phy *x, unsigned mA)
  551. {
  552. os_printk(K_DEBUG, "%s\n", __func__);
  553. return 0;
  554. }
  555. static int mtu3d_musb_exit(struct musb *musb)
  556. {
  557. #ifdef NEVER
  558. struct device *dev = musb->controller;
  559. struct musb_hdrc_platform_data *plat = dev->platform_data;
  560. #endif /* NEVER */
  561. usb_put_phy(musb->xceiv);
  562. return 0;
  563. }
  564. static void mtu3d_musb_reg_init(struct musb *musb)
  565. {
  566. int ret = 1;
  567. os_printk(K_DEBUG, "%s\n", __func__);
  568. /* initialize PHY related data structure */
  569. if (!u3phy_ops)
  570. ret = u3phy_init();
  571. if (ret || u3phy_ops) {
  572. #ifdef CONFIG_MTK_UART_USB_SWITCH
  573. if (usb_phy_check_in_uart_mode()) {
  574. os_printk(K_INFO, "%s+ UART_MODE\n", __func__);
  575. in_uart_mode = true;
  576. } else {
  577. os_printk(K_INFO, "%s+ USB_MODE\n", __func__);
  578. }
  579. #endif
  580. u3phy_ops->init(u3phy);
  581. musb->is_clk_on = 1;
  582. #ifndef CONFIG_MTK_FPGA
  583. usb_phy_recover(musb->is_clk_on);
  584. #endif
  585. /* USB 2.0 slew rate calibration */
  586. u3phy_ops->u2_slew_rate_calibration(u3phy);
  587. /* disable ip power down, disable U2/U3 ip power down */
  588. _ex_mu3d_hal_ssusb_en();
  589. /* USB PLL Force settings */
  590. #ifdef CONFIG_PROJECT_PHY
  591. usb20_pll_settings(false, false);
  592. #endif
  593. /* reset U3D all dev module. */
  594. mu3d_hal_rst_dev();
  595. } else {
  596. os_printk(K_ERR, "%s: PHY initialization fail!\n", __func__);
  597. BUG_ON(1);
  598. }
  599. }
  600. static u64 usb_dmamask = DMA_BIT_MASK(32);
  601. static int mtu3d_probe(struct platform_device *pdev)
  602. {
  603. const struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev);
  604. const struct of_device_id *match;
  605. struct platform_device *musb;
  606. struct mtu3d_glue *glue;
  607. int ret = -ENOMEM;
  608. os_printk(K_DEBUG, "%s\n", __func__);
  609. glue = kzalloc(sizeof(*glue), GFP_KERNEL);
  610. if (!glue) {
  611. /*WARNING:OOM_MESSAGE: Possible unnecessary 'out of memory' message*/
  612. /*dev_err(&pdev->dev, "failed to allocate glue context\n");*/
  613. goto err0;
  614. }
  615. musb = platform_device_alloc(MUSB_DRIVER_NAME, PLATFORM_DEVID_NONE);
  616. if (!musb) {
  617. dev_err(&pdev->dev, "failed to allocate musb device\n");
  618. goto err1;
  619. }
  620. musb->dev.parent = &pdev->dev;
  621. musb->dev.dma_mask = &usb_dmamask;
  622. musb->dev.coherent_dma_mask = usb_dmamask;
  623. glue->dev = &pdev->dev;
  624. glue->musb = musb;
  625. match = of_match_device(of_match_ptr(mtu3d_of_match), &pdev->dev);
  626. if (match)
  627. pdata = match->data;
  628. platform_set_drvdata(pdev, glue);
  629. ret = platform_device_add_resources(musb, pdev->resource, pdev->num_resources);
  630. if (ret) {
  631. dev_err(&pdev->dev, "failed to add resources\n");
  632. goto err2;
  633. }
  634. ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
  635. if (ret) {
  636. dev_err(&pdev->dev, "failed to add platform_data\n");
  637. goto err2;
  638. }
  639. ret = platform_device_add(musb);
  640. if (ret) {
  641. dev_err(&pdev->dev, "failed to register musb device\n");
  642. goto err2;
  643. }
  644. #ifdef CONFIG_USB_MTK_DUALMODE
  645. pinctrl = devm_pinctrl_get(&pdev->dev);
  646. if (IS_ERR(pinctrl))
  647. dev_err(&pdev->dev, "Cannot find usb pinctrl!\n");
  648. else {
  649. pinctrl_iddig = pinctrl_lookup_state(pinctrl, "iddig_init");
  650. if (IS_ERR(pinctrl_iddig))
  651. dev_err(&pdev->dev, "Cannot find usb pinctrl iddig_init\n");
  652. else
  653. pinctrl_select_state(pinctrl, pinctrl_iddig);
  654. }
  655. #endif
  656. return 0;
  657. err2:
  658. platform_device_put(musb);
  659. err1:
  660. kfree(glue);
  661. err0:
  662. return ret;
  663. }
  664. static int mtu3d_remove(struct platform_device *pdev)
  665. {
  666. struct mtu3d_glue *glue = platform_get_drvdata(pdev);
  667. platform_device_del(glue->musb);
  668. platform_device_put(glue->musb);
  669. kfree(glue);
  670. return 0;
  671. }
  672. #ifdef CONFIG_PM
  673. static int mtu3d_suspend_noirq(struct device *dev)
  674. {
  675. os_printk(K_INFO, "%s\n", __func__);
  676. /*J:I think it does _NOT_ have to do PHY savecurrent. Because when the phone with USB cable,
  677. * the system does _NOT_ enter suspend mode. At the normal case, the USB driver calls PHY savecurrent,
  678. * when USB cable is plugged out.
  679. */
  680. /*usb_phy_savecurrent(); */
  681. /*
  682. * SSUSB IP Software Reset - When this bit is set, whole SSUSB IP is reset.
  683. * All MAC regs(DEV, EPCTL CSR, USB3 MAC/SYS CSR, USB2 CSR can _NOT_ be read/written when this bit is set.)
  684. * Setting this bit when suspend is to improve USB current leakage problem of AVDD18_USB_P0.
  685. * After clearing this bit, the whole MAC registers would reset to the default value.
  686. */
  687. /* os_setmsk(U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST); */
  688. return 0;
  689. }
  690. static int mtu3d_resume_noirq(struct device *dev)
  691. {
  692. os_printk(K_INFO, "%s\n", __func__);
  693. /* disable ip power down, disable U2/U3 ip power down */
  694. /* _ex_mu3d_hal_ssusb_en(); */
  695. /* reset U3D all dev module. */
  696. /* mu3d_hal_rst_dev(); */
  697. /*J:I think it does _NOT_ have to do PHY savecurrent. Because after USB cable is plugged in,
  698. * the USB driver calls PHY recovery. So does _NOT_ have to do PHY recovery at this moment.*/
  699. /* usb_phy_recover(); */
  700. return 0;
  701. }
  702. static const struct dev_pm_ops mtu3d_pm_ops = {
  703. .suspend_noirq = mtu3d_suspend_noirq,
  704. .resume_noirq = mtu3d_resume_noirq,
  705. };
  706. #define DEV_PM_OPS (&mtu3d_pm_ops)
  707. #else
  708. #define DEV_PM_OPS NULL
  709. #endif
  710. static struct platform_driver mtu3d_driver = {
  711. .probe = mtu3d_probe,
  712. .remove = mtu3d_remove,
  713. .driver = {
  714. .name = "musb-mtu3d",
  715. .owner = THIS_MODULE,
  716. .pm = DEV_PM_OPS,
  717. .of_match_table = of_match_ptr(mtu3d_of_match),
  718. },
  719. };
  720. MODULE_DESCRIPTION("mtu3d MUSB Glue Layer");
  721. MODULE_AUTHOR("MediaTek");
  722. MODULE_LICENSE("GPL v2");
  723. module_platform_driver(mtu3d_driver);