syncpt_hw.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /*
  2. * Tegra host1x Syncpoints
  3. *
  4. * Copyright (c) 2010-2013, NVIDIA Corporation.
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms and conditions of the GNU General Public License,
  8. * version 2, as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <linux/io.h>
  19. #include "../dev.h"
  20. #include "../syncpt.h"
  21. /*
  22. * Write the current syncpoint value back to hw.
  23. */
  24. static void syncpt_restore(struct host1x_syncpt *sp)
  25. {
  26. u32 min = host1x_syncpt_read_min(sp);
  27. struct host1x *host = sp->host;
  28. host1x_sync_writel(host, min, HOST1X_SYNC_SYNCPT(sp->id));
  29. }
  30. /*
  31. * Write the current waitbase value back to hw.
  32. */
  33. static void syncpt_restore_wait_base(struct host1x_syncpt *sp)
  34. {
  35. struct host1x *host = sp->host;
  36. host1x_sync_writel(host, sp->base_val,
  37. HOST1X_SYNC_SYNCPT_BASE(sp->id));
  38. }
  39. /*
  40. * Read waitbase value from hw.
  41. */
  42. static void syncpt_read_wait_base(struct host1x_syncpt *sp)
  43. {
  44. struct host1x *host = sp->host;
  45. sp->base_val =
  46. host1x_sync_readl(host, HOST1X_SYNC_SYNCPT_BASE(sp->id));
  47. }
  48. /*
  49. * Updates the last value read from hardware.
  50. */
  51. static u32 syncpt_load(struct host1x_syncpt *sp)
  52. {
  53. struct host1x *host = sp->host;
  54. u32 old, live;
  55. /* Loop in case there's a race writing to min_val */
  56. do {
  57. old = host1x_syncpt_read_min(sp);
  58. live = host1x_sync_readl(host, HOST1X_SYNC_SYNCPT(sp->id));
  59. } while ((u32)atomic_cmpxchg(&sp->min_val, old, live) != old);
  60. if (!host1x_syncpt_check_max(sp, live))
  61. dev_err(host->dev, "%s failed: id=%u, min=%d, max=%d\n",
  62. __func__, sp->id, host1x_syncpt_read_min(sp),
  63. host1x_syncpt_read_max(sp));
  64. return live;
  65. }
  66. /*
  67. * Write a cpu syncpoint increment to the hardware, without touching
  68. * the cache.
  69. */
  70. static int syncpt_cpu_incr(struct host1x_syncpt *sp)
  71. {
  72. struct host1x *host = sp->host;
  73. u32 reg_offset = sp->id / 32;
  74. if (!host1x_syncpt_client_managed(sp) &&
  75. host1x_syncpt_idle(sp))
  76. return -EINVAL;
  77. host1x_sync_writel(host, BIT(sp->id % 32),
  78. HOST1X_SYNC_SYNCPT_CPU_INCR(reg_offset));
  79. wmb();
  80. return 0;
  81. }
  82. /**
  83. * syncpt_assign_to_channel() - Assign syncpoint to channel
  84. * @sp: syncpoint
  85. * @ch: channel
  86. *
  87. * On chips with the syncpoint protection feature (Tegra186+), assign @sp to
  88. * @ch, preventing other channels from incrementing the syncpoints. If @ch is
  89. * NULL, unassigns the syncpoint.
  90. *
  91. * On older chips, do nothing.
  92. */
  93. static void syncpt_assign_to_channel(struct host1x_syncpt *sp,
  94. struct host1x_channel *ch)
  95. {
  96. #if HOST1X_HW >= 6
  97. struct host1x *host = sp->host;
  98. if (!host->hv_regs)
  99. return;
  100. host1x_sync_writel(host,
  101. HOST1X_SYNC_SYNCPT_CH_APP_CH(ch ? ch->id : 0xff),
  102. HOST1X_SYNC_SYNCPT_CH_APP(sp->id));
  103. #endif
  104. }
  105. /**
  106. * syncpt_enable_protection() - Enable syncpoint protection
  107. * @host: host1x instance
  108. *
  109. * On chips with the syncpoint protection feature (Tegra186+), enable this
  110. * feature. On older chips, do nothing.
  111. */
  112. static void syncpt_enable_protection(struct host1x *host)
  113. {
  114. #if HOST1X_HW >= 6
  115. if (!host->hv_regs)
  116. return;
  117. host1x_hypervisor_writel(host, HOST1X_HV_SYNCPT_PROT_EN_CH_EN,
  118. HOST1X_HV_SYNCPT_PROT_EN);
  119. #endif
  120. }
  121. static const struct host1x_syncpt_ops host1x_syncpt_ops = {
  122. .restore = syncpt_restore,
  123. .restore_wait_base = syncpt_restore_wait_base,
  124. .load_wait_base = syncpt_read_wait_base,
  125. .load = syncpt_load,
  126. .cpu_incr = syncpt_cpu_incr,
  127. .assign_to_channel = syncpt_assign_to_channel,
  128. .enable_protection = syncpt_enable_protection,
  129. };