From f08700ec353ff65467239241558fcdf1a87e377f Mon Sep 17 00:00:00 2001 From: Glenn Miles Date: Fri, 27 Feb 2015 13:33:34 -0600 Subject: Add external interrupt support for standard PPE's Change-Id: I5ac49d4a9aace2dfbe3cdebf0dd7942c1e22da4e Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/16240 Reviewed-by: Glenn R. Miles Tested-by: Glenn R. Miles --- pk/README | 8 ++ pk/cme/Makefile | 50 ---------- pk/cme/cme.h | 22 ---- pk/cme/cme_common.h | 57 ----------- pk/cme/cme_init.c | 25 ----- pk/cme/pk_port.h | 16 --- pk/cme/pkcmefiles.mk | 33 ------ pk/gpe/gpe_init.c | 1 - pk/ppe42/div64.S | 13 --- pk/ppe42/ppe42.h | 43 +++++++- pk/ppe42/ppe42_asm.h | 216 +++++++++++++++++++++++++++++++++++++--- pk/ppe42/ppe42_irq.h | 4 + pk/std/Makefile | 50 ++++++++++ pk/std/pk_port.h | 16 +++ pk/std/pkstdfiles.mk | 33 ++++++ pk/std/std.h | 20 ++++ pk/std/std_common.h | 54 ++++++++++ pk/std/std_init.c | 50 ++++++++++ pk/std/std_irq.h | 86 ++++++++++++++++ pk/std/std_irq_config.h | 141 ++++++++++++++++++++++++++ pk/std/std_irq_init.c | 107 ++++++++++++++++++++ pk/std/std_register_addresses.h | 49 +++++++++ 22 files changed, 859 insertions(+), 235 deletions(-) create mode 100644 pk/README delete mode 100644 pk/cme/Makefile delete mode 100644 pk/cme/cme.h delete mode 100644 pk/cme/cme_common.h delete mode 100644 pk/cme/cme_init.c delete mode 100644 pk/cme/pk_port.h delete mode 100644 pk/cme/pkcmefiles.mk create mode 100644 pk/std/Makefile create mode 100644 pk/std/pk_port.h create mode 100644 pk/std/pkstdfiles.mk create mode 100644 pk/std/std.h create mode 100644 pk/std/std_common.h create mode 100644 pk/std/std_init.c create mode 100644 pk/std/std_irq.h create mode 100644 pk/std/std_irq_config.h create mode 100644 pk/std/std_irq_init.c create mode 100644 pk/std/std_register_addresses.h diff --git a/pk/README b/pk/README new file mode 100644 index 00000000..2227ec37 --- /dev/null +++ b/pk/README @@ -0,0 +1,8 @@ +Subdirectories are organized as follows: + +kernel: Architecture-independent kernel code +ppe42: Kernel code that is common for all ppe42 instances +std: External interrupt support for standard ppe42 instances (SBE, CME, etc.) +gpe: External interrupt support for ppe42 instances residing in the OCC complex +ppe: Support for ppe42 instances that do not require or have external interrupts +trace: Kernel trace support diff --git a/pk/cme/Makefile b/pk/cme/Makefile deleted file mode 100644 index 60c82c87..00000000 --- a/pk/cme/Makefile +++ /dev/null @@ -1,50 +0,0 @@ -# This Makefile compiles all of the PK code required for the CME port -# of PK. See the "pk.mk" file in this directory. - -#all generated files from this makefile will end up in obj/$(IMAGE_NAME)/pk -export SUB_OBJDIR = /pk - -include img_defs.mk -include pkcmefiles.mk - -ifeq "$(PK_TIMER_SUPPORT)" "1" -CME_OBJECTS += ${CME-TIMER-C-SOURCES:.c=.o} ${CME-TIMER-S-SOURCES:.S=.o} -endif - -ifeq "$(PK_THREAD_SUPPORT)" "1" -CME_OBJECTS += ${CME-THREAD-C-SOURCES:.c=.o} ${CME-THREAD-S-SOURCES:.S=.o} -endif - -ifeq "$(CME_ASYNC_SUPPORT)" "1" -CME_OBJECTS += ${CME-ASYNC-C-SOURCES:.c=.o} ${CME-ASYNC-S-SOURCES:.S=.o} -endif - -OBJS := $(addprefix $(OBJDIR)/, $(CME_OBJECTS)) - -libpk.a: kernel ppe42 trace cme - $(AR) crs $(OBJDIR)/libpk.a $(OBJDIR)/*.o - -.PHONY: clean cme kernel ppe42 trace -cme: $(OBJS) - -trace: - $(MAKE) -I $(IMAGE_SRCDIR) -C ../trace - -kernel: - $(MAKE) -I $(IMAGE_SRCDIR) -C ../kernel - -ppe42: - $(MAKE) -I $(IMAGE_SRCDIR) -C ../ppe42 - - -$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) - -$(OBJDIR): - mkdir -p $(OBJDIR) - -clean: - rm -fr $(OBJDIR) - -ifneq ($(MAKECMDGOALS),clean) -include $(OBJS:.o=.d) -endif diff --git a/pk/cme/cme.h b/pk/cme/cme.h deleted file mode 100644 index d789ff3b..00000000 --- a/pk/cme/cme.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef __CME_H__ -#define __CME_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pgp.h -/// \brief The CME environment for PK. - -// This is a 'circular' reference in PK, but included here to simplify PGAS -// programming. - -#ifndef HWMACRO_CME -#define HWMACRO_CME -#include "ppe42.h" -#endif - -#include "cme_common.h" - -#endif /* __CME_H__ */ diff --git a/pk/cme/cme_common.h b/pk/cme/cme_common.h deleted file mode 100644 index 23eb59ff..00000000 --- a/pk/cme/cme_common.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef __CME_COMMON_H__ -#define __CME_COMMON_H__ - -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file cme_common.h -/// \brief Common header for CME -/// -/// This header is maintained as part of the PK port for CME, but needs to be -/// physically present in the PMX area to allow dropping PMX code as a whole -/// to other teams. - -// -*- WARNING: This file is maintained as part of PK. Do not edit in -*- -// -*- the PMX area as your edits will be lost. -*- - -#ifndef __ASSEMBLER__ -#include -#endif - -/// This constant is used to define the size of the table of interrupt handler -/// structures as well as a limit for error checking. -/// NOTE: This can be specific to each PPE type (SBE, CME, GPE) -#define EXTERNAL_IRQS 64 - -#ifdef __ASSEMBLER__ -/// This macro contains CME specific code for determining what IRQ caused the -/// external exception handler to be invoked by the PPE - -/// Load noncritical status 0 and the handler array base address. Check -/// for interrupts pending in status register 0 while the IRQ is -/// computed. The IRQ is expected to be stored in r3. - .macro hwmacro_get_ext_irq - -#_lwzi %r4, %r4, OCB_ONISR0 - cntlzw %r3, %r4 - cmpwible %r3, 31, external_irq_found #branch if irq is lt or eq to 31 - - ## No IRQ pending in interrupt set 0. Try set 1. - -#_lwzi %r4, %r4, OCB_ONISR1 - cntlzw %r3, %r4 - addi %r3, %r3, 32 - - .endm - -/// Redirect the .hwmacro_irq_cfg_bitmaps macro to call our cme specific implementation -/// This is called from the ppe42_exceptions.S file. - .macro .hwmacro_irq_cfg_bitmaps - .endm - -#endif /* __ASSEMBLER__ */ - -#endif /* __CME_COMMON_H__ */ diff --git a/pk/cme/cme_init.c b/pk/cme/cme_init.c deleted file mode 100644 index 3a0c3910..00000000 --- a/pk/cme/cme_init.c +++ /dev/null @@ -1,25 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file cme_init.c -/// \brief PK initialization for CME -/// -/// The entry points in this routine are used during initialization. This -/// code space can be deallocated and reassigned after application -/// initialization if required. - -#include "pk.h" - -/// CME environment initial setup. -/// -/// This is setup common to all CME HW Macro applications. This setup takes place -/// during boot, before main() is called. - -void -__hwmacro_setup(void) -{ - //async_initialize(); -} diff --git a/pk/cme/pk_port.h b/pk/cme/pk_port.h deleted file mode 100644 index bf750d13..00000000 --- a/pk/cme/pk_port.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __PK_PORT_H__ -#define __PK_PORT_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_port.h -/// \brief The top-level CME environment header for PK. - -#define HWMACRO_CME - -#include "ppe42.h" - -#endif /* __PK_PORT_H__ */ diff --git a/pk/cme/pkcmefiles.mk b/pk/cme/pkcmefiles.mk deleted file mode 100644 index 66b0e4fb..00000000 --- a/pk/cme/pkcmefiles.mk +++ /dev/null @@ -1,33 +0,0 @@ -# @file pkcmefiles.mk -# -# @brief mk for including cme object files -# -# @page ChangeLogs Change Logs -# @section pkcmefiles.mk -# @verbatim -# -# -# Change Log ****************************************************************** -# Flag Defect/Feature User Date Description -# ------ -------------- ---------- ------------ ----------- -# -# @endverbatim -# -########################################################################## -# Object Files -########################################################################## - -CME-C-SOURCES = cme_init.c -CME-S-SOURCES = - -CME-TIMER-C-SOURCES = -CME-TIMER-S-SOURCES = - -CME-THREAD-C-SOURCES = -CME-THREAD-S-SOURCES = - -CME-ASYNC-C-SOURCES = -CME-ASYNC-S-SOURCES = - -CME_OBJECTS += $(CME-C-SOURCES:.c=.o) $(CME-S-SOURCES:.S=.o) - diff --git a/pk/gpe/gpe_init.c b/pk/gpe/gpe_init.c index 3801a2bd..b32c875b 100644 --- a/pk/gpe/gpe_init.c +++ b/pk/gpe/gpe_init.c @@ -119,5 +119,4 @@ __hwmacro_setup(void) //Wait for the last out32 operation to complete sync(); - //async_initialize(); } diff --git a/pk/ppe42/div64.S b/pk/ppe42/div64.S index 69de53b3..7d4b1ffa 100644 --- a/pk/ppe42/div64.S +++ b/pk/ppe42/div64.S @@ -60,19 +60,6 @@ #include "pk.h" .list - .set r0, 0 - .set r1, 1 - .set r3, 3 - .set r4, 4 - .set r5, 5 - .set r6, 6 - .set r7, 7 - .set r8, 8 - .set r9, 9 - .set r10, 10 - .set r30, 30 - .set r31, 31 - .global_function __ppe42_udiv64 /* diff --git a/pk/ppe42/ppe42.h b/pk/ppe42/ppe42.h index affd7f51..91ef5bf4 100644 --- a/pk/ppe42/ppe42.h +++ b/pk/ppe42/ppe42.h @@ -29,10 +29,8 @@ #ifdef HWMACRO_GPE #include "gpe.h" -#elif defined(HWMACRO_SBE) -#include "sbe.h" -#elif defined(HWMACRO_CME) -#include "cme.h" +#elif defined(HWMACRO_STD) +#include "std.h" #elif defined(HWMACRO_PPE) #include "ppe.h" #else @@ -154,6 +152,8 @@ do {*(volatile uint32_t *)(addr) = (data);} while(0) #define in32(addr) \ ({uint32_t __data = *(volatile uint32_t *)(addr); __data;}) +#ifdef HWMACRO_GPE + /// 64-bit MMIO Write #define out64(addr, data) \ do { \ @@ -164,6 +164,24 @@ do {*(volatile uint32_t *)(addr) = (data);} while(0) *__addr_lo = (__data & 0xffffffff); \ } while(0) +#else /* standard PPE's require a 64 bit write */ + +/// 64-bit MMIO Write +#define out64(addr, data) \ +{\ + uint64_t __d = (data); \ + uint32_t* __a = (uint32_t*)(addr); \ + asm volatile \ + (\ + "stvd %1, %0 \n" \ + : "=o"(*__a) \ + : "r"(__d) \ + ); \ +} + +#endif /* HWMACRO_GPE */ + +#ifdef HWMACRO_GPE /// 64-bit MMIO Read #define in64(addr) \ ({ \ @@ -174,6 +192,23 @@ do {*(volatile uint32_t *)(addr) = (data);} while(0) __data = (__data << 32) | *__addr_lo; \ __data;}) +#else /* Standard PPE's require a 64 bit read */ + +#define in64(addr) \ +({\ + uint64_t __d; \ + uint32_t* __a = (uint32_t*)(addr); \ + asm volatile \ + (\ + "lvd %0, %1 \n" \ + :"=r"(__d) \ + :"o"(*__a) \ + ); \ + __d; \ +}) + +#endif /* HWMACRO_GPE */ + #endif /* __ASSEMBLER__ */ #include "ppe42_irq.h" diff --git a/pk/ppe42/ppe42_asm.h b/pk/ppe42/ppe42_asm.h index 4a2e3aec..dd586706 100644 --- a/pk/ppe42/ppe42_asm.h +++ b/pk/ppe42/ppe42_asm.h @@ -201,20 +201,6 @@ #ifdef __ASSEMBLER__ -### **************************************************************************** -### TODO: shouldnt these be supported by the assembler?? -### **************************************************************************** -# .macro lis treg, imm -# addis \treg, 0, imm -# .endm - -# .macro li treg, imm -# addi \treg, 0, imm -# .endm - -# .macro beq target -# bc 12, 2, \target -# .endm ### **************************************************************************** ### _lzi @@ -409,6 +395,208 @@ .size \symbol, . - \symbol .endm +### *************************************************************************** +### 64-bit macros +### *************************************************************************** + +### *************************************************************************** +### Using symbols for register names makes the code more readable and allows +### us to do register arithmetic within macros. +### *************************************************************************** + +.equiv r0, 0 +.equiv r1, 1 +.equiv sp, 1 +.equiv r3, 3 +.equiv r4, 4 +.equiv r5, 5 +.equiv r6, 6 +.equiv r7, 7 +.equiv r8, 8 +.equiv r9, 9 +.equiv r10, 10 + +.equiv r28, 28 +.equiv r29, 29 +.equiv r30, 30 +.equiv r31, 31 + +.equiv d3, 3 +.equiv d4, 4 +.equiv d5, 5 +.equiv d6, 6 +.equiv d7, 7 +.equiv d8, 8 +.equiv d9, 9 +.equiv d10, 10 +.equiv d28, 28 +.equiv d29, 29 +.equiv d30, 30 +.equiv d31, 31 + +### *************************************************************************** +### Load virtual doubleword generic. Load a virtual doubleword from a relocatable +### address expression. If the optional RA is specified, the address remains in +### RA. +### *************************************************************************** +.macro _lvdg DT:req addr:req RA=-1 + .if \RA == -1 + lis \DT, (\addr)@ha + lvd \DT, (\addr)@l(\DT) + .else + lis \RA, (\addr)@ha + lvdu \DT, (\addr)@l(\RA) + .endif +.endm + +### *************************************************************************** +### Load virtual doubleword from a relocatable small data area address +### *************************************************************************** +.macro _lvdsd DT:req addr:req + lvd \DT, (\addr)@sda21(0) +.endm + +### *************************************************************************** +### Store virtual doubleword generic. Store a virtual doubleword based on a +### relocatable address expression. The address remains in RA. +### *************************************************************************** +.macro _stvdg DS:req addr:req RA:req + lis \RA, (\addr)@ha + stvdu \DS, (\addr)@l(\RA) +.endm + +### *************************************************************************** +### Store virtual doubleword to a relocatable small data address expression +### *************************************************************************** +.macro _stvdsd DS:req addr:req + stvd \DS, (\addr)@sda21(0) +.endm + +### *************************************************************************** +### Load virtual doubleword absolute. Set DT to an absolute 64-bit constant +### *************************************************************************** +.macro _lvda DT, cvalue + lwa (\DT + 1)%32, (\cvalue) & 0x00000000ffffffff + lwa \DT, (\cvalue) >> 32 +.endm + +### *************************************************************************** +### +### 64-bit arithmetic macros +### +### *************************************************************************** + +.macro check_overlap2 DA, DB + .if ((\DA - \DB) % 32) == 1 || ((\DA - \DB) % 32) == -1 + .error "virtual doubleword registers must be identical or non-overlapping" + .endif +.endm + +.macro check_overlap3 DA, DB, DC + check_overlap2 \DA, \DB + check_overlap2 \DA, \DC + check_overlap2 \DB, \DC +.endm + +### *************************************************************************** +### Add virtual doubleword carrying +### *************************************************************************** +.macro _addvdc DT, DA, DB + check_overlap3 \DT, \DA, \DB + addc (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 + adde \DT, \DA, \DB +.endm + +### *************************************************************************** +### Add virtual doubleword to signed 16-bit immediate carrying +### *************************************************************************** +.macro _addvdic DT, DA, SI + .if \DA == 31 + .error "d31 for addend register is not supported" + .endif + check_overlap2 \DT, \DA + addi (\DT+1)%32, \DA+1, SI + addze \DT, \DA +.endm + +### *************************************************************************** +### Add virtual doubleword to unsigned word carrying +### *************************************************************************** +.macro _addvdwuc DT, DA, RB + check_overlap2 \DT, \DA + addc (\DT+1)%32, (\DA+1)%32, \RB + addze \DT, \DA +.endm + +### *************************************************************************** +### Subtract virtual doubleword carrying +### *************************************************************************** +.macro _subvdc DT, DA, DB + check_overlap3 \DT, \DA, \DB + subfc (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 + subfe \DT, \DA, \DB +.endm + +### *************************************************************************** +### +### 64-bit logic macros +### +### *************************************************************************** + +### *************************************************************************** +### AND virtual doubleword +### *************************************************************************** +.macro _andvd DT, DA, DB + check_overlap3 \DT, \DA, \DB + and (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 + and \DT, \DA, \DB +.endm + +### *************************************************************************** +### ANDC virtual doubleword +### *************************************************************************** +.macro _andcvd DT, DA, DB + check_overlap3 \DT, \DA, \DB + andc (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 + andc \DT, \DA, \DB +.endm + +### *************************************************************************** +### EQV virtual doubleword +### *************************************************************************** +.macro _eqvvd DT, DA, DB + check_overlap3 \DT, \DA, \DB + eqv (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 + eqv \DT, \DA, \DB +.endm + +### *************************************************************************** +### OR virtual doubleword +### *************************************************************************** +.macro _orvd DT, DA, DB + check_overlap3 \DT, \DA, \DB + or (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 + or \DT, \DA, \DB +.endm + +### *************************************************************************** +### ORC virtual doubleword +### *************************************************************************** +.macro _orcvd DT, DA, DB + check_overlap3 \DT, \DA, \DB + orc (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 + orc \DT, \DA, \DB +.endm + +### *************************************************************************** +### XOR virtual doubleword +### *************************************************************************** +.macro _xorvd DT, DA, DB + check_overlap3 \DT, \DA, \DB + xor (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 + xor \DT, \DA, \DB +.endm + #endif /* __ASSEMBLER__ */ /// \endcond diff --git a/pk/ppe42/ppe42_irq.h b/pk/ppe42/ppe42_irq.h index 3c45a863..6567af64 100644 --- a/pk/ppe42/ppe42_irq.h +++ b/pk/ppe42/ppe42_irq.h @@ -219,6 +219,10 @@ asm("b __pk_irq_full_mode_exit"); #ifdef HWMACRO_GPE #include "gpe_irq.h" +#else +#ifdef HWMACRO_STD +#include "std_irq.h" +#endif #endif /// \page ppe42_irq_macros_page PPE42 PK IRQ Assembler Macros diff --git a/pk/std/Makefile b/pk/std/Makefile new file mode 100644 index 00000000..4101935d --- /dev/null +++ b/pk/std/Makefile @@ -0,0 +1,50 @@ +# This Makefile compiles all of the PK code required for the STD (standard PPE) port +# of PK. See the "pk.mk" file in this directory. + +#all generated files from this makefile will end up in obj/$(IMAGE_NAME)/pk +export SUB_OBJDIR = /pk + +include img_defs.mk +include pkstdfiles.mk + +ifeq "$(PK_TIMER_SUPPORT)" "1" +STD_OBJECTS += ${STD-TIMER-C-SOURCES:.c=.o} ${STD-TIMER-S-SOURCES:.S=.o} +endif + +ifeq "$(PK_THREAD_SUPPORT)" "1" +STD_OBJECTS += ${STD-THREAD-C-SOURCES:.c=.o} ${STD-THREAD-S-SOURCES:.S=.o} +endif + +ifeq "$(STD_ASYNC_SUPPORT)" "1" +STD_OBJECTS += ${STD-ASYNC-C-SOURCES:.c=.o} ${STD-ASYNC-S-SOURCES:.S=.o} +endif + +OBJS := $(addprefix $(OBJDIR)/, $(STD_OBJECTS)) + +libpk.a: kernel ppe42 trace std + $(AR) crs $(OBJDIR)/libpk.a $(OBJDIR)/*.o + +.PHONY: clean std kernel ppe42 trace +std: $(OBJS) + +trace: + $(MAKE) -I $(IMAGE_SRCDIR) -C ../trace + +kernel: + $(MAKE) -I $(IMAGE_SRCDIR) -C ../kernel + +ppe42: + $(MAKE) -I $(IMAGE_SRCDIR) -C ../ppe42 + + +$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) + +$(OBJDIR): + mkdir -p $(OBJDIR) + +clean: + rm -fr $(OBJDIR) + +ifneq ($(MAKECMDGOALS),clean) +include $(OBJS:.o=.d) +endif diff --git a/pk/std/pk_port.h b/pk/std/pk_port.h new file mode 100644 index 00000000..5998bd4b --- /dev/null +++ b/pk/std/pk_port.h @@ -0,0 +1,16 @@ +#ifndef __PK_PORT_H__ +#define __PK_PORT_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pk_port.h +/// \brief The top-level standard PPE environment header for PK. + +#define HWMACRO_STD + +#include "ppe42.h" + +#endif /* __PK_PORT_H__ */ diff --git a/pk/std/pkstdfiles.mk b/pk/std/pkstdfiles.mk new file mode 100644 index 00000000..7133bd47 --- /dev/null +++ b/pk/std/pkstdfiles.mk @@ -0,0 +1,33 @@ +# @file pkstdfiles.mk +# +# @brief mk for including std object files +# +# @page ChangeLogs Change Logs +# @section pkstdfiles.mk +# @verbatim +# +# +# Change Log ****************************************************************** +# Flag Defect/Feature User Date Description +# ------ -------------- ---------- ------------ ----------- +# +# @endverbatim +# +########################################################################## +# Object Files +########################################################################## + +STD-C-SOURCES = std_init.c std_irq_init.c +STD-S-SOURCES = + +STD-TIMER-C-SOURCES = +STD-TIMER-S-SOURCES = + +STD-THREAD-C-SOURCES = +STD-THREAD-S-SOURCES = + +STD-ASYNC-C-SOURCES = +STD-ASYNC-S-SOURCES = + +STD_OBJECTS += $(STD-C-SOURCES:.c=.o) $(STD-S-SOURCES:.S=.o) + diff --git a/pk/std/std.h b/pk/std/std.h new file mode 100644 index 00000000..c4e9dda6 --- /dev/null +++ b/pk/std/std.h @@ -0,0 +1,20 @@ +#ifndef __STD_H__ +#define __STD_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp.h +/// \brief The STD environment for PK. + +#ifndef HWMACRO_STD +#define HWMACRO_STD +#include "ppe42.h" +#endif + +#include "std_register_addresses.h" +#include "std_common.h" + +#endif /* __STD_H__ */ diff --git a/pk/std/std_common.h b/pk/std/std_common.h new file mode 100644 index 00000000..3c8fda2d --- /dev/null +++ b/pk/std/std_common.h @@ -0,0 +1,54 @@ +#ifndef __STD_COMMON_H__ +#define __STD_COMMON_H__ + +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file cme_common.h +/// \brief Common header for standard PPE's +/// + +#ifndef __ASSEMBLER__ +#include +#endif + +//#include "cmehw_interrupts.h" +#include "pk.h" +#include "std_irq_config.h" + +#ifdef __ASSEMBLER__ +/// This macro contains standard PPE code for determining what IRQ caused the +/// external exception handler to be invoked by the PPE + +/// Check for interrupts pending in the interrupt status register while the IRQ +/// is computed. The IRQ is expected to be stored in r4. If no IRQ is +/// pending then load the phantom irq # (EXTERNAL_IRQS). +/// Only the following registers have been saved off and can be used: +/// r3, r4, r5, r6, cr0, lr +/// + .macro hwmacro_get_ext_irq + + _lvdg d5, STD_LCL_EISTR #load the 64bit interrupt status into d5 + cntlzw r4, r5 + cmpwible r4, 31, external_irq_found #branch if irq is lt or eq to 31 + + ## No IRQ pending in r5. Try r6. + ## Note: irq # will be 64 (phantom irq) if no bits were set in either register + + cntlzw r4, r6 + addi r4, r4, 32 + + .endm + +/// Redirect the .hwmacro_irq_cfg_bitmaps macro to call our standard PPE implementation +/// This is called from the ppe42_exceptions.S file. + .macro .hwmacro_irq_cfg_bitmaps + .std_irq_cfg_bitmaps + .endm + +#endif /* __ASSEMBLER__ */ + +#endif /* __STD_COMMON_H__ */ diff --git a/pk/std/std_init.c b/pk/std/std_init.c new file mode 100644 index 00000000..b0aae325 --- /dev/null +++ b/pk/std/std_init.c @@ -0,0 +1,50 @@ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file std_init.c +/// \brief PK initialization for a standard PPE. +/// +/// The entry points in this routine are used during initialization. This +/// code space can be deallocated and reassigned after application +/// initialization if required. + +#include "pk.h" + +/// Standard PPE environment initial setup. +/// +/// This is setup common to all standard PPE Macro applications. This setup takes place +/// during boot, before main() is called. + +void +__hwmacro_setup(void) +{ + //mask all interrupts + out64(STD_LCL_EIMR_OR, 0xffffffffffffffffull); + + //Set all interrupts to active low, level sensitive by default + out64(STD_LCL_EIPR_CLR, 0xffffffffffffffffull); + out64(STD_LCL_EITR_CLR, 0xffffffffffffffffull); + + //set up the configured type + out64(STD_LCL_EITR_OR, g_ext_irqs_type); + + //set up the configured polarity + out64(STD_LCL_EIPR_OR, g_ext_irqs_polarity); + + //clear the status of all active-high interrupts (has no affect on + //level sensitive interrupts) + out64(STD_LCL_EISR_CLR, g_ext_irqs_polarity); + + //clear the status of all active-low interrupts (has no affect on + //level sensitive interrupts) + out64(STD_LCL_EISR_OR, ~g_ext_irqs_polarity); + + //unmask the interrupts that are to be enabled by default + out64(STD_LCL_EIMR_CLR, g_ext_irqs_enable); + + //wait for the last operation to complete + sync(); +} diff --git a/pk/std/std_irq.h b/pk/std/std_irq.h new file mode 100644 index 00000000..3920997e --- /dev/null +++ b/pk/std/std_irq.h @@ -0,0 +1,86 @@ +#ifndef __STD_IRQ_H__ +#define __STD_IRQ_H__ + +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file occhw_irq.h +/// \brief Standard PPE Externnal Interrupt handling for PK +/// +/// The standard PPE interrupt controller supports a maximum of 64 interrupts with +/// simple OR combining of the interrupt signals. +/// +/// The standard PPE interrupt controller allows interrupt status to be set directly by +/// software. It contains a 'mask' register, unlike most 405 interrupt +/// controllers that have an 'enable' register. The standard PPE mask and status +/// registers also have atomic CLR/OR function so that it is never necessary +/// to enter a critical section to enable/disable/clear interrupts and +/// interrupt status. + +#include "std_common.h" +#include "std_register_addresses.h" +#include "ppe42.h" + +#ifndef __ASSEMBLER__ + +/// Enable an interrupt by clearing the mask bit. + +UNLESS__PPE42_IRQ_CORE_C__(extern) +inline void +pk_irq_enable(PkIrqId irq) +{ + out64(STD_LCL_EIMR_CLR, STD_IRQ_MASK64(irq)); +} + + +/// Disable an interrupt by setting the mask bit. + +UNLESS__PPE42_IRQ_CORE_C__(extern) +inline void +pk_irq_disable(PkIrqId irq) +{ + out64(STD_LCL_EIMR_OR, STD_IRQ_MASK64(irq)); +} + + +/// Clear interrupt status with an CLR mask. Only meaningful for +/// edge-triggered interrupts. + +UNLESS__PPE42_IRQ_CORE_C__(extern) +inline void +pk_irq_status_clear(PkIrqId irq) +{ + out64(STD_LCL_EISR_CLR, STD_IRQ_MASK64(irq)); +} + + +/// Get IRQ status as a 0 or non-0 integer + +UNLESS__PPE42_IRQ_CORE_C__(extern) +inline int +pk_irq_status_get(PkIrqId irq) +{ + return (in64(STD_LCL_EISR) & STD_IRQ_MASK64(irq)) != 0; +} + + +/// Set or clear interrupt status explicitly. + +UNLESS__PPE42_IRQ_CORE_C__(extern) +inline void +pk_irq_status_set(PkIrqId irq, int value) +{ + if (value) { + out64(STD_LCL_EISR_OR, STD_IRQ_MASK64(irq)); + } else { + out64(STD_LCL_EISR_CLR, STD_IRQ_MASK64(irq)); + } +} + + +#endif /* __ASSEMBLER__ */ + +#endif /* __STD_IRQ_H__ */ diff --git a/pk/std/std_irq_config.h b/pk/std/std_irq_config.h new file mode 100644 index 00000000..a3d9426e --- /dev/null +++ b/pk/std/std_irq_config.h @@ -0,0 +1,141 @@ +#ifndef __STD_IRQ_CONFIG_H__ +#define __STD_IRQ_CONFIG_H__ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2015 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file std_irq_config.h +/// \brief Contains data and macros pertaining to external interrupt +/// configuration for a standard PPE. +/// + +/// This constant is used to define the size of the table of interrupt handler +/// structures as well as a limit for error checking. +#define EXTERNAL_IRQS 64 + +// Standard interrupt type values (level or edge) +#define STD_IRQ_TYPE_LEVEL 0 +#define STD_IRQ_TYPE_EDGE 1 + +// Standard interrupt polarity values (high or low, rising falling) +#define STD_IRQ_POLARITY_LO 0 +#define STD_IRQ_POLARITY_FALLING 0 +#define STD_IRQ_POLARITY_HI 1 +#define STD_IRQ_POLARITY_RISING 1 + +// Standard interrupt mask values (masked or enabled) +#define STD_IRQ_MASKED 0 +#define STD_IRQ_ENABLED 1 + +// Fail to compile if the application does not define this +#ifndef APPCFG_EXT_IRQS_CONFIG +#error "APPCFG_EXT_IRQS_CONFIG must be defined in pk_app_cfg.h" +#endif + +// Fail to compile if the application does not define this +#ifndef APPCFG_IRQ_INVALID_MASK +#error "APPCFG_IRQ_INVALID_MASK must be defined in pk_app_cfg.h" +#endif + +#ifndef __ASSEMBLER__ + +/// This expression recognizes only those IRQ numbers that have named +/// (non-reserved) interrupts in the standard PPE interrupt controller. +#define STD_IRQ_VALID(irq) \ + ({unsigned __irq = (unsigned)(irq); \ + ((__irq < EXTERNAL_IRQS) && \ + ((STD_IRQ_MASK64(__irq) & \ + APPCFG_IRQ_INVALID_MASK) == 0));}) + +/// This is a 64-bit mask, with big-endian bit 'irq' set. +#define STD_IRQ_MASK64(irq) (0x8000000000000000ull >> (irq)) + +#else + +//Untyped assembler version of STD_IRQ_MASK64 +#define STD_IRQ_MASK64(irq) (0x8000000000000000 >> (irq)) + +#endif /* __ASSEMBLER__ */ + +#ifndef __ASSEMBLER__ +/// These globals are statically initialized elsewhere +extern uint64_t g_ext_irqs_type; +extern uint64_t g_ext_irqs_valid; +extern uint64_t g_ext_irqs_polarity; +extern uint64_t g_ext_irqs_enable; +#endif + +#ifdef __ASSEMBLER__ +/// These macros aid in the initialization of the external interrupt globals. I would +/// prefer to use CPP macros, but they don't support recursive macros which I use to +/// convert the variable number of interrupts that a processor can control into static +/// bitmaps used by __hwmacro_setup() at runtime. + + + //helper macro for setting up the irq configuration bitmaps for a standard PPE + .macro .std_irq_config irq_num=-1 irq_type=-1 irq_polarity=-1 irq_mask=-1 parms:vararg + .if (( \irq_num == -1 ) && ( \irq_type == -1 ) && ( \irq_polarity == -1 ) && ( \irq_mask == -1 )) +#.if ( .ext_irqs_defd != .ext_irqs_valid ) +#.error "###### .std_irq_config: Missing configuration for one or more interrupts ######" +#.endif + + .section .sdata + .align 3 + .global g_ext_irqs_type + .global g_ext_irqs_polarity + .global g_ext_irqs_enable + g_ext_irqs_polarity: + .quad .ext_irqs_polarity + g_ext_irqs_type: + .quad .ext_irqs_type + g_ext_irqs_enable: + .quad .ext_irqs_enable + .else + .if (( \irq_num < 0 ) || ( \irq_num > (EXTERNAL_IRQS - 1))) + .error "###### .std_irq_config: invalid irq number \irq_num ######" + .elseif ((.ext_irqs_valid & (1 << ( EXTERNAL_IRQS - 1 - \irq_num ))) == 0 ) + .error "###### .std_irq_config: Attempt to configure invalid irq number \irq_num ######" + .elseif (.ext_irqs_defd & (1 << ( EXTERNAL_IRQS - 1 - \irq_num ))) + .error "###### .std_irq_config: duplicate definition for irq \irq_num ######" + .else + .ext_irqs_defd = .ext_irqs_defd | (1 << ( EXTERNAL_IRQS - 1 - \irq_num )) + .endif + + .if (( \irq_type < 0 ) || ( \irq_type > 1 )) + .error "###### .std_irq_config: invalid/unspecified irq type \irq_type for irq \irq_num ######" + .else + .ext_irqs_type = .ext_irqs_type | ( \irq_type << ( EXTERNAL_IRQS - 1 - \irq_num )) + .endif + + .if (( \irq_polarity < 0 ) || ( \irq_polarity > 1 )) + .error "###### .std_irq_config: invalid/unspecified irq polarity ( \irq_polarity ) for irq \irq_num ######" + .else + .ext_irqs_polarity = .ext_irqs_polarity | ( \irq_polarity << ( EXTERNAL_IRQS - 1 - \irq_num )) + .endif + + .if (( \irq_mask < 0 ) || ( \irq_mask > 1 )) + .error "###### .std_irq_config: invalid/unspecified irq mask ( \irq_mask ) for irq \irq_num ######" + .else + .ext_irqs_enable = .ext_irqs_enable | ( \irq_mask << ( EXTERNAL_IRQS - 1 - \irq_num )) + .endif + + .std_irq_config \parms + .endif + .endm + + //Top level macro for generating interrupt configuration globals for a standard PPE + .macro .std_irq_cfg_bitmaps + .ext_irqs_valid = ~(APPCFG_IRQ_INVALID_MASK) + .ext_irqs_type = 0 + .ext_irqs_polarity = 0 + .ext_irqs_enable = 0 + .irq_mask = 0 + .ext_irqs_defd = 0 + .std_irq_config APPCFG_EXT_IRQS_CONFIG + .endm + +#endif /*__ASSEMBLER__*/ + +#endif /*__STD_IRQ_CONFIG_H__*/ diff --git a/pk/std/std_irq_init.c b/pk/std/std_irq_init.c new file mode 100644 index 00000000..3c383caf --- /dev/null +++ b/pk/std/std_irq_init.c @@ -0,0 +1,107 @@ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2015 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file std_irq_init.c +/// \brief Standard PPE IRQ initialization code for PK +/// +/// The entry points in this file are initialization routines that could be +/// eliminated/deallocated by the application to free up storage if they are +/// no longer needed after initialization. + +#include "pk.h" + +/// Define the polarity and trigger condition for an interrupt. +/// +/// It is up to the application to take care of any side effects that may +/// occur from programming or reprogramming the interrupt controller. For +/// example, changing edge/level sensitivity or active level may set or clear +/// interrupt status in the controller. +/// +/// Note that PK allows this API to be called from any context, and changes +/// to the interrupt controller are made from a critical +/// section. +/// +/// Return values other then PK_OK (0) are errors; see \ref pk_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -PK_INVALID_ARGUMENT_IRQ_SETUP One or more arguments are invalid, +/// including an invalid \a irq, or invalid \a polarity or \a trigger parameters. + +int +pk_irq_setup(PkIrqId irq, + int polarity, + int trigger) +{ + PkMachineContext ctx; + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(!STD_IRQ_VALID(irq) || + !((polarity == PK_IRQ_POLARITY_ACTIVE_HIGH) || + (polarity == PK_IRQ_POLARITY_ACTIVE_LOW)) || + !((trigger == PK_IRQ_TRIGGER_LEVEL_SENSITIVE) || + (trigger == PK_IRQ_TRIGGER_EDGE_SENSITIVE)), + PK_INVALID_ARGUMENT_IRQ_SETUP); + } + + pk_critical_section_enter(&ctx); + + if (polarity == PK_IRQ_POLARITY_ACTIVE_HIGH) { + out64(STD_LCL_EIPR_OR, STD_IRQ_MASK64(irq)); + } else { + out64(STD_LCL_EIPR_CLR, STD_IRQ_MASK64(irq)); + } + + if (trigger == PK_IRQ_TRIGGER_EDGE_SENSITIVE) { + out64(STD_LCL_EITR_OR, STD_IRQ_MASK64(irq)); + } else { + out64(STD_LCL_EITR_CLR, STD_IRQ_MASK64(irq)); + } + + pk_critical_section_exit(&ctx); + + return PK_OK; +} + + +/// (Re)define the IRQ handler and priority for an interrupt. +/// Return values other then PK_OK (0) are errors; see \ref pk_errors +/// +/// Note that PK allows this API to be called from any context, and changes +/// to the interrupt controller are made from a critical +/// section. +/// +/// \retval 0 Successful completion +/// +/// \retval -PK_INVALID_ARGUMENT_IRQ_HANDLER One or more arguments are +/// invalid, including an invalid \a irq, a null (0) \a handler, +/// or invalid \a priority. + +int +pk_irq_handler_set(PkIrqId irq, + PkIrqHandler handler, + void *arg) +{ + PkMachineContext ctx; + + if (PK_ERROR_CHECK_API) { + PK_ERROR_IF(!STD_IRQ_VALID(irq) || + (handler == 0), + PK_INVALID_ARGUMENT_IRQ_HANDLER); + } + + pk_critical_section_enter(&ctx); + + __ppe42_irq_handlers[irq].handler = handler; + __ppe42_irq_handlers[irq].arg = arg; + + pk_critical_section_exit(&ctx); + + return PK_OK; +} + + + diff --git a/pk/std/std_register_addresses.h b/pk/std/std_register_addresses.h new file mode 100644 index 00000000..18153c7e --- /dev/null +++ b/pk/std/std_register_addresses.h @@ -0,0 +1,49 @@ +#ifndef __STD_REGISTER_ADDRESSES_H__ +#define __STD_REGISTER_ADDRESSES_H__ + +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2015 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file std_register_addresses.h +/// \brief Symbolic addresses for a standard PPE + +#include "pk.h" + +// Define the base address for the external interrupt controller registers +// This can be overridden in the pk_app_cfg.h file +#ifndef STD_EIC_BASE +#define STD_EIC_BASE 0xC0000000 +#endif + +// Define the base address for the PPE mode registers +// This can be overridden in the pk_app_cfg.h file +#ifndef STD_PMR_BASE +#define STD_PMR_BASE 0xC0000100 +#endif + +// Note: This list only contains registers that are needed by PK. If +// an application requires other registers, it should define them +// elsewhere (i.e., cme_register_addresses.h) +#define STD_LCL_EISR (STD_EIC_BASE + 0x0000) +#define STD_LCL_EISR_OR (STD_EIC_BASE + 0x0010) +#define STD_LCL_EISR_CLR (STD_EIC_BASE + 0x0018) +#define STD_LCL_EIMR (STD_EIC_BASE + 0x0020) +#define STD_LCL_EIMR_OR (STD_EIC_BASE + 0x0030) +#define STD_LCL_EIMR_CLR (STD_EIC_BASE + 0x0038) +#define STD_LCL_EIPR (STD_EIC_BASE + 0x0040) +#define STD_LCL_EIPR_OR (STD_EIC_BASE + 0x0050) +#define STD_LCL_EIPR_CLR (STD_EIC_BASE + 0x0058) +#define STD_LCL_EITR (STD_EIC_BASE + 0x0060) +#define STD_LCL_EITR_OR (STD_EIC_BASE + 0x0070) +#define STD_LCL_EITR_CLR (STD_EIC_BASE + 0x0078) +#define STD_LCL_EISTR (STD_EIC_BASE + 0x0080) +#define STD_LCL_EINR (STD_EIC_BASE + 0x00a0) + +#define STD_LCL_TSEL (STD_PMR_BASE + 0x0000) +#define STD_LCL_TBR (STD_PMR_BASE + 0x0040) + +#endif // __STD_REGISTER_ADDRESSES_H__ + -- cgit v1.2.1