Merge commit 'origin/master' into next
[deliverable/linux.git] / arch / blackfin / kernel / cplb-nompu / cplbinit.c
index 2debc900e246d2ae7d5fe81e55bf18b0437de4d3..d6c067782e638987ba406164f6df65adeb0b15db 100644 (file)
  * 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
+struct cplb_entry icplb_tbl[NR_CPUS][MAX_CPLBS] PDT_ATTR;
+struct cplb_entry dcplb_tbl[NR_CPUS][MAX_CPLBS] PDT_ATTR;
 
-/*
-* 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)
+int first_switched_icplb PDT_ATTR;
+int first_switched_dcplb PDT_ATTR;
 
-/*
-* 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)
+struct cplb_boundary dcplb_bounds[9] PDT_ATTR;
+struct cplb_boundary icplb_bounds[7] PDT_ATTR;
 
+int icplb_nr_bounds PDT_ATTR;
+int dcplb_nr_bounds PDT_ATTR;
 
-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
+void __init generate_cplb_tables_cpu(unsigned int cpu)
+{
+       int i_d, i_i;
+       unsigned long addr;
 
-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 *d_tbl = dcplb_tbl[cpu];
+       struct cplb_entry *i_tbl = icplb_tbl[cpu];
 
-#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
+       printk(KERN_INFO "NOMPU: setting up cplb tables\n");
 
-struct s_cplb {
-       struct cplb_tab init_i;
-       struct cplb_tab init_d;
-       struct cplb_tab switch_i;
-       struct cplb_tab switch_d;
-};
+       i_d = i_i = 0;
 
-#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,
+#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
+       /* Set up the zero page.  */
+       d_tbl[i_d].addr = 0;
+       d_tbl[i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB;
+       i_tbl[i_i].addr = 0;
+       i_tbl[i_i++].data = SDRAM_OOPS | PAGE_SIZE_1KB;
 #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",
-       },
-};
 
-static u16 __init lock_kernel_check(u32 start, u32 end)
-{
-       if (start >= (u32)_end || end <= (u32)_stext)
-               return 0;
-
-       /* This cplb block overlapped with kernel area. */
-       return IN_KERNEL;
-}
+       /* Cover kernel memory with 4M pages.  */
+       addr = 0;
 
-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;
-
-       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;
+       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;
        }
 
-       cplb_data = (cplb_data & ~(3 << 16)) | (i << 16);
-
-       while ((start < end) && (table->pos < table->size)) {
-
-               table->tab[table->pos++] = start;
-
-               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;
-
-               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;
        }
-       return 0;
-}
+       i_tbl[i_i].addr = L1_CODE_START;
+       i_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB;
 
-static unsigned short __init
-close_cplbtab(struct cplb_tab *table)
-{
+       first_switched_dcplb = i_d;
+       first_switched_icplb = i_i;
 
-       while (table->pos < table->size) {
+       BUG_ON(first_switched_dcplb > MAX_CPLBS);
+       BUG_ON(first_switched_icplb > MAX_CPLBS);
 
-               table->tab[table->pos++] = 0;
-               table->tab[table->pos++] = 0; /* !CPLB_VALID */
-       }
-       return 0;
+       while (i_d < MAX_CPLBS)
+               d_tbl[i_d++].data = 0;
+       while (i_i < MAX_CPLBS)
+               i_tbl[i_i++].data = 0;
 }
 
-/* helper function */
-static void __init
-__fill_code_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end)
+void __init generate_cplb_tables_all(void)
 {
-       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);
-               }
-       }
-}
-
-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);
-       }
-}
-
-void __init generate_cplb_tables(void)
-{
-
-       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;
+       int i_d, i_i;
 
+       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
-
This page took 0.030665 seconds and 5 git commands to generate.