blob: a6295eca7c5e826b9c126f93ba6acec19dbd5adb [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
Satyajit Desaibd2deda2017-04-20 18:28:38 -0700608 val = val & ~BM(18, 20);
609 val = val | (BMVAL(mcmb->mcmb_trig_lane, 0, 2) << 18);
610 val = val & ~BM(10, 17);
611 val = val | (BMVAL(mcmb->mcmb_lane_select, 0, 7) << 10);
Satyajit Desaie104ff52016-09-12 16:38:12 -0700612
613 tpdm_writel(drvdata, val, TPDM_CMB_CR);
614 /* Set the enable bit */
615 val = val | BIT(0);
616 tpdm_writel(drvdata, val, TPDM_CMB_CR);
617}
618
Satyajit Desaif151d682016-09-12 16:18:03 -0700619static void __tpdm_enable(struct tpdm_drvdata *drvdata)
620{
621 TPDM_UNLOCK(drvdata);
622
623 if (drvdata->clk_enable)
624 tpdm_writel(drvdata, 0x1, TPDM_CLK_CTRL);
625
626 if (test_bit(TPDM_DS_GPR, drvdata->enable_ds))
627 __tpdm_enable_gpr(drvdata);
628
629 if (test_bit(TPDM_DS_BC, drvdata->enable_ds))
630 __tpdm_enable_bc(drvdata);
631
632 if (test_bit(TPDM_DS_TC, drvdata->enable_ds))
633 __tpdm_enable_tc(drvdata);
634
635 if (test_bit(TPDM_DS_DSB, drvdata->enable_ds))
636 __tpdm_enable_dsb(drvdata);
637
638 if (test_bit(TPDM_DS_CMB, drvdata->enable_ds))
639 __tpdm_enable_cmb(drvdata);
Satyajit Desaie104ff52016-09-12 16:38:12 -0700640 else if (test_bit(TPDM_DS_MCMB, drvdata->enable_ds))
641 __tpdm_enable_mcmb(drvdata);
Satyajit Desaif151d682016-09-12 16:18:03 -0700642
643 TPDM_LOCK(drvdata);
644}
645
646static int tpdm_enable(struct coresight_device *csdev,
Satyajit Desaiee828fb2017-02-07 13:51:32 -0800647 struct perf_event *event, u32 mode)
Satyajit Desaif151d682016-09-12 16:18:03 -0700648{
649 struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
650 int ret;
651
652 ret = clk_prepare_enable(drvdata->clk);
653 if (ret)
654 return ret;
655
656 mutex_lock(&drvdata->lock);
657 __tpdm_enable(drvdata);
658 drvdata->enable = true;
659 mutex_unlock(&drvdata->lock);
660
661 dev_info(drvdata->dev, "TPDM tracing enabled\n");
662 return 0;
663}
664
665static void __tpdm_disable_bc(struct tpdm_drvdata *drvdata)
666{
667 uint32_t config;
668
669 config = tpdm_readl(drvdata, TPDM_BC_CR);
670 config = config & ~BIT(0);
671 tpdm_writel(drvdata, config, TPDM_BC_CR);
672}
673
674static void __tpdm_disable_tc(struct tpdm_drvdata *drvdata)
675{
676 uint32_t config;
677
678 config = tpdm_readl(drvdata, TPDM_TC_CR);
679 config = config & ~BIT(0);
680 tpdm_writel(drvdata, config, TPDM_TC_CR);
681}
682
683static void __tpdm_disable_dsb(struct tpdm_drvdata *drvdata)
684{
685 uint32_t config;
686
687 config = tpdm_readl(drvdata, TPDM_DSB_CR);
688 config = config & ~BIT(0);
689 tpdm_writel(drvdata, config, TPDM_DSB_CR);
690}
691
692static void __tpdm_disable_cmb(struct tpdm_drvdata *drvdata)
693{
694 uint32_t config;
695
696 config = tpdm_readl(drvdata, TPDM_CMB_CR);
697 config = config & ~BIT(0);
698 tpdm_writel(drvdata, config, TPDM_CMB_CR);
699}
700
701static void __tpdm_disable(struct tpdm_drvdata *drvdata)
702{
703 TPDM_UNLOCK(drvdata);
704
705 if (test_bit(TPDM_DS_BC, drvdata->enable_ds))
706 __tpdm_disable_bc(drvdata);
707
708 if (test_bit(TPDM_DS_TC, drvdata->enable_ds))
709 __tpdm_disable_tc(drvdata);
710
711 if (test_bit(TPDM_DS_DSB, drvdata->enable_ds))
712 __tpdm_disable_dsb(drvdata);
713
Satyajit Desaibd2deda2017-04-20 18:28:38 -0700714 if (test_bit(TPDM_DS_CMB, drvdata->enable_ds) ||
715 test_bit(TPDM_DS_MCMB, drvdata->enable_ds))
Satyajit Desaif151d682016-09-12 16:18:03 -0700716 __tpdm_disable_cmb(drvdata);
717
718 if (drvdata->clk_enable)
719 tpdm_writel(drvdata, 0x0, TPDM_CLK_CTRL);
720
721 TPDM_LOCK(drvdata);
722}
723
Satyajit Desaiee828fb2017-02-07 13:51:32 -0800724static void tpdm_disable(struct coresight_device *csdev,
725 struct perf_event *event)
Satyajit Desaif151d682016-09-12 16:18:03 -0700726{
727 struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
728
729 mutex_lock(&drvdata->lock);
730 __tpdm_disable(drvdata);
731 drvdata->enable = false;
732 mutex_unlock(&drvdata->lock);
733
734 clk_disable_unprepare(drvdata->clk);
735
736 dev_info(drvdata->dev, "TPDM tracing disabled\n");
737}
738
739static int tpdm_trace_id(struct coresight_device *csdev)
740{
741 struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
742
743 return drvdata->traceid;
744}
745
746static const struct coresight_ops_source tpdm_source_ops = {
747 .trace_id = tpdm_trace_id,
748 .enable = tpdm_enable,
749 .disable = tpdm_disable,
750};
751
752static const struct coresight_ops tpdm_cs_ops = {
753 .source_ops = &tpdm_source_ops,
754};
755
756static ssize_t tpdm_show_available_datasets(struct device *dev,
757 struct device_attribute *attr,
758 char *buf)
759{
760 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
761 ssize_t size = 0;
762
763 if (test_bit(TPDM_DS_IMPLDEF, drvdata->datasets))
764 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s",
765 "IMPLDEF");
766
767 if (test_bit(TPDM_DS_DSB, drvdata->datasets))
768 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "DSB");
769
770 if (test_bit(TPDM_DS_CMB, drvdata->datasets))
771 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "CMB");
772
773 if (test_bit(TPDM_DS_TC, drvdata->datasets))
774 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "TC");
775
776 if (test_bit(TPDM_DS_BC, drvdata->datasets))
777 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "BC");
778
779 if (test_bit(TPDM_DS_GPR, drvdata->datasets))
780 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "GPR");
781
Satyajit Desaie104ff52016-09-12 16:38:12 -0700782 if (test_bit(TPDM_DS_MCMB, drvdata->datasets))
783 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "MCMB");
784
Satyajit Desaif151d682016-09-12 16:18:03 -0700785 size += scnprintf(buf + size, PAGE_SIZE - size, "\n");
786 return size;
787}
Satyajit Desai326497c2016-11-14 10:15:03 -0800788static DEVICE_ATTR(available_datasets, 0444, tpdm_show_available_datasets,
Satyajit Desaif151d682016-09-12 16:18:03 -0700789 NULL);
790
791static ssize_t tpdm_show_enable_datasets(struct device *dev,
792 struct device_attribute *attr,
793 char *buf)
794{
795 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
796 ssize_t size;
797
798 size = scnprintf(buf, PAGE_SIZE, "%*pb\n", TPDM_DATASETS,
799 drvdata->enable_ds);
800
801 if (PAGE_SIZE - size < 2)
802 size = -EINVAL;
803 else
804 size += scnprintf(buf + size, 2, "\n");
805 return size;
806}
807
808static ssize_t tpdm_store_enable_datasets(struct device *dev,
809 struct device_attribute *attr,
810 const char *buf,
811 size_t size)
812{
813 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
814 unsigned long val;
815 int i;
816
817 if (kstrtoul(buf, 16, &val))
818 return -EINVAL;
819
820 mutex_lock(&drvdata->lock);
821 if (drvdata->enable) {
822 mutex_unlock(&drvdata->lock);
823 return -EPERM;
824 }
825
826 for (i = 0; i < TPDM_DATASETS; i++) {
827 if (test_bit(i, drvdata->datasets) && (val & BIT(i)))
828 __set_bit(i, drvdata->enable_ds);
829 else
830 __clear_bit(i, drvdata->enable_ds);
831 }
832 mutex_unlock(&drvdata->lock);
833 return size;
834}
Satyajit Desai326497c2016-11-14 10:15:03 -0800835static DEVICE_ATTR(enable_datasets, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -0700836 tpdm_show_enable_datasets, tpdm_store_enable_datasets);
837
838static ssize_t tpdm_show_gp_regs(struct device *dev,
839 struct device_attribute *attr,
840 char *buf)
841{
842 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
843 ssize_t size = 0;
844 int i = 0;
845
846 if (!test_bit(TPDM_DS_GPR, drvdata->datasets))
847 return -EPERM;
848
849 mutex_lock(&drvdata->lock);
850 for (i = 0; i < TPDM_GPR_REGS_MAX; i++) {
851 if (!test_bit(i, drvdata->gpr->gpr_dirty))
852 continue;
853 size += scnprintf(buf + size, PAGE_SIZE - size,
854 "Index: 0x%x Value: 0x%x\n", i,
855 drvdata->gpr->gp_regs[i]);
856 }
857 mutex_unlock(&drvdata->lock);
858 return size;
859}
860
861static ssize_t tpdm_store_gp_regs(struct device *dev,
862 struct device_attribute *attr,
863 const char *buf,
864 size_t size)
865{
866 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
867 unsigned long index, val;
868
869 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
870 return -EINVAL;
871 if (!test_bit(TPDM_DS_GPR, drvdata->datasets) ||
872 index >= TPDM_GPR_REGS_MAX)
873 return -EPERM;
874
875 mutex_lock(&drvdata->lock);
876 drvdata->gpr->gp_regs[index] = val;
877 __set_bit(index, drvdata->gpr->gpr_dirty);
878 mutex_unlock(&drvdata->lock);
879 return size;
880}
Satyajit Desai326497c2016-11-14 10:15:03 -0800881static DEVICE_ATTR(gp_regs, 0644, tpdm_show_gp_regs,
Satyajit Desaif151d682016-09-12 16:18:03 -0700882 tpdm_store_gp_regs);
883
884static ssize_t tpdm_show_bc_capture_mode(struct device *dev,
885 struct device_attribute *attr,
886 char *buf)
887{
888 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
889
890 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
891 return -EPERM;
892
893 return scnprintf(buf, PAGE_SIZE, "%s\n",
894 drvdata->bc->capture_mode == TPDM_MODE_ATB ?
895 "ATB" : "APB");
896}
897
898static ssize_t tpdm_store_bc_capture_mode(struct device *dev,
899 struct device_attribute *attr,
900 const char *buf,
901 size_t size)
902{
903 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
904 char str[20] = "";
905 uint32_t val;
906
907 if (size >= 20)
908 return -EINVAL;
909 if (sscanf(buf, "%s", str) != 1)
910 return -EINVAL;
911 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
912 return -EPERM;
913
914 mutex_lock(&drvdata->lock);
915 if (!drvdata->enable) {
916 mutex_unlock(&drvdata->lock);
917 return -EPERM;
918 }
919
920 if (!strcmp(str, "ATB")) {
921 drvdata->bc->capture_mode = TPDM_MODE_ATB;
922 } else if (!strcmp(str, "APB") &&
923 drvdata->bc->retrieval_mode == TPDM_MODE_APB) {
924
925 TPDM_UNLOCK(drvdata);
926 val = tpdm_readl(drvdata, TPDM_BC_CR);
927 val = val | BIT(3);
928 tpdm_writel(drvdata, val, TPDM_BC_CR);
929 TPDM_LOCK(drvdata);
930
931 drvdata->bc->capture_mode = TPDM_MODE_APB;
932 } else {
933 mutex_unlock(&drvdata->lock);
934 return -EINVAL;
935 }
936 mutex_unlock(&drvdata->lock);
937 return size;
938}
Satyajit Desai326497c2016-11-14 10:15:03 -0800939static DEVICE_ATTR(bc_capture_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -0700940 tpdm_show_bc_capture_mode, tpdm_store_bc_capture_mode);
941
942static ssize_t tpdm_show_bc_retrieval_mode(struct device *dev,
943 struct device_attribute *attr,
944 char *buf)
945{
946 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
947
948 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
949 return -EPERM;
950
951 return scnprintf(buf, PAGE_SIZE, "%s\n",
952 drvdata->bc->retrieval_mode == TPDM_MODE_ATB ?
953 "ATB" : "APB");
954}
955
956static ssize_t tpdm_store_bc_retrieval_mode(struct device *dev,
957 struct device_attribute *attr,
958 const char *buf,
959 size_t size)
960{
961 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
962 char str[20] = "";
963
964 if (size >= 20)
965 return -EINVAL;
966 if (sscanf(buf, "%s", str) != 1)
967 return -EINVAL;
968 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
969 return -EPERM;
970
971 mutex_lock(&drvdata->lock);
972 if (drvdata->enable) {
973 mutex_unlock(&drvdata->lock);
974 return -EPERM;
975 }
976
977 if (!strcmp(str, "ATB")) {
978 drvdata->bc->retrieval_mode = TPDM_MODE_ATB;
979 } else if (!strcmp(str, "APB")) {
980 drvdata->bc->retrieval_mode = TPDM_MODE_APB;
981 } else {
982 mutex_unlock(&drvdata->lock);
983 return -EINVAL;
984 }
985 mutex_unlock(&drvdata->lock);
986 return size;
987}
Satyajit Desai326497c2016-11-14 10:15:03 -0800988static DEVICE_ATTR(bc_retrieval_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -0700989 tpdm_show_bc_retrieval_mode, tpdm_store_bc_retrieval_mode);
990
991static ssize_t tpdm_store_bc_reset_counters(struct device *dev,
992 struct device_attribute *attr,
993 const char *buf,
994 size_t size)
995{
996 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
997 unsigned long val;
998
999 if (kstrtoul(buf, 16, &val))
1000 return -EINVAL;
1001 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1002 return -EPERM;
1003
1004 mutex_lock(&drvdata->lock);
1005 if (!drvdata->enable) {
1006 mutex_unlock(&drvdata->lock);
1007 return -EPERM;
1008 }
1009
1010 if (val) {
1011 TPDM_UNLOCK(drvdata);
1012 val = tpdm_readl(drvdata, TPDM_BC_CR);
1013 val = val | BIT(1);
1014 tpdm_writel(drvdata, val, TPDM_BC_CR);
1015 TPDM_LOCK(drvdata);
1016 }
1017 mutex_unlock(&drvdata->lock);
1018 return size;
1019}
Satyajit Desai326497c2016-11-14 10:15:03 -08001020static DEVICE_ATTR(bc_reset_counters, 0644, NULL,
Satyajit Desaif151d682016-09-12 16:18:03 -07001021 tpdm_store_bc_reset_counters);
1022
1023static ssize_t tpdm_show_bc_sat_mode(struct device *dev,
1024 struct device_attribute *attr,
1025 char *buf)
1026{
1027 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1028
1029 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1030 return -EPERM;
1031
1032 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1033 (unsigned long)drvdata->bc->sat_mode);
1034}
1035
1036static ssize_t tpdm_store_bc_sat_mode(struct device *dev,
1037 struct device_attribute *attr,
1038 const char *buf,
1039 size_t size)
1040{
1041 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1042 unsigned long val;
1043
1044 if (kstrtoul(buf, 16, &val))
1045 return -EINVAL;
1046 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1047 return -EPERM;
1048
1049 mutex_lock(&drvdata->lock);
1050 drvdata->bc->sat_mode = val;
1051 mutex_unlock(&drvdata->lock);
1052 return size;
1053}
Satyajit Desai326497c2016-11-14 10:15:03 -08001054static DEVICE_ATTR(bc_sat_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001055 tpdm_show_bc_sat_mode, tpdm_store_bc_sat_mode);
1056
1057static ssize_t tpdm_show_bc_enable_counters(struct device *dev,
1058 struct device_attribute *attr,
1059 char *buf)
1060{
1061 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1062
1063 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1064 return -EPERM;
1065
1066 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1067 (unsigned long)drvdata->bc->enable_counters);
1068}
1069
1070static ssize_t tpdm_store_bc_enable_counters(struct device *dev,
1071 struct device_attribute *attr,
1072 const char *buf,
1073 size_t size)
1074{
1075 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1076 unsigned long val;
1077
1078 if (kstrtoul(buf, 16, &val))
1079 return -EINVAL;
1080 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1081 return -EPERM;
1082
1083 mutex_lock(&drvdata->lock);
1084 drvdata->bc->enable_counters = val;
1085 mutex_unlock(&drvdata->lock);
1086 return size;
1087}
Satyajit Desai326497c2016-11-14 10:15:03 -08001088static DEVICE_ATTR(bc_enable_counters, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001089 tpdm_show_bc_enable_counters, tpdm_store_bc_enable_counters);
1090
1091static ssize_t tpdm_show_bc_clear_counters(struct device *dev,
1092 struct device_attribute *attr,
1093 char *buf)
1094{
1095 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1096
1097 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1098 return -EPERM;
1099
1100 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1101 (unsigned long)drvdata->bc->clear_counters);
1102}
1103
1104static ssize_t tpdm_store_bc_clear_counters(struct device *dev,
1105 struct device_attribute *attr,
1106 const char *buf,
1107 size_t size)
1108{
1109 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1110 unsigned long val;
1111
1112 if (kstrtoul(buf, 16, &val))
1113 return -EINVAL;
1114 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1115 return -EPERM;
1116
1117 mutex_lock(&drvdata->lock);
1118 drvdata->bc->clear_counters = val;
1119 mutex_unlock(&drvdata->lock);
1120 return size;
1121}
Satyajit Desai326497c2016-11-14 10:15:03 -08001122static DEVICE_ATTR(bc_clear_counters, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001123 tpdm_show_bc_clear_counters, tpdm_store_bc_clear_counters);
1124
1125static ssize_t tpdm_show_bc_enable_irq(struct device *dev,
1126 struct device_attribute *attr,
1127 char *buf)
1128{
1129 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1130
1131 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1132 return -EPERM;
1133
1134 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1135 (unsigned long)drvdata->bc->enable_irq);
1136}
1137
1138static ssize_t tpdm_store_bc_enable_irq(struct device *dev,
1139 struct device_attribute *attr,
1140 const char *buf,
1141 size_t size)
1142{
1143 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1144 unsigned long val;
1145
1146 if (kstrtoul(buf, 16, &val))
1147 return -EINVAL;
1148 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1149 return -EPERM;
1150
1151 mutex_lock(&drvdata->lock);
1152 drvdata->bc->enable_irq = val;
1153 mutex_unlock(&drvdata->lock);
1154 return size;
1155}
Satyajit Desai326497c2016-11-14 10:15:03 -08001156static DEVICE_ATTR(bc_enable_irq, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001157 tpdm_show_bc_enable_irq, tpdm_store_bc_enable_irq);
1158
1159static ssize_t tpdm_show_bc_clear_irq(struct device *dev,
1160 struct device_attribute *attr,
1161 char *buf)
1162{
1163 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1164
1165 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1166 return -EPERM;
1167
1168 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1169 (unsigned long)drvdata->bc->clear_irq);
1170}
1171
1172static ssize_t tpdm_store_bc_clear_irq(struct device *dev,
1173 struct device_attribute *attr,
1174 const char *buf,
1175 size_t size)
1176{
1177 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1178 unsigned long val;
1179
1180 if (kstrtoul(buf, 16, &val))
1181 return -EINVAL;
1182 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1183 return -EPERM;
1184
1185 mutex_lock(&drvdata->lock);
1186 drvdata->bc->clear_irq = val;
1187 mutex_unlock(&drvdata->lock);
1188 return size;
1189}
Satyajit Desai326497c2016-11-14 10:15:03 -08001190static DEVICE_ATTR(bc_clear_irq, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001191 tpdm_show_bc_clear_irq, tpdm_store_bc_clear_irq);
1192
1193static ssize_t tpdm_show_bc_trig_val_lo(struct device *dev,
1194 struct device_attribute *attr,
1195 char *buf)
1196{
1197 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1198 ssize_t size = 0;
1199 int i = 0;
1200
1201 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1202 return -EPERM;
1203
1204 mutex_lock(&drvdata->lock);
1205 for (i = 0; i < TPDM_BC_MAX_COUNTERS; i++)
1206 size += scnprintf(buf + size, PAGE_SIZE - size,
1207 "Index: 0x%x Value: 0x%x\n", i,
1208 drvdata->bc->trig_val_lo[i]);
1209 mutex_unlock(&drvdata->lock);
1210 return size;
1211}
1212
1213static ssize_t tpdm_store_bc_trig_val_lo(struct device *dev,
1214 struct device_attribute *attr,
1215 const char *buf,
1216 size_t size)
1217{
1218 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1219 unsigned long index, val;
1220
1221 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
1222 return -EINVAL;
1223 if (!test_bit(TPDM_DS_BC, drvdata->datasets) ||
1224 index >= drvdata->bc_counters_avail ||
1225 drvdata->bc_trig_type == TPDM_SUPPORT_TYPE_NO ||
1226 (drvdata->bc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL && index > 0))
1227 return -EPERM;
1228
1229 mutex_lock(&drvdata->lock);
1230 drvdata->bc->trig_val_lo[index] = val;
1231 mutex_unlock(&drvdata->lock);
1232 return size;
1233}
Satyajit Desai326497c2016-11-14 10:15:03 -08001234static DEVICE_ATTR(bc_trig_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001235 tpdm_show_bc_trig_val_lo, tpdm_store_bc_trig_val_lo);
1236
1237static ssize_t tpdm_show_bc_trig_val_hi(struct device *dev,
1238 struct device_attribute *attr,
1239 char *buf)
1240{
1241 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1242 ssize_t size = 0;
1243 int i = 0;
1244
1245 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1246 return -EPERM;
1247
1248 mutex_lock(&drvdata->lock);
1249 for (i = 0; i < TPDM_BC_MAX_COUNTERS; i++)
1250 size += scnprintf(buf + size, PAGE_SIZE - size,
1251 "Index: 0x%x Value: 0x%x\n", i,
1252 drvdata->bc->trig_val_hi[i]);
1253 mutex_unlock(&drvdata->lock);
1254 return size;
1255}
1256
1257static ssize_t tpdm_store_bc_trig_val_hi(struct device *dev,
1258 struct device_attribute *attr,
1259 const char *buf,
1260 size_t size)
1261{
1262 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1263 unsigned long index, val;
1264
1265 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
1266 return -EINVAL;
1267 if (!test_bit(TPDM_DS_BC, drvdata->datasets) ||
1268 index >= drvdata->bc_counters_avail ||
1269 drvdata->bc_trig_type == TPDM_SUPPORT_TYPE_NO ||
1270 (drvdata->bc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL && index > 0))
1271 return -EPERM;
1272
1273 mutex_lock(&drvdata->lock);
1274 drvdata->bc->trig_val_hi[index] = val;
1275 mutex_unlock(&drvdata->lock);
1276 return size;
1277}
Satyajit Desai326497c2016-11-14 10:15:03 -08001278static DEVICE_ATTR(bc_trig_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001279 tpdm_show_bc_trig_val_hi, tpdm_store_bc_trig_val_hi);
1280
1281static ssize_t tpdm_show_bc_enable_ganging(struct device *dev,
1282 struct device_attribute *attr,
1283 char *buf)
1284{
1285 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1286
1287 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1288 return -EPERM;
1289
1290 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1291 (unsigned long)drvdata->bc->enable_ganging);
1292}
1293
1294static ssize_t tpdm_store_bc_enable_ganging(struct device *dev,
1295 struct device_attribute *attr,
1296 const char *buf,
1297 size_t size)
1298{
1299 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1300 unsigned long val;
1301
1302 if (kstrtoul(buf, 16, &val))
1303 return -EINVAL;
1304 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1305 return -EPERM;
1306
1307 mutex_lock(&drvdata->lock);
1308 drvdata->bc->enable_ganging = val;
1309 mutex_unlock(&drvdata->lock);
1310 return size;
1311}
Satyajit Desai326497c2016-11-14 10:15:03 -08001312static DEVICE_ATTR(bc_enable_ganging, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001313 tpdm_show_bc_enable_ganging, tpdm_store_bc_enable_ganging);
1314
1315static ssize_t tpdm_show_bc_overflow_val(struct device *dev,
1316 struct device_attribute *attr,
1317 char *buf)
1318{
1319 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1320 ssize_t size = 0;
1321 int i = 0;
1322
1323 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1324 return -EPERM;
1325
1326 mutex_lock(&drvdata->lock);
1327 for (i = 0; i < TPDM_BC_MAX_OVERFLOW; i++)
1328 size += scnprintf(buf + size, PAGE_SIZE - size,
1329 "Index: 0x%x Value: 0x%x\n", i,
1330 drvdata->bc->overflow_val[i]);
1331 mutex_unlock(&drvdata->lock);
1332 return size;
1333}
1334
1335static ssize_t tpdm_store_bc_overflow_val(struct device *dev,
1336 struct device_attribute *attr,
1337 const char *buf,
1338 size_t size)
1339{
1340 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1341 unsigned long index, val;
1342
1343 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
1344 return -EINVAL;
1345 if (!test_bit(TPDM_DS_BC, drvdata->datasets) ||
1346 index >= TPDM_BC_MAX_OVERFLOW)
1347 return -EPERM;
1348
1349 mutex_lock(&drvdata->lock);
1350 drvdata->bc->overflow_val[index] = val;
1351 mutex_unlock(&drvdata->lock);
1352 return size;
1353}
Satyajit Desai326497c2016-11-14 10:15:03 -08001354static DEVICE_ATTR(bc_overflow_val, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001355 tpdm_show_bc_overflow_val, tpdm_store_bc_overflow_val);
1356
1357static ssize_t tpdm_show_bc_ovsr(struct device *dev,
1358 struct device_attribute *attr,
1359 char *buf)
1360{
1361 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1362 unsigned long val;
1363
1364 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1365 return -EPERM;
1366
1367 mutex_lock(&drvdata->lock);
1368 if (!drvdata->enable) {
1369 mutex_unlock(&drvdata->lock);
1370 return -EPERM;
1371 }
1372
1373 TPDM_UNLOCK(drvdata);
1374 val = tpdm_readl(drvdata, TPDM_BC_OVSR);
1375 TPDM_LOCK(drvdata);
1376 mutex_unlock(&drvdata->lock);
1377 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
1378}
1379
1380static ssize_t tpdm_store_bc_ovsr(struct device *dev,
1381 struct device_attribute *attr,
1382 const char *buf,
1383 size_t size)
1384{
1385 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1386 unsigned long val;
1387
1388 if (kstrtoul(buf, 16, &val))
1389 return -EINVAL;
1390 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1391 return -EPERM;
1392
1393 mutex_lock(&drvdata->lock);
1394 if (!drvdata->enable) {
1395 mutex_unlock(&drvdata->lock);
1396 return -EPERM;
1397 }
1398
1399 if (val) {
1400 TPDM_UNLOCK(drvdata);
1401 tpdm_writel(drvdata, val, TPDM_BC_OVSR);
1402 TPDM_LOCK(drvdata);
1403 }
1404 mutex_unlock(&drvdata->lock);
1405 return size;
1406}
Satyajit Desai326497c2016-11-14 10:15:03 -08001407static DEVICE_ATTR(bc_ovsr, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001408 tpdm_show_bc_ovsr, tpdm_store_bc_ovsr);
1409
1410static ssize_t tpdm_show_bc_counter_sel(struct device *dev,
1411 struct device_attribute *attr,
1412 char *buf)
1413{
1414 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1415 unsigned long val;
1416
1417 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1418 return -EPERM;
1419
1420 mutex_lock(&drvdata->lock);
1421 if (!drvdata->enable) {
1422 mutex_unlock(&drvdata->lock);
1423 return -EPERM;
1424 }
1425
1426 TPDM_UNLOCK(drvdata);
1427 val = tpdm_readl(drvdata, TPDM_BC_SELR);
1428 TPDM_LOCK(drvdata);
1429 mutex_unlock(&drvdata->lock);
1430 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
1431}
1432
1433static ssize_t tpdm_store_bc_counter_sel(struct device *dev,
1434 struct device_attribute *attr,
1435 const char *buf,
1436 size_t size)
1437{
1438 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1439 unsigned long val;
1440
1441 if (kstrtoul(buf, 16, &val))
1442 return -EINVAL;
1443 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1444 return -EPERM;
1445
1446 mutex_lock(&drvdata->lock);
1447 if (!drvdata->enable || val >= drvdata->bc_counters_avail) {
1448 mutex_unlock(&drvdata->lock);
1449 return -EPERM;
1450 }
1451
1452 TPDM_UNLOCK(drvdata);
1453 tpdm_writel(drvdata, val, TPDM_BC_SELR);
1454 TPDM_LOCK(drvdata);
1455 mutex_unlock(&drvdata->lock);
1456 return size;
1457}
Satyajit Desai326497c2016-11-14 10:15:03 -08001458static DEVICE_ATTR(bc_counter_sel, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001459 tpdm_show_bc_counter_sel, tpdm_store_bc_counter_sel);
1460
1461static ssize_t tpdm_show_bc_count_val_lo(struct device *dev,
1462 struct device_attribute *attr,
1463 char *buf)
1464{
1465 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1466 unsigned long val;
1467
1468 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1469 return -EPERM;
1470
1471 mutex_lock(&drvdata->lock);
1472 if (!drvdata->enable) {
1473 mutex_unlock(&drvdata->lock);
1474 return -EPERM;
1475 }
1476
1477 TPDM_UNLOCK(drvdata);
1478 val = tpdm_readl(drvdata, TPDM_BC_CNTR_LO);
1479 TPDM_LOCK(drvdata);
1480 mutex_unlock(&drvdata->lock);
1481 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
1482}
1483
1484static ssize_t tpdm_store_bc_count_val_lo(struct device *dev,
1485 struct device_attribute *attr,
1486 const char *buf,
1487 size_t size)
1488{
1489 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1490 unsigned long val, select;
1491
1492 if (kstrtoul(buf, 16, &val))
1493 return -EINVAL;
1494 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1495 return -EPERM;
1496
1497 mutex_lock(&drvdata->lock);
1498 if (!drvdata->enable) {
1499 mutex_unlock(&drvdata->lock);
1500 return -EPERM;
1501 }
1502
1503 if (val) {
1504 TPDM_UNLOCK(drvdata);
1505 select = tpdm_readl(drvdata, TPDM_BC_SELR);
1506
1507 /* Check if selected counter is disabled */
1508 if (BVAL(tpdm_readl(drvdata, TPDM_BC_CNTENSET), select)) {
1509 mutex_unlock(&drvdata->lock);
1510 return -EPERM;
1511 }
1512
1513 tpdm_writel(drvdata, val, TPDM_BC_CNTR_LO);
1514 TPDM_LOCK(drvdata);
1515 }
1516 mutex_unlock(&drvdata->lock);
1517 return size;
1518}
Satyajit Desai326497c2016-11-14 10:15:03 -08001519static DEVICE_ATTR(bc_count_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001520 tpdm_show_bc_count_val_lo, tpdm_store_bc_count_val_lo);
1521
1522static ssize_t tpdm_show_bc_count_val_hi(struct device *dev,
1523 struct device_attribute *attr,
1524 char *buf)
1525{
1526 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1527 unsigned long val;
1528
1529 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1530 return -EPERM;
1531
1532 mutex_lock(&drvdata->lock);
1533 if (!drvdata->enable) {
1534 mutex_unlock(&drvdata->lock);
1535 return -EPERM;
1536 }
1537
1538 TPDM_UNLOCK(drvdata);
1539 val = tpdm_readl(drvdata, TPDM_BC_CNTR_HI);
1540 TPDM_LOCK(drvdata);
1541 mutex_unlock(&drvdata->lock);
1542 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
1543}
1544
1545static ssize_t tpdm_store_bc_count_val_hi(struct device *dev,
1546 struct device_attribute *attr,
1547 const char *buf,
1548 size_t size)
1549{
1550 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1551 unsigned long val, select;
1552
1553 if (kstrtoul(buf, 16, &val))
1554 return -EINVAL;
1555 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1556 return -EPERM;
1557
1558 mutex_lock(&drvdata->lock);
1559 if (!drvdata->enable) {
1560 mutex_unlock(&drvdata->lock);
1561 return -EPERM;
1562 }
1563
1564 if (val) {
1565 TPDM_UNLOCK(drvdata);
1566 select = tpdm_readl(drvdata, TPDM_BC_SELR);
1567
1568 /* Check if selected counter is disabled */
1569 if (BVAL(tpdm_readl(drvdata, TPDM_BC_CNTENSET), select)) {
1570 mutex_unlock(&drvdata->lock);
1571 return -EPERM;
1572 }
1573
1574 tpdm_writel(drvdata, val, TPDM_BC_CNTR_HI);
1575 TPDM_LOCK(drvdata);
1576 }
1577 mutex_unlock(&drvdata->lock);
1578 return size;
1579}
Satyajit Desai326497c2016-11-14 10:15:03 -08001580static DEVICE_ATTR(bc_count_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001581 tpdm_show_bc_count_val_hi, tpdm_store_bc_count_val_hi);
1582
1583static ssize_t tpdm_show_bc_shadow_val_lo(struct device *dev,
1584 struct device_attribute *attr,
1585 char *buf)
1586{
1587 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1588 ssize_t size = 0;
1589 int i = 0;
1590
1591 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1592 return -EPERM;
1593
1594 mutex_lock(&drvdata->lock);
1595 if (!drvdata->enable) {
1596 mutex_unlock(&drvdata->lock);
1597 return -EPERM;
1598 }
1599
1600 TPDM_UNLOCK(drvdata);
1601 for (i = 0; i < drvdata->bc_counters_avail; i++) {
1602 size += scnprintf(buf + size, PAGE_SIZE - size,
1603 "Index: 0x%x Value: 0x%x\n", i,
1604 tpdm_readl(drvdata, TPDM_BC_SHADOW_LO(i)));
1605 }
1606 TPDM_LOCK(drvdata);
1607 mutex_unlock(&drvdata->lock);
1608 return size;
1609}
Satyajit Desai326497c2016-11-14 10:15:03 -08001610static DEVICE_ATTR(bc_shadow_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001611 tpdm_show_bc_shadow_val_lo, NULL);
1612
1613static ssize_t tpdm_show_bc_shadow_val_hi(struct device *dev,
1614 struct device_attribute *attr,
1615 char *buf)
1616{
1617 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1618 ssize_t size = 0;
1619 int i = 0;
1620
1621 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1622 return -EPERM;
1623
1624 mutex_lock(&drvdata->lock);
1625 if (!drvdata->enable) {
1626 mutex_unlock(&drvdata->lock);
1627 return -EPERM;
1628 }
1629
1630 TPDM_UNLOCK(drvdata);
1631 for (i = 0; i < drvdata->bc_counters_avail; i++)
1632 size += scnprintf(buf + size, PAGE_SIZE - size,
1633 "Index: 0x%x Value: 0x%x\n", i,
1634 tpdm_readl(drvdata, TPDM_BC_SHADOW_HI(i)));
1635 TPDM_LOCK(drvdata);
1636 mutex_unlock(&drvdata->lock);
1637 return size;
1638}
Satyajit Desai326497c2016-11-14 10:15:03 -08001639static DEVICE_ATTR(bc_shadow_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001640 tpdm_show_bc_shadow_val_hi, NULL);
1641
1642static ssize_t tpdm_show_bc_sw_inc(struct device *dev,
1643 struct device_attribute *attr,
1644 char *buf)
1645{
1646 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1647 unsigned long val;
1648
1649 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1650 return -EPERM;
1651
1652 mutex_lock(&drvdata->lock);
1653 if (!drvdata->enable) {
1654 mutex_unlock(&drvdata->lock);
1655 return -EPERM;
1656 }
1657
1658 TPDM_UNLOCK(drvdata);
1659 val = tpdm_readl(drvdata, TPDM_BC_SWINC);
1660 TPDM_LOCK(drvdata);
1661 mutex_unlock(&drvdata->lock);
1662 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
1663}
1664
1665static ssize_t tpdm_store_bc_sw_inc(struct device *dev,
1666 struct device_attribute *attr,
1667 const char *buf,
1668 size_t size)
1669{
1670 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1671 unsigned long val;
1672
1673 if (kstrtoul(buf, 16, &val))
1674 return -EINVAL;
1675 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1676 return -EPERM;
1677
1678 mutex_lock(&drvdata->lock);
1679 if (!drvdata->enable) {
1680 mutex_unlock(&drvdata->lock);
1681 return -EPERM;
1682 }
1683
1684 if (val) {
1685 TPDM_UNLOCK(drvdata);
1686 tpdm_writel(drvdata, val, TPDM_BC_SWINC);
1687 TPDM_LOCK(drvdata);
1688 }
1689 mutex_unlock(&drvdata->lock);
1690 return size;
1691}
Satyajit Desai326497c2016-11-14 10:15:03 -08001692static DEVICE_ATTR(bc_sw_inc, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001693 tpdm_show_bc_sw_inc, tpdm_store_bc_sw_inc);
1694
Satyajit Desaib34b2c02017-01-11 16:59:38 -08001695static ssize_t tpdm_show_bc_msr(struct device *dev,
1696 struct device_attribute *attr,
1697 char *buf)
1698{
1699 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1700 unsigned int i;
1701 ssize_t len = 0;
1702
1703 if (!drvdata->msr_support)
1704 return -EINVAL;
1705
1706 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1707 return -EPERM;
1708
1709 for (i = 0; i < TPDM_BC_MAX_MSR; i++)
1710 len += scnprintf(buf + len, PAGE_SIZE - len, "%u 0x%x\n",
1711 i, drvdata->bc->msr[i]);
1712
1713 return len;
1714}
1715
Satyajit Desaif151d682016-09-12 16:18:03 -07001716static ssize_t tpdm_store_bc_msr(struct device *dev,
1717 struct device_attribute *attr,
1718 const char *buf,
1719 size_t size)
1720{
1721 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1722 unsigned int num, val;
1723 int nval;
1724
1725 if (!drvdata->msr_support)
1726 return -EINVAL;
1727
1728 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1729 return -EPERM;
1730
1731 nval = sscanf(buf, "%u %x", &num, &val);
1732 if (nval != 2)
1733 return -EINVAL;
1734
1735 if (num >= TPDM_BC_MAX_MSR)
1736 return -EINVAL;
1737
1738 mutex_lock(&drvdata->lock);
1739 drvdata->bc->msr[num] = val;
1740 mutex_unlock(&drvdata->lock);
1741 return size;
1742}
Satyajit Desaib34b2c02017-01-11 16:59:38 -08001743static DEVICE_ATTR(bc_msr, 0644, tpdm_show_bc_msr, tpdm_store_bc_msr);
Satyajit Desaif151d682016-09-12 16:18:03 -07001744
1745static ssize_t tpdm_show_tc_capture_mode(struct device *dev,
1746 struct device_attribute *attr,
1747 char *buf)
1748{
1749 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1750
1751 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1752 return -EPERM;
1753
1754 return scnprintf(buf, PAGE_SIZE, "%s\n",
1755 drvdata->tc->capture_mode == TPDM_MODE_ATB ?
1756 "ATB" : "APB");
1757}
1758
1759static ssize_t tpdm_store_tc_capture_mode(struct device *dev,
1760 struct device_attribute *attr,
1761 const char *buf,
1762 size_t size)
1763{
1764 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1765 char str[20] = "";
1766 uint32_t val;
1767
1768 if (size >= 20)
1769 return -EINVAL;
1770 if (sscanf(buf, "%s", str) != 1)
1771 return -EINVAL;
1772 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
1773 return -EPERM;
1774
1775 mutex_lock(&drvdata->lock);
1776 if (!drvdata->enable) {
1777 mutex_unlock(&drvdata->lock);
1778 return -EPERM;
1779 }
1780
1781 if (!strcmp(str, "ATB")) {
1782 drvdata->tc->capture_mode = TPDM_MODE_ATB;
1783 } else if (!strcmp(str, "APB") &&
1784 drvdata->tc->retrieval_mode == TPDM_MODE_APB) {
1785
1786 TPDM_UNLOCK(drvdata);
1787 val = tpdm_readl(drvdata, TPDM_TC_CR);
1788 val = val | BIT(3);
1789 tpdm_writel(drvdata, val, TPDM_TC_CR);
1790 TPDM_LOCK(drvdata);
1791
1792 drvdata->tc->capture_mode = TPDM_MODE_APB;
1793 } else {
1794 mutex_unlock(&drvdata->lock);
1795 return -EINVAL;
1796 }
1797 mutex_unlock(&drvdata->lock);
1798 return size;
1799}
Satyajit Desai326497c2016-11-14 10:15:03 -08001800static DEVICE_ATTR(tc_capture_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001801 tpdm_show_tc_capture_mode, tpdm_store_tc_capture_mode);
1802
1803static ssize_t tpdm_show_tc_retrieval_mode(struct device *dev,
1804 struct device_attribute *attr,
1805 char *buf)
1806{
1807 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1808
1809 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1810 return -EPERM;
1811
1812 return scnprintf(buf, PAGE_SIZE, "%s\n",
1813 drvdata->tc->retrieval_mode == TPDM_MODE_ATB ?
1814 "ATB" : "APB");
1815}
1816
1817static ssize_t tpdm_store_tc_retrieval_mode(struct device *dev,
1818 struct device_attribute *attr,
1819 const char *buf,
1820 size_t size)
1821{
1822 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1823 char str[20] = "";
1824
1825 if (size >= 20)
1826 return -EINVAL;
1827 if (sscanf(buf, "%s", str) != 1)
1828 return -EINVAL;
1829 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1830 return -EPERM;
1831
1832 mutex_lock(&drvdata->lock);
1833 if (drvdata->enable) {
1834 mutex_unlock(&drvdata->lock);
1835 return -EPERM;
1836 }
1837
1838 if (!strcmp(str, "ATB")) {
1839 drvdata->tc->retrieval_mode = TPDM_MODE_ATB;
1840 } else if (!strcmp(str, "APB")) {
1841 drvdata->tc->retrieval_mode = TPDM_MODE_APB;
1842 } else {
1843 mutex_unlock(&drvdata->lock);
1844 return -EINVAL;
1845 }
1846 mutex_unlock(&drvdata->lock);
1847 return size;
1848}
Satyajit Desai326497c2016-11-14 10:15:03 -08001849static DEVICE_ATTR(tc_retrieval_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001850 tpdm_show_tc_retrieval_mode, tpdm_store_tc_retrieval_mode);
1851
1852static ssize_t tpdm_store_tc_reset_counters(struct device *dev,
1853 struct device_attribute *attr,
1854 const char *buf,
1855 size_t size)
1856{
1857 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1858 unsigned long val;
1859
1860 if (kstrtoul(buf, 16, &val))
1861 return -EINVAL;
1862 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1863 return -EPERM;
1864
1865 mutex_lock(&drvdata->lock);
1866 if (!drvdata->enable) {
1867 mutex_unlock(&drvdata->lock);
1868 return -EPERM;
1869 }
1870
1871 if (val) {
1872 TPDM_UNLOCK(drvdata);
1873 val = tpdm_readl(drvdata, TPDM_TC_CR);
1874 val = val | BIT(1);
1875 tpdm_writel(drvdata, val, TPDM_TC_CR);
1876 TPDM_LOCK(drvdata);
1877 }
1878 mutex_unlock(&drvdata->lock);
1879 return size;
1880}
Satyajit Desai326497c2016-11-14 10:15:03 -08001881static DEVICE_ATTR(tc_reset_counters, 0644, NULL,
Satyajit Desaif151d682016-09-12 16:18:03 -07001882 tpdm_store_tc_reset_counters);
1883
1884static ssize_t tpdm_show_tc_sat_mode(struct device *dev,
1885 struct device_attribute *attr,
1886 char *buf)
1887{
1888 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1889
1890 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1891 return -EPERM;
1892
1893 return scnprintf(buf, PAGE_SIZE, "%u\n",
1894 (unsigned int)drvdata->tc->sat_mode);
1895}
1896
1897static ssize_t tpdm_store_tc_sat_mode(struct device *dev,
1898 struct device_attribute *attr,
1899 const char *buf,
1900 size_t size)
1901{
1902 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1903 unsigned long val;
1904
1905 if (kstrtoul(buf, 16, &val))
1906 return -EINVAL;
1907 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1908 return -EPERM;
1909
1910 mutex_lock(&drvdata->lock);
1911 if (val)
1912 drvdata->tc->sat_mode = true;
1913 else
1914 drvdata->tc->sat_mode = false;
1915 mutex_unlock(&drvdata->lock);
1916 return size;
1917}
Satyajit Desai326497c2016-11-14 10:15:03 -08001918static DEVICE_ATTR(tc_sat_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001919 tpdm_show_tc_sat_mode, tpdm_store_tc_sat_mode);
1920
1921static ssize_t tpdm_show_tc_enable_counters(struct device *dev,
1922 struct device_attribute *attr,
1923 char *buf)
1924{
1925 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1926
1927 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1928 return -EPERM;
1929
1930 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1931 (unsigned long)drvdata->tc->enable_counters);
1932}
1933
1934static ssize_t tpdm_store_tc_enable_counters(struct device *dev,
1935 struct device_attribute *attr,
1936 const char *buf,
1937 size_t size)
1938{
1939 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1940 unsigned long val;
1941
1942 if (kstrtoul(buf, 16, &val))
1943 return -EINVAL;
1944 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1945 return -EPERM;
1946 if (val >> drvdata->tc_counters_avail)
1947 return -EPERM;
1948
1949 mutex_lock(&drvdata->lock);
1950 drvdata->tc->enable_counters = val;
1951 mutex_unlock(&drvdata->lock);
1952 return size;
1953}
Satyajit Desai326497c2016-11-14 10:15:03 -08001954static DEVICE_ATTR(tc_enable_counters, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001955 tpdm_show_tc_enable_counters, tpdm_store_tc_enable_counters);
1956
1957static ssize_t tpdm_show_tc_clear_counters(struct device *dev,
1958 struct device_attribute *attr,
1959 char *buf)
1960{
1961 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1962
1963 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1964 return -EPERM;
1965
1966 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1967 (unsigned long)drvdata->tc->clear_counters);
1968}
1969
1970static ssize_t tpdm_store_tc_clear_counters(struct device *dev,
1971 struct device_attribute *attr,
1972 const char *buf,
1973 size_t size)
1974{
1975 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1976 unsigned long val;
1977
1978 if (kstrtoul(buf, 16, &val))
1979 return -EINVAL;
1980 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1981 return -EPERM;
1982 if (val >> drvdata->tc_counters_avail)
1983 return -EPERM;
1984
1985 mutex_lock(&drvdata->lock);
1986 drvdata->tc->clear_counters = val;
1987 mutex_unlock(&drvdata->lock);
1988 return size;
1989}
Satyajit Desai326497c2016-11-14 10:15:03 -08001990static DEVICE_ATTR(tc_clear_counters, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001991 tpdm_show_tc_clear_counters, tpdm_store_tc_clear_counters);
1992
1993static ssize_t tpdm_show_tc_enable_irq(struct device *dev,
1994 struct device_attribute *attr,
1995 char *buf)
1996{
1997 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1998
1999 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2000 return -EPERM;
2001
2002 return scnprintf(buf, PAGE_SIZE, "%lx\n",
2003 (unsigned long)drvdata->tc->enable_irq);
2004}
2005
2006static ssize_t tpdm_store_tc_enable_irq(struct device *dev,
2007 struct device_attribute *attr,
2008 const char *buf,
2009 size_t size)
2010{
2011 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2012 unsigned long val;
2013
2014 if (kstrtoul(buf, 16, &val))
2015 return -EINVAL;
2016 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2017 return -EPERM;
2018
2019 mutex_lock(&drvdata->lock);
2020 drvdata->tc->enable_irq = val;
2021 mutex_unlock(&drvdata->lock);
2022 return size;
2023}
Satyajit Desai326497c2016-11-14 10:15:03 -08002024static DEVICE_ATTR(tc_enable_irq, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002025 tpdm_show_tc_enable_irq, tpdm_store_tc_enable_irq);
2026
2027static ssize_t tpdm_show_tc_clear_irq(struct device *dev,
2028 struct device_attribute *attr,
2029 char *buf)
2030{
2031 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2032
2033 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2034 return -EPERM;
2035
2036 return scnprintf(buf, PAGE_SIZE, "%lx\n",
2037 (unsigned long)drvdata->tc->clear_irq);
2038}
2039
2040static ssize_t tpdm_store_tc_clear_irq(struct device *dev,
2041 struct device_attribute *attr,
2042 const char *buf,
2043 size_t size)
2044{
2045 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2046 unsigned long val;
2047
2048 if (kstrtoul(buf, 16, &val))
2049 return -EINVAL;
2050 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2051 return -EPERM;
2052
2053 mutex_lock(&drvdata->lock);
2054 drvdata->tc->clear_irq = val;
2055 mutex_unlock(&drvdata->lock);
2056 return size;
2057}
Satyajit Desai326497c2016-11-14 10:15:03 -08002058static DEVICE_ATTR(tc_clear_irq, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002059 tpdm_show_tc_clear_irq, tpdm_store_tc_clear_irq);
2060
2061static ssize_t tpdm_show_tc_trig_sel(struct device *dev,
2062 struct device_attribute *attr,
2063 char *buf)
2064{
2065 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2066 ssize_t size = 0;
2067 int i = 0;
2068
2069 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2070 return -EPERM;
2071
2072 mutex_lock(&drvdata->lock);
2073 for (i = 0; i < TPDM_TC_MAX_TRIG; i++) {
2074 size += scnprintf(buf + size, PAGE_SIZE - size,
2075 "Index: 0x%x Value: 0x%x\n", i,
2076 drvdata->tc->trig_sel[i]);
2077 }
2078 mutex_unlock(&drvdata->lock);
2079 return size;
2080}
2081
2082static ssize_t tpdm_store_tc_trig_sel(struct device *dev,
2083 struct device_attribute *attr,
2084 const char *buf,
2085 size_t size)
2086{
2087 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2088 unsigned long index, val;
2089
2090 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2091 return -EINVAL;
2092 if (!test_bit(TPDM_DS_TC, drvdata->datasets) ||
2093 index >= TPDM_TC_MAX_TRIG ||
2094 drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_NO ||
2095 (drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL && index > 0))
2096 return -EPERM;
2097
2098 mutex_lock(&drvdata->lock);
2099 drvdata->tc->trig_sel[index] = val;
2100 mutex_unlock(&drvdata->lock);
2101 return size;
2102}
Satyajit Desai326497c2016-11-14 10:15:03 -08002103static DEVICE_ATTR(tc_trig_sel, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002104 tpdm_show_tc_trig_sel, tpdm_store_tc_trig_sel);
2105
2106static ssize_t tpdm_show_tc_trig_val_lo(struct device *dev,
2107 struct device_attribute *attr,
2108 char *buf)
2109{
2110 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2111 ssize_t size = 0;
2112 int i = 0;
2113
2114 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2115 return -EPERM;
2116
2117 mutex_lock(&drvdata->lock);
2118 for (i = 0; i < TPDM_TC_MAX_TRIG; i++) {
2119 size += scnprintf(buf + size, PAGE_SIZE - size,
2120 "Index: 0x%x Value: 0x%x\n", i,
2121 drvdata->tc->trig_val_lo[i]);
2122 }
2123 mutex_unlock(&drvdata->lock);
2124 return size;
2125}
2126
2127static ssize_t tpdm_store_tc_trig_val_lo(struct device *dev,
2128 struct device_attribute *attr,
2129 const char *buf,
2130 size_t size)
2131{
2132 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2133 unsigned long index, val;
2134
2135 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2136 return -EINVAL;
2137 if (!test_bit(TPDM_DS_TC, drvdata->datasets) ||
2138 index >= TPDM_TC_MAX_TRIG ||
2139 drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_NO ||
2140 (drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL && index > 0))
2141 return -EPERM;
2142
2143 mutex_lock(&drvdata->lock);
2144 drvdata->tc->trig_val_lo[index] = val;
2145 mutex_unlock(&drvdata->lock);
2146 return size;
2147}
Satyajit Desai326497c2016-11-14 10:15:03 -08002148static DEVICE_ATTR(tc_trig_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002149 tpdm_show_tc_trig_val_lo, tpdm_store_tc_trig_val_lo);
2150
2151static ssize_t tpdm_show_tc_trig_val_hi(struct device *dev,
2152 struct device_attribute *attr,
2153 char *buf)
2154{
2155 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2156 ssize_t size = 0;
2157 int i = 0;
2158
2159 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2160 return -EPERM;
2161
2162 mutex_lock(&drvdata->lock);
2163 for (i = 0; i < TPDM_TC_MAX_TRIG; i++) {
2164 size += scnprintf(buf + size, PAGE_SIZE - size,
2165 "Index: 0x%x Value: 0x%x\n", i,
2166 drvdata->tc->trig_val_hi[i]);
2167 }
2168 mutex_unlock(&drvdata->lock);
2169 return size;
2170}
2171
2172static ssize_t tpdm_store_tc_trig_val_hi(struct device *dev,
2173 struct device_attribute *attr,
2174 const char *buf,
2175 size_t size)
2176{
2177 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2178 unsigned long index, val;
2179
2180 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2181 return -EINVAL;
2182 if (!test_bit(TPDM_DS_TC, drvdata->datasets) ||
2183 index >= TPDM_TC_MAX_TRIG ||
2184 drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_NO ||
2185 (drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL && index > 0))
2186 return -EPERM;
2187
2188 mutex_lock(&drvdata->lock);
2189 drvdata->tc->trig_val_hi[index] = val;
2190 mutex_unlock(&drvdata->lock);
2191 return size;
2192}
Satyajit Desai326497c2016-11-14 10:15:03 -08002193static DEVICE_ATTR(tc_trig_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002194 tpdm_show_tc_trig_val_hi, tpdm_store_tc_trig_val_hi);
2195
2196static ssize_t tpdm_show_tc_ovsr_gp(struct device *dev,
2197 struct device_attribute *attr,
2198 char *buf)
2199{
2200 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2201 unsigned long val;
2202
2203 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2204 return -EPERM;
2205
2206 mutex_lock(&drvdata->lock);
2207 if (!drvdata->enable) {
2208 mutex_unlock(&drvdata->lock);
2209 return -EPERM;
2210 }
2211
2212 TPDM_UNLOCK(drvdata);
2213 val = tpdm_readl(drvdata, TPDM_TC_OVSR_GP);
2214 TPDM_LOCK(drvdata);
2215 mutex_unlock(&drvdata->lock);
2216 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2217}
2218
2219static ssize_t tpdm_store_tc_ovsr_gp(struct device *dev,
2220 struct device_attribute *attr,
2221 const char *buf,
2222 size_t size)
2223{
2224 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2225 unsigned long val;
2226
2227 if (kstrtoul(buf, 16, &val))
2228 return -EINVAL;
2229 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2230 return -EPERM;
2231
2232 mutex_lock(&drvdata->lock);
2233 if (!drvdata->enable) {
2234 mutex_unlock(&drvdata->lock);
2235 return -EPERM;
2236 }
2237
2238 if (val) {
2239 TPDM_UNLOCK(drvdata);
2240 tpdm_writel(drvdata, val, TPDM_TC_OVSR_GP);
2241 TPDM_LOCK(drvdata);
2242 }
2243 mutex_unlock(&drvdata->lock);
2244 return size;
2245}
Satyajit Desai326497c2016-11-14 10:15:03 -08002246static DEVICE_ATTR(tc_ovsr_gp, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002247 tpdm_show_tc_ovsr_gp, tpdm_store_tc_ovsr_gp);
2248
2249static ssize_t tpdm_show_tc_ovsr_impl(struct device *dev,
2250 struct device_attribute *attr,
2251 char *buf)
2252{
2253 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2254 unsigned long val;
2255
2256 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2257 return -EPERM;
2258
2259 mutex_lock(&drvdata->lock);
2260 if (!drvdata->enable) {
2261 mutex_unlock(&drvdata->lock);
2262 return -EPERM;
2263 }
2264
2265 TPDM_UNLOCK(drvdata);
2266 val = tpdm_readl(drvdata, TPDM_TC_OVSR_IMPL);
2267 TPDM_LOCK(drvdata);
2268 mutex_unlock(&drvdata->lock);
2269 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2270}
2271
2272static ssize_t tpdm_store_tc_ovsr_impl(struct device *dev,
2273 struct device_attribute *attr,
2274 const char *buf,
2275 size_t size)
2276{
2277 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2278 unsigned long val;
2279
2280 if (kstrtoul(buf, 16, &val))
2281 return -EINVAL;
2282 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2283 return -EPERM;
2284
2285 mutex_lock(&drvdata->lock);
2286 if (!drvdata->enable) {
2287 mutex_unlock(&drvdata->lock);
2288 return -EPERM;
2289 }
2290
2291 if (val) {
2292 TPDM_UNLOCK(drvdata);
2293 tpdm_writel(drvdata, val, TPDM_TC_OVSR_IMPL);
2294 TPDM_LOCK(drvdata);
2295 }
2296 mutex_unlock(&drvdata->lock);
2297 return size;
2298}
Satyajit Desai326497c2016-11-14 10:15:03 -08002299static DEVICE_ATTR(tc_ovsr_impl, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002300 tpdm_show_tc_ovsr_impl, tpdm_store_tc_ovsr_impl);
2301
2302static ssize_t tpdm_show_tc_counter_sel(struct device *dev,
2303 struct device_attribute *attr,
2304 char *buf)
2305{
2306 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2307 unsigned long val;
2308
2309 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2310 return -EPERM;
2311
2312 mutex_lock(&drvdata->lock);
2313 if (!drvdata->enable) {
2314 mutex_unlock(&drvdata->lock);
2315 return -EPERM;
2316 }
2317
2318 TPDM_UNLOCK(drvdata);
2319 val = tpdm_readl(drvdata, TPDM_TC_SELR);
2320 TPDM_LOCK(drvdata);
2321 mutex_unlock(&drvdata->lock);
2322 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2323}
2324
2325static ssize_t tpdm_store_tc_counter_sel(struct device *dev,
2326 struct device_attribute *attr,
2327 const char *buf,
2328 size_t size)
2329{
2330 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2331 unsigned long val;
2332
2333 if (kstrtoul(buf, 16, &val))
2334 return -EINVAL;
2335 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2336 return -EPERM;
2337
2338 mutex_lock(&drvdata->lock);
2339 if (!drvdata->enable) {
2340 mutex_unlock(&drvdata->lock);
2341 return -EPERM;
2342 }
2343
2344 TPDM_UNLOCK(drvdata);
2345 tpdm_writel(drvdata, val, TPDM_TC_SELR);
2346 TPDM_LOCK(drvdata);
2347 mutex_unlock(&drvdata->lock);
2348 return size;
2349}
Satyajit Desai326497c2016-11-14 10:15:03 -08002350static DEVICE_ATTR(tc_counter_sel, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002351 tpdm_show_tc_counter_sel, tpdm_store_tc_counter_sel);
2352
2353static ssize_t tpdm_show_tc_count_val_lo(struct device *dev,
2354 struct device_attribute *attr,
2355 char *buf)
2356{
2357 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2358 unsigned long val;
2359
2360 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2361 return -EPERM;
2362
2363 mutex_lock(&drvdata->lock);
2364 if (!drvdata->enable) {
2365 mutex_unlock(&drvdata->lock);
2366 return -EPERM;
2367 }
2368
2369 TPDM_UNLOCK(drvdata);
2370 val = tpdm_readl(drvdata, TPDM_TC_CNTR_LO);
2371 TPDM_LOCK(drvdata);
2372 mutex_unlock(&drvdata->lock);
2373 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2374}
2375
2376static ssize_t tpdm_store_tc_count_val_lo(struct device *dev,
2377 struct device_attribute *attr,
2378 const char *buf,
2379 size_t size)
2380{
2381 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2382 unsigned long val, select;
2383
2384 if (kstrtoul(buf, 16, &val))
2385 return -EINVAL;
2386 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2387 return -EPERM;
2388
2389 mutex_lock(&drvdata->lock);
2390 if (!drvdata->enable) {
2391 mutex_unlock(&drvdata->lock);
2392 return -EPERM;
2393 }
2394
2395 if (val) {
2396 TPDM_UNLOCK(drvdata);
2397 select = tpdm_readl(drvdata, TPDM_TC_SELR);
2398 select = (select >> 11) & 0x3;
2399
2400 /* Check if selected counter is disabled */
2401 if (BVAL(tpdm_readl(drvdata, TPDM_TC_CNTENSET), select)) {
2402 mutex_unlock(&drvdata->lock);
2403 return -EPERM;
2404 }
2405
2406 tpdm_writel(drvdata, val, TPDM_TC_CNTR_LO);
2407 TPDM_LOCK(drvdata);
2408 }
2409 mutex_unlock(&drvdata->lock);
2410 return size;
2411}
Satyajit Desai326497c2016-11-14 10:15:03 -08002412static DEVICE_ATTR(tc_count_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002413 tpdm_show_tc_count_val_lo, tpdm_store_tc_count_val_lo);
2414
2415static ssize_t tpdm_show_tc_count_val_hi(struct device *dev,
2416 struct device_attribute *attr,
2417 char *buf)
2418{
2419 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2420 unsigned long val;
2421
2422 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2423 return -EPERM;
2424
2425 mutex_lock(&drvdata->lock);
2426 if (!drvdata->enable) {
2427 mutex_unlock(&drvdata->lock);
2428 return -EPERM;
2429 }
2430
2431 TPDM_UNLOCK(drvdata);
2432 val = tpdm_readl(drvdata, TPDM_TC_CNTR_HI);
2433 TPDM_LOCK(drvdata);
2434 mutex_unlock(&drvdata->lock);
2435 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2436}
2437
2438static ssize_t tpdm_store_tc_count_val_hi(struct device *dev,
2439 struct device_attribute *attr,
2440 const char *buf,
2441 size_t size)
2442{
2443 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2444 unsigned long val, select;
2445
2446 if (kstrtoul(buf, 16, &val))
2447 return -EINVAL;
2448 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2449 return -EPERM;
2450
2451 mutex_lock(&drvdata->lock);
2452 if (!drvdata->enable) {
2453 mutex_unlock(&drvdata->lock);
2454 return -EPERM;
2455 }
2456
2457 if (val) {
2458 TPDM_UNLOCK(drvdata);
2459 select = tpdm_readl(drvdata, TPDM_TC_SELR);
2460 select = (select >> 11) & 0x3;
2461
2462 /* Check if selected counter is disabled */
2463 if (BVAL(tpdm_readl(drvdata, TPDM_TC_CNTENSET), select)) {
2464 mutex_unlock(&drvdata->lock);
2465 return -EPERM;
2466 }
2467
2468 tpdm_writel(drvdata, val, TPDM_TC_CNTR_HI);
2469 TPDM_LOCK(drvdata);
2470 }
2471 mutex_unlock(&drvdata->lock);
2472 return size;
2473}
Satyajit Desai326497c2016-11-14 10:15:03 -08002474static DEVICE_ATTR(tc_count_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002475 tpdm_show_tc_count_val_hi, tpdm_store_tc_count_val_hi);
2476
2477static ssize_t tpdm_show_tc_shadow_val_lo(struct device *dev,
2478 struct device_attribute *attr,
2479 char *buf)
2480{
2481 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2482 ssize_t size = 0;
2483 int i = 0;
2484
2485 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2486 return -EPERM;
2487
2488 mutex_lock(&drvdata->lock);
2489 if (!drvdata->enable) {
2490 mutex_unlock(&drvdata->lock);
2491 return -EPERM;
2492 }
2493
2494 TPDM_UNLOCK(drvdata);
2495 for (i = 0; i < TPDM_TC_MAX_COUNTERS; i++) {
2496 size += scnprintf(buf + size, PAGE_SIZE - size,
2497 "Index: 0x%x Value: 0x%x\n", i,
2498 tpdm_readl(drvdata, TPDM_TC_SHADOW_LO(i)));
2499 }
2500 TPDM_LOCK(drvdata);
2501 mutex_unlock(&drvdata->lock);
2502 return size;
2503}
Satyajit Desai326497c2016-11-14 10:15:03 -08002504static DEVICE_ATTR(tc_shadow_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002505 tpdm_show_tc_shadow_val_lo, NULL);
2506
2507static ssize_t tpdm_show_tc_shadow_val_hi(struct device *dev,
2508 struct device_attribute *attr,
2509 char *buf)
2510{
2511 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2512 ssize_t size = 0;
2513 int i = 0;
2514
2515 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2516 return -EPERM;
2517
2518 mutex_lock(&drvdata->lock);
2519 if (!drvdata->enable) {
2520 mutex_unlock(&drvdata->lock);
2521 return -EPERM;
2522 }
2523
2524 TPDM_UNLOCK(drvdata);
2525 for (i = 0; i < TPDM_TC_MAX_COUNTERS; i++) {
2526 size += scnprintf(buf + size, PAGE_SIZE - size,
2527 "Index: 0x%x Value: 0x%x\n", i,
2528 tpdm_readl(drvdata, TPDM_TC_SHADOW_HI(i)));
2529 }
2530 TPDM_LOCK(drvdata);
2531 mutex_unlock(&drvdata->lock);
2532 return size;
2533}
Satyajit Desai326497c2016-11-14 10:15:03 -08002534static DEVICE_ATTR(tc_shadow_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002535 tpdm_show_tc_shadow_val_hi, NULL);
2536
2537static ssize_t tpdm_show_tc_sw_inc(struct device *dev,
2538 struct device_attribute *attr,
2539 char *buf)
2540{
2541 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2542 unsigned long val;
2543
2544 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2545 return -EPERM;
2546
2547 mutex_lock(&drvdata->lock);
2548 if (!drvdata->enable) {
2549 mutex_unlock(&drvdata->lock);
2550 return -EPERM;
2551 }
2552
2553 TPDM_UNLOCK(drvdata);
2554 val = tpdm_readl(drvdata, TPDM_TC_SWINC);
2555 TPDM_LOCK(drvdata);
2556 mutex_unlock(&drvdata->lock);
2557 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2558}
2559
2560static ssize_t tpdm_store_tc_sw_inc(struct device *dev,
2561 struct device_attribute *attr,
2562 const char *buf,
2563 size_t size)
2564{
2565 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2566 unsigned long val;
2567
2568 if (kstrtoul(buf, 16, &val))
2569 return -EINVAL;
2570 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2571 return -EPERM;
2572
2573 mutex_lock(&drvdata->lock);
2574 if (!drvdata->enable) {
2575 mutex_unlock(&drvdata->lock);
2576 return -EPERM;
2577 }
2578
2579 if (val) {
2580 TPDM_UNLOCK(drvdata);
2581 tpdm_writel(drvdata, val, TPDM_TC_SWINC);
2582 TPDM_LOCK(drvdata);
2583 }
2584 mutex_unlock(&drvdata->lock);
2585 return size;
2586}
Satyajit Desai326497c2016-11-14 10:15:03 -08002587static DEVICE_ATTR(tc_sw_inc, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002588 tpdm_show_tc_sw_inc, tpdm_store_tc_sw_inc);
2589
Satyajit Desaib34b2c02017-01-11 16:59:38 -08002590static ssize_t tpdm_show_tc_msr(struct device *dev,
2591 struct device_attribute *attr,
2592 char *buf)
2593{
2594 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2595 unsigned int i;
2596 ssize_t len = 0;
2597
2598 if (!drvdata->msr_support)
2599 return -EINVAL;
2600
2601 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2602 return -EPERM;
2603
2604 for (i = 0; i < TPDM_TC_MAX_MSR; i++)
2605 len += scnprintf(buf + len, PAGE_SIZE - len, "%u 0x%x\n",
2606 i, drvdata->tc->msr[i]);
2607
2608 return len;
2609}
2610
Satyajit Desaif151d682016-09-12 16:18:03 -07002611static ssize_t tpdm_store_tc_msr(struct device *dev,
2612 struct device_attribute *attr,
2613 const char *buf,
2614 size_t size)
2615{
2616 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2617 unsigned int num, val;
2618 int nval;
2619
2620 if (!drvdata->msr_support)
2621 return -EINVAL;
2622
2623 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2624 return -EPERM;
2625
2626 nval = sscanf(buf, "%u %x", &num, &val);
2627 if (nval != 2)
2628 return -EINVAL;
2629
2630 if (num >= TPDM_TC_MAX_MSR)
2631 return -EINVAL;
2632
2633 mutex_lock(&drvdata->lock);
2634 drvdata->tc->msr[num] = val;
2635 mutex_unlock(&drvdata->lock);
2636 return size;
2637}
Satyajit Desaib34b2c02017-01-11 16:59:38 -08002638static DEVICE_ATTR(tc_msr, 0644, tpdm_show_tc_msr, tpdm_store_tc_msr);
Satyajit Desaif151d682016-09-12 16:18:03 -07002639
2640static ssize_t tpdm_show_dsb_mode(struct device *dev,
2641 struct device_attribute *attr,
2642 char *buf)
2643{
2644 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2645
2646 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2647 return -EPERM;
2648
2649 return scnprintf(buf, PAGE_SIZE, "%lx\n",
2650 (unsigned long)drvdata->dsb->mode);
2651}
2652
2653static ssize_t tpdm_store_dsb_mode(struct device *dev,
2654 struct device_attribute *attr,
2655 const char *buf,
2656 size_t size)
2657{
2658 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2659 unsigned long val;
2660
2661 if (kstrtoul(buf, 16, &val))
2662 return -EINVAL;
2663 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2664 return -EPERM;
2665
2666 mutex_lock(&drvdata->lock);
2667 drvdata->dsb->mode = val & TPDM_MODE_ALL;
2668 mutex_unlock(&drvdata->lock);
2669 return size;
2670}
Satyajit Desai326497c2016-11-14 10:15:03 -08002671static DEVICE_ATTR(dsb_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002672 tpdm_show_dsb_mode, tpdm_store_dsb_mode);
2673
2674static ssize_t tpdm_show_dsb_edge_ctrl(struct device *dev,
2675 struct device_attribute *attr,
2676 char *buf)
2677{
2678 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2679 ssize_t size = 0;
2680 int i;
2681
2682 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2683 return -EPERM;
2684
2685 mutex_lock(&drvdata->lock);
2686 for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) {
2687 size += scnprintf(buf + size, PAGE_SIZE - size,
2688 "Index:0x%x Val:0x%x\n", i,
2689 drvdata->dsb->edge_ctrl[i]);
2690 }
2691 mutex_unlock(&drvdata->lock);
2692 return size;
2693}
2694
2695static ssize_t tpdm_store_dsb_edge_ctrl(struct device *dev,
2696 struct device_attribute *attr,
2697 const char *buf,
2698 size_t size)
2699{
2700 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2701 unsigned long start, end, edge_ctrl;
2702 uint32_t val;
2703 int i, bit, reg;
2704
2705 if (sscanf(buf, "%lx %lx %lx", &start, &end, &edge_ctrl) != 3)
2706 return -EINVAL;
2707 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
2708 (start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES) ||
2709 edge_ctrl > 0x2)
2710 return -EPERM;
2711
2712 mutex_lock(&drvdata->lock);
2713 for (i = start; i <= end; i++) {
2714 reg = i / (NUM_OF_BITS / 2);
2715 bit = i % (NUM_OF_BITS / 2);
2716 bit = bit * 2;
2717
2718 val = drvdata->dsb->edge_ctrl[reg];
2719 val = val | (edge_ctrl << bit);
2720 drvdata->dsb->edge_ctrl[reg] = val;
2721 }
2722 mutex_unlock(&drvdata->lock);
2723 return size;
2724}
Satyajit Desai326497c2016-11-14 10:15:03 -08002725static DEVICE_ATTR(dsb_edge_ctrl, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002726 tpdm_show_dsb_edge_ctrl, tpdm_store_dsb_edge_ctrl);
2727
2728static ssize_t tpdm_show_dsb_edge_ctrl_mask(struct device *dev,
2729 struct device_attribute *attr,
2730 char *buf)
2731{
2732 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2733 ssize_t size = 0;
2734 int i;
2735
2736 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2737 return -EPERM;
2738
2739 mutex_lock(&drvdata->lock);
2740 for (i = 0; i < TPDM_DSB_MAX_EDCR / 2; i++) {
2741 size += scnprintf(buf + size, PAGE_SIZE - size,
2742 "Index:0x%x Val:0x%x\n", i,
2743 drvdata->dsb->edge_ctrl_mask[i]);
2744 }
2745 mutex_unlock(&drvdata->lock);
2746 return size;
2747}
2748
2749static ssize_t tpdm_store_dsb_edge_ctrl_mask(struct device *dev,
2750 struct device_attribute *attr,
2751 const char *buf,
2752 size_t size)
2753{
2754 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2755 unsigned long start, end, val;
2756 uint32_t set;
2757 int i, bit, reg;
2758
2759 if (sscanf(buf, "%lx %lx %lx", &start, &end, &val) != 3)
2760 return -EINVAL;
2761 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
2762 (start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES))
2763 return -EPERM;
2764
2765 mutex_lock(&drvdata->lock);
2766 for (i = start; i <= end; i++) {
2767 reg = i / NUM_OF_BITS;
2768 bit = (i % NUM_OF_BITS);
2769
2770 set = drvdata->dsb->edge_ctrl_mask[reg];
2771 if (val)
2772 set = set | BIT(bit);
2773 else
2774 set = set & ~BIT(bit);
2775 drvdata->dsb->edge_ctrl_mask[reg] = set;
2776 }
2777 mutex_unlock(&drvdata->lock);
2778 return size;
2779}
Satyajit Desai326497c2016-11-14 10:15:03 -08002780static DEVICE_ATTR(dsb_edge_ctrl_mask, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002781 tpdm_show_dsb_edge_ctrl_mask, tpdm_store_dsb_edge_ctrl_mask);
2782
2783static ssize_t tpdm_show_dsb_patt_val(struct device *dev,
2784 struct device_attribute *attr,
2785 char *buf)
2786{
2787 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2788 ssize_t size = 0;
2789 int i = 0;
2790
2791 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2792 return -EPERM;
2793
2794 mutex_lock(&drvdata->lock);
2795 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
2796 size += scnprintf(buf + size, PAGE_SIZE - size,
2797 "Index: 0x%x Value: 0x%x\n", i,
2798 drvdata->dsb->patt_val[i]);
2799 }
2800 mutex_unlock(&drvdata->lock);
2801 return size;
2802}
2803
2804static ssize_t tpdm_store_dsb_patt_val(struct device *dev,
2805 struct device_attribute *attr,
2806 const char *buf,
2807 size_t size)
2808{
2809 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2810 unsigned long index, val;
2811
2812 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2813 return -EINVAL;
2814 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
2815 index >= TPDM_DSB_MAX_PATT)
2816 return -EPERM;
2817
2818 mutex_lock(&drvdata->lock);
2819 drvdata->dsb->patt_val[index] = val;
2820 mutex_unlock(&drvdata->lock);
2821 return size;
2822}
Satyajit Desai326497c2016-11-14 10:15:03 -08002823static DEVICE_ATTR(dsb_patt_val, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002824 tpdm_show_dsb_patt_val, tpdm_store_dsb_patt_val);
2825
2826static ssize_t tpdm_show_dsb_patt_mask(struct device *dev,
2827 struct device_attribute *attr,
2828 char *buf)
2829{
2830 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2831 ssize_t size = 0;
2832 int i = 0;
2833
2834 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2835 return -EPERM;
2836
2837 mutex_lock(&drvdata->lock);
2838 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
2839 size += scnprintf(buf + size, PAGE_SIZE - size,
2840 "Index: 0x%x Value: 0x%x\n", i,
2841 drvdata->dsb->patt_mask[i]);
2842 }
2843 mutex_unlock(&drvdata->lock);
2844 return size;
2845}
2846
2847static ssize_t tpdm_store_dsb_patt_mask(struct device *dev,
2848 struct device_attribute *attr,
2849 const char *buf,
2850 size_t size)
2851{
2852 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2853 unsigned long index, val;
2854
2855 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2856 return -EINVAL;
2857 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
2858 index >= TPDM_DSB_MAX_PATT)
2859 return -EPERM;
2860
2861 mutex_lock(&drvdata->lock);
2862 drvdata->dsb->patt_mask[index] = val;
2863 mutex_unlock(&drvdata->lock);
2864 return size;
2865}
Satyajit Desai326497c2016-11-14 10:15:03 -08002866static DEVICE_ATTR(dsb_patt_mask, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002867 tpdm_show_dsb_patt_mask, tpdm_store_dsb_patt_mask);
2868
2869static ssize_t tpdm_show_dsb_patt_ts(struct device *dev,
2870 struct device_attribute *attr,
2871 char *buf)
2872{
2873 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2874
2875 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2876 return -EPERM;
2877
2878 return scnprintf(buf, PAGE_SIZE, "%u\n",
2879 (unsigned int)drvdata->dsb->patt_ts);
2880}
2881
2882static ssize_t tpdm_store_dsb_patt_ts(struct device *dev,
2883 struct device_attribute *attr,
2884 const char *buf,
2885 size_t size)
2886{
2887 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2888 unsigned long val;
2889
2890 if (kstrtoul(buf, 16, &val))
2891 return -EINVAL;
2892 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2893 return -EPERM;
2894
2895 mutex_lock(&drvdata->lock);
2896 if (val)
2897 drvdata->dsb->patt_ts = true;
2898 else
2899 drvdata->dsb->patt_ts = false;
2900 mutex_unlock(&drvdata->lock);
2901 return size;
2902}
Satyajit Desai326497c2016-11-14 10:15:03 -08002903static DEVICE_ATTR(dsb_patt_ts, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002904 tpdm_show_dsb_patt_ts, tpdm_store_dsb_patt_ts);
2905
2906static ssize_t tpdm_show_dsb_patt_type(struct device *dev,
2907 struct device_attribute *attr, char *buf)
2908{
2909 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2910
2911 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2912 return -EPERM;
2913
2914 return scnprintf(buf, PAGE_SIZE, "%u\n",
2915 (unsigned int)drvdata->dsb->patt_type);
2916}
2917
2918static ssize_t tpdm_store_dsb_patt_type(struct device *dev,
2919 struct device_attribute *attr,
2920 const char *buf, size_t size)
2921{
2922 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2923 unsigned long val;
2924
2925 if (kstrtoul(buf, 16, &val))
2926 return -EINVAL;
2927 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2928 return -EPERM;
2929
2930 mutex_lock(&drvdata->lock);
2931 if (val)
2932 drvdata->dsb->patt_type = true;
2933 else
2934 drvdata->dsb->patt_type = false;
2935 mutex_unlock(&drvdata->lock);
2936 return size;
2937}
Satyajit Desai326497c2016-11-14 10:15:03 -08002938static DEVICE_ATTR(dsb_patt_type, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002939 tpdm_show_dsb_patt_type, tpdm_store_dsb_patt_type);
2940
2941static ssize_t tpdm_show_dsb_trig_patt_val(struct device *dev,
2942 struct device_attribute *attr,
2943 char *buf)
2944{
2945 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2946 ssize_t size = 0;
2947 int i = 0;
2948
2949 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2950 return -EPERM;
2951
2952 mutex_lock(&drvdata->lock);
2953 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
2954 size += scnprintf(buf + size, PAGE_SIZE - size,
2955 "Index: 0x%x Value: 0x%x\n", i,
2956 drvdata->dsb->trig_patt_val[i]);
2957 }
2958 mutex_unlock(&drvdata->lock);
2959 return size;
2960}
2961
2962static ssize_t tpdm_store_dsb_trig_patt_val(struct device *dev,
2963 struct device_attribute *attr,
2964 const char *buf,
2965 size_t size)
2966{
2967 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2968 unsigned long index, val;
2969
2970 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2971 return -EINVAL;
2972 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
2973 index >= TPDM_DSB_MAX_PATT)
2974 return -EPERM;
2975
2976 mutex_lock(&drvdata->lock);
2977 drvdata->dsb->trig_patt_val[index] = val;
2978 mutex_unlock(&drvdata->lock);
2979 return size;
2980}
Satyajit Desai326497c2016-11-14 10:15:03 -08002981static DEVICE_ATTR(dsb_trig_patt_val, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002982 tpdm_show_dsb_trig_patt_val, tpdm_store_dsb_trig_patt_val);
2983
2984static ssize_t tpdm_show_dsb_trig_patt_mask(struct device *dev,
2985 struct device_attribute *attr,
2986 char *buf)
2987{
2988 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2989 ssize_t size = 0;
2990 int i = 0;
2991
2992 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2993 return -EPERM;
2994
2995 mutex_lock(&drvdata->lock);
2996 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
2997 size += scnprintf(buf + size, PAGE_SIZE - size,
2998 "Index: 0x%x Value: 0x%x\n", i,
2999 drvdata->dsb->trig_patt_mask[i]);
3000 }
3001 mutex_unlock(&drvdata->lock);
3002 return size;
3003}
3004
3005static ssize_t tpdm_store_dsb_trig_patt_mask(struct device *dev,
3006 struct device_attribute *attr,
3007 const char *buf,
3008 size_t size)
3009{
3010 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3011 unsigned long index, val;
3012
3013 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
3014 return -EINVAL;
3015 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
3016 index >= TPDM_DSB_MAX_PATT)
3017 return -EPERM;
3018
3019 mutex_lock(&drvdata->lock);
3020 drvdata->dsb->trig_patt_mask[index] = val;
3021 mutex_unlock(&drvdata->lock);
3022 return size;
3023}
Satyajit Desai326497c2016-11-14 10:15:03 -08003024static DEVICE_ATTR(dsb_trig_patt_mask, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003025 tpdm_show_dsb_trig_patt_mask, tpdm_store_dsb_trig_patt_mask);
3026
3027static ssize_t tpdm_show_dsb_trig_ts(struct device *dev,
3028 struct device_attribute *attr,
3029 char *buf)
3030{
3031 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3032
3033 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
3034 return -EPERM;
3035
3036 return scnprintf(buf, PAGE_SIZE, "%u\n",
3037 (unsigned int)drvdata->dsb->trig_ts);
3038}
3039
3040static ssize_t tpdm_store_dsb_trig_ts(struct device *dev,
3041 struct device_attribute *attr,
3042 const char *buf,
3043 size_t size)
3044{
3045 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3046 unsigned long val;
3047
3048 if (kstrtoul(buf, 16, &val))
3049 return -EINVAL;
3050 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
3051 return -EPERM;
3052
3053 mutex_lock(&drvdata->lock);
3054 if (val)
3055 drvdata->dsb->trig_ts = true;
3056 else
3057 drvdata->dsb->trig_ts = false;
3058 mutex_unlock(&drvdata->lock);
3059 return size;
3060}
Satyajit Desai326497c2016-11-14 10:15:03 -08003061static DEVICE_ATTR(dsb_trig_ts, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003062 tpdm_show_dsb_trig_ts, tpdm_store_dsb_trig_ts);
3063
3064static ssize_t tpdm_show_dsb_select_val(struct device *dev,
3065 struct device_attribute *attr,
3066 char *buf)
3067{
3068 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3069 ssize_t size = 0;
3070 int i;
3071
3072 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
3073 return -EPERM;
3074
3075 mutex_lock(&drvdata->lock);
3076 for (i = 0; i < TPDM_DSB_MAX_SELECT; i++) {
3077 size += scnprintf(buf + size, PAGE_SIZE - size,
3078 "Index:0x%x Val:0x%x\n", i,
3079 drvdata->dsb->select_val[i]);
3080 }
3081 mutex_unlock(&drvdata->lock);
3082 return size;
3083}
3084
3085static ssize_t tpdm_store_dsb_select_val(struct device *dev,
3086 struct device_attribute *attr,
3087 const char *buf,
3088 size_t size)
3089{
3090 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3091 unsigned long start, end;
3092 uint32_t val;
3093 int i, bit, reg;
3094
3095 if (sscanf(buf, "%lx %lx", &start, &end) != 2)
3096 return -EINVAL;
3097 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
3098 (start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES))
3099 return -EPERM;
3100
3101 mutex_lock(&drvdata->lock);
3102 for (i = start; i <= end; i++) {
3103 reg = i / NUM_OF_BITS;
3104 bit = (i % NUM_OF_BITS);
3105
3106 val = drvdata->dsb->select_val[reg];
3107 val = val | BIT(bit);
3108 drvdata->dsb->select_val[reg] = val;
3109 }
3110 mutex_unlock(&drvdata->lock);
3111 return size;
3112}
Satyajit Desai326497c2016-11-14 10:15:03 -08003113static DEVICE_ATTR(dsb_select_val, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003114 tpdm_show_dsb_select_val, tpdm_store_dsb_select_val);
3115
Satyajit Desaib34b2c02017-01-11 16:59:38 -08003116static ssize_t tpdm_show_dsb_msr(struct device *dev,
3117 struct device_attribute *attr,
3118 char *buf)
3119{
3120 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3121 unsigned int i;
3122 ssize_t len = 0;
3123
3124 if (!drvdata->msr_support)
3125 return -EINVAL;
3126
3127 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
3128 return -EPERM;
3129
3130 for (i = 0; i < TPDM_DSB_MAX_MSR; i++)
3131 len += scnprintf(buf + len, PAGE_SIZE - len, "%u 0x%x\n",
3132 i, drvdata->dsb->msr[i]);
3133
3134 return len;
3135}
3136
Satyajit Desaif151d682016-09-12 16:18:03 -07003137static ssize_t tpdm_store_dsb_msr(struct device *dev,
3138 struct device_attribute *attr,
3139 const char *buf,
3140 size_t size)
3141{
3142 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3143 unsigned int num, val;
3144 int nval;
3145
3146 if (!drvdata->msr_support)
3147 return -EINVAL;
3148
3149 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
3150 return -EPERM;
3151
3152 nval = sscanf(buf, "%u %x", &num, &val);
3153 if (nval != 2)
3154 return -EINVAL;
3155
3156 if (num >= TPDM_DSB_MAX_MSR)
3157 return -EINVAL;
3158
3159 mutex_lock(&drvdata->lock);
3160 drvdata->dsb->msr[num] = val;
3161 mutex_unlock(&drvdata->lock);
3162 return size;
3163}
Satyajit Desaib34b2c02017-01-11 16:59:38 -08003164static DEVICE_ATTR(dsb_msr, 0644, tpdm_show_dsb_msr, tpdm_store_dsb_msr);
Satyajit Desaif151d682016-09-12 16:18:03 -07003165
3166static ssize_t tpdm_show_cmb_available_modes(struct device *dev,
3167 struct device_attribute *attr,
3168 char *buf)
3169{
3170 return scnprintf(buf, PAGE_SIZE, "%s\n", "continuous trace_on_change");
3171}
Satyajit Desai326497c2016-11-14 10:15:03 -08003172static DEVICE_ATTR(cmb_available_modes, 0444, tpdm_show_cmb_available_modes,
Satyajit Desaif151d682016-09-12 16:18:03 -07003173 NULL);
3174
3175static ssize_t tpdm_show_cmb_mode(struct device *dev,
3176 struct device_attribute *attr,
3177 char *buf)
3178{
3179 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3180
Satyajit Desaie104ff52016-09-12 16:38:12 -07003181 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3182 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003183 return -EPERM;
3184
3185 return scnprintf(buf, PAGE_SIZE, "%s\n",
3186 drvdata->cmb->mode == TPDM_CMB_MODE_CONTINUOUS ?
3187 "continuous" : "trace_on_change");
3188}
3189
3190static ssize_t tpdm_store_cmb_mode(struct device *dev,
3191 struct device_attribute *attr,
3192 const char *buf,
3193 size_t size)
3194{
3195 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3196 char str[20] = "";
3197
3198 if (strlen(buf) >= 20)
3199 return -EINVAL;
3200 if (sscanf(buf, "%s", str) != 1)
3201 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003202 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3203 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003204 return -EPERM;
3205
3206 mutex_lock(&drvdata->lock);
3207 if (!strcmp(str, "continuous")) {
3208 drvdata->cmb->mode = TPDM_CMB_MODE_CONTINUOUS;
3209 } else if (!strcmp(str, "trace_on_change")) {
3210 drvdata->cmb->mode = TPDM_CMB_MODE_TRACE_ON_CHANGE;
3211 } else {
3212 mutex_unlock(&drvdata->lock);
3213 return -EINVAL;
3214 }
3215 mutex_unlock(&drvdata->lock);
3216 return size;
3217}
Satyajit Desai326497c2016-11-14 10:15:03 -08003218static DEVICE_ATTR(cmb_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003219 tpdm_show_cmb_mode, tpdm_store_cmb_mode);
3220
Satyajit Desai75411bc2017-04-19 18:41:27 -07003221static ssize_t tpdm_show_cmb_patt_val(struct device *dev,
Satyajit Desaif151d682016-09-12 16:18:03 -07003222 struct device_attribute *attr,
3223 char *buf)
3224{
3225 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Satyajit Desai75411bc2017-04-19 18:41:27 -07003226 ssize_t size = 0;
3227 int i;
Satyajit Desaif151d682016-09-12 16:18:03 -07003228
Satyajit Desaie104ff52016-09-12 16:38:12 -07003229 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3230 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003231 return -EPERM;
3232
Satyajit Desai75411bc2017-04-19 18:41:27 -07003233 mutex_lock(&drvdata->lock);
3234 for (i = 0; i < TPDM_CMB_PATT_CMP; i++) {
3235 size += scnprintf(buf + size, PAGE_SIZE - size,
3236 "Index: 0x%x Value: 0x%x\n", i,
3237 drvdata->cmb->patt_val[i]);
3238 }
3239 mutex_unlock(&drvdata->lock);
3240 return size;
Satyajit Desaif151d682016-09-12 16:18:03 -07003241}
3242
Satyajit Desai75411bc2017-04-19 18:41:27 -07003243static ssize_t tpdm_store_cmb_patt_val(struct device *dev,
Satyajit Desaif151d682016-09-12 16:18:03 -07003244 struct device_attribute *attr,
3245 const char *buf, size_t size)
3246{
3247 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Satyajit Desai75411bc2017-04-19 18:41:27 -07003248 unsigned long index, val;
Satyajit Desaif151d682016-09-12 16:18:03 -07003249
Satyajit Desai75411bc2017-04-19 18:41:27 -07003250 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
3251 return -EINVAL;
3252 if (index >= TPDM_CMB_PATT_CMP)
Satyajit Desaif151d682016-09-12 16:18:03 -07003253 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003254 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3255 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003256 return -EPERM;
3257
3258 mutex_lock(&drvdata->lock);
Satyajit Desai75411bc2017-04-19 18:41:27 -07003259 drvdata->cmb->patt_val[index] = val;
Satyajit Desaif151d682016-09-12 16:18:03 -07003260 mutex_unlock(&drvdata->lock);
Satyajit Desai75411bc2017-04-19 18:41:27 -07003261
Satyajit Desaif151d682016-09-12 16:18:03 -07003262 return size;
3263}
Satyajit Desai75411bc2017-04-19 18:41:27 -07003264static DEVICE_ATTR(cmb_patt_val, 0644,
3265 tpdm_show_cmb_patt_val,
3266 tpdm_store_cmb_patt_val);
Satyajit Desaif151d682016-09-12 16:18:03 -07003267
Satyajit Desai75411bc2017-04-19 18:41:27 -07003268static ssize_t tpdm_show_cmb_patt_mask(struct device *dev,
Satyajit Desaif151d682016-09-12 16:18:03 -07003269 struct device_attribute *attr,
3270 char *buf)
3271{
3272 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Satyajit Desai75411bc2017-04-19 18:41:27 -07003273 ssize_t size = 0;
3274 int i;
Satyajit Desaif151d682016-09-12 16:18:03 -07003275
Satyajit Desaie104ff52016-09-12 16:38:12 -07003276 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3277 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003278 return -EPERM;
3279
Satyajit Desai75411bc2017-04-19 18:41:27 -07003280 mutex_lock(&drvdata->lock);
3281 for (i = 0; i < TPDM_CMB_PATT_CMP; i++) {
3282 size += scnprintf(buf + size, PAGE_SIZE - size,
3283 "Index: 0x%x Value: 0x%x\n", i,
3284 drvdata->cmb->patt_mask[i]);
3285 }
3286 mutex_unlock(&drvdata->lock);
3287 return size;
Satyajit Desaif151d682016-09-12 16:18:03 -07003288
Satyajit Desaif151d682016-09-12 16:18:03 -07003289}
3290
Satyajit Desai75411bc2017-04-19 18:41:27 -07003291static ssize_t tpdm_store_cmb_patt_mask(struct device *dev,
Satyajit Desaif151d682016-09-12 16:18:03 -07003292 struct device_attribute *attr,
3293 const char *buf, size_t size)
3294{
3295 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
Satyajit Desai75411bc2017-04-19 18:41:27 -07003296 unsigned long index, val;
Satyajit Desaif151d682016-09-12 16:18:03 -07003297
Satyajit Desai75411bc2017-04-19 18:41:27 -07003298 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
3299 return -EINVAL;
3300 if (index >= TPDM_CMB_PATT_CMP)
Satyajit Desaif151d682016-09-12 16:18:03 -07003301 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003302 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3303 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003304 return -EPERM;
3305
3306 mutex_lock(&drvdata->lock);
Satyajit Desai75411bc2017-04-19 18:41:27 -07003307 drvdata->cmb->patt_mask[index] = val;
Satyajit Desaif151d682016-09-12 16:18:03 -07003308 mutex_unlock(&drvdata->lock);
3309 return size;
3310}
Satyajit Desai75411bc2017-04-19 18:41:27 -07003311static DEVICE_ATTR(cmb_patt_mask, 0644,
3312 tpdm_show_cmb_patt_mask, tpdm_store_cmb_patt_mask);
Satyajit Desaif151d682016-09-12 16:18:03 -07003313
3314static ssize_t tpdm_show_cmb_patt_ts(struct device *dev,
3315 struct device_attribute *attr,
3316 char *buf)
3317{
3318 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3319
Satyajit Desaie104ff52016-09-12 16:38:12 -07003320 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3321 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003322 return -EPERM;
3323
3324 return scnprintf(buf, PAGE_SIZE, "%u\n",
3325 (unsigned int)drvdata->cmb->patt_ts);
3326}
3327
3328static ssize_t tpdm_store_cmb_patt_ts(struct device *dev,
3329 struct device_attribute *attr,
3330 const char *buf,
3331 size_t size)
3332{
3333 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3334 unsigned long val;
3335
3336 if (kstrtoul(buf, 16, &val))
3337 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003338 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3339 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003340 return -EPERM;
3341
3342 mutex_lock(&drvdata->lock);
3343 if (val)
3344 drvdata->cmb->patt_ts = true;
3345 else
3346 drvdata->cmb->patt_ts = false;
3347 mutex_unlock(&drvdata->lock);
3348 return size;
3349}
Satyajit Desai326497c2016-11-14 10:15:03 -08003350static DEVICE_ATTR(cmb_patt_ts, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003351 tpdm_show_cmb_patt_ts, tpdm_store_cmb_patt_ts);
3352
3353static ssize_t tpdm_show_cmb_trig_patt_val_lsb(struct device *dev,
3354 struct device_attribute *attr,
3355 char *buf)
3356{
3357 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3358 unsigned long val;
3359
Satyajit Desaie104ff52016-09-12 16:38:12 -07003360 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3361 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003362 return -EPERM;
3363
3364 val = drvdata->cmb->trig_patt_val[TPDM_CMB_LSB];
3365
3366 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
3367}
3368
3369static ssize_t tpdm_store_cmb_trig_patt_val_lsb(struct device *dev,
3370 struct device_attribute *attr,
3371 const char *buf, size_t size)
3372{
3373 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3374 unsigned long val;
3375
3376 if (kstrtoul(buf, 16, &val))
3377 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003378 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3379 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003380 return -EPERM;
3381
3382 mutex_lock(&drvdata->lock);
3383 drvdata->cmb->trig_patt_val[TPDM_CMB_LSB] = val;
3384 mutex_unlock(&drvdata->lock);
3385 return size;
3386}
Satyajit Desai326497c2016-11-14 10:15:03 -08003387static DEVICE_ATTR(cmb_trig_patt_val_lsb, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003388 tpdm_show_cmb_trig_patt_val_lsb,
3389 tpdm_store_cmb_trig_patt_val_lsb);
3390
3391static ssize_t tpdm_show_cmb_trig_patt_mask_lsb(struct device *dev,
3392 struct device_attribute *attr,
3393 char *buf)
3394{
3395 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3396 unsigned long val;
3397
Satyajit Desaie104ff52016-09-12 16:38:12 -07003398 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3399 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003400 return -EPERM;
3401
3402 val = drvdata->cmb->trig_patt_mask[TPDM_CMB_LSB];
3403
3404 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
3405}
3406
3407static ssize_t tpdm_store_cmb_trig_patt_mask_lsb(struct device *dev,
3408 struct device_attribute *attr,
3409 const char *buf, size_t size)
3410{
3411 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3412 unsigned long val;
3413
3414 if (kstrtoul(buf, 16, &val))
3415 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003416 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3417 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003418 return -EPERM;
3419
3420 mutex_lock(&drvdata->lock);
3421 drvdata->cmb->trig_patt_mask[TPDM_CMB_LSB] = val;
3422 mutex_unlock(&drvdata->lock);
3423 return size;
3424}
Satyajit Desai326497c2016-11-14 10:15:03 -08003425static DEVICE_ATTR(cmb_trig_patt_mask_lsb, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003426 tpdm_show_cmb_trig_patt_mask_lsb,
3427 tpdm_store_cmb_trig_patt_mask_lsb);
3428
3429static ssize_t tpdm_show_cmb_trig_patt_val_msb(struct device *dev,
3430 struct device_attribute *attr,
3431 char *buf)
3432{
3433 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3434 unsigned long val;
3435
Satyajit Desaie104ff52016-09-12 16:38:12 -07003436 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3437 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003438 return -EPERM;
3439
3440 val = drvdata->cmb->trig_patt_val[TPDM_CMB_MSB];
3441
3442 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
3443}
3444
3445static ssize_t tpdm_store_cmb_trig_patt_val_msb(struct device *dev,
3446 struct device_attribute *attr,
3447 const char *buf, size_t size)
3448{
3449 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3450 unsigned long val;
3451
3452 if (kstrtoul(buf, 16, &val))
3453 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003454 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3455 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003456 return -EPERM;
3457
3458 mutex_lock(&drvdata->lock);
3459 drvdata->cmb->trig_patt_val[TPDM_CMB_MSB] = val;
3460 mutex_unlock(&drvdata->lock);
3461 return size;
3462}
Satyajit Desai326497c2016-11-14 10:15:03 -08003463static DEVICE_ATTR(cmb_trig_patt_val_msb, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003464 tpdm_show_cmb_trig_patt_val_msb,
3465 tpdm_store_cmb_trig_patt_val_msb);
3466
3467static ssize_t tpdm_show_cmb_trig_patt_mask_msb(struct device *dev,
3468 struct device_attribute *attr,
3469 char *buf)
3470{
3471 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3472 unsigned long val;
3473
Satyajit Desaie104ff52016-09-12 16:38:12 -07003474 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3475 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003476 return -EPERM;
3477
3478 val = drvdata->cmb->trig_patt_mask[TPDM_CMB_MSB];
3479
3480 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
3481}
3482
3483static ssize_t tpdm_store_cmb_trig_patt_mask_msb(struct device *dev,
3484 struct device_attribute *attr,
3485 const char *buf, size_t size)
3486{
3487 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3488 unsigned long val;
3489
3490 if (kstrtoul(buf, 16, &val))
3491 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003492 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3493 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003494 return -EPERM;
3495
3496 mutex_lock(&drvdata->lock);
3497 drvdata->cmb->trig_patt_mask[TPDM_CMB_MSB] = val;
3498 mutex_unlock(&drvdata->lock);
3499 return size;
3500}
Satyajit Desai326497c2016-11-14 10:15:03 -08003501static DEVICE_ATTR(cmb_trig_patt_mask_msb, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003502 tpdm_show_cmb_trig_patt_mask_msb,
3503 tpdm_store_cmb_trig_patt_mask_msb);
3504
3505static ssize_t tpdm_show_cmb_trig_ts(struct device *dev,
3506 struct device_attribute *attr,
3507 char *buf)
3508{
3509 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3510
Satyajit Desaie104ff52016-09-12 16:38:12 -07003511 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3512 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003513 return -EPERM;
3514
3515 return scnprintf(buf, PAGE_SIZE, "%u\n",
3516 (unsigned int)drvdata->cmb->trig_ts);
3517}
3518
3519static ssize_t tpdm_store_cmb_trig_ts(struct device *dev,
Satyajit Desaie104ff52016-09-12 16:38:12 -07003520 struct device_attribute *attr,
3521 const char *buf,
3522 size_t size)
Satyajit Desaif151d682016-09-12 16:18:03 -07003523{
3524 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3525 unsigned long val;
3526
3527 if (kstrtoul(buf, 16, &val))
3528 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003529 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3530 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003531 return -EPERM;
3532
3533 mutex_lock(&drvdata->lock);
3534 if (val)
3535 drvdata->cmb->trig_ts = true;
3536 else
3537 drvdata->cmb->trig_ts = false;
3538 mutex_unlock(&drvdata->lock);
3539 return size;
3540}
Satyajit Desai326497c2016-11-14 10:15:03 -08003541static DEVICE_ATTR(cmb_trig_ts, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003542 tpdm_show_cmb_trig_ts, tpdm_store_cmb_trig_ts);
3543
Satyajit Desaib34b2c02017-01-11 16:59:38 -08003544static ssize_t tpdm_show_cmb_msr(struct device *dev,
3545 struct device_attribute *attr,
3546 char *buf)
3547{
3548 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3549 unsigned int i;
3550 ssize_t len = 0;
3551
3552 if (!drvdata->msr_support)
3553 return -EINVAL;
3554
3555 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3556 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
3557 return -EPERM;
3558
3559 for (i = 0; i < TPDM_CMB_MAX_MSR; i++)
3560 len += scnprintf(buf + len, PAGE_SIZE - len, "%u 0x%x\n",
3561 i, drvdata->cmb->msr[i]);
3562
3563 return len;
3564}
3565
Satyajit Desaif151d682016-09-12 16:18:03 -07003566static ssize_t tpdm_store_cmb_msr(struct device *dev,
3567 struct device_attribute *attr,
3568 const char *buf,
3569 size_t size)
3570{
3571 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3572 unsigned int num, val;
3573 int nval;
3574
3575 if (!drvdata->msr_support)
3576 return -EINVAL;
3577
Satyajit Desaie104ff52016-09-12 16:38:12 -07003578 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3579 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003580 return -EPERM;
3581
3582 nval = sscanf(buf, "%u %x", &num, &val);
3583 if (nval != 2)
3584 return -EINVAL;
3585
3586 if (num >= TPDM_CMB_MAX_MSR)
3587 return -EINVAL;
3588
3589 mutex_lock(&drvdata->lock);
3590 drvdata->cmb->msr[num] = val;
3591 mutex_unlock(&drvdata->lock);
3592 return size;
3593}
Satyajit Desaib34b2c02017-01-11 16:59:38 -08003594static DEVICE_ATTR(cmb_msr, 0644, tpdm_show_cmb_msr, tpdm_store_cmb_msr);
Satyajit Desaif151d682016-09-12 16:18:03 -07003595
Satyajit Desaie104ff52016-09-12 16:38:12 -07003596static ssize_t tpdm_show_cmb_read_interface_state(struct device *dev,
3597 struct device_attribute *attr,
3598 char *buf)
3599{
3600 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3601 unsigned long val;
3602
3603 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3604 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
3605 return -EPERM;
3606
3607 mutex_lock(&drvdata->lock);
3608 TPDM_UNLOCK(drvdata);
3609 val = tpdm_readl(drvdata, TPDM_CMB_READVAL);
3610 TPDM_LOCK(drvdata);
3611 mutex_unlock(&drvdata->lock);
3612
3613 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
3614}
3615static DEVICE_ATTR(cmb_read_interface_state, 0444,
3616 tpdm_show_cmb_read_interface_state, NULL);
3617
3618static ssize_t tpdm_show_cmb_read_ctl_reg(struct device *dev,
3619 struct device_attribute *attr,
3620 char *buf)
3621{
3622 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3623 unsigned long val;
3624
3625 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3626 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
3627 return -EPERM;
3628
3629 mutex_lock(&drvdata->lock);
3630 TPDM_UNLOCK(drvdata);
3631 val = tpdm_readl(drvdata, TPDM_CMB_READCTL);
3632 TPDM_LOCK(drvdata);
3633 mutex_unlock(&drvdata->lock);
3634
3635 if (test_bit(TPDM_DS_CMB, drvdata->datasets))
3636 return scnprintf(buf, PAGE_SIZE, "SEL: %lx\n", val);
3637 else
3638 return scnprintf(buf, PAGE_SIZE, "Lane %u SEL: %lx\n",
3639 (unsigned int)BMVAL(val, 1, 3), val & 0x1);
3640}
3641
3642static ssize_t tpdm_store_cmb_read_ctl_reg(struct device *dev,
3643 struct device_attribute *attr,
3644 const char *buf,
3645 size_t size)
3646{
3647 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3648 unsigned long val;
3649
3650 if (kstrtoul(buf, 16, &val))
3651 return -EINVAL;
3652
3653 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3654 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
3655 return -EPERM;
3656
3657 mutex_lock(&drvdata->lock);
3658 TPDM_UNLOCK(drvdata);
3659 tpdm_writel(drvdata, val, TPDM_CMB_READCTL);
3660 TPDM_LOCK(drvdata);
3661 mutex_unlock(&drvdata->lock);
3662
3663 return size;
3664}
3665static DEVICE_ATTR(cmb_read_ctl_reg, 0644,
3666 tpdm_show_cmb_read_ctl_reg, tpdm_store_cmb_read_ctl_reg);
3667
3668static ssize_t tpdm_show_mcmb_trig_lane(struct device *dev,
3669 struct device_attribute *attr,
3670 char *buf)
3671{
3672 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3673
3674 if (!test_bit(TPDM_DS_MCMB, drvdata->datasets))
3675 return -EPERM;
3676
3677 return scnprintf(buf, PAGE_SIZE, "%u\n",
3678 (unsigned int)drvdata->cmb->mcmb->mcmb_trig_lane);
3679}
3680
3681static ssize_t tpdm_store_mcmb_trig_lane(struct device *dev,
3682 struct device_attribute *attr,
3683 const char *buf,
3684 size_t size)
3685{
3686 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3687 unsigned long val;
3688
3689 if (kstrtoul(buf, 10, &val))
3690 return -EINVAL;
3691 if (val >= TPDM_MCMB_MAX_LANES)
3692 return -EINVAL;
3693 if (!test_bit(TPDM_DS_MCMB, drvdata->datasets))
3694 return -EPERM;
3695
3696 mutex_lock(&drvdata->lock);
3697 drvdata->cmb->mcmb->mcmb_trig_lane = val;
3698 mutex_unlock(&drvdata->lock);
3699 return size;
3700}
3701static DEVICE_ATTR(mcmb_trig_lane, 0644,
3702 tpdm_show_mcmb_trig_lane, tpdm_store_mcmb_trig_lane);
3703
3704static ssize_t tpdm_show_mcmb_lanes_select(struct device *dev,
3705 struct device_attribute *attr,
3706 char *buf)
3707{
3708 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3709
3710 if (!test_bit(TPDM_DS_MCMB, drvdata->datasets))
3711 return -EPERM;
3712
3713 return scnprintf(buf, PAGE_SIZE, "%u\n",
3714 (unsigned int)drvdata->cmb->mcmb->mcmb_lane_select);
3715}
3716
3717static ssize_t tpdm_store_mcmb_lanes_select(struct device *dev,
3718 struct device_attribute *attr,
3719 const char *buf,
3720 size_t size)
3721{
3722 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3723 unsigned long val;
3724
3725 if (kstrtoul(buf, 16, &val))
3726 return -EINVAL;
3727 if (!test_bit(TPDM_DS_MCMB, drvdata->datasets))
3728 return -EPERM;
3729
3730 val = BMVAL(val, 0, TPDM_MCMB_MAX_LANES - 1);
3731
3732 mutex_lock(&drvdata->lock);
3733 drvdata->cmb->mcmb->mcmb_lane_select = val;
3734 mutex_unlock(&drvdata->lock);
3735 return size;
3736}
3737static DEVICE_ATTR(mcmb_lanes_select, 0644,
3738 tpdm_show_mcmb_lanes_select, tpdm_store_mcmb_lanes_select);
3739
3740static ssize_t tpdm_store_cmb_markr(struct device *dev,
3741 struct device_attribute *attr,
3742 const char *buf,
3743 size_t size)
3744{
3745 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3746 unsigned long val;
3747
3748 if (kstrtoul(buf, 16, &val))
3749 return -EINVAL;
3750
3751 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3752 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
3753 return -EPERM;
3754
3755 mutex_lock(&drvdata->lock);
3756 TPDM_UNLOCK(drvdata);
3757 tpdm_writel(drvdata, val, TPDM_CMB_MARKR);
3758 TPDM_LOCK(drvdata);
3759 mutex_unlock(&drvdata->lock);
3760
3761 return size;
3762}
3763static DEVICE_ATTR(cmb_markr, 0200, NULL, tpdm_store_cmb_markr);
3764
Satyajit Desaif151d682016-09-12 16:18:03 -07003765static struct attribute *tpdm_bc_attrs[] = {
3766 &dev_attr_bc_capture_mode.attr,
3767 &dev_attr_bc_retrieval_mode.attr,
3768 &dev_attr_bc_reset_counters.attr,
3769 &dev_attr_bc_sat_mode.attr,
3770 &dev_attr_bc_enable_counters.attr,
3771 &dev_attr_bc_clear_counters.attr,
3772 &dev_attr_bc_enable_irq.attr,
3773 &dev_attr_bc_clear_irq.attr,
3774 &dev_attr_bc_trig_val_lo.attr,
3775 &dev_attr_bc_trig_val_hi.attr,
3776 &dev_attr_bc_enable_ganging.attr,
3777 &dev_attr_bc_overflow_val.attr,
3778 &dev_attr_bc_ovsr.attr,
3779 &dev_attr_bc_counter_sel.attr,
3780 &dev_attr_bc_count_val_lo.attr,
3781 &dev_attr_bc_count_val_hi.attr,
3782 &dev_attr_bc_shadow_val_lo.attr,
3783 &dev_attr_bc_shadow_val_hi.attr,
3784 &dev_attr_bc_sw_inc.attr,
3785 &dev_attr_bc_msr.attr,
3786 NULL,
3787};
3788
3789static struct attribute *tpdm_tc_attrs[] = {
3790 &dev_attr_tc_capture_mode.attr,
3791 &dev_attr_tc_retrieval_mode.attr,
3792 &dev_attr_tc_reset_counters.attr,
3793 &dev_attr_tc_sat_mode.attr,
3794 &dev_attr_tc_enable_counters.attr,
3795 &dev_attr_tc_clear_counters.attr,
3796 &dev_attr_tc_enable_irq.attr,
3797 &dev_attr_tc_clear_irq.attr,
3798 &dev_attr_tc_trig_sel.attr,
3799 &dev_attr_tc_trig_val_lo.attr,
3800 &dev_attr_tc_trig_val_hi.attr,
3801 &dev_attr_tc_ovsr_gp.attr,
3802 &dev_attr_tc_ovsr_impl.attr,
3803 &dev_attr_tc_counter_sel.attr,
3804 &dev_attr_tc_count_val_lo.attr,
3805 &dev_attr_tc_count_val_hi.attr,
3806 &dev_attr_tc_shadow_val_lo.attr,
3807 &dev_attr_tc_shadow_val_hi.attr,
3808 &dev_attr_tc_sw_inc.attr,
3809 &dev_attr_tc_msr.attr,
3810 NULL,
3811};
3812
3813static struct attribute *tpdm_dsb_attrs[] = {
3814 &dev_attr_dsb_mode.attr,
3815 &dev_attr_dsb_edge_ctrl.attr,
3816 &dev_attr_dsb_edge_ctrl_mask.attr,
3817 &dev_attr_dsb_patt_val.attr,
3818 &dev_attr_dsb_patt_mask.attr,
3819 &dev_attr_dsb_patt_ts.attr,
3820 &dev_attr_dsb_patt_type.attr,
3821 &dev_attr_dsb_trig_patt_val.attr,
3822 &dev_attr_dsb_trig_patt_mask.attr,
3823 &dev_attr_dsb_trig_ts.attr,
3824 &dev_attr_dsb_select_val.attr,
3825 &dev_attr_dsb_msr.attr,
3826 NULL,
3827};
3828
3829static struct attribute *tpdm_cmb_attrs[] = {
3830 &dev_attr_cmb_available_modes.attr,
3831 &dev_attr_cmb_mode.attr,
Satyajit Desai75411bc2017-04-19 18:41:27 -07003832 &dev_attr_cmb_patt_val.attr,
3833 &dev_attr_cmb_patt_mask.attr,
Satyajit Desaif151d682016-09-12 16:18:03 -07003834 &dev_attr_cmb_patt_ts.attr,
3835 &dev_attr_cmb_trig_patt_val_lsb.attr,
3836 &dev_attr_cmb_trig_patt_mask_lsb.attr,
3837 &dev_attr_cmb_trig_patt_val_msb.attr,
3838 &dev_attr_cmb_trig_patt_mask_msb.attr,
3839 &dev_attr_cmb_trig_ts.attr,
3840 &dev_attr_cmb_msr.attr,
Satyajit Desaie104ff52016-09-12 16:38:12 -07003841 &dev_attr_cmb_read_interface_state.attr,
3842 &dev_attr_cmb_read_ctl_reg.attr,
3843 &dev_attr_cmb_markr.attr,
3844 &dev_attr_mcmb_trig_lane.attr,
3845 &dev_attr_mcmb_lanes_select.attr,
Satyajit Desaif151d682016-09-12 16:18:03 -07003846 NULL,
3847};
3848
3849static struct attribute_group tpdm_bc_attr_grp = {
3850 .attrs = tpdm_bc_attrs,
3851};
3852
3853static struct attribute_group tpdm_tc_attr_grp = {
3854 .attrs = tpdm_tc_attrs,
3855};
3856
3857static struct attribute_group tpdm_dsb_attr_grp = {
3858 .attrs = tpdm_dsb_attrs,
3859};
3860
3861static struct attribute_group tpdm_cmb_attr_grp = {
3862 .attrs = tpdm_cmb_attrs,
3863};
3864
3865static struct attribute *tpdm_attrs[] = {
3866 &dev_attr_available_datasets.attr,
3867 &dev_attr_enable_datasets.attr,
3868 &dev_attr_gp_regs.attr,
3869 NULL,
3870};
3871
3872static struct attribute_group tpdm_attr_grp = {
3873 .attrs = tpdm_attrs,
3874};
3875static const struct attribute_group *tpdm_attr_grps[] = {
3876 &tpdm_attr_grp,
3877 &tpdm_bc_attr_grp,
3878 &tpdm_tc_attr_grp,
3879 &tpdm_dsb_attr_grp,
3880 &tpdm_cmb_attr_grp,
3881 NULL,
3882};
3883
3884static int tpdm_datasets_alloc(struct tpdm_drvdata *drvdata)
3885{
3886 if (test_bit(TPDM_DS_GPR, drvdata->datasets)) {
3887 drvdata->gpr = devm_kzalloc(drvdata->dev, sizeof(*drvdata->gpr),
3888 GFP_KERNEL);
3889 if (!drvdata->gpr)
3890 return -ENOMEM;
3891 }
3892 if (test_bit(TPDM_DS_BC, drvdata->datasets)) {
3893 drvdata->bc = devm_kzalloc(drvdata->dev, sizeof(*drvdata->bc),
3894 GFP_KERNEL);
3895 if (!drvdata->bc)
3896 return -ENOMEM;
3897 }
3898 if (test_bit(TPDM_DS_TC, drvdata->datasets)) {
3899 drvdata->tc = devm_kzalloc(drvdata->dev, sizeof(*drvdata->tc),
3900 GFP_KERNEL);
3901 if (!drvdata->tc)
3902 return -ENOMEM;
3903 }
3904 if (test_bit(TPDM_DS_DSB, drvdata->datasets)) {
3905 drvdata->dsb = devm_kzalloc(drvdata->dev, sizeof(*drvdata->dsb),
3906 GFP_KERNEL);
3907 if (!drvdata->dsb)
3908 return -ENOMEM;
3909 }
3910 if (test_bit(TPDM_DS_CMB, drvdata->datasets)) {
3911 drvdata->cmb = devm_kzalloc(drvdata->dev, sizeof(*drvdata->cmb),
3912 GFP_KERNEL);
3913 if (!drvdata->cmb)
3914 return -ENOMEM;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003915 } else if (test_bit(TPDM_DS_MCMB, drvdata->datasets)) {
3916 drvdata->cmb = devm_kzalloc(drvdata->dev, sizeof(*drvdata->cmb),
3917 GFP_KERNEL);
3918 if (!drvdata->cmb)
3919 return -ENOMEM;
3920 drvdata->cmb->mcmb = devm_kzalloc(drvdata->dev,
3921 sizeof(*drvdata->cmb->mcmb),
3922 GFP_KERNEL);
3923 if (!drvdata->cmb->mcmb)
3924 return -ENOMEM;
Satyajit Desaif151d682016-09-12 16:18:03 -07003925 }
3926 return 0;
3927}
3928
3929static void tpdm_init_default_data(struct tpdm_drvdata *drvdata)
3930{
3931 if (test_bit(TPDM_DS_BC, drvdata->datasets))
3932 drvdata->bc->retrieval_mode = TPDM_MODE_ATB;
3933
3934 if (test_bit(TPDM_DS_TC, drvdata->datasets))
3935 drvdata->tc->retrieval_mode = TPDM_MODE_ATB;
3936
3937 if (test_bit(TPDM_DS_DSB, drvdata->datasets))
3938 drvdata->dsb->trig_ts = true;
3939
Satyajit Desaie104ff52016-09-12 16:38:12 -07003940 if (test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3941 test_bit(TPDM_DS_MCMB, drvdata->datasets))
Satyajit Desaif151d682016-09-12 16:18:03 -07003942 drvdata->cmb->trig_ts = true;
3943}
3944
3945static int tpdm_probe(struct platform_device *pdev)
3946{
3947 int ret, i;
3948 uint32_t pidr, devid;
3949 struct device *dev = &pdev->dev;
3950 struct coresight_platform_data *pdata;
3951 struct tpdm_drvdata *drvdata;
3952 struct resource *res;
3953 struct coresight_desc *desc;
3954 static int traceid = TPDM_TRACE_ID_START;
3955 uint32_t version;
3956
3957 pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
3958 if (IS_ERR(pdata))
3959 return PTR_ERR(pdata);
3960 pdev->dev.platform_data = pdata;
3961
3962 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
3963 if (!drvdata)
3964 return -ENOMEM;
3965 drvdata->dev = &pdev->dev;
3966 platform_set_drvdata(pdev, drvdata);
3967
3968 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tpdm-base");
3969 if (!res)
3970 return -ENODEV;
3971
3972 drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
3973 if (!drvdata->base)
3974 return -ENOMEM;
3975
3976 drvdata->clk_enable = of_property_read_bool(pdev->dev.of_node,
3977 "qcom,clk-enable");
3978
3979 drvdata->msr_fix_req = of_property_read_bool(pdev->dev.of_node,
3980 "qcom,msr-fix-req");
3981
3982 mutex_init(&drvdata->lock);
3983
3984 drvdata->clk = devm_clk_get(dev, "core_clk");
3985 if (IS_ERR(drvdata->clk))
3986 return PTR_ERR(drvdata->clk);
3987
3988 ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
3989 if (ret)
3990 return ret;
3991
3992 ret = clk_prepare_enable(drvdata->clk);
3993 if (ret)
3994 return ret;
3995
3996 version = tpdm_readl(drvdata, CORESIGHT_PERIPHIDR2);
3997 drvdata->version = BMVAL(version, 4, 7);
3998
3999 if (drvdata->version)
4000 drvdata->msr_support = true;
4001
4002 pidr = tpdm_readl(drvdata, CORESIGHT_PERIPHIDR0);
4003 for (i = 0; i < TPDM_DATASETS; i++) {
4004 if (pidr & BIT(i)) {
4005 __set_bit(i, drvdata->datasets);
4006 __set_bit(i, drvdata->enable_ds);
4007 }
4008 }
4009
4010 ret = tpdm_datasets_alloc(drvdata);
4011 if (ret)
4012 return ret;
4013
4014 tpdm_init_default_data(drvdata);
4015
4016 devid = tpdm_readl(drvdata, CORESIGHT_DEVID);
4017 drvdata->tc_trig_type = BMVAL(devid, 27, 28);
4018 drvdata->bc_trig_type = BMVAL(devid, 25, 26);
4019 drvdata->bc_gang_type = BMVAL(devid, 23, 24);
4020 drvdata->bc_counters_avail = BMVAL(devid, 6, 10) + 1;
4021 drvdata->tc_counters_avail = BMVAL(devid, 4, 5) + 1;
4022
4023 clk_disable_unprepare(drvdata->clk);
4024
4025 drvdata->traceid = traceid++;
4026
4027 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
4028 if (!desc)
4029 return -ENOMEM;
4030 desc->type = CORESIGHT_DEV_TYPE_SOURCE;
4031 desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
4032 desc->ops = &tpdm_cs_ops;
4033 desc->pdata = pdev->dev.platform_data;
4034 desc->dev = &pdev->dev;
4035 desc->groups = tpdm_attr_grps;
4036 drvdata->csdev = coresight_register(desc);
4037 if (IS_ERR(drvdata->csdev))
4038 return PTR_ERR(drvdata->csdev);
4039
4040 dev_dbg(drvdata->dev, "TPDM initialized\n");
4041
4042 if (boot_enable)
4043 coresight_enable(drvdata->csdev);
4044
4045 return 0;
4046}
4047
4048static int tpdm_remove(struct platform_device *pdev)
4049{
4050 struct tpdm_drvdata *drvdata = platform_get_drvdata(pdev);
4051
4052 coresight_unregister(drvdata->csdev);
4053 return 0;
4054}
4055
4056static const struct of_device_id tpdm_match[] = {
4057 {.compatible = "qcom,coresight-tpdm"},
4058 {}
4059};
4060
4061static struct platform_driver tpdm_driver = {
4062 .probe = tpdm_probe,
4063 .remove = tpdm_remove,
4064 .driver = {
4065 .name = "coresight-tpdm",
4066 .owner = THIS_MODULE,
4067 .of_match_table = tpdm_match,
4068 },
4069};
4070
4071static int __init tpdm_init(void)
4072{
4073 return platform_driver_register(&tpdm_driver);
4074}
4075module_init(tpdm_init);
4076
4077static void __exit tpdm_exit(void)
4078{
4079 platform_driver_unregister(&tpdm_driver);
4080}
4081module_exit(tpdm_exit);
4082
4083MODULE_LICENSE("GPL v2");
4084MODULE_DESCRIPTION("Trace, Profiling & Diagnostic Monitor driver");