diff options
author | David S. Miller <davem@davemloft.net> | 2008-05-15 00:34:44 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-05-15 00:34:44 -0700 |
commit | 63fe46da9c380b3f2bbdf3765044649517cc717c (patch) | |
tree | 9478c1aca1d692b408955aea20c9cd9a37e589c0 /arch/sh/kernel/cpu/irq | |
parent | 99dd1a2b8347ac2ae802300b7862f6f7bcf17139 (diff) | |
parent | 066b2118976e6e7cc50eed39e2747c75343a23c4 (diff) | |
download | talos-obmc-linux-63fe46da9c380b3f2bbdf3765044649517cc717c.tar.gz talos-obmc-linux-63fe46da9c380b3f2bbdf3765044649517cc717c.zip |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts:
drivers/net/wireless/iwlwifi/iwl-4965-rs.c
drivers/net/wireless/rt2x00/rt61pci.c
Diffstat (limited to 'arch/sh/kernel/cpu/irq')
-rw-r--r-- | arch/sh/kernel/cpu/irq/intc-sh5.c | 73 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/irq/intc.c | 93 |
2 files changed, 128 insertions, 38 deletions
diff --git a/arch/sh/kernel/cpu/irq/intc-sh5.c b/arch/sh/kernel/cpu/irq/intc-sh5.c index d6e0e2bdaad5..de45c6a3e33b 100644 --- a/arch/sh/kernel/cpu/irq/intc-sh5.c +++ b/arch/sh/kernel/cpu/irq/intc-sh5.c @@ -184,9 +184,8 @@ int intc_irq_describe(char* p, int irq) void __init plat_irq_setup(void) { - unsigned long long __dummy0, __dummy1=~0x00000000100000f0; + unsigned long long __dummy0, __dummy1=~0x00000000100000f0; unsigned long reg; - unsigned long data; int i; intc_virt = onchip_remap(INTC_BASE, 1024, "INTC"); @@ -196,11 +195,8 @@ void __init plat_irq_setup(void) /* Set default: per-line enable/disable, priority driven ack/eoi */ - for (i = 0; i < NR_INTC_IRQS; i++) { - if (platform_int_priority[i] != NO_PRIORITY) { - irq_desc[i].chip = &intc_irq_type; - } - } + for (i = 0; i < NR_INTC_IRQS; i++) + irq_desc[i].chip = &intc_irq_type; /* Disable all interrupts and set all priorities to 0 to avoid trouble */ @@ -211,35 +207,42 @@ void __init plat_irq_setup(void) ctrl_outl( NO_PRIORITY, reg); - /* Set IRLM */ - /* If all the priorities are set to 'no priority', then - * assume we are using encoded mode. - */ - irlm = platform_int_priority[IRQ_IRL0] + platform_int_priority[IRQ_IRL1] + \ - platform_int_priority[IRQ_IRL2] + platform_int_priority[IRQ_IRL3]; - - if (irlm == NO_PRIORITY) { - /* IRLM = 0 */ - reg = INTC_ICR_CLEAR; - i = IRQ_INTA; - printk("Trying to use encoded IRL0-3. IRLs unsupported.\n"); - } else { - /* IRLM = 1 */ - reg = INTC_ICR_SET; - i = IRQ_IRL0; - } - ctrl_outl(INTC_ICR_IRLM, reg); - - /* Set interrupt priorities according to platform description */ - for (data = 0, reg = INTC_INTPRI_0; i < NR_INTC_IRQS; i++) { - data |= platform_int_priority[i] << ((i % INTC_INTPRI_PPREG) * 4); - if ((i % INTC_INTPRI_PPREG) == (INTC_INTPRI_PPREG - 1)) { - /* Upon the 7th, set Priority Register */ - ctrl_outl(data, reg); - data = 0; - reg += 8; +#ifdef CONFIG_SH_CAYMAN + { + unsigned long data; + + /* Set IRLM */ + /* If all the priorities are set to 'no priority', then + * assume we are using encoded mode. + */ + irlm = platform_int_priority[IRQ_IRL0] + + platform_int_priority[IRQ_IRL1] + + platform_int_priority[IRQ_IRL2] + + platform_int_priority[IRQ_IRL3]; + if (irlm == NO_PRIORITY) { + /* IRLM = 0 */ + reg = INTC_ICR_CLEAR; + i = IRQ_INTA; + printk("Trying to use encoded IRL0-3. IRLs unsupported.\n"); + } else { + /* IRLM = 1 */ + reg = INTC_ICR_SET; + i = IRQ_IRL0; } - } + ctrl_outl(INTC_ICR_IRLM, reg); + + /* Set interrupt priorities according to platform description */ + for (data = 0, reg = INTC_INTPRI_0; i < NR_INTC_IRQS; i++) { + data |= platform_int_priority[i] << + ((i % INTC_INTPRI_PPREG) * 4); + if ((i % INTC_INTPRI_PPREG) == (INTC_INTPRI_PPREG - 1)) { + /* Upon the 7th, set Priority Register */ + ctrl_outl(data, reg); + data = 0; + reg += 8; + } + } +#endif /* * And now let interrupts come in. diff --git a/arch/sh/kernel/cpu/irq/intc.c b/arch/sh/kernel/cpu/irq/intc.c index 84806b2027f8..da5dae787888 100644 --- a/arch/sh/kernel/cpu/irq/intc.c +++ b/arch/sh/kernel/cpu/irq/intc.c @@ -1,7 +1,7 @@ /* * Shared interrupt handling code for IPR and INTC2 types of IRQs. * - * Copyright (C) 2007 Magnus Damm + * Copyright (C) 2007, 2008 Magnus Damm * * Based on intc2.c and ipr.c * @@ -62,6 +62,9 @@ struct intc_desc_int { #endif static unsigned int intc_prio_level[NR_IRQS]; /* for now */ +#ifdef CONFIG_CPU_SH3 +static unsigned long ack_handle[NR_IRQS]; +#endif static inline struct intc_desc_int *get_intc_desc(unsigned int irq) { @@ -98,17 +101,26 @@ static void write_32(unsigned long addr, unsigned long h, unsigned long data) static void modify_8(unsigned long addr, unsigned long h, unsigned long data) { + unsigned long flags; + local_irq_save(flags); ctrl_outb(set_field(ctrl_inb(addr), data, h), addr); + local_irq_restore(flags); } static void modify_16(unsigned long addr, unsigned long h, unsigned long data) { + unsigned long flags; + local_irq_save(flags); ctrl_outw(set_field(ctrl_inw(addr), data, h), addr); + local_irq_restore(flags); } static void modify_32(unsigned long addr, unsigned long h, unsigned long data) { + unsigned long flags; + local_irq_save(flags); ctrl_outl(set_field(ctrl_inl(addr), data, h), addr); + local_irq_restore(flags); } enum { REG_FN_ERR = 0, REG_FN_WRITE_BASE = 1, REG_FN_MODIFY_BASE = 5 }; @@ -219,6 +231,25 @@ static void intc_disable(unsigned int irq) } } +#ifdef CONFIG_CPU_SH3 +static void intc_mask_ack(unsigned int irq) +{ + struct intc_desc_int *d = get_intc_desc(irq); + unsigned long handle = ack_handle[irq]; + unsigned long addr; + + intc_disable(irq); + + /* read register and write zero only to the assocaited bit */ + + if (handle) { + addr = INTC_REG(d, _INTC_ADDR_D(handle), 0); + ctrl_inb(addr); + ctrl_outb(0x3f ^ set_field(0, 1, handle), addr); + } +} +#endif + static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp, unsigned int nr_hp, unsigned int irq) @@ -280,7 +311,12 @@ static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = { [IRQ_TYPE_EDGE_FALLING] = VALID(0), [IRQ_TYPE_EDGE_RISING] = VALID(1), [IRQ_TYPE_LEVEL_LOW] = VALID(2), + /* SH7706, SH7707 and SH7709 do not support high level triggered */ +#if !defined(CONFIG_CPU_SUBTYPE_SH7706) && \ + !defined(CONFIG_CPU_SUBTYPE_SH7707) && \ + !defined(CONFIG_CPU_SUBTYPE_SH7709) [IRQ_TYPE_LEVEL_HIGH] = VALID(3), +#endif }; static int intc_set_sense(unsigned int irq, unsigned int type) @@ -430,6 +466,40 @@ static unsigned int __init intc_prio_data(struct intc_desc *desc, return 0; } +#ifdef CONFIG_CPU_SH3 +static unsigned int __init intc_ack_data(struct intc_desc *desc, + struct intc_desc_int *d, + intc_enum enum_id) +{ + struct intc_mask_reg *mr = desc->ack_regs; + unsigned int i, j, fn, mode; + unsigned long reg_e, reg_d; + + for (i = 0; mr && enum_id && i < desc->nr_ack_regs; i++) { + mr = desc->ack_regs + i; + + for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) { + if (mr->enum_ids[j] != enum_id) + continue; + + fn = REG_FN_MODIFY_BASE; + mode = MODE_ENABLE_REG; + reg_e = mr->set_reg; + reg_d = mr->set_reg; + + fn += (mr->reg_width >> 3) - 1; + return _INTC_MK(fn, mode, + intc_get_reg(d, reg_e), + intc_get_reg(d, reg_d), + 1, + (mr->reg_width - 1) - j); + } + } + + return 0; +} +#endif + static unsigned int __init intc_sense_data(struct intc_desc *desc, struct intc_desc_int *d, intc_enum enum_id) @@ -530,6 +600,11 @@ static void __init intc_register_irq(struct intc_desc *desc, /* irq should be disabled by default */ d->chip.mask(irq); + +#ifdef CONFIG_CPU_SH3 + if (desc->ack_regs) + ack_handle[irq] = intc_ack_data(desc, d, enum_id); +#endif } static unsigned int __init save_reg(struct intc_desc_int *d, @@ -560,6 +635,9 @@ void __init register_intc_controller(struct intc_desc *desc) d->nr_reg += desc->prio_regs ? desc->nr_prio_regs * 2 : 0; d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0; +#ifdef CONFIG_CPU_SH3 + d->nr_reg += desc->ack_regs ? desc->nr_ack_regs : 0; +#endif d->reg = alloc_bootmem(d->nr_reg * sizeof(*d->reg)); #ifdef CONFIG_SMP d->smp = alloc_bootmem(d->nr_reg * sizeof(*d->smp)); @@ -592,14 +670,23 @@ void __init register_intc_controller(struct intc_desc *desc) } } - BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ - d->chip.name = desc->name; d->chip.mask = intc_disable; d->chip.unmask = intc_enable; d->chip.mask_ack = intc_disable; d->chip.set_type = intc_set_sense; +#ifdef CONFIG_CPU_SH3 + if (desc->ack_regs) { + for (i = 0; i < desc->nr_ack_regs; i++) + k += save_reg(d, k, desc->ack_regs[i].set_reg, 0); + + d->chip.mask_ack = intc_mask_ack; + } +#endif + + BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ + for (i = 0; i < desc->nr_vectors; i++) { struct intc_vect *vect = desc->vectors + i; |