bman_portal.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /* Copyright 2008 - 2016 Freescale Semiconductor, Inc.
  2. *
  3. * Redistribution and use in source and binary forms, with or without
  4. * modification, are permitted provided that the following conditions are met:
  5. * * Redistributions of source code must retain the above copyright
  6. * notice, this list of conditions and the following disclaimer.
  7. * * Redistributions in binary form must reproduce the above copyright
  8. * notice, this list of conditions and the following disclaimer in the
  9. * documentation and/or other materials provided with the distribution.
  10. * * Neither the name of Freescale Semiconductor nor the
  11. * names of its contributors may be used to endorse or promote products
  12. * derived from this software without specific prior written permission.
  13. *
  14. * ALTERNATIVELY, this software may be distributed under the terms of the
  15. * GNU General Public License ("GPL") as published by the Free Software
  16. * Foundation, either version 2 of that License or (at your option) any
  17. * later version.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
  20. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
  23. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  26. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  28. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. #include "bman_priv.h"
  31. static struct bman_portal *affine_bportals[NR_CPUS];
  32. static struct cpumask portal_cpus;
  33. /* protect bman global registers and global data shared among portals */
  34. static DEFINE_SPINLOCK(bman_lock);
  35. static struct bman_portal *init_pcfg(struct bm_portal_config *pcfg)
  36. {
  37. struct bman_portal *p = bman_create_affine_portal(pcfg);
  38. if (!p) {
  39. dev_crit(pcfg->dev, "%s: Portal failure on cpu %d\n",
  40. __func__, pcfg->cpu);
  41. return NULL;
  42. }
  43. bman_p_irqsource_add(p, BM_PIRQ_RCRI);
  44. affine_bportals[pcfg->cpu] = p;
  45. dev_info(pcfg->dev, "Portal initialised, cpu %d\n", pcfg->cpu);
  46. return p;
  47. }
  48. static int bman_offline_cpu(unsigned int cpu)
  49. {
  50. struct bman_portal *p = affine_bportals[cpu];
  51. const struct bm_portal_config *pcfg;
  52. if (!p)
  53. return 0;
  54. pcfg = bman_get_bm_portal_config(p);
  55. if (!pcfg)
  56. return 0;
  57. irq_set_affinity(pcfg->irq, cpumask_of(0));
  58. return 0;
  59. }
  60. static int bman_online_cpu(unsigned int cpu)
  61. {
  62. struct bman_portal *p = affine_bportals[cpu];
  63. const struct bm_portal_config *pcfg;
  64. if (!p)
  65. return 0;
  66. pcfg = bman_get_bm_portal_config(p);
  67. if (!pcfg)
  68. return 0;
  69. irq_set_affinity(pcfg->irq, cpumask_of(cpu));
  70. return 0;
  71. }
  72. static int bman_portal_probe(struct platform_device *pdev)
  73. {
  74. struct device *dev = &pdev->dev;
  75. struct device_node *node = dev->of_node;
  76. struct bm_portal_config *pcfg;
  77. struct resource *addr_phys[2];
  78. int irq, cpu, err;
  79. err = bman_is_probed();
  80. if (!err)
  81. return -EPROBE_DEFER;
  82. if (err < 0) {
  83. dev_err(&pdev->dev, "failing probe due to bman probe error\n");
  84. return -ENODEV;
  85. }
  86. pcfg = devm_kmalloc(dev, sizeof(*pcfg), GFP_KERNEL);
  87. if (!pcfg)
  88. return -ENOMEM;
  89. pcfg->dev = dev;
  90. addr_phys[0] = platform_get_resource(pdev, IORESOURCE_MEM,
  91. DPAA_PORTAL_CE);
  92. if (!addr_phys[0]) {
  93. dev_err(dev, "Can't get %pOF property 'reg::CE'\n", node);
  94. return -ENXIO;
  95. }
  96. addr_phys[1] = platform_get_resource(pdev, IORESOURCE_MEM,
  97. DPAA_PORTAL_CI);
  98. if (!addr_phys[1]) {
  99. dev_err(dev, "Can't get %pOF property 'reg::CI'\n", node);
  100. return -ENXIO;
  101. }
  102. pcfg->cpu = -1;
  103. irq = platform_get_irq(pdev, 0);
  104. if (irq <= 0) {
  105. dev_err(dev, "Can't get %pOF IRQ'\n", node);
  106. return -ENXIO;
  107. }
  108. pcfg->irq = irq;
  109. pcfg->addr_virt_ce = memremap(addr_phys[0]->start,
  110. resource_size(addr_phys[0]),
  111. QBMAN_MEMREMAP_ATTR);
  112. if (!pcfg->addr_virt_ce) {
  113. dev_err(dev, "memremap::CE failed\n");
  114. goto err_ioremap1;
  115. }
  116. pcfg->addr_virt_ci = ioremap(addr_phys[1]->start,
  117. resource_size(addr_phys[1]));
  118. if (!pcfg->addr_virt_ci) {
  119. dev_err(dev, "ioremap::CI failed\n");
  120. goto err_ioremap2;
  121. }
  122. spin_lock(&bman_lock);
  123. cpu = cpumask_next_zero(-1, &portal_cpus);
  124. if (cpu >= nr_cpu_ids) {
  125. /* unassigned portal, skip init */
  126. spin_unlock(&bman_lock);
  127. return 0;
  128. }
  129. cpumask_set_cpu(cpu, &portal_cpus);
  130. spin_unlock(&bman_lock);
  131. pcfg->cpu = cpu;
  132. if (!init_pcfg(pcfg)) {
  133. dev_err(dev, "portal init failed\n");
  134. goto err_portal_init;
  135. }
  136. /* clear irq affinity if assigned cpu is offline */
  137. if (!cpu_online(cpu))
  138. bman_offline_cpu(cpu);
  139. return 0;
  140. err_portal_init:
  141. iounmap(pcfg->addr_virt_ci);
  142. err_ioremap2:
  143. memunmap(pcfg->addr_virt_ce);
  144. err_ioremap1:
  145. return -ENXIO;
  146. }
  147. static const struct of_device_id bman_portal_ids[] = {
  148. {
  149. .compatible = "fsl,bman-portal",
  150. },
  151. {}
  152. };
  153. MODULE_DEVICE_TABLE(of, bman_portal_ids);
  154. static struct platform_driver bman_portal_driver = {
  155. .driver = {
  156. .name = KBUILD_MODNAME,
  157. .of_match_table = bman_portal_ids,
  158. },
  159. .probe = bman_portal_probe,
  160. };
  161. static int __init bman_portal_driver_register(struct platform_driver *drv)
  162. {
  163. int ret;
  164. ret = platform_driver_register(drv);
  165. if (ret < 0)
  166. return ret;
  167. ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
  168. "soc/qbman_portal:online",
  169. bman_online_cpu, bman_offline_cpu);
  170. if (ret < 0) {
  171. pr_err("bman: failed to register hotplug callbacks.\n");
  172. platform_driver_unregister(drv);
  173. return ret;
  174. }
  175. return 0;
  176. }
  177. module_driver(bman_portal_driver,
  178. bman_portal_driver_register, platform_driver_unregister);