]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/hwtracing/intel_th/gth.c
Merge branch 'for-4.8/core' of git://git.kernel.dk/linux-block
[karo-tx-linux.git] / drivers / hwtracing / intel_th / gth.c
1 /*
2  * Intel(R) Trace Hub Global Trace Hub
3  *
4  * Copyright (C) 2014-2015 Intel Corporation.
5  *
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.
9  *
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
13  * more details.
14  */
15
16 #define pr_fmt(fmt)     KBUILD_MODNAME ": " fmt
17
18 #include <linux/types.h>
19 #include <linux/module.h>
20 #include <linux/device.h>
21 #include <linux/io.h>
22 #include <linux/mm.h>
23 #include <linux/slab.h>
24 #include <linux/bitmap.h>
25 #include <linux/pm_runtime.h>
26
27 #include "intel_th.h"
28 #include "gth.h"
29
30 struct gth_device;
31
32 /**
33  * struct gth_output - GTH view on an output port
34  * @gth:        backlink to the GTH device
35  * @output:     link to output device's output descriptor
36  * @index:      output port number
37  * @port_type:  one of GTH_* port type values
38  * @master:     bitmap of masters configured for this output
39  */
40 struct gth_output {
41         struct gth_device       *gth;
42         struct intel_th_output  *output;
43         unsigned int            index;
44         unsigned int            port_type;
45         DECLARE_BITMAP(master, TH_CONFIGURABLE_MASTERS + 1);
46 };
47
48 /**
49  * struct gth_device - GTH device
50  * @dev:        driver core's device
51  * @base:       register window base address
52  * @output_group:       attributes describing output ports
53  * @master_group:       attributes describing master assignments
54  * @output:             output ports
55  * @master:             master/output port assignments
56  * @gth_lock:           serializes accesses to GTH bits
57  */
58 struct gth_device {
59         struct device           *dev;
60         void __iomem            *base;
61
62         struct attribute_group  output_group;
63         struct attribute_group  master_group;
64         struct gth_output       output[TH_POSSIBLE_OUTPUTS];
65         signed char             master[TH_CONFIGURABLE_MASTERS + 1];
66         spinlock_t              gth_lock;
67 };
68
69 static void gth_output_set(struct gth_device *gth, int port,
70                            unsigned int config)
71 {
72         unsigned long reg = port & 4 ? REG_GTH_GTHOPT1 : REG_GTH_GTHOPT0;
73         u32 val;
74         int shift = (port & 3) * 8;
75
76         val = ioread32(gth->base + reg);
77         val &= ~(0xff << shift);
78         val |= config << shift;
79         iowrite32(val, gth->base + reg);
80 }
81
82 static unsigned int gth_output_get(struct gth_device *gth, int port)
83 {
84         unsigned long reg = port & 4 ? REG_GTH_GTHOPT1 : REG_GTH_GTHOPT0;
85         u32 val;
86         int shift = (port & 3) * 8;
87
88         val = ioread32(gth->base + reg);
89         val &= 0xff << shift;
90         val >>= shift;
91
92         return val;
93 }
94
95 static void gth_smcfreq_set(struct gth_device *gth, int port,
96                             unsigned int freq)
97 {
98         unsigned long reg = REG_GTH_SMCR0 + ((port / 2) * 4);
99         int shift = (port & 1) * 16;
100         u32 val;
101
102         val = ioread32(gth->base + reg);
103         val &= ~(0xffff << shift);
104         val |= freq << shift;
105         iowrite32(val, gth->base + reg);
106 }
107
108 static unsigned int gth_smcfreq_get(struct gth_device *gth, int port)
109 {
110         unsigned long reg = REG_GTH_SMCR0 + ((port / 2) * 4);
111         int shift = (port & 1) * 16;
112         u32 val;
113
114         val = ioread32(gth->base + reg);
115         val &= 0xffff << shift;
116         val >>= shift;
117
118         return val;
119 }
120
121 /*
122  * "masters" attribute group
123  */
124
125 struct master_attribute {
126         struct device_attribute attr;
127         struct gth_device       *gth;
128         unsigned int            master;
129 };
130
131 static void
132 gth_master_set(struct gth_device *gth, unsigned int master, int port)
133 {
134         unsigned int reg = REG_GTH_SWDEST0 + ((master >> 1) & ~3u);
135         unsigned int shift = (master & 0x7) * 4;
136         u32 val;
137
138         if (master >= 256) {
139                 reg = REG_GTH_GSWTDEST;
140                 shift = 0;
141         }
142
143         val = ioread32(gth->base + reg);
144         val &= ~(0xf << shift);
145         if (port >= 0)
146                 val |= (0x8 | port) << shift;
147         iowrite32(val, gth->base + reg);
148 }
149
150 static ssize_t master_attr_show(struct device *dev,
151                                 struct device_attribute *attr,
152                                 char *buf)
153 {
154         struct master_attribute *ma =
155                 container_of(attr, struct master_attribute, attr);
156         struct gth_device *gth = ma->gth;
157         size_t count;
158         int port;
159
160         spin_lock(&gth->gth_lock);
161         port = gth->master[ma->master];
162         spin_unlock(&gth->gth_lock);
163
164         if (port >= 0)
165                 count = snprintf(buf, PAGE_SIZE, "%x\n", port);
166         else
167                 count = snprintf(buf, PAGE_SIZE, "disabled\n");
168
169         return count;
170 }
171
172 static ssize_t master_attr_store(struct device *dev,
173                                  struct device_attribute *attr,
174                                  const char *buf, size_t count)
175 {
176         struct master_attribute *ma =
177                 container_of(attr, struct master_attribute, attr);
178         struct gth_device *gth = ma->gth;
179         int old_port, port;
180
181         if (kstrtoint(buf, 10, &port) < 0)
182                 return -EINVAL;
183
184         if (port >= TH_POSSIBLE_OUTPUTS || port < -1)
185                 return -EINVAL;
186
187         spin_lock(&gth->gth_lock);
188
189         /* disconnect from the previous output port, if any */
190         old_port = gth->master[ma->master];
191         if (old_port >= 0) {
192                 gth->master[ma->master] = -1;
193                 clear_bit(ma->master, gth->output[old_port].master);
194
195                 /*
196                  * if the port is active, program this setting,
197                  * implies that runtime PM is on
198                  */
199                 if (gth->output[old_port].output->active)
200                         gth_master_set(gth, ma->master, -1);
201         }
202
203         /* connect to the new output port, if any */
204         if (port >= 0) {
205                 /* check if there's a driver for this port */
206                 if (!gth->output[port].output) {
207                         count = -ENODEV;
208                         goto unlock;
209                 }
210
211                 set_bit(ma->master, gth->output[port].master);
212
213                 /* if the port is active, program this setting, see above */
214                 if (gth->output[port].output->active)
215                         gth_master_set(gth, ma->master, port);
216         }
217
218         gth->master[ma->master] = port;
219
220 unlock:
221         spin_unlock(&gth->gth_lock);
222
223         return count;
224 }
225
226 struct output_attribute {
227         struct device_attribute attr;
228         struct gth_device       *gth;
229         unsigned int            port;
230         unsigned int            parm;
231 };
232
233 #define OUTPUT_PARM(_name, _mask, _r, _w, _what)                        \
234         [TH_OUTPUT_PARM(_name)] = { .name = __stringify(_name),         \
235                                     .get = gth_ ## _what ## _get,       \
236                                     .set = gth_ ## _what ## _set,       \
237                                     .mask = (_mask),                    \
238                                     .readable = (_r),                   \
239                                     .writable = (_w) }
240
241 static const struct output_parm {
242         const char      *name;
243         unsigned int    (*get)(struct gth_device *gth, int port);
244         void            (*set)(struct gth_device *gth, int port,
245                                unsigned int val);
246         unsigned int    mask;
247         unsigned int    readable : 1,
248                         writable : 1;
249 } output_parms[] = {
250         OUTPUT_PARM(port,       0x7,    1, 0, output),
251         OUTPUT_PARM(null,       BIT(3), 1, 1, output),
252         OUTPUT_PARM(drop,       BIT(4), 1, 1, output),
253         OUTPUT_PARM(reset,      BIT(5), 1, 0, output),
254         OUTPUT_PARM(flush,      BIT(7), 0, 1, output),
255         OUTPUT_PARM(smcfreq,    0xffff, 1, 1, smcfreq),
256 };
257
258 static void
259 gth_output_parm_set(struct gth_device *gth, int port, unsigned int parm,
260                     unsigned int val)
261 {
262         unsigned int config = output_parms[parm].get(gth, port);
263         unsigned int mask = output_parms[parm].mask;
264         unsigned int shift = __ffs(mask);
265
266         config &= ~mask;
267         config |= (val << shift) & mask;
268         output_parms[parm].set(gth, port, config);
269 }
270
271 static unsigned int
272 gth_output_parm_get(struct gth_device *gth, int port, unsigned int parm)
273 {
274         unsigned int config = output_parms[parm].get(gth, port);
275         unsigned int mask = output_parms[parm].mask;
276         unsigned int shift = __ffs(mask);
277
278         config &= mask;
279         config >>= shift;
280         return config;
281 }
282
283 /*
284  * Reset outputs and sources
285  */
286 static int intel_th_gth_reset(struct gth_device *gth)
287 {
288         u32 scratchpad;
289         int port, i;
290
291         scratchpad = ioread32(gth->base + REG_GTH_SCRPD0);
292         if (scratchpad & SCRPD_DEBUGGER_IN_USE)
293                 return -EBUSY;
294
295         /* Always save/restore STH and TU registers in S0ix entry/exit */
296         scratchpad |= SCRPD_STH_IS_ENABLED | SCRPD_TRIGGER_IS_ENABLED;
297         iowrite32(scratchpad, gth->base + REG_GTH_SCRPD0);
298
299         /* output ports */
300         for (port = 0; port < 8; port++) {
301                 if (gth_output_parm_get(gth, port, TH_OUTPUT_PARM(port)) ==
302                     GTH_NONE)
303                         continue;
304
305                 gth_output_set(gth, port, 0);
306                 gth_smcfreq_set(gth, port, 16);
307         }
308         /* disable overrides */
309         iowrite32(0, gth->base + REG_GTH_DESTOVR);
310
311         /* masters swdest_0~31 and gswdest */
312         for (i = 0; i < 33; i++)
313                 iowrite32(0, gth->base + REG_GTH_SWDEST0 + i * 4);
314
315         /* sources */
316         iowrite32(0, gth->base + REG_GTH_SCR);
317         iowrite32(0xfc, gth->base + REG_GTH_SCR2);
318
319         return 0;
320 }
321
322 /*
323  * "outputs" attribute group
324  */
325
326 static ssize_t output_attr_show(struct device *dev,
327                                 struct device_attribute *attr,
328                                 char *buf)
329 {
330         struct output_attribute *oa =
331                 container_of(attr, struct output_attribute, attr);
332         struct gth_device *gth = oa->gth;
333         size_t count;
334
335         pm_runtime_get_sync(dev);
336
337         spin_lock(&gth->gth_lock);
338         count = snprintf(buf, PAGE_SIZE, "%x\n",
339                          gth_output_parm_get(gth, oa->port, oa->parm));
340         spin_unlock(&gth->gth_lock);
341
342         pm_runtime_put(dev);
343
344         return count;
345 }
346
347 static ssize_t output_attr_store(struct device *dev,
348                                  struct device_attribute *attr,
349                                  const char *buf, size_t count)
350 {
351         struct output_attribute *oa =
352                 container_of(attr, struct output_attribute, attr);
353         struct gth_device *gth = oa->gth;
354         unsigned int config;
355
356         if (kstrtouint(buf, 16, &config) < 0)
357                 return -EINVAL;
358
359         pm_runtime_get_sync(dev);
360
361         spin_lock(&gth->gth_lock);
362         gth_output_parm_set(gth, oa->port, oa->parm, config);
363         spin_unlock(&gth->gth_lock);
364
365         pm_runtime_put(dev);
366
367         return count;
368 }
369
370 static int intel_th_master_attributes(struct gth_device *gth)
371 {
372         struct master_attribute *master_attrs;
373         struct attribute **attrs;
374         int i, nattrs = TH_CONFIGURABLE_MASTERS + 2;
375
376         attrs = devm_kcalloc(gth->dev, nattrs, sizeof(void *), GFP_KERNEL);
377         if (!attrs)
378                 return -ENOMEM;
379
380         master_attrs = devm_kcalloc(gth->dev, nattrs,
381                                     sizeof(struct master_attribute),
382                                     GFP_KERNEL);
383         if (!master_attrs)
384                 return -ENOMEM;
385
386         for (i = 0; i < TH_CONFIGURABLE_MASTERS + 1; i++) {
387                 char *name;
388
389                 name = devm_kasprintf(gth->dev, GFP_KERNEL, "%d%s", i,
390                                       i == TH_CONFIGURABLE_MASTERS ? "+" : "");
391                 if (!name)
392                         return -ENOMEM;
393
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;
398
399                 sysfs_attr_init(&master_attrs[i].attr.attr);
400                 attrs[i] = &master_attrs[i].attr.attr;
401
402                 master_attrs[i].gth = gth;
403                 master_attrs[i].master = i;
404         }
405
406         gth->master_group.name  = "masters";
407         gth->master_group.attrs = attrs;
408
409         return sysfs_create_group(&gth->dev->kobj, &gth->master_group);
410 }
411
412 static int intel_th_output_attributes(struct gth_device *gth)
413 {
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;
419
420         attrs = devm_kcalloc(gth->dev, nattrs, sizeof(void *), GFP_KERNEL);
421         if (!attrs)
422                 return -ENOMEM;
423
424         out_attrs = devm_kcalloc(gth->dev, nattrs,
425                                  sizeof(struct output_attribute),
426                                  GFP_KERNEL);
427         if (!out_attrs)
428                 return -ENOMEM;
429
430         for (i = 0; i < nouts; i++) {
431                 for (j = 0; j < nparms; j++) {
432                         unsigned int idx = i * nparms + j;
433                         char *name;
434
435                         name = devm_kasprintf(gth->dev, GFP_KERNEL, "%d_%s", i,
436                                               output_parms[j].name);
437                         if (!name)
438                                 return -ENOMEM;
439
440                         out_attrs[idx].attr.attr.name = name;
441
442                         if (output_parms[j].readable) {
443                                 out_attrs[idx].attr.attr.mode |= S_IRUGO;
444                                 out_attrs[idx].attr.show = output_attr_show;
445                         }
446
447                         if (output_parms[j].writable) {
448                                 out_attrs[idx].attr.attr.mode |= S_IWUSR;
449                                 out_attrs[idx].attr.store = output_attr_store;
450                         }
451
452                         sysfs_attr_init(&out_attrs[idx].attr.attr);
453                         attrs[idx] = &out_attrs[idx].attr.attr;
454
455                         out_attrs[idx].gth = gth;
456                         out_attrs[idx].port = i;
457                         out_attrs[idx].parm = j;
458                 }
459         }
460
461         gth->output_group.name  = "outputs";
462         gth->output_group.attrs = attrs;
463
464         return sysfs_create_group(&gth->dev->kobj, &gth->output_group);
465 }
466
467 /**
468  * intel_th_gth_disable() - disable tracing to an output device
469  * @thdev:      GTH device
470  * @output:     output device's descriptor
471  *
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.
475  */
476 static void intel_th_gth_disable(struct intel_th_device *thdev,
477                                  struct intel_th_output *output)
478 {
479         struct gth_device *gth = dev_get_drvdata(&thdev->dev);
480         unsigned long count;
481         int master;
482         u32 reg;
483
484         spin_lock(&gth->gth_lock);
485         output->active = false;
486
487         for_each_set_bit(master, gth->output[output->port].master,
488                          TH_CONFIGURABLE_MASTERS) {
489                 gth_master_set(gth, master, -1);
490         }
491         spin_unlock(&gth->gth_lock);
492
493         iowrite32(0, gth->base + REG_GTH_SCR);
494         iowrite32(0xfd, gth->base + REG_GTH_SCR2);
495
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);
500                 cpu_relax();
501         }
502
503         /* clear force capture done for next captures */
504         iowrite32(0xfc, gth->base + REG_GTH_SCR2);
505
506         if (!count)
507                 dev_dbg(&thdev->dev, "timeout waiting for GTH[%d] PLE\n",
508                         output->port);
509
510         reg = ioread32(gth->base + REG_GTH_SCRPD0);
511         reg &= ~output->scratchpad;
512         iowrite32(reg, gth->base + REG_GTH_SCRPD0);
513 }
514
515 /**
516  * intel_th_gth_enable() - enable tracing to an output device
517  * @thdev:      GTH device
518  * @output:     output device's descriptor
519  *
520  * This will configure all masters set to output to this device and
521  * enable tracing using force storeEn signal.
522  */
523 static void intel_th_gth_enable(struct intel_th_device *thdev,
524                                 struct intel_th_output *output)
525 {
526         struct gth_device *gth = dev_get_drvdata(&thdev->dev);
527         u32 scr = 0xfc0000, scrpd;
528         int master;
529
530         spin_lock(&gth->gth_lock);
531         for_each_set_bit(master, gth->output[output->port].master,
532                          TH_CONFIGURABLE_MASTERS + 1) {
533                 gth_master_set(gth, master, output->port);
534         }
535
536         if (output->multiblock)
537                 scr |= 0xff;
538
539         output->active = true;
540         spin_unlock(&gth->gth_lock);
541
542         scrpd = ioread32(gth->base + REG_GTH_SCRPD0);
543         scrpd |= output->scratchpad;
544         iowrite32(scrpd, gth->base + REG_GTH_SCRPD0);
545
546         iowrite32(scr, gth->base + REG_GTH_SCR);
547         iowrite32(0, gth->base + REG_GTH_SCR2);
548 }
549
550 /**
551  * intel_th_gth_assign() - assign output device to a GTH output port
552  * @thdev:      GTH device
553  * @othdev:     output device
554  *
555  * This will match a given output device parameters against present
556  * output ports on the GTH and fill out relevant bits in output device's
557  * descriptor.
558  *
559  * Return:      0 on success, -errno on error.
560  */
561 static int intel_th_gth_assign(struct intel_th_device *thdev,
562                                struct intel_th_device *othdev)
563 {
564         struct gth_device *gth = dev_get_drvdata(&thdev->dev);
565         int i, id;
566
567         if (othdev->type != INTEL_TH_OUTPUT)
568                 return -EINVAL;
569
570         for (i = 0, id = 0; i < TH_POSSIBLE_OUTPUTS; i++) {
571                 if (gth->output[i].port_type != othdev->output.type)
572                         continue;
573
574                 if (othdev->id == -1 || othdev->id == id)
575                         goto found;
576
577                 id++;
578         }
579
580         return -ENOENT;
581
582 found:
583         spin_lock(&gth->gth_lock);
584         othdev->output.port = i;
585         othdev->output.active = false;
586         gth->output[i].output = &othdev->output;
587         spin_unlock(&gth->gth_lock);
588
589         return 0;
590 }
591
592 /**
593  * intel_th_gth_unassign() - deassociate an output device from its output port
594  * @thdev:      GTH device
595  * @othdev:     output device
596  */
597 static void intel_th_gth_unassign(struct intel_th_device *thdev,
598                                   struct intel_th_device *othdev)
599 {
600         struct gth_device *gth = dev_get_drvdata(&thdev->dev);
601         int port = othdev->output.port;
602
603         spin_lock(&gth->gth_lock);
604         othdev->output.port = -1;
605         othdev->output.active = false;
606         gth->output[port].output = NULL;
607         spin_unlock(&gth->gth_lock);
608 }
609
610 static int
611 intel_th_gth_set_output(struct intel_th_device *thdev, unsigned int master)
612 {
613         struct gth_device *gth = dev_get_drvdata(&thdev->dev);
614         int port = 0; /* FIXME: make default output configurable */
615
616         /*
617          * everything above TH_CONFIGURABLE_MASTERS is controlled by the
618          * same register
619          */
620         if (master > TH_CONFIGURABLE_MASTERS)
621                 master = TH_CONFIGURABLE_MASTERS;
622
623         spin_lock(&gth->gth_lock);
624         if (gth->master[master] == -1) {
625                 set_bit(master, gth->output[port].master);
626                 gth->master[master] = port;
627         }
628         spin_unlock(&gth->gth_lock);
629
630         return 0;
631 }
632
633 static int intel_th_gth_probe(struct intel_th_device *thdev)
634 {
635         struct device *dev = &thdev->dev;
636         struct gth_device *gth;
637         struct resource *res;
638         void __iomem *base;
639         int i, ret;
640
641         res = intel_th_device_get_resource(thdev, IORESOURCE_MEM, 0);
642         if (!res)
643                 return -ENODEV;
644
645         base = devm_ioremap(dev, res->start, resource_size(res));
646         if (!base)
647                 return -ENOMEM;
648
649         gth = devm_kzalloc(dev, sizeof(*gth), GFP_KERNEL);
650         if (!gth)
651                 return -ENOMEM;
652
653         gth->dev = dev;
654         gth->base = base;
655         spin_lock_init(&gth->gth_lock);
656
657         ret = intel_th_gth_reset(gth);
658         if (ret)
659                 return ret;
660
661         for (i = 0; i < TH_CONFIGURABLE_MASTERS + 1; i++)
662                 gth->master[i] = -1;
663
664         for (i = 0; i < TH_POSSIBLE_OUTPUTS; i++) {
665                 gth->output[i].gth = gth;
666                 gth->output[i].index = i;
667                 gth->output[i].port_type =
668                         gth_output_parm_get(gth, i, TH_OUTPUT_PARM(port));
669         }
670
671         if (intel_th_output_attributes(gth) ||
672             intel_th_master_attributes(gth)) {
673                 pr_warn("Can't initialize sysfs attributes\n");
674
675                 if (gth->output_group.attrs)
676                         sysfs_remove_group(&gth->dev->kobj, &gth->output_group);
677                 return -ENOMEM;
678         }
679
680         dev_set_drvdata(dev, gth);
681
682         return 0;
683 }
684
685 static void intel_th_gth_remove(struct intel_th_device *thdev)
686 {
687         struct gth_device *gth = dev_get_drvdata(&thdev->dev);
688
689         sysfs_remove_group(&gth->dev->kobj, &gth->output_group);
690         sysfs_remove_group(&gth->dev->kobj, &gth->master_group);
691 }
692
693 static struct intel_th_driver intel_th_gth_driver = {
694         .probe          = intel_th_gth_probe,
695         .remove         = intel_th_gth_remove,
696         .assign         = intel_th_gth_assign,
697         .unassign       = intel_th_gth_unassign,
698         .set_output     = intel_th_gth_set_output,
699         .enable         = intel_th_gth_enable,
700         .disable        = intel_th_gth_disable,
701         .driver = {
702                 .name   = "gth",
703                 .owner  = THIS_MODULE,
704         },
705 };
706
707 module_driver(intel_th_gth_driver,
708               intel_th_driver_register,
709               intel_th_driver_unregister);
710
711 MODULE_ALIAS("intel_th_switch");
712 MODULE_LICENSE("GPL v2");
713 MODULE_DESCRIPTION("Intel(R) Trace Hub Global Trace Hub driver");
714 MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");