of_coresight.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2012, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/types.h>
  6. #include <linux/err.h>
  7. #include <linux/slab.h>
  8. #include <linux/clk.h>
  9. #include <linux/of.h>
  10. #include <linux/of_address.h>
  11. #include <linux/of_graph.h>
  12. #include <linux/of_platform.h>
  13. #include <linux/platform_device.h>
  14. #include <linux/amba/bus.h>
  15. #include <linux/coresight.h>
  16. #include <linux/cpumask.h>
  17. #include <asm/smp_plat.h>
  18. static int of_dev_node_match(struct device *dev, void *data)
  19. {
  20. return dev->of_node == data;
  21. }
  22. static struct device *
  23. of_coresight_get_endpoint_device(struct device_node *endpoint)
  24. {
  25. struct device *dev = NULL;
  26. /*
  27. * If we have a non-configurable replicator, it will be found on the
  28. * platform bus.
  29. */
  30. dev = bus_find_device(&platform_bus_type, NULL,
  31. endpoint, of_dev_node_match);
  32. if (dev)
  33. return dev;
  34. /*
  35. * We have a configurable component - circle through the AMBA bus
  36. * looking for the device that matches the endpoint node.
  37. */
  38. return bus_find_device(&amba_bustype, NULL,
  39. endpoint, of_dev_node_match);
  40. }
  41. static void of_coresight_get_ports(const struct device_node *node,
  42. int *nr_inport, int *nr_outport)
  43. {
  44. struct device_node *ep = NULL;
  45. int in = 0, out = 0;
  46. do {
  47. ep = of_graph_get_next_endpoint(node, ep);
  48. if (!ep)
  49. break;
  50. if (of_property_read_bool(ep, "slave-mode"))
  51. in++;
  52. else
  53. out++;
  54. } while (ep);
  55. *nr_inport = in;
  56. *nr_outport = out;
  57. }
  58. static int of_coresight_alloc_memory(struct device *dev,
  59. struct coresight_platform_data *pdata)
  60. {
  61. /* List of output port on this component */
  62. pdata->outports = devm_kcalloc(dev,
  63. pdata->nr_outport,
  64. sizeof(*pdata->outports),
  65. GFP_KERNEL);
  66. if (!pdata->outports)
  67. return -ENOMEM;
  68. /* Children connected to this component via @outports */
  69. pdata->child_names = devm_kcalloc(dev,
  70. pdata->nr_outport,
  71. sizeof(*pdata->child_names),
  72. GFP_KERNEL);
  73. if (!pdata->child_names)
  74. return -ENOMEM;
  75. /* Port number on the child this component is connected to */
  76. pdata->child_ports = devm_kcalloc(dev,
  77. pdata->nr_outport,
  78. sizeof(*pdata->child_ports),
  79. GFP_KERNEL);
  80. if (!pdata->child_ports)
  81. return -ENOMEM;
  82. return 0;
  83. }
  84. int of_coresight_get_cpu(const struct device_node *node)
  85. {
  86. int cpu;
  87. struct device_node *dn;
  88. dn = of_parse_phandle(node, "cpu", 0);
  89. /* Affinity defaults to CPU0 */
  90. if (!dn)
  91. return 0;
  92. cpu = of_cpu_node_to_id(dn);
  93. of_node_put(dn);
  94. /* Affinity to CPU0 if no cpu nodes are found */
  95. return (cpu < 0) ? 0 : cpu;
  96. }
  97. EXPORT_SYMBOL_GPL(of_coresight_get_cpu);
  98. struct coresight_platform_data *
  99. of_get_coresight_platform_data(struct device *dev,
  100. const struct device_node *node)
  101. {
  102. int i = 0, ret = 0;
  103. struct coresight_platform_data *pdata;
  104. struct of_endpoint endpoint, rendpoint;
  105. struct device *rdev;
  106. struct device_node *ep = NULL;
  107. struct device_node *rparent = NULL;
  108. struct device_node *rport = NULL;
  109. pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
  110. if (!pdata)
  111. return ERR_PTR(-ENOMEM);
  112. /* Use device name as sysfs handle */
  113. pdata->name = dev_name(dev);
  114. /* Get the number of input and output port for this component */
  115. of_coresight_get_ports(node, &pdata->nr_inport, &pdata->nr_outport);
  116. if (pdata->nr_outport) {
  117. ret = of_coresight_alloc_memory(dev, pdata);
  118. if (ret)
  119. return ERR_PTR(ret);
  120. /* Iterate through each port to discover topology */
  121. do {
  122. /* Get a handle on a port */
  123. ep = of_graph_get_next_endpoint(node, ep);
  124. if (!ep)
  125. break;
  126. /*
  127. * No need to deal with input ports, processing for as
  128. * processing for output ports will deal with them.
  129. */
  130. if (of_find_property(ep, "slave-mode", NULL))
  131. continue;
  132. /* Get a handle on the local endpoint */
  133. ret = of_graph_parse_endpoint(ep, &endpoint);
  134. if (ret)
  135. continue;
  136. /* The local out port number */
  137. pdata->outports[i] = endpoint.port;
  138. /*
  139. * Get a handle on the remote port and parent
  140. * attached to it.
  141. */
  142. rparent = of_graph_get_remote_port_parent(ep);
  143. rport = of_graph_get_remote_port(ep);
  144. if (!rparent || !rport)
  145. continue;
  146. if (of_graph_parse_endpoint(rport, &rendpoint))
  147. continue;
  148. rdev = of_coresight_get_endpoint_device(rparent);
  149. if (!rdev)
  150. return ERR_PTR(-EPROBE_DEFER);
  151. pdata->child_names[i] = dev_name(rdev);
  152. pdata->child_ports[i] = rendpoint.id;
  153. i++;
  154. } while (ep);
  155. }
  156. pdata->cpu = of_coresight_get_cpu(node);
  157. return pdata;
  158. }
  159. EXPORT_SYMBOL_GPL(of_get_coresight_platform_data);