this the hibats mapping patch. I have to manually edit out things that are only relevant on our board.
--- 2.6.7/linux/arch/ppc/mm/pgtable.c Fri, 18 Jun 2004 13:35:07 -0400 linhd (k26/O/c/1_pgtable.c 1.1 644) +++ local-2.6.7/arch/ppc/mm/pgtable.c Thu, 24 Jun 2004 15:24:06 -0400 linhd (k26/O/c/1_pgtable.c 1.3 644) @@ -34,9 +34,11 @@ #include "mmu_decl.h" +extern int bat_map_io_succeed(unsigned long virt, phys_addr_t phys, + unsigned int size, int flags); + unsigned long ioremap_base; unsigned long ioremap_bot; -int io_bat_index; #if defined(CONFIG_6xx) || defined(CONFIG_POWER3) #define HAVE_BATS 1 @@ -297,9 +299,6 @@ } } -/* is x a power of 2? */ -#define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0)) - /* * Set up a mapping for a block of I/O. * virt, phys, size must all be page-aligned. @@ -317,13 +316,9 @@ /* * Use a BAT for this if possible... */ - if (io_bat_index < 2 && is_power_of_2(size) - && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) { - setbat(io_bat_index, virt, phys, size, flags); - ++io_bat_index; + if (bat_map_io_succeed(virt, phys, size, flags)) return; - } #endif /* HAVE_BATS */ /* No BATs available, put it in the page tables. */ --- 2.6.7/linux/arch/ppc/mm/ppc_mmu.c Fri, 18 Jun 2004 13:35:07 -0400 linhd (k26/O/c/2_ppc_mmu.c 1.1 644) +++ local-2.6.7/arch/ppc/mm/ppc_mmu.c Tue, 29 Jun 2004 11:11:15 -0400 linhd (k26/O/c/2_ppc_mmu.c 1.3 644) @@ -40,6 +40,17 @@ unsigned long Hash_size, Hash_mask; unsigned long _SDR1; + +#define PPC32_MAX_BAT_PAIRS 8 /* maximum 8 dbats and 8 ibats */ + +unsigned cpu_num_bat_pairs = 4; /* the actual number of bat pairs for + * this CPU. default to 4 for most + * ppc32 */ + +unsigned cpu_num_ram_bats; + +int io_bat_index; /* the 1st bat for I/O mapping */ + union ubat { /* BAT register values to be loaded */ BAT bat; #ifdef CONFIG_PPC64BRIDGE @@ -47,13 +58,14 @@ #else u32 word[2]; #endif -} BATS[4][2]; /* 4 pairs of IBAT, DBAT */ +} BATS[PPC32_MAX_BAT_PAIRS][2]; /* 8 pairs of IBAT, DBAT */ struct batrange { /* stores address ranges mapped by BATs */ unsigned long start; unsigned long limit; unsigned long phys; -} bat_addrs[4]; +} bat_addrs[PPC32_MAX_BAT_PAIRS]; + /* * Return PA for this VA if it is mapped by a BAT, or 0 @@ -61,7 +73,7 @@ unsigned long v_mapped_by_bats(unsigned long va) { int b; - for (b = 0; b < 4; ++b) + for (b = 0; b < cpu_num_bat_pairs; ++b) if (va >= bat_addrs[b].start && va < bat_addrs[b].limit) return bat_addrs[b].phys + (va - bat_addrs[b].start); return 0; @@ -73,7 +85,7 @@ unsigned long p_mapped_by_bats(unsigned long pa) { int b; - for (b = 0; b < 4; ++b) + for (b = 0; b < cpu_num_bat_pairs; ++b) if (pa >= bat_addrs[b].phys && pa < (bat_addrs[b].limit-bat_addrs[b].start) +bat_addrs[b].phys) @@ -81,14 +93,35 @@ return 0; } + +int +bat_map_io_succeed(unsigned long virt, phys_addr_t phys, + unsigned int size, int flags) +{ +/* is x a power of 2? */ +#define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0)) + +#if defined(CONFIG_6xx) || defined(CONFIG_POWER3) + if (io_bat_index < cpu_num_bat_pairs && is_power_of_2(size) + && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) { + setbat(io_bat_index, virt, phys, size, flags); + ++io_bat_index; + return 1; + } +#endif + return 0; +} + + unsigned long __init mmu_mapin_ram(void) { #ifdef CONFIG_POWER4 return 0; #else - unsigned long tot, bl, done; + unsigned long tot, bl, done = 0; unsigned long max_size = (256<<20); unsigned long align; + unsigned i; if (__map_without_bats) return 0; @@ -103,24 +136,29 @@ if (align && align < max_size) max_size = align; + cpu_num_ram_bats = cpu_num_bat_pairs / 2; +/* if (cpu_num_bat_pairs > 4) */ +/* cpu_num_ram_bats++; */ + + /* + * cpu_num_ram_bats bats registers from bat0 will be used to + * map ram. the rest will be used to map I/O + */ + tot = total_lowmem; - for (bl = 128<<10; bl < max_size; bl <<= 1) { - if (bl * 2 > tot) - break; - } - setbat(2, KERNELBASE, PPC_MEMSTART, bl, _PAGE_RAM); - done = (unsigned long)bat_addrs[2].limit - KERNELBASE + 1; - if ((done < tot) && !bat_addrs[3].limit) { - /* use BAT3 to cover a bit more */ - tot -= done; - for (bl = 128<<10; bl < max_size; bl <<= 1) - if (bl * 2 > tot) - break; - setbat(3, KERNELBASE+done, PPC_MEMSTART+done, bl, _PAGE_RAM); - done = (unsigned long)bat_addrs[3].limit - KERNELBASE + 1; + for (i = 0, bl = 1UL << __ilog2(tot - done); + + i < cpu_num_ram_bats && done < tot && bat_addrs[i].limit == 0; + + i++, bl = 1UL << __ilog2(tot - done)) + { + setbat(i, KERNELBASE+done, PPC_MEMSTART+done, bl, _PAGE_RAM); + done = (unsigned long) bat_addrs[i].limit - KERNELBASE + 1; } + io_bat_index = i; /* set the 1st bat used for I/O mapping */ + return done; #endif } @@ -203,7 +241,16 @@ return; } + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_HAS_HIGH_BATS) + { + cpu_num_bat_pairs = 8; + if ( ppc_md.progress ) ppc_md.progress("cpu has hi bat registers", 8); + } + + if ( ppc_md.progress ) ppc_md.progress("num bat pairs:", cpu_num_bat_pairs); + + if ( ppc_md.progress ) ppc_md.progress("hash:enter", 0x105); #ifdef CONFIG_PPC64BRIDGE --- 2.6.7/linux/arch/ppc/kernel/head.S Fri, 18 Jun 2004 13:35:07 -0400 linhd (k26/P/c/20_head.S 1.1 644) +++ local-2.6.7/arch/ppc/kernel/head.S Thu, 24 Jun 2004 15:25:46 -0400 linhd (k26/P/c/20_head.S 1.2 644) @@ -1328,7 +1328,13 @@ LOAD_BAT(1,r3,r4,r5) LOAD_BAT(2,r3,r4,r5) LOAD_BAT(3,r3,r4,r5) +BEGIN_FTR_SECTION + LOAD_BAT(4,r3,r4,r5) + LOAD_BAT(5,r3,r4,r5) + LOAD_BAT(6,r3,r4,r5) + LOAD_BAT(7,r3,r4,r5) +END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS) #endif /* CONFIG_POWER4 */ blr --- 2.6.7/linux/arch/ppc/kernel/cpu_setup_6xx.S Fri, 18 Jun 2004 13:35:07 -0400 linhd (k26/P/c/32_cpu_setup_ 1.1 644) +++ local-2.6.7/arch/ppc/kernel/cpu_setup_6xx.S Thu, 24 Jun 2004 09:00:55 -0400 linhd (k26/P/c/32_cpu_setup_ 1.2 644) @@ -223,6 +223,10 @@ oris r11,r11,HID0_DPM at h /* enable dynamic power mgmt */ END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM) +BEGIN_FTR_SECTION + oris r11,r11,HID0_HIGH_BAT at h +END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS) + /* All of the bits we have to clear.... */ li r3,HID0_SPD | HID0_NOPDST | HID0_NOPTI ** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/