0025-Add-FIQ-patch-to-dwc_otg-driver.-Enable-with-dwc_otg.patch 106 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244
  1. From a29a51d9320d44124fe13457c45663d3051a9452 Mon Sep 17 00:00:00 2001
  2. From: popcornmix <popcornmix@gmail.com>
  3. Date: Wed, 3 Jul 2013 00:46:42 +0100
  4. Subject: [PATCH 025/114] Add FIQ patch to dwc_otg driver. Enable with
  5. dwc_otg.fiq_fix_enable=1. Should give about 10% more ARM performance. Thanks
  6. to Gordon and Costas
  7. Avoid dynamic memory allocation for channel lock in USB driver. Thanks ddv2005.
  8. Add NAK holdoff scheme. Enabled by default, disable with dwc_otg.nak_holdoff_enable=0. Thanks gsh
  9. Make sure we wait for the reset to finish
  10. dwc_otg: fix bug in dwc_otg_hcd.c resulting in silent kernel
  11. memory corruption, escalating to OOPS under high USB load.
  12. dwc_otg: Fix unsafe access of QTD during URB enqueue
  13. In dwc_otg_hcd_urb_enqueue during qtd creation, it was possible that the
  14. transaction could complete almost immediately after the qtd was assigned
  15. to a host channel during URB enqueue, which meant the qtd pointer was no
  16. longer valid having been completed and removed. Usually, this resulted in
  17. an OOPS during URB submission. By predetermining whether transactions
  18. need to be queued or not, this unsafe pointer access is avoided.
  19. This bug was only evident on the Pi model A where a device was attached
  20. that had no periodic endpoints (e.g. USB pendrive or some wlan devices).
  21. dwc_otg: Fix incorrect URB allocation error handling
  22. If the memory allocation for a dwc_otg_urb failed, the kernel would OOPS
  23. because for some reason a member of the *unallocated* struct was set to
  24. zero. Error handling changed to fail correctly.
  25. dwc_otg: fix potential use-after-free case in interrupt handler
  26. If a transaction had previously aborted, certain interrupts are
  27. enabled to track error counts and reset where necessary. On IN
  28. endpoints the host generates an ACK interrupt near-simultaneously
  29. with completion of transfer. In the case where this transfer had
  30. previously had an error, this results in a use-after-free on
  31. the QTD memory space with a 1-byte length being overwritten to
  32. 0x00.
  33. dwc_otg: add handling of SPLIT transaction data toggle errors
  34. Previously a data toggle error on packets from a USB1.1 device behind
  35. a TT would result in the Pi locking up as the driver never handled
  36. the associated interrupt. Patch adds basic retry mechanism and
  37. interrupt acknowledgement to cater for either a chance toggle error or
  38. for devices that have a broken initial toggle state (FT8U232/FT232BM).
  39. dwc_otg: implement tasklet for returning URBs to usbcore hcd layer
  40. The dwc_otg driver interrupt handler for transfer completion will spend
  41. a very long time with interrupts disabled when a URB is completed -
  42. this is because usb_hcd_giveback_urb is called from within the handler
  43. which for a USB device driver with complicated processing (e.g. webcam)
  44. will take an exorbitant amount of time to complete. This results in
  45. missed completion interrupts for other USB packets which lead to them
  46. being dropped due to microframe overruns.
  47. This patch splits returning the URB to the usb hcd layer into a
  48. high-priority tasklet. This will have most benefit for isochronous IN
  49. transfers but will also have incidental benefit where multiple periodic
  50. devices are active at once.
  51. dwc_otg: fix NAK holdoff and allow on split transactions only
  52. This corrects a bug where if a single active non-periodic endpoint
  53. had at least one transaction in its qh, on frnum == MAX_FRNUM the qh
  54. would get skipped and never get queued again. This would result in
  55. a silent device until error detection (automatic or otherwise) would
  56. either reset the device or flush and requeue the URBs.
  57. Additionally the NAK holdoff was enabled for all transactions - this
  58. would potentially stall a HS endpoint for 1ms if a previous error state
  59. enabled this interrupt and the next response was a NAK. Fix so that
  60. only split transactions get held off.
  61. dwc_otg: Call usb_hcd_unlink_urb_from_ep with lock held in completion handler
  62. usb_hcd_unlink_urb_from_ep must be called with the HCD lock held. Calling it
  63. asynchronously in the tasklet was not safe (regression in
  64. c4564d4a1a0a9b10d4419e48239f5d99e88d2667).
  65. This change unlinks it from the endpoint prior to queueing it for handling in
  66. the tasklet, and also adds a check to ensure the urb is OK to be unlinked
  67. before doing so.
  68. NULL pointer dereference kernel oopses had been observed in usb_hcd_giveback_urb
  69. when a USB device was unplugged/replugged during data transfer. This effect
  70. was reproduced using automated USB port power control, hundreds of replug
  71. events were performed during active transfers to confirm that the problem was
  72. eliminated.
  73. USB fix using a FIQ to implement split transactions
  74. This commit adds a FIQ implementaion that schedules
  75. the split transactions using a FIQ so we don't get
  76. held off by the interrupt latency of Linux
  77. dwc_otg: fix device attributes and avoid kernel warnings on boot
  78. dcw_otg: avoid logging function that can cause panics
  79. See: https://github.com/raspberrypi/firmware/issues/21
  80. Thanks to cleverca22 for fix
  81. dwc_otg: mask correct interrupts after transaction error recovery
  82. The dwc_otg driver will unmask certain interrupts on a transaction
  83. that previously halted in the error state in order to reset the
  84. QTD error count. The various fine-grained interrupt handlers do not
  85. consider that other interrupts besides themselves were unmasked.
  86. By disabling the two other interrupts only ever enabled in DMA mode
  87. for this purpose, we can avoid unnecessary function calls in the
  88. IRQ handler. This will also prevent an unneccesary FIQ interrupt
  89. from being generated if the FIQ is enabled.
  90. dwc_otg: fiq: prevent FIQ thrash and incorrect state passing to IRQ
  91. In the case of a transaction to a device that had previously aborted
  92. due to an error, several interrupts are enabled to reset the error
  93. count when a device responds. This has the side-effect of making the
  94. FIQ thrash because the hardware will generate multiple instances of
  95. a NAK on an IN bulk/interrupt endpoint and multiple instances of ACK
  96. on an OUT bulk/interrupt endpoint. Make the FIQ mask and clear the
  97. associated interrupts.
  98. Additionally, on non-split transactions make sure that only unmasked
  99. interrupts are cleared. This caused a hard-to-trigger but serious
  100. race condition when you had the combination of an endpoint awaiting
  101. error recovery and a transaction completed on an endpoint - due to
  102. the sequencing and timing of interrupts generated by the dwc_otg core,
  103. it was possible to confuse the IRQ handler.
  104. Fix function tracing
  105. dwc_otg: whitespace cleanup in dwc_otg_urb_enqueue
  106. dwc_otg: prevent OOPSes during device disconnects
  107. The dwc_otg_urb_enqueue function is thread-unsafe. In particular the
  108. access of urb->hcpriv, usb_hcd_link_urb_to_ep, dwc_otg_urb->qtd and
  109. friends does not occur within a critical section and so if a device
  110. was unplugged during activity there was a high chance that the
  111. usbcore hub_thread would try to disable the endpoint with partially-
  112. formed entries in the URB queue. This would result in BUG() or null
  113. pointer dereferences.
  114. Fix so that access of urb->hcpriv, enqueuing to the hardware and
  115. adding to usbcore endpoint URB lists is contained within a single
  116. critical section.
  117. dwc_otg: prevent BUG() in TT allocation if hub address is > 16
  118. A fixed-size array is used to track TT allocation. This was
  119. previously set to 16 which caused a crash because
  120. dwc_otg_hcd_allocate_port would read past the end of the array.
  121. This was hit if a hub was plugged in which enumerated as addr > 16,
  122. due to previous device resets or unplugs.
  123. Also add #ifdef FIQ_DEBUG around hcd->hub_port_alloc[], which grows
  124. to a large size if 128 hub addresses are supported. This field is
  125. for debug only for tracking which frame an allocate happened in.
  126. dwc_otg: make channel halts with unknown state less damaging
  127. If the IRQ received a channel halt interrupt through the FIQ
  128. with no other bits set, the IRQ would not release the host
  129. channel and never complete the URB.
  130. Add catchall handling to treat as a transaction error and retry.
  131. dwc_otg: fiq_split: use TTs with more granularity
  132. This fixes certain issues with split transaction scheduling.
  133. - Isochronous multi-packet OUT transactions now hog the TT until
  134. they are completed - this prevents hubs aborting transactions
  135. if they get a periodic start-split out-of-order
  136. - Don't perform TT allocation on non-periodic endpoints - this
  137. allows simultaneous use of the TT's bulk/control and periodic
  138. transaction buffers
  139. This commit will mainly affect USB audio playback.
  140. dwc_otg: fix potential sleep while atomic during urb enqueue
  141. Fixes a regression introduced with eb1b482a. Kmalloc called from
  142. dwc_otg_hcd_qtd_add / dwc_otg_hcd_qtd_create did not always have
  143. the GPF_ATOMIC flag set. Force this flag when inside the larger
  144. critical section.
  145. dwc_otg: make fiq_split_enable imply fiq_fix_enable
  146. Failing to set up the FIQ correctly would result in
  147. "IRQ 32: nobody cared" errors in dmesg.
  148. dwc_otg: prevent crashes on host port disconnects
  149. Fix several issues resulting in crashes or inconsistent state
  150. if a Model A root port was disconnected.
  151. - Clean up queue heads properly in kill_urbs_in_qh_list by
  152. removing the empty QHs from the schedule lists
  153. - Set the halt status properly to prevent IRQ handlers from
  154. using freed memory
  155. - Add fiq_split related cleanup for saved registers
  156. - Make microframe scheduling reclaim host channels if
  157. active during a disconnect
  158. - Abort URBs with -ESHUTDOWN status response, informing
  159. device drivers so they respond in a more correct fashion
  160. and don't try to resubmit URBs
  161. - Prevent IRQ handlers from attempting to handle channel
  162. interrupts if the associated URB was dequeued (and the
  163. driver state was cleared)
  164. dwc_otg: prevent leaking URBs during enqueue
  165. A dwc_otg_urb would get leaked if the HCD enqueue function
  166. failed for any reason. Free the URB at the appropriate points.
  167. dwc_otg: Enable NAK holdoff for control split transactions
  168. Certain low-speed devices take a very long time to complete a
  169. data or status stage of a control transaction, producing NAK
  170. responses until they complete internal processing - the USB2.0
  171. spec limit is up to 500mS. This causes the same type of interrupt
  172. storm as seen with USB-serial dongles prior to c8edb238.
  173. In certain circumstances, usually while booting, this interrupt
  174. storm could cause SD card timeouts.
  175. dwc_otg: Fix for occasional lockup on boot when doing a USB reset
  176. dwc_otg: Don't issue traffic to LS devices in FS mode
  177. Issuing low-speed packets when the root port is in full-speed mode
  178. causes the root port to stop responding. Explicitly fail when
  179. enqueuing URBs to a LS endpoint on a FS bus.
  180. Fix ARM architecture issue with local_irq_restore()
  181. If local_fiq_enable() is called before a local_irq_restore(flags) where
  182. the flags variable has the F bit set, the FIQ will be erroneously disabled.
  183. Fixup arch_local_irq_restore to avoid trampling the F bit in CPSR.
  184. Also fix some of the hacks previously implemented for previous dwc_otg
  185. incarnations.
  186. ---
  187. arch/arm/Kconfig | 1 +
  188. arch/arm/include/asm/irqflags.h | 16 +-
  189. arch/arm/kernel/fiqasm.S | 4 +
  190. arch/arm/mach-bcm2708/armctrl.c | 19 +-
  191. arch/arm/mach-bcm2708/bcm2708.c | 29 +-
  192. arch/arm/mach-bcm2708/include/mach/irqs.h | 153 ++---
  193. .../usb/host/dwc_common_port/dwc_common_linux.c | 11 +
  194. drivers/usb/host/dwc_common_port/dwc_list.h | 14 +-
  195. drivers/usb/host/dwc_common_port/dwc_os.h | 2 +
  196. drivers/usb/host/dwc_otg/Makefile | 1 +
  197. drivers/usb/host/dwc_otg/dwc_otg_attr.c | 14 +-
  198. drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c | 47 +-
  199. drivers/usb/host/dwc_otg/dwc_otg_dbg.h | 1 +
  200. drivers/usb/host/dwc_otg/dwc_otg_driver.c | 52 +-
  201. drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 303 +++++++--
  202. drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 37 +-
  203. drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c | 3 +-
  204. drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h | 5 +
  205. drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 705 ++++++++++++++++++++-
  206. drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 159 +++--
  207. drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 53 +-
  208. drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c | 113 ++++
  209. drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h | 48 ++
  210. drivers/usb/host/dwc_otg/dwc_otg_os_dep.h | 3 +
  211. drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c | 2 +-
  212. 25 files changed, 1544 insertions(+), 251 deletions(-)
  213. create mode 100755 drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c
  214. create mode 100755 drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h
  215. --- a/arch/arm/Kconfig
  216. +++ b/arch/arm/Kconfig
  217. @@ -395,6 +395,7 @@ config ARCH_BCM2708
  218. select ARM_ERRATA_411920
  219. select MACH_BCM2708
  220. select VC4
  221. + select FIQ
  222. help
  223. This enables support for Broadcom BCM2708 boards.
  224. --- a/arch/arm/include/asm/irqflags.h
  225. +++ b/arch/arm/include/asm/irqflags.h
  226. @@ -145,12 +145,22 @@ static inline unsigned long arch_local_s
  227. }
  228. /*
  229. - * restore saved IRQ & FIQ state
  230. + * restore saved IRQ state
  231. */
  232. static inline void arch_local_irq_restore(unsigned long flags)
  233. {
  234. - asm volatile(
  235. - " msr " IRQMASK_REG_NAME_W ", %0 @ local_irq_restore"
  236. + unsigned long temp = 0;
  237. + flags &= ~(1 << 6);
  238. + asm volatile (
  239. + " mrs %0, cpsr"
  240. + : "=r" (temp)
  241. + :
  242. + : "memory", "cc");
  243. + /* Preserve FIQ bit */
  244. + temp &= (1 << 6);
  245. + flags = flags | temp;
  246. + asm volatile (
  247. + " msr cpsr_c, %0 @ local_irq_restore"
  248. :
  249. : "r" (flags)
  250. : "memory", "cc");
  251. --- a/arch/arm/kernel/fiqasm.S
  252. +++ b/arch/arm/kernel/fiqasm.S
  253. @@ -47,3 +47,7 @@ ENTRY(__get_fiq_regs)
  254. mov r0, r0 @ avoid hazard prior to ARMv4
  255. ret lr
  256. ENDPROC(__get_fiq_regs)
  257. +
  258. +ENTRY(__FIQ_Branch)
  259. + mov pc, r8
  260. +ENDPROC(__FIQ_Branch)
  261. --- a/arch/arm/mach-bcm2708/armctrl.c
  262. +++ b/arch/arm/mach-bcm2708/armctrl.c
  263. @@ -52,8 +52,12 @@ static void armctrl_mask_irq(struct irq_
  264. 0
  265. };
  266. - unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
  267. - writel(1 << (data & 0x1f), __io_address(disables[(data >> 5) & 0x3]));
  268. + if (d->irq >= FIQ_START) {
  269. + writel(0, __io_address(ARM_IRQ_FAST));
  270. + } else {
  271. + unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
  272. + writel(1 << (data & 0x1f), __io_address(disables[(data >> 5) & 0x3]));
  273. + }
  274. }
  275. static void armctrl_unmask_irq(struct irq_data *d)
  276. @@ -65,8 +69,14 @@ static void armctrl_unmask_irq(struct ir
  277. 0
  278. };
  279. - unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
  280. - writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3]));
  281. + if (d->irq >= FIQ_START) {
  282. + unsigned int data =
  283. + (unsigned int)irq_get_chip_data(d->irq) - FIQ_START;
  284. + writel(0x80 | data, __io_address(ARM_IRQ_FAST));
  285. + } else {
  286. + unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
  287. + writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3]));
  288. + }
  289. }
  290. #if defined(CONFIG_PM)
  291. @@ -204,5 +214,6 @@ int __init armctrl_init(void __iomem * b
  292. }
  293. armctrl_pm_register(base, irq_start, resume_sources);
  294. + init_FIQ(FIQ_START);
  295. return 0;
  296. }
  297. --- a/arch/arm/mach-bcm2708/bcm2708.c
  298. +++ b/arch/arm/mach-bcm2708/bcm2708.c
  299. @@ -321,12 +321,32 @@ static struct resource bcm2708_usb_resou
  300. .flags = IORESOURCE_MEM,
  301. },
  302. [1] = {
  303. - .start = IRQ_USB,
  304. - .end = IRQ_USB,
  305. + .start = MPHI_BASE,
  306. + .end = MPHI_BASE + SZ_4K - 1,
  307. + .flags = IORESOURCE_MEM,
  308. + },
  309. + [2] = {
  310. + .start = IRQ_HOSTPORT,
  311. + .end = IRQ_HOSTPORT,
  312. .flags = IORESOURCE_IRQ,
  313. },
  314. };
  315. +bool fiq_fix_enable = true;
  316. +
  317. +static struct resource bcm2708_usb_resources_no_fiq_fix[] = {
  318. + [0] = {
  319. + .start = USB_BASE,
  320. + .end = USB_BASE + SZ_128K - 1,
  321. + .flags = IORESOURCE_MEM,
  322. + },
  323. + [1] = {
  324. + .start = IRQ_USB,
  325. + .end = IRQ_USB,
  326. + .flags = IORESOURCE_IRQ,
  327. + },
  328. +};
  329. +
  330. static u64 usb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
  331. static struct platform_device bcm2708_usb_device = {
  332. @@ -681,6 +701,11 @@ void __init bcm2708_init(void)
  333. #endif
  334. bcm_register_device(&bcm2708_systemtimer_device);
  335. bcm_register_device(&bcm2708_fb_device);
  336. + if (!fiq_fix_enable)
  337. + {
  338. + bcm2708_usb_device.resource = bcm2708_usb_resources_no_fiq_fix;
  339. + bcm2708_usb_device.num_resources = ARRAY_SIZE(bcm2708_usb_resources_no_fiq_fix);
  340. + }
  341. bcm_register_device(&bcm2708_usb_device);
  342. bcm_register_device(&bcm2708_uart1_device);
  343. bcm_register_device(&bcm2708_powerman_device);
  344. --- a/arch/arm/mach-bcm2708/include/mach/irqs.h
  345. +++ b/arch/arm/mach-bcm2708/include/mach/irqs.h
  346. @@ -106,87 +106,90 @@
  347. #define IRQ_PENDING1 (IRQ_ARMCTRL_START + INTERRUPT_PENDING1)
  348. #define IRQ_PENDING2 (IRQ_ARMCTRL_START + INTERRUPT_PENDING2)
  349. +#define FIQ_START HARD_IRQS
  350. +
  351. /*
  352. * FIQ interrupts definitions are the same as the INT definitions.
  353. */
  354. -#define FIQ_TIMER0 INT_TIMER0
  355. -#define FIQ_TIMER1 INT_TIMER1
  356. -#define FIQ_TIMER2 INT_TIMER2
  357. -#define FIQ_TIMER3 INT_TIMER3
  358. -#define FIQ_CODEC0 INT_CODEC0
  359. -#define FIQ_CODEC1 INT_CODEC1
  360. -#define FIQ_CODEC2 INT_CODEC2
  361. -#define FIQ_JPEG INT_JPEG
  362. -#define FIQ_ISP INT_ISP
  363. -#define FIQ_USB INT_USB
  364. -#define FIQ_3D INT_3D
  365. -#define FIQ_TRANSPOSER INT_TRANSPOSER
  366. -#define FIQ_MULTICORESYNC0 INT_MULTICORESYNC0
  367. -#define FIQ_MULTICORESYNC1 INT_MULTICORESYNC1
  368. -#define FIQ_MULTICORESYNC2 INT_MULTICORESYNC2
  369. -#define FIQ_MULTICORESYNC3 INT_MULTICORESYNC3
  370. -#define FIQ_DMA0 INT_DMA0
  371. -#define FIQ_DMA1 INT_DMA1
  372. -#define FIQ_DMA2 INT_DMA2
  373. -#define FIQ_DMA3 INT_DMA3
  374. -#define FIQ_DMA4 INT_DMA4
  375. -#define FIQ_DMA5 INT_DMA5
  376. -#define FIQ_DMA6 INT_DMA6
  377. -#define FIQ_DMA7 INT_DMA7
  378. -#define FIQ_DMA8 INT_DMA8
  379. -#define FIQ_DMA9 INT_DMA9
  380. -#define FIQ_DMA10 INT_DMA10
  381. -#define FIQ_DMA11 INT_DMA11
  382. -#define FIQ_DMA12 INT_DMA12
  383. -#define FIQ_AUX INT_AUX
  384. -#define FIQ_ARM INT_ARM
  385. -#define FIQ_VPUDMA INT_VPUDMA
  386. -#define FIQ_HOSTPORT INT_HOSTPORT
  387. -#define FIQ_VIDEOSCALER INT_VIDEOSCALER
  388. -#define FIQ_CCP2TX INT_CCP2TX
  389. -#define FIQ_SDC INT_SDC
  390. -#define FIQ_DSI0 INT_DSI0
  391. -#define FIQ_AVE INT_AVE
  392. -#define FIQ_CAM0 INT_CAM0
  393. -#define FIQ_CAM1 INT_CAM1
  394. -#define FIQ_HDMI0 INT_HDMI0
  395. -#define FIQ_HDMI1 INT_HDMI1
  396. -#define FIQ_PIXELVALVE1 INT_PIXELVALVE1
  397. -#define FIQ_I2CSPISLV INT_I2CSPISLV
  398. -#define FIQ_DSI1 INT_DSI1
  399. -#define FIQ_PWA0 INT_PWA0
  400. -#define FIQ_PWA1 INT_PWA1
  401. -#define FIQ_CPR INT_CPR
  402. -#define FIQ_SMI INT_SMI
  403. -#define FIQ_GPIO0 INT_GPIO0
  404. -#define FIQ_GPIO1 INT_GPIO1
  405. -#define FIQ_GPIO2 INT_GPIO2
  406. -#define FIQ_GPIO3 INT_GPIO3
  407. -#define FIQ_I2C INT_I2C
  408. -#define FIQ_SPI INT_SPI
  409. -#define FIQ_I2SPCM INT_I2SPCM
  410. -#define FIQ_SDIO INT_SDIO
  411. -#define FIQ_UART INT_UART
  412. -#define FIQ_SLIMBUS INT_SLIMBUS
  413. -#define FIQ_VEC INT_VEC
  414. -#define FIQ_CPG INT_CPG
  415. -#define FIQ_RNG INT_RNG
  416. -#define FIQ_ARASANSDIO INT_ARASANSDIO
  417. -#define FIQ_AVSPMON INT_AVSPMON
  418. +#define FIQ_TIMER0 (FIQ_START+INTERRUPT_TIMER0)
  419. +#define FIQ_TIMER1 (FIQ_START+INTERRUPT_TIMER1)
  420. +#define FIQ_TIMER2 (FIQ_START+INTERRUPT_TIMER2)
  421. +#define FIQ_TIMER3 (FIQ_START+INTERRUPT_TIMER3)
  422. +#define FIQ_CODEC0 (FIQ_START+INTERRUPT_CODEC0)
  423. +#define FIQ_CODEC1 (FIQ_START+INTERRUPT_CODEC1)
  424. +#define FIQ_CODEC2 (FIQ_START+INTERRUPT_CODEC2)
  425. +#define FIQ_JPEG (FIQ_START+INTERRUPT_JPEG)
  426. +#define FIQ_ISP (FIQ_START+INTERRUPT_ISP)
  427. +#define FIQ_USB (FIQ_START+INTERRUPT_USB)
  428. +#define FIQ_3D (FIQ_START+INTERRUPT_3D)
  429. +#define FIQ_TRANSPOSER (FIQ_START+INTERRUPT_TRANSPOSER)
  430. +#define FIQ_MULTICORESYNC0 (FIQ_START+INTERRUPT_MULTICORESYNC0)
  431. +#define FIQ_MULTICORESYNC1 (FIQ_START+INTERRUPT_MULTICORESYNC1)
  432. +#define FIQ_MULTICORESYNC2 (FIQ_START+INTERRUPT_MULTICORESYNC2)
  433. +#define FIQ_MULTICORESYNC3 (FIQ_START+INTERRUPT_MULTICORESYNC3)
  434. +#define FIQ_DMA0 (FIQ_START+INTERRUPT_DMA0)
  435. +#define FIQ_DMA1 (FIQ_START+INTERRUPT_DMA1)
  436. +#define FIQ_DMA2 (FIQ_START+INTERRUPT_DMA2)
  437. +#define FIQ_DMA3 (FIQ_START+INTERRUPT_DMA3)
  438. +#define FIQ_DMA4 (FIQ_START+INTERRUPT_DMA4)
  439. +#define FIQ_DMA5 (FIQ_START+INTERRUPT_DMA5)
  440. +#define FIQ_DMA6 (FIQ_START+INTERRUPT_DMA6)
  441. +#define FIQ_DMA7 (FIQ_START+INTERRUPT_DMA7)
  442. +#define FIQ_DMA8 (FIQ_START+INTERRUPT_DMA8)
  443. +#define FIQ_DMA9 (FIQ_START+INTERRUPT_DMA9)
  444. +#define FIQ_DMA10 (FIQ_START+INTERRUPT_DMA10)
  445. +#define FIQ_DMA11 (FIQ_START+INTERRUPT_DMA11)
  446. +#define FIQ_DMA12 (FIQ_START+INTERRUPT_DMA12)
  447. +#define FIQ_AUX (FIQ_START+INTERRUPT_AUX)
  448. +#define FIQ_ARM (FIQ_START+INTERRUPT_ARM)
  449. +#define FIQ_VPUDMA (FIQ_START+INTERRUPT_VPUDMA)
  450. +#define FIQ_HOSTPORT (FIQ_START+INTERRUPT_HOSTPORT)
  451. +#define FIQ_VIDEOSCALER (FIQ_START+INTERRUPT_VIDEOSCALER)
  452. +#define FIQ_CCP2TX (FIQ_START+INTERRUPT_CCP2TX)
  453. +#define FIQ_SDC (FIQ_START+INTERRUPT_SDC)
  454. +#define FIQ_DSI0 (FIQ_START+INTERRUPT_DSI0)
  455. +#define FIQ_AVE (FIQ_START+INTERRUPT_AVE)
  456. +#define FIQ_CAM0 (FIQ_START+INTERRUPT_CAM0)
  457. +#define FIQ_CAM1 (FIQ_START+INTERRUPT_CAM1)
  458. +#define FIQ_HDMI0 (FIQ_START+INTERRUPT_HDMI0)
  459. +#define FIQ_HDMI1 (FIQ_START+INTERRUPT_HDMI1)
  460. +#define FIQ_PIXELVALVE1 (FIQ_START+INTERRUPT_PIXELVALVE1)
  461. +#define FIQ_I2CSPISLV (FIQ_START+INTERRUPT_I2CSPISLV)
  462. +#define FIQ_DSI1 (FIQ_START+INTERRUPT_DSI1)
  463. +#define FIQ_PWA0 (FIQ_START+INTERRUPT_PWA0)
  464. +#define FIQ_PWA1 (FIQ_START+INTERRUPT_PWA1)
  465. +#define FIQ_CPR (FIQ_START+INTERRUPT_CPR)
  466. +#define FIQ_SMI (FIQ_START+INTERRUPT_SMI)
  467. +#define FIQ_GPIO0 (FIQ_START+INTERRUPT_GPIO0)
  468. +#define FIQ_GPIO1 (FIQ_START+INTERRUPT_GPIO1)
  469. +#define FIQ_GPIO2 (FIQ_START+INTERRUPT_GPIO2)
  470. +#define FIQ_GPIO3 (FIQ_START+INTERRUPT_GPIO3)
  471. +#define FIQ_I2C (FIQ_START+INTERRUPT_I2C)
  472. +#define FIQ_SPI (FIQ_START+INTERRUPT_SPI)
  473. +#define FIQ_I2SPCM (FIQ_START+INTERRUPT_I2SPCM)
  474. +#define FIQ_SDIO (FIQ_START+INTERRUPT_SDIO)
  475. +#define FIQ_UART (FIQ_START+INTERRUPT_UART)
  476. +#define FIQ_SLIMBUS (FIQ_START+INTERRUPT_SLIMBUS)
  477. +#define FIQ_VEC (FIQ_START+INTERRUPT_VEC)
  478. +#define FIQ_CPG (FIQ_START+INTERRUPT_CPG)
  479. +#define FIQ_RNG (FIQ_START+INTERRUPT_RNG)
  480. +#define FIQ_ARASANSDIO (FIQ_START+INTERRUPT_ARASANSDIO)
  481. +#define FIQ_AVSPMON (FIQ_START+INTERRUPT_AVSPMON)
  482. -#define FIQ_ARM_TIMER INT_ARM_TIMER
  483. -#define FIQ_ARM_MAILBOX INT_ARM_MAILBOX
  484. -#define FIQ_ARM_DOORBELL_0 INT_ARM_DOORBELL_0
  485. -#define FIQ_ARM_DOORBELL_1 INT_ARM_DOORBELL_1
  486. -#define FIQ_VPU0_HALTED INT_VPU0_HALTED
  487. -#define FIQ_VPU1_HALTED INT_VPU1_HALTED
  488. -#define FIQ_ILLEGAL_TYPE0 INT_ILLEGAL_TYPE0
  489. -#define FIQ_ILLEGAL_TYPE1 INT_ILLEGAL_TYPE1
  490. -#define FIQ_PENDING1 INT_PENDING1
  491. -#define FIQ_PENDING2 INT_PENDING2
  492. +#define FIQ_ARM_TIMER (FIQ_START+INTERRUPT_ARM_TIMER)
  493. +#define FIQ_ARM_MAILBOX (FIQ_START+INTERRUPT_ARM_MAILBOX)
  494. +#define FIQ_ARM_DOORBELL_0 (FIQ_START+INTERRUPT_ARM_DOORBELL_0)
  495. +#define FIQ_ARM_DOORBELL_1 (FIQ_START+INTERRUPT_ARM_DOORBELL_1)
  496. +#define FIQ_VPU0_HALTED (FIQ_START+INTERRUPT_VPU0_HALTED)
  497. +#define FIQ_VPU1_HALTED (FIQ_START+INTERRUPT_VPU1_HALTED)
  498. +#define FIQ_ILLEGAL_TYPE0 (FIQ_START+INTERRUPT_ILLEGAL_TYPE0)
  499. +#define FIQ_ILLEGAL_TYPE1 (FIQ_START+INTERRUPT_ILLEGAL_TYPE1)
  500. +#define FIQ_PENDING1 (FIQ_START+INTERRUPT_PENDING1)
  501. +#define FIQ_PENDING2 (FIQ_START+INTERRUPT_PENDING2)
  502. #define HARD_IRQS (64 + 21)
  503. -#define GPIO_IRQ_START (HARD_IRQS)
  504. +#define FIQ_IRQS (64 + 21)
  505. +#define GPIO_IRQ_START (HARD_IRQS + FIQ_IRQS)
  506. #define GPIO_IRQS (32*5)
  507. #define SPARE_ALLOC_IRQS 64
  508. #define BCM2708_ALLOC_IRQS (HARD_IRQS+FIQ_IRQS+GPIO_IRQS+SPARE_ALLOC_IRQS)
  509. --- a/drivers/usb/host/dwc_common_port/dwc_common_linux.c
  510. +++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c
  511. @@ -580,7 +580,13 @@ void DWC_WRITE_REG64(uint64_t volatile *
  512. void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask)
  513. {
  514. + unsigned long flags;
  515. +
  516. + local_irq_save(flags);
  517. + local_fiq_disable();
  518. writel((readl(reg) & ~clear_mask) | set_mask, reg);
  519. + local_fiq_enable();
  520. + local_irq_restore(flags);
  521. }
  522. #if 0
  523. @@ -995,6 +1001,11 @@ void DWC_TASK_SCHEDULE(dwc_tasklet_t *ta
  524. tasklet_schedule(&task->t);
  525. }
  526. +void DWC_TASK_HI_SCHEDULE(dwc_tasklet_t *task)
  527. +{
  528. + tasklet_hi_schedule(&task->t);
  529. +}
  530. +
  531. /* workqueues
  532. - run in process context (can sleep)
  533. --- a/drivers/usb/host/dwc_common_port/dwc_list.h
  534. +++ b/drivers/usb/host/dwc_common_port/dwc_list.h
  535. @@ -384,17 +384,17 @@ struct { \
  536. #define DWC_TAILQ_PREV(elm, headname, field) \
  537. (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
  538. #define DWC_TAILQ_EMPTY(head) \
  539. - (TAILQ_FIRST(head) == TAILQ_END(head))
  540. + (DWC_TAILQ_FIRST(head) == DWC_TAILQ_END(head))
  541. #define DWC_TAILQ_FOREACH(var, head, field) \
  542. - for((var) = TAILQ_FIRST(head); \
  543. - (var) != TAILQ_END(head); \
  544. - (var) = TAILQ_NEXT(var, field))
  545. + for ((var) = DWC_TAILQ_FIRST(head); \
  546. + (var) != DWC_TAILQ_END(head); \
  547. + (var) = DWC_TAILQ_NEXT(var, field))
  548. #define DWC_TAILQ_FOREACH_REVERSE(var, head, headname, field) \
  549. - for((var) = TAILQ_LAST(head, headname); \
  550. - (var) != TAILQ_END(head); \
  551. - (var) = TAILQ_PREV(var, headname, field))
  552. + for ((var) = DWC_TAILQ_LAST(head, headname); \
  553. + (var) != DWC_TAILQ_END(head); \
  554. + (var) = DWC_TAILQ_PREV(var, headname, field))
  555. /*
  556. * Tail queue functions.
  557. --- a/drivers/usb/host/dwc_common_port/dwc_os.h
  558. +++ b/drivers/usb/host/dwc_common_port/dwc_os.h
  559. @@ -982,6 +982,8 @@ extern void DWC_TASK_FREE(dwc_tasklet_t
  560. extern void DWC_TASK_SCHEDULE(dwc_tasklet_t *task);
  561. #define dwc_task_schedule DWC_TASK_SCHEDULE
  562. +extern void DWC_TASK_HI_SCHEDULE(dwc_tasklet_t *task);
  563. +#define dwc_task_hi_schedule DWC_TASK_HI_SCHEDULE
  564. /** @name Timer
  565. *
  566. --- a/drivers/usb/host/dwc_otg/Makefile
  567. +++ b/drivers/usb/host/dwc_otg/Makefile
  568. @@ -36,6 +36,7 @@ dwc_otg-objs += dwc_otg_cil.o dwc_otg_ci
  569. dwc_otg-objs += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o
  570. dwc_otg-objs += dwc_otg_hcd.o dwc_otg_hcd_linux.o dwc_otg_hcd_intr.o dwc_otg_hcd_queue.o dwc_otg_hcd_ddma.o
  571. dwc_otg-objs += dwc_otg_adp.o
  572. +dwc_otg-objs += dwc_otg_mphi_fix.o
  573. ifneq ($(CFI),)
  574. dwc_otg-objs += dwc_otg_cfi.o
  575. endif
  576. --- a/drivers/usb/host/dwc_otg/dwc_otg_attr.c
  577. +++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.c
  578. @@ -909,7 +909,7 @@ static ssize_t regdump_show(struct devic
  579. return sprintf(buf, "Register Dump\n");
  580. }
  581. -DEVICE_ATTR(regdump, S_IRUGO | S_IWUSR, regdump_show, 0);
  582. +DEVICE_ATTR(regdump, S_IRUGO, regdump_show, 0);
  583. /**
  584. * Dump global registers and either host or device registers (depending on the
  585. @@ -920,12 +920,12 @@ static ssize_t spramdump_show(struct dev
  586. {
  587. dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  588. - dwc_otg_dump_spram(otg_dev->core_if);
  589. + //dwc_otg_dump_spram(otg_dev->core_if);
  590. return sprintf(buf, "SPRAM Dump\n");
  591. }
  592. -DEVICE_ATTR(spramdump, S_IRUGO | S_IWUSR, spramdump_show, 0);
  593. +DEVICE_ATTR(spramdump, S_IRUGO, spramdump_show, 0);
  594. /**
  595. * Dump the current hcd state.
  596. @@ -940,7 +940,7 @@ static ssize_t hcddump_show(struct devic
  597. return sprintf(buf, "HCD Dump\n");
  598. }
  599. -DEVICE_ATTR(hcddump, S_IRUGO | S_IWUSR, hcddump_show, 0);
  600. +DEVICE_ATTR(hcddump, S_IRUGO, hcddump_show, 0);
  601. /**
  602. * Dump the average frame remaining at SOF. This can be used to
  603. @@ -958,7 +958,7 @@ static ssize_t hcd_frrem_show(struct dev
  604. return sprintf(buf, "HCD Dump Frame Remaining\n");
  605. }
  606. -DEVICE_ATTR(hcd_frrem, S_IRUGO | S_IWUSR, hcd_frrem_show, 0);
  607. +DEVICE_ATTR(hcd_frrem, S_IRUGO, hcd_frrem_show, 0);
  608. /**
  609. * Displays the time required to read the GNPTXFSIZ register many times (the
  610. @@ -986,7 +986,7 @@ static ssize_t rd_reg_test_show(struct d
  611. RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
  612. }
  613. -DEVICE_ATTR(rd_reg_test, S_IRUGO | S_IWUSR, rd_reg_test_show, 0);
  614. +DEVICE_ATTR(rd_reg_test, S_IRUGO, rd_reg_test_show, 0);
  615. /**
  616. * Displays the time required to write the GNPTXFSIZ register many times (the
  617. @@ -1014,7 +1014,7 @@ static ssize_t wr_reg_test_show(struct d
  618. RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
  619. }
  620. -DEVICE_ATTR(wr_reg_test, S_IRUGO | S_IWUSR, wr_reg_test_show, 0);
  621. +DEVICE_ATTR(wr_reg_test, S_IRUGO, wr_reg_test_show, 0);
  622. #ifdef CONFIG_USB_DWC_OTG_LPM
  623. --- a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
  624. +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
  625. @@ -45,6 +45,7 @@
  626. #include "dwc_otg_driver.h"
  627. #include "dwc_otg_pcd.h"
  628. #include "dwc_otg_hcd.h"
  629. +#include "dwc_otg_mphi_fix.h"
  630. #ifdef DEBUG
  631. inline const char *op_state_str(dwc_otg_core_if_t * core_if)
  632. @@ -1318,7 +1319,7 @@ static int32_t dwc_otg_handle_lpm_intr(d
  633. /**
  634. * This function returns the Core Interrupt register.
  635. */
  636. -static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if)
  637. +static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if, gintmsk_data_t *reenable_gintmsk)
  638. {
  639. gahbcfg_data_t gahbcfg = {.d32 = 0 };
  640. gintsts_data_t gintsts;
  641. @@ -1335,26 +1336,45 @@ static inline uint32_t dwc_otg_read_comm
  642. gintmsk_common.b.lpmtranrcvd = 1;
  643. #endif
  644. gintmsk_common.b.restoredone = 1;
  645. - /** @todo: The port interrupt occurs while in device
  646. - * mode. Added code to CIL to clear the interrupt for now!
  647. - */
  648. - gintmsk_common.b.portintr = 1;
  649. -
  650. + if(dwc_otg_is_device_mode(core_if))
  651. + {
  652. + /** @todo: The port interrupt occurs while in device
  653. + * mode. Added code to CIL to clear the interrupt for now!
  654. + */
  655. + gintmsk_common.b.portintr = 1;
  656. + }
  657. gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
  658. gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
  659. + {
  660. + unsigned long flags;
  661. +
  662. + // Re-enable the saved interrupts
  663. + local_irq_save(flags);
  664. + local_fiq_disable();
  665. + gintmsk.d32 |= gintmsk_common.d32;
  666. + gintsts_saved.d32 &= ~gintmsk_common.d32;
  667. + reenable_gintmsk->d32 = gintmsk.d32;
  668. + local_irq_restore(flags);
  669. + }
  670. +
  671. gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
  672. #ifdef DEBUG
  673. /* if any common interrupts set */
  674. if (gintsts.d32 & gintmsk_common.d32) {
  675. - DWC_DEBUGPL(DBG_ANY, "gintsts=%08x gintmsk=%08x\n",
  676. + DWC_DEBUGPL(DBG_ANY, "common_intr: gintsts=%08x gintmsk=%08x\n",
  677. gintsts.d32, gintmsk.d32);
  678. }
  679. #endif
  680. - if (gahbcfg.b.glblintrmsk)
  681. + if (!fiq_fix_enable){
  682. + if (gahbcfg.b.glblintrmsk)
  683. + return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
  684. + else
  685. + return 0;
  686. + }
  687. + else {
  688. return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
  689. - else
  690. - return 0;
  691. + }
  692. }
  693. @@ -1386,6 +1406,7 @@ int32_t dwc_otg_handle_common_intr(void
  694. {
  695. int retval = 0;
  696. gintsts_data_t gintsts;
  697. + gintmsk_data_t reenable_gintmsk;
  698. gpwrdn_data_t gpwrdn = {.d32 = 0 };
  699. dwc_otg_device_t *otg_dev = dev;
  700. dwc_otg_core_if_t *core_if = otg_dev->core_if;
  701. @@ -1407,7 +1428,7 @@ int32_t dwc_otg_handle_common_intr(void
  702. }
  703. if (core_if->hibernation_suspend <= 0) {
  704. - gintsts.d32 = dwc_otg_read_common_intr(core_if);
  705. + gintsts.d32 = dwc_otg_read_common_intr(core_if, &reenable_gintmsk);
  706. if (gintsts.b.modemismatch) {
  707. retval |= dwc_otg_handle_mode_mismatch_intr(core_if);
  708. @@ -1504,8 +1525,12 @@ int32_t dwc_otg_handle_common_intr(void
  709. gintsts.b.portintr = 1;
  710. DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32);
  711. retval |= 1;
  712. + reenable_gintmsk.b.portintr = 1;
  713. }
  714. +
  715. + DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, reenable_gintmsk.d32);
  716. +
  717. } else {
  718. DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32);
  719. --- a/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
  720. +++ b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
  721. @@ -49,6 +49,7 @@ static inline uint32_t SET_DEBUG_LEVEL(c
  722. return old;
  723. }
  724. +#define DBG_USER (0x1)
  725. /** When debug level has the DBG_CIL bit set, display CIL Debug messages. */
  726. #define DBG_CIL (0x2)
  727. /** When debug level has the DBG_CILV bit set, display CIL Verbose debug
  728. --- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c
  729. +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
  730. @@ -64,6 +64,8 @@ bool microframe_schedule=true;
  731. static const char dwc_driver_name[] = "dwc_otg";
  732. +extern void* dummy_send;
  733. +
  734. extern int pcd_init(
  735. #ifdef LM_INTERFACE
  736. struct lm_device *_dev
  737. @@ -238,6 +240,14 @@ static struct dwc_otg_driver_module_para
  738. .adp_enable = -1,
  739. };
  740. +//Global variable to switch the fiq fix on or off (declared in bcm2708.c)
  741. +extern bool fiq_fix_enable;
  742. +// Global variable to enable the split transaction fix
  743. +bool fiq_split_enable = true;
  744. +//Global variable to switch the nak holdoff on or off
  745. +bool nak_holdoff_enable = true;
  746. +
  747. +
  748. /**
  749. * This function shows the Driver Version.
  750. */
  751. @@ -779,17 +789,33 @@ static int dwc_otg_driver_probe(
  752. _dev->resource->start,
  753. _dev->resource->end - _dev->resource->start + 1);
  754. #if 1
  755. - if (!request_mem_region(_dev->resource->start,
  756. - _dev->resource->end - _dev->resource->start + 1,
  757. + if (!request_mem_region(_dev->resource[0].start,
  758. + _dev->resource[0].end - _dev->resource[0].start + 1,
  759. "dwc_otg")) {
  760. dev_dbg(&_dev->dev, "error reserving mapped memory\n");
  761. retval = -EFAULT;
  762. goto fail;
  763. }
  764. - dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource->start,
  765. - _dev->resource->end -
  766. - _dev->resource->start+1);
  767. + dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource[0].start,
  768. + _dev->resource[0].end -
  769. + _dev->resource[0].start+1);
  770. + if (fiq_fix_enable)
  771. + {
  772. + if (!request_mem_region(_dev->resource[1].start,
  773. + _dev->resource[1].end - _dev->resource[1].start + 1,
  774. + "dwc_otg")) {
  775. + dev_dbg(&_dev->dev, "error reserving mapped memory\n");
  776. + retval = -EFAULT;
  777. + goto fail;
  778. + }
  779. +
  780. + dwc_otg_device->os_dep.mphi_base = ioremap_nocache(_dev->resource[1].start,
  781. + _dev->resource[1].end -
  782. + _dev->resource[1].start + 1);
  783. + dummy_send = (void *) kmalloc(16, GFP_ATOMIC);
  784. + }
  785. +
  786. #else
  787. {
  788. struct map_desc desc = {
  789. @@ -1044,6 +1070,12 @@ static int __init dwc_otg_driver_init(vo
  790. int retval = 0;
  791. int error;
  792. struct device_driver *drv;
  793. +
  794. + if(fiq_split_enable && !fiq_fix_enable) {
  795. + printk(KERN_WARNING "dwc_otg: fiq_split_enable was set without fiq_fix_enable! Correcting.\n");
  796. + fiq_fix_enable = 1;
  797. + }
  798. +
  799. printk(KERN_INFO "%s: version %s (%s bus)\n", dwc_driver_name,
  800. DWC_DRIVER_VERSION,
  801. #ifdef LM_INTERFACE
  802. @@ -1063,6 +1095,9 @@ static int __init dwc_otg_driver_init(vo
  803. printk(KERN_ERR "%s retval=%d\n", __func__, retval);
  804. return retval;
  805. }
  806. + printk(KERN_DEBUG "dwc_otg: FIQ %s\n", fiq_fix_enable ? "enabled":"disabled");
  807. + printk(KERN_DEBUG "dwc_otg: NAK holdoff %s\n", nak_holdoff_enable ? "enabled":"disabled");
  808. + printk(KERN_DEBUG "dwc_otg: FIQ split fix %s\n", fiq_split_enable ? "enabled":"disabled");
  809. error = driver_create_file(drv, &driver_attr_version);
  810. #ifdef DEBUG
  811. @@ -1343,6 +1378,13 @@ MODULE_PARM_DESC(otg_ver, "OTG revision
  812. module_param(microframe_schedule, bool, 0444);
  813. MODULE_PARM_DESC(microframe_schedule, "Enable the microframe scheduler");
  814. +module_param(fiq_fix_enable, bool, 0444);
  815. +MODULE_PARM_DESC(fiq_fix_enable, "Enable the fiq fix");
  816. +module_param(nak_holdoff_enable, bool, 0444);
  817. +MODULE_PARM_DESC(nak_holdoff_enable, "Enable the NAK holdoff");
  818. +module_param(fiq_split_enable, bool, 0444);
  819. +MODULE_PARM_DESC(fiq_split_enable, "Enable the FIQ fix on split transactions");
  820. +
  821. /** @page "Module Parameters"
  822. *
  823. * The following parameters may be specified when starting the module.
  824. --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
  825. +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
  826. @@ -40,10 +40,14 @@
  827. * header file.
  828. */
  829. +#include <linux/usb.h>
  830. +#include <linux/usb/hcd.h>
  831. +
  832. #include "dwc_otg_hcd.h"
  833. #include "dwc_otg_regs.h"
  834. +#include "dwc_otg_mphi_fix.h"
  835. -extern bool microframe_schedule;
  836. +extern bool microframe_schedule, nak_holdoff_enable;
  837. //#define DEBUG_HOST_CHANNELS
  838. #ifdef DEBUG_HOST_CHANNELS
  839. @@ -53,6 +57,13 @@ static int last_sel_trans_num_avail_hc_a
  840. static int last_sel_trans_num_avail_hc_at_end = 0;
  841. #endif /* DEBUG_HOST_CHANNELS */
  842. +extern int g_next_sched_frame, g_np_count, g_np_sent;
  843. +
  844. +extern haint_data_t haint_saved;
  845. +extern hcintmsk_data_t hcintmsk_saved[MAX_EPS_CHANNELS];
  846. +extern hcint_data_t hcint_saved[MAX_EPS_CHANNELS];
  847. +extern gintsts_data_t ginsts_saved;
  848. +
  849. dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void)
  850. {
  851. return DWC_ALLOC(sizeof(dwc_otg_hcd_t));
  852. @@ -162,31 +173,43 @@ static void del_timers(dwc_otg_hcd_t * h
  853. /**
  854. * Processes all the URBs in a single list of QHs. Completes them with
  855. - * -ETIMEDOUT and frees the QTD.
  856. + * -ESHUTDOWN and frees the QTD.
  857. */
  858. static void kill_urbs_in_qh_list(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
  859. {
  860. - dwc_list_link_t *qh_item;
  861. + dwc_list_link_t *qh_item, *qh_tmp;
  862. dwc_otg_qh_t *qh;
  863. dwc_otg_qtd_t *qtd, *qtd_tmp;
  864. - DWC_LIST_FOREACH(qh_item, qh_list) {
  865. + DWC_LIST_FOREACH_SAFE(qh_item, qh_tmp, qh_list) {
  866. qh = DWC_LIST_ENTRY(qh_item, dwc_otg_qh_t, qh_list_entry);
  867. DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp,
  868. &qh->qtd_list, qtd_list_entry) {
  869. qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
  870. if (qtd->urb != NULL) {
  871. hcd->fops->complete(hcd, qtd->urb->priv,
  872. - qtd->urb, -DWC_E_TIMEOUT);
  873. + qtd->urb, -DWC_E_SHUTDOWN);
  874. dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
  875. }
  876. }
  877. + if(qh->channel) {
  878. + /* Using hcchar.chen == 1 is not a reliable test.
  879. + * It is possible that the channel has already halted
  880. + * but not yet been through the IRQ handler.
  881. + */
  882. + dwc_otg_hc_halt(hcd->core_if, qh->channel,
  883. + DWC_OTG_HC_XFER_URB_DEQUEUE);
  884. + if(microframe_schedule)
  885. + hcd->available_host_channels++;
  886. + qh->channel = NULL;
  887. + }
  888. + dwc_otg_hcd_qh_remove(hcd, qh);
  889. }
  890. }
  891. /**
  892. - * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic
  893. + * Responds with an error status of ESHUTDOWN to all URBs in the non-periodic
  894. * and periodic schedules. The QTD associated with each URB is removed from
  895. * the schedule and freed. This function may be called when a disconnect is
  896. * detected or when the HCD is being stopped.
  897. @@ -272,7 +295,8 @@ static int32_t dwc_otg_hcd_disconnect_cb
  898. */
  899. dwc_otg_hcd->flags.b.port_connect_status_change = 1;
  900. dwc_otg_hcd->flags.b.port_connect_status = 0;
  901. -
  902. + if(fiq_fix_enable)
  903. + local_fiq_disable();
  904. /*
  905. * Shutdown any transfers in process by clearing the Tx FIFO Empty
  906. * interrupt mask and status bits and disabling subsequent host
  907. @@ -368,8 +392,22 @@ static int32_t dwc_otg_hcd_disconnect_cb
  908. channel->qh = NULL;
  909. }
  910. }
  911. + if(fiq_split_enable) {
  912. + for(i=0; i < 128; i++) {
  913. + dwc_otg_hcd->hub_port[i] = 0;
  914. + }
  915. + haint_saved.d32 = 0;
  916. + for(i=0; i < MAX_EPS_CHANNELS; i++) {
  917. + hcint_saved[i].d32 = 0;
  918. + hcintmsk_saved[i].d32 = 0;
  919. + }
  920. + }
  921. +
  922. }
  923. + if(fiq_fix_enable)
  924. + local_fiq_enable();
  925. +
  926. if (dwc_otg_hcd->fops->disconnect) {
  927. dwc_otg_hcd->fops->disconnect(dwc_otg_hcd);
  928. }
  929. @@ -407,6 +445,7 @@ static int dwc_otg_hcd_sleep_cb(void *p)
  930. }
  931. #endif
  932. +
  933. /**
  934. * HCD Callback function for Remote Wakeup.
  935. *
  936. @@ -457,10 +496,12 @@ int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_
  937. dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle,
  938. int atomic_alloc)
  939. {
  940. - dwc_irqflags_t flags;
  941. int retval = 0;
  942. + uint8_t needs_scheduling = 0;
  943. + dwc_otg_transaction_type_e tr_type;
  944. dwc_otg_qtd_t *qtd;
  945. gintmsk_data_t intr_mask = {.d32 = 0 };
  946. + hprt0_data_t hprt0 = { .d32 = 0 };
  947. #ifdef DEBUG /* integrity checks (Broadcom) */
  948. if (NULL == hcd->core_if) {
  949. @@ -475,6 +516,16 @@ int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_
  950. return -DWC_E_NO_DEVICE;
  951. }
  952. + /* Some core configurations cannot support LS traffic on a FS root port */
  953. + if ((hcd->fops->speed(hcd, dwc_otg_urb->priv) == USB_SPEED_LOW) &&
  954. + (hcd->core_if->hwcfg2.b.fs_phy_type == 1) &&
  955. + (hcd->core_if->hwcfg2.b.hs_phy_type == 1)) {
  956. + hprt0.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0);
  957. + if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_FULL_SPEED) {
  958. + return -DWC_E_NO_DEVICE;
  959. + }
  960. + }
  961. +
  962. qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb, atomic_alloc);
  963. if (qtd == NULL) {
  964. DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n");
  965. @@ -490,32 +541,27 @@ int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_
  966. return -DWC_E_NO_MEMORY;
  967. }
  968. #endif
  969. - retval =
  970. - dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc);
  971. + intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk);
  972. + if(!intr_mask.b.sofintr) needs_scheduling = 1;
  973. + if((((dwc_otg_qh_t *)ep_handle)->ep_type == UE_BULK) && !(qtd->urb->flags & URB_GIVEBACK_ASAP))
  974. + /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */
  975. + needs_scheduling = 0;
  976. +
  977. + retval = dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc);
  978. // creates a new queue in ep_handle if it doesn't exist already
  979. if (retval < 0) {
  980. DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. "
  981. "Error status %d\n", retval);
  982. dwc_otg_hcd_qtd_free(qtd);
  983. - } else {
  984. - qtd->qh = *ep_handle;
  985. + return retval;
  986. }
  987. - intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk);
  988. - if (!intr_mask.b.sofintr && retval == 0) {
  989. - dwc_otg_transaction_type_e tr_type;
  990. - if ((qtd->qh->ep_type == UE_BULK)
  991. - && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) {
  992. - /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */
  993. - return 0;
  994. - }
  995. - DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
  996. +
  997. + if(needs_scheduling) {
  998. tr_type = dwc_otg_hcd_select_transactions(hcd);
  999. if (tr_type != DWC_OTG_TRANSACTION_NONE) {
  1000. dwc_otg_hcd_queue_transactions(hcd, tr_type);
  1001. }
  1002. - DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
  1003. }
  1004. -
  1005. return retval;
  1006. }
  1007. @@ -524,6 +570,8 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_
  1008. {
  1009. dwc_otg_qh_t *qh;
  1010. dwc_otg_qtd_t *urb_qtd;
  1011. + BUG_ON(!hcd);
  1012. + BUG_ON(!dwc_otg_urb);
  1013. #ifdef DEBUG /* integrity checks (Broadcom) */
  1014. @@ -540,14 +588,17 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_
  1015. return -DWC_E_INVALID;
  1016. }
  1017. urb_qtd = dwc_otg_urb->qtd;
  1018. + BUG_ON(!urb_qtd);
  1019. if (urb_qtd->qh == NULL) {
  1020. DWC_ERROR("**** DWC OTG HCD URB Dequeue with QTD with NULL Q handler\n");
  1021. return -DWC_E_INVALID;
  1022. }
  1023. #else
  1024. urb_qtd = dwc_otg_urb->qtd;
  1025. + BUG_ON(!urb_qtd);
  1026. #endif
  1027. qh = urb_qtd->qh;
  1028. + BUG_ON(!qh);
  1029. if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
  1030. if (urb_qtd->in_process) {
  1031. dump_channel_info(hcd, qh);
  1032. @@ -571,6 +622,8 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_
  1033. */
  1034. dwc_otg_hc_halt(hcd->core_if, qh->channel,
  1035. DWC_OTG_HC_XFER_URB_DEQUEUE);
  1036. +
  1037. + dwc_otg_hcd_release_port(hcd, qh);
  1038. }
  1039. }
  1040. @@ -687,6 +740,33 @@ static void reset_tasklet_func(void *dat
  1041. dwc_otg_hcd->flags.b.port_reset_change = 1;
  1042. }
  1043. +static void completion_tasklet_func(void *ptr)
  1044. +{
  1045. + dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) ptr;
  1046. + struct urb *urb;
  1047. + urb_tq_entry_t *item;
  1048. + dwc_irqflags_t flags;
  1049. +
  1050. + /* This could just be spin_lock_irq */
  1051. + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
  1052. + while (!DWC_TAILQ_EMPTY(&hcd->completed_urb_list)) {
  1053. + item = DWC_TAILQ_FIRST(&hcd->completed_urb_list);
  1054. + urb = item->urb;
  1055. + DWC_TAILQ_REMOVE(&hcd->completed_urb_list, item,
  1056. + urb_tq_entries);
  1057. + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
  1058. + DWC_FREE(item);
  1059. +
  1060. + usb_hcd_giveback_urb(hcd->priv, urb, urb->status);
  1061. +
  1062. + fiq_print(FIQDBG_PORTHUB, "COMPLETE");
  1063. +
  1064. + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
  1065. + }
  1066. + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
  1067. + return;
  1068. +}
  1069. +
  1070. static void qh_list_free(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
  1071. {
  1072. dwc_list_link_t *item;
  1073. @@ -819,12 +899,14 @@ static void dwc_otg_hcd_free(dwc_otg_hcd
  1074. } else if (dwc_otg_hcd->status_buf != NULL) {
  1075. DWC_FREE(dwc_otg_hcd->status_buf);
  1076. }
  1077. + DWC_SPINLOCK_FREE(dwc_otg_hcd->channel_lock);
  1078. DWC_SPINLOCK_FREE(dwc_otg_hcd->lock);
  1079. /* Set core_if's lock pointer to NULL */
  1080. dwc_otg_hcd->core_if->lock = NULL;
  1081. DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);
  1082. DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);
  1083. + DWC_TASK_FREE(dwc_otg_hcd->completion_tasklet);
  1084. #ifdef DWC_DEV_SRPCAP
  1085. if (dwc_otg_hcd->core_if->power_down == 2 &&
  1086. @@ -874,7 +956,7 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd
  1087. DWC_LIST_INIT(&hcd->periodic_sched_ready);
  1088. DWC_LIST_INIT(&hcd->periodic_sched_assigned);
  1089. DWC_LIST_INIT(&hcd->periodic_sched_queued);
  1090. -
  1091. + DWC_TAILQ_INIT(&hcd->completed_urb_list);
  1092. /*
  1093. * Create a host channel descriptor for each host channel implemented
  1094. * in the controller. Initialize the channel descriptor array.
  1095. @@ -912,6 +994,9 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd
  1096. /* Initialize reset tasklet. */
  1097. hcd->reset_tasklet = DWC_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd);
  1098. +
  1099. + hcd->completion_tasklet = DWC_TASK_ALLOC("completion_tasklet",
  1100. + completion_tasklet_func, hcd);
  1101. #ifdef DWC_DEV_SRPCAP
  1102. if (hcd->core_if->power_down == 2) {
  1103. /* Initialize Power on timer for Host power up in case hibernation */
  1104. @@ -944,6 +1029,12 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd
  1105. hcd->frame_list = NULL;
  1106. hcd->frame_list_dma = 0;
  1107. hcd->periodic_qh_count = 0;
  1108. +
  1109. + DWC_MEMSET(hcd->hub_port, 0, sizeof(hcd->hub_port));
  1110. +#ifdef FIQ_DEBUG
  1111. + DWC_MEMSET(hcd->hub_port_alloc, -1, sizeof(hcd->hub_port_alloc));
  1112. +#endif
  1113. +
  1114. out:
  1115. return retval;
  1116. }
  1117. @@ -1089,7 +1180,12 @@ static void assign_and_init_hc(dwc_otg_h
  1118. uint32_t hub_addr, port_addr;
  1119. hc->do_split = 1;
  1120. hc->xact_pos = qtd->isoc_split_pos;
  1121. - hc->complete_split = qtd->complete_split;
  1122. + /* We don't need to do complete splits anymore */
  1123. + if(fiq_split_enable)
  1124. + hc->complete_split = qtd->complete_split = 0;
  1125. + else
  1126. + hc->complete_split = qtd->complete_split;
  1127. +
  1128. hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr);
  1129. hc->hub_addr = (uint8_t) hub_addr;
  1130. hc->port_addr = (uint8_t) port_addr;
  1131. @@ -1236,6 +1332,65 @@ static void assign_and_init_hc(dwc_otg_h
  1132. hc->qh = qh;
  1133. }
  1134. +/*
  1135. +** Check the transaction to see if the port / hub has already been assigned for
  1136. +** a split transaction
  1137. +**
  1138. +** Return 0 - Port is already in use
  1139. +*/
  1140. +int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh)
  1141. +{
  1142. + uint32_t hub_addr, port_addr;
  1143. +
  1144. + if(!fiq_split_enable)
  1145. + return 0;
  1146. +
  1147. + hcd->fops->hub_info(hcd, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->priv, &hub_addr, &port_addr);
  1148. +
  1149. + if(hcd->hub_port[hub_addr] & (1 << port_addr))
  1150. + {
  1151. + fiq_print(FIQDBG_PORTHUB, "H%dP%d:S%02d", hub_addr, port_addr, qh->skip_count);
  1152. +
  1153. + qh->skip_count++;
  1154. +
  1155. + if(qh->skip_count > 40000)
  1156. + {
  1157. + printk_once(KERN_ERR "Error: Having to skip port allocation");
  1158. + local_fiq_disable();
  1159. + BUG();
  1160. + return 0;
  1161. + }
  1162. + return 1;
  1163. + }
  1164. + else
  1165. + {
  1166. + qh->skip_count = 0;
  1167. + hcd->hub_port[hub_addr] |= 1 << port_addr;
  1168. + fiq_print(FIQDBG_PORTHUB, "H%dP%d:A %d", hub_addr, port_addr, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->pipe_info.ep_num);
  1169. +#ifdef FIQ_DEBUG
  1170. + hcd->hub_port_alloc[hub_addr * 16 + port_addr] = dwc_otg_hcd_get_frame_number(hcd);
  1171. +#endif
  1172. + return 0;
  1173. + }
  1174. +}
  1175. +void dwc_otg_hcd_release_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh)
  1176. +{
  1177. + uint32_t hub_addr, port_addr;
  1178. +
  1179. + if(!fiq_split_enable)
  1180. + return;
  1181. +
  1182. + hcd->fops->hub_info(hcd, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->priv, &hub_addr, &port_addr);
  1183. +
  1184. + hcd->hub_port[hub_addr] &= ~(1 << port_addr);
  1185. +#ifdef FIQ_DEBUG
  1186. + hcd->hub_port_alloc[hub_addr * 16 + port_addr] = -1;
  1187. +#endif
  1188. + fiq_print(FIQDBG_PORTHUB, "H%dP%d:RO%d", hub_addr, port_addr, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->pipe_info.ep_num);
  1189. +
  1190. +}
  1191. +
  1192. +
  1193. /**
  1194. * This function selects transactions from the HCD transfer schedule and
  1195. * assigns them to available host channels. It is called from HCD interrupt
  1196. @@ -1249,9 +1404,10 @@ dwc_otg_transaction_type_e dwc_otg_hcd_s
  1197. {
  1198. dwc_list_link_t *qh_ptr;
  1199. dwc_otg_qh_t *qh;
  1200. + dwc_otg_qtd_t *qtd;
  1201. int num_channels;
  1202. dwc_irqflags_t flags;
  1203. - dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
  1204. + dwc_spinlock_t *channel_lock = hcd->channel_lock;
  1205. dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE;
  1206. #ifdef DEBUG_SOF
  1207. @@ -1269,11 +1425,29 @@ dwc_otg_transaction_type_e dwc_otg_hcd_s
  1208. while (qh_ptr != &hcd->periodic_sched_ready &&
  1209. !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
  1210. +
  1211. + qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
  1212. +
  1213. + if(qh->do_split) {
  1214. + qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
  1215. + if(!(qh->ep_type == UE_ISOCHRONOUS &&
  1216. + (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID ||
  1217. + qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END))) {
  1218. + if(dwc_otg_hcd_allocate_port(hcd, qh))
  1219. + {
  1220. + qh_ptr = DWC_LIST_NEXT(qh_ptr);
  1221. + g_next_sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd), 1);
  1222. + continue;
  1223. + }
  1224. + }
  1225. + }
  1226. +
  1227. if (microframe_schedule) {
  1228. // Make sure we leave one channel for non periodic transactions.
  1229. DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
  1230. if (hcd->available_host_channels <= 1) {
  1231. DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
  1232. + if(qh->do_split) dwc_otg_hcd_release_port(hcd, qh);
  1233. break;
  1234. }
  1235. hcd->available_host_channels--;
  1236. @@ -1294,8 +1468,6 @@ dwc_otg_transaction_type_e dwc_otg_hcd_s
  1237. DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
  1238. &qh->qh_list_entry);
  1239. DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
  1240. -
  1241. - ret_val = DWC_OTG_TRANSACTION_PERIODIC;
  1242. }
  1243. /*
  1244. @@ -1310,6 +1482,31 @@ dwc_otg_transaction_type_e dwc_otg_hcd_s
  1245. num_channels - hcd->periodic_channels) &&
  1246. !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
  1247. + qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
  1248. +
  1249. + /*
  1250. + * Check to see if this is a NAK'd retransmit, in which case ignore for retransmission
  1251. + * we hold off on bulk retransmissions to reduce NAK interrupt overhead for full-speed
  1252. + * cheeky devices that just hold off using NAKs
  1253. + */
  1254. + if (nak_holdoff_enable && qh->do_split) {
  1255. + if (qh->nak_frame != 0xffff &&
  1256. + dwc_full_frame_num(qh->nak_frame) ==
  1257. + dwc_full_frame_num(dwc_otg_hcd_get_frame_number(hcd))) {
  1258. + /*
  1259. + * Revisit: Need to avoid trampling on periodic scheduling.
  1260. + * Currently we are safe because g_np_count != g_np_sent whenever we hit this,
  1261. + * but if this behaviour is changed then periodic endpoints will get a slower
  1262. + * polling rate.
  1263. + */
  1264. + g_next_sched_frame = ((qh->nak_frame + 8) & ~7) & DWC_HFNUM_MAX_FRNUM;
  1265. + qh_ptr = DWC_LIST_NEXT(qh_ptr);
  1266. + continue;
  1267. + } else {
  1268. + qh->nak_frame = 0xffff;
  1269. + }
  1270. + }
  1271. +
  1272. if (microframe_schedule) {
  1273. DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
  1274. if (hcd->available_host_channels < 1) {
  1275. @@ -1322,7 +1519,6 @@ dwc_otg_transaction_type_e dwc_otg_hcd_s
  1276. last_sel_trans_num_nonper_scheduled++;
  1277. #endif /* DEBUG_HOST_CHANNELS */
  1278. }
  1279. - qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
  1280. assign_and_init_hc(hcd, qh);
  1281. @@ -1336,21 +1532,22 @@ dwc_otg_transaction_type_e dwc_otg_hcd_s
  1282. &qh->qh_list_entry);
  1283. DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
  1284. - if (ret_val == DWC_OTG_TRANSACTION_NONE) {
  1285. - ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC;
  1286. - } else {
  1287. - ret_val = DWC_OTG_TRANSACTION_ALL;
  1288. - }
  1289. + g_np_sent++;
  1290. if (!microframe_schedule)
  1291. hcd->non_periodic_channels++;
  1292. }
  1293. + if(!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned))
  1294. + ret_val |= DWC_OTG_TRANSACTION_PERIODIC;
  1295. +
  1296. + if(!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active))
  1297. + ret_val |= DWC_OTG_TRANSACTION_NON_PERIODIC;
  1298. +
  1299. +
  1300. #ifdef DEBUG_HOST_CHANNELS
  1301. last_sel_trans_num_avail_hc_at_end = hcd->available_host_channels;
  1302. #endif /* DEBUG_HOST_CHANNELS */
  1303. -
  1304. - DWC_SPINLOCK_FREE(channel_lock);
  1305. return ret_val;
  1306. }
  1307. @@ -1464,6 +1661,15 @@ static void process_periodic_channels(dw
  1308. qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
  1309. + // Do not send a split start transaction any later than frame .6
  1310. + // Note, we have to schedule a periodic in .5 to make it go in .6
  1311. + if(fiq_split_enable && qh->do_split && ((dwc_otg_hcd_get_frame_number(hcd) + 1) & 7) > 6)
  1312. + {
  1313. + qh_ptr = qh_ptr->next;
  1314. + g_next_sched_frame = dwc_otg_hcd_get_frame_number(hcd) | 7;
  1315. + continue;
  1316. + }
  1317. +
  1318. /*
  1319. * Set a flag if we're queuing high-bandwidth in slave mode.
  1320. * The flag prevents any halts to get into the request queue in
  1321. @@ -1593,6 +1799,15 @@ static void process_non_periodic_channel
  1322. qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t,
  1323. qh_list_entry);
  1324. +
  1325. + // Do not send a split start transaction any later than frame .5
  1326. + // non periodic transactions will start immediately in this uframe
  1327. + if(fiq_split_enable && qh->do_split && ((dwc_otg_hcd_get_frame_number(hcd) + 1) & 7) > 6)
  1328. + {
  1329. + g_next_sched_frame = dwc_otg_hcd_get_frame_number(hcd) | 7;
  1330. + break;
  1331. + }
  1332. +
  1333. status =
  1334. queue_transaction(hcd, qh->channel,
  1335. tx_status.b.nptxfspcavail);
  1336. @@ -3118,17 +3333,13 @@ dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc
  1337. else
  1338. dwc_otg_urb = DWC_ALLOC(size);
  1339. - if (NULL != dwc_otg_urb)
  1340. - dwc_otg_urb->packet_count = iso_desc_count;
  1341. + if (dwc_otg_urb)
  1342. + dwc_otg_urb->packet_count = iso_desc_count;
  1343. else {
  1344. - dwc_otg_urb->packet_count = 0;
  1345. - if (size != 0) {
  1346. - DWC_ERROR("**** DWC OTG HCD URB alloc - "
  1347. - "%salloc of %db failed\n",
  1348. - atomic_alloc?"atomic ":"", size);
  1349. - }
  1350. - }
  1351. -
  1352. + DWC_ERROR("**** DWC OTG HCD URB alloc - "
  1353. + "%salloc of %db failed\n",
  1354. + atomic_alloc?"atomic ":"", size);
  1355. + }
  1356. return dwc_otg_urb;
  1357. }
  1358. --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
  1359. +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
  1360. @@ -168,10 +168,10 @@ typedef enum dwc_otg_control_phase {
  1361. /** Transaction types. */
  1362. typedef enum dwc_otg_transaction_type {
  1363. - DWC_OTG_TRANSACTION_NONE,
  1364. - DWC_OTG_TRANSACTION_PERIODIC,
  1365. - DWC_OTG_TRANSACTION_NON_PERIODIC,
  1366. - DWC_OTG_TRANSACTION_ALL
  1367. + DWC_OTG_TRANSACTION_NONE = 0,
  1368. + DWC_OTG_TRANSACTION_PERIODIC = 1,
  1369. + DWC_OTG_TRANSACTION_NON_PERIODIC = 2,
  1370. + DWC_OTG_TRANSACTION_ALL = DWC_OTG_TRANSACTION_PERIODIC + DWC_OTG_TRANSACTION_NON_PERIODIC
  1371. } dwc_otg_transaction_type_e;
  1372. struct dwc_otg_qh;
  1373. @@ -321,6 +321,11 @@ typedef struct dwc_otg_qh {
  1374. */
  1375. uint16_t sched_frame;
  1376. + /*
  1377. + ** Frame a NAK was received on this queue head, used to minimise NAK retransmission
  1378. + */
  1379. + uint16_t nak_frame;
  1380. +
  1381. /** (micro)frame at which last start split was initialized. */
  1382. uint16_t start_split_frame;
  1383. @@ -365,10 +370,19 @@ typedef struct dwc_otg_qh {
  1384. uint16_t speed;
  1385. uint16_t frame_usecs[8];
  1386. +
  1387. + uint32_t skip_count;
  1388. } dwc_otg_qh_t;
  1389. DWC_CIRCLEQ_HEAD(hc_list, dwc_hc);
  1390. +typedef struct urb_tq_entry {
  1391. + struct urb *urb;
  1392. + DWC_TAILQ_ENTRY(urb_tq_entry) urb_tq_entries;
  1393. +} urb_tq_entry_t;
  1394. +
  1395. +DWC_TAILQ_HEAD(urb_list, urb_tq_entry);
  1396. +
  1397. /**
  1398. * This structure holds the state of the HCD, including the non-periodic and
  1399. * periodic schedules.
  1400. @@ -546,9 +560,12 @@ struct dwc_otg_hcd {
  1401. /* Tasket to do a reset */
  1402. dwc_tasklet_t *reset_tasklet;
  1403. + dwc_tasklet_t *completion_tasklet;
  1404. + struct urb_list completed_urb_list;
  1405. +
  1406. /* */
  1407. dwc_spinlock_t *lock;
  1408. -
  1409. + dwc_spinlock_t *channel_lock;
  1410. /**
  1411. * Private data that could be used by OS wrapper.
  1412. */
  1413. @@ -559,6 +576,12 @@ struct dwc_otg_hcd {
  1414. /** Frame List */
  1415. uint32_t *frame_list;
  1416. + /** Hub - Port assignment */
  1417. + int hub_port[128];
  1418. +#ifdef FIQ_DEBUG
  1419. + int hub_port_alloc[2048];
  1420. +#endif
  1421. +
  1422. /** Frame List DMA address */
  1423. dma_addr_t frame_list_dma;
  1424. @@ -589,6 +612,10 @@ extern dwc_otg_transaction_type_e dwc_ot
  1425. extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
  1426. dwc_otg_transaction_type_e tr_type);
  1427. +int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh);
  1428. +void dwc_otg_hcd_release_port(dwc_otg_hcd_t * dwc_otg_hcd, dwc_otg_qh_t *qh);
  1429. +
  1430. +
  1431. /** @} */
  1432. /** @name Interrupt Handler Functions */
  1433. --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
  1434. +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
  1435. @@ -276,7 +276,7 @@ void dump_frame_list(dwc_otg_hcd_t * hcd
  1436. static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
  1437. {
  1438. dwc_irqflags_t flags;
  1439. - dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
  1440. + dwc_spinlock_t *channel_lock = hcd->channel_lock;
  1441. dwc_hc_t *hc = qh->channel;
  1442. if (dwc_qh_is_non_per(qh)) {
  1443. @@ -306,7 +306,6 @@ static void release_channel_ddma(dwc_otg
  1444. dwc_memset(qh->desc_list, 0x00,
  1445. sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh));
  1446. }
  1447. - DWC_SPINLOCK_FREE(channel_lock);
  1448. }
  1449. /**
  1450. --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
  1451. +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
  1452. @@ -113,6 +113,11 @@ extern void dwc_otg_hcd_remove(dwc_otg_h
  1453. */
  1454. extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
  1455. +/** This function is used to handle the fast interrupt
  1456. + *
  1457. + */
  1458. +extern void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void);
  1459. +
  1460. /**
  1461. * Returns private data set by
  1462. * dwc_otg_hcd_set_priv_data function.
  1463. --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
  1464. +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
  1465. @@ -34,6 +34,12 @@
  1466. #include "dwc_otg_hcd.h"
  1467. #include "dwc_otg_regs.h"
  1468. +#include "dwc_otg_mphi_fix.h"
  1469. +
  1470. +#include <linux/jiffies.h>
  1471. +#include <mach/hardware.h>
  1472. +#include <asm/fiq.h>
  1473. +
  1474. extern bool microframe_schedule;
  1475. @@ -41,38 +47,487 @@ extern bool microframe_schedule;
  1476. * This file contains the implementation of the HCD Interrupt handlers.
  1477. */
  1478. +/*
  1479. + * Some globals to communicate between the FIQ and INTERRUPT
  1480. + */
  1481. +
  1482. +void * dummy_send;
  1483. +mphi_regs_t c_mphi_regs;
  1484. +volatile void *dwc_regs_base;
  1485. +int fiq_done, int_done;
  1486. +
  1487. +gintsts_data_t gintsts_saved = {.d32 = 0};
  1488. +hcint_data_t hcint_saved[MAX_EPS_CHANNELS];
  1489. +hcintmsk_data_t hcintmsk_saved[MAX_EPS_CHANNELS];
  1490. +int split_out_xfersize[MAX_EPS_CHANNELS];
  1491. +haint_data_t haint_saved;
  1492. +
  1493. +int g_next_sched_frame, g_np_count, g_np_sent;
  1494. +static int mphi_int_count = 0 ;
  1495. +
  1496. +hcchar_data_t nak_hcchar;
  1497. +hctsiz_data_t nak_hctsiz;
  1498. +hcsplt_data_t nak_hcsplt;
  1499. +int nak_count;
  1500. +
  1501. +int complete_sched[MAX_EPS_CHANNELS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
  1502. +int split_start_frame[MAX_EPS_CHANNELS];
  1503. +int queued_port[MAX_EPS_CHANNELS];
  1504. +
  1505. +#ifdef FIQ_DEBUG
  1506. +char buffer[1000*16];
  1507. +int wptr;
  1508. +void notrace _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...)
  1509. +{
  1510. + FIQDBG_T dbg_lvl_req = FIQDBG_PORTHUB;
  1511. + va_list args;
  1512. + char text[17];
  1513. + hfnum_data_t hfnum = { .d32 = FIQ_READ(dwc_regs_base + 0x408) };
  1514. + unsigned long flags;
  1515. +
  1516. + local_irq_save(flags);
  1517. + local_fiq_disable();
  1518. + if(dbg_lvl & dbg_lvl_req || dbg_lvl == FIQDBG_ERR)
  1519. + {
  1520. + snprintf(text, 9, "%4d%d:%d ", hfnum.b.frnum/8, hfnum.b.frnum%8, 8 - hfnum.b.frrem/937);
  1521. + va_start(args, fmt);
  1522. + vsnprintf(text+8, 9, fmt, args);
  1523. + va_end(args);
  1524. +
  1525. + memcpy(buffer + wptr, text, 16);
  1526. + wptr = (wptr + 16) % sizeof(buffer);
  1527. + }
  1528. + local_irq_restore(flags);
  1529. +}
  1530. +#endif
  1531. +
  1532. +void notrace fiq_queue_request(int channel, int odd_frame)
  1533. +{
  1534. + hcchar_data_t hcchar = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x0) };
  1535. + hcsplt_data_t hcsplt = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x4) };
  1536. + hctsiz_data_t hctsiz = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x10) };
  1537. +
  1538. + if(hcsplt.b.spltena == 0)
  1539. + {
  1540. + fiq_print(FIQDBG_ERR, "SPLTENA ");
  1541. + BUG();
  1542. + }
  1543. +
  1544. + if(hcchar.b.epdir == 1)
  1545. + {
  1546. + fiq_print(FIQDBG_SCHED, "IN Ch %d", channel);
  1547. + }
  1548. + else
  1549. + {
  1550. + hctsiz.b.xfersize = 0;
  1551. + fiq_print(FIQDBG_SCHED, "OUT Ch %d", channel);
  1552. + }
  1553. + FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x10), hctsiz.d32);
  1554. +
  1555. + hcsplt.b.compsplt = 1;
  1556. + FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x4), hcsplt.d32);
  1557. +
  1558. + // Send the Split complete
  1559. + hcchar.b.chen = 1;
  1560. + hcchar.b.oddfrm = odd_frame ? 1 : 0;
  1561. +
  1562. + // Post this for transmit on the next frame for periodic or this frame for non-periodic
  1563. + fiq_print(FIQDBG_SCHED, "SND_%s", odd_frame ? "ODD " : "EVEN");
  1564. +
  1565. + FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x0), hcchar.d32);
  1566. +}
  1567. +
  1568. +static int last_sof = -1;
  1569. +
  1570. +/*
  1571. +** Function to handle the start of frame interrupt, choose whether we need to do anything and
  1572. +** therefore trigger the main interrupt
  1573. +**
  1574. +** returns int != 0 - interrupt has been handled
  1575. +*/
  1576. +int diff;
  1577. +
  1578. +int notrace fiq_sof_handle(hfnum_data_t hfnum)
  1579. +{
  1580. + int handled = 0;
  1581. + int i;
  1582. +
  1583. + // Just check that once we're running we don't miss a SOF
  1584. + /*if(last_sof != -1 && (hfnum.b.frnum != ((last_sof + 1) & 0x3fff)))
  1585. + {
  1586. + fiq_print(FIQDBG_ERR, "LASTSOF ");
  1587. + fiq_print(FIQDBG_ERR, "%4d%d ", last_sof / 8, last_sof & 7);
  1588. + fiq_print(FIQDBG_ERR, "%4d%d ", hfnum.b.frnum / 8, hfnum.b.frnum & 7);
  1589. + BUG();
  1590. + }*/
  1591. +
  1592. + // Only start remembering the last sof when the interrupt has been
  1593. + // enabled (we don't check the mask to come in here...)
  1594. + if(last_sof != -1 || FIQ_READ(dwc_regs_base + 0x18) & (1<<3))
  1595. + last_sof = hfnum.b.frnum;
  1596. +
  1597. + for(i = 0; i < MAX_EPS_CHANNELS; i++)
  1598. + {
  1599. + if(complete_sched[i] != -1)
  1600. + {
  1601. + if(complete_sched[i] <= hfnum.b.frnum || (complete_sched[i] > 0x3f00 && hfnum.b.frnum < 0xf0))
  1602. + {
  1603. + fiq_queue_request(i, hfnum.b.frnum & 1);
  1604. + complete_sched[i] = -1;
  1605. + }
  1606. + }
  1607. +
  1608. + if(complete_sched[i] != -1)
  1609. + {
  1610. + // This is because we've seen a split complete occur with no start...
  1611. + // most likely because missed the complete 0x3fff frames ago!
  1612. +
  1613. + diff = (hfnum.b.frnum + 0x3fff - complete_sched[i]) & 0x3fff ;
  1614. + if(diff > 32 && diff < 0x3f00)
  1615. + {
  1616. + fiq_print(FIQDBG_ERR, "SPLTMISS");
  1617. + BUG();
  1618. + }
  1619. + }
  1620. + }
  1621. +
  1622. + if(g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum))
  1623. + {
  1624. + /*
  1625. + * If np_count != np_sent that means we need to queue non-periodic (bulk) packets this packet
  1626. + * g_next_sched_frame is the next frame we have periodic packets for
  1627. + *
  1628. + * if neither of these are required for this frame then just clear the interrupt
  1629. + */
  1630. + handled = 1;
  1631. +
  1632. + }
  1633. +
  1634. + return handled;
  1635. +}
  1636. +
  1637. +int notrace port_id(hcsplt_data_t hcsplt)
  1638. +{
  1639. + return hcsplt.b.prtaddr + (hcsplt.b.hubaddr << 8);
  1640. +}
  1641. +
  1642. +int notrace fiq_hcintr_handle(int channel, hfnum_data_t hfnum)
  1643. +{
  1644. + hcchar_data_t hcchar = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x0) };
  1645. + hcsplt_data_t hcsplt = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x4) };
  1646. + hcint_data_t hcint = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x8) };
  1647. + hcintmsk_data_t hcintmsk = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0xc) };
  1648. + hctsiz_data_t hctsiz = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x10)};
  1649. +
  1650. + hcint_saved[channel].d32 |= hcint.d32;
  1651. + hcintmsk_saved[channel].d32 = hcintmsk.d32;
  1652. +
  1653. + if(hcsplt.b.spltena)
  1654. + {
  1655. + fiq_print(FIQDBG_PORTHUB, "ph: %4x", port_id(hcsplt));
  1656. + if(hcint.b.chhltd)
  1657. + {
  1658. + fiq_print(FIQDBG_SCHED, "CH HLT %d", channel);
  1659. + fiq_print(FIQDBG_SCHED, "%08x", hcint_saved[channel]);
  1660. + }
  1661. + if(hcint.b.stall || hcint.b.xacterr || hcint.b.bblerr || hcint.b.frmovrun || hcint.b.datatglerr)
  1662. + {
  1663. + queued_port[channel] = 0;
  1664. + fiq_print(FIQDBG_ERR, "CHAN ERR");
  1665. + }
  1666. + if(hcint.b.xfercomp)
  1667. + {
  1668. + // Clear the port allocation and transmit anything also on this port
  1669. + queued_port[channel] = 0;
  1670. + fiq_print(FIQDBG_SCHED, "XFERCOMP");
  1671. + }
  1672. + if(hcint.b.nak)
  1673. + {
  1674. + queued_port[channel] = 0;
  1675. + fiq_print(FIQDBG_SCHED, "NAK");
  1676. + }
  1677. + if(hcint.b.ack && !hcsplt.b.compsplt)
  1678. + {
  1679. + int i;
  1680. +
  1681. + // Do not complete isochronous out transactions
  1682. + if(hcchar.b.eptype == 1 && hcchar.b.epdir == 0)
  1683. + {
  1684. + queued_port[channel] = 0;
  1685. + fiq_print(FIQDBG_SCHED, "ISOC_OUT");
  1686. + }
  1687. + else
  1688. + {
  1689. + // Make sure we check the port / hub combination that we sent this split on.
  1690. + // Do not queue a second request to the same port
  1691. + for(i = 0; i < MAX_EPS_CHANNELS; i++)
  1692. + {
  1693. + if(port_id(hcsplt) == queued_port[i])
  1694. + {
  1695. + fiq_print(FIQDBG_ERR, "PORTERR ");
  1696. + //BUG();
  1697. + }
  1698. + }
  1699. +
  1700. + split_start_frame[channel] = (hfnum.b.frnum + 1) & ~7;
  1701. +
  1702. + // Note, the size of an OUT is in the start split phase, not
  1703. + // the complete split
  1704. + split_out_xfersize[channel] = hctsiz.b.xfersize;
  1705. +
  1706. + hcint_saved[channel].b.chhltd = 0;
  1707. + hcint_saved[channel].b.ack = 0;
  1708. +
  1709. + queued_port[channel] = port_id(hcsplt);
  1710. +
  1711. + if(hcchar.b.eptype & 1)
  1712. + {
  1713. + // Send the periodic complete in the same oddness frame as the ACK went...
  1714. + fiq_queue_request(channel, !(hfnum.b.frnum & 1));
  1715. + // complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 1);
  1716. + }
  1717. + else
  1718. + {
  1719. + // Schedule the split complete to occur later
  1720. + complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 2);
  1721. + fiq_print(FIQDBG_SCHED, "ACK%04d%d", complete_sched[channel]/8, complete_sched[channel]%8);
  1722. + }
  1723. + }
  1724. + }
  1725. + if(hcint.b.nyet)
  1726. + {
  1727. + fiq_print(FIQDBG_ERR, "NYETERR1");
  1728. + //BUG();
  1729. + // Can transmit a split complete up to uframe .0 of the next frame
  1730. + if(hfnum.b.frnum <= dwc_frame_num_inc(split_start_frame[channel], 8))
  1731. + {
  1732. + // Send it next frame
  1733. + if(hcchar.b.eptype & 1) // type 1 & 3 are interrupt & isoc
  1734. + {
  1735. + fiq_print(FIQDBG_SCHED, "NYT:SEND");
  1736. + fiq_queue_request(channel, !(hfnum.b.frnum & 1));
  1737. + }
  1738. + else
  1739. + {
  1740. + // Schedule non-periodic access for next frame (the odd-even bit doesn't effect NP)
  1741. + complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 1);
  1742. + fiq_print(FIQDBG_SCHED, "NYT%04d%d", complete_sched[channel]/8, complete_sched[channel]%8);
  1743. + }
  1744. + hcint_saved[channel].b.chhltd = 0;
  1745. + hcint_saved[channel].b.nyet = 0;
  1746. + }
  1747. + else
  1748. + {
  1749. + queued_port[channel] = 0;
  1750. + fiq_print(FIQDBG_ERR, "NYETERR2");
  1751. + //BUG();
  1752. + }
  1753. + }
  1754. + }
  1755. + else
  1756. + {
  1757. + /*
  1758. + * If we have any of NAK, ACK, Datatlgerr active on a
  1759. + * non-split channel, the sole reason is to reset error
  1760. + * counts for a previously broken transaction. The FIQ
  1761. + * will thrash on NAK IN and ACK OUT in particular so
  1762. + * handle it "once" and allow the IRQ to do the rest.
  1763. + */
  1764. + hcint.d32 &= hcintmsk.d32;
  1765. + if(hcint.b.nak)
  1766. + {
  1767. + hcintmsk.b.nak = 0;
  1768. + FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0xc), hcintmsk.d32);
  1769. + }
  1770. + if (hcint.b.ack)
  1771. + {
  1772. + hcintmsk.b.ack = 0;
  1773. + FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0xc), hcintmsk.d32);
  1774. + }
  1775. + }
  1776. +
  1777. + // Clear the interrupt, this will also clear the HAINT bit
  1778. + FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x8), hcint.d32);
  1779. + return hcint_saved[channel].d32 == 0;
  1780. +}
  1781. +
  1782. +gintsts_data_t gintsts;
  1783. +gintmsk_data_t gintmsk;
  1784. +// triggered: The set of interrupts that were triggered
  1785. +// handled: The set of interrupts that have been handled (no IRQ is
  1786. +// required)
  1787. +// keep: The set of interrupts we want to keep unmasked even though we
  1788. +// want to trigger an IRQ to handle it (SOF and HCINTR)
  1789. +gintsts_data_t triggered, handled, keep;
  1790. +hfnum_data_t hfnum;
  1791. +
  1792. +void __attribute__ ((naked)) notrace dwc_otg_hcd_handle_fiq(void)
  1793. +{
  1794. +
  1795. + /* entry takes care to store registers we will be treading on here */
  1796. + asm __volatile__ (
  1797. + "mov ip, sp ;"
  1798. + /* stash FIQ and normal regs */
  1799. + "stmdb sp!, {r0-r12, lr};"
  1800. + /* !! THIS SETS THE FRAME, adjust to > sizeof locals */
  1801. + "sub fp, ip, #512 ;"
  1802. + );
  1803. +
  1804. + // Cannot put local variables at the beginning of the function
  1805. + // because otherwise 'C' will play with the stack pointer. any locals
  1806. + // need to be inside the following block
  1807. + do
  1808. + {
  1809. + fiq_done++;
  1810. + gintsts.d32 = FIQ_READ(dwc_regs_base + 0x14);
  1811. + gintmsk.d32 = FIQ_READ(dwc_regs_base + 0x18);
  1812. + hfnum.d32 = FIQ_READ(dwc_regs_base + 0x408);
  1813. + triggered.d32 = gintsts.d32 & gintmsk.d32;
  1814. + handled.d32 = 0;
  1815. + keep.d32 = 0;
  1816. + fiq_print(FIQDBG_INT, "FIQ ");
  1817. + fiq_print(FIQDBG_INT, "%08x", gintsts.d32);
  1818. + fiq_print(FIQDBG_INT, "%08x", gintmsk.d32);
  1819. + if(gintsts.d32)
  1820. + {
  1821. + // If port enabled
  1822. + if((FIQ_READ(dwc_regs_base + 0x440) & 0xf) == 0x5)
  1823. + {
  1824. + if(gintsts.b.sofintr)
  1825. + {
  1826. + if(fiq_sof_handle(hfnum))
  1827. + {
  1828. + handled.b.sofintr = 1; /* Handled in FIQ */
  1829. + }
  1830. + else
  1831. + {
  1832. + /* Keer interrupt unmasked */
  1833. + keep.b.sofintr = 1;
  1834. + }
  1835. + {
  1836. + // Need to make sure the read and clearing of the SOF interrupt is as close as possible to avoid the possibility of missing
  1837. + // a start of frame interrupt
  1838. + gintsts_data_t gintsts = { .b.sofintr = 1 };
  1839. + FIQ_WRITE((dwc_regs_base + 0x14), gintsts.d32);
  1840. + }
  1841. + }
  1842. +
  1843. + if(fiq_split_enable && gintsts.b.hcintr)
  1844. + {
  1845. + int i;
  1846. + haint_data_t haint;
  1847. + haintmsk_data_t haintmsk;
  1848. +
  1849. + haint.d32 = FIQ_READ(dwc_regs_base + 0x414);
  1850. + haintmsk.d32 = FIQ_READ(dwc_regs_base + 0x418);
  1851. + haint.d32 &= haintmsk.d32;
  1852. + haint_saved.d32 |= haint.d32;
  1853. +
  1854. + fiq_print(FIQDBG_INT, "hcintr");
  1855. + fiq_print(FIQDBG_INT, "%08x", FIQ_READ(dwc_regs_base + 0x414));
  1856. +
  1857. + // Go through each channel that has an enabled interrupt
  1858. + for(i = 0; i < 16; i++)
  1859. + if((haint.d32 >> i) & 1)
  1860. + if(fiq_hcintr_handle(i, hfnum))
  1861. + haint_saved.d32 &= ~(1 << i); /* this was handled */
  1862. +
  1863. + /* If we've handled all host channel interrupts then don't trigger the interrupt */
  1864. + if(haint_saved.d32 == 0)
  1865. + {
  1866. + handled.b.hcintr = 1;
  1867. + }
  1868. + else
  1869. + {
  1870. + /* Make sure we keep the channel interrupt unmasked when triggering the IRQ */
  1871. + keep.b.hcintr = 1;
  1872. + }
  1873. +
  1874. + {
  1875. + gintsts_data_t gintsts = { .b.hcintr = 1 };
  1876. +
  1877. + // Always clear the channel interrupt
  1878. + FIQ_WRITE((dwc_regs_base + 0x14), gintsts.d32);
  1879. + }
  1880. + }
  1881. + }
  1882. + else
  1883. + {
  1884. + last_sof = -1;
  1885. + }
  1886. + }
  1887. +
  1888. + // Mask out the interrupts triggered - those handled - don't mask out the ones we want to keep
  1889. + gintmsk.d32 = keep.d32 | (gintmsk.d32 & ~(triggered.d32 & ~handled.d32));
  1890. + // Save those that were triggered but not handled
  1891. + gintsts_saved.d32 |= triggered.d32 & ~handled.d32;
  1892. + FIQ_WRITE(dwc_regs_base + 0x18, gintmsk.d32);
  1893. +
  1894. + // Clear and save any unhandled interrupts and trigger the interrupt
  1895. + if(gintsts_saved.d32)
  1896. + {
  1897. + /* To enable the MPHI interrupt (INT 32)
  1898. + */
  1899. + FIQ_WRITE( c_mphi_regs.outdda, (int) dummy_send);
  1900. + FIQ_WRITE( c_mphi_regs.outddb, (1 << 29));
  1901. +
  1902. + mphi_int_count++;
  1903. + }
  1904. + }
  1905. + while(0);
  1906. +
  1907. + mb();
  1908. +
  1909. + /* exit back to normal mode restoring everything */
  1910. + asm __volatile__ (
  1911. + /* return FIQ regs back to pristine state
  1912. + * and get normal regs back
  1913. + */
  1914. + "ldmia sp!, {r0-r12, lr};"
  1915. +
  1916. + /* return */
  1917. + "subs pc, lr, #4;"
  1918. + );
  1919. +}
  1920. +
  1921. /** This function handles interrupts for the HCD. */
  1922. int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
  1923. {
  1924. int retval = 0;
  1925. + static int last_time;
  1926. dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
  1927. gintsts_data_t gintsts;
  1928. + gintmsk_data_t gintmsk;
  1929. + hfnum_data_t hfnum;
  1930. +
  1931. #ifdef DEBUG
  1932. dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
  1933. - //GRAYG: debugging
  1934. - if (NULL == global_regs) {
  1935. - DWC_DEBUGPL(DBG_HCD, "**** NULL regs: dwc_otg_hcd=%p "
  1936. - "core_if=%p\n",
  1937. - dwc_otg_hcd, global_regs);
  1938. - return retval;
  1939. - }
  1940. #endif
  1941. + gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
  1942. + gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
  1943. +
  1944. /* Exit from ISR if core is hibernated */
  1945. if (core_if->hibernation_suspend == 1) {
  1946. - return retval;
  1947. + goto exit_handler_routine;
  1948. }
  1949. DWC_SPINLOCK(dwc_otg_hcd->lock);
  1950. /* Check if HOST Mode */
  1951. if (dwc_otg_is_host_mode(core_if)) {
  1952. - gintsts.d32 = dwc_otg_read_core_intr(core_if);
  1953. + local_fiq_disable();
  1954. + gintmsk.d32 |= gintsts_saved.d32;
  1955. + gintsts.d32 |= gintsts_saved.d32;
  1956. + gintsts_saved.d32 = 0;
  1957. + local_fiq_enable();
  1958. if (!gintsts.d32) {
  1959. - DWC_SPINUNLOCK(dwc_otg_hcd->lock);
  1960. - return 0;
  1961. + goto exit_handler_routine;
  1962. }
  1963. + gintsts.d32 &= gintmsk.d32;
  1964. +
  1965. #ifdef DEBUG
  1966. + // We should be OK doing this because the common interrupts should already have been serviced
  1967. /* Don't print debug message in the interrupt handler on SOF */
  1968. #ifndef DEBUG_SOF
  1969. if (gintsts.d32 != DWC_SOF_INTR_MASK)
  1970. @@ -88,10 +543,16 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_
  1971. "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x core_if=%p\n",
  1972. gintsts.d32, core_if);
  1973. #endif
  1974. -
  1975. - if (gintsts.b.sofintr) {
  1976. + hfnum.d32 = DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs->hfnum);
  1977. + if (gintsts.b.sofintr && g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum))
  1978. + {
  1979. + /* Note, we should never get here if the FIQ is doing it's job properly*/
  1980. retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);
  1981. }
  1982. + else if (gintsts.b.sofintr) {
  1983. + retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);
  1984. + }
  1985. +
  1986. if (gintsts.b.rxstsqlvl) {
  1987. retval |=
  1988. dwc_otg_hcd_handle_rx_status_q_level_intr
  1989. @@ -106,7 +567,10 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_
  1990. /** @todo Implement i2cintr handler. */
  1991. }
  1992. if (gintsts.b.portintr) {
  1993. +
  1994. + gintmsk_data_t gintmsk = { .b.portintr = 1};
  1995. retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd);
  1996. + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32);
  1997. }
  1998. if (gintsts.b.hcintr) {
  1999. retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd);
  2000. @@ -138,11 +602,48 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_
  2001. #endif
  2002. }
  2003. +
  2004. +exit_handler_routine:
  2005. +
  2006. + if (fiq_fix_enable)
  2007. + {
  2008. + local_fiq_disable();
  2009. + // Make sure that we don't clear the interrupt if we've still got pending work to do
  2010. + if(gintsts_saved.d32 == 0)
  2011. + {
  2012. + /* Clear the MPHI interrupt */
  2013. + DWC_WRITE_REG32(c_mphi_regs.intstat, (1<<16));
  2014. + if (mphi_int_count >= 60)
  2015. + {
  2016. + DWC_WRITE_REG32(c_mphi_regs.ctrl, ((1<<31) + (1<<16)));
  2017. + while(!(DWC_READ_REG32(c_mphi_regs.ctrl) & (1 << 17)))
  2018. + ;
  2019. + DWC_WRITE_REG32(c_mphi_regs.ctrl, (1<<31));
  2020. + mphi_int_count = 0;
  2021. + }
  2022. + int_done++;
  2023. + }
  2024. +
  2025. + // Unmask handled interrupts
  2026. + FIQ_WRITE(dwc_regs_base + 0x18, gintmsk.d32);
  2027. + //DWC_MODIFY_REG32((uint32_t *)IO_ADDRESS(USB_BASE + 0x8), 0 , 1);
  2028. +
  2029. + local_fiq_enable();
  2030. +
  2031. + if((jiffies / HZ) > last_time)
  2032. + {
  2033. + /* Once a second output the fiq and irq numbers, useful for debug */
  2034. + last_time = jiffies / HZ;
  2035. + DWC_DEBUGPL(DBG_USER, "int_done = %d fiq_done = %d\n", int_done, fiq_done);
  2036. + }
  2037. + }
  2038. +
  2039. DWC_SPINUNLOCK(dwc_otg_hcd->lock);
  2040. return retval;
  2041. }
  2042. #ifdef DWC_TRACK_MISSED_SOFS
  2043. +
  2044. #warning Compiling code to track missed SOFs
  2045. #define FRAME_NUM_ARRAY_SIZE 1000
  2046. /**
  2047. @@ -188,7 +689,8 @@ int32_t dwc_otg_hcd_handle_sof_intr(dwc_
  2048. dwc_list_link_t *qh_entry;
  2049. dwc_otg_qh_t *qh;
  2050. dwc_otg_transaction_type_e tr_type;
  2051. - gintsts_data_t gintsts = {.d32 = 0 };
  2052. + int did_something = 0;
  2053. + int32_t next_sched_frame = -1;
  2054. hfnum.d32 =
  2055. DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum);
  2056. @@ -212,17 +714,31 @@ int32_t dwc_otg_hcd_handle_sof_intr(dwc_
  2057. qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry);
  2058. qh_entry = qh_entry->next;
  2059. if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) {
  2060. +
  2061. /*
  2062. * Move QH to the ready list to be executed next
  2063. * (micro)frame.
  2064. */
  2065. DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
  2066. &qh->qh_list_entry);
  2067. +
  2068. + did_something = 1;
  2069. + }
  2070. + else
  2071. + {
  2072. + if(next_sched_frame < 0 || dwc_frame_num_le(qh->sched_frame, next_sched_frame))
  2073. + {
  2074. + next_sched_frame = qh->sched_frame;
  2075. + }
  2076. }
  2077. }
  2078. +
  2079. + g_next_sched_frame = next_sched_frame;
  2080. +
  2081. tr_type = dwc_otg_hcd_select_transactions(hcd);
  2082. if (tr_type != DWC_OTG_TRANSACTION_NONE) {
  2083. dwc_otg_hcd_queue_transactions(hcd, tr_type);
  2084. + did_something = 1;
  2085. }
  2086. /* Clear interrupt */
  2087. @@ -511,6 +1027,15 @@ int32_t dwc_otg_hcd_handle_hc_intr(dwc_o
  2088. haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if);
  2089. + // Overwrite with saved interrupts from fiq handler
  2090. + if(fiq_split_enable)
  2091. + {
  2092. + local_fiq_disable();
  2093. + haint.d32 = haint_saved.d32;
  2094. + haint_saved.d32 = 0;
  2095. + local_fiq_enable();
  2096. + }
  2097. +
  2098. for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) {
  2099. if (haint.b2.chint & (1 << i)) {
  2100. retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i);
  2101. @@ -551,7 +1076,10 @@ static uint32_t get_actual_xfer_length(d
  2102. *short_read = (hctsiz.b.xfersize != 0);
  2103. }
  2104. } else if (hc->qh->do_split) {
  2105. - length = qtd->ssplit_out_xfer_count;
  2106. + if(fiq_split_enable)
  2107. + length = split_out_xfersize[hc->hc_num];
  2108. + else
  2109. + length = qtd->ssplit_out_xfer_count;
  2110. } else {
  2111. length = hc->xfer_len;
  2112. }
  2113. @@ -595,7 +1123,6 @@ static int update_urb_state_xfer_comp(dw
  2114. DWC_OTG_HC_XFER_COMPLETE,
  2115. &short_read);
  2116. -
  2117. /* non DWORD-aligned buffer case handling. */
  2118. if (hc->align_buff && xfer_length && hc->ep_is_in) {
  2119. dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf,
  2120. @@ -797,11 +1324,24 @@ static void release_channel(dwc_otg_hcd_
  2121. dwc_otg_transaction_type_e tr_type;
  2122. int free_qtd;
  2123. dwc_irqflags_t flags;
  2124. - dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
  2125. + dwc_spinlock_t *channel_lock = hcd->channel_lock;
  2126. +#ifdef FIQ_DEBUG
  2127. + int endp = qtd->urb ? qtd->urb->pipe_info.ep_num : 0;
  2128. +#endif
  2129. + int hog_port = 0;
  2130. DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d, xfer_len %d\n",
  2131. __func__, hc->hc_num, halt_status, hc->xfer_len);
  2132. + if(fiq_split_enable && hc->do_split) {
  2133. + if(!hc->ep_is_in && hc->ep_type == UE_ISOCHRONOUS) {
  2134. + if(hc->xact_pos == DWC_HCSPLIT_XACTPOS_MID ||
  2135. + hc->xact_pos == DWC_HCSPLIT_XACTPOS_BEGIN) {
  2136. + hog_port = 1;
  2137. + }
  2138. + }
  2139. + }
  2140. +
  2141. switch (halt_status) {
  2142. case DWC_OTG_HC_XFER_URB_COMPLETE:
  2143. free_qtd = 1;
  2144. @@ -876,15 +1416,32 @@ cleanup:
  2145. DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
  2146. hcd->available_host_channels++;
  2147. + fiq_print(FIQDBG_PORTHUB, "AHC = %d ", hcd->available_host_channels);
  2148. DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
  2149. }
  2150. + if(fiq_split_enable && hc->do_split)
  2151. + {
  2152. + if(!(hcd->hub_port[hc->hub_addr] & (1 << hc->port_addr)))
  2153. + {
  2154. + fiq_print(FIQDBG_ERR, "PRTNOTAL");
  2155. + //BUG();
  2156. + }
  2157. + if(!hog_port && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC ||
  2158. + hc->ep_type == DWC_OTG_EP_TYPE_INTR)) {
  2159. + hcd->hub_port[hc->hub_addr] &= ~(1 << hc->port_addr);
  2160. +#ifdef FIQ_DEBUG
  2161. + hcd->hub_port_alloc[hc->hub_addr * 16 + hc->port_addr] = -1;
  2162. +#endif
  2163. + fiq_print(FIQDBG_PORTHUB, "H%dP%d:RR%d", hc->hub_addr, hc->port_addr, endp);
  2164. + }
  2165. + }
  2166. +
  2167. /* Try to queue more transfers now that there's a free channel. */
  2168. tr_type = dwc_otg_hcd_select_transactions(hcd);
  2169. if (tr_type != DWC_OTG_TRANSACTION_NONE) {
  2170. dwc_otg_hcd_queue_transactions(hcd, tr_type);
  2171. }
  2172. - DWC_SPINLOCK_FREE(channel_lock);
  2173. }
  2174. /**
  2175. @@ -1295,6 +1852,17 @@ static int32_t handle_hc_nak_intr(dwc_ot
  2176. "NAK Received--\n", hc->hc_num);
  2177. /*
  2178. + * When we get bulk NAKs then remember this so we holdoff on this qh until
  2179. + * the beginning of the next frame
  2180. + */
  2181. + switch(dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
  2182. + case UE_BULK:
  2183. + case UE_CONTROL:
  2184. + if (nak_holdoff_enable)
  2185. + hc->qh->nak_frame = dwc_otg_hcd_get_frame_number(hcd);
  2186. + }
  2187. +
  2188. + /*
  2189. * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and
  2190. * interrupt. Re-start the SSPLIT transfer.
  2191. */
  2192. @@ -1316,7 +1884,11 @@ static int32_t handle_hc_nak_intr(dwc_ot
  2193. * transfers in DMA mode for the sole purpose of
  2194. * resetting the error count after a transaction error
  2195. * occurs. The core will continue transferring data.
  2196. + * Disable other interrupts unmasked for the same
  2197. + * reason.
  2198. */
  2199. + disable_hc_int(hc_regs, datatglerr);
  2200. + disable_hc_int(hc_regs, ack);
  2201. qtd->error_count = 0;
  2202. goto handle_nak_done;
  2203. }
  2204. @@ -1428,6 +2000,15 @@ static int32_t handle_hc_ack_intr(dwc_ot
  2205. halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
  2206. }
  2207. } else {
  2208. + /*
  2209. + * An unmasked ACK on a non-split DMA transaction is
  2210. + * for the sole purpose of resetting error counts. Disable other
  2211. + * interrupts unmasked for the same reason.
  2212. + */
  2213. + if(hcd->core_if->dma_enable) {
  2214. + disable_hc_int(hc_regs, datatglerr);
  2215. + disable_hc_int(hc_regs, nak);
  2216. + }
  2217. qtd->error_count = 0;
  2218. if (hc->qh->ping_state) {
  2219. @@ -1490,8 +2071,10 @@ static int32_t handle_hc_nyet_intr(dwc_o
  2220. hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
  2221. int frnum = dwc_otg_hcd_get_frame_number(hcd);
  2222. + // With the FIQ running we only ever see the failed NYET
  2223. if (dwc_full_frame_num(frnum) !=
  2224. - dwc_full_frame_num(hc->qh->sched_frame)) {
  2225. + dwc_full_frame_num(hc->qh->sched_frame) ||
  2226. + fiq_split_enable) {
  2227. /*
  2228. * No longer in the same full speed frame.
  2229. * Treat this as a transaction error.
  2230. @@ -1778,13 +2361,28 @@ static int32_t handle_hc_datatglerr_intr
  2231. dwc_otg_qtd_t * qtd)
  2232. {
  2233. DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
  2234. - "Data Toggle Error--\n", hc->hc_num);
  2235. + "Data Toggle Error on %s transfer--\n",
  2236. + hc->hc_num, (hc->ep_is_in ? "IN" : "OUT"));
  2237. - if (hc->ep_is_in) {
  2238. + /* Data toggles on split transactions cause the hc to halt.
  2239. + * restart transfer */
  2240. + if(hc->qh->do_split)
  2241. + {
  2242. + qtd->error_count++;
  2243. + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
  2244. + update_urb_state_xfer_intr(hc, hc_regs,
  2245. + qtd->urb, qtd, DWC_OTG_HC_XFER_XACT_ERR);
  2246. + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
  2247. + } else if (hc->ep_is_in) {
  2248. + /* An unmasked data toggle error on a non-split DMA transaction is
  2249. + * for the sole purpose of resetting error counts. Disable other
  2250. + * interrupts unmasked for the same reason.
  2251. + */
  2252. + if(hcd->core_if->dma_enable) {
  2253. + disable_hc_int(hc_regs, ack);
  2254. + disable_hc_int(hc_regs, nak);
  2255. + }
  2256. qtd->error_count = 0;
  2257. - } else {
  2258. - DWC_ERROR("Data Toggle Error on OUT transfer,"
  2259. - "channel %d\n", hc->hc_num);
  2260. }
  2261. disable_hc_int(hc_regs, datatglerr);
  2262. @@ -1862,10 +2460,10 @@ static inline int halt_status_ok(dwc_otg
  2263. static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd,
  2264. dwc_hc_t * hc,
  2265. dwc_otg_hc_regs_t * hc_regs,
  2266. - dwc_otg_qtd_t * qtd)
  2267. + dwc_otg_qtd_t * qtd,
  2268. + hcint_data_t hcint,
  2269. + hcintmsk_data_t hcintmsk)
  2270. {
  2271. - hcint_data_t hcint;
  2272. - hcintmsk_data_t hcintmsk;
  2273. int out_nak_enh = 0;
  2274. /* For core with OUT NAK enhancement, the flow for high-
  2275. @@ -1897,8 +2495,11 @@ static void handle_hc_chhltd_intr_dma(dw
  2276. }
  2277. /* Read the HCINTn register to determine the cause for the halt. */
  2278. - hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
  2279. - hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
  2280. + if(!fiq_split_enable)
  2281. + {
  2282. + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
  2283. + hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
  2284. + }
  2285. if (hcint.b.xfercomp) {
  2286. /** @todo This is here because of a possible hardware bug. Spec
  2287. @@ -1937,6 +2538,8 @@ static void handle_hc_chhltd_intr_dma(dw
  2288. handle_hc_babble_intr(hcd, hc, hc_regs, qtd);
  2289. } else if (hcint.b.frmovrun) {
  2290. handle_hc_frmovrun_intr(hcd, hc, hc_regs, qtd);
  2291. + } else if (hcint.b.datatglerr) {
  2292. + handle_hc_datatglerr_intr(hcd, hc, hc_regs, qtd);
  2293. } else if (!out_nak_enh) {
  2294. if (hcint.b.nyet) {
  2295. /*
  2296. @@ -1986,12 +2589,24 @@ static void handle_hc_chhltd_intr_dma(dw
  2297. DWC_READ_REG32(&hcd->
  2298. core_if->core_global_regs->
  2299. gintsts));
  2300. + /* Failthrough: use 3-strikes rule */
  2301. + qtd->error_count++;
  2302. + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
  2303. + update_urb_state_xfer_intr(hc, hc_regs,
  2304. + qtd->urb, qtd, DWC_OTG_HC_XFER_XACT_ERR);
  2305. + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
  2306. }
  2307. }
  2308. } else {
  2309. DWC_PRINTF("NYET/NAK/ACK/other in non-error case, 0x%08x\n",
  2310. hcint.d32);
  2311. + /* Failthrough: use 3-strikes rule */
  2312. + qtd->error_count++;
  2313. + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
  2314. + update_urb_state_xfer_intr(hc, hc_regs,
  2315. + qtd->urb, qtd, DWC_OTG_HC_XFER_XACT_ERR);
  2316. + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
  2317. }
  2318. }
  2319. @@ -2009,13 +2624,15 @@ static void handle_hc_chhltd_intr_dma(dw
  2320. static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd,
  2321. dwc_hc_t * hc,
  2322. dwc_otg_hc_regs_t * hc_regs,
  2323. - dwc_otg_qtd_t * qtd)
  2324. + dwc_otg_qtd_t * qtd,
  2325. + hcint_data_t hcint,
  2326. + hcintmsk_data_t hcintmsk)
  2327. {
  2328. DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
  2329. "Channel Halted--\n", hc->hc_num);
  2330. if (hcd->core_if->dma_enable) {
  2331. - handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd);
  2332. + handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd, hcint, hcintmsk);
  2333. } else {
  2334. #ifdef DEBUG
  2335. if (!halt_status_ok(hcd, hc, hc_regs, qtd)) {
  2336. @@ -2032,7 +2649,7 @@ static int32_t handle_hc_chhltd_intr(dwc
  2337. int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)
  2338. {
  2339. int retval = 0;
  2340. - hcint_data_t hcint;
  2341. + hcint_data_t hcint, hcint_orig;
  2342. hcintmsk_data_t hcintmsk;
  2343. dwc_hc_t *hc;
  2344. dwc_otg_hc_regs_t *hc_regs;
  2345. @@ -2042,15 +2659,33 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc
  2346. hc = dwc_otg_hcd->hc_ptr_array[num];
  2347. hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[num];
  2348. + if(hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
  2349. + /* We are responding to a channel disable. Driver
  2350. + * state is cleared - our qtd has gone away.
  2351. + */
  2352. + release_channel(dwc_otg_hcd, hc, NULL, hc->halt_status);
  2353. + return 1;
  2354. + }
  2355. qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list);
  2356. hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
  2357. + hcint_orig = hcint;
  2358. hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
  2359. DWC_DEBUGPL(DBG_HCDV,
  2360. " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",
  2361. hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32));
  2362. hcint.d32 = hcint.d32 & hcintmsk.d32;
  2363. + if(fiq_split_enable)
  2364. + {
  2365. + // replace with the saved interrupts from the fiq handler
  2366. + local_fiq_disable();
  2367. + hcint_orig.d32 = hcint_saved[num].d32;
  2368. + hcint.d32 = hcint_orig.d32 & hcintmsk_saved[num].d32;
  2369. + hcint_saved[num].d32 = 0;
  2370. + local_fiq_enable();
  2371. + }
  2372. +
  2373. if (!dwc_otg_hcd->core_if->dma_enable) {
  2374. if (hcint.b.chhltd && hcint.d32 != 0x2) {
  2375. hcint.b.chhltd = 0;
  2376. @@ -2068,7 +2703,7 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc
  2377. hcint.b.nyet = 0;
  2378. }
  2379. if (hcint.b.chhltd) {
  2380. - retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd);
  2381. + retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd, hcint_orig, hcintmsk_saved[num]);
  2382. }
  2383. if (hcint.b.ahberr) {
  2384. retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
  2385. @@ -2080,7 +2715,8 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc
  2386. retval |= handle_hc_nak_intr(dwc_otg_hcd, hc, hc_regs, qtd);
  2387. }
  2388. if (hcint.b.ack) {
  2389. - retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd);
  2390. + if(!hcint.b.chhltd)
  2391. + retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd);
  2392. }
  2393. if (hcint.b.nyet) {
  2394. retval |= handle_hc_nyet_intr(dwc_otg_hcd, hc, hc_regs, qtd);
  2395. @@ -2102,5 +2738,4 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc
  2396. return retval;
  2397. }
  2398. -
  2399. #endif /* DWC_DEVICE_ONLY */
  2400. --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
  2401. +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
  2402. @@ -1,3 +1,4 @@
  2403. +
  2404. /* ==========================================================================
  2405. * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $
  2406. * $Revision: #20 $
  2407. @@ -50,6 +51,7 @@
  2408. #include <linux/dma-mapping.h>
  2409. #include <linux/version.h>
  2410. #include <asm/io.h>
  2411. +#include <asm/fiq.h>
  2412. #include <linux/usb.h>
  2413. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
  2414. #include <../drivers/usb/core/hcd.h>
  2415. @@ -67,6 +69,8 @@
  2416. #include "dwc_otg_dbg.h"
  2417. #include "dwc_otg_driver.h"
  2418. #include "dwc_otg_hcd.h"
  2419. +#include "dwc_otg_mphi_fix.h"
  2420. +
  2421. /**
  2422. * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is
  2423. * qualified with its direction (possible 32 endpoints per device).
  2424. @@ -76,6 +80,8 @@
  2425. static const char dwc_otg_hcd_name[] = "dwc_otg_hcd";
  2426. +extern bool fiq_fix_enable;
  2427. +
  2428. /** @name Linux HC Driver API Functions */
  2429. /** @{ */
  2430. /* manage i/o requests, device state */
  2431. @@ -259,13 +265,15 @@ static void free_bus_bandwidth(struct us
  2432. /**
  2433. * Sets the final status of an URB and returns it to the device driver. Any
  2434. - * required cleanup of the URB is performed.
  2435. + * required cleanup of the URB is performed. The HCD lock should be held on
  2436. + * entry.
  2437. */
  2438. static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
  2439. dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status)
  2440. {
  2441. struct urb *urb = (struct urb *)urb_handle;
  2442. -
  2443. + urb_tq_entry_t *new_entry;
  2444. + int rc = 0;
  2445. if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
  2446. DWC_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n",
  2447. __func__, urb, usb_pipedevice(urb->pipe),
  2448. @@ -279,7 +287,7 @@ static int _complete(dwc_otg_hcd_t * hcd
  2449. }
  2450. }
  2451. }
  2452. -
  2453. + new_entry = DWC_ALLOC_ATOMIC(sizeof(urb_tq_entry_t));
  2454. urb->actual_length = dwc_otg_hcd_urb_get_actual_length(dwc_otg_urb);
  2455. /* Convert status value. */
  2456. switch (status) {
  2457. @@ -301,6 +309,9 @@ static int _complete(dwc_otg_hcd_t * hcd
  2458. case -DWC_E_OVERFLOW:
  2459. status = -EOVERFLOW;
  2460. break;
  2461. + case -DWC_E_SHUTDOWN:
  2462. + status = -ESHUTDOWN;
  2463. + break;
  2464. default:
  2465. if (status) {
  2466. DWC_PRINTF("Uknown urb status %d\n", status);
  2467. @@ -342,18 +353,33 @@ static int _complete(dwc_otg_hcd_t * hcd
  2468. }
  2469. DWC_FREE(dwc_otg_urb);
  2470. -
  2471. + if (!new_entry) {
  2472. + DWC_ERROR("dwc_otg_hcd: complete: cannot allocate URB TQ entry\n");
  2473. + urb->status = -EPROTO;
  2474. + /* don't schedule the tasklet -
  2475. + * directly return the packet here with error. */
  2476. #if USB_URB_EP_LINKING
  2477. - usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
  2478. + usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
  2479. #endif
  2480. - DWC_SPINUNLOCK(hcd->lock);
  2481. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
  2482. - usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb);
  2483. + usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb);
  2484. #else
  2485. - usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status);
  2486. + usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, urb->status);
  2487. #endif
  2488. - DWC_SPINLOCK(hcd->lock);
  2489. -
  2490. + } else {
  2491. + new_entry->urb = urb;
  2492. +#if USB_URB_EP_LINKING
  2493. + rc = usb_hcd_check_unlink_urb(dwc_otg_hcd_to_hcd(hcd), urb, urb->status);
  2494. + if(0 == rc) {
  2495. + usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
  2496. + }
  2497. +#endif
  2498. + if(0 == rc) {
  2499. + DWC_TAILQ_INSERT_TAIL(&hcd->completed_urb_list, new_entry,
  2500. + urb_tq_entries);
  2501. + DWC_TASK_HI_SCHEDULE(hcd->completion_tasklet);
  2502. + }
  2503. + }
  2504. return 0;
  2505. }
  2506. @@ -366,6 +392,16 @@ static struct dwc_otg_hcd_function_ops h
  2507. .get_b_hnp_enable = _get_b_hnp_enable,
  2508. };
  2509. +static struct fiq_handler fh = {
  2510. + .name = "usb_fiq",
  2511. +};
  2512. +struct fiq_stack_s {
  2513. + int magic1;
  2514. + uint8_t stack[2048];
  2515. + int magic2;
  2516. +} fiq_stack;
  2517. +
  2518. +extern mphi_regs_t c_mphi_regs;
  2519. /**
  2520. * Initializes the HCD. This function allocates memory for and initializes the
  2521. * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the
  2522. @@ -379,6 +415,7 @@ int hcd_init(dwc_bus_dev_t *_dev)
  2523. dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
  2524. int retval = 0;
  2525. u64 dmamask;
  2526. + struct pt_regs regs;
  2527. DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT otg_dev=%p\n", otg_dev);
  2528. @@ -396,6 +433,20 @@ int hcd_init(dwc_bus_dev_t *_dev)
  2529. pci_set_consistent_dma_mask(_dev, dmamask);
  2530. #endif
  2531. + if (fiq_fix_enable)
  2532. + {
  2533. + // Set up fiq
  2534. + claim_fiq(&fh);
  2535. + set_fiq_handler(__FIQ_Branch, 4);
  2536. + memset(&regs,0,sizeof(regs));
  2537. + regs.ARM_r8 = (long)dwc_otg_hcd_handle_fiq;
  2538. + regs.ARM_r9 = (long)0;
  2539. + regs.ARM_sp = (long)fiq_stack.stack + sizeof(fiq_stack.stack) - 4;
  2540. + set_fiq_regs(&regs);
  2541. + fiq_stack.magic1 = 0xdeadbeef;
  2542. + fiq_stack.magic2 = 0xaa995566;
  2543. + }
  2544. +
  2545. /*
  2546. * Allocate memory for the base HCD plus the DWC OTG HCD.
  2547. * Initialize the base HCD.
  2548. @@ -415,6 +466,30 @@ int hcd_init(dwc_bus_dev_t *_dev)
  2549. hcd->regs = otg_dev->os_dep.base;
  2550. + if (fiq_fix_enable)
  2551. + {
  2552. + volatile extern void *dwc_regs_base;
  2553. +
  2554. + //Set the mphi periph to the required registers
  2555. + c_mphi_regs.base = otg_dev->os_dep.mphi_base;
  2556. + c_mphi_regs.ctrl = otg_dev->os_dep.mphi_base + 0x4c;
  2557. + c_mphi_regs.outdda = otg_dev->os_dep.mphi_base + 0x28;
  2558. + c_mphi_regs.outddb = otg_dev->os_dep.mphi_base + 0x2c;
  2559. + c_mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50;
  2560. +
  2561. + dwc_regs_base = otg_dev->os_dep.base;
  2562. +
  2563. + //Enable mphi peripheral
  2564. + writel((1<<31),c_mphi_regs.ctrl);
  2565. +#ifdef DEBUG
  2566. + if (readl(c_mphi_regs.ctrl) & 0x80000000)
  2567. + DWC_DEBUGPL(DBG_USER, "MPHI periph has been enabled\n");
  2568. + else
  2569. + DWC_DEBUGPL(DBG_USER, "MPHI periph has NOT been enabled\n");
  2570. +#endif
  2571. + // Enable FIQ interrupt from USB peripheral
  2572. + enable_fiq(INTERRUPT_VC_USB);
  2573. + }
  2574. /* Initialize the DWC OTG HCD. */
  2575. dwc_otg_hcd = dwc_otg_hcd_alloc_hcd();
  2576. if (!dwc_otg_hcd) {
  2577. @@ -607,9 +682,7 @@ static int dwc_otg_urb_enqueue(struct us
  2578. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
  2579. struct usb_host_endpoint *ep = urb->ep;
  2580. #endif
  2581. -#if USB_URB_EP_LINKING
  2582. dwc_irqflags_t irqflags;
  2583. -#endif
  2584. void **ref_ep_hcpriv = &ep->hcpriv;
  2585. dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
  2586. dwc_otg_hcd_urb_t *dwc_otg_urb;
  2587. @@ -661,9 +734,8 @@ static int dwc_otg_urb_enqueue(struct us
  2588. if(dwc_otg_urb == NULL)
  2589. return -ENOMEM;
  2590. - urb->hcpriv = dwc_otg_urb;
  2591. - if (!dwc_otg_urb && urb->number_of_packets)
  2592. - return -ENOMEM;
  2593. + if (!dwc_otg_urb && urb->number_of_packets)
  2594. + return -ENOMEM;
  2595. dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_urb, usb_pipedevice(urb->pipe),
  2596. usb_pipeendpoint(urb->pipe), ep_type,
  2597. @@ -703,37 +775,42 @@ static int dwc_otg_urb_enqueue(struct us
  2598. iso_frame_desc[i].length);
  2599. }
  2600. + DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);
  2601. + urb->hcpriv = dwc_otg_urb;
  2602. #if USB_URB_EP_LINKING
  2603. - DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);
  2604. retval = usb_hcd_link_urb_to_ep(hcd, urb);
  2605. - DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
  2606. if (0 == retval)
  2607. #endif
  2608. - {
  2609. - retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb,
  2610. - /*(dwc_otg_qh_t **)*/
  2611. - ref_ep_hcpriv,
  2612. - mem_flags == GFP_ATOMIC ? 1 : 0);
  2613. - if (0 == retval) {
  2614. - if (alloc_bandwidth) {
  2615. - allocate_bus_bandwidth(hcd,
  2616. - dwc_otg_hcd_get_ep_bandwidth(
  2617. - dwc_otg_hcd, *ref_ep_hcpriv),
  2618. - urb);
  2619. - }
  2620. - } else {
  2621. + {
  2622. + retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb,
  2623. + /*(dwc_otg_qh_t **)*/
  2624. + ref_ep_hcpriv, 1);
  2625. + if (0 == retval) {
  2626. + if (alloc_bandwidth) {
  2627. + allocate_bus_bandwidth(hcd,
  2628. + dwc_otg_hcd_get_ep_bandwidth(
  2629. + dwc_otg_hcd, *ref_ep_hcpriv),
  2630. + urb);
  2631. + }
  2632. + } else {
  2633. + DWC_DEBUGPL(DBG_HCD, "DWC OTG dwc_otg_hcd_urb_enqueue failed rc %d\n", retval);
  2634. #if USB_URB_EP_LINKING
  2635. - dwc_irqflags_t irqflags;
  2636. - DWC_DEBUGPL(DBG_HCD, "DWC OTG dwc_otg_hcd_urb_enqueue failed rc %d\n", retval);
  2637. - DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);
  2638. - usb_hcd_unlink_urb_from_ep(hcd, urb);
  2639. - DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
  2640. -#endif
  2641. - if (retval == -DWC_E_NO_DEVICE) {
  2642. - retval = -ENODEV;
  2643. - }
  2644. - }
  2645. - }
  2646. + usb_hcd_unlink_urb_from_ep(hcd, urb);
  2647. +#endif
  2648. + DWC_FREE(dwc_otg_urb);
  2649. + urb->hcpriv = NULL;
  2650. + if (retval == -DWC_E_NO_DEVICE)
  2651. + retval = -ENODEV;
  2652. + }
  2653. + }
  2654. +#if USB_URB_EP_LINKING
  2655. + else
  2656. + {
  2657. + DWC_FREE(dwc_otg_urb);
  2658. + urb->hcpriv = NULL;
  2659. + }
  2660. +#endif
  2661. + DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
  2662. return retval;
  2663. }
  2664. @@ -777,6 +854,8 @@ static int dwc_otg_urb_dequeue(struct us
  2665. usb_hcd_unlink_urb_from_ep(hcd, urb);
  2666. #endif
  2667. DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
  2668. +
  2669. +
  2670. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
  2671. usb_hcd_giveback_urb(hcd, urb);
  2672. #else
  2673. --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
  2674. +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
  2675. @@ -41,6 +41,7 @@
  2676. #include "dwc_otg_hcd.h"
  2677. #include "dwc_otg_regs.h"
  2678. +#include "dwc_otg_mphi_fix.h"
  2679. extern bool microframe_schedule;
  2680. @@ -182,6 +183,7 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_ot
  2681. if (microframe_schedule)
  2682. qh->speed = dev_speed;
  2683. + qh->nak_frame = 0xffff;
  2684. if (((dev_speed == USB_SPEED_LOW) ||
  2685. (dev_speed == USB_SPEED_FULL)) &&
  2686. @@ -191,6 +193,7 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_ot
  2687. dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr,
  2688. hub_port);
  2689. qh->do_split = 1;
  2690. + qh->skip_count = 0;
  2691. }
  2692. if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) {
  2693. @@ -573,6 +576,9 @@ static int check_max_xfer_size(dwc_otg_h
  2694. return status;
  2695. }
  2696. +
  2697. +extern int g_next_sched_frame, g_np_count, g_np_sent;
  2698. +
  2699. /**
  2700. * Schedules an interrupt or isochronous transfer in the periodic schedule.
  2701. *
  2702. @@ -631,8 +637,13 @@ static int schedule_periodic(dwc_otg_hcd
  2703. DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_ready, &qh->qh_list_entry);
  2704. }
  2705. else {
  2706. - /* Always start in the inactive schedule. */
  2707. - DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry);
  2708. + if(DWC_LIST_EMPTY(&hcd->periodic_sched_inactive) || dwc_frame_num_le(qh->sched_frame, g_next_sched_frame))
  2709. + {
  2710. + g_next_sched_frame = qh->sched_frame;
  2711. +
  2712. + }
  2713. + /* Always start in the inactive schedule. */
  2714. + DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry);
  2715. }
  2716. if (!microframe_schedule) {
  2717. @@ -646,6 +657,7 @@ static int schedule_periodic(dwc_otg_hcd
  2718. return status;
  2719. }
  2720. +
  2721. /**
  2722. * This function adds a QH to either the non periodic or periodic schedule if
  2723. * it is not already in the schedule. If the QH is already in the schedule, no
  2724. @@ -668,6 +680,7 @@ int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * h
  2725. /* Always start in the inactive schedule. */
  2726. DWC_LIST_INSERT_TAIL(&hcd->non_periodic_sched_inactive,
  2727. &qh->qh_list_entry);
  2728. + g_np_count++;
  2729. } else {
  2730. status = schedule_periodic(hcd, qh);
  2731. if ( !hcd->periodic_qh_count ) {
  2732. @@ -727,6 +740,9 @@ void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t
  2733. hcd->non_periodic_qh_ptr->next;
  2734. }
  2735. DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);
  2736. +
  2737. + // If we've removed the last non-periodic entry then there are none left!
  2738. + g_np_count = g_np_sent;
  2739. } else {
  2740. deschedule_periodic(hcd, qh);
  2741. hcd->periodic_qh_count--;
  2742. @@ -755,6 +771,24 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_h
  2743. int sched_next_periodic_split)
  2744. {
  2745. if (dwc_qh_is_non_per(qh)) {
  2746. +
  2747. + dwc_otg_qh_t *qh_tmp;
  2748. + dwc_list_link_t *qh_list;
  2749. + DWC_LIST_FOREACH(qh_list, &hcd->non_periodic_sched_inactive)
  2750. + {
  2751. + qh_tmp = DWC_LIST_ENTRY(qh_list, struct dwc_otg_qh, qh_list_entry);
  2752. + if(qh_tmp == qh)
  2753. + {
  2754. + /*
  2755. + * FIQ is being disabled because this one nevers gets a np_count increment
  2756. + * This is still not absolutely correct, but it should fix itself with
  2757. + * just an unnecessary extra interrupt
  2758. + */
  2759. + g_np_sent = g_np_count;
  2760. + }
  2761. + }
  2762. +
  2763. +
  2764. dwc_otg_hcd_qh_remove(hcd, qh);
  2765. if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
  2766. /* Add back to inactive non-periodic schedule. */
  2767. @@ -768,6 +802,7 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_h
  2768. if (sched_next_periodic_split) {
  2769. qh->sched_frame = frame_number;
  2770. +
  2771. if (dwc_frame_num_le(frame_number,
  2772. dwc_frame_num_inc
  2773. (qh->start_split_frame,
  2774. @@ -816,6 +851,11 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_h
  2775. DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
  2776. &qh->qh_list_entry);
  2777. } else {
  2778. + if(!dwc_frame_num_le(g_next_sched_frame, qh->sched_frame))
  2779. + {
  2780. + g_next_sched_frame = qh->sched_frame;
  2781. + }
  2782. +
  2783. DWC_LIST_MOVE_HEAD
  2784. (&hcd->periodic_sched_inactive,
  2785. &qh->qh_list_entry);
  2786. @@ -880,6 +920,7 @@ void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t
  2787. * QH to place the QTD into. If it does not find a QH, then it will create a
  2788. * new QH. If the QH to which the QTD is added is not currently scheduled, it
  2789. * is placed into the proper schedule based on its EP type.
  2790. + * HCD lock must be held and interrupts must be disabled on entry
  2791. *
  2792. * @param[in] qtd The QTD to add
  2793. * @param[in] hcd The DWC HCD structure
  2794. @@ -892,8 +933,6 @@ int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t *
  2795. dwc_otg_hcd_t * hcd, dwc_otg_qh_t ** qh, int atomic_alloc)
  2796. {
  2797. int retval = 0;
  2798. - dwc_irqflags_t flags;
  2799. -
  2800. dwc_otg_hcd_urb_t *urb = qtd->urb;
  2801. /*
  2802. @@ -903,18 +942,16 @@ int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t *
  2803. if (*qh == NULL) {
  2804. *qh = dwc_otg_hcd_qh_create(hcd, urb, atomic_alloc);
  2805. if (*qh == NULL) {
  2806. - retval = -1;
  2807. + retval = -DWC_E_NO_MEMORY;
  2808. goto done;
  2809. }
  2810. }
  2811. - DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
  2812. retval = dwc_otg_hcd_qh_add(hcd, *qh);
  2813. if (retval == 0) {
  2814. DWC_CIRCLEQ_INSERT_TAIL(&((*qh)->qtd_list), qtd,
  2815. qtd_list_entry);
  2816. + qtd->qh = *qh;
  2817. }
  2818. - DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
  2819. -
  2820. done:
  2821. return retval;
  2822. --- /dev/null
  2823. +++ b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c
  2824. @@ -0,0 +1,113 @@
  2825. +#include "dwc_otg_regs.h"
  2826. +#include "dwc_otg_dbg.h"
  2827. +
  2828. +void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name)
  2829. +{
  2830. + DWC_DEBUGPL(DBG_USER, "*** Debugging from within the %s function: ***\n"
  2831. + "curmode: %1i Modemismatch: %1i otgintr: %1i sofintr: %1i\n"
  2832. + "rxstsqlvl: %1i nptxfempty : %1i ginnakeff: %1i goutnakeff: %1i\n"
  2833. + "ulpickint: %1i i2cintr: %1i erlysuspend:%1i usbsuspend: %1i\n"
  2834. + "usbreset: %1i enumdone: %1i isooutdrop: %1i eopframe: %1i\n"
  2835. + "restoredone: %1i epmismatch: %1i inepint: %1i outepintr: %1i\n"
  2836. + "incomplisoin:%1i incomplisoout:%1i fetsusp: %1i resetdet: %1i\n"
  2837. + "portintr: %1i hcintr: %1i ptxfempty: %1i lpmtranrcvd:%1i\n"
  2838. + "conidstschng:%1i disconnect: %1i sessreqintr:%1i wkupintr: %1i\n",
  2839. + function_name,
  2840. + gintsts.b.curmode,
  2841. + gintsts.b.modemismatch,
  2842. + gintsts.b.otgintr,
  2843. + gintsts.b.sofintr,
  2844. + gintsts.b.rxstsqlvl,
  2845. + gintsts.b.nptxfempty,
  2846. + gintsts.b.ginnakeff,
  2847. + gintsts.b.goutnakeff,
  2848. + gintsts.b.ulpickint,
  2849. + gintsts.b.i2cintr,
  2850. + gintsts.b.erlysuspend,
  2851. + gintsts.b.usbsuspend,
  2852. + gintsts.b.usbreset,
  2853. + gintsts.b.enumdone,
  2854. + gintsts.b.isooutdrop,
  2855. + gintsts.b.eopframe,
  2856. + gintsts.b.restoredone,
  2857. + gintsts.b.epmismatch,
  2858. + gintsts.b.inepint,
  2859. + gintsts.b.outepintr,
  2860. + gintsts.b.incomplisoin,
  2861. + gintsts.b.incomplisoout,
  2862. + gintsts.b.fetsusp,
  2863. + gintsts.b.resetdet,
  2864. + gintsts.b.portintr,
  2865. + gintsts.b.hcintr,
  2866. + gintsts.b.ptxfempty,
  2867. + gintsts.b.lpmtranrcvd,
  2868. + gintsts.b.conidstschng,
  2869. + gintsts.b.disconnect,
  2870. + gintsts.b.sessreqintr,
  2871. + gintsts.b.wkupintr);
  2872. + return;
  2873. +}
  2874. +
  2875. +void dwc_debug_core_int_mask(gintmsk_data_t gintmsk, const char* function_name)
  2876. +{
  2877. + DWC_DEBUGPL(DBG_USER, "Interrupt Mask status (called from %s) :\n"
  2878. + "modemismatch: %1i otgintr: %1i sofintr: %1i rxstsqlvl: %1i\n"
  2879. + "nptxfempty: %1i ginnakeff: %1i goutnakeff: %1i ulpickint: %1i\n"
  2880. + "i2cintr: %1i erlysuspend:%1i usbsuspend: %1i usbreset: %1i\n"
  2881. + "enumdone: %1i isooutdrop: %1i eopframe: %1i restoredone: %1i\n"
  2882. + "epmismatch: %1i inepintr: %1i outepintr: %1i incomplisoin:%1i\n"
  2883. + "incomplisoout:%1i fetsusp: %1i resetdet: %1i portintr: %1i\n"
  2884. + "hcintr: %1i ptxfempty: %1i lpmtranrcvd:%1i conidstschng:%1i\n"
  2885. + "disconnect: %1i sessreqintr:%1i wkupintr: %1i\n",
  2886. + function_name,
  2887. + gintmsk.b.modemismatch,
  2888. + gintmsk.b.otgintr,
  2889. + gintmsk.b.sofintr,
  2890. + gintmsk.b.rxstsqlvl,
  2891. + gintmsk.b.nptxfempty,
  2892. + gintmsk.b.ginnakeff,
  2893. + gintmsk.b.goutnakeff,
  2894. + gintmsk.b.ulpickint,
  2895. + gintmsk.b.i2cintr,
  2896. + gintmsk.b.erlysuspend,
  2897. + gintmsk.b.usbsuspend,
  2898. + gintmsk.b.usbreset,
  2899. + gintmsk.b.enumdone,
  2900. + gintmsk.b.isooutdrop,
  2901. + gintmsk.b.eopframe,
  2902. + gintmsk.b.restoredone,
  2903. + gintmsk.b.epmismatch,
  2904. + gintmsk.b.inepintr,
  2905. + gintmsk.b.outepintr,
  2906. + gintmsk.b.incomplisoin,
  2907. + gintmsk.b.incomplisoout,
  2908. + gintmsk.b.fetsusp,
  2909. + gintmsk.b.resetdet,
  2910. + gintmsk.b.portintr,
  2911. + gintmsk.b.hcintr,
  2912. + gintmsk.b.ptxfempty,
  2913. + gintmsk.b.lpmtranrcvd,
  2914. + gintmsk.b.conidstschng,
  2915. + gintmsk.b.disconnect,
  2916. + gintmsk.b.sessreqintr,
  2917. + gintmsk.b.wkupintr);
  2918. + return;
  2919. +}
  2920. +
  2921. +void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name)
  2922. +{
  2923. + DWC_DEBUGPL(DBG_USER, "otg int register (from %s function):\n"
  2924. + "sesenddet:%1i sesreqsucstschung:%2i hstnegsucstschng:%1i\n"
  2925. + "hstnegdet:%1i adevtoutchng: %2i debdone: %1i\n"
  2926. + "mvic: %1i\n",
  2927. + function_name,
  2928. + gotgint.b.sesenddet,
  2929. + gotgint.b.sesreqsucstschng,
  2930. + gotgint.b.hstnegsucstschng,
  2931. + gotgint.b.hstnegdet,
  2932. + gotgint.b.adevtoutchng,
  2933. + gotgint.b.debdone,
  2934. + gotgint.b.mvic);
  2935. +
  2936. + return;
  2937. +}
  2938. --- /dev/null
  2939. +++ b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h
  2940. @@ -0,0 +1,48 @@
  2941. +#ifndef __DWC_OTG_MPHI_FIX_H__
  2942. +#define __DWC_OTG_MPHI_FIX_H__
  2943. +#define FIQ_WRITE(_addr_,_data_) (*(volatile uint32_t *) (_addr_) = (_data_))
  2944. +#define FIQ_READ(_addr_) (*(volatile uint32_t *) (_addr_))
  2945. +
  2946. +typedef struct {
  2947. + volatile void* base;
  2948. + volatile void* ctrl;
  2949. + volatile void* outdda;
  2950. + volatile void* outddb;
  2951. + volatile void* intstat;
  2952. +} mphi_regs_t;
  2953. +
  2954. +void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name);
  2955. +void dwc_debug_core_int_mask(gintsts_data_t gintmsk, const char* function_name);
  2956. +void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name);
  2957. +
  2958. +extern gintsts_data_t gintsts_saved;
  2959. +
  2960. +#ifdef DEBUG
  2961. +#define DWC_DBG_PRINT_CORE_INT(_arg_) dwc_debug_print_core_int_reg(_arg_,__func__)
  2962. +#define DWC_DBG_PRINT_CORE_INT_MASK(_arg_) dwc_debug_core_int_mask(_arg_,__func__)
  2963. +#define DWC_DBG_PRINT_OTG_INT(_arg_) dwc_debug_otg_int(_arg_,__func__)
  2964. +
  2965. +#else
  2966. +#define DWC_DBG_PRINT_CORE_INT(_arg_)
  2967. +#define DWC_DBG_PRINT_CORE_INT_MASK(_arg_)
  2968. +#define DWC_DBG_PRINT_OTG_INT(_arg_)
  2969. +
  2970. +#endif
  2971. +
  2972. +typedef enum {
  2973. + FIQDBG_SCHED = (1 << 0),
  2974. + FIQDBG_INT = (1 << 1),
  2975. + FIQDBG_ERR = (1 << 2),
  2976. + FIQDBG_PORTHUB = (1 << 3),
  2977. +} FIQDBG_T;
  2978. +
  2979. +void _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...);
  2980. +#ifdef FIQ_DEBUG
  2981. +#define fiq_print _fiq_print
  2982. +#else
  2983. +#define fiq_print(x, y, ...)
  2984. +#endif
  2985. +
  2986. +extern bool fiq_fix_enable, nak_holdoff_enable, fiq_split_enable;
  2987. +
  2988. +#endif
  2989. --- a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
  2990. +++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
  2991. @@ -97,6 +97,9 @@ typedef struct os_dependent {
  2992. /** Register offset for Diagnostic API */
  2993. uint32_t reg_offset;
  2994. + /** Base address for MPHI peripheral */
  2995. + void *mphi_base;
  2996. +
  2997. #ifdef LM_INTERFACE
  2998. struct lm_device *lmdev;
  2999. #elif defined(PCI_INTERFACE)
  3000. --- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
  3001. +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
  3002. @@ -4276,7 +4276,7 @@ do { \
  3003. && (pcd->ep0state == EP0_OUT_DATA_PHASE))
  3004. status.d32 = core_if->dev_if->out_desc_addr->status.d32;
  3005. if (pcd->ep0state == EP0_OUT_STATUS_PHASE)
  3006. - status.d32 = status.d32 = core_if->dev_if->
  3007. + status.d32 = core_if->dev_if->
  3008. out_desc_addr->status.d32;
  3009. if (status.b.sr) {