nexef_plat.c 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799
  1. /*!
  2. *****************************************************************************
  3. * Copyright (c) Imagination Technologies Ltd.
  4. *
  5. * The contents of this file are subject to the MIT license as set out below.
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a
  8. * copy of this software and associated documentation files (the "Software"),
  9. * to deal in the Software without restriction, including without limitation
  10. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11. * and/or sell copies of the Software, and to permit persons to whom the
  12. * Software is furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. *
  25. * Alternatively, the contents of this file may be used under the terms of the
  26. * GNU General Public License Version 2 ("GPL")in which case the provisions of
  27. * GPL are applicable instead of those above.
  28. *
  29. * If you wish to allow use of your version of this file only under the terms
  30. * of GPL, and not to allow others to use your version of this file under the
  31. * terms of the MIT license, indicate your decision by deleting the provisions
  32. * above and replace them with the notice and other provisions required by GPL
  33. * as set out in the file called "GPLHEADER" included in this distribution. If
  34. * you do not delete the provisions above, a recipient may use your version of
  35. * this file under the terms of either the MIT license or GPL.
  36. *
  37. * This License is also included in this distribution in the file called
  38. * "MIT_COPYING".
  39. *
  40. *****************************************************************************/
  41. #include <linux/delay.h>
  42. #include <linux/interrupt.h>
  43. #include <linux/module.h>
  44. #include <linux/device.h>
  45. #include <linux/gfp.h>
  46. #include <linux/dma-mapping.h>
  47. #include <linux/pci.h>
  48. #include <linux/pm.h>
  49. #include <linux/mod_devicetable.h>
  50. #include <linux/workqueue.h>
  51. #include <linux/version.h>
  52. #include <linux/platform_device.h>
  53. #include <hwdefs/vha_cr_gyrus.h>
  54. #include <hwdefs/nn_sys_cr_gyrus.h>
  55. #include <hwdefs/gyrus_system.h>
  56. #define DEVICE_NAME "3NXF_plat"
  57. #include <nexef_plat.h>
  58. /* NNPU needed includes */
  59. #define SUPPORT_RGX
  60. #include <tc_drv.h>
  61. //region Defines
  62. /*
  63. * We don't support Apollo base board here, but to have a
  64. * proper error message if someone use the wrong baseboard,
  65. * we have a little bit of code to report it.
  66. *
  67. * For that we need to have the Apollo PCI IDs
  68. */
  69. #define PCI_APOLLO_VENDOR_ID (0x1010)
  70. #define PCI_APOLLO_DEVICE_ID (0x1CF2)
  71. #define IS_APOLLO_DEVICE(devid) ((devid) == PCI_APOLLO_DEVICE_ID)
  72. #define PCI_SIRIUS_VENDOR_ID (0x1AEE)
  73. #define PCI_SIRIUS_DEVICE_ID (0x1020)
  74. #define IS_SIRIUS_DEVICE(devid) ((devid) == PCI_SIRIUS_DEVICE_ID)
  75. /*
  76. * from Odin Lite TRM rev 1.0.88
  77. */
  78. #define PCI_ODIN_VENDOR_ID (0x1AEE)
  79. #define PCI_ODIN_DEVICE_ID (0x1010)
  80. #define IS_ODIN_DEVICE(devid) ((devid) == PCI_ODIN_DEVICE_ID)
  81. /* Odin - System control register bar */
  82. #define PCI_ODIN_SYS_CTRL_REGS_BAR (0)
  83. #define PCI_ODIN_SYS_CTRL_BASE_OFFSET (0x0000)
  84. /* srs_core */
  85. #define PCI_ODIN_CORE_ID (0x0000)
  86. #define PCI_ODIN_CORE_REVISION (0x0004)
  87. #define PCI_ODIN_CORE_CHANGE_SET (0x0008)
  88. #define PCI_ODIN_CORE_USER_ID (0x000C)
  89. #define PCI_ODIN_CORE_USER_BUILD (0x0010)
  90. /* Resets */
  91. #define PCI_ODIN_CORE_INTERNAL_RESETN (0x0080)
  92. #define PCI_ODIN_CORE_EXTERNAL_RESETN (0x0084)
  93. #define PCI_ODIN_CORE_EXTERNAL_RESET (0x0088)
  94. #define PCI_ODIN_CORE_INTERNAL_AUTO_RESETN (0x008C)
  95. /* Clock */
  96. #define PCI_ODIN_CORE_CLK_GEN_RESET (0x0090)
  97. /* Interrupts */
  98. #define PCI_ODIN_CORE_INTERRUPT_STATUS (0x0100)
  99. #define PCI_ODIN_CORE_INTERRUPT_ENABLE (0x0104)
  100. #define PCI_ODIN_CORE_INTERRUPT_CLR (0x010C)
  101. #define PCI_ODIN_CORE_INTERRUPT_TEST (0x0110)
  102. /* GPIOs */
  103. #define PCI_ODIN_CORE_NUM_GPIO (0x0180)
  104. #define PCI_ODIN_CORE_GPIO_EN (0x0184)
  105. #define PCI_ODIN_CORE_GPIO (0x0188)
  106. /* DUT Ctrl */
  107. #define PCI_ODIN_CORE_NUM_DUT_CTRL (0x0190)
  108. #define PCI_ODIN_CORE_DUT_CTRL1 (0x0194)
  109. #define PCI_ODIN_CORE_DUT_CTRL2 (0x0198)
  110. #define PCI_ODIN_CORE_NUM_DUT_STAT (0x019C)
  111. #define PCI_ODIN_CORE_DUT_STAT1 (0x01A0)
  112. #define PCI_ODIN_CORE_DUT_STAT2 (0x01A4)
  113. /* LEDs! */
  114. #define PCI_ODIN_CORE_DASH_LEDS (0x01A8)
  115. /* Core stuff */
  116. #define PCI_ODIN_CORE_CORE_STATUS (0x0200)
  117. #define PCI_ODIN_CORE_CORE_CONTROL (0x0204)
  118. #define PCI_ODIN_CORE_REG_BANK_STATUS (0x0208)
  119. #define PCI_ODIN_CORE_MMCM_LOCK_STATUS (0x020C)
  120. #define PCI_ODIN_CORE_GIST_STATUS (0x0210)
  121. #define PCI_ODIN_MMCM_LOCK_STATUS_DUT_CORE (1 << 0)
  122. #define PCI_ODIN_MMCM_LOCK_STATUS_DUT_IF (1 << 1)
  123. /* core bits definitions */
  124. #define INTERNAL_RESET_INTERNAL_RESETN_PIKE (1 << 7)
  125. #define EXTERNAL_RESET_EXTERNAL_RESETN_SPI (1 << 1)
  126. #define EXTERNAL_RESET_EXTERNAL_RESETN_DUT (1 << 0)
  127. #define EXTERNAL_RESET_DUT_CORE_MMCM (1 << 1)
  128. #define DUT_CTRL1_DUT_MST_OFFSET (1 << 31)
  129. #define ODIN_CORE_CONTROL_DUT_OFFSET_SHIFT (24)
  130. #define ODIN_CORE_CONTROL_DUT_OFFSET_MASK (0x7 << ODIN_CORE_CONTROL_DUT_OFFSET_SHIFT)
  131. /* interrupt bits definitions */
  132. #define INT_INTERRUPT_MASTER_ENABLE (1 << 31)
  133. #define INT_INTERRUPT_DUT0 (1 << 0)
  134. #define INT_INTERRUPT_PDP (1 << 1)
  135. #define INT_INTERRUPT_DUT1 (1 << 9)
  136. /* odn_clk_blk */
  137. #define PCI_ODIN_CLK_BLK_DUT_CORE_CLK_OUT_DIV1 (0x0020)
  138. #define PCI_ODIN_CLK_BLK_DUT_CORE_CLK_OUT_DIV2 (0x0024)
  139. #define PCI_ODIN_CLK_BLK_DUT_CORE_CLK_OUT_DIV3 (0x001C)
  140. #define PCI_ODIN_CLK_BLK_DUT_REG_CLK_OUT_DIV1 (0x0028)
  141. #define PCI_ODIN_CLK_BLK_DUT_REG_CLK_OUT_DIV2 (0x002C)
  142. #define PCI_ODIN_CLK_BLK_DUT_CORE_CLK_MULT1 (0x0050)
  143. #define PCI_ODIN_CLK_BLK_DUT_CORE_CLK_MULT2 (0x0054)
  144. #define PCI_ODIN_CLK_BLK_DUT_CORE_CLK_MULT3 (0x004C)
  145. #define PCI_ODIN_CLK_BLK_DUT_CORE_CLK_IN_DIV (0x0058)
  146. #define PCI_ODIN_CLK_BLK_DUT_SYS_CLK_OUT_DIV1 (0x0220)
  147. #define PCI_ODIN_CLK_BLK_DUT_SYS_CLK_OUT_DIV2 (0x0224)
  148. #define PCI_ODIN_CLK_BLK_DUT_SYS_CLK_OUT_DIV3 (0x021C)
  149. #define PCI_ODIN_CLK_BLK_DUT_MEM_CLK_OUT_DIV1 (0x0228)
  150. #define PCI_ODIN_CLK_BLK_DUT_MEM_CLK_OUT_DIV2 (0x022C)
  151. #define PCI_ODIN_CLK_BLK_DUT_SYS_CLK_MULT1 (0x0250)
  152. #define PCI_ODIN_CLK_BLK_DUT_SYS_CLK_MULT2 (0x0254)
  153. #define PCI_ODIN_CLK_BLK_DUT_SYS_CLK_MULT3 (0x024C)
  154. #define PCI_ODIN_CLK_BLK_DUT_SYS_CLK_IN_DIV (0x0258)
  155. #define PCI_ODIN_CLK_BLK_PDP_PIXEL_CLK_OUT_DIV1 (0x0620)
  156. #define PCI_ODIN_CLK_BLK_PDP_PIXEL_CLK_OUT_DIV2 (0x0624)
  157. #define PCI_ODIN_CLK_BLK_PDP_PIXEL_CLK_OUT_DIV3 (0x061C)
  158. #define PCI_ODIN_CLK_BLK_PDP_MEM_CLK_OUT_DIV1 (0x0628)
  159. #define PCI_ODIN_CLK_BLK_PDP_MEM_CLK_OUT_DIV2 (0x062C)
  160. #define PCI_ODIN_CLK_BLK_PDP_PIXEL_CLK_MULT1 (0x0650)
  161. #define PCI_ODIN_CLK_BLK_PDP_PIXEL_CLK_MULT2 (0x0654)
  162. #define PCI_ODIN_CLK_BLK_PDP_PIXEL_CLK_MULT3 (0x064C)
  163. #define PCI_ODIN_CLK_BLK_PDP_PIXEL_CLK_IN_DIV (0x0658)
  164. #define PCI_ODIN_CORE_REG_SIZE (0x1000)
  165. /* Odin - Device Under Test (DUT) register bar */
  166. #define PCI_ODIN_DUT_REGS_BAR (2)
  167. /* Odin - Device Under Test (DUT) memory bar */
  168. #define PCI_ODIN_DUT_MEM_BAR (4)
  169. /* Odin clock related infos */
  170. #define PCI_ODIN_INPUT_CLOCK_SPEED (100000000U)
  171. #define PCI_ODIN_INPUT_CLOCK_SPEED_MIN (10000000U)
  172. #define PCI_ODIN_INPUT_CLOCK_SPEED_MAX (933000000U)
  173. #define PCI_ODIN_OUTPUT_CLOCK_SPEED_MIN (4690000U)
  174. #define PCI_ODIN_OUTPUT_CLOCK_SPEED_MAX (933000000U)
  175. #define PCI_ODIN_VCO_MIN (600000000U)
  176. #define PCI_ODIN_VCO_MAX (1440000000U)
  177. #define PCI_ODIN_PFD_MIN (10000000U)
  178. #define PCI_ODIN_PFD_MAX (500000000U)
  179. /*
  180. * Max values that can be set in DRP registers771
  181. */
  182. #define PCI_ODIN_OREG_VALUE_MAX (126.875f)
  183. #define PCI_ODIN_MREG_VALUE_MAX (126.875f)
  184. #define PCI_ODIN_DREG_VALUE_MAX (126U)
  185. /*
  186. * DUT core clock input divider, multiplier and out divider.
  187. */
  188. #define ODN_DUT_CORE_CLK_OUT_DIVIDER1 (0x0028)
  189. #define ODN_DUT_CORE_CLK_OUT_DIVIDER1_HI_TIME_MASK (0x00000FC0U)
  190. #define ODN_DUT_CORE_CLK_OUT_DIVIDER1_HI_TIME_SHIFT (6)
  191. #define ODN_DUT_CORE_CLK_OUT_DIVIDER1_LO_TIME_MASK (0x0000003FU)
  192. #define ODN_DUT_CORE_CLK_OUT_DIVIDER1_LO_TIME_SHIFT (0)
  193. #define ODN_DUT_CORE_CLK_OUT_DIVIDER2 (0x002C)
  194. #define ODN_DUT_CORE_CLK_OUT_DIVIDER2_EDGE_MASK (0x00000080U)
  195. #define ODN_DUT_CORE_CLK_OUT_DIVIDER2_EDGE_SHIFT (7)
  196. #define ODN_DUT_CORE_CLK_OUT_DIVIDER2_NOCOUNT_MASK (0x00000040U)
  197. #define ODN_DUT_CORE_CLK_OUT_DIVIDER2_NOCOUNT_SHIFT (6)
  198. #define ODN_DUT_CORE_CLK_MULTIPLIER1 (0x0050)
  199. #define ODN_DUT_CORE_CLK_MULTIPLIER1_HI_TIME_MASK (0x00000FC0U)
  200. #define ODN_DUT_CORE_CLK_MULTIPLIER1_HI_TIME_SHIFT (6)
  201. #define ODN_DUT_CORE_CLK_MULTIPLIER1_LO_TIME_MASK (0x0000003FU)
  202. #define ODN_DUT_CORE_CLK_MULTIPLIER1_LO_TIME_SHIFT (0)
  203. #define ODN_DUT_CORE_CLK_MULTIPLIER2 (0x0054)
  204. #define ODN_DUT_CORE_CLK_MULTIPLIER2_FRAC_MASK (0x00007000U)
  205. #define ODN_DUT_CORE_CLK_MULTIPLIER2_FRAC_SHIFT (12)
  206. #define ODN_DUT_CORE_CLK_MULTIPLIER2_FRAC_EN_MASK (0x00000800U)
  207. #define ODN_DUT_CORE_CLK_MULTIPLIER2_FRAC_EN_SHIFT (11)
  208. #define ODN_DUT_CORE_CLK_MULTIPLIER2_EDGE_MASK (0x00000080U)
  209. #define ODN_DUT_CORE_CLK_MULTIPLIER2_EDGE_SHIFT (7)
  210. #define ODN_DUT_CORE_CLK_MULTIPLIER2_NOCOUNT_MASK (0x00000040U)
  211. #define ODN_DUT_CORE_CLK_MULTIPLIER2_NOCOUNT_SHIFT (6)
  212. #define ODN_DUT_CORE_CLK_IN_DIVIDER1 (0x0058)
  213. #define ODN_DUT_CORE_CLK_IN_DIVIDER1_EDGE_MASK (0x00002000U)
  214. #define ODN_DUT_CORE_CLK_IN_DIVIDER1_EDGE_SHIFT (13)
  215. #define ODN_DUT_CORE_CLK_IN_DIVIDER1_NOCOUNT_MASK (0x00001000U)
  216. #define ODN_DUT_CORE_CLK_IN_DIVIDER1_NOCOUNT_SHIFT (12)
  217. #define ODN_DUT_CORE_CLK_IN_DIVIDER1_HI_TIME_MASK (0x00000FC0U)
  218. #define ODN_DUT_CORE_CLK_IN_DIVIDER1_HI_TIME_SHIFT (6)
  219. #define ODN_DUT_CORE_CLK_IN_DIVIDER1_LO_TIME_MASK (0x0000003FU)
  220. #define ODN_DUT_CORE_CLK_IN_DIVIDER1_LO_TIME_SHIFT (0)
  221. /*
  222. * DUT interface clock input divider, multiplier and out divider.
  223. */
  224. #define ODN_DUT_IFACE_CLK_OUT_DIVIDER1 (0x0220)
  225. #define ODN_DUT_IFACE_CLK_OUT_DIVIDER1_HI_TIME_MASK (0x00000FC0U)
  226. #define ODN_DUT_IFACE_CLK_OUT_DIVIDER1_HI_TIME_SHIFT (6)
  227. #define ODN_DUT_IFACE_CLK_OUT_DIVIDER1_LO_TIME_MASK (0x0000003FU)
  228. #define ODN_DUT_IFACE_CLK_OUT_DIVIDER1_LO_TIME_SHIFT (0)
  229. #define ODN_DUT_IFACE_CLK_OUT_DIVIDER2 (0x0224)
  230. #define ODN_DUT_IFACE_CLK_OUT_DIVIDER2_EDGE_MASK (0x00000080U)
  231. #define ODN_DUT_IFACE_CLK_OUT_DIVIDER2_EDGE_SHIFT (7)
  232. #define ODN_DUT_IFACE_CLK_OUT_DIVIDER2_NOCOUNT_MASK (0x00000040U)
  233. #define ODN_DUT_IFACE_CLK_OUT_DIVIDER2_NOCOUNT_SHIFT (6)
  234. #define ODN_DUT_IFACE_CLK_MULTIPLIER1 (0x0250)
  235. #define ODN_DUT_IFACE_CLK_MULTIPLIER1_HI_TIME_MASK (0x00000FC0U)
  236. #define ODN_DUT_IFACE_CLK_MULTIPLIER1_HI_TIME_SHIFT (6)
  237. #define ODN_DUT_IFACE_CLK_MULTIPLIER1_LO_TIME_MASK (0x0000003FU)
  238. #define ODN_DUT_IFACE_CLK_MULTIPLIER1_LO_TIME_SHIFT (0)
  239. #define ODN_DUT_IFACE_CLK_MULTIPLIER2 (0x0254)
  240. #define ODN_DUT_IFACE_CLK_MULTIPLIER2_FRAC_MASK (0x00007000U)
  241. #define ODN_DUT_IFACE_CLK_MULTIPLIER2_FRAC_SHIFT (12)
  242. #define ODN_DUT_IFACE_CLK_MULTIPLIER2_FRAC_EN_MASK (0x00000800U)
  243. #define ODN_DUT_IFACE_CLK_MULTIPLIER2_FRAC_EN_SHIFT (11)
  244. #define ODN_DUT_IFACE_CLK_MULTIPLIER2_EDGE_MASK (0x00000080U)
  245. #define ODN_DUT_IFACE_CLK_MULTIPLIER2_EDGE_SHIFT (7)
  246. #define ODN_DUT_IFACE_CLK_MULTIPLIER2_NOCOUNT_MASK (0x00000040U)
  247. #define ODN_DUT_IFACE_CLK_MULTIPLIER2_NOCOUNT_SHIFT (6)
  248. #define ODN_DUT_IFACE_CLK_IN_DIVIDER1 (0x0258)
  249. #define ODN_DUT_IFACE_CLK_IN_DIVIDER1_EDGE_MASK (0x00002000U)
  250. #define ODN_DUT_IFACE_CLK_IN_DIVIDER1_EDGE_SHIFT (13)
  251. #define ODN_DUT_IFACE_CLK_IN_DIVIDER1_NOCOUNT_MASK (0x00001000U)
  252. #define ODN_DUT_IFACE_CLK_IN_DIVIDER1_NOCOUNT_SHIFT (12)
  253. #define ODN_DUT_IFACE_CLK_IN_DIVIDER1_HI_TIME_MASK (0x00000FC0U)
  254. #define ODN_DUT_IFACE_CLK_IN_DIVIDER1_HI_TIME_SHIFT (6)
  255. #define ODN_DUT_IFACE_CLK_IN_DIVIDER1_LO_TIME_MASK (0x0000003FU)
  256. #define ODN_DUT_IFACE_CLK_IN_DIVIDER1_LO_TIME_SHIFT (0)
  257. #define NEXEF_ROGUE_REG_BAR (PCI_ODIN_DUT_REGS_BAR)
  258. #define NEXEF_ROGUE_REG_SIZE (_RGXREG_SIZE)
  259. #define NEXEF_ROGUE_REG_OFFSET (_RGXREG_START)
  260. #define NEXEF_NNPU_PDEV_NAME "rogue-regs"
  261. #define NEXEF_NNA_REG_BAR (PCI_ODIN_DUT_REGS_BAR)
  262. #define NEXEF_NNA_REG_SIZE (_REG_NNA_SIZE)
  263. #define NEXEF_NNA_REG_OFFSET (_REG_NNA_START)
  264. #define NEXEF_NNA_PDEV_NAME "nna-regs"
  265. #define NEXEF_NNSYS_REG_BAR (PCI_ODIN_DUT_REGS_BAR)
  266. #define NEXEF_NNSYS_REG_SIZE (_REG_NNSYS_SIZE)
  267. #define NEXEF_NNSYS_REG_OFFSET (_REG_NNSYS_START)
  268. #define NEXEF_NNPU_HEAP_SIZE (128*1024*1024)
  269. //endregion Defines
  270. //region Struct and Prototypes
  271. static const struct pci_device_id pci_pci_ids[] = {
  272. /* We don't support the Apollo/TCF board, but we request for it to display a nice
  273. * friendly error message
  274. */
  275. { PCI_DEVICE(PCI_APOLLO_VENDOR_ID, PCI_APOLLO_DEVICE_ID), },
  276. /* There is currently no plan to use the Orion/Sirius platform, but I still can use
  277. * it to do some test. It is really close to the Odin/Sleipnir platform
  278. */
  279. { PCI_DEVICE(PCI_SIRIUS_VENDOR_ID, PCI_SIRIUS_DEVICE_ID), },
  280. { PCI_DEVICE(PCI_ODIN_VENDOR_ID, PCI_ODIN_DEVICE_ID), },
  281. { 0, }
  282. };
  283. MODULE_DEVICE_TABLE(pci, pci_pci_ids);
  284. /* We need the NNA reg bank because the secure bit is currently not handled by the NNA driver */
  285. enum { CORE_REG_BANK = 0, NNSYS_REG_BANK,
  286. NNA_REG_BANK,
  287. REG_BANK_COUNT /* Must be the last */};
  288. struct mem_region {
  289. resource_size_t base;
  290. resource_size_t size;
  291. };
  292. struct platdev_export_info {
  293. /* General infos */
  294. struct mem_region dut_mem;
  295. /* Rogue export infos */
  296. int rogue_mem_mode;
  297. struct platform_device *rogue_pdev;
  298. struct mem_region rogue_heap_mem;
  299. struct mem_region rogue_pdp_heap_mem;
  300. /* NNA export infos */
  301. struct platform_device *nna_pdev;
  302. struct mem_region nna_heap_mem;
  303. };
  304. struct nexefdrv_prvdata {
  305. int irq;
  306. struct {
  307. int bar;
  308. unsigned long addr;
  309. unsigned long size;
  310. void __iomem *km_addr;
  311. } reg_bank[REG_BANK_COUNT];
  312. struct platdev_export_info plat_exports;
  313. struct pci_dev *pci_dev;
  314. };
  315. struct img_pci_driver {
  316. struct pci_dev *pci_dev;
  317. struct pci_driver pci_driver;
  318. struct delayed_work irq_work;
  319. };
  320. static ulong maxmapsizeMB = (sizeof(void *) == 4) ? 400 : 1024;
  321. static int nexef_plat_probe(struct pci_dev *pci_dev,
  322. const struct pci_device_id *id);
  323. static void nexef_plat_remove(struct pci_dev *dev);
  324. static int nexef_plat_suspend(struct device *dev);
  325. static int nexef_plat_resume(struct device *dev);
  326. static SIMPLE_DEV_PM_OPS(nexef_pm_plat_ops,
  327. nexef_plat_suspend, nexef_plat_resume);
  328. static int nexef_register_rogue_plat_device(struct nexefdrv_prvdata *priv_data);
  329. static void nexef_unregister_rogue_plat_device(struct nexefdrv_prvdata *priv_data);
  330. static int nexef_register_nna_plat_device(struct nexefdrv_prvdata *priv_data);
  331. static void nexef_unregister_nna_plat_device(struct nexefdrv_prvdata *priv_data);
  332. static int nexef_nnsys_init(struct pci_dev *pci_dev, struct nexefdrv_prvdata *priv_data);
  333. static void nexef_nnsys_unlock(struct nexefdrv_prvdata *priv_data);
  334. static void nexef_nnsys_configure(struct nexefdrv_prvdata *priv_data);
  335. static int nexef_nna_init(struct pci_dev *pci_dev, struct nexefdrv_prvdata *priv_data);
  336. static void nexef_nna_unlock(struct nexefdrv_prvdata *priv_data);
  337. //endregion Struct and Prototypes
  338. //region Kernel module parameters
  339. /* Parameters applicable when using bus master mode */
  340. static unsigned long contig_phys_start;
  341. module_param(contig_phys_start, ulong, 0444);
  342. MODULE_PARM_DESC(contig_phys_start, "Physical address of start of contiguous region");
  343. static uint32_t contig_size;
  344. module_param(contig_size, uint, 0444);
  345. MODULE_PARM_DESC(contig_size, "Size of contiguous region: takes precedence over any PCI based memory");
  346. static unsigned long pci_size;
  347. module_param(pci_size, ulong, 0444);
  348. MODULE_PARM_DESC(pci_size, "physical size in bytes. when 0 (the default), use all memory in the PCI bar");
  349. static unsigned long pci_offset;
  350. module_param(pci_offset, ulong, 0444);
  351. MODULE_PARM_DESC(pci_offset, "offset from PCI bar start. (default: 0)");
  352. #ifdef CONFIG_SET_FPGA_CLOCK
  353. static int odin_fpga_dut_clock = 25000000;
  354. module_param(odin_fpga_dut_clock, int, 0444);
  355. MODULE_PARM_DESC(odin_fpga_dut_clock, "DUT clock speed");
  356. static int odin_fpga_mem_clock = 25000000;
  357. module_param(odin_fpga_mem_clock, int, 0444);
  358. MODULE_PARM_DESC(odin_fpga_mem_clock, "Memory clock speed");
  359. #endif
  360. static ssize_t info_show(struct device_driver *drv, char *buf)
  361. {
  362. return sprintf(buf, "PCI 3NX-F Platform driver version : N/A\n");
  363. }
  364. static DRIVER_ATTR_RO(info);
  365. static struct attribute *drv_attrs[] = {
  366. &driver_attr_info.attr,
  367. NULL
  368. };
  369. ATTRIBUTE_GROUPS(drv);
  370. static struct img_pci_driver nexef_pci_drv = {
  371. .pci_driver = {
  372. .name = "nexef_plat_pci",
  373. .id_table = pci_pci_ids,
  374. .probe = nexef_plat_probe,
  375. .remove = nexef_plat_remove,
  376. .driver = {
  377. .groups = drv_groups,
  378. .pm = &nexef_pm_plat_ops,
  379. }
  380. },
  381. };
  382. //endregion Kernel module parameters
  383. //region Utility functions
  384. /*
  385. * __readreg32 - Generic PCI bar read functions
  386. */
  387. static inline unsigned int __readreg32(struct nexefdrv_prvdata *data,
  388. int bank, unsigned long offset)
  389. {
  390. void __iomem *reg = (void __iomem *)(data->reg_bank[bank].km_addr +
  391. offset);
  392. return ioread32(reg);
  393. }
  394. /*
  395. * __writereg32 - Generic PCI bar write functions
  396. */
  397. static inline void __writereg32(struct nexefdrv_prvdata *data,
  398. int bank, unsigned long offset, int val)
  399. {
  400. void __iomem *reg = (void __iomem *)(data->reg_bank[bank].km_addr +
  401. offset);
  402. iowrite32(val, reg);
  403. }
  404. /*
  405. * __readreg64 - Generic PCI bar read functions
  406. */
  407. static inline uint64_t __readreg64(struct nexefdrv_prvdata *data,
  408. int bank, unsigned long offset)
  409. {
  410. void __iomem *reg = (void __iomem *)(data->reg_bank[bank].km_addr +
  411. offset);
  412. return (uint64_t)ioread32(reg) | ((uint64_t)ioread32(reg + 4) << 32);
  413. }
  414. /*
  415. * __writereg64 - Generic PCI bar write functions
  416. */
  417. static inline void __writereg64(struct nexefdrv_prvdata *data,
  418. int bank, unsigned long offset, uint64_t val)
  419. {
  420. void __iomem *reg = (void __iomem *)(data->reg_bank[bank].km_addr +
  421. offset);
  422. iowrite32(val & 0xFFFFFFFF, reg);
  423. iowrite32(val >> 32, reg + 4);
  424. }
  425. //endregion Utility functions
  426. //region Odin handling functions
  427. /*
  428. * odin_core_writereg32 - Write to Odin control registers
  429. */
  430. static inline void odin_core_writereg32(struct nexefdrv_prvdata *data,
  431. unsigned long offset, int val)
  432. {
  433. __writereg32(data, CORE_REG_BANK, offset, val);
  434. }
  435. /*
  436. * odin_core_readreg32 - Read Odin control registers
  437. */
  438. static inline unsigned int odin_core_readreg32(struct nexefdrv_prvdata *data,
  439. unsigned long offset)
  440. {
  441. return __readreg32(data, CORE_REG_BANK, offset);
  442. }
  443. static inline unsigned int odin_core_polreg32(struct nexefdrv_prvdata *data, unsigned long offset, uint32_t mask)
  444. {
  445. int timeout = 50;
  446. uint32_t read_value;
  447. while(timeout > 0)
  448. {
  449. read_value = odin_core_readreg32(data, offset) & mask;
  450. if (read_value != 0)
  451. break;
  452. msleep(20);
  453. timeout--;
  454. }
  455. if (timeout == 0)
  456. {
  457. dev_err(&data->pci_dev->dev, " %s(%08lX, %08X) timeout\n", __func__, offset, mask);
  458. return -ETIME;
  459. }
  460. return 0;
  461. }
  462. static void odin_set_mem_mode_lma(struct nexefdrv_prvdata *data)
  463. {
  464. uint32_t val;
  465. /* Enable memory offset to be applied to DUT and PDP1 */
  466. /*
  467. * 31: Set Enable DUT Offset
  468. * 11: JTAG EN
  469. * 9 CORE CLK DIV4
  470. * 4 PLL_BYPASS
  471. */
  472. odin_core_writereg32(data, PCI_ODIN_CORE_DUT_CTRL1, 0x80000A10);
  473. /* Apply memory offset to GPU and PDP1 to point to DDR memory.
  474. * Enable HDMI.
  475. */
  476. val = (0x4 << 24) | /* DUT_OFFSET */
  477. (0x4 << 16) | /* PDP1_OFFSET */
  478. (0x2 << 10) | /* HDMI Module Enable */
  479. (0x1 << 13); /* MCU Communicator */
  480. odin_core_writereg32(data, PCI_ODIN_CORE_CORE_CONTROL, val);
  481. }
  482. /*
  483. * reset_dut - Reset the Device Under Test
  484. */
  485. static void reset_dut(struct nexefdrv_prvdata *data)
  486. {
  487. uint32_t internal_rst = odin_core_readreg32(data, PCI_ODIN_CORE_INTERNAL_RESETN);
  488. uint32_t external_rst = odin_core_readreg32(data, PCI_ODIN_CORE_EXTERNAL_RESETN);
  489. dev_dbg(&data->pci_dev->dev, "going to reset DUT fpga!\n");
  490. odin_core_writereg32(data, PCI_ODIN_CORE_INTERNAL_RESETN,
  491. internal_rst & ~(INTERNAL_RESET_INTERNAL_RESETN_PIKE));
  492. odin_core_writereg32(data, PCI_ODIN_CORE_EXTERNAL_RESETN,
  493. external_rst & ~(EXTERNAL_RESET_EXTERNAL_RESETN_DUT));
  494. udelay(50); /* arbitrary delays, just in case! */
  495. odin_core_writereg32(data, PCI_ODIN_CORE_INTERNAL_RESETN, internal_rst);
  496. odin_core_writereg32(data, PCI_ODIN_CORE_EXTERNAL_RESETN, external_rst);
  497. udelay(50);
  498. nexef_nnsys_unlock(data);
  499. /* Call the NNA unlock function to make sure NNA driver can access it without any issue
  500. * The security bit is reverted after each reset.
  501. */
  502. nexef_nna_unlock(data);
  503. dev_dbg(&data->pci_dev->dev, "DUT fpga reset done!\n");
  504. }
  505. #ifdef CONFIG_SET_FPGA_CLOCK
  506. /*
  507. * Returns the divider group register fields for the specified counter value.
  508. * See Xilinx Application Note xapp888.
  509. */
  510. static void odin_mmcm_reg_param_calc(uint32_t value, uint32_t *low, uint32_t *high,
  511. uint32_t *edge, uint32_t *no_count)
  512. {
  513. if (value == 1U) {
  514. *no_count = 1U;
  515. *edge = 0;
  516. *high = 0;
  517. *low = 0;
  518. } else {
  519. *no_count = 0;
  520. *edge = value % 2U;
  521. *high = value >> 1;
  522. *low = (value + *edge) >> 1U;
  523. }
  524. }
  525. /* GPU clock functions use these macros: */
  526. #define REG_FIELD_GET(v, str) \
  527. (uint32_t)(((v) & (s##_MASK)) >> (s##_SHIFT))
  528. #define REG_FIELD_SET(v, f, str) \
  529. v = (uint32_t)(((v) & (uint32_t)~(str##_MASK)) | \
  530. (uint32_t)(((f) << (str##_SHIFT)) & (str##_MASK)))
  531. /*
  532. * Returns the MMCM Input Divider, FB Multiplier and Output Divider values for
  533. * the specified input frequency and target output frequency.
  534. * Function doesn't support fractional values for multiplier and output divider
  535. * As per Xilinx 7 series FPGAs clocking resources user guide, aims for highest
  536. * VCO and smallest D and M.
  537. * Configured for Xilinx Virtex7 speed grade 2.
  538. */
  539. static int odin_mmcm_counter_calc(struct device *dev,
  540. uint32_t freq_input, uint32_t freq_output,
  541. uint32_t *d, uint32_t *m, uint32_t *o)
  542. {
  543. uint32_t d_min, d_max;
  544. uint32_t m_min, m_max, m_ideal;
  545. uint32_t d_cur, m_cur, o_cur;
  546. uint32_t best_diff, d_best, m_best, o_best;
  547. /*
  548. * Check specified input frequency is within range
  549. */
  550. if (freq_input < PCI_ODIN_INPUT_CLOCK_SPEED_MIN) {
  551. dev_err(dev, "Input frequency (%u hz) below minimum supported value (%u hz)\n",
  552. freq_input, PCI_ODIN_INPUT_CLOCK_SPEED_MIN);
  553. return -EINVAL;
  554. }
  555. if (freq_input > PCI_ODIN_INPUT_CLOCK_SPEED_MAX) {
  556. dev_err(dev, "Input frequency (%u hz) above maximum supported value (%u hz)\n",
  557. freq_input, PCI_ODIN_INPUT_CLOCK_SPEED_MAX);
  558. return -EINVAL;
  559. }
  560. /*
  561. * Check specified target frequency is within range
  562. */
  563. if (freq_output < PCI_ODIN_OUTPUT_CLOCK_SPEED_MIN) {
  564. dev_err(dev, "Output frequency (%u hz) below minimum supported value (%u hz)\n",
  565. freq_input, PCI_ODIN_OUTPUT_CLOCK_SPEED_MIN);
  566. return -EINVAL;
  567. }
  568. if (freq_output > PCI_ODIN_OUTPUT_CLOCK_SPEED_MAX) {
  569. dev_err(dev, "Output frequency (%u hz) above maximum supported value (%u hz)\n",
  570. freq_output, PCI_ODIN_OUTPUT_CLOCK_SPEED_MAX);
  571. return -EINVAL;
  572. }
  573. /*
  574. * Calculate min and max for Input Divider.
  575. * Refer Xilinx 7 series FPGAs clocking resources user guide
  576. * equation 3-6 and 3-7
  577. */
  578. d_min = DIV_ROUND_UP(freq_input, PCI_ODIN_PFD_MAX);
  579. d_max = min(freq_input/PCI_ODIN_PFD_MIN, (uint32_t)PCI_ODIN_DREG_VALUE_MAX);
  580. /*
  581. * Calculate min and max for Input Divider.
  582. * Refer Xilinx 7 series FPGAs clocking resources user guide.
  583. * equation 3-8 and 3-9
  584. */
  585. m_min = DIV_ROUND_UP((PCI_ODIN_VCO_MIN * d_min), freq_input);
  586. m_max = min(((PCI_ODIN_VCO_MAX * d_max) / freq_input),
  587. (uint32_t)PCI_ODIN_MREG_VALUE_MAX);
  588. for (d_cur = d_min; d_cur <= d_max; d_cur++) {
  589. /*
  590. * Refer Xilinx 7 series FPGAs clocking resources user guide.
  591. * equation 3-10
  592. */
  593. m_ideal = min(((d_cur * PCI_ODIN_VCO_MAX)/freq_input), m_max);
  594. for (m_cur = m_ideal; m_cur >= m_min; m_cur -= 1) {
  595. /**
  596. * Skip if VCO for given 'm' and 'd' value is not an
  597. * integer since fractional component is not supported
  598. */
  599. if (((freq_input * m_cur) % d_cur) != 0)
  600. continue;
  601. /**
  602. * Skip if divider for given 'm' and 'd' value is not
  603. * an integer since fractional component is not
  604. * supported
  605. */
  606. if ((freq_input * m_cur) % (d_cur * freq_output) != 0)
  607. continue;
  608. /**
  609. * Calculate output divider value.
  610. */
  611. o_cur = (freq_input * m_cur)/(d_cur * freq_output);
  612. *d = d_cur;
  613. *m = m_cur;
  614. *o = o_cur;
  615. return 0;
  616. }
  617. }
  618. /* Failed to find exact optimal solution with high VCO. Brute-force find a suitable config,
  619. * again prioritising high VCO, to get lowest jitter */
  620. d_min = 1; d_max = (uint32_t)PCI_ODIN_DREG_VALUE_MAX;
  621. m_min = 1; m_max = (uint32_t)PCI_ODIN_MREG_VALUE_MAX;
  622. best_diff = 0xFFFFFFFF;
  623. for (d_cur = d_min; d_cur <= d_max; d_cur++) {
  624. for (m_cur = m_max; m_cur >= m_min; m_cur -= 1) {
  625. uint32_t pfd, vco, o_avg, o_min, o_max;
  626. pfd = freq_input / d_cur;
  627. vco = pfd * m_cur;
  628. if (pfd < PCI_ODIN_PFD_MIN)
  629. continue;
  630. if (pfd > PCI_ODIN_PFD_MAX)
  631. continue;
  632. if (vco < PCI_ODIN_VCO_MIN)
  633. continue;
  634. if (vco > PCI_ODIN_VCO_MAX)
  635. continue;
  636. /* A range of -1/+3 around o_avg gives us 100kHz granularity. It can be extended further. */
  637. o_avg = vco / freq_output;
  638. o_min = (o_avg >= 2) ? (o_avg - 1) : 1;
  639. o_max = o_avg + 3;
  640. if (o_max > (uint32_t)PCI_ODIN_OREG_VALUE_MAX)
  641. o_max = (uint32_t)PCI_ODIN_OREG_VALUE_MAX;
  642. for (o_cur = o_min; o_cur <= o_max; o_cur++) {
  643. uint32_t freq_cur, diff_cur;
  644. freq_cur = vco / o_cur;
  645. if (freq_cur > freq_output)
  646. continue;
  647. diff_cur = freq_output - freq_cur;
  648. if (diff_cur == 0) {
  649. /* Found an exact match */
  650. *d = d_cur;
  651. *m = m_cur;
  652. *o = o_cur;
  653. return 0;
  654. }
  655. if (diff_cur < best_diff) {
  656. best_diff = diff_cur;
  657. d_best = d_cur;
  658. m_best = m_cur;
  659. o_best = o_cur;
  660. }
  661. }
  662. }
  663. }
  664. if (best_diff != 0xFFFFFFFF) {
  665. dev_warn(dev, "Odin: Found similar freq of %u Hz\n", freq_output - best_diff);
  666. *d = d_best;
  667. *m = m_best;
  668. *o = o_best;
  669. return 0;
  670. }
  671. dev_err(dev, "Odin: Unable to find integer values for d, m and o for requested frequency (%u)\n",
  672. freq_output);
  673. return -ERANGE;
  674. }
  675. static int odin_set_dut_core_clk(struct nexefdrv_prvdata *data, uint32_t input_clk, uint32_t output_clk)
  676. {
  677. int err = 0;
  678. uint32_t in_div, mul, out_div;
  679. uint32_t high_time, low_time, edge, no_count;
  680. uint32_t value;
  681. struct device *dev = &data->pci_dev->dev;
  682. err = odin_mmcm_counter_calc(dev, input_clk, output_clk, &in_div,
  683. &mul, &out_div);
  684. if (err != 0)
  685. return err;
  686. /* Put DUT into reset */
  687. odin_core_writereg32(data, PCI_ODIN_CORE_EXTERNAL_RESETN, EXTERNAL_RESET_EXTERNAL_RESETN_SPI);
  688. msleep(20);
  689. /* Put DUT Core MMCM into reset */
  690. odin_core_writereg32(data, PCI_ODIN_CORE_CLK_GEN_RESET, EXTERNAL_RESET_DUT_CORE_MMCM);
  691. msleep(20);
  692. /* Calculate the register fields for output divider */
  693. odin_mmcm_reg_param_calc(out_div, &high_time, &low_time,
  694. &edge, &no_count);
  695. /* Read-modify-write the required fields to output divider register 1 */
  696. value = odin_core_readreg32(data, PCI_ODIN_CLK_BLK_DUT_CORE_CLK_OUT_DIV1);
  697. REG_FIELD_SET(value, high_time,
  698. ODN_DUT_CORE_CLK_OUT_DIVIDER1_HI_TIME);
  699. REG_FIELD_SET(value, low_time,
  700. ODN_DUT_CORE_CLK_OUT_DIVIDER1_LO_TIME);
  701. odin_core_writereg32(data, PCI_ODIN_CLK_BLK_DUT_CORE_CLK_OUT_DIV1, value);
  702. /* Read-modify-write the required fields to output divider register 2 */
  703. value = odin_core_readreg32(data, PCI_ODIN_CLK_BLK_DUT_CORE_CLK_OUT_DIV2);
  704. REG_FIELD_SET(value, edge,
  705. ODN_DUT_CORE_CLK_OUT_DIVIDER2_EDGE);
  706. REG_FIELD_SET(value, no_count,
  707. ODN_DUT_CORE_CLK_OUT_DIVIDER2_NOCOUNT);
  708. odin_core_writereg32(data, PCI_ODIN_CLK_BLK_DUT_CORE_CLK_OUT_DIV2, value);
  709. /* Calculate the register fields for multiplier */
  710. odin_mmcm_reg_param_calc(mul, &high_time, &low_time,
  711. &edge, &no_count);
  712. /* Read-modify-write the required fields to multiplier register 1*/
  713. value = odin_core_readreg32(data, PCI_ODIN_CLK_BLK_DUT_CORE_CLK_MULT1);
  714. REG_FIELD_SET(value, high_time,
  715. ODN_DUT_CORE_CLK_MULTIPLIER1_HI_TIME);
  716. REG_FIELD_SET(value, low_time,
  717. ODN_DUT_CORE_CLK_MULTIPLIER1_LO_TIME);
  718. odin_core_writereg32(data, PCI_ODIN_CLK_BLK_DUT_CORE_CLK_MULT1, value);
  719. /* Read-modify-write the required fields to multiplier register 2 */
  720. value = odin_core_readreg32(data, PCI_ODIN_CLK_BLK_DUT_CORE_CLK_MULT2);
  721. REG_FIELD_SET(value, edge,
  722. ODN_DUT_CORE_CLK_MULTIPLIER2_EDGE);
  723. REG_FIELD_SET(value, no_count,
  724. ODN_DUT_CORE_CLK_MULTIPLIER2_NOCOUNT);
  725. odin_core_writereg32(data, PCI_ODIN_CLK_BLK_DUT_CORE_CLK_MULT2, value);
  726. /* Calculate the register fields for input divider */
  727. odin_mmcm_reg_param_calc(in_div, &high_time, &low_time,
  728. &edge, &no_count);
  729. /* Read-modify-write the required fields to input divider register 1 */
  730. value = odin_core_readreg32(data, PCI_ODIN_CLK_BLK_DUT_CORE_CLK_IN_DIV);
  731. REG_FIELD_SET(value, high_time,
  732. ODN_DUT_CORE_CLK_IN_DIVIDER1_HI_TIME);
  733. REG_FIELD_SET(value, low_time,
  734. ODN_DUT_CORE_CLK_IN_DIVIDER1_LO_TIME);
  735. REG_FIELD_SET(value, edge,
  736. ODN_DUT_CORE_CLK_IN_DIVIDER1_EDGE);
  737. REG_FIELD_SET(value, no_count,
  738. ODN_DUT_CORE_CLK_IN_DIVIDER1_NOCOUNT);
  739. odin_core_writereg32(data, PCI_ODIN_CLK_BLK_DUT_CORE_CLK_IN_DIV, value);
  740. /* Bring DUT clock MMCM out of reset */
  741. odin_core_writereg32(data, PCI_ODIN_CORE_CLK_GEN_RESET, 0);
  742. err = odin_core_polreg32(data, PCI_ODIN_CORE_MMCM_LOCK_STATUS, PCI_ODIN_MMCM_LOCK_STATUS_DUT_CORE);
  743. if (err != 0) {
  744. dev_err(dev, "MMCM failed to lock for DUT core\n");
  745. return err;
  746. }
  747. /* Bring DUT out of reset */
  748. odin_core_writereg32(data, PCI_ODIN_CORE_EXTERNAL_RESETN,
  749. EXTERNAL_RESET_EXTERNAL_RESETN_SPI | EXTERNAL_RESET_EXTERNAL_RESETN_DUT);
  750. msleep(20);
  751. dev_info(dev, "DUT core clock set-up successful at %dHz\n", output_clk);
  752. return err;
  753. }
  754. static int odin_set_dut_if_clk(struct nexefdrv_prvdata *data, uint32_t input_clk, uint32_t output_clk)
  755. {
  756. int err = 0;
  757. uint32_t in_div, mul, out_div;
  758. uint32_t high_time, low_time, edge, no_count;
  759. uint32_t value;
  760. struct device *dev = &tc->pdev->dev;
  761. err = odin_mmcm_counter_calc(dev, input_clk, output_clk,
  762. &in_div, &mul, &out_div);
  763. if (err != 0)
  764. return err;
  765. /* Put DUT into reset */
  766. iowrite32(ODN_EXTERNAL_RESETN_DUT_SPI_MASK,
  767. base + ODN_CORE_EXTERNAL_RESETN);
  768. msleep(20);
  769. /* Put DUT Core MMCM into reset */
  770. iowrite32(ODN_CLK_GEN_RESET_DUT_IF_MMCM_MASK,
  771. base + ODN_CORE_CLK_GEN_RESET);
  772. msleep(20);
  773. /* Calculate the register fields for output divider */
  774. odin_mmcm_reg_param_calc(out_div, &high_time, &low_time,
  775. &edge, &no_count);
  776. /* Read-modify-write the required fields to output divider register 1 */
  777. value = odin_core_readreg32(data, PCI_ODIN_CLK_BLK_DUT_MEM_CLK_OUT_DIV1);
  778. REG_FIELD_SET(value, high_time,
  779. ODN_DUT_IFACE_CLK_OUT_DIVIDER1_HI_TIME);
  780. REG_FIELD_SET(value, low_time,
  781. ODN_DUT_IFACE_CLK_OUT_DIVIDER1_LO_TIME);
  782. iowrite32(value, clk_blk_base + ODN_DUT_IFACE_CLK_OUT_DIVIDER1);
  783. /* Read-modify-write the required fields to output divider register 2 */
  784. value = odin_core_readreg32(data, PCI_ODIN_CLK_BLK_DUT_MEM_CLK_OUT_DIV2);
  785. REG_FIELD_SET(value, edge,
  786. ODN_DUT_IFACE_CLK_OUT_DIVIDER2_EDGE);
  787. REG_FIELD_SET(value, no_count,
  788. ODN_DUT_IFACE_CLK_OUT_DIVIDER2_NOCOUNT);
  789. iowrite32(value, clk_blk_base + ODN_DUT_IFACE_CLK_OUT_DIVIDER2);
  790. /* Calculate the register fields for multiplier */
  791. odin_mmcm_reg_param_calc(mul, &high_time, &low_time, &edge, &no_count);
  792. /* Read-modify-write the required fields to multiplier register 1*/
  793. value = odin_core_readreg32(data, PCI_ODIN_CLK_BLK_DUT_MEM_CLK_MUL);
  794. value = ioread32(clk_blk_base + ODN_DUT_IFACE_CLK_MULTIPLIER1);
  795. REG_FIELD_SET(value, high_time,
  796. ODN_DUT_IFACE_CLK_MULTIPLIER1_HI_TIME);
  797. REG_FIELD_SET(value, low_time,
  798. ODN_DUT_IFACE_CLK_MULTIPLIER1_LO_TIME);
  799. iowrite32(value, clk_blk_base + ODN_DUT_IFACE_CLK_MULTIPLIER1);
  800. /* Read-modify-write the required fields to multiplier register 2 */
  801. value = ioread32(clk_blk_base + ODN_DUT_IFACE_CLK_MULTIPLIER2);
  802. REG_FIELD_SET(value, edge,
  803. ODN_DUT_IFACE_CLK_MULTIPLIER2_EDGE);
  804. REG_FIELD_SET(value, no_count,
  805. ODN_DUT_IFACE_CLK_MULTIPLIER2_NOCOUNT);
  806. iowrite32(value, clk_blk_base + ODN_DUT_IFACE_CLK_MULTIPLIER2);
  807. /* Calculate the register fields for input divider */
  808. odin_mmcm_reg_param_calc(in_div, &high_time, &low_time,
  809. &edge, &no_count);
  810. /* Read-modify-write the required fields to input divider register 1 */
  811. value = ioread32(clk_blk_base + ODN_DUT_IFACE_CLK_IN_DIVIDER1);
  812. REG_FIELD_SET(value, high_time,
  813. ODN_DUT_IFACE_CLK_IN_DIVIDER1_HI_TIME);
  814. REG_FIELD_SET(value, low_time,
  815. ODN_DUT_IFACE_CLK_IN_DIVIDER1_LO_TIME);
  816. REG_FIELD_SET(value, edge,
  817. ODN_DUT_IFACE_CLK_IN_DIVIDER1_EDGE);
  818. REG_FIELD_SET(value, no_count,
  819. ODN_DUT_IFACE_CLK_IN_DIVIDER1_NOCOUNT);
  820. iowrite32(value, clk_blk_base + ODN_DUT_IFACE_CLK_IN_DIVIDER1);
  821. /* Bring DUT interface clock MMCM out of reset */
  822. odin_core_writereg32(data, PCI_ODIN_CORE_CLK_GEN_RESET, 0);
  823. err = odin_core_polreg32(data, PCI_ODIN_CORE_MMCM_LOCK_STATUS, PCI_ODIN_MMCM_LOCK_STATUS_DUT_IF);
  824. if (err != 0) {
  825. dev_err(dev, "MMCM failed to lock for DUT IF\n");
  826. return err;
  827. }
  828. /* Bring DUT out of reset */
  829. odin_core_writereg32(data, PCI_ODIN_CORE_EXTERNAL_RESETN,
  830. EXTERNAL_RESET_EXTERNAL_RESETN_SPI | EXTERNAL_RESET_EXTERNAL_RESETN_DUT);
  831. msleep(20);
  832. dev_info(dev, "DUT IF clock set-up successful at %dHz\n", output_clk);
  833. return err;
  834. }
  835. #endif
  836. /*
  837. * odin_isr_clear - Clear an interrupt
  838. *
  839. *
  840. * note: the reason of that function is unclear, it is taken from Apollo/Atlas code that have
  841. * the same interrupt handler as Odin, is it because of a bug?
  842. */
  843. static void odin_isr_clear(struct nexefdrv_prvdata *data, unsigned int intstatus)
  844. {
  845. unsigned int max_retries = 1000;
  846. while ((odin_core_readreg32(data, PCI_ODIN_CORE_INTERRUPT_STATUS) & intstatus) && max_retries--)
  847. odin_core_writereg32(data, PCI_ODIN_CORE_INTERRUPT_CLR,
  848. (INT_INTERRUPT_MASTER_ENABLE | intstatus));
  849. }
  850. typedef void (*interrupt_callback_handler)(void *);
  851. struct interrupt_handlers {
  852. interrupt_callback_handler handler;
  853. void * data;
  854. uint8_t enabled;
  855. };
  856. static struct interrupt_handlers pdev_int_handlers[TC_INTERRUPT_COUNT];
  857. /*
  858. * pci_isr_cb - Low latency interrupt handler
  859. */
  860. static irqreturn_t pci_isr_cb(int irq, void *dev_id)
  861. {
  862. uint32_t intstatus;
  863. struct pci_dev *pcidev = (struct pci_dev *)dev_id;
  864. struct nexefdrv_prvdata *data = dev_get_drvdata(&pcidev->dev);
  865. irqreturn_t ret = IRQ_NONE;
  866. if (dev_id == NULL) {
  867. /* Spurious interrupt: not yet initialised. */
  868. pr_warn("Spurious interrupt data/dev_id not initialised!\n");
  869. goto exit;
  870. }
  871. /* Read interrupt status register */
  872. intstatus = odin_core_readreg32(data, PCI_ODIN_CORE_INTERRUPT_STATUS);
  873. dev_dbg(&pcidev->dev,
  874. "%s: Got an interrupt....\n",
  875. __func__);
  876. /* Now handle the ints */
  877. if (intstatus & INT_INTERRUPT_DUT0) {
  878. /* Check who called and say hello */
  879. dev_dbg(&pcidev->dev,
  880. "%s: Got a valid interrupt, trying to do something with it....\n",
  881. __func__);
  882. /* Check NNA event register */
  883. if ( (__readreg32(data, NNA_REG_BANK, VHA_CR_OS0_VHA_EVENT_STATUS) != 0) &&
  884. pdev_int_handlers[TC_INTERRUPT_TC5_PDP].enabled ) {
  885. dev_dbg(&pcidev->dev,
  886. "%s: NNA interrupt....\n",
  887. __func__);
  888. if ( pdev_int_handlers[TC_INTERRUPT_TC5_PDP].handler != NULL ) {
  889. pdev_int_handlers[TC_INTERRUPT_TC5_PDP].handler(pdev_int_handlers[TC_INTERRUPT_TC5_PDP].data);
  890. }
  891. else {
  892. WARN_ON(pdev_int_handlers[TC_INTERRUPT_TC5_PDP].handler == NULL);
  893. }
  894. }
  895. else if (pdev_int_handlers[TC_INTERRUPT_EXT].enabled) {
  896. /* Else it must be from the NNPU */
  897. dev_dbg(&pcidev->dev,
  898. "%s: Probably a NNPU interrupt....\n",
  899. __func__);
  900. if ( pdev_int_handlers[TC_INTERRUPT_EXT].handler != NULL ) {
  901. pdev_int_handlers[TC_INTERRUPT_EXT].handler(pdev_int_handlers[TC_INTERRUPT_EXT].data);
  902. }
  903. else {
  904. WARN_ON(pdev_int_handlers[TC_INTERRUPT_EXT].handler == NULL);
  905. }
  906. }
  907. else {
  908. dev_warn(&pcidev->dev, "Received an interrupt from DUT when no proper handling being registered.");
  909. }
  910. }
  911. else {
  912. /* most likely this is a shared interrupt line */
  913. dev_dbg(&pcidev->dev,
  914. "%s: unexpected or spurious interrupt [%x] (shared IRQ?)!\n",
  915. __func__, intstatus);
  916. /* WARN_ON(1); */
  917. goto exit;
  918. }
  919. /* Ack the ints */
  920. odin_isr_clear(data, intstatus);
  921. exit:
  922. return ret;
  923. }
  924. static inline void odin_reset_int(struct nexefdrv_prvdata *data) {
  925. odin_core_writereg32(data, PCI_ODIN_CORE_INTERRUPT_ENABLE, 0);
  926. odin_core_writereg32(data, PCI_ODIN_CORE_INTERRUPT_CLR, 0xFFFFFFFF);
  927. }
  928. /*
  929. * odin_enable_int - Enable an interrupt
  930. */
  931. static inline void odin_enable_int(struct nexefdrv_prvdata *data,
  932. uint32_t intmask)
  933. {
  934. uint32_t irq_enabled = odin_core_readreg32(data, PCI_ODIN_CORE_INTERRUPT_ENABLE);
  935. //intmask &= INT_INTERRUPT_DUT0;
  936. odin_core_writereg32(data, PCI_ODIN_CORE_INTERRUPT_ENABLE, irq_enabled | intmask | INT_INTERRUPT_MASTER_ENABLE);
  937. }
  938. /*
  939. * odin_disable_int - Disable an interrupt
  940. */
  941. static inline void odin_disable_int(struct nexefdrv_prvdata *data,
  942. uint32_t intmask)
  943. {
  944. uint32_t irq_enabled = odin_core_readreg32(data, PCI_ODIN_CORE_INTERRUPT_ENABLE);
  945. //intmask &= INT_INTERRUPT_DUT0;
  946. odin_core_writereg32(data, PCI_ODIN_CORE_INTERRUPT_ENABLE,
  947. irq_enabled & ~intmask);
  948. }
  949. /*
  950. * odin_allocate_registers - Allocate memory for a register (or memory) bank
  951. * @data: pointer to the data
  952. * @bank: bank to set
  953. * @bar: BAR where the register are
  954. * @base: base address in the BAR
  955. * @size: size of the register set
  956. */
  957. static inline int odin_allocate_registers(struct pci_dev *pci_dev,
  958. struct nexefdrv_prvdata *data, int bank,
  959. int bar, unsigned long base, unsigned long size)
  960. {
  961. unsigned long bar_size = pci_resource_len(pci_dev, bar);
  962. unsigned long bar_addr = pci_resource_start(pci_dev, bar);
  963. unsigned long bar_max_size = bar_size - base;
  964. BUG_ON((base > bar_size) || ((base+size) > bar_size));
  965. data->reg_bank[bank].bar = bar;
  966. data->reg_bank[bank].addr = bar_addr + base;
  967. data->reg_bank[bank].size = min(size, bar_max_size);
  968. #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0)
  969. data->reg_bank[bank].km_addr = devm_ioremap_nocache(
  970. &pci_dev->dev, data->reg_bank[bank].addr,
  971. data->reg_bank[bank].size);
  972. #else
  973. data->reg_bank[bank].km_addr = devm_ioremap(
  974. &pci_dev->dev, data->reg_bank[bank].addr,
  975. data->reg_bank[bank].size);
  976. #endif
  977. dev_dbg(&pci_dev->dev, "[bank %u] bar:%d addr:0x%lx size:0x%lx km:0x%p\n",
  978. bank, bar, data->reg_bank[bank].addr,
  979. data->reg_bank[bank].size,
  980. data->reg_bank[bank].km_addr);
  981. return data->reg_bank[bank].km_addr == NULL;
  982. }
  983. //endregion Odin handling functions
  984. //region Specific NNA handling functions
  985. /* The function here are to handly the secure reigster from the NNA.
  986. * The NNA driver currently don't know how to handle it
  987. */
  988. static int nexef_nna_init(struct pci_dev *pci_dev, struct nexefdrv_prvdata *priv_data)
  989. {
  990. int ret = 0;
  991. struct device *dev = &pci_dev->dev;
  992. /* Allocate nna registers registers */
  993. ret = odin_allocate_registers(pci_dev, priv_data,
  994. NNA_REG_BANK, NEXEF_NNA_REG_BAR,
  995. NEXEF_NNA_REG_OFFSET, NEXEF_NNA_REG_SIZE);
  996. if (ret) {
  997. dev_err(dev, "Can't allocate memory for nna regs!");
  998. ret = -ENOMEM;
  999. goto out;
  1000. }
  1001. out:
  1002. return ret;
  1003. }
  1004. static void nexef_nna_unlock(struct nexefdrv_prvdata *priv_data)
  1005. {
  1006. __writereg32(priv_data, NNA_REG_BANK, VHA_CR_SOCIF_BUS_SECURE, 0);
  1007. }
  1008. //endregion Specific NNA handling functions
  1009. //region NN_SYS related functions
  1010. static int nexef_nnsys_init(struct pci_dev *pci_dev, struct nexefdrv_prvdata *priv_data)
  1011. {
  1012. int ret = 0;
  1013. struct device *dev = &pci_dev->dev;
  1014. /* Allocate nnsys registers registers */
  1015. ret = odin_allocate_registers(pci_dev, priv_data,
  1016. NNSYS_REG_BANK, NEXEF_NNSYS_REG_BAR,
  1017. NEXEF_NNSYS_REG_OFFSET, NEXEF_NNSYS_REG_SIZE);
  1018. if (ret) {
  1019. dev_err(dev, "Can't allocate memory for nnsys regs!");
  1020. ret = -ENOMEM;
  1021. goto out;
  1022. }
  1023. out:
  1024. return ret;
  1025. }
  1026. static void nexef_nnsys_unlock(struct nexefdrv_prvdata *priv_data)
  1027. {
  1028. __writereg32(priv_data, NNSYS_REG_BANK, NN_SYS_CR_SOCIF_BUS_SECURE, 0);
  1029. }
  1030. static void nexef_nnsys_configure(struct nexefdrv_prvdata *priv_data)
  1031. {
  1032. /* Power up everything */
  1033. __writereg32(priv_data, NNSYS_REG_BANK, NN_SYS_CR_POWER_EVENT,
  1034. NN_SYS_CR_POWER_EVENT_DOMAIN_NNSYS_EN | NN_SYS_CR_POWER_EVENT_REQUEST_POWER_UP | NN_SYS_CR_POWER_EVENT_TYPE_EN);
  1035. __writereg32(priv_data, NNSYS_REG_BANK, NN_SYS_CR_POWER_EVENT,
  1036. NN_SYS_CR_POWER_EVENT_DOMAIN_NNA_EN | NN_SYS_CR_POWER_EVENT_REQUEST_POWER_UP | NN_SYS_CR_POWER_EVENT_TYPE_EN);
  1037. /* Doc talk about OCM power, but does not exist in the CR file ?! */
  1038. /* Disable OCM */
  1039. __writereg64(priv_data, NNSYS_REG_BANK, NN_SYS_CR_NOC_LOWER_ADDR1, 0xFFFFFFFF10000000);
  1040. __writereg64(priv_data, NNSYS_REG_BANK, NN_SYS_CR_NOC_UPPER_ADDR1, 0xFFFFFFFFFFFFFFFF);
  1041. }
  1042. //endregion NN_SYS related functions
  1043. //region Kernel related functions
  1044. static int nexef_plat_probe(struct pci_dev *pci_dev,
  1045. const struct pci_device_id *id)
  1046. {
  1047. int ret = 0;
  1048. struct nexefdrv_prvdata *data;
  1049. size_t maxmapsize = maxmapsizeMB * 1024 * 1024;
  1050. unsigned long dut_base_mem, dut_mem_size;
  1051. struct device *dev = &pci_dev->dev;
  1052. dev_dbg(dev, "probing device, pci_dev: %p\n", dev);
  1053. if (IS_APOLLO_DEVICE(id->device)) {
  1054. dev_err(dev, "This driver can't work with an APOLLO baseboard. Please check the hardware you are using!\n");
  1055. goto out;
  1056. }
  1057. if (IS_SIRIUS_DEVICE(id->device)) {
  1058. dev_warn(dev, "This driver is not design to work on an Orion system. As it is really similar" \
  1059. "to an Odin baseboard it may work or not. Use at your own risk.");
  1060. }
  1061. /* Enable the device */
  1062. if (pci_enable_device(pci_dev))
  1063. goto out;
  1064. /* Reserve PCI I/O and memory resources */
  1065. if (pci_request_region(pci_dev, 1, "odin-regs"))
  1066. goto out_disable;
  1067. /* Create a kernel space mapping for each of the bars */
  1068. data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
  1069. if (!data) {
  1070. dev_err(dev, "Memory allocation error, aborting.\n");
  1071. ret = -ENOMEM;
  1072. goto out_release;
  1073. }
  1074. dev_dbg(dev, "allocated nexefdrv_prvdata @ %p\n", data);
  1075. memset(data, 0, sizeof(*data));
  1076. /* Allocate odin core registers */
  1077. ret = odin_allocate_registers(pci_dev, data,
  1078. CORE_REG_BANK, PCI_ODIN_SYS_CTRL_REGS_BAR,
  1079. PCI_ODIN_SYS_CTRL_BASE_OFFSET,
  1080. PCI_ODIN_CORE_REG_SIZE);
  1081. if (ret) {
  1082. dev_err(dev, "Can't allocate memory for odin regs!");
  1083. ret = -ENOMEM;
  1084. goto out_release;
  1085. }
  1086. /* Display some infos */
  1087. {
  1088. uint32_t odin_id = odin_core_readreg32(data, PCI_ODIN_CORE_ID);
  1089. uint32_t odin_rev = odin_core_readreg32(data, PCI_ODIN_CORE_REVISION);
  1090. uint32_t odin_cs = odin_core_readreg32(data, PCI_ODIN_CORE_CHANGE_SET);
  1091. uint32_t odin_ui = odin_core_readreg32(data, PCI_ODIN_CORE_USER_ID);
  1092. uint32_t odin_ub = odin_core_readreg32(data, PCI_ODIN_CORE_USER_BUILD);
  1093. dev_info(dev, "Found Odin lite board v%d.%d (ID:%X CS:%X UI:%X UB:%X)",
  1094. (odin_rev >> 8) & 0xF, odin_rev & 0xF, odin_id & 0x7, odin_cs, odin_ui, odin_ub);
  1095. }
  1096. #ifdef CONFIG_SET_FPGA_CLOCK
  1097. odin_set_dut_core_clk(data, PCI_ODIN_INPUT_CLOCK_SPEED, odin_fpga_dut_clock);
  1098. #endif
  1099. /* Call NN_SYS init */
  1100. ret = nexef_nnsys_init(pci_dev, data);
  1101. if (ret) {
  1102. dev_err(dev, "nnsys register allocation failed!\n");
  1103. goto out_release;
  1104. }
  1105. ret = nexef_nna_init(pci_dev, data);
  1106. if (ret) {
  1107. dev_err(dev, "nna register allocation failed!\n");
  1108. goto out_release;
  1109. }
  1110. /* Get DUT memory infos */
  1111. dut_mem_size = pci_resource_len(pci_dev, PCI_ODIN_DUT_MEM_BAR);
  1112. if (dut_mem_size > maxmapsize)
  1113. dut_mem_size = maxmapsize;
  1114. dut_base_mem = pci_resource_start(pci_dev, PCI_ODIN_DUT_MEM_BAR) +
  1115. pci_offset;
  1116. /* change alloc size according to module parameter */
  1117. if (pci_size)
  1118. dut_mem_size = pci_size;
  1119. dev_info(dev, "DUT Memory: bar: %d addr: 0x%lx size: 0x%lx\n",
  1120. PCI_ODIN_DUT_MEM_BAR,
  1121. dut_base_mem,
  1122. dut_mem_size);
  1123. /* Get the IRQ...*/
  1124. data->irq = pci_dev->irq;
  1125. data->pci_dev = pci_dev;
  1126. dev_set_drvdata(&pci_dev->dev, data);
  1127. nexef_pci_drv.pci_dev = pci_dev;
  1128. dev_dbg(dev, "Going to reset DUT... (First time)\n");
  1129. reset_dut(data);
  1130. dev_dbg(dev, "Reseting interrupts\n");
  1131. odin_reset_int(data);
  1132. dev_dbg(dev, "Enabling interrupts\n");
  1133. odin_enable_int(data, INT_INTERRUPT_DUT0 | INT_INTERRUPT_PDP);
  1134. /*
  1135. * Reset FPGA DUT only after disabling clocks in
  1136. * vha_add_dev()-> get properties.
  1137. * This workaround is required to ensure that
  1138. * clocks (on daughter board) are enabled for test slave scripts to
  1139. * read FPGA build version register.
  1140. * NOTE: Asserting other bits like DDR reset bit cause problems
  1141. * with bus mastering feature, thus results in memory failures.
  1142. */
  1143. dev_dbg(dev, "Going to reset DUT... (Second time)\n");
  1144. reset_dut(data);
  1145. odin_set_mem_mode_lma(data);
  1146. /* Configure NN_SYS */
  1147. dev_info(dev, "Configuring NN_SYS\n");
  1148. nexef_nnsys_configure(data);
  1149. /* Install the ISR callback...*/
  1150. dev_dbg(dev, "Trying to insert IRQ handler\n");
  1151. ret = devm_request_irq(dev, data->irq, &pci_isr_cb, IRQF_SHARED, DEVICE_NAME,
  1152. (void *)pci_dev);
  1153. if (ret) {
  1154. dev_err(dev, "failed to request irq!\n");
  1155. goto out_disable_int;
  1156. }
  1157. dev_dbg(dev, "registered irq %d\n", data->irq);
  1158. /* Fill in export infos */
  1159. data->plat_exports.dut_mem.base = dut_base_mem;
  1160. data->plat_exports.dut_mem.size = dut_mem_size;
  1161. /* Set NNPU parameters */
  1162. data->plat_exports.rogue_mem_mode = TC_MEMORY_LOCAL;
  1163. data->plat_exports.rogue_heap_mem.base = data->plat_exports.dut_mem.base;
  1164. data->plat_exports.rogue_heap_mem.size = NEXEF_NNPU_HEAP_SIZE;
  1165. data->plat_exports.rogue_pdp_heap_mem.base = data->plat_exports.rogue_heap_mem.base +
  1166. data->plat_exports.rogue_heap_mem.size;
  1167. data->plat_exports.rogue_pdp_heap_mem.size = (data->plat_exports.dut_mem.size / 2) -
  1168. data->plat_exports.rogue_heap_mem.size;
  1169. data->plat_exports.nna_heap_mem.base = data->plat_exports.rogue_pdp_heap_mem.base +
  1170. data->plat_exports.rogue_pdp_heap_mem.size;
  1171. data->plat_exports.nna_heap_mem.size = (data->plat_exports.dut_mem.size / 2);
  1172. dev_info(dev, "DUT Memory regions:\n");
  1173. dev_info(dev, "DUT Mem : %08llx-%08llx (size: %08llx)\n",
  1174. data->plat_exports.dut_mem.base,
  1175. data->plat_exports.dut_mem.base + data->plat_exports.dut_mem.size,
  1176. data->plat_exports.dut_mem.size);
  1177. dev_info(dev, "NNPU heap: %08llx-%08llx (size: %08llx)\n",
  1178. data->plat_exports.rogue_heap_mem.base,
  1179. data->plat_exports.rogue_heap_mem.base + data->plat_exports.rogue_heap_mem.size,
  1180. data->plat_exports.rogue_heap_mem.size);
  1181. dev_info(dev, "NNPU pdp : %08llx-%08llx (size: %08llx)\n",
  1182. data->plat_exports.rogue_pdp_heap_mem.base,
  1183. data->plat_exports.rogue_pdp_heap_mem.base + data->plat_exports.rogue_pdp_heap_mem.size,
  1184. data->plat_exports.rogue_pdp_heap_mem.size);
  1185. dev_info(dev, "NNA : %08llx-%08llx (size: %08llx)\n",
  1186. data->plat_exports.nna_heap_mem.base,
  1187. data->plat_exports.nna_heap_mem.base + data->plat_exports.nna_heap_mem.size,
  1188. data->plat_exports.nna_heap_mem.size);
  1189. /* We now are ready to create the platform drivers */
  1190. ret = nexef_register_rogue_plat_device(data);
  1191. if (ret) {
  1192. dev_err(dev, "cannot create NNPU platform device!\n");
  1193. goto out_disable_int;
  1194. }
  1195. ret = nexef_register_nna_plat_device(data);
  1196. if (ret) {
  1197. dev_err(dev, "cannot create NNA platform device!\n");
  1198. goto out_disable_int;
  1199. }
  1200. return ret;
  1201. out_disable_int:
  1202. /* Make sure int are no longer enabled */
  1203. odin_disable_int(data, INT_INTERRUPT_DUT0);
  1204. out_release:
  1205. pci_release_regions(pci_dev);
  1206. out_disable:
  1207. pci_disable_device(pci_dev);
  1208. out:
  1209. return ret;
  1210. }
  1211. //region nn_sys related functions
  1212. //endregion nn_sys related functions
  1213. static void nexef_plat_remove(struct pci_dev *pcidev)
  1214. {
  1215. struct nexefdrv_prvdata *priv_data = dev_get_drvdata(&pcidev->dev);
  1216. dev_dbg(&pcidev->dev, "removing device\n");
  1217. if (priv_data == NULL) {
  1218. dev_err(&pcidev->dev, "PCI priv data missing!\n");
  1219. } else {
  1220. /*
  1221. * We need to disable interrupts for the
  1222. * embedded device via the fpga interrupt controller...
  1223. */
  1224. odin_disable_int(priv_data, INT_INTERRUPT_DUT0);
  1225. /* Unregister int */
  1226. devm_free_irq(&pcidev->dev, priv_data->irq, pcidev);
  1227. /* Unregister all potential platoform device allocated */
  1228. nexef_unregister_rogue_plat_device(priv_data);
  1229. nexef_unregister_nna_plat_device(priv_data);
  1230. }
  1231. #if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0)
  1232. /* Release any declared mem regions */
  1233. dma_release_declared_memory(&pcidev->dev);
  1234. #endif
  1235. pci_release_regions(pcidev);
  1236. pci_disable_device(pcidev);
  1237. /* Just to make sure */
  1238. nexef_pci_drv.pci_dev = NULL;
  1239. }
  1240. #ifdef CONFIG_PM
  1241. static int nexef_plat_suspend(struct device *dev)
  1242. {
  1243. /* nothing, for now, to be done here */
  1244. return 0;
  1245. }
  1246. static int nexef_plat_resume(struct device *dev)
  1247. {
  1248. /* nothing, for now, to be done here */
  1249. return 0;
  1250. }
  1251. #endif
  1252. static int nexef_plat_init(void)
  1253. {
  1254. int ret;
  1255. ret = pci_register_driver(&nexef_pci_drv.pci_driver);
  1256. if (ret) {
  1257. pr_err("failed to register PCI driver!\n");
  1258. return ret;
  1259. }
  1260. /* pci_dev should be set in probe */
  1261. if (!nexef_pci_drv.pci_dev) {
  1262. pr_err("failed to find compatible NeXeF PCI device!\n");
  1263. pci_unregister_driver(&nexef_pci_drv.pci_driver);
  1264. return -ENODEV;
  1265. }
  1266. return 0;
  1267. }
  1268. static void nexef_plat_exit(void)
  1269. {
  1270. /* Not sure we have thing to be done here... */
  1271. if (nexef_pci_drv.pci_dev) {
  1272. pci_unregister_driver(&nexef_pci_drv.pci_driver);
  1273. }
  1274. }
  1275. module_init(nexef_plat_init);
  1276. module_exit(nexef_plat_exit);
  1277. MODULE_LICENSE("GPL");
  1278. //endregion Kernel related functions
  1279. //region NNPU needed exported functions
  1280. int tc_enable(struct device *dev);
  1281. void tc_disable(struct device *dev);
  1282. int tc_set_interrupt_handler(struct device *dev, int interrupt_id,
  1283. void (*handler_function)(void *), void *data);
  1284. int tc_enable_interrupt(struct device *dev, int interrupt_id);
  1285. int tc_disable_interrupt(struct device *dev, int interrupt_id);
  1286. int tc_sys_info(struct device *dev, uint32_t *tmp, uint32_t *pll);
  1287. int tc_sys_strings(struct device *dev,
  1288. char *str_fpga_rev, size_t size_fpga_rev,
  1289. char *str_tcf_core_rev, size_t size_tcf_core_rev,
  1290. char *str_tcf_core_target_build_id,
  1291. size_t size_tcf_core_target_build_id,
  1292. char *str_pci_ver, size_t size_pci_ver,
  1293. char *str_macro_ver, size_t size_macro_ver);
  1294. int tc_core_clock_speed(struct device *dev);
  1295. #define FUNC_IN() pr_debug(">>> %s():%d\n", __func__, __LINE__)
  1296. int tc_enable(struct device *dev)
  1297. {
  1298. //struct pci_dev *pdev;
  1299. FUNC_IN();
  1300. //pdev = to_pci_dev(dev);
  1301. return 0; //pci_enable_device(pdev);
  1302. }
  1303. EXPORT_SYMBOL(tc_enable);
  1304. void tc_disable(struct device *dev)
  1305. {
  1306. //struct pci_dev *pdev;
  1307. FUNC_IN();
  1308. //pdev = to_pci_dev(dev);
  1309. //pci_disable_device(pdev);
  1310. }
  1311. EXPORT_SYMBOL(tc_disable);
  1312. static char *int_names[] = {
  1313. "PDP",
  1314. "NNPU",
  1315. "NNA"
  1316. };
  1317. int tc_set_interrupt_handler(struct device *dev, int interrupt_id,
  1318. void (*handler_function)(void *), void *data)
  1319. {
  1320. int err = -1;
  1321. FUNC_IN();
  1322. if ( (interrupt_id >= 0) && (interrupt_id < TC_INTERRUPT_COUNT) ) {
  1323. dev_info(dev, "Registering interrupt handler (%p) for %s [data: %p]", handler_function, int_names[interrupt_id], data);
  1324. err = 0;
  1325. pdev_int_handlers[interrupt_id].handler = handler_function;
  1326. pdev_int_handlers[interrupt_id].data = data;
  1327. pdev_int_handlers[interrupt_id].enabled = 0;
  1328. }
  1329. else {
  1330. dev_warn(dev, "%s: Invalid interrupt id %d!", __func__, interrupt_id);
  1331. }
  1332. return err;
  1333. }
  1334. EXPORT_SYMBOL(tc_set_interrupt_handler);
  1335. int tc_enable_interrupt(struct device *dev, int interrupt_id)
  1336. {
  1337. int err = -1;
  1338. FUNC_IN();
  1339. if ( (interrupt_id >= 0) && (interrupt_id < TC_INTERRUPT_COUNT) ) {
  1340. dev_info(dev, "Enabling interrupt handler for %s\n", int_names[interrupt_id]);
  1341. err = 0;
  1342. pdev_int_handlers[interrupt_id].enabled = 1;
  1343. }
  1344. else {
  1345. dev_warn(dev, "%s: Invalid interrupt id %d!", __func__, interrupt_id);
  1346. }
  1347. return err;
  1348. }
  1349. EXPORT_SYMBOL(tc_enable_interrupt);
  1350. int tc_disable_interrupt(struct device *dev, int interrupt_id)
  1351. {
  1352. int err = -1;
  1353. FUNC_IN();
  1354. if ( (interrupt_id >= 0) && (interrupt_id < TC_INTERRUPT_COUNT) ) {
  1355. dev_info(dev, "Disabling interrupt handler for %s\n", int_names[interrupt_id]);
  1356. err = 0;
  1357. pdev_int_handlers[interrupt_id].enabled = 0;
  1358. }
  1359. else {
  1360. dev_warn(dev, "%s: Invalid interrupt id %d!", __func__, interrupt_id);
  1361. }
  1362. return err;
  1363. }
  1364. EXPORT_SYMBOL(tc_disable_interrupt);
  1365. int tc_sys_info(struct device *dev, uint32_t *tmp, uint32_t *pll)
  1366. {
  1367. *tmp = 0;
  1368. *pll = 0;
  1369. return 0;
  1370. }
  1371. EXPORT_SYMBOL(tc_sys_info);
  1372. int tc_sys_strings(struct device *dev,
  1373. char *str_fpga_rev, size_t size_fpga_rev,
  1374. char *str_tcf_core_rev, size_t size_tcf_core_rev,
  1375. char *str_tcf_core_target_build_id,
  1376. size_t size_tcf_core_target_build_id,
  1377. char *str_pci_ver, size_t size_pci_ver,
  1378. char *str_macro_ver, size_t size_macro_ver)
  1379. {
  1380. struct nexefdrv_prvdata *priv_data = dev_get_drvdata(dev);
  1381. uint32_t odin_rev, odin_cs;
  1382. FUNC_IN();
  1383. odin_rev = odin_core_readreg32(priv_data, PCI_ODIN_CORE_REVISION);
  1384. odin_cs = odin_core_readreg32(priv_data, PCI_ODIN_CORE_CHANGE_SET);
  1385. snprintf(str_fpga_rev, size_fpga_rev, "3NX-F odin build\n");
  1386. snprintf(str_tcf_core_rev, size_tcf_core_rev, "%d.%d", (odin_rev >> 8) & 0xF, odin_rev & 0xF);
  1387. snprintf(str_tcf_core_target_build_id, size_tcf_core_target_build_id, "%d", odin_cs);
  1388. snprintf(str_pci_ver, size_pci_ver, "??\n");
  1389. snprintf(str_macro_ver, size_macro_ver, "??\n");
  1390. return 0;
  1391. }
  1392. EXPORT_SYMBOL(tc_sys_strings);
  1393. int tc_core_clock_speed(struct device *dev)
  1394. {
  1395. FUNC_IN();
  1396. return 25000000L;
  1397. }
  1398. EXPORT_SYMBOL(tc_core_clock_speed);
  1399. //endregion NNPU needed exported functions
  1400. //region Platform related functions
  1401. static uint64_t nexef_get_rogue_dma_mask(struct platdev_export_info *export_info)
  1402. {
  1403. /* Does not access system memory, so there is no DMA limitation */
  1404. if (export_info->rogue_mem_mode == TC_MEMORY_LOCAL)
  1405. return DMA_BIT_MASK(64);
  1406. return DMA_BIT_MASK(32);
  1407. }
  1408. static int nexef_register_rogue_plat_device(struct nexefdrv_prvdata *priv_data)
  1409. {
  1410. int err = 0;
  1411. struct resource nexef_rogue_resources[] = {
  1412. DEFINE_RES_MEM_NAMED(NEXEF_ROGUE_REG_OFFSET +
  1413. pci_resource_start(priv_data->pci_dev,
  1414. NEXEF_ROGUE_REG_BAR),
  1415. NEXEF_ROGUE_REG_SIZE, NEXEF_NNPU_PDEV_NAME),
  1416. };
  1417. struct tc_rogue_platform_data pdata = {
  1418. .mem_mode = priv_data->plat_exports.rogue_mem_mode,
  1419. .tc_memory_base = priv_data->plat_exports.dut_mem.base,
  1420. .rogue_heap_memory_base = priv_data->plat_exports.rogue_heap_mem.base,
  1421. .rogue_heap_memory_size = priv_data->plat_exports.rogue_heap_mem.size,
  1422. .pdp_heap_memory_base = priv_data->plat_exports.rogue_pdp_heap_mem.base,
  1423. .pdp_heap_memory_size = priv_data->plat_exports.rogue_pdp_heap_mem.size,
  1424. };
  1425. struct platform_device_info odin_rogue_dev_info = {
  1426. .parent = &priv_data->pci_dev->dev,
  1427. .name = TC_DEVICE_NAME_ROGUE,
  1428. .id = -2,
  1429. .res = nexef_rogue_resources,
  1430. .num_res = ARRAY_SIZE(nexef_rogue_resources),
  1431. .data = &pdata,
  1432. .size_data = sizeof(pdata),
  1433. .dma_mask = nexef_get_rogue_dma_mask(&priv_data->plat_exports),
  1434. };
  1435. priv_data->plat_exports.rogue_pdev = platform_device_register_full(&odin_rogue_dev_info);
  1436. if (IS_ERR(priv_data->plat_exports.rogue_pdev)) {
  1437. err = PTR_ERR(priv_data->plat_exports.rogue_pdev);
  1438. dev_err(&priv_data->pci_dev->dev,
  1439. "Failed to register `%s' device (%d)\n", TC_DEVICE_NAME_ROGUE, err);
  1440. priv_data->plat_exports.rogue_pdev = NULL;
  1441. }
  1442. return err;
  1443. }
  1444. static int nexef_register_nna_plat_device(struct nexefdrv_prvdata *priv_data)
  1445. {
  1446. int err = 0;
  1447. struct resource nexef_nna_resources[] = {
  1448. DEFINE_RES_MEM_NAMED(NEXEF_NNA_REG_OFFSET +
  1449. pci_resource_start(priv_data->pci_dev,
  1450. NEXEF_NNA_REG_BAR),
  1451. NEXEF_NNA_REG_SIZE, NEXEF_NNA_PDEV_NAME),
  1452. };
  1453. struct nexef_nna_platform_data pdata = {
  1454. // tc->dut2_mem_base - tc->tc_mem.base
  1455. .nna_memory_base = priv_data->plat_exports.nna_heap_mem.base,
  1456. .nna_memory_offset = priv_data->plat_exports.nna_heap_mem.base - priv_data->plat_exports.dut_mem.base,
  1457. .nna_memory_size = priv_data->plat_exports.nna_heap_mem.size,
  1458. };
  1459. struct platform_device_info nexef_nna_dev_info = {
  1460. .parent = &priv_data->pci_dev->dev,
  1461. .name = NEXEF_NNA_DEVICE_NAME,
  1462. .id = -2,
  1463. .res = nexef_nna_resources,
  1464. .num_res = ARRAY_SIZE(nexef_nna_resources),
  1465. .data = &pdata,
  1466. .size_data = sizeof(pdata),
  1467. //.dma_mask = nexef_get_rogue_dma_mask(tc),
  1468. };
  1469. priv_data->plat_exports.nna_pdev = platform_device_register_full(&nexef_nna_dev_info);
  1470. if (IS_ERR(priv_data->plat_exports.nna_pdev)) {
  1471. err = PTR_ERR(priv_data->plat_exports.nna_pdev);
  1472. dev_err(&priv_data->pci_dev->dev,
  1473. "Failed to register `%s' device (%d)\n", NEXEF_NNA_DEVICE_NAME, err);
  1474. priv_data->plat_exports.nna_pdev = NULL;
  1475. }
  1476. return err;
  1477. }
  1478. static void nexef_unregister_rogue_plat_device(struct nexefdrv_prvdata *priv_data)
  1479. {
  1480. if (priv_data->plat_exports.rogue_pdev) {
  1481. dev_dbg(&priv_data->pci_dev->dev, "Unregistering NNPU platform device");
  1482. platform_device_unregister(priv_data->plat_exports.rogue_pdev);
  1483. }
  1484. }
  1485. static void nexef_unregister_nna_plat_device(struct nexefdrv_prvdata *priv_data)
  1486. {
  1487. if (priv_data->plat_exports.nna_pdev) {
  1488. dev_dbg(&priv_data->pci_dev->dev, "Unregistering NNA platform device");
  1489. platform_device_unregister(priv_data->plat_exports.nna_pdev);
  1490. }
  1491. }
  1492. //endregion Platform related functions