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/kernel | |
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/kernel')
-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 |
11 files changed, 427 insertions, 1276 deletions
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. */ + dcplb_bounds[i_d].eaddr = BOOT_ROM_START; + dcplb_bounds[i_d++].data = 0; + /* BootROM -- largest one should be less than 1 meg. */ + dcplb_bounds[i_d].eaddr = BOOT_ROM_START + (1 * 1024 * 1024); + dcplb_bounds[i_d++].data = SDRAM_DGENERIC; + if (L2_LENGTH) { + /* Addressing hole up to L2 SRAM. */ + dcplb_bounds[i_d].eaddr = L2_START; + dcplb_bounds[i_d++].data = 0; + /* L2 SRAM. */ + dcplb_bounds[i_d].eaddr = L2_START + L2_LENGTH; + dcplb_bounds[i_d++].data = L2_DMEMORY; + } + dcplb_nr_bounds = i_d; + BUG_ON(dcplb_nr_bounds > ARRAY_SIZE(dcplb_bounds)); - cplb_data[SDRAM_DMAZ].start = _ramend - DMA_UNCACHED_REGION; - cplb_data[SDRAM_DMAZ].end = _ramend; - - cplb_data[RES_MEM].start = _ramend; - cplb_data[RES_MEM].end = physical_mem_end; - - if (reserved_mem_dcache_on) - cplb_data[RES_MEM].d_conf = SDRAM_DGENERIC; - else - cplb_data[RES_MEM].d_conf = SDRAM_DNON_CHBL; - - if (reserved_mem_icache_on) - cplb_data[RES_MEM].i_conf = SDRAM_IGENERIC; - else - cplb_data[RES_MEM].i_conf = SDRAM_INON_CHBL; - - for (i = ZERO_P; i < ARRAY_SIZE(cplb_data); ++i) { - if (!cplb_data[i].valid) - continue; - - as_1m = cplb_data[i].start % SIZE_1M; - - /* We need to make sure all sections are properly 1M aligned - * However between Kernel Memory and the Kernel mtd section, depending on the - * rootfs size, there can be overlapping memory areas. - */ - - if (as_1m && i != L1I_MEM && i != L1D_MEM) { + i_i = 0; + /* Normal RAM, including MTD FS. */ #ifdef CONFIG_MTD_UCLINUX - if (i == SDRAM_RAM_MTD) { - if ((cplb_data[SDRAM_KERN].end + 1) > cplb_data[SDRAM_RAM_MTD].start) - cplb_data[SDRAM_RAM_MTD].start = (cplb_data[i].start & (-2*SIZE_1M)) + SIZE_1M; - else - cplb_data[SDRAM_RAM_MTD].start = (cplb_data[i].start & (-2*SIZE_1M)); - } else + icplb_bounds[i_i].eaddr = memory_mtd_start + mtd_size; +#else + icplb_bounds[i_i].eaddr = memory_end; #endif - printk(KERN_WARNING "Unaligned Start of %s at 0x%X\n", - cplb_data[i].name, cplb_data[i].start); - } - - as = cplb_data[i].start % SIZE_4M; - ae = cplb_data[i].end % SIZE_4M; - - if (as) - a_start = cplb_data[i].start + (SIZE_4M - (as)); - else - a_start = cplb_data[i].start; - - a_end = cplb_data[i].end - ae; - - for (j = INITIAL_T; j <= SWITCH_T; j++) { - - switch (j) { - case INITIAL_T: - if (cplb_data[i].attr & INITIAL_T) { - t_i = &cplb.init_i; - t_d = &cplb.init_d; - process = 1; - } else - process = 0; - break; - case SWITCH_T: - if (cplb_data[i].attr & SWITCH_T) { - t_i = &cplb.switch_i; - t_d = &cplb.switch_d; - process = 1; - } else - process = 0; - break; - default: - process = 0; - break; - } - - if (!process) - continue; - if (cplb_data[i].attr & I_CPLB) - __fill_code_cplbtab(t_i, i, a_start, a_end); - - if (cplb_data[i].attr & D_CPLB) - __fill_data_cplbtab(t_d, i, a_start, a_end); - } + icplb_bounds[i_i++].data = SDRAM_IGENERIC; + /* DMA uncached region. */ + if (DMA_UNCACHED_REGION) { + icplb_bounds[i_i].eaddr = _ramend; + icplb_bounds[i_i++].data = 0; } - - /* make sure we locked the kernel start */ - BUG_ON(cplb.init_i.pos < 2 + cplb_data[ZERO_P].valid); - BUG_ON(cplb.init_d.pos < 1 + cplb_data[ZERO_P].valid + cplb_data[L1D_MEM].valid); - - /* make sure we didnt overflow the table */ - BUG_ON(cplb.init_i.size < cplb.init_i.pos); - BUG_ON(cplb.init_d.size < cplb.init_d.pos); - BUG_ON(cplb.switch_i.size < cplb.switch_i.pos); - BUG_ON(cplb.switch_d.size < cplb.switch_d.pos); - - /* close tables */ - close_cplbtab(&cplb.init_i); - close_cplbtab(&cplb.init_d); - - cplb.init_i.tab[cplb.init_i.pos] = -1; - cplb.init_d.tab[cplb.init_d.pos] = -1; - cplb.switch_i.tab[cplb.switch_i.pos] = -1; - cplb.switch_d.tab[cplb.switch_d.pos] = -1; - + if (_ramend != physical_mem_end) { + /* Reserved memory. */ + icplb_bounds[i_i].eaddr = physical_mem_end; + icplb_bounds[i_i++].data = (reserved_mem_icache_on ? + SDRAM_IGENERIC : SDRAM_INON_CHBL); + } + /* Addressing hole up to BootROM. */ + icplb_bounds[i_i].eaddr = BOOT_ROM_START; + icplb_bounds[i_i++].data = 0; + /* BootROM -- largest one should be less than 1 meg. */ + icplb_bounds[i_i].eaddr = BOOT_ROM_START + (1 * 1024 * 1024); + icplb_bounds[i_i++].data = SDRAM_IGENERIC; + if (L2_LENGTH) { + /* Addressing hole up to L2 SRAM, including the async bank. */ + icplb_bounds[i_i].eaddr = L2_START; + icplb_bounds[i_i++].data = 0; + /* L2 SRAM. */ + icplb_bounds[i_i].eaddr = L2_START + L2_LENGTH; + icplb_bounds[i_i++].data = L2_IMEMORY; + } + icplb_nr_bounds = i_i; + BUG_ON(icplb_nr_bounds > ARRAY_SIZE(icplb_bounds)); } - -#endif diff --git a/arch/blackfin/kernel/cplb-nompu/cplbmgr.S b/arch/blackfin/kernel/cplb-nompu/cplbmgr.S deleted file mode 100644 index f4ca76c7239..00000000000 --- a/arch/blackfin/kernel/cplb-nompu/cplbmgr.S +++ /dev/null @@ -1,648 +0,0 @@ -/* - * File: arch/blackfin/mach-common/cplbmgtr.S - * Based on: - * Author: LG Soft India - * - * Created: ? - * Description: CPLB replacement routine for CPLB mismatch - * - * 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 - */ - -/* Usage: int _cplb_mgr(is_data_miss,int enable_cache) - * is_data_miss==2 => Mark as Dirty, write to the clean data page - * is_data_miss==1 => Replace a data CPLB. - * is_data_miss==0 => Replace an instruction CPLB. - * - * Returns: - * CPLB_RELOADED => Successfully updated CPLB table. - * CPLB_NO_UNLOCKED => All CPLBs are locked, so cannot be evicted. - * This indicates that the CPLBs in the configuration - * tablei are badly configured, as this should never - * occur. - * CPLB_NO_ADDR_MATCH => The address being accessed, that triggered the - * exception, is not covered by any of the CPLBs in - * the configuration table. The application is - * presumably misbehaving. - * CPLB_PROT_VIOL => The address being accessed, that triggered the - * exception, was not a first-write to a clean Write - * Back Data page, and so presumably is a genuine - * violation of the page's protection attributes. - * The application is misbehaving. - */ - -#include <linux/linkage.h> -#include <asm/blackfin.h> -#include <asm/cplb.h> -#include <asm/asm-offsets.h> - -#ifdef CONFIG_EXCPT_IRQ_SYSC_L1 -.section .l1.text -#else -.text -#endif - -.align 2; -ENTRY(_cplb_mgr) - - [--SP]=( R7:4,P5:3 ); - - CC = R0 == 2; - IF CC JUMP .Ldcplb_write; - - CC = R0 == 0; - IF !CC JUMP .Ldcplb_miss_compare; - - /* ICPLB Miss Exception. We need to choose one of the - * currently-installed CPLBs, and replace it with one - * from the configuration table. - */ - - /* A multi-word instruction can cross a page boundary. This means the - * first part of the instruction can be in a valid page, but the - * second part is not, and hence generates the instruction miss. - * However, the fault address is for the start of the instruction, - * not the part that's in the bad page. Therefore, we have to check - * whether the fault address applies to a page that is already present - * in the table. - */ - - P4.L = LO(ICPLB_FAULT_ADDR); - P4.H = HI(ICPLB_FAULT_ADDR); - - P1 = 16; - P5.L = _page_size_table; - P5.H = _page_size_table; - - P0.L = LO(ICPLB_DATA0); - P0.H = HI(ICPLB_DATA0); - R4 = [P4]; /* Get faulting address*/ - R6 = 64; /* Advance past the fault address, which*/ - R6 = R6 + R4; /* we'll use if we find a match*/ - R3 = ((16 << 8) | 2); /* Extract mask, two bits at posn 16 */ - - R5 = 0; -.Lisearch: - - R1 = [P0-0x100]; /* Address for this CPLB */ - - R0 = [P0++]; /* Info for this CPLB*/ - CC = BITTST(R0,0); /* Is the CPLB valid?*/ - IF !CC JUMP .Lnomatch; /* Skip it, if not.*/ - CC = R4 < R1(IU); /* If fault address less than page start*/ - IF CC JUMP .Lnomatch; /* then skip this one.*/ - R2 = EXTRACT(R0,R3.L) (Z); /* Get page size*/ - P1 = R2; - P1 = P5 + (P1<<2); /* index into page-size table*/ - R2 = [P1]; /* Get the page size*/ - R1 = R1 + R2; /* and add to page start, to get page end*/ - CC = R4 < R1(IU); /* and see whether fault addr is in page.*/ - IF !CC R4 = R6; /* If so, advance the address and finish loop.*/ - IF !CC JUMP .Lisearch_done; -.Lnomatch: - /* Go around again*/ - R5 += 1; - CC = BITTST(R5, 4); /* i.e CC = R5 >= 16*/ - IF !CC JUMP .Lisearch; - -.Lisearch_done: - I0 = R4; /* Fault address we'll search for*/ - - /* set up pointers */ - P0.L = LO(ICPLB_DATA0); - P0.H = HI(ICPLB_DATA0); - - /* The replacement procedure for ICPLBs */ - - P4.L = LO(IMEM_CONTROL); - P4.H = HI(IMEM_CONTROL); - - /* Turn off CPLBs while we work, necessary according to HRM before - * modifying CPLB descriptors - */ - R5 = [P4]; /* Control Register*/ - BITCLR(R5,ENICPLB_P); - CLI R1; - SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */ - .align 8; - [P4] = R5; - SSYNC; - STI R1; - - R1 = -1; /* end point comparison */ - R3 = 16; /* counter */ - - /* Search through CPLBs for first non-locked entry */ - /* Overwrite it by moving everyone else up by 1 */ -.Licheck_lock: - R0 = [P0++]; - R3 = R3 + R1; - CC = R3 == R1; - IF CC JUMP .Lall_locked; - CC = BITTST(R0, 0); /* an invalid entry is good */ - IF !CC JUMP .Lifound_victim; - CC = BITTST(R0,1); /* but a locked entry isn't */ - IF CC JUMP .Licheck_lock; - -.Lifound_victim: -#ifdef CONFIG_CPLB_INFO - R7 = [P0 - 0x104]; - GET_PDA(P2, R2); - P3 = [P2 + PDA_IPDT_SWAPCOUNT]; - P2 = [P2 + PDA_IPDT]; - P3 += -4; -.Licount: - R2 = [P2]; /* address from config table */ - P2 += 8; - P3 += 8; - CC = R2==-1; - IF CC JUMP .Licount_done; - CC = R7==R2; - IF !CC JUMP .Licount; - R7 = [P3]; - R7 += 1; - [P3] = R7; - CSYNC; -.Licount_done: -#endif - LC0=R3; - LSETUP(.Lis_move,.Lie_move) LC0; -.Lis_move: - R0 = [P0]; - [P0 - 4] = R0; - R0 = [P0 - 0x100]; - [P0-0x104] = R0; -.Lie_move: - P0+=4; - - /* Clear ICPLB_DATA15, in case we don't find a replacement - * otherwise, we would have a duplicate entry, and will crash - */ - R0 = 0; - [P0 - 4] = R0; - - /* We've made space in the ICPLB table, so that ICPLB15 - * is now free to be overwritten. Next, we have to determine - * which CPLB we need to install, from the configuration - * table. This is a matter of getting the start-of-page - * addresses and page-lengths from the config table, and - * determining whether the fault address falls within that - * range. - */ - - GET_PDA(P3, R0); - P2 = [P3 + PDA_IPDT]; -#ifdef CONFIG_CPLB_INFO - P3 = [P3 + PDA_IPDT_SWAPCOUNT]; - P3 += -8; -#endif - P0.L = _page_size_table; - P0.H = _page_size_table; - - /* Retrieve our fault address (whi |