1620165f9SKumar Gala /* 28a56e1eeSYang Li * Copyright 2009 Freescale Semiconductor, Inc. 3620165f9SKumar Gala * 4620165f9SKumar Gala * This program is free software; you can redistribute it and/or 5620165f9SKumar Gala * modify it under the terms of the GNU General Public License 6620165f9SKumar Gala * as published by the Free Software Foundation; either version 7620165f9SKumar Gala * 2 of the License, or (at your option) any later version. 8620165f9SKumar Gala * 9620165f9SKumar Gala * provides masks and opcode images for use by code generation, emulation 10620165f9SKumar Gala * and for instructions that older assemblers might not know about 11620165f9SKumar Gala */ 12620165f9SKumar Gala #ifndef _ASM_POWERPC_DBELL_H 13620165f9SKumar Gala #define _ASM_POWERPC_DBELL_H 14620165f9SKumar Gala 15620165f9SKumar Gala #include <linux/smp.h> 16620165f9SKumar Gala #include <linux/threads.h> 17620165f9SKumar Gala 18620165f9SKumar Gala #include <asm/ppc-opcode.h> 192c86cd18SChristophe Leroy #include <asm/feature-fixups.h> 20620165f9SKumar Gala 21620165f9SKumar Gala #define PPC_DBELL_MSG_BRDCAST (0x04000000) 22dc28518fSMichael Neuling #define PPC_DBELL_TYPE(x) (((x) & 0xf) << (63-36)) 234ab96919SAlexander Graf #define PPC_DBELL_TYPE_MASK PPC_DBELL_TYPE(0xf) 24d30f6e48SScott Wood #define PPC_DBELL_LPID(x) ((x) << (63 - 49)) 254ab96919SAlexander Graf #define PPC_DBELL_PIR_MASK 0x3fff 26620165f9SKumar Gala enum ppc_dbell { 27620165f9SKumar Gala PPC_DBELL = 0, /* doorbell */ 28620165f9SKumar Gala PPC_DBELL_CRIT = 1, /* critical doorbell */ 29620165f9SKumar Gala PPC_G_DBELL = 2, /* guest doorbell */ 30620165f9SKumar Gala PPC_G_DBELL_CRIT = 3, /* guest critical doorbell */ 31620165f9SKumar Gala PPC_G_DBELL_MC = 4, /* guest mcheck doorbell */ 3242d02b81SIan Munsie PPC_DBELL_SERVER = 5, /* doorbell on server */ 33620165f9SKumar Gala }; 34620165f9SKumar Gala 3542d02b81SIan Munsie #ifdef CONFIG_PPC_BOOK3S 3642d02b81SIan Munsie 3742d02b81SIan Munsie #define PPC_DBELL_MSGTYPE PPC_DBELL_SERVER 3842d02b81SIan Munsie 39919ca868SIan Munsie static inline void _ppc_msgsnd(u32 msg) 40919ca868SIan Munsie { 41a5adf282SNicholas Piggin __asm__ __volatile__ (ASM_FTR_IFSET(PPC_MSGSND(%1), PPC_MSGSNDP(%1), %0) 42a5adf282SNicholas Piggin : : "i" (CPU_FTR_HVMODE), "r" (msg)); 43919ca868SIan Munsie } 44919ca868SIan Munsie 45b87ac021SNicholas Piggin /* sync before sending message */ 46b87ac021SNicholas Piggin static inline void ppc_msgsnd_sync(void) 47b87ac021SNicholas Piggin { 48b87ac021SNicholas Piggin __asm__ __volatile__ ("sync" : : : "memory"); 49b87ac021SNicholas Piggin } 50b87ac021SNicholas Piggin 51b87ac021SNicholas Piggin /* sync after taking message interrupt */ 52b87ac021SNicholas Piggin static inline void ppc_msgsync(void) 53b87ac021SNicholas Piggin { 546b3edefeSNicholas Piggin /* sync is not required when taking messages from the same core */ 556b3edefeSNicholas Piggin __asm__ __volatile__ (ASM_FTR_IFSET(PPC_MSGSYNC " ; lwsync", "", %0) 566b3edefeSNicholas Piggin : : "i" (CPU_FTR_HVMODE|CPU_FTR_ARCH_300)); 57b87ac021SNicholas Piggin } 58b87ac021SNicholas Piggin 59a9af97aaSNicholas Piggin static inline void _ppc_msgclr(u32 msg) 60a9af97aaSNicholas Piggin { 61a9af97aaSNicholas Piggin __asm__ __volatile__ (ASM_FTR_IFSET(PPC_MSGCLR(%1), PPC_MSGCLRP(%1), %0) 62a9af97aaSNicholas Piggin : : "i" (CPU_FTR_HVMODE), "r" (msg)); 63a9af97aaSNicholas Piggin } 64a9af97aaSNicholas Piggin 65a9af97aaSNicholas Piggin static inline void ppc_msgclr(enum ppc_dbell type) 66a9af97aaSNicholas Piggin { 67a9af97aaSNicholas Piggin u32 msg = PPC_DBELL_TYPE(type); 68a9af97aaSNicholas Piggin 69a9af97aaSNicholas Piggin _ppc_msgclr(msg); 70a9af97aaSNicholas Piggin } 71a9af97aaSNicholas Piggin 7242d02b81SIan Munsie #else /* CONFIG_PPC_BOOK3S */ 7342d02b81SIan Munsie 7442d02b81SIan Munsie #define PPC_DBELL_MSGTYPE PPC_DBELL 7542d02b81SIan Munsie 76919ca868SIan Munsie static inline void _ppc_msgsnd(u32 msg) 77919ca868SIan Munsie { 78919ca868SIan Munsie __asm__ __volatile__ (PPC_MSGSND(%0) : : "r" (msg)); 79919ca868SIan Munsie } 80919ca868SIan Munsie 81b87ac021SNicholas Piggin /* sync before sending message */ 82b87ac021SNicholas Piggin static inline void ppc_msgsnd_sync(void) 83b87ac021SNicholas Piggin { 84b87ac021SNicholas Piggin __asm__ __volatile__ ("sync" : : : "memory"); 85b87ac021SNicholas Piggin } 86b87ac021SNicholas Piggin 87b87ac021SNicholas Piggin /* sync after taking message interrupt */ 88b87ac021SNicholas Piggin static inline void ppc_msgsync(void) 89b87ac021SNicholas Piggin { 90b87ac021SNicholas Piggin } 91b87ac021SNicholas Piggin 9242d02b81SIan Munsie #endif /* CONFIG_PPC_BOOK3S */ 9342d02b81SIan Munsie 94b866cc21SNicholas Piggin extern void doorbell_global_ipi(int cpu); 95b866cc21SNicholas Piggin extern void doorbell_core_ipi(int cpu); 96b866cc21SNicholas Piggin extern int doorbell_try_core_ipi(int cpu); 97b9f1cd71SBenjamin Herrenschmidt extern void doorbell_exception(struct pt_regs *regs); 98620165f9SKumar Gala 99620165f9SKumar Gala static inline void ppc_msgsnd(enum ppc_dbell type, u32 flags, u32 tag) 100620165f9SKumar Gala { 101620165f9SKumar Gala u32 msg = PPC_DBELL_TYPE(type) | (flags & PPC_DBELL_MSG_BRDCAST) | 102620165f9SKumar Gala (tag & 0x07ffffff); 103620165f9SKumar Gala 104919ca868SIan Munsie _ppc_msgsnd(msg); 105620165f9SKumar Gala } 106620165f9SKumar Gala 107620165f9SKumar Gala #endif /* _ASM_POWERPC_DBELL_H */ 108