bman_portal.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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 void 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;
  54. pcfg = bman_get_bm_portal_config(p);
  55. if (!pcfg)
  56. return;
  57. irq_set_affinity(pcfg->irq, cpumask_of(0));
  58. }
  59. static void bman_online_cpu(unsigned int cpu)
  60. {
  61. struct bman_portal *p = affine_bportals[cpu];
  62. const struct bm_portal_config *pcfg;
  63. if (!p)
  64. return;
  65. pcfg = bman_get_bm_portal_config(p);
  66. if (!pcfg)
  67. return;
  68. irq_set_affinity(pcfg->irq, cpumask_of(cpu));
  69. }
  70. static int bman_hotplug_cpu_callback(struct notifier_block *nfb,
  71. unsigned long action, void *hcpu)
  72. {
  73. unsigned int cpu = (unsigned long)hcpu;
  74. switch (action) {
  75. case CPU_ONLINE:
  76. case CPU_ONLINE_FROZEN:
  77. bman_online_cpu(cpu);
  78. break;
  79. case CPU_DOWN_PREPARE:
  80. case CPU_DOWN_PREPARE_FROZEN:
  81. bman_offline_cpu(cpu);
  82. }
  83. return NOTIFY_OK;
  84. }
  85. static struct notifier_block bman_hotplug_cpu_notifier = {
  86. .notifier_call = bman_hotplug_cpu_callback,
  87. };
  88. static int bman_portal_probe(struct platform_device *pdev)
  89. {
  90. struct device *dev = &pdev->dev;
  91. struct device_node *node = dev->of_node;
  92. struct bm_portal_config *pcfg;
  93. struct resource *addr_phys[2];
  94. void __iomem *va;
  95. int irq, cpu;
  96. pcfg = devm_kmalloc(dev, sizeof(*pcfg), GFP_KERNEL);
  97. if (!pcfg)
  98. return -ENOMEM;
  99. pcfg->dev = dev;
  100. addr_phys[0] = platform_get_resource(pdev, IORESOURCE_MEM,
  101. DPAA_PORTAL_CE);
  102. if (!addr_phys[0]) {
  103. dev_err(dev, "Can't get %s property 'reg::CE'\n",
  104. node->full_name);
  105. return -ENXIO;
  106. }
  107. addr_phys[1] = platform_get_resource(pdev, IORESOURCE_MEM,
  108. DPAA_PORTAL_CI);
  109. if (!addr_phys[1]) {
  110. dev_err(dev, "Can't get %s property 'reg::CI'\n",
  111. node->full_name);
  112. return -ENXIO;
  113. }
  114. pcfg->cpu = -1;
  115. irq = platform_get_irq(pdev, 0);
  116. if (irq <= 0) {
  117. dev_err(dev, "Can't get %s IRQ'\n", node->full_name);
  118. return -ENXIO;
  119. }
  120. pcfg->irq = irq;
  121. va = ioremap_prot(addr_phys[0]->start, resource_size(addr_phys[0]), 0);
  122. if (!va)
  123. goto err_ioremap1;
  124. pcfg->addr_virt[DPAA_PORTAL_CE] = va;
  125. va = ioremap_prot(addr_phys[1]->start, resource_size(addr_phys[1]),
  126. _PAGE_GUARDED | _PAGE_NO_CACHE);
  127. if (!va)
  128. goto err_ioremap2;
  129. pcfg->addr_virt[DPAA_PORTAL_CI] = va;
  130. spin_lock(&bman_lock);
  131. cpu = cpumask_next_zero(-1, &portal_cpus);
  132. if (cpu >= nr_cpu_ids) {
  133. /* unassigned portal, skip init */
  134. spin_unlock(&bman_lock);
  135. return 0;
  136. }
  137. cpumask_set_cpu(cpu, &portal_cpus);
  138. spin_unlock(&bman_lock);
  139. pcfg->cpu = cpu;
  140. if (!init_pcfg(pcfg))
  141. goto err_ioremap2;
  142. /* clear irq affinity if assigned cpu is offline */
  143. if (!cpu_online(cpu))
  144. bman_offline_cpu(cpu);
  145. return 0;
  146. err_ioremap2:
  147. iounmap(pcfg->addr_virt[DPAA_PORTAL_CE]);
  148. err_ioremap1:
  149. dev_err(dev, "ioremap failed\n");
  150. return -ENXIO;
  151. }
  152. static const struct of_device_id bman_portal_ids[] = {
  153. {
  154. .compatible = "fsl,bman-portal",
  155. },
  156. {}
  157. };
  158. MODULE_DEVICE_TABLE(of, bman_portal_ids);
  159. static struct platform_driver bman_portal_driver = {
  160. .driver = {
  161. .name = KBUILD_MODNAME,
  162. .of_match_table = bman_portal_ids,
  163. },
  164. .probe = bman_portal_probe,
  165. };
  166. static int __init bman_portal_driver_register(struct platform_driver *drv)
  167. {
  168. int ret;
  169. ret = platform_driver_register(drv);
  170. if (ret < 0)
  171. return ret;
  172. register_hotcpu_notifier(&bman_hotplug_cpu_notifier);
  173. return 0;
  174. }
  175. module_driver(bman_portal_driver,
  176. bman_portal_driver_register, platform_driver_unregister);