1*473c88f9SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
2*473c88f9SBruce Richardson * Copyright(c) 2010-2018 Intel Corporation
3*473c88f9SBruce Richardson */
4*473c88f9SBruce Richardson
5*473c88f9SBruce Richardson #include "ifpga_feature_dev.h"
6*473c88f9SBruce Richardson
7*473c88f9SBruce Richardson #define PERF_OBJ_ROOT_ID 0xff
8*473c88f9SBruce Richardson
fme_dperf_get_clock(struct ifpga_fme_hw * fme,u64 * clock)9*473c88f9SBruce Richardson static int fme_dperf_get_clock(struct ifpga_fme_hw *fme, u64 *clock)
10*473c88f9SBruce Richardson {
11*473c88f9SBruce Richardson struct feature_fme_dperf *dperf;
12*473c88f9SBruce Richardson struct feature_fme_dfpmon_clk_ctr clk;
13*473c88f9SBruce Richardson
14*473c88f9SBruce Richardson dperf = get_fme_feature_ioaddr_by_index(fme,
15*473c88f9SBruce Richardson FME_FEATURE_ID_GLOBAL_DPERF);
16*473c88f9SBruce Richardson clk.afu_interf_clock = readq(&dperf->clk);
17*473c88f9SBruce Richardson
18*473c88f9SBruce Richardson *clock = clk.afu_interf_clock;
19*473c88f9SBruce Richardson return 0;
20*473c88f9SBruce Richardson }
21*473c88f9SBruce Richardson
fme_dperf_get_revision(struct ifpga_fme_hw * fme,u64 * revision)22*473c88f9SBruce Richardson static int fme_dperf_get_revision(struct ifpga_fme_hw *fme, u64 *revision)
23*473c88f9SBruce Richardson {
24*473c88f9SBruce Richardson struct feature_fme_dperf *dperf;
25*473c88f9SBruce Richardson struct feature_header header;
26*473c88f9SBruce Richardson
27*473c88f9SBruce Richardson dperf = get_fme_feature_ioaddr_by_index(fme,
28*473c88f9SBruce Richardson FME_FEATURE_ID_GLOBAL_DPERF);
29*473c88f9SBruce Richardson header.csr = readq(&dperf->header);
30*473c88f9SBruce Richardson *revision = header.revision;
31*473c88f9SBruce Richardson
32*473c88f9SBruce Richardson return 0;
33*473c88f9SBruce Richardson }
34*473c88f9SBruce Richardson
35*473c88f9SBruce Richardson #define DPERF_TIMEOUT 30
36*473c88f9SBruce Richardson
fabric_pobj_is_enabled(int port_id,struct feature_fme_dperf * dperf)37*473c88f9SBruce Richardson static bool fabric_pobj_is_enabled(int port_id,
38*473c88f9SBruce Richardson struct feature_fme_dperf *dperf)
39*473c88f9SBruce Richardson {
40*473c88f9SBruce Richardson struct feature_fme_dfpmon_fab_ctl ctl;
41*473c88f9SBruce Richardson
42*473c88f9SBruce Richardson ctl.csr = readq(&dperf->fab_ctl);
43*473c88f9SBruce Richardson
44*473c88f9SBruce Richardson if (ctl.port_filter == FAB_DISABLE_FILTER)
45*473c88f9SBruce Richardson return port_id == PERF_OBJ_ROOT_ID;
46*473c88f9SBruce Richardson
47*473c88f9SBruce Richardson return port_id == ctl.port_id;
48*473c88f9SBruce Richardson }
49*473c88f9SBruce Richardson
read_fabric_counter(struct ifpga_fme_hw * fme,u8 port_id,enum dperf_fab_events fab_event)50*473c88f9SBruce Richardson static u64 read_fabric_counter(struct ifpga_fme_hw *fme, u8 port_id,
51*473c88f9SBruce Richardson enum dperf_fab_events fab_event)
52*473c88f9SBruce Richardson {
53*473c88f9SBruce Richardson struct feature_fme_dfpmon_fab_ctl ctl;
54*473c88f9SBruce Richardson struct feature_fme_dfpmon_fab_ctr ctr;
55*473c88f9SBruce Richardson struct feature_fme_dperf *dperf;
56*473c88f9SBruce Richardson u64 counter = 0;
57*473c88f9SBruce Richardson
58*473c88f9SBruce Richardson spinlock_lock(&fme->lock);
59*473c88f9SBruce Richardson dperf = get_fme_feature_ioaddr_by_index(fme,
60*473c88f9SBruce Richardson FME_FEATURE_ID_GLOBAL_DPERF);
61*473c88f9SBruce Richardson
62*473c88f9SBruce Richardson /* if it is disabled, force the counter to return zero. */
63*473c88f9SBruce Richardson if (!fabric_pobj_is_enabled(port_id, dperf))
64*473c88f9SBruce Richardson goto exit;
65*473c88f9SBruce Richardson
66*473c88f9SBruce Richardson ctl.csr = readq(&dperf->fab_ctl);
67*473c88f9SBruce Richardson ctl.fab_evtcode = fab_event;
68*473c88f9SBruce Richardson writeq(ctl.csr, &dperf->fab_ctl);
69*473c88f9SBruce Richardson
70*473c88f9SBruce Richardson ctr.event_code = fab_event;
71*473c88f9SBruce Richardson
72*473c88f9SBruce Richardson if (fpga_wait_register_field(event_code, ctr,
73*473c88f9SBruce Richardson &dperf->fab_ctr, DPERF_TIMEOUT, 1)) {
74*473c88f9SBruce Richardson dev_err(fme, "timeout, unmatched VTd event type in counter registers.\n");
75*473c88f9SBruce Richardson spinlock_unlock(&fme->lock);
76*473c88f9SBruce Richardson return -ETIMEDOUT;
77*473c88f9SBruce Richardson }
78*473c88f9SBruce Richardson
79*473c88f9SBruce Richardson ctr.csr = readq(&dperf->fab_ctr);
80*473c88f9SBruce Richardson counter = ctr.fab_cnt;
81*473c88f9SBruce Richardson exit:
82*473c88f9SBruce Richardson spinlock_unlock(&fme->lock);
83*473c88f9SBruce Richardson return counter;
84*473c88f9SBruce Richardson }
85*473c88f9SBruce Richardson
86*473c88f9SBruce Richardson #define FAB_PORT_SHOW(name, event) \
87*473c88f9SBruce Richardson static int fme_dperf_get_fab_port_##name(struct ifpga_fme_hw *fme, \
88*473c88f9SBruce Richardson u8 port_id, u64 *counter) \
89*473c88f9SBruce Richardson { \
90*473c88f9SBruce Richardson *counter = read_fabric_counter(fme, port_id, event); \
91*473c88f9SBruce Richardson return 0; \
92*473c88f9SBruce Richardson }
93*473c88f9SBruce Richardson
94*473c88f9SBruce Richardson FAB_PORT_SHOW(pcie0_read, DPERF_FAB_PCIE0_RD);
95*473c88f9SBruce Richardson FAB_PORT_SHOW(pcie0_write, DPERF_FAB_PCIE0_WR);
96*473c88f9SBruce Richardson FAB_PORT_SHOW(mmio_read, DPERF_FAB_MMIO_RD);
97*473c88f9SBruce Richardson FAB_PORT_SHOW(mmio_write, DPERF_FAB_MMIO_WR);
98*473c88f9SBruce Richardson
fme_dperf_get_fab_port_enable(struct ifpga_fme_hw * fme,u8 port_id,u64 * enable)99*473c88f9SBruce Richardson static int fme_dperf_get_fab_port_enable(struct ifpga_fme_hw *fme,
100*473c88f9SBruce Richardson u8 port_id, u64 *enable)
101*473c88f9SBruce Richardson {
102*473c88f9SBruce Richardson struct feature_fme_dperf *dperf;
103*473c88f9SBruce Richardson int status;
104*473c88f9SBruce Richardson
105*473c88f9SBruce Richardson dperf = get_fme_feature_ioaddr_by_index(fme,
106*473c88f9SBruce Richardson FME_FEATURE_ID_GLOBAL_DPERF);
107*473c88f9SBruce Richardson
108*473c88f9SBruce Richardson status = fabric_pobj_is_enabled(port_id, dperf);
109*473c88f9SBruce Richardson *enable = (u64)status;
110*473c88f9SBruce Richardson
111*473c88f9SBruce Richardson return 0;
112*473c88f9SBruce Richardson }
113*473c88f9SBruce Richardson
114*473c88f9SBruce Richardson /*
115*473c88f9SBruce Richardson * If enable one port or all port event counter in fabric, other
116*473c88f9SBruce Richardson * fabric event counter originally enabled will be disable automatically.
117*473c88f9SBruce Richardson */
fme_dperf_set_fab_port_enable(struct ifpga_fme_hw * fme,u8 port_id,u64 enable)118*473c88f9SBruce Richardson static int fme_dperf_set_fab_port_enable(struct ifpga_fme_hw *fme,
119*473c88f9SBruce Richardson u8 port_id, u64 enable)
120*473c88f9SBruce Richardson {
121*473c88f9SBruce Richardson struct feature_fme_dfpmon_fab_ctl ctl;
122*473c88f9SBruce Richardson struct feature_fme_dperf *dperf;
123*473c88f9SBruce Richardson bool state;
124*473c88f9SBruce Richardson
125*473c88f9SBruce Richardson state = !!enable;
126*473c88f9SBruce Richardson
127*473c88f9SBruce Richardson if (!state)
128*473c88f9SBruce Richardson return -EINVAL;
129*473c88f9SBruce Richardson
130*473c88f9SBruce Richardson dperf = get_fme_feature_ioaddr_by_index(fme,
131*473c88f9SBruce Richardson FME_FEATURE_ID_GLOBAL_DPERF);
132*473c88f9SBruce Richardson
133*473c88f9SBruce Richardson /* if it is already enabled. */
134*473c88f9SBruce Richardson if (fabric_pobj_is_enabled(port_id, dperf))
135*473c88f9SBruce Richardson return 0;
136*473c88f9SBruce Richardson
137*473c88f9SBruce Richardson spinlock_lock(&fme->lock);
138*473c88f9SBruce Richardson ctl.csr = readq(&dperf->fab_ctl);
139*473c88f9SBruce Richardson if (port_id == PERF_OBJ_ROOT_ID) {
140*473c88f9SBruce Richardson ctl.port_filter = FAB_DISABLE_FILTER;
141*473c88f9SBruce Richardson } else {
142*473c88f9SBruce Richardson ctl.port_filter = FAB_ENABLE_FILTER;
143*473c88f9SBruce Richardson ctl.port_id = port_id;
144*473c88f9SBruce Richardson }
145*473c88f9SBruce Richardson
146*473c88f9SBruce Richardson writeq(ctl.csr, &dperf->fab_ctl);
147*473c88f9SBruce Richardson spinlock_unlock(&fme->lock);
148*473c88f9SBruce Richardson
149*473c88f9SBruce Richardson return 0;
150*473c88f9SBruce Richardson }
151*473c88f9SBruce Richardson
fme_dperf_get_fab_freeze(struct ifpga_fme_hw * fme,u64 * freeze)152*473c88f9SBruce Richardson static int fme_dperf_get_fab_freeze(struct ifpga_fme_hw *fme, u64 *freeze)
153*473c88f9SBruce Richardson {
154*473c88f9SBruce Richardson struct feature_fme_dperf *dperf;
155*473c88f9SBruce Richardson struct feature_fme_dfpmon_fab_ctl ctl;
156*473c88f9SBruce Richardson
157*473c88f9SBruce Richardson dperf = get_fme_feature_ioaddr_by_index(fme,
158*473c88f9SBruce Richardson FME_FEATURE_ID_GLOBAL_DPERF);
159*473c88f9SBruce Richardson ctl.csr = readq(&dperf->fab_ctl);
160*473c88f9SBruce Richardson *freeze = (u64)ctl.freeze;
161*473c88f9SBruce Richardson
162*473c88f9SBruce Richardson return 0;
163*473c88f9SBruce Richardson }
164*473c88f9SBruce Richardson
fme_dperf_set_fab_freeze(struct ifpga_fme_hw * fme,u64 freeze)165*473c88f9SBruce Richardson static int fme_dperf_set_fab_freeze(struct ifpga_fme_hw *fme, u64 freeze)
166*473c88f9SBruce Richardson {
167*473c88f9SBruce Richardson struct feature_fme_dperf *dperf;
168*473c88f9SBruce Richardson struct feature_fme_dfpmon_fab_ctl ctl;
169*473c88f9SBruce Richardson bool state;
170*473c88f9SBruce Richardson
171*473c88f9SBruce Richardson state = !!freeze;
172*473c88f9SBruce Richardson
173*473c88f9SBruce Richardson spinlock_lock(&fme->lock);
174*473c88f9SBruce Richardson dperf = get_fme_feature_ioaddr_by_index(fme,
175*473c88f9SBruce Richardson FME_FEATURE_ID_GLOBAL_DPERF);
176*473c88f9SBruce Richardson ctl.csr = readq(&dperf->fab_ctl);
177*473c88f9SBruce Richardson ctl.freeze = state;
178*473c88f9SBruce Richardson writeq(ctl.csr, &dperf->fab_ctl);
179*473c88f9SBruce Richardson spinlock_unlock(&fme->lock);
180*473c88f9SBruce Richardson
181*473c88f9SBruce Richardson return 0;
182*473c88f9SBruce Richardson }
183*473c88f9SBruce Richardson
184*473c88f9SBruce Richardson #define PERF_MAX_PORT_NUM 1
185*473c88f9SBruce Richardson
fme_global_dperf_init(struct ifpga_feature * feature)186*473c88f9SBruce Richardson static int fme_global_dperf_init(struct ifpga_feature *feature)
187*473c88f9SBruce Richardson {
188*473c88f9SBruce Richardson UNUSED(feature);
189*473c88f9SBruce Richardson
190*473c88f9SBruce Richardson dev_info(NULL, "FME global_dperf Init.\n");
191*473c88f9SBruce Richardson
192*473c88f9SBruce Richardson return 0;
193*473c88f9SBruce Richardson }
194*473c88f9SBruce Richardson
fme_global_dperf_uinit(struct ifpga_feature * feature)195*473c88f9SBruce Richardson static void fme_global_dperf_uinit(struct ifpga_feature *feature)
196*473c88f9SBruce Richardson {
197*473c88f9SBruce Richardson UNUSED(feature);
198*473c88f9SBruce Richardson
199*473c88f9SBruce Richardson dev_info(NULL, "FME global_dperf UInit.\n");
200*473c88f9SBruce Richardson }
201*473c88f9SBruce Richardson
fme_dperf_fab_get_prop(struct ifpga_feature * feature,struct feature_prop * prop)202*473c88f9SBruce Richardson static int fme_dperf_fab_get_prop(struct ifpga_feature *feature,
203*473c88f9SBruce Richardson struct feature_prop *prop)
204*473c88f9SBruce Richardson {
205*473c88f9SBruce Richardson struct ifpga_fme_hw *fme = feature->parent;
206*473c88f9SBruce Richardson u8 sub = GET_FIELD(PROP_SUB, prop->prop_id);
207*473c88f9SBruce Richardson u16 id = GET_FIELD(PROP_ID, prop->prop_id);
208*473c88f9SBruce Richardson
209*473c88f9SBruce Richardson switch (id) {
210*473c88f9SBruce Richardson case 0x1: /* FREEZE */
211*473c88f9SBruce Richardson return fme_dperf_get_fab_freeze(fme, &prop->data);
212*473c88f9SBruce Richardson case 0x2: /* PCIE0_READ */
213*473c88f9SBruce Richardson return fme_dperf_get_fab_port_pcie0_read(fme, sub, &prop->data);
214*473c88f9SBruce Richardson case 0x3: /* PCIE0_WRITE */
215*473c88f9SBruce Richardson return fme_dperf_get_fab_port_pcie0_write(fme, sub,
216*473c88f9SBruce Richardson &prop->data);
217*473c88f9SBruce Richardson case 0x4: /* MMIO_READ */
218*473c88f9SBruce Richardson return fme_dperf_get_fab_port_mmio_read(fme, sub, &prop->data);
219*473c88f9SBruce Richardson case 0x5: /* MMIO_WRITE */
220*473c88f9SBruce Richardson return fme_dperf_get_fab_port_mmio_write(fme, sub, &prop->data);
221*473c88f9SBruce Richardson case 0x6: /* ENABLE */
222*473c88f9SBruce Richardson return fme_dperf_get_fab_port_enable(fme, sub, &prop->data);
223*473c88f9SBruce Richardson }
224*473c88f9SBruce Richardson
225*473c88f9SBruce Richardson return -ENOENT;
226*473c88f9SBruce Richardson }
227*473c88f9SBruce Richardson
fme_dperf_root_get_prop(struct ifpga_feature * feature,struct feature_prop * prop)228*473c88f9SBruce Richardson static int fme_dperf_root_get_prop(struct ifpga_feature *feature,
229*473c88f9SBruce Richardson struct feature_prop *prop)
230*473c88f9SBruce Richardson {
231*473c88f9SBruce Richardson struct ifpga_fme_hw *fme = feature->parent;
232*473c88f9SBruce Richardson u8 sub = GET_FIELD(PROP_SUB, prop->prop_id);
233*473c88f9SBruce Richardson u16 id = GET_FIELD(PROP_ID, prop->prop_id);
234*473c88f9SBruce Richardson
235*473c88f9SBruce Richardson if (sub != PERF_PROP_SUB_UNUSED)
236*473c88f9SBruce Richardson return -ENOENT;
237*473c88f9SBruce Richardson
238*473c88f9SBruce Richardson switch (id) {
239*473c88f9SBruce Richardson case 0x1: /* CLOCK */
240*473c88f9SBruce Richardson return fme_dperf_get_clock(fme, &prop->data);
241*473c88f9SBruce Richardson case 0x2: /* REVISION */
242*473c88f9SBruce Richardson return fme_dperf_get_revision(fme, &prop->data);
243*473c88f9SBruce Richardson }
244*473c88f9SBruce Richardson
245*473c88f9SBruce Richardson return -ENOENT;
246*473c88f9SBruce Richardson }
247*473c88f9SBruce Richardson
fme_global_dperf_get_prop(struct ifpga_feature * feature,struct feature_prop * prop)248*473c88f9SBruce Richardson static int fme_global_dperf_get_prop(struct ifpga_feature *feature,
249*473c88f9SBruce Richardson struct feature_prop *prop)
250*473c88f9SBruce Richardson {
251*473c88f9SBruce Richardson u8 top = GET_FIELD(PROP_TOP, prop->prop_id);
252*473c88f9SBruce Richardson
253*473c88f9SBruce Richardson switch (top) {
254*473c88f9SBruce Richardson case PERF_PROP_TOP_FAB:
255*473c88f9SBruce Richardson return fme_dperf_fab_get_prop(feature, prop);
256*473c88f9SBruce Richardson case PERF_PROP_TOP_UNUSED:
257*473c88f9SBruce Richardson return fme_dperf_root_get_prop(feature, prop);
258*473c88f9SBruce Richardson }
259*473c88f9SBruce Richardson
260*473c88f9SBruce Richardson return -ENOENT;
261*473c88f9SBruce Richardson }
262*473c88f9SBruce Richardson
fme_dperf_fab_set_prop(struct ifpga_feature * feature,struct feature_prop * prop)263*473c88f9SBruce Richardson static int fme_dperf_fab_set_prop(struct ifpga_feature *feature,
264*473c88f9SBruce Richardson struct feature_prop *prop)
265*473c88f9SBruce Richardson {
266*473c88f9SBruce Richardson struct ifpga_fme_hw *fme = feature->parent;
267*473c88f9SBruce Richardson u8 sub = GET_FIELD(PROP_SUB, prop->prop_id);
268*473c88f9SBruce Richardson u16 id = GET_FIELD(PROP_ID, prop->prop_id);
269*473c88f9SBruce Richardson
270*473c88f9SBruce Richardson switch (id) {
271*473c88f9SBruce Richardson case 0x1: /* FREEZE - fab root only prop */
272*473c88f9SBruce Richardson if (sub != PERF_PROP_SUB_UNUSED)
273*473c88f9SBruce Richardson return -ENOENT;
274*473c88f9SBruce Richardson return fme_dperf_set_fab_freeze(fme, prop->data);
275*473c88f9SBruce Richardson case 0x6: /* ENABLE - fab both root and sub */
276*473c88f9SBruce Richardson return fme_dperf_set_fab_port_enable(fme, sub, prop->data);
277*473c88f9SBruce Richardson }
278*473c88f9SBruce Richardson
279*473c88f9SBruce Richardson return -ENOENT;
280*473c88f9SBruce Richardson }
281*473c88f9SBruce Richardson
fme_global_dperf_set_prop(struct ifpga_feature * feature,struct feature_prop * prop)282*473c88f9SBruce Richardson static int fme_global_dperf_set_prop(struct ifpga_feature *feature,
283*473c88f9SBruce Richardson struct feature_prop *prop)
284*473c88f9SBruce Richardson {
285*473c88f9SBruce Richardson u8 top = GET_FIELD(PROP_TOP, prop->prop_id);
286*473c88f9SBruce Richardson
287*473c88f9SBruce Richardson switch (top) {
288*473c88f9SBruce Richardson case PERF_PROP_TOP_FAB:
289*473c88f9SBruce Richardson return fme_dperf_fab_set_prop(feature, prop);
290*473c88f9SBruce Richardson }
291*473c88f9SBruce Richardson
292*473c88f9SBruce Richardson return -ENOENT;
293*473c88f9SBruce Richardson }
294*473c88f9SBruce Richardson
295*473c88f9SBruce Richardson struct ifpga_feature_ops fme_global_dperf_ops = {
296*473c88f9SBruce Richardson .init = fme_global_dperf_init,
297*473c88f9SBruce Richardson .uinit = fme_global_dperf_uinit,
298*473c88f9SBruce Richardson .get_prop = fme_global_dperf_get_prop,
299*473c88f9SBruce Richardson .set_prop = fme_global_dperf_set_prop,
300*473c88f9SBruce Richardson
301*473c88f9SBruce Richardson };
302