diff options
Diffstat (limited to 'arch/blackfin/kernel/cplb-nompu/cplbinit.c')
-rw-r--r-- | arch/blackfin/kernel/cplb-nompu/cplbinit.c | 521 |
1 files changed, 114 insertions, 407 deletions
diff --git a/arch/blackfin/kernel/cplb-nompu/cplbinit.c b/arch/blackfin/kernel/cplb-nompu/cplbinit.c index 2debc900e24..0e28f759573 100644 --- a/arch/blackfin/kernel/cplb-nompu/cplbinit.c +++ b/arch/blackfin/kernel/cplb-nompu/cplbinit.c @@ -20,445 +20,152 @@ * to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + #include <linux/module.h> #include <asm/blackfin.h> #include <asm/cacheflush.h> #include <asm/cplb.h> #include <asm/cplbinit.h> +#include <asm/mem_map.h> -#define CPLB_MEM CONFIG_MAX_MEM_SIZE - -/* -* 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) - -/* -* 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) - - -u_long icplb_table[MAX_CPLBS + 1]; -u_long dcplb_table[MAX_CPLBS + 1]; - -#ifdef CONFIG_CPLB_SWITCH_TAB_L1 -# define PDT_ATTR __attribute__((l1_data)) -#else -# define PDT_ATTR -#endif - -u_long ipdt_table[MAX_SWITCH_I_CPLBS + 1] PDT_ATTR; -u_long dpdt_table[MAX_SWITCH_D_CPLBS + 1] PDT_ATTR; +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_INFO -u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS] PDT_ATTR; -u_long dpdt_swapcount_table[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 = L1_CODE_START, - .end = L1_CODE_START + L1_CODE_LENGTH, - .psize = SIZE_4M, - .attr = INITIAL_T | SWITCH_T | I_CPLB, - .i_conf = L1_IMEMORY, - .d_conf = 0, - .valid = 1, - .name = "L1 I-Memory", - }, - { - .start = L1_DATA_A_START, - .end = L1_DATA_B_START + L1_DATA_B_LENGTH, - .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 = 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 = L2_START, - .end = L2_START + L2_LENGTH, - .psize = SIZE_1M, - .attr = SWITCH_T | I_CPLB | D_CPLB, - .i_conf = L2_IMEMORY, - .d_conf = L2_DMEMORY, - .valid = (L2_LENGTH > 0), - .name = "L2 Memory", - }, - { - .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 u16 __init lock_kernel_check(u32 start, u32 end) +void __init generate_cplb_tables_cpu(unsigned int cpu) { - if (start >= (u32)_end || end <= (u32)_stext) - return 0; + int i_d, i_i; + unsigned long addr; - /* This cplb block overlapped with kernel area. */ - return IN_KERNEL; -} + struct cplb_entry *d_tbl = dcplb_tbl[cpu]; + struct cplb_entry *i_tbl = icplb_tbl[cpu]; -static unsigned short __init -fill_cplbtab(struct cplb_tab *table, - unsigned long start, unsigned long end, - unsigned long block_size, unsigned long cplb_data) -{ - int i; + printk(KERN_INFO "NOMPU: setting up cplb tables\n"); - 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; - } - - cplb_data = (cplb_data & ~(3 << 16)) | (i << 16); - - while ((start < end) && (table->pos < table->size)) { + i_d = i_i = 0; - table->tab[table->pos++] = start; + /* Set up the zero page. */ + d_tbl[i_d].addr = 0; + d_tbl[i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB; - if (lock_kernel_check(start, start + block_size) == IN_KERNEL) - table->tab[table->pos++] = - cplb_data | CPLB_LOCK | CPLB_DIRTY; - else - table->tab[table->pos++] = cplb_data; + /* Cover kernel memory with 4M pages. */ + addr = 0; - start += block_size; + 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; } - return 0; -} -static unsigned short __init -close_cplbtab(struct cplb_tab *table) -{ - - while (table->pos < table->size) { - - table->tab[table->pos++] = 0; - table->tab[table->pos++] = 0; /* !CPLB_VALID */ + /* 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; } - return 0; -} + i_tbl[i_i].addr = L1_CODE_START; + i_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB; -/* 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); - } - } -} + first_switched_dcplb = i_d; + first_switched_icplb = i_i; -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); - } + BUG_ON(first_switched_dcplb > MAX_CPLBS); + BUG_ON(first_switched_icplb > MAX_CPLBS); + + 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(void) +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 = MAX_CPLBS; - cplb.init_d.size = MAX_CPLBS; - 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_table; - cplb.init_d.tab = dcplb_table; - cplb.switch_i.tab = ipdt_table; - cplb.switch_d.tab = dpdt_table; - - 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; } - -/* 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 - |