xtensa.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * Copyright 2013 Ilia Mirkin
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  17. * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18. * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20. * OTHER DEALINGS IN THE SOFTWARE.
  21. */
  22. #include <engine/xtensa.h>
  23. u32
  24. _nouveau_xtensa_rd32(struct nouveau_object *object, u64 addr)
  25. {
  26. struct nouveau_xtensa *xtensa = (void *)object;
  27. return nv_rd32(xtensa, xtensa->addr + addr);
  28. }
  29. void
  30. _nouveau_xtensa_wr32(struct nouveau_object *object, u64 addr, u32 data)
  31. {
  32. struct nouveau_xtensa *xtensa = (void *)object;
  33. nv_wr32(xtensa, xtensa->addr + addr, data);
  34. }
  35. int
  36. _nouveau_xtensa_engctx_ctor(struct nouveau_object *parent,
  37. struct nouveau_object *engine,
  38. struct nouveau_oclass *oclass, void *data, u32 size,
  39. struct nouveau_object **pobject)
  40. {
  41. struct nouveau_engctx *engctx;
  42. int ret;
  43. ret = nouveau_engctx_create(parent, engine, oclass, NULL,
  44. 0x10000, 0x1000,
  45. NVOBJ_FLAG_ZERO_ALLOC, &engctx);
  46. *pobject = nv_object(engctx);
  47. return ret;
  48. }
  49. void
  50. _nouveau_xtensa_intr(struct nouveau_subdev *subdev)
  51. {
  52. struct nouveau_xtensa *xtensa = (void *)subdev;
  53. u32 unk104 = nv_ro32(xtensa, 0xd04);
  54. u32 intr = nv_ro32(xtensa, 0xc20);
  55. u32 chan = nv_ro32(xtensa, 0xc28);
  56. u32 unk10c = nv_ro32(xtensa, 0xd0c);
  57. if (intr & 0x10)
  58. nv_warn(xtensa, "Watchdog interrupt, engine hung.\n");
  59. nv_wo32(xtensa, 0xc20, intr);
  60. intr = nv_ro32(xtensa, 0xc20);
  61. if (unk104 == 0x10001 && unk10c == 0x200 && chan && !intr) {
  62. nv_debug(xtensa, "Enabling FIFO_CTRL\n");
  63. nv_mask(xtensa, xtensa->addr + 0xd94, 0, xtensa->fifo_val);
  64. }
  65. }
  66. int
  67. nouveau_xtensa_create_(struct nouveau_object *parent,
  68. struct nouveau_object *engine,
  69. struct nouveau_oclass *oclass, u32 addr, bool enable,
  70. const char *iname, const char *fname,
  71. int length, void **pobject)
  72. {
  73. struct nouveau_xtensa *xtensa;
  74. int ret;
  75. ret = nouveau_engine_create_(parent, engine, oclass, enable, iname,
  76. fname, length, pobject);
  77. xtensa = *pobject;
  78. if (ret)
  79. return ret;
  80. nv_subdev(xtensa)->intr = _nouveau_xtensa_intr;
  81. xtensa->addr = addr;
  82. return 0;
  83. }
  84. int
  85. _nouveau_xtensa_init(struct nouveau_object *object)
  86. {
  87. struct nouveau_device *device = nv_device(object);
  88. struct nouveau_xtensa *xtensa = (void *)object;
  89. const struct firmware *fw;
  90. char name[32];
  91. int i, ret;
  92. u32 tmp;
  93. ret = nouveau_engine_init(&xtensa->base);
  94. if (ret)
  95. return ret;
  96. if (!xtensa->gpu_fw) {
  97. snprintf(name, sizeof(name), "nouveau/nv84_xuc%03x",
  98. xtensa->addr >> 12);
  99. ret = request_firmware(&fw, name, nv_device_base(device));
  100. if (ret) {
  101. nv_warn(xtensa, "unable to load firmware %s\n", name);
  102. return ret;
  103. }
  104. if (fw->size > 0x40000) {
  105. nv_warn(xtensa, "firmware %s too large\n", name);
  106. release_firmware(fw);
  107. return -EINVAL;
  108. }
  109. ret = nouveau_gpuobj_new(object, NULL, 0x40000, 0x1000, 0,
  110. &xtensa->gpu_fw);
  111. if (ret) {
  112. release_firmware(fw);
  113. return ret;
  114. }
  115. nv_debug(xtensa, "Loading firmware to address: 0x%llx\n",
  116. xtensa->gpu_fw->addr);
  117. for (i = 0; i < fw->size / 4; i++)
  118. nv_wo32(xtensa->gpu_fw, i * 4, *((u32 *)fw->data + i));
  119. release_firmware(fw);
  120. }
  121. nv_wo32(xtensa, 0xd10, 0x1fffffff); /* ?? */
  122. nv_wo32(xtensa, 0xd08, 0x0fffffff); /* ?? */
  123. nv_wo32(xtensa, 0xd28, xtensa->unkd28); /* ?? */
  124. nv_wo32(xtensa, 0xc20, 0x3f); /* INTR */
  125. nv_wo32(xtensa, 0xd84, 0x3f); /* INTR_EN */
  126. nv_wo32(xtensa, 0xcc0, xtensa->gpu_fw->addr >> 8); /* XT_REGION_BASE */
  127. nv_wo32(xtensa, 0xcc4, 0x1c); /* XT_REGION_SETUP */
  128. nv_wo32(xtensa, 0xcc8, xtensa->gpu_fw->size >> 8); /* XT_REGION_LIMIT */
  129. tmp = nv_rd32(xtensa, 0x0);
  130. nv_wo32(xtensa, 0xde0, tmp); /* SCRATCH_H2X */
  131. nv_wo32(xtensa, 0xce8, 0xf); /* XT_REGION_SETUP */
  132. nv_wo32(xtensa, 0xc20, 0x3f); /* INTR */
  133. nv_wo32(xtensa, 0xd84, 0x3f); /* INTR_EN */
  134. return 0;
  135. }
  136. int
  137. _nouveau_xtensa_fini(struct nouveau_object *object, bool suspend)
  138. {
  139. struct nouveau_xtensa *xtensa = (void *)object;
  140. nv_wo32(xtensa, 0xd84, 0); /* INTR_EN */
  141. nv_wo32(xtensa, 0xd94, 0); /* FIFO_CTRL */
  142. if (!suspend)
  143. nouveau_gpuobj_ref(NULL, &xtensa->gpu_fw);
  144. return nouveau_engine_fini(&xtensa->base, suspend);
  145. }