1
2
3
4
5
6#include <linux/kernel.h>
7#include <linux/init.h>
8#include <linux/types.h>
9#include <linux/device.h>
10#include <linux/io.h>
11#include <linux/err.h>
12#include <linux/export.h>
13#include <linux/slab.h>
14#include <linux/mutex.h>
15#include <linux/clk.h>
16#include <linux/coresight.h>
17#include <linux/of_platform.h>
18#include <linux/delay.h>
19#include <linux/pm_runtime.h>
20
21#include "coresight-priv.h"
22
23static DEFINE_MUTEX(coresight_mutex);
24
25
26
27
28
29
30struct coresight_node {
31 struct coresight_device *csdev;
32 struct list_head link;
33};
34
35
36
37
38
39static DEFINE_PER_CPU(struct list_head *, tracer_path);
40
41
42
43
44
45
46
47static struct list_head *stm_path;
48
49
50
51
52
53
54const u32 barrier_pkt[5] = {0x7fffffff, 0x7fffffff,
55 0x7fffffff, 0x7fffffff, 0x0};
56
57static int coresight_id_match(struct device *dev, void *data)
58{
59 int trace_id, i_trace_id;
60 struct coresight_device *csdev, *i_csdev;
61
62 csdev = data;
63 i_csdev = to_coresight_device(dev);
64
65
66
67
68
69 if (i_csdev == csdev || !i_csdev->enable ||
70 i_csdev->type != CORESIGHT_DEV_TYPE_SOURCE)
71 return 0;
72
73
74 trace_id = source_ops(csdev)->trace_id(csdev);
75 i_trace_id = source_ops(i_csdev)->trace_id(i_csdev);
76
77
78 if (trace_id == i_trace_id)
79 return 1;
80
81 return 0;
82}
83
84static int coresight_source_is_unique(struct coresight_device *csdev)
85{
86 int trace_id = source_ops(csdev)->trace_id(csdev);
87
88
89 if (trace_id < 0)
90 return 0;
91
92 return !bus_for_each_dev(&coresight_bustype, NULL,
93 csdev, coresight_id_match);
94}
95
96static int coresight_find_link_inport(struct coresight_device *csdev,
97 struct coresight_device *parent)
98{
99 int i;
100 struct coresight_connection *conn;
101
102 for (i = 0; i < parent->nr_outport; i++) {
103 conn = &parent->conns[i];
104 if (conn->child_dev == csdev)
105 return conn->child_port;
106 }
107
108 dev_err(&csdev->dev, "couldn't find inport, parent: %s, child: %s\n",
109 dev_name(&parent->dev), dev_name(&csdev->dev));
110
111 return 0;
112}
113
114static int coresight_find_link_outport(struct coresight_device *csdev,
115 struct coresight_device *child)
116{
117 int i;
118 struct coresight_connection *conn;
119
120 for (i = 0; i < csdev->nr_outport; i++) {
121 conn = &csdev->conns[i];
122 if (conn->child_dev == child)
123 return conn->outport;
124 }
125
126 dev_err(&csdev->dev, "couldn't find outport, parent: %s, child: %s\n",
127 dev_name(&csdev->dev), dev_name(&child->dev));
128
129 return 0;
130}
131
132static int coresight_enable_sink(struct coresight_device *csdev, u32 mode)
133{
134 int ret;
135
136 if (!csdev->enable) {
137 if (sink_ops(csdev)->enable) {
138 ret = sink_ops(csdev)->enable(csdev, mode);
139 if (ret)
140 return ret;
141 }
142 csdev->enable = true;
143 }
144
145 atomic_inc(csdev->refcnt);
146
147 return 0;
148}
149
150static void coresight_disable_sink(struct coresight_device *csdev)
151{
152 if (atomic_dec_return(csdev->refcnt) == 0) {
153 if (sink_ops(csdev)->disable) {
154 sink_ops(csdev)->disable(csdev);
155 csdev->enable = false;
156 }
157 }
158}
159
160static int coresight_enable_link(struct coresight_device *csdev,
161 struct coresight_device *parent,
162 struct coresight_device *child)
163{
164 int ret;
165 int link_subtype;
166 int refport, inport, outport;
167
168 if (!parent || !child)
169 return -EINVAL;
170
171 inport = coresight_find_link_inport(csdev, parent);
172 outport = coresight_find_link_outport(csdev, child);
173 link_subtype = csdev->subtype.link_subtype;
174
175 if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG)
176 refport = inport;
177 else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT)
178 refport = outport;
179 else
180 refport = 0;
181
182 if (atomic_inc_return(&csdev->refcnt[refport]) == 1) {
183 if (link_ops(csdev)->enable) {
184 ret = link_ops(csdev)->enable(csdev, inport, outport);
185 if (ret)
186 return ret;
187 }
188 }
189
190 csdev->enable = true;
191
192 return 0;
193}
194
195static void coresight_disable_link(struct coresight_device *csdev,
196 struct coresight_device *parent,
197 struct coresight_device *child)
198{
199 int i, nr_conns;
200 int link_subtype;
201 int refport, inport, outport;
202
203 if (!parent || !child)
204 return;
205
206 inport = coresight_find_link_inport(csdev, parent);
207 outport = coresight_find_link_outport(csdev, child);
208 link_subtype = csdev->subtype.link_subtype;
209
210 if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) {
211 refport = inport;
212 nr_conns = csdev->nr_inport;
213 } else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) {
214 refport = outport;
215 nr_conns = csdev->nr_outport;
216 } else {
217 refport = 0;
218 nr_conns = 1;
219 }
220
221 if (atomic_dec_return(&csdev->refcnt[refport]) == 0) {
222 if (link_ops(csdev)->disable)
223 link_ops(csdev)->disable(csdev, inport, outport);
224 }
225
226 for (i = 0; i < nr_conns; i++)
227 if (atomic_read(&csdev->refcnt[i]) != 0)
228 return;
229
230 csdev->enable = false;
231}
232
233static int coresight_enable_source(struct coresight_device *csdev, u32 mode)
234{
235 int ret;
236
237 if (!coresight_source_is_unique(csdev)) {
238 dev_warn(&csdev->dev, "traceID %d not unique\n",
239 source_ops(csdev)->trace_id(csdev));
240 return -EINVAL;
241 }
242
243 if (!csdev->enable) {
244 if (source_ops(csdev)->enable) {
245 ret = source_ops(csdev)->enable(csdev, NULL, mode);
246 if (ret)
247 return ret;
248 }
249 csdev->enable = true;
250 }
251
252 atomic_inc(csdev->refcnt);
253
254 return 0;
255}
256
257
258
259
260
261
262
263
264
265static bool coresight_disable_source(struct coresight_device *csdev)
266{
267 if (atomic_dec_return(csdev->refcnt) == 0) {
268 if (source_ops(csdev)->disable)
269 source_ops(csdev)->disable(csdev, NULL);
270 csdev->enable = false;
271 }
272 return !csdev->enable;
273}
274
275void coresight_disable_path(struct list_head *path)
276{
277 u32 type;
278 struct coresight_node *nd;
279 struct coresight_device *csdev, *parent, *child;
280
281 list_for_each_entry(nd, path, link) {
282 csdev = nd->csdev;
283 type = csdev->type;
284
285
286
287
288
289
290
291 if (type == CORESIGHT_DEV_TYPE_LINKSINK)
292 type = (csdev == coresight_get_sink(path)) ?
293 CORESIGHT_DEV_TYPE_SINK :
294 CORESIGHT_DEV_TYPE_LINK;
295
296 switch (type) {
297 case CORESIGHT_DEV_TYPE_SINK:
298 coresight_disable_sink(csdev);
299 break;
300 case CORESIGHT_DEV_TYPE_SOURCE:
301
302 break;
303 case CORESIGHT_DEV_TYPE_LINK:
304 parent = list_prev_entry(nd, link)->csdev;
305 child = list_next_entry(nd, link)->csdev;
306 coresight_disable_link(csdev, parent, child);
307 break;
308 default:
309 break;
310 }
311 }
312}
313
314int coresight_enable_path(struct list_head *path, u32 mode)
315{
316
317 int ret = 0;
318 u32 type;
319 struct coresight_node *nd;
320 struct coresight_device *csdev, *parent, *child;
321
322 list_for_each_entry_reverse(nd, path, link) {
323 csdev = nd->csdev;
324 type = csdev->type;
325
326
327
328
329
330
331
332 if (type == CORESIGHT_DEV_TYPE_LINKSINK)
333 type = (csdev == coresight_get_sink(path)) ?
334 CORESIGHT_DEV_TYPE_SINK :
335 CORESIGHT_DEV_TYPE_LINK;
336
337 switch (type) {
338 case CORESIGHT_DEV_TYPE_SINK:
339 ret = coresight_enable_sink(csdev, mode);
340 if (ret)
341 goto err;
342 break;
343 case CORESIGHT_DEV_TYPE_SOURCE:
344
345 break;
346 case CORESIGHT_DEV_TYPE_LINK:
347 parent = list_prev_entry(nd, link)->csdev;
348 child = list_next_entry(nd, link)->csdev;
349 ret = coresight_enable_link(csdev, parent, child);
350 if (ret)
351 goto err;
352 break;
353 default:
354 goto err;
355 }
356 }
357
358out:
359 return ret;
360err:
361 coresight_disable_path(path);
362 goto out;
363}
364
365struct coresight_device *coresight_get_sink(struct list_head *path)
366{
367 struct coresight_device *csdev;
368
369 if (!path)
370 return NULL;
371
372 csdev = list_last_entry(path, struct coresight_node, link)->csdev;
373 if (csdev->type != CORESIGHT_DEV_TYPE_SINK &&
374 csdev->type != CORESIGHT_DEV_TYPE_LINKSINK)
375 return NULL;
376
377 return csdev;
378}
379
380static int coresight_enabled_sink(struct device *dev, const void *data)
381{
382 const bool *reset = data;
383 struct coresight_device *csdev = to_coresight_device(dev);
384
385 if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
386 csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) &&
387 csdev->activated) {
388
389
390
391
392
393
394
395 if (*reset)
396 csdev->activated = false;
397
398 return 1;
399 }
400
401 return 0;
402}
403
404
405
406
407
408
409
410
411
412
413
414
415
416struct coresight_device *coresight_get_enabled_sink(bool deactivate)
417{
418 struct device *dev = NULL;
419
420 dev = bus_find_device(&coresight_bustype, NULL, &deactivate,
421 coresight_enabled_sink);
422
423 return dev ? to_coresight_device(dev) : NULL;
424}
425
426
427
428
429
430
431
432
433
434
435
436
437static int _coresight_build_path(struct coresight_device *csdev,
438 struct coresight_device *sink,
439 struct list_head *path)
440{
441 int i;
442 bool found = false;
443 struct coresight_node *node;
444
445
446 if (csdev == sink)
447 goto out;
448
449
450 for (i = 0; i < csdev->nr_outport; i++) {
451 struct coresight_device *child_dev = csdev->conns[i].child_dev;
452
453 if (child_dev &&
454 _coresight_build_path(child_dev, sink, path) == 0) {
455 found = true;
456 break;
457 }
458 }
459
460 if (!found)
461 return -ENODEV;
462
463out:
464
465
466
467
468
469
470 node = kzalloc(sizeof(struct coresight_node), GFP_KERNEL);
471 if (!node)
472 return -ENOMEM;
473
474 node->csdev = csdev;
475 list_add(&node->link, path);
476 pm_runtime_get_sync(csdev->dev.parent);
477
478 return 0;
479}
480
481struct list_head *coresight_build_path(struct coresight_device *source,
482 struct coresight_device *sink)
483{
484 struct list_head *path;
485 int rc;
486
487 if (!sink)
488 return ERR_PTR(-EINVAL);
489
490 path = kzalloc(sizeof(struct list_head), GFP_KERNEL);
491 if (!path)
492 return ERR_PTR(-ENOMEM);
493
494 INIT_LIST_HEAD(path);
495
496 rc = _coresight_build_path(source, sink, path);
497 if (rc) {
498 kfree(path);
499 return ERR_PTR(rc);
500 }
501
502 return path;
503}
504
505
506
507
508
509
510
511
512void coresight_release_path(struct list_head *path)
513{
514 struct coresight_device *csdev;
515 struct coresight_node *nd, *next;
516
517 list_for_each_entry_safe(nd, next, path, link) {
518 csdev = nd->csdev;
519
520 pm_runtime_put_sync(csdev->dev.parent);
521 list_del(&nd->link);
522 kfree(nd);
523 }
524
525 kfree(path);
526 path = NULL;
527}
528
529
530
531
532
533
534
535static int coresight_validate_source(struct coresight_device *csdev,
536 const char *function)
537{
538 u32 type, subtype;
539
540 type = csdev->type;
541 subtype = csdev->subtype.source_subtype;
542
543 if (type != CORESIGHT_DEV_TYPE_SOURCE) {
544 dev_err(&csdev->dev, "wrong device type in %s\n", function);
545 return -EINVAL;
546 }
547
548 if (subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_PROC &&
549 subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE) {
550 dev_err(&csdev->dev, "wrong device subtype in %s\n", function);
551 return -EINVAL;
552 }
553
554 return 0;
555}
556
557int coresight_enable(struct coresight_device *csdev)
558{
559 int cpu, ret = 0;
560 struct coresight_device *sink;
561 struct list_head *path;
562 enum coresight_dev_subtype_source subtype;
563
564 subtype = csdev->subtype.source_subtype;
565
566 mutex_lock(&coresight_mutex);
567
568 ret = coresight_validate_source(csdev, __func__);
569 if (ret)
570 goto out;
571
572 if (csdev->enable) {
573
574
575
576
577
578 if (subtype == CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE)
579 atomic_inc(csdev->refcnt);
580 goto out;
581 }
582
583
584
585
586
587 sink = coresight_get_enabled_sink(false);
588 if (!sink) {
589 ret = -EINVAL;
590 goto out;
591 }
592
593 path = coresight_build_path(csdev, sink);
594 if (IS_ERR(path)) {
595 pr_err("building path(s) failed\n");
596 ret = PTR_ERR(path);
597 goto out;
598 }
599
600 ret = coresight_enable_path(path, CS_MODE_SYSFS);
601 if (ret)
602 goto err_path;
603
604 ret = coresight_enable_source(csdev, CS_MODE_SYSFS);
605 if (ret)
606 goto err_source;
607
608 switch (subtype) {
609 case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC:
610
611
612
613
614
615
616
617 cpu = source_ops(csdev)->cpu_id(csdev);
618 per_cpu(tracer_path, cpu) = path;
619 break;
620 case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE:
621 stm_path = path;
622 break;
623 default:
624
625 break;
626 }
627
628out:
629 mutex_unlock(&coresight_mutex);
630 return ret;
631
632err_source:
633 coresight_disable_path(path);
634
635err_path:
636 coresight_release_path(path);
637 goto out;
638}
639EXPORT_SYMBOL_GPL(coresight_enable);
640
641void coresight_disable(struct coresight_device *csdev)
642{
643 int cpu, ret;
644 struct list_head *path = NULL;
645
646 mutex_lock(&coresight_mutex);
647
648 ret = coresight_validate_source(csdev, __func__);
649 if (ret)
650 goto out;
651
652 if (!csdev->enable || !coresight_disable_source(csdev))
653 goto out;
654
655 switch (csdev->subtype.source_subtype) {
656 case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC:
657 cpu = source_ops(csdev)->cpu_id(csdev);
658 path = per_cpu(tracer_path, cpu);
659 per_cpu(tracer_path, cpu) = NULL;
660 break;
661 case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE:
662 path = stm_path;
663 stm_path = NULL;
664 break;
665 default:
666
667 break;
668 }
669
670 coresight_disable_path(path);
671 coresight_release_path(path);
672
673out:
674 mutex_unlock(&coresight_mutex);
675}
676EXPORT_SYMBOL_GPL(coresight_disable);
677
678static ssize_t enable_sink_show(struct device *dev,
679 struct device_attribute *attr, char *buf)
680{
681 struct coresight_device *csdev = to_coresight_device(dev);
682
683 return scnprintf(buf, PAGE_SIZE, "%u\n", csdev->activated);
684}
685
686static ssize_t enable_sink_store(struct device *dev,
687 struct device_attribute *attr,
688 const char *buf, size_t size)
689{
690 int ret;
691 unsigned long val;
692 struct coresight_device *csdev = to_coresight_device(dev);
693
694 ret = kstrtoul(buf, 10, &val);
695 if (ret)
696 return ret;
697
698 if (val)
699 csdev->activated = true;
700 else
701 csdev->activated = false;
702
703 return size;
704
705}
706static DEVICE_ATTR_RW(enable_sink);
707
708static ssize_t enable_source_show(struct device *dev,
709 struct device_attribute *attr, char *buf)
710{
711 struct coresight_device *csdev = to_coresight_device(dev);
712
713 return scnprintf(buf, PAGE_SIZE, "%u\n", csdev->enable);
714}
715
716static ssize_t enable_source_store(struct device *dev,
717 struct device_attribute *attr,
718 const char *buf, size_t size)
719{
720 int ret = 0;
721 unsigned long val;
722 struct coresight_device *csdev = to_coresight_device(dev);
723
724 ret = kstrtoul(buf, 10, &val);
725 if (ret)
726 return ret;
727
728 if (val) {
729 ret = coresight_enable(csdev);
730 if (ret)
731 return ret;
732 } else {
733 coresight_disable(csdev);
734 }
735
736 return size;
737}
738static DEVICE_ATTR_RW(enable_source);
739
740static struct attribute *coresight_sink_attrs[] = {
741 &dev_attr_enable_sink.attr,
742 NULL,
743};
744ATTRIBUTE_GROUPS(coresight_sink);
745
746static struct attribute *coresight_source_attrs[] = {
747 &dev_attr_enable_source.attr,
748 NULL,
749};
750ATTRIBUTE_GROUPS(coresight_source);
751
752static struct device_type coresight_dev_type[] = {
753 {
754 .name = "none",
755 },
756 {
757 .name = "sink",
758 .groups = coresight_sink_groups,
759 },
760 {
761 .name = "link",
762 },
763 {
764 .name = "linksink",
765 .groups = coresight_sink_groups,
766 },
767 {
768 .name = "source",
769 .groups = coresight_source_groups,
770 },
771};
772
773static void coresight_device_release(struct device *dev)
774{
775 struct coresight_device *csdev = to_coresight_device(dev);
776
777 kfree(csdev->conns);
778 kfree(csdev->refcnt);
779 kfree(csdev);
780}
781
782static int coresight_orphan_match(struct device *dev, void *data)
783{
784 int i;
785 bool still_orphan = false;
786 struct coresight_device *csdev, *i_csdev;
787 struct coresight_connection *conn;
788
789 csdev = data;
790 i_csdev = to_coresight_device(dev);
791
792
793 if (csdev == i_csdev)
794 return 0;
795
796
797 if (!i_csdev->orphan)
798 return 0;
799
800
801
802
803 for (i = 0; i < i_csdev->nr_outport; i++) {
804 conn = &i_csdev->conns[i];
805
806
807 if (conn->child_dev == NULL) {
808
809 if (conn->child_name &&
810 !strcmp(dev_name(&csdev->dev), conn->child_name)) {
811 conn->child_dev = csdev;
812 } else {
813
814 still_orphan = true;
815 }
816 }
817 }
818
819 i_csdev->orphan = still_orphan;
820
821
822
823
824
825 return 0;
826}
827
828static void coresight_fixup_orphan_conns(struct coresight_device *csdev)
829{
830
831
832
833
834 bus_for_each_dev(&coresight_bustype, NULL,
835 csdev, coresight_orphan_match);
836}
837
838
839static void coresight_fixup_device_conns(struct coresight_device *csdev)
840{
841 int i;
842
843 for (i = 0; i < csdev->nr_outport; i++) {
844 struct coresight_connection *conn = &csdev->conns[i];
845 struct device *dev = NULL;
846
847 if (conn->child_name)
848 dev = bus_find_device_by_name(&coresight_bustype, NULL,
849 conn->child_name);
850 if (dev) {
851 conn->child_dev = to_coresight_device(dev);
852
853 put_device(dev);
854 } else {
855 csdev->orphan = true;
856 conn->child_dev = NULL;
857 }
858 }
859}
860
861static int coresight_remove_match(struct device *dev, void *data)
862{
863 int i;
864 struct coresight_device *csdev, *iterator;
865 struct coresight_connection *conn;
866
867 csdev = data;
868 iterator = to_coresight_device(dev);
869
870
871 if (csdev == iterator)
872 return 0;
873
874
875
876
877
878 for (i = 0; i < iterator->nr_outport; i++) {
879 conn = &iterator->conns[i];
880
881 if (conn->child_dev == NULL)
882 continue;
883
884 if (!strcmp(dev_name(&csdev->dev), conn->child_name)) {
885 iterator->orphan = true;
886 conn->child_dev = NULL;
887
888 break;
889 }
890 }
891
892
893
894
895
896 return 0;
897}
898
899static void coresight_remove_conns(struct coresight_device *csdev)
900{
901 bus_for_each_dev(&coresight_bustype, NULL,
902 csdev, coresight_remove_match);
903}
904
905
906
907
908
909
910
911
912
913
914
915
916int coresight_timeout(void __iomem *addr, u32 offset, int position, int value)
917{
918 int i;
919 u32 val;
920
921 for (i = TIMEOUT_US; i > 0; i--) {
922 val = __raw_readl(addr + offset);
923
924 if (value) {
925 if (val & BIT(position))
926 return 0;
927
928 } else {
929 if (!(val & BIT(position)))
930 return 0;
931 }
932
933
934
935
936
937
938 if (i - 1)
939 udelay(1);
940 }
941
942 return -EAGAIN;
943}
944
945struct bus_type coresight_bustype = {
946 .name = "coresight",
947};
948
949static int __init coresight_init(void)
950{
951 return bus_register(&coresight_bustype);
952}
953postcore_initcall(coresight_init);
954
955struct coresight_device *coresight_register(struct coresight_desc *desc)
956{
957 int i;
958 int ret;
959 int link_subtype;
960 int nr_refcnts = 1;
961 atomic_t *refcnts = NULL;
962 struct coresight_device *csdev;
963 struct coresight_connection *conns = NULL;
964
965 csdev = kzalloc(sizeof(*csdev), GFP_KERNEL);
966 if (!csdev) {
967 ret = -ENOMEM;
968 goto err_kzalloc_csdev;
969 }
970
971 if (desc->type == CORESIGHT_DEV_TYPE_LINK ||
972 desc->type == CORESIGHT_DEV_TYPE_LINKSINK) {
973 link_subtype = desc->subtype.link_subtype;
974
975 if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG)
976 nr_refcnts = desc->pdata->nr_inport;
977 else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT)
978 nr_refcnts = desc->pdata->nr_outport;
979 }
980
981 refcnts = kcalloc(nr_refcnts, sizeof(*refcnts), GFP_KERNEL);
982 if (!refcnts) {
983 ret = -ENOMEM;
984 goto err_kzalloc_refcnts;
985 }
986
987 csdev->refcnt = refcnts;
988
989 csdev->nr_inport = desc->pdata->nr_inport;
990 csdev->nr_outport = desc->pdata->nr_outport;
991
992
993 if (csdev->nr_outport) {
994 conns = kcalloc(csdev->nr_outport, sizeof(*conns), GFP_KERNEL);
995 if (!conns) {
996 ret = -ENOMEM;
997 goto err_kzalloc_conns;
998 }
999
1000 for (i = 0; i < csdev->nr_outport; i++) {
1001 conns[i].outport = desc->pdata->outports[i];
1002 conns[i].child_name = desc->pdata->child_names[i];
1003 conns[i].child_port = desc->pdata->child_ports[i];
1004 }
1005 }
1006
1007 csdev->conns = conns;
1008
1009 csdev->type = desc->type;
1010 csdev->subtype = desc->subtype;
1011 csdev->ops = desc->ops;
1012 csdev->orphan = false;
1013
1014 csdev->dev.type = &coresight_dev_type[desc->type];
1015 csdev->dev.groups = desc->groups;
1016 csdev->dev.parent = desc->dev;
1017 csdev->dev.release = coresight_device_release;
1018 csdev->dev.bus = &coresight_bustype;
1019 dev_set_name(&csdev->dev, "%s", desc->pdata->name);
1020
1021 ret = device_register(&csdev->dev);
1022 if (ret) {
1023 put_device(&csdev->dev);
1024 goto err_kzalloc_csdev;
1025 }
1026
1027 mutex_lock(&coresight_mutex);
1028
1029 coresight_fixup_device_conns(csdev);
1030 coresight_fixup_orphan_conns(csdev);
1031
1032 mutex_unlock(&coresight_mutex);
1033
1034 return csdev;
1035
1036err_kzalloc_conns:
1037 kfree(refcnts);
1038err_kzalloc_refcnts:
1039 kfree(csdev);
1040err_kzalloc_csdev:
1041 return ERR_PTR(ret);
1042}
1043EXPORT_SYMBOL_GPL(coresight_register);
1044
1045void coresight_unregister(struct coresight_device *csdev)
1046{
1047
1048 coresight_remove_conns(csdev);
1049 device_unregister(&csdev->dev);
1050}
1051EXPORT_SYMBOL_GPL(coresight_unregister);
1052