diff options
Diffstat (limited to 'arch/blackfin/mach-common')
-rw-r--r-- | arch/blackfin/mach-common/Makefile | 4 | ||||
-rw-r--r-- | arch/blackfin/mach-common/cacheinit.S | 89 | ||||
-rw-r--r-- | arch/blackfin/mach-common/cplbinfo.c | 13 | ||||
-rw-r--r-- | arch/blackfin/mach-common/entry.S | 76 | ||||
-rw-r--r-- | arch/blackfin/mach-common/interrupt.S | 8 | ||||
-rw-r--r-- | arch/blackfin/mach-common/ints-priority-dc.c | 13 | ||||
-rw-r--r-- | arch/blackfin/mach-common/ints-priority-sc.c | 405 | ||||
-rw-r--r-- | arch/blackfin/mach-common/pm.c | 4 |
8 files changed, 416 insertions, 196 deletions
diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile index d3a49073d19..0279ede7039 100644 --- a/arch/blackfin/mach-common/Makefile +++ b/arch/blackfin/mach-common/Makefile @@ -4,9 +4,9 @@ obj-y := \ cache.o cacheinit.o cplbhdlr.o cplbmgr.o entry.o \ - interrupt.o lock.o dpmc.o irqpanic.o + interrupt.o lock.o irqpanic.o obj-$(CONFIG_CPLB_INFO) += cplbinfo.o obj-$(CONFIG_BFIN_SINGLE_CORE) += ints-priority-sc.o obj-$(CONFIG_BFIN_DUAL_CORE) += ints-priority-dc.o -obj-$(CONFIG_PM) += pm.o +obj-$(CONFIG_PM) += pm.o dpmc.o diff --git a/arch/blackfin/mach-common/cacheinit.S b/arch/blackfin/mach-common/cacheinit.S index 7924a90d965..9d475623b72 100644 --- a/arch/blackfin/mach-common/cacheinit.S +++ b/arch/blackfin/mach-common/cacheinit.S @@ -38,104 +38,37 @@ .text +#ifdef ANOMALY_05000125 #if defined(CONFIG_BLKFIN_CACHE) -ENTRY(_bfin_icache_init) +ENTRY(_bfin_write_IMEM_CONTROL) - /* Initialize Instruction CPLBS */ - - I0.L = (ICPLB_ADDR0 & 0xFFFF); - I0.H = (ICPLB_ADDR0 >> 16); - - I1.L = (ICPLB_DATA0 & 0xFFFF); - I1.H = (ICPLB_DATA0 >> 16); - - I2.L = _icplb_table; - I2.H = _icplb_table; - - r1 = -1; /* end point comparison */ - r3 = 15; /* max counter */ - -/* read entries from table */ - -.Lread_iaddr: - R0 = [I2++]; - CC = R0 == R1; - IF CC JUMP .Lidone; - [I0++] = R0; - -.Lread_idata: - R2 = [I2++]; - [I1++] = R2; - R3 = R3 + R1; - CC = R3 == R1; - IF !CC JUMP .Lread_iaddr; - -.Lidone: /* Enable Instruction Cache */ P0.l = (IMEM_CONTROL & 0xFFFF); P0.h = (IMEM_CONTROL >> 16); - R1 = [P0]; - R0 = (IMC | ENICPLB); - R0 = R0 | R1; /* Anomaly 05000125 */ - CLI R2; + CLI R1; SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */ .align 8; [P0] = R0; SSYNC; - STI R2; + STI R1; RTS; -ENDPROC(_bfin_icache_init) +ENDPROC(_bfin_write_IMEM_CONTROL) #endif #if defined(CONFIG_BLKFIN_DCACHE) -ENTRY(_bfin_dcache_init) - - /* Initialize Data CPLBS */ - - I0.L = (DCPLB_ADDR0 & 0xFFFF); - I0.H = (DCPLB_ADDR0 >> 16); - - I1.L = (DCPLB_DATA0 & 0xFFFF); - I1.H = (DCPLB_DATA0 >> 16); - - I2.L = _dcplb_table; - I2.H = _dcplb_table; - - R1 = -1; /* end point comparison */ - R3 = 15; /* max counter */ - - /* read entries from table */ -.Lread_daddr: - R0 = [I2++]; - cc = R0 == R1; - IF CC JUMP .Lddone; - [I0++] = R0; - -.Lread_ddata: - R2 = [I2++]; - [I1++] = R2; - R3 = R3 + R1; - CC = R3 == R1; - IF !CC JUMP .Lread_daddr; -.Lddone: - P0.L = (DMEM_CONTROL & 0xFFFF); - P0.H = (DMEM_CONTROL >> 16); - R1 = [P0]; - - R0 = DMEM_CNTR; - - R0 = R0 | R1; - /* Anomaly 05000125 */ - CLI R2; +ENTRY(_bfin_write_DMEM_CONTROL) + CLI R1; SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */ .align 8; [P0] = R0; SSYNC; - STI R2; + STI R1; RTS; -ENDPROC(_bfin_dcache_init) +ENDPROC(_bfin_write_DMEM_CONTROL) +#endif + #endif diff --git a/arch/blackfin/mach-common/cplbinfo.c b/arch/blackfin/mach-common/cplbinfo.c index caa9623e6bd..785ca981697 100644 --- a/arch/blackfin/mach-common/cplbinfo.c +++ b/arch/blackfin/mach-common/cplbinfo.c @@ -31,11 +31,10 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/proc_fs.h> +#include <linux/uaccess.h> #include <asm/current.h> -#include <asm/uaccess.h> #include <asm/system.h> - #include <asm/cplb.h> #include <asm/blackfin.h> @@ -92,8 +91,7 @@ static char *cplb_print_entry(char *buf, int type) } else buf += sprintf(buf, "Data CPLB entry:\n"); - buf += sprintf(buf, "Address\t\tData\tSize\tValid\tLocked\tSwapin\ -\tiCount\toCount\n"); + buf += sprintf(buf, "Address\t\tData\tSize\tValid\tLocked\tSwapin\n\tiCount\toCount\n"); while (*p_addr != 0xffffffff) { entry = cplb_find_entry(cplb_addr, cplb_data, *p_addr, *p_data); @@ -144,8 +142,7 @@ static int cplbinfo_proc_output(char *buf) p = buf; - p += sprintf(p, - "------------------ CPLB Information ------------------\n\n"); + p += sprintf(p, "------------------ CPLB Information ------------------\n\n"); if (bfin_read_IMEM_CONTROL() & ENICPLB) p = cplb_print_entry(p, CPLB_I); @@ -191,9 +188,9 @@ static int __init cplbinfo_init(void) { struct proc_dir_entry *entry; - if ((entry = create_proc_entry("cplbinfo", 0, NULL)) == NULL) { + entry = create_proc_entry("cplbinfo", 0, NULL); + if (!entry) return -ENOMEM; - } entry->read_proc = cplbinfo_read_proc; entry->write_proc = cplbinfo_write_proc; diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 40045b1386a..d61bba98fb5 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -49,34 +49,15 @@ #include <linux/linkage.h> +#include <linux/unistd.h> #include <asm/blackfin.h> -#include <asm/unistd.h> #include <asm/errno.h> #include <asm/thread_info.h> /* TIF_NEED_RESCHED */ #include <asm/asm-offsets.h> +#include <asm/trace.h> #include <asm/mach-common/context.S> -#ifdef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE - /* - * TODO: this should be proper save/restore, but for now - * we'll just cheat and use 0x1/0x13 - */ -# define DEBUG_START_HWTRACE \ - P5.l = LO(TBUFCTL); \ - P5.h = HI(TBUFCTL); \ - R7 = 0x13; \ - [P5] = R7; -# define DEBUG_STOP_HWTRACE \ - P5.l = LO(TBUFCTL); \ - P5.h = HI(TBUFCTL); \ - R7 = 0x01; \ - [P5] = R7; -#else -# define DEBUG_START_HWTRACE -# define DEBUG_STOP_HWTRACE -#endif - #ifdef CONFIG_EXCPT_IRQ_SYSC_L1 .section .l1.text #else @@ -110,25 +91,14 @@ ENTRY(_ex_icplb) ASTAT = [sp++]; SAVE_ALL_SYS call __cplb_hdr; - DEBUG_START_HWTRACE + DEBUG_START_HWTRACE(p5, r7) RESTORE_ALL_SYS SP = RETN; rtx; ENDPROC(_ex_icplb) -ENTRY(_ex_spinlock) - /* Transform this into a syscall - twiddle the syscall vector. */ - p5.l = lo(EVT15); - p5.h = hi(EVT15); - r7.l = _spinlock_bh; - r7.h = _spinlock_bh; - [p5] = r7; - csync; - /* Fall through. */ -ENDPROC(_ex_spinlock) - ENTRY(_ex_syscall) - DEBUG_START_HWTRACE + DEBUG_START_HWTRACE(p5, r7) (R7:6,P5:4) = [sp++]; ASTAT = [sp++]; raise 15; /* invoked by TRAP #0, for sys call */ @@ -136,26 +106,6 @@ ENTRY(_ex_syscall) rtx ENDPROC(_ex_syscall) -ENTRY(_spinlock_bh) - SAVE_ALL_SYS - /* To end up here, vector 15 was changed - so we have to change it - * back. - */ - p0.l = lo(EVT15); - p0.h = hi(EVT15); - p1.l = _evt_system_call; - p1.h = _evt_system_call; - [p0] = p1; - csync; - r0 = [sp + PT_R0]; - sp += -12; - call _sys_bfin_spinlock; - sp += 12; - [SP + PT_R0] = R0; - RESTORE_ALL_SYS - rti; -ENDPROC(_spinlock_bh) - ENTRY(_ex_soft_bp) r7 = retx; r7 += -2; @@ -186,7 +136,7 @@ ENTRY(_ex_single_step) if !cc jump _ex_trap_c; _return_from_exception: - DEBUG_START_HWTRACE + DEBUG_START_HWTRACE(p5, r7) #ifdef ANOMALY_05000257 R7=LC0; LC0=R7; @@ -208,7 +158,7 @@ ENTRY(_handle_bad_cplb) * need to make a CPLB exception look like a normal exception */ - DEBUG_START_HWTRACE + DEBUG_START_HWTRACE(p5, r7) RESTORE_ALL_SYS [--sp] = ASTAT; [--sp] = (R7:6, P5:4); @@ -251,7 +201,7 @@ ENTRY(_ex_trap_c) R6 = SEQSTAT; [P5] = R6; - DEBUG_START_HWTRACE + DEBUG_START_HWTRACE(p5, r7) (R7:6,P5:4) = [sp++]; ASTAT = [sp++]; SP = RETN; @@ -335,7 +285,7 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/ /* Try to deal with syscalls quickly. */ [--sp] = ASTAT; [--sp] = (R7:6, P5:4); - DEBUG_STOP_HWTRACE + DEBUG_STOP_HWTRACE(p5, r7) r7 = SEQSTAT; /* reason code is in bit 5:0 */ r6.l = lo(SEQSTAT_EXCAUSE); r6.h = hi(SEQSTAT_EXCAUSE); @@ -741,6 +691,10 @@ _schedule_and_signal_from_int: r0 = [p0]; sti r0; + r0 = sp; + sp += -12; + call _finish_atomic_sections; + sp += 12; jump.s .Lresume_userspace; _schedule_and_signal: @@ -790,14 +744,14 @@ ENDPROC(_init_exception_buff) ALIGN _extable: /* entry for each EXCAUSE[5:0] - * This table bmust be in sync with the table in ./kernel/traps.c + * This table must be in sync with the table in ./kernel/traps.c * EXCPT instruction can provide 4 bits of EXCAUSE, allowing 16 to be user defined */ .long _ex_syscall; /* 0x00 - User Defined - Linux Syscall */ .long _ex_soft_bp /* 0x01 - User Defined - Software breakpoint */ .long _ex_trap_c /* 0x02 - User Defined */ - .long _ex_trap_c /* 0x03 - User Defined - Atomic test and set service */ - .long _ex_spinlock /* 0x04 - User Defined */ + .long _ex_trap_c /* 0x03 - User Defined - userspace stack overflow */ + .long _ex_trap_c /* 0x04 - User Defined */ .long _ex_trap_c /* 0x05 - User Defined */ .long _ex_trap_c /* 0x06 - User Defined */ .long _ex_trap_c /* 0x07 - User Defined */ diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S index 8be548e061b..203e2070916 100644 --- a/arch/blackfin/mach-common/interrupt.S +++ b/arch/blackfin/mach-common/interrupt.S @@ -34,6 +34,7 @@ #include <linux/linkage.h> #include <asm/entry.h> #include <asm/asm-offsets.h> +#include <asm/trace.h> #include <asm/mach-common/context.S> @@ -170,10 +171,9 @@ ENTRY(_evt_ivhw) r7.l = W[p5]; 1: #endif - p0.l = lo(TBUFCTL); - p0.h = hi(TBUFCTL); - r0 = 1; - [p0] = r0; + + trace_buffer_stop(p0, r0); + r0 = IRQ_HWERR; r1 = sp; diff --git a/arch/blackfin/mach-common/ints-priority-dc.c b/arch/blackfin/mach-common/ints-priority-dc.c index 80943bbd37c..6b9fd03ce83 100644 --- a/arch/blackfin/mach-common/ints-priority-dc.c +++ b/arch/blackfin/mach-common/ints-priority-dc.c @@ -183,7 +183,7 @@ static void bf561_gpio_ack_irq(unsigned int irq) { u16 gpionr = irq - IRQ_PF0; - if(gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) { + if (gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) { set_gpio_data(gpionr, 0); SSYNC(); } @@ -193,7 +193,7 @@ static void bf561_gpio_mask_ack_irq(unsigned int irq) { u16 gpionr = irq - IRQ_PF0; - if(gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) { + if (gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) { set_gpio_data(gpionr, 0); SSYNC(); } @@ -222,7 +222,7 @@ static unsigned int bf561_gpio_irq_startup(unsigned int irq) if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { ret = gpio_request(gpionr, NULL); - if(ret) + if (ret) return ret; } @@ -262,7 +262,7 @@ static int bf561_gpio_irq_type(unsigned int irq, unsigned int type) if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { ret = gpio_request(gpionr, NULL); - if(ret) + if (ret) return ret; } @@ -371,6 +371,9 @@ int __init init_arch_irq(void) bfin_write_SICA_IMASK1(SIC_UNMASK_ALL); SSYNC(); + bfin_write_SICA_IWR0(IWR_ENABLE_ALL); + bfin_write_SICA_IWR1(IWR_ENABLE_ALL); + local_irq_disable(); init_exception_buff(); @@ -393,7 +396,7 @@ int __init init_arch_irq(void) bfin_write_EVT15(evt_system_call); CSYNC(); - for (irq = 0; irq < SYS_IRQS; irq++) { + for (irq = 0; irq <= SYS_IRQS; irq++) { if (irq <= IRQ_CORETMR) set_irq_chip(irq, &bf561_core_irqchip); else diff --git a/arch/blackfin/mach-common/ints-priority-sc.c b/arch/blackfin/mach-common/ints-priority-sc.c index 2cfc7d5aec5..28a878c3577 100644 --- a/arch/blackfin/mach-common/ints-priority-sc.c +++ b/arch/blackfin/mach-common/ints-priority-sc.c @@ -13,7 +13,7 @@ * 2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca> * 2003 Metrowerks/Motorola * 2003 Bas Vermeulen <bas@buyways.nl> - * Copyright 2004-2006 Analog Devices Inc. + * Copyright 2004-2007 Analog Devices Inc. * * Bugs: Enter bugs at http://blackfin.uclinux.org/ * @@ -65,9 +65,9 @@ atomic_t num_spurious; struct ivgx { /* irq number for request_irq, available in mach-bf533/irq.h */ - int irqno; + unsigned int irqno; /* corresponding bit in the SIC_ISR register */ - int isrflag; + unsigned int isrflag; } ivg_table[NR_PERI_INTS]; struct ivg_slice { @@ -88,17 +88,16 @@ static void __init search_IAR(void) for (ivg = 0; ivg <= IVG13 - IVG7; ivg++) { int irqn; - ivg7_13[ivg].istop = ivg7_13[ivg].ifirst = - &ivg_table[irq_pos]; + ivg7_13[ivg].istop = ivg7_13[ivg].ifirst = &ivg_table[irq_pos]; for (irqn = 0; irqn < NR_PERI_INTS; irqn++) { int iar_shift = (irqn & 7) * 4; if (ivg == (0xf & - bfin_read32((unsigned long *) SIC_IAR0 + + bfin_read32((unsigned long *)SIC_IAR0 + (irqn >> 3)) >> iar_shift)) { ivg_table[irq_pos].irqno = IVG7 + irqn; - ivg_table[irq_pos].isrflag = 1 << irqn; + ivg_table[irq_pos].isrflag = 1 << (irqn % 32); ivg7_13[ivg].istop++; irq_pos++; } @@ -141,15 +140,31 @@ static void bfin_core_unmask_irq(unsigned int irq) static void bfin_internal_mask_irq(unsigned int irq) { +#ifndef CONFIG_BF54x bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() & ~(1 << (irq - (IRQ_CORETMR + 1)))); +#else + unsigned mask_bank, mask_bit; + mask_bank = (irq - (IRQ_CORETMR + 1)) / 32; + mask_bit = (irq - (IRQ_CORETMR + 1)) % 32; + bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) & + ~(1 << mask_bit)); +#endif SSYNC(); } static void bfin_internal_unmask_irq(unsigned int irq) { +#ifndef CONFIG_BF54x bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() | (1 << (irq - (IRQ_CORETMR + 1)))); +#else + unsigned mask_bank, mask_bit; + mask_bank = (irq - (IRQ_CORETMR + 1)) / 32; + mask_bit = (irq - (IRQ_CORETMR + 1)) % 32; + bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) | + (1 << mask_bit)); +#endif SSYNC(); } @@ -206,7 +221,7 @@ static struct irq_chip bfin_generic_error_irqchip = { }; static void bfin_demux_error_irq(unsigned int int_err_irq, - struct irq_desc *intb_desc) + struct irq_desc *intb_desc) { int irq = 0; @@ -270,8 +285,8 @@ static void bfin_demux_error_irq(unsigned int int_err_irq, } pr_debug("IRQ %d:" - " MASKED PERIPHERAL ERROR INTERRUPT ASSERTED\n", - irq); + " MASKED PERIPHERAL ERROR INTERRUPT ASSERTED\n", + irq); } } else printk(KERN_ERR @@ -279,11 +294,10 @@ static void bfin_demux_error_irq(unsigned int int_err_irq, " INTERRUPT ASSERTED BUT NO SOURCE FOUND\n", __FUNCTION__, __FILE__, __LINE__); - } #endif /* BF537_GENERIC_ERROR_INT_DEMUX */ -#ifdef CONFIG_IRQCHIP_DEMUX_GPIO +#if defined(CONFIG_IRQCHIP_DEMUX_GPIO) && !defined(CONFIG_BF54x) static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)]; static unsigned short gpio_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)]; @@ -361,8 +375,7 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) } if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | - IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) - { + IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { ret = gpio_request(gpionr, NULL); if (ret) @@ -407,7 +420,6 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) return 0; } - static struct irq_chip bfin_gpio_irqchip = { .ack = bfin_gpio_ack_irq, .mask = bfin_gpio_mask_irq, @@ -419,20 +431,20 @@ static struct irq_chip bfin_gpio_irqchip = { }; static void bfin_demux_gpio_irq(unsigned int intb_irq, - struct irq_desc *intb_desc) + struct irq_desc *intb_desc) { u16 i; + struct irq_desc *desc; - for (i = 0; i < MAX_BLACKFIN_GPIOS; i+=16) { + for (i = 0; i < MAX_BLACKFIN_GPIOS; i += 16) { int irq = IRQ_PF0 + i; int flag_d = get_gpiop_data(i); int mask = - flag_d & (gpio_enabled[gpio_bank(i)] & - get_gpiop_maska(i)); + flag_d & (gpio_enabled[gpio_bank(i)] & get_gpiop_maska(i)); while (mask) { if (mask & 1) { - struct irq_desc *desc = irq_desc + irq; + desc = irq_desc + irq; desc->handle_irq(irq, desc); } irq++; @@ -441,6 +453,264 @@ static void bfin_demux_gpio_irq(unsigned int intb_irq, } } +#else /* CONFIG_IRQCHIP_DEMUX_GPIO */ + +#define NR_PINT_SYS_IRQS 4 +#define NR_PINT_BITS 32 +#define NR_PINTS 160 +#define IRQ_NOT_AVAIL 0xFF + +#define PINT_2_BANK(x) ((x) >> 5) +#define PINT_2_BIT(x) ((x) & 0x1F) +#define PINT_BIT(x) (1 << (PINT_2_BIT(x))) + +static unsigned char irq2pint_lut[NR_PINTS]; +static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS]; + +struct pin_int_t { + unsigned int mask_set; + unsigned int mask_clear; + unsigned int request; + unsigned int assign; + unsigned int edge_set; + unsigned int edge_clear; + unsigned int invert_set; + unsigned int invert_clear; + unsigned int pinstate; + unsigned int latch; +}; + +static struct pin_int_t *pint[NR_PINT_SYS_IRQS] = { + (struct pin_int_t *)PINT0_MASK_SET, + (struct pin_int_t *)PINT1_MASK_SET, + (struct pin_int_t *)PINT2_MASK_SET, + (struct pin_int_t *)PINT3_MASK_SET, +}; + +unsigned short get_irq_base(u8 bank, u8 bmap) +{ + + u16 irq_base; + + if (bank < 2) { /*PA-PB */ + irq_base = IRQ_PA0 + bmap * 16; + } else { /*PC-PJ */ + irq_base = IRQ_PC0 + bmap * 16; + } + + return irq_base; + +} + + /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */ +void init_pint_lut(void) +{ + u16 bank, bit, irq_base, bit_pos; + u32 pint_assign; + u8 bmap; + + memset(irq2pint_lut, IRQ_NOT_AVAIL, sizeof(irq2pint_lut)); + + for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) { + + pint_assign = pint[bank]->assign; + + for (bit = 0; bit < NR_PINT_BITS; bit++) { + + bmap = (pint_assign >> ((bit / 8) * 8)) & 0xFF; + + irq_base = get_irq_base(bank, bmap); + + irq_base += (bit % 8) + ((bit / 8) & 1 ? 8 : 0); + bit_pos = bit + bank * NR_PINT_BITS; + + pint2irq_lut[bit_pos] = irq_base - SYS_IRQS; + irq2pint_lut[irq_base - SYS_IRQS] = bit_pos; + + } + + } + +} + +static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)]; + +static void bfin_gpio_ack_irq(unsigned int irq) +{ + u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; + + pint[PINT_2_BANK(pint_val)]->request = PINT_BIT(pint_val); + SSYNC(); +} + +static void bfin_gpio_mask_ack_irq(unsigned int irq) +{ + u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; + u32 pintbit = PINT_BIT(pint_val); + u8 bank = PINT_2_BANK(pint_val); + + pint[bank]->request = pintbit; + pint[bank]->mask_clear = pintbit; + SSYNC(); +} + +static void bfin_gpio_mask_irq(unsigned int irq) +{ + u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; + + pint[PINT_2_BANK(pint_val)]->mask_clear = PINT_BIT(pint_val); + SSYNC(); +} + +static void bfin_gpio_unmask_irq(unsigned int irq) +{ + u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; + u32 pintbit = PINT_BIT(pint_val); + u8 bank = PINT_2_BANK(pint_val); + + pint[bank]->request = pintbit; + pint[bank]->mask_set = pintbit; + SSYNC(); +} + +static unsigned int bfin_gpio_irq_startup(unsigned int irq) +{ + unsigned int ret; + u16 gpionr = irq - IRQ_PA0; + u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; + + if (pint_val == IRQ_NOT_AVAIL) + return -ENODEV; + + if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { + ret = gpio_request(gpionr, NULL); + if (ret) + return ret; + } + + gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr); + bfin_gpio_unmask_irq(irq); + + return ret; +} + +static void bfin_gpio_irq_shutdown(unsigned int irq) +{ + bfin_gpio_mask_irq(irq); + gpio_free(irq - IRQ_PA0); + gpio_enabled[gpio_bank(irq - IRQ_PA0)] &= ~gpio_bit(irq - IRQ_PA0); +} + +static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) +{ + + unsigned int ret; + u16 gpionr = irq - IRQ_PA0; + u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; + u32 pintbit = PINT_BIT(pint_val); + u8 bank = PINT_2_BANK(pint_val); + + if (pint_val == IRQ_NOT_AVAIL) + return -ENODEV; + + if (type == IRQ_TYPE_PROBE) { + /* only probe unenabled GPIO interrupt lines */ + if (gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)) + return 0; + type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; + } + + if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | + IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { + if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { + ret = gpio_request(gpionr, NULL); + if (ret) + return ret; + } + + gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr); + } else { + gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr); + return 0; + } + + gpio_direction_input(gpionr); + + if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { + pint[bank]->edge_set = pintbit; + } else { + pint[bank]->edge_clear = pintbit; + } + + if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW))) + pint[bank]->invert_set = pintbit; /* low or falling edge denoted by one */ + else + pint[bank]->invert_set = pintbit; /* high or rising edge denoted by zero */ + + if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) + pint[bank]->invert_set = pintbit; + else + pint[bank]->invert_set = pintbit; + + SSYNC(); + + if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) + set_irq_handler(irq, handle_edge_irq); + else + set_irq_handler(irq, handle_level_irq); + + return 0; +} + +static struct irq_chip bfin_gpio_irqchip = { + .ack = bfin_gpio_ack_irq, + .mask = bfin_gpio_mask_irq, + .mask_ack = bfin_gpio_mask_ack_irq, + .unmask = bfin_gpio_unmask_irq, + .set_type = bfin_gpio_irq_type, + .startup = bfin_gpio_irq_startup, + .shutdown = bfin_gpio_irq_shutdown +}; + +static void bfin_demux_gpio_irq(unsigned int intb_irq, + struct irq_desc *intb_desc) +{ + u8 bank, pint_val; + u32 request, irq; + struct irq_desc *desc; + + switch (intb_irq) { + case IRQ_PINT0: + bank = 0; + break; + case IRQ_PINT2: + bank = 2; + break; + case IRQ_PINT3: + bank = 3; + break; + case IRQ_PINT1: + bank = 1; + break; + default: + return; + } + + pint_val = bank * NR_PINT_BITS; + + request = pint[bank]->request; + + while (request) { + if (request & 1) { + irq = pint2irq_lut[pint_val] + SYS_IRQS; + desc = irq_desc + irq; + desc->handle_irq(irq, desc); + } + pint_val++; + request >>= 1; + } + +} #endif /* CONFIG_IRQCHIP_DEMUX_GPIO */ /* @@ -452,7 +722,18 @@ int __init init_arch_irq(void) int irq; unsigned long ilat = 0; /* Disable all the peripheral intrs - page 4-29 HW Ref manual */ +#ifdef CONFIG_BF54x + bfin_write_SIC_IMASK0(SIC_UNMASK_ALL); + bfin_write_SIC_IMASK1(SIC_UNMASK_ALL); + bfin_write_SIC_IMASK2(SIC_UNMASK_ALL); + bfin_write_SIC_IWR0(IWR_ENABLE_ALL); + bfin_write_SIC_IWR1(IWR_ENABLE_ALL); + bfin_write_SIC_IWR2(IWR_ENABLE_ALL); +#else bfin_write_SIC_IMASK(SIC_UNMASK_ALL); + bfin_write_SIC_IWR(IWR_ENABLE_ALL); +#endif + SSYNC(); local_irq_disable(); @@ -475,7 +756,18 @@ int __init init_arch_irq(void) bfin_write_EVT15(evt_system_call); CSYNC(); - for (irq = 0; irq < SYS_IRQS; irq++) { +#if defined(CONFIG_IRQCHIP_DEMUX_GPIO) && defined(CONFIG_BF54x) +#ifdef CONFIG_PINTx_REASSIGN + pint[0]->assign = CONFIG_PINT0_ASSIGN; + pint[1]->assign = CONFIG_PINT1_ASSIGN; + pint[2]->assign = CONFIG_PINT2_ASSIGN; + pint[3]->assign = CONFIG_PINT3_ASSIGN; +#endif + /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */ + init_pint_lut(); +#endif + + for (irq = 0; irq <= SYS_IRQS; irq++) { if (irq <= IRQ_CORETMR) set_irq_chip(irq, &bfin_core_irqchip); else @@ -484,20 +776,42 @@ int __init init_arch_irq(void) if (irq != IRQ_GENERIC_ERROR) { #endif + switch (irq) { #ifdef CONFIG_IRQCHIP_DEMUX_GPIO - if ((irq != IRQ_PROG_INTA) /*PORT F & G MASK_A Interrupt*/ -# if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)) - && (irq != IRQ_MAC_RX) /*PORT H MASK_A Interrupt*/ -# endif - ) { +#ifndef CONFIG_BF54x + case IRQ_PROG_INTA: + set_irq_chained_handler(irq, + bfin_demux_gpio_irq); + break; +#if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)) + case IRQ_MAC_RX: + set_irq_chained_handler(irq, + bfin_demux_gpio_irq); + break; #endif - set_irq_handler(irq, handle_simple_irq); -#ifdef CONFIG_IRQCHIP_DEMUX_GPIO - } else { +#else + case IRQ_PINT0: set_irq_chained_handler(irq, bfin_demux_gpio_irq); - } + break; + case IRQ_PINT1: + set_irq_chained_handler(irq, + bfin_demux_gpio_irq); + break; + case IRQ_PINT2: + set_irq_chained_handler(irq, + bfin_demux_gpio_irq); + break; + case IRQ_PINT3: + set_irq_chained_handler(irq, + bfin_demux_gpio_irq); + break; +#endif /*CONFIG_BF54x */ #endif + default: + set_irq_handler(irq, handle_simple_irq); + break; + } #ifdef BF537_GENERIC_ERROR_INT_DEMUX } else { @@ -513,7 +827,11 @@ int __init init_arch_irq(void) #endif #ifdef CONFIG_IRQCHIP_DEMUX_GPIO +#ifndef CONFIG_BF54x for (irq = IRQ_PF0; irq < NR_IRQS; irq++) { +#else + for (irq = IRQ_PA0; irq < NR_IRQS; irq++) { +#endif set_irq_chip(irq, &bfin_gpio_irqchip); /* if configured as edge, then will be changed to do_edge_IRQ */ set_irq_handler(irq, handle_level_irq); @@ -526,8 +844,7 @@ int __init init_arch_irq(void) bfin_write_ILAT(ilat); CSYNC(); - printk(KERN_INFO - "Configuring Blackfin Priority Driven Interrupts\n"); + printk(KERN_INFO "Configuring Blackfin Priority Driven Interrupts\n"); /* IMASK=xxx is equivalent to STI xx or irq_flags=xx, * local_irq_enable() */ @@ -538,14 +855,13 @@ int __init init_arch_irq(void) /* Enable interrupts IVG7-15 */ irq_flags = irq_flags | IMASK_IVG15 | IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 | - IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | - IMASK_IVGHW; + IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW; return 0; } #ifdef CONFIG_DO_IRQ_L1 -void do_irq(int vec, struct pt_regs *fp)__attribute__((l1_text)); +void do_irq(int vec, struct pt_regs *fp) __attribute__((l1_text)); #endif void do_irq(int vec, struct pt_regs *fp) @@ -555,9 +871,25 @@ void do_irq(int vec, struct pt_regs *fp) } else { struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst; struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop; - unsigned long sic_status; +#ifdef CONFIG_BF54x + unsigned long sic_status[3]; SSYNC(); + sic_status[0] = bfin_read_SIC_ISR(0) & bfin_read_SIC_IMASK(0); + sic_status[1] = bfin_read_SIC_ISR(1) & bfin_read_SIC_IMASK(1); + sic_status[2] = bfin_read_SIC_ISR(2) & bfin_read_SIC_IMASK(2); + + for (;; ivg++) { + if (ivg >= ivg_stop) { + atomic_inc(&num_spurious); + return; + } + if (sic_status[(ivg->irqno - IVG7) / 32] & ivg->isrflag) + break; + } +#else + unsigned long sic_status; + SSYNC(); sic_status = bfin_read_SIC_IMASK() & bfin_read_SIC_ISR(); for (;; ivg++) { @@ -567,6 +899,7 @@ void do_irq(int vec, struct pt_regs *fp) } else if (sic_status & ivg->isrflag) break; } +#endif vec = ivg->irqno; } asm_do_IRQ(vec, fp); diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c index 150ef5d088d..1772d8d2c1a 100644 --- a/arch/blackfin/mach-common/pm.c +++ b/arch/blackfin/mach-common/pm.c @@ -35,10 +35,10 @@ #include <linux/pm.h> #include <linux/sched.h> #include <linux/proc_fs.h> +#include <linux/io.h> +#include <linux/irq.h> -#include <asm/io.h> #include <asm/dpmc.h> -#include <asm/irq.h> #include <asm/gpio.h> #ifdef CONFIG_PM_WAKEUP_GPIO_POLAR_H |