summaryrefslogtreecommitdiffstats
path: root/pk/gpe/gpe_irq.h
diff options
context:
space:
mode:
authorGlenn Miles <milesg@us.ibm.com>2015-02-18 13:54:50 -0600
committerDerk Rembold <rembold@de.ibm.com>2015-02-19 09:45:49 -0600
commitf7a56090b73768f8fec063e41aba12662ee59a45 (patch)
treed2373137870269e93d215ba65319ad1af4b131c3 /pk/gpe/gpe_irq.h
parentd84a1393ddec82dda67207a6f21edb5153877b5a (diff)
downloadtalos-sbe-f7a56090b73768f8fec063e41aba12662ee59a45.tar.gz
talos-sbe-f7a56090b73768f8fec063e41aba12662ee59a45.zip
Seed the files in the pk directory
Change-Id: I03398098e6625f0e06e4a96769b03002a1c71d35 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/15813 Reviewed-by: Glenn R. Miles <milesg@us.ibm.com> Reviewed-by: Derk Rembold <rembold@de.ibm.com> Tested-by: Derk Rembold <rembold@de.ibm.com>
Diffstat (limited to 'pk/gpe/gpe_irq.h')
-rw-r--r--pk/gpe/gpe_irq.h247
1 files changed, 247 insertions, 0 deletions
diff --git a/pk/gpe/gpe_irq.h b/pk/gpe/gpe_irq.h
new file mode 100644
index 00000000..3b018916
--- /dev/null
+++ b/pk/gpe/gpe_irq.h
@@ -0,0 +1,247 @@
+#ifndef __GPE_IRQ_H__
+#define __GPE_IRQ_H__
+
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file occhw_irq.h
+/// \brief GPE-OCCHW Interrupt handling for PK
+///
+/// The OCCHW interrupt controller supports a maximum of 64 interrupts, split
+/// into 2 x 32-bit non-cascaded interrupt controllers with simple OR
+/// combining of the interrupt signals.
+///
+/// The OCB interrupt controller allows interrupt status to be set directly by
+/// software, as well as providing a mode that causes an enabled pending
+/// interrupt to trigger an Unconditional Debug Event. The OCB interrupt
+/// controller contains a 'mask' register, unlike other 405 interrupt
+/// controllers that have an 'enable' register. The OCCHW 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 "occhw_common.h"
+#include "ocb_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)
+{
+ out32(OCCHW_OIMR_CLR(irq), OCCHW_IRQ_MASK32(irq));
+}
+
+
+/// Disable an interrupt by setting the mask bit.
+
+UNLESS__PPE42_IRQ_CORE_C__(extern)
+inline void
+pk_irq_disable(PkIrqId irq)
+{
+ out32(OCCHW_OIMR_OR(irq), OCCHW_IRQ_MASK32(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)
+{
+ out32(OCCHW_OISR_CLR(irq), OCCHW_IRQ_MASK32(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 (in32(OCCHW_OISR(irq)) & OCCHW_IRQ_MASK32(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) {
+ out32(OCCHW_OISR_OR(irq), OCCHW_IRQ_MASK32(irq));
+ } else {
+ out32(OCCHW_OISR_CLR(irq), OCCHW_IRQ_MASK32(irq));
+ }
+}
+
+
+#endif /* __ASSEMBLER__ */
+
+/// \page occhw_irq_macros OCCHW IRQ API Assembler Macros
+///
+/// These macros encapsulate the PK API for the OCCHW interrupt
+/// controller. These macros require 2 scratch registers in addition to the \c
+/// irq parameter register passed into the handler from PK interrupt
+/// dispatch. These macros also modify CR0.
+///
+/// \arg \c rirq A register that holds the \c irq parameter passed to
+/// the handler from PK interrupt dispatch. This register is not
+/// modified.
+/// \arg \c rmask A scratch register - At the end of macro execution this
+/// register contains the 32-bit mask form of the irq.
+///
+/// \arg \c raddr A scratch register - At the end of macro execution this
+/// register holds the address of the interrupt
+/// controller facility that implements the action.
+///
+/// \arg \c imm An immediate (0/non-0) value for certain macros.
+///
+/// Forms:
+///
+/// \b _pk_irq_enable \a rirq, \a rmask, \a raddr - Enable an \c irq. \n
+/// \b _pk_irq_disable \a rirq, \a rmask, \a raddr - Disable an \c irq. \n
+/// \b _pk_irq_status_clear \a rirq, \a rmask, \a raddr - Clear \c irq
+/// interrupt status. \n
+/// \b _pk_irq_status_set \a rirq, \a rmask, \a raddr, \a imm - Set \c irq status
+/// with an immediate (0/non-0) value. \n
+///
+/// \todo Once the logic design is locked down, revisit whether these macros
+/// (and C-code versions) can be implemented without branching. This could be
+/// done in theory by converting bit 26 into the byte offset between addresses
+/// in interupt controller 0 and interrupt controller 1 - assuming the
+/// distances are all the same power-of-two.
+///
+/// \cond
+
+// IRQ numbers are in the range 0..63. IRQs are converted to the 32-bit
+// residue used to compute the mask. CR0 is set as a test of IRQ > 32 - the
+// register \c raddr is used as scratch for these computations. Hopefully the
+// local labels 888 and 999 are unique enough.
+
+// Register names must be compared as strings - e.g., %r0 is not
+// a symbol, it is converted to "0" by the assembler.
+
+#ifdef __ASSEMBLER__
+
+ .macro .two_unique, ra, rb
+ .ifnc \ra, \rb
+ .exitm
+ .endif
+ .error "Both register arguments must be unique"
+ .endm
+
+
+ .macro .three_unique, ra, rb, rc
+ .ifnc \ra, \rb
+ .ifnc \rb, \rc
+ .ifnc \ra, \rc
+ .exitm
+ .endif
+ .endif
+ .endif
+ .error "All three register arguments must be unique"
+ .endm
+
+
+ .macro _occhw_irq_or_mask, rirq:req, rmask:req
+ .two_unique \rirq, \rmask
+ lis \rmask, 0x8000
+ srw \rmask, \rmask, \rirq
+ .endm
+
+ .macro _occhw_irq_clr_mask, rirq:req, rmask:req
+ .two_unique \rirq, \rmask
+ _occhw_irq_or_mask \rirq, \rmask
+ .endm
+
+
+ .macro _pk_irq_enable, rirq:req, rmask:req, raddr:req
+ .three_unique \rirq, \rmask, \raddr
+
+ andi. \raddr, \rirq, 0x20
+ clrlwi \raddr, \rirq, 27
+ _occhw_irq_clr_mask \raddr, \rmask
+ bne- 888f
+ _stwi \rmask, \raddr, OCB_OIMR0_CLR
+ b 999f
+888:
+ _stwi \rmask, \raddr, OCB_OIMR1_CLR
+999:
+ eieio
+ .endm
+
+
+ .macro _pk_irq_disable, rirq:req, rmask:req, raddr:req
+ .three_unique \rirq, \rmask, \raddr
+
+ andi. \raddr, \rirq, 0x20
+ clrlwi \raddr, \rirq, 27
+ _occhw_irq_or_mask \raddr, \rmask
+ bne- 888f
+ _stwi \rmask, \raddr, OCB_OIMR0_OR
+ b 999f
+888:
+ _stwi \rmask, \raddr, OCB_OIMR1_OR
+999:
+ eieio
+ .endm
+
+
+ .macro _pk_irq_status_clear, rirq:req, rmask:req, raddr:req
+ .three_unique \rirq, \rmask, \raddr
+
+ andi. \raddr, \rirq, 0x20
+ clrlwi \raddr, \rirq, 27
+ _occhw_irq_clr_mask \raddr, \rmask
+ bne- 888f
+ _stwi \rmask, \raddr, OCB_OISR0_CLR
+ b 999f
+888:
+ _stwi \rmask, \raddr, OCB_OISR1_CLR
+999:
+ eieio
+ .endm
+
+
+ .macro _pk_irq_status_set, rirq:req, rmask:req, raddr:req, imm:req
+ .three_unique \rirq, \rmask, \raddr
+
+ andi. \raddr, \rirq, 0x20
+ clrlwi \raddr, \rirq, 27
+
+ .if \imm
+ _occhw_irq_or_mask \raddr, \rmask
+ bne- 888f
+ _stwi \rmask, \raddr, OCB_OISR0_OR
+ b 999f
+888:
+ _stwi \rmask, \raddr, OCB_OISR1_OR
+
+ .else
+
+ _occhw_irq_clr_mask \raddr, \rmask
+ bne- 888f
+ _stwi \rmask, \raddr, OCB_OISR0_CLR
+ b 999f
+888:
+ _stwi \rmask, \raddr, OCB_OISR1_CLR
+ .endif
+
+999:
+ eieio
+ .endm
+
+#endif /* __ASSEMBLER__ */
+
+/// \endcond
+
+#endif /* __GPE_IRQ_H__ */
OpenPOWER on IntegriCloud