Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.16 80 lines 1.7 kB view raw
1// SPDX-License-Identifier: GPL-2.0-or-later 2 3/* 4 * SMP support functions for Microwatt 5 * Copyright 2025 Paul Mackerras <paulus@ozlabs.org> 6 */ 7 8#include <linux/kernel.h> 9#include <linux/smp.h> 10#include <linux/io.h> 11#include <asm/early_ioremap.h> 12#include <asm/ppc-opcode.h> 13#include <asm/reg.h> 14#include <asm/smp.h> 15#include <asm/xics.h> 16 17#include "microwatt.h" 18 19static void __init microwatt_smp_probe(void) 20{ 21 xics_smp_probe(); 22} 23 24static void microwatt_smp_setup_cpu(int cpu) 25{ 26 if (cpu != 0) 27 xics_setup_cpu(); 28} 29 30static struct smp_ops_t microwatt_smp_ops = { 31 .probe = microwatt_smp_probe, 32 .message_pass = NULL, /* Use smp_muxed_ipi_message_pass */ 33 .kick_cpu = smp_generic_kick_cpu, 34 .setup_cpu = microwatt_smp_setup_cpu, 35}; 36 37/* XXX get from device tree */ 38#define SYSCON_BASE 0xc0000000 39#define SYSCON_LENGTH 0x100 40 41#define SYSCON_CPU_CTRL 0x58 42 43void __init microwatt_init_smp(void) 44{ 45 volatile unsigned char __iomem *syscon; 46 int ncpus; 47 int timeout; 48 49 syscon = early_ioremap(SYSCON_BASE, SYSCON_LENGTH); 50 if (syscon == NULL) { 51 pr_err("Failed to map SYSCON\n"); 52 return; 53 } 54 ncpus = (readl(syscon + SYSCON_CPU_CTRL) >> 8) & 0xff; 55 if (ncpus < 2) 56 goto out; 57 58 smp_ops = &microwatt_smp_ops; 59 60 /* 61 * Write two instructions at location 0: 62 * mfspr r3, PIR 63 * b __secondary_hold 64 */ 65 *(unsigned int *)KERNELBASE = PPC_RAW_MFSPR(3, SPRN_PIR); 66 *(unsigned int *)(KERNELBASE+4) = PPC_RAW_BRANCH(&__secondary_hold - (char *)(KERNELBASE+4)); 67 68 /* enable the other CPUs, they start at location 0 */ 69 writel((1ul << ncpus) - 1, syscon + SYSCON_CPU_CTRL); 70 71 timeout = 10000; 72 while (!__secondary_hold_acknowledge) { 73 if (--timeout == 0) 74 break; 75 barrier(); 76 } 77 78 out: 79 early_iounmap((void *)syscon, SYSCON_LENGTH); 80}