diff options
author | Bernd Schmidt <bernds_cb1@t-online.de> | 2009-01-07 23:14:38 +0800 |
---|---|---|
committer | Bryan Wu <cooloney@kernel.org> | 2009-01-07 23:14:38 +0800 |
commit | dbdf20db537a5369c65330f878ad4905020a8bfa (patch) | |
tree | c7fa553755e2d75a6e98d3f32fbe41fab9f72609 /arch/blackfin | |
parent | 6651ece9e257302ee695ee76e69a4427f7033235 (diff) |
Blackfin arch: Faster C implementation of no-MPU CPLB handler
This is a mixture ofcMichael McTernan's patch and the existing cplb-mpu code.
We ditch the old cplb-nompu implementation, which is a good example of
why a good algorithm in a HLL is preferrable to a bad algorithm written in
assembly. Rather than try to construct a table of all posible CPLBs and
search it, we just create a (smaller) table of memory regions and
their attributes. Some of the data structures are now unified for both
the mpu and nompu cases. A lot of needless complexity in cplbinit.c is
removed.
Further optimizations:
* compile cplbmgr.c with a lot of -ffixed-reg options, and omit saving
these registers on the stack when entering a CPLB exception.
* lose cli/nop/nop/sti sequences for some workarounds - these don't
* make
sense in an exception context
Additional code unification should be possible after this.
[Mike Frysinger <vapier.adi@gmail.com>:
- convert CPP if statements to C if statements
- remove redundant statements
- use a do...while loop rather than a for loop to get slightly better
optimization and to avoid gcc "may be used uninitialized" warnings ...
we know that the [id]cplb_nr_bounds variables will never be 0, so this
is OK
- the no-mpu code was the last user of MAX_MEM_SIZE and with that rewritten,
we can punt it
- add some BUG_ON() checks to make sure we dont overflow the small
cplb_bounds array
- add i/d cplb entries for the bootrom because there is functions/data in
there we want to access
- we do not need a NULL trailing entry as any time we access the bounds
arrays, we use the nr_bounds variable
]
Signed-off-by: Michael McTernan <mmcternan@airvana.com>
Signed-off-by: Mike Frysinger <vapier.adi@gmail.com>
Signed-off-by: Bernd Schmidt <bernds_cb1@t-online.de>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
Diffstat (limited to 'arch/blackfin')
-rw-r--r-- | arch/blackfin/Kconfig | 8 | ||||
-rw-r--r-- | arch/blackfin/include/asm/context.S | 39 | ||||
-rw-r--r-- | arch/blackfin/include/asm/cplb-mpu.h | 62 | ||||
-rw-r--r-- | arch/blackfin/include/asm/cplb.h | 4 | ||||
-rw-r--r-- | arch/blackfin/include/asm/cplbinit.h | 108 | ||||
-rw-r--r-- | arch/blackfin/include/asm/entry.h | 2 | ||||
-rw-r--r-- | arch/blackfin/kernel/cplb-mpu/Makefile | 5 | ||||
-rw-r--r-- | arch/blackfin/kernel/cplb-mpu/cplbinit.c | 4 | ||||
-rw-r--r-- | arch/blackfin/kernel/cplb-mpu/cplbmgr.c | 9 | ||||
-rw-r--r-- | arch/blackfin/kernel/cplb-nompu/Makefile | 7 | ||||
-rw-r--r-- | arch/blackfin/kernel/cplb-nompu/cacheinit.c | 26 | ||||
-rw-r--r-- | arch/blackfin/kernel/cplb-nompu/cplbhdlr.S | 130 | ||||
-rw-r--r-- | arch/blackfin/kernel/cplb-nompu/cplbinit.c | 498 | ||||
-rw-r--r-- | arch/blackfin/kernel/cplb-nompu/cplbmgr.S | 648 | ||||
-rw-r--r-- | arch/blackfin/kernel/cplb-nompu/cplbmgr.c | 283 | ||||
-rw-r--r-- | arch/blackfin/kernel/cplbinfo.c | 84 | ||||
-rw-r--r-- | arch/blackfin/kernel/setup.c | 9 | ||||
-rw-r--r-- | arch/blackfin/mach-common/entry.S | 21 | ||||
-rw-r--r-- | arch/blackfin/mm/init.c | 10 |
19 files changed, 515 insertions, 1442 deletions
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index b58af2b1bff..bbfeecae640 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -524,14 +524,6 @@ config MEM_SDGCTL default 0x0 endmenu -config MAX_MEM_SIZE - int "Max SDRAM Memory Size in MBytes" - depends on !MPU - default 512 - help - This is the max memory size that the kernel will create CPLB - tables for. Your system will not be able to handle any more. - # # Max & Min Speeds for various Chips # diff --git a/arch/blackfin/include/asm/context.S b/arch/blackfin/include/asm/context.S index 9ce21f68e91..16561ab18b3 100644 --- a/arch/blackfin/include/asm/context.S +++ b/arch/blackfin/include/asm/context.S @@ -357,3 +357,42 @@ SYSCFG = [sp++]; csync; .endm + +.macro save_context_cplb + [--sp] = (R7:0, P5:0); + [--sp] = fp; + + [--sp] = a0.x; + [--sp] = a0.w; + [--sp] = a1.x; + [--sp] = a1.w; + + [--sp] = LC0; + [--sp] = LC1; + [--sp] = LT0; + [--sp] = LT1; + [--sp] = LB0; + [--sp] = LB1; + + [--sp] = RETS; +.endm + +.macro restore_context_cplb + RETS = [sp++]; + + LB1 = [sp++]; + LB0 = [sp++]; + LT1 = [sp++]; + LT0 = [sp++]; + LC1 = [sp++]; + LC0 = [sp++]; + + a1.w = [sp++]; + a1.x = [sp++]; + a0.w = [sp++]; + a0.x = [sp++]; + + fp = [sp++]; + + (R7:0, P5:0) = [SP++]; +.endm diff --git a/arch/blackfin/include/asm/cplb-mpu.h b/arch/blackfin/include/asm/cplb-mpu.h deleted file mode 100644 index 80680ad7a37..00000000000 --- a/arch/blackfin/include/asm/cplb-mpu.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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 -#include <linux/threads.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[NR_CPUS][MAX_CPLBS]; -extern struct cplb_entry icplb_tbl[NR_CPUS][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[]; -extern int nr_dcplb_prot[], nr_cplb_flush[]; - -extern int page_mask_order; -extern int page_mask_nelts; - -extern unsigned long *current_rwx_mask[NR_CPUS]; - -extern void flush_switched_cplbs(unsigned int); -extern void set_mask_dcplbs(unsigned long *, unsigned int); - -extern void __noreturn panic_cplb_error(int seqstat, struct pt_regs *); - -#endif /* __ASM_BFIN_CPLB_MPU_H */ diff --git a/arch/blackfin/include/asm/cplb.h b/arch/blackfin/include/asm/cplb.h index 5f7545d0620..ad566ff9ad1 100644 --- a/arch/blackfin/include/asm/cplb.h +++ b/arch/blackfin/include/asm/cplb.h @@ -116,4 +116,8 @@ #define CPLB_INOCACHE CPLB_USER_RD | CPLB_VALID #define CPLB_IDOCACHE CPLB_INOCACHE | CPLB_L1_CHBL +#define FAULT_RW (1 << 16) +#define FAULT_USERSUPV (1 << 17) +#define FAULT_CPLBBITS 0x0000ffff + #endif /* _CPLB_H */ diff --git a/arch/blackfin/include/asm/cplbinit.h b/arch/blackfin/include/asm/cplbinit.h index 2aeec87d24e..05b14a631d0 100644 --- a/arch/blackfin/include/asm/cplbinit.h +++ b/arch/blackfin/include/asm/cplbinit.h @@ -32,96 +32,56 @@ #include <asm/blackfin.h> #include <asm/cplb.h> +#include <linux/threads.h> -#ifdef CONFIG_MPU - -#include <asm/cplb-mpu.h> -extern void bfin_icache_init(struct cplb_entry *icplb_tbl); -extern void bfin_dcache_init(struct cplb_entry *icplb_tbl); - +#ifdef CONFIG_CPLB_SWITCH_TAB_L1 +# define PDT_ATTR __attribute__((l1_data)) #else +# define PDT_ATTR +#endif -#define INITIAL_T 0x1 -#define SWITCH_T 0x2 -#define I_CPLB 0x4 -#define D_CPLB 0x8 +struct cplb_entry { + unsigned long data, addr; +}; -#define ASYNC_MEMORY_CPLB_COVERAGE ((ASYNC_BANK0_SIZE + ASYNC_BANK1_SIZE + \ - ASYNC_BANK2_SIZE + ASYNC_BANK3_SIZE) / SIZE_4M) +struct cplb_boundary { + unsigned long eaddr; /* End of this region. */ + unsigned long data; /* CPLB data value. */ +}; -#define CPLB_MEM CONFIG_MAX_MEM_SIZE +extern struct cplb_boundary dcplb_bounds[]; +extern struct cplb_boundary icplb_bounds[]; +extern int dcplb_nr_bounds, icplb_nr_bounds; -/* -* Number of required data CPLB switchtable entries -* MEMSIZE / 4 (we mostly install 4M page size CPLBs -* approx 16 for smaller 1MB page size CPLBs for allignment purposes -* 1 for L1 Data Memory -* possibly 1 for L2 Data Memory -* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO -* 1 for ASYNC Memory -*/ -#define MAX_SWITCH_D_CPLBS (((CPLB_MEM / 4) + 16 + 1 + 1 + 1 \ - + ASYNC_MEMORY_CPLB_COVERAGE) * 2) +extern struct cplb_entry dcplb_tbl[NR_CPUS][MAX_CPLBS]; +extern struct cplb_entry icplb_tbl[NR_CPUS][MAX_CPLBS]; +extern int first_switched_icplb; +extern int first_switched_dcplb; -/* -* Number of required instruction CPLB switchtable entries -* MEMSIZE / 4 (we mostly install 4M page size CPLBs -* approx 12 for smaller 1MB page size CPLBs for allignment purposes -* 1 for L1 Instruction Memory -* possibly 1 for L2 Instruction Memory -* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO -*/ -#define MAX_SWITCH_I_CPLBS (((CPLB_MEM / 4) + 12 + 1 + 1 + 1) * 2) - -/* Number of CPLB table entries, used for cplb-nompu. */ -#define CPLB_TBL_ENTRIES (16 * 4) - -enum { - ZERO_P, L1I_MEM, L1D_MEM, L2_MEM, SDRAM_KERN, SDRAM_RAM_MTD, SDRAM_DMAZ, - RES_MEM, ASYNC_MEM, OCB_ROM -}; +extern int nr_dcplb_miss[], nr_icplb_miss[], nr_icplb_supv_miss[]; +extern int nr_dcplb_prot[], nr_cplb_flush[]; -struct cplb_desc { - u32 start; /* start address */ - u32 end; /* end address */ - u32 psize; /* prefered size if any otherwise 1MB or 4MB*/ - u16 attr;/* attributes */ - u16 i_conf;/* I-CPLB DATA */ - u16 d_conf;/* D-CPLB DATA */ - u16 valid;/* valid */ - const s8 name[30];/* name */ -}; +#ifdef CONFIG_MPU -struct cplb_tab { - u_long *tab; - u16 pos; - u16 size; -}; +extern int first_mask_dcplb; -extern u_long icplb_tables[NR_CPUS][CPLB_TBL_ENTRIES+1]; -extern u_long dcplb_tables[NR_CPUS][CPLB_TBL_ENTRIES+1]; +extern int page_mask_order; +extern int page_mask_nelts; -/* Till here we are discussing about the static memory management model. - * However, the operating envoronments commonly define more CPLB - * descriptors to cover the entire addressable memory than will fit into - * the available on-chip 16 CPLB MMRs. When this happens, the below table - * will be used which will hold all the potentially required CPLB descriptors - * - * This is how Page descriptor Table is implemented in uClinux/Blackfin. - */ +extern unsigned long *current_rwx_mask[NR_CPUS]; -extern u_long ipdt_tables[NR_CPUS][MAX_SWITCH_I_CPLBS+1]; -extern u_long dpdt_tables[NR_CPUS][MAX_SWITCH_D_CPLBS+1]; -#ifdef CONFIG_CPLB_INFO -extern u_long ipdt_swapcount_tables[NR_CPUS][MAX_SWITCH_I_CPLBS]; -extern u_long dpdt_swapcount_tables[NR_CPUS][MAX_SWITCH_D_CPLBS]; -#endif -extern void bfin_icache_init(u_long icplbs[]); -extern void bfin_dcache_init(u_long dcplbs[]); +extern void flush_switched_cplbs(unsigned int); +extern void set_mask_dcplbs(unsigned long *, unsigned int); + +extern void __noreturn panic_cplb_error(int seqstat, struct pt_regs *); #endif /* CONFIG_MPU */ +extern void bfin_icache_init(struct cplb_entry *icplb_tbl); +extern void bfin_dcache_init(struct cplb_entry *icplb_tbl); + #if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE) +extern void generate_cplb_tables_all(void); extern void generate_cplb_tables_cpu(unsigned int cpu); #endif #endif diff --git a/arch/blackfin/include/asm/entry.h b/arch/blackfin/include/asm/entry.h index c4f721e0d00..d94e4f5139d 100644 --- a/arch/blackfin/include/asm/entry.h +++ b/arch/blackfin/include/asm/entry.h @@ -53,9 +53,11 @@ /* This one pushes RETI without using CLI. Interrupts are enabled. */ #define SAVE_CONTEXT_SYSCALL save_context_syscall #define SAVE_CONTEXT save_context_with_interrupts +#define SAVE_CONTEXT_CPLB save_context_cplb #define RESTORE_ALL_SYS restore_context_no_interrupts #define RESTORE_CONTEXT restore_context_with_interrupts +#define RESTORE_CONTEXT_CPLB restore_context_cplb #endif /* __ASSEMBLY__ */ #endif /* __BFIN_ENTRY_H */ diff --git a/arch/blackfin/kernel/cplb-mpu/Makefile b/arch/blackfin/kernel/cplb-mpu/Makefile index bd92301a704..7d70d3bf321 100644 --- a/arch/blackfin/kernel/cplb-mpu/Makefile +++ b/arch/blackfin/kernel/cplb-mpu/Makefile @@ -3,3 +3,8 @@ # obj-y := cplbinit.o cacheinit.o cplbmgr.o + +CFLAGS_cplbmgr.o := -ffixed-I0 -ffixed-I1 -ffixed-I2 -ffixed-I3 \ + -ffixed-L0 -ffixed-L1 -ffixed-L2 -ffixed-L3 \ + -ffixed-M0 -ffixed-M1 -ffixed-M2 -ffixed-M3 \ + -ffixed-B0 -ffixed-B1 -ffixed-B2 -ffixed-B3 diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinit.c b/arch/blackfin/kernel/cplb-mpu/cplbinit.c index 1ea7c18435a..bdb958486e7 100644 --- a/arch/blackfin/kernel/cplb-mpu/cplbinit.c +++ b/arch/blackfin/kernel/cplb-mpu/cplbinit.c @@ -107,3 +107,7 @@ void __init generate_cplb_tables_cpu(unsigned int cpu) while (i_i < MAX_CPLBS) icplb_tbl[cpu][i_i++].data = 0; } + +void generate_cplb_tables_all(void) +{ +} diff --git a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c index 76bd99177de..5ef5d1a787f 100644 --- a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c +++ b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c @@ -25,8 +25,13 @@ #include <asm/cplbinit.h> #include <asm/mmu_context.h> -#define FAULT_RW (1 << 16) -#define FAULT_USERSUPV (1 << 17) +/* + * WARNING + * + * This file is compiled with certain -ffixed-reg options. We have to + * make sure not to call any functions here that could clobber these + * registers. + */ int page_mask_nelts; int page_mask_order; diff --git a/arch/blackfin/kernel/cplb-nompu/Makefile b/arch/blackfin/kernel/cplb-nompu/Makefile index 4010eca1c6c..7d70d3bf321 100644 --- a/arch/blackfin/kernel/cplb-nompu/Makefile +++ b/arch/blackfin/kernel/cplb-nompu/Makefile @@ -2,4 +2,9 @@ # arch/blackfin/kernel/cplb-nompu/Makefile # -obj-y := cplbinit.o cacheinit.o cplbhdlr.o cplbmgr.o +obj-y := cplbinit.o cacheinit.o cplbmgr.o + +CFLAGS_cplbmgr.o := -ffixed-I0 -ffixed-I1 -ffixed-I2 -ffixed-I3 \ + -ffixed-L0 -ffixed-L1 -ffixed-L2 -ffixed-L3 \ + -ffixed-M0 -ffixed-M1 -ffixed-M2 -ffixed-M3 \ + -ffixed-B0 -ffixed-B1 -ffixed-B2 -ffixed-B3 diff --git a/arch/blackfin/kernel/cplb-nompu/cacheinit.c b/arch/blackfin/kernel/cplb-nompu/cacheinit.c index 3a385aec67d..c6ff947f9d3 100644 --- a/arch/blackfin/kernel/cplb-nompu/cacheinit.c +++ b/arch/blackfin/kernel/cplb-nompu/cacheinit.c @@ -25,19 +25,15 @@ #include <asm/cplbinit.h> #if defined(CONFIG_BFIN_ICACHE) -void __cpuinit bfin_icache_init(u_long icplb[]) +void __cpuinit bfin_icache_init(struct cplb_entry *icplb_tbl) { - unsigned long *table = icplb; unsigned long ctrl; int i; + SSYNC(); for (i = 0; i < MAX_CPLBS; i++) { - unsigned long addr = *table++; - unsigned long data = *table++; - if (addr == (unsigned long)-1) - break; - bfin_write32(ICPLB_ADDR0 + i * 4, addr); - bfin_write32(ICPLB_DATA0 + i * 4, data); + 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; @@ -47,24 +43,20 @@ void __cpuinit bfin_icache_init(u_long icplb[]) #endif #if defined(CONFIG_BFIN_DCACHE) -void __cpuinit bfin_dcache_init(u_long dcplb[]) +void __cpuinit bfin_dcache_init(struct cplb_entry *dcplb_tbl) { - unsigned long *table = dcplb; unsigned long ctrl; int i; + SSYNC(); for (i = 0; i < MAX_CPLBS; i++) { - unsigned long addr = *table++; - unsigned long data = *table++; - if (addr == (unsigned long)-1) - break; - bfin_write32(DCPLB_ADDR0 + i * 4, addr); - bfin_write32(DCPLB_DATA0 + i * 4, data); + 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-nompu/cplbhdlr.S b/arch/blackfin/kernel/cplb-nompu/cplbhdlr.S deleted file mode 100644 index ecbabc0a1fe..00000000000 --- a/arch/blackfin/kernel/cplb-nompu/cplbhdlr.S +++ /dev/null @@ -1,130 +0,0 @@ -/* - * File: arch/blackfin/mach-common/cplbhdlr.S - * Based on: - * Author: LG Soft India - * - * Created: ? - * Description: CPLB exception handler - * - * 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 <linux/linkage.h> -#include <asm/cplb.h> -#include <asm/entry.h> - -#ifdef CONFIG_EXCPT_IRQ_SYSC_L1 -.section .l1.text -#else -.text -#endif - -.type _cplb_mgr, STT_FUNC; -.type _panic_cplb_error, STT_FUNC; - -.align 2 - -ENTRY(__cplb_hdr) - R2 = SEQSTAT; - - /* Mask the contents of SEQSTAT and leave only EXCAUSE in R2 */ - R2 <<= 26; - R2 >>= 26; - - R1 = 0x23; /* Data access CPLB protection violation */ - CC = R2 == R1; - IF !CC JUMP .Lnot_data_write; - R0 = 2; /* is a write to data space*/ - JUMP .Lis_icplb_miss; - -.Lnot_data_write: - R1 = 0x2C; /* CPLB miss on an instruction fetch */ - CC = R2 == R1; - R0 = 0; /* is_data_miss == False*/ - IF CC JUMP .Lis_icplb_miss; - - R1 = 0x26; - CC = R2 == R1; - IF !CC JUMP .Lunknown; - - R0 = 1; /* is_data_miss == True*/ - -.Lis_icplb_miss: - -#if defined(CONFIG_BFIN_ICACHE) || defined(CONFIG_BFIN_DCACHE) -# if defined(CONFIG_BFIN_ICACHE) && !defined(CONFIG_BFIN_DCACHE) - R1 = CPLB_ENABLE_ICACHE; -# endif -# if !defined(CONFIG_BFIN_ICACHE) && defined(CONFIG_BFIN_DCACHE) - R1 = CPLB_ENABLE_DCACHE; -# endif -# if defined(CONFIG_BFIN_ICACHE) && defined(CONFIG_BFIN_DCACHE) - R1 = CPLB_ENABLE_DCACHE | CPLB_ENABLE_ICACHE; -# endif -#else - R1 = 0; -#endif - - [--SP] = RETS; - CALL _cplb_mgr; - RETS = [SP++]; - CC = R0 == 0; - IF !CC JUMP .Lnot_replaced; - RTS; - -/* - * Diagnostic exception handlers - */ -.Lunknown: - R0 = CPLB_UNKNOWN_ERR; - JUMP .Lcplb_error; - -.Lnot_replaced: - CC = R0 == CPLB_NO_UNLOCKED; - IF !CC JUMP .Lnext_check; - R0 = CPLB_NO_UNLOCKED; - JUMP .Lcplb_error; - -.Lnext_check: - CC = R0 == CPLB_NO_ADDR_MATCH; - IF !CC JUMP .Lnext_check2; - R0 = CPLB_NO_ADDR_MATCH; - JUMP .Lcplb_error; - -.Lnext_check2: - CC = R0 == CPLB_PROT_VIOL; - IF !CC JUMP .Lstrange_return_from_cplb_mgr; - R0 = CPLB_PROT_VIOL; - JUMP .Lcplb_error; - -.Lstrange_return_from_cplb_mgr: - IDLE; - CSYNC; - JUMP .Lstrange_return_from_cplb_mgr; - -.Lcplb_error: - R1 = sp; - SP += -12; - call _panic_cplb_error; - SP += 12; - JUMP.L _handle_bad_cplb; - -ENDPROC(__cplb_hdr) diff --git a/arch/blackfin/kernel/cplb-nompu/cplbinit.c b/arch/blackfin/kernel/cplb-nompu/cplbinit.c index 4c010ba50a8..0e28f759573 100644 --- a/arch/blackfin/kernel/cplb-nompu/cplbinit.c +++ b/arch/blackfin/kernel/cplb-nompu/cplbinit.c @@ -29,417 +29,143 @@ #include <asm/cplbinit.h> #include <asm/mem_map.h> -u_long icplb_tables[NR_CPUS][CPLB_TBL_ENTRIES+1]; -u_long dcplb_tables[NR_CPUS][CPLB_TBL_ENTRIES+1]; +struct cplb_entry icplb_tbl[NR_CPUS][MAX_CPLBS] PDT_ATTR; +struct cplb_entry dcplb_tbl[NR_CPUS][MAX_CPLBS] PDT_ATTR; -#ifdef CONFIG_CPLB_SWITCH_TAB_L1 -#define PDT_ATTR __attribute__((l1_data)) -#else -#define PDT_ATTR -#endif - -u_long ipdt_tables[NR_CPUS][MAX_SWITCH_I_CPLBS+1] PDT_ATTR; -u_long dpdt_tables[NR_CPUS][MAX_SWITCH_D_CPLBS+1] PDT_ATTR; -#ifdef CONFIG_CPLB_INFO -u_long ipdt_swapcount_tables[NR_CPUS][MAX_SWITCH_I_CPLBS] PDT_ATTR; -u_long dpdt_swapcount_tables[NR_CPUS][MAX_SWITCH_D_CPLBS] PDT_ATTR; -#endif +int first_switched_icplb PDT_ATTR; +int first_switched_dcplb PDT_ATTR; -struct s_cplb { - struct cplb_tab init_i; - struct cplb_tab init_d; - struct cplb_tab switch_i; - struct cplb_tab switch_d; -}; +struct cplb_boundary dcplb_bounds[9] PDT_ATTR; +struct cplb_boundary icplb_bounds[7] PDT_ATTR; -#if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE) -static struct cplb_desc cplb_data[] = { - { - .start = 0, - .end = SIZE_1K, - .psize = SIZE_1K, - .attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB, - .i_conf = SDRAM_OOPS, - .d_conf = SDRAM_OOPS, -#if defined(CONFIG_DEBUG_HUNT_FOR_ZERO) - .valid = 1, -#else - .valid = 0, -#endif - .name = "Zero Pointer Guard Page", - }, - { - .start = 0, /* dyanmic */ - .end = 0, /* dynamic */ - .psize = SIZE_4M, - .attr = INITIAL_T | SWITCH_T | I_CPLB, - .i_conf = L1_IMEMORY, - .d_conf = 0, - .valid = 1, - .name = "L1 I-Memory", - }, - { - .start = 0, /* dynamic */ - .end = 0, /* dynamic */ - .psize = SIZE_4M, - .attr = INITIAL_T | SWITCH_T | D_CPLB, - .i_conf = 0, - .d_conf = L1_DMEMORY, -#if ((L1_DATA_A_LENGTH > 0) || (L1_DATA_B_LENGTH > 0)) - .valid = 1, -#else - .valid = 0, -#endif - .name = "L1 D-Memory", - }, - { - .start = L2_START, - .end = L2_START + L2_LENGTH, - .psize = SIZE_1M, - .attr = L2_ATTR, - .i_conf = L2_IMEMORY, - .d_conf = L2_DMEMORY, - .valid = (L2_LENGTH > 0), - .name = "L2 Memory", - }, - { - .start = 0, - .end = 0, /* dynamic */ - .psize = 0, - .attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB, - .i_conf = SDRAM_IGENERIC, - .d_conf = SDRAM_DGENERIC, - .valid = 1, - .name = "Kernel Memory", - }, - { - .start = 0, /* dynamic */ - .end = 0, /* dynamic */ - .psize = 0, - .attr = INITIAL_T | SWITCH_T | D_CPLB, - .i_conf = SDRAM_IGENERIC, - .d_conf = SDRAM_DNON_CHBL, - .valid = 1, - .name = "uClinux MTD Memory", - }, - { - .start = 0, /* dynamic */ - .end = 0, /* dynamic */ - .psize = SIZE_1M, - .attr = INITIAL_T | SWITCH_T | D_CPLB, - .d_conf = SDRAM_DNON_CHBL, - .valid = 1, - .name = "Uncached DMA Zone", - }, - { - .start = 0, /* dynamic */ - .end = 0, /* dynamic */ - .psize = 0, - .attr = SWITCH_T | D_CPLB, - .i_conf = 0, /* dynamic */ - .d_conf = 0, /* dynamic */ - .valid = 1, - .name = "Reserved Memory", - }, - { - .start = ASYNC_BANK0_BASE, - .end = ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE, - .psize = 0, - .attr = SWITCH_T | D_CPLB, - .d_conf = SDRAM_EBIU, - .valid = 1, - .name = "Asynchronous Memory Banks", - }, - { - .start = BOOT_ROM_START, - .end = BOOT_ROM_START + BOOT_ROM_LENGTH, - .psize = SIZE_1M, - .attr = SWITCH_T | I_CPLB | D_CPLB, - .i_conf = SDRAM_IGENERIC, - .d_conf = SDRAM_DGENERIC, - .valid = 1, - .name = "On-Chip BootROM", - }, -}; +int icplb_nr_bounds PDT_ATTR; +int dcplb_nr_bounds PDT_ATTR; -static bool __init lock_kernel_check(u32 start, u32 end) +void __init generate_cplb_tables_cpu(unsigned int cpu) { - if (start >= (u32)__init_begin || end <= (u32)_stext) - return false; - - /* This cplb block overlapped with kernel area. */ - return true; -} + int i_d, i_i; + unsigned long addr; -static void __init -fill_cplbtab(struct cplb_tab *table, - unsigned long start, unsigned long end, - unsigned long block_size, unsigned long cplb_data) -{ - int i; + struct cplb_entry *d_tbl = dcplb_tbl[cpu]; + struct cplb_entry *i_tbl = icplb_tbl[cpu]; - switch (block_size) { - case SIZE_4M: - i = 3; - break; - case SIZE_1M: - i = 2; - break; - case SIZE_4K: - i = 1; - break; - case SIZE_1K: - default: - i = 0; - break; - } + printk(KERN_INFO "NOMPU: setting up cplb tables\n"); - cplb_data = (cplb_data & ~(3 << 16)) | (i << 16); + i_d = i_i = 0; - while ((start < end) && (table->pos < table->size)) { + /* Set up the zero page. */ + d_tbl[i_d].addr = 0; + d_tbl[i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB; - table->tab[table->pos++] = start; + /* Cover kernel memory with 4M pages. */ + addr = 0; - if (lock_kernel_check(start, start + block_size)) - table->tab[table->pos++] = - cplb_data | CPLB_LOCK | CPLB_DIRTY; - else - table->tab[table->pos++] = cplb_data; + for (; addr < memory_start; addr += 4 * 1024 * 1024) { + d_tbl[i_d].addr = addr; + d_tbl[i_d++].data = SDRAM_DGENERIC | PAGE_SIZE_4MB; + i_tbl[i_i].addr = addr; + i_tbl[i_i++].data = SDRAM_IGENERIC | PAGE_SIZE_4MB; + } - start += block_size; + /* Cover L1 memory. One 4M area for code and data each is enough. */ + if (L1_DATA_A_LENGTH || L1_DATA_B_LENGTH) { + d_tbl[i_d].addr = L1_DATA_A_START; + d_tbl[i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB; } -} + i_tbl[i_i].addr = L1_CODE_START; + i_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB; -static void __init close_cplbtab(struct cplb_tab *table) -{ - while (table->pos < table->size) - table->tab[table->pos++] = 0; -} + first_switched_dcplb = i_d; + first_switched_icplb = i_i; -/* helper function */ -static void __init -__fill_code_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end) -{ - if (cplb_data[i].psize) { - fill_cplbtab(t, - cplb_data[i].start, - cplb_data[i].end, - cplb_data[i].psize, - cplb_data[i].i_conf); - } else { -#if defined(CONFIG_BFIN_ICACHE) - if (ANOMALY_05000263 && i == SDRAM_KERN) { - fill_cplbtab(t, - cplb_data[i].start, - cplb_data[i].end, - SIZE_4M, - cplb_data[i].i_conf); - } else -#endif - { - fill_cplbtab(t, - cplb_data[i].start, - a_start, - SIZE_1M, - cplb_data[i].i_conf); - fill_cplbtab(t, - a_start, - a_end, - SIZE_4M, - cplb_data[i].i_conf); - fill_cplbtab(t, a_end, - cplb_data[i].end, - SIZE_1M, - cplb_data[i].i_conf); - } - } -} + BUG_ON(first_switched_dcplb > MAX_CPLBS); + BUG_ON(first_switched_icplb > MAX_CPLBS); -static void __init -__fill_data_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end) -{ - if (cplb_data[i].psize) { - fill_cplbtab(t, - cplb_data[i].start, - cplb_data[i].end, - cplb_data[i].psize, - cplb_data[i].d_conf); - } else { - fill_cplbtab(t, - cplb_data[i].start, - a_start, SIZE_1M, - cplb_data[i].d_conf); - fill_cplbtab(t, a_start, - a_end, SIZE_4M, - cplb_data[i].d_conf); - fill_cplbtab(t, a_end, - cplb_data[i].end, - SIZE_1M, - cplb_data[i].d_conf); - } + while (i_d < MAX_CPLBS) + d_tbl[i_d++].data = 0; + while (i_i < MAX_CPLBS) + i_tbl[i_i++].data = 0; } -void __init generate_cplb_tables_cpu(unsigned int cpu) +void __init generate_cplb_tables_all(void) { + int i_d, i_i; - u16 i, j, process; - u32 a_start, a_end, as, ae, as_1m; - - struct cplb_tab *t_i = NULL; - struct cplb_tab *t_d = NULL; - struct s_cplb cplb; - - printk(KERN_INFO "NOMPU: setting up cplb tables for global access\n"); - - cplb.init_i.size = CPLB_TBL_ENTRIES; - cplb.init_d.size = CPLB_TBL_ENTRIES; - cplb.switch_i.size = MAX_SWITCH_I_CPLBS; - cplb.switch_d.size = MAX_SWITCH_D_CPLBS; - - cplb.init_i.pos = 0; - cplb.init_d.pos = 0; - cplb.switch_i.pos = 0; - cplb.switch_d.pos = 0; - - cplb.init_i.tab = icplb_tables[cpu]; - cplb.init_d.tab = dcplb_tables[cpu]; - cplb.switch_i.tab = ipdt_tables[cpu]; - cplb.switch_d.tab = dpdt_tables[cpu]; - - cplb_data[L1I_MEM].start = get_l1_code_start_cpu(cpu); - cplb_data[L1I_MEM].end = cplb_data[L1I_MEM].start + L1_CODE_LENGTH; - cplb_data[L1D_MEM].start = get_l1_data_a_start_cpu(cpu); - cplb_data[L1D_MEM].end = get_l1_data_b_start_cpu(cpu) + L1_DATA_B_LENGTH; - cplb_data[SDRAM_KERN].end = memory_end; - + i_d = 0; + /* Normal RAM, including MTD FS. */ #ifdef CONFIG_MTD_UCLINUX - cplb_data[SDRAM_RAM_MTD].start = memory_mtd_start; - cplb_data[SDRAM_RAM_MTD].end = memory_mtd_start + mtd_size; - cplb_data[SDRAM_RAM_MTD].valid = mtd_size > 0; -# if defined(CONFIG_ROMFS_FS) - cplb_data[SDRAM_RAM_MTD].attr |= I_CPLB; - - /* - * The ROMFS_FS size is often not multiple of 1MB. - * This can cause multiple CPLB sets covering the same memory area. - * This will then cause multiple CPLB hit exceptions. - * Workaround: We ensure a contiguous memory area by extending the kernel - * memory section over the mtd section. - * For ROMFS_FS memory must be covered with ICPLBs anyways. - * So there is no difference between kernel and mtd memory setup. - */ - - cplb_data[SDRAM_KERN].end = memory_mtd_start + mtd_size;; - cplb_data[SDRAM_RAM_MTD].valid = 0; - -# endif + dcplb_bounds[i_d].eaddr = memory_mtd_start + mtd_size; #else - cplb_data[SDRAM_RAM_MTD].valid = 0; + dcplb_bounds[i_d].eaddr = memory_end; #endif + dcplb_bounds[i_d++].data = SDRAM_DGENERIC; + /* DMA uncached region. */ + if (DMA_UNCACHED_REGION) { + dcplb_bounds[i_d].eaddr = _ramend; + dcplb_bounds[i_d++].data = SDRAM_DNON_CHBL; + } + if (_ramend != physical_mem_end) { + /* Reserved memory. */ + dcplb_bounds[i_d].eaddr = physical_mem_end; + dcplb_bounds[i_d++].data = (reserved_mem_dcache_on ? + SDRAM_DGENERIC : SDRAM_DNON_CHBL); + } + /* Addressing hole up to the async bank. */ + dcplb_bounds[i_d].eaddr = ASYNC_BANK0_BASE; + dcplb_bounds[i_d++].data = 0; + /* ASYNC banks. */ + dcplb_bounds[i_d].eaddr = ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE; + dcplb_bounds[i_d++].data = SDRAM_EBIU; + /* Addressing hole up to BootROM. */ |