syncpt_hw.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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. struct host1x *host = sp->host;
  27. int min = host1x_syncpt_read_min(sp);
  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_MASK(sp->id),
  78. HOST1X_SYNC_SYNCPT_CPU_INCR(reg_offset));
  79. wmb();
  80. return 0;
  81. }
  82. /* remove a wait pointed to by patch_addr */
  83. static int syncpt_patch_wait(struct host1x_syncpt *sp, void *patch_addr)
  84. {
  85. u32 override = host1x_class_host_wait_syncpt(
  86. HOST1X_SYNCPT_RESERVED, 0);
  87. *((u32 *)patch_addr) = override;
  88. return 0;
  89. }
  90. static const struct host1x_syncpt_ops host1x_syncpt_ops = {
  91. .restore = syncpt_restore,
  92. .restore_wait_base = syncpt_restore_wait_base,
  93. .load_wait_base = syncpt_read_wait_base,
  94. .load = syncpt_load,
  95. .cpu_incr = syncpt_cpu_incr,
  96. .patch_wait = syncpt_patch_wait,
  97. };