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