base.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. * Copyright 2012 Red Hat Inc.
  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. * Authors: Ben Skeggs
  23. */
  24. #include "priv.h"
  25. #include <core/option.h>
  26. void
  27. nvkm_mc_unk260(struct nvkm_mc *mc, u32 data)
  28. {
  29. if (mc->func->unk260)
  30. mc->func->unk260(mc, data);
  31. }
  32. void
  33. nvkm_mc_intr_unarm(struct nvkm_mc *mc)
  34. {
  35. return mc->func->intr_unarm(mc);
  36. }
  37. void
  38. nvkm_mc_intr_rearm(struct nvkm_mc *mc)
  39. {
  40. return mc->func->intr_rearm(mc);
  41. }
  42. static u32
  43. nvkm_mc_intr_mask(struct nvkm_mc *mc)
  44. {
  45. u32 intr = mc->func->intr_mask(mc);
  46. if (WARN_ON_ONCE(intr == 0xffffffff))
  47. intr = 0; /* likely fallen off the bus */
  48. return intr;
  49. }
  50. void
  51. nvkm_mc_intr(struct nvkm_mc *mc, bool *handled)
  52. {
  53. struct nvkm_device *device = mc->subdev.device;
  54. struct nvkm_subdev *subdev;
  55. const struct nvkm_mc_intr *map = mc->func->intr;
  56. u32 stat, intr;
  57. stat = intr = nvkm_mc_intr_mask(mc);
  58. while (map->stat) {
  59. if (intr & map->stat) {
  60. subdev = nvkm_device_subdev(device, map->unit);
  61. if (subdev)
  62. nvkm_subdev_intr(subdev);
  63. stat &= ~map->stat;
  64. }
  65. map++;
  66. }
  67. if (stat)
  68. nvkm_error(&mc->subdev, "intr %08x\n", stat);
  69. *handled = intr != 0;
  70. }
  71. static int
  72. nvkm_mc_fini(struct nvkm_subdev *subdev, bool suspend)
  73. {
  74. struct nvkm_mc *mc = nvkm_mc(subdev);
  75. nvkm_mc_intr_unarm(mc);
  76. return 0;
  77. }
  78. static int
  79. nvkm_mc_init(struct nvkm_subdev *subdev)
  80. {
  81. struct nvkm_mc *mc = nvkm_mc(subdev);
  82. if (mc->func->init)
  83. mc->func->init(mc);
  84. nvkm_mc_intr_rearm(mc);
  85. return 0;
  86. }
  87. static void *
  88. nvkm_mc_dtor(struct nvkm_subdev *subdev)
  89. {
  90. return nvkm_mc(subdev);
  91. }
  92. static const struct nvkm_subdev_func
  93. nvkm_mc = {
  94. .dtor = nvkm_mc_dtor,
  95. .init = nvkm_mc_init,
  96. .fini = nvkm_mc_fini,
  97. };
  98. int
  99. nvkm_mc_new_(const struct nvkm_mc_func *func, struct nvkm_device *device,
  100. int index, struct nvkm_mc **pmc)
  101. {
  102. struct nvkm_mc *mc;
  103. if (!(mc = *pmc = kzalloc(sizeof(*mc), GFP_KERNEL)))
  104. return -ENOMEM;
  105. nvkm_subdev_ctor(&nvkm_mc, device, index, 0, &mc->subdev);
  106. mc->func = func;
  107. return 0;
  108. }