diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-03 15:28:34 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-03 15:28:34 -0700 |
commit | 912b2539e1e062cec73e2e61448e507f7719bd08 (patch) | |
tree | 233807569ee5e0ab3118dd54c0ae9164fec8343e /include/asm-powerpc | |
parent | 70b97a7f0b19cf1f2619deb5cc41e8b78c591aa7 (diff) | |
parent | 39ab9c212aac48f2744f2fd7722fa639ec048eb7 (diff) | |
download | talos-obmc-linux-912b2539e1e062cec73e2e61448e507f7719bd08.tar.gz talos-obmc-linux-912b2539e1e062cec73e2e61448e507f7719bd08.zip |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc:
powerpc: add defconfig for Freescale MPC8349E-mITX board
powerpc: Add base support for the Freescale MPC8349E-mITX eval board
Documentation: correct values in MPC8548E SEC example node
[POWERPC] Actually copy over i8259.c to arch/ppc/syslib this time
[POWERPC] Add new interrupt mapping core and change platforms to use it
[POWERPC] Copy i8259 code back to arch/ppc
[POWERPC] New device-tree interrupt parsing code
[POWERPC] Use the genirq framework
[PATCH] genirq: Allow fasteoi handler to retrigger disabled interrupts
[POWERPC] Update the SWIM3 (powermac) floppy driver
[POWERPC] Fix error handling in detecting legacy serial ports
[POWERPC] Fix booting on Momentum "Apache" board (a Maple derivative)
[POWERPC] Fix various offb and BootX-related issues
[POWERPC] Add a default config for 32-bit CHRP machines
[POWERPC] fix implicit declaration on cell.
[POWERPC] change get_property to return void *
Diffstat (limited to 'include/asm-powerpc')
-rw-r--r-- | include/asm-powerpc/i8259.h | 8 | ||||
-rw-r--r-- | include/asm-powerpc/irq.h | 358 | ||||
-rw-r--r-- | include/asm-powerpc/machdep.h | 2 | ||||
-rw-r--r-- | include/asm-powerpc/mpic.h | 67 | ||||
-rw-r--r-- | include/asm-powerpc/prom.h | 98 | ||||
-rw-r--r-- | include/asm-powerpc/spu.h | 1 |
6 files changed, 436 insertions, 98 deletions
diff --git a/include/asm-powerpc/i8259.h b/include/asm-powerpc/i8259.h index 0392159e16e4..c80e113052cd 100644 --- a/include/asm-powerpc/i8259.h +++ b/include/asm-powerpc/i8259.h @@ -4,11 +4,13 @@ #include <linux/irq.h> -extern struct hw_interrupt_type i8259_pic; - +#ifdef CONFIG_PPC_MERGE +extern void i8259_init(struct device_node *node, unsigned long intack_addr); +extern unsigned int i8259_irq(struct pt_regs *regs); +#else extern void i8259_init(unsigned long intack_addr, int offset); extern int i8259_irq(struct pt_regs *regs); -extern int i8259_irq_cascade(struct pt_regs *regs, void *unused); +#endif #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_I8259_H */ diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h index eb5f33e1977a..e05754752028 100644 --- a/include/asm-powerpc/irq.h +++ b/include/asm-powerpc/irq.h @@ -9,26 +9,14 @@ * 2 of the License, or (at your option) any later version. */ +#include <linux/config.h> #include <linux/threads.h> +#include <linux/list.h> +#include <linux/radix-tree.h> #include <asm/types.h> #include <asm/atomic.h> -/* this number is used when no interrupt has been assigned */ -#define NO_IRQ (-1) - -/* - * These constants are used for passing information about interrupt - * signal polarity and level/edge sensing to the low-level PIC chip - * drivers. - */ -#define IRQ_SENSE_MASK 0x1 -#define IRQ_SENSE_LEVEL 0x1 /* interrupt on active level */ -#define IRQ_SENSE_EDGE 0x0 /* interrupt triggered by edge */ - -#define IRQ_POLARITY_MASK 0x2 -#define IRQ_POLARITY_POSITIVE 0x2 /* high level or low->high edge */ -#define IRQ_POLARITY_NEGATIVE 0x0 /* low level or high->low edge */ #define get_irq_desc(irq) (&irq_desc[(irq)]) @@ -36,50 +24,325 @@ #define for_each_irq(i) \ for ((i) = 0; (i) < NR_IRQS; ++(i)) -#ifdef CONFIG_PPC64 +extern atomic_t ppc_n_lost_interrupts; -/* - * Maximum number of interrupt sources that we can handle. +#ifdef CONFIG_PPC_MERGE + +/* This number is used when no interrupt has been assigned */ +#define NO_IRQ (0) + +/* This is a special irq number to return from get_irq() to tell that + * no interrupt happened _and_ ignore it (don't count it as bad). Some + * platforms like iSeries rely on that. */ +#define NO_IRQ_IGNORE ((unsigned int)-1) + +/* Total number of virq in the platform (make it a CONFIG_* option ? */ #define NR_IRQS 512 -/* Interrupt numbers are virtual in case they are sparsely - * distributed by the hardware. +/* Number of irqs reserved for the legacy controller */ +#define NUM_ISA_INTERRUPTS 16 + +/* This type is the placeholder for a hardware interrupt number. It has to + * be big enough to enclose whatever representation is used by a given + * platform. + */ +typedef unsigned long irq_hw_number_t; + +/* Interrupt controller "host" data structure. This could be defined as a + * irq domain controller. That is, it handles the mapping between hardware + * and virtual interrupt numbers for a given interrupt domain. The host + * structure is generally created by the PIC code for a given PIC instance + * (though a host can cover more than one PIC if they have a flat number + * model). It's the host callbacks that are responsible for setting the + * irq_chip on a given irq_desc after it's been mapped. + * + * The host code and data structures are fairly agnostic to the fact that + * we use an open firmware device-tree. We do have references to struct + * device_node in two places: in irq_find_host() to find the host matching + * a given interrupt controller node, and of course as an argument to its + * counterpart host->ops->match() callback. However, those are treated as + * generic pointers by the core and the fact that it's actually a device-node + * pointer is purely a convention between callers and implementation. This + * code could thus be used on other architectures by replacing those two + * by some sort of arch-specific void * "token" used to identify interrupt + * controllers. */ -extern unsigned int virt_irq_to_real_map[NR_IRQS]; +struct irq_host; +struct radix_tree_root; -/* The maximum virtual IRQ number that we support. This - * can be set by the platform and will be reduced by the - * value of __irq_offset_value. It defaults to and is - * capped by (NR_IRQS - 1). +/* Functions below are provided by the host and called whenever a new mapping + * is created or an old mapping is disposed. The host can then proceed to + * whatever internal data structures management is required. It also needs + * to setup the irq_desc when returning from map(). */ -extern unsigned int virt_irq_max; +struct irq_host_ops { + /* Match an interrupt controller device node to a host, returns + * 1 on a match + */ + int (*match)(struct irq_host *h, struct device_node *node); + + /* Create or update a mapping between a virtual irq number and a hw + * irq number. This can be called several times for the same mapping + * but with different flags, though unmap shall always be called + * before the virq->hw mapping is changed. + */ + int (*map)(struct irq_host *h, unsigned int virq, + irq_hw_number_t hw, unsigned int flags); + + /* Dispose of such a mapping */ + void (*unmap)(struct irq_host *h, unsigned int virq); + + /* Translate device-tree interrupt specifier from raw format coming + * from the firmware to a irq_hw_number_t (interrupt line number) and + * trigger flags that can be passed to irq_create_mapping(). + * If no translation is provided, raw format is assumed to be one cell + * for interrupt line and default sense. + */ + int (*xlate)(struct irq_host *h, struct device_node *ctrler, + u32 *intspec, unsigned int intsize, + irq_hw_number_t *out_hwirq, unsigned int *out_flags); +}; + +struct irq_host { + struct list_head link; + + /* type of reverse mapping technique */ + unsigned int revmap_type; +#define IRQ_HOST_MAP_LEGACY 0 /* legacy 8259, gets irqs 1..15 */ +#define IRQ_HOST_MAP_NOMAP 1 /* no fast reverse mapping */ +#define IRQ_HOST_MAP_LINEAR 2 /* linear map of interrupts */ +#define IRQ_HOST_MAP_TREE 3 /* radix tree */ + union { + struct { + unsigned int size; + unsigned int *revmap; + } linear; + struct radix_tree_root tree; + } revmap_data; + struct irq_host_ops *ops; + void *host_data; + irq_hw_number_t inval_irq; +}; + +/* The main irq map itself is an array of NR_IRQ entries containing the + * associate host and irq number. An entry with a host of NULL is free. + * An entry can be allocated if it's free, the allocator always then sets + * hwirq first to the host's invalid irq number and then fills ops. + */ +struct irq_map_entry { + irq_hw_number_t hwirq; + struct irq_host *host; +}; + +extern struct irq_map_entry irq_map[NR_IRQS]; + -/* Create a mapping for a real_irq if it doesn't already exist. - * Return the virtual irq as a convenience. +/*** + * irq_alloc_host - Allocate a new irq_host data structure + * @node: device-tree node of the interrupt controller + * @revmap_type: type of reverse mapping to use + * @revmap_arg: for IRQ_HOST_MAP_LINEAR linear only: size of the map + * @ops: map/unmap host callbacks + * @inval_irq: provide a hw number in that host space that is always invalid + * + * Allocates and initialize and irq_host structure. Note that in the case of + * IRQ_HOST_MAP_LEGACY, the map() callback will be called before this returns + * for all legacy interrupts except 0 (which is always the invalid irq for + * a legacy controller). For a IRQ_HOST_MAP_LINEAR, the map is allocated by + * this call as well. For a IRQ_HOST_MAP_TREE, the radix tree will be allocated + * later during boot automatically (the reverse mapping will use the slow path + * until that happens). + */ +extern struct irq_host *irq_alloc_host(unsigned int revmap_type, + unsigned int revmap_arg, + struct irq_host_ops *ops, + irq_hw_number_t inval_irq); + + +/*** + * irq_find_host - Locates a host for a given device node + * @node: device-tree node of the interrupt controller + */ +extern struct irq_host *irq_find_host(struct device_node *node); + + +/*** + * irq_set_default_host - Set a "default" host + * @host: default host pointer + * + * For convenience, it's possible to set a "default" host that will be used + * whenever NULL is passed to irq_create_mapping(). It makes life easier for + * platforms that want to manipulate a few hard coded interrupt numbers that + * aren't properly represented in the device-tree. + */ +extern void irq_set_default_host(struct irq_host *host); + + +/*** + * irq_set_virq_count - Set the maximum number of virt irqs + * @count: number of linux virtual irqs, capped with NR_IRQS + * + * This is mainly for use by platforms like iSeries who want to program + * the virtual irq number in the controller to avoid the reverse mapping + */ +extern void irq_set_virq_count(unsigned int count); + + +/*** + * irq_create_mapping - Map a hardware interrupt into linux virq space + * @host: host owning this hardware interrupt or NULL for default host + * @hwirq: hardware irq number in that host space + * @flags: flags passed to the controller. contains the trigger type among + * others. Use IRQ_TYPE_* defined in include/linux/irq.h + * + * Only one mapping per hardware interrupt is permitted. Returns a linux + * virq number. The flags can be used to provide sense information to the + * controller (typically extracted from the device-tree). If no information + * is passed, the controller defaults will apply (for example, xics can only + * do edge so flags are irrelevant for some pseries specific irqs). + * + * The device-tree generally contains the trigger info in an encoding that is + * specific to a given type of controller. In that case, you can directly use + * host->ops->trigger_xlate() to translate that. + * + * It is recommended that new PICs that don't have existing OF bindings chose + * to use a representation of triggers identical to linux. + */ +extern unsigned int irq_create_mapping(struct irq_host *host, + irq_hw_number_t hwirq, + unsigned int flags); + + +/*** + * irq_dispose_mapping - Unmap an interrupt + * @virq: linux virq number of the interrupt to unmap + */ +extern void irq_dispose_mapping(unsigned int virq); + +/*** + * irq_find_mapping - Find a linux virq from an hw irq number. + * @host: host owning this hardware interrupt + * @hwirq: hardware irq number in that host space + * + * This is a slow path, for use by generic code. It's expected that an + * irq controller implementation directly calls the appropriate low level + * mapping function. */ -int virt_irq_create_mapping(unsigned int real_irq); -void virt_irq_init(void); +extern unsigned int irq_find_mapping(struct irq_host *host, + irq_hw_number_t hwirq); -static inline unsigned int virt_irq_to_real(unsigned int virt_irq) + +/*** + * irq_radix_revmap - Find a linux virq from a hw irq number. + * @host: host owning this hardware interrupt + * @hwirq: hardware irq number in that host space + * + * This is a fast path, for use by irq controller code that uses radix tree + * revmaps + */ +extern unsigned int irq_radix_revmap(struct irq_host *host, + irq_hw_number_t hwirq); + +/*** + * irq_linear_revmap - Find a linux virq from a hw irq number. + * @host: host owning this hardware interrupt + * @hwirq: hardware irq number in that host space + * + * This is a fast path, for use by irq controller code that uses linear + * revmaps. It does fallback to the slow path if the revmap doesn't exist + * yet and will create the revmap entry with appropriate locking + */ + +extern unsigned int irq_linear_revmap(struct irq_host *host, + irq_hw_number_t hwirq); + + + +/*** + * irq_alloc_virt - Allocate virtual irq numbers + * @host: host owning these new virtual irqs + * @count: number of consecutive numbers to allocate + * @hint: pass a hint number, the allocator will try to use a 1:1 mapping + * + * This is a low level function that is used internally by irq_create_mapping() + * and that can be used by some irq controllers implementations for things + * like allocating ranges of numbers for MSIs. The revmaps are left untouched. + */ +extern unsigned int irq_alloc_virt(struct irq_host *host, + unsigned int count, + unsigned int hint); + +/*** + * irq_free_virt - Free virtual irq numbers + * @virq: virtual irq number of the first interrupt to free + * @count: number of interrupts to free + * + * This function is the opposite of irq_alloc_virt. It will not clear reverse + * maps, this should be done previously by unmap'ing the interrupt. In fact, + * all interrupts covered by the range being freed should have been unmapped + * prior to calling this. + */ +extern void irq_free_virt(unsigned int virq, unsigned int count); + + +/* -- OF helpers -- */ + +/* irq_create_of_mapping - Map a hardware interrupt into linux virq space + * @controller: Device node of the interrupt controller + * @inspec: Interrupt specifier from the device-tree + * @intsize: Size of the interrupt specifier from the device-tree + * + * This function is identical to irq_create_mapping except that it takes + * as input informations straight from the device-tree (typically the results + * of the of_irq_map_*() functions + */ +extern unsigned int irq_create_of_mapping(struct device_node *controller, + u32 *intspec, unsigned int intsize); + + +/* irq_of_parse_and_map - Parse nad Map an interrupt into linux virq space + * @device: Device node of the device whose interrupt is to be mapped + * @index: Index of the interrupt to map + * + * This function is a wrapper that chains of_irq_map_one() and + * irq_create_of_mapping() to make things easier to callers + */ +extern unsigned int irq_of_parse_and_map(struct device_node *dev, int index); + +/* -- End OF helpers -- */ + +/*** + * irq_early_init - Init irq remapping subsystem + */ +extern void irq_early_init(void); + +static __inline__ int irq_canonicalize(int irq) { - return virt_irq_to_real_map[virt_irq]; + return irq; } -extern unsigned int real_irq_to_virt_slowpath(unsigned int real_irq); + +#else /* CONFIG_PPC_MERGE */ + +/* This number is used when no interrupt has been assigned */ +#define NO_IRQ (-1) +#define NO_IRQ_IGNORE (-2) + /* - * List of interrupt controllers. + * These constants are used for passing information about interrupt + * signal polarity and level/edge sensing to the low-level PIC chip + * drivers. */ -#define IC_INVALID 0 -#define IC_OPEN_PIC 1 -#define IC_PPC_XIC 2 -#define IC_CELL_PIC 3 -#define IC_ISERIES 4 +#define IRQ_SENSE_MASK 0x1 +#define IRQ_SENSE_LEVEL 0x1 /* interrupt on active level */ +#define IRQ_SENSE_EDGE 0x0 /* interrupt triggered by edge */ -extern u64 ppc64_interrupt_controller; +#define IRQ_POLARITY_MASK 0x2 +#define IRQ_POLARITY_POSITIVE 0x2 /* high level or low->high edge */ +#define IRQ_POLARITY_NEGATIVE 0x0 /* low level or high->low edge */ -#else /* 32-bit */ #if defined(CONFIG_40x) #include <asm/ibm4xx.h> @@ -512,16 +775,11 @@ extern u64 ppc64_interrupt_controller; #endif /* CONFIG_8260 */ -#endif +#endif /* Whatever way too big #ifdef */ #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) /* pedantic: these are long because they are used with set_bit --RR */ extern unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; -extern atomic_t ppc_n_lost_interrupts; - -#define virt_irq_create_mapping(x) (x) - -#endif /* * Because many systems have two overlapping names spaces for @@ -560,6 +818,7 @@ static __inline__ int irq_canonicalize(int irq) irq = 9; return irq; } +#endif /* CONFIG_PPC_MERGE */ extern int distribute_irqs; @@ -579,9 +838,8 @@ extern struct thread_info *softirq_ctx[NR_CPUS]; extern void irq_ctx_init(void); extern void call_do_softirq(struct thread_info *tp); -extern int call___do_IRQ(int irq, struct pt_regs *regs, - struct thread_info *tp); - +extern int call_handle_irq(int irq, void *p1, void *p2, + struct thread_info *tp, void *func); #else #define irq_ctx_init() diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index eba133d149a7..c17c13742401 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h @@ -97,7 +97,7 @@ struct machdep_calls { void (*show_percpuinfo)(struct seq_file *m, int i); void (*init_IRQ)(void); - int (*get_irq)(struct pt_regs *); + unsigned int (*get_irq)(struct pt_regs *); #ifdef CONFIG_KEXEC void (*kexec_cpu_down)(int crash_shutdown, int secondary); #endif diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h index f0d22ac34b96..eb241c99c457 100644 --- a/include/asm-powerpc/mpic.h +++ b/include/asm-powerpc/mpic.h @@ -114,9 +114,6 @@ #define MPIC_VEC_TIMER_1 248 #define MPIC_VEC_TIMER_0 247 -/* Type definition of the cascade handler */ -typedef int (*mpic_cascade_t)(struct pt_regs *regs, void *data); - #ifdef CONFIG_MPIC_BROKEN_U3 /* Fixup table entry */ struct mpic_irq_fixup @@ -132,10 +129,19 @@ struct mpic_irq_fixup /* The instance data of a given MPIC */ struct mpic { + /* The device node of the interrupt controller */ + struct device_node *of_node; + + /* The remapper for this MPIC */ + struct irq_host *irqhost; + /* The "linux" controller struct */ - hw_irq_controller hc_irq; + struct irq_chip hc_irq; +#ifdef CONFIG_MPIC_BROKEN_U3 + struct irq_chip hc_ht_irq; +#endif #ifdef CONFIG_SMP - hw_irq_controller hc_ipi; + struct irq_chip hc_ipi; #endif const char *name; /* Flags */ @@ -144,20 +150,12 @@ struct mpic unsigned int isu_size; unsigned int isu_shift; unsigned int isu_mask; - /* Offset of irq vector numbers */ - unsigned int irq_offset; unsigned int irq_count; - /* Offset of ipi vector numbers */ - unsigned int ipi_offset; /* Number of sources */ unsigned int num_sources; /* Number of CPUs */ unsigned int num_cpus; - /* cascade handler */ - mpic_cascade_t cascade; - void *cascade_data; - unsigned int cascade_vec; - /* senses array */ + /* default senses array */ unsigned char *senses; unsigned int senses_count; @@ -213,14 +211,11 @@ struct mpic * The values in the array start at the first source of the MPIC, * that is senses[0] correspond to linux irq "irq_offset". */ -extern struct mpic *mpic_alloc(unsigned long phys_addr, +extern struct mpic *mpic_alloc(struct device_node *node, + unsigned long phys_addr, unsigned int flags, unsigned int isu_size, - unsigned int irq_offset, unsigned int irq_count, - unsigned int ipi_offset, - unsigned char *senses, - unsigned int senses_num, const char *name); /* Assign ISUs, to call before mpic_init() @@ -232,22 +227,27 @@ extern struct mpic *mpic_alloc(unsigned long phys_addr, extern void mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, unsigned long phys_addr); +/* 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); + + /* 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); -/* Setup a cascade. Currently, only one cascade is supported this - * way, though you can always do a normal request_irq() and add - * other cascades this way. You should call this _after_ having - * added all the ISUs - * - * @irq_no: "linux" irq number of the cascade (that is offset'ed vector) - * @handler: cascade handler function - */ -extern void mpic_setup_cascade(unsigned int irq_no, mpic_cascade_t hanlder, - void *data); - /* * All of the following functions must only be used after the * ISUs have been assigned and the controller fully initialized @@ -284,9 +284,9 @@ extern void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask); void smp_mpic_message_pass(int target, int msg); /* Fetch interrupt from a given mpic */ -extern int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs); +extern unsigned int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs); /* This one gets to the primary mpic */ -extern int mpic_get_irq(struct pt_regs *regs); +extern unsigned int mpic_get_irq(struct pt_regs *regs); /* Set the EPIC clock ratio */ void mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio); @@ -294,8 +294,5 @@ 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); -/* global mpic for pSeries */ -extern struct mpic *pSeries_mpic; - #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_MPIC_H */ diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 010d186d095b..b095a285c84b 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -64,11 +64,6 @@ struct boot_param_header typedef u32 phandle; typedef u32 ihandle; -struct interrupt_info { - int line; - int sense; /* +ve/-ve logic, edge or level, etc. */ -}; - struct property { char *name; int length; @@ -81,8 +76,6 @@ struct device_node { char *type; phandle node; phandle linux_phandle; - int n_intrs; - struct interrupt_info *intrs; char *full_name; struct property *properties; @@ -167,8 +160,8 @@ extern void unflatten_device_tree(void); extern void early_init_devtree(void *); extern int device_is_compatible(struct device_node *device, const char *); extern int machine_is_compatible(const char *compat); -extern unsigned char *get_property(struct device_node *node, const char *name, - int *lenp); +extern void *get_property(struct device_node *node, const char *name, + int *lenp); extern void print_properties(struct device_node *node); extern int prom_n_addr_cells(struct device_node* np); extern int prom_n_size_cells(struct device_node* np); @@ -204,6 +197,15 @@ extern int release_OF_resource(struct device_node* node, int index); */ +/* Helper to read a big number */ +static inline u64 of_read_number(u32 *cell, int size) +{ + u64 r = 0; + while (size--) + r = (r << 32) | *(cell++); + return r; +} + /* Translate an OF address block into a CPU physical address */ #define OF_BAD_ADDR ((u64)-1) @@ -240,5 +242,83 @@ extern void kdump_move_device_tree(void); /* CPU OF node matching */ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread); + +/* + * OF interrupt mapping + */ + +/* This structure is returned when an interrupt is mapped. The controller + * field needs to be put() after use + */ + +#define OF_MAX_IRQ_SPEC 4 /* We handle specifiers of at most 4 cells */ + +struct of_irq { + struct device_node *controller; /* Interrupt controller node */ + u32 size; /* Specifier size */ + u32 specifier[OF_MAX_IRQ_SPEC]; /* Specifier copy */ +}; + +/*** + * of_irq_map_init - Initialize the irq remapper + * @flags: flags defining workarounds to enable + * + * Some machines have bugs in the device-tree which require certain workarounds + * to be applied. Call this before any interrupt mapping attempts to enable + * those workarounds. + */ +#define OF_IMAP_OLDWORLD_MAC 0x00000001 +#define OF_IMAP_NO_PHANDLE 0x00000002 + +extern void of_irq_map_init(unsigned int flags); + +/*** + * of_irq_map_raw - Low level interrupt tree parsing + * @parent: the device interrupt parent + * @intspec: interrupt specifier ("interrupts" property of the device) + * @addr: address specifier (start of "reg" property of the device) + * @out_irq: structure of_irq filled by this function + * + * Returns 0 on success and a negative number on error + * + * This function is a low-level interrupt tree walking function. It + * can be used to do a partial walk with synthetized reg and interrupts + * properties, for example when resolving PCI interrupts when no device + * node exist for the parent. + * + */ + +extern int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 *addr, + struct of_irq *out_irq); + + +/*** + * of_irq_map_one - Resolve an interrupt for a device + * @device: the device whose interrupt is to be resolved + * @index: index of the interrupt to resolve + * @out_irq: structure of_irq filled by this function + * + * This function resolves an interrupt, walking the tree, for a given + * device-tree node. It's the high level pendant to of_irq_map_raw(). + * It also implements the workarounds for OldWolrd Macs. + */ +extern int of_irq_map_one(struct device_node *device, int index, + struct of_irq *out_irq); + +/*** + * of_irq_map_pci - Resolve the interrupt for a PCI device + * @pdev: the device whose interrupt is to be resolved + * @out_irq: structure of_irq filled by this function + * + * This function resolves the PCI interrupt for a given PCI device. If a + * device-node exists for a given pci_dev, it will use normal OF tree + * walking. If not, it will implement standard swizzling and walk up the + * PCI tree until an device-node is found, at which point it will finish + * resolving using the OF tree walking. + */ +struct pci_dev; +extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq); + + #endif /* __KERNEL__ */ #endif /* _POWERPC_PROM_H */ diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h index 9609d3ee8798..c02d105d8294 100644 --- a/include/asm-powerpc/spu.h +++ b/include/asm-powerpc/spu.h @@ -117,6 +117,7 @@ struct spu { struct list_head sched_list; int number; int nid; + unsigned int irqs[3]; u32 isrc; u32 node; u64 flags; |