File Index
Files and directories
Sign in
FILE

ip30-smp.c

File preview with syntax highlighting.

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