blob: 1ccf3dace7555a6bb812a26a9dc96cd4e779b64b [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;
531
532 tpdm_writel(drvdata, drvdata->cmb->patt_val[TPDM_CMB_LSB],
533 TPDM_CMB_TPR(TPDM_CMB_LSB));
534 tpdm_writel(drvdata, drvdata->cmb->patt_mask[TPDM_CMB_LSB],
535 TPDM_CMB_TPMR(TPDM_CMB_LSB));
536 tpdm_writel(drvdata, drvdata->cmb->patt_val[TPDM_CMB_MSB],
537 TPDM_CMB_TPR(TPDM_CMB_MSB));
538 tpdm_writel(drvdata, drvdata->cmb->patt_mask[TPDM_CMB_MSB],
539 TPDM_CMB_TPMR(TPDM_CMB_MSB));
540
541 tpdm_writel(drvdata, drvdata->cmb->trig_patt_val[TPDM_CMB_LSB],
542 TPDM_CMB_XPR(TPDM_CMB_LSB));
543 tpdm_writel(drvdata, drvdata->cmb->trig_patt_mask[TPDM_CMB_LSB],
544 TPDM_CMB_XPMR(TPDM_CMB_LSB));
545 tpdm_writel(drvdata, drvdata->cmb->trig_patt_val[TPDM_CMB_MSB],
546 TPDM_CMB_XPR(TPDM_CMB_MSB));
547 tpdm_writel(drvdata, drvdata->cmb->trig_patt_mask[TPDM_CMB_MSB],
548 TPDM_CMB_XPMR(TPDM_CMB_MSB));
549
550 val = tpdm_readl(drvdata, TPDM_CMB_TIER);
551 if (drvdata->cmb->patt_ts == true)
552 val = val | BIT(0);
553 else
554 val = val & ~BIT(0);
555 if (drvdata->cmb->trig_ts == true)
556 val = val | BIT(1);
557 else
558 val = val & ~BIT(1);
559 tpdm_writel(drvdata, val, TPDM_CMB_TIER);
560
561 __tpdm_config_cmb_msr(drvdata);
562
563 val = tpdm_readl(drvdata, TPDM_CMB_CR);
564 /* Set the flow control bit */
565 val = val & ~BIT(2);
566 if (drvdata->cmb->mode == TPDM_CMB_MODE_CONTINUOUS)
567 val = val & ~BIT(1);
568 else
569 val = val | BIT(1);
570 tpdm_writel(drvdata, val, TPDM_CMB_CR);
571 /* Set the enable bit */
572 val = val | BIT(0);
573 tpdm_writel(drvdata, val, TPDM_CMB_CR);
574}
575
Satyajit Desaie104ff52016-09-12 16:38:12 -0700576static void __tpdm_enable_mcmb(struct tpdm_drvdata *drvdata)
577{
578 uint32_t val;
579 struct mcmb_dataset *mcmb = drvdata->cmb->mcmb;
580
581 tpdm_writel(drvdata, drvdata->cmb->patt_val[TPDM_CMB_LSB],
582 TPDM_CMB_TPR(TPDM_CMB_LSB));
583 tpdm_writel(drvdata, drvdata->cmb->patt_mask[TPDM_CMB_LSB],
584 TPDM_CMB_TPMR(TPDM_CMB_LSB));
585 tpdm_writel(drvdata, drvdata->cmb->patt_val[TPDM_CMB_MSB],
586 TPDM_CMB_TPR(TPDM_CMB_MSB));
587 tpdm_writel(drvdata, drvdata->cmb->patt_mask[TPDM_CMB_MSB],
588 TPDM_CMB_TPMR(TPDM_CMB_MSB));
589
590 tpdm_writel(drvdata, drvdata->cmb->trig_patt_val[TPDM_CMB_LSB],
591 TPDM_CMB_XPR(TPDM_CMB_LSB));
592 tpdm_writel(drvdata, drvdata->cmb->trig_patt_mask[TPDM_CMB_LSB],
593 TPDM_CMB_XPMR(TPDM_CMB_LSB));
594 tpdm_writel(drvdata, drvdata->cmb->trig_patt_val[TPDM_CMB_MSB],
595 TPDM_CMB_XPR(TPDM_CMB_MSB));
596 tpdm_writel(drvdata, drvdata->cmb->trig_patt_mask[TPDM_CMB_MSB],
597 TPDM_CMB_XPMR(TPDM_CMB_MSB));
598
599 val = tpdm_readl(drvdata, TPDM_CMB_TIER);
600 if (drvdata->cmb->patt_ts == true)
601 val = val | BIT(0);
602 else
603 val = val & ~BIT(0);
604 if (drvdata->cmb->trig_ts == true)
605 val = val | BIT(1);
606 else
607 val = val & ~BIT(1);
608 tpdm_writel(drvdata, val, TPDM_CMB_TIER);
609
610 __tpdm_config_cmb_msr(drvdata);
611
612 val = tpdm_readl(drvdata, TPDM_CMB_CR);
613 /* Set the flow control bit */
614 val = val & ~BIT(2);
615 if (drvdata->cmb->mode == TPDM_CMB_MODE_CONTINUOUS)
616 val = val & ~BIT(1);
617 else
618 val = val | BIT(1);
619
620 val = val | (BMVAL(mcmb->mcmb_trig_lane, 0, 3) << 18);
621
622 val = val | (mcmb->mcmb_lane_select << 10);
623
624 tpdm_writel(drvdata, val, TPDM_CMB_CR);
625 /* Set the enable bit */
626 val = val | BIT(0);
627 tpdm_writel(drvdata, val, TPDM_CMB_CR);
628}
629
Satyajit Desaif151d682016-09-12 16:18:03 -0700630static void __tpdm_enable(struct tpdm_drvdata *drvdata)
631{
632 TPDM_UNLOCK(drvdata);
633
634 if (drvdata->clk_enable)
635 tpdm_writel(drvdata, 0x1, TPDM_CLK_CTRL);
636
637 if (test_bit(TPDM_DS_GPR, drvdata->enable_ds))
638 __tpdm_enable_gpr(drvdata);
639
640 if (test_bit(TPDM_DS_BC, drvdata->enable_ds))
641 __tpdm_enable_bc(drvdata);
642
643 if (test_bit(TPDM_DS_TC, drvdata->enable_ds))
644 __tpdm_enable_tc(drvdata);
645
646 if (test_bit(TPDM_DS_DSB, drvdata->enable_ds))
647 __tpdm_enable_dsb(drvdata);
648
649 if (test_bit(TPDM_DS_CMB, drvdata->enable_ds))
650 __tpdm_enable_cmb(drvdata);
Satyajit Desaie104ff52016-09-12 16:38:12 -0700651 else if (test_bit(TPDM_DS_MCMB, drvdata->enable_ds))
652 __tpdm_enable_mcmb(drvdata);
Satyajit Desaif151d682016-09-12 16:18:03 -0700653
654 TPDM_LOCK(drvdata);
655}
656
657static int tpdm_enable(struct coresight_device *csdev,
Satyajit Desaiee828fb2017-02-07 13:51:32 -0800658 struct perf_event *event, u32 mode)
Satyajit Desaif151d682016-09-12 16:18:03 -0700659{
660 struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
661 int ret;
662
663 ret = clk_prepare_enable(drvdata->clk);
664 if (ret)
665 return ret;
666
667 mutex_lock(&drvdata->lock);
668 __tpdm_enable(drvdata);
669 drvdata->enable = true;
670 mutex_unlock(&drvdata->lock);
671
672 dev_info(drvdata->dev, "TPDM tracing enabled\n");
673 return 0;
674}
675
676static void __tpdm_disable_bc(struct tpdm_drvdata *drvdata)
677{
678 uint32_t config;
679
680 config = tpdm_readl(drvdata, TPDM_BC_CR);
681 config = config & ~BIT(0);
682 tpdm_writel(drvdata, config, TPDM_BC_CR);
683}
684
685static void __tpdm_disable_tc(struct tpdm_drvdata *drvdata)
686{
687 uint32_t config;
688
689 config = tpdm_readl(drvdata, TPDM_TC_CR);
690 config = config & ~BIT(0);
691 tpdm_writel(drvdata, config, TPDM_TC_CR);
692}
693
694static void __tpdm_disable_dsb(struct tpdm_drvdata *drvdata)
695{
696 uint32_t config;
697
698 config = tpdm_readl(drvdata, TPDM_DSB_CR);
699 config = config & ~BIT(0);
700 tpdm_writel(drvdata, config, TPDM_DSB_CR);
701}
702
703static void __tpdm_disable_cmb(struct tpdm_drvdata *drvdata)
704{
705 uint32_t config;
706
707 config = tpdm_readl(drvdata, TPDM_CMB_CR);
708 config = config & ~BIT(0);
709 tpdm_writel(drvdata, config, TPDM_CMB_CR);
710}
711
712static void __tpdm_disable(struct tpdm_drvdata *drvdata)
713{
714 TPDM_UNLOCK(drvdata);
715
716 if (test_bit(TPDM_DS_BC, drvdata->enable_ds))
717 __tpdm_disable_bc(drvdata);
718
719 if (test_bit(TPDM_DS_TC, drvdata->enable_ds))
720 __tpdm_disable_tc(drvdata);
721
722 if (test_bit(TPDM_DS_DSB, drvdata->enable_ds))
723 __tpdm_disable_dsb(drvdata);
724
725 if (test_bit(TPDM_DS_CMB, drvdata->enable_ds))
726 __tpdm_disable_cmb(drvdata);
727
728 if (drvdata->clk_enable)
729 tpdm_writel(drvdata, 0x0, TPDM_CLK_CTRL);
730
731 TPDM_LOCK(drvdata);
732}
733
Satyajit Desaiee828fb2017-02-07 13:51:32 -0800734static void tpdm_disable(struct coresight_device *csdev,
735 struct perf_event *event)
Satyajit Desaif151d682016-09-12 16:18:03 -0700736{
737 struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
738
739 mutex_lock(&drvdata->lock);
740 __tpdm_disable(drvdata);
741 drvdata->enable = false;
742 mutex_unlock(&drvdata->lock);
743
744 clk_disable_unprepare(drvdata->clk);
745
746 dev_info(drvdata->dev, "TPDM tracing disabled\n");
747}
748
749static int tpdm_trace_id(struct coresight_device *csdev)
750{
751 struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
752
753 return drvdata->traceid;
754}
755
756static const struct coresight_ops_source tpdm_source_ops = {
757 .trace_id = tpdm_trace_id,
758 .enable = tpdm_enable,
759 .disable = tpdm_disable,
760};
761
762static const struct coresight_ops tpdm_cs_ops = {
763 .source_ops = &tpdm_source_ops,
764};
765
766static ssize_t tpdm_show_available_datasets(struct device *dev,
767 struct device_attribute *attr,
768 char *buf)
769{
770 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
771 ssize_t size = 0;
772
773 if (test_bit(TPDM_DS_IMPLDEF, drvdata->datasets))
774 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s",
775 "IMPLDEF");
776
777 if (test_bit(TPDM_DS_DSB, drvdata->datasets))
778 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "DSB");
779
780 if (test_bit(TPDM_DS_CMB, drvdata->datasets))
781 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "CMB");
782
783 if (test_bit(TPDM_DS_TC, drvdata->datasets))
784 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "TC");
785
786 if (test_bit(TPDM_DS_BC, drvdata->datasets))
787 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "BC");
788
789 if (test_bit(TPDM_DS_GPR, drvdata->datasets))
790 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "GPR");
791
Satyajit Desaie104ff52016-09-12 16:38:12 -0700792 if (test_bit(TPDM_DS_MCMB, drvdata->datasets))
793 size += scnprintf(buf + size, PAGE_SIZE - size, "%-8s", "MCMB");
794
Satyajit Desaif151d682016-09-12 16:18:03 -0700795 size += scnprintf(buf + size, PAGE_SIZE - size, "\n");
796 return size;
797}
Satyajit Desai326497c2016-11-14 10:15:03 -0800798static DEVICE_ATTR(available_datasets, 0444, tpdm_show_available_datasets,
Satyajit Desaif151d682016-09-12 16:18:03 -0700799 NULL);
800
801static ssize_t tpdm_show_enable_datasets(struct device *dev,
802 struct device_attribute *attr,
803 char *buf)
804{
805 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
806 ssize_t size;
807
808 size = scnprintf(buf, PAGE_SIZE, "%*pb\n", TPDM_DATASETS,
809 drvdata->enable_ds);
810
811 if (PAGE_SIZE - size < 2)
812 size = -EINVAL;
813 else
814 size += scnprintf(buf + size, 2, "\n");
815 return size;
816}
817
818static ssize_t tpdm_store_enable_datasets(struct device *dev,
819 struct device_attribute *attr,
820 const char *buf,
821 size_t size)
822{
823 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
824 unsigned long val;
825 int i;
826
827 if (kstrtoul(buf, 16, &val))
828 return -EINVAL;
829
830 mutex_lock(&drvdata->lock);
831 if (drvdata->enable) {
832 mutex_unlock(&drvdata->lock);
833 return -EPERM;
834 }
835
836 for (i = 0; i < TPDM_DATASETS; i++) {
837 if (test_bit(i, drvdata->datasets) && (val & BIT(i)))
838 __set_bit(i, drvdata->enable_ds);
839 else
840 __clear_bit(i, drvdata->enable_ds);
841 }
842 mutex_unlock(&drvdata->lock);
843 return size;
844}
Satyajit Desai326497c2016-11-14 10:15:03 -0800845static DEVICE_ATTR(enable_datasets, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -0700846 tpdm_show_enable_datasets, tpdm_store_enable_datasets);
847
848static ssize_t tpdm_show_gp_regs(struct device *dev,
849 struct device_attribute *attr,
850 char *buf)
851{
852 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
853 ssize_t size = 0;
854 int i = 0;
855
856 if (!test_bit(TPDM_DS_GPR, drvdata->datasets))
857 return -EPERM;
858
859 mutex_lock(&drvdata->lock);
860 for (i = 0; i < TPDM_GPR_REGS_MAX; i++) {
861 if (!test_bit(i, drvdata->gpr->gpr_dirty))
862 continue;
863 size += scnprintf(buf + size, PAGE_SIZE - size,
864 "Index: 0x%x Value: 0x%x\n", i,
865 drvdata->gpr->gp_regs[i]);
866 }
867 mutex_unlock(&drvdata->lock);
868 return size;
869}
870
871static ssize_t tpdm_store_gp_regs(struct device *dev,
872 struct device_attribute *attr,
873 const char *buf,
874 size_t size)
875{
876 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
877 unsigned long index, val;
878
879 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
880 return -EINVAL;
881 if (!test_bit(TPDM_DS_GPR, drvdata->datasets) ||
882 index >= TPDM_GPR_REGS_MAX)
883 return -EPERM;
884
885 mutex_lock(&drvdata->lock);
886 drvdata->gpr->gp_regs[index] = val;
887 __set_bit(index, drvdata->gpr->gpr_dirty);
888 mutex_unlock(&drvdata->lock);
889 return size;
890}
Satyajit Desai326497c2016-11-14 10:15:03 -0800891static DEVICE_ATTR(gp_regs, 0644, tpdm_show_gp_regs,
Satyajit Desaif151d682016-09-12 16:18:03 -0700892 tpdm_store_gp_regs);
893
894static ssize_t tpdm_show_bc_capture_mode(struct device *dev,
895 struct device_attribute *attr,
896 char *buf)
897{
898 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
899
900 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
901 return -EPERM;
902
903 return scnprintf(buf, PAGE_SIZE, "%s\n",
904 drvdata->bc->capture_mode == TPDM_MODE_ATB ?
905 "ATB" : "APB");
906}
907
908static ssize_t tpdm_store_bc_capture_mode(struct device *dev,
909 struct device_attribute *attr,
910 const char *buf,
911 size_t size)
912{
913 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
914 char str[20] = "";
915 uint32_t val;
916
917 if (size >= 20)
918 return -EINVAL;
919 if (sscanf(buf, "%s", str) != 1)
920 return -EINVAL;
921 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
922 return -EPERM;
923
924 mutex_lock(&drvdata->lock);
925 if (!drvdata->enable) {
926 mutex_unlock(&drvdata->lock);
927 return -EPERM;
928 }
929
930 if (!strcmp(str, "ATB")) {
931 drvdata->bc->capture_mode = TPDM_MODE_ATB;
932 } else if (!strcmp(str, "APB") &&
933 drvdata->bc->retrieval_mode == TPDM_MODE_APB) {
934
935 TPDM_UNLOCK(drvdata);
936 val = tpdm_readl(drvdata, TPDM_BC_CR);
937 val = val | BIT(3);
938 tpdm_writel(drvdata, val, TPDM_BC_CR);
939 TPDM_LOCK(drvdata);
940
941 drvdata->bc->capture_mode = TPDM_MODE_APB;
942 } else {
943 mutex_unlock(&drvdata->lock);
944 return -EINVAL;
945 }
946 mutex_unlock(&drvdata->lock);
947 return size;
948}
Satyajit Desai326497c2016-11-14 10:15:03 -0800949static DEVICE_ATTR(bc_capture_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -0700950 tpdm_show_bc_capture_mode, tpdm_store_bc_capture_mode);
951
952static ssize_t tpdm_show_bc_retrieval_mode(struct device *dev,
953 struct device_attribute *attr,
954 char *buf)
955{
956 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
957
958 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
959 return -EPERM;
960
961 return scnprintf(buf, PAGE_SIZE, "%s\n",
962 drvdata->bc->retrieval_mode == TPDM_MODE_ATB ?
963 "ATB" : "APB");
964}
965
966static ssize_t tpdm_store_bc_retrieval_mode(struct device *dev,
967 struct device_attribute *attr,
968 const char *buf,
969 size_t size)
970{
971 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
972 char str[20] = "";
973
974 if (size >= 20)
975 return -EINVAL;
976 if (sscanf(buf, "%s", str) != 1)
977 return -EINVAL;
978 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
979 return -EPERM;
980
981 mutex_lock(&drvdata->lock);
982 if (drvdata->enable) {
983 mutex_unlock(&drvdata->lock);
984 return -EPERM;
985 }
986
987 if (!strcmp(str, "ATB")) {
988 drvdata->bc->retrieval_mode = TPDM_MODE_ATB;
989 } else if (!strcmp(str, "APB")) {
990 drvdata->bc->retrieval_mode = TPDM_MODE_APB;
991 } else {
992 mutex_unlock(&drvdata->lock);
993 return -EINVAL;
994 }
995 mutex_unlock(&drvdata->lock);
996 return size;
997}
Satyajit Desai326497c2016-11-14 10:15:03 -0800998static DEVICE_ATTR(bc_retrieval_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -0700999 tpdm_show_bc_retrieval_mode, tpdm_store_bc_retrieval_mode);
1000
1001static ssize_t tpdm_store_bc_reset_counters(struct device *dev,
1002 struct device_attribute *attr,
1003 const char *buf,
1004 size_t size)
1005{
1006 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1007 unsigned long val;
1008
1009 if (kstrtoul(buf, 16, &val))
1010 return -EINVAL;
1011 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1012 return -EPERM;
1013
1014 mutex_lock(&drvdata->lock);
1015 if (!drvdata->enable) {
1016 mutex_unlock(&drvdata->lock);
1017 return -EPERM;
1018 }
1019
1020 if (val) {
1021 TPDM_UNLOCK(drvdata);
1022 val = tpdm_readl(drvdata, TPDM_BC_CR);
1023 val = val | BIT(1);
1024 tpdm_writel(drvdata, val, TPDM_BC_CR);
1025 TPDM_LOCK(drvdata);
1026 }
1027 mutex_unlock(&drvdata->lock);
1028 return size;
1029}
Satyajit Desai326497c2016-11-14 10:15:03 -08001030static DEVICE_ATTR(bc_reset_counters, 0644, NULL,
Satyajit Desaif151d682016-09-12 16:18:03 -07001031 tpdm_store_bc_reset_counters);
1032
1033static ssize_t tpdm_show_bc_sat_mode(struct device *dev,
1034 struct device_attribute *attr,
1035 char *buf)
1036{
1037 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1038
1039 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1040 return -EPERM;
1041
1042 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1043 (unsigned long)drvdata->bc->sat_mode);
1044}
1045
1046static ssize_t tpdm_store_bc_sat_mode(struct device *dev,
1047 struct device_attribute *attr,
1048 const char *buf,
1049 size_t size)
1050{
1051 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1052 unsigned long val;
1053
1054 if (kstrtoul(buf, 16, &val))
1055 return -EINVAL;
1056 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1057 return -EPERM;
1058
1059 mutex_lock(&drvdata->lock);
1060 drvdata->bc->sat_mode = val;
1061 mutex_unlock(&drvdata->lock);
1062 return size;
1063}
Satyajit Desai326497c2016-11-14 10:15:03 -08001064static DEVICE_ATTR(bc_sat_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001065 tpdm_show_bc_sat_mode, tpdm_store_bc_sat_mode);
1066
1067static ssize_t tpdm_show_bc_enable_counters(struct device *dev,
1068 struct device_attribute *attr,
1069 char *buf)
1070{
1071 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1072
1073 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1074 return -EPERM;
1075
1076 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1077 (unsigned long)drvdata->bc->enable_counters);
1078}
1079
1080static ssize_t tpdm_store_bc_enable_counters(struct device *dev,
1081 struct device_attribute *attr,
1082 const char *buf,
1083 size_t size)
1084{
1085 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1086 unsigned long val;
1087
1088 if (kstrtoul(buf, 16, &val))
1089 return -EINVAL;
1090 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1091 return -EPERM;
1092
1093 mutex_lock(&drvdata->lock);
1094 drvdata->bc->enable_counters = val;
1095 mutex_unlock(&drvdata->lock);
1096 return size;
1097}
Satyajit Desai326497c2016-11-14 10:15:03 -08001098static DEVICE_ATTR(bc_enable_counters, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001099 tpdm_show_bc_enable_counters, tpdm_store_bc_enable_counters);
1100
1101static ssize_t tpdm_show_bc_clear_counters(struct device *dev,
1102 struct device_attribute *attr,
1103 char *buf)
1104{
1105 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1106
1107 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1108 return -EPERM;
1109
1110 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1111 (unsigned long)drvdata->bc->clear_counters);
1112}
1113
1114static ssize_t tpdm_store_bc_clear_counters(struct device *dev,
1115 struct device_attribute *attr,
1116 const char *buf,
1117 size_t size)
1118{
1119 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1120 unsigned long val;
1121
1122 if (kstrtoul(buf, 16, &val))
1123 return -EINVAL;
1124 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1125 return -EPERM;
1126
1127 mutex_lock(&drvdata->lock);
1128 drvdata->bc->clear_counters = val;
1129 mutex_unlock(&drvdata->lock);
1130 return size;
1131}
Satyajit Desai326497c2016-11-14 10:15:03 -08001132static DEVICE_ATTR(bc_clear_counters, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001133 tpdm_show_bc_clear_counters, tpdm_store_bc_clear_counters);
1134
1135static ssize_t tpdm_show_bc_enable_irq(struct device *dev,
1136 struct device_attribute *attr,
1137 char *buf)
1138{
1139 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1140
1141 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1142 return -EPERM;
1143
1144 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1145 (unsigned long)drvdata->bc->enable_irq);
1146}
1147
1148static ssize_t tpdm_store_bc_enable_irq(struct device *dev,
1149 struct device_attribute *attr,
1150 const char *buf,
1151 size_t size)
1152{
1153 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1154 unsigned long val;
1155
1156 if (kstrtoul(buf, 16, &val))
1157 return -EINVAL;
1158 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1159 return -EPERM;
1160
1161 mutex_lock(&drvdata->lock);
1162 drvdata->bc->enable_irq = val;
1163 mutex_unlock(&drvdata->lock);
1164 return size;
1165}
Satyajit Desai326497c2016-11-14 10:15:03 -08001166static DEVICE_ATTR(bc_enable_irq, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001167 tpdm_show_bc_enable_irq, tpdm_store_bc_enable_irq);
1168
1169static ssize_t tpdm_show_bc_clear_irq(struct device *dev,
1170 struct device_attribute *attr,
1171 char *buf)
1172{
1173 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1174
1175 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1176 return -EPERM;
1177
1178 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1179 (unsigned long)drvdata->bc->clear_irq);
1180}
1181
1182static ssize_t tpdm_store_bc_clear_irq(struct device *dev,
1183 struct device_attribute *attr,
1184 const char *buf,
1185 size_t size)
1186{
1187 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1188 unsigned long val;
1189
1190 if (kstrtoul(buf, 16, &val))
1191 return -EINVAL;
1192 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1193 return -EPERM;
1194
1195 mutex_lock(&drvdata->lock);
1196 drvdata->bc->clear_irq = val;
1197 mutex_unlock(&drvdata->lock);
1198 return size;
1199}
Satyajit Desai326497c2016-11-14 10:15:03 -08001200static DEVICE_ATTR(bc_clear_irq, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001201 tpdm_show_bc_clear_irq, tpdm_store_bc_clear_irq);
1202
1203static ssize_t tpdm_show_bc_trig_val_lo(struct device *dev,
1204 struct device_attribute *attr,
1205 char *buf)
1206{
1207 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1208 ssize_t size = 0;
1209 int i = 0;
1210
1211 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1212 return -EPERM;
1213
1214 mutex_lock(&drvdata->lock);
1215 for (i = 0; i < TPDM_BC_MAX_COUNTERS; i++)
1216 size += scnprintf(buf + size, PAGE_SIZE - size,
1217 "Index: 0x%x Value: 0x%x\n", i,
1218 drvdata->bc->trig_val_lo[i]);
1219 mutex_unlock(&drvdata->lock);
1220 return size;
1221}
1222
1223static ssize_t tpdm_store_bc_trig_val_lo(struct device *dev,
1224 struct device_attribute *attr,
1225 const char *buf,
1226 size_t size)
1227{
1228 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1229 unsigned long index, val;
1230
1231 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
1232 return -EINVAL;
1233 if (!test_bit(TPDM_DS_BC, drvdata->datasets) ||
1234 index >= drvdata->bc_counters_avail ||
1235 drvdata->bc_trig_type == TPDM_SUPPORT_TYPE_NO ||
1236 (drvdata->bc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL && index > 0))
1237 return -EPERM;
1238
1239 mutex_lock(&drvdata->lock);
1240 drvdata->bc->trig_val_lo[index] = val;
1241 mutex_unlock(&drvdata->lock);
1242 return size;
1243}
Satyajit Desai326497c2016-11-14 10:15:03 -08001244static DEVICE_ATTR(bc_trig_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001245 tpdm_show_bc_trig_val_lo, tpdm_store_bc_trig_val_lo);
1246
1247static ssize_t tpdm_show_bc_trig_val_hi(struct device *dev,
1248 struct device_attribute *attr,
1249 char *buf)
1250{
1251 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1252 ssize_t size = 0;
1253 int i = 0;
1254
1255 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1256 return -EPERM;
1257
1258 mutex_lock(&drvdata->lock);
1259 for (i = 0; i < TPDM_BC_MAX_COUNTERS; i++)
1260 size += scnprintf(buf + size, PAGE_SIZE - size,
1261 "Index: 0x%x Value: 0x%x\n", i,
1262 drvdata->bc->trig_val_hi[i]);
1263 mutex_unlock(&drvdata->lock);
1264 return size;
1265}
1266
1267static ssize_t tpdm_store_bc_trig_val_hi(struct device *dev,
1268 struct device_attribute *attr,
1269 const char *buf,
1270 size_t size)
1271{
1272 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1273 unsigned long index, val;
1274
1275 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
1276 return -EINVAL;
1277 if (!test_bit(TPDM_DS_BC, drvdata->datasets) ||
1278 index >= drvdata->bc_counters_avail ||
1279 drvdata->bc_trig_type == TPDM_SUPPORT_TYPE_NO ||
1280 (drvdata->bc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL && index > 0))
1281 return -EPERM;
1282
1283 mutex_lock(&drvdata->lock);
1284 drvdata->bc->trig_val_hi[index] = val;
1285 mutex_unlock(&drvdata->lock);
1286 return size;
1287}
Satyajit Desai326497c2016-11-14 10:15:03 -08001288static DEVICE_ATTR(bc_trig_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001289 tpdm_show_bc_trig_val_hi, tpdm_store_bc_trig_val_hi);
1290
1291static ssize_t tpdm_show_bc_enable_ganging(struct device *dev,
1292 struct device_attribute *attr,
1293 char *buf)
1294{
1295 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1296
1297 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1298 return -EPERM;
1299
1300 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1301 (unsigned long)drvdata->bc->enable_ganging);
1302}
1303
1304static ssize_t tpdm_store_bc_enable_ganging(struct device *dev,
1305 struct device_attribute *attr,
1306 const char *buf,
1307 size_t size)
1308{
1309 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1310 unsigned long val;
1311
1312 if (kstrtoul(buf, 16, &val))
1313 return -EINVAL;
1314 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1315 return -EPERM;
1316
1317 mutex_lock(&drvdata->lock);
1318 drvdata->bc->enable_ganging = val;
1319 mutex_unlock(&drvdata->lock);
1320 return size;
1321}
Satyajit Desai326497c2016-11-14 10:15:03 -08001322static DEVICE_ATTR(bc_enable_ganging, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001323 tpdm_show_bc_enable_ganging, tpdm_store_bc_enable_ganging);
1324
1325static ssize_t tpdm_show_bc_overflow_val(struct device *dev,
1326 struct device_attribute *attr,
1327 char *buf)
1328{
1329 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1330 ssize_t size = 0;
1331 int i = 0;
1332
1333 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1334 return -EPERM;
1335
1336 mutex_lock(&drvdata->lock);
1337 for (i = 0; i < TPDM_BC_MAX_OVERFLOW; i++)
1338 size += scnprintf(buf + size, PAGE_SIZE - size,
1339 "Index: 0x%x Value: 0x%x\n", i,
1340 drvdata->bc->overflow_val[i]);
1341 mutex_unlock(&drvdata->lock);
1342 return size;
1343}
1344
1345static ssize_t tpdm_store_bc_overflow_val(struct device *dev,
1346 struct device_attribute *attr,
1347 const char *buf,
1348 size_t size)
1349{
1350 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1351 unsigned long index, val;
1352
1353 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
1354 return -EINVAL;
1355 if (!test_bit(TPDM_DS_BC, drvdata->datasets) ||
1356 index >= TPDM_BC_MAX_OVERFLOW)
1357 return -EPERM;
1358
1359 mutex_lock(&drvdata->lock);
1360 drvdata->bc->overflow_val[index] = val;
1361 mutex_unlock(&drvdata->lock);
1362 return size;
1363}
Satyajit Desai326497c2016-11-14 10:15:03 -08001364static DEVICE_ATTR(bc_overflow_val, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001365 tpdm_show_bc_overflow_val, tpdm_store_bc_overflow_val);
1366
1367static ssize_t tpdm_show_bc_ovsr(struct device *dev,
1368 struct device_attribute *attr,
1369 char *buf)
1370{
1371 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1372 unsigned long val;
1373
1374 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1375 return -EPERM;
1376
1377 mutex_lock(&drvdata->lock);
1378 if (!drvdata->enable) {
1379 mutex_unlock(&drvdata->lock);
1380 return -EPERM;
1381 }
1382
1383 TPDM_UNLOCK(drvdata);
1384 val = tpdm_readl(drvdata, TPDM_BC_OVSR);
1385 TPDM_LOCK(drvdata);
1386 mutex_unlock(&drvdata->lock);
1387 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
1388}
1389
1390static ssize_t tpdm_store_bc_ovsr(struct device *dev,
1391 struct device_attribute *attr,
1392 const char *buf,
1393 size_t size)
1394{
1395 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1396 unsigned long val;
1397
1398 if (kstrtoul(buf, 16, &val))
1399 return -EINVAL;
1400 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1401 return -EPERM;
1402
1403 mutex_lock(&drvdata->lock);
1404 if (!drvdata->enable) {
1405 mutex_unlock(&drvdata->lock);
1406 return -EPERM;
1407 }
1408
1409 if (val) {
1410 TPDM_UNLOCK(drvdata);
1411 tpdm_writel(drvdata, val, TPDM_BC_OVSR);
1412 TPDM_LOCK(drvdata);
1413 }
1414 mutex_unlock(&drvdata->lock);
1415 return size;
1416}
Satyajit Desai326497c2016-11-14 10:15:03 -08001417static DEVICE_ATTR(bc_ovsr, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001418 tpdm_show_bc_ovsr, tpdm_store_bc_ovsr);
1419
1420static ssize_t tpdm_show_bc_counter_sel(struct device *dev,
1421 struct device_attribute *attr,
1422 char *buf)
1423{
1424 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1425 unsigned long val;
1426
1427 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1428 return -EPERM;
1429
1430 mutex_lock(&drvdata->lock);
1431 if (!drvdata->enable) {
1432 mutex_unlock(&drvdata->lock);
1433 return -EPERM;
1434 }
1435
1436 TPDM_UNLOCK(drvdata);
1437 val = tpdm_readl(drvdata, TPDM_BC_SELR);
1438 TPDM_LOCK(drvdata);
1439 mutex_unlock(&drvdata->lock);
1440 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
1441}
1442
1443static ssize_t tpdm_store_bc_counter_sel(struct device *dev,
1444 struct device_attribute *attr,
1445 const char *buf,
1446 size_t size)
1447{
1448 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1449 unsigned long val;
1450
1451 if (kstrtoul(buf, 16, &val))
1452 return -EINVAL;
1453 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1454 return -EPERM;
1455
1456 mutex_lock(&drvdata->lock);
1457 if (!drvdata->enable || val >= drvdata->bc_counters_avail) {
1458 mutex_unlock(&drvdata->lock);
1459 return -EPERM;
1460 }
1461
1462 TPDM_UNLOCK(drvdata);
1463 tpdm_writel(drvdata, val, TPDM_BC_SELR);
1464 TPDM_LOCK(drvdata);
1465 mutex_unlock(&drvdata->lock);
1466 return size;
1467}
Satyajit Desai326497c2016-11-14 10:15:03 -08001468static DEVICE_ATTR(bc_counter_sel, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001469 tpdm_show_bc_counter_sel, tpdm_store_bc_counter_sel);
1470
1471static ssize_t tpdm_show_bc_count_val_lo(struct device *dev,
1472 struct device_attribute *attr,
1473 char *buf)
1474{
1475 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1476 unsigned long val;
1477
1478 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1479 return -EPERM;
1480
1481 mutex_lock(&drvdata->lock);
1482 if (!drvdata->enable) {
1483 mutex_unlock(&drvdata->lock);
1484 return -EPERM;
1485 }
1486
1487 TPDM_UNLOCK(drvdata);
1488 val = tpdm_readl(drvdata, TPDM_BC_CNTR_LO);
1489 TPDM_LOCK(drvdata);
1490 mutex_unlock(&drvdata->lock);
1491 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
1492}
1493
1494static ssize_t tpdm_store_bc_count_val_lo(struct device *dev,
1495 struct device_attribute *attr,
1496 const char *buf,
1497 size_t size)
1498{
1499 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1500 unsigned long val, select;
1501
1502 if (kstrtoul(buf, 16, &val))
1503 return -EINVAL;
1504 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1505 return -EPERM;
1506
1507 mutex_lock(&drvdata->lock);
1508 if (!drvdata->enable) {
1509 mutex_unlock(&drvdata->lock);
1510 return -EPERM;
1511 }
1512
1513 if (val) {
1514 TPDM_UNLOCK(drvdata);
1515 select = tpdm_readl(drvdata, TPDM_BC_SELR);
1516
1517 /* Check if selected counter is disabled */
1518 if (BVAL(tpdm_readl(drvdata, TPDM_BC_CNTENSET), select)) {
1519 mutex_unlock(&drvdata->lock);
1520 return -EPERM;
1521 }
1522
1523 tpdm_writel(drvdata, val, TPDM_BC_CNTR_LO);
1524 TPDM_LOCK(drvdata);
1525 }
1526 mutex_unlock(&drvdata->lock);
1527 return size;
1528}
Satyajit Desai326497c2016-11-14 10:15:03 -08001529static DEVICE_ATTR(bc_count_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001530 tpdm_show_bc_count_val_lo, tpdm_store_bc_count_val_lo);
1531
1532static ssize_t tpdm_show_bc_count_val_hi(struct device *dev,
1533 struct device_attribute *attr,
1534 char *buf)
1535{
1536 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1537 unsigned long val;
1538
1539 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1540 return -EPERM;
1541
1542 mutex_lock(&drvdata->lock);
1543 if (!drvdata->enable) {
1544 mutex_unlock(&drvdata->lock);
1545 return -EPERM;
1546 }
1547
1548 TPDM_UNLOCK(drvdata);
1549 val = tpdm_readl(drvdata, TPDM_BC_CNTR_HI);
1550 TPDM_LOCK(drvdata);
1551 mutex_unlock(&drvdata->lock);
1552 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
1553}
1554
1555static ssize_t tpdm_store_bc_count_val_hi(struct device *dev,
1556 struct device_attribute *attr,
1557 const char *buf,
1558 size_t size)
1559{
1560 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1561 unsigned long val, select;
1562
1563 if (kstrtoul(buf, 16, &val))
1564 return -EINVAL;
1565 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1566 return -EPERM;
1567
1568 mutex_lock(&drvdata->lock);
1569 if (!drvdata->enable) {
1570 mutex_unlock(&drvdata->lock);
1571 return -EPERM;
1572 }
1573
1574 if (val) {
1575 TPDM_UNLOCK(drvdata);
1576 select = tpdm_readl(drvdata, TPDM_BC_SELR);
1577
1578 /* Check if selected counter is disabled */
1579 if (BVAL(tpdm_readl(drvdata, TPDM_BC_CNTENSET), select)) {
1580 mutex_unlock(&drvdata->lock);
1581 return -EPERM;
1582 }
1583
1584 tpdm_writel(drvdata, val, TPDM_BC_CNTR_HI);
1585 TPDM_LOCK(drvdata);
1586 }
1587 mutex_unlock(&drvdata->lock);
1588 return size;
1589}
Satyajit Desai326497c2016-11-14 10:15:03 -08001590static DEVICE_ATTR(bc_count_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001591 tpdm_show_bc_count_val_hi, tpdm_store_bc_count_val_hi);
1592
1593static ssize_t tpdm_show_bc_shadow_val_lo(struct device *dev,
1594 struct device_attribute *attr,
1595 char *buf)
1596{
1597 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1598 ssize_t size = 0;
1599 int i = 0;
1600
1601 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1602 return -EPERM;
1603
1604 mutex_lock(&drvdata->lock);
1605 if (!drvdata->enable) {
1606 mutex_unlock(&drvdata->lock);
1607 return -EPERM;
1608 }
1609
1610 TPDM_UNLOCK(drvdata);
1611 for (i = 0; i < drvdata->bc_counters_avail; i++) {
1612 size += scnprintf(buf + size, PAGE_SIZE - size,
1613 "Index: 0x%x Value: 0x%x\n", i,
1614 tpdm_readl(drvdata, TPDM_BC_SHADOW_LO(i)));
1615 }
1616 TPDM_LOCK(drvdata);
1617 mutex_unlock(&drvdata->lock);
1618 return size;
1619}
Satyajit Desai326497c2016-11-14 10:15:03 -08001620static DEVICE_ATTR(bc_shadow_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001621 tpdm_show_bc_shadow_val_lo, NULL);
1622
1623static ssize_t tpdm_show_bc_shadow_val_hi(struct device *dev,
1624 struct device_attribute *attr,
1625 char *buf)
1626{
1627 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1628 ssize_t size = 0;
1629 int i = 0;
1630
1631 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1632 return -EPERM;
1633
1634 mutex_lock(&drvdata->lock);
1635 if (!drvdata->enable) {
1636 mutex_unlock(&drvdata->lock);
1637 return -EPERM;
1638 }
1639
1640 TPDM_UNLOCK(drvdata);
1641 for (i = 0; i < drvdata->bc_counters_avail; i++)
1642 size += scnprintf(buf + size, PAGE_SIZE - size,
1643 "Index: 0x%x Value: 0x%x\n", i,
1644 tpdm_readl(drvdata, TPDM_BC_SHADOW_HI(i)));
1645 TPDM_LOCK(drvdata);
1646 mutex_unlock(&drvdata->lock);
1647 return size;
1648}
Satyajit Desai326497c2016-11-14 10:15:03 -08001649static DEVICE_ATTR(bc_shadow_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001650 tpdm_show_bc_shadow_val_hi, NULL);
1651
1652static ssize_t tpdm_show_bc_sw_inc(struct device *dev,
1653 struct device_attribute *attr,
1654 char *buf)
1655{
1656 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1657 unsigned long val;
1658
1659 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1660 return -EPERM;
1661
1662 mutex_lock(&drvdata->lock);
1663 if (!drvdata->enable) {
1664 mutex_unlock(&drvdata->lock);
1665 return -EPERM;
1666 }
1667
1668 TPDM_UNLOCK(drvdata);
1669 val = tpdm_readl(drvdata, TPDM_BC_SWINC);
1670 TPDM_LOCK(drvdata);
1671 mutex_unlock(&drvdata->lock);
1672 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
1673}
1674
1675static ssize_t tpdm_store_bc_sw_inc(struct device *dev,
1676 struct device_attribute *attr,
1677 const char *buf,
1678 size_t size)
1679{
1680 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1681 unsigned long val;
1682
1683 if (kstrtoul(buf, 16, &val))
1684 return -EINVAL;
1685 if (!test_bit(TPDM_DS_BC, drvdata->enable_ds))
1686 return -EPERM;
1687
1688 mutex_lock(&drvdata->lock);
1689 if (!drvdata->enable) {
1690 mutex_unlock(&drvdata->lock);
1691 return -EPERM;
1692 }
1693
1694 if (val) {
1695 TPDM_UNLOCK(drvdata);
1696 tpdm_writel(drvdata, val, TPDM_BC_SWINC);
1697 TPDM_LOCK(drvdata);
1698 }
1699 mutex_unlock(&drvdata->lock);
1700 return size;
1701}
Satyajit Desai326497c2016-11-14 10:15:03 -08001702static DEVICE_ATTR(bc_sw_inc, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001703 tpdm_show_bc_sw_inc, tpdm_store_bc_sw_inc);
1704
1705static ssize_t tpdm_store_bc_msr(struct device *dev,
1706 struct device_attribute *attr,
1707 const char *buf,
1708 size_t size)
1709{
1710 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1711 unsigned int num, val;
1712 int nval;
1713
1714 if (!drvdata->msr_support)
1715 return -EINVAL;
1716
1717 if (!test_bit(TPDM_DS_BC, drvdata->datasets))
1718 return -EPERM;
1719
1720 nval = sscanf(buf, "%u %x", &num, &val);
1721 if (nval != 2)
1722 return -EINVAL;
1723
1724 if (num >= TPDM_BC_MAX_MSR)
1725 return -EINVAL;
1726
1727 mutex_lock(&drvdata->lock);
1728 drvdata->bc->msr[num] = val;
1729 mutex_unlock(&drvdata->lock);
1730 return size;
1731}
Satyajit Desai326497c2016-11-14 10:15:03 -08001732static DEVICE_ATTR(bc_msr, 0200, NULL, tpdm_store_bc_msr);
Satyajit Desaif151d682016-09-12 16:18:03 -07001733
1734static ssize_t tpdm_show_tc_capture_mode(struct device *dev,
1735 struct device_attribute *attr,
1736 char *buf)
1737{
1738 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1739
1740 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1741 return -EPERM;
1742
1743 return scnprintf(buf, PAGE_SIZE, "%s\n",
1744 drvdata->tc->capture_mode == TPDM_MODE_ATB ?
1745 "ATB" : "APB");
1746}
1747
1748static ssize_t tpdm_store_tc_capture_mode(struct device *dev,
1749 struct device_attribute *attr,
1750 const char *buf,
1751 size_t size)
1752{
1753 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1754 char str[20] = "";
1755 uint32_t val;
1756
1757 if (size >= 20)
1758 return -EINVAL;
1759 if (sscanf(buf, "%s", str) != 1)
1760 return -EINVAL;
1761 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
1762 return -EPERM;
1763
1764 mutex_lock(&drvdata->lock);
1765 if (!drvdata->enable) {
1766 mutex_unlock(&drvdata->lock);
1767 return -EPERM;
1768 }
1769
1770 if (!strcmp(str, "ATB")) {
1771 drvdata->tc->capture_mode = TPDM_MODE_ATB;
1772 } else if (!strcmp(str, "APB") &&
1773 drvdata->tc->retrieval_mode == TPDM_MODE_APB) {
1774
1775 TPDM_UNLOCK(drvdata);
1776 val = tpdm_readl(drvdata, TPDM_TC_CR);
1777 val = val | BIT(3);
1778 tpdm_writel(drvdata, val, TPDM_TC_CR);
1779 TPDM_LOCK(drvdata);
1780
1781 drvdata->tc->capture_mode = TPDM_MODE_APB;
1782 } else {
1783 mutex_unlock(&drvdata->lock);
1784 return -EINVAL;
1785 }
1786 mutex_unlock(&drvdata->lock);
1787 return size;
1788}
Satyajit Desai326497c2016-11-14 10:15:03 -08001789static DEVICE_ATTR(tc_capture_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001790 tpdm_show_tc_capture_mode, tpdm_store_tc_capture_mode);
1791
1792static ssize_t tpdm_show_tc_retrieval_mode(struct device *dev,
1793 struct device_attribute *attr,
1794 char *buf)
1795{
1796 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1797
1798 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1799 return -EPERM;
1800
1801 return scnprintf(buf, PAGE_SIZE, "%s\n",
1802 drvdata->tc->retrieval_mode == TPDM_MODE_ATB ?
1803 "ATB" : "APB");
1804}
1805
1806static ssize_t tpdm_store_tc_retrieval_mode(struct device *dev,
1807 struct device_attribute *attr,
1808 const char *buf,
1809 size_t size)
1810{
1811 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1812 char str[20] = "";
1813
1814 if (size >= 20)
1815 return -EINVAL;
1816 if (sscanf(buf, "%s", str) != 1)
1817 return -EINVAL;
1818 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1819 return -EPERM;
1820
1821 mutex_lock(&drvdata->lock);
1822 if (drvdata->enable) {
1823 mutex_unlock(&drvdata->lock);
1824 return -EPERM;
1825 }
1826
1827 if (!strcmp(str, "ATB")) {
1828 drvdata->tc->retrieval_mode = TPDM_MODE_ATB;
1829 } else if (!strcmp(str, "APB")) {
1830 drvdata->tc->retrieval_mode = TPDM_MODE_APB;
1831 } else {
1832 mutex_unlock(&drvdata->lock);
1833 return -EINVAL;
1834 }
1835 mutex_unlock(&drvdata->lock);
1836 return size;
1837}
Satyajit Desai326497c2016-11-14 10:15:03 -08001838static DEVICE_ATTR(tc_retrieval_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001839 tpdm_show_tc_retrieval_mode, tpdm_store_tc_retrieval_mode);
1840
1841static ssize_t tpdm_store_tc_reset_counters(struct device *dev,
1842 struct device_attribute *attr,
1843 const char *buf,
1844 size_t size)
1845{
1846 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1847 unsigned long val;
1848
1849 if (kstrtoul(buf, 16, &val))
1850 return -EINVAL;
1851 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1852 return -EPERM;
1853
1854 mutex_lock(&drvdata->lock);
1855 if (!drvdata->enable) {
1856 mutex_unlock(&drvdata->lock);
1857 return -EPERM;
1858 }
1859
1860 if (val) {
1861 TPDM_UNLOCK(drvdata);
1862 val = tpdm_readl(drvdata, TPDM_TC_CR);
1863 val = val | BIT(1);
1864 tpdm_writel(drvdata, val, TPDM_TC_CR);
1865 TPDM_LOCK(drvdata);
1866 }
1867 mutex_unlock(&drvdata->lock);
1868 return size;
1869}
Satyajit Desai326497c2016-11-14 10:15:03 -08001870static DEVICE_ATTR(tc_reset_counters, 0644, NULL,
Satyajit Desaif151d682016-09-12 16:18:03 -07001871 tpdm_store_tc_reset_counters);
1872
1873static ssize_t tpdm_show_tc_sat_mode(struct device *dev,
1874 struct device_attribute *attr,
1875 char *buf)
1876{
1877 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1878
1879 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1880 return -EPERM;
1881
1882 return scnprintf(buf, PAGE_SIZE, "%u\n",
1883 (unsigned int)drvdata->tc->sat_mode);
1884}
1885
1886static ssize_t tpdm_store_tc_sat_mode(struct device *dev,
1887 struct device_attribute *attr,
1888 const char *buf,
1889 size_t size)
1890{
1891 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1892 unsigned long val;
1893
1894 if (kstrtoul(buf, 16, &val))
1895 return -EINVAL;
1896 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1897 return -EPERM;
1898
1899 mutex_lock(&drvdata->lock);
1900 if (val)
1901 drvdata->tc->sat_mode = true;
1902 else
1903 drvdata->tc->sat_mode = false;
1904 mutex_unlock(&drvdata->lock);
1905 return size;
1906}
Satyajit Desai326497c2016-11-14 10:15:03 -08001907static DEVICE_ATTR(tc_sat_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001908 tpdm_show_tc_sat_mode, tpdm_store_tc_sat_mode);
1909
1910static ssize_t tpdm_show_tc_enable_counters(struct device *dev,
1911 struct device_attribute *attr,
1912 char *buf)
1913{
1914 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1915
1916 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1917 return -EPERM;
1918
1919 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1920 (unsigned long)drvdata->tc->enable_counters);
1921}
1922
1923static ssize_t tpdm_store_tc_enable_counters(struct device *dev,
1924 struct device_attribute *attr,
1925 const char *buf,
1926 size_t size)
1927{
1928 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1929 unsigned long val;
1930
1931 if (kstrtoul(buf, 16, &val))
1932 return -EINVAL;
1933 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1934 return -EPERM;
1935 if (val >> drvdata->tc_counters_avail)
1936 return -EPERM;
1937
1938 mutex_lock(&drvdata->lock);
1939 drvdata->tc->enable_counters = val;
1940 mutex_unlock(&drvdata->lock);
1941 return size;
1942}
Satyajit Desai326497c2016-11-14 10:15:03 -08001943static DEVICE_ATTR(tc_enable_counters, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001944 tpdm_show_tc_enable_counters, tpdm_store_tc_enable_counters);
1945
1946static ssize_t tpdm_show_tc_clear_counters(struct device *dev,
1947 struct device_attribute *attr,
1948 char *buf)
1949{
1950 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1951
1952 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1953 return -EPERM;
1954
1955 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1956 (unsigned long)drvdata->tc->clear_counters);
1957}
1958
1959static ssize_t tpdm_store_tc_clear_counters(struct device *dev,
1960 struct device_attribute *attr,
1961 const char *buf,
1962 size_t size)
1963{
1964 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1965 unsigned long val;
1966
1967 if (kstrtoul(buf, 16, &val))
1968 return -EINVAL;
1969 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1970 return -EPERM;
1971 if (val >> drvdata->tc_counters_avail)
1972 return -EPERM;
1973
1974 mutex_lock(&drvdata->lock);
1975 drvdata->tc->clear_counters = val;
1976 mutex_unlock(&drvdata->lock);
1977 return size;
1978}
Satyajit Desai326497c2016-11-14 10:15:03 -08001979static DEVICE_ATTR(tc_clear_counters, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07001980 tpdm_show_tc_clear_counters, tpdm_store_tc_clear_counters);
1981
1982static ssize_t tpdm_show_tc_enable_irq(struct device *dev,
1983 struct device_attribute *attr,
1984 char *buf)
1985{
1986 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
1987
1988 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
1989 return -EPERM;
1990
1991 return scnprintf(buf, PAGE_SIZE, "%lx\n",
1992 (unsigned long)drvdata->tc->enable_irq);
1993}
1994
1995static ssize_t tpdm_store_tc_enable_irq(struct device *dev,
1996 struct device_attribute *attr,
1997 const char *buf,
1998 size_t size)
1999{
2000 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2001 unsigned long val;
2002
2003 if (kstrtoul(buf, 16, &val))
2004 return -EINVAL;
2005 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2006 return -EPERM;
2007
2008 mutex_lock(&drvdata->lock);
2009 drvdata->tc->enable_irq = val;
2010 mutex_unlock(&drvdata->lock);
2011 return size;
2012}
Satyajit Desai326497c2016-11-14 10:15:03 -08002013static DEVICE_ATTR(tc_enable_irq, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002014 tpdm_show_tc_enable_irq, tpdm_store_tc_enable_irq);
2015
2016static ssize_t tpdm_show_tc_clear_irq(struct device *dev,
2017 struct device_attribute *attr,
2018 char *buf)
2019{
2020 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2021
2022 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2023 return -EPERM;
2024
2025 return scnprintf(buf, PAGE_SIZE, "%lx\n",
2026 (unsigned long)drvdata->tc->clear_irq);
2027}
2028
2029static ssize_t tpdm_store_tc_clear_irq(struct device *dev,
2030 struct device_attribute *attr,
2031 const char *buf,
2032 size_t size)
2033{
2034 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2035 unsigned long val;
2036
2037 if (kstrtoul(buf, 16, &val))
2038 return -EINVAL;
2039 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2040 return -EPERM;
2041
2042 mutex_lock(&drvdata->lock);
2043 drvdata->tc->clear_irq = val;
2044 mutex_unlock(&drvdata->lock);
2045 return size;
2046}
Satyajit Desai326497c2016-11-14 10:15:03 -08002047static DEVICE_ATTR(tc_clear_irq, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002048 tpdm_show_tc_clear_irq, tpdm_store_tc_clear_irq);
2049
2050static ssize_t tpdm_show_tc_trig_sel(struct device *dev,
2051 struct device_attribute *attr,
2052 char *buf)
2053{
2054 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2055 ssize_t size = 0;
2056 int i = 0;
2057
2058 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2059 return -EPERM;
2060
2061 mutex_lock(&drvdata->lock);
2062 for (i = 0; i < TPDM_TC_MAX_TRIG; i++) {
2063 size += scnprintf(buf + size, PAGE_SIZE - size,
2064 "Index: 0x%x Value: 0x%x\n", i,
2065 drvdata->tc->trig_sel[i]);
2066 }
2067 mutex_unlock(&drvdata->lock);
2068 return size;
2069}
2070
2071static ssize_t tpdm_store_tc_trig_sel(struct device *dev,
2072 struct device_attribute *attr,
2073 const char *buf,
2074 size_t size)
2075{
2076 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2077 unsigned long index, val;
2078
2079 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2080 return -EINVAL;
2081 if (!test_bit(TPDM_DS_TC, drvdata->datasets) ||
2082 index >= TPDM_TC_MAX_TRIG ||
2083 drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_NO ||
2084 (drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL && index > 0))
2085 return -EPERM;
2086
2087 mutex_lock(&drvdata->lock);
2088 drvdata->tc->trig_sel[index] = val;
2089 mutex_unlock(&drvdata->lock);
2090 return size;
2091}
Satyajit Desai326497c2016-11-14 10:15:03 -08002092static DEVICE_ATTR(tc_trig_sel, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002093 tpdm_show_tc_trig_sel, tpdm_store_tc_trig_sel);
2094
2095static ssize_t tpdm_show_tc_trig_val_lo(struct device *dev,
2096 struct device_attribute *attr,
2097 char *buf)
2098{
2099 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2100 ssize_t size = 0;
2101 int i = 0;
2102
2103 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2104 return -EPERM;
2105
2106 mutex_lock(&drvdata->lock);
2107 for (i = 0; i < TPDM_TC_MAX_TRIG; i++) {
2108 size += scnprintf(buf + size, PAGE_SIZE - size,
2109 "Index: 0x%x Value: 0x%x\n", i,
2110 drvdata->tc->trig_val_lo[i]);
2111 }
2112 mutex_unlock(&drvdata->lock);
2113 return size;
2114}
2115
2116static ssize_t tpdm_store_tc_trig_val_lo(struct device *dev,
2117 struct device_attribute *attr,
2118 const char *buf,
2119 size_t size)
2120{
2121 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2122 unsigned long index, val;
2123
2124 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2125 return -EINVAL;
2126 if (!test_bit(TPDM_DS_TC, drvdata->datasets) ||
2127 index >= TPDM_TC_MAX_TRIG ||
2128 drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_NO ||
2129 (drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL && index > 0))
2130 return -EPERM;
2131
2132 mutex_lock(&drvdata->lock);
2133 drvdata->tc->trig_val_lo[index] = val;
2134 mutex_unlock(&drvdata->lock);
2135 return size;
2136}
Satyajit Desai326497c2016-11-14 10:15:03 -08002137static DEVICE_ATTR(tc_trig_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002138 tpdm_show_tc_trig_val_lo, tpdm_store_tc_trig_val_lo);
2139
2140static ssize_t tpdm_show_tc_trig_val_hi(struct device *dev,
2141 struct device_attribute *attr,
2142 char *buf)
2143{
2144 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2145 ssize_t size = 0;
2146 int i = 0;
2147
2148 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2149 return -EPERM;
2150
2151 mutex_lock(&drvdata->lock);
2152 for (i = 0; i < TPDM_TC_MAX_TRIG; i++) {
2153 size += scnprintf(buf + size, PAGE_SIZE - size,
2154 "Index: 0x%x Value: 0x%x\n", i,
2155 drvdata->tc->trig_val_hi[i]);
2156 }
2157 mutex_unlock(&drvdata->lock);
2158 return size;
2159}
2160
2161static ssize_t tpdm_store_tc_trig_val_hi(struct device *dev,
2162 struct device_attribute *attr,
2163 const char *buf,
2164 size_t size)
2165{
2166 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2167 unsigned long index, val;
2168
2169 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2170 return -EINVAL;
2171 if (!test_bit(TPDM_DS_TC, drvdata->datasets) ||
2172 index >= TPDM_TC_MAX_TRIG ||
2173 drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_NO ||
2174 (drvdata->tc_trig_type == TPDM_SUPPORT_TYPE_PARTIAL && index > 0))
2175 return -EPERM;
2176
2177 mutex_lock(&drvdata->lock);
2178 drvdata->tc->trig_val_hi[index] = val;
2179 mutex_unlock(&drvdata->lock);
2180 return size;
2181}
Satyajit Desai326497c2016-11-14 10:15:03 -08002182static DEVICE_ATTR(tc_trig_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002183 tpdm_show_tc_trig_val_hi, tpdm_store_tc_trig_val_hi);
2184
2185static ssize_t tpdm_show_tc_ovsr_gp(struct device *dev,
2186 struct device_attribute *attr,
2187 char *buf)
2188{
2189 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2190 unsigned long val;
2191
2192 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2193 return -EPERM;
2194
2195 mutex_lock(&drvdata->lock);
2196 if (!drvdata->enable) {
2197 mutex_unlock(&drvdata->lock);
2198 return -EPERM;
2199 }
2200
2201 TPDM_UNLOCK(drvdata);
2202 val = tpdm_readl(drvdata, TPDM_TC_OVSR_GP);
2203 TPDM_LOCK(drvdata);
2204 mutex_unlock(&drvdata->lock);
2205 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2206}
2207
2208static ssize_t tpdm_store_tc_ovsr_gp(struct device *dev,
2209 struct device_attribute *attr,
2210 const char *buf,
2211 size_t size)
2212{
2213 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2214 unsigned long val;
2215
2216 if (kstrtoul(buf, 16, &val))
2217 return -EINVAL;
2218 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2219 return -EPERM;
2220
2221 mutex_lock(&drvdata->lock);
2222 if (!drvdata->enable) {
2223 mutex_unlock(&drvdata->lock);
2224 return -EPERM;
2225 }
2226
2227 if (val) {
2228 TPDM_UNLOCK(drvdata);
2229 tpdm_writel(drvdata, val, TPDM_TC_OVSR_GP);
2230 TPDM_LOCK(drvdata);
2231 }
2232 mutex_unlock(&drvdata->lock);
2233 return size;
2234}
Satyajit Desai326497c2016-11-14 10:15:03 -08002235static DEVICE_ATTR(tc_ovsr_gp, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002236 tpdm_show_tc_ovsr_gp, tpdm_store_tc_ovsr_gp);
2237
2238static ssize_t tpdm_show_tc_ovsr_impl(struct device *dev,
2239 struct device_attribute *attr,
2240 char *buf)
2241{
2242 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2243 unsigned long val;
2244
2245 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2246 return -EPERM;
2247
2248 mutex_lock(&drvdata->lock);
2249 if (!drvdata->enable) {
2250 mutex_unlock(&drvdata->lock);
2251 return -EPERM;
2252 }
2253
2254 TPDM_UNLOCK(drvdata);
2255 val = tpdm_readl(drvdata, TPDM_TC_OVSR_IMPL);
2256 TPDM_LOCK(drvdata);
2257 mutex_unlock(&drvdata->lock);
2258 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2259}
2260
2261static ssize_t tpdm_store_tc_ovsr_impl(struct device *dev,
2262 struct device_attribute *attr,
2263 const char *buf,
2264 size_t size)
2265{
2266 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2267 unsigned long val;
2268
2269 if (kstrtoul(buf, 16, &val))
2270 return -EINVAL;
2271 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2272 return -EPERM;
2273
2274 mutex_lock(&drvdata->lock);
2275 if (!drvdata->enable) {
2276 mutex_unlock(&drvdata->lock);
2277 return -EPERM;
2278 }
2279
2280 if (val) {
2281 TPDM_UNLOCK(drvdata);
2282 tpdm_writel(drvdata, val, TPDM_TC_OVSR_IMPL);
2283 TPDM_LOCK(drvdata);
2284 }
2285 mutex_unlock(&drvdata->lock);
2286 return size;
2287}
Satyajit Desai326497c2016-11-14 10:15:03 -08002288static DEVICE_ATTR(tc_ovsr_impl, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002289 tpdm_show_tc_ovsr_impl, tpdm_store_tc_ovsr_impl);
2290
2291static ssize_t tpdm_show_tc_counter_sel(struct device *dev,
2292 struct device_attribute *attr,
2293 char *buf)
2294{
2295 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2296 unsigned long val;
2297
2298 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2299 return -EPERM;
2300
2301 mutex_lock(&drvdata->lock);
2302 if (!drvdata->enable) {
2303 mutex_unlock(&drvdata->lock);
2304 return -EPERM;
2305 }
2306
2307 TPDM_UNLOCK(drvdata);
2308 val = tpdm_readl(drvdata, TPDM_TC_SELR);
2309 TPDM_LOCK(drvdata);
2310 mutex_unlock(&drvdata->lock);
2311 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2312}
2313
2314static ssize_t tpdm_store_tc_counter_sel(struct device *dev,
2315 struct device_attribute *attr,
2316 const char *buf,
2317 size_t size)
2318{
2319 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2320 unsigned long val;
2321
2322 if (kstrtoul(buf, 16, &val))
2323 return -EINVAL;
2324 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2325 return -EPERM;
2326
2327 mutex_lock(&drvdata->lock);
2328 if (!drvdata->enable) {
2329 mutex_unlock(&drvdata->lock);
2330 return -EPERM;
2331 }
2332
2333 TPDM_UNLOCK(drvdata);
2334 tpdm_writel(drvdata, val, TPDM_TC_SELR);
2335 TPDM_LOCK(drvdata);
2336 mutex_unlock(&drvdata->lock);
2337 return size;
2338}
Satyajit Desai326497c2016-11-14 10:15:03 -08002339static DEVICE_ATTR(tc_counter_sel, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002340 tpdm_show_tc_counter_sel, tpdm_store_tc_counter_sel);
2341
2342static ssize_t tpdm_show_tc_count_val_lo(struct device *dev,
2343 struct device_attribute *attr,
2344 char *buf)
2345{
2346 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2347 unsigned long val;
2348
2349 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2350 return -EPERM;
2351
2352 mutex_lock(&drvdata->lock);
2353 if (!drvdata->enable) {
2354 mutex_unlock(&drvdata->lock);
2355 return -EPERM;
2356 }
2357
2358 TPDM_UNLOCK(drvdata);
2359 val = tpdm_readl(drvdata, TPDM_TC_CNTR_LO);
2360 TPDM_LOCK(drvdata);
2361 mutex_unlock(&drvdata->lock);
2362 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2363}
2364
2365static ssize_t tpdm_store_tc_count_val_lo(struct device *dev,
2366 struct device_attribute *attr,
2367 const char *buf,
2368 size_t size)
2369{
2370 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2371 unsigned long val, select;
2372
2373 if (kstrtoul(buf, 16, &val))
2374 return -EINVAL;
2375 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2376 return -EPERM;
2377
2378 mutex_lock(&drvdata->lock);
2379 if (!drvdata->enable) {
2380 mutex_unlock(&drvdata->lock);
2381 return -EPERM;
2382 }
2383
2384 if (val) {
2385 TPDM_UNLOCK(drvdata);
2386 select = tpdm_readl(drvdata, TPDM_TC_SELR);
2387 select = (select >> 11) & 0x3;
2388
2389 /* Check if selected counter is disabled */
2390 if (BVAL(tpdm_readl(drvdata, TPDM_TC_CNTENSET), select)) {
2391 mutex_unlock(&drvdata->lock);
2392 return -EPERM;
2393 }
2394
2395 tpdm_writel(drvdata, val, TPDM_TC_CNTR_LO);
2396 TPDM_LOCK(drvdata);
2397 }
2398 mutex_unlock(&drvdata->lock);
2399 return size;
2400}
Satyajit Desai326497c2016-11-14 10:15:03 -08002401static DEVICE_ATTR(tc_count_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002402 tpdm_show_tc_count_val_lo, tpdm_store_tc_count_val_lo);
2403
2404static ssize_t tpdm_show_tc_count_val_hi(struct device *dev,
2405 struct device_attribute *attr,
2406 char *buf)
2407{
2408 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2409 unsigned long val;
2410
2411 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2412 return -EPERM;
2413
2414 mutex_lock(&drvdata->lock);
2415 if (!drvdata->enable) {
2416 mutex_unlock(&drvdata->lock);
2417 return -EPERM;
2418 }
2419
2420 TPDM_UNLOCK(drvdata);
2421 val = tpdm_readl(drvdata, TPDM_TC_CNTR_HI);
2422 TPDM_LOCK(drvdata);
2423 mutex_unlock(&drvdata->lock);
2424 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2425}
2426
2427static ssize_t tpdm_store_tc_count_val_hi(struct device *dev,
2428 struct device_attribute *attr,
2429 const char *buf,
2430 size_t size)
2431{
2432 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2433 unsigned long val, select;
2434
2435 if (kstrtoul(buf, 16, &val))
2436 return -EINVAL;
2437 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2438 return -EPERM;
2439
2440 mutex_lock(&drvdata->lock);
2441 if (!drvdata->enable) {
2442 mutex_unlock(&drvdata->lock);
2443 return -EPERM;
2444 }
2445
2446 if (val) {
2447 TPDM_UNLOCK(drvdata);
2448 select = tpdm_readl(drvdata, TPDM_TC_SELR);
2449 select = (select >> 11) & 0x3;
2450
2451 /* Check if selected counter is disabled */
2452 if (BVAL(tpdm_readl(drvdata, TPDM_TC_CNTENSET), select)) {
2453 mutex_unlock(&drvdata->lock);
2454 return -EPERM;
2455 }
2456
2457 tpdm_writel(drvdata, val, TPDM_TC_CNTR_HI);
2458 TPDM_LOCK(drvdata);
2459 }
2460 mutex_unlock(&drvdata->lock);
2461 return size;
2462}
Satyajit Desai326497c2016-11-14 10:15:03 -08002463static DEVICE_ATTR(tc_count_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002464 tpdm_show_tc_count_val_hi, tpdm_store_tc_count_val_hi);
2465
2466static ssize_t tpdm_show_tc_shadow_val_lo(struct device *dev,
2467 struct device_attribute *attr,
2468 char *buf)
2469{
2470 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2471 ssize_t size = 0;
2472 int i = 0;
2473
2474 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2475 return -EPERM;
2476
2477 mutex_lock(&drvdata->lock);
2478 if (!drvdata->enable) {
2479 mutex_unlock(&drvdata->lock);
2480 return -EPERM;
2481 }
2482
2483 TPDM_UNLOCK(drvdata);
2484 for (i = 0; i < TPDM_TC_MAX_COUNTERS; i++) {
2485 size += scnprintf(buf + size, PAGE_SIZE - size,
2486 "Index: 0x%x Value: 0x%x\n", i,
2487 tpdm_readl(drvdata, TPDM_TC_SHADOW_LO(i)));
2488 }
2489 TPDM_LOCK(drvdata);
2490 mutex_unlock(&drvdata->lock);
2491 return size;
2492}
Satyajit Desai326497c2016-11-14 10:15:03 -08002493static DEVICE_ATTR(tc_shadow_val_lo, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002494 tpdm_show_tc_shadow_val_lo, NULL);
2495
2496static ssize_t tpdm_show_tc_shadow_val_hi(struct device *dev,
2497 struct device_attribute *attr,
2498 char *buf)
2499{
2500 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2501 ssize_t size = 0;
2502 int i = 0;
2503
2504 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2505 return -EPERM;
2506
2507 mutex_lock(&drvdata->lock);
2508 if (!drvdata->enable) {
2509 mutex_unlock(&drvdata->lock);
2510 return -EPERM;
2511 }
2512
2513 TPDM_UNLOCK(drvdata);
2514 for (i = 0; i < TPDM_TC_MAX_COUNTERS; i++) {
2515 size += scnprintf(buf + size, PAGE_SIZE - size,
2516 "Index: 0x%x Value: 0x%x\n", i,
2517 tpdm_readl(drvdata, TPDM_TC_SHADOW_HI(i)));
2518 }
2519 TPDM_LOCK(drvdata);
2520 mutex_unlock(&drvdata->lock);
2521 return size;
2522}
Satyajit Desai326497c2016-11-14 10:15:03 -08002523static DEVICE_ATTR(tc_shadow_val_hi, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002524 tpdm_show_tc_shadow_val_hi, NULL);
2525
2526static ssize_t tpdm_show_tc_sw_inc(struct device *dev,
2527 struct device_attribute *attr,
2528 char *buf)
2529{
2530 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2531 unsigned long val;
2532
2533 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2534 return -EPERM;
2535
2536 mutex_lock(&drvdata->lock);
2537 if (!drvdata->enable) {
2538 mutex_unlock(&drvdata->lock);
2539 return -EPERM;
2540 }
2541
2542 TPDM_UNLOCK(drvdata);
2543 val = tpdm_readl(drvdata, TPDM_TC_SWINC);
2544 TPDM_LOCK(drvdata);
2545 mutex_unlock(&drvdata->lock);
2546 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
2547}
2548
2549static ssize_t tpdm_store_tc_sw_inc(struct device *dev,
2550 struct device_attribute *attr,
2551 const char *buf,
2552 size_t size)
2553{
2554 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2555 unsigned long val;
2556
2557 if (kstrtoul(buf, 16, &val))
2558 return -EINVAL;
2559 if (!test_bit(TPDM_DS_TC, drvdata->enable_ds))
2560 return -EPERM;
2561
2562 mutex_lock(&drvdata->lock);
2563 if (!drvdata->enable) {
2564 mutex_unlock(&drvdata->lock);
2565 return -EPERM;
2566 }
2567
2568 if (val) {
2569 TPDM_UNLOCK(drvdata);
2570 tpdm_writel(drvdata, val, TPDM_TC_SWINC);
2571 TPDM_LOCK(drvdata);
2572 }
2573 mutex_unlock(&drvdata->lock);
2574 return size;
2575}
Satyajit Desai326497c2016-11-14 10:15:03 -08002576static DEVICE_ATTR(tc_sw_inc, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002577 tpdm_show_tc_sw_inc, tpdm_store_tc_sw_inc);
2578
2579static ssize_t tpdm_store_tc_msr(struct device *dev,
2580 struct device_attribute *attr,
2581 const char *buf,
2582 size_t size)
2583{
2584 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2585 unsigned int num, val;
2586 int nval;
2587
2588 if (!drvdata->msr_support)
2589 return -EINVAL;
2590
2591 if (!test_bit(TPDM_DS_TC, drvdata->datasets))
2592 return -EPERM;
2593
2594 nval = sscanf(buf, "%u %x", &num, &val);
2595 if (nval != 2)
2596 return -EINVAL;
2597
2598 if (num >= TPDM_TC_MAX_MSR)
2599 return -EINVAL;
2600
2601 mutex_lock(&drvdata->lock);
2602 drvdata->tc->msr[num] = val;
2603 mutex_unlock(&drvdata->lock);
2604 return size;
2605}
Satyajit Desai326497c2016-11-14 10:15:03 -08002606static DEVICE_ATTR(tc_msr, 0200, NULL, tpdm_store_tc_msr);
Satyajit Desaif151d682016-09-12 16:18:03 -07002607
2608static ssize_t tpdm_show_dsb_mode(struct device *dev,
2609 struct device_attribute *attr,
2610 char *buf)
2611{
2612 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2613
2614 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2615 return -EPERM;
2616
2617 return scnprintf(buf, PAGE_SIZE, "%lx\n",
2618 (unsigned long)drvdata->dsb->mode);
2619}
2620
2621static ssize_t tpdm_store_dsb_mode(struct device *dev,
2622 struct device_attribute *attr,
2623 const char *buf,
2624 size_t size)
2625{
2626 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2627 unsigned long val;
2628
2629 if (kstrtoul(buf, 16, &val))
2630 return -EINVAL;
2631 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2632 return -EPERM;
2633
2634 mutex_lock(&drvdata->lock);
2635 drvdata->dsb->mode = val & TPDM_MODE_ALL;
2636 mutex_unlock(&drvdata->lock);
2637 return size;
2638}
Satyajit Desai326497c2016-11-14 10:15:03 -08002639static DEVICE_ATTR(dsb_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002640 tpdm_show_dsb_mode, tpdm_store_dsb_mode);
2641
2642static ssize_t tpdm_show_dsb_edge_ctrl(struct device *dev,
2643 struct device_attribute *attr,
2644 char *buf)
2645{
2646 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2647 ssize_t size = 0;
2648 int i;
2649
2650 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2651 return -EPERM;
2652
2653 mutex_lock(&drvdata->lock);
2654 for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) {
2655 size += scnprintf(buf + size, PAGE_SIZE - size,
2656 "Index:0x%x Val:0x%x\n", i,
2657 drvdata->dsb->edge_ctrl[i]);
2658 }
2659 mutex_unlock(&drvdata->lock);
2660 return size;
2661}
2662
2663static ssize_t tpdm_store_dsb_edge_ctrl(struct device *dev,
2664 struct device_attribute *attr,
2665 const char *buf,
2666 size_t size)
2667{
2668 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2669 unsigned long start, end, edge_ctrl;
2670 uint32_t val;
2671 int i, bit, reg;
2672
2673 if (sscanf(buf, "%lx %lx %lx", &start, &end, &edge_ctrl) != 3)
2674 return -EINVAL;
2675 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
2676 (start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES) ||
2677 edge_ctrl > 0x2)
2678 return -EPERM;
2679
2680 mutex_lock(&drvdata->lock);
2681 for (i = start; i <= end; i++) {
2682 reg = i / (NUM_OF_BITS / 2);
2683 bit = i % (NUM_OF_BITS / 2);
2684 bit = bit * 2;
2685
2686 val = drvdata->dsb->edge_ctrl[reg];
2687 val = val | (edge_ctrl << bit);
2688 drvdata->dsb->edge_ctrl[reg] = val;
2689 }
2690 mutex_unlock(&drvdata->lock);
2691 return size;
2692}
Satyajit Desai326497c2016-11-14 10:15:03 -08002693static DEVICE_ATTR(dsb_edge_ctrl, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002694 tpdm_show_dsb_edge_ctrl, tpdm_store_dsb_edge_ctrl);
2695
2696static ssize_t tpdm_show_dsb_edge_ctrl_mask(struct device *dev,
2697 struct device_attribute *attr,
2698 char *buf)
2699{
2700 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2701 ssize_t size = 0;
2702 int i;
2703
2704 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2705 return -EPERM;
2706
2707 mutex_lock(&drvdata->lock);
2708 for (i = 0; i < TPDM_DSB_MAX_EDCR / 2; i++) {
2709 size += scnprintf(buf + size, PAGE_SIZE - size,
2710 "Index:0x%x Val:0x%x\n", i,
2711 drvdata->dsb->edge_ctrl_mask[i]);
2712 }
2713 mutex_unlock(&drvdata->lock);
2714 return size;
2715}
2716
2717static ssize_t tpdm_store_dsb_edge_ctrl_mask(struct device *dev,
2718 struct device_attribute *attr,
2719 const char *buf,
2720 size_t size)
2721{
2722 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2723 unsigned long start, end, val;
2724 uint32_t set;
2725 int i, bit, reg;
2726
2727 if (sscanf(buf, "%lx %lx %lx", &start, &end, &val) != 3)
2728 return -EINVAL;
2729 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
2730 (start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES))
2731 return -EPERM;
2732
2733 mutex_lock(&drvdata->lock);
2734 for (i = start; i <= end; i++) {
2735 reg = i / NUM_OF_BITS;
2736 bit = (i % NUM_OF_BITS);
2737
2738 set = drvdata->dsb->edge_ctrl_mask[reg];
2739 if (val)
2740 set = set | BIT(bit);
2741 else
2742 set = set & ~BIT(bit);
2743 drvdata->dsb->edge_ctrl_mask[reg] = set;
2744 }
2745 mutex_unlock(&drvdata->lock);
2746 return size;
2747}
Satyajit Desai326497c2016-11-14 10:15:03 -08002748static DEVICE_ATTR(dsb_edge_ctrl_mask, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002749 tpdm_show_dsb_edge_ctrl_mask, tpdm_store_dsb_edge_ctrl_mask);
2750
2751static ssize_t tpdm_show_dsb_patt_val(struct device *dev,
2752 struct device_attribute *attr,
2753 char *buf)
2754{
2755 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2756 ssize_t size = 0;
2757 int i = 0;
2758
2759 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2760 return -EPERM;
2761
2762 mutex_lock(&drvdata->lock);
2763 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
2764 size += scnprintf(buf + size, PAGE_SIZE - size,
2765 "Index: 0x%x Value: 0x%x\n", i,
2766 drvdata->dsb->patt_val[i]);
2767 }
2768 mutex_unlock(&drvdata->lock);
2769 return size;
2770}
2771
2772static ssize_t tpdm_store_dsb_patt_val(struct device *dev,
2773 struct device_attribute *attr,
2774 const char *buf,
2775 size_t size)
2776{
2777 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2778 unsigned long index, val;
2779
2780 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2781 return -EINVAL;
2782 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
2783 index >= TPDM_DSB_MAX_PATT)
2784 return -EPERM;
2785
2786 mutex_lock(&drvdata->lock);
2787 drvdata->dsb->patt_val[index] = val;
2788 mutex_unlock(&drvdata->lock);
2789 return size;
2790}
Satyajit Desai326497c2016-11-14 10:15:03 -08002791static DEVICE_ATTR(dsb_patt_val, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002792 tpdm_show_dsb_patt_val, tpdm_store_dsb_patt_val);
2793
2794static ssize_t tpdm_show_dsb_patt_mask(struct device *dev,
2795 struct device_attribute *attr,
2796 char *buf)
2797{
2798 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2799 ssize_t size = 0;
2800 int i = 0;
2801
2802 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2803 return -EPERM;
2804
2805 mutex_lock(&drvdata->lock);
2806 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
2807 size += scnprintf(buf + size, PAGE_SIZE - size,
2808 "Index: 0x%x Value: 0x%x\n", i,
2809 drvdata->dsb->patt_mask[i]);
2810 }
2811 mutex_unlock(&drvdata->lock);
2812 return size;
2813}
2814
2815static ssize_t tpdm_store_dsb_patt_mask(struct device *dev,
2816 struct device_attribute *attr,
2817 const char *buf,
2818 size_t size)
2819{
2820 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2821 unsigned long index, val;
2822
2823 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2824 return -EINVAL;
2825 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
2826 index >= TPDM_DSB_MAX_PATT)
2827 return -EPERM;
2828
2829 mutex_lock(&drvdata->lock);
2830 drvdata->dsb->patt_mask[index] = val;
2831 mutex_unlock(&drvdata->lock);
2832 return size;
2833}
Satyajit Desai326497c2016-11-14 10:15:03 -08002834static DEVICE_ATTR(dsb_patt_mask, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002835 tpdm_show_dsb_patt_mask, tpdm_store_dsb_patt_mask);
2836
2837static ssize_t tpdm_show_dsb_patt_ts(struct device *dev,
2838 struct device_attribute *attr,
2839 char *buf)
2840{
2841 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2842
2843 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2844 return -EPERM;
2845
2846 return scnprintf(buf, PAGE_SIZE, "%u\n",
2847 (unsigned int)drvdata->dsb->patt_ts);
2848}
2849
2850static ssize_t tpdm_store_dsb_patt_ts(struct device *dev,
2851 struct device_attribute *attr,
2852 const char *buf,
2853 size_t size)
2854{
2855 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2856 unsigned long val;
2857
2858 if (kstrtoul(buf, 16, &val))
2859 return -EINVAL;
2860 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2861 return -EPERM;
2862
2863 mutex_lock(&drvdata->lock);
2864 if (val)
2865 drvdata->dsb->patt_ts = true;
2866 else
2867 drvdata->dsb->patt_ts = false;
2868 mutex_unlock(&drvdata->lock);
2869 return size;
2870}
Satyajit Desai326497c2016-11-14 10:15:03 -08002871static DEVICE_ATTR(dsb_patt_ts, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002872 tpdm_show_dsb_patt_ts, tpdm_store_dsb_patt_ts);
2873
2874static ssize_t tpdm_show_dsb_patt_type(struct device *dev,
2875 struct device_attribute *attr, char *buf)
2876{
2877 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2878
2879 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2880 return -EPERM;
2881
2882 return scnprintf(buf, PAGE_SIZE, "%u\n",
2883 (unsigned int)drvdata->dsb->patt_type);
2884}
2885
2886static ssize_t tpdm_store_dsb_patt_type(struct device *dev,
2887 struct device_attribute *attr,
2888 const char *buf, size_t size)
2889{
2890 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2891 unsigned long val;
2892
2893 if (kstrtoul(buf, 16, &val))
2894 return -EINVAL;
2895 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2896 return -EPERM;
2897
2898 mutex_lock(&drvdata->lock);
2899 if (val)
2900 drvdata->dsb->patt_type = true;
2901 else
2902 drvdata->dsb->patt_type = false;
2903 mutex_unlock(&drvdata->lock);
2904 return size;
2905}
Satyajit Desai326497c2016-11-14 10:15:03 -08002906static DEVICE_ATTR(dsb_patt_type, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002907 tpdm_show_dsb_patt_type, tpdm_store_dsb_patt_type);
2908
2909static ssize_t tpdm_show_dsb_trig_patt_val(struct device *dev,
2910 struct device_attribute *attr,
2911 char *buf)
2912{
2913 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2914 ssize_t size = 0;
2915 int i = 0;
2916
2917 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2918 return -EPERM;
2919
2920 mutex_lock(&drvdata->lock);
2921 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
2922 size += scnprintf(buf + size, PAGE_SIZE - size,
2923 "Index: 0x%x Value: 0x%x\n", i,
2924 drvdata->dsb->trig_patt_val[i]);
2925 }
2926 mutex_unlock(&drvdata->lock);
2927 return size;
2928}
2929
2930static ssize_t tpdm_store_dsb_trig_patt_val(struct device *dev,
2931 struct device_attribute *attr,
2932 const char *buf,
2933 size_t size)
2934{
2935 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2936 unsigned long index, val;
2937
2938 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2939 return -EINVAL;
2940 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
2941 index >= TPDM_DSB_MAX_PATT)
2942 return -EPERM;
2943
2944 mutex_lock(&drvdata->lock);
2945 drvdata->dsb->trig_patt_val[index] = val;
2946 mutex_unlock(&drvdata->lock);
2947 return size;
2948}
Satyajit Desai326497c2016-11-14 10:15:03 -08002949static DEVICE_ATTR(dsb_trig_patt_val, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002950 tpdm_show_dsb_trig_patt_val, tpdm_store_dsb_trig_patt_val);
2951
2952static ssize_t tpdm_show_dsb_trig_patt_mask(struct device *dev,
2953 struct device_attribute *attr,
2954 char *buf)
2955{
2956 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2957 ssize_t size = 0;
2958 int i = 0;
2959
2960 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
2961 return -EPERM;
2962
2963 mutex_lock(&drvdata->lock);
2964 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
2965 size += scnprintf(buf + size, PAGE_SIZE - size,
2966 "Index: 0x%x Value: 0x%x\n", i,
2967 drvdata->dsb->trig_patt_mask[i]);
2968 }
2969 mutex_unlock(&drvdata->lock);
2970 return size;
2971}
2972
2973static ssize_t tpdm_store_dsb_trig_patt_mask(struct device *dev,
2974 struct device_attribute *attr,
2975 const char *buf,
2976 size_t size)
2977{
2978 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
2979 unsigned long index, val;
2980
2981 if (sscanf(buf, "%lx %lx", &index, &val) != 2)
2982 return -EINVAL;
2983 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
2984 index >= TPDM_DSB_MAX_PATT)
2985 return -EPERM;
2986
2987 mutex_lock(&drvdata->lock);
2988 drvdata->dsb->trig_patt_mask[index] = val;
2989 mutex_unlock(&drvdata->lock);
2990 return size;
2991}
Satyajit Desai326497c2016-11-14 10:15:03 -08002992static DEVICE_ATTR(dsb_trig_patt_mask, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07002993 tpdm_show_dsb_trig_patt_mask, tpdm_store_dsb_trig_patt_mask);
2994
2995static ssize_t tpdm_show_dsb_trig_ts(struct device *dev,
2996 struct device_attribute *attr,
2997 char *buf)
2998{
2999 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3000
3001 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
3002 return -EPERM;
3003
3004 return scnprintf(buf, PAGE_SIZE, "%u\n",
3005 (unsigned int)drvdata->dsb->trig_ts);
3006}
3007
3008static ssize_t tpdm_store_dsb_trig_ts(struct device *dev,
3009 struct device_attribute *attr,
3010 const char *buf,
3011 size_t size)
3012{
3013 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3014 unsigned long val;
3015
3016 if (kstrtoul(buf, 16, &val))
3017 return -EINVAL;
3018 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
3019 return -EPERM;
3020
3021 mutex_lock(&drvdata->lock);
3022 if (val)
3023 drvdata->dsb->trig_ts = true;
3024 else
3025 drvdata->dsb->trig_ts = false;
3026 mutex_unlock(&drvdata->lock);
3027 return size;
3028}
Satyajit Desai326497c2016-11-14 10:15:03 -08003029static DEVICE_ATTR(dsb_trig_ts, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003030 tpdm_show_dsb_trig_ts, tpdm_store_dsb_trig_ts);
3031
3032static ssize_t tpdm_show_dsb_select_val(struct device *dev,
3033 struct device_attribute *attr,
3034 char *buf)
3035{
3036 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3037 ssize_t size = 0;
3038 int i;
3039
3040 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
3041 return -EPERM;
3042
3043 mutex_lock(&drvdata->lock);
3044 for (i = 0; i < TPDM_DSB_MAX_SELECT; i++) {
3045 size += scnprintf(buf + size, PAGE_SIZE - size,
3046 "Index:0x%x Val:0x%x\n", i,
3047 drvdata->dsb->select_val[i]);
3048 }
3049 mutex_unlock(&drvdata->lock);
3050 return size;
3051}
3052
3053static ssize_t tpdm_store_dsb_select_val(struct device *dev,
3054 struct device_attribute *attr,
3055 const char *buf,
3056 size_t size)
3057{
3058 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3059 unsigned long start, end;
3060 uint32_t val;
3061 int i, bit, reg;
3062
3063 if (sscanf(buf, "%lx %lx", &start, &end) != 2)
3064 return -EINVAL;
3065 if (!test_bit(TPDM_DS_DSB, drvdata->datasets) ||
3066 (start >= TPDM_DSB_MAX_LINES) || (end >= TPDM_DSB_MAX_LINES))
3067 return -EPERM;
3068
3069 mutex_lock(&drvdata->lock);
3070 for (i = start; i <= end; i++) {
3071 reg = i / NUM_OF_BITS;
3072 bit = (i % NUM_OF_BITS);
3073
3074 val = drvdata->dsb->select_val[reg];
3075 val = val | BIT(bit);
3076 drvdata->dsb->select_val[reg] = val;
3077 }
3078 mutex_unlock(&drvdata->lock);
3079 return size;
3080}
Satyajit Desai326497c2016-11-14 10:15:03 -08003081static DEVICE_ATTR(dsb_select_val, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003082 tpdm_show_dsb_select_val, tpdm_store_dsb_select_val);
3083
3084static ssize_t tpdm_store_dsb_msr(struct device *dev,
3085 struct device_attribute *attr,
3086 const char *buf,
3087 size_t size)
3088{
3089 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3090 unsigned int num, val;
3091 int nval;
3092
3093 if (!drvdata->msr_support)
3094 return -EINVAL;
3095
3096 if (!test_bit(TPDM_DS_DSB, drvdata->datasets))
3097 return -EPERM;
3098
3099 nval = sscanf(buf, "%u %x", &num, &val);
3100 if (nval != 2)
3101 return -EINVAL;
3102
3103 if (num >= TPDM_DSB_MAX_MSR)
3104 return -EINVAL;
3105
3106 mutex_lock(&drvdata->lock);
3107 drvdata->dsb->msr[num] = val;
3108 mutex_unlock(&drvdata->lock);
3109 return size;
3110}
Satyajit Desai326497c2016-11-14 10:15:03 -08003111static DEVICE_ATTR(dsb_msr, 0200, NULL, tpdm_store_dsb_msr);
Satyajit Desaif151d682016-09-12 16:18:03 -07003112
3113static ssize_t tpdm_show_cmb_available_modes(struct device *dev,
3114 struct device_attribute *attr,
3115 char *buf)
3116{
3117 return scnprintf(buf, PAGE_SIZE, "%s\n", "continuous trace_on_change");
3118}
Satyajit Desai326497c2016-11-14 10:15:03 -08003119static DEVICE_ATTR(cmb_available_modes, 0444, tpdm_show_cmb_available_modes,
Satyajit Desaif151d682016-09-12 16:18:03 -07003120 NULL);
3121
3122static ssize_t tpdm_show_cmb_mode(struct device *dev,
3123 struct device_attribute *attr,
3124 char *buf)
3125{
3126 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3127
Satyajit Desaie104ff52016-09-12 16:38:12 -07003128 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3129 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003130 return -EPERM;
3131
3132 return scnprintf(buf, PAGE_SIZE, "%s\n",
3133 drvdata->cmb->mode == TPDM_CMB_MODE_CONTINUOUS ?
3134 "continuous" : "trace_on_change");
3135}
3136
3137static ssize_t tpdm_store_cmb_mode(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 char str[20] = "";
3144
3145 if (strlen(buf) >= 20)
3146 return -EINVAL;
3147 if (sscanf(buf, "%s", str) != 1)
3148 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003149 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3150 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003151 return -EPERM;
3152
3153 mutex_lock(&drvdata->lock);
3154 if (!strcmp(str, "continuous")) {
3155 drvdata->cmb->mode = TPDM_CMB_MODE_CONTINUOUS;
3156 } else if (!strcmp(str, "trace_on_change")) {
3157 drvdata->cmb->mode = TPDM_CMB_MODE_TRACE_ON_CHANGE;
3158 } else {
3159 mutex_unlock(&drvdata->lock);
3160 return -EINVAL;
3161 }
3162 mutex_unlock(&drvdata->lock);
3163 return size;
3164}
Satyajit Desai326497c2016-11-14 10:15:03 -08003165static DEVICE_ATTR(cmb_mode, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003166 tpdm_show_cmb_mode, tpdm_store_cmb_mode);
3167
3168static ssize_t tpdm_show_cmb_patt_val_lsb(struct device *dev,
3169 struct device_attribute *attr,
3170 char *buf)
3171{
3172 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3173 unsigned long val;
3174
Satyajit Desaie104ff52016-09-12 16:38:12 -07003175 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3176 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003177 return -EPERM;
3178
3179 val = drvdata->cmb->patt_val[TPDM_CMB_LSB];
3180
3181 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
3182}
3183
3184static ssize_t tpdm_store_cmb_patt_val_lsb(struct device *dev,
3185 struct device_attribute *attr,
3186 const char *buf, size_t size)
3187{
3188 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3189 unsigned long val;
3190
3191 if (kstrtoul(buf, 16, &val))
3192 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003193 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3194 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003195 return -EPERM;
3196
3197 mutex_lock(&drvdata->lock);
3198 drvdata->cmb->patt_val[TPDM_CMB_LSB] = val;
3199 mutex_unlock(&drvdata->lock);
3200 return size;
3201}
Satyajit Desai326497c2016-11-14 10:15:03 -08003202static DEVICE_ATTR(cmb_patt_val_lsb, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003203 tpdm_show_cmb_patt_val_lsb,
3204 tpdm_store_cmb_patt_val_lsb);
3205
3206static ssize_t tpdm_show_cmb_patt_mask_lsb(struct device *dev,
3207 struct device_attribute *attr,
3208 char *buf)
3209{
3210 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3211 unsigned long val;
3212
Satyajit Desaie104ff52016-09-12 16:38:12 -07003213 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3214 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003215 return -EPERM;
3216
3217 val = drvdata->cmb->patt_mask[TPDM_CMB_LSB];
3218
3219 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
3220}
3221
3222static ssize_t tpdm_store_cmb_patt_mask_lsb(struct device *dev,
3223 struct device_attribute *attr,
3224 const char *buf, size_t size)
3225{
3226 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3227 unsigned long val;
3228
3229 if (kstrtoul(buf, 16, &val))
3230 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003231 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3232 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003233 return -EPERM;
3234
3235 mutex_lock(&drvdata->lock);
3236 drvdata->cmb->patt_mask[TPDM_CMB_LSB] = val;
3237 mutex_unlock(&drvdata->lock);
3238 return size;
3239}
Satyajit Desai326497c2016-11-14 10:15:03 -08003240static DEVICE_ATTR(cmb_patt_mask_lsb, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003241 tpdm_show_cmb_patt_mask_lsb, tpdm_store_cmb_patt_mask_lsb);
3242
3243static ssize_t tpdm_show_cmb_patt_val_msb(struct device *dev,
3244 struct device_attribute *attr,
3245 char *buf)
3246{
3247 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3248 unsigned long val;
3249
Satyajit Desaie104ff52016-09-12 16:38:12 -07003250 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3251 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003252 return -EPERM;
3253
3254 val = drvdata->cmb->patt_val[TPDM_CMB_MSB];
3255
3256 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
3257}
3258
3259static ssize_t tpdm_store_cmb_patt_val_msb(struct device *dev,
3260 struct device_attribute *attr,
3261 const char *buf, size_t size)
3262{
3263 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3264 unsigned long val;
3265
3266 if (kstrtoul(buf, 16, &val))
3267 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003268 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3269 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003270 return -EPERM;
3271
3272 mutex_lock(&drvdata->lock);
3273 drvdata->cmb->patt_val[TPDM_CMB_MSB] = val;
3274 mutex_unlock(&drvdata->lock);
3275 return size;
3276}
Satyajit Desai326497c2016-11-14 10:15:03 -08003277static DEVICE_ATTR(cmb_patt_val_msb, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003278 tpdm_show_cmb_patt_val_msb,
3279 tpdm_store_cmb_patt_val_msb);
3280
3281static ssize_t tpdm_show_cmb_patt_mask_msb(struct device *dev,
3282 struct device_attribute *attr,
3283 char *buf)
3284{
3285 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3286 unsigned long val;
3287
Satyajit Desaie104ff52016-09-12 16:38:12 -07003288 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3289 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003290 return -EPERM;
3291
3292 val = drvdata->cmb->patt_mask[TPDM_CMB_MSB];
3293
3294 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
3295}
3296
3297static ssize_t tpdm_store_cmb_patt_mask_msb(struct device *dev,
3298 struct device_attribute *attr,
3299 const char *buf, size_t size)
3300{
3301 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3302 unsigned long val;
3303
3304 if (kstrtoul(buf, 16, &val))
3305 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003306 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3307 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003308 return -EPERM;
3309
3310 mutex_lock(&drvdata->lock);
3311 drvdata->cmb->patt_mask[TPDM_CMB_MSB] = val;
3312 mutex_unlock(&drvdata->lock);
3313 return size;
3314}
Satyajit Desai326497c2016-11-14 10:15:03 -08003315static DEVICE_ATTR(cmb_patt_mask_msb, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003316 tpdm_show_cmb_patt_mask_msb, tpdm_store_cmb_patt_mask_msb);
3317
3318static ssize_t tpdm_show_cmb_patt_ts(struct device *dev,
3319 struct device_attribute *attr,
3320 char *buf)
3321{
3322 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3323
Satyajit Desaie104ff52016-09-12 16:38:12 -07003324 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3325 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003326 return -EPERM;
3327
3328 return scnprintf(buf, PAGE_SIZE, "%u\n",
3329 (unsigned int)drvdata->cmb->patt_ts);
3330}
3331
3332static ssize_t tpdm_store_cmb_patt_ts(struct device *dev,
3333 struct device_attribute *attr,
3334 const char *buf,
3335 size_t size)
3336{
3337 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3338 unsigned long val;
3339
3340 if (kstrtoul(buf, 16, &val))
3341 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003342 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3343 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003344 return -EPERM;
3345
3346 mutex_lock(&drvdata->lock);
3347 if (val)
3348 drvdata->cmb->patt_ts = true;
3349 else
3350 drvdata->cmb->patt_ts = false;
3351 mutex_unlock(&drvdata->lock);
3352 return size;
3353}
Satyajit Desai326497c2016-11-14 10:15:03 -08003354static DEVICE_ATTR(cmb_patt_ts, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003355 tpdm_show_cmb_patt_ts, tpdm_store_cmb_patt_ts);
3356
3357static ssize_t tpdm_show_cmb_trig_patt_val_lsb(struct device *dev,
3358 struct device_attribute *attr,
3359 char *buf)
3360{
3361 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3362 unsigned long val;
3363
Satyajit Desaie104ff52016-09-12 16:38:12 -07003364 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3365 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003366 return -EPERM;
3367
3368 val = drvdata->cmb->trig_patt_val[TPDM_CMB_LSB];
3369
3370 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
3371}
3372
3373static ssize_t tpdm_store_cmb_trig_patt_val_lsb(struct device *dev,
3374 struct device_attribute *attr,
3375 const char *buf, size_t size)
3376{
3377 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3378 unsigned long val;
3379
3380 if (kstrtoul(buf, 16, &val))
3381 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003382 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3383 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003384 return -EPERM;
3385
3386 mutex_lock(&drvdata->lock);
3387 drvdata->cmb->trig_patt_val[TPDM_CMB_LSB] = val;
3388 mutex_unlock(&drvdata->lock);
3389 return size;
3390}
Satyajit Desai326497c2016-11-14 10:15:03 -08003391static DEVICE_ATTR(cmb_trig_patt_val_lsb, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003392 tpdm_show_cmb_trig_patt_val_lsb,
3393 tpdm_store_cmb_trig_patt_val_lsb);
3394
3395static ssize_t tpdm_show_cmb_trig_patt_mask_lsb(struct device *dev,
3396 struct device_attribute *attr,
3397 char *buf)
3398{
3399 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3400 unsigned long val;
3401
Satyajit Desaie104ff52016-09-12 16:38:12 -07003402 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3403 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003404 return -EPERM;
3405
3406 val = drvdata->cmb->trig_patt_mask[TPDM_CMB_LSB];
3407
3408 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
3409}
3410
3411static ssize_t tpdm_store_cmb_trig_patt_mask_lsb(struct device *dev,
3412 struct device_attribute *attr,
3413 const char *buf, size_t size)
3414{
3415 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3416 unsigned long val;
3417
3418 if (kstrtoul(buf, 16, &val))
3419 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003420 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3421 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003422 return -EPERM;
3423
3424 mutex_lock(&drvdata->lock);
3425 drvdata->cmb->trig_patt_mask[TPDM_CMB_LSB] = val;
3426 mutex_unlock(&drvdata->lock);
3427 return size;
3428}
Satyajit Desai326497c2016-11-14 10:15:03 -08003429static DEVICE_ATTR(cmb_trig_patt_mask_lsb, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003430 tpdm_show_cmb_trig_patt_mask_lsb,
3431 tpdm_store_cmb_trig_patt_mask_lsb);
3432
3433static ssize_t tpdm_show_cmb_trig_patt_val_msb(struct device *dev,
3434 struct device_attribute *attr,
3435 char *buf)
3436{
3437 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3438 unsigned long val;
3439
Satyajit Desaie104ff52016-09-12 16:38:12 -07003440 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3441 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003442 return -EPERM;
3443
3444 val = drvdata->cmb->trig_patt_val[TPDM_CMB_MSB];
3445
3446 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
3447}
3448
3449static ssize_t tpdm_store_cmb_trig_patt_val_msb(struct device *dev,
3450 struct device_attribute *attr,
3451 const char *buf, size_t size)
3452{
3453 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3454 unsigned long val;
3455
3456 if (kstrtoul(buf, 16, &val))
3457 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003458 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3459 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003460 return -EPERM;
3461
3462 mutex_lock(&drvdata->lock);
3463 drvdata->cmb->trig_patt_val[TPDM_CMB_MSB] = val;
3464 mutex_unlock(&drvdata->lock);
3465 return size;
3466}
Satyajit Desai326497c2016-11-14 10:15:03 -08003467static DEVICE_ATTR(cmb_trig_patt_val_msb, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003468 tpdm_show_cmb_trig_patt_val_msb,
3469 tpdm_store_cmb_trig_patt_val_msb);
3470
3471static ssize_t tpdm_show_cmb_trig_patt_mask_msb(struct device *dev,
3472 struct device_attribute *attr,
3473 char *buf)
3474{
3475 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3476 unsigned long val;
3477
Satyajit Desaie104ff52016-09-12 16:38:12 -07003478 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3479 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003480 return -EPERM;
3481
3482 val = drvdata->cmb->trig_patt_mask[TPDM_CMB_MSB];
3483
3484 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
3485}
3486
3487static ssize_t tpdm_store_cmb_trig_patt_mask_msb(struct device *dev,
3488 struct device_attribute *attr,
3489 const char *buf, size_t size)
3490{
3491 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3492 unsigned long val;
3493
3494 if (kstrtoul(buf, 16, &val))
3495 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003496 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3497 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003498 return -EPERM;
3499
3500 mutex_lock(&drvdata->lock);
3501 drvdata->cmb->trig_patt_mask[TPDM_CMB_MSB] = val;
3502 mutex_unlock(&drvdata->lock);
3503 return size;
3504}
Satyajit Desai326497c2016-11-14 10:15:03 -08003505static DEVICE_ATTR(cmb_trig_patt_mask_msb, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003506 tpdm_show_cmb_trig_patt_mask_msb,
3507 tpdm_store_cmb_trig_patt_mask_msb);
3508
3509static ssize_t tpdm_show_cmb_trig_ts(struct device *dev,
3510 struct device_attribute *attr,
3511 char *buf)
3512{
3513 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3514
Satyajit Desaie104ff52016-09-12 16:38:12 -07003515 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3516 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003517 return -EPERM;
3518
3519 return scnprintf(buf, PAGE_SIZE, "%u\n",
3520 (unsigned int)drvdata->cmb->trig_ts);
3521}
3522
3523static ssize_t tpdm_store_cmb_trig_ts(struct device *dev,
Satyajit Desaie104ff52016-09-12 16:38:12 -07003524 struct device_attribute *attr,
3525 const char *buf,
3526 size_t size)
Satyajit Desaif151d682016-09-12 16:18:03 -07003527{
3528 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3529 unsigned long val;
3530
3531 if (kstrtoul(buf, 16, &val))
3532 return -EINVAL;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003533 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3534 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003535 return -EPERM;
3536
3537 mutex_lock(&drvdata->lock);
3538 if (val)
3539 drvdata->cmb->trig_ts = true;
3540 else
3541 drvdata->cmb->trig_ts = false;
3542 mutex_unlock(&drvdata->lock);
3543 return size;
3544}
Satyajit Desai326497c2016-11-14 10:15:03 -08003545static DEVICE_ATTR(cmb_trig_ts, 0644,
Satyajit Desaif151d682016-09-12 16:18:03 -07003546 tpdm_show_cmb_trig_ts, tpdm_store_cmb_trig_ts);
3547
3548static ssize_t tpdm_store_cmb_msr(struct device *dev,
3549 struct device_attribute *attr,
3550 const char *buf,
3551 size_t size)
3552{
3553 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3554 unsigned int num, val;
3555 int nval;
3556
3557 if (!drvdata->msr_support)
3558 return -EINVAL;
3559
Satyajit Desaie104ff52016-09-12 16:38:12 -07003560 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3561 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
Satyajit Desaif151d682016-09-12 16:18:03 -07003562 return -EPERM;
3563
3564 nval = sscanf(buf, "%u %x", &num, &val);
3565 if (nval != 2)
3566 return -EINVAL;
3567
3568 if (num >= TPDM_CMB_MAX_MSR)
3569 return -EINVAL;
3570
3571 mutex_lock(&drvdata->lock);
3572 drvdata->cmb->msr[num] = val;
3573 mutex_unlock(&drvdata->lock);
3574 return size;
3575}
Satyajit Desai326497c2016-11-14 10:15:03 -08003576static DEVICE_ATTR(cmb_msr, 0200, NULL, tpdm_store_cmb_msr);
Satyajit Desaif151d682016-09-12 16:18:03 -07003577
Satyajit Desaie104ff52016-09-12 16:38:12 -07003578static ssize_t tpdm_show_cmb_read_interface_state(struct device *dev,
3579 struct device_attribute *attr,
3580 char *buf)
3581{
3582 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3583 unsigned long val;
3584
3585 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3586 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
3587 return -EPERM;
3588
3589 mutex_lock(&drvdata->lock);
3590 TPDM_UNLOCK(drvdata);
3591 val = tpdm_readl(drvdata, TPDM_CMB_READVAL);
3592 TPDM_LOCK(drvdata);
3593 mutex_unlock(&drvdata->lock);
3594
3595 return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
3596}
3597static DEVICE_ATTR(cmb_read_interface_state, 0444,
3598 tpdm_show_cmb_read_interface_state, NULL);
3599
3600static ssize_t tpdm_show_cmb_read_ctl_reg(struct device *dev,
3601 struct device_attribute *attr,
3602 char *buf)
3603{
3604 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3605 unsigned long val;
3606
3607 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3608 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
3609 return -EPERM;
3610
3611 mutex_lock(&drvdata->lock);
3612 TPDM_UNLOCK(drvdata);
3613 val = tpdm_readl(drvdata, TPDM_CMB_READCTL);
3614 TPDM_LOCK(drvdata);
3615 mutex_unlock(&drvdata->lock);
3616
3617 if (test_bit(TPDM_DS_CMB, drvdata->datasets))
3618 return scnprintf(buf, PAGE_SIZE, "SEL: %lx\n", val);
3619 else
3620 return scnprintf(buf, PAGE_SIZE, "Lane %u SEL: %lx\n",
3621 (unsigned int)BMVAL(val, 1, 3), val & 0x1);
3622}
3623
3624static ssize_t tpdm_store_cmb_read_ctl_reg(struct device *dev,
3625 struct device_attribute *attr,
3626 const char *buf,
3627 size_t size)
3628{
3629 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3630 unsigned long val;
3631
3632 if (kstrtoul(buf, 16, &val))
3633 return -EINVAL;
3634
3635 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3636 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
3637 return -EPERM;
3638
3639 mutex_lock(&drvdata->lock);
3640 TPDM_UNLOCK(drvdata);
3641 tpdm_writel(drvdata, val, TPDM_CMB_READCTL);
3642 TPDM_LOCK(drvdata);
3643 mutex_unlock(&drvdata->lock);
3644
3645 return size;
3646}
3647static DEVICE_ATTR(cmb_read_ctl_reg, 0644,
3648 tpdm_show_cmb_read_ctl_reg, tpdm_store_cmb_read_ctl_reg);
3649
3650static ssize_t tpdm_show_mcmb_trig_lane(struct device *dev,
3651 struct device_attribute *attr,
3652 char *buf)
3653{
3654 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3655
3656 if (!test_bit(TPDM_DS_MCMB, drvdata->datasets))
3657 return -EPERM;
3658
3659 return scnprintf(buf, PAGE_SIZE, "%u\n",
3660 (unsigned int)drvdata->cmb->mcmb->mcmb_trig_lane);
3661}
3662
3663static ssize_t tpdm_store_mcmb_trig_lane(struct device *dev,
3664 struct device_attribute *attr,
3665 const char *buf,
3666 size_t size)
3667{
3668 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3669 unsigned long val;
3670
3671 if (kstrtoul(buf, 10, &val))
3672 return -EINVAL;
3673 if (val >= TPDM_MCMB_MAX_LANES)
3674 return -EINVAL;
3675 if (!test_bit(TPDM_DS_MCMB, drvdata->datasets))
3676 return -EPERM;
3677
3678 mutex_lock(&drvdata->lock);
3679 drvdata->cmb->mcmb->mcmb_trig_lane = val;
3680 mutex_unlock(&drvdata->lock);
3681 return size;
3682}
3683static DEVICE_ATTR(mcmb_trig_lane, 0644,
3684 tpdm_show_mcmb_trig_lane, tpdm_store_mcmb_trig_lane);
3685
3686static ssize_t tpdm_show_mcmb_lanes_select(struct device *dev,
3687 struct device_attribute *attr,
3688 char *buf)
3689{
3690 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3691
3692 if (!test_bit(TPDM_DS_MCMB, drvdata->datasets))
3693 return -EPERM;
3694
3695 return scnprintf(buf, PAGE_SIZE, "%u\n",
3696 (unsigned int)drvdata->cmb->mcmb->mcmb_lane_select);
3697}
3698
3699static ssize_t tpdm_store_mcmb_lanes_select(struct device *dev,
3700 struct device_attribute *attr,
3701 const char *buf,
3702 size_t size)
3703{
3704 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3705 unsigned long val;
3706
3707 if (kstrtoul(buf, 16, &val))
3708 return -EINVAL;
3709 if (!test_bit(TPDM_DS_MCMB, drvdata->datasets))
3710 return -EPERM;
3711
3712 val = BMVAL(val, 0, TPDM_MCMB_MAX_LANES - 1);
3713
3714 mutex_lock(&drvdata->lock);
3715 drvdata->cmb->mcmb->mcmb_lane_select = val;
3716 mutex_unlock(&drvdata->lock);
3717 return size;
3718}
3719static DEVICE_ATTR(mcmb_lanes_select, 0644,
3720 tpdm_show_mcmb_lanes_select, tpdm_store_mcmb_lanes_select);
3721
3722static ssize_t tpdm_store_cmb_markr(struct device *dev,
3723 struct device_attribute *attr,
3724 const char *buf,
3725 size_t size)
3726{
3727 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
3728 unsigned long val;
3729
3730 if (kstrtoul(buf, 16, &val))
3731 return -EINVAL;
3732
3733 if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3734 test_bit(TPDM_DS_MCMB, drvdata->datasets)))
3735 return -EPERM;
3736
3737 mutex_lock(&drvdata->lock);
3738 TPDM_UNLOCK(drvdata);
3739 tpdm_writel(drvdata, val, TPDM_CMB_MARKR);
3740 TPDM_LOCK(drvdata);
3741 mutex_unlock(&drvdata->lock);
3742
3743 return size;
3744}
3745static DEVICE_ATTR(cmb_markr, 0200, NULL, tpdm_store_cmb_markr);
3746
Satyajit Desaif151d682016-09-12 16:18:03 -07003747static struct attribute *tpdm_bc_attrs[] = {
3748 &dev_attr_bc_capture_mode.attr,
3749 &dev_attr_bc_retrieval_mode.attr,
3750 &dev_attr_bc_reset_counters.attr,
3751 &dev_attr_bc_sat_mode.attr,
3752 &dev_attr_bc_enable_counters.attr,
3753 &dev_attr_bc_clear_counters.attr,
3754 &dev_attr_bc_enable_irq.attr,
3755 &dev_attr_bc_clear_irq.attr,
3756 &dev_attr_bc_trig_val_lo.attr,
3757 &dev_attr_bc_trig_val_hi.attr,
3758 &dev_attr_bc_enable_ganging.attr,
3759 &dev_attr_bc_overflow_val.attr,
3760 &dev_attr_bc_ovsr.attr,
3761 &dev_attr_bc_counter_sel.attr,
3762 &dev_attr_bc_count_val_lo.attr,
3763 &dev_attr_bc_count_val_hi.attr,
3764 &dev_attr_bc_shadow_val_lo.attr,
3765 &dev_attr_bc_shadow_val_hi.attr,
3766 &dev_attr_bc_sw_inc.attr,
3767 &dev_attr_bc_msr.attr,
3768 NULL,
3769};
3770
3771static struct attribute *tpdm_tc_attrs[] = {
3772 &dev_attr_tc_capture_mode.attr,
3773 &dev_attr_tc_retrieval_mode.attr,
3774 &dev_attr_tc_reset_counters.attr,
3775 &dev_attr_tc_sat_mode.attr,
3776 &dev_attr_tc_enable_counters.attr,
3777 &dev_attr_tc_clear_counters.attr,
3778 &dev_attr_tc_enable_irq.attr,
3779 &dev_attr_tc_clear_irq.attr,
3780 &dev_attr_tc_trig_sel.attr,
3781 &dev_attr_tc_trig_val_lo.attr,
3782 &dev_attr_tc_trig_val_hi.attr,
3783 &dev_attr_tc_ovsr_gp.attr,
3784 &dev_attr_tc_ovsr_impl.attr,
3785 &dev_attr_tc_counter_sel.attr,
3786 &dev_attr_tc_count_val_lo.attr,
3787 &dev_attr_tc_count_val_hi.attr,
3788 &dev_attr_tc_shadow_val_lo.attr,
3789 &dev_attr_tc_shadow_val_hi.attr,
3790 &dev_attr_tc_sw_inc.attr,
3791 &dev_attr_tc_msr.attr,
3792 NULL,
3793};
3794
3795static struct attribute *tpdm_dsb_attrs[] = {
3796 &dev_attr_dsb_mode.attr,
3797 &dev_attr_dsb_edge_ctrl.attr,
3798 &dev_attr_dsb_edge_ctrl_mask.attr,
3799 &dev_attr_dsb_patt_val.attr,
3800 &dev_attr_dsb_patt_mask.attr,
3801 &dev_attr_dsb_patt_ts.attr,
3802 &dev_attr_dsb_patt_type.attr,
3803 &dev_attr_dsb_trig_patt_val.attr,
3804 &dev_attr_dsb_trig_patt_mask.attr,
3805 &dev_attr_dsb_trig_ts.attr,
3806 &dev_attr_dsb_select_val.attr,
3807 &dev_attr_dsb_msr.attr,
3808 NULL,
3809};
3810
3811static struct attribute *tpdm_cmb_attrs[] = {
3812 &dev_attr_cmb_available_modes.attr,
3813 &dev_attr_cmb_mode.attr,
3814 &dev_attr_cmb_patt_val_lsb.attr,
3815 &dev_attr_cmb_patt_mask_lsb.attr,
3816 &dev_attr_cmb_patt_val_msb.attr,
3817 &dev_attr_cmb_patt_mask_msb.attr,
3818 &dev_attr_cmb_patt_ts.attr,
3819 &dev_attr_cmb_trig_patt_val_lsb.attr,
3820 &dev_attr_cmb_trig_patt_mask_lsb.attr,
3821 &dev_attr_cmb_trig_patt_val_msb.attr,
3822 &dev_attr_cmb_trig_patt_mask_msb.attr,
3823 &dev_attr_cmb_trig_ts.attr,
3824 &dev_attr_cmb_msr.attr,
Satyajit Desaie104ff52016-09-12 16:38:12 -07003825 &dev_attr_cmb_read_interface_state.attr,
3826 &dev_attr_cmb_read_ctl_reg.attr,
3827 &dev_attr_cmb_markr.attr,
3828 &dev_attr_mcmb_trig_lane.attr,
3829 &dev_attr_mcmb_lanes_select.attr,
Satyajit Desaif151d682016-09-12 16:18:03 -07003830 NULL,
3831};
3832
3833static struct attribute_group tpdm_bc_attr_grp = {
3834 .attrs = tpdm_bc_attrs,
3835};
3836
3837static struct attribute_group tpdm_tc_attr_grp = {
3838 .attrs = tpdm_tc_attrs,
3839};
3840
3841static struct attribute_group tpdm_dsb_attr_grp = {
3842 .attrs = tpdm_dsb_attrs,
3843};
3844
3845static struct attribute_group tpdm_cmb_attr_grp = {
3846 .attrs = tpdm_cmb_attrs,
3847};
3848
3849static struct attribute *tpdm_attrs[] = {
3850 &dev_attr_available_datasets.attr,
3851 &dev_attr_enable_datasets.attr,
3852 &dev_attr_gp_regs.attr,
3853 NULL,
3854};
3855
3856static struct attribute_group tpdm_attr_grp = {
3857 .attrs = tpdm_attrs,
3858};
3859static const struct attribute_group *tpdm_attr_grps[] = {
3860 &tpdm_attr_grp,
3861 &tpdm_bc_attr_grp,
3862 &tpdm_tc_attr_grp,
3863 &tpdm_dsb_attr_grp,
3864 &tpdm_cmb_attr_grp,
3865 NULL,
3866};
3867
3868static int tpdm_datasets_alloc(struct tpdm_drvdata *drvdata)
3869{
3870 if (test_bit(TPDM_DS_GPR, drvdata->datasets)) {
3871 drvdata->gpr = devm_kzalloc(drvdata->dev, sizeof(*drvdata->gpr),
3872 GFP_KERNEL);
3873 if (!drvdata->gpr)
3874 return -ENOMEM;
3875 }
3876 if (test_bit(TPDM_DS_BC, drvdata->datasets)) {
3877 drvdata->bc = devm_kzalloc(drvdata->dev, sizeof(*drvdata->bc),
3878 GFP_KERNEL);
3879 if (!drvdata->bc)
3880 return -ENOMEM;
3881 }
3882 if (test_bit(TPDM_DS_TC, drvdata->datasets)) {
3883 drvdata->tc = devm_kzalloc(drvdata->dev, sizeof(*drvdata->tc),
3884 GFP_KERNEL);
3885 if (!drvdata->tc)
3886 return -ENOMEM;
3887 }
3888 if (test_bit(TPDM_DS_DSB, drvdata->datasets)) {
3889 drvdata->dsb = devm_kzalloc(drvdata->dev, sizeof(*drvdata->dsb),
3890 GFP_KERNEL);
3891 if (!drvdata->dsb)
3892 return -ENOMEM;
3893 }
3894 if (test_bit(TPDM_DS_CMB, drvdata->datasets)) {
3895 drvdata->cmb = devm_kzalloc(drvdata->dev, sizeof(*drvdata->cmb),
3896 GFP_KERNEL);
3897 if (!drvdata->cmb)
3898 return -ENOMEM;
Satyajit Desaie104ff52016-09-12 16:38:12 -07003899 } else if (test_bit(TPDM_DS_MCMB, drvdata->datasets)) {
3900 drvdata->cmb = devm_kzalloc(drvdata->dev, sizeof(*drvdata->cmb),
3901 GFP_KERNEL);
3902 if (!drvdata->cmb)
3903 return -ENOMEM;
3904 drvdata->cmb->mcmb = devm_kzalloc(drvdata->dev,
3905 sizeof(*drvdata->cmb->mcmb),
3906 GFP_KERNEL);
3907 if (!drvdata->cmb->mcmb)
3908 return -ENOMEM;
Satyajit Desaif151d682016-09-12 16:18:03 -07003909 }
3910 return 0;
3911}
3912
3913static void tpdm_init_default_data(struct tpdm_drvdata *drvdata)
3914{
3915 if (test_bit(TPDM_DS_BC, drvdata->datasets))
3916 drvdata->bc->retrieval_mode = TPDM_MODE_ATB;
3917
3918 if (test_bit(TPDM_DS_TC, drvdata->datasets))
3919 drvdata->tc->retrieval_mode = TPDM_MODE_ATB;
3920
3921 if (test_bit(TPDM_DS_DSB, drvdata->datasets))
3922 drvdata->dsb->trig_ts = true;
3923
Satyajit Desaie104ff52016-09-12 16:38:12 -07003924 if (test_bit(TPDM_DS_CMB, drvdata->datasets) ||
3925 test_bit(TPDM_DS_MCMB, drvdata->datasets))
Satyajit Desaif151d682016-09-12 16:18:03 -07003926 drvdata->cmb->trig_ts = true;
3927}
3928
3929static int tpdm_probe(struct platform_device *pdev)
3930{
3931 int ret, i;
3932 uint32_t pidr, devid;
3933 struct device *dev = &pdev->dev;
3934 struct coresight_platform_data *pdata;
3935 struct tpdm_drvdata *drvdata;
3936 struct resource *res;
3937 struct coresight_desc *desc;
3938 static int traceid = TPDM_TRACE_ID_START;
3939 uint32_t version;
3940
3941 pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
3942 if (IS_ERR(pdata))
3943 return PTR_ERR(pdata);
3944 pdev->dev.platform_data = pdata;
3945
3946 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
3947 if (!drvdata)
3948 return -ENOMEM;
3949 drvdata->dev = &pdev->dev;
3950 platform_set_drvdata(pdev, drvdata);
3951
3952 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tpdm-base");
3953 if (!res)
3954 return -ENODEV;
3955
3956 drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
3957 if (!drvdata->base)
3958 return -ENOMEM;
3959
3960 drvdata->clk_enable = of_property_read_bool(pdev->dev.of_node,
3961 "qcom,clk-enable");
3962
3963 drvdata->msr_fix_req = of_property_read_bool(pdev->dev.of_node,
3964 "qcom,msr-fix-req");
3965
3966 mutex_init(&drvdata->lock);
3967
3968 drvdata->clk = devm_clk_get(dev, "core_clk");
3969 if (IS_ERR(drvdata->clk))
3970 return PTR_ERR(drvdata->clk);
3971
3972 ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
3973 if (ret)
3974 return ret;
3975
3976 ret = clk_prepare_enable(drvdata->clk);
3977 if (ret)
3978 return ret;
3979
3980 version = tpdm_readl(drvdata, CORESIGHT_PERIPHIDR2);
3981 drvdata->version = BMVAL(version, 4, 7);
3982
3983 if (drvdata->version)
3984 drvdata->msr_support = true;
3985
3986 pidr = tpdm_readl(drvdata, CORESIGHT_PERIPHIDR0);
3987 for (i = 0; i < TPDM_DATASETS; i++) {
3988 if (pidr & BIT(i)) {
3989 __set_bit(i, drvdata->datasets);
3990 __set_bit(i, drvdata->enable_ds);
3991 }
3992 }
3993
3994 ret = tpdm_datasets_alloc(drvdata);
3995 if (ret)
3996 return ret;
3997
3998 tpdm_init_default_data(drvdata);
3999
4000 devid = tpdm_readl(drvdata, CORESIGHT_DEVID);
4001 drvdata->tc_trig_type = BMVAL(devid, 27, 28);
4002 drvdata->bc_trig_type = BMVAL(devid, 25, 26);
4003 drvdata->bc_gang_type = BMVAL(devid, 23, 24);
4004 drvdata->bc_counters_avail = BMVAL(devid, 6, 10) + 1;
4005 drvdata->tc_counters_avail = BMVAL(devid, 4, 5) + 1;
4006
4007 clk_disable_unprepare(drvdata->clk);
4008
4009 drvdata->traceid = traceid++;
4010
4011 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
4012 if (!desc)
4013 return -ENOMEM;
4014 desc->type = CORESIGHT_DEV_TYPE_SOURCE;
4015 desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
4016 desc->ops = &tpdm_cs_ops;
4017 desc->pdata = pdev->dev.platform_data;
4018 desc->dev = &pdev->dev;
4019 desc->groups = tpdm_attr_grps;
4020 drvdata->csdev = coresight_register(desc);
4021 if (IS_ERR(drvdata->csdev))
4022 return PTR_ERR(drvdata->csdev);
4023
4024 dev_dbg(drvdata->dev, "TPDM initialized\n");
4025
4026 if (boot_enable)
4027 coresight_enable(drvdata->csdev);
4028
4029 return 0;
4030}
4031
4032static int tpdm_remove(struct platform_device *pdev)
4033{
4034 struct tpdm_drvdata *drvdata = platform_get_drvdata(pdev);
4035
4036 coresight_unregister(drvdata->csdev);
4037 return 0;
4038}
4039
4040static const struct of_device_id tpdm_match[] = {
4041 {.compatible = "qcom,coresight-tpdm"},
4042 {}
4043};
4044
4045static struct platform_driver tpdm_driver = {
4046 .probe = tpdm_probe,
4047 .remove = tpdm_remove,
4048 .driver = {
4049 .name = "coresight-tpdm",
4050 .owner = THIS_MODULE,
4051 .of_match_table = tpdm_match,
4052 },
4053};
4054
4055static int __init tpdm_init(void)
4056{
4057 return platform_driver_register(&tpdm_driver);
4058}
4059module_init(tpdm_init);
4060
4061static void __exit tpdm_exit(void)
4062{
4063 platform_driver_unregister(&tpdm_driver);
4064}
4065module_exit(tpdm_exit);
4066
4067MODULE_LICENSE("GPL v2");
4068MODULE_DESCRIPTION("Trace, Profiling & Diagnostic Monitor driver");