Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * ip30-smp.c: SMP on IP30 architecture.
0004  * Based off of the original IP30 SMP code, with inspiration from ip27-smp.c
0005  * and smp-bmips.c.
0006  *
0007  * Copyright (C) 2005-2007 Stanislaw Skowronek <skylark@unaligned.org>
0008  *               2006-2007, 2014-2015 Joshua Kinard <kumba@gentoo.org>
0009  *               2009 Johannes Dickgreber <tanzy@gmx.de>
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 /* HEART can theoretically do 4 CPUs, but only 2 are physically possible */
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     /* Poke the other CPU -- it's got mail! */
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     /* Scan the MPCONF structure and enumerate available CPUs. */
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      * Set the coherency algorithm to '5' (cacheable coherent
0098      * exclusive on write).  This is needed on IP30 SMP, especially
0099      * for R14000 CPUs, otherwise, instruction bus errors will
0100      * occur upon reaching userland.
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     /* nothing to do here */
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     /* Stack pointer (sp). */
0115     mpc->stackaddr = (void *)__KSTK_TOS(idle);
0116 
0117     /* Global pointer (gp). */
0118     mpc->lnch_parm = task_thread_info(idle);
0119 
0120     mb(); /* make sure stack and lparm are written */
0121 
0122     /* Boot CPUx. */
0123     mpc->launch = smp_bootstrap;
0124 
0125     /* CPUx now executes smp_bootstrap, then ip30_smp_finish */
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 };