musbfsh_virthub.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  1. /*
  2. * MUSB OTG driver virtual root hub support
  3. *
  4. * Copyright 2005 Mentor Graphics Corporation
  5. * Copyright (C) 2005-2006 by Texas Instruments
  6. * Copyright (C) 2006-2007 Nokia Corporation
  7. *
  8. * Copyright 2015 Mediatek Inc.
  9. * Marvin Lin <marvin.lin@mediatek.com>
  10. * Arvin Wang <arvin.wang@mediatek.com>
  11. * Vincent Fan <vincent.fan@mediatek.com>
  12. * Bryant Lu <bryant.lu@mediatek.com>
  13. * Yu-Chang Wang <yu-chang.wang@mediatek.com>
  14. * Macpaul Lin <macpaul.lin@mediatek.com>
  15. *
  16. * This program is free software; you can redistribute it and/or
  17. * modify it under the terms of the GNU General Public License
  18. * version 2 as published by the Free Software Foundation.
  19. *
  20. * This program is distributed in the hope that it will be useful, but
  21. * WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  23. * General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU General Public License
  26. * along with this program.
  27. *
  28. * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
  29. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  30. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
  31. * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  32. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  33. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  34. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  35. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  36. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  37. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. #include <linux/module.h>
  41. #include <linux/kernel.h>
  42. #include <linux/sched.h>
  43. #include <linux/errno.h>
  44. #include <linux/init.h>
  45. #include <linux/time.h>
  46. #include <linux/timer.h>
  47. #include <asm/unaligned.h>
  48. #include "musbfsh_core.h"
  49. #include "musbfsh_host.h"
  50. #include "usb.h"
  51. #ifdef CONFIG_MTK_ICUSB_SUPPORT
  52. #include "musbfsh_mt65xx.h"
  53. #endif
  54. #ifdef CONFIG_MTK_ICUSB_SUPPORT
  55. struct my_attr resistor_control_attr = {
  56. .attr.name = "resistor_control",
  57. .attr.mode = 0644,
  58. #ifdef MTK_ICUSB_RESISTOR_CONTROL
  59. .value = 1
  60. #else
  61. .value = 0
  62. #endif
  63. };
  64. struct my_attr skip_port_pm_attr = {
  65. .attr.name = "skip_port_pm",
  66. .attr.mode = 0644,
  67. #ifdef MTK_ICUSB_SKIP_PORT_PM
  68. .value = 1
  69. #else
  70. .value = 0
  71. #endif
  72. };
  73. #endif
  74. static void musbfsh_port_suspend(struct musbfsh *musbfsh, bool do_suspend)
  75. {
  76. u8 power;
  77. u8 intrusbe;
  78. u8 intrusb;
  79. void __iomem *mbase = musbfsh->mregs;
  80. int retries = 0;
  81. /* MYDBG("cpuid:%d\n", smp_processor_id()); */
  82. /* NOTE: this doesn't necessarily put PHY into low power mode,
  83. * turning off its clock; that's a function of PHY integration and
  84. * MUSBFSH_POWER_ENSUSPEND. PHY may need a clock (sigh) to detect
  85. * SE0 changing to connect (J) or wakeup (K) states.
  86. */
  87. if (do_suspend) {
  88. #ifdef CONFIG_MTK_DT_USB_SUPPORT
  89. if (musbfsh_skip_port_suspend) {
  90. MYDBG("\n");
  91. musbfsh->port1_status |= USB_PORT_STAT_SUSPEND;
  92. return;
  93. }
  94. #endif
  95. /* clean MUSBFSH_INTR_SOF in MUSBFSH_INTRUSBE */
  96. intrusbe = musbfsh_readb(mbase, MUSBFSH_INTRUSBE);
  97. intrusbe &= ~MUSBFSH_INTR_SOF;
  98. musbfsh_writeb(mbase, MUSBFSH_INTRUSBE, intrusbe);
  99. mb(); /* flush POWER and PHY setting immediately */
  100. /* clean MUSBFSH_INTR_SOF in MUSBFSH_INTRUSB */
  101. intrusb = musbfsh_readb(mbase, MUSBFSH_INTRUSB);
  102. intrusb |= MUSBFSH_INTR_SOF;
  103. musbfsh_writeb(mbase, MUSBFSH_INTRUSB, intrusb);
  104. mb(); /* flush POWER and PHY setting immediately */
  105. retries = 10000;
  106. intrusb = musbfsh_readb(mbase, MUSBFSH_INTRUSB);
  107. while (!(intrusb & MUSBFSH_INTR_SOF)) {
  108. intrusb = musbfsh_readb(mbase, MUSBFSH_INTRUSB);
  109. if (retries-- < 1) {
  110. MYDBG("\n");
  111. break;
  112. }
  113. }
  114. /* delay 10 us */
  115. udelay(10);
  116. /* set MUSBFSH_POWER_SUSPENDM in MUSBFSH_POWER_SUSPENDM */
  117. power = musbfsh_readb(mbase, MUSBFSH_POWER);
  118. #ifdef CONFIG_MTK_DT_USB_SUPPORT
  119. #if defined(CONFIG_PM_RUNTIME) && defined(USB11_REMOTE_IRQ_NON_AUTO_MASK)
  120. disable_remote_wake_up();
  121. #endif
  122. #endif
  123. #ifdef MTK_USB_RUNTIME_SUPPORT
  124. /*
  125. * mask remote wake up IRQ between port suspend and bus suspend.
  126. * hub.c will call set_port_feature first then
  127. * usb_set_device_state, so if EINT comes between them,
  128. * resume flow may see device state without USB_STATE_SUSPENDED
  129. * and do nothing.
  130. * So we postpone remote wake up IRQ until the suspend flow
  131. * is all done (when bus_suspend is called). Since suspend flow
  132. * may be interrupted (root hub is suspended, but not host
  133. * controller), so we also unmaks EINT when resume is done.
  134. */
  135. mt_eint_mask(CUST_EINT_MT6280_USB_WAKEUP_NUM);
  136. #endif
  137. retries = 10000;
  138. #ifdef CONFIG_MTK_ICUSB_SUPPORT
  139. if (skip_port_pm_attr.value) {
  140. MYDBG("skip hw operation for port suspend\n");
  141. } else {
  142. power &= ~MUSBFSH_POWER_RESUME;
  143. power |= MUSBFSH_POWER_SUSPENDM;
  144. musbfsh_writeb(mbase, MUSBFSH_POWER, power);
  145. /* Needed for OPT A tests */
  146. power = musbfsh_readb(mbase, MUSBFSH_POWER);
  147. while (power & MUSBFSH_POWER_SUSPENDM) {
  148. power = musbfsh_readb(mbase, MUSBFSH_POWER);
  149. if (retries-- < 1)
  150. break;
  151. }
  152. }
  153. #else
  154. power &= ~MUSBFSH_POWER_RESUME;
  155. power |= MUSBFSH_POWER_SUSPENDM;
  156. musbfsh_writeb(mbase, MUSBFSH_POWER, power);
  157. /* Needed for OPT A tests */
  158. power = musbfsh_readb(mbase, MUSBFSH_POWER);
  159. while (power & MUSBFSH_POWER_SUSPENDM) {
  160. power = musbfsh_readb(mbase, MUSBFSH_POWER);
  161. if (retries-- < 1) {
  162. MYDBG("\n");
  163. break;
  164. }
  165. }
  166. #endif
  167. mb(); /* flush POWER and PHY setting immediately */
  168. WARNING("Root port suspended, power 0x%02x\n", power);
  169. #ifdef CONFIG_MTK_DT_USB_SUPPORT
  170. #if defined(CONFIG_PM_RUNTIME)
  171. disable_usb11_clk();
  172. #endif
  173. #endif
  174. musbfsh->port1_status |= USB_PORT_STAT_SUSPEND;
  175. } else {
  176. #ifdef CONFIG_MTK_DT_USB_SUPPORT
  177. if (musbfsh_skip_port_resume) {
  178. MYDBG("\n");
  179. request_wakeup_md_timeout(0, 0);
  180. musbfsh->port1_status |= MUSBFSH_PORT_STAT_RESUME;
  181. musbfsh->rh_timer = jiffies + msecs_to_jiffies(20);
  182. return;
  183. }
  184. #if defined(CONFIG_PM_RUNTIME)
  185. enable_usb11_clk();
  186. #endif
  187. #endif
  188. power = musbfsh_readb(mbase, MUSBFSH_POWER);
  189. if (!(power & MUSBFSH_POWER_SUSPENDM)) {
  190. WARNING("Root port resuming abort, power 0x%02x\n",
  191. power);
  192. if (power & MUSBFSH_POWER_RESUME)
  193. goto finish;
  194. else
  195. return;
  196. }
  197. #ifdef CONFIG_MTK_DT_USB_SUPPORT
  198. request_wakeup_md_timeout(0, 0);
  199. #endif
  200. #ifdef MTK_USB_RUNTIME_SUPPORT
  201. /* ERR("EINT to wake up MD for resume\n"); */
  202. /* request_wakeup_md_timeout(0, 0); //wx, wakeup MD first */
  203. #endif
  204. #ifdef CONFIG_MTK_ICUSB_SUPPORT
  205. if (skip_port_pm_attr.value) {
  206. MYDBG("skip hw operation for port resume\n");
  207. } else {
  208. power &= ~MUSBFSH_POWER_SUSPENDM;
  209. power |= MUSBFSH_POWER_RESUME;
  210. musbfsh_writeb(mbase, MUSBFSH_POWER, power);
  211. }
  212. #else
  213. power &= ~MUSBFSH_POWER_SUSPENDM;
  214. power |= MUSBFSH_POWER_RESUME;
  215. musbfsh_writeb(mbase, MUSBFSH_POWER, power);
  216. #endif
  217. mb(); /* flush POWER and PHY setting immediately */
  218. WARNING("Root port resuming, power 0x%02x\n", power);
  219. finish:
  220. /* later, GetPortStatus will stop RESUME signaling */
  221. musbfsh->port1_status |= MUSBFSH_PORT_STAT_RESUME;
  222. musbfsh->rh_timer = jiffies + msecs_to_jiffies(20);
  223. }
  224. }
  225. static void musbfsh_port_reset(struct musbfsh *musbfsh, bool do_reset)
  226. {
  227. u8 power;
  228. void __iomem *mbase = musbfsh->mregs;
  229. /* NOTE: caller guarantees it will turn off the reset when
  230. * the appropriate amount of time has passed
  231. */
  232. power = musbfsh_readb(mbase, MUSBFSH_POWER);
  233. WARNING("reset=%d power=0x%x\n", do_reset, power);
  234. if (do_reset) {
  235. if (power & MUSBFSH_POWER_SUSPENDM) {
  236. WARNING("reset a suspended device\n");
  237. #ifdef CONFIG_MTK_DT_USB_SUPPORT
  238. request_wakeup_md_timeout(0, 0);
  239. #endif
  240. #ifdef MTK_USB_RUNTIME_SUPPORT
  241. /* ERR("EINT to wake up MD for reset\n"); */
  242. /* wx, we may have to reset a suspended MD */
  243. /* request_wakeup_md_timeout(0, 0); */
  244. #endif
  245. musbfsh_writeb(mbase,
  246. MUSBFSH_POWER, power |
  247. MUSBFSH_POWER_RESUME);
  248. mdelay(20);
  249. musbfsh_writeb(mbase, MUSBFSH_POWER,
  250. power & ~MUSBFSH_POWER_RESUME);
  251. }
  252. /*
  253. * If RESUME is set, we must make sure it stays minimum 20 ms.
  254. * Then we must clear RESUME and wait a bit to let musb start
  255. * generating SOFs. If we don't do this, OPT HS A 6.8 tests
  256. * fail with "Error! Did not receive an SOF before suspend
  257. * detected".
  258. */
  259. if (power & MUSBFSH_POWER_RESUME) {
  260. WARNING("reset a resuming device\n");
  261. while (time_before(jiffies, musbfsh->rh_timer))
  262. mdelay(1);
  263. /* stop the resume signal */
  264. musbfsh_writeb(mbase, MUSBFSH_POWER,
  265. power & ~MUSBFSH_POWER_RESUME);
  266. mdelay(1);
  267. }
  268. musbfsh->ignore_disconnect = true;
  269. power &= 0xf0;
  270. musbfsh_writeb(mbase, MUSBFSH_POWER,
  271. power | MUSBFSH_POWER_RESET);
  272. mb(); /* flush POWER and PHY setting immediately */
  273. musbfsh->port1_status |= USB_PORT_STAT_RESET;
  274. musbfsh->port1_status &= ~USB_PORT_STAT_ENABLE;
  275. musbfsh->rh_timer = jiffies + msecs_to_jiffies(50);
  276. } else {
  277. INFO("Root port reset stopped\n");
  278. #ifdef CONFIG_MTK_ICUSB_SUPPORT
  279. if (resistor_control_attr.value) {
  280. /* improve signal quality, from Dingjun */
  281. #if 0
  282. /* FS_DISC_DISABLE */
  283. u32 TM1;
  284. TM1 = musbfsh_readl(mbase, 0x604);
  285. musbfsh_writel(mbase, 0x604, TM1 | 0x4);
  286. MYDBG("set FS_DISC_DISABLE\n");
  287. #endif
  288. /* original flow from SS5 */
  289. USB11PHY_SET8(U1PHTCR2,
  290. force_usb11_dm_rpd | force_usb11_dp_rpd);
  291. /*
  292. * disconnect host port's pull down resistors
  293. * on D+ and D-
  294. */
  295. USB11PHY_CLR8(U1PHTCR2,
  296. RG_USB11_DM_RPD | RG_USB11_DP_RPD);
  297. /*
  298. * Tell MAC there still is a device attached,
  299. * ohterwise we will get disconnect interrupt
  300. */
  301. USB11PHY_SET8(U1PHTCR2,
  302. force_usb11_dp_rpu | RG_USB11_DP_RPU);
  303. /* force */
  304. USB11PHY_SET8(0x6a, 0x20 | 0x10);
  305. /* RG */
  306. /*
  307. * disconnect host port's pull down resistors
  308. * on D+ and D-
  309. */
  310. USB11PHY_CLR8(0x68, 0x80 | 0x40);
  311. /*
  312. * Tell MAC there still is a device attached,
  313. * ohterwise we will get disconnect interrupt.
  314. */
  315. /* USB11PHY_SET8(U1PHTCR2,
  316. * force_usb11_dp_rpu |
  317. * RG_USB11_DP_RPU);
  318. */
  319. MYDBG("USB1.1 PHY special config for IC-USB\n");
  320. } else {
  321. MYDBG("");
  322. }
  323. #endif
  324. musbfsh_writeb(mbase,
  325. MUSBFSH_POWER, power & ~MUSBFSH_POWER_RESET);
  326. #ifdef CONFIG_MTK_ICUSB_SUPPORT
  327. if (resistor_control_attr.value)
  328. USB11PHY_CLR8(0x6a, 0x20 | 0x10);
  329. else
  330. MYDBG("");
  331. #endif
  332. mb(); /* flush POWER and PHY setting immediately */
  333. musbfsh->ignore_disconnect = false;
  334. power = musbfsh_readb(mbase, MUSBFSH_POWER);
  335. if (power & MUSBFSH_POWER_HSMODE) {
  336. INFO("high-speed device connected\n");
  337. musbfsh->port1_status |= USB_PORT_STAT_HIGH_SPEED;
  338. }
  339. #if 0 /* IC_USB from SS5 */
  340. #ifdef IC_USB
  341. USB11PHY_SET8(U1PHTCR2,
  342. force_usb11_dm_rpd | force_usb11_dp_rpd);
  343. /* disconnect host port's pull down resistors on D+ and D- */
  344. USB11PHY_CLR8(U1PHTCR2, RG_USB11_DM_RPD | RG_USB11_DP_RPD);
  345. /*
  346. * tell MAC there still is a device attached,
  347. * ohterwise we will get disconnect interrupt
  348. */
  349. USB11PHY_SET8(U1PHTCR2, force_usb11_dp_rpu | RG_USB11_DP_RPU);
  350. WARNING("USB1.1 PHY special config for IC-USB 0x%X=%x\n",
  351. U1PHTCR2, USB11PHY_READ8(U1PHTCR2));
  352. #endif
  353. #endif
  354. musbfsh->port1_status &= ~USB_PORT_STAT_RESET;
  355. musbfsh->port1_status |=
  356. USB_PORT_STAT_ENABLE | (USB_PORT_STAT_C_RESET << 16) |
  357. (USB_PORT_STAT_C_ENABLE << 16);
  358. /* call back func to notify the hub thread the state of hub! */
  359. usb_hcd_poll_rh_status(musbfsh_to_hcd(musbfsh));
  360. musbfsh->vbuserr_retry = VBUSERR_RETRY_COUNT;
  361. }
  362. }
  363. void musbfsh_root_disconnect(struct musbfsh *musbfsh)
  364. {
  365. INFO("%s++\r\n", __func__);
  366. musbfsh->port1_status =
  367. USB_PORT_STAT_POWER | (USB_PORT_STAT_C_CONNECTION << 16);
  368. usb_hcd_poll_rh_status(musbfsh_to_hcd(musbfsh));
  369. musbfsh->is_active = 0;
  370. }
  371. /*---------------------------------------------------------------------*/
  372. /* Caller may or may not hold musbfsh->lock */
  373. int musbfsh_hub_status_data(struct usb_hcd *hcd, char *buf)
  374. {
  375. struct musbfsh *musbfsh = hcd_to_musbfsh(hcd);
  376. int retval = 0;
  377. INFO("musbfsh_hub_status_data++\r\n");
  378. /* called in_irq() via usb_hcd_poll_rh_status() */
  379. if (musbfsh->port1_status & 0xffff0000) {
  380. *buf = 0x02;
  381. retval = 1;
  382. }
  383. return retval;
  384. }
  385. int musbfsh_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
  386. u16 wIndex, char *buf, u16 wLength)
  387. {
  388. struct musbfsh *musbfsh = hcd_to_musbfsh(hcd);
  389. u32 temp;
  390. int retval = 0;
  391. unsigned long flags;
  392. INFO("%s++, typeReq=0x%x, wValue=0x%x, wIndex=0x%x\r\n",
  393. __func__, typeReq, wValue, wIndex);
  394. spin_lock_irqsave(&musbfsh->lock, flags);
  395. if (unlikely(!HCD_HW_ACCESSIBLE(hcd))) {
  396. spin_unlock_irqrestore(&musbfsh->lock, flags);
  397. return -ESHUTDOWN;
  398. }
  399. /* hub features: always zero, setting is a NOP
  400. * port features: reported, sometimes updated when host is active
  401. * no indicators
  402. */
  403. switch (typeReq) {
  404. case ClearHubFeature:
  405. case SetHubFeature:
  406. switch (wValue) {
  407. case C_HUB_OVER_CURRENT:
  408. case C_HUB_LOCAL_POWER:
  409. break;
  410. default:
  411. goto error;
  412. }
  413. break;
  414. case ClearPortFeature:
  415. /* wIndex indicate the port number, here it is should be 1 */
  416. if ((wIndex & 0xff) != 1)
  417. goto error;
  418. switch (wValue) {
  419. case USB_PORT_FEAT_ENABLE:
  420. break;
  421. case USB_PORT_FEAT_SUSPEND:
  422. /* here is clearing the suspend */
  423. musbfsh_port_suspend(musbfsh, false);
  424. break;
  425. case USB_PORT_FEAT_POWER:
  426. #ifndef MTK_ALPS_BOX_SUPPORT
  427. /* only power off the vbus */
  428. musbfsh_set_vbus(musbfsh, 0);
  429. #else
  430. /* only power off the vbus */
  431. musbfsh_platform_set_vbus(musbfsh, 0);
  432. #endif
  433. break;
  434. case USB_PORT_FEAT_C_CONNECTION:
  435. case USB_PORT_FEAT_C_ENABLE:
  436. case USB_PORT_FEAT_C_OVER_CURRENT:
  437. case USB_PORT_FEAT_C_RESET:
  438. case USB_PORT_FEAT_C_SUSPEND:
  439. break;
  440. default:
  441. goto error;
  442. }
  443. INFO("clear feature %d\n", wValue);
  444. musbfsh->port1_status &= ~(1 << wValue);
  445. break;
  446. case GetHubDescriptor:
  447. {
  448. struct usb_hub_descriptor *desc = (void *)buf;
  449. desc->bDescLength = 9;
  450. desc->bDescriptorType = 0x29;
  451. desc->bNbrPorts = 1;
  452. /* 0x0001: per-port power switching */
  453. /* 0x0010: no overcurrent reporting */
  454. desc->wHubCharacteristics =
  455. cpu_to_le16(0x0001 | 0x0010);
  456. /* msec/2 */
  457. desc->bPwrOn2PwrGood = 5;
  458. desc->bHubContrCurrent = 0;
  459. /* workaround bogus struct definition */
  460. desc->u.hs.DeviceRemovable[0] = 0x02; /* port 1 */
  461. desc->u.hs.DeviceRemovable[1] = 0xff;
  462. }
  463. break;
  464. case GetHubStatus:
  465. temp = 0;
  466. *(__le32 *)buf = cpu_to_le32(temp);
  467. break;
  468. case GetPortStatus:
  469. if (wIndex != 1)
  470. goto error;
  471. /* finish RESET signaling? */
  472. /* if FALSE: stop the reset because the timeout of reset. */
  473. if ((musbfsh->port1_status & USB_PORT_STAT_RESET)
  474. && time_after_eq(jiffies, musbfsh->rh_timer))
  475. musbfsh_port_reset(musbfsh, false);
  476. /* finish RESUME signaling? */
  477. if ((musbfsh->port1_status & MUSBFSH_PORT_STAT_RESUME)
  478. && time_after_eq(jiffies, musbfsh->rh_timer)) {
  479. u8 pwr;
  480. #ifdef CONFIG_MTK_DT_USB_SUPPORT
  481. if (!musbfsh_skip_port_resume) {
  482. pwr = musbfsh_readb(musbfsh->mregs,
  483. MUSBFSH_POWER);
  484. pwr &= ~MUSBFSH_POWER_RESUME;
  485. WARNING("Root port resume stopped\n");
  486. WARNING("power 0x%02x\n", pwr);
  487. musbfsh_writeb(musbfsh->mregs, MUSBFSH_POWER,
  488. pwr);
  489. #if defined(CONFIG_PM_RUNTIME) && defined(USB11_REMOTE_IRQ_NON_AUTO_MASK)
  490. enable_remote_wake_up();
  491. #endif
  492. } else {
  493. MYDBG("\n");
  494. }
  495. #else
  496. pwr = musbfsh_readb(musbfsh->mregs, MUSBFSH_POWER);
  497. pwr &= ~MUSBFSH_POWER_RESUME;
  498. WARNING("Root port resume stopped, power 0x%02x\n",
  499. pwr);
  500. musbfsh_writeb(musbfsh->mregs, MUSBFSH_POWER, pwr);
  501. #endif
  502. #ifdef MTK_USB_RUNTIME_SUPPORT
  503. /* mt_eint_unmask(CUST_EINT_MT6280_USB_WAKEUP_NUM); */
  504. #endif
  505. /*
  506. * ISSUE: DaVinci (RTL 1.300) disconnects after
  507. * resume of high speed peripherals (but not full
  508. * speed ones).
  509. */
  510. musbfsh->is_active = 1;
  511. musbfsh->port1_status &= ~(USB_PORT_STAT_SUSPEND
  512. | MUSBFSH_PORT_STAT_RESUME);
  513. musbfsh->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
  514. usb_hcd_poll_rh_status(musbfsh_to_hcd(musbfsh));
  515. }
  516. put_unaligned(cpu_to_le32(musbfsh->port1_status &
  517. ~MUSBFSH_PORT_STAT_RESUME),
  518. (__le32 *)buf);
  519. /* port change status is more interesting */
  520. WARNING("port status %08x,devctl=0x%x\n", musbfsh->port1_status,
  521. musbfsh_readb(musbfsh->mregs, MUSBFSH_DEVCTL));
  522. break;
  523. case SetPortFeature:
  524. if ((wIndex & 0xff) != 1)
  525. goto error;
  526. switch (wValue) {
  527. case USB_PORT_FEAT_POWER:
  528. /* NOTE: this controller has a strange state machine
  529. * that involves "requesting sessions" according to
  530. * magic side effects from incompletely-described
  531. * rules about startup...
  532. *
  533. * This call is what really starts the host mode; be
  534. * very careful about side effects if you reorder any
  535. * initialization logic, e.g. for OTG, or change any
  536. * logic relating to VBUS power-up.
  537. */
  538. INFO("musbfsh_start is called in hub control\r\n");
  539. #ifdef CONFIG_MTK_ICUSB_SUPPORT
  540. if (skip_mac_init_attr.value)
  541. MYDBG("");
  542. else
  543. musbfsh_start(musbfsh);
  544. #else
  545. musbfsh_start(musbfsh);
  546. #endif
  547. break;
  548. case USB_PORT_FEAT_RESET:
  549. /* enable the reset, but not finish */
  550. musbfsh_port_reset(musbfsh, true);
  551. break;
  552. case USB_PORT_FEAT_SUSPEND:
  553. musbfsh_port_suspend(musbfsh, true);
  554. break;
  555. case USB_PORT_FEAT_TEST:
  556. #if 0
  557. if (unlikely(is_host_active(musbfsh)))
  558. goto error;
  559. wIndex >>= 8;
  560. switch (wIndex) {
  561. case 1:
  562. pr_debug("TEST_J\n");
  563. temp = MUSBFSH_TEST_J;
  564. break;
  565. case 2:
  566. pr_debug("TEST_K\n");
  567. temp = MUSBFSH_TEST_K;
  568. break;
  569. case 3:
  570. pr_debug("TEST_SE0_NAK\n");
  571. temp = MUSBFSH_TEST_SE0_NAK;
  572. break;
  573. case 4:
  574. pr_debug("TEST_PACKET\n");
  575. temp = MUSBFSH_TEST_PACKET;
  576. musbfsh_load_testpacket(musbfsh);
  577. break;
  578. case 5:
  579. pr_debug("TEST_FORCE_ENABLE\n");
  580. temp = MUSBFSH_TEST_FORCE_HOST |
  581. MUSBFSH_TEST_FORCE_FS;
  582. musbfsh_writeb(musbfsh->mregs, MUSBFSH_DEVCTL,
  583. MUSBFSH_DEVCTL_SESSION);
  584. break;
  585. case 6:
  586. pr_debug("TEST_FIFO_ACCESS\n");
  587. temp = MUSBFSH_TEST_FIFO_ACCESS;
  588. break;
  589. default:
  590. goto error;
  591. }
  592. musbfsh_writeb(musbfsh->mregs, MUSBFSH_TESTMODE, temp);
  593. #endif
  594. break;
  595. default:
  596. goto error;
  597. }
  598. INFO("set feature %d\n", wValue);
  599. musbfsh->port1_status |= 1 << wValue;
  600. break;
  601. default:
  602. error:
  603. /* "protocol stall" on error */
  604. retval = -EPIPE;
  605. }
  606. spin_unlock_irqrestore(&musbfsh->lock, flags);
  607. return retval;
  608. }