mt_mu3d_hal_qmu_drv.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091
  1. /*
  2. * Copyright (c) 2013 MediaTek Inc.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining
  5. * a copy of this software and associated documentation files
  6. * (the "Software"), to deal in the Software without restriction,
  7. * including without limitation the rights to use, copy, modify, merge,
  8. * publish, distribute, sublicense, and/or sell copies of the Software,
  9. * and to permit persons to whom the Software is furnished to do so,
  10. * subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be
  13. * included in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  18. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  19. * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  20. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  21. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. #include <sys/types.h>
  24. #include <string.h>
  25. #include <stdlib.h>
  26. #include <debug.h>
  27. #include <reg.h>
  28. #include <platform/bitops.h>
  29. #include <platform/mt_irq.h>
  30. #include <platform/mt_reg_base.h>
  31. #include <platform/mt_typedefs.h>
  32. #include <platform/timer.h>
  33. #include <kernel/thread.h>
  34. #include <dev/udc.h>
  35. #include <mt_ssusb.h>
  36. #include <mt_ssusb_qmu.h>
  37. #include <mt_mu3d_hal_qmu_drv.h>
  38. /* USB DEBUG */
  39. #ifdef DBG_USB_QMU
  40. #define DBG_C(x...) dprintf(CRITICAL, "[USB][QMU] " x)
  41. #define DBG_I(x...) dprintf(INFO, "[USB][QMU] " x)
  42. #define DBG_S(x...) dprintf(SPEW, "[USB][QMU] " x)
  43. #else
  44. #define DBG_C(x...) do {} while (0)
  45. #define DBG_I(x...) do {} while (0)
  46. #define DBG_S(x...) do {} while (0)
  47. #endif
  48. #ifdef SUPPORT_QMU
  49. /*
  50. * get_bd - get a null bd
  51. * @args - arg1: dir, arg2: ep number
  52. */
  53. struct tbd *get_bd(u8 dir, u32 num)
  54. {
  55. struct tbd *ptr;
  56. if (dir == USB_DIR_OUT) {
  57. ptr = rx_bd_list[num].pnext;
  58. DBG_I("(rx_bd_list[%d].pnext: %p)\n", num, rx_bd_list[num].pnext);
  59. if ((rx_bd_list[num].pnext + 1) < rx_bd_list[num].pend)
  60. rx_bd_list[num].pnext++;
  61. else
  62. rx_bd_list[num].pnext = rx_bd_list[num].pstart;
  63. } else {
  64. ptr = tx_bd_list[num].pnext;
  65. DBG_I("(tx_gpd_list[%d].pnext: %p)\n", num, (void *)(tx_bd_list[num].pnext));
  66. tx_bd_list[num].pnext++;
  67. tx_bd_list[num].pnext = (struct tbd *)((u8*)(tx_bd_list[num].pnext) + AT_BD_EXT_LEN);
  68. if (tx_bd_list[num].pnext >= tx_bd_list[num].pend) {
  69. tx_bd_list[num].pnext = tx_bd_list[num].pstart;
  70. }
  71. }
  72. return ptr;
  73. }
  74. /*
  75. * get_bd - get a null gpd
  76. * @args - arg1: dir, arg2: ep number
  77. */
  78. struct tgpd *get_gpd(u8 dir, u32 num)
  79. {
  80. struct tgpd *ptr;
  81. if (dir == USB_DIR_OUT) {
  82. ptr = (struct tgpd *)rx_gpd_list[num].pnext;
  83. DBG_I("(rx_gpd_list[%d].pnext: %p)\n", num, (void *)(rx_gpd_list[num].pnext));
  84. if ((rx_gpd_list[num].pnext +1) < rx_gpd_list[num].pend)
  85. rx_gpd_list[num].pnext++;
  86. else
  87. rx_gpd_list[num].pnext = rx_gpd_list[num].pstart;
  88. } else {
  89. ptr = (struct tgpd *)tx_gpd_list[num].pnext;
  90. DBG_I("(tx_gpd_list[%d].pnext: %p)\n", num, (void *)(tx_gpd_list[num].pnext));
  91. tx_gpd_list[num].pnext++;
  92. #ifdef USB_QMU_GPDEXT
  93. tx_gpd_list[num].pnext = (struct tbd *)((u8 *)tx_gpd_list[num].pnext + AT_GPD_EXT_LEN);
  94. #endif
  95. if (tx_gpd_list[num].pnext >= tx_gpd_list[num].pend) {
  96. tx_gpd_list[num].pnext = tx_gpd_list[num].pstart;
  97. }
  98. }
  99. return ptr;
  100. }
  101. /*
  102. * get_bd - align gpd ptr to target ptr
  103. * @args - arg1: dir, arg2: ep number, arg3: target ptr
  104. */
  105. void gpd_ptr_align(u8 dir, u32 num, struct tgpd *ptr)
  106. {
  107. u32 run_next;
  108. run_next = true;
  109. while (run_next) {
  110. if (ptr == get_gpd(dir, num)) {
  111. run_next = false;
  112. }
  113. }
  114. }
  115. /*
  116. * bd_virt_to_phys - map bd virtual address to physical address
  117. * @args - arg1: virtual address, arg2: dir, arg3: ep number
  118. * @return - physical address
  119. */
  120. void *bd_virt_to_phys(void *vaddr, u8 dir, u32 num)
  121. {
  122. void *ptr;
  123. if (dir == USB_DIR_OUT) {
  124. ptr = (vaddr - rx_bd_offset[num]);
  125. } else {
  126. ptr = (vaddr - tx_bd_offset[num]);
  127. }
  128. return ptr;
  129. }
  130. /*
  131. * bd_phys_to_virt - map bd physical address to virtual address
  132. * @args - arg1: physical address, arg2: dir, arg3: ep number
  133. * @return - virtual address
  134. */
  135. void *bd_phys_to_virt(void *paddr, u8 dir, u32 num)
  136. {
  137. void *ptr;
  138. DBG_I("paddr: %p\n", paddr);
  139. DBG_I("num: %d\n", num);
  140. if (dir == USB_DIR_OUT) {
  141. DBG_I("rx_bd_offset[%d]: %p\n", num, (void *)rx_bd_offset[num]);
  142. ptr = (paddr + rx_bd_offset[num]);
  143. } else {
  144. DBG_I("tx_bd_offset[%d]: %p\n", num, (void *)tx_bd_offset[num]);
  145. ptr = (paddr + tx_bd_offset[num]);
  146. }
  147. DBG_I("ptr: %p\n", ptr);
  148. return ptr;
  149. }
  150. /*
  151. * mu3d_hal_gpd_virt_to_phys - map gpd virtual address to physical address
  152. * @args - arg1: virtual address, arg2: dir, arg3: ep number
  153. * @return - physical address
  154. */
  155. void *mu3d_hal_gpd_virt_to_phys(void *vaddr, u8 dir, u32 num)
  156. {
  157. void *ptr;
  158. if (dir == USB_DIR_OUT) {
  159. ptr = (vaddr - rx_gpd_offset[num]);
  160. } else {
  161. ptr = (vaddr - tx_gpd_offset[num]);
  162. }
  163. return ptr;
  164. }
  165. /*
  166. * gpd_phys_to_virt - map gpd physical address to virtual address
  167. * @args - arg1: physical address, arg2: dir, arg3: ep number
  168. * @return - virtual address
  169. */
  170. void *gpd_phys_to_virt(void *paddr, u8 dir, u32 num)
  171. {
  172. void *ptr;
  173. DBG_I("paddr: %p\n", paddr);
  174. DBG_I("num: %d\n", num);
  175. if (dir == USB_DIR_OUT) {
  176. DBG_I("rx_gpd_offset[%d]: %p\n", num, (void *)rx_gpd_offset[num]);
  177. ptr = (paddr + rx_gpd_offset[num]);
  178. } else {
  179. DBG_I("tx_gpd_offset[%d]: %p\n", num, (void *)tx_gpd_offset[num]);
  180. ptr = (paddr + tx_gpd_offset[num]);
  181. }
  182. DBG_I("ptr: %p\n", ptr);
  183. return ptr;
  184. }
  185. /*
  186. * init_bd_list - initialize bd management list
  187. * @args - arg1: dir, arg2: ep number, arg3: bd virtual addr, arg4: bd ioremap addr, arg5: bd number
  188. */
  189. void init_bd_list(u8 dir, int num, struct tbd * ptr, struct tbd *io_ptr, u32 size)
  190. {
  191. if (dir == USB_DIR_OUT) {
  192. rx_bd_list[num].pstart = io_ptr;
  193. rx_bd_list[num].pend = (struct tbd *)(io_ptr + size);
  194. #if defined(SUPPORT_VA)
  195. rx_bd_offset[num] = (u32)io_ptr - (u32)os_virt_to_phys(ptr);
  196. #else
  197. rx_bd_offset[num] = (u32)io_ptr - (u32)ptr;
  198. #endif
  199. io_ptr++;
  200. rx_bd_list[num].pnext = io_ptr;
  201. DBG_I("rx_bd_list[%d].pstart: %p\n", num, rx_bd_list[num].pstart);
  202. DBG_I("rx_bd_list[%d].pnext: %p\n", num, rx_bd_list[num].pnext);
  203. DBG_I("rx_bd_list[%d].pend : %p\n", num, rx_bd_list[num].pend);
  204. DBG_I("rx_bd_offset[%d]: %p\n", num, (void *)rx_bd_offset[num]);
  205. #if defined(SUPPORT_VA)
  206. DBG_I("phy: %p\n", os_virt_to_phys(ptr));
  207. #else
  208. DBG_I("phy: %p\n", ptr);
  209. #endif
  210. DBG_I("io_ptr: %p\n", io_ptr);
  211. DBG_I("io_ptr end:%p\n", io_ptr+size);
  212. } else {
  213. tx_bd_list[num].pstart = io_ptr;
  214. tx_bd_list[num].pend = (struct tbd *)((u8*)(io_ptr+size) + AT_BD_EXT_LEN * size);
  215. #if defined(SUPPORT_VA)
  216. tx_bd_offset[num] = (u32)io_ptr-(u32)os_virt_to_phys(ptr);
  217. #else
  218. tx_bd_offset[num] = (u32)io_ptr-(u32)ptr;
  219. #endif
  220. io_ptr++;
  221. tx_bd_list[num].pnext = (struct tbd *)((u8*)io_ptr + AT_BD_EXT_LEN);
  222. DBG_I("tx_bd_list[%d].pstart: %p\n", num, tx_bd_list[num].pstart);
  223. DBG_I("tx_bd_list[%d].pnext : %p\n", num, tx_bd_list[num].pnext);
  224. DBG_I("tx_bd_list[%d].pend : %p\n", num, tx_bd_list[num].pend);
  225. DBG_I("tx_bd_offset[%d]: %p\n", num, (void *)tx_bd_offset[num]);
  226. #if defined(SUPPORT_VA)
  227. DBG_I("phy: %p\n", os_virt_to_phys(ptr));
  228. #else
  229. DBG_I("phy: %p\n", ptr);
  230. #endif
  231. DBG_I("io_ptr: %p\n", io_ptr);
  232. DBG_I("io_ptr end:%p\n", io_ptr+size);
  233. }
  234. }
  235. /*
  236. * init_gpd_list - initialize gpd management list
  237. * @args - arg1: dir, arg2: ep number, arg3: gpd virtual addr, arg4: gpd ioremap addr, arg5: gpd number
  238. */
  239. void init_gpd_list(u8 dir, int num, struct tgpd *ptr, struct tgpd *io_ptr, u32 size)
  240. {
  241. if (dir == USB_DIR_OUT) {
  242. rx_gpd_list[num].pstart = (struct tbd *)io_ptr;
  243. rx_gpd_list[num].pend = (struct tbd *)(io_ptr + size);
  244. #if defined(SUPPORT_VA)
  245. rx_gpd_offset[num] = (u32)io_ptr - (u32)os_virt_to_phys(ptr);
  246. #else
  247. rx_gpd_offset[num] = (u32)io_ptr - (u32)ptr;
  248. #endif
  249. io_ptr++;
  250. rx_gpd_list[num].pnext = (struct tbd *)io_ptr;
  251. DBG_I("rx_gpd_list[%d].pstart: %p\n", num, rx_gpd_list[num].pstart);
  252. DBG_I("rx_gpd_list[%d].pnext: %p\n", num, rx_gpd_list[num].pnext);
  253. DBG_I("rx_gpd_list[%d].pend: %p\n", num, rx_gpd_list[num].pend);
  254. DBG_I("rx_gpd_offset[%d]: %p\n", num, (void *)rx_gpd_offset[num]);
  255. #if defined(SUPPORT_VA)
  256. DBG_I("phy: %p\n", os_virt_to_phys(ptr));
  257. DBG_I("phy end: %p\n", os_virt_to_phys(ptr) + size);
  258. #else
  259. DBG_I("phy: %p\n", ptr);
  260. DBG_I("phy end: %p\n", ptr + size);
  261. #endif
  262. DBG_I("io_ptr: %p\n", io_ptr);
  263. DBG_I("io_ptr end: %p\n", io_ptr + size);
  264. } else {
  265. tx_gpd_list[num].pstart = (struct tbd *)io_ptr;
  266. #ifdef USB_QMU_GPDEXT
  267. tx_gpd_list[num].pend = (struct tbd *)((u8 *)(io_ptr + size) + AT_GPD_EXT_LEN * size);
  268. #else
  269. tx_gpd_list[num].pend = (struct tbd *)((u8 *)(io_ptr + size));
  270. #endif
  271. #if defined(SUPPORT_VA)
  272. tx_gpd_offset[num] = (u32)io_ptr - (u32)os_virt_to_phys(ptr);
  273. #else
  274. tx_gpd_offset[num] = (u32)io_ptr - (u32)ptr;
  275. #endif
  276. io_ptr++;
  277. #ifdef USB_QMU_GPDEXT
  278. tx_gpd_list[num].pnext = (struct tbd *)((u8 *)io_ptr + AT_GPD_EXT_LEN);
  279. #else
  280. tx_gpd_list[num].pnext = (struct tbd *)((u8 *)io_ptr);
  281. #endif
  282. DBG_I("tx_gpd_list[%d].pstart: %p\n", num, tx_gpd_list[num].pstart);
  283. DBG_I("tx_gpd_list[%d].pnext: %p\n", num, tx_gpd_list[num].pnext);
  284. DBG_I("tx_gpd_list[%d].pend: %p\n", num, tx_gpd_list[num].pend);
  285. DBG_I("tx_gpd_offset[%d]: %p\n", num, (void *)tx_gpd_offset[num]);
  286. #if defined(SUPPORT_VA)
  287. DBG_I("phy: %p\n", os_virt_to_phys(ptr));
  288. DBG_I("phy end: %p\n", os_virt_to_phys(ptr)); /* no need to add size? */
  289. #else
  290. DBG_I("phy: %p\n", ptr);
  291. DBG_I("phy end: %p\n", ptr); /* no need to add size? */
  292. #endif
  293. DBG_I("io_ptr: %p\n", io_ptr);
  294. DBG_I("io_ptr end: %p\n", io_ptr+size);
  295. }
  296. }
  297. /*
  298. * free_gpd - free gpd management list
  299. * @args - arg1: dir, arg2: ep number
  300. */
  301. void free_gpd(u8 dir, int num)
  302. {
  303. if (dir == USB_DIR_OUT) {
  304. memset(rx_gpd_list[num].pstart, 0, MAX_GPD_NUM * sizeof(struct tgpd));
  305. } else {
  306. memset(tx_gpd_list[num].pstart, 0, MAX_GPD_NUM * sizeof(struct tgpd));
  307. }
  308. }
  309. /*
  310. * mu3d_hal_alloc_qmu_mem - allocate gpd and bd memory for all ep
  311. *
  312. */
  313. void mu3d_hal_alloc_qmu_mem(void)
  314. {
  315. u32 i, size;
  316. struct tgpd *ptr, *io_ptr;
  317. struct tbd *bptr, *io_bptr;
  318. for (i = 1; i <= MAX_QMU_EP; i++) {
  319. /* alloc RX */
  320. size = sizeof(struct tgpd);
  321. size *= MAX_GPD_NUM;
  322. ptr = (struct tgpd*)memalign(32, size);
  323. if (!ptr)
  324. panic("%s: ptr rx memory allocate fail\n", __func__);
  325. memset(ptr, 0 , size);
  326. #if defined(SUPPORT_VA)
  327. io_ptr = (struct tgpd*)os_ioremap(os_virt_to_phys(ptr), size);
  328. #else
  329. //io_ptr = (struct tgpd*)os_ioremap(ptr, size);
  330. io_ptr = (struct tgpd*)ptr;
  331. #endif
  332. init_gpd_list(USB_DIR_OUT, i, ptr, io_ptr, MAX_GPD_NUM);
  333. rx_gpd_end[i] = io_ptr;
  334. DBG_I("ALLOC RX GPD End [%d] Virtual Mem@%p\n", i, (void *)rx_gpd_end[i]);
  335. memset(rx_gpd_end[i], 0 , sizeof(struct tgpd));
  336. TGPD_CLR_FLAGS_HWO(rx_gpd_end[i]);
  337. rx_gpd_head[i] = rx_gpd_last[i] = rx_gpd_end[i];
  338. #if defined(SUPPORT_VA)
  339. DBG_I("RQSAR[%d]: %p\n", i, mu3d_hal_gpd_virt_to_phys(rx_gpd_end[i], USB_DIR_OUT, i));
  340. #else
  341. DBG_I("RQSAR[%d]: %p\n", i, rx_gpd_end[i]);
  342. #endif
  343. /* alloc TX */
  344. size = sizeof(struct tgpd);
  345. #ifdef USB_QMU_GPDEXT
  346. size += AT_GPD_EXT_LEN;
  347. #endif
  348. size *= MAX_GPD_NUM;
  349. ptr = (struct tgpd*)memalign(32, size);
  350. if (!ptr)
  351. panic("%s: ptr tx memory allocate fail\n", __func__);
  352. memset(ptr, 0, size);
  353. #if defined(SUPPORT_VA)
  354. io_ptr = (struct tgpd*)os_ioremap(os_virt_to_phys(ptr), size);
  355. #else
  356. io_ptr = (struct tgpd*)ptr;
  357. #endif
  358. init_gpd_list(USB_DIR_IN, i, ptr, io_ptr, MAX_GPD_NUM);
  359. tx_gpd_end[i] = io_ptr;
  360. DBG_I("ALLOC TX GPD End [%d] Virtual Mem@%p\n", i, (void *)tx_gpd_end[i]);
  361. #ifdef USB_QMU_GPDEXT
  362. memset(tx_gpd_end[i], 0 , sizeof(struct tgpd) + AT_GPD_EXT_LEN);
  363. #else
  364. memset(tx_gpd_end[i], 0 , sizeof(struct tgpd));
  365. #endif
  366. TGPD_CLR_FLAGS_HWO(tx_gpd_end[i]);
  367. tx_gpd_head[i] = tx_gpd_last[i] = tx_gpd_end[i];
  368. #if defined(SUPPORT_VA)
  369. DBG_I("TQSAR[%d]: %p\n", i, mu3d_hal_gpd_virt_to_phys(tx_gpd_end[i], USB_DIR_IN, i));
  370. #else
  371. DBG_I("TQSAR[%d]: %p\n", i, tx_gpd_end[i]);
  372. #endif
  373. size = (sizeof(struct tbd));
  374. size *= MAX_BD_NUM;
  375. bptr = (struct tbd*)memalign(32, size);
  376. if (!bptr)
  377. panic("%s: bptr rx memory allocate fail\n", __func__);
  378. memset(bptr, 0, size);
  379. #if defined(SUPPORT_VA)
  380. io_bptr = (struct tbd*)os_ioremap(os_virt_to_phys(bptr), size);
  381. #else
  382. io_bptr = (struct tbd*)bptr;
  383. #endif
  384. init_bd_list(USB_DIR_OUT, i, bptr, io_bptr ,MAX_BD_NUM);
  385. size = (sizeof(struct tbd));
  386. size += AT_BD_EXT_LEN;
  387. size *= MAX_BD_NUM;
  388. bptr = (struct tbd*)memalign(32, size);
  389. if (!bptr)
  390. panic("%s: bptr tx memory allocate fail\n", __func__);
  391. memset(bptr, 0, size);
  392. #if defined(SUPPORT_VA)
  393. io_bptr = (struct tbd*)os_ioremap(os_virt_to_phys(bptr),size);
  394. #else
  395. io_bptr = (struct tbd*)bptr;
  396. #endif
  397. init_bd_list(USB_DIR_IN, i, bptr, io_bptr ,MAX_BD_NUM);
  398. }
  399. }
  400. /*
  401. * mu3d_hal_init_qmu - initialize qmu
  402. *
  403. */
  404. void mu3d_hal_init_qmu(void)
  405. {
  406. DBG_I("%s\n", __func__);
  407. u32 i;
  408. u32 qcr = 0;
  409. /* Initialize QMU Tx/Rx start address. */
  410. for (i = 1; i <= MAX_QMU_EP; i++) {
  411. qcr |= QMU_RX_EN(i);
  412. qcr |= QMU_TX_EN(i);
  413. #if defined(SUPPORT_VA)
  414. writel(mu3d_hal_gpd_virt_to_phys(rx_gpd_head[i], USB_DIR_OUT, i), U3D_RXQSAR(i));
  415. writel(mu3d_hal_gpd_virt_to_phys(tx_gpd_head[i], USB_DIR_IN, i), U3D_TXQSAR(i));
  416. #else
  417. writel((u32)rx_gpd_head[i], U3D_RXQSAR(i));
  418. writel((u32)tx_gpd_head[i], U3D_TXQSAR(i));
  419. DBG_I("U3D_RXQSAR%d: %p, val: %x\n", i, (void *)U3D_RXQSAR(i), readl(U3D_RXQSAR(i)));
  420. DBG_I("U3D_TXQSAR%d: %p, val: %x\n", i, (void *)U3D_TXQSAR(i), readl(U3D_TXQSAR(i)));
  421. #endif
  422. arch_clean_invalidate_cache_range((addr_t) tx_gpd_head[i], MAX_GPD_NUM * sizeof(struct tgpd));
  423. arch_clean_invalidate_cache_range((addr_t) rx_gpd_head[i], MAX_GPD_NUM * sizeof(struct tgpd));
  424. tx_gpd_end[i] = tx_gpd_last[i] = tx_gpd_head[i];
  425. rx_gpd_end[i] = rx_gpd_last[i] = rx_gpd_head[i];
  426. gpd_ptr_align(USB_DIR_OUT, i, rx_gpd_end[i]);
  427. gpd_ptr_align(USB_DIR_IN, i, tx_gpd_end[i]);
  428. }
  429. /* Enable QMU Tx/Rx. */
  430. writel(qcr, U3D_QGCSR);
  431. writel(qcr, U3D_QIESR0);
  432. /* Enable QMU interrupt. */
  433. writel((TXQ_EMPTY_IESR | TXQ_CSERR_IESR | TXQ_LENERR_IESR | RXQ_EMPTY_IESR | RXQ_CSERR_IESR | RXQ_LENERR_IESR | RXQ_ZLPERR_IESR), U3D_QIESR1);
  434. writel(EP0ISR, U3D_EPIESR);
  435. }
  436. /*
  437. * mu3d_hal_cal_checksum - calculate check sum
  438. * @args - arg1: data buffer, arg2: data length
  439. */
  440. u8 mu3d_hal_cal_checksum(u8 *data, int len)
  441. {
  442. u8 *pdata, cksum;
  443. int i;
  444. *(data + 1) = 0x0;
  445. pdata = data;
  446. cksum = 0;
  447. for (i = 0; i < len; i++) {
  448. cksum += *(pdata + i);
  449. }
  450. return 0xFF - cksum;
  451. }
  452. /*
  453. * mu3d_hal_resume_qmu - resume qmu function
  454. * @args - arg1: ep number, arg2: dir
  455. */
  456. void mu3d_hal_resume_qmu(int q_ep_num, u8 dir)
  457. {
  458. DBG_I("%s\n", __func__);
  459. #if defined(USB_RISC_CACHE_ENABLED)
  460. os_flushinvalidateDcache();
  461. #endif
  462. if (dir == USB_DIR_IN) {
  463. writel(QMU_Q_RESUME, U3D_TXQCSR(q_ep_num));
  464. if (!readl(U3D_TXQCSR(q_ep_num))) { //judge if Queue is still inactive
  465. DBG_I("%s: TXQCSR1 val: %x\n", __func__, readl(U3D_TXQCSR(q_ep_num)));
  466. writel(QMU_Q_RESUME, U3D_TXQCSR(q_ep_num));
  467. }
  468. } else if (dir == USB_DIR_OUT) {
  469. writel(QMU_Q_RESUME, U3D_RXQCSR(q_ep_num));
  470. if (!readl(U3D_RXQCSR(q_ep_num))) {
  471. DBG_I("%s: RXQCSR1 val: %x\n", __func__, readl(U3D_RXQCSR(q_ep_num)));
  472. writel(QMU_Q_RESUME, U3D_RXQCSR(q_ep_num));
  473. }
  474. }
  475. }
  476. /*
  477. * mu3d_hal_prepare_tx_gpd - prepare tx gpd/bd
  478. * @args - arg1: gpd address, arg2: data buffer address, arg3: data length, arg4: ep number, arg5: with bd or not, arg6: write hwo bit or not, arg7: write ioc bit or not
  479. */
  480. struct tgpd* mu3d_hal_prepare_tx_gpd(struct tgpd *gpd, u8 *pbuf, u32 data_len, u8 ep_num, u8 _is_bdp, u8 ishwo, u8 ioc, u8 bps, u8 zlp)
  481. {
  482. u32 offset;
  483. int i, bd_num;
  484. struct tbd *bd_next;
  485. struct tbd *bd_head, *bd;
  486. u32 length;
  487. u8 *pbuffer;
  488. u8 *_tmp;
  489. #if defined(SUPPORT_VA)
  490. u8 *vbuffer;
  491. #endif
  492. DBG_I("%s: ep_num: %d, pbuf: %x, data_len: %x, zlp: %x\n", __func__, (int)ep_num, (u32)pbuf, data_len, (u32)zlp);
  493. if (data_len <= gpd_extension) {
  494. _is_bdp = 0;
  495. }
  496. arch_clean_invalidate_cache_range((addr_t) gpd, sizeof(struct tgpd));
  497. if (!_is_bdp) {
  498. TGPD_SET_DATA(gpd, pbuf + gpd_extension);
  499. TGPD_CLR_FORMAT_BDP(gpd);
  500. } else {
  501. bd_head = (struct tbd*)get_bd(USB_DIR_IN, ep_num);
  502. DBG_I("Malloc Tx 01 (BD): 0x%x\n", (u32)bd_head);
  503. bd = bd_head;
  504. memset(bd, 0, sizeof(struct tbd) + bd_extension);
  505. length = data_len - gpd_extension;
  506. pbuffer = (u8*)(pbuf + gpd_extension);
  507. offset = bd_buf_size + bd_extension;
  508. bd_num = (!(length%offset)) ? (length/offset) : ((length/offset) + 1);
  509. if (offset > length) {
  510. offset = length;
  511. }
  512. for (i = 0; i < bd_num; i++) {
  513. DBG_I("bd[%d]: %p\n", i, bd);
  514. if (i == (bd_num - 1)) {
  515. if (length < bd_extension) {
  516. TBD_SET_EXT_LEN(bd, length);
  517. TBD_SET_BUF_LEN(bd, 0);
  518. TBD_SET_DATA(bd, pbuffer + bd_extension);
  519. } else {
  520. TBD_SET_EXT_LEN(bd, bd_extension);
  521. TBD_SET_BUF_LEN(bd, length - bd_extension);
  522. TBD_SET_DATA(bd, pbuffer + bd_extension);
  523. }
  524. TBD_SET_FLAGS_EOL(bd);
  525. TBD_SET_NEXT(bd, 0);
  526. TBD_SET_CHKSUM(bd, CHECKSUM_LENGTH);
  527. if (bd_extension) {
  528. #if defined(SUPPORT_VA)
  529. vbuffer = os_phys_to_virt(pbuffer);
  530. #endif
  531. arch_clean_invalidate_cache_range((addr_t) pbuf, g_dma_buffer_size);
  532. _tmp = TBD_GET_EXT(bd);
  533. #if defined(SUPPORT_VA)
  534. memcpy(_tmp, vbuffer, bd_extension);
  535. #else
  536. memcpy(_tmp, pbuffer, bd_extension);
  537. #endif
  538. arch_clean_invalidate_cache_range((addr_t) pbuf, g_dma_buffer_size);
  539. }
  540. DBG_I("BD number %d\n", i + 1);
  541. data_len = length + gpd_extension;
  542. length = 0;
  543. break;
  544. } else { /* if (i != (bd_num - 1)) */
  545. TBD_SET_EXT_LEN(bd, bd_extension);
  546. TBD_SET_BUF_LEN(bd, offset - bd_extension);
  547. TBD_SET_DATA(bd, pbuffer + bd_extension);
  548. TBD_CLR_FLAGS_EOL(bd);
  549. bd_next = (struct tbd*)get_bd(USB_DIR_IN, ep_num);
  550. memset(bd_next, 0, sizeof(struct tbd) + bd_extension);
  551. #if defined(SUPPORT_VA)
  552. TBD_SET_NEXT(bd, bd_virt_to_phys(bd_next, USB_DIR_IN, ep_num));
  553. #else
  554. TBD_SET_NEXT(bd, bd_next);
  555. #endif
  556. TBD_SET_CHKSUM(bd, CHECKSUM_LENGTH);
  557. if (bd_extension) {
  558. #if defined(SUPPORT_VA)
  559. vbuffer = os_phys_to_virt(pbuffer);
  560. #endif
  561. arch_clean_invalidate_cache_range((addr_t) pbuf, g_dma_buffer_size);
  562. _tmp = TBD_GET_EXT(bd);
  563. #if defined(SUPPORT_VA)
  564. memcpy(_tmp, vbuffer, bd_extension);
  565. #else
  566. memcpy(_tmp, pbuffer, bd_extension);
  567. #endif
  568. arch_clean_invalidate_cache_range((addr_t) pbuf, g_dma_buffer_size);
  569. }
  570. length -= offset;
  571. pbuffer += offset;
  572. bd = bd_next;
  573. }
  574. }
  575. #if defined(SUPPORT_VA)
  576. TGPD_SET_DATA(gpd, bd_virt_to_phys(bd_head, USB_DIR_IN, ep_num));
  577. #else
  578. TGPD_SET_DATA(gpd, bd_head);
  579. #endif
  580. TGPD_SET_FORMAT_BDP(gpd);
  581. }
  582. DBG_I("GPD data_len %d\n", (data_len - gpd_extension));
  583. if (data_len < gpd_extension) {
  584. TGPD_SET_BUF_LEN(gpd, 0);
  585. TGPD_SET_EXT_LEN(gpd, data_len);
  586. } else {
  587. TGPD_SET_BUF_LEN(gpd, data_len - gpd_extension);
  588. TGPD_SET_EXT_LEN(gpd, gpd_extension);
  589. }
  590. if (gpd_extension) {
  591. #if defined(SUPPORT_VA)
  592. vbuffer = os_phys_to_virt(pbuf);
  593. #endif
  594. arch_clean_invalidate_cache_range((addr_t) pbuf, g_dma_buffer_size);
  595. _tmp = TGPD_GET_EXT(gpd);
  596. #if defined(SUPPORT_VA)
  597. memcpy(_tmp, vbuffer, gpd_extension);
  598. #else
  599. memcpy(_tmp, pbuf, gpd_extension);
  600. #endif
  601. arch_clean_invalidate_cache_range((addr_t) pbuf, g_dma_buffer_size);
  602. }
  603. if (zlp) {
  604. TGPD_SET_FORMAT_ZLP(gpd);
  605. } else {
  606. TGPD_CLR_FORMAT_ZLP(gpd);
  607. }
  608. if (bps) {
  609. TGPD_SET_FORMAT_BPS(gpd);
  610. } else {
  611. TGPD_CLR_FORMAT_BPS(gpd);
  612. }
  613. if (ioc) {
  614. TGPD_SET_FORMAT_IOC(gpd);
  615. } else {
  616. TGPD_CLR_FORMAT_IOC(gpd);
  617. }
  618. /* Create next GPD */
  619. tx_gpd_end[ep_num] = get_gpd(USB_DIR_IN, ep_num);
  620. DBG_I("Malloc Tx 01 (GPD+EXT) (tx_gpd_end): 0x%x\n", (u32)tx_gpd_end[ep_num]);
  621. arch_clean_invalidate_cache_range((addr_t) tx_gpd_end[ep_num], sizeof(struct tgpd));
  622. memset(tx_gpd_end[ep_num], 0 , sizeof(struct tgpd) + gpd_extension);
  623. TGPD_CLR_FLAGS_HWO(tx_gpd_end[ep_num]);
  624. #if defined(SUPPORT_VA)
  625. TGPD_SET_NEXT(gpd, mu3d_hal_gpd_virt_to_phys(tx_gpd_end[ep_num],USB_DIR_IN, ep_num));
  626. #else
  627. TGPD_SET_NEXT(gpd, tx_gpd_end[ep_num]);
  628. #endif
  629. if (ishwo) {
  630. TGPD_SET_CHKSUM(gpd, CHECKSUM_LENGTH);
  631. TGPD_SET_FLAGS_HWO(gpd);
  632. } else {
  633. TGPD_CLR_FLAGS_HWO(gpd);
  634. TGPD_SET_CHKSUM_HWO(gpd, CHECKSUM_LENGTH);
  635. }
  636. #if defined(USB_RISC_CACHE_ENABLED)
  637. os_flushinvalidateDcache();
  638. #endif
  639. /* gpd end */
  640. arch_clean_invalidate_cache_range((addr_t) gpd, sizeof(struct tgpd));
  641. return gpd;
  642. }
  643. /*
  644. * mu3d_hal_prepare_rx_gpd - prepare rx gpd/bd
  645. * @args - arg1: gpd address, arg2: data buffer address, arg3: data length, arg4: ep number, arg5: with bd or not, arg6: write hwo bit or not, arg7: write ioc bit or not
  646. */
  647. struct tgpd* mu3d_hal_prepare_rx_gpd(struct tgpd *gpd, u8 *pbuf, u32 data_len, u8 ep_num, u8 _is_bdp, u8 ishwo, u8 ioc, u8 bps, u32 max_pkt_size)
  648. {
  649. u32 offset;
  650. int i, bd_num;
  651. unsigned int length;
  652. struct tbd *bd_next;
  653. struct tbd *bd_head, *bd;
  654. u8 *pbuffer;
  655. DBG_I("%s: GPD: %p, ep_num: %d, pbuf: %x, data_len: %x, _is_bdp: %d, ishwo: %d, ioc: %d, bps: %d\n", __func__, gpd, (int)ep_num, (u32)pbuf, data_len, _is_bdp, ishwo, ioc, bps);
  656. length = data_len;
  657. arch_clean_invalidate_cache_range((addr_t) gpd, sizeof(struct tgpd));
  658. if (!_is_bdp) {
  659. TGPD_SET_DATA(gpd, pbuf);
  660. TGPD_CLR_FORMAT_BDP(gpd);
  661. } else {
  662. bd_head = (struct tbd*)get_bd(USB_DIR_OUT, ep_num);
  663. bd = bd_head;
  664. memset(bd, 0, sizeof(struct tbd));
  665. offset = bd_buf_size;
  666. pbuffer = (u8*)(pbuf);
  667. bd_num = (!(length%offset)) ? (length/offset) : ((length/offset)+1);
  668. for (i = 0; i < bd_num; i++) {
  669. DBG_I("bd[%d]: %p\n", i, bd);
  670. TBD_SET_BUF_LEN(bd, 0);
  671. TBD_SET_DATA(bd, pbuffer);
  672. if (i == (bd_num - 1)) {
  673. length = (!(length%max_pkt_size)) ? (length) : ((length/max_pkt_size)+1)*max_pkt_size;
  674. TBD_SET_DATABUF_LEN(bd, length); //The last one's data buffer lengnth must be precise, or the GPD will never done unless ZLP or short packet.
  675. TBD_SET_FLAGS_EOL(bd);
  676. TBD_SET_NEXT(bd, 0);
  677. TBD_SET_CHKSUM(bd, CHECKSUM_LENGTH);
  678. DBG_I("BD number %d\n", i + 1);
  679. break;
  680. } else {
  681. TBD_SET_DATABUF_LEN(bd, offset);
  682. TBD_CLR_FLAGS_EOL(bd);
  683. bd_next = (struct tbd*)get_bd(USB_DIR_OUT, ep_num);
  684. memset(bd_next, 0, sizeof(struct tbd));
  685. #if defined(SUPPORT_VA)
  686. TBD_SET_NEXT(bd, bd_virt_to_phys(bd_next,USB_DIR_OUT, ep_num));
  687. #else
  688. TBD_SET_NEXT(bd, bd_next);
  689. #endif
  690. TBD_SET_CHKSUM(bd, CHECKSUM_LENGTH);
  691. pbuffer += offset;
  692. length -= offset;
  693. bd = bd_next;
  694. }
  695. }
  696. #if defined(SUPPORT_VA)
  697. TGPD_SET_DATA(gpd, bd_virt_to_phys(bd_head, USB_DIR_OUT, ep_num));
  698. #else
  699. TGPD_SET_DATA(gpd, bd_head);
  700. #endif
  701. TGPD_SET_FORMAT_BDP(gpd);
  702. }
  703. if (data_len < gpd_buf_size)
  704. TGPD_SET_DATABUF_LEN(gpd, data_len); /* or length?? */
  705. else
  706. TGPD_SET_DATABUF_LEN(gpd, gpd_buf_size);
  707. TGPD_SET_BUF_LEN(gpd, 0);
  708. if (bps) {
  709. TGPD_SET_FORMAT_BPS(gpd);
  710. } else {
  711. TGPD_CLR_FORMAT_BPS(gpd);
  712. }
  713. if (ioc) {
  714. TGPD_SET_FORMAT_IOC(gpd);
  715. } else {
  716. TGPD_CLR_FORMAT_IOC(gpd);
  717. }
  718. rx_gpd_end[ep_num] = get_gpd(USB_DIR_OUT, ep_num);
  719. memset(rx_gpd_end[ep_num], 0, sizeof(struct tgpd));
  720. DBG_I("Rx Next GPD 0x%x\n", (u32)rx_gpd_end[ep_num]);
  721. TGPD_CLR_FLAGS_HWO(rx_gpd_end[ep_num]);
  722. #if defined(SUPPORT_VA)
  723. TGPD_SET_NEXT(gpd, mu3d_hal_gpd_virt_to_phys(rx_gpd_end[ep_num], USB_DIR_OUT, ep_num));
  724. #else
  725. TGPD_SET_NEXT(gpd, rx_gpd_end[ep_num]);
  726. #endif
  727. if (ishwo) {
  728. TGPD_SET_CHKSUM(gpd, CHECKSUM_LENGTH);
  729. TGPD_SET_FLAGS_HWO(gpd);
  730. } else {
  731. TGPD_CLR_FLAGS_HWO(gpd);
  732. TGPD_SET_CHKSUM_HWO(gpd, CHECKSUM_LENGTH);
  733. }
  734. DBG_I("Rx gpd info { HWO %d, Next_GPD %x ,databuf_length %d, DataBuffer %x, Recived Len %d, Endpoint %d, TGL %d, ZLP %d}\n",
  735. (u32)TGPD_GET_FLAG(gpd), (u32)TGPD_GET_NEXT(gpd),
  736. (u32)TGPD_GET_DATABUF_LEN(gpd), (u32)TGPD_GET_DATA(gpd),
  737. (u32)TGPD_GET_BUF_LEN(gpd), (u32)TGPD_GET_EPaddr(gpd),
  738. (u32)TGPD_GET_TGL(gpd), (u32)TGPD_GET_ZLP(gpd));
  739. arch_clean_invalidate_cache_range((addr_t) gpd, sizeof(struct tgpd));
  740. return gpd;
  741. }
  742. /*
  743. * mu3d_hal_insert_transfer_gpd - insert new gpd/bd
  744. * @args - arg1: ep number, arg2: dir, arg3: data buffer, arg4: data length, arg5: write hwo bit or not, arg6: write ioc bit or not
  745. */
  746. void mu3d_hal_insert_transfer_gpd(int ep_num, u8 dir, u8* buf, u32 count, u8 ishwo, u8 ioc, u8 bps, u8 zlp, u32 max_pkt_size)
  747. {
  748. struct tgpd* gpd;
  749. DBG_I("%s: ep_num: %d, dir: %d, buf: %x, count: %x, ishwo: %d, ioc: :%d, bps: %d, zlp: %x, maxp: %x\n", __func__, (int)ep_num, dir, (u32)buf, count, ishwo, ioc, bps, (u32)zlp, (u32)max_pkt_size);
  750. if (dir == USB_DIR_IN) {
  751. gpd = tx_gpd_end[ep_num];
  752. DBG_I("TX gpd: %x\n", (unsigned int)gpd);
  753. mu3d_hal_prepare_tx_gpd(gpd, buf, count, ep_num, is_bdp, ishwo, ioc, bps, zlp);
  754. } else if (dir == USB_DIR_OUT) {
  755. gpd = rx_gpd_end[ep_num];
  756. DBG_I("RX gpd: %x\n", (unsigned int)gpd);
  757. mu3d_hal_prepare_rx_gpd(gpd, buf, count, ep_num, is_bdp, ishwo, ioc, bps, max_pkt_size);
  758. }
  759. }
  760. /*
  761. * mu3d_hal_start_qmu - start qmu function (QMU flow : mu3d_hal_init_qmu ->mu3d_hal_start_qmu -> mu3d_hal_insert_transfer_gpd -> mu3d_hal_resume_qmu)
  762. * @args - arg1: ep number, arg2: dir
  763. */
  764. void mu3d_hal_start_qmu(int q_ep_num, u8 dir)
  765. {
  766. u32 qcr;
  767. u32 txcsr;
  768. DBG_I("%s: dir: %x\n", __func__, dir);
  769. if (dir == USB_DIR_IN) {
  770. txcsr = USB_READCSR32(U3D_TX1CSR0, q_ep_num) & 0xFFFEFFFF;
  771. USB_WRITECSR32(U3D_TX1CSR0, q_ep_num, txcsr | TX_DMAREQEN);
  772. qcr = readl(U3D_QCR0);
  773. writel(qcr | QMU_TX_CS_EN(q_ep_num), U3D_QCR0);
  774. #if (TXZLP == HW_MODE)
  775. qcr = readl(U3D_QCR1);
  776. writel(qcr &~ QMU_TX_ZLP(q_ep_num), U3D_QCR1);
  777. qcr = readl(U3D_QCR2);
  778. writel(qcr | QMU_TX_ZLP(q_ep_num), U3D_QCR2);
  779. #elif (TXZLP == GPD_MODE)
  780. qcr = readl(U3D_QCR1);
  781. writel(qcr | QMU_TX_ZLP(q_ep_num), U3D_QCR1);
  782. #endif
  783. writel(readl(U3D_QEMIESR) | QMU_TX_EMPTY(q_ep_num), U3D_QEMIESR);
  784. writel(QMU_TX_LEN_ERR(q_ep_num) | QMU_TX_CS_ERR(q_ep_num), U3D_TQERRIESR0);
  785. if (readl(U3D_TXQCSR(q_ep_num)) & QMU_Q_ACTIVE) {
  786. DBG_I("Tx %d Active Now!\n", q_ep_num);
  787. return;
  788. }
  789. #if defined(USB_RISC_CACHE_ENABLED)
  790. os_flushinvalidateDcache();
  791. #endif
  792. writel(QMU_Q_START, U3D_TXQCSR(q_ep_num));
  793. } else if (dir == USB_DIR_OUT) {
  794. USB_WRITECSR32(U3D_RX1CSR0, q_ep_num, USB_READCSR32(U3D_RX1CSR0, q_ep_num) |(RX_DMAREQEN));
  795. qcr = readl(U3D_QCR0);
  796. writel(qcr | QMU_RX_CS_EN(q_ep_num), U3D_QCR0);
  797. #ifdef CFG_RX_ZLP_EN
  798. qcr = readl(U3D_QCR3);
  799. writel(qcr | QMU_RX_ZLP(q_ep_num), U3D_QCR3);
  800. #else
  801. qcr = readl(U3D_QCR3);
  802. writel(qcr & ~(QMU_RX_ZLP(q_ep_num)), U3D_QCR3);
  803. #endif
  804. #ifdef CFG_RX_COZ_EN
  805. qcr = readl(U3D_QCR3);
  806. writel(qcr | QMU_RX_COZ(q_ep_num), U3D_QCR3);
  807. #else
  808. qcr = readl(U3D_QCR3);
  809. writel(qcr & ~(QMU_RX_COZ(q_ep_num)), U3D_QCR3);
  810. #endif
  811. writel(readl(U3D_QEMIESR) | QMU_RX_EMPTY(q_ep_num), U3D_QEMIESR);
  812. writel(QMU_RX_LEN_ERR(q_ep_num) | QMU_RX_CS_ERR(q_ep_num), U3D_RQERRIESR0);
  813. writel(QMU_RX_EP_ERR(q_ep_num) | QMU_RX_ZLP_ERR(q_ep_num), U3D_RQERRIESR1);
  814. if (readl(U3D_RXQCSR(q_ep_num)) & QMU_Q_ACTIVE) {
  815. DBG_I("Rx %d Active Now!\n", q_ep_num);
  816. return;
  817. }
  818. #if defined(USB_RISC_CACHE_ENABLED)
  819. os_flushinvalidateDcache();
  820. #endif
  821. writel(QMU_Q_START, U3D_RXQCSR(q_ep_num));
  822. }
  823. #if (CHECKSUM_TYPE == CS_16B)
  824. writel(readl(U3D_QCR0) | CS16B_EN, U3D_QCR0);
  825. #else
  826. writel(readl(U3D_QCR0) &~ CS16B_EN, U3D_QCR0);
  827. #endif
  828. }
  829. /*
  830. * mu3d_hal_stop_qmu - stop qmu function (after qmu stop, fifo should be flushed)
  831. * @args - arg1: ep number, arg2: dir
  832. */
  833. void mu3d_hal_stop_qmu(int q_ep_num, u8 dir)
  834. {
  835. DBG_I("%s\n", __func__);
  836. if (dir == USB_DIR_IN) {
  837. if (!(readl(U3D_TXQCSR(q_ep_num)) & (QMU_Q_ACTIVE))) {
  838. DBG_I("Tx %d inActive Now!\n", q_ep_num);
  839. return;
  840. }
  841. writel(QMU_Q_STOP, U3D_TXQCSR(q_ep_num));
  842. while ((readl(U3D_TXQCSR(q_ep_num)) & (QMU_Q_ACTIVE)));
  843. DBG_I("Tx %d stop Now!\n", q_ep_num);
  844. } else if (dir == USB_DIR_OUT) {
  845. if (!(readl(U3D_RXQCSR(q_ep_num)) & QMU_Q_ACTIVE)) {
  846. DBG_I("Rx %d inActive Now!\n", q_ep_num);
  847. return;
  848. }
  849. writel(QMU_Q_STOP, U3D_RXQCSR(q_ep_num));
  850. while ((readl(U3D_RXQCSR(q_ep_num)) & (QMU_Q_ACTIVE)));
  851. DBG_I("Rx %d stop Now!\n", q_ep_num);
  852. }
  853. }
  854. /*
  855. * mu3d_hal_send_stall - send stall
  856. * @args - arg1: ep number, arg2: dir
  857. */
  858. void mu3d_hal_send_stall(int q_ep_num, u8 dir)
  859. {
  860. if (dir == USB_DIR_IN) {
  861. USB_WRITECSR32(U3D_TX1CSR0, q_ep_num, USB_READCSR32(U3D_TX1CSR0, q_ep_num) | TX_SENDSTALL);
  862. while (!(USB_READCSR32(U3D_TX1CSR0, q_ep_num) & TX_SENTSTALL));
  863. USB_WRITECSR32(U3D_TX1CSR0, q_ep_num, USB_READCSR32(U3D_TX1CSR0, q_ep_num) | TX_SENTSTALL);
  864. USB_WRITECSR32(U3D_TX1CSR0, q_ep_num, USB_READCSR32(U3D_TX1CSR0, q_ep_num) &~ TX_SENDSTALL);
  865. DBG_I("EP[%d] SENTSTALL!\n",q_ep_num);
  866. } else if (dir == USB_DIR_OUT) {
  867. USB_WRITECSR32(U3D_RX1CSR0, q_ep_num, USB_READCSR32(U3D_RX1CSR0, q_ep_num) | RX_SENDSTALL);
  868. while (!(USB_READCSR32(U3D_RX1CSR0, q_ep_num) & RX_SENTSTALL));
  869. USB_WRITECSR32(U3D_RX1CSR0, q_ep_num, USB_READCSR32(U3D_RX1CSR0, q_ep_num) | RX_SENTSTALL);
  870. USB_WRITECSR32(U3D_RX1CSR0, q_ep_num, USB_READCSR32(U3D_RX1CSR0, q_ep_num) &~ RX_SENDSTALL);
  871. DBG_I("EP[%d] SENTSTALL!\n",q_ep_num);
  872. }
  873. }
  874. /*
  875. * mu3d_hal_reset_qmu_ep - clear toggle(or sequence) number
  876. * @args - arg1: ep number, arg2: dir
  877. */
  878. void mu3d_hal_reset_qmu_ep(int q_ep_num, u8 dir)
  879. {
  880. u32 ep_rst;
  881. DBG_I("%s\n", __func__);
  882. if (dir == USB_DIR_IN) {
  883. ep_rst = BIT16 << q_ep_num;
  884. writel(ep_rst, U3D_EP_RST);
  885. mdelay(1);
  886. writel(0, U3D_EP_RST);
  887. } else {
  888. ep_rst = 1 << q_ep_num;
  889. writel(ep_rst, U3D_EP_RST);
  890. mdelay(1);
  891. writel(0, U3D_EP_RST);
  892. }
  893. }
  894. /*
  895. * mu3d_hal_restart_qmu - clear toggle(or sequence) number and start qmu
  896. * @args - arg1: ep number, arg2: dir
  897. */
  898. void mu3d_hal_restart_qmu_ep(int q_ep_num, u8 dir)
  899. {
  900. mu3d_hal_reset_qmu_ep(q_ep_num, dir);
  901. mu3d_hal_start_qmu(q_ep_num, dir);
  902. }
  903. /*
  904. * flush_qmu - stop qmu and align qmu start ptr t0 current ptr
  905. * @args - arg1: ep number, arg2: dir
  906. */
  907. void mu3d_hal_flush_qmu(int q_ep_num, u8 dir)
  908. {
  909. struct tgpd *gpd_current;
  910. struct udc_endpoint *ept;
  911. struct urb *urb;
  912. //struct USB_REQ *req = mu3d_hal_get_req(q_ep_num, dir);
  913. ept = mt_find_ep(q_ep_num, dir);
  914. if (dir == USB_DIR_IN) {
  915. urb = ept->tx_urb;
  916. mu3d_hal_stop_qmu(q_ep_num, USB_DIR_IN);
  917. gpd_current = (struct tgpd*)(readl(U3D_TXQCPR(q_ep_num)));
  918. if (!gpd_current) {
  919. gpd_current = (struct tgpd*)(readl(U3D_TXQSAR(q_ep_num)));
  920. }
  921. #if defined(SUPPORT_VA)
  922. gpd_current = gpd_phys_to_virt(gpd_current, USB_DIR_IN, q_ep_num);
  923. #endif
  924. if (gpd_current != 0)
  925. tx_gpd_end[q_ep_num] = tx_gpd_last[q_ep_num] = gpd_current;
  926. gpd_ptr_align(dir, q_ep_num, tx_gpd_end[q_ep_num]);
  927. free_gpd(dir, q_ep_num);
  928. arch_clean_invalidate_cache_range((addr_t) tx_gpd_list[q_ep_num].pstart, MAX_GPD_NUM * sizeof(struct tgpd));
  929. #if defined(SUPPORT_VA)
  930. writel(mu3d_hal_gpd_virt_to_phys(tx_gpd_last[q_ep_num], USB_DIR_IN, q_ep_num), U3D_TXQSAR(q_ep_num));
  931. #else
  932. writel((u32)tx_gpd_last[q_ep_num], U3D_TXQSAR(q_ep_num));
  933. #endif
  934. urb->qmu_complete = true;
  935. DBG_I("TxQ %d Flush Now!\n", q_ep_num);
  936. } else if (dir == USB_DIR_OUT) {
  937. urb = ept->rcv_urb;
  938. mu3d_hal_stop_qmu(q_ep_num, USB_DIR_OUT);
  939. gpd_current = (struct tgpd *)(readl(U3D_RXQCPR(q_ep_num)));
  940. if (!gpd_current) {
  941. gpd_current = (struct tgpd *)(readl(U3D_RXQSAR(q_ep_num)));
  942. }
  943. #if defined(SUPPORT_VA)
  944. gpd_current = gpd_phys_to_virt(gpd_current, USB_DIR_OUT, q_ep_num);
  945. #endif
  946. if (gpd_current != 0)
  947. rx_gpd_end[q_ep_num] = rx_gpd_last[q_ep_num] = gpd_current;
  948. gpd_ptr_align(dir, q_ep_num, rx_gpd_end[q_ep_num]);
  949. free_gpd(dir, q_ep_num);
  950. arch_clean_invalidate_cache_range((addr_t) rx_gpd_list[q_ep_num].pstart, MAX_GPD_NUM * sizeof(struct tgpd));
  951. #if defined(SUPPORT_VA)
  952. writel(mu3d_hal_gpd_virt_to_phys(rx_gpd_end[q_ep_num], USB_DIR_OUT, q_ep_num), U3D_RXQSAR(q_ep_num));
  953. #else
  954. writel((u32)rx_gpd_end[q_ep_num], U3D_RXQSAR(q_ep_num));
  955. #endif
  956. urb->qmu_complete = true;
  957. DBG_I("RxQ %d Flush Now!\n", q_ep_num);
  958. }
  959. }
  960. #endif /* #ifdef SUPPORT_QMU */