blob: e919f475a02e8285ee0562780006bd0878559d7d [file] [log] [blame]
Rama Aparna Mallavarapua2a8e3e2017-08-16 20:56:00 -07001/* Copyright (c) 2017, 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/init.h>
16#include <linux/device.h>
17#include <linux/platform_device.h>
18#include <linux/io.h>
19#include <linux/err.h>
20#include <linux/slab.h>
21#include <linux/mutex.h>
22#include <linux/amba/bus.h>
23#include <linux/topology.h>
24#include <linux/of.h>
25#include <linux/coresight.h>
26
27#include "coresight-priv.h"
28
29#define tgu_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off)
30#define tgu_readl(drvdata, off) __raw_readl(drvdata->base + off)
31
32#define TGU_LOCK(drvdata) \
33do { \
34 mb(); /* ensure configuration take effect before we lock it */ \
35 tgu_writel(drvdata, 0x0, CORESIGHT_LAR); \
36} while (0)
37#define TGU_UNLOCK(drvdata) \
38do { \
39 tgu_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
40 mb(); /* ensure unlock take effect before we configure */ \
41} while (0)
42
43#define TGU_CONTROL 0x0000
44#define TIMER0_STATUS 0x0004
45#define COUNTER0_STATUS 0x000C
46#define TGU_STATUS 0x0014
47#define TIMER0_COMPARE_STEP(n) (0x0040 + 0x1D8 * n)
48#define COUNTER0_COMPARE_STEP(n) (0x0048 + 0x1D8 * n)
49#define GROUP_REG_STEP(grp, reg, step) (0x0074 + 0x60 * grp + 0x4 * reg + \
50 0x1D8 * step)
51#define CONDITION_DECODE_STEP(m, n) (0x0050 + 0x4 * m + 0x1D8 * n)
52#define CONDITION_SELECT_STEP(m, n) (0x0060 + 0x4 * m + 0x1D8 * n)
53#define GROUP0 0x0074
54#define GROUP1 0x00D4
55#define GROUP2 0x0134
56#define GROUP3 0x0194
57#define TGU_LAR 0x0FB0
58
59#define MAX_GROUP_SETS 256
60#define MAX_GROUPS 4
61#define MAX_CONDITION_SETS 64
62#define MAX_TIMER_COUNTER_SETS 8
63
64#define to_tgu_drvdata(c) container_of(c, struct tgu_drvdata, tgu)
65
66struct Trigger_group_data {
67 unsigned long grpaddr;
68 unsigned long value;
69};
70
71struct Trigger_condition_data {
72 unsigned long condaddr;
73 unsigned long value;
74};
75
76struct Trigger_select_data {
77 unsigned long selectaddr;
78 unsigned long value;
79};
80
81struct Trigger_timer_data {
82 unsigned long timeraddr;
83 unsigned long value;
84};
85
86struct Trigger_counter_data {
87 unsigned long counteraddr;
88 unsigned long value;
89};
90struct tgu_drvdata {
91 void __iomem *base;
92 struct device *dev;
93 struct coresight_device *csdev;
94 struct clk *clk;
95 spinlock_t spinlock;
96 int max_steps;
97 int max_conditions;
98 int max_regs;
99 int max_timer_counter;
100 struct Trigger_group_data *grp_data;
101 struct Trigger_condition_data *condition_data;
102 struct Trigger_select_data *select_data;
103 struct Trigger_timer_data *timer_data;
104 struct Trigger_counter_data *counter_data;
105 int grp_refcnt;
106 int cond_refcnt;
107 int select_refcnt;
108 int timer_refcnt;
109 int counter_refcnt;
110 bool enable;
111};
112
113static ssize_t enable_tgu(struct device *dev,
114 struct device_attribute *attr,
115 const char *buf, size_t size)
116{
117 unsigned long value;
118 struct tgu_drvdata *drvdata = dev_get_drvdata(dev->parent);
119 int ret, i, j;
120
121 if (kstrtoul(buf, 16, &value))
122 return -EINVAL;
123
124 /* Enable clock */
125 ret = pm_runtime_get_sync(drvdata->dev);
126 if (ret)
127 return ret;
128
129 spin_lock(&drvdata->spinlock);
130 /* Unlock the TGU LAR */
131 TGU_UNLOCK(drvdata);
132
133 if (value) {
134
135 /* Disable TGU to program the triggers */
136 tgu_writel(drvdata, 0, TGU_CONTROL);
137
138 /* program the TGU Group data for the desired use case*/
139
140 for (i = 0; i <= drvdata->grp_refcnt; i++)
141 tgu_writel(drvdata, drvdata->grp_data[i].value,
142 drvdata->grp_data[i].grpaddr);
143
144 /* program the unused Condition Decode registers NOT bits to 1*/
145 for (i = 0; i <= drvdata->max_conditions; i++) {
146 for (j = 0; j <= drvdata->max_steps; j++)
147 tgu_writel(drvdata, 0x1000000,
148 CONDITION_DECODE_STEP(i, j));
149 }
150 /* program the TGU Condition Decode for the desired use case*/
151 for (i = 0; i <= drvdata->cond_refcnt; i++)
152 tgu_writel(drvdata, drvdata->condition_data[i].value,
153 drvdata->condition_data[i].condaddr);
154
155 /* program the TGU Condition Select for the desired use case*/
156 for (i = 0; i <= drvdata->select_refcnt; i++)
157 tgu_writel(drvdata, drvdata->select_data[i].value,
158 drvdata->select_data[i].selectaddr);
159
160 /* Timer and Counter Check */
161 for (i = 0; i <= drvdata->timer_refcnt; i++)
162 tgu_writel(drvdata, drvdata->timer_data[i].value,
163 drvdata->timer_data[i].timeraddr);
164
165 for (i = 0; i <= drvdata->counter_refcnt; i++)
166 tgu_writel(drvdata, drvdata->counter_data[i].value,
167 drvdata->counter_data[i].counteraddr);
168
169 /* Enable TGU to program the triggers */
170 tgu_writel(drvdata, 1, TGU_CONTROL);
171
172 drvdata->enable = true;
173 dev_dbg(dev, "Coresight-TGU enabled\n");
174
175 } else {
176 /* Disable TGU to program the triggers */
177 tgu_writel(drvdata, 0, TGU_CONTROL);
178 TGU_LOCK(drvdata);
179 spin_unlock(&drvdata->spinlock);
180
181 pm_runtime_put(drvdata->dev);
182 dev_dbg(dev, "Coresight-TGU disabled\n");
183 }
184
185 TGU_LOCK(drvdata);
186 spin_unlock(&drvdata->spinlock);
187 return size;
188}
189static DEVICE_ATTR(enable_tgu, 0200, NULL, enable_tgu);
190
191static ssize_t reset_tgu(struct device *dev,
192 struct device_attribute *attr,
193 const char *buf, size_t size)
194{
195 unsigned long value;
196 struct tgu_drvdata *drvdata = dev_get_drvdata(dev->parent);
197 int ret;
198
199 if (kstrtoul(buf, 16, &value))
200 return -EINVAL;
201
202 if (!drvdata->enable) {
203 /* Enable clock */
204 ret = pm_runtime_get_sync(drvdata->dev);
205 if (ret)
206 return ret;
207 }
208
209 spin_lock(&drvdata->spinlock);
210 /* Unlock the TGU LAR */
211 TGU_UNLOCK(drvdata);
212
213 if (value) {
214 /* Disable TGU to program the triggers */
215 tgu_writel(drvdata, 0, TGU_CONTROL);
216
217 /* Reset the Reference counters*/
218 drvdata->grp_refcnt = 0;
219 drvdata->cond_refcnt = 0;
220 drvdata->select_refcnt = 0;
221 drvdata->timer_refcnt = 0;
222 drvdata->counter_refcnt = 0;
223
224 dev_dbg(dev, "Coresight-TGU disabled\n");
225 } else
226 dev_dbg(dev, "Invalid input to reset the TGU\n");
227
228 TGU_LOCK(drvdata);
229 spin_unlock(&drvdata->spinlock);
230 pm_runtime_put(drvdata->dev);
231 return size;
232}
233static DEVICE_ATTR(reset_tgu, 0200, NULL, reset_tgu);
234
235static ssize_t set_group(struct device *dev, struct device_attribute *attr,
236 const char *buf, size_t size)
237{
238 struct tgu_drvdata *drvdata = dev_get_drvdata(dev->parent);
239 int grp, reg, step;
240 unsigned long value;
241
242 if (drvdata->grp_refcnt >= MAX_GROUP_SETS) {
243 dev_err(drvdata->dev, " Too many groups are being configured");
244 return -EINVAL;
245 }
246
247 if (sscanf(buf, "%d %d %d %lx", &grp, &reg, &step, &value) != 4)
248 return -EINVAL;
249
250 spin_lock(&drvdata->spinlock);
251 if ((grp <= MAX_GROUPS) && (reg <= drvdata->max_regs)) {
252 drvdata->grp_data[drvdata->grp_refcnt].grpaddr =
253 GROUP_REG_STEP(grp, reg, step);
254 drvdata->grp_data[drvdata->grp_refcnt].value = value;
255 drvdata->grp_refcnt++;
256 } else
257 dev_err(drvdata->dev, "Invalid group data\n");
258
259 spin_unlock(&drvdata->spinlock);
260
261 return size;
262}
263static DEVICE_ATTR(set_group, 0200, NULL, set_group);
264
265static ssize_t tgu_set_condition(struct device *dev, struct device_attribute
266 *attr, const char *buf, size_t size)
267{
268 struct tgu_drvdata *drvdata = dev_get_drvdata(dev->parent);
269 unsigned long value;
270 int cond, step;
271
272 if (drvdata->cond_refcnt >= MAX_CONDITION_SETS) {
273 dev_err(drvdata->dev, " Too many groups are being configured");
274 return -EINVAL;
275 }
276
277 if (sscanf(buf, "%d %d %lx", &cond, &step, &value) != 3)
278 return -EINVAL;
279
280 spin_lock(&drvdata->spinlock);
281 if ((cond <= drvdata->max_conditions) && (step <=
282 drvdata->max_steps)) {
283 drvdata->condition_data[drvdata->cond_refcnt].condaddr =
284 CONDITION_DECODE_STEP(cond, step);
285 drvdata->condition_data[drvdata->cond_refcnt].value = value;
286 drvdata->cond_refcnt++;
287 } else
288 dev_err(drvdata->dev, "Invalid condition decode data\n");
289
290 spin_unlock(&drvdata->spinlock);
291
292 return size;
293}
294static DEVICE_ATTR(set_condition, 0200, NULL, tgu_set_condition);
295
296static ssize_t tgu_set_select(struct device *dev, struct device_attribute *attr,
297 const char *buf, size_t size)
298{
299 struct tgu_drvdata *drvdata = dev_get_drvdata(dev->parent);
300 unsigned long value;
301 int select, step;
302
303 if (drvdata->select_refcnt >= MAX_CONDITION_SETS) {
304 dev_err(drvdata->dev, " Too many groups are being configured");
305 return -EINVAL;
306 }
307
308 if (sscanf(buf, "%d %d %lx", &select, &step, &value) != 3)
309 return -EINVAL;
310
311 spin_lock(&drvdata->spinlock);
312
313 if ((select <= drvdata->max_conditions) && (step <=
314 drvdata->max_steps)) {
315 drvdata->select_data[drvdata->select_refcnt].selectaddr =
316 CONDITION_SELECT_STEP(select, step);
317 drvdata->select_data[drvdata->select_refcnt].value = value;
318 drvdata->select_refcnt++;
319 } else
320 dev_err(drvdata->dev, "Invalid select decode data\n");
321
322 spin_unlock(&drvdata->spinlock);
323
324 return size;
325}
326static DEVICE_ATTR(set_select, 0200, NULL, tgu_set_select);
327
328static ssize_t tgu_set_timers(struct device *dev, struct device_attribute *attr,
329 const char *buf, size_t size)
330{
331 struct tgu_drvdata *drvdata = dev_get_drvdata(dev->parent);
332 unsigned long value;
333 int step;
334
335 if (drvdata->select_refcnt >= MAX_TIMER_COUNTER_SETS) {
336 dev_err(drvdata->dev, " Too many groups are being configured");
337 return -EINVAL;
338 }
339
340 if (sscanf(buf, "%d %lx", &step, &value) != 2)
341 return -EINVAL;
342
343 spin_lock(&drvdata->spinlock);
344 if (step <= drvdata->max_timer_counter) {
345 drvdata->timer_data[drvdata->timer_refcnt].timeraddr =
346 TIMER0_COMPARE_STEP(step);
347 drvdata->timer_data[drvdata->timer_refcnt].value = value;
348 drvdata->timer_refcnt++;
349 } else
350 dev_err(drvdata->dev, "Invalid TGU timer data\n");
351
352 spin_unlock(&drvdata->spinlock);
353
354 return size;
355}
356static DEVICE_ATTR(set_timer, 0200, NULL, tgu_set_timers);
357
358static ssize_t tgu_set_counters(struct device *dev, struct device_attribute
359 *attr, const char *buf, size_t size)
360{
361 struct tgu_drvdata *drvdata = dev_get_drvdata(dev->parent);
362 unsigned long value;
363 int step;
364
365 if (drvdata->counter_refcnt >= MAX_TIMER_COUNTER_SETS) {
366 dev_err(drvdata->dev, " Too many groups are being configured");
367 return -EINVAL;
368 }
369
370 if (sscanf(buf, "%d %lx", &step, &value) != 2)
371 return -EINVAL;
372
373 spin_lock(&drvdata->spinlock);
374 if (step <= drvdata->max_timer_counter) {
375 drvdata->counter_data[drvdata->counter_refcnt].counteraddr =
376 COUNTER0_COMPARE_STEP(step);
377 drvdata->counter_data[drvdata->counter_refcnt].value = value;
378 drvdata->counter_refcnt++;
379 } else
380 dev_err(drvdata->dev, "Invalid TGU counter data\n");
381
382 spin_unlock(&drvdata->spinlock);
383
384 return size;
385}
386static DEVICE_ATTR(set_counter, 0200, NULL, tgu_set_counters);
387
388static struct attribute *tgu_attrs[] = {
389 &dev_attr_enable_tgu.attr,
390 &dev_attr_reset_tgu.attr,
391 &dev_attr_set_group.attr,
392 &dev_attr_set_condition.attr,
393 &dev_attr_set_select.attr,
394 &dev_attr_set_timer.attr,
395 &dev_attr_set_counter.attr,
396 NULL,
397};
398
399static struct attribute_group tgu_attr_grp = {
400 .attrs = tgu_attrs,
401};
402
403static const struct attribute_group *tgu_attr_grps[] = {
404 &tgu_attr_grp,
405 NULL,
406};
407
408static int tgu_probe(struct amba_device *adev, const struct amba_id *id)
409{
410 int ret = 0;
411 struct device *dev = &adev->dev;
412 struct coresight_platform_data *pdata;
413 struct tgu_drvdata *drvdata;
414 struct coresight_desc *desc;
415
416 pdata = of_get_coresight_platform_data(dev, adev->dev.of_node);
417 if (IS_ERR(pdata))
418 return PTR_ERR(pdata);
419 adev->dev.platform_data = pdata;
420
421 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
422 if (!drvdata)
423 return -ENOMEM;
424
425 drvdata->dev = &adev->dev;
426
427 dev_set_drvdata(dev, drvdata);
428
429 drvdata->base = devm_ioremap_resource(dev, &adev->res);
430 if (!drvdata->base)
431 return -ENOMEM;
432
433 spin_lock_init(&drvdata->spinlock);
434
435 ret = of_property_read_u32(adev->dev.of_node, "tgu-steps",
436 &drvdata->max_steps);
437 if (ret)
438 return -EINVAL;
439
440 ret = of_property_read_u32(adev->dev.of_node, "tgu-conditions",
441 &drvdata->max_conditions);
442 if (ret)
443 return -EINVAL;
444
445 ret = of_property_read_u32(adev->dev.of_node, "tgu-regs",
446 &drvdata->max_regs);
447 if (ret)
448 return -EINVAL;
449
450 ret = of_property_read_u32(adev->dev.of_node, "tgu-timer-counters",
451 &drvdata->max_timer_counter);
452 if (ret)
453 return -EINVAL;
454
455 /* Alloc memory for Grps, Conditions and Steps */
456 drvdata->grp_data = devm_kzalloc(dev, MAX_GROUP_SETS *
457 sizeof(*drvdata->grp_data),
458 GFP_KERNEL);
459 if (!drvdata->grp_data)
460 return -ENOMEM;
461
462 drvdata->condition_data = devm_kzalloc(dev, MAX_CONDITION_SETS *
463 sizeof(*drvdata->condition_data),
464 GFP_KERNEL);
465
466 if (!drvdata->condition_data)
467 return -ENOMEM;
468
469 drvdata->select_data = devm_kzalloc(dev, MAX_CONDITION_SETS *
470 sizeof(*drvdata->select_data),
471 GFP_KERNEL);
472 if (!drvdata->select_data)
473 return -ENOMEM;
474
475 drvdata->timer_data = devm_kzalloc(dev, MAX_TIMER_COUNTER_SETS *
476 sizeof(*drvdata->timer_data),
477 GFP_KERNEL);
478 if (!drvdata->timer_data)
479 return -ENOMEM;
480
481 drvdata->counter_data = devm_kzalloc(dev, MAX_TIMER_COUNTER_SETS *
482 sizeof(*drvdata->counter_data),
483 GFP_KERNEL);
484 if (!drvdata->counter_data)
485 return -ENOMEM;
486
487 drvdata->enable = false;
488
489 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
490 if (!desc) {
491 ret = -ENOMEM;
492 goto err;
493 }
494 desc->type = CORESIGHT_DEV_TYPE_NONE;
495 desc->pdata = adev->dev.platform_data;
496 desc->dev = &adev->dev;
497 desc->groups = tgu_attr_grps;
498 drvdata->csdev = coresight_register(desc);
499 if (IS_ERR(drvdata->csdev)) {
500 ret = PTR_ERR(drvdata->csdev);
501 goto err;
502 }
503
504 pm_runtime_put(&adev->dev);
505 dev_dbg(dev, "TGU initialized\n");
506 return 0;
507err:
508 pm_runtime_put(&adev->dev);
509 return ret;
510}
511
512static struct amba_id tgu_ids[] = {
513 {
514 .id = 0x0003b999,
515 .mask = 0x0003ffff,
516 .data = "TGU",
517 },
518 { 0, 0},
519};
520
521static struct amba_driver tgu_driver = {
522 .drv = {
523 .name = "coresight-tgu",
524 .owner = THIS_MODULE,
525 .suppress_bind_attrs = true,
526 },
527 .probe = tgu_probe,
528 .id_table = tgu_ids,
529};
530
531builtin_amba_driver(tgu_driver);
532
533MODULE_LICENSE("GPL v2");
534MODULE_DESCRIPTION("CoreSight TGU driver");