bman_portal.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  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;
  79. pcfg = devm_kmalloc(dev, sizeof(*pcfg), GFP_KERNEL);
  80. if (!pcfg)
  81. return -ENOMEM;
  82. pcfg->dev = dev;
  83. addr_phys[0] = platform_get_resource(pdev, IORESOURCE_MEM,
  84. DPAA_PORTAL_CE);
  85. if (!addr_phys[0]) {
  86. dev_err(dev, "Can't get %pOF property 'reg::CE'\n", node);
  87. return -ENXIO;
  88. }
  89. addr_phys[1] = platform_get_resource(pdev, IORESOURCE_MEM,
  90. DPAA_PORTAL_CI);
  91. if (!addr_phys[1]) {
  92. dev_err(dev, "Can't get %pOF property 'reg::CI'\n", node);
  93. return -ENXIO;
  94. }
  95. pcfg->cpu = -1;
  96. irq = platform_get_irq(pdev, 0);
  97. if (irq <= 0) {
  98. dev_err(dev, "Can't get %pOF IRQ'\n", node);
  99. return -ENXIO;
  100. }
  101. pcfg->irq = irq;
  102. pcfg->addr_virt_ce = memremap(addr_phys[0]->start,
  103. resource_size(addr_phys[0]),
  104. QBMAN_MEMREMAP_ATTR);
  105. if (!pcfg->addr_virt_ce) {
  106. dev_err(dev, "memremap::CE failed\n");
  107. goto err_ioremap1;
  108. }
  109. pcfg->addr_virt_ci = ioremap(addr_phys[1]->start,
  110. resource_size(addr_phys[1]));
  111. if (!pcfg->addr_virt_ci) {
  112. dev_err(dev, "ioremap::CI failed\n");
  113. goto err_ioremap2;
  114. }
  115. spin_lock(&bman_lock);
  116. cpu = cpumask_next_zero(-1, &portal_cpus);
  117. if (cpu >= nr_cpu_ids) {
  118. /* unassigned portal, skip init */
  119. spin_unlock(&bman_lock);
  120. return 0;
  121. }
  122. cpumask_set_cpu(cpu, &portal_cpus);
  123. spin_unlock(&bman_lock);
  124. pcfg->cpu = cpu;
  125. if (!init_pcfg(pcfg)) {
  126. dev_err(dev, "portal init failed\n");
  127. goto err_portal_init;
  128. }
  129. /* clear irq affinity if assigned cpu is offline */
  130. if (!cpu_online(cpu))
  131. bman_offline_cpu(cpu);
  132. return 0;
  133. err_portal_init:
  134. iounmap(pcfg->addr_virt_ci);
  135. err_ioremap2:
  136. memunmap(pcfg->addr_virt_ce);
  137. err_ioremap1:
  138. return -ENXIO;
  139. }
  140. static const struct of_device_id bman_portal_ids[] = {
  141. {
  142. .compatible = "fsl,bman-portal",
  143. },
  144. {}
  145. };
  146. MODULE_DEVICE_TABLE(of, bman_portal_ids);
  147. static struct platform_driver bman_portal_driver = {
  148. .driver = {
  149. .name = KBUILD_MODNAME,
  150. .of_match_table = bman_portal_ids,
  151. },
  152. .probe = bman_portal_probe,
  153. };
  154. static int __init bman_portal_driver_register(struct platform_driver *drv)
  155. {
  156. int ret;
  157. ret = platform_driver_register(drv);
  158. if (ret < 0)
  159. return ret;
  160. ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
  161. "soc/qbman_portal:online",
  162. bman_online_cpu, bman_offline_cpu);
  163. if (ret < 0) {
  164. pr_err("bman: failed to register hotplug callbacks.\n");
  165. platform_driver_unregister(drv);
  166. return ret;
  167. }
  168. return 0;
  169. }
  170. module_driver(bman_portal_driver,
  171. bman_portal_driver_register, platform_driver_unregister);