ip30-smp.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * ip30-smp.c: SMP on IP30 architecture.
  4. * Based off of the original IP30 SMP code, with inspiration from ip27-smp.c
  5. * and smp-bmips.c.
  6. *
  7. * Copyright (C) 2005-2007 Stanislaw Skowronek <skylark@unaligned.org>
  8. * 2006-2007, 2014-2015 Joshua Kinard <kumba@gentoo.org>
  9. * 2009 Johannes Dickgreber <tanzy@gmx.de>
  10. */
  11. #include <linux/init.h>
  12. #include <linux/sched.h>
  13. #include <linux/sched/task_stack.h>
  14. #include <asm/time.h>
  15. #include <asm/sgi/heart.h>
  16. #include "ip30-common.h"
  17. #define MPCONF_MAGIC 0xbaddeed2
  18. #define MPCONF_ADDR 0xa800000000000600L
  19. #define MPCONF_SIZE 0x80
  20. #define MPCONF(x) (MPCONF_ADDR + (x) * MPCONF_SIZE)
  21. /* HEART can theoretically do 4 CPUs, but only 2 are physically possible */
  22. #define MP_NCPU 2
  23. struct mpconf {
  24. u32 magic;
  25. u32 prid;
  26. u32 physid;
  27. u32 virtid;
  28. u32 scachesz;
  29. u16 fanloads;
  30. u16 res;
  31. void *launch;
  32. void *rendezvous;
  33. u64 res2[3];
  34. void *stackaddr;
  35. void *lnch_parm;
  36. void *rndv_parm;
  37. u32 idleflag;
  38. };
  39. static void ip30_smp_send_ipi_single(int cpu, u32 action)
  40. {
  41. int irq;
  42. switch (action) {
  43. case SMP_RESCHEDULE_YOURSELF:
  44. irq = HEART_L2_INT_RESCHED_CPU_0;
  45. break;
  46. case SMP_CALL_FUNCTION:
  47. irq = HEART_L2_INT_CALL_CPU_0;
  48. break;
  49. default:
  50. panic("IP30: Unknown action value in %s!\n", __func__);
  51. }
  52. irq += cpu;
  53. /* Poke the other CPU -- it's got mail! */
  54. heart_write(BIT_ULL(irq), &heart_regs->set_isr);
  55. }
  56. static void ip30_smp_send_ipi_mask(const struct cpumask *mask, u32 action)
  57. {
  58. u32 i;
  59. for_each_cpu(i, mask)
  60. ip30_smp_send_ipi_single(i, action);
  61. }
  62. static void __init ip30_smp_setup(void)
  63. {
  64. int i;
  65. int ncpu = 0;
  66. struct mpconf *mpc;
  67. init_cpu_possible(cpumask_of(0));
  68. /* Scan the MPCONF structure and enumerate available CPUs. */
  69. for (i = 0; i < MP_NCPU; i++) {
  70. mpc = (struct mpconf *)MPCONF(i);
  71. if (mpc->magic == MPCONF_MAGIC) {
  72. set_cpu_possible(i, true);
  73. __cpu_number_map[i] = ++ncpu;
  74. __cpu_logical_map[ncpu] = i;
  75. pr_info("IP30: Slot: %d, PrID: %.8x, PhyID: %d, VirtID: %d\n",
  76. i, mpc->prid, mpc->physid, mpc->virtid);
  77. }
  78. }
  79. pr_info("IP30: Detected %d CPU(s) present.\n", ncpu);
  80. /*
  81. * Set the coherency algorithm to '5' (cacheable coherent
  82. * exclusive on write). This is needed on IP30 SMP, especially
  83. * for R14000 CPUs, otherwise, instruction bus errors will
  84. * occur upon reaching userland.
  85. */
  86. change_c0_config(CONF_CM_CMASK, CONF_CM_CACHABLE_COW);
  87. }
  88. static void __init ip30_smp_prepare_cpus(unsigned int max_cpus)
  89. {
  90. /* nothing to do here */
  91. }
  92. static int __init ip30_smp_boot_secondary(int cpu, struct task_struct *idle)
  93. {
  94. struct mpconf *mpc = (struct mpconf *)MPCONF(cpu);
  95. /* Stack pointer (sp). */
  96. mpc->stackaddr = (void *)__KSTK_TOS(idle);
  97. /* Global pointer (gp). */
  98. mpc->lnch_parm = task_thread_info(idle);
  99. mb(); /* make sure stack and lparm are written */
  100. /* Boot CPUx. */
  101. mpc->launch = smp_bootstrap;
  102. /* CPUx now executes smp_bootstrap, then ip30_smp_finish */
  103. return 0;
  104. }
  105. static void __init ip30_smp_init_cpu(void)
  106. {
  107. ip30_per_cpu_init();
  108. }
  109. static void __init ip30_smp_finish(void)
  110. {
  111. enable_percpu_irq(get_c0_compare_int(), IRQ_TYPE_NONE);
  112. local_irq_enable();
  113. }
  114. struct plat_smp_ops __read_mostly ip30_smp_ops = {
  115. .send_ipi_single = ip30_smp_send_ipi_single,
  116. .send_ipi_mask = ip30_smp_send_ipi_mask,
  117. .smp_setup = ip30_smp_setup,
  118. .prepare_cpus = ip30_smp_prepare_cpus,
  119. .boot_secondary = ip30_smp_boot_secondary,
  120. .init_secondary = ip30_smp_init_cpu,
  121. .smp_finish = ip30_smp_finish,
  122. .prepare_boot_cpu = ip30_smp_init_cpu,
  123. };