2005-09-27 13:51:59 +10:00
# ifndef _ASM_POWERPC_MPIC_H
# define _ASM_POWERPC_MPIC_H
2005-12-16 22:43:46 +01:00
# ifdef __KERNEL__
2005-09-27 13:51:59 +10:00
2005-09-26 16:04:21 +10:00
# include <linux/irq.h>
2007-05-02 16:33:41 +10:00
# include <linux/sysdev.h>
2006-11-11 17:24:55 +11:00
# include <asm/dcr.h>
2005-09-26 16:04:21 +10:00
/*
* Global registers
*/
# define MPIC_GREG_BASE 0x01000
# define MPIC_GREG_FEATURE_0 0x00000
# define MPIC_GREG_FEATURE_LAST_SRC_MASK 0x07ff0000
# define MPIC_GREG_FEATURE_LAST_SRC_SHIFT 16
# define MPIC_GREG_FEATURE_LAST_CPU_MASK 0x00001f00
# define MPIC_GREG_FEATURE_LAST_CPU_SHIFT 8
# define MPIC_GREG_FEATURE_VERSION_MASK 0xff
# define MPIC_GREG_FEATURE_1 0x00010
# define MPIC_GREG_GLOBAL_CONF_0 0x00020
# define MPIC_GREG_GCONF_RESET 0x80000000
# define MPIC_GREG_GCONF_8259_PTHROU_DIS 0x20000000
2007-12-27 22:16:29 -06:00
# define MPIC_GREG_GCONF_NO_BIAS 0x10000000
2005-09-26 16:04:21 +10:00
# define MPIC_GREG_GCONF_BASE_MASK 0x000fffff
2007-12-20 13:11:18 -06:00
# define MPIC_GREG_GCONF_MCK 0x08000000
2005-09-26 16:04:21 +10:00
# define MPIC_GREG_GLOBAL_CONF_1 0x00030
2006-06-20 14:15:36 -07:00
# define MPIC_GREG_GLOBAL_CONF_1_SIE 0x08000000
# define MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO_MASK 0x70000000
# define MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO(r) \
( ( ( r ) < < 28 ) & MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO_MASK )
2005-09-26 16:04:21 +10:00
# define MPIC_GREG_VENDOR_0 0x00040
# define MPIC_GREG_VENDOR_1 0x00050
# define MPIC_GREG_VENDOR_2 0x00060
# define MPIC_GREG_VENDOR_3 0x00070
# define MPIC_GREG_VENDOR_ID 0x00080
# define MPIC_GREG_VENDOR_ID_STEPPING_MASK 0x00ff0000
# define MPIC_GREG_VENDOR_ID_STEPPING_SHIFT 16
# define MPIC_GREG_VENDOR_ID_DEVICE_ID_MASK 0x0000ff00
# define MPIC_GREG_VENDOR_ID_DEVICE_ID_SHIFT 8
# define MPIC_GREG_VENDOR_ID_VENDOR_ID_MASK 0x000000ff
# define MPIC_GREG_PROCESSOR_INIT 0x00090
# define MPIC_GREG_IPI_VECTOR_PRI_0 0x000a0
# define MPIC_GREG_IPI_VECTOR_PRI_1 0x000b0
# define MPIC_GREG_IPI_VECTOR_PRI_2 0x000c0
# define MPIC_GREG_IPI_VECTOR_PRI_3 0x000d0
2006-08-25 14:16:30 +10:00
# define MPIC_GREG_IPI_STRIDE 0x10
2005-09-26 16:04:21 +10:00
# define MPIC_GREG_SPURIOUS 0x000e0
# define MPIC_GREG_TIMER_FREQ 0x000f0
/*
*
* Timer registers
*/
# define MPIC_TIMER_BASE 0x01100
# define MPIC_TIMER_STRIDE 0x40
# define MPIC_TIMER_CURRENT_CNT 0x00000
# define MPIC_TIMER_BASE_CNT 0x00010
# define MPIC_TIMER_VECTOR_PRI 0x00020
# define MPIC_TIMER_DESTINATION 0x00030
/*
* Per - Processor registers
*/
# define MPIC_CPU_THISBASE 0x00000
# define MPIC_CPU_BASE 0x20000
# define MPIC_CPU_STRIDE 0x01000
# define MPIC_CPU_IPI_DISPATCH_0 0x00040
# define MPIC_CPU_IPI_DISPATCH_1 0x00050
# define MPIC_CPU_IPI_DISPATCH_2 0x00060
# define MPIC_CPU_IPI_DISPATCH_3 0x00070
2006-08-25 14:16:30 +10:00
# define MPIC_CPU_IPI_DISPATCH_STRIDE 0x00010
2005-09-26 16:04:21 +10:00
# define MPIC_CPU_CURRENT_TASK_PRI 0x00080
# define MPIC_CPU_TASKPRI_MASK 0x0000000f
# define MPIC_CPU_WHOAMI 0x00090
# define MPIC_CPU_WHOAMI_MASK 0x0000001f
# define MPIC_CPU_INTACK 0x000a0
# define MPIC_CPU_EOI 0x000b0
2007-12-20 13:11:18 -06:00
# define MPIC_CPU_MCACK 0x000c0
2005-09-26 16:04:21 +10:00
/*
* Per - source registers
*/
# define MPIC_IRQ_BASE 0x10000
# define MPIC_IRQ_STRIDE 0x00020
# define MPIC_IRQ_VECTOR_PRI 0x00000
# define MPIC_VECPRI_MASK 0x80000000
# define MPIC_VECPRI_ACTIVITY 0x40000000 /* Read Only */
# define MPIC_VECPRI_PRIORITY_MASK 0x000f0000
# define MPIC_VECPRI_PRIORITY_SHIFT 16
# define MPIC_VECPRI_VECTOR_MASK 0x000007ff
# define MPIC_VECPRI_POLARITY_POSITIVE 0x00800000
# define MPIC_VECPRI_POLARITY_NEGATIVE 0x00000000
# define MPIC_VECPRI_POLARITY_MASK 0x00800000
# define MPIC_VECPRI_SENSE_LEVEL 0x00400000
# define MPIC_VECPRI_SENSE_EDGE 0x00000000
# define MPIC_VECPRI_SENSE_MASK 0x00400000
# define MPIC_IRQ_DESTINATION 0x00010
# define MPIC_MAX_IRQ_SOURCES 2048
# define MPIC_MAX_CPUS 32
# define MPIC_MAX_ISU 32
2006-08-25 14:16:30 +10:00
/*
* Tsi108 implementation of MPIC has many differences from the original one
*/
/*
* Global registers
*/
# define TSI108_GREG_BASE 0x00000
# define TSI108_GREG_FEATURE_0 0x00000
# define TSI108_GREG_GLOBAL_CONF_0 0x00004
# define TSI108_GREG_VENDOR_ID 0x0000c
# define TSI108_GREG_IPI_VECTOR_PRI_0 0x00204 /* Doorbell 0 */
# define TSI108_GREG_IPI_STRIDE 0x0c
# define TSI108_GREG_SPURIOUS 0x00010
# define TSI108_GREG_TIMER_FREQ 0x00014
/*
* Timer registers
*/
# define TSI108_TIMER_BASE 0x0030
# define TSI108_TIMER_STRIDE 0x10
# define TSI108_TIMER_CURRENT_CNT 0x00000
# define TSI108_TIMER_BASE_CNT 0x00004
# define TSI108_TIMER_VECTOR_PRI 0x00008
# define TSI108_TIMER_DESTINATION 0x0000c
/*
* Per - Processor registers
*/
# define TSI108_CPU_BASE 0x00300
# define TSI108_CPU_STRIDE 0x00040
# define TSI108_CPU_IPI_DISPATCH_0 0x00200
# define TSI108_CPU_IPI_DISPATCH_STRIDE 0x00000
# define TSI108_CPU_CURRENT_TASK_PRI 0x00000
# define TSI108_CPU_WHOAMI 0xffffffff
# define TSI108_CPU_INTACK 0x00004
# define TSI108_CPU_EOI 0x00008
2007-12-20 13:11:18 -06:00
# define TSI108_CPU_MCACK 0x00004 /* Doesn't really exist here */
2006-08-25 14:16:30 +10:00
/*
* Per - source registers
*/
# define TSI108_IRQ_BASE 0x00100
# define TSI108_IRQ_STRIDE 0x00008
# define TSI108_IRQ_VECTOR_PRI 0x00000
# define TSI108_VECPRI_VECTOR_MASK 0x000000ff
# define TSI108_VECPRI_POLARITY_POSITIVE 0x01000000
# define TSI108_VECPRI_POLARITY_NEGATIVE 0x00000000
# define TSI108_VECPRI_SENSE_LEVEL 0x02000000
# define TSI108_VECPRI_SENSE_EDGE 0x00000000
# define TSI108_VECPRI_POLARITY_MASK 0x01000000
# define TSI108_VECPRI_SENSE_MASK 0x02000000
# define TSI108_IRQ_DESTINATION 0x00004
/* weird mpic register indices and mask bits in the HW info array */
enum {
MPIC_IDX_GREG_BASE = 0 ,
MPIC_IDX_GREG_FEATURE_0 ,
MPIC_IDX_GREG_GLOBAL_CONF_0 ,
MPIC_IDX_GREG_VENDOR_ID ,
MPIC_IDX_GREG_IPI_VECTOR_PRI_0 ,
MPIC_IDX_GREG_IPI_STRIDE ,
MPIC_IDX_GREG_SPURIOUS ,
MPIC_IDX_GREG_TIMER_FREQ ,
MPIC_IDX_TIMER_BASE ,
MPIC_IDX_TIMER_STRIDE ,
MPIC_IDX_TIMER_CURRENT_CNT ,
MPIC_IDX_TIMER_BASE_CNT ,
MPIC_IDX_TIMER_VECTOR_PRI ,
MPIC_IDX_TIMER_DESTINATION ,
MPIC_IDX_CPU_BASE ,
MPIC_IDX_CPU_STRIDE ,
MPIC_IDX_CPU_IPI_DISPATCH_0 ,
MPIC_IDX_CPU_IPI_DISPATCH_STRIDE ,
MPIC_IDX_CPU_CURRENT_TASK_PRI ,
MPIC_IDX_CPU_WHOAMI ,
MPIC_IDX_CPU_INTACK ,
MPIC_IDX_CPU_EOI ,
2007-12-20 13:11:18 -06:00
MPIC_IDX_CPU_MCACK ,
2006-08-25 14:16:30 +10:00
MPIC_IDX_IRQ_BASE ,
MPIC_IDX_IRQ_STRIDE ,
MPIC_IDX_IRQ_VECTOR_PRI ,
MPIC_IDX_VECPRI_VECTOR_MASK ,
MPIC_IDX_VECPRI_POLARITY_POSITIVE ,
MPIC_IDX_VECPRI_POLARITY_NEGATIVE ,
MPIC_IDX_VECPRI_SENSE_LEVEL ,
MPIC_IDX_VECPRI_SENSE_EDGE ,
MPIC_IDX_VECPRI_POLARITY_MASK ,
MPIC_IDX_VECPRI_SENSE_MASK ,
MPIC_IDX_IRQ_DESTINATION ,
MPIC_IDX_END
} ;
2007-04-23 18:47:08 +10:00
# ifdef CONFIG_MPIC_U3_HT_IRQS
2005-09-26 16:04:21 +10:00
/* Fixup table entry */
struct mpic_irq_fixup
{
u8 __iomem * base ;
2005-12-14 13:10:10 +11:00
u8 __iomem * applebase ;
2005-12-13 18:04:29 +11:00
u32 data ;
2005-12-14 13:10:10 +11:00
unsigned int index ;
2005-09-26 16:04:21 +10:00
} ;
2007-04-23 18:47:08 +10:00
# endif /* CONFIG_MPIC_U3_HT_IRQS */
2005-09-26 16:04:21 +10:00
2006-11-11 17:24:55 +11:00
enum mpic_reg_type {
mpic_access_mmio_le ,
mpic_access_mmio_be ,
# ifdef CONFIG_PPC_DCR
mpic_access_dcr
# endif
} ;
struct mpic_reg_bank {
u32 __iomem * base ;
# ifdef CONFIG_PPC_DCR
dcr_host_t dhost ;
# endif /* CONFIG_PPC_DCR */
} ;
2007-05-02 16:33:41 +10:00
struct mpic_irq_save {
u32 vecprio ,
dest ;
# ifdef CONFIG_MPIC_U3_HT_IRQS
u32 fixup_data ;
# endif
} ;
2005-09-26 16:04:21 +10:00
/* The instance data of a given MPIC */
struct mpic
{
2006-07-03 21:36:01 +10:00
/* The remapper for this MPIC */
struct irq_host * irqhost ;
2005-09-26 16:04:21 +10:00
/* The "linux" controller struct */
2006-07-03 19:32:51 +10:00
struct irq_chip hc_irq ;
2007-04-23 18:47:08 +10:00
# ifdef CONFIG_MPIC_U3_HT_IRQS
2006-07-03 19:32:51 +10:00
struct irq_chip hc_ht_irq ;
# endif
2005-09-26 16:04:21 +10:00
# ifdef CONFIG_SMP
2006-07-03 19:32:51 +10:00
struct irq_chip hc_ipi ;
2005-09-26 16:04:21 +10:00
# endif
const char * name ;
/* Flags */
unsigned int flags ;
/* How many irq sources in a given ISU */
unsigned int isu_size ;
unsigned int isu_shift ;
unsigned int isu_mask ;
unsigned int irq_count ;
/* Number of sources */
unsigned int num_sources ;
/* Number of CPUs */
unsigned int num_cpus ;
2006-07-03 21:36:01 +10:00
/* default senses array */
2005-09-26 16:04:21 +10:00
unsigned char * senses ;
unsigned int senses_count ;
2007-01-28 23:33:18 -06:00
/* vector numbers used for internal sources (ipi/timers) */
unsigned int ipi_vecs [ 4 ] ;
unsigned int timer_vecs [ 4 ] ;
/* Spurious vector to program into unused sources */
unsigned int spurious_vec ;
2007-04-23 18:47:08 +10:00
# ifdef CONFIG_MPIC_U3_HT_IRQS
2005-09-26 16:04:21 +10:00
/* The fixup table */
struct mpic_irq_fixup * fixups ;
spinlock_t fixup_lock ;
# endif
2006-11-11 17:24:55 +11:00
/* Register access method */
enum mpic_reg_type reg_type ;
2005-09-26 16:04:21 +10:00
/* The various ioremap'ed bases */
2006-11-11 17:24:55 +11:00
struct mpic_reg_bank gregs ;
struct mpic_reg_bank tmregs ;
struct mpic_reg_bank cpuregs [ MPIC_MAX_CPUS ] ;
struct mpic_reg_bank isus [ MPIC_MAX_ISU ] ;
2007-07-21 09:55:21 +10:00
/* Protected sources */
unsigned long * protected ;
2006-08-25 14:16:30 +10:00
# ifdef CONFIG_MPIC_WEIRD
/* Pointer to HW info array */
u32 * hw_set ;
# endif
2007-05-08 12:58:36 +10:00
# ifdef CONFIG_PCI_MSI
spinlock_t bitmap_lock ;
unsigned long * hwirq_bitmap ;
# endif
2007-09-08 05:13:19 +10:00
# ifdef CONFIG_MPIC_BROKEN_REGREAD
u32 isu_reg0_shadow [ MPIC_MAX_IRQ_SOURCES ] ;
# endif
2005-09-26 16:04:21 +10:00
/* link */
struct mpic * next ;
2007-05-02 16:33:41 +10:00
struct sys_device sysdev ;
# ifdef CONFIG_PM
struct mpic_irq_save * save_data ;
# endif
2005-09-26 16:04:21 +10:00
} ;
2006-08-25 14:16:30 +10:00
/*
* MPIC flags ( passed to mpic_alloc )
*
* The top 4 bits contain an MPIC bhw id that is used to index the
* register offsets and some masks when CONFIG_MPIC_WEIRD is set .
* Note setting any ID ( leaving those bits to 0 ) means standard MPIC
*/
2005-09-26 16:04:21 +10:00
/* This is the primary controller, only that one has IPIs and
* has afinity control . A non - primary MPIC always uses CPU0
* registers only
*/
# define MPIC_PRIMARY 0x00000001
2006-08-25 14:16:30 +10:00
2005-09-26 16:04:21 +10:00
/* Set this for a big-endian MPIC */
# define MPIC_BIG_ENDIAN 0x00000002
/* Broken U3 MPIC */
2007-04-23 18:47:08 +10:00
# define MPIC_U3_HT_IRQS 0x00000004
2005-09-26 16:04:21 +10:00
/* Broken IPI registers (autodetected) */
# define MPIC_BROKEN_IPI 0x00000008
/* MPIC wants a reset */
# define MPIC_WANTS_RESET 0x00000010
2006-08-25 14:16:30 +10:00
/* Spurious vector requires EOI */
# define MPIC_SPV_EOI 0x00000020
/* No passthrough disable */
# define MPIC_NO_PTHROU_DIS 0x00000040
2006-11-11 17:24:55 +11:00
/* DCR based MPIC */
# define MPIC_USES_DCR 0x00000080
2007-01-28 23:33:18 -06:00
/* MPIC has 11-bit vector fields (or larger) */
# define MPIC_LARGE_VECTORS 0x00000100
2007-12-20 13:11:18 -06:00
/* Enable delivery of prio 15 interrupts as MCK instead of EE */
# define MPIC_ENABLE_MCK 0x00000200
2007-12-27 22:16:29 -06:00
/* Disable bias among target selection, spread interrupts evenly */
# define MPIC_NO_BIAS 0x00000400
2006-08-25 14:16:30 +10:00
/* MPIC HW modification ID */
# define MPIC_REGSET_MASK 0xf0000000
# define MPIC_REGSET(val) (((val) & 0xf ) << 28)
# define MPIC_GET_REGSET(flags) (((flags) >> 28) & 0xf)
# define MPIC_REGSET_STANDARD MPIC_REGSET(0) /* Original MPIC */
# define MPIC_REGSET_TSI108 MPIC_REGSET(1) /* Tsi108/109 PIC */
2005-09-26 16:04:21 +10:00
/* Allocate the controller structure and setup the linux irq descs
* for the range if interrupts passed in . No HW initialization is
* actually performed .
*
* @ phys_addr : physial base address of the MPIC
* @ flags : flags , see constants above
* @ isu_size : number of interrupts in an ISU . Use 0 to use a
* standard ISU - less setup ( aka powermac )
* @ irq_offset : first irq number to assign to this mpic
* @ irq_count : number of irqs to use with this mpic IRQ sources . Pass 0
* to match the number of sources
* @ ipi_offset : first irq number to assign to this mpic IPI sources ,
* used only on primary mpic
* @ senses : array of sense values
* @ senses_num : number of entries in the array
*
* Note about the sense array . If none is passed , all interrupts are
2007-04-23 18:47:08 +10:00
* setup to be level negative unless MPIC_U3_HT_IRQS is set in which
2005-09-26 16:04:21 +10:00
* case they are edge positive ( and the array is ignored anyway ) .
* The values in the array start at the first source of the MPIC ,
* that is senses [ 0 ] correspond to linux irq " irq_offset " .
*/
2006-07-03 21:36:01 +10:00
extern struct mpic * mpic_alloc ( struct device_node * node ,
2006-11-11 17:24:56 +11:00
phys_addr_t phys_addr ,
2005-09-26 16:04:21 +10:00
unsigned int flags ,
unsigned int isu_size ,
unsigned int irq_count ,
const char * name ) ;
/* Assign ISUs, to call before mpic_init()
*
* @ mpic : controller structure as returned by mpic_alloc ( )
* @ isu_num : ISU number
* @ phys_addr : physical address of the ISU
*/
extern void mpic_assign_isu ( struct mpic * mpic , unsigned int isu_num ,
2006-11-11 17:24:56 +11:00
phys_addr_t phys_addr ) ;
2005-09-26 16:04:21 +10:00
2006-07-03 21:36:01 +10:00
/* Set default sense codes
*
* @ mpic : controller
* @ senses : array of sense codes
* @ count : size of above array
*
* Optionally provide an array ( indexed on hardware interrupt numbers
* for this MPIC ) of default sense codes for the chip . Those are linux
* sense codes IRQ_TYPE_ *
*
* The driver gets ownership of the pointer , don ' t dispose of it or
* anything like that . __init only .
*/
extern void mpic_set_default_senses ( struct mpic * mpic , u8 * senses , int count ) ;
2005-09-26 16:04:21 +10:00
/* Initialize the controller. After this has been called, none of the above
* should be called again for this mpic
*/
extern void mpic_init ( struct mpic * mpic ) ;
/*
* All of the following functions must only be used after the
* ISUs have been assigned and the controller fully initialized
* with mpic_init ( )
*/
/* Change/Read the priority of an interrupt. Default is 8 for irqs and
* 10 for IPIs . You can call this on both IPIs and IRQ numbers , but the
* IPI number is then the offset ' ed ( linux irq number mapped to the IPI )
*/
extern void mpic_irq_set_priority ( unsigned int irq , unsigned int pri ) ;
extern unsigned int mpic_irq_get_priority ( unsigned int irq ) ;
/* Setup a non-boot CPU */
extern void mpic_setup_this_cpu ( void ) ;
/* Clean up for kexec (or cpu offline or ...) */
extern void mpic_teardown_this_cpu ( int secondary ) ;
/* Get the current cpu priority for this cpu (0..15) */
extern int mpic_cpu_get_priority ( void ) ;
/* Set the current cpu priority for this cpu */
extern void mpic_cpu_set_priority ( int prio ) ;
/* Request IPIs on primary mpic */
extern void mpic_request_ipis ( void ) ;
/* Send an IPI (non offseted number 0..3) */
extern void mpic_send_ipi ( unsigned int ipi_no , unsigned int cpu_mask ) ;
2005-10-20 17:09:51 +10:00
/* Send a message (IPI) to a given target (cpu number or MSG_*) */
void smp_mpic_message_pass ( int target , int msg ) ;
2007-12-20 13:11:18 -06:00
/* Unmask a specific virq */
extern void mpic_unmask_irq ( unsigned int irq ) ;
/* Mask a specific virq */
extern void mpic_mask_irq ( unsigned int irq ) ;
/* EOI a specific virq */
extern void mpic_end_irq ( unsigned int irq ) ;
2005-09-26 16:04:21 +10:00
/* Fetch interrupt from a given mpic */
2006-10-07 22:08:26 +10:00
extern unsigned int mpic_get_one_irq ( struct mpic * mpic ) ;
2007-12-20 13:11:18 -06:00
/* This one gets from the primary mpic */
2006-10-07 22:08:26 +10:00
extern unsigned int mpic_get_irq ( void ) ;
2007-12-20 13:11:18 -06:00
/* Fetch Machine Check interrupt from primary mpic */
extern unsigned int mpic_get_mcirq ( void ) ;
2005-09-26 16:04:21 +10:00
2006-06-20 14:15:36 -07:00
/* Set the EPIC clock ratio */
void mpic_set_clk_ratio ( struct mpic * mpic , u32 clock_ratio ) ;
/* Enable/Disable EPIC serial interrupt mode */
void mpic_set_serial_int ( struct mpic * mpic , int enable ) ;
2005-12-16 22:43:46 +01:00
# endif /* __KERNEL__ */
2005-09-27 13:51:59 +10:00
# endif /* _ASM_POWERPC_MPIC_H */