bman_portal.c 5.6 KB

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