coresight-tmc-etr.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. /*
  2. * Copyright(C) 2016 Linaro Limited. All rights reserved.
  3. * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License version 2 as published by
  7. * the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. * more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along with
  15. * this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include <linux/coresight.h>
  18. #include <linux/dma-mapping.h>
  19. #include "coresight-priv.h"
  20. #include "coresight-tmc.h"
  21. static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
  22. {
  23. u32 axictl;
  24. /* Zero out the memory to help with debug */
  25. memset(drvdata->vaddr, 0, drvdata->size);
  26. CS_UNLOCK(drvdata->base);
  27. /* Wait for TMCSReady bit to be set */
  28. tmc_wait_for_tmcready(drvdata);
  29. writel_relaxed(drvdata->size / 4, drvdata->base + TMC_RSZ);
  30. writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
  31. axictl = readl_relaxed(drvdata->base + TMC_AXICTL);
  32. axictl |= TMC_AXICTL_WR_BURST_16;
  33. writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
  34. axictl &= ~TMC_AXICTL_SCT_GAT_MODE;
  35. writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
  36. axictl = (axictl &
  37. ~(TMC_AXICTL_PROT_CTL_B0 | TMC_AXICTL_PROT_CTL_B1)) |
  38. TMC_AXICTL_PROT_CTL_B1;
  39. writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
  40. writel_relaxed(drvdata->paddr, drvdata->base + TMC_DBALO);
  41. writel_relaxed(0x0, drvdata->base + TMC_DBAHI);
  42. writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
  43. TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
  44. TMC_FFCR_TRIGON_TRIGIN,
  45. drvdata->base + TMC_FFCR);
  46. writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
  47. tmc_enable_hw(drvdata);
  48. CS_LOCK(drvdata->base);
  49. }
  50. static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
  51. {
  52. u32 rwp, val;
  53. rwp = readl_relaxed(drvdata->base + TMC_RWP);
  54. val = readl_relaxed(drvdata->base + TMC_STS);
  55. /*
  56. * Adjust the buffer to point to the beginning of the trace data
  57. * and update the available trace data.
  58. */
  59. if (val & TMC_STS_FULL) {
  60. drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
  61. drvdata->len = drvdata->size;
  62. } else {
  63. drvdata->buf = drvdata->vaddr;
  64. drvdata->len = rwp - drvdata->paddr;
  65. }
  66. }
  67. static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
  68. {
  69. CS_UNLOCK(drvdata->base);
  70. tmc_flush_and_stop(drvdata);
  71. /*
  72. * When operating in sysFS mode the content of the buffer needs to be
  73. * read before the TMC is disabled.
  74. */
  75. if (local_read(&drvdata->mode) == CS_MODE_SYSFS)
  76. tmc_etr_dump_hw(drvdata);
  77. tmc_disable_hw(drvdata);
  78. CS_LOCK(drvdata->base);
  79. }
  80. static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev, u32 mode)
  81. {
  82. int ret = 0;
  83. bool used = false;
  84. long val;
  85. unsigned long flags;
  86. void __iomem *vaddr = NULL;
  87. dma_addr_t paddr;
  88. struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
  89. /* This shouldn't be happening */
  90. if (WARN_ON(mode != CS_MODE_SYSFS))
  91. return -EINVAL;
  92. /*
  93. * If we don't have a buffer release the lock and allocate memory.
  94. * Otherwise keep the lock and move along.
  95. */
  96. spin_lock_irqsave(&drvdata->spinlock, flags);
  97. if (!drvdata->vaddr) {
  98. spin_unlock_irqrestore(&drvdata->spinlock, flags);
  99. /*
  100. * Contiguous memory can't be allocated while a spinlock is
  101. * held. As such allocate memory here and free it if a buffer
  102. * has already been allocated (from a previous session).
  103. */
  104. vaddr = dma_alloc_coherent(drvdata->dev, drvdata->size,
  105. &paddr, GFP_KERNEL);
  106. if (!vaddr)
  107. return -ENOMEM;
  108. /* Let's try again */
  109. spin_lock_irqsave(&drvdata->spinlock, flags);
  110. }
  111. if (drvdata->reading) {
  112. ret = -EBUSY;
  113. goto out;
  114. }
  115. val = local_xchg(&drvdata->mode, mode);
  116. /*
  117. * In sysFS mode we can have multiple writers per sink. Since this
  118. * sink is already enabled no memory is needed and the HW need not be
  119. * touched.
  120. */
  121. if (val == CS_MODE_SYSFS)
  122. goto out;
  123. /*
  124. * If drvdata::buf == NULL, use the memory allocated above.
  125. * Otherwise a buffer still exists from a previous session, so
  126. * simply use that.
  127. */
  128. if (drvdata->buf == NULL) {
  129. used = true;
  130. drvdata->vaddr = vaddr;
  131. drvdata->paddr = paddr;
  132. drvdata->buf = drvdata->vaddr;
  133. }
  134. memset(drvdata->vaddr, 0, drvdata->size);
  135. tmc_etr_enable_hw(drvdata);
  136. out:
  137. spin_unlock_irqrestore(&drvdata->spinlock, flags);
  138. /* Free memory outside the spinlock if need be */
  139. if (!used && vaddr)
  140. dma_free_coherent(drvdata->dev, drvdata->size, vaddr, paddr);
  141. if (!ret)
  142. dev_info(drvdata->dev, "TMC-ETR enabled\n");
  143. return ret;
  144. }
  145. static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, u32 mode)
  146. {
  147. int ret = 0;
  148. long val;
  149. unsigned long flags;
  150. struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
  151. /* This shouldn't be happening */
  152. if (WARN_ON(mode != CS_MODE_PERF))
  153. return -EINVAL;
  154. spin_lock_irqsave(&drvdata->spinlock, flags);
  155. if (drvdata->reading) {
  156. ret = -EINVAL;
  157. goto out;
  158. }
  159. val = local_xchg(&drvdata->mode, mode);
  160. /*
  161. * In Perf mode there can be only one writer per sink. There
  162. * is also no need to continue if the ETR is already operated
  163. * from sysFS.
  164. */
  165. if (val != CS_MODE_DISABLED) {
  166. ret = -EINVAL;
  167. goto out;
  168. }
  169. tmc_etr_enable_hw(drvdata);
  170. out:
  171. spin_unlock_irqrestore(&drvdata->spinlock, flags);
  172. return ret;
  173. }
  174. static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
  175. {
  176. switch (mode) {
  177. case CS_MODE_SYSFS:
  178. return tmc_enable_etr_sink_sysfs(csdev, mode);
  179. case CS_MODE_PERF:
  180. return tmc_enable_etr_sink_perf(csdev, mode);
  181. }
  182. /* We shouldn't be here */
  183. return -EINVAL;
  184. }
  185. static void tmc_disable_etr_sink(struct coresight_device *csdev)
  186. {
  187. long val;
  188. unsigned long flags;
  189. struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
  190. spin_lock_irqsave(&drvdata->spinlock, flags);
  191. if (drvdata->reading) {
  192. spin_unlock_irqrestore(&drvdata->spinlock, flags);
  193. return;
  194. }
  195. val = local_xchg(&drvdata->mode, CS_MODE_DISABLED);
  196. /* Disable the TMC only if it needs to */
  197. if (val != CS_MODE_DISABLED)
  198. tmc_etr_disable_hw(drvdata);
  199. spin_unlock_irqrestore(&drvdata->spinlock, flags);
  200. dev_info(drvdata->dev, "TMC-ETR disabled\n");
  201. }
  202. static const struct coresight_ops_sink tmc_etr_sink_ops = {
  203. .enable = tmc_enable_etr_sink,
  204. .disable = tmc_disable_etr_sink,
  205. };
  206. const struct coresight_ops tmc_etr_cs_ops = {
  207. .sink_ops = &tmc_etr_sink_ops,
  208. };
  209. int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
  210. {
  211. int ret = 0;
  212. long val;
  213. unsigned long flags;
  214. /* config types are set a boot time and never change */
  215. if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
  216. return -EINVAL;
  217. spin_lock_irqsave(&drvdata->spinlock, flags);
  218. if (drvdata->reading) {
  219. ret = -EBUSY;
  220. goto out;
  221. }
  222. val = local_read(&drvdata->mode);
  223. /* Don't interfere if operated from Perf */
  224. if (val == CS_MODE_PERF) {
  225. ret = -EINVAL;
  226. goto out;
  227. }
  228. /* If drvdata::buf is NULL the trace data has been read already */
  229. if (drvdata->buf == NULL) {
  230. ret = -EINVAL;
  231. goto out;
  232. }
  233. /* Disable the TMC if need be */
  234. if (val == CS_MODE_SYSFS)
  235. tmc_etr_disable_hw(drvdata);
  236. drvdata->reading = true;
  237. out:
  238. spin_unlock_irqrestore(&drvdata->spinlock, flags);
  239. return ret;
  240. }
  241. int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
  242. {
  243. unsigned long flags;
  244. dma_addr_t paddr;
  245. void __iomem *vaddr = NULL;
  246. /* config types are set a boot time and never change */
  247. if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
  248. return -EINVAL;
  249. spin_lock_irqsave(&drvdata->spinlock, flags);
  250. /* RE-enable the TMC if need be */
  251. if (local_read(&drvdata->mode) == CS_MODE_SYSFS) {
  252. /*
  253. * The trace run will continue with the same allocated trace
  254. * buffer. The trace buffer is cleared in tmc_etr_enable_hw(),
  255. * so we don't have to explicitly clear it. Also, since the
  256. * tracer is still enabled drvdata::buf can't be NULL.
  257. */
  258. tmc_etr_enable_hw(drvdata);
  259. } else {
  260. /*
  261. * The ETR is not tracing and the buffer was just read.
  262. * As such prepare to free the trace buffer.
  263. */
  264. vaddr = drvdata->vaddr;
  265. paddr = drvdata->paddr;
  266. drvdata->buf = drvdata->vaddr = NULL;
  267. }
  268. drvdata->reading = false;
  269. spin_unlock_irqrestore(&drvdata->spinlock, flags);
  270. /* Free allocated memory out side of the spinlock */
  271. if (vaddr)
  272. dma_free_coherent(drvdata->dev, drvdata->size, vaddr, paddr);
  273. return 0;
  274. }