platsmp.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /*
  2. * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. */
  14. #include <linux/sizes.h>
  15. #include <linux/compiler.h>
  16. #include <linux/init.h>
  17. #include <linux/io.h>
  18. #include <linux/regmap.h>
  19. #include <linux/mfd/syscon.h>
  20. #include <asm/smp.h>
  21. #include <asm/smp_scu.h>
  22. static struct regmap *sbcm_regmap;
  23. static void __init uniphier_smp_prepare_cpus(unsigned int max_cpus)
  24. {
  25. static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 };
  26. unsigned long scu_base_phys = 0;
  27. void __iomem *scu_base;
  28. sbcm_regmap = syscon_regmap_lookup_by_compatible(
  29. "socionext,uniphier-system-bus-controller-misc");
  30. if (IS_ERR(sbcm_regmap)) {
  31. pr_err("failed to regmap system-bus-controller-misc\n");
  32. goto err;
  33. }
  34. if (scu_a9_has_base())
  35. scu_base_phys = scu_a9_get_base();
  36. if (!scu_base_phys) {
  37. pr_err("failed to get scu base\n");
  38. goto err;
  39. }
  40. scu_base = ioremap(scu_base_phys, SZ_128);
  41. if (!scu_base) {
  42. pr_err("failed to remap scu base (0x%08lx)\n", scu_base_phys);
  43. goto err;
  44. }
  45. scu_enable(scu_base);
  46. iounmap(scu_base);
  47. return;
  48. err:
  49. pr_warn("disabling SMP\n");
  50. init_cpu_present(&only_cpu_0);
  51. sbcm_regmap = NULL;
  52. }
  53. static int uniphier_boot_secondary(unsigned int cpu,
  54. struct task_struct *idle)
  55. {
  56. int ret;
  57. if (!sbcm_regmap)
  58. return -ENODEV;
  59. ret = regmap_write(sbcm_regmap, 0x1208,
  60. virt_to_phys(secondary_startup));
  61. if (!ret)
  62. asm("sev"); /* wake up secondary CPU */
  63. return ret;
  64. }
  65. struct smp_operations uniphier_smp_ops __initdata = {
  66. .smp_prepare_cpus = uniphier_smp_prepare_cpus,
  67. .smp_boot_secondary = uniphier_boot_secondary,
  68. };
  69. CPU_METHOD_OF_DECLARE(uniphier_smp, "socionext,uniphier-smp",
  70. &uniphier_smp_ops);