Skip to content

Commit de03aea

Browse files
coresight: tmc: splitting driver in ETB/ETF and ETR components
The TMC block can operate in 3 modes (ETB, ETF and ETR) and accessed via two interfaces (sysFS and Perf). That makes 6 mode to cover, which is way too much coupling for a single file. This patch splits the original TMC driver in 2 halves, one for ETB/ETF and another one for ETR mode. A common core is kept for functionality common to all 3 modes. Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> (cherry picked from commit 6c6ed1e244c0530fb76a8b52024f199f398ef100)
1 parent 5364b7d commit de03aea

5 files changed

Lines changed: 357 additions & 261 deletions

File tree

drivers/hwtracing/coresight/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
#
44
obj-$(CONFIG_CORESIGHT) += coresight.o coresight-etm-perf.o
55
obj-$(CONFIG_OF) += of_coresight.o
6-
obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o
6+
obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o \
7+
coresight-tmc-etf.o \
8+
coresight-tmc-etr.o
79
obj-$(CONFIG_CORESIGHT_SINK_TPIU) += coresight-tpiu.o
810
obj-$(CONFIG_CORESIGHT_SINK_ETBV10) += coresight-etb10.o
911
obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-funnel.o \
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
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+
18+
#include <linux/coresight.h>
19+
#include "coresight-priv.h"
20+
#include "coresight-tmc.h"
21+
22+
void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
23+
{
24+
/* Zero out the memory to help with debug */
25+
memset(drvdata->buf, 0, drvdata->size);
26+
27+
CS_UNLOCK(drvdata->base);
28+
29+
/* Wait for TMCSReady bit to be set */
30+
tmc_wait_for_tmcready(drvdata);
31+
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);
37+
38+
writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
39+
tmc_enable_hw(drvdata);
40+
41+
CS_LOCK(drvdata->base);
42+
}
43+
44+
static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
45+
{
46+
enum tmc_mem_intf_width memwidth;
47+
u8 memwords;
48+
char *bufp;
49+
u32 read_data;
50+
int i;
51+
52+
memwidth = BMVAL(readl_relaxed(drvdata->base + CORESIGHT_DEVID), 8, 10);
53+
if (memwidth == TMC_MEM_INTF_WIDTH_32BITS)
54+
memwords = 1;
55+
else if (memwidth == TMC_MEM_INTF_WIDTH_64BITS)
56+
memwords = 2;
57+
else if (memwidth == TMC_MEM_INTF_WIDTH_128BITS)
58+
memwords = 4;
59+
else
60+
memwords = 8;
61+
62+
bufp = drvdata->buf;
63+
while (1) {
64+
for (i = 0; i < memwords; i++) {
65+
read_data = readl_relaxed(drvdata->base + TMC_RRD);
66+
if (read_data == 0xFFFFFFFF)
67+
return;
68+
memcpy(bufp, &read_data, 4);
69+
bufp += 4;
70+
}
71+
}
72+
}
73+
74+
void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
75+
{
76+
CS_UNLOCK(drvdata->base);
77+
78+
tmc_flush_and_stop(drvdata);
79+
tmc_etb_dump_hw(drvdata);
80+
tmc_disable_hw(drvdata);
81+
82+
CS_LOCK(drvdata->base);
83+
}
84+
85+
static void tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
86+
{
87+
CS_UNLOCK(drvdata->base);
88+
89+
/* Wait for TMCSReady bit to be set */
90+
tmc_wait_for_tmcready(drvdata);
91+
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);
97+
98+
CS_LOCK(drvdata->base);
99+
}
100+
101+
static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
102+
{
103+
CS_UNLOCK(drvdata->base);
104+
105+
tmc_flush_and_stop(drvdata);
106+
tmc_disable_hw(drvdata);
107+
108+
CS_LOCK(drvdata->base);
109+
}
110+
111+
static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
112+
{
113+
unsigned long flags;
114+
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
115+
116+
spin_lock_irqsave(&drvdata->spinlock, flags);
117+
if (drvdata->reading) {
118+
spin_unlock_irqrestore(&drvdata->spinlock, flags);
119+
return -EBUSY;
120+
}
121+
122+
tmc_etb_enable_hw(drvdata);
123+
drvdata->enable = true;
124+
spin_unlock_irqrestore(&drvdata->spinlock, flags);
125+
126+
dev_info(drvdata->dev, "TMC-ETB/ETF enabled\n");
127+
return 0;
128+
}
129+
130+
static void tmc_disable_etf_sink(struct coresight_device *csdev)
131+
{
132+
unsigned long flags;
133+
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
134+
135+
spin_lock_irqsave(&drvdata->spinlock, flags);
136+
if (drvdata->reading) {
137+
spin_unlock_irqrestore(&drvdata->spinlock, flags);
138+
return;
139+
}
140+
141+
tmc_etb_disable_hw(drvdata);
142+
drvdata->enable = false;
143+
spin_unlock_irqrestore(&drvdata->spinlock, flags);
144+
145+
dev_info(drvdata->dev, "TMC-ETB/ETF disabled\n");
146+
}
147+
148+
static int tmc_enable_etf_link(struct coresight_device *csdev,
149+
int inport, int outport)
150+
{
151+
unsigned long flags;
152+
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
153+
154+
spin_lock_irqsave(&drvdata->spinlock, flags);
155+
if (drvdata->reading) {
156+
spin_unlock_irqrestore(&drvdata->spinlock, flags);
157+
return -EBUSY;
158+
}
159+
160+
tmc_etf_enable_hw(drvdata);
161+
drvdata->enable = true;
162+
spin_unlock_irqrestore(&drvdata->spinlock, flags);
163+
164+
dev_info(drvdata->dev, "TMC-ETF enabled\n");
165+
return 0;
166+
}
167+
168+
static void tmc_disable_etf_link(struct coresight_device *csdev,
169+
int inport, int outport)
170+
{
171+
unsigned long flags;
172+
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
173+
174+
spin_lock_irqsave(&drvdata->spinlock, flags);
175+
if (drvdata->reading) {
176+
spin_unlock_irqrestore(&drvdata->spinlock, flags);
177+
return;
178+
}
179+
180+
tmc_etf_disable_hw(drvdata);
181+
drvdata->enable = false;
182+
spin_unlock_irqrestore(&drvdata->spinlock, flags);
183+
184+
dev_info(drvdata->dev, "TMC disabled\n");
185+
}
186+
187+
static const struct coresight_ops_sink tmc_etf_sink_ops = {
188+
.enable = tmc_enable_etf_sink,
189+
.disable = tmc_disable_etf_sink,
190+
};
191+
192+
static const struct coresight_ops_link tmc_etf_link_ops = {
193+
.enable = tmc_enable_etf_link,
194+
.disable = tmc_disable_etf_link,
195+
};
196+
197+
const struct coresight_ops tmc_etb_cs_ops = {
198+
.sink_ops = &tmc_etf_sink_ops,
199+
};
200+
201+
const struct coresight_ops tmc_etf_cs_ops = {
202+
.sink_ops = &tmc_etf_sink_ops,
203+
.link_ops = &tmc_etf_link_ops,
204+
};
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
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+
18+
#include <linux/coresight.h>
19+
#include "coresight-priv.h"
20+
#include "coresight-tmc.h"
21+
22+
void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
23+
{
24+
u32 axictl;
25+
26+
/* Zero out the memory to help with debug */
27+
memset(drvdata->vaddr, 0, drvdata->size);
28+
29+
CS_UNLOCK(drvdata->base);
30+
31+
/* Wait for TMCSReady bit to be set */
32+
tmc_wait_for_tmcready(drvdata);
33+
34+
writel_relaxed(drvdata->size / 4, drvdata->base + TMC_RSZ);
35+
writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
36+
37+
axictl = readl_relaxed(drvdata->base + TMC_AXICTL);
38+
axictl |= TMC_AXICTL_WR_BURST_16;
39+
writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
40+
axictl &= ~TMC_AXICTL_SCT_GAT_MODE;
41+
writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
42+
axictl = (axictl &
43+
~(TMC_AXICTL_PROT_CTL_B0 | TMC_AXICTL_PROT_CTL_B1)) |
44+
TMC_AXICTL_PROT_CTL_B1;
45+
writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
46+
47+
writel_relaxed(drvdata->paddr, drvdata->base + TMC_DBALO);
48+
writel_relaxed(0x0, drvdata->base + TMC_DBAHI);
49+
writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
50+
TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
51+
TMC_FFCR_TRIGON_TRIGIN,
52+
drvdata->base + TMC_FFCR);
53+
writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
54+
tmc_enable_hw(drvdata);
55+
56+
CS_LOCK(drvdata->base);
57+
}
58+
59+
static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
60+
{
61+
u32 rwp, val;
62+
63+
rwp = readl_relaxed(drvdata->base + TMC_RWP);
64+
val = readl_relaxed(drvdata->base + TMC_STS);
65+
66+
/* How much memory do we still have */
67+
if (val & BIT(0))
68+
drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
69+
else
70+
drvdata->buf = drvdata->vaddr;
71+
}
72+
73+
void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
74+
{
75+
CS_UNLOCK(drvdata->base);
76+
77+
tmc_flush_and_stop(drvdata);
78+
tmc_etr_dump_hw(drvdata);
79+
tmc_disable_hw(drvdata);
80+
81+
CS_LOCK(drvdata->base);
82+
}
83+
84+
static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
85+
{
86+
unsigned long flags;
87+
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
88+
89+
spin_lock_irqsave(&drvdata->spinlock, flags);
90+
if (drvdata->reading) {
91+
spin_unlock_irqrestore(&drvdata->spinlock, flags);
92+
return -EBUSY;
93+
}
94+
95+
tmc_etr_enable_hw(drvdata);
96+
drvdata->enable = true;
97+
spin_unlock_irqrestore(&drvdata->spinlock, flags);
98+
99+
dev_info(drvdata->dev, "TMC-ETR enabled\n");
100+
return 0;
101+
}
102+
103+
static void tmc_disable_etr_sink(struct coresight_device *csdev)
104+
{
105+
unsigned long flags;
106+
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
107+
108+
spin_lock_irqsave(&drvdata->spinlock, flags);
109+
if (drvdata->reading) {
110+
spin_unlock_irqrestore(&drvdata->spinlock, flags);
111+
return;
112+
}
113+
114+
tmc_etr_disable_hw(drvdata);
115+
drvdata->enable = false;
116+
spin_unlock_irqrestore(&drvdata->spinlock, flags);
117+
118+
dev_info(drvdata->dev, "TMC-ETR disabled\n");
119+
}
120+
121+
static const struct coresight_ops_sink tmc_etr_sink_ops = {
122+
.enable = tmc_enable_etr_sink,
123+
.disable = tmc_disable_etr_sink,
124+
};
125+
126+
const struct coresight_ops tmc_etr_cs_ops = {
127+
.sink_ops = &tmc_etr_sink_ops,
128+
};

0 commit comments

Comments
 (0)