Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 620165f9 authored by Kumar Gala's avatar Kumar Gala Committed by Benjamin Herrenschmidt
Browse files

powerpc: Add support for using doorbells for SMP IPI



The e500mc supports the new msgsnd/doorbell mechanisms that were added in
the Power ISA 2.05 architecture.  We use the normal level doorbell for
doing SMP IPIs at this point.

Signed-off-by: default avatarKumar Gala <galak@kernel.crashing.org>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 6ed8d128
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -145,6 +145,7 @@ extern const char *powerpc_base_platform;
#define CPU_FTR_USE_TB			ASM_CONST(0x0000000000000040)
#define CPU_FTR_L2CSR			ASM_CONST(0x0000000000000080)
#define CPU_FTR_601			ASM_CONST(0x0000000000000100)
#define CPU_FTR_DBELL			ASM_CONST(0x0000000000000200)
#define CPU_FTR_CAN_NAP			ASM_CONST(0x0000000000000400)
#define CPU_FTR_L3CR			ASM_CONST(0x0000000000000800)
#define CPU_FTR_L3_DISABLE_NAP		ASM_CONST(0x0000000000001000)
@@ -373,7 +374,8 @@ extern const char *powerpc_base_platform;
	    CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE)
#define CPU_FTRS_E500MC	(CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_NODSISRALIGN | \
	    CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE)
	    CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \
	    CPU_FTR_DBELL)
#define CPU_FTRS_GENERIC_32	(CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)

/* 64-bit CPUs */
+43 −0
Original line number Diff line number Diff line
/*
 * Copyright 2009 Freescale Semicondutor, Inc.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 *
 * provides masks and opcode images for use by code generation, emulation
 * and for instructions that older assemblers might not know about
 */
#ifndef _ASM_POWERPC_DBELL_H
#define _ASM_POWERPC_DBELL_H

#include <linux/smp.h>
#include <linux/threads.h>

#include <asm/ppc-opcode.h>

#define PPC_DBELL_MSG_BRDCAST	(0x04000000)
#define PPC_DBELL_TYPE(x)	(((x) & 0xf) << 28)
enum ppc_dbell {
	PPC_DBELL = 0,		/* doorbell */
	PPC_DBELL_CRIT = 1,	/* critical doorbell */
	PPC_G_DBELL = 2,	/* guest doorbell */
	PPC_G_DBELL_CRIT = 3,	/* guest critical doorbell */
	PPC_G_DBELL_MC = 4,	/* guest mcheck doorbell */
};

#ifdef CONFIG_SMP
extern unsigned long dbell_smp_message[NR_CPUS];
extern void smp_dbell_message_pass(int target, int msg);
#endif

static inline void ppc_msgsnd(enum ppc_dbell type, u32 flags, u32 tag)
{
	u32 msg = PPC_DBELL_TYPE(type) | (flags & PPC_DBELL_MSG_BRDCAST) |
			(tag & 0x07ffffff);

	__asm__ __volatile__ (PPC_MSGSND(%0) : : "r" (msg));
}

#endif /* _ASM_POWERPC_DBELL_H */
+1 −1
Original line number Diff line number Diff line
@@ -59,7 +59,7 @@ obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o \
obj64-$(CONFIG_HIBERNATION)	+= swsusp_asm64.o
obj-$(CONFIG_MODULES)		+= module.o module_$(CONFIG_WORD_SIZE).o
obj-$(CONFIG_44x)		+= cpu_setup_44x.o
obj-$(CONFIG_FSL_BOOKE)		+= cpu_setup_fsl_booke.o
obj-$(CONFIG_FSL_BOOKE)		+= cpu_setup_fsl_booke.o dbell.o

extra-$(CONFIG_PPC_STD_MMU)	:= head_32.o
extra-$(CONFIG_PPC64)		:= head_64.o
+44 −0
Original line number Diff line number Diff line
/*
 * Author: Kumar Gala <galak@kernel.crashing.org>
 *
 * Copyright 2009 Freescale Semiconductor Inc.
 *
 * This program is free software; you can redistribute  it and/or modify it
 * under  the terms of  the GNU General  Public License as published by the
 * Free Software Foundation;  either version 2 of the  License, or (at your
 * option) any later version.
 */

#include <linux/stddef.h>
#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/threads.h>

#include <asm/dbell.h>

#ifdef CONFIG_SMP
unsigned long dbell_smp_message[NR_CPUS];

void smp_dbell_message_pass(int target, int msg)
{
	int i;

	if(target < NR_CPUS) {
		set_bit(msg, &dbell_smp_message[target]);
		ppc_msgsnd(PPC_DBELL, 0, target);
	}
	else if(target == MSG_ALL_BUT_SELF) {
		for_each_online_cpu(i) {
			if (i == smp_processor_id())
				continue;
			set_bit(msg, &dbell_smp_message[i]);
			ppc_msgsnd(PPC_DBELL, 0, i);
		}
	}
	else { /* target == MSG_ALL */
		for_each_online_cpu(i)
			set_bit(msg, &dbell_smp_message[i]);
		ppc_msgsnd(PPC_DBELL, PPC_DBELL_MSG_BRDCAST, 0);
	}
}
#endif
+5 −1
Original line number Diff line number Diff line
@@ -698,7 +698,9 @@ interrupt_base:
	/* Performance Monitor */
	EXCEPTION(0x2060, PerformanceMonitor, performance_monitor_exception, EXC_XFER_STD)

	EXCEPTION(0x2070, Doorbell, unknown_exception, EXC_XFER_STD)
	EXCEPTION(0x2070, Doorbell, doorbell_exception, EXC_XFER_STD)

	CRITICAL_EXCEPTION(0x2080, CriticalDoorbell, unknown_exception)

	/* Debug Interrupt */
	DEBUG_DEBUG_EXCEPTION
@@ -921,6 +923,8 @@ _GLOBAL(__setup_e500mc_ivors)
	mtspr	SPRN_IVOR35,r3
	li	r3,Doorbell@l
	mtspr	SPRN_IVOR36,r3
	li	r3,CriticalDoorbell@l
	mtspr	SPRN_IVOR37,r3
	sync
	blr

Loading