summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Miles <milesg@us.ibm.com>2015-02-27 13:33:34 -0600
committerGlenn R. Miles <milesg@us.ibm.com>2015-03-09 12:10:05 -0500
commitf08700ec353ff65467239241558fcdf1a87e377f (patch)
treee31a9c6655634e3c59f9a509c4ace8daeca09487
parent69207c6c1750b4051b9be1dd9bdd984dd7d3db3d (diff)
downloadtalos-sbe-f08700ec353ff65467239241558fcdf1a87e377f.tar.gz
talos-sbe-f08700ec353ff65467239241558fcdf1a87e377f.zip
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 <milesg@us.ibm.com> Tested-by: Glenn R. Miles <milesg@us.ibm.com>
-rw-r--r--pk/README8
-rw-r--r--pk/cme/cme_common.h57
-rw-r--r--pk/cme/cme_init.c25
-rw-r--r--pk/gpe/gpe_init.c1
-rw-r--r--pk/ppe42/div64.S13
-rw-r--r--pk/ppe42/ppe42.h43
-rw-r--r--pk/ppe42/ppe42_asm.h216
-rw-r--r--pk/ppe42/ppe42_irq.h4
-rw-r--r--pk/std/Makefile (renamed from pk/cme/Makefile)20
-rw-r--r--pk/std/pk_port.h (renamed from pk/cme/pk_port.h)4
-rw-r--r--pk/std/pkstdfiles.mk (renamed from pk/cme/pkcmefiles.mk)24
-rw-r--r--pk/std/std.h (renamed from pk/cme/cme.h)18
-rw-r--r--pk/std/std_common.h54
-rw-r--r--pk/std/std_init.c50
-rw-r--r--pk/std/std_irq.h86
-rw-r--r--pk/std/std_irq_config.h141
-rw-r--r--pk/std/std_irq_init.c107
-rw-r--r--pk/std/std_register_addresses.h49
18 files changed, 772 insertions, 148 deletions
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/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 <stdint.h>
-#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/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
### ****************************************************************************
### _l<b,h,w>zi
@@ -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/cme/Makefile b/pk/std/Makefile
index 60c82c87..4101935d 100644
--- a/pk/cme/Makefile
+++ b/pk/std/Makefile
@@ -1,31 +1,31 @@
-# This Makefile compiles all of the PK code required for the CME port
+# 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 pkcmefiles.mk
+include pkstdfiles.mk
ifeq "$(PK_TIMER_SUPPORT)" "1"
-CME_OBJECTS += ${CME-TIMER-C-SOURCES:.c=.o} ${CME-TIMER-S-SOURCES:.S=.o}
+STD_OBJECTS += ${STD-TIMER-C-SOURCES:.c=.o} ${STD-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}
+STD_OBJECTS += ${STD-THREAD-C-SOURCES:.c=.o} ${STD-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}
+ifeq "$(STD_ASYNC_SUPPORT)" "1"
+STD_OBJECTS += ${STD-ASYNC-C-SOURCES:.c=.o} ${STD-ASYNC-S-SOURCES:.S=.o}
endif
-OBJS := $(addprefix $(OBJDIR)/, $(CME_OBJECTS))
+OBJS := $(addprefix $(OBJDIR)/, $(STD_OBJECTS))
-libpk.a: kernel ppe42 trace cme
+libpk.a: kernel ppe42 trace std
$(AR) crs $(OBJDIR)/libpk.a $(OBJDIR)/*.o
-.PHONY: clean cme kernel ppe42 trace
-cme: $(OBJS)
+.PHONY: clean std kernel ppe42 trace
+std: $(OBJS)
trace:
$(MAKE) -I $(IMAGE_SRCDIR) -C ../trace
diff --git a/pk/cme/pk_port.h b/pk/std/pk_port.h
index bf750d13..5998bd4b 100644
--- a/pk/cme/pk_port.h
+++ b/pk/std/pk_port.h
@@ -7,9 +7,9 @@
//-----------------------------------------------------------------------------
/// \file pk_port.h
-/// \brief The top-level CME environment header for PK.
+/// \brief The top-level standard PPE environment header for PK.
-#define HWMACRO_CME
+#define HWMACRO_STD
#include "ppe42.h"
diff --git a/pk/cme/pkcmefiles.mk b/pk/std/pkstdfiles.mk
index 66b0e4fb..7133bd47 100644
--- a/pk/cme/pkcmefiles.mk
+++ b/pk/std/pkstdfiles.mk
@@ -1,9 +1,9 @@
-# @file pkcmefiles.mk
+# @file pkstdfiles.mk
#
-# @brief mk for including cme object files
+# @brief mk for including std object files
#
# @page ChangeLogs Change Logs
-# @section pkcmefiles.mk
+# @section pkstdfiles.mk
# @verbatim
#
#
@@ -17,17 +17,17 @@
# Object Files
##########################################################################
-CME-C-SOURCES = cme_init.c
-CME-S-SOURCES =
+STD-C-SOURCES = std_init.c std_irq_init.c
+STD-S-SOURCES =
-CME-TIMER-C-SOURCES =
-CME-TIMER-S-SOURCES =
+STD-TIMER-C-SOURCES =
+STD-TIMER-S-SOURCES =
-CME-THREAD-C-SOURCES =
-CME-THREAD-S-SOURCES =
+STD-THREAD-C-SOURCES =
+STD-THREAD-S-SOURCES =
-CME-ASYNC-C-SOURCES =
-CME-ASYNC-S-SOURCES =
+STD-ASYNC-C-SOURCES =
+STD-ASYNC-S-SOURCES =
-CME_OBJECTS += $(CME-C-SOURCES:.c=.o) $(CME-S-SOURCES:.S=.o)
+STD_OBJECTS += $(STD-C-SOURCES:.c=.o) $(STD-S-SOURCES:.S=.o)
diff --git a/pk/cme/cme.h b/pk/std/std.h
index d789ff3b..c4e9dda6 100644
--- a/pk/cme/cme.h
+++ b/pk/std/std.h
@@ -1,5 +1,5 @@
-#ifndef __CME_H__
-#define __CME_H__
+#ifndef __STD_H__
+#define __STD_H__
//-----------------------------------------------------------------------------
// *! (C) Copyright International Business Machines Corp. 2014
// *! All Rights Reserved -- Property of IBM
@@ -7,16 +7,14 @@
//-----------------------------------------------------------------------------
/// \file pgp.h
-/// \brief The CME environment for PK.
+/// \brief The STD environment for PK.
-// This is a 'circular' reference in PK, but included here to simplify PGAS
-// programming.
-
-#ifndef HWMACRO_CME
-#define HWMACRO_CME
+#ifndef HWMACRO_STD
+#define HWMACRO_STD
#include "ppe42.h"
#endif
-#include "cme_common.h"
+#include "std_register_addresses.h"
+#include "std_common.h"
-#endif /* __CME_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 <stdint.h>
+#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__
+
OpenPOWER on IntegriCloud