2 * Intel(R) Trace Hub Global Trace Hub
4 * Copyright (C) 2014-2015 Intel Corporation.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18 #include <linux/types.h>
19 #include <linux/module.h>
20 #include <linux/device.h>
23 #include <linux/slab.h>
24 #include <linux/bitmap.h>
32 * struct gth_output - GTH view on an output port
33 * @gth: backlink to the GTH device
34 * @output: link to output device's output descriptor
35 * @index: output port number
36 * @port_type: one of GTH_* port type values
37 * @master: bitmap of masters configured for this output
40 struct gth_device
*gth
;
41 struct intel_th_output
*output
;
43 unsigned int port_type
;
44 DECLARE_BITMAP(master
, TH_CONFIGURABLE_MASTERS
+ 1);
48 * struct gth_device - GTH device
49 * @dev: driver core's device
50 * @base: register window base address
51 * @output_group: attributes describing output ports
52 * @master_group: attributes describing master assignments
53 * @output: output ports
54 * @master: master/output port assignments
55 * @gth_lock: serializes accesses to GTH bits
61 struct attribute_group output_group
;
62 struct attribute_group master_group
;
63 struct gth_output output
[TH_POSSIBLE_OUTPUTS
];
64 signed char master
[TH_CONFIGURABLE_MASTERS
+ 1];
68 static void gth_output_set(struct gth_device
*gth
, int port
,
71 unsigned long reg
= port
& 4 ? REG_GTH_GTHOPT1
: REG_GTH_GTHOPT0
;
73 int shift
= (port
& 3) * 8;
75 val
= ioread32(gth
->base
+ reg
);
76 val
&= ~(0xff << shift
);
77 val
|= config
<< shift
;
78 iowrite32(val
, gth
->base
+ reg
);
81 static unsigned int gth_output_get(struct gth_device
*gth
, int port
)
83 unsigned long reg
= port
& 4 ? REG_GTH_GTHOPT1
: REG_GTH_GTHOPT0
;
85 int shift
= (port
& 3) * 8;
87 val
= ioread32(gth
->base
+ reg
);
94 static void gth_smcfreq_set(struct gth_device
*gth
, int port
,
97 unsigned long reg
= REG_GTH_SMCR0
+ ((port
/ 2) * 4);
98 int shift
= (port
& 1) * 16;
101 val
= ioread32(gth
->base
+ reg
);
102 val
&= ~(0xffff << shift
);
103 val
|= freq
<< shift
;
104 iowrite32(val
, gth
->base
+ reg
);
107 static unsigned int gth_smcfreq_get(struct gth_device
*gth
, int port
)
109 unsigned long reg
= REG_GTH_SMCR0
+ ((port
/ 2) * 4);
110 int shift
= (port
& 1) * 16;
113 val
= ioread32(gth
->base
+ reg
);
114 val
&= 0xffff << shift
;
121 * "masters" attribute group
124 struct master_attribute
{
125 struct device_attribute attr
;
126 struct gth_device
*gth
;
131 gth_master_set(struct gth_device
*gth
, unsigned int master
, int port
)
133 unsigned int reg
= REG_GTH_SWDEST0
+ ((master
>> 1) & ~3u);
134 unsigned int shift
= (master
& 0x7) * 4;
138 reg
= REG_GTH_GSWTDEST
;
142 val
= ioread32(gth
->base
+ reg
);
143 val
&= ~(0xf << shift
);
145 val
|= (0x8 | port
) << shift
;
146 iowrite32(val
, gth
->base
+ reg
);
149 /*static int gth_master_get(struct gth_device *gth, unsigned int master)
151 unsigned int reg = REG_GTH_SWDEST0 + ((master >> 1) & ~3u);
152 unsigned int shift = (master & 0x7) * 4;
156 reg = REG_GTH_GSWTDEST;
160 val = ioread32(gth->base + reg);
161 val &= (0xf << shift);
164 return val ? val & 0x7 : -1;
167 static ssize_t
master_attr_show(struct device
*dev
,
168 struct device_attribute
*attr
,
171 struct master_attribute
*ma
=
172 container_of(attr
, struct master_attribute
, attr
);
173 struct gth_device
*gth
= ma
->gth
;
177 spin_lock(>h
->gth_lock
);
178 port
= gth
->master
[ma
->master
];
179 spin_unlock(>h
->gth_lock
);
182 count
= snprintf(buf
, PAGE_SIZE
, "%x\n", port
);
184 count
= snprintf(buf
, PAGE_SIZE
, "disabled\n");
189 static ssize_t
master_attr_store(struct device
*dev
,
190 struct device_attribute
*attr
,
191 const char *buf
, size_t count
)
193 struct master_attribute
*ma
=
194 container_of(attr
, struct master_attribute
, attr
);
195 struct gth_device
*gth
= ma
->gth
;
198 if (kstrtoint(buf
, 10, &port
) < 0)
201 if (port
>= TH_POSSIBLE_OUTPUTS
|| port
< -1)
204 spin_lock(>h
->gth_lock
);
206 /* disconnect from the previous output port, if any */
207 old_port
= gth
->master
[ma
->master
];
209 gth
->master
[ma
->master
] = -1;
210 clear_bit(ma
->master
, gth
->output
[old_port
].master
);
211 if (gth
->output
[old_port
].output
->active
)
212 gth_master_set(gth
, ma
->master
, -1);
215 /* connect to the new output port, if any */
217 /* check if there's a driver for this port */
218 if (!gth
->output
[port
].output
) {
223 set_bit(ma
->master
, gth
->output
[port
].master
);
225 /* if the port is active, program this setting */
226 if (gth
->output
[port
].output
->active
)
227 gth_master_set(gth
, ma
->master
, port
);
230 gth
->master
[ma
->master
] = port
;
233 spin_unlock(>h
->gth_lock
);
238 struct output_attribute
{
239 struct device_attribute attr
;
240 struct gth_device
*gth
;
245 #define OUTPUT_PARM(_name, _mask, _r, _w, _what) \
246 [TH_OUTPUT_PARM(_name)] = { .name = __stringify(_name), \
247 .get = gth_ ## _what ## _get, \
248 .set = gth_ ## _what ## _set, \
253 static const struct output_parm
{
255 unsigned int (*get
)(struct gth_device
*gth
, int port
);
256 void (*set
)(struct gth_device
*gth
, int port
,
259 unsigned int readable
: 1,
262 OUTPUT_PARM(port
, 0x7, 1, 0, output
),
263 OUTPUT_PARM(null
, BIT(3), 1, 1, output
),
264 OUTPUT_PARM(drop
, BIT(4), 1, 1, output
),
265 OUTPUT_PARM(reset
, BIT(5), 1, 0, output
),
266 OUTPUT_PARM(flush
, BIT(7), 0, 1, output
),
267 OUTPUT_PARM(smcfreq
, 0xffff, 1, 1, smcfreq
),
271 gth_output_parm_set(struct gth_device
*gth
, int port
, unsigned int parm
,
274 unsigned int config
= output_parms
[parm
].get(gth
, port
);
275 unsigned int mask
= output_parms
[parm
].mask
;
276 unsigned int shift
= __ffs(mask
);
279 config
|= (val
<< shift
) & mask
;
280 output_parms
[parm
].set(gth
, port
, config
);
284 gth_output_parm_get(struct gth_device
*gth
, int port
, unsigned int parm
)
286 unsigned int config
= output_parms
[parm
].get(gth
, port
);
287 unsigned int mask
= output_parms
[parm
].mask
;
288 unsigned int shift
= __ffs(mask
);
296 * Reset outputs and sources
298 static int intel_th_gth_reset(struct gth_device
*gth
)
303 scratchpad
= ioread32(gth
->base
+ REG_GTH_SCRPD0
);
304 if (scratchpad
& SCRPD_DEBUGGER_IN_USE
)
308 for (port
= 0; port
< 8; port
++) {
309 if (gth_output_parm_get(gth
, port
, TH_OUTPUT_PARM(port
)) ==
313 gth_output_set(gth
, port
, 0);
314 gth_smcfreq_set(gth
, port
, 16);
316 /* disable overrides */
317 iowrite32(0, gth
->base
+ REG_GTH_DESTOVR
);
319 /* masters swdest_0~31 and gswdest */
320 for (i
= 0; i
< 33; i
++)
321 iowrite32(0, gth
->base
+ REG_GTH_SWDEST0
+ i
* 4);
324 iowrite32(0, gth
->base
+ REG_GTH_SCR
);
325 iowrite32(0xfc, gth
->base
+ REG_GTH_SCR2
);
331 * "outputs" attribute group
334 static ssize_t
output_attr_show(struct device
*dev
,
335 struct device_attribute
*attr
,
338 struct output_attribute
*oa
=
339 container_of(attr
, struct output_attribute
, attr
);
340 struct gth_device
*gth
= oa
->gth
;
343 spin_lock(>h
->gth_lock
);
344 count
= snprintf(buf
, PAGE_SIZE
, "%x\n",
345 gth_output_parm_get(gth
, oa
->port
, oa
->parm
));
346 spin_unlock(>h
->gth_lock
);
351 static ssize_t
output_attr_store(struct device
*dev
,
352 struct device_attribute
*attr
,
353 const char *buf
, size_t count
)
355 struct output_attribute
*oa
=
356 container_of(attr
, struct output_attribute
, attr
);
357 struct gth_device
*gth
= oa
->gth
;
360 if (kstrtouint(buf
, 16, &config
) < 0)
363 spin_lock(>h
->gth_lock
);
364 gth_output_parm_set(gth
, oa
->port
, oa
->parm
, config
);
365 spin_unlock(>h
->gth_lock
);
370 static int intel_th_master_attributes(struct gth_device
*gth
)
372 struct master_attribute
*master_attrs
;
373 struct attribute
**attrs
;
374 int i
, nattrs
= TH_CONFIGURABLE_MASTERS
+ 2;
376 attrs
= devm_kcalloc(gth
->dev
, nattrs
, sizeof(void *), GFP_KERNEL
);
380 master_attrs
= devm_kcalloc(gth
->dev
, nattrs
,
381 sizeof(struct master_attribute
),
386 for (i
= 0; i
< TH_CONFIGURABLE_MASTERS
+ 1; i
++) {
389 name
= devm_kasprintf(gth
->dev
, GFP_KERNEL
, "%d%s", i
,
390 i
== TH_CONFIGURABLE_MASTERS
? "+" : "");
394 master_attrs
[i
].attr
.attr
.name
= name
;
395 master_attrs
[i
].attr
.attr
.mode
= S_IRUGO
| S_IWUSR
;
396 master_attrs
[i
].attr
.show
= master_attr_show
;
397 master_attrs
[i
].attr
.store
= master_attr_store
;
399 sysfs_attr_init(&master_attrs
[i
].attr
.attr
);
400 attrs
[i
] = &master_attrs
[i
].attr
.attr
;
402 master_attrs
[i
].gth
= gth
;
403 master_attrs
[i
].master
= i
;
406 gth
->master_group
.name
= "masters";
407 gth
->master_group
.attrs
= attrs
;
409 return sysfs_create_group(>h
->dev
->kobj
, >h
->master_group
);
412 static int intel_th_output_attributes(struct gth_device
*gth
)
414 struct output_attribute
*out_attrs
;
415 struct attribute
**attrs
;
416 int i
, j
, nouts
= TH_POSSIBLE_OUTPUTS
;
417 int nparms
= ARRAY_SIZE(output_parms
);
418 int nattrs
= nouts
* nparms
+ 1;
420 attrs
= devm_kcalloc(gth
->dev
, nattrs
, sizeof(void *), GFP_KERNEL
);
424 out_attrs
= devm_kcalloc(gth
->dev
, nattrs
,
425 sizeof(struct output_attribute
),
430 for (i
= 0; i
< nouts
; i
++) {
431 for (j
= 0; j
< nparms
; j
++) {
432 unsigned int idx
= i
* nparms
+ j
;
435 name
= devm_kasprintf(gth
->dev
, GFP_KERNEL
, "%d_%s", i
,
436 output_parms
[j
].name
);
440 out_attrs
[idx
].attr
.attr
.name
= name
;
442 if (output_parms
[j
].readable
) {
443 out_attrs
[idx
].attr
.attr
.mode
|= S_IRUGO
;
444 out_attrs
[idx
].attr
.show
= output_attr_show
;
447 if (output_parms
[j
].writable
) {
448 out_attrs
[idx
].attr
.attr
.mode
|= S_IWUSR
;
449 out_attrs
[idx
].attr
.store
= output_attr_store
;
452 sysfs_attr_init(&out_attrs
[idx
].attr
.attr
);
453 attrs
[idx
] = &out_attrs
[idx
].attr
.attr
;
455 out_attrs
[idx
].gth
= gth
;
456 out_attrs
[idx
].port
= i
;
457 out_attrs
[idx
].parm
= j
;
461 gth
->output_group
.name
= "outputs";
462 gth
->output_group
.attrs
= attrs
;
464 return sysfs_create_group(>h
->dev
->kobj
, >h
->output_group
);
468 * intel_th_gth_disable() - enable tracing to an output device
470 * @output: output device's descriptor
472 * This will deconfigure all masters set to output to this device,
473 * disable tracing using force storeEn off signal and wait for the
474 * "pipeline empty" bit for corresponding output port.
476 static void intel_th_gth_disable(struct intel_th_device
*thdev
,
477 struct intel_th_output
*output
)
479 struct gth_device
*gth
= dev_get_drvdata(&thdev
->dev
);
484 spin_lock(>h
->gth_lock
);
485 output
->active
= false;
487 for_each_set_bit(master
, gth
->output
[output
->port
].master
,
488 TH_CONFIGURABLE_MASTERS
) {
489 gth_master_set(gth
, master
, -1);
491 spin_unlock(>h
->gth_lock
);
493 iowrite32(0, gth
->base
+ REG_GTH_SCR
);
494 iowrite32(0xfd, gth
->base
+ REG_GTH_SCR2
);
496 /* wait on pipeline empty for the given port */
497 for (reg
= 0, count
= GTH_PLE_WAITLOOP_DEPTH
;
498 count
&& !(reg
& BIT(output
->port
)); count
--) {
499 reg
= ioread32(gth
->base
+ REG_GTH_STAT
);
503 /* clear force capture done for next captures */
504 iowrite32(0xfc, gth
->base
+ REG_GTH_SCR2
);
507 dev_dbg(&thdev
->dev
, "timeout waiting for GTH[%d] PLE\n",
512 * intel_th_gth_enable() - enable tracing to an output device
514 * @output: output device's descriptor
516 * This will configure all masters set to output to this device and
517 * enable tracing using force storeEn signal.
519 static void intel_th_gth_enable(struct intel_th_device
*thdev
,
520 struct intel_th_output
*output
)
522 struct gth_device
*gth
= dev_get_drvdata(&thdev
->dev
);
526 spin_lock(>h
->gth_lock
);
527 for_each_set_bit(master
, gth
->output
[output
->port
].master
,
528 TH_CONFIGURABLE_MASTERS
+ 1) {
529 gth_master_set(gth
, master
, output
->port
);
532 if (output
->multiblock
)
535 output
->active
= true;
536 spin_unlock(>h
->gth_lock
);
538 iowrite32(scr
, gth
->base
+ REG_GTH_SCR
);
539 iowrite32(0, gth
->base
+ REG_GTH_SCR2
);
543 * intel_th_gth_assign() - assign output device to a GTH output port
545 * @othdev: output device
547 * This will match a given output device parameters against present
548 * output ports on the GTH and fill out relevant bits in output device's
551 * Return: 0 on success, -errno on error.
553 static int intel_th_gth_assign(struct intel_th_device
*thdev
,
554 struct intel_th_device
*othdev
)
556 struct gth_device
*gth
= dev_get_drvdata(&thdev
->dev
);
559 if (othdev
->type
!= INTEL_TH_OUTPUT
)
562 for (i
= 0, id
= 0; i
< TH_POSSIBLE_OUTPUTS
; i
++) {
563 if (gth
->output
[i
].port_type
!= othdev
->output
.type
)
566 if (othdev
->id
== -1 || othdev
->id
== id
)
575 spin_lock(>h
->gth_lock
);
576 othdev
->output
.port
= i
;
577 othdev
->output
.active
= false;
578 gth
->output
[i
].output
= &othdev
->output
;
579 spin_unlock(>h
->gth_lock
);
585 * intel_th_gth_unassign() - deassociate an output device from its output port
587 * @othdev: output device
589 static void intel_th_gth_unassign(struct intel_th_device
*thdev
,
590 struct intel_th_device
*othdev
)
592 struct gth_device
*gth
= dev_get_drvdata(&thdev
->dev
);
593 int port
= othdev
->output
.port
;
595 spin_lock(>h
->gth_lock
);
596 othdev
->output
.port
= -1;
597 othdev
->output
.active
= false;
598 gth
->output
[port
].output
= NULL
;
599 spin_unlock(>h
->gth_lock
);
603 intel_th_gth_set_output(struct intel_th_device
*thdev
, unsigned int master
)
605 struct gth_device
*gth
= dev_get_drvdata(&thdev
->dev
);
606 int port
= 0; /* FIXME: make default output configurable */
609 * everything above TH_CONFIGURABLE_MASTERS is controlled by the
612 if (master
> TH_CONFIGURABLE_MASTERS
)
613 master
= TH_CONFIGURABLE_MASTERS
;
615 spin_lock(>h
->gth_lock
);
616 if (gth
->master
[master
] == -1) {
617 set_bit(master
, gth
->output
[port
].master
);
618 gth
->master
[master
] = port
;
620 spin_unlock(>h
->gth_lock
);
625 static int intel_th_gth_probe(struct intel_th_device
*thdev
)
627 struct device
*dev
= &thdev
->dev
;
628 struct gth_device
*gth
;
629 struct resource
*res
;
633 res
= intel_th_device_get_resource(thdev
, IORESOURCE_MEM
, 0);
637 base
= devm_ioremap(dev
, res
->start
, resource_size(res
));
641 gth
= devm_kzalloc(dev
, sizeof(*gth
), GFP_KERNEL
);
647 spin_lock_init(>h
->gth_lock
);
649 ret
= intel_th_gth_reset(gth
);
653 for (i
= 0; i
< TH_CONFIGURABLE_MASTERS
+ 1; i
++)
656 for (i
= 0; i
< TH_POSSIBLE_OUTPUTS
; i
++) {
657 gth
->output
[i
].gth
= gth
;
658 gth
->output
[i
].index
= i
;
659 gth
->output
[i
].port_type
=
660 gth_output_parm_get(gth
, i
, TH_OUTPUT_PARM(port
));
663 if (intel_th_output_attributes(gth
) ||
664 intel_th_master_attributes(gth
)) {
665 pr_warn("Can't initialize sysfs attributes\n");
667 if (gth
->output_group
.attrs
)
668 sysfs_remove_group(>h
->dev
->kobj
, >h
->output_group
);
672 dev_set_drvdata(dev
, gth
);
677 static void intel_th_gth_remove(struct intel_th_device
*thdev
)
679 struct gth_device
*gth
= dev_get_drvdata(&thdev
->dev
);
681 sysfs_remove_group(>h
->dev
->kobj
, >h
->output_group
);
682 sysfs_remove_group(>h
->dev
->kobj
, >h
->master_group
);
685 static struct intel_th_driver intel_th_gth_driver
= {
686 .probe
= intel_th_gth_probe
,
687 .remove
= intel_th_gth_remove
,
688 .assign
= intel_th_gth_assign
,
689 .unassign
= intel_th_gth_unassign
,
690 .set_output
= intel_th_gth_set_output
,
691 .enable
= intel_th_gth_enable
,
692 .disable
= intel_th_gth_disable
,
695 .owner
= THIS_MODULE
,
699 module_driver(intel_th_gth_driver
,
700 intel_th_driver_register
,
701 intel_th_driver_unregister
);
703 MODULE_ALIAS("intel_th_switch");
704 MODULE_LICENSE("GPL v2");
705 MODULE_DESCRIPTION("Intel(R) Trace Hub Global Trace Hub driver");
706 MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");