vha_io.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  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. #ifndef VHA_IO_H
  42. #define VHA_IO_H
  43. #ifndef OSID
  44. #define _OSID_ 0
  45. #else
  46. #define _OSID_ OSID
  47. #endif
  48. #define _CONCAT(x, y, z) x ## y ## z
  49. #define OSID_TOKEN(group, osid, reg) _CONCAT(group, osid, reg)
  50. #define VHA_CR_OS(reg_name) \
  51. OSID_TOKEN(VHA_CR_OS, _OSID_, _ ## reg_name)
  52. /* ignore bottom 4 bits of CONFIG_ID: they identify different build variants */
  53. #define VHA_CR_CORE_ID_BVNC_CLRMSK (0xfffffffffffffff0ULL)
  54. /* value missing from vha_cr.h: value obtained from email from SS */
  55. #define VHA_CR_CNN_DEBUG_STATUS_CNN_DEBUG_OFFSET_ALIGNSHIFT 32
  56. #define IMG_UINT64_C(v) v##ULL
  57. #define VHA_DEAD_HW (0xdead1000dead1ULL)
  58. #define ADDR_CAST __force void *
  59. /* IO access macros */
  60. #define IOREAD64(b, o) vha_plat_read64((ADDR_CAST)b + (o))
  61. #define IOWRITE64(b, o, v) vha_plat_write64((ADDR_CAST)b + (o), v)
  62. #define IOREAD64_REGIO(r) vha_plat_read64((ADDR_CAST)vha->reg_base + (r))
  63. #define IOREAD64_CR_REGIO(r) vha_plat_read64((ADDR_CAST)vha->reg_base + (VHA_CR_##r))
  64. #define IOWRITE64_REGIO(v, r) vha_plat_write64((ADDR_CAST)vha->reg_base + (r), v)
  65. #define IOWRITE64_CR_REGIO(v, r) vha_plat_write64((ADDR_CAST)vha->reg_base + (VHA_CR_##r), v)
  66. /* write value to register and log into pdump file using specified reg namespace */
  67. #define IOWRITE64_PDUMP_REGIO(v, o, r, s) do { \
  68. uint64_t _val_ = v; \
  69. vha_plat_write64((ADDR_CAST)vha->reg_base + o + r, _val_); \
  70. img_pdump_printf("WRW64 :%s:%#x %#llx\n", \
  71. s, (r), _val_); \
  72. } while (0)
  73. /* write value to register and log into pdump file using default regspace */
  74. #define IOWRITE64_PDUMP(v, r) \
  75. IOWRITE64_PDUMP_REGIO(v, 0, r, "REG")
  76. #define IOWRITE64_CR_PDUMP(v, r) \
  77. IOWRITE64_PDUMP_REGIO(v, 0, VHA_CR_##r, "REG")
  78. /* read value from register and log into pdump file using specified reg namespace */
  79. #define IOREAD64_PDUMP_REGIO(o, r, s) ({ \
  80. uint64_t _val_; \
  81. do { \
  82. _val_ = vha_plat_read64((ADDR_CAST)vha->reg_base + o + r); \
  83. img_pdump_printf("RDW64 :%s:%#x\n", s, (r)); \
  84. } while (0); \
  85. _val_; \
  86. })
  87. /* read value from register and log into pdump file using default regspace */
  88. #define IOREAD64_PDUMP(r) \
  89. IOREAD64_PDUMP_REGIO(0, r, "REG")
  90. #define IOREAD64_CR_PDUMP(r) \
  91. IOREAD64_PDUMP_REGIO(0, VHA_CR_##r, "REG")
  92. #ifdef CONFIG_FUNCTION_ERROR_INJECTION
  93. int __IOPOLL64_RET(int ret);
  94. #else
  95. #define __IOPOLL64_RET(ret) ret
  96. #endif
  97. /* poll c-times for the exact register value(v) masked with m,
  98. * using d-cycles delay between polls and log into pdump file
  99. * using specified reg namespace */
  100. #ifdef CONFIG_VHA_DUMMY
  101. #define IOPOLL64_PDUMP_REGIO(v, c, d, m, o, r, s) \
  102. ({ img_pdump_printf("POL64 :%s:%#x %#llx %#llx 0 %d %d\n", \
  103. s, (r), v & m, m, c, d); \
  104. __IOPOLL64_RET(0); \
  105. })
  106. /* Question: shall we generate pdump script to calculate parity in runtime? */
  107. #define IOPOLL64_PDUMP_REGIO_PARITY(v, c, d, m, o, r, s) \
  108. IOPOLL64_PDUMP_REGIO(v, c, d, m, o, r, s)
  109. #else /* CONFIG_VHA_DUMMY */
  110. #define IOPOLL64_PDUMP_REGIO(v, c, d, m, o, r, s) \
  111. ({ int _ret_ = -EIO; \
  112. do { \
  113. uint64_t _req_ = v & m; \
  114. uint64_t _val_ = ~_req_; \
  115. int _count_ = (c < 1 ? 1 : c); \
  116. while (--_count_ >= 0) { \
  117. _val_ = vha_plat_read64( \
  118. (ADDR_CAST)vha->reg_base + ((o + r))) & m; \
  119. if (_val_ == _req_) { \
  120. _ret_ = 0; \
  121. break; \
  122. } \
  123. if (vha->freq_khz > 0) { \
  124. ndelay(d*1000000/vha->freq_khz); \
  125. } else \
  126. udelay(100); \
  127. } \
  128. WARN_ON(_val_ != _req_ && !vha->hw_props.dummy_dev); \
  129. img_pdump_printf("POL64 :%s:%#x %#llx %#llx 0 %d %d\n", \
  130. s, (r), _req_, m, c, d); \
  131. } while (0); \
  132. __IOPOLL64_RET(_ret_); \
  133. })
  134. #ifdef VHA_SCF
  135. #define _PARITY_CHECKS 4
  136. #define _PARITY_CHECK_VAL_IMP(val) \
  137. if((_parity_ok = !img_mem_calc_parity(val))) { \
  138. _parity_count=_PARITY_CHECKS; \
  139. } else { \
  140. if(--_parity_count==0) { \
  141. _ret_ = -EIO; \
  142. break; \
  143. } \
  144. }
  145. #ifdef VHA_EVENT_INJECT
  146. #define _PARITY_CHECK_VAL(val, reg) \
  147. if((vha->injection.parity_poll_err_reg == reg) && __EVENT_INJECT()) { \
  148. _parity_ok = false; \
  149. } else { \
  150. _PARITY_CHECK_VAL_IMP(val) \
  151. WARN_ON(!_parity_ok); \
  152. }
  153. #else
  154. #define _PARITY_CHECK_VAL(val, reg) _PARITY_CHECK_VAL_IMP(val)
  155. #endif
  156. /* poll c-times for the exact register value(v) masked with m,
  157. * using d-cycles delay between polls and log into pdump file
  158. * using specified reg namespace
  159. * return error if parity calculated from 4 consecutive reads
  160. * is wrong
  161. * */
  162. #define IOPOLL64_PDUMP_REGIO_PARITY(v, c, d, m, o, r, s) \
  163. ({ int _ret_ = -EIO; \
  164. if (vha->hw_props.supported.parity && !vha->parity_disable) { \
  165. do { \
  166. bool _parity_ok = false; \
  167. int _parity_count=_PARITY_CHECKS; \
  168. uint64_t _req_ = (v) & (m); \
  169. uint64_t _val_ = ~_req_; \
  170. int _count_ = (c) < _PARITY_CHECKS ? _PARITY_CHECKS : (c); \
  171. while (_count_-- > 0) { \
  172. _val_ = vha_plat_read64( \
  173. (ADDR_CAST)vha->reg_base + ((o + r))); \
  174. _PARITY_CHECK_VAL(_val_, r); \
  175. _val_ &= m; \
  176. if (_parity_ok && _val_ == _req_) { \
  177. _ret_ = 0; \
  178. break; \
  179. } \
  180. if (vha->freq_khz > 0) { \
  181. ndelay(d*1000000/vha->freq_khz); \
  182. } else \
  183. udelay(100); \
  184. } \
  185. WARN_ON(_val_ != _req_); \
  186. img_pdump_printf("POL64 :%s:%#x %#llx %#llx 0 %d %d\n", \
  187. s, (r), _req_, m, c, d); \
  188. } while (0); \
  189. } else { \
  190. _ret_ = IOPOLL64_PDUMP_REGIO(v, c, d, m, o, r, s); \
  191. } \
  192. __IOPOLL64_RET(_ret_); \
  193. })
  194. #else /* VHA_SCF */
  195. #define IOPOLL64_PDUMP_REGIO_PARITY(v, c, d, m, o, r, s) \
  196. IOPOLL64_PDUMP_REGIO(v, c, d, m, o, r, s)
  197. #endif /* VHA_SCF */
  198. #endif /* CONFIG_VHA_DUMMY */
  199. /* poll c-times for the exact register value(v) masked with m,
  200. * using d-cycles delay between polls and log into pdump file
  201. * using specified reg namespace */
  202. #define IOPOLL64_PDUMP(v, c, d, m, r) \
  203. IOPOLL64_PDUMP_REGIO(v, c, d, m, 0, r, "REG")
  204. #define IOPOLL64_CR_PDUMP(v, c, d, m, r) \
  205. IOPOLL64_PDUMP_REGIO(v, c, d, m, 0, VHA_CR_##r, "REG")
  206. #define IOPOLL64_PDUMP_PARITY(v, c, d, m, r) \
  207. IOPOLL64_PDUMP_REGIO_PARITY(v, c, d, m, 0, r, "REG")
  208. #define IOPOLL64_CR_PDUMP_PARITY(v, c, d, m, r) \
  209. IOPOLL64_PDUMP_REGIO_PARITY(v, c, d, m, 0, VHA_CR_##r, "REG")
  210. /* write phys address of buffer to register, and log into pdump */
  211. #define IOWRITE_PDUMP_PHYS(buf, offset, reg) do { \
  212. uint64_t __maybe_unused _addr_ = vha_buf_addr(session, buf); \
  213. vha_plat_write64( \
  214. (ADDR_CAST)session->vha->reg_base + reg,\
  215. _addr_ + offset); \
  216. img_pdump_printf( \
  217. "WRW64 :REG:%#x "_PMEM_":BLOCK_%d:%#x -- '%s%s'\n", \
  218. reg, buf->id, offset, buf->name, \
  219. buf->pcache.valid ? "_cached" : ""); \
  220. } while (0)
  221. /* write virt address of buffer to register, and log into pdump */
  222. #define IOWRITE_PDUMP_VIRT(buf, offset, reg) \
  223. IOWRITE64_PDUMP(buf->devvirt + offset, reg)
  224. /* write address of buffer to register and log into pdump file */
  225. #define IOWRITE_PDUMP_BUFADDR(session, buf, offset, reg) do { \
  226. if (session->vha->mmu_mode) \
  227. IOWRITE_PDUMP_VIRT(buf, offset, reg); \
  228. else if (buf->attr & IMG_MEM_ATTR_OCM) { \
  229. IOWRITE_PDUMP_VIRT(buf, offset, reg); \
  230. } else { \
  231. IOWRITE_PDUMP_PHYS(buf, offset, reg); \
  232. } \
  233. } while (0)
  234. /* write phys address of buffer to register, and log into pdump */
  235. #define SET_PHYS(buf, offset, addr) do { \
  236. uint64_t _addr_ = vha_buf_addr(session, buf); \
  237. *addr = _addr_ + offset; \
  238. } while (0)
  239. /* write virt address of buffer to register, and log into pdump */
  240. #define SET_VIRT(buf, offset, addr) do { \
  241. *addr = buf->devvirt + offset; \
  242. } while (0)
  243. #define SET_BUFADDR(session, buf, offset, addr) do { \
  244. if (session->vha->mmu_mode) \
  245. SET_VIRT(buf, offset, addr); \
  246. else if (buf->attr & IMG_MEM_ATTR_OCM) { \
  247. SET_VIRT(buf, offset, addr); \
  248. } else { \
  249. SET_PHYS(buf, offset, addr); \
  250. } \
  251. } while (0)
  252. /* extract bitfield from a register value */
  253. static inline
  254. uint64_t _get_bits(uint64_t val, uint32_t shift, uint64_t mask)
  255. {
  256. return (val & mask) >> shift;
  257. }
  258. /* set bitfield in a register value */
  259. static inline
  260. uint64_t _set_bits(uint64_t val, uint32_t shift, uint64_t mask)
  261. {
  262. uint64_t v = val << shift;
  263. return v & mask;
  264. }
  265. /* utility macros for manipulating fields within registers */
  266. /* apply bitmask */
  267. #define VHA_CR_BITMASK(reg, field) \
  268. (~VHA_CR_##reg##_##field##_CLRMSK)
  269. /* get field from register */
  270. #define VHA_CR_GETBITS(reg, field, val) \
  271. _get_bits(val, \
  272. VHA_CR_##reg##_##field##_SHIFT, \
  273. VHA_CR_BITMASK(reg, field))
  274. /* get value of a field in a register, taking alignment into account */
  275. #define VHA_CR_ALIGN_GETBITS(reg, field, val) \
  276. (VHA_CR_GETBITS(reg, field, val) \
  277. << VHA_CR_##reg##_##field##_ALIGNSHIFT)
  278. /* apply bitmask - OS dependent */
  279. #define VHA_CR_BITMASK_OS(reg, field) \
  280. ~OSID_TOKEN(VHA_CR_OS, _OSID_, _ ## reg ## _ ## field ## _CLRMSK)
  281. /* get field from register - OS dependent */
  282. #define VHA_CR_GETBITS_OS(reg, field, val) \
  283. _get_bits(val, \
  284. OSID_TOKEN(VHA_CR_OS, _OSID_, _ ## reg ## _ ## field ## _SHIFT), \
  285. VHA_CR_BITMASK_OS(reg, field))
  286. /* get value of a field in a register, taking alignment into account - OS */
  287. #define VHA_CR_ALIGN_GETBITS_OS(reg, field, val) \
  288. (VHA_CR_GETBITS_OS(reg, field, val) \
  289. << OSID_TOKEN(VHA_CR_OS, _OSID_, _ ## reg ## _ ## field ## _ALIGNSHIFT)) \
  290. /* max value of a field */
  291. #define VHA_CR_MAX(reg, field) \
  292. VHA_CR_GETBITS(reg, field, ~0ULL)
  293. /* max value of an field taking alignment into account */
  294. #define VHA_CR_ALIGN_MAX(reg, field) \
  295. (VHA_CR_MAX(reg, field) \
  296. << VHA_CR_##reg##_##field##_SHIFT)
  297. /* max value of a field - OS dependent */
  298. #define VHA_CR_MAX_OS(reg, field) \
  299. VHA_CR_GETBITS_OS(reg, field, ~0ULL)
  300. /* max value of an field taking alignment into account - OS dependent */
  301. #define VHA_CR_ALIGN_MAX_OS(reg, field) \
  302. (VHA_CR_MAX_OS(reg, field) \
  303. << OSID_TOKEN(VHA_CR_OS, _OSID_, _ ## reg ## _ ## field ## _SHIFT)) \
  304. /* set value of a field within a register */
  305. #define VHA_CR_SETBITS(reg, field, val) \
  306. _set_bits(val, \
  307. VHA_CR_##reg##_##field##_SHIFT, \
  308. VHA_CR_BITMASK(reg, field))
  309. /* set value of a field within a register reducing value by alignment */
  310. #define VHA_CR_ALIGN_SETBITS(reg, field, val) \
  311. VHA_CR_SETBITS( \
  312. reg, field, (val) \
  313. >> VHA_CR_##reg##_##field##_ALIGNSHIFT)
  314. /* set value of a field within a register - OS dependent */
  315. #define VHA_CR_SETBITS_OS(reg, field, val) \
  316. _set_bits(val, \
  317. OSID_TOKEN(VHA_CR_OS, _OSID_, _ ## reg ## _ ## field ## _SHIFT), \
  318. VHA_CR_BITMASK_OS(reg, field))
  319. /* set value of a field within a register reducing value by alignment - OS */
  320. #define VHA_CR_ALIGN_SETBITS_OS(reg, field, val) \
  321. VHA_CR_SETBITS_OS( \
  322. reg, field, (val) \
  323. >> OSID_TOKEN(VHA_CR_OS, _OSID_, _ ## reg ## _ ## field ## _ALIGNSHIFT)) \
  324. /* clear bits of a field within a register */
  325. #define VHA_CR_CLEARBITS(val, reg, field) \
  326. (val &= ~VHA_CR_BITMASK(reg, field))
  327. /* clear bits of a field within a register - OS dependent */
  328. #define VHA_CR_CLEARBITS_OS(val, reg, field) \
  329. (val &= ~VHA_CR_BITMASK_OS(reg, field))
  330. #endif /* VHA_IO_H */