1
2
3
4
5
6#include <linux/acpi.h>
7#include <linux/types.h>
8#include <linux/err.h>
9#include <linux/slab.h>
10#include <linux/clk.h>
11#include <linux/of.h>
12#include <linux/of_address.h>
13#include <linux/of_graph.h>
14#include <linux/of_platform.h>
15#include <linux/platform_device.h>
16#include <linux/amba/bus.h>
17#include <linux/coresight.h>
18#include <linux/cpumask.h>
19#include <asm/smp_plat.h>
20
21#include "coresight-priv.h"
22
23
24
25
26static int coresight_alloc_conns(struct device *dev,
27 struct coresight_platform_data *pdata)
28{
29 if (pdata->nr_outport) {
30 pdata->conns = devm_kzalloc(dev, pdata->nr_outport *
31 sizeof(*pdata->conns),
32 GFP_KERNEL);
33 if (!pdata->conns)
34 return -ENOMEM;
35 }
36
37 return 0;
38}
39
40static struct device *
41coresight_find_device_by_fwnode(struct fwnode_handle *fwnode)
42{
43 struct device *dev = NULL;
44
45
46
47
48
49 dev = bus_find_device_by_fwnode(&platform_bus_type, fwnode);
50 if (dev)
51 return dev;
52
53
54
55
56
57 return bus_find_device_by_fwnode(&amba_bustype, fwnode);
58}
59
60#ifdef CONFIG_OF
61static inline bool of_coresight_legacy_ep_is_input(struct device_node *ep)
62{
63 return of_property_read_bool(ep, "slave-mode");
64}
65
66static void of_coresight_get_ports_legacy(const struct device_node *node,
67 int *nr_inport, int *nr_outport)
68{
69 struct device_node *ep = NULL;
70 int in = 0, out = 0;
71
72 do {
73 ep = of_graph_get_next_endpoint(node, ep);
74 if (!ep)
75 break;
76
77 if (of_coresight_legacy_ep_is_input(ep))
78 in++;
79 else
80 out++;
81
82 } while (ep);
83
84 *nr_inport = in;
85 *nr_outport = out;
86}
87
88static struct device_node *of_coresight_get_port_parent(struct device_node *ep)
89{
90 struct device_node *parent = of_graph_get_port_parent(ep);
91
92
93
94
95
96 if (of_node_name_eq(parent, "in-ports") ||
97 of_node_name_eq(parent, "out-ports"))
98 parent = of_get_next_parent(parent);
99
100 return parent;
101}
102
103static inline struct device_node *
104of_coresight_get_input_ports_node(const struct device_node *node)
105{
106 return of_get_child_by_name(node, "in-ports");
107}
108
109static inline struct device_node *
110of_coresight_get_output_ports_node(const struct device_node *node)
111{
112 return of_get_child_by_name(node, "out-ports");
113}
114
115static inline int
116of_coresight_count_ports(struct device_node *port_parent)
117{
118 int i = 0;
119 struct device_node *ep = NULL;
120
121 while ((ep = of_graph_get_next_endpoint(port_parent, ep)))
122 i++;
123 return i;
124}
125
126static void of_coresight_get_ports(const struct device_node *node,
127 int *nr_inport, int *nr_outport)
128{
129 struct device_node *input_ports = NULL, *output_ports = NULL;
130
131 input_ports = of_coresight_get_input_ports_node(node);
132 output_ports = of_coresight_get_output_ports_node(node);
133
134 if (input_ports || output_ports) {
135 if (input_ports) {
136 *nr_inport = of_coresight_count_ports(input_ports);
137 of_node_put(input_ports);
138 }
139 if (output_ports) {
140 *nr_outport = of_coresight_count_ports(output_ports);
141 of_node_put(output_ports);
142 }
143 } else {
144
145 of_coresight_get_ports_legacy(node, nr_inport, nr_outport);
146 }
147}
148
149static int of_coresight_get_cpu(struct device *dev)
150{
151 int cpu;
152 struct device_node *dn;
153
154 if (!dev->of_node)
155 return -ENODEV;
156
157 dn = of_parse_phandle(dev->of_node, "cpu", 0);
158 if (!dn)
159 return -ENODEV;
160
161 cpu = of_cpu_node_to_id(dn);
162 of_node_put(dn);
163
164 return cpu;
165}
166
167
168
169
170
171
172
173
174
175
176
177
178
179static int of_coresight_parse_endpoint(struct device *dev,
180 struct device_node *ep,
181 struct coresight_connection *conn)
182{
183 int ret = 0;
184 struct of_endpoint endpoint, rendpoint;
185 struct device_node *rparent = NULL;
186 struct device_node *rep = NULL;
187 struct device *rdev = NULL;
188 struct fwnode_handle *rdev_fwnode;
189
190 do {
191
192 if (of_graph_parse_endpoint(ep, &endpoint))
193 break;
194
195
196
197
198 rep = of_graph_get_remote_endpoint(ep);
199 if (!rep)
200 break;
201 rparent = of_coresight_get_port_parent(rep);
202 if (!rparent)
203 break;
204 if (of_graph_parse_endpoint(rep, &rendpoint))
205 break;
206
207 rdev_fwnode = of_fwnode_handle(rparent);
208
209 rdev = coresight_find_device_by_fwnode(rdev_fwnode);
210 if (!rdev) {
211 ret = -EPROBE_DEFER;
212 break;
213 }
214
215 conn->outport = endpoint.port;
216
217
218
219
220
221
222
223
224 conn->child_fwnode = fwnode_handle_get(rdev_fwnode);
225 conn->child_port = rendpoint.port;
226
227 ret = 1;
228 } while (0);
229
230 of_node_put(rparent);
231 of_node_put(rep);
232 put_device(rdev);
233
234 return ret;
235}
236
237static int of_get_coresight_platform_data(struct device *dev,
238 struct coresight_platform_data *pdata)
239{
240 int ret = 0;
241 struct coresight_connection *conn;
242 struct device_node *ep = NULL;
243 const struct device_node *parent = NULL;
244 bool legacy_binding = false;
245 struct device_node *node = dev->of_node;
246
247
248 of_coresight_get_ports(node, &pdata->nr_inport, &pdata->nr_outport);
249
250
251 if (!pdata->nr_outport)
252 return 0;
253
254 ret = coresight_alloc_conns(dev, pdata);
255 if (ret)
256 return ret;
257
258 parent = of_coresight_get_output_ports_node(node);
259
260
261
262
263
264 if (!parent) {
265 legacy_binding = true;
266 parent = node;
267 dev_warn_once(dev, "Uses obsolete Coresight DT bindings\n");
268 }
269
270 conn = pdata->conns;
271
272
273 while ((ep = of_graph_get_next_endpoint(parent, ep))) {
274
275
276
277
278
279
280 if (legacy_binding && of_coresight_legacy_ep_is_input(ep))
281 continue;
282
283 ret = of_coresight_parse_endpoint(dev, ep, conn);
284 switch (ret) {
285 case 1:
286 conn++;
287 case 0:
288 break;
289 default:
290 return ret;
291 }
292 }
293
294 return 0;
295}
296#else
297static inline int
298of_get_coresight_platform_data(struct device *dev,
299 struct coresight_platform_data *pdata)
300{
301 return -ENOENT;
302}
303
304static inline int of_coresight_get_cpu(struct device *dev)
305{
306 return -ENODEV;
307}
308#endif
309
310#ifdef CONFIG_ACPI
311
312#include <acpi/actypes.h>
313#include <acpi/processor.h>
314
315
316static const guid_t acpi_graph_uuid = GUID_INIT(0xab02a46b, 0x74c7, 0x45a2,
317 0xbd, 0x68, 0xf7, 0xd3,
318 0x44, 0xef, 0x21, 0x53);
319
320static const guid_t coresight_graph_uuid = GUID_INIT(0x3ecbc8b6, 0x1d0e, 0x4fb3,
321 0x81, 0x07, 0xe6, 0x27,
322 0xf8, 0x05, 0xc6, 0xcd);
323#define ACPI_CORESIGHT_LINK_SLAVE 0
324#define ACPI_CORESIGHT_LINK_MASTER 1
325
326static inline bool is_acpi_guid(const union acpi_object *obj)
327{
328 return (obj->type == ACPI_TYPE_BUFFER) && (obj->buffer.length == 16);
329}
330
331
332
333
334
335static inline bool acpi_guid_matches(const union acpi_object *obj,
336 const guid_t *guid)
337{
338 return is_acpi_guid(obj) &&
339 guid_equal((guid_t *)obj->buffer.pointer, guid);
340}
341
342static inline bool is_acpi_dsd_graph_guid(const union acpi_object *obj)
343{
344 return acpi_guid_matches(obj, &acpi_graph_uuid);
345}
346
347static inline bool is_acpi_coresight_graph_guid(const union acpi_object *obj)
348{
349 return acpi_guid_matches(obj, &coresight_graph_uuid);
350}
351
352static inline bool is_acpi_coresight_graph(const union acpi_object *obj)
353{
354 const union acpi_object *graphid, *guid, *links;
355
356 if (obj->type != ACPI_TYPE_PACKAGE ||
357 obj->package.count < 3)
358 return false;
359
360 graphid = &obj->package.elements[0];
361 guid = &obj->package.elements[1];
362 links = &obj->package.elements[2];
363
364 if (graphid->type != ACPI_TYPE_INTEGER ||
365 links->type != ACPI_TYPE_INTEGER)
366 return false;
367
368 return is_acpi_coresight_graph_guid(guid);
369}
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439static inline bool acpi_validate_dsd_graph(const union acpi_object *graph)
440{
441 int i, n;
442 const union acpi_object *rev, *nr_graphs;
443
444
445 if (graph->package.count < 2)
446 return false;
447
448 rev = &graph->package.elements[0];
449 nr_graphs = &graph->package.elements[1];
450
451 if (rev->type != ACPI_TYPE_INTEGER ||
452 nr_graphs->type != ACPI_TYPE_INTEGER)
453 return false;
454
455
456 if (rev->integer.value != 0)
457 return false;
458
459 n = nr_graphs->integer.value;
460
461 if (n != 1)
462 return false;
463
464
465 if (graph->package.count != (n + 2))
466 return false;
467
468
469
470
471
472 for (i = 2; i < n + 2; i++) {
473 const union acpi_object *obj = &graph->package.elements[i];
474
475 if (obj->type != ACPI_TYPE_PACKAGE ||
476 obj->package.count < 3)
477 return false;
478 }
479
480 return true;
481}
482
483
484const union acpi_object *
485acpi_get_dsd_graph(struct acpi_device *adev)
486{
487 int i;
488 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
489 acpi_status status;
490 const union acpi_object *dsd;
491
492 status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL,
493 &buf, ACPI_TYPE_PACKAGE);
494 if (ACPI_FAILURE(status))
495 return NULL;
496
497 dsd = buf.pointer;
498
499
500
501
502
503 for (i = 0; i + 1 < dsd->package.count; i += 2) {
504 const union acpi_object *guid, *package;
505
506 guid = &dsd->package.elements[i];
507 package = &dsd->package.elements[i + 1];
508
509
510 if (!is_acpi_guid(guid) || package->type != ACPI_TYPE_PACKAGE)
511 break;
512
513 if (!is_acpi_dsd_graph_guid(guid))
514 continue;
515 if (acpi_validate_dsd_graph(package))
516 return package;
517
518 dev_warn(&adev->dev, "Invalid Graph _DSD property\n");
519 }
520
521 return NULL;
522}
523
524static inline bool
525acpi_validate_coresight_graph(const union acpi_object *cs_graph)
526{
527 int nlinks;
528
529 nlinks = cs_graph->package.elements[2].integer.value;
530
531
532
533
534 if (cs_graph->package.count != (nlinks + 3))
535 return false;
536
537 return true;
538}
539
540
541
542
543
544
545
546
547const union acpi_object *
548acpi_get_coresight_graph(struct acpi_device *adev)
549{
550 const union acpi_object *graph_list, *graph;
551 int i, nr_graphs;
552
553 graph_list = acpi_get_dsd_graph(adev);
554 if (!graph_list)
555 return graph_list;
556
557 nr_graphs = graph_list->package.elements[1].integer.value;
558
559 for (i = 2; i < nr_graphs + 2; i++) {
560 graph = &graph_list->package.elements[i];
561 if (!is_acpi_coresight_graph(graph))
562 continue;
563 if (acpi_validate_coresight_graph(graph))
564 return graph;
565
566 break;
567 }
568
569 return NULL;
570}
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589static int acpi_coresight_parse_link(struct acpi_device *adev,
590 const union acpi_object *link,
591 struct coresight_connection *conn)
592{
593 int rc, dir;
594 const union acpi_object *fields;
595 struct acpi_device *r_adev;
596 struct device *rdev;
597
598 if (link->type != ACPI_TYPE_PACKAGE ||
599 link->package.count != 4)
600 return -EINVAL;
601
602 fields = link->package.elements;
603
604 if (fields[0].type != ACPI_TYPE_INTEGER ||
605 fields[1].type != ACPI_TYPE_INTEGER ||
606 fields[2].type != ACPI_TYPE_LOCAL_REFERENCE ||
607 fields[3].type != ACPI_TYPE_INTEGER)
608 return -EINVAL;
609
610 rc = acpi_bus_get_device(fields[2].reference.handle, &r_adev);
611 if (rc)
612 return rc;
613
614 dir = fields[3].integer.value;
615 if (dir == ACPI_CORESIGHT_LINK_MASTER) {
616 conn->outport = fields[0].integer.value;
617 conn->child_port = fields[1].integer.value;
618 rdev = coresight_find_device_by_fwnode(&r_adev->fwnode);
619 if (!rdev)
620 return -EPROBE_DEFER;
621
622
623
624
625
626
627
628
629 conn->child_fwnode = fwnode_handle_get(&r_adev->fwnode);
630 }
631
632 return dir;
633}
634
635
636
637
638
639
640static int acpi_coresight_parse_graph(struct acpi_device *adev,
641 struct coresight_platform_data *pdata)
642{
643 int rc, i, nlinks;
644 const union acpi_object *graph;
645 struct coresight_connection *conns, *ptr;
646
647 pdata->nr_inport = pdata->nr_outport = 0;
648 graph = acpi_get_coresight_graph(adev);
649 if (!graph)
650 return -ENOENT;
651
652 nlinks = graph->package.elements[2].integer.value;
653 if (!nlinks)
654 return 0;
655
656
657
658
659
660
661
662 conns = devm_kcalloc(&adev->dev, nlinks, sizeof(*conns), GFP_KERNEL);
663 if (!conns)
664 return -ENOMEM;
665 ptr = conns;
666 for (i = 0; i < nlinks; i++) {
667 const union acpi_object *link = &graph->package.elements[3 + i];
668 int dir;
669
670 dir = acpi_coresight_parse_link(adev, link, ptr);
671 if (dir < 0)
672 return dir;
673
674 if (dir == ACPI_CORESIGHT_LINK_MASTER) {
675 pdata->nr_outport++;
676 ptr++;
677 } else {
678 pdata->nr_inport++;
679 }
680 }
681
682 rc = coresight_alloc_conns(&adev->dev, pdata);
683 if (rc)
684 return rc;
685
686
687 for (i = 0; i < pdata->nr_outport; i++)
688 pdata->conns[i] = conns[i];
689
690 devm_kfree(&adev->dev, conns);
691 return 0;
692}
693
694
695
696
697
698
699
700static int
701acpi_handle_to_logical_cpuid(acpi_handle handle)
702{
703 int i;
704 struct acpi_processor *pr;
705
706 for_each_possible_cpu(i) {
707 pr = per_cpu(processors, i);
708 if (pr && pr->handle == handle)
709 break;
710 }
711
712 return i;
713}
714
715
716
717
718
719
720
721
722static int acpi_coresight_get_cpu(struct device *dev)
723{
724 int cpu;
725 acpi_handle cpu_handle;
726 acpi_status status;
727 struct acpi_device *adev = ACPI_COMPANION(dev);
728
729 if (!adev)
730 return -ENODEV;
731 status = acpi_get_parent(adev->handle, &cpu_handle);
732 if (ACPI_FAILURE(status))
733 return -ENODEV;
734
735 cpu = acpi_handle_to_logical_cpuid(cpu_handle);
736 if (cpu >= nr_cpu_ids)
737 return -ENODEV;
738 return cpu;
739}
740
741static int
742acpi_get_coresight_platform_data(struct device *dev,
743 struct coresight_platform_data *pdata)
744{
745 struct acpi_device *adev;
746
747 adev = ACPI_COMPANION(dev);
748 if (!adev)
749 return -EINVAL;
750
751 return acpi_coresight_parse_graph(adev, pdata);
752}
753
754#else
755
756static inline int
757acpi_get_coresight_platform_data(struct device *dev,
758 struct coresight_platform_data *pdata)
759{
760 return -ENOENT;
761}
762
763static inline int acpi_coresight_get_cpu(struct device *dev)
764{
765 return -ENODEV;
766}
767#endif
768
769int coresight_get_cpu(struct device *dev)
770{
771 if (is_of_node(dev->fwnode))
772 return of_coresight_get_cpu(dev);
773 else if (is_acpi_device_node(dev->fwnode))
774 return acpi_coresight_get_cpu(dev);
775 return 0;
776}
777EXPORT_SYMBOL_GPL(coresight_get_cpu);
778
779struct coresight_platform_data *
780coresight_get_platform_data(struct device *dev)
781{
782 int ret = -ENOENT;
783 struct coresight_platform_data *pdata = NULL;
784 struct fwnode_handle *fwnode = dev_fwnode(dev);
785
786 if (IS_ERR_OR_NULL(fwnode))
787 goto error;
788
789 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
790 if (!pdata) {
791 ret = -ENOMEM;
792 goto error;
793 }
794
795 if (is_of_node(fwnode))
796 ret = of_get_coresight_platform_data(dev, pdata);
797 else if (is_acpi_device_node(fwnode))
798 ret = acpi_get_coresight_platform_data(dev, pdata);
799
800 if (!ret)
801 return pdata;
802error:
803 if (!IS_ERR_OR_NULL(pdata))
804
805 coresight_release_platform_data(pdata);
806 return ERR_PTR(ret);
807}
808EXPORT_SYMBOL_GPL(coresight_get_platform_data);
809