aboutsummaryrefslogtreecommitdiff
path: root/arch/sh/kernel/cpu/irq
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel/cpu/irq')
-rw-r--r--arch/sh/kernel/cpu/irq/imask.c71
-rw-r--r--arch/sh/kernel/cpu/irq/intc-sh5.c95
-rw-r--r--arch/sh/kernel/cpu/irq/ipr.c46
3 files changed, 66 insertions, 146 deletions
diff --git a/arch/sh/kernel/cpu/irq/imask.c b/arch/sh/kernel/cpu/irq/imask.c
index 301b505c427..e7f1745bd12 100644
--- a/arch/sh/kernel/cpu/irq/imask.c
+++ b/arch/sh/kernel/cpu/irq/imask.c
@@ -18,38 +18,16 @@
#include <linux/spinlock.h>
#include <linux/cache.h>
#include <linux/irq.h>
-#include <asm/system.h>
+#include <linux/bitmap.h>
#include <asm/irq.h>
/* Bitmap of IRQ masked */
-static unsigned long imask_mask = 0x7fff;
-static int interrupt_priority = 0;
-
-static void enable_imask_irq(unsigned int irq);
-static void disable_imask_irq(unsigned int irq);
-static void shutdown_imask_irq(unsigned int irq);
-static void mask_and_ack_imask(unsigned int);
-static void end_imask_irq(unsigned int irq);
-
#define IMASK_PRIORITY 15
-static unsigned int startup_imask_irq(unsigned int irq)
-{
- /* Nothing to do */
- return 0; /* never anything pending */
-}
+static DECLARE_BITMAP(imask_mask, IMASK_PRIORITY);
+static int interrupt_priority;
-static struct hw_interrupt_type imask_irq_type = {
- .typename = "SR.IMASK",
- .startup = startup_imask_irq,
- .shutdown = shutdown_imask_irq,
- .enable = enable_imask_irq,
- .disable = disable_imask_irq,
- .ack = mask_and_ack_imask,
- .end = end_imask_irq
-};
-
-void static inline set_interrupt_registers(int ip)
+static inline void set_interrupt_registers(int ip)
{
unsigned long __dummy;
@@ -72,42 +50,35 @@ void static inline set_interrupt_registers(int ip)
: "t");
}
-static void disable_imask_irq(unsigned int irq)
+static void mask_imask_irq(struct irq_data *data)
{
- clear_bit(irq, &imask_mask);
+ unsigned int irq = data->irq;
+
+ clear_bit(irq, imask_mask);
if (interrupt_priority < IMASK_PRIORITY - irq)
interrupt_priority = IMASK_PRIORITY - irq;
-
set_interrupt_registers(interrupt_priority);
}
-static void enable_imask_irq(unsigned int irq)
+static void unmask_imask_irq(struct irq_data *data)
{
- set_bit(irq, &imask_mask);
- interrupt_priority = IMASK_PRIORITY - ffz(imask_mask);
+ unsigned int irq = data->irq;
+ set_bit(irq, imask_mask);
+ interrupt_priority = IMASK_PRIORITY -
+ find_first_zero_bit(imask_mask, IMASK_PRIORITY);
set_interrupt_registers(interrupt_priority);
}
-static void mask_and_ack_imask(unsigned int irq)
-{
- disable_imask_irq(irq);
-}
-
-static void end_imask_irq(unsigned int irq)
-{
- if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
- enable_imask_irq(irq);
-}
-
-static void shutdown_imask_irq(unsigned int irq)
-{
- /* Nothing to do */
-}
+static struct irq_chip imask_irq_chip = {
+ .name = "SR.IMASK",
+ .irq_mask = mask_imask_irq,
+ .irq_unmask = unmask_imask_irq,
+ .irq_mask_ack = mask_imask_irq,
+};
void make_imask_irq(unsigned int irq)
{
- disable_irq_nosync(irq);
- irq_desc[irq].chip = &imask_irq_type;
- enable_irq(irq);
+ irq_set_chip_and_handler_name(irq, &imask_irq_chip, handle_level_irq,
+ "level");
}
diff --git a/arch/sh/kernel/cpu/irq/intc-sh5.c b/arch/sh/kernel/cpu/irq/intc-sh5.c
index 726f0335da7..9e056a3a0c7 100644
--- a/arch/sh/kernel/cpu/irq/intc-sh5.c
+++ b/arch/sh/kernel/cpu/irq/intc-sh5.c
@@ -76,39 +76,11 @@ int intc_evt_to_irq[(0xE20/0x20)+1] = {
};
static unsigned long intc_virt;
-
-static unsigned int startup_intc_irq(unsigned int irq);
-static void shutdown_intc_irq(unsigned int irq);
-static void enable_intc_irq(unsigned int irq);
-static void disable_intc_irq(unsigned int irq);
-static void mask_and_ack_intc(unsigned int);
-static void end_intc_irq(unsigned int irq);
-
-static struct hw_interrupt_type intc_irq_type = {
- .typename = "INTC",
- .startup = startup_intc_irq,
- .shutdown = shutdown_intc_irq,
- .enable = enable_intc_irq,
- .disable = disable_intc_irq,
- .ack = mask_and_ack_intc,
- .end = end_intc_irq
-};
-
static int irlm; /* IRL mode */
-static unsigned int startup_intc_irq(unsigned int irq)
-{
- enable_intc_irq(irq);
- return 0; /* never anything pending */
-}
-
-static void shutdown_intc_irq(unsigned int irq)
-{
- disable_intc_irq(irq);
-}
-
-static void enable_intc_irq(unsigned int irq)
+static void enable_intc_irq(struct irq_data *data)
{
+ unsigned int irq = data->irq;
unsigned long reg;
unsigned long bitmask;
@@ -123,11 +95,12 @@ static void enable_intc_irq(unsigned int irq)
bitmask = 1 << (irq - 32);
}
- ctrl_outl(bitmask, reg);
+ __raw_writel(bitmask, reg);
}
-static void disable_intc_irq(unsigned int irq)
+static void disable_intc_irq(struct irq_data *data)
{
+ unsigned int irq = data->irq;
unsigned long reg;
unsigned long bitmask;
@@ -139,56 +112,22 @@ static void disable_intc_irq(unsigned int irq)
bitmask = 1 << (irq - 32);
}
- ctrl_outl(bitmask, reg);
-}
-
-static void mask_and_ack_intc(unsigned int irq)
-{
- disable_intc_irq(irq);
-}
-
-static void end_intc_irq(unsigned int irq)
-{
- enable_intc_irq(irq);
-}
-
-/* For future use, if we ever support IRLM=0) */
-void make_intc_irq(unsigned int irq)
-{
- disable_irq_nosync(irq);
- irq_desc[irq].chip = &intc_irq_type;
- disable_intc_irq(irq);
+ __raw_writel(bitmask, reg);
}
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
-static int IRQ_to_vectorN[NR_INTC_IRQS] = {
- 0x12, 0x15, 0x18, 0x1B, 0x40, 0x41, 0x42, 0x43, /* 0- 7 */
- -1, -1, -1, -1, 0x50, 0x51, 0x52, 0x53, /* 8-15 */
- 0x54, 0x55, 0x32, 0x33, 0x34, 0x35, 0x36, -1, /* 16-23 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 24-31 */
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x38, /* 32-39 */
- 0x39, 0x3A, 0x3B, -1, -1, -1, -1, -1, /* 40-47 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 48-55 */
- -1, -1, -1, -1, -1, -1, -1, 0x2B, /* 56-63 */
-
+static struct irq_chip intc_irq_type = {
+ .name = "INTC",
+ .irq_enable = enable_intc_irq,
+ .irq_disable = disable_intc_irq,
};
-int intc_irq_describe(char* p, int irq)
-{
- if (irq < NR_INTC_IRQS)
- return sprintf(p, "(0x%3x)", IRQ_to_vectorN[irq]*0x20);
- else
- return 0;
-}
-#endif
-
void __init plat_irq_setup(void)
{
unsigned long long __dummy0, __dummy1=~0x00000000100000f0;
unsigned long reg;
int i;
- intc_virt = onchip_remap(INTC_BASE, 1024, "INTC");
+ intc_virt = (unsigned long)ioremap_nocache(INTC_BASE, 1024);
if (!intc_virt) {
panic("Unable to remap INTC\n");
}
@@ -196,15 +135,15 @@ void __init plat_irq_setup(void)
/* Set default: per-line enable/disable, priority driven ack/eoi */
for (i = 0; i < NR_INTC_IRQS; i++)
- irq_desc[i].chip = &intc_irq_type;
+ irq_set_chip_and_handler(i, &intc_irq_type, handle_level_irq);
/* Disable all interrupts and set all priorities to 0 to avoid trouble */
- ctrl_outl(-1, INTC_INTDSB_0);
- ctrl_outl(-1, INTC_INTDSB_1);
+ __raw_writel(-1, INTC_INTDSB_0);
+ __raw_writel(-1, INTC_INTDSB_1);
for (reg = INTC_INTPRI_0, i = 0; i < INTC_INTPRI_PREGS; i++, reg += 8)
- ctrl_outl( NO_PRIORITY, reg);
+ __raw_writel( NO_PRIORITY, reg);
#ifdef CONFIG_SH_CAYMAN
@@ -229,7 +168,7 @@ void __init plat_irq_setup(void)
reg = INTC_ICR_SET;
i = IRQ_IRL0;
}
- ctrl_outl(INTC_ICR_IRLM, reg);
+ __raw_writel(INTC_ICR_IRLM, reg);
/* Set interrupt priorities according to platform description */
for (data = 0, reg = INTC_INTPRI_0; i < NR_INTC_IRQS; i++) {
@@ -237,7 +176,7 @@ void __init plat_irq_setup(void)
((i % INTC_INTPRI_PPREG) * 4);
if ((i % INTC_INTPRI_PPREG) == (INTC_INTPRI_PPREG - 1)) {
/* Upon the 7th, set Priority Register */
- ctrl_outl(data, reg);
+ __raw_writel(data, reg);
data = 0;
reg += 8;
}
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c
index 3eb17ee5540..5de6dff5c21 100644
--- a/arch/sh/kernel/cpu/irq/ipr.c
+++ b/arch/sh/kernel/cpu/irq/ipr.c
@@ -17,29 +17,32 @@
* for more details.
*/
#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
#include <linux/irq.h>
+#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
+#include <linux/topology.h>
-static inline struct ipr_desc *get_ipr_desc(unsigned int irq)
+static inline struct ipr_desc *get_ipr_desc(struct irq_data *data)
{
- struct irq_chip *chip = get_irq_chip(irq);
- return (void *)((char *)chip - offsetof(struct ipr_desc, chip));
+ struct irq_chip *chip = irq_data_get_irq_chip(data);
+ return container_of(chip, struct ipr_desc, chip);
}
-static void disable_ipr_irq(unsigned int irq)
+static void disable_ipr_irq(struct irq_data *data)
{
- struct ipr_data *p = get_irq_chip_data(irq);
- unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx];
+ struct ipr_data *p = irq_data_get_irq_chip_data(data);
+ unsigned long addr = get_ipr_desc(data)->ipr_offsets[p->ipr_idx];
/* Set the priority in IPR to 0 */
__raw_writew(__raw_readw(addr) & (0xffff ^ (0xf << p->shift)), addr);
+ (void)__raw_readw(addr); /* Read back to flush write posting */
}
-static void enable_ipr_irq(unsigned int irq)
+static void enable_ipr_irq(struct irq_data *data)
{
- struct ipr_data *p = get_irq_chip_data(irq);
- unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx];
+ struct ipr_data *p = irq_data_get_irq_chip_data(data);
+ unsigned long addr = get_ipr_desc(data)->ipr_offsets[p->ipr_idx];
/* Set priority in IPR back to original value */
__raw_writew(__raw_readw(addr) | (p->priority << p->shift), addr);
}
@@ -53,21 +56,28 @@ void register_ipr_controller(struct ipr_desc *desc)
{
int i;
- desc->chip.mask = disable_ipr_irq;
- desc->chip.unmask = enable_ipr_irq;
- desc->chip.mask_ack = disable_ipr_irq;
+ desc->chip.irq_mask = disable_ipr_irq;
+ desc->chip.irq_unmask = enable_ipr_irq;
for (i = 0; i < desc->nr_irqs; i++) {
struct ipr_data *p = desc->ipr_data + i;
+ int res;
BUG_ON(p->ipr_idx >= desc->nr_offsets);
BUG_ON(!desc->ipr_offsets[p->ipr_idx]);
+ res = irq_alloc_desc_at(p->irq, numa_node_id());
+ if (unlikely(res != p->irq && res != -EEXIST)) {
+ printk(KERN_INFO "can not get irq_desc for %d\n",
+ p->irq);
+ continue;
+ }
+
disable_irq_nosync(p->irq);
- set_irq_chip_and_handler_name(p->irq, &desc->chip,
- handle_level_irq, "level");
- set_irq_chip_data(p->irq, p);
- disable_ipr_irq(p->irq);
+ irq_set_chip_and_handler_name(p->irq, &desc->chip,
+ handle_level_irq, "level");
+ irq_set_chip_data(p->irq, p);
+ disable_ipr_irq(irq_get_irq_data(p->irq));
}
}
EXPORT_SYMBOL(register_ipr_controller);