blob: 69511cd331f87bdb00129353a6e99afe1d942d97 [file] [log] [blame]
Satyajit Desaiee828fb2017-02-07 13:51:32 -08001/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
Satyajit Desaif151d682016-09-12 16:18:03 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/device.h>
16#include <linux/platform_device.h>
17#include <linux/io.h>
18#include <linux/err.h>
19#include <linux/fs.h>
20#include <linux/clk.h>
21#include <linux/bitmap.h>
22#include <linux/of.h>
23#include <linux/coresight.h>
24
25#include "coresight-priv.h"
26
27#define tpdm_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off)
28#define tpdm_readl(drvdata, off) __raw_readl(drvdata->base + off)
29
30#define TPDM_LOCK(drvdata) \
31do { \
32 mb(); /* ensure configuration take effect before we lock it */ \
33 tpdm_writel(drvdata, 0x0, CORESIGHT_LAR); \
34} while (0)
35#define TPDM_UNLOCK(drvdata) \
36do { \
37 tpdm_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
38 mb(); /* ensure unlock take effect before we configure */ \
39} while (0)
40
41/* GPR Registers */
42#define TPDM_GPR_CR(n) (0x0 + (n * 4))
43
44/* BC Subunit Registers */
45#define TPDM_BC_CR (0x280)
46#define TPDM_BC_SATROLL (0x284)
47#define TPDM_BC_CNTENSET (0x288)
48#define TPDM_BC_CNTENCLR (0x28C)
49#define TPDM_BC_INTENSET (0x290)
50#define TPDM_BC_INTENCLR (0x294)
51#define TPDM_BC_TRIG_LO(n) (0x298 + (n * 4))
52#define TPDM_BC_TRIG_HI(n) (0x318 + (n * 4))
53#define TPDM_BC_GANG (0x398)
54#define TPDM_BC_OVERFLOW(n) (0x39C + (n * 4))
55#define TPDM_BC_OVSR (0x3C0)
56#define TPDM_BC_SELR (0x3C4)
57#define TPDM_BC_CNTR_LO (0x3C8)
58#define TPDM_BC_CNTR_HI (0x3CC)
59#define TPDM_BC_SHADOW_LO(n) (0x3D0 + (n * 4))
60#define TPDM_BC_SHADOW_HI(n) (0x450 + (n * 4))
61#define TPDM_BC_SWINC (0x4D0)
62#define TPDM_BC_MSR(n) (0x4F0 + (n * 4))
63
64/* TC Subunit Registers */
65#define TPDM_TC_CR (0x500)
66#define TPDM_TC_CNTENSET (0x504)
67#define TPDM_TC_CNTENCLR (0x508)
68#define TPDM_TC_INTENSET (0x50C)
69#define TPDM_TC_INTENCLR (0x510)
70#define TPDM_TC_TRIG_SEL(n) (0x514 + (n * 4))
71#define TPDM_TC_TRIG_LO(n) (0x534 + (n * 4))
72#define TPDM_TC_TRIG_HI(n) (0x554 + (n * 4))
73#define TPDM_TC_OVSR_GP (0x580)
74#define TPDM_TC_OVSR_IMPL (0x584)
75#define TPDM_TC_SELR (0x588)
76#define TPDM_TC_CNTR_LO (0x58C)
77#define TPDM_TC_CNTR_HI (0x590)
78#define TPDM_TC_SHADOW_LO(n) (0x594 + (n * 4))
79#define TPDM_TC_SHADOW_HI(n) (0x644 + (n * 4))
80#define TPDM_TC_SWINC (0x700)
81#define TPDM_TC_MSR(n) (0x768 + (n * 4))
82
83/* DSB Subunit Registers */
84#define TPDM_DSB_CR (0x780)
85#define TPDM_DSB_TIER (0x784)
86#define TPDM_DSB_TPR(n) (0x788 + (n * 4))
87#define TPDM_DSB_TPMR(n) (0x7A8 + (n * 4))
88#define TPDM_DSB_XPR(n) (0x7C8 + (n * 4))
89#define TPDM_DSB_XPMR(n) (0x7E8 + (n * 4))
90#define TPDM_DSB_EDCR(n) (0x808 + (n * 4))
91#define TPDM_DSB_EDCMR(n) (0x848 + (n * 4))
92#define TPDM_DSB_CA_SELECT(n) (0x86c + (n * 4))
93#define TPDM_DSB_MSR(n) (0x980 + (n * 4))
94
Satyajit Desaie104ff52016-09-12 16:38:12 -070095/* CMB/MCMB Subunit Registers */
Satyajit Desaif151d682016-09-12 16:18:03 -070096#define TPDM_CMB_CR (0xA00)
97#define TPDM_CMB_TIER (0xA04)
98#define TPDM_CMB_TPR(n) (0xA08 + (n * 4))
99#define TPDM_CMB_TPMR(n) (0xA10 + (n * 4))
100#define TPDM_CMB_XPR(n) (0xA18 + (n * 4))
101#define TPDM_CMB_XPMR(n) (0xA20 + (n * 4))
Satyajit Desaie104ff52016-09-12 16:38:12 -0700102#define TPDM_CMB_MARKR (0xA28)
103#define TPDM_CMB_READCTL (0xA70)
104#define TPDM_CMB_READVAL (0xA74)
Satyajit Desaif151d682016-09-12 16:18:03 -0700105#define TPDM_CMB_MSR(n) (0xA80 + (n * 4))
106
107/* TPDM Specific Registers */
108#define TPDM_ITATBCNTRL (0xEF0)
109#define TPDM_CLK_CTRL (0x220)
110
111#define TPDM_DATASETS 32
112#define TPDM_BC_MAX_COUNTERS 32
113#define TPDM_BC_MAX_OVERFLOW 6
114#define TPDM_BC_MAX_MSR 4
115#define TPDM_TC_MAX_COUNTERS 44
116#define TPDM_TC_MAX_TRIG 8
117#define TPDM_TC_MAX_MSR 6
118#define TPDM_DSB_MAX_PATT 8
119#define TPDM_DSB_MAX_SELECT 8
120#define TPDM_DSB_MAX_MSR 32
121#define TPDM_DSB_MAX_EDCR 16
122#define TPDM_DSB_MAX_LINES 256
123#define TPDM_CMB_PATT_CMP 2
124#define TPDM_CMB_MAX_MSR 128
Satyajit Desaie104ff52016-09-12 16:38:12 -0700125#define TPDM_MCMB_MAX_LANES 8
Satyajit Desaif151d682016-09-12 16:18:03 -0700126
127/* DSB programming modes */
128#define TPDM_DSB_MODE_CYCACC(val) BMVAL(val, 0, 2)
129#define TPDM_DSB_MODE_PERF BIT(3)
130#define TPDM_DSB_MODE_HPBYTESEL(val) BMVAL(val, 4, 8)
131#define TPDM_MODE_ALL (0xFFFFFFF)
132
133#define NUM_OF_BITS 32
134#define TPDM_GPR_REGS_MAX 160
135
136#define TPDM_TRACE_ID_START 128
137
138#define TPDM_REVISION_A 0
139#define TPDM_REVISION_B 1
140
141enum tpdm_dataset {
142 TPDM_DS_IMPLDEF,
143 TPDM_DS_DSB,
144 TPDM_DS_CMB,
145 TPDM_DS_TC,
146 TPDM_DS_BC,
147 TPDM_DS_GPR,
Satyajit Desaie104ff52016-09-12 16:38:12 -0700148 TPDM_DS_MCMB,
Satyajit Desaif151d682016-09-12 16:18:03 -0700149};
150
151enum tpdm_mode {
152 TPDM_MODE_ATB,
153 TPDM_MODE_APB,
154};
155
156enum tpdm_support_type {
157 TPDM_SUPPORT_TYPE_FULL,
158 TPDM_SUPPORT_TYPE_PARTIAL,
159 TPDM_SUPPORT_TYPE_NO,
160};
161
Satyajit Desaif151d682016-09-12 16:18:03 -0700162enum tpdm_cmb_patt_bits {
163 TPDM_CMB_LSB,
164 TPDM_CMB_MSB,
165};
166
167#ifdef CONFIG_CORESIGHT_TPDM_DEFAULT_ENABLE
168static int boot_enable = 1;
169#else
170static int boot_enable;
171#endif
172
173module_param_named(
Satyajit Desai326497c2016-11-14 10:15:03 -0800174 boot_enable, boot_enable, int, 0444
Satyajit Desaif151d682016-09-12 16:18:03 -0700175);
176
177struct gpr_dataset {
178 DECLARE_BITMAP(gpr_dirty, TPDM_GPR_REGS_MAX);
179 uint32_t gp_regs[TPDM_GPR_REGS_MAX];
180};
181
182struct bc_dataset {
183 enum tpdm_mode capture_mode;
184 enum tpdm_mode retrieval_mode;
185 uint32_t sat_mode;
186 uint32_t enable_counters;
187 uint32_t clear_counters;
188 uint32_t enable_irq;
189 uint32_t clear_irq;
190 uint32_t trig_val_lo[TPDM_BC_MAX_COUNTERS];
191 uint32_t trig_val_hi[TPDM_BC_MAX_COUNTERS];
192 uint32_t enable_ganging;
193 uint32_t overflow_val[TPDM_BC_MAX_OVERFLOW];
194 uint32_t msr[TPDM_BC_MAX_MSR];
195};
196
197struct tc_dataset {
198 enum tpdm_mode capture_mode;
199 enum tpdm_mode retrieval_mode;
200 bool sat_mode;
201 uint32_t enable_counters;
202 uint32_t clear_counters;
203 uint32_t enable_irq;
204 uint32_t clear_irq;
205 uint32_t trig_sel[TPDM_TC_MAX_TRIG];
206 uint32_t trig_val_lo[TPDM_TC_MAX_TRIG];
207 uint32_t trig_val_hi[TPDM_TC_MAX_TRIG];
208 uint32_t msr[TPDM_TC_MAX_MSR];
209};
210
211struct dsb_dataset {
212 uint32_t mode;
213 uint32_t edge_ctrl[TPDM_DSB_MAX_EDCR];
214 uint32_t edge_ctrl_mask[TPDM_DSB_MAX_EDCR / 2];
215 uint32_t patt_val[TPDM_DSB_MAX_PATT];
216 uint32_t patt_mask[TPDM_DSB_MAX_PATT];
217 bool patt_ts;
218 bool patt_type;
219 uint32_t trig_patt_val[TPDM_DSB_MAX_PATT];
220 uint32_t trig_patt_mask[TPDM_DSB_MAX_PATT];
221 bool trig_ts;
222 uint32_t select_val[TPDM_DSB_MAX_SELECT];
223 uint32_t msr[TPDM_DSB_MAX_MSR];
224};
225
Satyajit Desaie104ff52016-09-12 16:38:12 -0700226struct mcmb_dataset {
227 uint8_t mcmb_trig_lane;
228 uint8_t mcmb_lane_select;
229};
230
Satyajit Desaif151d682016-09-12 16:18:03 -0700231struct cmb_dataset {
Satyajit Desaic75e7642017-04-24 20:35:57 -0700232 bool trace_mode;
233 uint32_t cycle_acc;
Satyajit Desaif151d682016-09-12 16:18:03 -0700234 uint32_t patt_val[TPDM_CMB_PATT_CMP];
235 uint32_t patt_mask[TPDM_CMB_PATT_CMP];
236 bool patt_ts;
237 uint32_t trig_patt_val[TPDM_CMB_PATT_CMP];
238 uint32_t trig_patt_mask[TPDM_CMB_PATT_CMP];
239 bool trig_ts;
240 uint32_t msr[TPDM_CMB_MAX_MSR];
Satyajit Desaie104ff52016-09-12 16:38:12 -0700241 uint8_t read_ctl_reg;
242 struct mcmb_dataset *mcmb;
Satyajit Desaif151d682016-09-12 16:18:03 -0700243};
244
245struct tpdm_drvdata {
246 void __iomem *base;
247 struct device *dev;
248 struct coresight_device *csdev;
249 struct clk *clk;
250 struct mutex lock;
251 bool enable;
252 bool clk_enable;
253 DECLARE_BITMAP(datasets, TPDM_DATASETS);
254 DECLARE_BITMAP(enable_ds, TPDM_DATASETS);
255 enum tpdm_support_type tc_trig_type;
256 enum tpdm_support_type bc_trig_type;
257 enum tpdm_support_type bc_gang_type;
258 uint32_t bc_counters_avail;
259 uint32_t tc_counters_avail;
260 struct gpr_dataset *gpr;
261 struct bc_dataset *bc;
262 struct tc_dataset *tc;
263 struct dsb_dataset *dsb;
264 struct cmb_dataset *cmb;
265 int traceid;
266 uint32_t version;
267 bool msr_support;
268 bool msr_fix_req;
269};
270
271static void __tpdm_enable_gpr(struct tpdm_drvdata *drvdata)
272{
273 int i;
274
275 for (i = 0; i < TPDM_GPR_REGS_MAX; i++) {
276 if (!test_bit(i, drvdata->gpr->gpr_dirty))
277 continue;
278 tpdm_writel(drvdata, drvdata->gpr->gp_regs[i], TPDM_GPR_CR(i));
279 }
280}
281
282static void __tpdm_config_bc_msr(struct tpdm_drvdata *drvdata)
283{
284 int i;
285
286 if (!drvdata->msr_support)
287 return;
288
289 for (i = 0; i < TPDM_BC_MAX_MSR; i++)
290 tpdm_writel(drvdata, drvdata->bc->msr[i], TPDM_BC_MSR(i));
291}
292
293static void __tpdm_config_tc_msr(struct tpdm_drvdata *drvdata)
294{
295 int i;
296
297 if (!drvdata->msr_support)
298 return;
299
300 for (i = 0; i < TPDM_TC_MAX_MSR; i++)
301 tpdm_writel(drvdata, drvdata->tc->msr[i], TPDM_TC_MSR(i));
302}
303
304static void __tpdm_config_dsb_msr(struct tpdm_drvdata *drvdata)
305{
306 int i;
307
308 if (!drvdata->msr_support)
309 return;
310
311 for (i = 0; i < TPDM_DSB_MAX_MSR; i++)
312 tpdm_writel(drvdata, drvdata->dsb->msr[i], TPDM_DSB_MSR(i));
313}
314
315static void __tpdm_config_cmb_msr(struct tpdm_drvdata *drvdata)
316{
317 int i;
318
319 if (!drvdata->msr_support)
320 return;
321
322 for (i = 0; i < TPDM_CMB_MAX_MSR; i++)
323 tpdm_writel(drvdata, drvdata->cmb->msr[i], TPDM_CMB_MSR(i));
324}
325
326static void __tpdm_enable_bc(struct tpdm_drvdata *drvdata)
327{
328 int i;
329 uint32_t val;
330
331 if (drvdata->bc->sat_mode)
332 tpdm_writel(drvdata, drvdata->bc->sat_mode,
333 TPDM_BC_SATROLL);
334 else
335 tpdm_writel(drvdata, 0x0, TPDM_BC_SATROLL);
336
337 if (drvdata->bc->enable_counters) {
338 tpdm_writel(drvdata, 0xFFFFFFFF, TPDM_BC_CNTENCLR);
339 tpdm_writel(drvdata, drvdata->bc->enable_counters,
340 TPDM_BC_CNTENSET);
341 }
342 if (drvdata->bc->clear_counters)
343 tpdm_writel(drvdata, drvdata->bc->clear_counters,
344 TPDM_BC_CNTENCLR);
345
346 if (drvdata->bc->enable_irq) {
347 tpdm_writel(drvdata, 0xFFFFFFFF, TPDM_BC_INTENCLR);
348 tpdm_writel(drvdata, drvdata->bc->enable_irq,
349 TPDM_BC_INTENSET);
350 }
351 if (drvdata->bc->clear_irq)
352 tpdm_writel(drvdata, drvdata->bc->clear_irq,
353 TPDM_BC_INTENCLR);
354
355 if (drvdata->bc_trig_type == TPDM_SUPPORT_TYPE_FULL) {
356 for (i = 0; i < drvdata->bc_counters_avail; i++) {
357 tpdm_writel(drvdata, drvdata->bc->trig_val_lo[i],
358 TPDM_BC_TRIG_LO(i));
359 tpdm_writel(drvdata, drvdata->bc->trig_val_hi[i],
360 TPDM_BC_TRIG_HI(i));
361 }
362 } else if (drvdata->bc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL) {
363 tpdm_writel(drvdata, drvdata->bc->trig_val_lo[0],
364 TPDM_BC_TRIG_LO(0));
365 tpdm_writel(drvdata, drvdata->bc->trig_val_hi[0],
366 TPDM_BC_TRIG_HI(0));
367 }
368
369 if (drvdata->bc->enable_ganging)
370 tpdm_writel(drvdata, drvdata->bc->enable_ganging, TPDM_BC_GANG);
371
372 for (i = 0; i < TPDM_BC_MAX_OVERFLOW; i++)
373 tpdm_writel(drvdata, drvdata->bc->overflow_val[i],
374 TPDM_BC_OVERFLOW(i));
375
376 __tpdm_config_bc_msr(drvdata);
377
378 val = tpdm_readl(drvdata, TPDM_BC_CR);
379 if (drvdata->bc->retrieval_mode == TPDM_MODE_APB)
380 val = val | BIT(2);
381 else
382 val = val & ~BIT(2);
383 tpdm_writel(drvdata, val, TPDM_BC_CR);
384
385 val = tpdm_readl(drvdata, TPDM_BC_CR);
386 /* Set the enable bit */
387 val = val | BIT(0);
388 tpdm_writel(drvdata, val, TPDM_BC_CR);
389}
390
391static void __tpdm_enable_tc(struct tpdm_drvdata *drvdata)
392{
393 int i;
394 uint32_t val;
395
396 if (drvdata->tc->enable_counters) {
397 tpdm_writel(drvdata, 0xF, TPDM_TC_CNTENCLR);
398 tpdm_writel(drvdata, drvdata->tc->enable_counters,
399 TPDM_TC_CNTENSET);
400 }
401 if (drvdata->tc->clear_counters)
402 tpdm_writel(drvdata, drvdata->tc->clear_counters,
403 TPDM_TC_CNTENCLR);
404
405 if (drvdata->tc->enable_irq) {
406 tpdm_writel(drvdata, 0xF, TPDM_TC_INTENCLR);
407 tpdm_writel(drvdata, drvdata->tc->enable_irq,
408 TPDM_TC_INTENSET);
409 }
410 if (drvdata->tc->clear_irq)
411 tpdm_writel(drvdata, drvdata->tc->clear_irq,
412 TPDM_TC_INTENCLR);
413
414 if (drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_FULL) {
415 for (i = 0; i < TPDM_TC_MAX_TRIG; i++) {
416 tpdm_writel(drvdata, drvdata->tc->trig_sel[i],
417 TPDM_TC_TRIG_SEL(i));
418 tpdm_writel(drvdata, drvdata->tc->trig_val_lo[i],
419 TPDM_TC_TRIG_LO(i));
420 tpdm_writel(drvdata, drvdata->tc->trig_val_hi[i],
421 TPDM_TC_TRIG_HI(i));
422 }
423 } else if (drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL) {
424 tpdm_writel(drvdata, drvdata->tc->trig_sel[0],
425 TPDM_TC_TRIG_SEL(0));
426 tpdm_writel(drvdata, drvdata->tc->trig_val_lo[0],
427 TPDM_TC_TRIG_LO(0));
428 tpdm_writel(drvdata, drvdata->tc->trig_val_hi[0],
429 TPDM_TC_TRIG_HI(0));
430 }
431
432 __tpdm_config_tc_msr(drvdata);
433
434 val = tpdm_readl(drvdata, TPDM_TC_CR);
435 if (drvdata->tc->sat_mode)
436 val = val | BIT(4);
437 else
438 val = val & ~BIT(4);
439 if (drvdata->tc->retrieval_mode == TPDM_MODE_APB)
440 val = val | BIT(2);
441 else
442 val = val & ~BIT(2);
443 tpdm_writel(drvdata, val, TPDM_TC_CR);
444
445 val = tpdm_readl(drvdata, TPDM_TC_CR);
446 /* Set the enable bit */
447 val = val | BIT(0);
448 tpdm_writel(drvdata, val, TPDM_TC_CR);
449}
450
451static void __tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
452{
453 uint32_t val, mode, i;
454
455 for (i = 0; i < TPDM_DSB_MAX_EDCR; i++)
456 tpdm_writel(drvdata, drvdata->dsb->edge_ctrl[i],
457 TPDM_DSB_EDCR(i));
458 for (i = 0; i < TPDM_DSB_MAX_EDCR / 2; i++)
459 tpdm_writel(drvdata, drvdata->dsb->edge_ctrl_mask[i],
460 TPDM_DSB_EDCMR(i));
461
462 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
463 tpdm_writel(drvdata, drvdata->dsb->patt_val[i],
464 TPDM_DSB_TPR(i));
465 tpdm_writel(drvdata, drvdata->dsb->patt_mask[i],
466 TPDM_DSB_TPMR(i));
467 }
468
469 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
470 tpdm_writel(drvdata, drvdata->dsb->trig_patt_val[i],
471 TPDM_DSB_XPR(i));
472 tpdm_writel(drvdata, drvdata->dsb->trig_patt_mask[i],
473 TPDM_DSB_XPMR(i));
474 }
475
476 for (i = 0; i < TPDM_DSB_MAX_SELECT; i++)
477 tpdm_writel(drvdata, drvdata->dsb->select_val[i],
478 TPDM_DSB_CA_SELECT(i));
479
480 val = tpdm_readl(drvdata, TPDM_DSB_TIER);
481 if (drvdata->dsb->patt_ts == true) {
482 val = val | BIT(0);
483 if (drvdata->dsb->patt_type == true)
484 val = val | BIT(2);
485 else
486 val = val & ~BIT(2);
487 } else {
488 val = val & ~BIT(0);
489 }
490 if (drvdata->dsb->trig_ts == true)
491 val = val | BIT(1);
492 else
493 val = val & ~BIT(1);
494 tpdm_writel(drvdata, val, TPDM_DSB_TIER);
495
496 if (!drvdata->msr_fix_req)
497 __tpdm_config_dsb_msr(drvdata);
498
499 val = tpdm_readl(drvdata, TPDM_DSB_CR);
500 /* Set the cycle accurate mode */
501 mode = TPDM_DSB_MODE_CYCACC(drvdata->dsb->mode);
502 val = val & ~(0x7 << 9);
503 val = val | (mode << 9);
504 /* Set the byte lane for high-performance mode */
505 mode = TPDM_DSB_MODE_HPBYTESEL(drvdata->dsb->mode);
506 val = val & ~(0x1F << 2);
507 val = val | (mode << 2);
508 /* Set the performance mode */
509 if (drvdata->dsb->mode & TPDM_DSB_MODE_PERF)
510 val = val | BIT(1);
511 else
512 val = val & ~BIT(1);
513 tpdm_writel(drvdata, val, TPDM_DSB_CR);
514
515 val = tpdm_readl(drvdata, TPDM_DSB_CR);
516 /* Set the enable bit */
517 val = val | BIT(0);
518 tpdm_writel(drvdata, val, TPDM_DSB_CR);
519
520 if (drvdata->msr_fix_req)
521 __tpdm_config_dsb_msr(drvdata);
522}
523
524static void __tpdm_enable_cmb(struct tpdm_drvdata *drvdata)
525{
526 uint32_t val;
Satyajit Desai75411bc2017-04-19 18:41:27 -0700527 int i;
Satyajit Desaif151d682016-09-12 16:18:03 -0700528
Satyajit Desai75411bc2017-04-19 18:41:27 -0700529 for (i = 0; i < TPDM_CMB_PATT_CMP; i++) {
530 tpdm_writel(drvdata, drvdata->cmb->patt_val[i],
531 TPDM_CMB_TPR(i));
532 tpdm_writel(drvdata, drvdata->cmb->patt_mask[i],
533 TPDM_CMB_TPMR(i));
534 tpdm_writel(drvdata, drvdata->cmb->trig_patt_val[i],
535 TPDM_CMB_XPR(i));
536 tpdm_writel(drvdata, drvdata->cmb->trig_patt_mask[i],
537 TPDM_CMB_XPMR(i));
538 }
Satyajit Desaif151d682016-09-12 16:18:03 -0700539
540 val = tpdm_readl(drvdata, TPDM_CMB_TIER);
541 if (drvdata->cmb->patt_ts == true)
542 val = val | BIT(0);
543 else
544 val = val & ~BIT(0);
545 if (drvdata->cmb->trig_ts == true)
546 val = val | BIT(1);
547 else
548 val = val & ~BIT(1);
549 tpdm_writel(drvdata, val, TPDM_CMB_TIER);
550
551 __tpdm_config_cmb_msr(drvdata);
552
553 val = tpdm_readl(drvdata, TPDM_CMB_CR);
554 /* Set the flow control bit */
555 val = val & ~BIT(2);
Satyajit Desaic75e7642017-04-24 20:35:57 -0700556 if (drvdata->cmb->trace_mode)
Satyajit Desaif151d682016-09-12 16:18:03 -0700557 val = val | BIT(1);
Satyajit Desaic75e7642017-04-24 20:35:57 -0700558 else
559 val = val & ~BIT(1);
560
561 val = val & ~BM(8, 9);
562 val = val | BMVAL(drvdata->cmb->cycle_acc, 0, 1) << 8;
Satyajit Desaif151d682016-09-12 16:18:03 -0700563 tpdm_writel(drvdata, val, TPDM_CMB_CR);
564 /* Set the enable bit */
565 val = val | BIT(0);
566 tpdm_writel(drvdata, val, TPDM_CMB_CR);
567}
568
Satyajit Desaie104ff52016-09-12 16:38:12 -0700569static void __tpdm_enable_mcmb(struct tpdm_drvdata *drvdata)
570{
571 uint32_t val;
572 struct mcmb_dataset *mcmb = drvdata->cmb->mcmb;
Satyajit Desai75411bc2017-04-19 18:41:27 -0700573 int i;
Satyajit Desaie104ff52016-09-12 16:38:12 -0700574
Satyajit Desai75411bc2017-04-19 18:41:27 -0700575 for (i = 0; i < TPDM_CMB_PATT_CMP; i++) {
576 tpdm_writel(drvdata, drvdata->cmb->patt_val[i],
577 TPDM_CMB_TPR(i));
578 tpdm_writel(drvdata, drvdata->cmb->patt_mask[i],
579 TPDM_CMB_TPMR(i));
580 tpdm_writel(drvdata, drvdata->cmb->trig_patt_val[i],
581 TPDM_CMB_XPR(i));
582 tpdm_writel(drvdata, drvdata->cmb->trig_patt_mask[i],
583 TPDM_CMB_XPMR(i));
584 }
Satyajit Desaie104ff52016-09-12 16:38:12 -0700585
586 val = tpdm_readl(drvdata, TPDM_CMB_TIER);
587 if (drvdata->cmb->patt_ts == true)
588 val = val | BIT(0);
589 else
590 val = val & ~BIT(0);
591 if (drvdata->cmb->trig_ts == true)
592 val = val | BIT(1);
593 else
594 val = val & ~BIT(1);
595 tpdm_writel(drvdata, val, TPDM_CMB_TIER);
596
597 __tpdm_config_cmb_msr(drvdata);
598
599 val = tpdm_readl(drvdata, TPDM_CMB_CR);
600 /* Set the flow control bit */
601 val = val & ~BIT(2);
Satyajit Desaic75e7642017-04-24 20:35:57 -0700602 if (drvdata->cmb->trace_mode)
Satyajit Desaie104ff52016-09-12 16:38:12 -0700603 val = val | BIT(1);
Satyajit Desaic75e7642017-04-24 20:35:57 -0700604 else
605 val = val & ~BIT(1);
Satyajit Desaie104ff52016-09-12 16:38:12 -0700606
Satyajit Desaic75e7642017-04-24 20:35:57 -0700607 val = val & ~BM(8, 9);
608 val = val | BMVAL(drvdata->cmb->cycle_acc, 0, 1) << 8;
Satyajit Desaibd2deda2017-04-20 18:28:38 -0700609 val = val & ~BM(18, 20);
610 val = val | (BMVAL(mcmb->mcmb_trig_lane, 0, 2) << 18);
611 val = val & ~BM(10, 17);
612 val = val | (BMVAL(mcmb->mcmb_lane_select, 0, 7) << 10);
Satyajit Desaie104ff52016-09-12 16:38:12 -0700613
614 tpdm_writel(drvdata, val, TPDM_CMB_CR);
615 /* Set the enable bit */
616 val = val | BIT(0);
617 tpdm_writel(drvdata, val, TPDM_CMB_CR);
618}
619
Satyajit Desaif151d682016-09-12 16:18:03 -0700620static void __tpdm_enable(struct tpdm_drvdata *drvdata)
621{
622 TPDM_UNLOCK(drvdata);
623
624 if (drvdata->clk_enable)
625 tpdm_writel(drvdata, 0x1, TPDM_CLK_CTRL);
626
627 if (test_bit(TPDM_DS_GPR, drvdata->enable_ds))
628 __tpdm_enable_gpr(drvdata);
629
630 if (test_bit(TPDM_DS_BC, drvdata->enable_ds))
631 __tpdm_enable_bc(drvdata);
632
633 if (test_bit(TPDM_DS_TC, drvdata->enable_ds))
634 __tpdm_enable_tc(drvdata);
635
636 if (test_bit(TPDM_DS_DSB, drvdata->enable_ds))
637 __tpdm_enable_dsb(drvdata);
638
639 if (test_bit(TPDM_DS_CMB, drvdata->enable_ds))
640 __tpdm_enable_cmb(drvdata);
Satyajit Desaie104ff52016-09-12 16:38:12 -0700641 else if (test_bit(TPDM_DS_MCMB, drvdata->enable_ds))
642 __tpdm_enable_mcmb(drvdata);
Satyajit Desaif151d682016-09-12 16:18:03 -0700643
644 TPDM_LOCK(drvdata);
645}
646
647static int tpdm_enable(struct coresight_device *csdev,
Satyajit Desaiee828fb2017-02-07 13:51:32 -0800648 struct perf_event *event, u32 mode)
Satyajit Desaif151d682016-09-12 16:18:03 -0700649{
650 struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
651 int ret;
652
653 ret = clk_prepare_enable(drvdata->clk);
654 if (ret)
655 return ret;
656
657 mutex_lock(&drvdata->lock);
658 __tpdm_enable(drvdata);
659 drvdata->enable = true;
660 mutex_unlock(&drvdata->lock);
661
662 dev_info(drvdata->dev, "TPDM tracing enabled\n");
663 return 0;
664}
665
666static void __tpdm_disable_bc(struct tpdm_drvdata *drvdata)
667{
668 uint32_t config;
669
670 config = tpdm_readl(drvdata, TPDM_BC_CR);
671 config = config & ~BIT(0);
672 tpdm_writel(drvdata, config, TPDM_BC_CR);
673}
674
675static void __tpdm_disable_tc(struct tpdm_drvdata *drvdata)
676{
677 uint32_t config;
678
679 config = tpdm_readl(drvdata, TPDM_TC_CR);
680 config = config & ~BIT(0);
681 tpdm_writel(drvdata, config, TPDM_TC_CR);
682}
683
684static void __tpdm_disable_dsb(struct tpdm_drvdata *drvdata)
685{
686 uint32_t config;
687
688 config = tpdm_readl(drvdata, TPDM_DSB_CR);
689 config = config & ~BIT(0);
690 tpdm_writel(drvdata, config, TPDM_DSB_CR);
691}
692
693static void __tpdm_disable_cmb(struct tpdm_drvdata *drvdata)
694{
695 uint32_t config;
696
697 config = tpdm_readl(drvdata, TPDM_CMB_CR);
698 config = config & ~BIT(0);
699 tpdm_writel(drvdata, config, TPDM_CMB_CR);
700}
701
702static void __tpdm_disable(struct tpdm_drvdata *drvdata)
703{
704 TPDM_UNLOCK(drvdata);
705
706 if (test_bit(TPDM_DS_BC, drvdata->enable_ds))
707 __tpdm_disable_bc(drvdata);
708
709 if (test_bit(TPDM_DS_TC, drvdata->enable_ds))
710 __tpdm_disable_tc(drvdata);
711
712 if (test_bit(TPDM_DS_DSB, drvdata->enable_ds))
713 __tpdm_disable_dsb(drvdata);
714
Satyajit Desaibd2deda2017-04-20 18:28:38 -0700715 if (test_bit(TPDM_DS_CMB, drvdata->enable_ds) ||
716 test_bit(TPDM_DS_MCMB, drvdata->enable_ds))
Satyajit Desaif151d682016-09-12 16:18:03 -0700717 __tpdm_disable_cmb(drvdata);
718
719 if (drvdata->clk_enable)
720 tpdm_writel(drvdata, 0x0, TPDM_CLK_CTRL);
721
722 TPDM_LOCK(drvdata);
723}
724
Satyajit Desaiee828fb2017-02-07 13:51:32 -0800725static void tpdm_disable(struct coresight_device *csdev,
726 struct perf_event *event)
Satyajit Desaif151d682016-09-12 16:18:03 -0700727{
728 struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
729
730 mutex_lock(&drvdata->lock);
731 __tpdm_disable(drvdata);
732 drvdata->enable = false;
733 mutex_unlock(&drvdata->lock);
734
735 clk_disable_unprepare(drvdata->clk);
736
737 dev_info(drvdata->dev, "TPDM tracing disabled\n");
738}
739
740static int tpdm_trace_id(struct coresight_device *csdev)
741{
742 struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
743
744 return drvdata->traceid;
745}
746
747static const struct coresight_ops_source tpdm_source_ops = {
748 .trace_id = tpdm_trace_id,
749 .enable = tpdm_enable,
750 .disable = tpdm_disable,
751};
752
753static const struct coresight_ops tpdm_cs_ops = {
754 .source_ops = &tpdm_source_ops,
755};
756
757static ssize_t tpdm_show_available_datasets(struct device *dev,
758 struct device_attribute *attr,
759 char *buf)
760{
761 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
762 ssize_t size = 0;
763
764 if (test_bit(TPDM_DS_IMPLDEF, drvdata->datasets))
765 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s",
766 "IMPLDEF");
767
768 if (test_bit(TPDM_DS_DSB, drvdata->datasets))
769 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "DSB");
770
771 if (test_bit(TPDM_DS_CMB, drvdata->datasets))
772 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "CMB");
773
774 if (test_bit(TPDM_DS_TC, drvdata->datasets))
775 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "TC");
776
777 if (test_bit(TPDM_DS_BC, drvdata->datasets))
778 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "BC");
779
780 if (test_bit(TPDM_DS_GPR, drvdata->datasets))
781 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "GPR");
782
Satyajit Desaie104ff52016-09-12 16:38:12 -0700783 if (test_bit(TPDM_DS_MCMB, drvdata->datasets))
784 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "MCMB");
785
Satyajit Desaif151d682016-09-12 16:18:03 -0700786 size += scnprintf(buf + size, PAGE_SIZE - size, "\n");
787 return size;
788}
Satyajit Desai326497c2016-11-14 10:15:03 -0800789static DEVICE_ATTR(available_datasets, 0444, tpdm_show_available_datasets,
Satyajit Desaif151d682016-09-12 16:18:03 -0700790 NULL);
791
792static ssize_t tpdm_show_enable_datasets(struct device *dev,
793 struct device_attribute *attr,
794 char *buf)
795{
796 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
797 ssize_t size;
798
799 size = scnprintf(buf, PAGE_SIZE, "%*pb\n", TPDM_DATASETS,
800 drvdata->enable_ds);
801
802 if (PAGE_SIZE - size < 2)
803 size = -EINVAL;
804 else
805 size += scnprintf(buf + size, 2, "\n");
806 return size;
807}
808
809static ssize_t tpdm_store_enable_datasets(struct device *dev,
810 struct device_attribute *attr,
811 const char *buf,
812 size_t size)
813{
814 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
815 unsigned long val;
816 int i;
817
818 if (kstrtoul(buf, 16, &val))
819 return -EINVAL;
820
821 mutex_lock(&drvdata->lock);
822 if (drvdata->enable) {
823 mutex_unlock(&drvdata->lock);
824 return -EPERM;
825 }
826
827 for (i = 0; i < TPDM_DATASETS; i++) {
828 if (test_bit(i, drvdata->datasets) && (val & BIT(i)))
829 __set_bit(i, drvdata->enable_ds);
830 else
831 __clear_bit(i, drvdata->enable_ds);
832 }
833 mutex_unlock(&drvdata->lock);
834 return size;
835}
Satyajit Desai326497c2016-11-14 10:15:03 -0800836static DEVICE_ATTR(enable_datasets, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -0700837 tpdm_show_enable_datasets, tpdm_store_enable_datasets);
838
839static ssize_t tpdm_show_gp_regs(struct device *dev,
840 struct device_attribute *attr,
841 char *buf)
842{
843 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
844 ssize_t size = 0;
845 int i = 0;
846
847 if (!test_bit(TPDM_DS_GPR, drvdata->datasets))
848 return -EPERM;
849
850 mutex_lock(&drvdata->lock);
851 for (i = 0; i < TPDM_GPR_REGS_MAX; i++) {
852 if (!test_bit(i, drvdata->gpr->gpr_dirty))
853 continue;
854 size += scnprintf(buf + size, PAGE_SIZE - size,
855 "Index: 0x%x Value: 0x%x\n", i,
856 drvdata->gpr->gp_regs[i]);
857 }
858 mutex_unlock(&drvdata->lock);
859 return size;
860}
861
862static ssize_t tpdm_store_gp_regs(struct device *dev,
863 struct device_attribute *attr,
864 const char *buf,
865 size_t size)
866{
867 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
868 unsigned long index, val;
869
870 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
871 return -EINVAL;
872 if (!test_bit(TPDM_DS_GPR, drvdata->datasets) ||
873 index >= TPDM_GPR_REGS_MAX)
874 return -EPERM;
875
876 mutex_lock(&drvdata->lock);
877 drvdata->gpr->gp_regs[index] = val;
878 __set_bit(index, drvdata->gpr->gpr_dirty);
879 mutex_unlock(&drvdata->lock);
880 return size;
881}
Satyajit Desai326497c2016-11-14 10:15:03 -0800882static DEVICE_ATTR(gp_regs, 0644, tpdm_show_gp_regs,
Satyajit Desaif151d682016-09-12 16:18:03 -0700883 tpdm_store_gp_regs);
884
885static ssize_t tpdm_show_bc_capture_mode(struct device *dev,
886 struct device_attribute *attr,
887 char *buf)
888{
889 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
890
891 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
892 return -EPERM;
893
894 return scnprintf(buf, PAGE_SIZE, "%s\n",
895 drvdata->bc->capture_mode == TPDM_MODE_ATB ?
896 "ATB" : "APB");
897}
898
899static ssize_t tpdm_store_bc_capture_mode(struct device *dev,
900 struct device_attribute *attr,
901 const char *buf,
902 size_t size)
903{
904 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
905 char str[20] = "";
906 uint32_t val;
907
908 if (size >= 20)
909 return -EINVAL;
910 if (sscanf(buf, "%s", str) != 1)
911 return -EINVAL;
912 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
913 return -EPERM;
914
915 mutex_lock(&drvdata->lock);
916 if (!drvdata->enable) {
917 mutex_unlock(&drvdata->lock);
918 return -EPERM;
919 }
920
921 if (!strcmp(str, "ATB")) {
922 drvdata->bc->capture_mode = TPDM_MODE_ATB;
923 } else if (!strcmp(str, "APB") &&
924 drvdata->bc->retrieval_mode == TPDM_MODE_APB) {
925
926 TPDM_UNLOCK(drvdata);
927 val = tpdm_readl(drvdata, TPDM_BC_CR);
928 val = val | BIT(3);
929 tpdm_writel(drvdata, val, TPDM_BC_CR);
930 TPDM_LOCK(drvdata);
931
932 drvdata->bc->capture_mode = TPDM_MODE_APB;
933 } else {
934 mutex_unlock(&drvdata->lock);
935 return -EINVAL;
936 }
937 mutex_unlock(&drvdata->lock);
938 return size;
939}
Satyajit Desai326497c2016-11-14 10:15:03 -0800940static DEVICE_ATTR(bc_capture_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -0700941 tpdm_show_bc_capture_mode, tpdm_store_bc_capture_mode);
942
943static ssize_t tpdm_show_bc_retrieval_mode(struct device *dev,
944 struct device_attribute *attr,
945 char *buf)
946{
947 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
948
949 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
950 return -EPERM;
951
952 return scnprintf(buf, PAGE_SIZE, "%s\n",
953 drvdata->bc->retrieval_mode == TPDM_MODE_ATB ?
954 "ATB" : "APB");
955}
956
957static ssize_t tpdm_store_bc_retrieval_mode(struct device *dev,
958 struct device_attribute *attr,
959 const char *buf,
960 size_t size)
961{
962 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
963 char str[20] = "";
964
965 if (size >= 20)
966 return -EINVAL;
967 if (sscanf(buf, "%s", str) != 1)
968 return -EINVAL;
969 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
970 return -EPERM;
971
972 mutex_lock(&drvdata->lock);
973 if (drvdata->enable) {
974 mutex_unlock(&drvdata->lock);
975 return -EPERM;
976 }
977
978 if (!strcmp(str, "ATB")) {
979 drvdata->bc->retrieval_mode = TPDM_MODE_ATB;
980 } else if (!strcmp(str, "APB")) {
981 drvdata->bc->retrieval_mode = TPDM_MODE_APB;
982 } else {
983 mutex_unlock(&drvdata->lock);
984 return -EINVAL;
985 }
986 mutex_unlock(&drvdata->lock);
987 return size;
988}
Satyajit Desai326497c2016-11-14 10:15:03 -0800989static DEVICE_ATTR(bc_retrieval_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -0700990 tpdm_show_bc_retrieval_mode, tpdm_store_bc_retrieval_mode);
991
992static ssize_t tpdm_store_bc_reset_counters(struct device *dev,
993 struct device_attribute *attr,
994 const char *buf,
995 size_t size)
996{
997 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
998 unsigned long val;
999
1000 if (kstrtoul(buf, 16, &val))
1001 return -EINVAL;
1002 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1003 return -EPERM;
1004
1005 mutex_lock(&drvdata->lock);
1006 if (!drvdata->enable) {
1007 mutex_unlock(&drvdata->lock);
1008 return -EPERM;
1009 }
1010
1011 if (val) {
1012 TPDM_UNLOCK(drvdata);
1013 val = tpdm_readl(drvdata, TPDM_BC_CR);
1014 val = val | BIT(1);
1015 tpdm_writel(drvdata, val, TPDM_BC_CR);
1016 TPDM_LOCK(drvdata);
1017 }
1018 mutex_unlock(&drvdata->lock);
1019 return size;
1020}
Satyajit Desai326497c2016-11-14 10:15:03 -08001021static DEVICE_ATTR(bc_reset_counters, 0644, NULL,
Satyajit Desaif151d682016-09-12 16:18:03 -07001022 tpdm_store_bc_reset_counters);
1023
1024static ssize_t tpdm_show_bc_sat_mode(struct device *dev,
1025 struct device_attribute *attr,
1026 char *buf)
1027{
1028 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1029
1030 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1031 return -EPERM;
1032
1033 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1034 (unsigned long)drvdata->bc->sat_mode);
1035}
1036
1037static ssize_t tpdm_store_bc_sat_mode(struct device *dev,
1038 struct device_attribute *attr,
1039 const char *buf,
1040 size_t size)
1041{
1042 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1043 unsigned long val;
1044
1045 if (kstrtoul(buf, 16, &val))
1046 return -EINVAL;
1047 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1048 return -EPERM;
1049
1050 mutex_lock(&drvdata->lock);
1051 drvdata->bc->sat_mode = val;
1052 mutex_unlock(&drvdata->lock);
1053 return size;
1054}
Satyajit Desai326497c2016-11-14 10:15:03 -08001055static DEVICE_ATTR(bc_sat_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001056 tpdm_show_bc_sat_mode, tpdm_store_bc_sat_mode);
1057
1058static ssize_t tpdm_show_bc_enable_counters(struct device *dev,
1059 struct device_attribute *attr,
1060 char *buf)
1061{
1062 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1063
1064 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1065 return -EPERM;
1066
1067 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1068 (unsigned long)drvdata->bc->enable_counters);
1069}
1070
1071static ssize_t tpdm_store_bc_enable_counters(struct device *dev,
1072 struct device_attribute *attr,
1073 const char *buf,
1074 size_t size)
1075{
1076 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1077 unsigned long val;
1078
1079 if (kstrtoul(buf, 16, &val))
1080 return -EINVAL;
1081 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1082 return -EPERM;
1083
1084 mutex_lock(&drvdata->lock);
1085 drvdata->bc->enable_counters = val;
1086 mutex_unlock(&drvdata->lock);
1087 return size;
1088}
Satyajit Desai326497c2016-11-14 10:15:03 -08001089static DEVICE_ATTR(bc_enable_counters, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001090 tpdm_show_bc_enable_counters, tpdm_store_bc_enable_counters);
1091
1092static ssize_t tpdm_show_bc_clear_counters(struct device *dev,
1093 struct device_attribute *attr,
1094 char *buf)
1095{
1096 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1097
1098 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1099 return -EPERM;
1100
1101 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1102 (unsigned long)drvdata->bc->clear_counters);
1103}
1104
1105static ssize_t tpdm_store_bc_clear_counters(struct device *dev,
1106 struct device_attribute *attr,
1107 const char *buf,
1108 size_t size)
1109{
1110 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1111 unsigned long val;
1112
1113 if (kstrtoul(buf, 16, &val))
1114 return -EINVAL;
1115 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1116 return -EPERM;
1117
1118 mutex_lock(&drvdata->lock);
1119 drvdata->bc->clear_counters = val;
1120 mutex_unlock(&drvdata->lock);
1121 return size;
1122}
Satyajit Desai326497c2016-11-14 10:15:03 -08001123static DEVICE_ATTR(bc_clear_counters, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001124 tpdm_show_bc_clear_counters, tpdm_store_bc_clear_counters);
1125
1126static ssize_t tpdm_show_bc_enable_irq(struct device *dev,
1127 struct device_attribute *attr,
1128 char *buf)
1129{
1130 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1131
1132 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1133 return -EPERM;
1134
1135 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1136 (unsigned long)drvdata->bc->enable_irq);
1137}
1138
1139static ssize_t tpdm_store_bc_enable_irq(struct device *dev,
1140 struct device_attribute *attr,
1141 const char *buf,
1142 size_t size)
1143{
1144 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1145 unsigned long val;
1146
1147 if (kstrtoul(buf, 16, &val))
1148 return -EINVAL;
1149 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1150 return -EPERM;
1151
1152 mutex_lock(&drvdata->lock);
1153 drvdata->bc->enable_irq = val;
1154 mutex_unlock(&drvdata->lock);
1155 return size;
1156}
Satyajit Desai326497c2016-11-14 10:15:03 -08001157static DEVICE_ATTR(bc_enable_irq, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001158 tpdm_show_bc_enable_irq, tpdm_store_bc_enable_irq);
1159
1160static ssize_t tpdm_show_bc_clear_irq(struct device *dev,
1161 struct device_attribute *attr,
1162 char *buf)
1163{
1164 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1165
1166 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1167 return -EPERM;
1168
1169 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1170 (unsigned long)drvdata->bc->clear_irq);
1171}
1172
1173static ssize_t tpdm_store_bc_clear_irq(struct device *dev,
1174 struct device_attribute *attr,
1175 const char *buf,
1176 size_t size)
1177{
1178 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1179 unsigned long val;
1180
1181 if (kstrtoul(buf, 16, &val))
1182 return -EINVAL;
1183 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1184 return -EPERM;
1185
1186 mutex_lock(&drvdata->lock);
1187 drvdata->bc->clear_irq = val;
1188 mutex_unlock(&drvdata->lock);
1189 return size;
1190}
Satyajit Desai326497c2016-11-14 10:15:03 -08001191static DEVICE_ATTR(bc_clear_irq, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001192 tpdm_show_bc_clear_irq, tpdm_store_bc_clear_irq);
1193
1194static ssize_t tpdm_show_bc_trig_val_lo(struct device *dev,
1195 struct device_attribute *attr,
1196 char *buf)
1197{
1198 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1199 ssize_t size = 0;
1200 int i = 0;
1201
1202 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1203 return -EPERM;
1204
1205 mutex_lock(&drvdata->lock);
1206 for (i = 0; i < TPDM_BC_MAX_COUNTERS; i++)
1207 size += scnprintf(buf + size, PAGE_SIZE - size,
1208 "Index: 0x%x Value: 0x%x\n", i,
1209 drvdata->bc->trig_val_lo[i]);
1210 mutex_unlock(&drvdata->lock);
1211 return size;
1212}
1213
1214static ssize_t tpdm_store_bc_trig_val_lo(struct device *dev,
1215 struct device_attribute *attr,
1216 const char *buf,
1217 size_t size)
1218{
1219 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1220 unsigned long index, val;
1221
1222 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
1223 return -EINVAL;
1224 if (!test_bit(TPDM_DS_BC, drvdata->datasets) ||
1225 index >= drvdata->bc_counters_avail ||
1226 drvdata->bc_trig_type == TPDM_SUPPORT_TYPE_NO ||
1227 (drvdata->bc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL && index > 0))
1228 return -EPERM;
1229
1230 mutex_lock(&drvdata->lock);
1231 drvdata->bc->trig_val_lo[index] = val;
1232 mutex_unlock(&drvdata->lock);
1233 return size;
1234}
Satyajit Desai326497c2016-11-14 10:15:03 -08001235static DEVICE_ATTR(bc_trig_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001236 tpdm_show_bc_trig_val_lo, tpdm_store_bc_trig_val_lo);
1237
1238static ssize_t tpdm_show_bc_trig_val_hi(struct device *dev,
1239 struct device_attribute *attr,
1240 char *buf)
1241{
1242 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1243 ssize_t size = 0;
1244 int i = 0;
1245
1246 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1247 return -EPERM;
1248
1249 mutex_lock(&drvdata->lock);
1250 for (i = 0; i < TPDM_BC_MAX_COUNTERS; i++)
1251 size += scnprintf(buf + size, PAGE_SIZE - size,
1252 "Index: 0x%x Value: 0x%x\n", i,
1253 drvdata->bc->trig_val_hi[i]);
1254 mutex_unlock(&drvdata->lock);
1255 return size;
1256}
1257
1258static ssize_t tpdm_store_bc_trig_val_hi(struct device *dev,
1259 struct device_attribute *attr,
1260 const char *buf,
1261 size_t size)
1262{
1263 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1264 unsigned long index, val;
1265
1266 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
1267 return -EINVAL;
1268 if (!test_bit(TPDM_DS_BC, drvdata->datasets) ||
1269 index >= drvdata->bc_counters_avail ||
1270 drvdata->bc_trig_type == TPDM_SUPPORT_TYPE_NO ||
1271 (drvdata->bc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL && index > 0))
1272 return -EPERM;
1273
1274 mutex_lock(&drvdata->lock);
1275 drvdata->bc->trig_val_hi[index] = val;
1276 mutex_unlock(&drvdata->lock);
1277 return size;
1278}
Satyajit Desai326497c2016-11-14 10:15:03 -08001279static DEVICE_ATTR(bc_trig_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001280 tpdm_show_bc_trig_val_hi, tpdm_store_bc_trig_val_hi);
1281
1282static ssize_t tpdm_show_bc_enable_ganging(struct device *dev,
1283 struct device_attribute *attr,
1284 char *buf)
1285{
1286 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1287
1288 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1289 return -EPERM;
1290
1291 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1292 (unsigned long)drvdata->bc->enable_ganging);
1293}
1294
1295static ssize_t tpdm_store_bc_enable_ganging(struct device *dev,
1296 struct device_attribute *attr,
1297 const char *buf,
1298 size_t size)
1299{
1300 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1301 unsigned long val;
1302
1303 if (kstrtoul(buf, 16, &val))
1304 return -EINVAL;
1305 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1306 return -EPERM;
1307
1308 mutex_lock(&drvdata->lock);
1309 drvdata->bc->enable_ganging = val;
1310 mutex_unlock(&drvdata->lock);
1311 return size;
1312}
Satyajit Desai326497c2016-11-14 10:15:03 -08001313static DEVICE_ATTR(bc_enable_ganging, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001314 tpdm_show_bc_enable_ganging, tpdm_store_bc_enable_ganging);
1315
1316static ssize_t tpdm_show_bc_overflow_val(struct device *dev,
1317 struct device_attribute *attr,
1318 char *buf)
1319{
1320 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1321 ssize_t size = 0;
1322 int i = 0;
1323
1324 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1325 return -EPERM;
1326
1327 mutex_lock(&drvdata->lock);
1328 for (i = 0; i < TPDM_BC_MAX_OVERFLOW; i++)
1329 size += scnprintf(buf + size, PAGE_SIZE - size,
1330 "Index: 0x%x Value: 0x%x\n", i,
1331 drvdata->bc->overflow_val[i]);
1332 mutex_unlock(&drvdata->lock);
1333 return size;
1334}
1335
1336static ssize_t tpdm_store_bc_overflow_val(struct device *dev,
1337 struct device_attribute *attr,
1338 const char *buf,
1339 size_t size)
1340{
1341 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1342 unsigned long index, val;
1343
1344 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
1345 return -EINVAL;
1346 if (!test_bit(TPDM_DS_BC, drvdata->datasets) ||
1347 index >= TPDM_BC_MAX_OVERFLOW)
1348 return -EPERM;
1349
1350 mutex_lock(&drvdata->lock);
1351 drvdata->bc->overflow_val[index] = val;
1352 mutex_unlock(&drvdata->lock);
1353 return size;
1354}
Satyajit Desai326497c2016-11-14 10:15:03 -08001355static DEVICE_ATTR(bc_overflow_val, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001356 tpdm_show_bc_overflow_val, tpdm_store_bc_overflow_val);
1357
1358static ssize_t tpdm_show_bc_ovsr(struct device *dev,
1359 struct device_attribute *attr,
1360 char *buf)
1361{
1362 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1363 unsigned long val;
1364
1365 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1366 return -EPERM;
1367
1368 mutex_lock(&drvdata->lock);
1369 if (!drvdata->enable) {
1370 mutex_unlock(&drvdata->lock);
1371 return -EPERM;
1372 }
1373
1374 TPDM_UNLOCK(drvdata);
1375 val = tpdm_readl(drvdata, TPDM_BC_OVSR);
1376 TPDM_LOCK(drvdata);
1377 mutex_unlock(&drvdata->lock);
1378 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
1379}
1380
1381static ssize_t tpdm_store_bc_ovsr(struct device *dev,
1382 struct device_attribute *attr,
1383 const char *buf,
1384 size_t size)
1385{
1386 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1387 unsigned long val;
1388
1389 if (kstrtoul(buf, 16, &val))
1390 return -EINVAL;
1391 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1392 return -EPERM;
1393
1394 mutex_lock(&drvdata->lock);
1395 if (!drvdata->enable) {
1396 mutex_unlock(&drvdata->lock);
1397 return -EPERM;
1398 }
1399
1400 if (val) {
1401 TPDM_UNLOCK(drvdata);
1402 tpdm_writel(drvdata, val, TPDM_BC_OVSR);
1403 TPDM_LOCK(drvdata);
1404 }
1405 mutex_unlock(&drvdata->lock);
1406 return size;
1407}
Satyajit Desai326497c2016-11-14 10:15:03 -08001408static DEVICE_ATTR(bc_ovsr, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001409 tpdm_show_bc_ovsr, tpdm_store_bc_ovsr);
1410
1411static ssize_t tpdm_show_bc_counter_sel(struct device *dev,
1412 struct device_attribute *attr,
1413 char *buf)
1414{
1415 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1416 unsigned long val;
1417
1418 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1419 return -EPERM;
1420
1421 mutex_lock(&drvdata->lock);
1422 if (!drvdata->enable) {
1423 mutex_unlock(&drvdata->lock);
1424 return -EPERM;
1425 }
1426
1427 TPDM_UNLOCK(drvdata);
1428 val = tpdm_readl(drvdata, TPDM_BC_SELR);
1429 TPDM_LOCK(drvdata);
1430 mutex_unlock(&drvdata->lock);
1431 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
1432}
1433
1434static ssize_t tpdm_store_bc_counter_sel(struct device *dev,
1435 struct device_attribute *attr,
1436 const char *buf,
1437 size_t size)
1438{
1439 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1440 unsigned long val;
1441
1442 if (kstrtoul(buf, 16, &val))
1443 return -EINVAL;
1444 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1445 return -EPERM;
1446
1447 mutex_lock(&drvdata->lock);
1448 if (!drvdata->enable || val >= drvdata->bc_counters_avail) {
1449 mutex_unlock(&drvdata->lock);
1450 return -EPERM;
1451 }
1452
1453 TPDM_UNLOCK(drvdata);
1454 tpdm_writel(drvdata, val, TPDM_BC_SELR);
1455 TPDM_LOCK(drvdata);
1456 mutex_unlock(&drvdata->lock);
1457 return size;
1458}
Satyajit Desai326497c2016-11-14 10:15:03 -08001459static DEVICE_ATTR(bc_counter_sel, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001460 tpdm_show_bc_counter_sel, tpdm_store_bc_counter_sel);
1461
1462static ssize_t tpdm_show_bc_count_val_lo(struct device *dev,
1463 struct device_attribute *attr,
1464 char *buf)
1465{
1466 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1467 unsigned long val;
1468
1469 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1470 return -EPERM;
1471
1472 mutex_lock(&drvdata->lock);
1473 if (!drvdata->enable) {
1474 mutex_unlock(&drvdata->lock);
1475 return -EPERM;
1476 }
1477
1478 TPDM_UNLOCK(drvdata);
1479 val = tpdm_readl(drvdata, TPDM_BC_CNTR_LO);
1480 TPDM_LOCK(drvdata);
1481 mutex_unlock(&drvdata->lock);
1482 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
1483}
1484
1485static ssize_t tpdm_store_bc_count_val_lo(struct device *dev,
1486 struct device_attribute *attr,
1487 const char *buf,
1488 size_t size)
1489{
1490 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1491 unsigned long val, select;
1492
1493 if (kstrtoul(buf, 16, &val))
1494 return -EINVAL;
1495 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1496 return -EPERM;
1497
1498 mutex_lock(&drvdata->lock);
1499 if (!drvdata->enable) {
1500 mutex_unlock(&drvdata->lock);
1501 return -EPERM;
1502 }
1503
1504 if (val) {
1505 TPDM_UNLOCK(drvdata);
1506 select = tpdm_readl(drvdata, TPDM_BC_SELR);
1507
1508 /* Check if selected counter is disabled */
1509 if (BVAL(tpdm_readl(drvdata, TPDM_BC_CNTENSET), select)) {
1510 mutex_unlock(&drvdata->lock);
1511 return -EPERM;
1512 }
1513
1514 tpdm_writel(drvdata, val, TPDM_BC_CNTR_LO);
1515 TPDM_LOCK(drvdata);
1516 }
1517 mutex_unlock(&drvdata->lock);
1518 return size;
1519}
Satyajit Desai326497c2016-11-14 10:15:03 -08001520static DEVICE_ATTR(bc_count_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001521 tpdm_show_bc_count_val_lo, tpdm_store_bc_count_val_lo);
1522
1523static ssize_t tpdm_show_bc_count_val_hi(struct device *dev,
1524 struct device_attribute *attr,
1525 char *buf)
1526{
1527 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1528 unsigned long val;
1529
1530 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1531 return -EPERM;
1532
1533 mutex_lock(&drvdata->lock);
1534 if (!drvdata->enable) {
1535 mutex_unlock(&drvdata->lock);
1536 return -EPERM;
1537 }
1538
1539 TPDM_UNLOCK(drvdata);
1540 val = tpdm_readl(drvdata, TPDM_BC_CNTR_HI);
1541 TPDM_LOCK(drvdata);
1542 mutex_unlock(&drvdata->lock);
1543 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
1544}
1545
1546static ssize_t tpdm_store_bc_count_val_hi(struct device *dev,
1547 struct device_attribute *attr,
1548 const char *buf,
1549 size_t size)
1550{
1551 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1552 unsigned long val, select;
1553
1554 if (kstrtoul(buf, 16, &val))
1555 return -EINVAL;
1556 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1557 return -EPERM;
1558
1559 mutex_lock(&drvdata->lock);
1560 if (!drvdata->enable) {
1561 mutex_unlock(&drvdata->lock);
1562 return -EPERM;
1563 }
1564
1565 if (val) {
1566 TPDM_UNLOCK(drvdata);
1567 select = tpdm_readl(drvdata, TPDM_BC_SELR);
1568
1569 /* Check if selected counter is disabled */
1570 if (BVAL(tpdm_readl(drvdata, TPDM_BC_CNTENSET), select)) {
1571 mutex_unlock(&drvdata->lock);
1572 return -EPERM;
1573 }
1574
1575 tpdm_writel(drvdata, val, TPDM_BC_CNTR_HI);
1576 TPDM_LOCK(drvdata);
1577 }
1578 mutex_unlock(&drvdata->lock);
1579 return size;
1580}
Satyajit Desai326497c2016-11-14 10:15:03 -08001581static DEVICE_ATTR(bc_count_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001582 tpdm_show_bc_count_val_hi, tpdm_store_bc_count_val_hi);
1583
1584static ssize_t tpdm_show_bc_shadow_val_lo(struct device *dev,
1585 struct device_attribute *attr,
1586 char *buf)
1587{
1588 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1589 ssize_t size = 0;
1590 int i = 0;
1591
1592 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1593 return -EPERM;
1594
1595 mutex_lock(&drvdata->lock);
1596 if (!drvdata->enable) {
1597 mutex_unlock(&drvdata->lock);
1598 return -EPERM;
1599 }
1600
1601 TPDM_UNLOCK(drvdata);
1602 for (i = 0; i < drvdata->bc_counters_avail; i++) {
1603 size += scnprintf(buf + size, PAGE_SIZE - size,
1604 "Index: 0x%x Value: 0x%x\n", i,
1605 tpdm_readl(drvdata, TPDM_BC_SHADOW_LO(i)));
1606 }
1607 TPDM_LOCK(drvdata);
1608 mutex_unlock(&drvdata->lock);
1609 return size;
1610}
Satyajit Desai326497c2016-11-14 10:15:03 -08001611static DEVICE_ATTR(bc_shadow_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001612 tpdm_show_bc_shadow_val_lo, NULL);
1613
1614static ssize_t tpdm_show_bc_shadow_val_hi(struct device *dev,
1615 struct device_attribute *attr,
1616 char *buf)
1617{
1618 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1619 ssize_t size = 0;
1620 int i = 0;
1621
1622 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1623 return -EPERM;
1624
1625 mutex_lock(&drvdata->lock);
1626 if (!drvdata->enable) {
1627 mutex_unlock(&drvdata->lock);
1628 return -EPERM;
1629 }
1630
1631 TPDM_UNLOCK(drvdata);
1632 for (i = 0; i < drvdata->bc_counters_avail; i++)
1633 size += scnprintf(buf + size, PAGE_SIZE - size,
1634 "Index: 0x%x Value: 0x%x\n", i,
1635 tpdm_readl(drvdata, TPDM_BC_SHADOW_HI(i)));
1636 TPDM_LOCK(drvdata);
1637 mutex_unlock(&drvdata->lock);
1638 return size;
1639}
Satyajit Desai326497c2016-11-14 10:15:03 -08001640static DEVICE_ATTR(bc_shadow_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001641 tpdm_show_bc_shadow_val_hi, NULL);
1642
1643static ssize_t tpdm_show_bc_sw_inc(struct device *dev,
1644 struct device_attribute *attr,
1645 char *buf)
1646{
1647 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1648 unsigned long val;
1649
1650 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1651 return -EPERM;
1652
1653 mutex_lock(&drvdata->lock);
1654 if (!drvdata->enable) {
1655 mutex_unlock(&drvdata->lock);
1656 return -EPERM;
1657 }
1658
1659 TPDM_UNLOCK(drvdata);
1660 val = tpdm_readl(drvdata, TPDM_BC_SWINC);
1661 TPDM_LOCK(drvdata);
1662 mutex_unlock(&drvdata->lock);
1663 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
1664}
1665
1666static ssize_t tpdm_store_bc_sw_inc(struct device *dev,
1667 struct device_attribute *attr,
1668 const char *buf,
1669 size_t size)
1670{
1671 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1672 unsigned long val;
1673
1674 if (kstrtoul(buf, 16, &val))
1675 return -EINVAL;
1676 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1677 return -EPERM;
1678
1679 mutex_lock(&drvdata->lock);
1680 if (!drvdata->enable) {
1681 mutex_unlock(&drvdata->lock);
1682 return -EPERM;
1683 }
1684
1685 if (val) {
1686 TPDM_UNLOCK(drvdata);
1687 tpdm_writel(drvdata, val, TPDM_BC_SWINC);
1688 TPDM_LOCK(drvdata);
1689 }
1690 mutex_unlock(&drvdata->lock);
1691 return size;
1692}
Satyajit Desai326497c2016-11-14 10:15:03 -08001693static DEVICE_ATTR(bc_sw_inc, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001694 tpdm_show_bc_sw_inc, tpdm_store_bc_sw_inc);
1695
Satyajit Desaib34b2c02017-01-11 16:59:38 -08001696static ssize_t tpdm_show_bc_msr(struct device *dev,
1697 struct device_attribute *attr,
1698 char *buf)
1699{
1700 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1701 unsigned int i;
1702 ssize_t len = 0;
1703
1704 if (!drvdata->msr_support)
1705 return -EINVAL;
1706
1707 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1708 return -EPERM;
1709
1710 for (i = 0; i < TPDM_BC_MAX_MSR; i++)
1711 len += scnprintf(buf + len, PAGE_SIZE - len, "%u 0x%x\n",
1712 i, drvdata->bc->msr[i]);
1713
1714 return len;
1715}
1716
Satyajit Desaif151d682016-09-12 16:18:03 -07001717static ssize_t tpdm_store_bc_msr(struct device *dev,
1718 struct device_attribute *attr,
1719 const char *buf,
1720 size_t size)
1721{
1722 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1723 unsigned int num, val;
1724 int nval;
1725
1726 if (!drvdata->msr_support)
1727 return -EINVAL;
1728
1729 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1730 return -EPERM;
1731
1732 nval = sscanf(buf, "%u %x", &num, &val);
1733 if (nval != 2)
1734 return -EINVAL;
1735
1736 if (num >= TPDM_BC_MAX_MSR)
1737 return -EINVAL;
1738
1739 mutex_lock(&drvdata->lock);
1740 drvdata->bc->msr[num] = val;
1741 mutex_unlock(&drvdata->lock);
1742 return size;
1743}
Satyajit Desaib34b2c02017-01-11 16:59:38 -08001744static DEVICE_ATTR(bc_msr, 0644, tpdm_show_bc_msr, tpdm_store_bc_msr);
Satyajit Desaif151d682016-09-12 16:18:03 -07001745
1746static ssize_t tpdm_show_tc_capture_mode(struct device *dev,
1747 struct device_attribute *attr,
1748 char *buf)
1749{
1750 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1751
1752 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1753 return -EPERM;
1754
1755 return scnprintf(buf, PAGE_SIZE, "%s\n",
1756 drvdata->tc->capture_mode == TPDM_MODE_ATB ?
1757 "ATB" : "APB");
1758}
1759
1760static ssize_t tpdm_store_tc_capture_mode(struct device *dev,
1761 struct device_attribute *attr,
1762 const char *buf,
1763 size_t size)
1764{
1765 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1766 char str[20] = "";
1767 uint32_t val;
1768
1769 if (size >= 20)
1770 return -EINVAL;
1771 if (sscanf(buf, "%s", str) != 1)
1772 return -EINVAL;
1773 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
1774 return -EPERM;
1775
1776 mutex_lock(&drvdata->lock);
1777 if (!drvdata->enable) {
1778 mutex_unlock(&drvdata->lock);
1779 return -EPERM;
1780 }
1781
1782 if (!strcmp(str, "ATB")) {
1783 drvdata->tc->capture_mode = TPDM_MODE_ATB;
1784 } else if (!strcmp(str, "APB") &&
1785 drvdata->tc->retrieval_mode == TPDM_MODE_APB) {
1786
1787 TPDM_UNLOCK(drvdata);
1788 val = tpdm_readl(drvdata, TPDM_TC_CR);
1789 val = val | BIT(3);
1790 tpdm_writel(drvdata, val, TPDM_TC_CR);
1791 TPDM_LOCK(drvdata);
1792
1793 drvdata->tc->capture_mode = TPDM_MODE_APB;
1794 } else {
1795 mutex_unlock(&drvdata->lock);
1796 return -EINVAL;
1797 }
1798 mutex_unlock(&drvdata->lock);
1799 return size;
1800}
Satyajit Desai326497c2016-11-14 10:15:03 -08001801static DEVICE_ATTR(tc_capture_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001802 tpdm_show_tc_capture_mode, tpdm_store_tc_capture_mode);
1803
1804static ssize_t tpdm_show_tc_retrieval_mode(struct device *dev,
1805 struct device_attribute *attr,
1806 char *buf)
1807{
1808 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1809
1810 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1811 return -EPERM;
1812
1813 return scnprintf(buf, PAGE_SIZE, "%s\n",
1814 drvdata->tc->retrieval_mode == TPDM_MODE_ATB ?
1815 "ATB" : "APB");
1816}
1817
1818static ssize_t tpdm_store_tc_retrieval_mode(struct device *dev,
1819 struct device_attribute *attr,
1820 const char *buf,
1821 size_t size)
1822{
1823 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1824 char str[20] = "";
1825
1826 if (size >= 20)
1827 return -EINVAL;
1828 if (sscanf(buf, "%s", str) != 1)
1829 return -EINVAL;
1830 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1831 return -EPERM;
1832
1833 mutex_lock(&drvdata->lock);
1834 if (drvdata->enable) {
1835 mutex_unlock(&drvdata->lock);
1836 return -EPERM;
1837 }
1838
1839 if (!strcmp(str, "ATB")) {
1840 drvdata->tc->retrieval_mode = TPDM_MODE_ATB;
1841 } else if (!strcmp(str, "APB")) {
1842 drvdata->tc->retrieval_mode = TPDM_MODE_APB;
1843 } else {
1844 mutex_unlock(&drvdata->lock);
1845 return -EINVAL;
1846 }
1847 mutex_unlock(&drvdata->lock);
1848 return size;
1849}
Satyajit Desai326497c2016-11-14 10:15:03 -08001850static DEVICE_ATTR(tc_retrieval_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001851 tpdm_show_tc_retrieval_mode, tpdm_store_tc_retrieval_mode);
1852
1853static ssize_t tpdm_store_tc_reset_counters(struct device *dev,
1854 struct device_attribute *attr,
1855 const char *buf,
1856 size_t size)
1857{
1858 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1859 unsigned long val;
1860
1861 if (kstrtoul(buf, 16, &val))
1862 return -EINVAL;
1863 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1864 return -EPERM;
1865
1866 mutex_lock(&drvdata->lock);
1867 if (!drvdata->enable) {
1868 mutex_unlock(&drvdata->lock);
1869 return -EPERM;
1870 }
1871
1872 if (val) {
1873 TPDM_UNLOCK(drvdata);
1874 val = tpdm_readl(drvdata, TPDM_TC_CR);
1875 val = val | BIT(1);
1876 tpdm_writel(drvdata, val, TPDM_TC_CR);
1877 TPDM_LOCK(drvdata);
1878 }
1879 mutex_unlock(&drvdata->lock);
1880 return size;
1881}
Satyajit Desai326497c2016-11-14 10:15:03 -08001882static DEVICE_ATTR(tc_reset_counters, 0644, NULL,
Satyajit Desaif151d682016-09-12 16:18:03 -07001883 tpdm_store_tc_reset_counters);
1884
1885static ssize_t tpdm_show_tc_sat_mode(struct device *dev,
1886 struct device_attribute *attr,
1887 char *buf)
1888{
1889 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1890
1891 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1892 return -EPERM;
1893
1894 return scnprintf(buf, PAGE_SIZE, "%u\n",
1895 (unsigned int)drvdata->tc->sat_mode);
1896}
1897
1898static ssize_t tpdm_store_tc_sat_mode(struct device *dev,
1899 struct device_attribute *attr,
1900 const char *buf,
1901 size_t size)
1902{
1903 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1904 unsigned long val;
1905
1906 if (kstrtoul(buf, 16, &val))
1907 return -EINVAL;
1908 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1909 return -EPERM;
1910
1911 mutex_lock(&drvdata->lock);
1912 if (val)
1913 drvdata->tc->sat_mode = true;
1914 else
1915 drvdata->tc->sat_mode = false;
1916 mutex_unlock(&drvdata->lock);
1917 return size;
1918}
Satyajit Desai326497c2016-11-14 10:15:03 -08001919static DEVICE_ATTR(tc_sat_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001920 tpdm_show_tc_sat_mode, tpdm_store_tc_sat_mode);
1921
1922static ssize_t tpdm_show_tc_enable_counters(struct device *dev,
1923 struct device_attribute *attr,
1924 char *buf)
1925{
1926 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1927
1928 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1929 return -EPERM;
1930
1931 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1932 (unsigned long)drvdata->tc->enable_counters);
1933}
1934
1935static ssize_t tpdm_store_tc_enable_counters(struct device *dev,
1936 struct device_attribute *attr,
1937 const char *buf,
1938 size_t size)
1939{
1940 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1941 unsigned long val;
1942
1943 if (kstrtoul(buf, 16, &val))
1944 return -EINVAL;
1945 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1946 return -EPERM;
1947 if (val >> drvdata->tc_counters_avail)
1948 return -EPERM;
1949
1950 mutex_lock(&drvdata->lock);
1951 drvdata->tc->enable_counters = val;
1952 mutex_unlock(&drvdata->lock);
1953 return size;
1954}
Satyajit Desai326497c2016-11-14 10:15:03 -08001955static DEVICE_ATTR(tc_enable_counters, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001956 tpdm_show_tc_enable_counters, tpdm_store_tc_enable_counters);
1957
1958static ssize_t tpdm_show_tc_clear_counters(struct device *dev,
1959 struct device_attribute *attr,
1960 char *buf)
1961{
1962 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1963
1964 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1965 return -EPERM;
1966
1967 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1968 (unsigned long)drvdata->tc->clear_counters);
1969}
1970
1971static ssize_t tpdm_store_tc_clear_counters(struct device *dev,
1972 struct device_attribute *attr,
1973 const char *buf,
1974 size_t size)
1975{
1976 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1977 unsigned long val;
1978
1979 if (kstrtoul(buf, 16, &val))
1980 return -EINVAL;
1981 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1982 return -EPERM;
1983 if (val >> drvdata->tc_counters_avail)
1984 return -EPERM;
1985
1986 mutex_lock(&drvdata->lock);
1987 drvdata->tc->clear_counters = val;
1988 mutex_unlock(&drvdata->lock);
1989 return size;
1990}
Satyajit Desai326497c2016-11-14 10:15:03 -08001991static DEVICE_ATTR(tc_clear_counters, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001992 tpdm_show_tc_clear_counters, tpdm_store_tc_clear_counters);
1993
1994static ssize_t tpdm_show_tc_enable_irq(struct device *dev,
1995 struct device_attribute *attr,
1996 char *buf)
1997{
1998 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1999
2000 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2001 return -EPERM;
2002
2003 return scnprintf(buf, PAGE_SIZE, "%lx\n",
2004 (unsigned long)drvdata->tc->enable_irq);
2005}
2006
2007static ssize_t tpdm_store_tc_enable_irq(struct device *dev,
2008 struct device_attribute *attr,
2009 const char *buf,
2010 size_t size)
2011{
2012 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2013 unsigned long val;
2014
2015 if (kstrtoul(buf, 16, &val))
2016 return -EINVAL;
2017 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2018 return -EPERM;
2019
2020 mutex_lock(&drvdata->lock);
2021 drvdata->tc->enable_irq = val;
2022 mutex_unlock(&drvdata->lock);
2023 return size;
2024}
Satyajit Desai326497c2016-11-14 10:15:03 -08002025static DEVICE_ATTR(tc_enable_irq, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002026 tpdm_show_tc_enable_irq, tpdm_store_tc_enable_irq);
2027
2028static ssize_t tpdm_show_tc_clear_irq(struct device *dev,
2029 struct device_attribute *attr,
2030 char *buf)
2031{
2032 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2033
2034 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2035 return -EPERM;
2036
2037 return scnprintf(buf, PAGE_SIZE, "%lx\n",
2038 (unsigned long)drvdata->tc->clear_irq);
2039}
2040
2041static ssize_t tpdm_store_tc_clear_irq(struct device *dev,
2042 struct device_attribute *attr,
2043 const char *buf,
2044 size_t size)
2045{
2046 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2047 unsigned long val;
2048
2049 if (kstrtoul(buf, 16, &val))
2050 return -EINVAL;
2051 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2052 return -EPERM;
2053
2054 mutex_lock(&drvdata->lock);
2055 drvdata->tc->clear_irq = val;
2056 mutex_unlock(&drvdata->lock);
2057 return size;
2058}
Satyajit Desai326497c2016-11-14 10:15:03 -08002059static DEVICE_ATTR(tc_clear_irq, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002060 tpdm_show_tc_clear_irq, tpdm_store_tc_clear_irq);
2061
2062static ssize_t tpdm_show_tc_trig_sel(struct device *dev,
2063 struct device_attribute *attr,
2064 char *buf)
2065{
2066 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2067 ssize_t size = 0;
2068 int i = 0;
2069
2070 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2071 return -EPERM;
2072
2073 mutex_lock(&drvdata->lock);
2074 for (i = 0; i < TPDM_TC_MAX_TRIG; i++) {
2075 size += scnprintf(buf + size, PAGE_SIZE - size,
2076 "Index: 0x%x Value: 0x%x\n", i,
2077 drvdata->tc->trig_sel[i]);
2078 }
2079 mutex_unlock(&drvdata->lock);
2080 return size;
2081}
2082
2083static ssize_t tpdm_store_tc_trig_sel(struct device *dev,
2084 struct device_attribute *attr,
2085 const char *buf,
2086 size_t size)
2087{
2088 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2089 unsigned long index, val;
2090
2091 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2092 return -EINVAL;
2093 if (!test_bit(TPDM_DS_TC, drvdata->datasets) ||
2094 index >= TPDM_TC_MAX_TRIG ||
2095 drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_NO ||
2096 (drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL && index > 0))
2097 return -EPERM;
2098
2099 mutex_lock(&drvdata->lock);
2100 drvdata->tc->trig_sel[index] = val;
2101 mutex_unlock(&drvdata->lock);
2102 return size;
2103}
Satyajit Desai326497c2016-11-14 10:15:03 -08002104static DEVICE_ATTR(tc_trig_sel, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002105 tpdm_show_tc_trig_sel, tpdm_store_tc_trig_sel);
2106
2107static ssize_t tpdm_show_tc_trig_val_lo(struct device *dev,
2108 struct device_attribute *attr,
2109 char *buf)
2110{
2111 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2112 ssize_t size = 0;
2113 int i = 0;
2114
2115 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2116 return -EPERM;
2117
2118 mutex_lock(&drvdata->lock);
2119 for (i = 0; i < TPDM_TC_MAX_TRIG; i++) {
2120 size += scnprintf(buf + size, PAGE_SIZE - size,
2121 "Index: 0x%x Value: 0x%x\n", i,
2122 drvdata->tc->trig_val_lo[i]);
2123 }
2124 mutex_unlock(&drvdata->lock);
2125 return size;
2126}
2127
2128static ssize_t tpdm_store_tc_trig_val_lo(struct device *dev,
2129 struct device_attribute *attr,
2130 const char *buf,
2131 size_t size)
2132{
2133 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2134 unsigned long index, val;
2135
2136 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2137 return -EINVAL;
2138 if (!test_bit(TPDM_DS_TC, drvdata->datasets) ||
2139 index >= TPDM_TC_MAX_TRIG ||
2140 drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_NO ||
2141 (drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL && index > 0))
2142 return -EPERM;
2143
2144 mutex_lock(&drvdata->lock);
2145 drvdata->tc->trig_val_lo[index] = val;
2146 mutex_unlock(&drvdata->lock);
2147 return size;
2148}
Satyajit Desai326497c2016-11-14 10:15:03 -08002149static DEVICE_ATTR(tc_trig_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002150 tpdm_show_tc_trig_val_lo, tpdm_store_tc_trig_val_lo);
2151
2152static ssize_t tpdm_show_tc_trig_val_hi(struct device *dev,
2153 struct device_attribute *attr,
2154 char *buf)
2155{
2156 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2157 ssize_t size = 0;
2158 int i = 0;
2159
2160 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2161 return -EPERM;
2162
2163 mutex_lock(&drvdata->lock);
2164 for (i = 0; i < TPDM_TC_MAX_TRIG; i++) {
2165 size += scnprintf(buf + size, PAGE_SIZE - size,
2166 "Index: 0x%x Value: 0x%x\n", i,
2167 drvdata->tc->trig_val_hi[i]);
2168 }
2169 mutex_unlock(&drvdata->lock);
2170 return size;
2171}
2172
2173static ssize_t tpdm_store_tc_trig_val_hi(struct device *dev,
2174 struct device_attribute *attr,
2175 const char *buf,
2176 size_t size)
2177{
2178 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2179 unsigned long index, val;
2180
2181 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2182 return -EINVAL;
2183 if (!test_bit(TPDM_DS_TC, drvdata->datasets) ||
2184 index >= TPDM_TC_MAX_TRIG ||
2185 drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_NO ||
2186 (drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL && index > 0))
2187 return -EPERM;
2188
2189 mutex_lock(&drvdata->lock);
2190 drvdata->tc->trig_val_hi[index] = val;
2191 mutex_unlock(&drvdata->lock);
2192 return size;
2193}
Satyajit Desai326497c2016-11-14 10:15:03 -08002194static DEVICE_ATTR(tc_trig_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002195 tpdm_show_tc_trig_val_hi, tpdm_store_tc_trig_val_hi);
2196
2197static ssize_t tpdm_show_tc_ovsr_gp(struct device *dev,
2198 struct device_attribute *attr,
2199 char *buf)
2200{
2201 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2202 unsigned long val;
2203
2204 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2205 return -EPERM;
2206
2207 mutex_lock(&drvdata->lock);
2208 if (!drvdata->enable) {
2209 mutex_unlock(&drvdata->lock);
2210 return -EPERM;
2211 }
2212
2213 TPDM_UNLOCK(drvdata);
2214 val = tpdm_readl(drvdata, TPDM_TC_OVSR_GP);
2215 TPDM_LOCK(drvdata);
2216 mutex_unlock(&drvdata->lock);
2217 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2218}
2219
2220static ssize_t tpdm_store_tc_ovsr_gp(struct device *dev,
2221 struct device_attribute *attr,
2222 const char *buf,
2223 size_t size)
2224{
2225 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2226 unsigned long val;
2227
2228 if (kstrtoul(buf, 16, &val))
2229 return -EINVAL;
2230 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2231 return -EPERM;
2232
2233 mutex_lock(&drvdata->lock);
2234 if (!drvdata->enable) {
2235 mutex_unlock(&drvdata->lock);
2236 return -EPERM;
2237 }
2238
2239 if (val) {
2240 TPDM_UNLOCK(drvdata);
2241 tpdm_writel(drvdata, val, TPDM_TC_OVSR_GP);
2242 TPDM_LOCK(drvdata);
2243 }
2244 mutex_unlock(&drvdata->lock);
2245 return size;
2246}
Satyajit Desai326497c2016-11-14 10:15:03 -08002247static DEVICE_ATTR(tc_ovsr_gp, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002248 tpdm_show_tc_ovsr_gp, tpdm_store_tc_ovsr_gp);
2249
2250static ssize_t tpdm_show_tc_ovsr_impl(struct device *dev,
2251 struct device_attribute *attr,
2252 char *buf)
2253{
2254 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2255 unsigned long val;
2256
2257 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2258 return -EPERM;
2259
2260 mutex_lock(&drvdata->lock);
2261 if (!drvdata->enable) {
2262 mutex_unlock(&drvdata->lock);
2263 return -EPERM;
2264 }
2265
2266 TPDM_UNLOCK(drvdata);
2267 val = tpdm_readl(drvdata, TPDM_TC_OVSR_IMPL);
2268 TPDM_LOCK(drvdata);
2269 mutex_unlock(&drvdata->lock);
2270 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2271}
2272
2273static ssize_t tpdm_store_tc_ovsr_impl(struct device *dev,
2274 struct device_attribute *attr,
2275 const char *buf,
2276 size_t size)
2277{
2278 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2279 unsigned long val;
2280
2281 if (kstrtoul(buf, 16, &val))
2282 return -EINVAL;
2283 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2284 return -EPERM;
2285
2286 mutex_lock(&drvdata->lock);
2287 if (!drvdata->enable) {
2288 mutex_unlock(&drvdata->lock);
2289 return -EPERM;
2290 }
2291
2292 if (val) {
2293 TPDM_UNLOCK(drvdata);
2294 tpdm_writel(drvdata, val, TPDM_TC_OVSR_IMPL);
2295 TPDM_LOCK(drvdata);
2296 }
2297 mutex_unlock(&drvdata->lock);
2298 return size;
2299}
Satyajit Desai326497c2016-11-14 10:15:03 -08002300static DEVICE_ATTR(tc_ovsr_impl, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002301 tpdm_show_tc_ovsr_impl, tpdm_store_tc_ovsr_impl);
2302
2303static ssize_t tpdm_show_tc_counter_sel(struct device *dev,
2304 struct device_attribute *attr,
2305 char *buf)
2306{
2307 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2308 unsigned long val;
2309
2310 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2311 return -EPERM;
2312
2313 mutex_lock(&drvdata->lock);
2314 if (!drvdata->enable) {
2315 mutex_unlock(&drvdata->lock);
2316 return -EPERM;
2317 }
2318
2319 TPDM_UNLOCK(drvdata);
2320 val = tpdm_readl(drvdata, TPDM_TC_SELR);
2321 TPDM_LOCK(drvdata);
2322 mutex_unlock(&drvdata->lock);
2323 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2324}
2325
2326static ssize_t tpdm_store_tc_counter_sel(struct device *dev,
2327 struct device_attribute *attr,
2328 const char *buf,
2329 size_t size)
2330{
2331 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2332 unsigned long val;
2333
2334 if (kstrtoul(buf, 16, &val))
2335 return -EINVAL;
2336 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2337 return -EPERM;
2338
2339 mutex_lock(&drvdata->lock);
2340 if (!drvdata->enable) {
2341 mutex_unlock(&drvdata->lock);
2342 return -EPERM;
2343 }
2344
2345 TPDM_UNLOCK(drvdata);
2346 tpdm_writel(drvdata, val, TPDM_TC_SELR);
2347 TPDM_LOCK(drvdata);
2348 mutex_unlock(&drvdata->lock);
2349 return size;
2350}
Satyajit Desai326497c2016-11-14 10:15:03 -08002351static DEVICE_ATTR(tc_counter_sel, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002352 tpdm_show_tc_counter_sel, tpdm_store_tc_counter_sel);
2353
2354static ssize_t tpdm_show_tc_count_val_lo(struct device *dev,
2355 struct device_attribute *attr,
2356 char *buf)
2357{
2358 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2359 unsigned long val;
2360
2361 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2362 return -EPERM;
2363
2364 mutex_lock(&drvdata->lock);
2365 if (!drvdata->enable) {
2366 mutex_unlock(&drvdata->lock);
2367 return -EPERM;
2368 }
2369
2370 TPDM_UNLOCK(drvdata);
2371 val = tpdm_readl(drvdata, TPDM_TC_CNTR_LO);
2372 TPDM_LOCK(drvdata);
2373 mutex_unlock(&drvdata->lock);
2374 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2375}
2376
2377static ssize_t tpdm_store_tc_count_val_lo(struct device *dev,
2378 struct device_attribute *attr,
2379 const char *buf,
2380 size_t size)
2381{
2382 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2383 unsigned long val, select;
2384
2385 if (kstrtoul(buf, 16, &val))
2386 return -EINVAL;
2387 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2388 return -EPERM;
2389
2390 mutex_lock(&drvdata->lock);
2391 if (!drvdata->enable) {
2392 mutex_unlock(&drvdata->lock);
2393 return -EPERM;
2394 }
2395
2396 if (val) {
2397 TPDM_UNLOCK(drvdata);
2398 select = tpdm_readl(drvdata, TPDM_TC_SELR);
2399 select = (select >> 11) & 0x3;
2400
2401 /* Check if selected counter is disabled */
2402 if (BVAL(tpdm_readl(drvdata, TPDM_TC_CNTENSET), select)) {
2403 mutex_unlock(&drvdata->lock);
2404 return -EPERM;
2405 }
2406
2407 tpdm_writel(drvdata, val, TPDM_TC_CNTR_LO);
2408 TPDM_LOCK(drvdata);
2409 }
2410 mutex_unlock(&drvdata->lock);
2411 return size;
2412}
Satyajit Desai326497c2016-11-14 10:15:03 -08002413static DEVICE_ATTR(tc_count_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002414 tpdm_show_tc_count_val_lo, tpdm_store_tc_count_val_lo);
2415
2416static ssize_t tpdm_show_tc_count_val_hi(struct device *dev,
2417 struct device_attribute *attr,
2418 char *buf)
2419{
2420 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2421 unsigned long val;
2422
2423 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2424 return -EPERM;
2425
2426 mutex_lock(&drvdata->lock);
2427 if (!drvdata->enable) {
2428 mutex_unlock(&drvdata->lock);
2429 return -EPERM;
2430 }
2431
2432 TPDM_UNLOCK(drvdata);
2433 val = tpdm_readl(drvdata, TPDM_TC_CNTR_HI);
2434 TPDM_LOCK(drvdata);
2435 mutex_unlock(&drvdata->lock);
2436 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2437}
2438
2439static ssize_t tpdm_store_tc_count_val_hi(struct device *dev,
2440 struct device_attribute *attr,
2441 const char *buf,
2442 size_t size)
2443{
2444 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2445 unsigned long val, select;
2446
2447 if (kstrtoul(buf, 16, &val))
2448 return -EINVAL;
2449 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2450 return -EPERM;
2451
2452 mutex_lock(&drvdata->lock);
2453 if (!drvdata->enable) {
2454 mutex_unlock(&drvdata->lock);
2455 return -EPERM;
2456 }
2457
2458 if (val) {
2459 TPDM_UNLOCK(drvdata);
2460 select = tpdm_readl(drvdata, TPDM_TC_SELR);
2461 select = (select >> 11) & 0x3;
2462
2463 /* Check if selected counter is disabled */
2464 if (BVAL(tpdm_readl(drvdata, TPDM_TC_CNTENSET), select)) {
2465 mutex_unlock(&drvdata->lock);
2466 return -EPERM;
2467 }
2468
2469 tpdm_writel(drvdata, val, TPDM_TC_CNTR_HI);
2470 TPDM_LOCK(drvdata);
2471 }
2472 mutex_unlock(&drvdata->lock);
2473 return size;
2474}
Satyajit Desai326497c2016-11-14 10:15:03 -08002475static DEVICE_ATTR(tc_count_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002476 tpdm_show_tc_count_val_hi, tpdm_store_tc_count_val_hi);
2477
2478static ssize_t tpdm_show_tc_shadow_val_lo(struct device *dev,
2479 struct device_attribute *attr,
2480 char *buf)
2481{
2482 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2483 ssize_t size = 0;
2484 int i = 0;
2485
2486 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2487 return -EPERM;
2488
2489 mutex_lock(&drvdata->lock);
2490 if (!drvdata->enable) {
2491 mutex_unlock(&drvdata->lock);
2492 return -EPERM;
2493 }
2494
2495 TPDM_UNLOCK(drvdata);
2496 for (i = 0; i < TPDM_TC_MAX_COUNTERS; i++) {
2497 size += scnprintf(buf + size, PAGE_SIZE - size,
2498 "Index: 0x%x Value: 0x%x\n", i,
2499 tpdm_readl(drvdata, TPDM_TC_SHADOW_LO(i)));
2500 }
2501 TPDM_LOCK(drvdata);
2502 mutex_unlock(&drvdata->lock);
2503 return size;
2504}
Satyajit Desai326497c2016-11-14 10:15:03 -08002505static DEVICE_ATTR(tc_shadow_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002506 tpdm_show_tc_shadow_val_lo, NULL);
2507
2508static ssize_t tpdm_show_tc_shadow_val_hi(struct device *dev,
2509 struct device_attribute *attr,
2510 char *buf)
2511{
2512 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2513 ssize_t size = 0;
2514 int i = 0;
2515
2516 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2517 return -EPERM;
2518
2519 mutex_lock(&drvdata->lock);
2520 if (!drvdata->enable) {
2521 mutex_unlock(&drvdata->lock);
2522 return -EPERM;
2523 }
2524
2525 TPDM_UNLOCK(drvdata);
2526 for (i = 0; i < TPDM_TC_MAX_COUNTERS; i++) {
2527 size += scnprintf(buf + size, PAGE_SIZE - size,
2528 "Index: 0x%x Value: 0x%x\n", i,
2529 tpdm_readl(drvdata, TPDM_TC_SHADOW_HI(i)));
2530 }
2531 TPDM_LOCK(drvdata);
2532 mutex_unlock(&drvdata->lock);
2533 return size;
2534}
Satyajit Desai326497c2016-11-14 10:15:03 -08002535static DEVICE_ATTR(tc_shadow_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002536 tpdm_show_tc_shadow_val_hi, NULL);
2537
2538static ssize_t tpdm_show_tc_sw_inc(struct device *dev,
2539 struct device_attribute *attr,
2540 char *buf)
2541{
2542 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2543 unsigned long val;
2544
2545 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2546 return -EPERM;
2547
2548 mutex_lock(&drvdata->lock);
2549 if (!drvdata->enable) {
2550 mutex_unlock(&drvdata->lock);
2551 return -EPERM;
2552 }
2553
2554 TPDM_UNLOCK(drvdata);
2555 val = tpdm_readl(drvdata, TPDM_TC_SWINC);
2556 TPDM_LOCK(drvdata);
2557 mutex_unlock(&drvdata->lock);
2558 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2559}
2560
2561static ssize_t tpdm_store_tc_sw_inc(struct device *dev,
2562 struct device_attribute *attr,
2563 const char *buf,
2564 size_t size)
2565{
2566 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2567 unsigned long val;
2568
2569 if (kstrtoul(buf, 16, &val))
2570 return -EINVAL;
2571 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2572 return -EPERM;
2573
2574 mutex_lock(&drvdata->lock);
2575 if (!drvdata->enable) {
2576 mutex_unlock(&drvdata->lock);
2577 return -EPERM;
2578 }
2579
2580 if (val) {
2581 TPDM_UNLOCK(drvdata);
2582 tpdm_writel(drvdata, val, TPDM_TC_SWINC);
2583 TPDM_LOCK(drvdata);
2584 }
2585 mutex_unlock(&drvdata->lock);
2586 return size;
2587}
Satyajit Desai326497c2016-11-14 10:15:03 -08002588static DEVICE_ATTR(tc_sw_inc, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002589 tpdm_show_tc_sw_inc, tpdm_store_tc_sw_inc);
2590
Satyajit Desaib34b2c02017-01-11 16:59:38 -08002591static ssize_t tpdm_show_tc_msr(struct device *dev,
2592 struct device_attribute *attr,
2593 char *buf)
2594{
2595 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2596 unsigned int i;
2597 ssize_t len = 0;
2598
2599 if (!drvdata->msr_support)
2600 return -EINVAL;
2601
2602 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2603 return -EPERM;
2604
2605 for (i = 0; i < TPDM_TC_MAX_MSR; i++)
2606 len += scnprintf(buf + len, PAGE_SIZE - len, "%u 0x%x\n",
2607 i, drvdata->tc->msr[i]);
2608
2609 return len;
2610}
2611
Satyajit Desaif151d682016-09-12 16:18:03 -07002612static ssize_t tpdm_store_tc_msr(struct device *dev,
2613 struct device_attribute *attr,
2614 const char *buf,
2615 size_t size)
2616{
2617 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2618 unsigned int num, val;
2619 int nval;
2620
2621 if (!drvdata->msr_support)
2622 return -EINVAL;
2623
2624 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2625 return -EPERM;
2626
2627 nval = sscanf(buf, "%u %x", &num, &val);
2628 if (nval != 2)
2629 return -EINVAL;
2630
2631 if (num >= TPDM_TC_MAX_MSR)
2632 return -EINVAL;
2633
2634 mutex_lock(&drvdata->lock);
2635 drvdata->tc->msr[num] = val;
2636 mutex_unlock(&drvdata->lock);
2637 return size;
2638}
Satyajit Desaib34b2c02017-01-11 16:59:38 -08002639static DEVICE_ATTR(tc_msr, 0644, tpdm_show_tc_msr, tpdm_store_tc_msr);
Satyajit Desaif151d682016-09-12 16:18:03 -07002640
2641static ssize_t tpdm_show_dsb_mode(struct device *dev,
2642 struct device_attribute *attr,
2643 char *buf)
2644{
2645 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2646
2647 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2648 return -EPERM;
2649
2650 return scnprintf(buf, PAGE_SIZE, "%lx\n",
2651 (unsigned long)drvdata->dsb->mode);
2652}
2653
2654static ssize_t tpdm_store_dsb_mode(struct device *dev,
2655 struct device_attribute *attr,
2656 const char *buf,
2657 size_t size)
2658{
2659 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2660 unsigned long val;
2661
2662 if (kstrtoul(buf, 16, &val))
2663 return -EINVAL;
2664 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2665 return -EPERM;
2666
2667 mutex_lock(&drvdata->lock);
2668 drvdata->dsb->mode = val & TPDM_MODE_ALL;
2669 mutex_unlock(&drvdata->lock);
2670 return size;
2671}
Satyajit Desai326497c2016-11-14 10:15:03 -08002672static DEVICE_ATTR(dsb_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002673 tpdm_show_dsb_mode, tpdm_store_dsb_mode);
2674
2675static ssize_t tpdm_show_dsb_edge_ctrl(struct device *dev,
2676 struct device_attribute *attr,
2677 char *buf)
2678{
2679 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2680 ssize_t size = 0;
2681 int i;
2682
2683 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2684 return -EPERM;
2685
2686 mutex_lock(&drvdata->lock);
2687 for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) {
2688 size += scnprintf(buf + size, PAGE_SIZE - size,
2689 "Index:0x%x Val:0x%x\n", i,
2690 drvdata->dsb->edge_ctrl[i]);
2691 }
2692 mutex_unlock(&drvdata->lock);
2693 return size;
2694}
2695
2696static ssize_t tpdm_store_dsb_edge_ctrl(struct device *dev,
2697 struct device_attribute *attr,
2698 const char *buf,
2699 size_t size)
2700{
2701 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2702 unsigned long start, end, edge_ctrl;
2703 uint32_t val;
2704 int i, bit, reg;
2705
2706 if (sscanf(buf, "%lx %lx %lx", &start, &end, &edge_ctrl) != 3)
2707 return -EINVAL;
2708 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
2709 (start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES) ||
2710 edge_ctrl > 0x2)
2711 return -EPERM;
2712
2713 mutex_lock(&drvdata->lock);
2714 for (i = start; i <= end; i++) {
2715 reg = i / (NUM_OF_BITS / 2);
2716 bit = i % (NUM_OF_BITS / 2);
2717 bit = bit * 2;
2718
2719 val = drvdata->dsb->edge_ctrl[reg];
2720 val = val | (edge_ctrl << bit);
2721 drvdata->dsb->edge_ctrl[reg] = val;
2722 }
2723 mutex_unlock(&drvdata->lock);
2724 return size;
2725}
Satyajit Desai326497c2016-11-14 10:15:03 -08002726static DEVICE_ATTR(dsb_edge_ctrl, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002727 tpdm_show_dsb_edge_ctrl, tpdm_store_dsb_edge_ctrl);
2728
2729static ssize_t tpdm_show_dsb_edge_ctrl_mask(struct device *dev,
2730 struct device_attribute *attr,
2731 char *buf)
2732{
2733 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2734 ssize_t size = 0;
2735 int i;
2736
2737 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2738 return -EPERM;
2739
2740 mutex_lock(&drvdata->lock);
2741 for (i = 0; i < TPDM_DSB_MAX_EDCR / 2; i++) {
2742 size += scnprintf(buf + size, PAGE_SIZE - size,
2743 "Index:0x%x Val:0x%x\n", i,
2744 drvdata->dsb->edge_ctrl_mask[i]);
2745 }
2746 mutex_unlock(&drvdata->lock);
2747 return size;
2748}
2749
2750static ssize_t tpdm_store_dsb_edge_ctrl_mask(struct device *dev,
2751 struct device_attribute *attr,
2752 const char *buf,
2753 size_t size)
2754{
2755 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2756 unsigned long start, end, val;
2757 uint32_t set;
2758 int i, bit, reg;
2759
2760 if (sscanf(buf, "%lx %lx %lx", &start, &end, &val) != 3)
2761 return -EINVAL;
2762 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
2763 (start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES))
2764 return -EPERM;
2765
2766 mutex_lock(&drvdata->lock);
2767 for (i = start; i <= end; i++) {
2768 reg = i / NUM_OF_BITS;
2769 bit = (i % NUM_OF_BITS);
2770
2771 set = drvdata->dsb->edge_ctrl_mask[reg];
2772 if (val)
2773 set = set | BIT(bit);
2774 else
2775 set = set & ~BIT(bit);
2776 drvdata->dsb->edge_ctrl_mask[reg] = set;
2777 }
2778 mutex_unlock(&drvdata->lock);
2779 return size;
2780}
Satyajit Desai326497c2016-11-14 10:15:03 -08002781static DEVICE_ATTR(dsb_edge_ctrl_mask, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002782 tpdm_show_dsb_edge_ctrl_mask, tpdm_store_dsb_edge_ctrl_mask);
2783
2784static ssize_t tpdm_show_dsb_patt_val(struct device *dev,
2785 struct device_attribute *attr,
2786 char *buf)
2787{
2788 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2789 ssize_t size = 0;
2790 int i = 0;
2791
2792 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2793 return -EPERM;
2794
2795 mutex_lock(&drvdata->lock);
2796 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
2797 size += scnprintf(buf + size, PAGE_SIZE - size,
2798 "Index: 0x%x Value: 0x%x\n", i,
2799 drvdata->dsb->patt_val[i]);
2800 }
2801 mutex_unlock(&drvdata->lock);
2802 return size;
2803}
2804
2805static ssize_t tpdm_store_dsb_patt_val(struct device *dev,
2806 struct device_attribute *attr,
2807 const char *buf,
2808 size_t size)
2809{
2810 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2811 unsigned long index, val;
2812
2813 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2814 return -EINVAL;
2815 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
2816 index >= TPDM_DSB_MAX_PATT)
2817 return -EPERM;
2818
2819 mutex_lock(&drvdata->lock);
2820 drvdata->dsb->patt_val[index] = val;
2821 mutex_unlock(&drvdata->lock);
2822 return size;
2823}
Satyajit Desai326497c2016-11-14 10:15:03 -08002824static DEVICE_ATTR(dsb_patt_val, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002825 tpdm_show_dsb_patt_val, tpdm_store_dsb_patt_val);
2826
2827static ssize_t tpdm_show_dsb_patt_mask(struct device *dev,
2828 struct device_attribute *attr,
2829 char *buf)
2830{
2831 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2832 ssize_t size = 0;
2833 int i = 0;
2834
2835 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2836 return -EPERM;
2837
2838 mutex_lock(&drvdata->lock);
2839 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
2840 size += scnprintf(buf + size, PAGE_SIZE - size,
2841 "Index: 0x%x Value: 0x%x\n", i,
2842 drvdata->dsb->patt_mask[i]);
2843 }
2844 mutex_unlock(&drvdata->lock);
2845 return size;
2846}
2847
2848static ssize_t tpdm_store_dsb_patt_mask(struct device *dev,
2849 struct device_attribute *attr,
2850 const char *buf,
2851 size_t size)
2852{
2853 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2854 unsigned long index, val;
2855
2856 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2857 return -EINVAL;
2858 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
2859 index >= TPDM_DSB_MAX_PATT)
2860 return -EPERM;
2861
2862 mutex_lock(&drvdata->lock);
2863 drvdata->dsb->patt_mask[index] = val;
2864 mutex_unlock(&drvdata->lock);
2865 return size;
2866}
Satyajit Desai326497c2016-11-14 10:15:03 -08002867static DEVICE_ATTR(dsb_patt_mask, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002868 tpdm_show_dsb_patt_mask, tpdm_store_dsb_patt_mask);
2869
2870static ssize_t tpdm_show_dsb_patt_ts(struct device *dev,
2871 struct device_attribute *attr,
2872 char *buf)
2873{
2874 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2875
2876 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2877 return -EPERM;
2878
2879 return scnprintf(buf, PAGE_SIZE, "%u\n",
2880 (unsigned int)drvdata->dsb->patt_ts);
2881}
2882
2883static ssize_t tpdm_store_dsb_patt_ts(struct device *dev,
2884 struct device_attribute *attr,
2885 const char *buf,
2886 size_t size)
2887{
2888 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2889 unsigned long val;
2890
2891 if (kstrtoul(buf, 16, &val))
2892 return -EINVAL;
2893 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2894 return -EPERM;
2895
2896 mutex_lock(&drvdata->lock);
2897 if (val)
2898 drvdata->dsb->patt_ts = true;
2899 else
2900 drvdata->dsb->patt_ts = false;
2901 mutex_unlock(&drvdata->lock);
2902 return size;
2903}
Satyajit Desai326497c2016-11-14 10:15:03 -08002904static DEVICE_ATTR(dsb_patt_ts, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002905 tpdm_show_dsb_patt_ts, tpdm_store_dsb_patt_ts);
2906
2907static ssize_t tpdm_show_dsb_patt_type(struct device *dev,
2908 struct device_attribute *attr, char *buf)
2909{
2910 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2911
2912 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2913 return -EPERM;
2914
2915 return scnprintf(buf, PAGE_SIZE, "%u\n",
2916 (unsigned int)drvdata->dsb->patt_type);
2917}
2918
2919static ssize_t tpdm_store_dsb_patt_type(struct device *dev,
2920 struct device_attribute *attr,
2921 const char *buf, size_t size)
2922{
2923 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2924 unsigned long val;
2925
2926 if (kstrtoul(buf, 16, &val))
2927 return -EINVAL;
2928 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2929 return -EPERM;
2930
2931 mutex_lock(&drvdata->lock);
2932 if (val)
2933 drvdata->dsb->patt_type = true;
2934 else
2935 drvdata->dsb->patt_type = false;
2936 mutex_unlock(&drvdata->lock);
2937 return size;
2938}
Satyajit Desai326497c2016-11-14 10:15:03 -08002939static DEVICE_ATTR(dsb_patt_type, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002940 tpdm_show_dsb_patt_type, tpdm_store_dsb_patt_type);
2941
2942static ssize_t tpdm_show_dsb_trig_patt_val(struct device *dev,
2943 struct device_attribute *attr,
2944 char *buf)
2945{
2946 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2947 ssize_t size = 0;
2948 int i = 0;
2949
2950 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2951 return -EPERM;
2952
2953 mutex_lock(&drvdata->lock);
2954 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
2955 size += scnprintf(buf + size, PAGE_SIZE - size,
2956 "Index: 0x%x Value: 0x%x\n", i,
2957 drvdata->dsb->trig_patt_val[i]);
2958 }
2959 mutex_unlock(&drvdata->lock);
2960 return size;
2961}
2962
2963static ssize_t tpdm_store_dsb_trig_patt_val(struct device *dev,
2964 struct device_attribute *attr,
2965 const char *buf,
2966 size_t size)
2967{
2968 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2969 unsigned long index, val;
2970
2971 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2972 return -EINVAL;
2973 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
2974 index >= TPDM_DSB_MAX_PATT)
2975 return -EPERM;
2976
2977 mutex_lock(&drvdata->lock);
2978 drvdata->dsb->trig_patt_val[index] = val;
2979 mutex_unlock(&drvdata->lock);
2980 return size;
2981}
Satyajit Desai326497c2016-11-14 10:15:03 -08002982static DEVICE_ATTR(dsb_trig_patt_val, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002983 tpdm_show_dsb_trig_patt_val, tpdm_store_dsb_trig_patt_val);
2984
2985static ssize_t tpdm_show_dsb_trig_patt_mask(struct device *dev,
2986 struct device_attribute *attr,
2987 char *buf)
2988{
2989 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2990 ssize_t size = 0;
2991 int i = 0;
2992
2993 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2994 return -EPERM;
2995
2996 mutex_lock(&drvdata->lock);
2997 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
2998 size += scnprintf(buf + size, PAGE_SIZE - size,
2999 "Index: 0x%x Value: 0x%x\n", i,
3000 drvdata->dsb->trig_patt_mask[i]);
3001 }
3002 mutex_unlock(&drvdata->lock);
3003 return size;
3004}
3005
3006static ssize_t tpdm_store_dsb_trig_patt_mask(struct device *dev,
3007 struct device_attribute *attr,
3008 const char *buf,
3009 size_t size)
3010{
3011 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3012 unsigned long index, val;
3013
3014 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
3015 return -EINVAL;
3016 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
3017 index >= TPDM_DSB_MAX_PATT)
3018 return -EPERM;
3019
3020 mutex_lock(&drvdata->lock);
3021 drvdata->dsb->trig_patt_mask[index] = val;
3022 mutex_unlock(&drvdata->lock);
3023 return size;
3024}
Satyajit Desai326497c2016-11-14 10:15:03 -08003025static DEVICE_ATTR(dsb_trig_patt_mask, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003026 tpdm_show_dsb_trig_patt_mask, tpdm_store_dsb_trig_patt_mask);
3027
3028static ssize_t tpdm_show_dsb_trig_ts(struct device *dev,
3029 struct device_attribute *attr,
3030 char *buf)
3031{
3032 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3033
3034 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
3035 return -EPERM;
3036
3037 return scnprintf(buf, PAGE_SIZE, "%u\n",
3038 (unsigned int)drvdata->dsb->trig_ts);
3039}
3040
3041static ssize_t tpdm_store_dsb_trig_ts(struct device *dev,
3042 struct device_attribute *attr,
3043 const char *buf,
3044 size_t size)
3045{
3046 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3047 unsigned long val;
3048
3049 if (kstrtoul(buf, 16, &val))
3050 return -EINVAL;
3051 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
3052 return -EPERM;
3053
3054 mutex_lock(&drvdata->lock);
3055 if (val)
3056 drvdata->dsb->trig_ts = true;
3057 else
3058 drvdata->dsb->trig_ts = false;
3059 mutex_unlock(&drvdata->lock);
3060 return size;
3061}
Satyajit Desai326497c2016-11-14 10:15:03 -08003062static DEVICE_ATTR(dsb_trig_ts, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003063 tpdm_show_dsb_trig_ts, tpdm_store_dsb_trig_ts);
3064
3065static ssize_t tpdm_show_dsb_select_val(struct device *dev,
3066 struct device_attribute *attr,
3067 char *buf)
3068{
3069 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3070 ssize_t size = 0;
3071 int i;
3072
3073 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
3074 return -EPERM;
3075
3076 mutex_lock(&drvdata->lock);
3077 for (i = 0; i < TPDM_DSB_MAX_SELECT; i++) {
3078 size += scnprintf(buf + size, PAGE_SIZE - size,
3079 "Index:0x%x Val:0x%x\n", i,
3080 drvdata->dsb->select_val[i]);
3081 }
3082 mutex_unlock(&drvdata->lock);
3083 return size;
3084}
3085
3086static ssize_t tpdm_store_dsb_select_val(struct device *dev,
3087 struct device_attribute *attr,
3088 const char *buf,
3089 size_t size)
3090{
3091 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3092 unsigned long start, end;
3093 uint32_t val;
3094 int i, bit, reg;
3095
3096 if (sscanf(buf, "%lx %lx", &start, &end) != 2)
3097 return -EINVAL;
3098 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
3099 (start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES))
3100 return -EPERM;
3101
3102 mutex_lock(&drvdata->lock);
3103 for (i = start; i <= end; i++) {
3104 reg = i / NUM_OF_BITS;
3105 bit = (i % NUM_OF_BITS);
3106
3107 val = drvdata->dsb->select_val[reg];
3108 val = val | BIT(bit);
3109 drvdata->dsb->select_val[reg] = val;
3110 }
3111 mutex_unlock(&drvdata->lock);
3112 return size;
3113}
Satyajit Desai326497c2016-11-14 10:15:03 -08003114static DEVICE_ATTR(dsb_select_val, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003115 tpdm_show_dsb_select_val, tpdm_store_dsb_select_val);
3116
Satyajit Desaib34b2c02017-01-11 16:59:38 -08003117static ssize_t tpdm_show_dsb_msr(struct device *dev,
3118 struct device_attribute *attr,
3119 char *buf)
3120{
3121 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3122 unsigned int i;
3123 ssize_t len = 0;
3124
3125 if (!drvdata->msr_support)
3126 return -EINVAL;
3127
3128 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
3129 return -EPERM;
3130
3131 for (i = 0; i < TPDM_DSB_MAX_MSR; i++)
3132 len += scnprintf(buf + len, PAGE_SIZE - len, "%u 0x%x\n",
3133 i, drvdata->dsb->msr[i]);
3134
3135 return len;
3136}
3137
Satyajit Desaif151d682016-09-12 16:18:03 -07003138static ssize_t tpdm_store_dsb_msr(struct device *dev,
3139 struct device_attribute *attr,
3140 const char *buf,
3141 size_t size)
3142{
3143 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3144 unsigned int num, val;
3145 int nval;
3146
3147 if (!drvdata->msr_support)
3148 return -EINVAL;
3149
3150 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
3151 return -EPERM;
3152
3153 nval = sscanf(buf, "%u %x", &num, &val);
3154 if (nval != 2)
3155 return -EINVAL;
3156
3157 if (num >= TPDM_DSB_MAX_MSR)
3158 return -EINVAL;
3159
3160 mutex_lock(&drvdata->lock);
3161 drvdata->dsb->msr[num] = val;
3162 mutex_unlock(&drvdata->lock);
3163 return size;
3164}
Satyajit Desaib34b2c02017-01-11 16:59:38 -08003165static DEVICE_ATTR(dsb_msr, 0644, tpdm_show_dsb_msr, tpdm_store_dsb_msr);
Satyajit Desaif151d682016-09-12 16:18:03 -07003166
3167static ssize_t tpdm_show_cmb_available_modes(struct device *dev,
3168 struct device_attribute *attr,
3169 char *buf)
3170{
3171 return scnprintf(buf, PAGE_SIZE, "%s\n", "continuous trace_on_change");
3172}
Satyajit Desai326497c2016-11-14 10:15:03 -08003173static DEVICE_ATTR(cmb_available_modes, 0444, tpdm_show_cmb_available_modes,
Satyajit Desaif151d682016-09-12 16:18:03 -07003174 NULL);
3175
3176static ssize_t tpdm_show_cmb_mode(struct device *dev,
3177 struct device_attribute *attr,
3178 char *buf)
3179{
3180 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3181
Satyajit Desaie104ff52016-09-12 16:38:12 -07003182 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3183 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003184 return -EPERM;
3185
Satyajit Desaic75e7642017-04-24 20:35:57 -07003186 return scnprintf(buf, PAGE_SIZE, "trace_mode: %s cycle_acc: %d\n",
3187 drvdata->cmb->trace_mode ?
3188 "trace_on_change" : "continuous",
3189 drvdata->cmb->cycle_acc);
Satyajit Desaif151d682016-09-12 16:18:03 -07003190}
3191
3192static ssize_t tpdm_store_cmb_mode(struct device *dev,
3193 struct device_attribute *attr,
3194 const char *buf,
3195 size_t size)
3196{
3197 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Satyajit Desaic75e7642017-04-24 20:35:57 -07003198 unsigned int trace_mode, cycle_acc;
3199 int nval;
Satyajit Desaif151d682016-09-12 16:18:03 -07003200
Satyajit Desaic75e7642017-04-24 20:35:57 -07003201 nval = sscanf(buf, "%u %u", &trace_mode, &cycle_acc);
3202 if (nval != 2)
Satyajit Desaif151d682016-09-12 16:18:03 -07003203 return -EINVAL;
Satyajit Desaic75e7642017-04-24 20:35:57 -07003204
Satyajit Desaie104ff52016-09-12 16:38:12 -07003205 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3206 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003207 return -EPERM;
3208
3209 mutex_lock(&drvdata->lock);
Satyajit Desaic75e7642017-04-24 20:35:57 -07003210 drvdata->cmb->trace_mode = trace_mode;
3211 drvdata->cmb->cycle_acc = cycle_acc;
Satyajit Desaif151d682016-09-12 16:18:03 -07003212 mutex_unlock(&drvdata->lock);
3213 return size;
3214}
Satyajit Desai326497c2016-11-14 10:15:03 -08003215static DEVICE_ATTR(cmb_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003216 tpdm_show_cmb_mode, tpdm_store_cmb_mode);
3217
Satyajit Desai75411bc2017-04-19 18:41:27 -07003218static ssize_t tpdm_show_cmb_patt_val(struct device *dev,
Satyajit Desaif151d682016-09-12 16:18:03 -07003219 struct device_attribute *attr,
3220 char *buf)
3221{
3222 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Satyajit Desai75411bc2017-04-19 18:41:27 -07003223 ssize_t size = 0;
3224 int i;
Satyajit Desaif151d682016-09-12 16:18:03 -07003225
Satyajit Desaie104ff52016-09-12 16:38:12 -07003226 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3227 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003228 return -EPERM;
3229
Satyajit Desai75411bc2017-04-19 18:41:27 -07003230 mutex_lock(&drvdata->lock);
3231 for (i = 0; i < TPDM_CMB_PATT_CMP; i++) {
3232 size += scnprintf(buf + size, PAGE_SIZE - size,
3233 "Index: 0x%x Value: 0x%x\n", i,
3234 drvdata->cmb->patt_val[i]);
3235 }
3236 mutex_unlock(&drvdata->lock);
3237 return size;
Satyajit Desaif151d682016-09-12 16:18:03 -07003238}
3239
Satyajit Desai75411bc2017-04-19 18:41:27 -07003240static ssize_t tpdm_store_cmb_patt_val(struct device *dev,
Satyajit Desaif151d682016-09-12 16:18:03 -07003241 struct device_attribute *attr,
3242 const char *buf, size_t size)
3243{
3244 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Satyajit Desai75411bc2017-04-19 18:41:27 -07003245 unsigned long index, val;
Satyajit Desaif151d682016-09-12 16:18:03 -07003246
Satyajit Desai75411bc2017-04-19 18:41:27 -07003247 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
3248 return -EINVAL;
3249 if (index >= TPDM_CMB_PATT_CMP)
Satyajit Desaif151d682016-09-12 16:18:03 -07003250 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003251 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3252 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003253 return -EPERM;
3254
3255 mutex_lock(&drvdata->lock);
Satyajit Desai75411bc2017-04-19 18:41:27 -07003256 drvdata->cmb->patt_val[index] = val;
Satyajit Desaif151d682016-09-12 16:18:03 -07003257 mutex_unlock(&drvdata->lock);
Satyajit Desai75411bc2017-04-19 18:41:27 -07003258
Satyajit Desaif151d682016-09-12 16:18:03 -07003259 return size;
3260}
Satyajit Desai75411bc2017-04-19 18:41:27 -07003261static DEVICE_ATTR(cmb_patt_val, 0644,
3262 tpdm_show_cmb_patt_val,
3263 tpdm_store_cmb_patt_val);
Satyajit Desaif151d682016-09-12 16:18:03 -07003264
Satyajit Desai75411bc2017-04-19 18:41:27 -07003265static ssize_t tpdm_show_cmb_patt_mask(struct device *dev,
Satyajit Desaif151d682016-09-12 16:18:03 -07003266 struct device_attribute *attr,
3267 char *buf)
3268{
3269 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Satyajit Desai75411bc2017-04-19 18:41:27 -07003270 ssize_t size = 0;
3271 int i;
Satyajit Desaif151d682016-09-12 16:18:03 -07003272
Satyajit Desaie104ff52016-09-12 16:38:12 -07003273 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3274 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003275 return -EPERM;
3276
Satyajit Desai75411bc2017-04-19 18:41:27 -07003277 mutex_lock(&drvdata->lock);
3278 for (i = 0; i < TPDM_CMB_PATT_CMP; i++) {
3279 size += scnprintf(buf + size, PAGE_SIZE - size,
3280 "Index: 0x%x Value: 0x%x\n", i,
3281 drvdata->cmb->patt_mask[i]);
3282 }
3283 mutex_unlock(&drvdata->lock);
3284 return size;
Satyajit Desaif151d682016-09-12 16:18:03 -07003285
Satyajit Desaif151d682016-09-12 16:18:03 -07003286}
3287
Satyajit Desai75411bc2017-04-19 18:41:27 -07003288static ssize_t tpdm_store_cmb_patt_mask(struct device *dev,
Satyajit Desaif151d682016-09-12 16:18:03 -07003289 struct device_attribute *attr,
3290 const char *buf, size_t size)
3291{
3292 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Satyajit Desai75411bc2017-04-19 18:41:27 -07003293 unsigned long index, val;
Satyajit Desaif151d682016-09-12 16:18:03 -07003294
Satyajit Desai75411bc2017-04-19 18:41:27 -07003295 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
3296 return -EINVAL;
3297 if (index >= TPDM_CMB_PATT_CMP)
Satyajit Desaif151d682016-09-12 16:18:03 -07003298 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003299 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3300 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003301 return -EPERM;
3302
3303 mutex_lock(&drvdata->lock);
Satyajit Desai75411bc2017-04-19 18:41:27 -07003304 drvdata->cmb->patt_mask[index] = val;
Satyajit Desaif151d682016-09-12 16:18:03 -07003305 mutex_unlock(&drvdata->lock);
3306 return size;
3307}
Satyajit Desai75411bc2017-04-19 18:41:27 -07003308static DEVICE_ATTR(cmb_patt_mask, 0644,
3309 tpdm_show_cmb_patt_mask, tpdm_store_cmb_patt_mask);
Satyajit Desaif151d682016-09-12 16:18:03 -07003310
3311static ssize_t tpdm_show_cmb_patt_ts(struct device *dev,
3312 struct device_attribute *attr,
3313 char *buf)
3314{
3315 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3316
Satyajit Desaie104ff52016-09-12 16:38:12 -07003317 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3318 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003319 return -EPERM;
3320
3321 return scnprintf(buf, PAGE_SIZE, "%u\n",
3322 (unsigned int)drvdata->cmb->patt_ts);
3323}
3324
3325static ssize_t tpdm_store_cmb_patt_ts(struct device *dev,
3326 struct device_attribute *attr,
3327 const char *buf,
3328 size_t size)
3329{
3330 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3331 unsigned long val;
3332
3333 if (kstrtoul(buf, 16, &val))
3334 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003335 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3336 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003337 return -EPERM;
3338
3339 mutex_lock(&drvdata->lock);
3340 if (val)
3341 drvdata->cmb->patt_ts = true;
3342 else
3343 drvdata->cmb->patt_ts = false;
3344 mutex_unlock(&drvdata->lock);
3345 return size;
3346}
Satyajit Desai326497c2016-11-14 10:15:03 -08003347static DEVICE_ATTR(cmb_patt_ts, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003348 tpdm_show_cmb_patt_ts, tpdm_store_cmb_patt_ts);
3349
3350static ssize_t tpdm_show_cmb_trig_patt_val_lsb(struct device *dev,
3351 struct device_attribute *attr,
3352 char *buf)
3353{
3354 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3355 unsigned long val;
3356
Satyajit Desaie104ff52016-09-12 16:38:12 -07003357 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3358 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003359 return -EPERM;
3360
3361 val = drvdata->cmb->trig_patt_val[TPDM_CMB_LSB];
3362
3363 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
3364}
3365
3366static ssize_t tpdm_store_cmb_trig_patt_val_lsb(struct device *dev,
3367 struct device_attribute *attr,
3368 const char *buf, size_t size)
3369{
3370 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3371 unsigned long val;
3372
3373 if (kstrtoul(buf, 16, &val))
3374 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003375 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3376 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003377 return -EPERM;
3378
3379 mutex_lock(&drvdata->lock);
3380 drvdata->cmb->trig_patt_val[TPDM_CMB_LSB] = val;
3381 mutex_unlock(&drvdata->lock);
3382 return size;
3383}
Satyajit Desai326497c2016-11-14 10:15:03 -08003384static DEVICE_ATTR(cmb_trig_patt_val_lsb, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003385 tpdm_show_cmb_trig_patt_val_lsb,
3386 tpdm_store_cmb_trig_patt_val_lsb);
3387
3388static ssize_t tpdm_show_cmb_trig_patt_mask_lsb(struct device *dev,
3389 struct device_attribute *attr,
3390 char *buf)
3391{
3392 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3393 unsigned long val;
3394
Satyajit Desaie104ff52016-09-12 16:38:12 -07003395 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3396 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003397 return -EPERM;
3398
3399 val = drvdata->cmb->trig_patt_mask[TPDM_CMB_LSB];
3400
3401 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
3402}
3403
3404static ssize_t tpdm_store_cmb_trig_patt_mask_lsb(struct device *dev,
3405 struct device_attribute *attr,
3406 const char *buf, size_t size)
3407{
3408 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3409 unsigned long val;
3410
3411 if (kstrtoul(buf, 16, &val))
3412 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003413 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3414 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003415 return -EPERM;
3416
3417 mutex_lock(&drvdata->lock);
3418 drvdata->cmb->trig_patt_mask[TPDM_CMB_LSB] = val;
3419 mutex_unlock(&drvdata->lock);
3420 return size;
3421}
Satyajit Desai326497c2016-11-14 10:15:03 -08003422static DEVICE_ATTR(cmb_trig_patt_mask_lsb, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003423 tpdm_show_cmb_trig_patt_mask_lsb,
3424 tpdm_store_cmb_trig_patt_mask_lsb);
3425
3426static ssize_t tpdm_show_cmb_trig_patt_val_msb(struct device *dev,
3427 struct device_attribute *attr,
3428 char *buf)
3429{
3430 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3431 unsigned long val;
3432
Satyajit Desaie104ff52016-09-12 16:38:12 -07003433 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3434 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003435 return -EPERM;
3436
3437 val = drvdata->cmb->trig_patt_val[TPDM_CMB_MSB];
3438
3439 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
3440}
3441
3442static ssize_t tpdm_store_cmb_trig_patt_val_msb(struct device *dev,
3443 struct device_attribute *attr,
3444 const char *buf, size_t size)
3445{
3446 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3447 unsigned long val;
3448
3449 if (kstrtoul(buf, 16, &val))
3450 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003451 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3452 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003453 return -EPERM;
3454
3455 mutex_lock(&drvdata->lock);
3456 drvdata->cmb->trig_patt_val[TPDM_CMB_MSB] = val;
3457 mutex_unlock(&drvdata->lock);
3458 return size;
3459}
Satyajit Desai326497c2016-11-14 10:15:03 -08003460static DEVICE_ATTR(cmb_trig_patt_val_msb, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003461 tpdm_show_cmb_trig_patt_val_msb,
3462 tpdm_store_cmb_trig_patt_val_msb);
3463
3464static ssize_t tpdm_show_cmb_trig_patt_mask_msb(struct device *dev,
3465 struct device_attribute *attr,
3466 char *buf)
3467{
3468 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3469 unsigned long val;
3470
Satyajit Desaie104ff52016-09-12 16:38:12 -07003471 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3472 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003473 return -EPERM;
3474
3475 val = drvdata->cmb->trig_patt_mask[TPDM_CMB_MSB];
3476
3477 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
3478}
3479
3480static ssize_t tpdm_store_cmb_trig_patt_mask_msb(struct device *dev,
3481 struct device_attribute *attr,
3482 const char *buf, size_t size)
3483{
3484 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3485 unsigned long val;
3486
3487 if (kstrtoul(buf, 16, &val))
3488 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003489 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3490 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003491 return -EPERM;
3492
3493 mutex_lock(&drvdata->lock);
3494 drvdata->cmb->trig_patt_mask[TPDM_CMB_MSB] = val;
3495 mutex_unlock(&drvdata->lock);
3496 return size;
3497}
Satyajit Desai326497c2016-11-14 10:15:03 -08003498static DEVICE_ATTR(cmb_trig_patt_mask_msb, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003499 tpdm_show_cmb_trig_patt_mask_msb,
3500 tpdm_store_cmb_trig_patt_mask_msb);
3501
3502static ssize_t tpdm_show_cmb_trig_ts(struct device *dev,
3503 struct device_attribute *attr,
3504 char *buf)
3505{
3506 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3507
Satyajit Desaie104ff52016-09-12 16:38:12 -07003508 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3509 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003510 return -EPERM;
3511
3512 return scnprintf(buf, PAGE_SIZE, "%u\n",
3513 (unsigned int)drvdata->cmb->trig_ts);
3514}
3515
3516static ssize_t tpdm_store_cmb_trig_ts(struct device *dev,
Satyajit Desaie104ff52016-09-12 16:38:12 -07003517 struct device_attribute *attr,
3518 const char *buf,
3519 size_t size)
Satyajit Desaif151d682016-09-12 16:18:03 -07003520{
3521 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3522 unsigned long val;
3523
3524 if (kstrtoul(buf, 16, &val))
3525 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003526 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3527 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003528 return -EPERM;
3529
3530 mutex_lock(&drvdata->lock);
3531 if (val)
3532 drvdata->cmb->trig_ts = true;
3533 else
3534 drvdata->cmb->trig_ts = false;
3535 mutex_unlock(&drvdata->lock);
3536 return size;
3537}
Satyajit Desai326497c2016-11-14 10:15:03 -08003538static DEVICE_ATTR(cmb_trig_ts, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003539 tpdm_show_cmb_trig_ts, tpdm_store_cmb_trig_ts);
3540
Satyajit Desaib34b2c02017-01-11 16:59:38 -08003541static ssize_t tpdm_show_cmb_msr(struct device *dev,
3542 struct device_attribute *attr,
3543 char *buf)
3544{
3545 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3546 unsigned int i;
3547 ssize_t len = 0;
3548
3549 if (!drvdata->msr_support)
3550 return -EINVAL;
3551
3552 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3553 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
3554 return -EPERM;
3555
3556 for (i = 0; i < TPDM_CMB_MAX_MSR; i++)
3557 len += scnprintf(buf + len, PAGE_SIZE - len, "%u 0x%x\n",
3558 i, drvdata->cmb->msr[i]);
3559
3560 return len;
3561}
3562
Satyajit Desaif151d682016-09-12 16:18:03 -07003563static ssize_t tpdm_store_cmb_msr(struct device *dev,
3564 struct device_attribute *attr,
3565 const char *buf,
3566 size_t size)
3567{
3568 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3569 unsigned int num, val;
3570 int nval;
3571
3572 if (!drvdata->msr_support)
3573 return -EINVAL;
3574
Satyajit Desaie104ff52016-09-12 16:38:12 -07003575 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3576 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003577 return -EPERM;
3578
3579 nval = sscanf(buf, "%u %x", &num, &val);
3580 if (nval != 2)
3581 return -EINVAL;
3582
3583 if (num >= TPDM_CMB_MAX_MSR)
3584 return -EINVAL;
3585
3586 mutex_lock(&drvdata->lock);
3587 drvdata->cmb->msr[num] = val;
3588 mutex_unlock(&drvdata->lock);
3589 return size;
3590}
Satyajit Desaib34b2c02017-01-11 16:59:38 -08003591static DEVICE_ATTR(cmb_msr, 0644, tpdm_show_cmb_msr, tpdm_store_cmb_msr);
Satyajit Desaif151d682016-09-12 16:18:03 -07003592
Satyajit Desaie104ff52016-09-12 16:38:12 -07003593static ssize_t tpdm_show_cmb_read_interface_state(struct device *dev,
3594 struct device_attribute *attr,
3595 char *buf)
3596{
3597 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3598 unsigned long val;
3599
3600 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3601 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
3602 return -EPERM;
3603
3604 mutex_lock(&drvdata->lock);
3605 TPDM_UNLOCK(drvdata);
3606 val = tpdm_readl(drvdata, TPDM_CMB_READVAL);
3607 TPDM_LOCK(drvdata);
3608 mutex_unlock(&drvdata->lock);
3609
3610 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
3611}
3612static DEVICE_ATTR(cmb_read_interface_state, 0444,
3613 tpdm_show_cmb_read_interface_state, NULL);
3614
3615static ssize_t tpdm_show_cmb_read_ctl_reg(struct device *dev,
3616 struct device_attribute *attr,
3617 char *buf)
3618{
3619 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3620 unsigned long val;
3621
3622 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3623 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
3624 return -EPERM;
3625
3626 mutex_lock(&drvdata->lock);
3627 TPDM_UNLOCK(drvdata);
3628 val = tpdm_readl(drvdata, TPDM_CMB_READCTL);
3629 TPDM_LOCK(drvdata);
3630 mutex_unlock(&drvdata->lock);
3631
3632 if (test_bit(TPDM_DS_CMB, drvdata->datasets))
3633 return scnprintf(buf, PAGE_SIZE, "SEL: %lx\n", val);
3634 else
3635 return scnprintf(buf, PAGE_SIZE, "Lane %u SEL: %lx\n",
3636 (unsigned int)BMVAL(val, 1, 3), val & 0x1);
3637}
3638
3639static ssize_t tpdm_store_cmb_read_ctl_reg(struct device *dev,
3640 struct device_attribute *attr,
3641 const char *buf,
3642 size_t size)
3643{
3644 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3645 unsigned long val;
3646
3647 if (kstrtoul(buf, 16, &val))
3648 return -EINVAL;
3649
3650 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3651 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
3652 return -EPERM;
3653
3654 mutex_lock(&drvdata->lock);
3655 TPDM_UNLOCK(drvdata);
3656 tpdm_writel(drvdata, val, TPDM_CMB_READCTL);
3657 TPDM_LOCK(drvdata);
3658 mutex_unlock(&drvdata->lock);
3659
3660 return size;
3661}
3662static DEVICE_ATTR(cmb_read_ctl_reg, 0644,
3663 tpdm_show_cmb_read_ctl_reg, tpdm_store_cmb_read_ctl_reg);
3664
3665static ssize_t tpdm_show_mcmb_trig_lane(struct device *dev,
3666 struct device_attribute *attr,
3667 char *buf)
3668{
3669 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3670
3671 if (!test_bit(TPDM_DS_MCMB, drvdata->datasets))
3672 return -EPERM;
3673
3674 return scnprintf(buf, PAGE_SIZE, "%u\n",
3675 (unsigned int)drvdata->cmb->mcmb->mcmb_trig_lane);
3676}
3677
3678static ssize_t tpdm_store_mcmb_trig_lane(struct device *dev,
3679 struct device_attribute *attr,
3680 const char *buf,
3681 size_t size)
3682{
3683 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3684 unsigned long val;
3685
3686 if (kstrtoul(buf, 10, &val))
3687 return -EINVAL;
3688 if (val >= TPDM_MCMB_MAX_LANES)
3689 return -EINVAL;
3690 if (!test_bit(TPDM_DS_MCMB, drvdata->datasets))
3691 return -EPERM;
3692
3693 mutex_lock(&drvdata->lock);
3694 drvdata->cmb->mcmb->mcmb_trig_lane = val;
3695 mutex_unlock(&drvdata->lock);
3696 return size;
3697}
3698static DEVICE_ATTR(mcmb_trig_lane, 0644,
3699 tpdm_show_mcmb_trig_lane, tpdm_store_mcmb_trig_lane);
3700
3701static ssize_t tpdm_show_mcmb_lanes_select(struct device *dev,
3702 struct device_attribute *attr,
3703 char *buf)
3704{
3705 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3706
3707 if (!test_bit(TPDM_DS_MCMB, drvdata->datasets))
3708 return -EPERM;
3709
3710 return scnprintf(buf, PAGE_SIZE, "%u\n",
3711 (unsigned int)drvdata->cmb->mcmb->mcmb_lane_select);
3712}
3713
3714static ssize_t tpdm_store_mcmb_lanes_select(struct device *dev,
3715 struct device_attribute *attr,
3716 const char *buf,
3717 size_t size)
3718{
3719 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3720 unsigned long val;
3721
3722 if (kstrtoul(buf, 16, &val))
3723 return -EINVAL;
3724 if (!test_bit(TPDM_DS_MCMB, drvdata->datasets))
3725 return -EPERM;
3726
3727 val = BMVAL(val, 0, TPDM_MCMB_MAX_LANES - 1);
3728
3729 mutex_lock(&drvdata->lock);
3730 drvdata->cmb->mcmb->mcmb_lane_select = val;
3731 mutex_unlock(&drvdata->lock);
3732 return size;
3733}
3734static DEVICE_ATTR(mcmb_lanes_select, 0644,
3735 tpdm_show_mcmb_lanes_select, tpdm_store_mcmb_lanes_select);
3736
3737static ssize_t tpdm_store_cmb_markr(struct device *dev,
3738 struct device_attribute *attr,
3739 const char *buf,
3740 size_t size)
3741{
3742 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3743 unsigned long val;
3744
3745 if (kstrtoul(buf, 16, &val))
3746 return -EINVAL;
3747
3748 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3749 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
3750 return -EPERM;
3751
3752 mutex_lock(&drvdata->lock);
3753 TPDM_UNLOCK(drvdata);
3754 tpdm_writel(drvdata, val, TPDM_CMB_MARKR);
3755 TPDM_LOCK(drvdata);
3756 mutex_unlock(&drvdata->lock);
3757
3758 return size;
3759}
3760static DEVICE_ATTR(cmb_markr, 0200, NULL, tpdm_store_cmb_markr);
3761
Satyajit Desaif151d682016-09-12 16:18:03 -07003762static struct attribute *tpdm_bc_attrs[] = {
3763 &dev_attr_bc_capture_mode.attr,
3764 &dev_attr_bc_retrieval_mode.attr,
3765 &dev_attr_bc_reset_counters.attr,
3766 &dev_attr_bc_sat_mode.attr,
3767 &dev_attr_bc_enable_counters.attr,
3768 &dev_attr_bc_clear_counters.attr,
3769 &dev_attr_bc_enable_irq.attr,
3770 &dev_attr_bc_clear_irq.attr,
3771 &dev_attr_bc_trig_val_lo.attr,
3772 &dev_attr_bc_trig_val_hi.attr,
3773 &dev_attr_bc_enable_ganging.attr,
3774 &dev_attr_bc_overflow_val.attr,
3775 &dev_attr_bc_ovsr.attr,
3776 &dev_attr_bc_counter_sel.attr,
3777 &dev_attr_bc_count_val_lo.attr,
3778 &dev_attr_bc_count_val_hi.attr,
3779 &dev_attr_bc_shadow_val_lo.attr,
3780 &dev_attr_bc_shadow_val_hi.attr,
3781 &dev_attr_bc_sw_inc.attr,
3782 &dev_attr_bc_msr.attr,
3783 NULL,
3784};
3785
3786static struct attribute *tpdm_tc_attrs[] = {
3787 &dev_attr_tc_capture_mode.attr,
3788 &dev_attr_tc_retrieval_mode.attr,
3789 &dev_attr_tc_reset_counters.attr,
3790 &dev_attr_tc_sat_mode.attr,
3791 &dev_attr_tc_enable_counters.attr,
3792 &dev_attr_tc_clear_counters.attr,
3793 &dev_attr_tc_enable_irq.attr,
3794 &dev_attr_tc_clear_irq.attr,
3795 &dev_attr_tc_trig_sel.attr,
3796 &dev_attr_tc_trig_val_lo.attr,
3797 &dev_attr_tc_trig_val_hi.attr,
3798 &dev_attr_tc_ovsr_gp.attr,
3799 &dev_attr_tc_ovsr_impl.attr,
3800 &dev_attr_tc_counter_sel.attr,
3801 &dev_attr_tc_count_val_lo.attr,
3802 &dev_attr_tc_count_val_hi.attr,
3803 &dev_attr_tc_shadow_val_lo.attr,
3804 &dev_attr_tc_shadow_val_hi.attr,
3805 &dev_attr_tc_sw_inc.attr,
3806 &dev_attr_tc_msr.attr,
3807 NULL,
3808};
3809
3810static struct attribute *tpdm_dsb_attrs[] = {
3811 &dev_attr_dsb_mode.attr,
3812 &dev_attr_dsb_edge_ctrl.attr,
3813 &dev_attr_dsb_edge_ctrl_mask.attr,
3814 &dev_attr_dsb_patt_val.attr,
3815 &dev_attr_dsb_patt_mask.attr,
3816 &dev_attr_dsb_patt_ts.attr,
3817 &dev_attr_dsb_patt_type.attr,
3818 &dev_attr_dsb_trig_patt_val.attr,
3819 &dev_attr_dsb_trig_patt_mask.attr,
3820 &dev_attr_dsb_trig_ts.attr,
3821 &dev_attr_dsb_select_val.attr,
3822 &dev_attr_dsb_msr.attr,
3823 NULL,
3824};
3825
3826static struct attribute *tpdm_cmb_attrs[] = {
3827 &dev_attr_cmb_available_modes.attr,
3828 &dev_attr_cmb_mode.attr,
Satyajit Desai75411bc2017-04-19 18:41:27 -07003829 &dev_attr_cmb_patt_val.attr,
3830 &dev_attr_cmb_patt_mask.attr,
Satyajit Desaif151d682016-09-12 16:18:03 -07003831 &dev_attr_cmb_patt_ts.attr,
3832 &dev_attr_cmb_trig_patt_val_lsb.attr,
3833 &dev_attr_cmb_trig_patt_mask_lsb.attr,
3834 &dev_attr_cmb_trig_patt_val_msb.attr,
3835 &dev_attr_cmb_trig_patt_mask_msb.attr,
3836 &dev_attr_cmb_trig_ts.attr,
3837 &dev_attr_cmb_msr.attr,
Satyajit Desaie104ff52016-09-12 16:38:12 -07003838 &dev_attr_cmb_read_interface_state.attr,
3839 &dev_attr_cmb_read_ctl_reg.attr,
3840 &dev_attr_cmb_markr.attr,
3841 &dev_attr_mcmb_trig_lane.attr,
3842 &dev_attr_mcmb_lanes_select.attr,
Satyajit Desaif151d682016-09-12 16:18:03 -07003843 NULL,
3844};
3845
3846static struct attribute_group tpdm_bc_attr_grp = {
3847 .attrs = tpdm_bc_attrs,
3848};
3849
3850static struct attribute_group tpdm_tc_attr_grp = {
3851 .attrs = tpdm_tc_attrs,
3852};
3853
3854static struct attribute_group tpdm_dsb_attr_grp = {
3855 .attrs = tpdm_dsb_attrs,
3856};
3857
3858static struct attribute_group tpdm_cmb_attr_grp = {
3859 .attrs = tpdm_cmb_attrs,
3860};
3861
3862static struct attribute *tpdm_attrs[] = {
3863 &dev_attr_available_datasets.attr,
3864 &dev_attr_enable_datasets.attr,
3865 &dev_attr_gp_regs.attr,
3866 NULL,
3867};
3868
3869static struct attribute_group tpdm_attr_grp = {
3870 .attrs = tpdm_attrs,
3871};
3872static const struct attribute_group *tpdm_attr_grps[] = {
3873 &tpdm_attr_grp,
3874 &tpdm_bc_attr_grp,
3875 &tpdm_tc_attr_grp,
3876 &tpdm_dsb_attr_grp,
3877 &tpdm_cmb_attr_grp,
3878 NULL,
3879};
3880
3881static int tpdm_datasets_alloc(struct tpdm_drvdata *drvdata)
3882{
3883 if (test_bit(TPDM_DS_GPR, drvdata->datasets)) {
3884 drvdata->gpr = devm_kzalloc(drvdata->dev, sizeof(*drvdata->gpr),
3885 GFP_KERNEL);
3886 if (!drvdata->gpr)
3887 return -ENOMEM;
3888 }
3889 if (test_bit(TPDM_DS_BC, drvdata->datasets)) {
3890 drvdata->bc = devm_kzalloc(drvdata->dev, sizeof(*drvdata->bc),
3891 GFP_KERNEL);
3892 if (!drvdata->bc)
3893 return -ENOMEM;
3894 }
3895 if (test_bit(TPDM_DS_TC, drvdata->datasets)) {
3896 drvdata->tc = devm_kzalloc(drvdata->dev, sizeof(*drvdata->tc),
3897 GFP_KERNEL);
3898 if (!drvdata->tc)
3899 return -ENOMEM;
3900 }
3901 if (test_bit(TPDM_DS_DSB, drvdata->datasets)) {
3902 drvdata->dsb = devm_kzalloc(drvdata->dev, sizeof(*drvdata->dsb),
3903 GFP_KERNEL);
3904 if (!drvdata->dsb)
3905 return -ENOMEM;
3906 }
3907 if (test_bit(TPDM_DS_CMB, drvdata->datasets)) {
3908 drvdata->cmb = devm_kzalloc(drvdata->dev, sizeof(*drvdata->cmb),
3909 GFP_KERNEL);
3910 if (!drvdata->cmb)
3911 return -ENOMEM;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003912 } else if (test_bit(TPDM_DS_MCMB, drvdata->datasets)) {
3913 drvdata->cmb = devm_kzalloc(drvdata->dev, sizeof(*drvdata->cmb),
3914 GFP_KERNEL);
3915 if (!drvdata->cmb)
3916 return -ENOMEM;
3917 drvdata->cmb->mcmb = devm_kzalloc(drvdata->dev,
3918 sizeof(*drvdata->cmb->mcmb),
3919 GFP_KERNEL);
3920 if (!drvdata->cmb->mcmb)
3921 return -ENOMEM;
Satyajit Desaif151d682016-09-12 16:18:03 -07003922 }
3923 return 0;
3924}
3925
3926static void tpdm_init_default_data(struct tpdm_drvdata *drvdata)
3927{
3928 if (test_bit(TPDM_DS_BC, drvdata->datasets))
3929 drvdata->bc->retrieval_mode = TPDM_MODE_ATB;
3930
3931 if (test_bit(TPDM_DS_TC, drvdata->datasets))
3932 drvdata->tc->retrieval_mode = TPDM_MODE_ATB;
3933
3934 if (test_bit(TPDM_DS_DSB, drvdata->datasets))
3935 drvdata->dsb->trig_ts = true;
3936
Satyajit Desaie104ff52016-09-12 16:38:12 -07003937 if (test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3938 test_bit(TPDM_DS_MCMB, drvdata->datasets))
Satyajit Desaif151d682016-09-12 16:18:03 -07003939 drvdata->cmb->trig_ts = true;
3940}
3941
3942static int tpdm_probe(struct platform_device *pdev)
3943{
3944 int ret, i;
3945 uint32_t pidr, devid;
3946 struct device *dev = &pdev->dev;
3947 struct coresight_platform_data *pdata;
3948 struct tpdm_drvdata *drvdata;
3949 struct resource *res;
3950 struct coresight_desc *desc;
3951 static int traceid = TPDM_TRACE_ID_START;
3952 uint32_t version;
3953
3954 pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
3955 if (IS_ERR(pdata))
3956 return PTR_ERR(pdata);
3957 pdev->dev.platform_data = pdata;
3958
3959 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
3960 if (!drvdata)
3961 return -ENOMEM;
3962 drvdata->dev = &pdev->dev;
3963 platform_set_drvdata(pdev, drvdata);
3964
3965 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tpdm-base");
3966 if (!res)
3967 return -ENODEV;
3968
3969 drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
3970 if (!drvdata->base)
3971 return -ENOMEM;
3972
3973 drvdata->clk_enable = of_property_read_bool(pdev->dev.of_node,
3974 "qcom,clk-enable");
3975
3976 drvdata->msr_fix_req = of_property_read_bool(pdev->dev.of_node,
3977 "qcom,msr-fix-req");
3978
3979 mutex_init(&drvdata->lock);
3980
3981 drvdata->clk = devm_clk_get(dev, "core_clk");
3982 if (IS_ERR(drvdata->clk))
3983 return PTR_ERR(drvdata->clk);
3984
3985 ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
3986 if (ret)
3987 return ret;
3988
3989 ret = clk_prepare_enable(drvdata->clk);
3990 if (ret)
3991 return ret;
3992
3993 version = tpdm_readl(drvdata, CORESIGHT_PERIPHIDR2);
3994 drvdata->version = BMVAL(version, 4, 7);
3995
3996 if (drvdata->version)
3997 drvdata->msr_support = true;
3998
3999 pidr = tpdm_readl(drvdata, CORESIGHT_PERIPHIDR0);
4000 for (i = 0; i < TPDM_DATASETS; i++) {
4001 if (pidr & BIT(i)) {
4002 __set_bit(i, drvdata->datasets);
4003 __set_bit(i, drvdata->enable_ds);
4004 }
4005 }
4006
4007 ret = tpdm_datasets_alloc(drvdata);
4008 if (ret)
4009 return ret;
4010
4011 tpdm_init_default_data(drvdata);
4012
4013 devid = tpdm_readl(drvdata, CORESIGHT_DEVID);
4014 drvdata->tc_trig_type = BMVAL(devid, 27, 28);
4015 drvdata->bc_trig_type = BMVAL(devid, 25, 26);
4016 drvdata->bc_gang_type = BMVAL(devid, 23, 24);
4017 drvdata->bc_counters_avail = BMVAL(devid, 6, 10) + 1;
4018 drvdata->tc_counters_avail = BMVAL(devid, 4, 5) + 1;
4019
4020 clk_disable_unprepare(drvdata->clk);
4021
4022 drvdata->traceid = traceid++;
4023
4024 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
4025 if (!desc)
4026 return -ENOMEM;
4027 desc->type = CORESIGHT_DEV_TYPE_SOURCE;
4028 desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
4029 desc->ops = &tpdm_cs_ops;
4030 desc->pdata = pdev->dev.platform_data;
4031 desc->dev = &pdev->dev;
4032 desc->groups = tpdm_attr_grps;
4033 drvdata->csdev = coresight_register(desc);
4034 if (IS_ERR(drvdata->csdev))
4035 return PTR_ERR(drvdata->csdev);
4036
4037 dev_dbg(drvdata->dev, "TPDM initialized\n");
4038
4039 if (boot_enable)
4040 coresight_enable(drvdata->csdev);
4041
4042 return 0;
4043}
4044
4045static int tpdm_remove(struct platform_device *pdev)
4046{
4047 struct tpdm_drvdata *drvdata = platform_get_drvdata(pdev);
4048
4049 coresight_unregister(drvdata->csdev);
4050 return 0;
4051}
4052
4053static const struct of_device_id tpdm_match[] = {
4054 {.compatible = "qcom,coresight-tpdm"},
4055 {}
4056};
4057
4058static struct platform_driver tpdm_driver = {
4059 .probe = tpdm_probe,
4060 .remove = tpdm_remove,
4061 .driver = {
4062 .name = "coresight-tpdm",
4063 .owner = THIS_MODULE,
4064 .of_match_table = tpdm_match,
4065 },
4066};
4067
4068static int __init tpdm_init(void)
4069{
4070 return platform_driver_register(&tpdm_driver);
4071}
4072module_init(tpdm_init);
4073
4074static void __exit tpdm_exit(void)
4075{
4076 platform_driver_unregister(&tpdm_driver);
4077}
4078module_exit(tpdm_exit);
4079
4080MODULE_LICENSE("GPL v2");
4081MODULE_DESCRIPTION("Trace, Profiling & Diagnostic Monitor driver");