0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/init.h>
0013 #include <linux/sched.h>
0014 #include <linux/sched/task_stack.h>
0015
0016 #include <asm/time.h>
0017 #include <asm/sgi/heart.h>
0018
0019 #include "ip30-common.h"
0020
0021 #define MPCONF_MAGIC 0xbaddeed2
0022 #define MPCONF_ADDR 0xa800000000000600L
0023 #define MPCONF_SIZE 0x80
0024 #define MPCONF(x) (MPCONF_ADDR + (x) * MPCONF_SIZE)
0025
0026
0027 #define MP_NCPU 2
0028
0029 struct mpconf {
0030 u32 magic;
0031 u32 prid;
0032 u32 physid;
0033 u32 virtid;
0034 u32 scachesz;
0035 u16 fanloads;
0036 u16 res;
0037 void *launch;
0038 void *rendezvous;
0039 u64 res2[3];
0040 void *stackaddr;
0041 void *lnch_parm;
0042 void *rndv_parm;
0043 u32 idleflag;
0044 };
0045
0046 static void ip30_smp_send_ipi_single(int cpu, u32 action)
0047 {
0048 int irq;
0049
0050 switch (action) {
0051 case SMP_RESCHEDULE_YOURSELF:
0052 irq = HEART_L2_INT_RESCHED_CPU_0;
0053 break;
0054 case SMP_CALL_FUNCTION:
0055 irq = HEART_L2_INT_CALL_CPU_0;
0056 break;
0057 default:
0058 panic("IP30: Unknown action value in %s!\n", __func__);
0059 }
0060
0061 irq += cpu;
0062
0063
0064 heart_write(BIT_ULL(irq), &heart_regs->set_isr);
0065 }
0066
0067 static void ip30_smp_send_ipi_mask(const struct cpumask *mask, u32 action)
0068 {
0069 u32 i;
0070
0071 for_each_cpu(i, mask)
0072 ip30_smp_send_ipi_single(i, action);
0073 }
0074
0075 static void __init ip30_smp_setup(void)
0076 {
0077 int i;
0078 int ncpu = 0;
0079 struct mpconf *mpc;
0080
0081 init_cpu_possible(cpumask_of(0));
0082
0083
0084 for (i = 0; i < MP_NCPU; i++) {
0085 mpc = (struct mpconf *)MPCONF(i);
0086 if (mpc->magic == MPCONF_MAGIC) {
0087 set_cpu_possible(i, true);
0088 __cpu_number_map[i] = ++ncpu;
0089 __cpu_logical_map[ncpu] = i;
0090 pr_info("IP30: Slot: %d, PrID: %.8x, PhyID: %d, VirtID: %d\n",
0091 i, mpc->prid, mpc->physid, mpc->virtid);
0092 }
0093 }
0094 pr_info("IP30: Detected %d CPU(s) present.\n", ncpu);
0095
0096
0097
0098
0099
0100
0101
0102 change_c0_config(CONF_CM_CMASK, CONF_CM_CACHABLE_COW);
0103 }
0104
0105 static void __init ip30_smp_prepare_cpus(unsigned int max_cpus)
0106 {
0107
0108 }
0109
0110 static int __init ip30_smp_boot_secondary(int cpu, struct task_struct *idle)
0111 {
0112 struct mpconf *mpc = (struct mpconf *)MPCONF(cpu);
0113
0114
0115 mpc->stackaddr = (void *)__KSTK_TOS(idle);
0116
0117
0118 mpc->lnch_parm = task_thread_info(idle);
0119
0120 mb();
0121
0122
0123 mpc->launch = smp_bootstrap;
0124
0125
0126 return 0;
0127 }
0128
0129 static void __init ip30_smp_init_cpu(void)
0130 {
0131 ip30_per_cpu_init();
0132 }
0133
0134 static void __init ip30_smp_finish(void)
0135 {
0136 enable_percpu_irq(get_c0_compare_int(), IRQ_TYPE_NONE);
0137 local_irq_enable();
0138 }
0139
0140 struct plat_smp_ops __read_mostly ip30_smp_ops = {
0141 .send_ipi_single = ip30_smp_send_ipi_single,
0142 .send_ipi_mask = ip30_smp_send_ipi_mask,
0143 .smp_setup = ip30_smp_setup,
0144 .prepare_cpus = ip30_smp_prepare_cpus,
0145 .boot_secondary = ip30_smp_boot_secondary,
0146 .init_secondary = ip30_smp_init_cpu,
0147 .smp_finish = ip30_smp_finish,
0148 .prepare_boot_cpu = ip30_smp_init_cpu,
0149 };