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