2 * Copyright(C) 2016 Linaro Limited. All rights reserved.
3 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
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.
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
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/>.
18 #include <linux/coresight.h>
19 #include "coresight-priv.h"
20 #include "coresight-tmc.h"
22 void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
24 /* Zero out the memory to help with debug */
25 memset(drvdata->buf, 0, drvdata->size);
27 CS_UNLOCK(drvdata->base);
29 /* Wait for TMCSReady bit to be set */
30 tmc_wait_for_tmcready(drvdata);
32 writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
33 writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
34 TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
35 TMC_FFCR_TRIGON_TRIGIN,
36 drvdata->base + TMC_FFCR);
38 writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
39 tmc_enable_hw(drvdata);
41 CS_LOCK(drvdata->base);
44 static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
46 enum tmc_mem_intf_width memwidth;
52 memwidth = BMVAL(readl_relaxed(drvdata->base + CORESIGHT_DEVID), 8, 10);
53 if (memwidth == TMC_MEM_INTF_WIDTH_32BITS)
55 else if (memwidth == TMC_MEM_INTF_WIDTH_64BITS)
57 else if (memwidth == TMC_MEM_INTF_WIDTH_128BITS)
64 for (i = 0; i < memwords; i++) {
65 read_data = readl_relaxed(drvdata->base + TMC_RRD);
66 if (read_data == 0xFFFFFFFF)
68 memcpy(bufp, &read_data, 4);
74 void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
76 CS_UNLOCK(drvdata->base);
78 tmc_flush_and_stop(drvdata);
79 tmc_etb_dump_hw(drvdata);
80 tmc_disable_hw(drvdata);
82 CS_LOCK(drvdata->base);
85 static void tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
87 CS_UNLOCK(drvdata->base);
89 /* Wait for TMCSReady bit to be set */
90 tmc_wait_for_tmcready(drvdata);
92 writel_relaxed(TMC_MODE_HARDWARE_FIFO, drvdata->base + TMC_MODE);
93 writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI,
94 drvdata->base + TMC_FFCR);
95 writel_relaxed(0x0, drvdata->base + TMC_BUFWM);
96 tmc_enable_hw(drvdata);
98 CS_LOCK(drvdata->base);
101 static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
103 CS_UNLOCK(drvdata->base);
105 tmc_flush_and_stop(drvdata);
106 tmc_disable_hw(drvdata);
108 CS_LOCK(drvdata->base);
111 static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
114 struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
116 spin_lock_irqsave(&drvdata->spinlock, flags);
117 if (drvdata->reading) {
118 spin_unlock_irqrestore(&drvdata->spinlock, flags);
122 tmc_etb_enable_hw(drvdata);
123 drvdata->enable = true;
124 spin_unlock_irqrestore(&drvdata->spinlock, flags);
126 dev_info(drvdata->dev, "TMC-ETB/ETF enabled\n");
130 static void tmc_disable_etf_sink(struct coresight_device *csdev)
133 struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
135 spin_lock_irqsave(&drvdata->spinlock, flags);
136 if (drvdata->reading) {
137 spin_unlock_irqrestore(&drvdata->spinlock, flags);
141 tmc_etb_disable_hw(drvdata);
142 drvdata->enable = false;
143 spin_unlock_irqrestore(&drvdata->spinlock, flags);
145 dev_info(drvdata->dev, "TMC-ETB/ETF disabled\n");
148 static int tmc_enable_etf_link(struct coresight_device *csdev,
149 int inport, int outport)
152 struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
154 spin_lock_irqsave(&drvdata->spinlock, flags);
155 if (drvdata->reading) {
156 spin_unlock_irqrestore(&drvdata->spinlock, flags);
160 tmc_etf_enable_hw(drvdata);
161 drvdata->enable = true;
162 spin_unlock_irqrestore(&drvdata->spinlock, flags);
164 dev_info(drvdata->dev, "TMC-ETF enabled\n");
168 static void tmc_disable_etf_link(struct coresight_device *csdev,
169 int inport, int outport)
172 struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
174 spin_lock_irqsave(&drvdata->spinlock, flags);
175 if (drvdata->reading) {
176 spin_unlock_irqrestore(&drvdata->spinlock, flags);
180 tmc_etf_disable_hw(drvdata);
181 drvdata->enable = false;
182 spin_unlock_irqrestore(&drvdata->spinlock, flags);
184 dev_info(drvdata->dev, "TMC disabled\n");
187 static const struct coresight_ops_sink tmc_etf_sink_ops = {
188 .enable = tmc_enable_etf_sink,
189 .disable = tmc_disable_etf_sink,
192 static const struct coresight_ops_link tmc_etf_link_ops = {
193 .enable = tmc_enable_etf_link,
194 .disable = tmc_disable_etf_link,
197 const struct coresight_ops tmc_etb_cs_ops = {
198 .sink_ops = &tmc_etf_sink_ops,
201 const struct coresight_ops tmc_etf_cs_ops = {
202 .sink_ops = &tmc_etf_sink_ops,
203 .link_ops = &tmc_etf_link_ops,