Path: blob/master/arch/powerpc/platforms/86xx/mpc86xx_smp.c
26481 views
// SPDX-License-Identifier: GPL-2.0-or-later1/*2* Author: Xianghua Xiao <[email protected]>3* Zhang Wei <[email protected]>4*5* Copyright 2006 Freescale Semiconductor Inc.6*/78#include <linux/stddef.h>9#include <linux/kernel.h>10#include <linux/init.h>11#include <linux/delay.h>12#include <linux/pgtable.h>1314#include <asm/text-patching.h>15#include <asm/page.h>16#include <asm/pci-bridge.h>17#include <asm/mpic.h>18#include <asm/cacheflush.h>19#include <asm/inst.h>2021#include <sysdev/fsl_soc.h>2223#include "mpc86xx.h"2425extern void __secondary_start_mpc86xx(void);2627#define MCM_PORT_CONFIG_OFFSET 0x102829/* Offset from CCSRBAR */30#define MPC86xx_MCM_OFFSET (0x1000)31#define MPC86xx_MCM_SIZE (0x1000)3233static void __init34smp_86xx_release_core(int nr)35{36__be32 __iomem *mcm_vaddr;37unsigned long pcr;3839if (nr < 0 || nr >= NR_CPUS)40return;4142/*43* Startup Core #nr.44*/45mcm_vaddr = ioremap(get_immrbase() + MPC86xx_MCM_OFFSET,46MPC86xx_MCM_SIZE);47pcr = in_be32(mcm_vaddr + (MCM_PORT_CONFIG_OFFSET >> 2));48pcr |= 1 << (nr + 24);49out_be32(mcm_vaddr + (MCM_PORT_CONFIG_OFFSET >> 2), pcr);5051iounmap(mcm_vaddr);52}535455static int __init56smp_86xx_kick_cpu(int nr)57{58unsigned int save_vector;59unsigned long target, flags;60int n = 0;61unsigned int *vector = (unsigned int *)(KERNELBASE + 0x100);6263if (nr < 0 || nr >= NR_CPUS)64return -ENOENT;6566pr_debug("smp_86xx_kick_cpu: kick CPU #%d\n", nr);6768local_irq_save(flags);6970/* Save reset vector */71save_vector = *vector;7273/* Setup fake reset vector to call __secondary_start_mpc86xx. */74target = (unsigned long) __secondary_start_mpc86xx;75patch_branch(vector, target, BRANCH_SET_LINK);7677/* Kick that CPU */78smp_86xx_release_core(nr);7980/* Wait a bit for the CPU to take the exception. */81while ((__secondary_hold_acknowledge != nr) && (n++, n < 1000))82mdelay(1);8384/* Restore the exception vector */85patch_instruction(vector, ppc_inst(save_vector));8687local_irq_restore(flags);8889pr_debug("wait CPU #%d for %d msecs.\n", nr, n);9091return 0;92}939495static void __init96smp_86xx_setup_cpu(int cpu_nr)97{98mpic_setup_this_cpu();99}100101102struct smp_ops_t smp_86xx_ops = {103.cause_nmi_ipi = NULL,104.message_pass = smp_mpic_message_pass,105.probe = smp_mpic_probe,106.kick_cpu = smp_86xx_kick_cpu,107.setup_cpu = smp_86xx_setup_cpu,108.take_timebase = smp_generic_take_timebase,109.give_timebase = smp_generic_give_timebase,110};111112113void __init114mpc86xx_smp_init(void)115{116smp_ops = &smp_86xx_ops;117}118119120