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