Path: blob/master/arch/powerpc/platforms/microwatt/smp.c
26481 views
// SPDX-License-Identifier: GPL-2.0-or-later12/*3* SMP support functions for Microwatt4* Copyright 2025 Paul Mackerras <[email protected]>5*/67#include <linux/kernel.h>8#include <linux/smp.h>9#include <linux/io.h>10#include <asm/early_ioremap.h>11#include <asm/ppc-opcode.h>12#include <asm/reg.h>13#include <asm/smp.h>14#include <asm/xics.h>1516#include "microwatt.h"1718static void __init microwatt_smp_probe(void)19{20xics_smp_probe();21}2223static void microwatt_smp_setup_cpu(int cpu)24{25if (cpu != 0)26xics_setup_cpu();27}2829static struct smp_ops_t microwatt_smp_ops = {30.probe = microwatt_smp_probe,31.message_pass = NULL, /* Use smp_muxed_ipi_message_pass */32.kick_cpu = smp_generic_kick_cpu,33.setup_cpu = microwatt_smp_setup_cpu,34};3536/* XXX get from device tree */37#define SYSCON_BASE 0xc000000038#define SYSCON_LENGTH 0x1003940#define SYSCON_CPU_CTRL 0x584142void __init microwatt_init_smp(void)43{44volatile unsigned char __iomem *syscon;45int ncpus;46int timeout;4748syscon = early_ioremap(SYSCON_BASE, SYSCON_LENGTH);49if (syscon == NULL) {50pr_err("Failed to map SYSCON\n");51return;52}53ncpus = (readl(syscon + SYSCON_CPU_CTRL) >> 8) & 0xff;54if (ncpus < 2)55goto out;5657smp_ops = µwatt_smp_ops;5859/*60* Write two instructions at location 0:61* mfspr r3, PIR62* b __secondary_hold63*/64*(unsigned int *)KERNELBASE = PPC_RAW_MFSPR(3, SPRN_PIR);65*(unsigned int *)(KERNELBASE+4) = PPC_RAW_BRANCH(&__secondary_hold - (char *)(KERNELBASE+4));6667/* enable the other CPUs, they start at location 0 */68writel((1ul << ncpus) - 1, syscon + SYSCON_CPU_CTRL);6970timeout = 10000;71while (!__secondary_hold_acknowledge) {72if (--timeout == 0)73break;74barrier();75}7677out:78early_iounmap((void *)syscon, SYSCON_LENGTH);79}808182