home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / arch / powerpc / include / asm / irq.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-24  |  12.9 KB  |  379 lines

  1. #ifdef __KERNEL__
  2. #ifndef _ASM_POWERPC_IRQ_H
  3. #define _ASM_POWERPC_IRQ_H
  4.  
  5. /*
  6.  * This program is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU General Public License
  8.  * as published by the Free Software Foundation; either version
  9.  * 2 of the License, or (at your option) any later version.
  10.  */
  11.  
  12. #include <linux/threads.h>
  13. #include <linux/list.h>
  14. #include <linux/radix-tree.h>
  15.  
  16. #include <asm/types.h>
  17. #include <asm/atomic.h>
  18.  
  19.  
  20. #define get_irq_desc(irq) (&irq_desc[(irq)])
  21.  
  22. /* Define a way to iterate across irqs. */
  23. #define for_each_irq(i) \
  24.     for ((i) = 0; (i) < NR_IRQS; ++(i))
  25.  
  26. extern atomic_t ppc_n_lost_interrupts;
  27.  
  28. /* This number is used when no interrupt has been assigned */
  29. #define NO_IRQ            (0)
  30.  
  31. /* This is a special irq number to return from get_irq() to tell that
  32.  * no interrupt happened _and_ ignore it (don't count it as bad). Some
  33.  * platforms like iSeries rely on that.
  34.  */
  35. #define NO_IRQ_IGNORE        ((unsigned int)-1)
  36.  
  37. /* Total number of virq in the platform (make it a CONFIG_* option ? */
  38. #define NR_IRQS        512
  39.  
  40. /* Number of irqs reserved for the legacy controller */
  41. #define NUM_ISA_INTERRUPTS    16
  42.  
  43. /* This type is the placeholder for a hardware interrupt number. It has to
  44.  * be big enough to enclose whatever representation is used by a given
  45.  * platform.
  46.  */
  47. typedef unsigned long irq_hw_number_t;
  48.  
  49. /* Interrupt controller "host" data structure. This could be defined as a
  50.  * irq domain controller. That is, it handles the mapping between hardware
  51.  * and virtual interrupt numbers for a given interrupt domain. The host
  52.  * structure is generally created by the PIC code for a given PIC instance
  53.  * (though a host can cover more than one PIC if they have a flat number
  54.  * model). It's the host callbacks that are responsible for setting the
  55.  * irq_chip on a given irq_desc after it's been mapped.
  56.  *
  57.  * The host code and data structures are fairly agnostic to the fact that
  58.  * we use an open firmware device-tree. We do have references to struct
  59.  * device_node in two places: in irq_find_host() to find the host matching
  60.  * a given interrupt controller node, and of course as an argument to its
  61.  * counterpart host->ops->match() callback. However, those are treated as
  62.  * generic pointers by the core and the fact that it's actually a device-node
  63.  * pointer is purely a convention between callers and implementation. This
  64.  * code could thus be used on other architectures by replacing those two
  65.  * by some sort of arch-specific void * "token" used to identify interrupt
  66.  * controllers.
  67.  */
  68. struct irq_host;
  69. struct radix_tree_root;
  70.  
  71. /* Functions below are provided by the host and called whenever a new mapping
  72.  * is created or an old mapping is disposed. The host can then proceed to
  73.  * whatever internal data structures management is required. It also needs
  74.  * to setup the irq_desc when returning from map().
  75.  */
  76. struct irq_host_ops {
  77.     /* Match an interrupt controller device node to a host, returns
  78.      * 1 on a match
  79.      */
  80.     int (*match)(struct irq_host *h, struct device_node *node);
  81.  
  82.     /* Create or update a mapping between a virtual irq number and a hw
  83.      * irq number. This is called only once for a given mapping.
  84.      */
  85.     int (*map)(struct irq_host *h, unsigned int virq, irq_hw_number_t hw);
  86.  
  87.     /* Dispose of such a mapping */
  88.     void (*unmap)(struct irq_host *h, unsigned int virq);
  89.  
  90.     /* Update of such a mapping  */
  91.     void (*remap)(struct irq_host *h, unsigned int virq, irq_hw_number_t hw);
  92.  
  93.     /* Translate device-tree interrupt specifier from raw format coming
  94.      * from the firmware to a irq_hw_number_t (interrupt line number) and
  95.      * type (sense) that can be passed to set_irq_type(). In the absence
  96.      * of this callback, irq_create_of_mapping() and irq_of_parse_and_map()
  97.      * will return the hw number in the first cell and IRQ_TYPE_NONE for
  98.      * the type (which amount to keeping whatever default value the
  99.      * interrupt controller has for that line)
  100.      */
  101.     int (*xlate)(struct irq_host *h, struct device_node *ctrler,
  102.              u32 *intspec, unsigned int intsize,
  103.              irq_hw_number_t *out_hwirq, unsigned int *out_type);
  104. };
  105.  
  106. struct irq_host {
  107.     struct list_head    link;
  108.  
  109.     /* type of reverse mapping technique */
  110.     unsigned int        revmap_type;
  111. #define IRQ_HOST_MAP_LEGACY     0 /* legacy 8259, gets irqs 1..15 */
  112. #define IRQ_HOST_MAP_NOMAP    1 /* no fast reverse mapping */
  113. #define IRQ_HOST_MAP_LINEAR    2 /* linear map of interrupts */
  114. #define IRQ_HOST_MAP_TREE    3 /* radix tree */
  115.     union {
  116.         struct {
  117.             unsigned int size;
  118.             unsigned int *revmap;
  119.         } linear;
  120.         struct radix_tree_root tree;
  121.     } revmap_data;
  122.     struct irq_host_ops    *ops;
  123.     void            *host_data;
  124.     irq_hw_number_t        inval_irq;
  125.  
  126.     /* Optional device node pointer */
  127.     struct device_node    *of_node;
  128. };
  129.  
  130. /* The main irq map itself is an array of NR_IRQ entries containing the
  131.  * associate host and irq number. An entry with a host of NULL is free.
  132.  * An entry can be allocated if it's free, the allocator always then sets
  133.  * hwirq first to the host's invalid irq number and then fills ops.
  134.  */
  135. struct irq_map_entry {
  136.     irq_hw_number_t    hwirq;
  137.     struct irq_host    *host;
  138. };
  139.  
  140. extern struct irq_map_entry irq_map[NR_IRQS];
  141.  
  142. extern irq_hw_number_t virq_to_hw(unsigned int virq);
  143.  
  144. /**
  145.  * irq_alloc_host - Allocate a new irq_host data structure
  146.  * @of_node: optional device-tree node of the interrupt controller
  147.  * @revmap_type: type of reverse mapping to use
  148.  * @revmap_arg: for IRQ_HOST_MAP_LINEAR linear only: size of the map
  149.  * @ops: map/unmap host callbacks
  150.  * @inval_irq: provide a hw number in that host space that is always invalid
  151.  *
  152.  * Allocates and initialize and irq_host structure. Note that in the case of
  153.  * IRQ_HOST_MAP_LEGACY, the map() callback will be called before this returns
  154.  * for all legacy interrupts except 0 (which is always the invalid irq for
  155.  * a legacy controller). For a IRQ_HOST_MAP_LINEAR, the map is allocated by
  156.  * this call as well. For a IRQ_HOST_MAP_TREE, the radix tree will be allocated
  157.  * later during boot automatically (the reverse mapping will use the slow path
  158.  * until that happens).
  159.  */
  160. extern struct irq_host *irq_alloc_host(struct device_node *of_node,
  161.                        unsigned int revmap_type,
  162.                        unsigned int revmap_arg,
  163.                        struct irq_host_ops *ops,
  164.                        irq_hw_number_t inval_irq);
  165.  
  166.  
  167. /**
  168.  * irq_find_host - Locates a host for a given device node
  169.  * @node: device-tree node of the interrupt controller
  170.  */
  171. extern struct irq_host *irq_find_host(struct device_node *node);
  172.  
  173.  
  174. /**
  175.  * irq_set_default_host - Set a "default" host
  176.  * @host: default host pointer
  177.  *
  178.  * For convenience, it's possible to set a "default" host that will be used
  179.  * whenever NULL is passed to irq_create_mapping(). It makes life easier for
  180.  * platforms that want to manipulate a few hard coded interrupt numbers that
  181.  * aren't properly represented in the device-tree.
  182.  */
  183. extern void irq_set_default_host(struct irq_host *host);
  184.  
  185.  
  186. /**
  187.  * irq_set_virq_count - Set the maximum number of virt irqs
  188.  * @count: number of linux virtual irqs, capped with NR_IRQS
  189.  *
  190.  * This is mainly for use by platforms like iSeries who want to program
  191.  * the virtual irq number in the controller to avoid the reverse mapping
  192.  */
  193. extern void irq_set_virq_count(unsigned int count);
  194.  
  195.  
  196. /**
  197.  * irq_create_mapping - Map a hardware interrupt into linux virq space
  198.  * @host: host owning this hardware interrupt or NULL for default host
  199.  * @hwirq: hardware irq number in that host space
  200.  *
  201.  * Only one mapping per hardware interrupt is permitted. Returns a linux
  202.  * virq number.
  203.  * If the sense/trigger is to be specified, set_irq_type() should be called
  204.  * on the number returned from that call.
  205.  */
  206. extern unsigned int irq_create_mapping(struct irq_host *host,
  207.                        irq_hw_number_t hwirq);
  208.  
  209.  
  210. /**
  211.  * irq_dispose_mapping - Unmap an interrupt
  212.  * @virq: linux virq number of the interrupt to unmap
  213.  */
  214. extern void irq_dispose_mapping(unsigned int virq);
  215.  
  216. /**
  217.  * irq_find_mapping - Find a linux virq from an hw irq number.
  218.  * @host: host owning this hardware interrupt
  219.  * @hwirq: hardware irq number in that host space
  220.  *
  221.  * This is a slow path, for use by generic code. It's expected that an
  222.  * irq controller implementation directly calls the appropriate low level
  223.  * mapping function.
  224.  */
  225. extern unsigned int irq_find_mapping(struct irq_host *host,
  226.                      irq_hw_number_t hwirq);
  227.  
  228. /**
  229.  * irq_create_direct_mapping - Allocate a virq for direct mapping
  230.  * @host: host to allocate the virq for or NULL for default host
  231.  *
  232.  * This routine is used for irq controllers which can choose the hardware
  233.  * interrupt numbers they generate. In such a case it's simplest to use
  234.  * the linux virq as the hardware interrupt number.
  235.  */
  236. extern unsigned int irq_create_direct_mapping(struct irq_host *host);
  237.  
  238. /**
  239.  * irq_radix_revmap_insert - Insert a hw irq to linux virq number mapping.
  240.  * @host: host owning this hardware interrupt
  241.  * @virq: linux irq number
  242.  * @hwirq: hardware irq number in that host space
  243.  *
  244.  * This is for use by irq controllers that use a radix tree reverse
  245.  * mapping for fast lookup.
  246.  */
  247. extern void irq_radix_revmap_insert(struct irq_host *host, unsigned int virq,
  248.                     irq_hw_number_t hwirq);
  249.  
  250. /**
  251.  * irq_radix_revmap_lookup - Find a linux virq from a hw irq number.
  252.  * @host: host owning this hardware interrupt
  253.  * @hwirq: hardware irq number in that host space
  254.  *
  255.  * This is a fast path, for use by irq controller code that uses radix tree
  256.  * revmaps
  257.  */
  258. extern unsigned int irq_radix_revmap_lookup(struct irq_host *host,
  259.                         irq_hw_number_t hwirq);
  260.  
  261. /**
  262.  * irq_linear_revmap - Find a linux virq from a hw irq number.
  263.  * @host: host owning this hardware interrupt
  264.  * @hwirq: hardware irq number in that host space
  265.  *
  266.  * This is a fast path, for use by irq controller code that uses linear
  267.  * revmaps. It does fallback to the slow path if the revmap doesn't exist
  268.  * yet and will create the revmap entry with appropriate locking
  269.  */
  270.  
  271. extern unsigned int irq_linear_revmap(struct irq_host *host,
  272.                       irq_hw_number_t hwirq);
  273.  
  274.  
  275.  
  276. /**
  277.  * irq_alloc_virt - Allocate virtual irq numbers
  278.  * @host: host owning these new virtual irqs
  279.  * @count: number of consecutive numbers to allocate
  280.  * @hint: pass a hint number, the allocator will try to use a 1:1 mapping
  281.  *
  282.  * This is a low level function that is used internally by irq_create_mapping()
  283.  * and that can be used by some irq controllers implementations for things
  284.  * like allocating ranges of numbers for MSIs. The revmaps are left untouched.
  285.  */
  286. extern unsigned int irq_alloc_virt(struct irq_host *host,
  287.                    unsigned int count,
  288.                    unsigned int hint);
  289.  
  290. /**
  291.  * irq_free_virt - Free virtual irq numbers
  292.  * @virq: virtual irq number of the first interrupt to free
  293.  * @count: number of interrupts to free
  294.  *
  295.  * This function is the opposite of irq_alloc_virt. It will not clear reverse
  296.  * maps, this should be done previously by unmap'ing the interrupt. In fact,
  297.  * all interrupts covered by the range being freed should have been unmapped
  298.  * prior to calling this.
  299.  */
  300. extern void irq_free_virt(unsigned int virq, unsigned int count);
  301.  
  302.  
  303. /* -- OF helpers -- */
  304.  
  305. /* irq_create_of_mapping - Map a hardware interrupt into linux virq space
  306.  * @controller: Device node of the interrupt controller
  307.  * @inspec: Interrupt specifier from the device-tree
  308.  * @intsize: Size of the interrupt specifier from the device-tree
  309.  *
  310.  * This function is identical to irq_create_mapping except that it takes
  311.  * as input informations straight from the device-tree (typically the results
  312.  * of the of_irq_map_*() functions.
  313.  */
  314. extern unsigned int irq_create_of_mapping(struct device_node *controller,
  315.                       u32 *intspec, unsigned int intsize);
  316.  
  317.  
  318. /* irq_of_parse_and_map - Parse nad Map an interrupt into linux virq space
  319.  * @device: Device node of the device whose interrupt is to be mapped
  320.  * @index: Index of the interrupt to map
  321.  *
  322.  * This function is a wrapper that chains of_irq_map_one() and
  323.  * irq_create_of_mapping() to make things easier to callers
  324.  */
  325. extern unsigned int irq_of_parse_and_map(struct device_node *dev, int index);
  326.  
  327. /* -- End OF helpers -- */
  328.  
  329. /**
  330.  * irq_early_init - Init irq remapping subsystem
  331.  */
  332. extern void irq_early_init(void);
  333.  
  334. static __inline__ int irq_canonicalize(int irq)
  335. {
  336.     return irq;
  337. }
  338.  
  339. extern int distribute_irqs;
  340.  
  341. struct irqaction;
  342. struct pt_regs;
  343.  
  344. #define __ARCH_HAS_DO_SOFTIRQ
  345.  
  346. #if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
  347. /*
  348.  * Per-cpu stacks for handling critical, debug and machine check
  349.  * level interrupts.
  350.  */
  351. extern struct thread_info *critirq_ctx[NR_CPUS];
  352. extern struct thread_info *dbgirq_ctx[NR_CPUS];
  353. extern struct thread_info *mcheckirq_ctx[NR_CPUS];
  354. extern void exc_lvl_ctx_init(void);
  355. #else
  356. #define exc_lvl_ctx_init()
  357. #endif
  358.  
  359. #ifdef CONFIG_IRQSTACKS
  360. /*
  361.  * Per-cpu stacks for handling hard and soft interrupts.
  362.  */
  363. extern struct thread_info *hardirq_ctx[NR_CPUS];
  364. extern struct thread_info *softirq_ctx[NR_CPUS];
  365.  
  366. extern void irq_ctx_init(void);
  367. extern void call_do_softirq(struct thread_info *tp);
  368. extern int call_handle_irq(int irq, void *p1,
  369.                struct thread_info *tp, void *func);
  370. #else
  371. #define irq_ctx_init()
  372.  
  373. #endif /* CONFIG_IRQSTACKS */
  374.  
  375. extern void do_IRQ(struct pt_regs *regs);
  376.  
  377. #endif /* _ASM_IRQ_H */
  378. #endif /* __KERNEL__ */
  379.