From 13fe24f37df20e580a5a364e67ec8cf3219d8f8c Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sun, 27 Jan 2008 15:38:56 +0800 Subject: [Blackfin] arch: fix bug - trap_tests fails to recover on some tests. http://blackfin.uclinux.org/gf/project/uclinux-dist/tracker/?action=TrackerItemEdit&tracker_item_id=3719 When the CPLBs get a miss, we do: - find a victim in the HW table - remove the victim - find the replacement in the software table - put it into the HW table. If we can't find a replacement in the software table, we accidently leave a duplicate in the HW table. This patch ensures that duplicate is marked as not valid. What we should do is find the replacement in the software table, before we find a victim in the HW table - but its too late in the release cycle to do that much restructuring of this code. Rather that duplicate code, connect Hardware Errors (irq5) into trap_c, so user space processes get killed properly. The rest of irq_panic() can be moved into traps.c (later) There is still a small corner case that causes problems when a pheriperal interrupt goes off a single cycle before a user space hardware error. This causes a kernel panic, rather than the user space process being killed. But, this checkin makes things work in 99.9% of the cases, and is a vast improvement from what is there today (which fails 100% of the time). Signed-off-by: Robin Getz Signed-off-by: Bryan Wu --- include/asm-blackfin/traps.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/asm-blackfin/traps.h b/include/asm-blackfin/traps.h index ee1cbf73a9ab..f0e5f940d9ca 100644 --- a/include/asm-blackfin/traps.h +++ b/include/asm-blackfin/traps.h @@ -45,6 +45,10 @@ #define VEC_CPLB_I_M (44) #define VEC_CPLB_I_MHIT (45) #define VEC_ILL_RES (46) /* including unvalid supervisor mode insn */ +/* The hardware reserves (63) for future use - we use it to tell our + * normal exception handling code we have a hardware error + */ +#define VEC_HWERR (63) #ifndef __ASSEMBLY__ -- cgit v1.2.3 From a5bb85dfffd38714d83cf7798886462d7314b90a Mon Sep 17 00:00:00 2001 From: Cliff Cai Date: Fri, 21 Dec 2007 21:04:40 +0800 Subject: [Blackfin] arch: fix bug SDIO driver fails to build for BF542/BF548 modified CMD_TIMEOUT and DAT_TIMEOUT to CMD_TIME_OUT and DAT_TIME_OUT Signed-off-by: Cliff Cai Signed-off-by: Bryan Wu --- include/asm-blackfin/mach-bf548/defBF542.h | 4 ++-- include/asm-blackfin/mach-bf548/defBF548.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/asm-blackfin/mach-bf548/defBF542.h b/include/asm-blackfin/mach-bf548/defBF542.h index 32d07130200c..a7c809f29ede 100644 --- a/include/asm-blackfin/mach-bf548/defBF542.h +++ b/include/asm-blackfin/mach-bf548/defBF542.h @@ -432,8 +432,8 @@ #define CMD_CRC_FAIL 0x1 /* CMD CRC Fail */ #define DAT_CRC_FAIL 0x2 /* Data CRC Fail */ -#define CMD_TIMEOUT 0x4 /* CMD Time Out */ -#define DAT_TIMEOUT 0x8 /* Data Time Out */ +#define CMD_TIME_OUT 0x4 /* CMD Time Out */ +#define DAT_TIME_OUT 0x8 /* Data Time Out */ #define TX_UNDERRUN 0x10 /* Transmit Underrun */ #define RX_OVERRUN 0x20 /* Receive Overrun */ #define CMD_RESP_END 0x40 /* CMD Response End */ diff --git a/include/asm-blackfin/mach-bf548/defBF548.h b/include/asm-blackfin/mach-bf548/defBF548.h index ecbca952985c..e46f56891e6a 100644 --- a/include/asm-blackfin/mach-bf548/defBF548.h +++ b/include/asm-blackfin/mach-bf548/defBF548.h @@ -1095,8 +1095,8 @@ #define CMD_CRC_FAIL 0x1 /* CMD CRC Fail */ #define DAT_CRC_FAIL 0x2 /* Data CRC Fail */ -#define CMD_TIMEOUT 0x4 /* CMD Time Out */ -#define DAT_TIMEOUT 0x8 /* Data Time Out */ +#define CMD_TIME_OUT 0x4 /* CMD Time Out */ +#define DAT_TIME_OUT 0x8 /* Data Time Out */ #define TX_UNDERRUN 0x10 /* Transmit Underrun */ #define RX_OVERRUN 0x20 /* Receive Overrun */ #define CMD_RESP_END 0x40 /* CMD Response End */ -- cgit v1.2.3 From fb5f00492a748facc9f069c95621e05c148edf53 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Sun, 23 Dec 2007 23:02:13 +0800 Subject: [Blackfin] arch: Fix bug to Enable kernel to build for bf548 with PM. On BF548-EZKIT, build kernel faills with power management, video and audio enabled. This patch fix this. Signed-off-by: Sonic Zhang Signed-off-by: Bryan Wu --- arch/blackfin/Kconfig | 2 ++ arch/blackfin/mach-bf548/head.S | 8 +++--- arch/blackfin/mach-bf548/ints-priority.c | 2 +- arch/blackfin/mach-common/dpmc.S | 46 ++++++++++++++++++++++++------ arch/blackfin/mach-common/pm.c | 16 +++++++++++ include/asm-blackfin/mach-bf548/irq.h | 4 +-- include/asm-blackfin/mach-bf548/mem_init.h | 1 + 7 files changed, 64 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 25232ba08119..5ebcfd226ed8 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -951,6 +951,8 @@ config PM_WAKEUP_SIC_IWR depends on PM_WAKEUP_GPIO_BY_SIC_IWR default 0x80000000 if (BF537 || BF536 || BF534) default 0x100000 if (BF533 || BF532 || BF531) + default 0x800000 if (BF549 || BF548 || BF547 || BF542) + default 0x800000 if (BF527 || BF524 || BF522) config PM_WAKEUP_GPIO_NUMBER int "Wakeup GPIO number" diff --git a/arch/blackfin/mach-bf548/head.S b/arch/blackfin/mach-bf548/head.S index 74b34c7f3629..745662e88759 100644 --- a/arch/blackfin/mach-bf548/head.S +++ b/arch/blackfin/mach-bf548/head.S @@ -298,8 +298,8 @@ ENTRY(_start_dma_code) w[p0] = r0.l; ssync; - p0.h = hi(SIC_IWR); - p0.l = lo(SIC_IWR); + p0.h = hi(SIC_IWR0); + p0.l = lo(SIC_IWR0); r0.l = 0x1; r0.h = 0x0; [p0] = r0; @@ -395,8 +395,8 @@ ENTRY(_start_dma_code) [P2] = R1; SSYNC; - p0.h = hi(SIC_IWR); - p0.l = lo(SIC_IWR); + p0.h = hi(SIC_IWR0); + p0.l = lo(SIC_IWR0); r0.l = lo(IWR_ENABLE_ALL); r0.h = hi(IWR_ENABLE_ALL); [p0] = r0; diff --git a/arch/blackfin/mach-bf548/ints-priority.c b/arch/blackfin/mach-bf548/ints-priority.c index cb0ebac53c79..05e3b3cb4c0a 100644 --- a/arch/blackfin/mach-bf548/ints-priority.c +++ b/arch/blackfin/mach-bf548/ints-priority.c @@ -58,7 +58,7 @@ void program_IAR(void) ((CONFIG_IRQ_PINT1 - 7) << IRQ_PINT1_POS) | ((CONFIG_IRQ_MDMAS0 - 7) << IRQ_MDMAS0_POS) | ((CONFIG_IRQ_MDMAS1 - 7) << IRQ_MDMAS1_POS) | - ((CONFIG_IRQ_WATCHDOG - 7) << IRQ_WATCHDOG_POS)); + ((CONFIG_IRQ_WATCHDOG - 7) << IRQ_WATCH_POS)); bfin_write_SIC_IAR3(((CONFIG_IRQ_DMAC1_ERR - 7) << IRQ_DMAC1_ERR_POS) | ((CONFIG_IRQ_SPORT2_ERR - 7) << IRQ_SPORT2_ERR_POS) | diff --git a/arch/blackfin/mach-common/dpmc.S b/arch/blackfin/mach-common/dpmc.S index 39fbc2861107..301ac1b6681f 100644 --- a/arch/blackfin/mach-common/dpmc.S +++ b/arch/blackfin/mach-common/dpmc.S @@ -38,6 +38,9 @@ ENTRY(_unmask_wdog_wakeup_evt) #if defined(CONFIG_BF561) P0.H = hi(SICA_IWR1); P0.L = lo(SICA_IWR1); +#elif defined(CONFIG_BF54x) || defined(CONFIG_BF52x) + P0.h = HI(SIC_IWR0); + P0.l = LO(SIC_IWR0); #else P0.h = HI(SIC_IWR); P0.l = LO(SIC_IWR); @@ -236,7 +239,7 @@ ENTRY(_deep_sleep) call _set_sic_iwr; - call _set_sdram_srfs; + call _set_dram_srfs; /* Clear all the interrupts,bits sticky */ R0 = 0xFFFF (Z); @@ -253,7 +256,7 @@ ENTRY(_deep_sleep) SSYNC; IDLE; - call _unset_sdram_srfs; + call _unset_dram_srfs; call _test_pll_locked; @@ -285,7 +288,7 @@ ENTRY(_sleep_deeper) P3 = R0; R0 = IWR_ENABLE(0); call _set_sic_iwr; - call _set_sdram_srfs; + call _set_dram_srfs; /* Clear all the interrupts,bits sticky */ R0 = 0xFFFF (Z); @@ -360,7 +363,7 @@ ENTRY(_sleep_deeper) IDLE; call _test_pll_locked; - call _unset_sdram_srfs; + call _unset_dram_srfs; STI R4; @@ -368,25 +371,47 @@ ENTRY(_sleep_deeper) ( R7:0, P5:0 ) = [SP++]; RTS; -ENTRY(_set_sdram_srfs) - /* set the sdram to self refresh mode */ +ENTRY(_set_dram_srfs) + /* set the dram to self refresh mode */ +#if defined(CONFIG_BF54x) + P0.H = hi(EBIU_RSTCTL); + P0.L = lo(EBIU_RSTCTL); + R2 = [P0]; + R3.H = hi(SRREQ); + R3.L = lo(SRREQ); +#else P0.H = hi(EBIU_SDGCTL); P0.L = lo(EBIU_SDGCTL); R2 = [P0]; R3.H = hi(SRFS); R3.L = lo(SRFS); +#endif R2 = R2|R3; [P0] = R2; ssync; +#if defined(CONFIG_BF54x) +.LSRR_MODE: + R2 = [P0]; + CC = BITTST(R2, 4); + if !CC JUMP .LSRR_MODE; +#endif RTS; -ENTRY(_unset_sdram_srfs) - /* set the sdram out of self refresh mode */ +ENTRY(_unset_dram_srfs) + /* set the dram out of self refresh mode */ +#if defined(CONFIG_BF54x) + P0.H = hi(EBIU_RSTCTL); + P0.L = lo(EBIU_RSTCTL); + R2 = [P0]; + R3.H = hi(SRREQ); + R3.L = lo(SRREQ); +#else P0.H = hi(EBIU_SDGCTL); P0.L = lo(EBIU_SDGCTL); R2 = [P0]; R3.H = hi(SRFS); R3.L = lo(SRFS); +#endif R3 = ~R3; R2 = R2&R3; [P0] = R2; @@ -394,8 +419,13 @@ ENTRY(_unset_sdram_srfs) RTS; ENTRY(_set_sic_iwr) +#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) + P0.H = hi(SIC_IWR0); + P0.L = lo(SIC_IWR0); +#else P0.H = hi(SIC_IWR); P0.L = lo(SIC_IWR); +#endif [P0] = R0; SSYNC; RTS; diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c index dac51fb06f22..81930f7d06f1 100644 --- a/arch/blackfin/mach-common/pm.c +++ b/arch/blackfin/mach-common/pm.c @@ -77,7 +77,15 @@ void bfin_pm_suspend_standby_enter(void) gpio_pm_restore(); +#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) + bfin_write_SIC_IWR0(IWR_ENABLE_ALL); + bfin_write_SIC_IWR1(IWR_ENABLE_ALL); +# ifdef CONFIG_BF54x + bfin_write_SIC_IWR2(IWR_ENABLE_ALL); +# endif +#else bfin_write_SIC_IWR(IWR_ENABLE_ALL); +#endif local_irq_restore(flags); } @@ -85,7 +93,15 @@ void bfin_pm_suspend_standby_enter(void) #if defined(CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR) sleep_deeper(CONFIG_PM_WAKEUP_SIC_IWR); +# if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) + bfin_write_SIC_IWR0(IWR_ENABLE_ALL); + bfin_write_SIC_IWR1(IWR_ENABLE_ALL); +# ifdef CONFIG_BF54x + bfin_write_SIC_IWR2(IWR_ENABLE_ALL); +# endif +# else bfin_write_SIC_IWR(IWR_ENABLE_ALL); +# endif #endif /* CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR */ } diff --git a/include/asm-blackfin/mach-bf548/irq.h b/include/asm-blackfin/mach-bf548/irq.h index 9fb7bc5399a8..c34507a3f1df 100644 --- a/include/asm-blackfin/mach-bf548/irq.h +++ b/include/asm-blackfin/mach-bf548/irq.h @@ -88,7 +88,7 @@ Events (highest priority) EMU 0 #define IRQ_PINT1 BFIN_IRQ(20) /* PINT1 Interrupt */ #define IRQ_MDMAS0 BFIN_IRQ(21) /* MDMA Stream 0 Interrupt */ #define IRQ_MDMAS1 BFIN_IRQ(22) /* MDMA Stream 1 Interrupt */ -#define IRQ_WATCHDOG BFIN_IRQ(23) /* Watchdog Interrupt */ +#define IRQ_WATCH BFIN_IRQ(23) /* Watchdog Interrupt */ #define IRQ_DMAC1_ERROR BFIN_IRQ(24) /* DMAC1 Status (Error) Interrupt */ #define IRQ_SPORT2_ERROR BFIN_IRQ(25) /* SPORT2 Error Interrupt */ #define IRQ_SPORT3_ERROR BFIN_IRQ(26) /* SPORT3 Error Interrupt */ @@ -406,7 +406,7 @@ Events (highest priority) EMU 0 #define IRQ_PINT1_POS 16 #define IRQ_MDMAS0_POS 20 #define IRQ_MDMAS1_POS 24 -#define IRQ_WATCHDOG_POS 28 +#define IRQ_WATCH_POS 28 /* IAR3 BIT FIELDS */ #define IRQ_DMAC1_ERR_POS 0 diff --git a/include/asm-blackfin/mach-bf548/mem_init.h b/include/asm-blackfin/mach-bf548/mem_init.h index 0cb279e973d7..e792eb7ae6a0 100644 --- a/include/asm-blackfin/mach-bf548/mem_init.h +++ b/include/asm-blackfin/mach-bf548/mem_init.h @@ -30,6 +30,7 @@ */ #if (CONFIG_MEM_MT46V32M16) +#endif #if defined CONFIG_CLKIN_HALF #define CLKIN_HALF 1 -- cgit v1.2.3 From b03b08ba9c7235861adf4dde712dade0bb756fe0 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sun, 23 Dec 2007 22:57:01 +0800 Subject: [Blackfin] arch: Clean up dump_bfin_mem Clean up dump_bfin_mem so that it will display content from the kernel, as well as l1 instruction, when deferred HW errors happen, print out the last frame info if it makes sense. Signed-off-by: Robin Getz Signed-off-by: Bryan Wu --- arch/blackfin/kernel/early_printk.c | 2 +- arch/blackfin/kernel/process.c | 1 + arch/blackfin/kernel/traps.c | 132 +++++++++++++++++++++++------------- include/asm-blackfin/bfin-global.h | 2 +- 4 files changed, 87 insertions(+), 50 deletions(-) (limited to 'include') diff --git a/arch/blackfin/kernel/early_printk.c b/arch/blackfin/kernel/early_printk.c index 724f4a5a1d46..c892777267d5 100644 --- a/arch/blackfin/kernel/early_printk.c +++ b/arch/blackfin/kernel/early_printk.c @@ -205,7 +205,7 @@ asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr) if (likely(early_console == NULL)) setup_early_printk(DEFAULT_EARLY_PORT); - dump_bfin_mem((void *)fp->retx); + dump_bfin_mem(fp); show_regs(fp); dump_bfin_trace_buffer(); diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index 5bf15125f0d6..fff3dd9eadda 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c @@ -327,6 +327,7 @@ void finish_atomic_sections (struct pt_regs *regs) } #if defined(CONFIG_ACCESS_CHECK) +/* Return 1 if access to memory range is OK, 0 otherwise */ int _access_ok(unsigned long addr, unsigned long size) { if (size == 0) diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 8bbfef31666b..c90f16825f98 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -39,6 +39,7 @@ #include #include #include +#include #ifdef CONFIG_KGDB # include @@ -171,7 +172,7 @@ asmlinkage void double_fault_c(struct pt_regs *fp) oops_in_progress = 1; printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); dump_bfin_process(fp); - dump_bfin_mem((void *)fp->retx); + dump_bfin_mem(fp); show_regs(fp); panic("Double Fault - unrecoverable event\n"); @@ -196,6 +197,10 @@ asmlinkage void trap_c(struct pt_regs *fp) * we will kernel panic, so the system reboots. * If KGDB is enabled, don't set this for kernel breakpoints */ + + /* TODO: check to see if we are in some sort of deferred HWERR + * that we should be able to recover from, not kernel panic + */ if ((bfin_read_IPEND() & 0xFFC0) #ifdef CONFIG_KGDB && trapnr != VEC_EXCPT02 @@ -478,11 +483,7 @@ asmlinkage void trap_c(struct pt_regs *fp) if (sig != SIGTRAP) { unsigned long stack; dump_bfin_process(fp); - /* Is it an interrupt, or an exception? */ - if (trapnr == VEC_HWERR) - dump_bfin_mem((void *)fp->pc); - else - dump_bfin_mem((void *)fp->retx); + dump_bfin_mem(fp); show_regs(fp); /* Print out the trace buffer if it makes sense */ @@ -644,8 +645,10 @@ void dump_bfin_process(struct pt_regs *fp) if (oops_in_progress) printk(KERN_EMERG "Kernel OOPS in progress\n"); - if (context & 0x0020) - printk(KERN_NOTICE "Deferred excecption or HW Error context\n"); + if (context & 0x0020 && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) + printk(KERN_NOTICE "HW Error context\n"); + else if (context & 0x0020) + printk(KERN_NOTICE "Defered Exception context\n"); else if (context & 0x3FC0) printk(KERN_NOTICE "Interrupt context\n"); else if (context & 0x4000) @@ -673,49 +676,82 @@ void dump_bfin_process(struct pt_regs *fp) "No Valid process in current context\n"); } -void dump_bfin_mem(void *retaddr) +void dump_bfin_mem(struct pt_regs *fp) { + unsigned short *addr, *erraddr, val = 0, err = 0; + char sti = 0, buf[6]; - if (retaddr >= (void *)FIXED_CODE_START && retaddr < (void *)physical_mem_end -#if L1_CODE_LENGTH != 0 - /* FIXME: Copy the code out of L1 Instruction SRAM through dma - memcpy. */ - && !(retaddr >= (void *)L1_CODE_START - && retaddr < (void *)(L1_CODE_START + L1_CODE_LENGTH)) -#endif - ) { - int i = ((unsigned int)retaddr & 0xFFFFFFF0) - 32; - unsigned short x = 0; - printk(KERN_NOTICE "return address: [0x%p]; contents of:", retaddr); - for (; i < ((unsigned int)retaddr & 0xFFFFFFF0) + 32; i += 2) { - if (!(i & 0xF)) - printk("\n" KERN_NOTICE "0x%08x: ", i); - - if (get_user(x, (unsigned short *)i)) - break; + if (unlikely((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR)) + erraddr = (void *)fp->pc; + else + erraddr = (void *)fp->retx; + + printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr); + + for (addr = (unsigned short *)((unsigned long)erraddr & ~0xF) - 0x10; + addr < (unsigned short *)((unsigned long)erraddr & ~0xF) + 0x10; + addr++) { + if (!((unsigned long)addr & 0xF)) + printk("\n" KERN_NOTICE "0x%p: ", addr); + + if (get_user(val, addr)) { + if (addr >= (unsigned short *)L1_CODE_START && + addr < (unsigned short *)(L1_CODE_START + L1_CODE_LENGTH)) { + dma_memcpy(&val, addr, sizeof(val)); + sprintf(buf, "%04x", val); + } else if (addr >= (unsigned short *)FIXED_CODE_START && + addr <= (unsigned short *)memory_start) { + val = bfin_read16(addr); + sprintf(buf, "%04x", val); + } else { + val = 0; + sprintf(buf, "????"); + } + } else + sprintf(buf, "%04x", val); + + if (addr == erraddr) { + printk("[%s]", buf); + err = val; + } else + printk(" %s ", buf); + + /* Do any previous instructions turn on interrupts? */ + if (addr <= erraddr && /* in the past */ + ((val >= 0x0040 && val <= 0x0047) || /* STI instruction */ + val == 0x017b)) /* [SP++] = RETI */ + sti = 1; + } + + printk("\n"); + + /* Hardware error interrupts can be deferred */ + if (unlikely(sti && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR && + oops_in_progress)){ + printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n"); #ifndef CONFIG_DEBUG_HWERR - /* If one of the last few instructions was a STI - * it is likely that the error occured awhile ago - * and we just noticed. This only happens in kernel - * context, which should mean an oops is happening - */ - if (oops_in_progress && x >= 0x0040 && x <= 0x0047 && i <= 0) - printk(KERN_EMERG "\n" - KERN_EMERG "WARNING : You should reconfigure" - " the kernel to turn on\n" - KERN_EMERG " 'Hardware error interrupt debugging'\n" - KERN_EMERG " The rest of this error is meanless\n"); -#endif - if (i == (unsigned int)retaddr) - printk("[%04x]", x); - else - printk(" %04x ", x); + printk(KERN_NOTICE "The remaining message may be meaningless\n" + KERN_NOTICE "You should enable CONFIG_DEBUG_HWERR to get a" + " better idea where it came from\n"); +#else + /* If we are handling only one peripheral interrupt + * and current mm and pid are valid, and the last error + * was in that user space process's text area + * print it out - because that is where the problem exists + */ + if ((!(((fp)->ipend & ~0x30) & (((fp)->ipend & ~0x30) - 1))) && + (current->pid && current->mm)) { + /* And the last RETI points to the current userspace context */ + if ((fp + 1)->pc >= current->mm->start_code && + (fp + 1)->pc <= current->mm->end_code) { + printk(KERN_NOTICE "It might be better to look around here : \n"); + printk(KERN_NOTICE "-------------------------------------------\n"); + show_regs(fp + 1); + printk(KERN_NOTICE "-------------------------------------------\n"); + } } - printk("\n"); - } else - printk("\n" KERN_NOTICE - "Cannot look at the [PC] <%p> for it is" - " in unreadable memory - sorry\n", retaddr); +#endif + } } void show_regs(struct pt_regs *fp) @@ -885,7 +921,7 @@ void panic_cplb_error(int cplb_panic, struct pt_regs *fp) printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void *)bfin_read_DCPLB_FAULT_ADDR()); printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void *)bfin_read_ICPLB_FAULT_ADDR()); dump_bfin_process(fp); - dump_bfin_mem((void *)fp->retx); + dump_bfin_mem(fp); show_regs(fp); dump_stack(); panic("Unrecoverable event\n"); diff --git a/include/asm-blackfin/bfin-global.h b/include/asm-blackfin/bfin-global.h index 39bdd86871cf..6ae0619d7696 100644 --- a/include/asm-blackfin/bfin-global.h +++ b/include/asm-blackfin/bfin-global.h @@ -51,7 +51,7 @@ extern unsigned long sclk_to_usecs(unsigned long sclk); extern unsigned long usecs_to_sclk(unsigned long usecs); extern void dump_bfin_process(struct pt_regs *regs); -extern void dump_bfin_mem(void *retaddr); +extern void dump_bfin_mem(struct pt_regs *regs); extern void dump_bfin_trace_buffer(void); extern int init_arch_irq(void); -- cgit v1.2.3 From 971d5bc4e5c75bfc4466deaff09839cd6f918eca Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Sun, 27 Jan 2008 16:32:31 +0800 Subject: [Blackfin] arch: Fix bug to Enable bf548 to Re-program Clocks while Kernel boots. Reprogram DDR EBIU register properly for bf548. Signed-off-by: Sonic Zhang Signed-off-by: Bryan Wu --- arch/blackfin/Kconfig | 19 +++++++- arch/blackfin/mach-bf548/head.S | 47 +++++++++++++++++++ include/asm-blackfin/mach-bf548/defBF54x_base.h | 31 ++++++++++++- include/asm-blackfin/mach-bf548/mem_init.h | 61 ++++++++++++++++++++++++- 4 files changed, 153 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 5ebcfd226ed8..1364dcaccc18 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -317,7 +317,7 @@ config VCO_MULT range 1 64 default "22" if BFIN533_EZKIT default "45" if BFIN533_STAMP - default "20" if (BFIN537_STAMP || BFIN527_EZKIT) + default "20" if (BFIN537_STAMP || BFIN527_EZKIT || BFIN548_EZKIT) default "22" if BFIN533_BLUETECHNIX_CM default "20" if BFIN537_BLUETECHNIX_CM default "20" if BFIN561_BLUETECHNIX_CM @@ -354,7 +354,7 @@ config SCLK_DIV range 1 15 default 5 if BFIN533_EZKIT default 5 if BFIN533_STAMP - default 4 if (BFIN537_STAMP || BFIN527_EZKIT) + default 4 if (BFIN537_STAMP || BFIN527_EZKIT || BFIN548_EZKIT) default 5 if BFIN533_BLUETECHNIX_CM default 4 if BFIN537_BLUETECHNIX_CM default 4 if BFIN561_BLUETECHNIX_CM @@ -409,6 +409,7 @@ config MEM_SIZE default 32 if BFIN533_EZKIT default 64 if BFIN527_EZKIT default 64 if BFIN537_STAMP + default 64 if BFIN548_EZKIT default 64 if BFIN561_EZKIT default 128 if BFIN533_STAMP default 64 if PNAV10 @@ -416,6 +417,7 @@ config MEM_SIZE config MEM_ADD_WIDTH int "SDRAM Memory Address Width" + depends on (!BF54x) default 9 if BFIN533_EZKIT default 9 if BFIN561_EZKIT default 9 if H8606_HVSISTEMAS @@ -424,6 +426,19 @@ config MEM_ADD_WIDTH default 11 if BFIN533_STAMP default 10 if PNAV10 + +choice + prompt "DDR SDRAM Chip Type" + depends on BFIN548_EZKIT + default MEM_MT46V32M16_5B + +config MEM_MT46V32M16_6T + bool "MT46V32M16_6T" + +config MEM_MT46V32M16_5B + bool "MT46V32M16_5B" +endchoice + config ENET_FLASH_PIN int "PF port/pin used for flash and ethernet sharing" depends on (BFIN533_STAMP) diff --git a/arch/blackfin/mach-bf548/head.S b/arch/blackfin/mach-bf548/head.S index 745662e88759..74fe258421a5 100644 --- a/arch/blackfin/mach-bf548/head.S +++ b/arch/blackfin/mach-bf548/head.S @@ -324,12 +324,25 @@ ENTRY(_start_dma_code) w[p0] = r0.l; ssync; +#if defined(CONFIG_BF54x) + P2.H = hi(EBIU_RSTCTL); + P2.L = lo(EBIU_RSTCTL); + R0 = [P2]; + BITSET (R0, 3); +#else P2.H = hi(EBIU_SDGCTL); P2.L = lo(EBIU_SDGCTL); R0 = [P2]; BITSET (R0, 24); +#endif [P2] = R0; SSYNC; +#if defined(CONFIG_BF54x) +.LSRR_MODE: + R0 = [P2]; + CC = BITTST(R0, 4); + if !CC JUMP .LSRR_MODE; +#endif r0 = CONFIG_VCO_MULT & 63; /* Load the VCO multiplier */ r0 = r0 << 9; /* Shift it over, */ @@ -361,6 +374,39 @@ ENTRY(_start_dma_code) w[p0] = r0.l; ssync; +#if defined(CONFIG_BF54x) + P2.H = hi(EBIU_RSTCTL); + P2.L = lo(EBIU_RSTCTL); + R0 = [P2]; + CC = BITTST(R0, 0); + if CC jump .Lskipddrrst; + BITSET (R0, 0); +.Lskipddrrst: + BITCLR (R0, 3); + [P2] = R0; + SSYNC; + + p0.l = lo(EBIU_DDRCTL0); + p0.h = hi(EBIU_DDRCTL0); + r0.l = lo(mem_DDRCTL0); + r0.h = hi(mem_DDRCTL0); + [p0] = r0; + ssync; + + p0.l = lo(EBIU_DDRCTL1); + p0.h = hi(EBIU_DDRCTL1); + r0.l = lo(mem_DDRCTL1); + r0.h = hi(mem_DDRCTL1); + [p0] = r0; + ssync; + + p0.l = lo(EBIU_DDRCTL2); + p0.h = hi(EBIU_DDRCTL2); + r0.l = lo(mem_DDRCTL2); + r0.h = hi(mem_DDRCTL2); + [p0] = r0; + ssync; +#else p0.l = lo(EBIU_SDRRC); p0.h = hi(EBIU_SDRRC); r0 = mem_SDRRC; @@ -394,6 +440,7 @@ ENTRY(_start_dma_code) R1 = R1 | R0; [P2] = R1; SSYNC; +#endif p0.h = hi(SIC_IWR0); p0.l = lo(SIC_IWR0); diff --git a/include/asm-blackfin/mach-bf548/defBF54x_base.h b/include/asm-blackfin/mach-bf548/defBF54x_base.h index 319a48590c9c..08f90c21fe8a 100644 --- a/include/asm-blackfin/mach-bf548/defBF54x_base.h +++ b/include/asm-blackfin/mach-bf548/defBF54x_base.h @@ -1772,17 +1772,36 @@ #define TRP 0x3c0000 /* Pre charge-to-active command period */ #define TRAS 0x3c00000 /* Min Active-to-pre charge time */ #define TRC 0x3c000000 /* Active-to-active time */ +#define DDR_TRAS(x) ((x<<22)&TRAS) /* DDR tRAS = (1~15) cycles */ +#define DDR_TRP(x) ((x<<18)&TRP) /* DDR tRP = (1~15) cycles */ +#define DDR_TRC(x) ((x<<26)&TRC) /* DDR tRC = (1~15) cycles */ +#define DDR_TRFC(x) ((x<<14)&TRFC) /* DDR tRFC = (1~15) cycles */ +#define DDR_TREFI(x) (x&TREFI) /* DDR tRFC = (1~15) cycles */ /* Bit masks for EBIU_DDRCTL1 */ #define TRCD 0xf /* Active-to-Read/write delay */ -#define MRD 0xf0 /* Mode register set to active */ +#define TMRD 0xf0 /* Mode register set to active */ #define TWR 0x300 /* Write Recovery time */ #define DDRDATWIDTH 0x3000 /* DDR data width */ #define EXTBANKS 0xc000 /* External banks */ #define DDRDEVWIDTH 0x30000 /* DDR device width */ #define DDRDEVSIZE 0xc0000 /* DDR device size */ -#define TWWTR 0xf0000000 /* Write-to-read delay */ +#define TWTR 0xf0000000 /* Write-to-read delay */ +#define DDR_TWTR(x) ((x<<28)&TWTR) /* DDR tWTR = (1~15) cycles */ +#define DDR_TMRD(x) ((x<<4)&TMRD) /* DDR tMRD = (1~15) cycles */ +#define DDR_TWR(x) ((x<<8)&TWR) /* DDR tWR = (1~15) cycles */ +#define DDR_TRCD(x) (x&TRCD) /* DDR tRCD = (1~15) cycles */ +#define DDR_DATWIDTH 0x2000 /* DDR data width */ +#define EXTBANK_1 0 /* 1 external bank */ +#define EXTBANK_2 0x4000 /* 2 external banks */ +#define DEVSZ_64 0x40000 /* DDR External Bank Size = 64MB */ +#define DEVSZ_128 0x80000 /* DDR External Bank Size = 128MB */ +#define DEVSZ_256 0xc0000 /* DDR External Bank Size = 256MB */ +#define DEVSZ_512 0 /* DDR External Bank Size = 512MB */ +#define DEVWD_4 0 /* DDR Device Width = 4 Bits */ +#define DEVWD_8 0x10000 /* DDR Device Width = 8 Bits */ +#define DEVWD_16 0x20000 /* DDR Device Width = 16 Bits */ /* Bit masks for EBIU_DDRCTL2 */ @@ -1790,6 +1809,10 @@ #define CASLATENCY 0x70 /* CAS latency */ #define DLLRESET 0x100 /* DLL Reset */ #define REGE 0x1000 /* Register mode enable */ +#define CL_1_5 0x50 /* DDR CAS Latency = 1.5 cycles */ +#define CL_2 0x20 /* DDR CAS Latency = 2 cycles */ +#define CL_2_5 0x60 /* DDR CAS Latency = 2.5 cycles */ +#define CL_3 0x30 /* DDR CAS Latency = 3 cycles */ /* Bit masks for EBIU_DDRCTL3 */ @@ -2257,6 +2280,10 @@ #define CSEL 0x30 /* Core Select */ #define SSEL 0xf /* System Select */ +#define CSEL_DIV1 0x0000 /* CCLK = VCO / 1 */ +#define CSEL_DIV2 0x0010 /* CCLK = VCO / 2 */ +#define CSEL_DIV4 0x0020 /* CCLK = VCO / 4 */ +#define CSEL_DIV8 0x0030 /* CCLK = VCO / 8 */ /* Bit masks for PLL_CTL */ diff --git a/include/asm-blackfin/mach-bf548/mem_init.h b/include/asm-blackfin/mach-bf548/mem_init.h index e792eb7ae6a0..befc2903d5a5 100644 --- a/include/asm-blackfin/mach-bf548/mem_init.h +++ b/include/asm-blackfin/mach-bf548/mem_init.h @@ -28,10 +28,69 @@ * If not, write to the Free Software Foundation, * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#define MIN_DDR_SCLK(x) (x*(CONFIG_SCLK_HZ/1000/1000)/1000 + 1) -#if (CONFIG_MEM_MT46V32M16) +#if (CONFIG_MEM_MT46V32M16_6T) +#define DDR_SIZE DEVSZ_512 +#define DDR_WIDTH DEVWD_16 + +#define DDR_tRC DDR_TRC(MIN_DDR_SCLK(60)) +#define DDR_tRAS DDR_TRAS(MIN_DDR_SCLK(42)) +#define DDR_tRP DDR_TRP(MIN_DDR_SCLK(15)) +#define DDR_tRFC DDR_TRFC(MIN_DDR_SCLK(72)) +#define DDR_tREFI DDR_TREFI(MIN_DDR_SCLK(7800)) + +#define DDR_tRCD DDR_TRCD(MIN_DDR_SCLK(15)) +#define DDR_tWTR DDR_TWTR(1) +#define DDR_tMRD DDR_TMRD(MIN_DDR_SCLK(12)) +#define DDR_tWR DDR_TWR(MIN_DDR_SCLK(15)) +#endif + +#if (CONFIG_MEM_MT46V32M16_5B) +#define DDR_SIZE DEVSZ_512 +#define DDR_WIDTH DEVWD_16 + +#define DDR_tRC DDR_TRC(MIN_DDR_SCLK(55)) +#define DDR_tRAS DDR_TRAS(MIN_DDR_SCLK(40)) +#define DDR_tRP DDR_TRP(MIN_DDR_SCLK(15)) +#define DDR_tRFC DDR_TRFC(MIN_DDR_SCLK(70)) +#define DDR_tREFI DDR_TREFI(MIN_DDR_SCLK(7800)) + +#define DDR_tRCD DDR_TRCD(MIN_DDR_SCLK(15)) +#define DDR_tWTR DDR_TWTR(2) +#define DDR_tMRD DDR_TMRD(MIN_DDR_SCLK(10)) +#define DDR_tWR DDR_TWR(MIN_DDR_SCLK(15)) +#endif + +#if (CONFIG_MEM_GENERIC_BOARD) +#define DDR_SIZE DEVSZ_512 +#define DDR_WIDTH DEVWD_16 + +#define DDR_tRCD DDR_TRCD(3) +#define DDR_tWTR DDR_TWTR(2) +#define DDR_tWR DDR_TWR(2) +#define DDR_tMRD DDR_TMRD(2) +#define DDR_tRP DDR_TRP(3) +#define DDR_tRAS DDR_TRAS(7) +#define DDR_tRC DDR_TRC(10) +#define DDR_tRFC DDR_TRFC(12) +#define DDR_tREFI DDR_TREFI(1288) #endif +#if (CONFIG_SCLK_HZ <= 133333333) +#define DDR_CL CL_2 +#elif (CONFIG_SCLK_HZ <= 166666666) +#define DDR_CL CL_2_5 +#else +#define DDR_CL CL_3 +#endif + +#define mem_DDRCTL0 (DDR_tRP | DDR_tRAS | DDR_tRC | DDR_tRFC | DDR_tREFI) +#define mem_DDRCTL1 (DDR_DATWIDTH | EXTBANK_1 | DDR_SIZE | DDR_WIDTH | DDR_tWTR \ + | DDR_tMRD | DDR_tWR | DDR_tRCD) +#define mem_DDRCTL2 DDR_CL + + #if defined CONFIG_CLKIN_HALF #define CLKIN_HALF 1 #else -- cgit v1.2.3 From 3ca32c1dc62dabe67d7e51f6e8568e3965f52236 Mon Sep 17 00:00:00 2001 From: Bernd Schmidt Date: Mon, 24 Dec 2007 12:40:29 +0800 Subject: [Blackfin] arch: fix up coding style in uaccess.h Signed-off-by: Bernd Schmidt Signed-off-by: Bryan Wu --- include/asm-blackfin/uaccess.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-blackfin/uaccess.h b/include/asm-blackfin/uaccess.h index 2233f8f9314d..22a410b8003b 100644 --- a/include/asm-blackfin/uaccess.h +++ b/include/asm-blackfin/uaccess.h @@ -31,7 +31,7 @@ static inline void set_fs(mm_segment_t fs) #define VERIFY_READ 0 #define VERIFY_WRITE 1 -#define access_ok(type,addr,size) _access_ok((unsigned long)(addr),(size)) +#define access_ok(type, addr, size) _access_ok((unsigned long)(addr), (size)) static inline int is_in_rom(unsigned long addr) { -- cgit v1.2.3 From fac3cf432ef9b6bfd64b35b95afe0b7e0079da74 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Mon, 24 Dec 2007 20:07:03 +0800 Subject: [Blackfin] arch: Fix gpio label handling early serial init also utilizes the peripheral request api - however at this point bfin_gpio_init didn't allocate memory for the labels. So we always have two zombies (allocated pin functions without labels) This happens before the initcalls - We now allocate memory statically. Define MAX_RESOURCES individually for each cpu. Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/kernel/bfin_gpio.c | 31 ++++++++++++++++++------------- include/asm-blackfin/mach-bf527/portmux.h | 2 ++ include/asm-blackfin/mach-bf533/portmux.h | 2 ++ include/asm-blackfin/mach-bf537/portmux.h | 2 ++ include/asm-blackfin/mach-bf548/portmux.h | 2 ++ include/asm-blackfin/mach-bf561/portmux.h | 2 ++ 6 files changed, 28 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index ea13d2a22d69..ffee36910288 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -179,15 +179,13 @@ static struct gpio_port_t *gpio_array[gpio_bank(MAX_BLACKFIN_GPIOS)] = { #endif static unsigned short reserved_gpio_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; -static unsigned short reserved_peri_map[gpio_bank(MAX_BLACKFIN_GPIOS + 16)]; +static unsigned short reserved_peri_map[gpio_bank(MAX_RESOURCES)]; -#define MAX_RESOURCES 256 #define RESOURCE_LABEL_SIZE 16 -struct str_ident { +static struct str_ident { char name[RESOURCE_LABEL_SIZE]; -} *str_ident; - +} str_ident[MAX_RESOURCES]; #ifdef CONFIG_PM static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)]; @@ -251,6 +249,11 @@ static char *get_label(unsigned short ident) static int cmp_label(unsigned short ident, const char *label) { + if (label == NULL) { + dump_stack(); + printk(KERN_ERR "Please provide none-null label\n"); + } + if (label && str_ident) return strncmp(str_ident[ident].name, label, strlen(label)); @@ -419,12 +422,6 @@ static void default_gpio(unsigned short gpio) static int __init bfin_gpio_init(void) { - str_ident = kcalloc(MAX_RESOURCES, - sizeof(struct str_ident), GFP_KERNEL); - if (str_ident == NULL) - return -ENOMEM; - - memset(str_ident, 0, MAX_RESOURCES * sizeof(struct str_ident)); printk(KERN_INFO "Blackfin GPIO Controller\n"); @@ -785,6 +782,14 @@ void gpio_pm_restore(void) } #endif +#else /* BF548_FAMILY */ + +unsigned short get_gpio_dir(unsigned short gpio) +{ + return (0x01 & (gpio_array[gpio_bank(gpio)]->port_dir_clear >> gpio_sub_n(gpio))); +} +EXPORT_SYMBOL(get_gpio_dir); + #endif /* BF548_FAMILY */ /*********************************************************** @@ -1204,10 +1209,10 @@ static int gpio_proc_read(char *buf, char **start, off_t offset, for (c = 0; c < MAX_RESOURCES; c++) { if (!check_gpio(c) && (reserved_gpio_map[gpio_bank(c)] & gpio_bit(c))) - len = sprintf(buf, "GPIO_%d: %s \tGPIO %s\n", c, + len = sprintf(buf, "GPIO_%d: %s \t\tGPIO %s\n", c, get_label(c), get_gpio_dir(c) ? "OUTPUT" : "INPUT"); else if (reserved_peri_map[gpio_bank(c)] & gpio_bit(c)) - len = sprintf(buf, "GPIO_%d: %s \tPeripheral\n", c, get_label(c)); + len = sprintf(buf, "GPIO_%d: %s \t\tPeripheral\n", c, get_label(c)); else continue; buf += len; diff --git a/include/asm-blackfin/mach-bf527/portmux.h b/include/asm-blackfin/mach-bf527/portmux.h index dcf001adc63c..ae4d205bfcf5 100644 --- a/include/asm-blackfin/mach-bf527/portmux.h +++ b/include/asm-blackfin/mach-bf527/portmux.h @@ -1,6 +1,8 @@ #ifndef _MACH_PORTMUX_H_ #define _MACH_PORTMUX_H_ +#define MAX_RESOURCES MAX_BLACKFIN_GPIOS + #define P_PPI0_D0 (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(0)) #define P_PPI0_D1 (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(0)) #define P_PPI0_D2 (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(0)) diff --git a/include/asm-blackfin/mach-bf533/portmux.h b/include/asm-blackfin/mach-bf533/portmux.h index 137f4884acfe..685a2651dcda 100644 --- a/include/asm-blackfin/mach-bf533/portmux.h +++ b/include/asm-blackfin/mach-bf533/portmux.h @@ -1,6 +1,8 @@ #ifndef _MACH_PORTMUX_H_ #define _MACH_PORTMUX_H_ +#define MAX_RESOURCES MAX_BLACKFIN_GPIOS + #define P_PPI0_CLK (P_DONTCARE) #define P_PPI0_FS1 (P_DONTCARE) #define P_PPI0_FS2 (P_DONTCARE) diff --git a/include/asm-blackfin/mach-bf537/portmux.h b/include/asm-blackfin/mach-bf537/portmux.h index 5a3f7d3bf73d..78fee6e0f237 100644 --- a/include/asm-blackfin/mach-bf537/portmux.h +++ b/include/asm-blackfin/mach-bf537/portmux.h @@ -1,6 +1,8 @@ #ifndef _MACH_PORTMUX_H_ #define _MACH_PORTMUX_H_ +#define MAX_RESOURCES (MAX_BLACKFIN_GPIOS + GPIO_BANKSIZE) /* We additionally handle PORTJ */ + #define P_UART0_TX (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(0)) #define P_UART0_RX (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(0)) #define P_UART1_TX (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(0)) diff --git a/include/asm-blackfin/mach-bf548/portmux.h b/include/asm-blackfin/mach-bf548/portmux.h index 6b485120015f..8177a567dcdb 100644 --- a/include/asm-blackfin/mach-bf548/portmux.h +++ b/include/asm-blackfin/mach-bf548/portmux.h @@ -1,6 +1,8 @@ #ifndef _MACH_PORTMUX_H_ #define _MACH_PORTMUX_H_ +#define MAX_RESOURCES MAX_BLACKFIN_GPIOS + #define P_SPORT2_TFS (P_DEFINED | P_IDENT(GPIO_PA0) | P_FUNCT(0)) #define P_SPORT2_DTSEC (P_DEFINED | P_IDENT(GPIO_PA1) | P_FUNCT(0)) #define P_SPORT2_DTPRI (P_DEFINED | P_IDENT(GPIO_PA2) | P_FUNCT(0)) diff --git a/include/asm-blackfin/mach-bf561/portmux.h b/include/asm-blackfin/mach-bf561/portmux.h index 132ad31665e3..a6ee8206efb6 100644 --- a/include/asm-blackfin/mach-bf561/portmux.h +++ b/include/asm-blackfin/mach-bf561/portmux.h @@ -1,6 +1,8 @@ #ifndef _MACH_PORTMUX_H_ #define _MACH_PORTMUX_H_ +#define MAX_RESOURCES MAX_BLACKFIN_GPIOS + #define P_PPI0_CLK (P_DONTCARE) #define P_PPI0_FS1 (P_DONTCARE) #define P_PPI0_FS2 (P_DONTCARE) -- cgit v1.2.3 From 7cc1c4b2c44d7807f55da6a36f5b2e49977c67b7 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 24 Dec 2007 20:05:09 +0800 Subject: [Blackfin] arch: update to latest anomaly sheets Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- include/asm-blackfin/mach-bf533/anomaly.h | 12 ++++--- include/asm-blackfin/mach-bf537/anomaly.h | 14 +++++--- include/asm-blackfin/mach-bf548/anomaly.h | 54 +++++++++++++++++++------------ include/asm-blackfin/mach-bf561/anomaly.h | 18 +++++++++-- 4 files changed, 67 insertions(+), 31 deletions(-) (limited to 'include') diff --git a/include/asm-blackfin/mach-bf533/anomaly.h b/include/asm-blackfin/mach-bf533/anomaly.h index f36ff5af1b91..98209d40abba 100644 --- a/include/asm-blackfin/mach-bf533/anomaly.h +++ b/include/asm-blackfin/mach-bf533/anomaly.h @@ -7,9 +7,7 @@ */ /* This file shoule be up to date with: - * - Revision X, March 23, 2007; ADSP-BF533 Blackfin Processor Anomaly List - * - Revision AB, March 23, 2007; ADSP-BF532 Blackfin Processor Anomaly List - * - Revision W, March 23, 2007; ADSP-BF531 Blackfin Processor Anomaly List + * - Revision B, 12/10/2007; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List */ #ifndef _MACH_ANOMALY_H_ @@ -17,7 +15,7 @@ /* We do not support 0.1 or 0.2 silicon - sorry */ #if __SILICON_REVISION__ < 3 -# error Kernel will not work on BF533 silicon version 0.0, 0.1, or 0.2 +# error will not work on BF533 silicon version 0.0, 0.1, or 0.2 #endif #if defined(__ADSPBF531__) @@ -251,6 +249,12 @@ #define ANOMALY_05000192 (__SILICON_REVISION__ < 3) /* Internal Voltage Regulator may not start up */ #define ANOMALY_05000206 (__SILICON_REVISION__ < 3) +/* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */ +#define ANOMALY_05000357 (1) +/* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */ +#define ANOMALY_05000366 (1) +/* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */ +#define ANOMALY_05000371 (1) /* Anomalies that don't exist on this proc */ #define ANOMALY_05000266 (0) diff --git a/include/asm-blackfin/mach-bf537/anomaly.h b/include/asm-blackfin/mach-bf537/anomaly.h index 2b66ecf489f7..746a794b3119 100644 --- a/include/asm-blackfin/mach-bf537/anomaly.h +++ b/include/asm-blackfin/mach-bf537/anomaly.h @@ -7,9 +7,7 @@ */ /* This file shoule be up to date with: - * - Revision M, March 13, 2007; ADSP-BF537 Blackfin Processor Anomaly List - * - Revision L, March 13, 2007; ADSP-BF536 Blackfin Processor Anomaly List - * - Revision M, March 13, 2007; ADSP-BF534 Blackfin Processor Anomaly List + * - Revision A, 09/04/2007; ADSP-BF534/ADSP-BF536/ADSP-BF537 Blackfin Processor Anomaly List */ #ifndef _MACH_ANOMALY_H_ @@ -17,7 +15,7 @@ /* We do not support 0.1 silicon - sorry */ #if __SILICON_REVISION__ < 2 -# error Kernel will not work on BF537 silicon version 0.0 or 0.1 +# error will not work on BF537 silicon version 0.0 or 0.1 #endif #if defined(__ADSPBF534__) @@ -44,6 +42,8 @@ #define ANOMALY_05000122 (1) /* Killed 32-bit MMR write leads to next system MMR access thinking it should be 32-bit */ #define ANOMALY_05000157 (__SILICON_REVISION__ < 2) +/* Turning SPORTs on while External Frame Sync Is Active May Corrupt Data */ +#define ANOMALY_05000167 (1) /* PPI_DELAY not functional in PPI modes with 0 frame syncs */ #define ANOMALY_05000180 (1) /* Instruction Cache Is Not Functional */ @@ -130,6 +130,12 @@ #define ANOMALY_05000321 (__SILICON_REVISION__ < 3) /* EMAC RMII mode at 10-Base-T speed: RX frames not received properly */ #define ANOMALY_05000322 (1) +/* Ethernet MAC MDIO Reads Do Not Meet IEEE Specification */ +#define ANOMALY_05000341 (__SILICON_REVISION__ >= 3) +/* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */ +#define ANOMALY_05000357 (1) +/* DMAs that Go Urgent during Tight Core Writes to External Memory Are Blocked */ +#define ANOMALY_05000359 (1) /* Anomalies that don't exist on this proc */ #define ANOMALY_05000125 (0) diff --git a/include/asm-blackfin/mach-bf548/anomaly.h b/include/asm-blackfin/mach-bf548/anomaly.h index c5b63759cdee..850dc12eb7f2 100644 --- a/include/asm-blackfin/mach-bf548/anomaly.h +++ b/include/asm-blackfin/mach-bf548/anomaly.h @@ -7,7 +7,7 @@ */ /* This file shoule be up to date with: - * - Revision C, July 16, 2007; ADSP-BF549 Silicon Anomaly List + * - Revision E, 11/28/2007; ADSP-BF542/BF544/BF547/BF548/BF549 Blackfin Processor Anomaly List */ #ifndef _MACH_ANOMALY_H_ @@ -26,47 +26,59 @@ /* Certain Data Cache Writethrough Modes Fail for Vddint <= 0.9V */ #define ANOMALY_05000272 (1) /* False Hardware Error Exception when ISR context is not restored */ -#define ANOMALY_05000281 (1) +#define ANOMALY_05000281 (__SILICON_REVISION__ < 1) /* SSYNCs After Writes To CAN/DMA MMR Registers Are Not Always Handled Correctly */ -#define ANOMALY_05000304 (1) +#define ANOMALY_05000304 (__SILICON_REVISION__ < 1) /* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */ #define ANOMALY_05000310 (1) /* Errors When SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */ -#define ANOMALY_05000312 (1) +#define ANOMALY_05000312 (__SILICON_REVISION__ < 1) /* TWI Slave Boot Mode Is Not Functional */ -#define ANOMALY_05000324 (1) +#define ANOMALY_05000324 (__SILICON_REVISION__ < 1) /* External FIFO Boot Mode Is Not Functional */ -#define ANOMALY_05000325 (1) +#define ANOMALY_05000325 (__SILICON_REVISION__ < 1) /* Data Lost When Core and DMA Accesses Are Made to the USB FIFO Simultaneously */ -#define ANOMALY_05000327 (1) +#define ANOMALY_05000327 (__SILICON_REVISION__ < 1) /* Incorrect Access of OTP_STATUS During otp_write() Function */ -#define ANOMALY_05000328 (1) +#define ANOMALY_05000328 (__SILICON_REVISION__ < 1) /* Synchronous Burst Flash Boot Mode Is Not Functional */ -#define ANOMALY_05000329 (1) +#define ANOMALY_05000329 (__SILICON_REVISION__ < 1) /* Host DMA Boot Mode Is Not Functional */ -#define ANOMALY_05000330 (1) +#define ANOMALY_05000330 (__SILICON_REVISION__ < 1) /* Inadequate Timing Margins on DDR DQS to DQ and DQM Skew */ -#define ANOMALY_05000334 (1) +#define ANOMALY_05000334 (__SILICON_REVISION__ < 1) /* Inadequate Rotary Debounce Logic Duration */ -#define ANOMALY_05000335 (1) +#define ANOMALY_05000335 (__SILICON_REVISION__ < 1) /* Phantom Interrupt Occurs After First Configuration of Host DMA Port */ -#define ANOMALY_05000336 (1) +#define ANOMALY_05000336 (__SILICON_REVISION__ < 1) /* Disallowed Configuration Prevents Subsequent Allowed Configuration on Host DMA Port */ -#define ANOMALY_05000337 (1) +#define ANOMALY_05000337 (__SILICON_REVISION__ < 1) /* Slave-Mode SPI0 MISO Failure With CPHA = 0 */ -#define ANOMALY_05000338 (1) +#define ANOMALY_05000338 (__SILICON_REVISION__ < 1) /* If Memory Reads Are Enabled on SDH or HOSTDP, Other DMAC1 Peripherals Cannot Read */ -#define ANOMALY_05000340 (1) +#define ANOMALY_05000340 (__SILICON_REVISION__ < 1) /* Boot Host Wait (HWAIT) and Boot Host Wait Alternate (HWAITA) Signals Are Swapped */ -#define ANOMALY_05000344 (1) +#define ANOMALY_05000344 (__SILICON_REVISION__ < 1) /* USB Calibration Value Is Not Intialized */ -#define ANOMALY_05000346 (1) +#define ANOMALY_05000346 (__SILICON_REVISION__ < 1) /* Boot ROM Kernel Incorrectly Alters Reset Value of USB Register */ -#define ANOMALY_05000347 (1) +#define ANOMALY_05000347 (__SILICON_REVISION__ < 1) /* Data Lost when Core Reads SDH Data FIFO */ -#define ANOMALY_05000349 (1) +#define ANOMALY_05000349 (__SILICON_REVISION__ < 1) /* PLL Status Register Is Inaccurate */ -#define ANOMALY_05000351 (1) +#define ANOMALY_05000351 (__SILICON_REVISION__ < 1) +/* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */ +#define ANOMALY_05000357 (1) +/* External Memory Read Access Hangs Core With PLL Bypass */ +#define ANOMALY_05000360 (1) +/* DMAs that Go Urgent during Tight Core Writes to External Memory Are Blocked */ +#define ANOMALY_05000365 (1) +/* Addressing Conflict between Boot ROM and Asynchronous Memory */ +#define ANOMALY_05000369 (1) +/* Mobile DDR Operation Not Functional */ +#define ANOMALY_05000377 (1) +/* Security/Authentication Speedpath Causes Authentication To Fail To Initiate */ +#define ANOMALY_05000378 (1) /* Anomalies that don't exist on this proc */ #define ANOMALY_05000125 (0) diff --git a/include/asm-blackfin/mach-bf561/anomaly.h b/include/asm-blackfin/mach-bf561/anomaly.h index bed956456884..0c1d46193939 100644 --- a/include/asm-blackfin/mach-bf561/anomaly.h +++ b/include/asm-blackfin/mach-bf561/anomaly.h @@ -7,7 +7,7 @@ */ /* This file shoule be up to date with: - * - Revision N, March 28, 2007; ADSP-BF561 Silicon Anomaly List + * - Revision O, 11/15/2007; ADSP-BF561 Blackfin Processor Anomaly List */ #ifndef _MACH_ANOMALY_H_ @@ -15,7 +15,7 @@ /* We do not support 0.1, 0.2, or 0.4 silicon - sorry */ #if __SILICON_REVISION__ < 3 || __SILICON_REVISION__ == 4 -# error Kernel will not work on BF561 silicon version 0.0, 0.1, 0.2, or 0.4 +# error will not work on BF561 silicon version 0.0, 0.1, 0.2, or 0.4 #endif /* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot 2 Not Supported */ @@ -208,6 +208,8 @@ #define ANOMALY_05000275 (__SILICON_REVISION__ > 2) /* Timing Requirements Change for External Frame Sync PPI Modes with Non-Zero PPI_DELAY */ #define ANOMALY_05000276 (__SILICON_REVISION__ < 5) +/* Writes to an I/O data register one SCLK cycle after an edge is detected may clear interrupt */ +#define ANOMALY_05000277 (__SILICON_REVISION__ < 3) /* Disabling Peripherals with DMA Running May Cause DMA System Instability */ #define ANOMALY_05000278 (__SILICON_REVISION__ < 5) /* False Hardware Error Exception When ISR Context Is Not Restored */ @@ -246,6 +248,18 @@ #define ANOMALY_05000332 (__SILICON_REVISION__ < 5) /* Flag Data Register Writes One SCLK Cycle After Edge Is Detected May Clear Interrupt Status */ #define ANOMALY_05000333 (__SILICON_REVISION__ < 5) +/* New Feature: Additional PPI Frame Sync Sampling Options (Not Available on Older Silicon) */ +#define ANOMALY_05000339 (__SILICON_REVISION__ < 5) +/* Memory DMA FIFO Causes Throughput Degradation on Writes to External Memory */ +#define ANOMALY_05000343 (__SILICON_REVISION__ < 5) +/* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */ +#define ANOMALY_05000357 (1) +/* Conflicting Column Address Widths Causes SDRAM Errors */ +#define ANOMALY_05000362 (1) +/* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */ +#define ANOMALY_05000366 (1) +/* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */ +#define ANOMALY_05000371 (1) /* Anomalies that don't exist on this proc */ #define ANOMALY_05000158 (0) -- cgit v1.2.3 From 2047e40d724d42928c0b5994a1568c1b738efdb7 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 22 Jan 2008 15:29:18 +0800 Subject: [Blackfin] arch: set_bfin_dma_config shouldnt set SYNC or RESTART by default - add argument or option Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/kernel/bfin_dma_5xx.c | 4 ++-- drivers/serial/bfin_5xx.c | 6 ++++-- drivers/video/bf54x-lq043fb.c | 3 ++- include/asm-blackfin/dma.h | 6 +++++- 4 files changed, 13 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c index b54446055a43..fa9debe8d5f4 100644 --- a/arch/blackfin/kernel/bfin_dma_5xx.c +++ b/arch/blackfin/kernel/bfin_dma_5xx.c @@ -339,13 +339,13 @@ EXPORT_SYMBOL(set_dma_config); unsigned short set_bfin_dma_config(char direction, char flow_mode, - char intr_mode, char dma_mode, char width) + char intr_mode, char dma_mode, char width, char syncmode) { unsigned short config; config = ((direction << 1) | (width << 2) | (dma_mode << 4) | - (intr_mode << 6) | (flow_mode << 12) | RESTART); + (intr_mode << 6) | (flow_mode << 12) | (syncmode << 5)); return config; } EXPORT_SYMBOL(set_bfin_dma_config); diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index 6f475b609864..ac2a3ef28d55 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c @@ -442,7 +442,8 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart) set_bfin_dma_config(DIR_READ, DMA_FLOW_STOP, INTR_ON_BUF, DIMENSION_LINEAR, - DATA_SIZE_8)); + DATA_SIZE_8, + DMA_SYNC_RESTART)); set_dma_start_addr(uart->tx_dma_channel, (unsigned long)(xmit->buf+xmit->tail)); set_dma_x_count(uart->tx_dma_channel, uart->tx_count); set_dma_x_modify(uart->tx_dma_channel, 1); @@ -689,7 +690,8 @@ static int bfin_serial_startup(struct uart_port *port) set_dma_config(uart->rx_dma_channel, set_bfin_dma_config(DIR_WRITE, DMA_FLOW_AUTO, INTR_ON_ROW, DIMENSION_2D, - DATA_SIZE_8)); + DATA_SIZE_8, + DMA_SYNC_RESTART)); set_dma_x_count(uart->rx_dma_channel, DMA_RX_XCOUNT); set_dma_x_modify(uart->rx_dma_channel, 1); set_dma_y_count(uart->rx_dma_channel, DMA_RX_YCOUNT); diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c index 74d11c318987..1b7e54de0d76 100644 --- a/drivers/video/bf54x-lq043fb.c +++ b/drivers/video/bf54x-lq043fb.c @@ -224,7 +224,8 @@ static int config_dma(struct bfin_bf54xfb_info *fbi) set_dma_config(CH_EPPI0, set_bfin_dma_config(DIR_READ, DMA_FLOW_AUTO, INTR_DISABLE, DIMENSION_2D, - DATA_SIZE_32)); + DATA_SIZE_32, + DMA_NOSYNC_KEEP_DMA_BUF)); set_dma_x_count(CH_EPPI0, (LCD_X_RES * LCD_BPP) / DMA_BUS_SIZE); set_dma_x_modify(CH_EPPI0, DMA_BUS_SIZE / 8); set_dma_y_count(CH_EPPI0, LCD_Y_RES); diff --git a/include/asm-blackfin/dma.h b/include/asm-blackfin/dma.h index b469505af364..5abaa2cee8db 100644 --- a/include/asm-blackfin/dma.h +++ b/include/asm-blackfin/dma.h @@ -76,6 +76,9 @@ enum dma_chan_status { #define INTR_ON_BUF 2 #define INTR_ON_ROW 3 +#define DMA_NOSYNC_KEEP_DMA_BUF 0 +#define DMA_SYNC_RESTART 1 + struct dmasg { unsigned long next_desc_addr; unsigned long start_addr; @@ -157,7 +160,8 @@ void set_dma_y_count(unsigned int channel, unsigned short y_count); void set_dma_y_modify(unsigned int channel, short y_modify); void set_dma_config(unsigned int channel, unsigned short config); unsigned short set_bfin_dma_config(char direction, char flow_mode, - char intr_mode, char dma_mode, char width); + char intr_mode, char dma_mode, char width, + char syncmode); void set_dma_curr_addr(unsigned int channel, unsigned long addr); /* get curr status for polling */ -- cgit v1.2.3 From b97b8a998397e8c64699559099fa9febffae2b4d Mon Sep 17 00:00:00 2001 From: Bernd Schmidt Date: Sun, 27 Jan 2008 18:39:16 +0800 Subject: [Blackfin] arch: Initial checkin of the memory protection support. Enable it with CONFIG_MPU. Signed-off-by: Bernd Schmidt Signed-off-by: Bryan Wu --- arch/blackfin/Kconfig | 9 + arch/blackfin/Makefile | 6 +- arch/blackfin/kernel/cplb-mpu/Makefile | 8 + arch/blackfin/kernel/cplb-mpu/cacheinit.c | 62 ++++++ arch/blackfin/kernel/cplb-mpu/cplbinfo.c | 144 +++++++++++++ arch/blackfin/kernel/cplb-mpu/cplbinit.c | 91 ++++++++ arch/blackfin/kernel/cplb-mpu/cplbmgr.c | 338 ++++++++++++++++++++++++++++++ arch/blackfin/kernel/setup.c | 10 + arch/blackfin/mach-common/entry.S | 19 ++ arch/blackfin/mm/init.c | 4 +- include/asm-blackfin/cplb-mpu.h | 61 ++++++ include/asm-blackfin/cplb.h | 4 + include/asm-blackfin/cplbinit.h | 8 + include/asm-blackfin/mmu.h | 4 +- include/asm-blackfin/mmu_context.h | 62 +++++- 15 files changed, 822 insertions(+), 8 deletions(-) create mode 100644 arch/blackfin/kernel/cplb-mpu/Makefile create mode 100644 arch/blackfin/kernel/cplb-mpu/cacheinit.c create mode 100644 arch/blackfin/kernel/cplb-mpu/cplbinfo.c create mode 100644 arch/blackfin/kernel/cplb-mpu/cplbinit.c create mode 100644 arch/blackfin/kernel/cplb-mpu/cplbmgr.c create mode 100644 include/asm-blackfin/cplb-mpu.h (limited to 'include') diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index ce521a921bee..6b96d7d21aea 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -765,6 +765,15 @@ config L1_MAX_PIECE Set the max memory pieces for the L1 SRAM allocation algorithm. Min value is 16. Max value is 1024. + +config MPU + bool "Enable the memory protection unit (EXPERIMENTAL)" + default n + help + Use the processor's MPU to protect applications from accessing + memory they do not own. This comes at a performance penalty + and is recommended only for debugging. + comment "Asynchonous Memory Configuration" menu "EBIU_AMGCTL Global Control" diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile index 2fc899c5e45f..0edc402fef54 100644 --- a/arch/blackfin/Makefile +++ b/arch/blackfin/Makefile @@ -82,7 +82,11 @@ core-y += arch/$(ARCH)/mach-$(MACHINE)/ core-y += arch/$(ARCH)/mach-$(MACHINE)/boards/ endif -core-y += arch/$(ARCH)/kernel/cplb-nompu/ +ifeq ($(CONFIG_MPU),y) +core-y += arch/$(ARCH)/kernel/cplb-mpu/ +else +core-y += arch/$(ARCH)/kernel/cplb-nompu/ +endif libs-y += arch/$(ARCH)/lib/ diff --git a/arch/blackfin/kernel/cplb-mpu/Makefile b/arch/blackfin/kernel/cplb-mpu/Makefile new file mode 100644 index 000000000000..286b69357f97 --- /dev/null +++ b/arch/blackfin/kernel/cplb-mpu/Makefile @@ -0,0 +1,8 @@ +# +# arch/blackfin/kernel/cplb-nompu/Makefile +# + +obj-y := cplbinit.o cacheinit.o cplbmgr.o + +obj-$(CONFIG_CPLB_INFO) += cplbinfo.o + diff --git a/arch/blackfin/kernel/cplb-mpu/cacheinit.c b/arch/blackfin/kernel/cplb-mpu/cacheinit.c new file mode 100644 index 000000000000..9eecfa403187 --- /dev/null +++ b/arch/blackfin/kernel/cplb-mpu/cacheinit.c @@ -0,0 +1,62 @@ +/* + * Copyright 2004-2007 Analog Devices Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include +#include +#include + +#if defined(CONFIG_BFIN_ICACHE) +void bfin_icache_init(void) +{ + unsigned long ctrl; + int i; + + SSYNC(); + for (i = 0; i < MAX_CPLBS; i++) { + bfin_write32(ICPLB_ADDR0 + i * 4, icplb_tbl[i].addr); + bfin_write32(ICPLB_DATA0 + i * 4, icplb_tbl[i].data); + } + ctrl = bfin_read_IMEM_CONTROL(); + ctrl |= IMC | ENICPLB; + bfin_write_IMEM_CONTROL(ctrl); + SSYNC(); +} +#endif + +#if defined(CONFIG_BFIN_DCACHE) +void bfin_dcache_init(void) +{ + unsigned long ctrl; + int i; + + SSYNC(); + for (i = 0; i < MAX_CPLBS; i++) { + bfin_write32(DCPLB_ADDR0 + i * 4, dcplb_tbl[i].addr); + bfin_write32(DCPLB_DATA0 + i * 4, dcplb_tbl[i].data); + } + + ctrl = bfin_read_DMEM_CONTROL(); + ctrl |= DMEM_CNTR; + bfin_write_DMEM_CONTROL(ctrl); + SSYNC(); +} +#endif diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinfo.c b/arch/blackfin/kernel/cplb-mpu/cplbinfo.c new file mode 100644 index 000000000000..bd072299f7f2 --- /dev/null +++ b/arch/blackfin/kernel/cplb-mpu/cplbinfo.c @@ -0,0 +1,144 @@ +/* + * File: arch/blackfin/mach-common/cplbinfo.c + * Based on: + * Author: Sonic Zhang + * + * Created: Jan. 2005 + * Description: Display CPLB status + * + * Modified: + * Copyright 2004-2006 Analog Devices Inc. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define CPLB_I 1 +#define CPLB_D 2 + +#define SYNC_SYS SSYNC() +#define SYNC_CORE CSYNC() + +#define CPLB_BIT_PAGESIZE 0x30000 + +static char page_size_string_table[][4] = { "1K", "4K", "1M", "4M" }; + +static char *cplb_print_entry(char *buf, struct cplb_entry *tbl, int switched) +{ + int i; + buf += sprintf(buf, "Index\tAddress\t\tData\tSize\tU/RD\tU/WR\tS/WR\tSwitch\n"); + for (i = 0; i < MAX_CPLBS; i++) { + unsigned long data = tbl[i].data; + unsigned long addr = tbl[i].addr; + if (!(data & CPLB_VALID)) + continue; + + buf += + sprintf(buf, + "%d\t0x%08lx\t%06lx\t%s\t%c\t%c\t%c\t%c\n", + i, addr, data, + page_size_string_table[(data & 0x30000) >> 16], + (data & CPLB_USER_RD) ? 'Y' : 'N', + (data & CPLB_USER_WR) ? 'Y' : 'N', + (data & CPLB_SUPV_WR) ? 'Y' : 'N', + i < switched ? 'N' : 'Y'); + } + buf += sprintf(buf, "\n"); + + return buf; +} + +int cplbinfo_proc_output(char *buf) +{ + char *p; + + p = buf; + + p += sprintf(p, "------------------ CPLB Information ------------------\n\n"); + + if (bfin_read_IMEM_CONTROL() & ENICPLB) { + p += sprintf(p, "Instruction CPLB entry:\n"); + p = cplb_print_entry(p, icplb_tbl, first_switched_icplb); + } else + p += sprintf(p, "Instruction CPLB is disabled.\n\n"); + + if (1 || bfin_read_DMEM_CONTROL() & ENDCPLB) { + p += sprintf(p, "Data CPLB entry:\n"); + p = cplb_print_entry(p, dcplb_tbl, first_switched_dcplb); + } else + p += sprintf(p, "Data CPLB is disabled.\n"); + + p += sprintf(p, "ICPLB miss: %d\nICPLB supervisor miss: %d\n", + nr_icplb_miss, nr_icplb_supv_miss); + p += sprintf(p, "DCPLB miss: %d\nDCPLB protection fault:%d\n", + nr_dcplb_miss, nr_dcplb_prot); + p += sprintf(p, "CPLB flushes: %d\n", + nr_cplb_flush); + + return p - buf; +} + +static int cplbinfo_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len; + + len = cplbinfo_proc_output(page); + if (len <= off + count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; +} + +static int __init cplbinfo_init(void) +{ + struct proc_dir_entry *entry; + + entry = create_proc_entry("cplbinfo", 0, NULL); + if (!entry) + return -ENOMEM; + + entry->read_proc = cplbinfo_read_proc; + entry->data = NULL; + + return 0; +} + +static void __exit cplbinfo_exit(void) +{ + remove_proc_entry("cplbinfo", NULL); +} + +module_init(cplbinfo_init); +module_exit(cplbinfo_exit); diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinit.c b/arch/blackfin/kernel/cplb-mpu/cplbinit.c new file mode 100644 index 000000000000..e2e2b5079f5b --- /dev/null +++ b/arch/blackfin/kernel/cplb-mpu/cplbinit.c @@ -0,0 +1,91 @@ +/* + * Blackfin CPLB initialization + * + * Copyright 2004-2007 Analog Devices Inc. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include + +#include +#include +#include + +struct cplb_entry icplb_tbl[MAX_CPLBS]; +struct cplb_entry dcplb_tbl[MAX_CPLBS]; + +int first_switched_icplb, first_switched_dcplb; +int first_mask_dcplb; + +void __init generate_cpl_tables(void) +{ + int i_d, i_i; + unsigned long addr; + unsigned long d_data, i_data; + unsigned long d_cache = 0, i_cache = 0; + +#ifdef CONFIG_BFIN_ICACHE + i_cache = CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND; +#endif + +#ifdef CONFIG_BFIN_DCACHE + d_cache = CPLB_L1_CHBL; +#ifdef CONFIG_BLKFIN_WT + d_cache |= CPLB_L1_AOW | CPLB_WT; +#endif +#endif + i_d = i_i = 0; + + /* Set up the zero page. */ + dcplb_tbl[i_d].addr = 0; + dcplb_tbl[i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB; + +#if 0 + icplb_tbl[i_i].addr = 0; + icplb_tbl[i_i++].data = i_cache | CPLB_USER_RD | PAGE_SIZE_4KB; +#endif + + /* Cover kernel memory with 4M pages. */ + addr = 0; + d_data = d_cache | CPLB_SUPV_WR | CPLB_VALID | PAGE_SIZE_4MB | CPLB_DIRTY; + i_data = i_cache | CPLB_VALID | CPLB_PORTPRIO | PAGE_SIZE_4MB; + + for (; addr < memory_start; addr += 4 * 1024 * 1024) { + dcplb_tbl[i_d].addr = addr; + dcplb_tbl[i_d++].data = d_data; + icplb_tbl[i_i].addr = addr; + icplb_tbl[i_i++].data = i_data | (addr == 0 ? CPLB_USER_RD : 0); + } + + /* Cover L1 memory. One 4M area for code and data each is enough. */ +#if L1_DATA_A_LENGTH > 0 || L1_DATA_B_LENGTH > 0 + dcplb_tbl[i_d].addr = L1_DATA_A_START; + dcplb_tbl[i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB; +#endif + icplb_tbl[i_i].addr = L1_CODE_START; + icplb_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB; + + first_mask_dcplb = i_d; + first_switched_dcplb = i_d + (1 << page_mask_order); + first_switched_icplb = i_i; + + while (i_d < MAX_CPLBS) + dcplb_tbl[i_d++].data = 0; + while (i_i < MAX_CPLBS) + icplb_tbl[i_i++].data = 0; +} diff --git a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c new file mode 100644 index 000000000000..c426a22f9907 --- /dev/null +++ b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c @@ -0,0 +1,338 @@ +/* + * Blackfin CPLB exception handling. + * Copyright 2004-2007 Analog Devices Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include + +#include +#include +#include + +#ifdef CONFIG_BFIN_ICACHE + +#define FAULT_RW (1 << 16) +#define FAULT_USERSUPV (1 << 17) + +int page_mask_nelts; +int page_mask_order; +unsigned long *current_rwx_mask; + +int nr_dcplb_miss, nr_icplb_miss, nr_icplb_supv_miss, nr_dcplb_prot; +int nr_cplb_flush; + +static inline void disable_dcplb(void) +{ + unsigned long ctrl; + SSYNC(); + ctrl = bfin_read_DMEM_CONTROL(); + ctrl &= ~ENDCPLB; + bfin_write_DMEM_CONTROL(ctrl); + SSYNC(); +} + +static inline void enable_dcplb(void) +{ + unsigned long ctrl; + SSYNC(); + ctrl = bfin_read_DMEM_CONTROL(); + ctrl |= ENDCPLB; + bfin_write_DMEM_CONTROL(ctrl); + SSYNC(); +} + +static inline void disable_icplb(void) +{ + unsigned long ctrl; + SSYNC(); + ctrl = bfin_read_IMEM_CONTROL(); + ctrl &= ~ENICPLB; + bfin_write_IMEM_CONTROL(ctrl); + SSYNC(); +} + +static inline void enable_icplb(void) +{ + unsigned long ctrl; + SSYNC(); + ctrl = bfin_read_IMEM_CONTROL(); + ctrl |= ENICPLB; + bfin_write_IMEM_CONTROL(ctrl); + SSYNC(); +} + +/* + * Given the contents of the status register, return the index of the + * CPLB that caused the fault. + */ +static inline int faulting_cplb_index(int status) +{ + int signbits = __builtin_bfin_norm_fr1x32(status & 0xFFFF); + return 30 - signbits; +} + +/* + * Given the contents of the status register and the DCPLB_DATA contents, + * return true if a write access should be permitted. + */ +static inline int write_permitted(int status, unsigned long data) +{ + if (status & FAULT_USERSUPV) + return !!(data & CPLB_SUPV_WR); + else + return !!(data & CPLB_USER_WR); +} + +/* Counters to implement round-robin replacement. */ +static int icplb_rr_index, dcplb_rr_index; + +/* + * Find an ICPLB entry to be evicted and return its index. + */ +static int evict_one_icplb(void) +{ + int i; + for (i = first_switched_icplb; i < MAX_CPLBS; i++) + if ((icplb_tbl[i].data & CPLB_VALID) == 0) + return i; + i = first_switched_icplb + icplb_rr_index; + if (i >= MAX_CPLBS) { + i -= MAX_CPLBS - first_switched_icplb; + icplb_rr_index -= MAX_CPLBS - first_switched_icplb; + } + icplb_rr_index++; + return i; +} + +static int evict_one_dcplb(void) +{ + int i; + for (i = first_switched_dcplb; i < MAX_CPLBS; i++) + if ((dcplb_tbl[i].data & CPLB_VALID) == 0) + return i; + i = first_switched_dcplb + dcplb_rr_index; + if (i >= MAX_CPLBS) { + i -= MAX_CPLBS - first_switched_dcplb; + dcplb_rr_index -= MAX_CPLBS - first_switched_dcplb; + } + dcplb_rr_index++; + return i; +} + +static noinline int dcplb_miss(void) +{ + unsigned long addr = bfin_read_DCPLB_FAULT_ADDR(); + int status = bfin_read_DCPLB_STATUS(); + unsigned long *mask; + int idx; + unsigned long d_data; + + nr_dcplb_miss++; + if (addr >= _ramend) + return CPLB_PROT_VIOL; + + d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB; +#ifdef CONFIG_BFIN_DCACHE + d_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND; +#ifdef CONFIG_BLKFIN_WT + d_data |= CPLB_L1_AOW | CPLB_WT; +#endif +#endif + mask = current_rwx_mask; + if (mask) { + int page = addr >> PAGE_SHIFT; + int offs = page >> 5; + int bit = 1 << (page & 31); + + if (mask[offs] & bit) + d_data |= CPLB_USER_RD; + + mask += page_mask_nelts; + if (mask[offs] & bit) + d_data |= CPLB_USER_WR; + } + + idx = evict_one_dcplb(); + + addr &= PAGE_MASK; + dcplb_tbl[idx].addr = addr; + dcplb_tbl[idx].data = d_data; + + disable_dcplb(); + bfin_write32(DCPLB_DATA0 + idx * 4, d_data); + bfin_write32(DCPLB_ADDR0 + idx * 4, addr); + enable_dcplb(); + + return 0; +} + +static noinline int icplb_miss(void) +{ + unsigned long addr = bfin_read_ICPLB_FAULT_ADDR(); + int status = bfin_read_ICPLB_STATUS(); + int idx; + unsigned long i_data; + + nr_icplb_miss++; + if (status & FAULT_USERSUPV) + nr_icplb_supv_miss++; + + if (addr >= _ramend) + return CPLB_PROT_VIOL; + + /* + * First, try to find a CPLB that matches this address. If we + * find one, then the fact that we're in the miss handler means + * that the instruction crosses a page boundary. + */ + for (idx = first_switched_icplb; idx < MAX_CPLBS; idx++) { + if (icplb_tbl[idx].data & CPLB_VALID) { + unsigned long this_addr = icplb_tbl[idx].addr; + if (this_addr <= addr && this_addr + PAGE_SIZE > addr) { + addr += PAGE_SIZE; + break; + } + } + } + + i_data = CPLB_VALID | CPLB_PORTPRIO | PAGE_SIZE_4KB; +#ifdef CONFIG_BFIN_ICACHE + i_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND; +#endif + + /* + * Two cases to distinguish - a supervisor access must necessarily + * be for a module page; we grant it unconditionally (could do better + * here in the future). Otherwise, check the x bitmap of the current + * process. + */ + if (!(status & FAULT_USERSUPV)) { + unsigned long *mask = current_rwx_mask; + + if (mask) { + int page = addr >> PAGE_SHIFT; + int offs = page >> 5; + int bit = 1 << (page & 31); + + mask += 2 * page_mask_nelts; + if (mask[offs] & bit) + i_data |= CPLB_USER_RD; + } + } + + idx = evict_one_icplb(); + addr &= PAGE_MASK; + icplb_tbl[idx].addr = addr; + icplb_tbl[idx].data = i_data; + + disable_icplb(); + bfin_write32(ICPLB_DATA0 + idx * 4, i_data); + bfin_write32(ICPLB_ADDR0 + idx * 4, addr); + enable_icplb(); + + return 0; +} + +static noinline int dcplb_protection_fault(void) +{ + unsigned long addr = bfin_read_DCPLB_FAULT_ADDR(); + int status = bfin_read_DCPLB_STATUS(); + + nr_dcplb_prot++; + + if (status & FAULT_RW) { + int idx = faulting_cplb_index(status); + unsigned long data = dcplb_tbl[idx].data; + if (!(data & CPLB_WT) && !(data & CPLB_DIRTY) && + write_permitted(status, data)) { + data |= CPLB_DIRTY; + dcplb_tbl[idx].data = data; + bfin_write32(DCPLB_DATA0 + idx * 4, data); + return 0; + } + } + return CPLB_PROT_VIOL; +} + +int cplb_hdr(int seqstat, struct pt_regs *regs) +{ + int cause = seqstat & 0x3f; + switch (cause) { + case 0x23: + return dcplb_protection_fault(); + case 0x2C: + return icplb_miss(); + case 0x26: + return dcplb_miss(); + default: + return 1; + panic_cplb_error(seqstat, regs); + } +} + +void flush_switched_cplbs(void) +{ + int i; + + nr_cplb_flush++; + + disable_icplb(); + for (i = first_switched_icplb; i < MAX_CPLBS; i++) { + icplb_tbl[i].data = 0; + bfin_write32(ICPLB_DATA0 + i * 4, 0); + } + enable_icplb(); + + disable_dcplb(); + for (i = first_mask_dcplb; i < MAX_CPLBS; i++) { + dcplb_tbl[i].data = 0; + bfin_write32(DCPLB_DATA0 + i * 4, 0); + } + enable_dcplb(); +} + +void set_mask_dcplbs(unsigned long *masks) +{ + int i; + unsigned long addr = (unsigned long)masks; + unsigned long d_data; + current_rwx_mask = masks; + + if (!masks) + return; + + d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB; +#ifdef CONFIG_BFIN_DCACHE + d_data |= CPLB_L1_CHBL; +#ifdef CONFIG_BLKFIN_WT + d_data |= CPLB_L1_AOW | CPLB_WT; +#endif +#endif + + disable_dcplb(); + for (i = first_mask_dcplb; i < first_switched_dcplb; i++) { + dcplb_tbl[i].addr = addr; + dcplb_tbl[i].data = d_data; + bfin_write32(DCPLB_DATA0 + i * 4, d_data); + bfin_write32(DCPLB_ADDR0 + i * 4, addr); + addr += PAGE_SIZE; + } + enable_dcplb(); +} + +#endif diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index a03c2dfff4a3..1a942a721d51 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -238,7 +238,12 @@ void __init setup_arch(char **cmdline_p) memory_end = _ramend - DMA_UNCACHED_REGION; _ramstart = (unsigned long)__bss_stop; +#ifdef CONFIG_MPU + /* Round up to multiple of 4MB. */ + memory_start = (_ramstart + 0x3fffff) & ~0x3fffff; +#else memory_start = PAGE_ALIGN(_ramstart); +#endif #if defined(CONFIG_MTD_UCLINUX) /* generic memory mapped MTD driver */ @@ -307,6 +312,11 @@ void __init setup_arch(char **cmdline_p) printk(KERN_NOTICE "Warning: limiting memory to %liMB due to hardware anomaly 05000263\n", memory_end >> 20); #endif /* ANOMALY_05000263 */ +#ifdef CONFIG_MPU + page_mask_nelts = ((_ramend >> PAGE_SHIFT) + 31) / 32; + page_mask_order = get_order(3 * page_mask_nelts * sizeof(long)); +#endif + #if !defined(CONFIG_MTD_UCLINUX) memory_end -= SIZE_4K; /*In case there is no valid CPLB behind memory_end make sure we don't get to close*/ #endif diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 58f7ad617992..c2e81a10c47b 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -95,24 +95,43 @@ ENTRY(_ex_workaround_261) R6 = 0x26; /* Data CPLB Miss */ cc = R6 == R7; if cc jump _ex_dcplb_miss (BP); + R6 = 0x23; /* Data CPLB Miss */ + cc = R6 == R7; + if cc jump _ex_dcplb_viol (BP); /* Handle 0x23 Data CPLB Protection Violation * and Data CPLB Multiple Hits - Linux Trap Zero */ jump _ex_trap_c; ENDPROC(_ex_workaround_261) +#else +#ifdef CONFIG_MPU +#define _ex_dviol _ex_dcplb_viol #else #define _ex_dviol _ex_trap_c +#endif #define _ex_dmiss _ex_dcplb_miss #define _ex_dmult _ex_trap_c #endif + +ENTRY(_ex_dcplb_viol) ENTRY(_ex_dcplb_miss) ENTRY(_ex_icplb_miss) (R7:6,P5:4) = [sp++]; ASTAT = [sp++]; SAVE_ALL_SYS +#ifdef CONFIG_MPU + R0 = SEQSTAT; + R1 = SP; + sp += -12; + call _cplb_hdr; + sp += 12; + CC = R0 == 0; + IF !CC JUMP _handle_bad_cplb; +#else call __cplb_hdr; +#endif DEBUG_START_HWTRACE(p5, r7) RESTORE_ALL_SYS SP = EX_SCRATCH_REG; diff --git a/arch/blackfin/mm/init.c b/arch/blackfin/mm/init.c index e97ea8fc8dc4..9f007cace6e6 100644 --- a/arch/blackfin/mm/init.c +++ b/arch/blackfin/mm/init.c @@ -184,13 +184,15 @@ static __init void free_init_pages(const char *what, unsigned long begin, unsign #ifdef CONFIG_BLK_DEV_INITRD void __init free_initrd_mem(unsigned long start, unsigned long end) { +#ifndef CONFIG_MPU free_init_pages("initrd memory", start, end); +#endif } #endif void __init free_initmem(void) { -#ifdef CONFIG_RAMKERNEL +#if defined CONFIG_RAMKERNEL && !defined CONFIG_MPU free_init_pages("unused kernel memory", (unsigned long)(&__init_begin), (unsigned long)(&__init_end)); diff --git a/include/asm-blackfin/cplb-mpu.h b/include/asm-blackfin/cplb-mpu.h new file mode 100644 index 000000000000..75c67b99d607 --- /dev/null +++ b/include/asm-blackfin/cplb-mpu.h @@ -0,0 +1,61 @@ +/* + * File: include/asm-blackfin/cplbinit.h + * Based on: + * Author: + * + * Created: + * Description: + * + * Modified: + * Copyright 2004-2006 Analog Devices Inc. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef __ASM_BFIN_CPLB_MPU_H +#define __ASM_BFIN_CPLB_MPU_H + +struct cplb_entry { + unsigned long data, addr; +}; + +struct mem_region { + unsigned long start, end; + unsigned long dcplb_data; + unsigned long icplb_data; +}; + +extern struct cplb_entry dcplb_tbl[MAX_CPLBS]; +extern struct cplb_entry icplb_tbl[MAX_CPLBS]; +extern int first_switched_icplb; +extern int first_mask_dcplb; +extern int first_switched_dcplb; + +extern int nr_dcplb_miss, nr_icplb_miss, nr_icplb_supv_miss, nr_dcplb_prot; +extern int nr_cplb_flush; + +extern int page_mask_order; +extern int page_mask_nelts; + +extern unsigned long *current_rwx_mask; + +extern void flush_switched_cplbs(void); +extern void set_mask_dcplbs(unsigned long *); + +extern void __noreturn panic_cplb_error(int seqstat, struct pt_regs *); + +#endif /* __ASM_BFIN_CPLB_MPU_H */ diff --git a/include/asm-blackfin/cplb.h b/include/asm-blackfin/cplb.h index 06828d77a58f..654375c2b746 100644 --- a/include/asm-blackfin/cplb.h +++ b/include/asm-blackfin/cplb.h @@ -65,7 +65,11 @@ #define SIZE_1M 0x00100000 /* 1M */ #define SIZE_4M 0x00400000 /* 4M */ +#ifdef CONFIG_MPU +#define MAX_CPLBS 16 +#else #define MAX_CPLBS (16 * 2) +#endif #define ASYNC_MEMORY_CPLB_COVERAGE ((ASYNC_BANK0_SIZE + ASYNC_BANK1_SIZE + \ ASYNC_BANK2_SIZE + ASYNC_BANK3_SIZE) / SIZE_4M) diff --git a/include/asm-blackfin/cplbinit.h b/include/asm-blackfin/cplbinit.h index c4d0596e8e9f..0eb1c1b685a7 100644 --- a/include/asm-blackfin/cplbinit.h +++ b/include/asm-blackfin/cplbinit.h @@ -33,6 +33,12 @@ #include #include +#ifdef CONFIG_MPU + +#include + +#else + #define INITIAL_T 0x1 #define SWITCH_T 0x2 #define I_CPLB 0x4 @@ -79,6 +85,8 @@ extern u_long ipdt_swapcount_table[]; extern u_long dpdt_swapcount_table[]; #endif +#endif /* CONFIG_MPU */ + extern unsigned long reserved_mem_dcache_on; extern unsigned long reserved_mem_icache_on; diff --git a/include/asm-blackfin/mmu.h b/include/asm-blackfin/mmu.h index 11d52f1167d0..757e43906ed4 100644 --- a/include/asm-blackfin/mmu.h +++ b/include/asm-blackfin/mmu.h @@ -24,7 +24,9 @@ typedef struct { unsigned long exec_fdpic_loadmap; unsigned long interp_fdpic_loadmap; #endif - +#ifdef CONFIG_MPU + unsigned long *page_rwx_mask; +#endif } mm_context_t; #endif diff --git a/include/asm-blackfin/mmu_context.h b/include/asm-blackfin/mmu_context.h index c5c71a6aaf19..b5eb67596ad5 100644 --- a/include/asm-blackfin/mmu_context.h +++ b/include/asm-blackfin/mmu_context.h @@ -30,9 +30,12 @@ #ifndef __BLACKFIN_MMU_CONTEXT_H__ #define __BLACKFIN_MMU_CONTEXT_H__ +#include +#include #include #include #include +#include extern void *current_l1_stack_save; extern int nr_l1stack_tasks; @@ -50,6 +53,12 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) static inline int init_new_context(struct task_struct *tsk, struct mm_struct *mm) { +#ifdef CONFIG_MPU + unsigned long p = __get_free_pages(GFP_KERNEL, page_mask_order); + mm->context.page_rwx_mask = (unsigned long *)p; + memset(mm->context.page_rwx_mask, 0, + page_mask_nelts * 3 * sizeof(long)); +#endif return 0; } @@ -73,6 +82,11 @@ static inline void destroy_context(struct mm_struct *mm) sram_free(tmp->addr); kfree(tmp); } +#ifdef CONFIG_MPU + if (current_rwx_mask == mm->context.page_rwx_mask) + current_rwx_mask = NULL; + free_pages((unsigned long)mm->context.page_rwx_mask, page_mask_order); +#endif } static inline unsigned long @@ -106,9 +120,21 @@ activate_l1stack(struct mm_struct *mm, unsigned long sp_base) #define deactivate_mm(tsk,mm) do { } while (0) -static inline void activate_mm(struct mm_struct *prev_mm, - struct mm_struct *next_mm) +#define activate_mm(prev, next) switch_mm(prev, next, NULL) + +static inline void switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm, + struct task_struct *tsk) { + if (prev_mm == next_mm) + return; +#ifdef CONFIG_MPU + if (prev_mm->context.page_rwx_mask == current_rwx_mask) { + flush_switched_cplbs(); + set_mask_dcplbs(next_mm->context.page_rwx_mask); + } +#endif + + /* L1 stack switching. */ if (!next_mm->context.l1_stack_save) return; if (next_mm->context.l1_stack_save == current_l1_stack_save) @@ -120,10 +146,36 @@ static inline void activate_mm(struct mm_struct *prev_mm, memcpy(l1_stack_base, current_l1_stack_save, l1_stack_len); } -static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, - struct task_struct *tsk) +#ifdef CONFIG_MPU +static inline void protect_page(struct mm_struct *mm, unsigned long addr, + unsigned long flags) +{ + unsigned long *mask = mm->context.page_rwx_mask; + unsigned long page = addr >> 12; + unsigned long idx = page >> 5; + unsigned long bit = 1 << (page & 31); + + if (flags & VM_MAYREAD) + mask[idx] |= bit; + else + mask[idx] &= ~bit; + mask += page_mask_nelts; + if (flags & VM_MAYWRITE) + mask[idx] |= bit; + else + mask[idx] &= ~bit; + mask += page_mask_nelts; + if (flags & VM_MAYEXEC) + mask[idx] |= bit; + else + mask[idx] &= ~bit; +} + +static inline void update_protections(struct mm_struct *mm) { - activate_mm(prev, next); + flush_switched_cplbs(); + set_mask_dcplbs(mm->context.page_rwx_mask); } +#endif #endif -- cgit v1.2.3 From acbcd2631975cf6f0be5cd294cbfd12226cd9958 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 22 Jan 2008 18:36:20 +0800 Subject: [Blackfin] arch: Fix BUG gpio_direction_output API is not compatitable with GENERIC_GPIO API interface signef-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/kernel/bfin_gpio.c | 55 +++++++++++++++++------ arch/blackfin/mach-bf527/boards/ezkit.c | 7 +-- arch/blackfin/mach-bf537/boards/generic_board.c | 6 +-- arch/blackfin/mach-bf537/boards/pnav10.c | 6 +-- arch/blackfin/mach-bf537/boards/stamp.c | 7 +-- drivers/video/bf54x-lq043fb.c | 3 +- include/asm-blackfin/gpio.h | 12 ++--- include/asm-blackfin/mach-bf527/bfin_serial_5xx.h | 2 +- include/asm-blackfin/mach-bf533/bfin_serial_5xx.h | 2 +- include/asm-blackfin/mach-bf537/bfin_serial_5xx.h | 2 +- include/asm-blackfin/mach-bf548/bfin_serial_5xx.h | 2 +- include/asm-blackfin/mach-bf561/bfin_serial_5xx.h | 2 +- 12 files changed, 58 insertions(+), 48 deletions(-) (limited to 'include') diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index ffee36910288..7312011a4211 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -229,6 +229,11 @@ inline int check_gpio(unsigned short gpio) } #endif +void gpio_error(unsigned gpio) +{ + printk(KERN_ERR "bfin-gpio: GPIO %d wasn't requested!\n", gpio); +} + static void set_label(unsigned short ident, const char *label) { @@ -1034,7 +1039,7 @@ EXPORT_SYMBOL(peripheral_free_list); * MODIFICATION HISTORY : **************************************************************/ -int gpio_request(unsigned short gpio, const char *label) +int gpio_request(unsigned gpio, const char *label) { unsigned long flags; @@ -1081,7 +1086,7 @@ int gpio_request(unsigned short gpio, const char *label) } EXPORT_SYMBOL(gpio_request); -void gpio_free(unsigned short gpio) +void gpio_free(unsigned gpio) { unsigned long flags; @@ -1091,7 +1096,7 @@ void gpio_free(unsigned short gpio) local_irq_save(flags); if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) { - printk(KERN_ERR "bfin-gpio: GPIO %d wasn't reserved!\n", gpio); + gpio_error(gpio); dump_stack(); local_irq_restore(flags); return; @@ -1107,34 +1112,47 @@ void gpio_free(unsigned short gpio) } EXPORT_SYMBOL(gpio_free); + #ifdef BF548_FAMILY -void gpio_direction_input(unsigned short gpio) +int gpio_direction_input(unsigned gpio) { unsigned long flags; - BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); + if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { + gpio_error(gpio); + return -EINVAL; + } + local_irq_save(flags); gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio); gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio); local_irq_restore(flags); + + return 0; } EXPORT_SYMBOL(gpio_direction_input); -void gpio_direction_output(unsigned short gpio) +int gpio_direction_output(unsigned gpio, int value) { unsigned long flags; - BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); + if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { + gpio_error(gpio); + return -EINVAL; + } local_irq_save(flags); gpio_array[gpio_bank(gpio)]->port_inen &= ~gpio_bit(gpio); + gpio_set_value(gpio, value); gpio_array[gpio_bank(gpio)]->port_dir_set = gpio_bit(gpio); local_irq_restore(flags); + + return 0; } EXPORT_SYMBOL(gpio_direction_output); -void gpio_set_value(unsigned short gpio, unsigned short arg) +void gpio_set_value(unsigned gpio, int arg) { if (arg) gpio_array[gpio_bank(gpio)]->port_set = gpio_bit(gpio); @@ -1144,7 +1162,7 @@ void gpio_set_value(unsigned short gpio, unsigned short arg) } EXPORT_SYMBOL(gpio_set_value); -unsigned short gpio_get_value(unsigned short gpio) +int gpio_get_value(unsigned gpio) { return (1 & (gpio_array[gpio_bank(gpio)]->port_data >> gpio_sub_n(gpio))); } @@ -1152,31 +1170,42 @@ EXPORT_SYMBOL(gpio_get_value); #else -void gpio_direction_input(unsigned short gpio) +int gpio_direction_input(unsigned gpio) { unsigned long flags; - BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); + if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { + gpio_error(gpio); + return -EINVAL; + } local_irq_save(flags); gpio_bankb[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); gpio_bankb[gpio_bank(gpio)]->inen |= gpio_bit(gpio); AWA_DUMMY_READ(inen); local_irq_restore(flags); + + return 0; } EXPORT_SYMBOL(gpio_direction_input); -void gpio_direction_output(unsigned short gpio) +int gpio_direction_output(unsigned gpio, int value) { unsigned long flags; - BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); + if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { + gpio_error(gpio); + return -EINVAL; + } local_irq_save(flags); gpio_bankb[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); + gpio_set_value(gpio, value); gpio_bankb[gpio_bank(gpio)]->dir |= gpio_bit(gpio); AWA_DUMMY_READ(dir); local_irq_restore(flags); + + return 0; } EXPORT_SYMBOL(gpio_direction_output); diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c index bc256811a5e3..6d70aae4cc9b 100644 --- a/arch/blackfin/mach-bf527/boards/ezkit.c +++ b/arch/blackfin/mach-bf527/boards/ezkit.c @@ -317,12 +317,7 @@ static struct resource sl811_hcd_resources[] = { void sl811_port_power(struct device *dev, int is_on) { gpio_request(CONFIG_USB_SL811_BFIN_GPIO_VBUS, "usb:SL811_VBUS"); - gpio_direction_output(CONFIG_USB_SL811_BFIN_GPIO_VBUS); - - if (is_on) - gpio_set_value(CONFIG_USB_SL811_BFIN_GPIO_VBUS, 1); - else - gpio_set_value(CONFIG_USB_SL811_BFIN_GPIO_VBUS, 0); + gpio_direction_output(CONFIG_USB_SL811_BFIN_GPIO_VBUS, is_on); } #endif diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c index 1c97219a2ab5..3225b1588398 100644 --- a/arch/blackfin/mach-bf537/boards/generic_board.c +++ b/arch/blackfin/mach-bf537/boards/generic_board.c @@ -205,12 +205,8 @@ static struct resource sl811_hcd_resources[] = { void sl811_port_power(struct device *dev, int is_on) { gpio_request(CONFIG_USB_SL811_BFIN_GPIO_VBUS, "usb:SL811_VBUS"); - gpio_direction_output(CONFIG_USB_SL811_BFIN_GPIO_VBUS); + gpio_direction_output(CONFIG_USB_SL811_BFIN_GPIO_VBUS, is_on); - if (is_on) - gpio_set_value(CONFIG_USB_SL811_BFIN_GPIO_VBUS, 1); - else - gpio_set_value(CONFIG_USB_SL811_BFIN_GPIO_VBUS, 0); } #endif diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c index 23e10c7dab5b..4c4870590bd8 100644 --- a/arch/blackfin/mach-bf537/boards/pnav10.c +++ b/arch/blackfin/mach-bf537/boards/pnav10.c @@ -134,12 +134,8 @@ static struct resource sl811_hcd_resources[] = { void sl811_port_power(struct device *dev, int is_on) { gpio_request(CONFIG_USB_SL811_BFIN_GPIO_VBUS, "usb:SL811_VBUS"); - gpio_direction_output(CONFIG_USB_SL811_BFIN_GPIO_VBUS); + gpio_direction_output(CONFIG_USB_SL811_BFIN_GPIO_VBUS, is_on); - if (is_on) - gpio_set_value(CONFIG_USB_SL811_BFIN_GPIO_VBUS, 1); - else - gpio_set_value(CONFIG_USB_SL811_BFIN_GPIO_VBUS, 0); } #endif diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index 3e0ad04d8d75..37759ac7df2a 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -250,12 +250,7 @@ static struct resource sl811_hcd_resources[] = { void sl811_port_power(struct device *dev, int is_on) { gpio_request(CONFIG_USB_SL811_BFIN_GPIO_VBUS, "usb:SL811_VBUS"); - gpio_direction_output(CONFIG_USB_SL811_BFIN_GPIO_VBUS); - - if (is_on) - gpio_set_value(CONFIG_USB_SL811_BFIN_GPIO_VBUS, 1); - else - gpio_set_value(CONFIG_USB_SL811_BFIN_GPIO_VBUS, 0); + gpio_direction_output(CONFIG_USB_SL811_BFIN_GPIO_VBUS, is_on); } #endif diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c index 1b7e54de0d76..c8e7427a0bc8 100644 --- a/drivers/video/bf54x-lq043fb.c +++ b/drivers/video/bf54x-lq043fb.c @@ -264,8 +264,7 @@ static int request_ports(struct bfin_bf54xfb_info *fbi) } } - gpio_direction_output(disp); - gpio_set_value(disp, 1); + gpio_direction_output(disp, 1); return 0; } diff --git a/include/asm-blackfin/gpio.h b/include/asm-blackfin/gpio.h index 33ce98ef7e0f..7bba9b17654e 100644 --- a/include/asm-blackfin/gpio.h +++ b/include/asm-blackfin/gpio.h @@ -426,19 +426,19 @@ struct gpio_port_s { * MODIFICATION HISTORY : **************************************************************/ -int gpio_request(unsigned short, const char *); -void gpio_free(unsigned short); +int gpio_request(unsigned, const char *); +void gpio_free(unsigned); -void gpio_set_value(unsigned short gpio, unsigned short arg); -unsigned short gpio_get_value(unsigned short gpio); +void gpio_set_value(unsigned gpio, int arg); +int gpio_get_value(unsigned gpio); #ifndef BF548_FAMILY #define gpio_get_value(gpio) get_gpio_data(gpio) #define gpio_set_value(gpio, value) set_gpio_data(gpio, value) #endif -void gpio_direction_input(unsigned short gpio); -void gpio_direction_output(unsigned short gpio); +int gpio_direction_input(unsigned gpio); +int gpio_direction_output(unsigned gpio, int value); #include /* cansleep wrappers */ #include diff --git a/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h index 0b867e6a76c4..15dbc21eed8b 100644 --- a/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h +++ b/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h @@ -146,7 +146,7 @@ static void bfin_serial_hw_init(struct bfin_serial_port *uart) if (uart->rts_pin >= 0) { gpio_request(uart->rts_pin, DRIVER_NAME); - gpio_direction_output(uart->rts_pin); + gpio_direction_output(uart->rts_pin, 0); } #endif } diff --git a/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h index 69b9f8e120e9..7871d4313f49 100644 --- a/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h +++ b/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h @@ -111,7 +111,7 @@ static void bfin_serial_hw_init(struct bfin_serial_port *uart) } if (uart->rts_pin >= 0) { gpio_request(uart->rts_pin, DRIVER_NAME); - gpio_direction_input(uart->rts_pin); + gpio_direction_input(uart->rts_pin, 0); } #endif } diff --git a/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h index 6fb328f5186a..86e45c379838 100644 --- a/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h +++ b/include/asm-blackfin/mach-bf537/bfin_serial_5xx.h @@ -146,7 +146,7 @@ static void bfin_serial_hw_init(struct bfin_serial_port *uart) if (uart->rts_pin >= 0) { gpio_request(uart->rts_pin, DRIVER_NAME); - gpio_direction_output(uart->rts_pin); + gpio_direction_output(uart->rts_pin, 0); } #endif } diff --git a/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h index f21a1620e6bd..3770aa38ee9f 100644 --- a/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h +++ b/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h @@ -186,7 +186,7 @@ static void bfin_serial_hw_init(struct bfin_serial_port *uart) if (uart->rts_pin >= 0) { gpio_request(uart->rts_pin, DRIVER_NAME); - gpio_direction_output(uart->rts_pin); + gpio_direction_output(uart->rts_pin, 0); } #endif } diff --git a/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h index 69b9f8e120e9..7871d4313f49 100644 --- a/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h +++ b/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h @@ -111,7 +111,7 @@ static void bfin_serial_hw_init(struct bfin_serial_port *uart) } if (uart->rts_pin >= 0) { gpio_request(uart->rts_pin, DRIVER_NAME); - gpio_direction_input(uart->rts_pin); + gpio_direction_input(uart->rts_pin, 0); } #endif } -- cgit v1.2.3 From a2c8cfef6abb33ee49d80c58391ebfc4f94221ef Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 22 Jan 2008 17:20:10 +0800 Subject: [Blackfin] arch: GPIO API cleanup and anomaly update - Add anomaly workaround for bfin_gpio_reset_spi0_ssel1 - Fix style - Update copyright - Remove BUG_ON checks for functions intended to be used only by arch support. GPIO users should only access using the generic GPIO API - Make all GPIO identifier unsigned int Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/kernel/bfin_gpio.c | 63 ++++++++++++++++------------------- include/asm-blackfin/gpio.h | 72 ++++++++++++++++++++-------------------- 2 files changed, 64 insertions(+), 71 deletions(-) (limited to 'include') diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index 7312011a4211..6bbe0a2fccb8 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -7,7 +7,7 @@ * Description: GPIO Abstraction Layer * * Modified: - * Copyright 2007 Analog Devices Inc. + * Copyright 2008 Analog Devices Inc. * * Bugs: Enter bugs at http://blackfin.uclinux.org/ * @@ -137,7 +137,6 @@ static unsigned short *port_fer[gpio_bank(MAX_BLACKFIN_GPIOS)] = { (unsigned short *) PORTG_FER, (unsigned short *) PORTH_FER, }; - #endif #ifdef BF527_FAMILY @@ -211,7 +210,7 @@ static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG0_INT #endif /* CONFIG_PM */ #if defined(BF548_FAMILY) -inline int check_gpio(unsigned short gpio) +inline int check_gpio(unsigned gpio) { if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15 || gpio == GPIO_PH14 || gpio == GPIO_PH15 @@ -221,7 +220,7 @@ inline int check_gpio(unsigned short gpio) return 0; } #else -inline int check_gpio(unsigned short gpio) +inline int check_gpio(unsigned gpio) { if (gpio >= MAX_BLACKFIN_GPIOS) return -EINVAL; @@ -236,7 +235,6 @@ void gpio_error(unsigned gpio) static void set_label(unsigned short ident, const char *label) { - if (label && str_ident) { strncpy(str_ident[ident].name, label, RESOURCE_LABEL_SIZE); @@ -267,7 +265,7 @@ static int cmp_label(unsigned short ident, const char *label) } #if defined(BF527_FAMILY) || defined(BF537_FAMILY) -static void port_setup(unsigned short gpio, unsigned short usage) +static void port_setup(unsigned gpio, unsigned short usage) { if (!check_gpio(gpio)) { if (usage == GPIO_USAGE) @@ -278,7 +276,7 @@ static void port_setup(unsigned short gpio, unsigned short usage) } } #elif defined(BF548_FAMILY) -static void port_setup(unsigned short gpio, unsigned short usage) +static void port_setup(unsigned gpio, unsigned short usage) { if (usage == GPIO_USAGE) gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio); @@ -399,7 +397,7 @@ inline void portmux_setup(unsigned short portno, unsigned short function) #endif #ifndef BF548_FAMILY -static void default_gpio(unsigned short gpio) +static void default_gpio(unsigned gpio) { unsigned short bank, bitmask; unsigned long flags; @@ -419,7 +417,6 @@ static void default_gpio(unsigned short gpio) gpio_bankb[bank]->edge &= ~bitmask; AWA_DUMMY_READ(edge); local_irq_restore(flags); - } #else # define default_gpio(...) do { } while (0) @@ -457,10 +454,9 @@ arch_initcall(bfin_gpio_init); /* Set a specific bit */ #define SET_GPIO(name) \ -void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ +void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ { \ unsigned long flags; \ - BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); \ local_irq_save(flags); \ if (arg) \ gpio_bankb[gpio_bank(gpio)]->name |= gpio_bit(gpio); \ @@ -480,10 +476,9 @@ SET_GPIO(both) #if ANOMALY_05000311 || ANOMALY_05000323 #define SET_GPIO_SC(name) \ -void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ +void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ { \ unsigned long flags; \ - BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); \ local_irq_save(flags); \ if (arg) \ gpio_bankb[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \ @@ -495,9 +490,8 @@ void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ EXPORT_SYMBOL(set_gpio_ ## name); #else #define SET_GPIO_SC(name) \ -void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \ +void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ { \ - BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); \ if (arg) \ gpio_bankb[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \ else \ @@ -511,19 +505,17 @@ SET_GPIO_SC(maskb) SET_GPIO_SC(data) #if ANOMALY_05000311 || ANOMALY_05000323 -void set_gpio_toggle(unsigned short gpio) +void set_gpio_toggle(unsigned gpio) { unsigned long flags; - BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); local_irq_save(flags); gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio); AWA_DUMMY_READ(toggle); local_irq_restore(flags); } #else -void set_gpio_toggle(unsigned short gpio) +void set_gpio_toggle(unsigned gpio) { - BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))); gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio); } #endif @@ -534,7 +526,7 @@ EXPORT_SYMBOL(set_gpio_toggle); #if ANOMALY_05000311 || ANOMALY_05000323 #define SET_GPIO_P(name) \ -void set_gpiop_ ## name(unsigned short gpio, unsigned short arg) \ +void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \ { \ unsigned long flags; \ local_irq_save(flags); \ @@ -545,7 +537,7 @@ void set_gpiop_ ## name(unsigned short gpio, unsigned short arg) \ EXPORT_SYMBOL(set_gpiop_ ## name); #else #define SET_GPIO_P(name) \ -void set_gpiop_ ## name(unsigned short gpio, unsigned short arg) \ +void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \ { \ gpio_bankb[gpio_bank(gpio)]->name = arg; \ } \ @@ -561,11 +553,10 @@ SET_GPIO_P(both) SET_GPIO_P(maska) SET_GPIO_P(maskb) - /* Get a specific bit */ #if ANOMALY_05000311 || ANOMALY_05000323 #define GET_GPIO(name) \ -unsigned short get_gpio_ ## name(unsigned short gpio) \ +unsigned short get_gpio_ ## name(unsigned gpio) \ { \ unsigned long flags; \ unsigned short ret; \ @@ -578,7 +569,7 @@ unsigned short get_gpio_ ## name(unsigned short gpio) \ EXPORT_SYMBOL(get_gpio_ ## name); #else #define GET_GPIO(name) \ -unsigned short get_gpio_ ## name(unsigned short gpio) \ +unsigned short get_gpio_ ## name(unsigned gpio) \ { \ return (0x01 & (gpio_bankb[gpio_bank(gpio)]->name >> gpio_sub_n(gpio))); \ } \ @@ -598,7 +589,7 @@ GET_GPIO(maskb) #if ANOMALY_05000311 || ANOMALY_05000323 #define GET_GPIO_P(name) \ -unsigned short get_gpiop_ ## name(unsigned short gpio) \ +unsigned short get_gpiop_ ## name(unsigned gpio) \ { \ unsigned long flags; \ unsigned short ret; \ @@ -611,7 +602,7 @@ unsigned short get_gpiop_ ## name(unsigned short gpio) \ EXPORT_SYMBOL(get_gpiop_ ## name); #else #define GET_GPIO_P(name) \ -unsigned short get_gpiop_ ## name(unsigned short gpio) \ +unsigned short get_gpiop_ ## name(unsigned gpio) \ { \ return (gpio_bankb[gpio_bank(gpio)]->name);\ } \ @@ -648,7 +639,7 @@ GET_GPIO_P(maskb) ************************************************************* * MODIFICATION HISTORY : **************************************************************/ -int gpio_pm_wakeup_request(unsigned short gpio, unsigned char type) +int gpio_pm_wakeup_request(unsigned gpio, unsigned char type) { unsigned long flags; @@ -656,7 +647,6 @@ int gpio_pm_wakeup_request(unsigned short gpio, unsigned char type) return -EINVAL; local_irq_save(flags); - wakeup_map[gpio_bank(gpio)] |= gpio_bit(gpio); wakeup_flags_map[gpio] = type; local_irq_restore(flags); @@ -665,7 +655,7 @@ int gpio_pm_wakeup_request(unsigned short gpio, unsigned char type) } EXPORT_SYMBOL(gpio_pm_wakeup_request); -void gpio_pm_wakeup_free(unsigned short gpio) +void gpio_pm_wakeup_free(unsigned gpio) { unsigned long flags; @@ -680,7 +670,7 @@ void gpio_pm_wakeup_free(unsigned short gpio) } EXPORT_SYMBOL(gpio_pm_wakeup_free); -static int bfin_gpio_wakeup_type(unsigned short gpio, unsigned char type) +static int bfin_gpio_wakeup_type(unsigned gpio, unsigned char type) { port_setup(gpio, GPIO_USAGE); set_gpio_dir(gpio, 0); @@ -789,7 +779,7 @@ void gpio_pm_restore(void) #endif #else /* BF548_FAMILY */ -unsigned short get_gpio_dir(unsigned short gpio) +unsigned short get_gpio_dir(unsigned gpio) { return (0x01 & (gpio_array[gpio_bank(gpio)]->port_dir_clear >> gpio_sub_n(gpio))); } @@ -1123,7 +1113,6 @@ int gpio_direction_input(unsigned gpio) return -EINVAL; } - local_irq_save(flags); gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio); gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio); @@ -1158,7 +1147,6 @@ void gpio_set_value(unsigned gpio, int arg) gpio_array[gpio_bank(gpio)]->port_set = gpio_bit(gpio); else gpio_array[gpio_bank(gpio)]->port_clear = gpio_bit(gpio); - } EXPORT_SYMBOL(gpio_set_value); @@ -1200,7 +1188,12 @@ int gpio_direction_output(unsigned gpio, int value) local_irq_save(flags); gpio_bankb[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); - gpio_set_value(gpio, value); + + if (value) + gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio); + else + gpio_bankb[gpio_bank(gpio)]->data_clear = gpio_bit(gpio); + gpio_bankb[gpio_bank(gpio)]->dir |= gpio_bit(gpio); AWA_DUMMY_READ(dir); local_irq_restore(flags); @@ -1225,6 +1218,7 @@ void bfin_gpio_reset_spi0_ssel1(void) port_setup(gpio, GPIO_USAGE); gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio); + AWA_DUMMY_READ(data_set); udelay(1); } @@ -1259,6 +1253,5 @@ static __init int gpio_register_proc(void) proc_gpio->read_proc = gpio_proc_read; return proc_gpio != NULL; } - __initcall(gpio_register_proc); #endif diff --git a/include/asm-blackfin/gpio.h b/include/asm-blackfin/gpio.h index 7bba9b17654e..d0426c108262 100644 --- a/include/asm-blackfin/gpio.h +++ b/include/asm-blackfin/gpio.h @@ -7,7 +7,7 @@ * Description: * * Modified: - * Copyright 2004-2006 Analog Devices Inc. + * Copyright 2004-2008 Analog Devices Inc. * * Bugs: Enter bugs at http://blackfin.uclinux.org/ * @@ -304,39 +304,39 @@ **************************************************************/ #ifndef BF548_FAMILY -void set_gpio_dir(unsigned short, unsigned short); -void set_gpio_inen(unsigned short, unsigned short); -void set_gpio_polar(unsigned short, unsigned short); -void set_gpio_edge(unsigned short, unsigned short); -void set_gpio_both(unsigned short, unsigned short); -void set_gpio_data(unsigned short, unsigned short); -void set_gpio_maska(unsigned short, unsigned short); -void set_gpio_maskb(unsigned short, unsigned short); -void set_gpio_toggle(unsigned short); -void set_gpiop_dir(unsigned short, unsigned short); -void set_gpiop_inen(unsigned short, unsigned short); -void set_gpiop_polar(unsigned short, unsigned short); -void set_gpiop_edge(unsigned short, unsigned short); -void set_gpiop_both(unsigned short, unsigned short); -void set_gpiop_data(unsigned short, unsigned short); -void set_gpiop_maska(unsigned short, unsigned short); -void set_gpiop_maskb(unsigned short, unsigned short); -unsigned short get_gpio_dir(unsigned short); -unsigned short get_gpio_inen(unsigned short); -unsigned short get_gpio_polar(unsigned short); -unsigned short get_gpio_edge(unsigned short); -unsigned short get_gpio_both(unsigned short); -unsigned short get_gpio_maska(unsigned short); -unsigned short get_gpio_maskb(unsigned short); -unsigned short get_gpio_data(unsigned short); -unsigned short get_gpiop_dir(unsigned short); -unsigned short get_gpiop_inen(unsigned short); -unsigned short get_gpiop_polar(unsigned short); -unsigned short get_gpiop_edge(unsigned short); -unsigned short get_gpiop_both(unsigned short); -unsigned short get_gpiop_maska(unsigned short); -unsigned short get_gpiop_maskb(unsigned short); -unsigned short get_gpiop_data(unsigned short); +void set_gpio_dir(unsigned, unsigned short); +void set_gpio_inen(unsigned, unsigned short); +void set_gpio_polar(unsigned, unsigned short); +void set_gpio_edge(unsigned, unsigned short); +void set_gpio_both(unsigned, unsigned short); +void set_gpio_data(unsigned, unsigned short); +void set_gpio_maska(unsigned, unsigned short); +void set_gpio_maskb(unsigned, unsigned short); +void set_gpio_toggle(unsigned); +void set_gpiop_dir(unsigned, unsigned short); +void set_gpiop_inen(unsigned, unsigned short); +void set_gpiop_polar(unsigned, unsigned short); +void set_gpiop_edge(unsigned, unsigned short); +void set_gpiop_both(unsigned, unsigned short); +void set_gpiop_data(unsigned, unsigned short); +void set_gpiop_maska(unsigned, unsigned short); +void set_gpiop_maskb(unsigned, unsigned short); +unsigned short get_gpio_dir(unsigned); +unsigned short get_gpio_inen(unsigned); +unsigned short get_gpio_polar(unsigned); +unsigned short get_gpio_edge(unsigned); +unsigned short get_gpio_both(unsigned); +unsigned short get_gpio_maska(unsigned); +unsigned short get_gpio_maskb(unsigned); +unsigned short get_gpio_data(unsigned); +unsigned short get_gpiop_dir(unsigned); +unsigned short get_gpiop_inen(unsigned); +unsigned short get_gpiop_polar(unsigned); +unsigned short get_gpiop_edge(unsigned); +unsigned short get_gpiop_both(unsigned); +unsigned short get_gpiop_maska(unsigned); +unsigned short get_gpiop_maskb(unsigned); +unsigned short get_gpiop_data(unsigned); struct gpio_port_t { unsigned short data; @@ -382,8 +382,8 @@ struct gpio_port_t { #define PM_WAKE_LOW 0x8 #define PM_WAKE_BOTH_EDGES (PM_WAKE_RISING | PM_WAKE_FALLING) -int gpio_pm_wakeup_request(unsigned short gpio, unsigned char type); -void gpio_pm_wakeup_free(unsigned short gpio); +int gpio_pm_wakeup_request(unsigned gpio, unsigned char type); +void gpio_pm_wakeup_free(unsigned gpio); unsigned int gpio_pm_setup(void); void gpio_pm_restore(void); -- cgit v1.2.3 From fc97551db9e4e9402ff2b5c94be8267b2e5f32f4 Mon Sep 17 00:00:00 2001 From: Bernd Schmidt Date: Sun, 27 Jan 2008 19:56:43 +0800 Subject: [Blackfin] arch: Add the semtimedop syscall. Upstream uClibc doesn't compile without it. Signed-off-by: Bernd Schmidt Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/entry.S | 1 + include/asm-blackfin/unistd.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index c2e81a10c47b..56ff51bc8c21 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -1381,6 +1381,7 @@ ENTRY(_sys_call_table) .long _sys_set_robust_list .long _sys_get_robust_list /* 355 */ .long _sys_fallocate + .long _sys_semtimedop .rept NR_syscalls-(.-_sys_call_table)/4 .long _sys_ni_syscall .endr diff --git a/include/asm-blackfin/unistd.h b/include/asm-blackfin/unistd.h index 07ffe8b718c5..e98167358d26 100644 --- a/include/asm-blackfin/unistd.h +++ b/include/asm-blackfin/unistd.h @@ -369,8 +369,9 @@ #define __NR_set_robust_list 354 #define __NR_get_robust_list 355 #define __NR_fallocate 356 +#define __NR_semtimedop 357 -#define __NR_syscall 357 +#define __NR_syscall 358 #define NR_syscalls __NR_syscall /* Old optional stuff no one actually uses */ -- cgit v1.2.3 From 408dbc0da29913f99e56001db892eb653b47c13b Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Sun, 27 Jan 2008 18:38:12 +0800 Subject: [Blackfin] arch: remove old I2C BF54x porting. Signed-off-by: Bryan Wu --- include/asm-blackfin/mach-bf548/cdefBF54x_base.h | 33 ------------------------ 1 file changed, 33 deletions(-) (limited to 'include') diff --git a/include/asm-blackfin/mach-bf548/cdefBF54x_base.h b/include/asm-blackfin/mach-bf548/cdefBF54x_base.h index aefab3f618c1..19ddcd83c71f 100644 --- a/include/asm-blackfin/mach-bf548/cdefBF54x_base.h +++ b/include/asm-blackfin/mach-bf548/cdefBF54x_base.h @@ -244,39 +244,6 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val) #define bfin_read_TWI0_RCV_DATA16() bfin_read16(TWI0_RCV_DATA16) #define bfin_write_TWI0_RCV_DATA16(val) bfin_write16(TWI0_RCV_DATA16, val) -#define bfin_read_TWI_CLKDIV() bfin_read16(TWI0_CLKDIV) -#define bfin_write_TWI_CLKDIV(val) bfin_write16(TWI0_CLKDIV, val) -#define bfin_read_TWI_CONTROL() bfin_read16(TWI0_CONTROL) -#define bfin_write_TWI_CONTROL(val) bfin_write16(TWI0_CONTROL, val) -#define bfin_read_TWI_SLAVE_CTRL() bfin_read16(TWI0_SLAVE_CTRL) -#define bfin_write_TWI_SLAVE_CTRL(val) bfin_write16(TWI0_SLAVE_CTRL, val) -#define bfin_read_TWI_SLAVE_STAT() bfin_read16(TWI0_SLAVE_STAT) -#define bfin_write_TWI_SLAVE_STAT(val) bfin_write16(TWI0_SLAVE_STAT, val) -#define bfin_read_TWI_SLAVE_ADDR() bfin_read16(TWI0_SLAVE_ADDR) -#define bfin_write_TWI_SLAVE_ADDR(val) bfin_write16(TWI0_SLAVE_ADDR, val) -#define bfin_read_TWI_MASTER_CTL() bfin_read16(TWI0_MASTER_CTRL) -#define bfin_write_TWI_MASTER_CTL(val) bfin_write16(TWI0_MASTER_CTRL, val) -#define bfin_read_TWI_MASTER_STAT() bfin_read16(TWI0_MASTER_STAT) -#define bfin_write_TWI_MASTER_STAT(val) bfin_write16(TWI0_MASTER_STAT, val) -#define bfin_read_TWI_MASTER_ADDR() bfin_read16(TWI0_MASTER_ADDR) -#define bfin_write_TWI_MASTER_ADDR(val) bfin_write16(TWI0_MASTER_ADDR, val) -#define bfin_read_TWI_INT_STAT() bfin_read16(TWI0_INT_STAT) -#define bfin_write_TWI_INT_STAT(val) bfin_write16(TWI0_INT_STAT, val) -#define bfin_read_TWI_INT_MASK() bfin_read16(TWI0_INT_MASK) -#define bfin_write_TWI_INT_MASK(val) bfin_write16(TWI0_INT_MASK, val) -#define bfin_read_TWI_FIFO_CTL() bfin_read16(TWI0_FIFO_CTRL) -#define bfin_write_TWI_FIFO_CTL(val) bfin_write16(TWI0_FIFO_CTRL, val) -#define bfin_read_TWI_FIFO_STAT() bfin_read16(TWI0_FIFO_STAT) -#define bfin_write_TWI_FIFO_STAT(val) bfin_write16(TWI0_FIFO_STAT, val) -#define bfin_read_TWI_XMT_DATA8() bfin_read16(TWI0_XMT_DATA8) -#define bfin_write_TWI_XMT_DATA8(val) bfin_write16(TWI0_XMT_DATA8, val) -#define bfin_read_TWI_XMT_DATA16() bfin_read16(TWI0_XMT_DATA16) -#define bfin_write_TWI_XMT_DATA16(val) bfin_write16(TWI0_XMT_DATA16, val) -#define bfin_read_TWI_RCV_DATA8() bfin_read16(TWI0_RCV_DATA8) -#define bfin_write_TWI_RCV_DATA8(val) bfin_write16(TWI0_RCV_DATA8, val) -#define bfin_read_TWI_RCV_DATA16() bfin_read16(TWI0_RCV_DATA16) -#define bfin_write_TWI_RCV_DATA16(val) bfin_write16(TWI0_RCV_DATA16, val) - /* SPORT0 is not defined in the shared file because it is not available on the ADSP-BF542 and ADSP-BF544 bfin_read_()rocessors */ /* SPORT1 Registers */ -- cgit v1.2.3