blob: baacaca2962e58dede367b8c029bd804962caf84 [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
162enum tpdm_cmb_mode {
163 TPDM_CMB_MODE_CONTINUOUS,
164 TPDM_CMB_MODE_TRACE_ON_CHANGE,
165};
166
167enum tpdm_cmb_patt_bits {
168 TPDM_CMB_LSB,
169 TPDM_CMB_MSB,
170};
171
172#ifdef CONFIG_CORESIGHT_TPDM_DEFAULT_ENABLE
173static int boot_enable = 1;
174#else
175static int boot_enable;
176#endif
177
178module_param_named(
Satyajit Desai326497c2016-11-14 10:15:03 -0800179 boot_enable, boot_enable, int, 0444
Satyajit Desaif151d682016-09-12 16:18:03 -0700180);
181
182struct gpr_dataset {
183 DECLARE_BITMAP(gpr_dirty, TPDM_GPR_REGS_MAX);
184 uint32_t gp_regs[TPDM_GPR_REGS_MAX];
185};
186
187struct bc_dataset {
188 enum tpdm_mode capture_mode;
189 enum tpdm_mode retrieval_mode;
190 uint32_t sat_mode;
191 uint32_t enable_counters;
192 uint32_t clear_counters;
193 uint32_t enable_irq;
194 uint32_t clear_irq;
195 uint32_t trig_val_lo[TPDM_BC_MAX_COUNTERS];
196 uint32_t trig_val_hi[TPDM_BC_MAX_COUNTERS];
197 uint32_t enable_ganging;
198 uint32_t overflow_val[TPDM_BC_MAX_OVERFLOW];
199 uint32_t msr[TPDM_BC_MAX_MSR];
200};
201
202struct tc_dataset {
203 enum tpdm_mode capture_mode;
204 enum tpdm_mode retrieval_mode;
205 bool sat_mode;
206 uint32_t enable_counters;
207 uint32_t clear_counters;
208 uint32_t enable_irq;
209 uint32_t clear_irq;
210 uint32_t trig_sel[TPDM_TC_MAX_TRIG];
211 uint32_t trig_val_lo[TPDM_TC_MAX_TRIG];
212 uint32_t trig_val_hi[TPDM_TC_MAX_TRIG];
213 uint32_t msr[TPDM_TC_MAX_MSR];
214};
215
216struct dsb_dataset {
217 uint32_t mode;
218 uint32_t edge_ctrl[TPDM_DSB_MAX_EDCR];
219 uint32_t edge_ctrl_mask[TPDM_DSB_MAX_EDCR / 2];
220 uint32_t patt_val[TPDM_DSB_MAX_PATT];
221 uint32_t patt_mask[TPDM_DSB_MAX_PATT];
222 bool patt_ts;
223 bool patt_type;
224 uint32_t trig_patt_val[TPDM_DSB_MAX_PATT];
225 uint32_t trig_patt_mask[TPDM_DSB_MAX_PATT];
226 bool trig_ts;
227 uint32_t select_val[TPDM_DSB_MAX_SELECT];
228 uint32_t msr[TPDM_DSB_MAX_MSR];
229};
230
Satyajit Desaie104ff52016-09-12 16:38:12 -0700231struct mcmb_dataset {
232 uint8_t mcmb_trig_lane;
233 uint8_t mcmb_lane_select;
234};
235
Satyajit Desaif151d682016-09-12 16:18:03 -0700236struct cmb_dataset {
237 enum tpdm_cmb_mode mode;
238 uint32_t patt_val[TPDM_CMB_PATT_CMP];
239 uint32_t patt_mask[TPDM_CMB_PATT_CMP];
240 bool patt_ts;
241 uint32_t trig_patt_val[TPDM_CMB_PATT_CMP];
242 uint32_t trig_patt_mask[TPDM_CMB_PATT_CMP];
243 bool trig_ts;
244 uint32_t msr[TPDM_CMB_MAX_MSR];
Satyajit Desaie104ff52016-09-12 16:38:12 -0700245 uint8_t read_ctl_reg;
246 struct mcmb_dataset *mcmb;
Satyajit Desaif151d682016-09-12 16:18:03 -0700247};
248
249struct tpdm_drvdata {
250 void __iomem *base;
251 struct device *dev;
252 struct coresight_device *csdev;
253 struct clk *clk;
254 struct mutex lock;
255 bool enable;
256 bool clk_enable;
257 DECLARE_BITMAP(datasets, TPDM_DATASETS);
258 DECLARE_BITMAP(enable_ds, TPDM_DATASETS);
259 enum tpdm_support_type tc_trig_type;
260 enum tpdm_support_type bc_trig_type;
261 enum tpdm_support_type bc_gang_type;
262 uint32_t bc_counters_avail;
263 uint32_t tc_counters_avail;
264 struct gpr_dataset *gpr;
265 struct bc_dataset *bc;
266 struct tc_dataset *tc;
267 struct dsb_dataset *dsb;
268 struct cmb_dataset *cmb;
269 int traceid;
270 uint32_t version;
271 bool msr_support;
272 bool msr_fix_req;
273};
274
275static void __tpdm_enable_gpr(struct tpdm_drvdata *drvdata)
276{
277 int i;
278
279 for (i = 0; i < TPDM_GPR_REGS_MAX; i++) {
280 if (!test_bit(i, drvdata->gpr->gpr_dirty))
281 continue;
282 tpdm_writel(drvdata, drvdata->gpr->gp_regs[i], TPDM_GPR_CR(i));
283 }
284}
285
286static void __tpdm_config_bc_msr(struct tpdm_drvdata *drvdata)
287{
288 int i;
289
290 if (!drvdata->msr_support)
291 return;
292
293 for (i = 0; i < TPDM_BC_MAX_MSR; i++)
294 tpdm_writel(drvdata, drvdata->bc->msr[i], TPDM_BC_MSR(i));
295}
296
297static void __tpdm_config_tc_msr(struct tpdm_drvdata *drvdata)
298{
299 int i;
300
301 if (!drvdata->msr_support)
302 return;
303
304 for (i = 0; i < TPDM_TC_MAX_MSR; i++)
305 tpdm_writel(drvdata, drvdata->tc->msr[i], TPDM_TC_MSR(i));
306}
307
308static void __tpdm_config_dsb_msr(struct tpdm_drvdata *drvdata)
309{
310 int i;
311
312 if (!drvdata->msr_support)
313 return;
314
315 for (i = 0; i < TPDM_DSB_MAX_MSR; i++)
316 tpdm_writel(drvdata, drvdata->dsb->msr[i], TPDM_DSB_MSR(i));
317}
318
319static void __tpdm_config_cmb_msr(struct tpdm_drvdata *drvdata)
320{
321 int i;
322
323 if (!drvdata->msr_support)
324 return;
325
326 for (i = 0; i < TPDM_CMB_MAX_MSR; i++)
327 tpdm_writel(drvdata, drvdata->cmb->msr[i], TPDM_CMB_MSR(i));
328}
329
330static void __tpdm_enable_bc(struct tpdm_drvdata *drvdata)
331{
332 int i;
333 uint32_t val;
334
335 if (drvdata->bc->sat_mode)
336 tpdm_writel(drvdata, drvdata->bc->sat_mode,
337 TPDM_BC_SATROLL);
338 else
339 tpdm_writel(drvdata, 0x0, TPDM_BC_SATROLL);
340
341 if (drvdata->bc->enable_counters) {
342 tpdm_writel(drvdata, 0xFFFFFFFF, TPDM_BC_CNTENCLR);
343 tpdm_writel(drvdata, drvdata->bc->enable_counters,
344 TPDM_BC_CNTENSET);
345 }
346 if (drvdata->bc->clear_counters)
347 tpdm_writel(drvdata, drvdata->bc->clear_counters,
348 TPDM_BC_CNTENCLR);
349
350 if (drvdata->bc->enable_irq) {
351 tpdm_writel(drvdata, 0xFFFFFFFF, TPDM_BC_INTENCLR);
352 tpdm_writel(drvdata, drvdata->bc->enable_irq,
353 TPDM_BC_INTENSET);
354 }
355 if (drvdata->bc->clear_irq)
356 tpdm_writel(drvdata, drvdata->bc->clear_irq,
357 TPDM_BC_INTENCLR);
358
359 if (drvdata->bc_trig_type == TPDM_SUPPORT_TYPE_FULL) {
360 for (i = 0; i < drvdata->bc_counters_avail; i++) {
361 tpdm_writel(drvdata, drvdata->bc->trig_val_lo[i],
362 TPDM_BC_TRIG_LO(i));
363 tpdm_writel(drvdata, drvdata->bc->trig_val_hi[i],
364 TPDM_BC_TRIG_HI(i));
365 }
366 } else if (drvdata->bc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL) {
367 tpdm_writel(drvdata, drvdata->bc->trig_val_lo[0],
368 TPDM_BC_TRIG_LO(0));
369 tpdm_writel(drvdata, drvdata->bc->trig_val_hi[0],
370 TPDM_BC_TRIG_HI(0));
371 }
372
373 if (drvdata->bc->enable_ganging)
374 tpdm_writel(drvdata, drvdata->bc->enable_ganging, TPDM_BC_GANG);
375
376 for (i = 0; i < TPDM_BC_MAX_OVERFLOW; i++)
377 tpdm_writel(drvdata, drvdata->bc->overflow_val[i],
378 TPDM_BC_OVERFLOW(i));
379
380 __tpdm_config_bc_msr(drvdata);
381
382 val = tpdm_readl(drvdata, TPDM_BC_CR);
383 if (drvdata->bc->retrieval_mode == TPDM_MODE_APB)
384 val = val | BIT(2);
385 else
386 val = val & ~BIT(2);
387 tpdm_writel(drvdata, val, TPDM_BC_CR);
388
389 val = tpdm_readl(drvdata, TPDM_BC_CR);
390 /* Set the enable bit */
391 val = val | BIT(0);
392 tpdm_writel(drvdata, val, TPDM_BC_CR);
393}
394
395static void __tpdm_enable_tc(struct tpdm_drvdata *drvdata)
396{
397 int i;
398 uint32_t val;
399
400 if (drvdata->tc->enable_counters) {
401 tpdm_writel(drvdata, 0xF, TPDM_TC_CNTENCLR);
402 tpdm_writel(drvdata, drvdata->tc->enable_counters,
403 TPDM_TC_CNTENSET);
404 }
405 if (drvdata->tc->clear_counters)
406 tpdm_writel(drvdata, drvdata->tc->clear_counters,
407 TPDM_TC_CNTENCLR);
408
409 if (drvdata->tc->enable_irq) {
410 tpdm_writel(drvdata, 0xF, TPDM_TC_INTENCLR);
411 tpdm_writel(drvdata, drvdata->tc->enable_irq,
412 TPDM_TC_INTENSET);
413 }
414 if (drvdata->tc->clear_irq)
415 tpdm_writel(drvdata, drvdata->tc->clear_irq,
416 TPDM_TC_INTENCLR);
417
418 if (drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_FULL) {
419 for (i = 0; i < TPDM_TC_MAX_TRIG; i++) {
420 tpdm_writel(drvdata, drvdata->tc->trig_sel[i],
421 TPDM_TC_TRIG_SEL(i));
422 tpdm_writel(drvdata, drvdata->tc->trig_val_lo[i],
423 TPDM_TC_TRIG_LO(i));
424 tpdm_writel(drvdata, drvdata->tc->trig_val_hi[i],
425 TPDM_TC_TRIG_HI(i));
426 }
427 } else if (drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL) {
428 tpdm_writel(drvdata, drvdata->tc->trig_sel[0],
429 TPDM_TC_TRIG_SEL(0));
430 tpdm_writel(drvdata, drvdata->tc->trig_val_lo[0],
431 TPDM_TC_TRIG_LO(0));
432 tpdm_writel(drvdata, drvdata->tc->trig_val_hi[0],
433 TPDM_TC_TRIG_HI(0));
434 }
435
436 __tpdm_config_tc_msr(drvdata);
437
438 val = tpdm_readl(drvdata, TPDM_TC_CR);
439 if (drvdata->tc->sat_mode)
440 val = val | BIT(4);
441 else
442 val = val & ~BIT(4);
443 if (drvdata->tc->retrieval_mode == TPDM_MODE_APB)
444 val = val | BIT(2);
445 else
446 val = val & ~BIT(2);
447 tpdm_writel(drvdata, val, TPDM_TC_CR);
448
449 val = tpdm_readl(drvdata, TPDM_TC_CR);
450 /* Set the enable bit */
451 val = val | BIT(0);
452 tpdm_writel(drvdata, val, TPDM_TC_CR);
453}
454
455static void __tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
456{
457 uint32_t val, mode, i;
458
459 for (i = 0; i < TPDM_DSB_MAX_EDCR; i++)
460 tpdm_writel(drvdata, drvdata->dsb->edge_ctrl[i],
461 TPDM_DSB_EDCR(i));
462 for (i = 0; i < TPDM_DSB_MAX_EDCR / 2; i++)
463 tpdm_writel(drvdata, drvdata->dsb->edge_ctrl_mask[i],
464 TPDM_DSB_EDCMR(i));
465
466 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
467 tpdm_writel(drvdata, drvdata->dsb->patt_val[i],
468 TPDM_DSB_TPR(i));
469 tpdm_writel(drvdata, drvdata->dsb->patt_mask[i],
470 TPDM_DSB_TPMR(i));
471 }
472
473 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
474 tpdm_writel(drvdata, drvdata->dsb->trig_patt_val[i],
475 TPDM_DSB_XPR(i));
476 tpdm_writel(drvdata, drvdata->dsb->trig_patt_mask[i],
477 TPDM_DSB_XPMR(i));
478 }
479
480 for (i = 0; i < TPDM_DSB_MAX_SELECT; i++)
481 tpdm_writel(drvdata, drvdata->dsb->select_val[i],
482 TPDM_DSB_CA_SELECT(i));
483
484 val = tpdm_readl(drvdata, TPDM_DSB_TIER);
485 if (drvdata->dsb->patt_ts == true) {
486 val = val | BIT(0);
487 if (drvdata->dsb->patt_type == true)
488 val = val | BIT(2);
489 else
490 val = val & ~BIT(2);
491 } else {
492 val = val & ~BIT(0);
493 }
494 if (drvdata->dsb->trig_ts == true)
495 val = val | BIT(1);
496 else
497 val = val & ~BIT(1);
498 tpdm_writel(drvdata, val, TPDM_DSB_TIER);
499
500 if (!drvdata->msr_fix_req)
501 __tpdm_config_dsb_msr(drvdata);
502
503 val = tpdm_readl(drvdata, TPDM_DSB_CR);
504 /* Set the cycle accurate mode */
505 mode = TPDM_DSB_MODE_CYCACC(drvdata->dsb->mode);
506 val = val & ~(0x7 << 9);
507 val = val | (mode << 9);
508 /* Set the byte lane for high-performance mode */
509 mode = TPDM_DSB_MODE_HPBYTESEL(drvdata->dsb->mode);
510 val = val & ~(0x1F << 2);
511 val = val | (mode << 2);
512 /* Set the performance mode */
513 if (drvdata->dsb->mode & TPDM_DSB_MODE_PERF)
514 val = val | BIT(1);
515 else
516 val = val & ~BIT(1);
517 tpdm_writel(drvdata, val, TPDM_DSB_CR);
518
519 val = tpdm_readl(drvdata, TPDM_DSB_CR);
520 /* Set the enable bit */
521 val = val | BIT(0);
522 tpdm_writel(drvdata, val, TPDM_DSB_CR);
523
524 if (drvdata->msr_fix_req)
525 __tpdm_config_dsb_msr(drvdata);
526}
527
528static void __tpdm_enable_cmb(struct tpdm_drvdata *drvdata)
529{
530 uint32_t val;
Satyajit Desai75411bc2017-04-19 18:41:27 -0700531 int i;
Satyajit Desaif151d682016-09-12 16:18:03 -0700532
Satyajit Desai75411bc2017-04-19 18:41:27 -0700533 for (i = 0; i < TPDM_CMB_PATT_CMP; i++) {
534 tpdm_writel(drvdata, drvdata->cmb->patt_val[i],
535 TPDM_CMB_TPR(i));
536 tpdm_writel(drvdata, drvdata->cmb->patt_mask[i],
537 TPDM_CMB_TPMR(i));
538 tpdm_writel(drvdata, drvdata->cmb->trig_patt_val[i],
539 TPDM_CMB_XPR(i));
540 tpdm_writel(drvdata, drvdata->cmb->trig_patt_mask[i],
541 TPDM_CMB_XPMR(i));
542 }
Satyajit Desaif151d682016-09-12 16:18:03 -0700543
544 val = tpdm_readl(drvdata, TPDM_CMB_TIER);
545 if (drvdata->cmb->patt_ts == true)
546 val = val | BIT(0);
547 else
548 val = val & ~BIT(0);
549 if (drvdata->cmb->trig_ts == true)
550 val = val | BIT(1);
551 else
552 val = val & ~BIT(1);
553 tpdm_writel(drvdata, val, TPDM_CMB_TIER);
554
555 __tpdm_config_cmb_msr(drvdata);
556
557 val = tpdm_readl(drvdata, TPDM_CMB_CR);
558 /* Set the flow control bit */
559 val = val & ~BIT(2);
560 if (drvdata->cmb->mode == TPDM_CMB_MODE_CONTINUOUS)
561 val = val & ~BIT(1);
562 else
563 val = val | BIT(1);
564 tpdm_writel(drvdata, val, TPDM_CMB_CR);
565 /* Set the enable bit */
566 val = val | BIT(0);
567 tpdm_writel(drvdata, val, TPDM_CMB_CR);
568}
569
Satyajit Desaie104ff52016-09-12 16:38:12 -0700570static void __tpdm_enable_mcmb(struct tpdm_drvdata *drvdata)
571{
572 uint32_t val;
573 struct mcmb_dataset *mcmb = drvdata->cmb->mcmb;
Satyajit Desai75411bc2017-04-19 18:41:27 -0700574 int i;
Satyajit Desaie104ff52016-09-12 16:38:12 -0700575
Satyajit Desai75411bc2017-04-19 18:41:27 -0700576 for (i = 0; i < TPDM_CMB_PATT_CMP; i++) {
577 tpdm_writel(drvdata, drvdata->cmb->patt_val[i],
578 TPDM_CMB_TPR(i));
579 tpdm_writel(drvdata, drvdata->cmb->patt_mask[i],
580 TPDM_CMB_TPMR(i));
581 tpdm_writel(drvdata, drvdata->cmb->trig_patt_val[i],
582 TPDM_CMB_XPR(i));
583 tpdm_writel(drvdata, drvdata->cmb->trig_patt_mask[i],
584 TPDM_CMB_XPMR(i));
585 }
Satyajit Desaie104ff52016-09-12 16:38:12 -0700586
587 val = tpdm_readl(drvdata, TPDM_CMB_TIER);
588 if (drvdata->cmb->patt_ts == true)
589 val = val | BIT(0);
590 else
591 val = val & ~BIT(0);
592 if (drvdata->cmb->trig_ts == true)
593 val = val | BIT(1);
594 else
595 val = val & ~BIT(1);
596 tpdm_writel(drvdata, val, TPDM_CMB_TIER);
597
598 __tpdm_config_cmb_msr(drvdata);
599
600 val = tpdm_readl(drvdata, TPDM_CMB_CR);
601 /* Set the flow control bit */
602 val = val & ~BIT(2);
603 if (drvdata->cmb->mode == TPDM_CMB_MODE_CONTINUOUS)
604 val = val & ~BIT(1);
605 else
606 val = val | BIT(1);
607
608 val = val | (BMVAL(mcmb->mcmb_trig_lane, 0, 3) << 18);
609
610 val = val | (mcmb->mcmb_lane_select << 10);
611
612 tpdm_writel(drvdata, val, TPDM_CMB_CR);
613 /* Set the enable bit */
614 val = val | BIT(0);
615 tpdm_writel(drvdata, val, TPDM_CMB_CR);
616}
617
Satyajit Desaif151d682016-09-12 16:18:03 -0700618static void __tpdm_enable(struct tpdm_drvdata *drvdata)
619{
620 TPDM_UNLOCK(drvdata);
621
622 if (drvdata->clk_enable)
623 tpdm_writel(drvdata, 0x1, TPDM_CLK_CTRL);
624
625 if (test_bit(TPDM_DS_GPR, drvdata->enable_ds))
626 __tpdm_enable_gpr(drvdata);
627
628 if (test_bit(TPDM_DS_BC, drvdata->enable_ds))
629 __tpdm_enable_bc(drvdata);
630
631 if (test_bit(TPDM_DS_TC, drvdata->enable_ds))
632 __tpdm_enable_tc(drvdata);
633
634 if (test_bit(TPDM_DS_DSB, drvdata->enable_ds))
635 __tpdm_enable_dsb(drvdata);
636
637 if (test_bit(TPDM_DS_CMB, drvdata->enable_ds))
638 __tpdm_enable_cmb(drvdata);
Satyajit Desaie104ff52016-09-12 16:38:12 -0700639 else if (test_bit(TPDM_DS_MCMB, drvdata->enable_ds))
640 __tpdm_enable_mcmb(drvdata);
Satyajit Desaif151d682016-09-12 16:18:03 -0700641
642 TPDM_LOCK(drvdata);
643}
644
645static int tpdm_enable(struct coresight_device *csdev,
Satyajit Desaiee828fb2017-02-07 13:51:32 -0800646 struct perf_event *event, u32 mode)
Satyajit Desaif151d682016-09-12 16:18:03 -0700647{
648 struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
649 int ret;
650
651 ret = clk_prepare_enable(drvdata->clk);
652 if (ret)
653 return ret;
654
655 mutex_lock(&drvdata->lock);
656 __tpdm_enable(drvdata);
657 drvdata->enable = true;
658 mutex_unlock(&drvdata->lock);
659
660 dev_info(drvdata->dev, "TPDM tracing enabled\n");
661 return 0;
662}
663
664static void __tpdm_disable_bc(struct tpdm_drvdata *drvdata)
665{
666 uint32_t config;
667
668 config = tpdm_readl(drvdata, TPDM_BC_CR);
669 config = config & ~BIT(0);
670 tpdm_writel(drvdata, config, TPDM_BC_CR);
671}
672
673static void __tpdm_disable_tc(struct tpdm_drvdata *drvdata)
674{
675 uint32_t config;
676
677 config = tpdm_readl(drvdata, TPDM_TC_CR);
678 config = config & ~BIT(0);
679 tpdm_writel(drvdata, config, TPDM_TC_CR);
680}
681
682static void __tpdm_disable_dsb(struct tpdm_drvdata *drvdata)
683{
684 uint32_t config;
685
686 config = tpdm_readl(drvdata, TPDM_DSB_CR);
687 config = config & ~BIT(0);
688 tpdm_writel(drvdata, config, TPDM_DSB_CR);
689}
690
691static void __tpdm_disable_cmb(struct tpdm_drvdata *drvdata)
692{
693 uint32_t config;
694
695 config = tpdm_readl(drvdata, TPDM_CMB_CR);
696 config = config & ~BIT(0);
697 tpdm_writel(drvdata, config, TPDM_CMB_CR);
698}
699
700static void __tpdm_disable(struct tpdm_drvdata *drvdata)
701{
702 TPDM_UNLOCK(drvdata);
703
704 if (test_bit(TPDM_DS_BC, drvdata->enable_ds))
705 __tpdm_disable_bc(drvdata);
706
707 if (test_bit(TPDM_DS_TC, drvdata->enable_ds))
708 __tpdm_disable_tc(drvdata);
709
710 if (test_bit(TPDM_DS_DSB, drvdata->enable_ds))
711 __tpdm_disable_dsb(drvdata);
712
713 if (test_bit(TPDM_DS_CMB, drvdata->enable_ds))
714 __tpdm_disable_cmb(drvdata);
715
716 if (drvdata->clk_enable)
717 tpdm_writel(drvdata, 0x0, TPDM_CLK_CTRL);
718
719 TPDM_LOCK(drvdata);
720}
721
Satyajit Desaiee828fb2017-02-07 13:51:32 -0800722static void tpdm_disable(struct coresight_device *csdev,
723 struct perf_event *event)
Satyajit Desaif151d682016-09-12 16:18:03 -0700724{
725 struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
726
727 mutex_lock(&drvdata->lock);
728 __tpdm_disable(drvdata);
729 drvdata->enable = false;
730 mutex_unlock(&drvdata->lock);
731
732 clk_disable_unprepare(drvdata->clk);
733
734 dev_info(drvdata->dev, "TPDM tracing disabled\n");
735}
736
737static int tpdm_trace_id(struct coresight_device *csdev)
738{
739 struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
740
741 return drvdata->traceid;
742}
743
744static const struct coresight_ops_source tpdm_source_ops = {
745 .trace_id = tpdm_trace_id,
746 .enable = tpdm_enable,
747 .disable = tpdm_disable,
748};
749
750static const struct coresight_ops tpdm_cs_ops = {
751 .source_ops = &tpdm_source_ops,
752};
753
754static ssize_t tpdm_show_available_datasets(struct device *dev,
755 struct device_attribute *attr,
756 char *buf)
757{
758 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
759 ssize_t size = 0;
760
761 if (test_bit(TPDM_DS_IMPLDEF, drvdata->datasets))
762 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s",
763 "IMPLDEF");
764
765 if (test_bit(TPDM_DS_DSB, drvdata->datasets))
766 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "DSB");
767
768 if (test_bit(TPDM_DS_CMB, drvdata->datasets))
769 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "CMB");
770
771 if (test_bit(TPDM_DS_TC, drvdata->datasets))
772 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "TC");
773
774 if (test_bit(TPDM_DS_BC, drvdata->datasets))
775 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "BC");
776
777 if (test_bit(TPDM_DS_GPR, drvdata->datasets))
778 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "GPR");
779
Satyajit Desaie104ff52016-09-12 16:38:12 -0700780 if (test_bit(TPDM_DS_MCMB, drvdata->datasets))
781 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "MCMB");
782
Satyajit Desaif151d682016-09-12 16:18:03 -0700783 size += scnprintf(buf + size, PAGE_SIZE - size, "\n");
784 return size;
785}
Satyajit Desai326497c2016-11-14 10:15:03 -0800786static DEVICE_ATTR(available_datasets, 0444, tpdm_show_available_datasets,
Satyajit Desaif151d682016-09-12 16:18:03 -0700787 NULL);
788
789static ssize_t tpdm_show_enable_datasets(struct device *dev,
790 struct device_attribute *attr,
791 char *buf)
792{
793 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
794 ssize_t size;
795
796 size = scnprintf(buf, PAGE_SIZE, "%*pb\n", TPDM_DATASETS,
797 drvdata->enable_ds);
798
799 if (PAGE_SIZE - size < 2)
800 size = -EINVAL;
801 else
802 size += scnprintf(buf + size, 2, "\n");
803 return size;
804}
805
806static ssize_t tpdm_store_enable_datasets(struct device *dev,
807 struct device_attribute *attr,
808 const char *buf,
809 size_t size)
810{
811 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
812 unsigned long val;
813 int i;
814
815 if (kstrtoul(buf, 16, &val))
816 return -EINVAL;
817
818 mutex_lock(&drvdata->lock);
819 if (drvdata->enable) {
820 mutex_unlock(&drvdata->lock);
821 return -EPERM;
822 }
823
824 for (i = 0; i < TPDM_DATASETS; i++) {
825 if (test_bit(i, drvdata->datasets) && (val & BIT(i)))
826 __set_bit(i, drvdata->enable_ds);
827 else
828 __clear_bit(i, drvdata->enable_ds);
829 }
830 mutex_unlock(&drvdata->lock);
831 return size;
832}
Satyajit Desai326497c2016-11-14 10:15:03 -0800833static DEVICE_ATTR(enable_datasets, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -0700834 tpdm_show_enable_datasets, tpdm_store_enable_datasets);
835
836static ssize_t tpdm_show_gp_regs(struct device *dev,
837 struct device_attribute *attr,
838 char *buf)
839{
840 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
841 ssize_t size = 0;
842 int i = 0;
843
844 if (!test_bit(TPDM_DS_GPR, drvdata->datasets))
845 return -EPERM;
846
847 mutex_lock(&drvdata->lock);
848 for (i = 0; i < TPDM_GPR_REGS_MAX; i++) {
849 if (!test_bit(i, drvdata->gpr->gpr_dirty))
850 continue;
851 size += scnprintf(buf + size, PAGE_SIZE - size,
852 "Index: 0x%x Value: 0x%x\n", i,
853 drvdata->gpr->gp_regs[i]);
854 }
855 mutex_unlock(&drvdata->lock);
856 return size;
857}
858
859static ssize_t tpdm_store_gp_regs(struct device *dev,
860 struct device_attribute *attr,
861 const char *buf,
862 size_t size)
863{
864 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
865 unsigned long index, val;
866
867 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
868 return -EINVAL;
869 if (!test_bit(TPDM_DS_GPR, drvdata->datasets) ||
870 index >= TPDM_GPR_REGS_MAX)
871 return -EPERM;
872
873 mutex_lock(&drvdata->lock);
874 drvdata->gpr->gp_regs[index] = val;
875 __set_bit(index, drvdata->gpr->gpr_dirty);
876 mutex_unlock(&drvdata->lock);
877 return size;
878}
Satyajit Desai326497c2016-11-14 10:15:03 -0800879static DEVICE_ATTR(gp_regs, 0644, tpdm_show_gp_regs,
Satyajit Desaif151d682016-09-12 16:18:03 -0700880 tpdm_store_gp_regs);
881
882static ssize_t tpdm_show_bc_capture_mode(struct device *dev,
883 struct device_attribute *attr,
884 char *buf)
885{
886 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
887
888 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
889 return -EPERM;
890
891 return scnprintf(buf, PAGE_SIZE, "%s\n",
892 drvdata->bc->capture_mode == TPDM_MODE_ATB ?
893 "ATB" : "APB");
894}
895
896static ssize_t tpdm_store_bc_capture_mode(struct device *dev,
897 struct device_attribute *attr,
898 const char *buf,
899 size_t size)
900{
901 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
902 char str[20] = "";
903 uint32_t val;
904
905 if (size >= 20)
906 return -EINVAL;
907 if (sscanf(buf, "%s", str) != 1)
908 return -EINVAL;
909 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
910 return -EPERM;
911
912 mutex_lock(&drvdata->lock);
913 if (!drvdata->enable) {
914 mutex_unlock(&drvdata->lock);
915 return -EPERM;
916 }
917
918 if (!strcmp(str, "ATB")) {
919 drvdata->bc->capture_mode = TPDM_MODE_ATB;
920 } else if (!strcmp(str, "APB") &&
921 drvdata->bc->retrieval_mode == TPDM_MODE_APB) {
922
923 TPDM_UNLOCK(drvdata);
924 val = tpdm_readl(drvdata, TPDM_BC_CR);
925 val = val | BIT(3);
926 tpdm_writel(drvdata, val, TPDM_BC_CR);
927 TPDM_LOCK(drvdata);
928
929 drvdata->bc->capture_mode = TPDM_MODE_APB;
930 } else {
931 mutex_unlock(&drvdata->lock);
932 return -EINVAL;
933 }
934 mutex_unlock(&drvdata->lock);
935 return size;
936}
Satyajit Desai326497c2016-11-14 10:15:03 -0800937static DEVICE_ATTR(bc_capture_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -0700938 tpdm_show_bc_capture_mode, tpdm_store_bc_capture_mode);
939
940static ssize_t tpdm_show_bc_retrieval_mode(struct device *dev,
941 struct device_attribute *attr,
942 char *buf)
943{
944 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
945
946 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
947 return -EPERM;
948
949 return scnprintf(buf, PAGE_SIZE, "%s\n",
950 drvdata->bc->retrieval_mode == TPDM_MODE_ATB ?
951 "ATB" : "APB");
952}
953
954static ssize_t tpdm_store_bc_retrieval_mode(struct device *dev,
955 struct device_attribute *attr,
956 const char *buf,
957 size_t size)
958{
959 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
960 char str[20] = "";
961
962 if (size >= 20)
963 return -EINVAL;
964 if (sscanf(buf, "%s", str) != 1)
965 return -EINVAL;
966 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
967 return -EPERM;
968
969 mutex_lock(&drvdata->lock);
970 if (drvdata->enable) {
971 mutex_unlock(&drvdata->lock);
972 return -EPERM;
973 }
974
975 if (!strcmp(str, "ATB")) {
976 drvdata->bc->retrieval_mode = TPDM_MODE_ATB;
977 } else if (!strcmp(str, "APB")) {
978 drvdata->bc->retrieval_mode = TPDM_MODE_APB;
979 } else {
980 mutex_unlock(&drvdata->lock);
981 return -EINVAL;
982 }
983 mutex_unlock(&drvdata->lock);
984 return size;
985}
Satyajit Desai326497c2016-11-14 10:15:03 -0800986static DEVICE_ATTR(bc_retrieval_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -0700987 tpdm_show_bc_retrieval_mode, tpdm_store_bc_retrieval_mode);
988
989static ssize_t tpdm_store_bc_reset_counters(struct device *dev,
990 struct device_attribute *attr,
991 const char *buf,
992 size_t size)
993{
994 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
995 unsigned long val;
996
997 if (kstrtoul(buf, 16, &val))
998 return -EINVAL;
999 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1000 return -EPERM;
1001
1002 mutex_lock(&drvdata->lock);
1003 if (!drvdata->enable) {
1004 mutex_unlock(&drvdata->lock);
1005 return -EPERM;
1006 }
1007
1008 if (val) {
1009 TPDM_UNLOCK(drvdata);
1010 val = tpdm_readl(drvdata, TPDM_BC_CR);
1011 val = val | BIT(1);
1012 tpdm_writel(drvdata, val, TPDM_BC_CR);
1013 TPDM_LOCK(drvdata);
1014 }
1015 mutex_unlock(&drvdata->lock);
1016 return size;
1017}
Satyajit Desai326497c2016-11-14 10:15:03 -08001018static DEVICE_ATTR(bc_reset_counters, 0644, NULL,
Satyajit Desaif151d682016-09-12 16:18:03 -07001019 tpdm_store_bc_reset_counters);
1020
1021static ssize_t tpdm_show_bc_sat_mode(struct device *dev,
1022 struct device_attribute *attr,
1023 char *buf)
1024{
1025 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1026
1027 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1028 return -EPERM;
1029
1030 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1031 (unsigned long)drvdata->bc->sat_mode);
1032}
1033
1034static ssize_t tpdm_store_bc_sat_mode(struct device *dev,
1035 struct device_attribute *attr,
1036 const char *buf,
1037 size_t size)
1038{
1039 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1040 unsigned long val;
1041
1042 if (kstrtoul(buf, 16, &val))
1043 return -EINVAL;
1044 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1045 return -EPERM;
1046
1047 mutex_lock(&drvdata->lock);
1048 drvdata->bc->sat_mode = val;
1049 mutex_unlock(&drvdata->lock);
1050 return size;
1051}
Satyajit Desai326497c2016-11-14 10:15:03 -08001052static DEVICE_ATTR(bc_sat_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001053 tpdm_show_bc_sat_mode, tpdm_store_bc_sat_mode);
1054
1055static ssize_t tpdm_show_bc_enable_counters(struct device *dev,
1056 struct device_attribute *attr,
1057 char *buf)
1058{
1059 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1060
1061 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1062 return -EPERM;
1063
1064 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1065 (unsigned long)drvdata->bc->enable_counters);
1066}
1067
1068static ssize_t tpdm_store_bc_enable_counters(struct device *dev,
1069 struct device_attribute *attr,
1070 const char *buf,
1071 size_t size)
1072{
1073 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1074 unsigned long val;
1075
1076 if (kstrtoul(buf, 16, &val))
1077 return -EINVAL;
1078 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1079 return -EPERM;
1080
1081 mutex_lock(&drvdata->lock);
1082 drvdata->bc->enable_counters = val;
1083 mutex_unlock(&drvdata->lock);
1084 return size;
1085}
Satyajit Desai326497c2016-11-14 10:15:03 -08001086static DEVICE_ATTR(bc_enable_counters, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001087 tpdm_show_bc_enable_counters, tpdm_store_bc_enable_counters);
1088
1089static ssize_t tpdm_show_bc_clear_counters(struct device *dev,
1090 struct device_attribute *attr,
1091 char *buf)
1092{
1093 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1094
1095 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1096 return -EPERM;
1097
1098 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1099 (unsigned long)drvdata->bc->clear_counters);
1100}
1101
1102static ssize_t tpdm_store_bc_clear_counters(struct device *dev,
1103 struct device_attribute *attr,
1104 const char *buf,
1105 size_t size)
1106{
1107 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1108 unsigned long val;
1109
1110 if (kstrtoul(buf, 16, &val))
1111 return -EINVAL;
1112 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1113 return -EPERM;
1114
1115 mutex_lock(&drvdata->lock);
1116 drvdata->bc->clear_counters = val;
1117 mutex_unlock(&drvdata->lock);
1118 return size;
1119}
Satyajit Desai326497c2016-11-14 10:15:03 -08001120static DEVICE_ATTR(bc_clear_counters, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001121 tpdm_show_bc_clear_counters, tpdm_store_bc_clear_counters);
1122
1123static ssize_t tpdm_show_bc_enable_irq(struct device *dev,
1124 struct device_attribute *attr,
1125 char *buf)
1126{
1127 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1128
1129 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1130 return -EPERM;
1131
1132 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1133 (unsigned long)drvdata->bc->enable_irq);
1134}
1135
1136static ssize_t tpdm_store_bc_enable_irq(struct device *dev,
1137 struct device_attribute *attr,
1138 const char *buf,
1139 size_t size)
1140{
1141 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1142 unsigned long val;
1143
1144 if (kstrtoul(buf, 16, &val))
1145 return -EINVAL;
1146 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1147 return -EPERM;
1148
1149 mutex_lock(&drvdata->lock);
1150 drvdata->bc->enable_irq = val;
1151 mutex_unlock(&drvdata->lock);
1152 return size;
1153}
Satyajit Desai326497c2016-11-14 10:15:03 -08001154static DEVICE_ATTR(bc_enable_irq, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001155 tpdm_show_bc_enable_irq, tpdm_store_bc_enable_irq);
1156
1157static ssize_t tpdm_show_bc_clear_irq(struct device *dev,
1158 struct device_attribute *attr,
1159 char *buf)
1160{
1161 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1162
1163 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1164 return -EPERM;
1165
1166 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1167 (unsigned long)drvdata->bc->clear_irq);
1168}
1169
1170static ssize_t tpdm_store_bc_clear_irq(struct device *dev,
1171 struct device_attribute *attr,
1172 const char *buf,
1173 size_t size)
1174{
1175 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1176 unsigned long val;
1177
1178 if (kstrtoul(buf, 16, &val))
1179 return -EINVAL;
1180 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1181 return -EPERM;
1182
1183 mutex_lock(&drvdata->lock);
1184 drvdata->bc->clear_irq = val;
1185 mutex_unlock(&drvdata->lock);
1186 return size;
1187}
Satyajit Desai326497c2016-11-14 10:15:03 -08001188static DEVICE_ATTR(bc_clear_irq, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001189 tpdm_show_bc_clear_irq, tpdm_store_bc_clear_irq);
1190
1191static ssize_t tpdm_show_bc_trig_val_lo(struct device *dev,
1192 struct device_attribute *attr,
1193 char *buf)
1194{
1195 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1196 ssize_t size = 0;
1197 int i = 0;
1198
1199 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1200 return -EPERM;
1201
1202 mutex_lock(&drvdata->lock);
1203 for (i = 0; i < TPDM_BC_MAX_COUNTERS; i++)
1204 size += scnprintf(buf + size, PAGE_SIZE - size,
1205 "Index: 0x%x Value: 0x%x\n", i,
1206 drvdata->bc->trig_val_lo[i]);
1207 mutex_unlock(&drvdata->lock);
1208 return size;
1209}
1210
1211static ssize_t tpdm_store_bc_trig_val_lo(struct device *dev,
1212 struct device_attribute *attr,
1213 const char *buf,
1214 size_t size)
1215{
1216 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1217 unsigned long index, val;
1218
1219 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
1220 return -EINVAL;
1221 if (!test_bit(TPDM_DS_BC, drvdata->datasets) ||
1222 index >= drvdata->bc_counters_avail ||
1223 drvdata->bc_trig_type == TPDM_SUPPORT_TYPE_NO ||
1224 (drvdata->bc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL && index > 0))
1225 return -EPERM;
1226
1227 mutex_lock(&drvdata->lock);
1228 drvdata->bc->trig_val_lo[index] = val;
1229 mutex_unlock(&drvdata->lock);
1230 return size;
1231}
Satyajit Desai326497c2016-11-14 10:15:03 -08001232static DEVICE_ATTR(bc_trig_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001233 tpdm_show_bc_trig_val_lo, tpdm_store_bc_trig_val_lo);
1234
1235static ssize_t tpdm_show_bc_trig_val_hi(struct device *dev,
1236 struct device_attribute *attr,
1237 char *buf)
1238{
1239 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1240 ssize_t size = 0;
1241 int i = 0;
1242
1243 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1244 return -EPERM;
1245
1246 mutex_lock(&drvdata->lock);
1247 for (i = 0; i < TPDM_BC_MAX_COUNTERS; i++)
1248 size += scnprintf(buf + size, PAGE_SIZE - size,
1249 "Index: 0x%x Value: 0x%x\n", i,
1250 drvdata->bc->trig_val_hi[i]);
1251 mutex_unlock(&drvdata->lock);
1252 return size;
1253}
1254
1255static ssize_t tpdm_store_bc_trig_val_hi(struct device *dev,
1256 struct device_attribute *attr,
1257 const char *buf,
1258 size_t size)
1259{
1260 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1261 unsigned long index, val;
1262
1263 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
1264 return -EINVAL;
1265 if (!test_bit(TPDM_DS_BC, drvdata->datasets) ||
1266 index >= drvdata->bc_counters_avail ||
1267 drvdata->bc_trig_type == TPDM_SUPPORT_TYPE_NO ||
1268 (drvdata->bc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL && index > 0))
1269 return -EPERM;
1270
1271 mutex_lock(&drvdata->lock);
1272 drvdata->bc->trig_val_hi[index] = val;
1273 mutex_unlock(&drvdata->lock);
1274 return size;
1275}
Satyajit Desai326497c2016-11-14 10:15:03 -08001276static DEVICE_ATTR(bc_trig_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001277 tpdm_show_bc_trig_val_hi, tpdm_store_bc_trig_val_hi);
1278
1279static ssize_t tpdm_show_bc_enable_ganging(struct device *dev,
1280 struct device_attribute *attr,
1281 char *buf)
1282{
1283 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1284
1285 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1286 return -EPERM;
1287
1288 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1289 (unsigned long)drvdata->bc->enable_ganging);
1290}
1291
1292static ssize_t tpdm_store_bc_enable_ganging(struct device *dev,
1293 struct device_attribute *attr,
1294 const char *buf,
1295 size_t size)
1296{
1297 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1298 unsigned long val;
1299
1300 if (kstrtoul(buf, 16, &val))
1301 return -EINVAL;
1302 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1303 return -EPERM;
1304
1305 mutex_lock(&drvdata->lock);
1306 drvdata->bc->enable_ganging = val;
1307 mutex_unlock(&drvdata->lock);
1308 return size;
1309}
Satyajit Desai326497c2016-11-14 10:15:03 -08001310static DEVICE_ATTR(bc_enable_ganging, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001311 tpdm_show_bc_enable_ganging, tpdm_store_bc_enable_ganging);
1312
1313static ssize_t tpdm_show_bc_overflow_val(struct device *dev,
1314 struct device_attribute *attr,
1315 char *buf)
1316{
1317 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1318 ssize_t size = 0;
1319 int i = 0;
1320
1321 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1322 return -EPERM;
1323
1324 mutex_lock(&drvdata->lock);
1325 for (i = 0; i < TPDM_BC_MAX_OVERFLOW; i++)
1326 size += scnprintf(buf + size, PAGE_SIZE - size,
1327 "Index: 0x%x Value: 0x%x\n", i,
1328 drvdata->bc->overflow_val[i]);
1329 mutex_unlock(&drvdata->lock);
1330 return size;
1331}
1332
1333static ssize_t tpdm_store_bc_overflow_val(struct device *dev,
1334 struct device_attribute *attr,
1335 const char *buf,
1336 size_t size)
1337{
1338 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1339 unsigned long index, val;
1340
1341 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
1342 return -EINVAL;
1343 if (!test_bit(TPDM_DS_BC, drvdata->datasets) ||
1344 index >= TPDM_BC_MAX_OVERFLOW)
1345 return -EPERM;
1346
1347 mutex_lock(&drvdata->lock);
1348 drvdata->bc->overflow_val[index] = val;
1349 mutex_unlock(&drvdata->lock);
1350 return size;
1351}
Satyajit Desai326497c2016-11-14 10:15:03 -08001352static DEVICE_ATTR(bc_overflow_val, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001353 tpdm_show_bc_overflow_val, tpdm_store_bc_overflow_val);
1354
1355static ssize_t tpdm_show_bc_ovsr(struct device *dev,
1356 struct device_attribute *attr,
1357 char *buf)
1358{
1359 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1360 unsigned long val;
1361
1362 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1363 return -EPERM;
1364
1365 mutex_lock(&drvdata->lock);
1366 if (!drvdata->enable) {
1367 mutex_unlock(&drvdata->lock);
1368 return -EPERM;
1369 }
1370
1371 TPDM_UNLOCK(drvdata);
1372 val = tpdm_readl(drvdata, TPDM_BC_OVSR);
1373 TPDM_LOCK(drvdata);
1374 mutex_unlock(&drvdata->lock);
1375 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
1376}
1377
1378static ssize_t tpdm_store_bc_ovsr(struct device *dev,
1379 struct device_attribute *attr,
1380 const char *buf,
1381 size_t size)
1382{
1383 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1384 unsigned long val;
1385
1386 if (kstrtoul(buf, 16, &val))
1387 return -EINVAL;
1388 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1389 return -EPERM;
1390
1391 mutex_lock(&drvdata->lock);
1392 if (!drvdata->enable) {
1393 mutex_unlock(&drvdata->lock);
1394 return -EPERM;
1395 }
1396
1397 if (val) {
1398 TPDM_UNLOCK(drvdata);
1399 tpdm_writel(drvdata, val, TPDM_BC_OVSR);
1400 TPDM_LOCK(drvdata);
1401 }
1402 mutex_unlock(&drvdata->lock);
1403 return size;
1404}
Satyajit Desai326497c2016-11-14 10:15:03 -08001405static DEVICE_ATTR(bc_ovsr, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001406 tpdm_show_bc_ovsr, tpdm_store_bc_ovsr);
1407
1408static ssize_t tpdm_show_bc_counter_sel(struct device *dev,
1409 struct device_attribute *attr,
1410 char *buf)
1411{
1412 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1413 unsigned long val;
1414
1415 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1416 return -EPERM;
1417
1418 mutex_lock(&drvdata->lock);
1419 if (!drvdata->enable) {
1420 mutex_unlock(&drvdata->lock);
1421 return -EPERM;
1422 }
1423
1424 TPDM_UNLOCK(drvdata);
1425 val = tpdm_readl(drvdata, TPDM_BC_SELR);
1426 TPDM_LOCK(drvdata);
1427 mutex_unlock(&drvdata->lock);
1428 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
1429}
1430
1431static ssize_t tpdm_store_bc_counter_sel(struct device *dev,
1432 struct device_attribute *attr,
1433 const char *buf,
1434 size_t size)
1435{
1436 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1437 unsigned long val;
1438
1439 if (kstrtoul(buf, 16, &val))
1440 return -EINVAL;
1441 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1442 return -EPERM;
1443
1444 mutex_lock(&drvdata->lock);
1445 if (!drvdata->enable || val >= drvdata->bc_counters_avail) {
1446 mutex_unlock(&drvdata->lock);
1447 return -EPERM;
1448 }
1449
1450 TPDM_UNLOCK(drvdata);
1451 tpdm_writel(drvdata, val, TPDM_BC_SELR);
1452 TPDM_LOCK(drvdata);
1453 mutex_unlock(&drvdata->lock);
1454 return size;
1455}
Satyajit Desai326497c2016-11-14 10:15:03 -08001456static DEVICE_ATTR(bc_counter_sel, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001457 tpdm_show_bc_counter_sel, tpdm_store_bc_counter_sel);
1458
1459static ssize_t tpdm_show_bc_count_val_lo(struct device *dev,
1460 struct device_attribute *attr,
1461 char *buf)
1462{
1463 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1464 unsigned long val;
1465
1466 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1467 return -EPERM;
1468
1469 mutex_lock(&drvdata->lock);
1470 if (!drvdata->enable) {
1471 mutex_unlock(&drvdata->lock);
1472 return -EPERM;
1473 }
1474
1475 TPDM_UNLOCK(drvdata);
1476 val = tpdm_readl(drvdata, TPDM_BC_CNTR_LO);
1477 TPDM_LOCK(drvdata);
1478 mutex_unlock(&drvdata->lock);
1479 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
1480}
1481
1482static ssize_t tpdm_store_bc_count_val_lo(struct device *dev,
1483 struct device_attribute *attr,
1484 const char *buf,
1485 size_t size)
1486{
1487 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1488 unsigned long val, select;
1489
1490 if (kstrtoul(buf, 16, &val))
1491 return -EINVAL;
1492 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1493 return -EPERM;
1494
1495 mutex_lock(&drvdata->lock);
1496 if (!drvdata->enable) {
1497 mutex_unlock(&drvdata->lock);
1498 return -EPERM;
1499 }
1500
1501 if (val) {
1502 TPDM_UNLOCK(drvdata);
1503 select = tpdm_readl(drvdata, TPDM_BC_SELR);
1504
1505 /* Check if selected counter is disabled */
1506 if (BVAL(tpdm_readl(drvdata, TPDM_BC_CNTENSET), select)) {
1507 mutex_unlock(&drvdata->lock);
1508 return -EPERM;
1509 }
1510
1511 tpdm_writel(drvdata, val, TPDM_BC_CNTR_LO);
1512 TPDM_LOCK(drvdata);
1513 }
1514 mutex_unlock(&drvdata->lock);
1515 return size;
1516}
Satyajit Desai326497c2016-11-14 10:15:03 -08001517static DEVICE_ATTR(bc_count_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001518 tpdm_show_bc_count_val_lo, tpdm_store_bc_count_val_lo);
1519
1520static ssize_t tpdm_show_bc_count_val_hi(struct device *dev,
1521 struct device_attribute *attr,
1522 char *buf)
1523{
1524 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1525 unsigned long val;
1526
1527 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1528 return -EPERM;
1529
1530 mutex_lock(&drvdata->lock);
1531 if (!drvdata->enable) {
1532 mutex_unlock(&drvdata->lock);
1533 return -EPERM;
1534 }
1535
1536 TPDM_UNLOCK(drvdata);
1537 val = tpdm_readl(drvdata, TPDM_BC_CNTR_HI);
1538 TPDM_LOCK(drvdata);
1539 mutex_unlock(&drvdata->lock);
1540 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
1541}
1542
1543static ssize_t tpdm_store_bc_count_val_hi(struct device *dev,
1544 struct device_attribute *attr,
1545 const char *buf,
1546 size_t size)
1547{
1548 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1549 unsigned long val, select;
1550
1551 if (kstrtoul(buf, 16, &val))
1552 return -EINVAL;
1553 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1554 return -EPERM;
1555
1556 mutex_lock(&drvdata->lock);
1557 if (!drvdata->enable) {
1558 mutex_unlock(&drvdata->lock);
1559 return -EPERM;
1560 }
1561
1562 if (val) {
1563 TPDM_UNLOCK(drvdata);
1564 select = tpdm_readl(drvdata, TPDM_BC_SELR);
1565
1566 /* Check if selected counter is disabled */
1567 if (BVAL(tpdm_readl(drvdata, TPDM_BC_CNTENSET), select)) {
1568 mutex_unlock(&drvdata->lock);
1569 return -EPERM;
1570 }
1571
1572 tpdm_writel(drvdata, val, TPDM_BC_CNTR_HI);
1573 TPDM_LOCK(drvdata);
1574 }
1575 mutex_unlock(&drvdata->lock);
1576 return size;
1577}
Satyajit Desai326497c2016-11-14 10:15:03 -08001578static DEVICE_ATTR(bc_count_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001579 tpdm_show_bc_count_val_hi, tpdm_store_bc_count_val_hi);
1580
1581static ssize_t tpdm_show_bc_shadow_val_lo(struct device *dev,
1582 struct device_attribute *attr,
1583 char *buf)
1584{
1585 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1586 ssize_t size = 0;
1587 int i = 0;
1588
1589 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1590 return -EPERM;
1591
1592 mutex_lock(&drvdata->lock);
1593 if (!drvdata->enable) {
1594 mutex_unlock(&drvdata->lock);
1595 return -EPERM;
1596 }
1597
1598 TPDM_UNLOCK(drvdata);
1599 for (i = 0; i < drvdata->bc_counters_avail; i++) {
1600 size += scnprintf(buf + size, PAGE_SIZE - size,
1601 "Index: 0x%x Value: 0x%x\n", i,
1602 tpdm_readl(drvdata, TPDM_BC_SHADOW_LO(i)));
1603 }
1604 TPDM_LOCK(drvdata);
1605 mutex_unlock(&drvdata->lock);
1606 return size;
1607}
Satyajit Desai326497c2016-11-14 10:15:03 -08001608static DEVICE_ATTR(bc_shadow_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001609 tpdm_show_bc_shadow_val_lo, NULL);
1610
1611static ssize_t tpdm_show_bc_shadow_val_hi(struct device *dev,
1612 struct device_attribute *attr,
1613 char *buf)
1614{
1615 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1616 ssize_t size = 0;
1617 int i = 0;
1618
1619 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1620 return -EPERM;
1621
1622 mutex_lock(&drvdata->lock);
1623 if (!drvdata->enable) {
1624 mutex_unlock(&drvdata->lock);
1625 return -EPERM;
1626 }
1627
1628 TPDM_UNLOCK(drvdata);
1629 for (i = 0; i < drvdata->bc_counters_avail; i++)
1630 size += scnprintf(buf + size, PAGE_SIZE - size,
1631 "Index: 0x%x Value: 0x%x\n", i,
1632 tpdm_readl(drvdata, TPDM_BC_SHADOW_HI(i)));
1633 TPDM_LOCK(drvdata);
1634 mutex_unlock(&drvdata->lock);
1635 return size;
1636}
Satyajit Desai326497c2016-11-14 10:15:03 -08001637static DEVICE_ATTR(bc_shadow_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001638 tpdm_show_bc_shadow_val_hi, NULL);
1639
1640static ssize_t tpdm_show_bc_sw_inc(struct device *dev,
1641 struct device_attribute *attr,
1642 char *buf)
1643{
1644 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1645 unsigned long val;
1646
1647 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1648 return -EPERM;
1649
1650 mutex_lock(&drvdata->lock);
1651 if (!drvdata->enable) {
1652 mutex_unlock(&drvdata->lock);
1653 return -EPERM;
1654 }
1655
1656 TPDM_UNLOCK(drvdata);
1657 val = tpdm_readl(drvdata, TPDM_BC_SWINC);
1658 TPDM_LOCK(drvdata);
1659 mutex_unlock(&drvdata->lock);
1660 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
1661}
1662
1663static ssize_t tpdm_store_bc_sw_inc(struct device *dev,
1664 struct device_attribute *attr,
1665 const char *buf,
1666 size_t size)
1667{
1668 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1669 unsigned long val;
1670
1671 if (kstrtoul(buf, 16, &val))
1672 return -EINVAL;
1673 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1674 return -EPERM;
1675
1676 mutex_lock(&drvdata->lock);
1677 if (!drvdata->enable) {
1678 mutex_unlock(&drvdata->lock);
1679 return -EPERM;
1680 }
1681
1682 if (val) {
1683 TPDM_UNLOCK(drvdata);
1684 tpdm_writel(drvdata, val, TPDM_BC_SWINC);
1685 TPDM_LOCK(drvdata);
1686 }
1687 mutex_unlock(&drvdata->lock);
1688 return size;
1689}
Satyajit Desai326497c2016-11-14 10:15:03 -08001690static DEVICE_ATTR(bc_sw_inc, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001691 tpdm_show_bc_sw_inc, tpdm_store_bc_sw_inc);
1692
Satyajit Desaib34b2c02017-01-11 16:59:38 -08001693static ssize_t tpdm_show_bc_msr(struct device *dev,
1694 struct device_attribute *attr,
1695 char *buf)
1696{
1697 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1698 unsigned int i;
1699 ssize_t len = 0;
1700
1701 if (!drvdata->msr_support)
1702 return -EINVAL;
1703
1704 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1705 return -EPERM;
1706
1707 for (i = 0; i < TPDM_BC_MAX_MSR; i++)
1708 len += scnprintf(buf + len, PAGE_SIZE - len, "%u 0x%x\n",
1709 i, drvdata->bc->msr[i]);
1710
1711 return len;
1712}
1713
Satyajit Desaif151d682016-09-12 16:18:03 -07001714static ssize_t tpdm_store_bc_msr(struct device *dev,
1715 struct device_attribute *attr,
1716 const char *buf,
1717 size_t size)
1718{
1719 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1720 unsigned int num, val;
1721 int nval;
1722
1723 if (!drvdata->msr_support)
1724 return -EINVAL;
1725
1726 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1727 return -EPERM;
1728
1729 nval = sscanf(buf, "%u %x", &num, &val);
1730 if (nval != 2)
1731 return -EINVAL;
1732
1733 if (num >= TPDM_BC_MAX_MSR)
1734 return -EINVAL;
1735
1736 mutex_lock(&drvdata->lock);
1737 drvdata->bc->msr[num] = val;
1738 mutex_unlock(&drvdata->lock);
1739 return size;
1740}
Satyajit Desaib34b2c02017-01-11 16:59:38 -08001741static DEVICE_ATTR(bc_msr, 0644, tpdm_show_bc_msr, tpdm_store_bc_msr);
Satyajit Desaif151d682016-09-12 16:18:03 -07001742
1743static ssize_t tpdm_show_tc_capture_mode(struct device *dev,
1744 struct device_attribute *attr,
1745 char *buf)
1746{
1747 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1748
1749 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1750 return -EPERM;
1751
1752 return scnprintf(buf, PAGE_SIZE, "%s\n",
1753 drvdata->tc->capture_mode == TPDM_MODE_ATB ?
1754 "ATB" : "APB");
1755}
1756
1757static ssize_t tpdm_store_tc_capture_mode(struct device *dev,
1758 struct device_attribute *attr,
1759 const char *buf,
1760 size_t size)
1761{
1762 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1763 char str[20] = "";
1764 uint32_t val;
1765
1766 if (size >= 20)
1767 return -EINVAL;
1768 if (sscanf(buf, "%s", str) != 1)
1769 return -EINVAL;
1770 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
1771 return -EPERM;
1772
1773 mutex_lock(&drvdata->lock);
1774 if (!drvdata->enable) {
1775 mutex_unlock(&drvdata->lock);
1776 return -EPERM;
1777 }
1778
1779 if (!strcmp(str, "ATB")) {
1780 drvdata->tc->capture_mode = TPDM_MODE_ATB;
1781 } else if (!strcmp(str, "APB") &&
1782 drvdata->tc->retrieval_mode == TPDM_MODE_APB) {
1783
1784 TPDM_UNLOCK(drvdata);
1785 val = tpdm_readl(drvdata, TPDM_TC_CR);
1786 val = val | BIT(3);
1787 tpdm_writel(drvdata, val, TPDM_TC_CR);
1788 TPDM_LOCK(drvdata);
1789
1790 drvdata->tc->capture_mode = TPDM_MODE_APB;
1791 } else {
1792 mutex_unlock(&drvdata->lock);
1793 return -EINVAL;
1794 }
1795 mutex_unlock(&drvdata->lock);
1796 return size;
1797}
Satyajit Desai326497c2016-11-14 10:15:03 -08001798static DEVICE_ATTR(tc_capture_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001799 tpdm_show_tc_capture_mode, tpdm_store_tc_capture_mode);
1800
1801static ssize_t tpdm_show_tc_retrieval_mode(struct device *dev,
1802 struct device_attribute *attr,
1803 char *buf)
1804{
1805 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1806
1807 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1808 return -EPERM;
1809
1810 return scnprintf(buf, PAGE_SIZE, "%s\n",
1811 drvdata->tc->retrieval_mode == TPDM_MODE_ATB ?
1812 "ATB" : "APB");
1813}
1814
1815static ssize_t tpdm_store_tc_retrieval_mode(struct device *dev,
1816 struct device_attribute *attr,
1817 const char *buf,
1818 size_t size)
1819{
1820 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1821 char str[20] = "";
1822
1823 if (size >= 20)
1824 return -EINVAL;
1825 if (sscanf(buf, "%s", str) != 1)
1826 return -EINVAL;
1827 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1828 return -EPERM;
1829
1830 mutex_lock(&drvdata->lock);
1831 if (drvdata->enable) {
1832 mutex_unlock(&drvdata->lock);
1833 return -EPERM;
1834 }
1835
1836 if (!strcmp(str, "ATB")) {
1837 drvdata->tc->retrieval_mode = TPDM_MODE_ATB;
1838 } else if (!strcmp(str, "APB")) {
1839 drvdata->tc->retrieval_mode = TPDM_MODE_APB;
1840 } else {
1841 mutex_unlock(&drvdata->lock);
1842 return -EINVAL;
1843 }
1844 mutex_unlock(&drvdata->lock);
1845 return size;
1846}
Satyajit Desai326497c2016-11-14 10:15:03 -08001847static DEVICE_ATTR(tc_retrieval_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001848 tpdm_show_tc_retrieval_mode, tpdm_store_tc_retrieval_mode);
1849
1850static ssize_t tpdm_store_tc_reset_counters(struct device *dev,
1851 struct device_attribute *attr,
1852 const char *buf,
1853 size_t size)
1854{
1855 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1856 unsigned long val;
1857
1858 if (kstrtoul(buf, 16, &val))
1859 return -EINVAL;
1860 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1861 return -EPERM;
1862
1863 mutex_lock(&drvdata->lock);
1864 if (!drvdata->enable) {
1865 mutex_unlock(&drvdata->lock);
1866 return -EPERM;
1867 }
1868
1869 if (val) {
1870 TPDM_UNLOCK(drvdata);
1871 val = tpdm_readl(drvdata, TPDM_TC_CR);
1872 val = val | BIT(1);
1873 tpdm_writel(drvdata, val, TPDM_TC_CR);
1874 TPDM_LOCK(drvdata);
1875 }
1876 mutex_unlock(&drvdata->lock);
1877 return size;
1878}
Satyajit Desai326497c2016-11-14 10:15:03 -08001879static DEVICE_ATTR(tc_reset_counters, 0644, NULL,
Satyajit Desaif151d682016-09-12 16:18:03 -07001880 tpdm_store_tc_reset_counters);
1881
1882static ssize_t tpdm_show_tc_sat_mode(struct device *dev,
1883 struct device_attribute *attr,
1884 char *buf)
1885{
1886 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1887
1888 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1889 return -EPERM;
1890
1891 return scnprintf(buf, PAGE_SIZE, "%u\n",
1892 (unsigned int)drvdata->tc->sat_mode);
1893}
1894
1895static ssize_t tpdm_store_tc_sat_mode(struct device *dev,
1896 struct device_attribute *attr,
1897 const char *buf,
1898 size_t size)
1899{
1900 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1901 unsigned long val;
1902
1903 if (kstrtoul(buf, 16, &val))
1904 return -EINVAL;
1905 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1906 return -EPERM;
1907
1908 mutex_lock(&drvdata->lock);
1909 if (val)
1910 drvdata->tc->sat_mode = true;
1911 else
1912 drvdata->tc->sat_mode = false;
1913 mutex_unlock(&drvdata->lock);
1914 return size;
1915}
Satyajit Desai326497c2016-11-14 10:15:03 -08001916static DEVICE_ATTR(tc_sat_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001917 tpdm_show_tc_sat_mode, tpdm_store_tc_sat_mode);
1918
1919static ssize_t tpdm_show_tc_enable_counters(struct device *dev,
1920 struct device_attribute *attr,
1921 char *buf)
1922{
1923 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1924
1925 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1926 return -EPERM;
1927
1928 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1929 (unsigned long)drvdata->tc->enable_counters);
1930}
1931
1932static ssize_t tpdm_store_tc_enable_counters(struct device *dev,
1933 struct device_attribute *attr,
1934 const char *buf,
1935 size_t size)
1936{
1937 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1938 unsigned long val;
1939
1940 if (kstrtoul(buf, 16, &val))
1941 return -EINVAL;
1942 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1943 return -EPERM;
1944 if (val >> drvdata->tc_counters_avail)
1945 return -EPERM;
1946
1947 mutex_lock(&drvdata->lock);
1948 drvdata->tc->enable_counters = val;
1949 mutex_unlock(&drvdata->lock);
1950 return size;
1951}
Satyajit Desai326497c2016-11-14 10:15:03 -08001952static DEVICE_ATTR(tc_enable_counters, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001953 tpdm_show_tc_enable_counters, tpdm_store_tc_enable_counters);
1954
1955static ssize_t tpdm_show_tc_clear_counters(struct device *dev,
1956 struct device_attribute *attr,
1957 char *buf)
1958{
1959 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1960
1961 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1962 return -EPERM;
1963
1964 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1965 (unsigned long)drvdata->tc->clear_counters);
1966}
1967
1968static ssize_t tpdm_store_tc_clear_counters(struct device *dev,
1969 struct device_attribute *attr,
1970 const char *buf,
1971 size_t size)
1972{
1973 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1974 unsigned long val;
1975
1976 if (kstrtoul(buf, 16, &val))
1977 return -EINVAL;
1978 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1979 return -EPERM;
1980 if (val >> drvdata->tc_counters_avail)
1981 return -EPERM;
1982
1983 mutex_lock(&drvdata->lock);
1984 drvdata->tc->clear_counters = val;
1985 mutex_unlock(&drvdata->lock);
1986 return size;
1987}
Satyajit Desai326497c2016-11-14 10:15:03 -08001988static DEVICE_ATTR(tc_clear_counters, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001989 tpdm_show_tc_clear_counters, tpdm_store_tc_clear_counters);
1990
1991static ssize_t tpdm_show_tc_enable_irq(struct device *dev,
1992 struct device_attribute *attr,
1993 char *buf)
1994{
1995 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1996
1997 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1998 return -EPERM;
1999
2000 return scnprintf(buf, PAGE_SIZE, "%lx\n",
2001 (unsigned long)drvdata->tc->enable_irq);
2002}
2003
2004static ssize_t tpdm_store_tc_enable_irq(struct device *dev,
2005 struct device_attribute *attr,
2006 const char *buf,
2007 size_t size)
2008{
2009 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2010 unsigned long val;
2011
2012 if (kstrtoul(buf, 16, &val))
2013 return -EINVAL;
2014 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2015 return -EPERM;
2016
2017 mutex_lock(&drvdata->lock);
2018 drvdata->tc->enable_irq = val;
2019 mutex_unlock(&drvdata->lock);
2020 return size;
2021}
Satyajit Desai326497c2016-11-14 10:15:03 -08002022static DEVICE_ATTR(tc_enable_irq, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002023 tpdm_show_tc_enable_irq, tpdm_store_tc_enable_irq);
2024
2025static ssize_t tpdm_show_tc_clear_irq(struct device *dev,
2026 struct device_attribute *attr,
2027 char *buf)
2028{
2029 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2030
2031 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2032 return -EPERM;
2033
2034 return scnprintf(buf, PAGE_SIZE, "%lx\n",
2035 (unsigned long)drvdata->tc->clear_irq);
2036}
2037
2038static ssize_t tpdm_store_tc_clear_irq(struct device *dev,
2039 struct device_attribute *attr,
2040 const char *buf,
2041 size_t size)
2042{
2043 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2044 unsigned long val;
2045
2046 if (kstrtoul(buf, 16, &val))
2047 return -EINVAL;
2048 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2049 return -EPERM;
2050
2051 mutex_lock(&drvdata->lock);
2052 drvdata->tc->clear_irq = val;
2053 mutex_unlock(&drvdata->lock);
2054 return size;
2055}
Satyajit Desai326497c2016-11-14 10:15:03 -08002056static DEVICE_ATTR(tc_clear_irq, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002057 tpdm_show_tc_clear_irq, tpdm_store_tc_clear_irq);
2058
2059static ssize_t tpdm_show_tc_trig_sel(struct device *dev,
2060 struct device_attribute *attr,
2061 char *buf)
2062{
2063 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2064 ssize_t size = 0;
2065 int i = 0;
2066
2067 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2068 return -EPERM;
2069
2070 mutex_lock(&drvdata->lock);
2071 for (i = 0; i < TPDM_TC_MAX_TRIG; i++) {
2072 size += scnprintf(buf + size, PAGE_SIZE - size,
2073 "Index: 0x%x Value: 0x%x\n", i,
2074 drvdata->tc->trig_sel[i]);
2075 }
2076 mutex_unlock(&drvdata->lock);
2077 return size;
2078}
2079
2080static ssize_t tpdm_store_tc_trig_sel(struct device *dev,
2081 struct device_attribute *attr,
2082 const char *buf,
2083 size_t size)
2084{
2085 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2086 unsigned long index, val;
2087
2088 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2089 return -EINVAL;
2090 if (!test_bit(TPDM_DS_TC, drvdata->datasets) ||
2091 index >= TPDM_TC_MAX_TRIG ||
2092 drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_NO ||
2093 (drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL && index > 0))
2094 return -EPERM;
2095
2096 mutex_lock(&drvdata->lock);
2097 drvdata->tc->trig_sel[index] = val;
2098 mutex_unlock(&drvdata->lock);
2099 return size;
2100}
Satyajit Desai326497c2016-11-14 10:15:03 -08002101static DEVICE_ATTR(tc_trig_sel, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002102 tpdm_show_tc_trig_sel, tpdm_store_tc_trig_sel);
2103
2104static ssize_t tpdm_show_tc_trig_val_lo(struct device *dev,
2105 struct device_attribute *attr,
2106 char *buf)
2107{
2108 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2109 ssize_t size = 0;
2110 int i = 0;
2111
2112 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2113 return -EPERM;
2114
2115 mutex_lock(&drvdata->lock);
2116 for (i = 0; i < TPDM_TC_MAX_TRIG; i++) {
2117 size += scnprintf(buf + size, PAGE_SIZE - size,
2118 "Index: 0x%x Value: 0x%x\n", i,
2119 drvdata->tc->trig_val_lo[i]);
2120 }
2121 mutex_unlock(&drvdata->lock);
2122 return size;
2123}
2124
2125static ssize_t tpdm_store_tc_trig_val_lo(struct device *dev,
2126 struct device_attribute *attr,
2127 const char *buf,
2128 size_t size)
2129{
2130 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2131 unsigned long index, val;
2132
2133 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2134 return -EINVAL;
2135 if (!test_bit(TPDM_DS_TC, drvdata->datasets) ||
2136 index >= TPDM_TC_MAX_TRIG ||
2137 drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_NO ||
2138 (drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL && index > 0))
2139 return -EPERM;
2140
2141 mutex_lock(&drvdata->lock);
2142 drvdata->tc->trig_val_lo[index] = val;
2143 mutex_unlock(&drvdata->lock);
2144 return size;
2145}
Satyajit Desai326497c2016-11-14 10:15:03 -08002146static DEVICE_ATTR(tc_trig_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002147 tpdm_show_tc_trig_val_lo, tpdm_store_tc_trig_val_lo);
2148
2149static ssize_t tpdm_show_tc_trig_val_hi(struct device *dev,
2150 struct device_attribute *attr,
2151 char *buf)
2152{
2153 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2154 ssize_t size = 0;
2155 int i = 0;
2156
2157 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2158 return -EPERM;
2159
2160 mutex_lock(&drvdata->lock);
2161 for (i = 0; i < TPDM_TC_MAX_TRIG; i++) {
2162 size += scnprintf(buf + size, PAGE_SIZE - size,
2163 "Index: 0x%x Value: 0x%x\n", i,
2164 drvdata->tc->trig_val_hi[i]);
2165 }
2166 mutex_unlock(&drvdata->lock);
2167 return size;
2168}
2169
2170static ssize_t tpdm_store_tc_trig_val_hi(struct device *dev,
2171 struct device_attribute *attr,
2172 const char *buf,
2173 size_t size)
2174{
2175 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2176 unsigned long index, val;
2177
2178 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2179 return -EINVAL;
2180 if (!test_bit(TPDM_DS_TC, drvdata->datasets) ||
2181 index >= TPDM_TC_MAX_TRIG ||
2182 drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_NO ||
2183 (drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL && index > 0))
2184 return -EPERM;
2185
2186 mutex_lock(&drvdata->lock);
2187 drvdata->tc->trig_val_hi[index] = val;
2188 mutex_unlock(&drvdata->lock);
2189 return size;
2190}
Satyajit Desai326497c2016-11-14 10:15:03 -08002191static DEVICE_ATTR(tc_trig_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002192 tpdm_show_tc_trig_val_hi, tpdm_store_tc_trig_val_hi);
2193
2194static ssize_t tpdm_show_tc_ovsr_gp(struct device *dev,
2195 struct device_attribute *attr,
2196 char *buf)
2197{
2198 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2199 unsigned long val;
2200
2201 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2202 return -EPERM;
2203
2204 mutex_lock(&drvdata->lock);
2205 if (!drvdata->enable) {
2206 mutex_unlock(&drvdata->lock);
2207 return -EPERM;
2208 }
2209
2210 TPDM_UNLOCK(drvdata);
2211 val = tpdm_readl(drvdata, TPDM_TC_OVSR_GP);
2212 TPDM_LOCK(drvdata);
2213 mutex_unlock(&drvdata->lock);
2214 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2215}
2216
2217static ssize_t tpdm_store_tc_ovsr_gp(struct device *dev,
2218 struct device_attribute *attr,
2219 const char *buf,
2220 size_t size)
2221{
2222 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2223 unsigned long val;
2224
2225 if (kstrtoul(buf, 16, &val))
2226 return -EINVAL;
2227 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2228 return -EPERM;
2229
2230 mutex_lock(&drvdata->lock);
2231 if (!drvdata->enable) {
2232 mutex_unlock(&drvdata->lock);
2233 return -EPERM;
2234 }
2235
2236 if (val) {
2237 TPDM_UNLOCK(drvdata);
2238 tpdm_writel(drvdata, val, TPDM_TC_OVSR_GP);
2239 TPDM_LOCK(drvdata);
2240 }
2241 mutex_unlock(&drvdata->lock);
2242 return size;
2243}
Satyajit Desai326497c2016-11-14 10:15:03 -08002244static DEVICE_ATTR(tc_ovsr_gp, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002245 tpdm_show_tc_ovsr_gp, tpdm_store_tc_ovsr_gp);
2246
2247static ssize_t tpdm_show_tc_ovsr_impl(struct device *dev,
2248 struct device_attribute *attr,
2249 char *buf)
2250{
2251 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2252 unsigned long val;
2253
2254 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2255 return -EPERM;
2256
2257 mutex_lock(&drvdata->lock);
2258 if (!drvdata->enable) {
2259 mutex_unlock(&drvdata->lock);
2260 return -EPERM;
2261 }
2262
2263 TPDM_UNLOCK(drvdata);
2264 val = tpdm_readl(drvdata, TPDM_TC_OVSR_IMPL);
2265 TPDM_LOCK(drvdata);
2266 mutex_unlock(&drvdata->lock);
2267 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2268}
2269
2270static ssize_t tpdm_store_tc_ovsr_impl(struct device *dev,
2271 struct device_attribute *attr,
2272 const char *buf,
2273 size_t size)
2274{
2275 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2276 unsigned long val;
2277
2278 if (kstrtoul(buf, 16, &val))
2279 return -EINVAL;
2280 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2281 return -EPERM;
2282
2283 mutex_lock(&drvdata->lock);
2284 if (!drvdata->enable) {
2285 mutex_unlock(&drvdata->lock);
2286 return -EPERM;
2287 }
2288
2289 if (val) {
2290 TPDM_UNLOCK(drvdata);
2291 tpdm_writel(drvdata, val, TPDM_TC_OVSR_IMPL);
2292 TPDM_LOCK(drvdata);
2293 }
2294 mutex_unlock(&drvdata->lock);
2295 return size;
2296}
Satyajit Desai326497c2016-11-14 10:15:03 -08002297static DEVICE_ATTR(tc_ovsr_impl, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002298 tpdm_show_tc_ovsr_impl, tpdm_store_tc_ovsr_impl);
2299
2300static ssize_t tpdm_show_tc_counter_sel(struct device *dev,
2301 struct device_attribute *attr,
2302 char *buf)
2303{
2304 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2305 unsigned long val;
2306
2307 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2308 return -EPERM;
2309
2310 mutex_lock(&drvdata->lock);
2311 if (!drvdata->enable) {
2312 mutex_unlock(&drvdata->lock);
2313 return -EPERM;
2314 }
2315
2316 TPDM_UNLOCK(drvdata);
2317 val = tpdm_readl(drvdata, TPDM_TC_SELR);
2318 TPDM_LOCK(drvdata);
2319 mutex_unlock(&drvdata->lock);
2320 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2321}
2322
2323static ssize_t tpdm_store_tc_counter_sel(struct device *dev,
2324 struct device_attribute *attr,
2325 const char *buf,
2326 size_t size)
2327{
2328 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2329 unsigned long val;
2330
2331 if (kstrtoul(buf, 16, &val))
2332 return -EINVAL;
2333 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2334 return -EPERM;
2335
2336 mutex_lock(&drvdata->lock);
2337 if (!drvdata->enable) {
2338 mutex_unlock(&drvdata->lock);
2339 return -EPERM;
2340 }
2341
2342 TPDM_UNLOCK(drvdata);
2343 tpdm_writel(drvdata, val, TPDM_TC_SELR);
2344 TPDM_LOCK(drvdata);
2345 mutex_unlock(&drvdata->lock);
2346 return size;
2347}
Satyajit Desai326497c2016-11-14 10:15:03 -08002348static DEVICE_ATTR(tc_counter_sel, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002349 tpdm_show_tc_counter_sel, tpdm_store_tc_counter_sel);
2350
2351static ssize_t tpdm_show_tc_count_val_lo(struct device *dev,
2352 struct device_attribute *attr,
2353 char *buf)
2354{
2355 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2356 unsigned long val;
2357
2358 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2359 return -EPERM;
2360
2361 mutex_lock(&drvdata->lock);
2362 if (!drvdata->enable) {
2363 mutex_unlock(&drvdata->lock);
2364 return -EPERM;
2365 }
2366
2367 TPDM_UNLOCK(drvdata);
2368 val = tpdm_readl(drvdata, TPDM_TC_CNTR_LO);
2369 TPDM_LOCK(drvdata);
2370 mutex_unlock(&drvdata->lock);
2371 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2372}
2373
2374static ssize_t tpdm_store_tc_count_val_lo(struct device *dev,
2375 struct device_attribute *attr,
2376 const char *buf,
2377 size_t size)
2378{
2379 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2380 unsigned long val, select;
2381
2382 if (kstrtoul(buf, 16, &val))
2383 return -EINVAL;
2384 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2385 return -EPERM;
2386
2387 mutex_lock(&drvdata->lock);
2388 if (!drvdata->enable) {
2389 mutex_unlock(&drvdata->lock);
2390 return -EPERM;
2391 }
2392
2393 if (val) {
2394 TPDM_UNLOCK(drvdata);
2395 select = tpdm_readl(drvdata, TPDM_TC_SELR);
2396 select = (select >> 11) & 0x3;
2397
2398 /* Check if selected counter is disabled */
2399 if (BVAL(tpdm_readl(drvdata, TPDM_TC_CNTENSET), select)) {
2400 mutex_unlock(&drvdata->lock);
2401 return -EPERM;
2402 }
2403
2404 tpdm_writel(drvdata, val, TPDM_TC_CNTR_LO);
2405 TPDM_LOCK(drvdata);
2406 }
2407 mutex_unlock(&drvdata->lock);
2408 return size;
2409}
Satyajit Desai326497c2016-11-14 10:15:03 -08002410static DEVICE_ATTR(tc_count_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002411 tpdm_show_tc_count_val_lo, tpdm_store_tc_count_val_lo);
2412
2413static ssize_t tpdm_show_tc_count_val_hi(struct device *dev,
2414 struct device_attribute *attr,
2415 char *buf)
2416{
2417 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2418 unsigned long val;
2419
2420 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2421 return -EPERM;
2422
2423 mutex_lock(&drvdata->lock);
2424 if (!drvdata->enable) {
2425 mutex_unlock(&drvdata->lock);
2426 return -EPERM;
2427 }
2428
2429 TPDM_UNLOCK(drvdata);
2430 val = tpdm_readl(drvdata, TPDM_TC_CNTR_HI);
2431 TPDM_LOCK(drvdata);
2432 mutex_unlock(&drvdata->lock);
2433 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2434}
2435
2436static ssize_t tpdm_store_tc_count_val_hi(struct device *dev,
2437 struct device_attribute *attr,
2438 const char *buf,
2439 size_t size)
2440{
2441 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2442 unsigned long val, select;
2443
2444 if (kstrtoul(buf, 16, &val))
2445 return -EINVAL;
2446 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2447 return -EPERM;
2448
2449 mutex_lock(&drvdata->lock);
2450 if (!drvdata->enable) {
2451 mutex_unlock(&drvdata->lock);
2452 return -EPERM;
2453 }
2454
2455 if (val) {
2456 TPDM_UNLOCK(drvdata);
2457 select = tpdm_readl(drvdata, TPDM_TC_SELR);
2458 select = (select >> 11) & 0x3;
2459
2460 /* Check if selected counter is disabled */
2461 if (BVAL(tpdm_readl(drvdata, TPDM_TC_CNTENSET), select)) {
2462 mutex_unlock(&drvdata->lock);
2463 return -EPERM;
2464 }
2465
2466 tpdm_writel(drvdata, val, TPDM_TC_CNTR_HI);
2467 TPDM_LOCK(drvdata);
2468 }
2469 mutex_unlock(&drvdata->lock);
2470 return size;
2471}
Satyajit Desai326497c2016-11-14 10:15:03 -08002472static DEVICE_ATTR(tc_count_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002473 tpdm_show_tc_count_val_hi, tpdm_store_tc_count_val_hi);
2474
2475static ssize_t tpdm_show_tc_shadow_val_lo(struct device *dev,
2476 struct device_attribute *attr,
2477 char *buf)
2478{
2479 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2480 ssize_t size = 0;
2481 int i = 0;
2482
2483 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2484 return -EPERM;
2485
2486 mutex_lock(&drvdata->lock);
2487 if (!drvdata->enable) {
2488 mutex_unlock(&drvdata->lock);
2489 return -EPERM;
2490 }
2491
2492 TPDM_UNLOCK(drvdata);
2493 for (i = 0; i < TPDM_TC_MAX_COUNTERS; i++) {
2494 size += scnprintf(buf + size, PAGE_SIZE - size,
2495 "Index: 0x%x Value: 0x%x\n", i,
2496 tpdm_readl(drvdata, TPDM_TC_SHADOW_LO(i)));
2497 }
2498 TPDM_LOCK(drvdata);
2499 mutex_unlock(&drvdata->lock);
2500 return size;
2501}
Satyajit Desai326497c2016-11-14 10:15:03 -08002502static DEVICE_ATTR(tc_shadow_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002503 tpdm_show_tc_shadow_val_lo, NULL);
2504
2505static ssize_t tpdm_show_tc_shadow_val_hi(struct device *dev,
2506 struct device_attribute *attr,
2507 char *buf)
2508{
2509 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2510 ssize_t size = 0;
2511 int i = 0;
2512
2513 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2514 return -EPERM;
2515
2516 mutex_lock(&drvdata->lock);
2517 if (!drvdata->enable) {
2518 mutex_unlock(&drvdata->lock);
2519 return -EPERM;
2520 }
2521
2522 TPDM_UNLOCK(drvdata);
2523 for (i = 0; i < TPDM_TC_MAX_COUNTERS; i++) {
2524 size += scnprintf(buf + size, PAGE_SIZE - size,
2525 "Index: 0x%x Value: 0x%x\n", i,
2526 tpdm_readl(drvdata, TPDM_TC_SHADOW_HI(i)));
2527 }
2528 TPDM_LOCK(drvdata);
2529 mutex_unlock(&drvdata->lock);
2530 return size;
2531}
Satyajit Desai326497c2016-11-14 10:15:03 -08002532static DEVICE_ATTR(tc_shadow_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002533 tpdm_show_tc_shadow_val_hi, NULL);
2534
2535static ssize_t tpdm_show_tc_sw_inc(struct device *dev,
2536 struct device_attribute *attr,
2537 char *buf)
2538{
2539 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2540 unsigned long val;
2541
2542 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2543 return -EPERM;
2544
2545 mutex_lock(&drvdata->lock);
2546 if (!drvdata->enable) {
2547 mutex_unlock(&drvdata->lock);
2548 return -EPERM;
2549 }
2550
2551 TPDM_UNLOCK(drvdata);
2552 val = tpdm_readl(drvdata, TPDM_TC_SWINC);
2553 TPDM_LOCK(drvdata);
2554 mutex_unlock(&drvdata->lock);
2555 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2556}
2557
2558static ssize_t tpdm_store_tc_sw_inc(struct device *dev,
2559 struct device_attribute *attr,
2560 const char *buf,
2561 size_t size)
2562{
2563 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2564 unsigned long val;
2565
2566 if (kstrtoul(buf, 16, &val))
2567 return -EINVAL;
2568 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2569 return -EPERM;
2570
2571 mutex_lock(&drvdata->lock);
2572 if (!drvdata->enable) {
2573 mutex_unlock(&drvdata->lock);
2574 return -EPERM;
2575 }
2576
2577 if (val) {
2578 TPDM_UNLOCK(drvdata);
2579 tpdm_writel(drvdata, val, TPDM_TC_SWINC);
2580 TPDM_LOCK(drvdata);
2581 }
2582 mutex_unlock(&drvdata->lock);
2583 return size;
2584}
Satyajit Desai326497c2016-11-14 10:15:03 -08002585static DEVICE_ATTR(tc_sw_inc, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002586 tpdm_show_tc_sw_inc, tpdm_store_tc_sw_inc);
2587
Satyajit Desaib34b2c02017-01-11 16:59:38 -08002588static ssize_t tpdm_show_tc_msr(struct device *dev,
2589 struct device_attribute *attr,
2590 char *buf)
2591{
2592 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2593 unsigned int i;
2594 ssize_t len = 0;
2595
2596 if (!drvdata->msr_support)
2597 return -EINVAL;
2598
2599 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2600 return -EPERM;
2601
2602 for (i = 0; i < TPDM_TC_MAX_MSR; i++)
2603 len += scnprintf(buf + len, PAGE_SIZE - len, "%u 0x%x\n",
2604 i, drvdata->tc->msr[i]);
2605
2606 return len;
2607}
2608
Satyajit Desaif151d682016-09-12 16:18:03 -07002609static ssize_t tpdm_store_tc_msr(struct device *dev,
2610 struct device_attribute *attr,
2611 const char *buf,
2612 size_t size)
2613{
2614 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2615 unsigned int num, val;
2616 int nval;
2617
2618 if (!drvdata->msr_support)
2619 return -EINVAL;
2620
2621 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2622 return -EPERM;
2623
2624 nval = sscanf(buf, "%u %x", &num, &val);
2625 if (nval != 2)
2626 return -EINVAL;
2627
2628 if (num >= TPDM_TC_MAX_MSR)
2629 return -EINVAL;
2630
2631 mutex_lock(&drvdata->lock);
2632 drvdata->tc->msr[num] = val;
2633 mutex_unlock(&drvdata->lock);
2634 return size;
2635}
Satyajit Desaib34b2c02017-01-11 16:59:38 -08002636static DEVICE_ATTR(tc_msr, 0644, tpdm_show_tc_msr, tpdm_store_tc_msr);
Satyajit Desaif151d682016-09-12 16:18:03 -07002637
2638static ssize_t tpdm_show_dsb_mode(struct device *dev,
2639 struct device_attribute *attr,
2640 char *buf)
2641{
2642 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2643
2644 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2645 return -EPERM;
2646
2647 return scnprintf(buf, PAGE_SIZE, "%lx\n",
2648 (unsigned long)drvdata->dsb->mode);
2649}
2650
2651static ssize_t tpdm_store_dsb_mode(struct device *dev,
2652 struct device_attribute *attr,
2653 const char *buf,
2654 size_t size)
2655{
2656 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2657 unsigned long val;
2658
2659 if (kstrtoul(buf, 16, &val))
2660 return -EINVAL;
2661 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2662 return -EPERM;
2663
2664 mutex_lock(&drvdata->lock);
2665 drvdata->dsb->mode = val & TPDM_MODE_ALL;
2666 mutex_unlock(&drvdata->lock);
2667 return size;
2668}
Satyajit Desai326497c2016-11-14 10:15:03 -08002669static DEVICE_ATTR(dsb_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002670 tpdm_show_dsb_mode, tpdm_store_dsb_mode);
2671
2672static ssize_t tpdm_show_dsb_edge_ctrl(struct device *dev,
2673 struct device_attribute *attr,
2674 char *buf)
2675{
2676 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2677 ssize_t size = 0;
2678 int i;
2679
2680 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2681 return -EPERM;
2682
2683 mutex_lock(&drvdata->lock);
2684 for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) {
2685 size += scnprintf(buf + size, PAGE_SIZE - size,
2686 "Index:0x%x Val:0x%x\n", i,
2687 drvdata->dsb->edge_ctrl[i]);
2688 }
2689 mutex_unlock(&drvdata->lock);
2690 return size;
2691}
2692
2693static ssize_t tpdm_store_dsb_edge_ctrl(struct device *dev,
2694 struct device_attribute *attr,
2695 const char *buf,
2696 size_t size)
2697{
2698 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2699 unsigned long start, end, edge_ctrl;
2700 uint32_t val;
2701 int i, bit, reg;
2702
2703 if (sscanf(buf, "%lx %lx %lx", &start, &end, &edge_ctrl) != 3)
2704 return -EINVAL;
2705 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
2706 (start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES) ||
2707 edge_ctrl > 0x2)
2708 return -EPERM;
2709
2710 mutex_lock(&drvdata->lock);
2711 for (i = start; i <= end; i++) {
2712 reg = i / (NUM_OF_BITS / 2);
2713 bit = i % (NUM_OF_BITS / 2);
2714 bit = bit * 2;
2715
2716 val = drvdata->dsb->edge_ctrl[reg];
2717 val = val | (edge_ctrl << bit);
2718 drvdata->dsb->edge_ctrl[reg] = val;
2719 }
2720 mutex_unlock(&drvdata->lock);
2721 return size;
2722}
Satyajit Desai326497c2016-11-14 10:15:03 -08002723static DEVICE_ATTR(dsb_edge_ctrl, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002724 tpdm_show_dsb_edge_ctrl, tpdm_store_dsb_edge_ctrl);
2725
2726static ssize_t tpdm_show_dsb_edge_ctrl_mask(struct device *dev,
2727 struct device_attribute *attr,
2728 char *buf)
2729{
2730 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2731 ssize_t size = 0;
2732 int i;
2733
2734 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2735 return -EPERM;
2736
2737 mutex_lock(&drvdata->lock);
2738 for (i = 0; i < TPDM_DSB_MAX_EDCR / 2; i++) {
2739 size += scnprintf(buf + size, PAGE_SIZE - size,
2740 "Index:0x%x Val:0x%x\n", i,
2741 drvdata->dsb->edge_ctrl_mask[i]);
2742 }
2743 mutex_unlock(&drvdata->lock);
2744 return size;
2745}
2746
2747static ssize_t tpdm_store_dsb_edge_ctrl_mask(struct device *dev,
2748 struct device_attribute *attr,
2749 const char *buf,
2750 size_t size)
2751{
2752 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2753 unsigned long start, end, val;
2754 uint32_t set;
2755 int i, bit, reg;
2756
2757 if (sscanf(buf, "%lx %lx %lx", &start, &end, &val) != 3)
2758 return -EINVAL;
2759 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
2760 (start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES))
2761 return -EPERM;
2762
2763 mutex_lock(&drvdata->lock);
2764 for (i = start; i <= end; i++) {
2765 reg = i / NUM_OF_BITS;
2766 bit = (i % NUM_OF_BITS);
2767
2768 set = drvdata->dsb->edge_ctrl_mask[reg];
2769 if (val)
2770 set = set | BIT(bit);
2771 else
2772 set = set & ~BIT(bit);
2773 drvdata->dsb->edge_ctrl_mask[reg] = set;
2774 }
2775 mutex_unlock(&drvdata->lock);
2776 return size;
2777}
Satyajit Desai326497c2016-11-14 10:15:03 -08002778static DEVICE_ATTR(dsb_edge_ctrl_mask, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002779 tpdm_show_dsb_edge_ctrl_mask, tpdm_store_dsb_edge_ctrl_mask);
2780
2781static ssize_t tpdm_show_dsb_patt_val(struct device *dev,
2782 struct device_attribute *attr,
2783 char *buf)
2784{
2785 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2786 ssize_t size = 0;
2787 int i = 0;
2788
2789 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2790 return -EPERM;
2791
2792 mutex_lock(&drvdata->lock);
2793 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
2794 size += scnprintf(buf + size, PAGE_SIZE - size,
2795 "Index: 0x%x Value: 0x%x\n", i,
2796 drvdata->dsb->patt_val[i]);
2797 }
2798 mutex_unlock(&drvdata->lock);
2799 return size;
2800}
2801
2802static ssize_t tpdm_store_dsb_patt_val(struct device *dev,
2803 struct device_attribute *attr,
2804 const char *buf,
2805 size_t size)
2806{
2807 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2808 unsigned long index, val;
2809
2810 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2811 return -EINVAL;
2812 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
2813 index >= TPDM_DSB_MAX_PATT)
2814 return -EPERM;
2815
2816 mutex_lock(&drvdata->lock);
2817 drvdata->dsb->patt_val[index] = val;
2818 mutex_unlock(&drvdata->lock);
2819 return size;
2820}
Satyajit Desai326497c2016-11-14 10:15:03 -08002821static DEVICE_ATTR(dsb_patt_val, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002822 tpdm_show_dsb_patt_val, tpdm_store_dsb_patt_val);
2823
2824static ssize_t tpdm_show_dsb_patt_mask(struct device *dev,
2825 struct device_attribute *attr,
2826 char *buf)
2827{
2828 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2829 ssize_t size = 0;
2830 int i = 0;
2831
2832 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2833 return -EPERM;
2834
2835 mutex_lock(&drvdata->lock);
2836 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
2837 size += scnprintf(buf + size, PAGE_SIZE - size,
2838 "Index: 0x%x Value: 0x%x\n", i,
2839 drvdata->dsb->patt_mask[i]);
2840 }
2841 mutex_unlock(&drvdata->lock);
2842 return size;
2843}
2844
2845static ssize_t tpdm_store_dsb_patt_mask(struct device *dev,
2846 struct device_attribute *attr,
2847 const char *buf,
2848 size_t size)
2849{
2850 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2851 unsigned long index, val;
2852
2853 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2854 return -EINVAL;
2855 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
2856 index >= TPDM_DSB_MAX_PATT)
2857 return -EPERM;
2858
2859 mutex_lock(&drvdata->lock);
2860 drvdata->dsb->patt_mask[index] = val;
2861 mutex_unlock(&drvdata->lock);
2862 return size;
2863}
Satyajit Desai326497c2016-11-14 10:15:03 -08002864static DEVICE_ATTR(dsb_patt_mask, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002865 tpdm_show_dsb_patt_mask, tpdm_store_dsb_patt_mask);
2866
2867static ssize_t tpdm_show_dsb_patt_ts(struct device *dev,
2868 struct device_attribute *attr,
2869 char *buf)
2870{
2871 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2872
2873 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2874 return -EPERM;
2875
2876 return scnprintf(buf, PAGE_SIZE, "%u\n",
2877 (unsigned int)drvdata->dsb->patt_ts);
2878}
2879
2880static ssize_t tpdm_store_dsb_patt_ts(struct device *dev,
2881 struct device_attribute *attr,
2882 const char *buf,
2883 size_t size)
2884{
2885 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2886 unsigned long val;
2887
2888 if (kstrtoul(buf, 16, &val))
2889 return -EINVAL;
2890 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2891 return -EPERM;
2892
2893 mutex_lock(&drvdata->lock);
2894 if (val)
2895 drvdata->dsb->patt_ts = true;
2896 else
2897 drvdata->dsb->patt_ts = false;
2898 mutex_unlock(&drvdata->lock);
2899 return size;
2900}
Satyajit Desai326497c2016-11-14 10:15:03 -08002901static DEVICE_ATTR(dsb_patt_ts, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002902 tpdm_show_dsb_patt_ts, tpdm_store_dsb_patt_ts);
2903
2904static ssize_t tpdm_show_dsb_patt_type(struct device *dev,
2905 struct device_attribute *attr, char *buf)
2906{
2907 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2908
2909 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2910 return -EPERM;
2911
2912 return scnprintf(buf, PAGE_SIZE, "%u\n",
2913 (unsigned int)drvdata->dsb->patt_type);
2914}
2915
2916static ssize_t tpdm_store_dsb_patt_type(struct device *dev,
2917 struct device_attribute *attr,
2918 const char *buf, size_t size)
2919{
2920 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2921 unsigned long val;
2922
2923 if (kstrtoul(buf, 16, &val))
2924 return -EINVAL;
2925 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2926 return -EPERM;
2927
2928 mutex_lock(&drvdata->lock);
2929 if (val)
2930 drvdata->dsb->patt_type = true;
2931 else
2932 drvdata->dsb->patt_type = false;
2933 mutex_unlock(&drvdata->lock);
2934 return size;
2935}
Satyajit Desai326497c2016-11-14 10:15:03 -08002936static DEVICE_ATTR(dsb_patt_type, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002937 tpdm_show_dsb_patt_type, tpdm_store_dsb_patt_type);
2938
2939static ssize_t tpdm_show_dsb_trig_patt_val(struct device *dev,
2940 struct device_attribute *attr,
2941 char *buf)
2942{
2943 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2944 ssize_t size = 0;
2945 int i = 0;
2946
2947 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2948 return -EPERM;
2949
2950 mutex_lock(&drvdata->lock);
2951 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
2952 size += scnprintf(buf + size, PAGE_SIZE - size,
2953 "Index: 0x%x Value: 0x%x\n", i,
2954 drvdata->dsb->trig_patt_val[i]);
2955 }
2956 mutex_unlock(&drvdata->lock);
2957 return size;
2958}
2959
2960static ssize_t tpdm_store_dsb_trig_patt_val(struct device *dev,
2961 struct device_attribute *attr,
2962 const char *buf,
2963 size_t size)
2964{
2965 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2966 unsigned long index, val;
2967
2968 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2969 return -EINVAL;
2970 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
2971 index >= TPDM_DSB_MAX_PATT)
2972 return -EPERM;
2973
2974 mutex_lock(&drvdata->lock);
2975 drvdata->dsb->trig_patt_val[index] = val;
2976 mutex_unlock(&drvdata->lock);
2977 return size;
2978}
Satyajit Desai326497c2016-11-14 10:15:03 -08002979static DEVICE_ATTR(dsb_trig_patt_val, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002980 tpdm_show_dsb_trig_patt_val, tpdm_store_dsb_trig_patt_val);
2981
2982static ssize_t tpdm_show_dsb_trig_patt_mask(struct device *dev,
2983 struct device_attribute *attr,
2984 char *buf)
2985{
2986 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2987 ssize_t size = 0;
2988 int i = 0;
2989
2990 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2991 return -EPERM;
2992
2993 mutex_lock(&drvdata->lock);
2994 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
2995 size += scnprintf(buf + size, PAGE_SIZE - size,
2996 "Index: 0x%x Value: 0x%x\n", i,
2997 drvdata->dsb->trig_patt_mask[i]);
2998 }
2999 mutex_unlock(&drvdata->lock);
3000 return size;
3001}
3002
3003static ssize_t tpdm_store_dsb_trig_patt_mask(struct device *dev,
3004 struct device_attribute *attr,
3005 const char *buf,
3006 size_t size)
3007{
3008 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3009 unsigned long index, val;
3010
3011 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
3012 return -EINVAL;
3013 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
3014 index >= TPDM_DSB_MAX_PATT)
3015 return -EPERM;
3016
3017 mutex_lock(&drvdata->lock);
3018 drvdata->dsb->trig_patt_mask[index] = val;
3019 mutex_unlock(&drvdata->lock);
3020 return size;
3021}
Satyajit Desai326497c2016-11-14 10:15:03 -08003022static DEVICE_ATTR(dsb_trig_patt_mask, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003023 tpdm_show_dsb_trig_patt_mask, tpdm_store_dsb_trig_patt_mask);
3024
3025static ssize_t tpdm_show_dsb_trig_ts(struct device *dev,
3026 struct device_attribute *attr,
3027 char *buf)
3028{
3029 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3030
3031 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
3032 return -EPERM;
3033
3034 return scnprintf(buf, PAGE_SIZE, "%u\n",
3035 (unsigned int)drvdata->dsb->trig_ts);
3036}
3037
3038static ssize_t tpdm_store_dsb_trig_ts(struct device *dev,
3039 struct device_attribute *attr,
3040 const char *buf,
3041 size_t size)
3042{
3043 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3044 unsigned long val;
3045
3046 if (kstrtoul(buf, 16, &val))
3047 return -EINVAL;
3048 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
3049 return -EPERM;
3050
3051 mutex_lock(&drvdata->lock);
3052 if (val)
3053 drvdata->dsb->trig_ts = true;
3054 else
3055 drvdata->dsb->trig_ts = false;
3056 mutex_unlock(&drvdata->lock);
3057 return size;
3058}
Satyajit Desai326497c2016-11-14 10:15:03 -08003059static DEVICE_ATTR(dsb_trig_ts, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003060 tpdm_show_dsb_trig_ts, tpdm_store_dsb_trig_ts);
3061
3062static ssize_t tpdm_show_dsb_select_val(struct device *dev,
3063 struct device_attribute *attr,
3064 char *buf)
3065{
3066 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3067 ssize_t size = 0;
3068 int i;
3069
3070 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
3071 return -EPERM;
3072
3073 mutex_lock(&drvdata->lock);
3074 for (i = 0; i < TPDM_DSB_MAX_SELECT; i++) {
3075 size += scnprintf(buf + size, PAGE_SIZE - size,
3076 "Index:0x%x Val:0x%x\n", i,
3077 drvdata->dsb->select_val[i]);
3078 }
3079 mutex_unlock(&drvdata->lock);
3080 return size;
3081}
3082
3083static ssize_t tpdm_store_dsb_select_val(struct device *dev,
3084 struct device_attribute *attr,
3085 const char *buf,
3086 size_t size)
3087{
3088 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3089 unsigned long start, end;
3090 uint32_t val;
3091 int i, bit, reg;
3092
3093 if (sscanf(buf, "%lx %lx", &start, &end) != 2)
3094 return -EINVAL;
3095 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
3096 (start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES))
3097 return -EPERM;
3098
3099 mutex_lock(&drvdata->lock);
3100 for (i = start; i <= end; i++) {
3101 reg = i / NUM_OF_BITS;
3102 bit = (i % NUM_OF_BITS);
3103
3104 val = drvdata->dsb->select_val[reg];
3105 val = val | BIT(bit);
3106 drvdata->dsb->select_val[reg] = val;
3107 }
3108 mutex_unlock(&drvdata->lock);
3109 return size;
3110}
Satyajit Desai326497c2016-11-14 10:15:03 -08003111static DEVICE_ATTR(dsb_select_val, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003112 tpdm_show_dsb_select_val, tpdm_store_dsb_select_val);
3113
Satyajit Desaib34b2c02017-01-11 16:59:38 -08003114static ssize_t tpdm_show_dsb_msr(struct device *dev,
3115 struct device_attribute *attr,
3116 char *buf)
3117{
3118 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3119 unsigned int i;
3120 ssize_t len = 0;
3121
3122 if (!drvdata->msr_support)
3123 return -EINVAL;
3124
3125 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
3126 return -EPERM;
3127
3128 for (i = 0; i < TPDM_DSB_MAX_MSR; i++)
3129 len += scnprintf(buf + len, PAGE_SIZE - len, "%u 0x%x\n",
3130 i, drvdata->dsb->msr[i]);
3131
3132 return len;
3133}
3134
Satyajit Desaif151d682016-09-12 16:18:03 -07003135static ssize_t tpdm_store_dsb_msr(struct device *dev,
3136 struct device_attribute *attr,
3137 const char *buf,
3138 size_t size)
3139{
3140 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3141 unsigned int num, val;
3142 int nval;
3143
3144 if (!drvdata->msr_support)
3145 return -EINVAL;
3146
3147 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
3148 return -EPERM;
3149
3150 nval = sscanf(buf, "%u %x", &num, &val);
3151 if (nval != 2)
3152 return -EINVAL;
3153
3154 if (num >= TPDM_DSB_MAX_MSR)
3155 return -EINVAL;
3156
3157 mutex_lock(&drvdata->lock);
3158 drvdata->dsb->msr[num] = val;
3159 mutex_unlock(&drvdata->lock);
3160 return size;
3161}
Satyajit Desaib34b2c02017-01-11 16:59:38 -08003162static DEVICE_ATTR(dsb_msr, 0644, tpdm_show_dsb_msr, tpdm_store_dsb_msr);
Satyajit Desaif151d682016-09-12 16:18:03 -07003163
3164static ssize_t tpdm_show_cmb_available_modes(struct device *dev,
3165 struct device_attribute *attr,
3166 char *buf)
3167{
3168 return scnprintf(buf, PAGE_SIZE, "%s\n", "continuous trace_on_change");
3169}
Satyajit Desai326497c2016-11-14 10:15:03 -08003170static DEVICE_ATTR(cmb_available_modes, 0444, tpdm_show_cmb_available_modes,
Satyajit Desaif151d682016-09-12 16:18:03 -07003171 NULL);
3172
3173static ssize_t tpdm_show_cmb_mode(struct device *dev,
3174 struct device_attribute *attr,
3175 char *buf)
3176{
3177 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3178
Satyajit Desaie104ff52016-09-12 16:38:12 -07003179 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3180 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003181 return -EPERM;
3182
3183 return scnprintf(buf, PAGE_SIZE, "%s\n",
3184 drvdata->cmb->mode == TPDM_CMB_MODE_CONTINUOUS ?
3185 "continuous" : "trace_on_change");
3186}
3187
3188static ssize_t tpdm_store_cmb_mode(struct device *dev,
3189 struct device_attribute *attr,
3190 const char *buf,
3191 size_t size)
3192{
3193 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3194 char str[20] = "";
3195
3196 if (strlen(buf) >= 20)
3197 return -EINVAL;
3198 if (sscanf(buf, "%s", str) != 1)
3199 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003200 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3201 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003202 return -EPERM;
3203
3204 mutex_lock(&drvdata->lock);
3205 if (!strcmp(str, "continuous")) {
3206 drvdata->cmb->mode = TPDM_CMB_MODE_CONTINUOUS;
3207 } else if (!strcmp(str, "trace_on_change")) {
3208 drvdata->cmb->mode = TPDM_CMB_MODE_TRACE_ON_CHANGE;
3209 } else {
3210 mutex_unlock(&drvdata->lock);
3211 return -EINVAL;
3212 }
3213 mutex_unlock(&drvdata->lock);
3214 return size;
3215}
Satyajit Desai326497c2016-11-14 10:15:03 -08003216static DEVICE_ATTR(cmb_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003217 tpdm_show_cmb_mode, tpdm_store_cmb_mode);
3218
Satyajit Desai75411bc2017-04-19 18:41:27 -07003219static ssize_t tpdm_show_cmb_patt_val(struct device *dev,
Satyajit Desaif151d682016-09-12 16:18:03 -07003220 struct device_attribute *attr,
3221 char *buf)
3222{
3223 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Satyajit Desai75411bc2017-04-19 18:41:27 -07003224 ssize_t size = 0;
3225 int i;
Satyajit Desaif151d682016-09-12 16:18:03 -07003226
Satyajit Desaie104ff52016-09-12 16:38:12 -07003227 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3228 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003229 return -EPERM;
3230
Satyajit Desai75411bc2017-04-19 18:41:27 -07003231 mutex_lock(&drvdata->lock);
3232 for (i = 0; i < TPDM_CMB_PATT_CMP; i++) {
3233 size += scnprintf(buf + size, PAGE_SIZE - size,
3234 "Index: 0x%x Value: 0x%x\n", i,
3235 drvdata->cmb->patt_val[i]);
3236 }
3237 mutex_unlock(&drvdata->lock);
3238 return size;
Satyajit Desaif151d682016-09-12 16:18:03 -07003239}
3240
Satyajit Desai75411bc2017-04-19 18:41:27 -07003241static ssize_t tpdm_store_cmb_patt_val(struct device *dev,
Satyajit Desaif151d682016-09-12 16:18:03 -07003242 struct device_attribute *attr,
3243 const char *buf, size_t size)
3244{
3245 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Satyajit Desai75411bc2017-04-19 18:41:27 -07003246 unsigned long index, val;
Satyajit Desaif151d682016-09-12 16:18:03 -07003247
Satyajit Desai75411bc2017-04-19 18:41:27 -07003248 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
3249 return -EINVAL;
3250 if (index >= TPDM_CMB_PATT_CMP)
Satyajit Desaif151d682016-09-12 16:18:03 -07003251 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003252 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3253 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003254 return -EPERM;
3255
3256 mutex_lock(&drvdata->lock);
Satyajit Desai75411bc2017-04-19 18:41:27 -07003257 drvdata->cmb->patt_val[index] = val;
Satyajit Desaif151d682016-09-12 16:18:03 -07003258 mutex_unlock(&drvdata->lock);
Satyajit Desai75411bc2017-04-19 18:41:27 -07003259
Satyajit Desaif151d682016-09-12 16:18:03 -07003260 return size;
3261}
Satyajit Desai75411bc2017-04-19 18:41:27 -07003262static DEVICE_ATTR(cmb_patt_val, 0644,
3263 tpdm_show_cmb_patt_val,
3264 tpdm_store_cmb_patt_val);
Satyajit Desaif151d682016-09-12 16:18:03 -07003265
Satyajit Desai75411bc2017-04-19 18:41:27 -07003266static ssize_t tpdm_show_cmb_patt_mask(struct device *dev,
Satyajit Desaif151d682016-09-12 16:18:03 -07003267 struct device_attribute *attr,
3268 char *buf)
3269{
3270 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Satyajit Desai75411bc2017-04-19 18:41:27 -07003271 ssize_t size = 0;
3272 int i;
Satyajit Desaif151d682016-09-12 16:18:03 -07003273
Satyajit Desaie104ff52016-09-12 16:38:12 -07003274 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3275 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003276 return -EPERM;
3277
Satyajit Desai75411bc2017-04-19 18:41:27 -07003278 mutex_lock(&drvdata->lock);
3279 for (i = 0; i < TPDM_CMB_PATT_CMP; i++) {
3280 size += scnprintf(buf + size, PAGE_SIZE - size,
3281 "Index: 0x%x Value: 0x%x\n", i,
3282 drvdata->cmb->patt_mask[i]);
3283 }
3284 mutex_unlock(&drvdata->lock);
3285 return size;
Satyajit Desaif151d682016-09-12 16:18:03 -07003286
Satyajit Desaif151d682016-09-12 16:18:03 -07003287}
3288
Satyajit Desai75411bc2017-04-19 18:41:27 -07003289static ssize_t tpdm_store_cmb_patt_mask(struct device *dev,
Satyajit Desaif151d682016-09-12 16:18:03 -07003290 struct device_attribute *attr,
3291 const char *buf, size_t size)
3292{
3293 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Satyajit Desai75411bc2017-04-19 18:41:27 -07003294 unsigned long index, val;
Satyajit Desaif151d682016-09-12 16:18:03 -07003295
Satyajit Desai75411bc2017-04-19 18:41:27 -07003296 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
3297 return -EINVAL;
3298 if (index >= TPDM_CMB_PATT_CMP)
Satyajit Desaif151d682016-09-12 16:18:03 -07003299 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003300 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3301 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003302 return -EPERM;
3303
3304 mutex_lock(&drvdata->lock);
Satyajit Desai75411bc2017-04-19 18:41:27 -07003305 drvdata->cmb->patt_mask[index] = val;
Satyajit Desaif151d682016-09-12 16:18:03 -07003306 mutex_unlock(&drvdata->lock);
3307 return size;
3308}
Satyajit Desai75411bc2017-04-19 18:41:27 -07003309static DEVICE_ATTR(cmb_patt_mask, 0644,
3310 tpdm_show_cmb_patt_mask, tpdm_store_cmb_patt_mask);
Satyajit Desaif151d682016-09-12 16:18:03 -07003311
3312static ssize_t tpdm_show_cmb_patt_ts(struct device *dev,
3313 struct device_attribute *attr,
3314 char *buf)
3315{
3316 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3317
Satyajit Desaie104ff52016-09-12 16:38:12 -07003318 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3319 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003320 return -EPERM;
3321
3322 return scnprintf(buf, PAGE_SIZE, "%u\n",
3323 (unsigned int)drvdata->cmb->patt_ts);
3324}
3325
3326static ssize_t tpdm_store_cmb_patt_ts(struct device *dev,
3327 struct device_attribute *attr,
3328 const char *buf,
3329 size_t size)
3330{
3331 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3332 unsigned long val;
3333
3334 if (kstrtoul(buf, 16, &val))
3335 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003336 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3337 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003338 return -EPERM;
3339
3340 mutex_lock(&drvdata->lock);
3341 if (val)
3342 drvdata->cmb->patt_ts = true;
3343 else
3344 drvdata->cmb->patt_ts = false;
3345 mutex_unlock(&drvdata->lock);
3346 return size;
3347}
Satyajit Desai326497c2016-11-14 10:15:03 -08003348static DEVICE_ATTR(cmb_patt_ts, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003349 tpdm_show_cmb_patt_ts, tpdm_store_cmb_patt_ts);
3350
3351static ssize_t tpdm_show_cmb_trig_patt_val_lsb(struct device *dev,
3352 struct device_attribute *attr,
3353 char *buf)
3354{
3355 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3356 unsigned long val;
3357
Satyajit Desaie104ff52016-09-12 16:38:12 -07003358 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3359 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003360 return -EPERM;
3361
3362 val = drvdata->cmb->trig_patt_val[TPDM_CMB_LSB];
3363
3364 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
3365}
3366
3367static ssize_t tpdm_store_cmb_trig_patt_val_lsb(struct device *dev,
3368 struct device_attribute *attr,
3369 const char *buf, size_t size)
3370{
3371 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3372 unsigned long val;
3373
3374 if (kstrtoul(buf, 16, &val))
3375 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003376 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3377 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003378 return -EPERM;
3379
3380 mutex_lock(&drvdata->lock);
3381 drvdata->cmb->trig_patt_val[TPDM_CMB_LSB] = val;
3382 mutex_unlock(&drvdata->lock);
3383 return size;
3384}
Satyajit Desai326497c2016-11-14 10:15:03 -08003385static DEVICE_ATTR(cmb_trig_patt_val_lsb, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003386 tpdm_show_cmb_trig_patt_val_lsb,
3387 tpdm_store_cmb_trig_patt_val_lsb);
3388
3389static ssize_t tpdm_show_cmb_trig_patt_mask_lsb(struct device *dev,
3390 struct device_attribute *attr,
3391 char *buf)
3392{
3393 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3394 unsigned long val;
3395
Satyajit Desaie104ff52016-09-12 16:38:12 -07003396 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3397 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003398 return -EPERM;
3399
3400 val = drvdata->cmb->trig_patt_mask[TPDM_CMB_LSB];
3401
3402 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
3403}
3404
3405static ssize_t tpdm_store_cmb_trig_patt_mask_lsb(struct device *dev,
3406 struct device_attribute *attr,
3407 const char *buf, size_t size)
3408{
3409 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3410 unsigned long val;
3411
3412 if (kstrtoul(buf, 16, &val))
3413 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003414 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3415 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003416 return -EPERM;
3417
3418 mutex_lock(&drvdata->lock);
3419 drvdata->cmb->trig_patt_mask[TPDM_CMB_LSB] = val;
3420 mutex_unlock(&drvdata->lock);
3421 return size;
3422}
Satyajit Desai326497c2016-11-14 10:15:03 -08003423static DEVICE_ATTR(cmb_trig_patt_mask_lsb, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003424 tpdm_show_cmb_trig_patt_mask_lsb,
3425 tpdm_store_cmb_trig_patt_mask_lsb);
3426
3427static ssize_t tpdm_show_cmb_trig_patt_val_msb(struct device *dev,
3428 struct device_attribute *attr,
3429 char *buf)
3430{
3431 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3432 unsigned long val;
3433
Satyajit Desaie104ff52016-09-12 16:38:12 -07003434 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3435 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003436 return -EPERM;
3437
3438 val = drvdata->cmb->trig_patt_val[TPDM_CMB_MSB];
3439
3440 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
3441}
3442
3443static ssize_t tpdm_store_cmb_trig_patt_val_msb(struct device *dev,
3444 struct device_attribute *attr,
3445 const char *buf, size_t size)
3446{
3447 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3448 unsigned long val;
3449
3450 if (kstrtoul(buf, 16, &val))
3451 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003452 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3453 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003454 return -EPERM;
3455
3456 mutex_lock(&drvdata->lock);
3457 drvdata->cmb->trig_patt_val[TPDM_CMB_MSB] = val;
3458 mutex_unlock(&drvdata->lock);
3459 return size;
3460}
Satyajit Desai326497c2016-11-14 10:15:03 -08003461static DEVICE_ATTR(cmb_trig_patt_val_msb, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003462 tpdm_show_cmb_trig_patt_val_msb,
3463 tpdm_store_cmb_trig_patt_val_msb);
3464
3465static ssize_t tpdm_show_cmb_trig_patt_mask_msb(struct device *dev,
3466 struct device_attribute *attr,
3467 char *buf)
3468{
3469 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3470 unsigned long val;
3471
Satyajit Desaie104ff52016-09-12 16:38:12 -07003472 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3473 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003474 return -EPERM;
3475
3476 val = drvdata->cmb->trig_patt_mask[TPDM_CMB_MSB];
3477
3478 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
3479}
3480
3481static ssize_t tpdm_store_cmb_trig_patt_mask_msb(struct device *dev,
3482 struct device_attribute *attr,
3483 const char *buf, size_t size)
3484{
3485 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3486 unsigned long val;
3487
3488 if (kstrtoul(buf, 16, &val))
3489 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003490 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3491 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003492 return -EPERM;
3493
3494 mutex_lock(&drvdata->lock);
3495 drvdata->cmb->trig_patt_mask[TPDM_CMB_MSB] = val;
3496 mutex_unlock(&drvdata->lock);
3497 return size;
3498}
Satyajit Desai326497c2016-11-14 10:15:03 -08003499static DEVICE_ATTR(cmb_trig_patt_mask_msb, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003500 tpdm_show_cmb_trig_patt_mask_msb,
3501 tpdm_store_cmb_trig_patt_mask_msb);
3502
3503static ssize_t tpdm_show_cmb_trig_ts(struct device *dev,
3504 struct device_attribute *attr,
3505 char *buf)
3506{
3507 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3508
Satyajit Desaie104ff52016-09-12 16:38:12 -07003509 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3510 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003511 return -EPERM;
3512
3513 return scnprintf(buf, PAGE_SIZE, "%u\n",
3514 (unsigned int)drvdata->cmb->trig_ts);
3515}
3516
3517static ssize_t tpdm_store_cmb_trig_ts(struct device *dev,
Satyajit Desaie104ff52016-09-12 16:38:12 -07003518 struct device_attribute *attr,
3519 const char *buf,
3520 size_t size)
Satyajit Desaif151d682016-09-12 16:18:03 -07003521{
3522 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3523 unsigned long val;
3524
3525 if (kstrtoul(buf, 16, &val))
3526 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003527 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3528 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003529 return -EPERM;
3530
3531 mutex_lock(&drvdata->lock);
3532 if (val)
3533 drvdata->cmb->trig_ts = true;
3534 else
3535 drvdata->cmb->trig_ts = false;
3536 mutex_unlock(&drvdata->lock);
3537 return size;
3538}
Satyajit Desai326497c2016-11-14 10:15:03 -08003539static DEVICE_ATTR(cmb_trig_ts, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003540 tpdm_show_cmb_trig_ts, tpdm_store_cmb_trig_ts);
3541
Satyajit Desaib34b2c02017-01-11 16:59:38 -08003542static ssize_t tpdm_show_cmb_msr(struct device *dev,
3543 struct device_attribute *attr,
3544 char *buf)
3545{
3546 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3547 unsigned int i;
3548 ssize_t len = 0;
3549
3550 if (!drvdata->msr_support)
3551 return -EINVAL;
3552
3553 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3554 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
3555 return -EPERM;
3556
3557 for (i = 0; i < TPDM_CMB_MAX_MSR; i++)
3558 len += scnprintf(buf + len, PAGE_SIZE - len, "%u 0x%x\n",
3559 i, drvdata->cmb->msr[i]);
3560
3561 return len;
3562}
3563
Satyajit Desaif151d682016-09-12 16:18:03 -07003564static ssize_t tpdm_store_cmb_msr(struct device *dev,
3565 struct device_attribute *attr,
3566 const char *buf,
3567 size_t size)
3568{
3569 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3570 unsigned int num, val;
3571 int nval;
3572
3573 if (!drvdata->msr_support)
3574 return -EINVAL;
3575
Satyajit Desaie104ff52016-09-12 16:38:12 -07003576 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3577 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003578 return -EPERM;
3579
3580 nval = sscanf(buf, "%u %x", &num, &val);
3581 if (nval != 2)
3582 return -EINVAL;
3583
3584 if (num >= TPDM_CMB_MAX_MSR)
3585 return -EINVAL;
3586
3587 mutex_lock(&drvdata->lock);
3588 drvdata->cmb->msr[num] = val;
3589 mutex_unlock(&drvdata->lock);
3590 return size;
3591}
Satyajit Desaib34b2c02017-01-11 16:59:38 -08003592static DEVICE_ATTR(cmb_msr, 0644, tpdm_show_cmb_msr, tpdm_store_cmb_msr);
Satyajit Desaif151d682016-09-12 16:18:03 -07003593
Satyajit Desaie104ff52016-09-12 16:38:12 -07003594static ssize_t tpdm_show_cmb_read_interface_state(struct device *dev,
3595 struct device_attribute *attr,
3596 char *buf)
3597{
3598 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3599 unsigned long val;
3600
3601 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3602 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
3603 return -EPERM;
3604
3605 mutex_lock(&drvdata->lock);
3606 TPDM_UNLOCK(drvdata);
3607 val = tpdm_readl(drvdata, TPDM_CMB_READVAL);
3608 TPDM_LOCK(drvdata);
3609 mutex_unlock(&drvdata->lock);
3610
3611 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
3612}
3613static DEVICE_ATTR(cmb_read_interface_state, 0444,
3614 tpdm_show_cmb_read_interface_state, NULL);
3615
3616static ssize_t tpdm_show_cmb_read_ctl_reg(struct device *dev,
3617 struct device_attribute *attr,
3618 char *buf)
3619{
3620 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3621 unsigned long val;
3622
3623 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3624 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
3625 return -EPERM;
3626
3627 mutex_lock(&drvdata->lock);
3628 TPDM_UNLOCK(drvdata);
3629 val = tpdm_readl(drvdata, TPDM_CMB_READCTL);
3630 TPDM_LOCK(drvdata);
3631 mutex_unlock(&drvdata->lock);
3632
3633 if (test_bit(TPDM_DS_CMB, drvdata->datasets))
3634 return scnprintf(buf, PAGE_SIZE, "SEL: %lx\n", val);
3635 else
3636 return scnprintf(buf, PAGE_SIZE, "Lane %u SEL: %lx\n",
3637 (unsigned int)BMVAL(val, 1, 3), val & 0x1);
3638}
3639
3640static ssize_t tpdm_store_cmb_read_ctl_reg(struct device *dev,
3641 struct device_attribute *attr,
3642 const char *buf,
3643 size_t size)
3644{
3645 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3646 unsigned long val;
3647
3648 if (kstrtoul(buf, 16, &val))
3649 return -EINVAL;
3650
3651 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3652 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
3653 return -EPERM;
3654
3655 mutex_lock(&drvdata->lock);
3656 TPDM_UNLOCK(drvdata);
3657 tpdm_writel(drvdata, val, TPDM_CMB_READCTL);
3658 TPDM_LOCK(drvdata);
3659 mutex_unlock(&drvdata->lock);
3660
3661 return size;
3662}
3663static DEVICE_ATTR(cmb_read_ctl_reg, 0644,
3664 tpdm_show_cmb_read_ctl_reg, tpdm_store_cmb_read_ctl_reg);
3665
3666static ssize_t tpdm_show_mcmb_trig_lane(struct device *dev,
3667 struct device_attribute *attr,
3668 char *buf)
3669{
3670 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3671
3672 if (!test_bit(TPDM_DS_MCMB, drvdata->datasets))
3673 return -EPERM;
3674
3675 return scnprintf(buf, PAGE_SIZE, "%u\n",
3676 (unsigned int)drvdata->cmb->mcmb->mcmb_trig_lane);
3677}
3678
3679static ssize_t tpdm_store_mcmb_trig_lane(struct device *dev,
3680 struct device_attribute *attr,
3681 const char *buf,
3682 size_t size)
3683{
3684 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3685 unsigned long val;
3686
3687 if (kstrtoul(buf, 10, &val))
3688 return -EINVAL;
3689 if (val >= TPDM_MCMB_MAX_LANES)
3690 return -EINVAL;
3691 if (!test_bit(TPDM_DS_MCMB, drvdata->datasets))
3692 return -EPERM;
3693
3694 mutex_lock(&drvdata->lock);
3695 drvdata->cmb->mcmb->mcmb_trig_lane = val;
3696 mutex_unlock(&drvdata->lock);
3697 return size;
3698}
3699static DEVICE_ATTR(mcmb_trig_lane, 0644,
3700 tpdm_show_mcmb_trig_lane, tpdm_store_mcmb_trig_lane);
3701
3702static ssize_t tpdm_show_mcmb_lanes_select(struct device *dev,
3703 struct device_attribute *attr,
3704 char *buf)
3705{
3706 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3707
3708 if (!test_bit(TPDM_DS_MCMB, drvdata->datasets))
3709 return -EPERM;
3710
3711 return scnprintf(buf, PAGE_SIZE, "%u\n",
3712 (unsigned int)drvdata->cmb->mcmb->mcmb_lane_select);
3713}
3714
3715static ssize_t tpdm_store_mcmb_lanes_select(struct device *dev,
3716 struct device_attribute *attr,
3717 const char *buf,
3718 size_t size)
3719{
3720 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3721 unsigned long val;
3722
3723 if (kstrtoul(buf, 16, &val))
3724 return -EINVAL;
3725 if (!test_bit(TPDM_DS_MCMB, drvdata->datasets))
3726 return -EPERM;
3727
3728 val = BMVAL(val, 0, TPDM_MCMB_MAX_LANES - 1);
3729
3730 mutex_lock(&drvdata->lock);
3731 drvdata->cmb->mcmb->mcmb_lane_select = val;
3732 mutex_unlock(&drvdata->lock);
3733 return size;
3734}
3735static DEVICE_ATTR(mcmb_lanes_select, 0644,
3736 tpdm_show_mcmb_lanes_select, tpdm_store_mcmb_lanes_select);
3737
3738static ssize_t tpdm_store_cmb_markr(struct device *dev,
3739 struct device_attribute *attr,
3740 const char *buf,
3741 size_t size)
3742{
3743 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3744 unsigned long val;
3745
3746 if (kstrtoul(buf, 16, &val))
3747 return -EINVAL;
3748
3749 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3750 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
3751 return -EPERM;
3752
3753 mutex_lock(&drvdata->lock);
3754 TPDM_UNLOCK(drvdata);
3755 tpdm_writel(drvdata, val, TPDM_CMB_MARKR);
3756 TPDM_LOCK(drvdata);
3757 mutex_unlock(&drvdata->lock);
3758
3759 return size;
3760}
3761static DEVICE_ATTR(cmb_markr, 0200, NULL, tpdm_store_cmb_markr);
3762
Satyajit Desaif151d682016-09-12 16:18:03 -07003763static struct attribute *tpdm_bc_attrs[] = {
3764 &dev_attr_bc_capture_mode.attr,
3765 &dev_attr_bc_retrieval_mode.attr,
3766 &dev_attr_bc_reset_counters.attr,
3767 &dev_attr_bc_sat_mode.attr,
3768 &dev_attr_bc_enable_counters.attr,
3769 &dev_attr_bc_clear_counters.attr,
3770 &dev_attr_bc_enable_irq.attr,
3771 &dev_attr_bc_clear_irq.attr,
3772 &dev_attr_bc_trig_val_lo.attr,
3773 &dev_attr_bc_trig_val_hi.attr,
3774 &dev_attr_bc_enable_ganging.attr,
3775 &dev_attr_bc_overflow_val.attr,
3776 &dev_attr_bc_ovsr.attr,
3777 &dev_attr_bc_counter_sel.attr,
3778 &dev_attr_bc_count_val_lo.attr,
3779 &dev_attr_bc_count_val_hi.attr,
3780 &dev_attr_bc_shadow_val_lo.attr,
3781 &dev_attr_bc_shadow_val_hi.attr,
3782 &dev_attr_bc_sw_inc.attr,
3783 &dev_attr_bc_msr.attr,
3784 NULL,
3785};
3786
3787static struct attribute *tpdm_tc_attrs[] = {
3788 &dev_attr_tc_capture_mode.attr,
3789 &dev_attr_tc_retrieval_mode.attr,
3790 &dev_attr_tc_reset_counters.attr,
3791 &dev_attr_tc_sat_mode.attr,
3792 &dev_attr_tc_enable_counters.attr,
3793 &dev_attr_tc_clear_counters.attr,
3794 &dev_attr_tc_enable_irq.attr,
3795 &dev_attr_tc_clear_irq.attr,
3796 &dev_attr_tc_trig_sel.attr,
3797 &dev_attr_tc_trig_val_lo.attr,
3798 &dev_attr_tc_trig_val_hi.attr,
3799 &dev_attr_tc_ovsr_gp.attr,
3800 &dev_attr_tc_ovsr_impl.attr,
3801 &dev_attr_tc_counter_sel.attr,
3802 &dev_attr_tc_count_val_lo.attr,
3803 &dev_attr_tc_count_val_hi.attr,
3804 &dev_attr_tc_shadow_val_lo.attr,
3805 &dev_attr_tc_shadow_val_hi.attr,
3806 &dev_attr_tc_sw_inc.attr,
3807 &dev_attr_tc_msr.attr,
3808 NULL,
3809};
3810
3811static struct attribute *tpdm_dsb_attrs[] = {
3812 &dev_attr_dsb_mode.attr,
3813 &dev_attr_dsb_edge_ctrl.attr,
3814 &dev_attr_dsb_edge_ctrl_mask.attr,
3815 &dev_attr_dsb_patt_val.attr,
3816 &dev_attr_dsb_patt_mask.attr,
3817 &dev_attr_dsb_patt_ts.attr,
3818 &dev_attr_dsb_patt_type.attr,
3819 &dev_attr_dsb_trig_patt_val.attr,
3820 &dev_attr_dsb_trig_patt_mask.attr,
3821 &dev_attr_dsb_trig_ts.attr,
3822 &dev_attr_dsb_select_val.attr,
3823 &dev_attr_dsb_msr.attr,
3824 NULL,
3825};
3826
3827static struct attribute *tpdm_cmb_attrs[] = {
3828 &dev_attr_cmb_available_modes.attr,
3829 &dev_attr_cmb_mode.attr,
Satyajit Desai75411bc2017-04-19 18:41:27 -07003830 &dev_attr_cmb_patt_val.attr,
3831 &dev_attr_cmb_patt_mask.attr,
Satyajit Desaif151d682016-09-12 16:18:03 -07003832 &dev_attr_cmb_patt_ts.attr,
3833 &dev_attr_cmb_trig_patt_val_lsb.attr,
3834 &dev_attr_cmb_trig_patt_mask_lsb.attr,
3835 &dev_attr_cmb_trig_patt_val_msb.attr,
3836 &dev_attr_cmb_trig_patt_mask_msb.attr,
3837 &dev_attr_cmb_trig_ts.attr,
3838 &dev_attr_cmb_msr.attr,
Satyajit Desaie104ff52016-09-12 16:38:12 -07003839 &dev_attr_cmb_read_interface_state.attr,
3840 &dev_attr_cmb_read_ctl_reg.attr,
3841 &dev_attr_cmb_markr.attr,
3842 &dev_attr_mcmb_trig_lane.attr,
3843 &dev_attr_mcmb_lanes_select.attr,
Satyajit Desaif151d682016-09-12 16:18:03 -07003844 NULL,
3845};
3846
3847static struct attribute_group tpdm_bc_attr_grp = {
3848 .attrs = tpdm_bc_attrs,
3849};
3850
3851static struct attribute_group tpdm_tc_attr_grp = {
3852 .attrs = tpdm_tc_attrs,
3853};
3854
3855static struct attribute_group tpdm_dsb_attr_grp = {
3856 .attrs = tpdm_dsb_attrs,
3857};
3858
3859static struct attribute_group tpdm_cmb_attr_grp = {
3860 .attrs = tpdm_cmb_attrs,
3861};
3862
3863static struct attribute *tpdm_attrs[] = {
3864 &dev_attr_available_datasets.attr,
3865 &dev_attr_enable_datasets.attr,
3866 &dev_attr_gp_regs.attr,
3867 NULL,
3868};
3869
3870static struct attribute_group tpdm_attr_grp = {
3871 .attrs = tpdm_attrs,
3872};
3873static const struct attribute_group *tpdm_attr_grps[] = {
3874 &tpdm_attr_grp,
3875 &tpdm_bc_attr_grp,
3876 &tpdm_tc_attr_grp,
3877 &tpdm_dsb_attr_grp,
3878 &tpdm_cmb_attr_grp,
3879 NULL,
3880};
3881
3882static int tpdm_datasets_alloc(struct tpdm_drvdata *drvdata)
3883{
3884 if (test_bit(TPDM_DS_GPR, drvdata->datasets)) {
3885 drvdata->gpr = devm_kzalloc(drvdata->dev, sizeof(*drvdata->gpr),
3886 GFP_KERNEL);
3887 if (!drvdata->gpr)
3888 return -ENOMEM;
3889 }
3890 if (test_bit(TPDM_DS_BC, drvdata->datasets)) {
3891 drvdata->bc = devm_kzalloc(drvdata->dev, sizeof(*drvdata->bc),
3892 GFP_KERNEL);
3893 if (!drvdata->bc)
3894 return -ENOMEM;
3895 }
3896 if (test_bit(TPDM_DS_TC, drvdata->datasets)) {
3897 drvdata->tc = devm_kzalloc(drvdata->dev, sizeof(*drvdata->tc),
3898 GFP_KERNEL);
3899 if (!drvdata->tc)
3900 return -ENOMEM;
3901 }
3902 if (test_bit(TPDM_DS_DSB, drvdata->datasets)) {
3903 drvdata->dsb = devm_kzalloc(drvdata->dev, sizeof(*drvdata->dsb),
3904 GFP_KERNEL);
3905 if (!drvdata->dsb)
3906 return -ENOMEM;
3907 }
3908 if (test_bit(TPDM_DS_CMB, drvdata->datasets)) {
3909 drvdata->cmb = devm_kzalloc(drvdata->dev, sizeof(*drvdata->cmb),
3910 GFP_KERNEL);
3911 if (!drvdata->cmb)
3912 return -ENOMEM;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003913 } else if (test_bit(TPDM_DS_MCMB, drvdata->datasets)) {
3914 drvdata->cmb = devm_kzalloc(drvdata->dev, sizeof(*drvdata->cmb),
3915 GFP_KERNEL);
3916 if (!drvdata->cmb)
3917 return -ENOMEM;
3918 drvdata->cmb->mcmb = devm_kzalloc(drvdata->dev,
3919 sizeof(*drvdata->cmb->mcmb),
3920 GFP_KERNEL);
3921 if (!drvdata->cmb->mcmb)
3922 return -ENOMEM;
Satyajit Desaif151d682016-09-12 16:18:03 -07003923 }
3924 return 0;
3925}
3926
3927static void tpdm_init_default_data(struct tpdm_drvdata *drvdata)
3928{
3929 if (test_bit(TPDM_DS_BC, drvdata->datasets))
3930 drvdata->bc->retrieval_mode = TPDM_MODE_ATB;
3931
3932 if (test_bit(TPDM_DS_TC, drvdata->datasets))
3933 drvdata->tc->retrieval_mode = TPDM_MODE_ATB;
3934
3935 if (test_bit(TPDM_DS_DSB, drvdata->datasets))
3936 drvdata->dsb->trig_ts = true;
3937
Satyajit Desaie104ff52016-09-12 16:38:12 -07003938 if (test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3939 test_bit(TPDM_DS_MCMB, drvdata->datasets))
Satyajit Desaif151d682016-09-12 16:18:03 -07003940 drvdata->cmb->trig_ts = true;
3941}
3942
3943static int tpdm_probe(struct platform_device *pdev)
3944{
3945 int ret, i;
3946 uint32_t pidr, devid;
3947 struct device *dev = &pdev->dev;
3948 struct coresight_platform_data *pdata;
3949 struct tpdm_drvdata *drvdata;
3950 struct resource *res;
3951 struct coresight_desc *desc;
3952 static int traceid = TPDM_TRACE_ID_START;
3953 uint32_t version;
3954
3955 pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
3956 if (IS_ERR(pdata))
3957 return PTR_ERR(pdata);
3958 pdev->dev.platform_data = pdata;
3959
3960 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
3961 if (!drvdata)
3962 return -ENOMEM;
3963 drvdata->dev = &pdev->dev;
3964 platform_set_drvdata(pdev, drvdata);
3965
3966 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tpdm-base");
3967 if (!res)
3968 return -ENODEV;
3969
3970 drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
3971 if (!drvdata->base)
3972 return -ENOMEM;
3973
3974 drvdata->clk_enable = of_property_read_bool(pdev->dev.of_node,
3975 "qcom,clk-enable");
3976
3977 drvdata->msr_fix_req = of_property_read_bool(pdev->dev.of_node,
3978 "qcom,msr-fix-req");
3979
3980 mutex_init(&drvdata->lock);
3981
3982 drvdata->clk = devm_clk_get(dev, "core_clk");
3983 if (IS_ERR(drvdata->clk))
3984 return PTR_ERR(drvdata->clk);
3985
3986 ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
3987 if (ret)
3988 return ret;
3989
3990 ret = clk_prepare_enable(drvdata->clk);
3991 if (ret)
3992 return ret;
3993
3994 version = tpdm_readl(drvdata, CORESIGHT_PERIPHIDR2);
3995 drvdata->version = BMVAL(version, 4, 7);
3996
3997 if (drvdata->version)
3998 drvdata->msr_support = true;
3999
4000 pidr = tpdm_readl(drvdata, CORESIGHT_PERIPHIDR0);
4001 for (i = 0; i < TPDM_DATASETS; i++) {
4002 if (pidr & BIT(i)) {
4003 __set_bit(i, drvdata->datasets);
4004 __set_bit(i, drvdata->enable_ds);
4005 }
4006 }
4007
4008 ret = tpdm_datasets_alloc(drvdata);
4009 if (ret)
4010 return ret;
4011
4012 tpdm_init_default_data(drvdata);
4013
4014 devid = tpdm_readl(drvdata, CORESIGHT_DEVID);
4015 drvdata->tc_trig_type = BMVAL(devid, 27, 28);
4016 drvdata->bc_trig_type = BMVAL(devid, 25, 26);
4017 drvdata->bc_gang_type = BMVAL(devid, 23, 24);
4018 drvdata->bc_counters_avail = BMVAL(devid, 6, 10) + 1;
4019 drvdata->tc_counters_avail = BMVAL(devid, 4, 5) + 1;
4020
4021 clk_disable_unprepare(drvdata->clk);
4022
4023 drvdata->traceid = traceid++;
4024
4025 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
4026 if (!desc)
4027 return -ENOMEM;
4028 desc->type = CORESIGHT_DEV_TYPE_SOURCE;
4029 desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
4030 desc->ops = &tpdm_cs_ops;
4031 desc->pdata = pdev->dev.platform_data;
4032 desc->dev = &pdev->dev;
4033 desc->groups = tpdm_attr_grps;
4034 drvdata->csdev = coresight_register(desc);
4035 if (IS_ERR(drvdata->csdev))
4036 return PTR_ERR(drvdata->csdev);
4037
4038 dev_dbg(drvdata->dev, "TPDM initialized\n");
4039
4040 if (boot_enable)
4041 coresight_enable(drvdata->csdev);
4042
4043 return 0;
4044}
4045
4046static int tpdm_remove(struct platform_device *pdev)
4047{
4048 struct tpdm_drvdata *drvdata = platform_get_drvdata(pdev);
4049
4050 coresight_unregister(drvdata->csdev);
4051 return 0;
4052}
4053
4054static const struct of_device_id tpdm_match[] = {
4055 {.compatible = "qcom,coresight-tpdm"},
4056 {}
4057};
4058
4059static struct platform_driver tpdm_driver = {
4060 .probe = tpdm_probe,
4061 .remove = tpdm_remove,
4062 .driver = {
4063 .name = "coresight-tpdm",
4064 .owner = THIS_MODULE,
4065 .of_match_table = tpdm_match,
4066 },
4067};
4068
4069static int __init tpdm_init(void)
4070{
4071 return platform_driver_register(&tpdm_driver);
4072}
4073module_init(tpdm_init);
4074
4075static void __exit tpdm_exit(void)
4076{
4077 platform_driver_unregister(&tpdm_driver);
4078}
4079module_exit(tpdm_exit);
4080
4081MODULE_LICENSE("GPL v2");
4082MODULE_DESCRIPTION("Trace, Profiling & Diagnostic Monitor driver");