diff options
author | Glenn Miles <milesg@us.ibm.com> | 2015-02-18 13:54:50 -0600 |
---|---|---|
committer | Derk Rembold <rembold@de.ibm.com> | 2015-02-19 09:45:49 -0600 |
commit | f7a56090b73768f8fec063e41aba12662ee59a45 (patch) | |
tree | d2373137870269e93d215ba65319ad1af4b131c3 /pk/gpe/gpe_irq.h | |
parent | d84a1393ddec82dda67207a6f21edb5153877b5a (diff) | |
download | talos-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.h | 247 |
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__ */ |