intel_pcode.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. // SPDX-License-Identifier: MIT
  2. /*
  3. * Copyright © 2013-2021 Intel Corporation
  4. */
  5. #include <drm/drm_print.h>
  6. #include "i915_drv.h"
  7. #include "i915_reg.h"
  8. #include "i915_wait_util.h"
  9. #include "intel_pcode.h"
  10. static int gen6_check_mailbox_status(u32 mbox)
  11. {
  12. switch (mbox & GEN6_PCODE_ERROR_MASK) {
  13. case GEN6_PCODE_SUCCESS:
  14. return 0;
  15. case GEN6_PCODE_UNIMPLEMENTED_CMD:
  16. return -ENODEV;
  17. case GEN6_PCODE_ILLEGAL_CMD:
  18. return -ENXIO;
  19. case GEN6_PCODE_MIN_FREQ_TABLE_GT_RATIO_OUT_OF_RANGE:
  20. case GEN7_PCODE_MIN_FREQ_TABLE_GT_RATIO_OUT_OF_RANGE:
  21. return -EOVERFLOW;
  22. case GEN6_PCODE_TIMEOUT:
  23. return -ETIMEDOUT;
  24. default:
  25. MISSING_CASE(mbox & GEN6_PCODE_ERROR_MASK);
  26. return 0;
  27. }
  28. }
  29. static int gen7_check_mailbox_status(u32 mbox)
  30. {
  31. switch (mbox & GEN6_PCODE_ERROR_MASK) {
  32. case GEN6_PCODE_SUCCESS:
  33. return 0;
  34. case GEN6_PCODE_ILLEGAL_CMD:
  35. return -ENXIO;
  36. case GEN7_PCODE_TIMEOUT:
  37. return -ETIMEDOUT;
  38. case GEN7_PCODE_ILLEGAL_DATA:
  39. return -EINVAL;
  40. case GEN11_PCODE_ILLEGAL_SUBCOMMAND:
  41. return -ENXIO;
  42. case GEN11_PCODE_LOCKED:
  43. return -EBUSY;
  44. case GEN11_PCODE_REJECTED:
  45. return -EACCES;
  46. case GEN7_PCODE_MIN_FREQ_TABLE_GT_RATIO_OUT_OF_RANGE:
  47. return -EOVERFLOW;
  48. default:
  49. MISSING_CASE(mbox & GEN6_PCODE_ERROR_MASK);
  50. return 0;
  51. }
  52. }
  53. static int __snb_pcode_rw(struct intel_uncore *uncore, u32 mbox,
  54. u32 *val, u32 *val1,
  55. int fast_timeout_us, int slow_timeout_ms,
  56. bool is_read)
  57. {
  58. lockdep_assert_held(&uncore->i915->sb_lock);
  59. /*
  60. * GEN6_PCODE_* are outside of the forcewake domain, we can use
  61. * intel_uncore_read/write_fw variants to reduce the amount of work
  62. * required when reading/writing.
  63. */
  64. if (intel_uncore_read_fw(uncore, GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY)
  65. return -EAGAIN;
  66. intel_uncore_write_fw(uncore, GEN6_PCODE_DATA, *val);
  67. intel_uncore_write_fw(uncore, GEN6_PCODE_DATA1, val1 ? *val1 : 0);
  68. intel_uncore_write_fw(uncore,
  69. GEN6_PCODE_MAILBOX, GEN6_PCODE_READY | mbox);
  70. if (__intel_wait_for_register_fw(uncore,
  71. GEN6_PCODE_MAILBOX,
  72. GEN6_PCODE_READY, 0,
  73. fast_timeout_us,
  74. slow_timeout_ms,
  75. &mbox))
  76. return -ETIMEDOUT;
  77. if (is_read)
  78. *val = intel_uncore_read_fw(uncore, GEN6_PCODE_DATA);
  79. if (is_read && val1)
  80. *val1 = intel_uncore_read_fw(uncore, GEN6_PCODE_DATA1);
  81. if (GRAPHICS_VER(uncore->i915) > 6)
  82. return gen7_check_mailbox_status(mbox);
  83. else
  84. return gen6_check_mailbox_status(mbox);
  85. }
  86. int snb_pcode_read(struct intel_uncore *uncore, u32 mbox, u32 *val, u32 *val1)
  87. {
  88. int err;
  89. mutex_lock(&uncore->i915->sb_lock);
  90. err = __snb_pcode_rw(uncore, mbox, val, val1, 500, 20, true);
  91. mutex_unlock(&uncore->i915->sb_lock);
  92. if (err) {
  93. drm_dbg(&uncore->i915->drm,
  94. "warning: pcode (read from mbox %x) mailbox access failed for %ps: %d\n",
  95. mbox, __builtin_return_address(0), err);
  96. }
  97. return err;
  98. }
  99. int snb_pcode_write_timeout(struct intel_uncore *uncore, u32 mbox, u32 val,
  100. int timeout_ms)
  101. {
  102. int err;
  103. mutex_lock(&uncore->i915->sb_lock);
  104. err = __snb_pcode_rw(uncore, mbox, &val, NULL, 250, timeout_ms, false);
  105. mutex_unlock(&uncore->i915->sb_lock);
  106. if (err) {
  107. drm_dbg(&uncore->i915->drm,
  108. "warning: pcode (write of 0x%08x to mbox %x) mailbox access failed for %ps: %d\n",
  109. val, mbox, __builtin_return_address(0), err);
  110. }
  111. return err;
  112. }
  113. static bool skl_pcode_try_request(struct intel_uncore *uncore, u32 mbox,
  114. u32 request, u32 reply_mask, u32 reply,
  115. u32 *status)
  116. {
  117. *status = __snb_pcode_rw(uncore, mbox, &request, NULL, 500, 0, true);
  118. return (*status == 0) && ((request & reply_mask) == reply);
  119. }
  120. /**
  121. * skl_pcode_request - send PCODE request until acknowledgment
  122. * @uncore: uncore
  123. * @mbox: PCODE mailbox ID the request is targeted for
  124. * @request: request ID
  125. * @reply_mask: mask used to check for request acknowledgment
  126. * @reply: value used to check for request acknowledgment
  127. * @timeout_base_ms: timeout for polling with preemption enabled
  128. *
  129. * Keep resending the @request to @mbox until PCODE acknowledges it, PCODE
  130. * reports an error or an overall timeout of @timeout_base_ms+50 ms expires.
  131. * The request is acknowledged once the PCODE reply dword equals @reply after
  132. * applying @reply_mask. Polling is first attempted with preemption enabled
  133. * for @timeout_base_ms and if this times out for another 50 ms with
  134. * preemption disabled.
  135. *
  136. * Returns 0 on success, %-ETIMEDOUT in case of a timeout, <0 in case of some
  137. * other error as reported by PCODE.
  138. */
  139. int skl_pcode_request(struct intel_uncore *uncore, u32 mbox, u32 request,
  140. u32 reply_mask, u32 reply, int timeout_base_ms)
  141. {
  142. u32 status;
  143. int ret;
  144. mutex_lock(&uncore->i915->sb_lock);
  145. #define COND \
  146. skl_pcode_try_request(uncore, mbox, request, reply_mask, reply, &status)
  147. /*
  148. * Prime the PCODE by doing a request first. Normally it guarantees
  149. * that a subsequent request, at most @timeout_base_ms later, succeeds.
  150. * _wait_for() doesn't guarantee when its passed condition is evaluated
  151. * first, so send the first request explicitly.
  152. */
  153. if (COND) {
  154. ret = 0;
  155. goto out;
  156. }
  157. ret = _wait_for(COND, timeout_base_ms * 1000, 10, 10);
  158. if (!ret)
  159. goto out;
  160. /*
  161. * The above can time out if the number of requests was low (2 in the
  162. * worst case) _and_ PCODE was busy for some reason even after a
  163. * (queued) request and @timeout_base_ms delay. As a workaround retry
  164. * the poll with preemption disabled to maximize the number of
  165. * requests. Increase the timeout from @timeout_base_ms to 50ms to
  166. * account for interrupts that could reduce the number of these
  167. * requests, and for any quirks of the PCODE firmware that delays
  168. * the request completion.
  169. */
  170. drm_dbg_kms(&uncore->i915->drm,
  171. "PCODE timeout, retrying with preemption disabled\n");
  172. drm_WARN_ON_ONCE(&uncore->i915->drm, timeout_base_ms > 3);
  173. preempt_disable();
  174. ret = wait_for_atomic(COND, 50);
  175. preempt_enable();
  176. out:
  177. mutex_unlock(&uncore->i915->sb_lock);
  178. return status ? status : ret;
  179. #undef COND
  180. }
  181. static int pcode_init_wait(struct intel_uncore *uncore, int timeout_ms)
  182. {
  183. if (__intel_wait_for_register_fw(uncore,
  184. GEN6_PCODE_MAILBOX,
  185. GEN6_PCODE_READY, 0,
  186. 500, timeout_ms,
  187. NULL))
  188. return -EPROBE_DEFER;
  189. return skl_pcode_request(uncore,
  190. DG1_PCODE_STATUS,
  191. DG1_UNCORE_GET_INIT_STATUS,
  192. DG1_UNCORE_INIT_STATUS_COMPLETE,
  193. DG1_UNCORE_INIT_STATUS_COMPLETE, timeout_ms);
  194. }
  195. int intel_pcode_init(struct intel_uncore *uncore)
  196. {
  197. int err;
  198. if (!IS_DGFX(uncore->i915))
  199. return 0;
  200. /*
  201. * Wait 10 seconds so that the punit to settle and complete
  202. * any outstanding transactions upon module load
  203. */
  204. err = pcode_init_wait(uncore, 10000);
  205. if (err) {
  206. drm_notice(&uncore->i915->drm,
  207. "Waiting for HW initialisation...\n");
  208. err = pcode_init_wait(uncore, 180000);
  209. }
  210. return err;
  211. }
  212. int snb_pcode_read_p(struct intel_uncore *uncore, u32 mbcmd, u32 p1, u32 p2, u32 *val)
  213. {
  214. intel_wakeref_t wakeref;
  215. u32 mbox;
  216. int err;
  217. mbox = REG_FIELD_PREP(GEN6_PCODE_MB_COMMAND, mbcmd)
  218. | REG_FIELD_PREP(GEN6_PCODE_MB_PARAM1, p1)
  219. | REG_FIELD_PREP(GEN6_PCODE_MB_PARAM2, p2);
  220. with_intel_runtime_pm(uncore->rpm, wakeref)
  221. err = snb_pcode_read(uncore, mbox, val, NULL);
  222. return err;
  223. }
  224. int snb_pcode_write_p(struct intel_uncore *uncore, u32 mbcmd, u32 p1, u32 p2, u32 val)
  225. {
  226. intel_wakeref_t wakeref;
  227. u32 mbox;
  228. int err;
  229. mbox = REG_FIELD_PREP(GEN6_PCODE_MB_COMMAND, mbcmd)
  230. | REG_FIELD_PREP(GEN6_PCODE_MB_PARAM1, p1)
  231. | REG_FIELD_PREP(GEN6_PCODE_MB_PARAM2, p2);
  232. with_intel_runtime_pm(uncore->rpm, wakeref)
  233. err = snb_pcode_write(uncore, mbox, val);
  234. return err;
  235. }
  236. /* Helpers with drm device */
  237. int intel_pcode_read(struct drm_device *drm, u32 mbox, u32 *val, u32 *val1)
  238. {
  239. struct drm_i915_private *i915 = to_i915(drm);
  240. return snb_pcode_read(&i915->uncore, mbox, val, val1);
  241. }
  242. int intel_pcode_write_timeout(struct drm_device *drm, u32 mbox, u32 val, int timeout_ms)
  243. {
  244. struct drm_i915_private *i915 = to_i915(drm);
  245. return snb_pcode_write_timeout(&i915->uncore, mbox, val, timeout_ms);
  246. }
  247. int intel_pcode_request(struct drm_device *drm, u32 mbox, u32 request,
  248. u32 reply_mask, u32 reply, int timeout_base_ms)
  249. {
  250. struct drm_i915_private *i915 = to_i915(drm);
  251. return skl_pcode_request(&i915->uncore, mbox, request, reply_mask, reply,
  252. timeout_base_ms);
  253. }