Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: SGI-IP22/28: Use PROM for memory detection

EARLY_PRINTK uses ArcWrite (via prom_putchar) on IP22/28, which needs
to not mess up PROMs data structures. ARC PROM gives out a list of
memory chunks, which are used and which are free. This fixes the
problem of not working early printk.

By using XKPHYS spaces more than 256MB memory on Indigo2 R4k machines
is working now, too.

Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@vger.kernel.org
Cc: linux-kernel@vger.kernel.org

authored by

Thomas Bogendoerfer and committed by
Paul Burton
c0de00b2 931e1bfe

+35 -80
+4 -16
arch/mips/Kconfig
··· 634 634 635 635 config SGI_IP22 636 636 bool "SGI IP22 (Indy/Indigo2)" 637 + select ARC_MEMORY 637 638 select ARC_PROMLIB 638 639 select FW_ARC 639 640 select FW_ARC32 ··· 659 658 select SWAP_IO_SPACE 660 659 select SYS_HAS_CPU_R4X00 661 660 select SYS_HAS_CPU_R5000 662 - # 663 - # Disable EARLY_PRINTK for now since it leads to overwritten prom 664 - # memory during early boot on some machines. 665 - # 666 - # See http://www.linux-mips.org/cgi-bin/mesg.cgi?a=linux-mips&i=20091119164009.GA15038%40deprecation.cyrius.com 667 - # for a more details discussion 668 - # 669 - # select SYS_HAS_EARLY_PRINTK 661 + select SYS_HAS_EARLY_PRINTK 670 662 select SYS_SUPPORTS_32BIT_KERNEL 671 663 select SYS_SUPPORTS_64BIT_KERNEL 672 664 select SYS_SUPPORTS_BIG_ENDIAN ··· 697 703 698 704 config SGI_IP28 699 705 bool "SGI IP28 (Indigo2 R10k)" 706 + select ARC_MEMORY 700 707 select ARC_PROMLIB 701 708 select FW_ARC 702 709 select FW_ARC64 ··· 720 725 select SGI_HAS_ZILOG 721 726 select SWAP_IO_SPACE 722 727 select SYS_HAS_CPU_R10000 723 - # 724 - # Disable EARLY_PRINTK for now since it leads to overwritten prom 725 - # memory during early boot on some machines. 726 - # 727 - # See http://www.linux-mips.org/cgi-bin/mesg.cgi?a=linux-mips&i=20091119164009.GA15038%40deprecation.cyrius.com 728 - # for a more details discussion 729 - # 730 - # select SYS_HAS_EARLY_PRINTK 728 + select SYS_HAS_EARLY_PRINTK 731 729 select SYS_SUPPORTS_64BIT_KERNEL 732 730 select SYS_SUPPORTS_BIG_ENDIAN 733 731 select MIPS_L1_CACHE_SHIFT_7
+9
arch/mips/fw/arc/memory.c
··· 158 158 } 159 159 } 160 160 161 + void __weak __init prom_cleanup(void) 162 + { 163 + } 164 + 161 165 void __init prom_free_prom_memory(void) 162 166 { 163 167 int i; ··· 173 169 free_init_pages("prom memory", 174 170 prom_mem_base[i], prom_mem_base[i] + prom_mem_size[i]); 175 171 } 172 + /* 173 + * at this point it isn't safe to call PROM functions 174 + * give platforms a way to do PROM cleanups 175 + */ 176 + prom_cleanup(); 176 177 }
+1
arch/mips/include/asm/bootinfo.h
··· 99 99 100 100 extern void prom_init(void); 101 101 extern void prom_free_prom_memory(void); 102 + extern void prom_cleanup(void); 102 103 103 104 extern void free_init_pages(const char *what, 104 105 unsigned long begin, unsigned long end);
-9
arch/mips/include/asm/mach-ip22/spaces.h
··· 12 12 13 13 #define PHYS_OFFSET _AC(0x08000000, UL) 14 14 15 - #ifdef CONFIG_64BIT 16 - 17 - #define CAC_BASE 0xffffffff80000000 18 - #define IO_BASE 0xffffffffa0000000 19 - #define UNCAC_BASE 0xffffffffa0000000 20 - #define MAP_BASE 0xc000000000000000 21 - 22 - #endif /* CONFIG_64BIT */ 23 - 24 15 #include <asm/mach-generic/spaces.h> 25 16 26 17 #endif /* __ASM_MACH_IP22_SPACES_H */
+21 -55
arch/mips/sgi-ip22/ip22-mc.c
··· 11 11 #include <linux/init.h> 12 12 #include <linux/export.h> 13 13 #include <linux/kernel.h> 14 + #include <linux/memblock.h> 14 15 #include <linux/spinlock.h> 15 16 16 17 #include <asm/io.h> ··· 41 40 return bank % 2 ? res & 0xffff : res >> 16; 42 41 } 43 42 44 - struct mem { 45 - unsigned long addr; 46 - unsigned long size; 47 - }; 48 - 43 + #if defined(CONFIG_SGI_IP28) || defined(CONFIG_32BIT) 44 + static void __init probe_memory(void) 45 + { 46 + /* prom detects all usable memory */ 47 + } 48 + #else 49 49 /* 50 - * Detect installed memory, do some sanity checks and notify kernel about it 50 + * Detect installed memory, which PROM misses 51 51 */ 52 52 static void __init probe_memory(void) 53 53 { 54 - int i, j, found, cnt = 0; 55 - struct mem bank[4]; 56 - struct mem space[2] = {{SGIMC_SEG0_BADDR, 0}, {SGIMC_SEG1_BADDR, 0}}; 54 + unsigned long addr, size; 55 + int i; 57 56 58 57 printk(KERN_INFO "MC: Probing memory configuration:\n"); 59 - for (i = 0; i < ARRAY_SIZE(bank); i++) { 58 + for (i = 0; i < 4; i++) { 60 59 unsigned int tmp = get_bank_config(i); 61 60 if (!(tmp & SGIMC_MCONFIG_BVALID)) 62 61 continue; 63 62 64 - bank[cnt].size = get_bank_size(tmp); 65 - bank[cnt].addr = get_bank_addr(tmp); 63 + size = get_bank_size(tmp); 64 + addr = get_bank_addr(tmp); 66 65 printk(KERN_INFO " bank%d: %3ldM @ %08lx\n", 67 - i, bank[cnt].size / 1024 / 1024, bank[cnt].addr); 68 - cnt++; 66 + i, size / 1024 / 1024, addr); 67 + 68 + if (addr >= SGIMC_SEG1_BADDR) 69 + memblock_add(addr, size); 69 70 } 70 - 71 - /* And you thought bubble sort is dead algorithm... */ 72 - do { 73 - unsigned long addr, size; 74 - 75 - found = 0; 76 - for (i = 1; i < cnt; i++) 77 - if (bank[i-1].addr > bank[i].addr) { 78 - addr = bank[i].addr; 79 - size = bank[i].size; 80 - bank[i].addr = bank[i-1].addr; 81 - bank[i].size = bank[i-1].size; 82 - bank[i-1].addr = addr; 83 - bank[i-1].size = size; 84 - found = 1; 85 - } 86 - } while (found); 87 - 88 - /* Figure out how are memory banks mapped into spaces */ 89 - for (i = 0; i < cnt; i++) { 90 - found = 0; 91 - for (j = 0; j < ARRAY_SIZE(space) && !found; j++) 92 - if (space[j].addr + space[j].size == bank[i].addr) { 93 - space[j].size += bank[i].size; 94 - found = 1; 95 - } 96 - /* There is either hole or overlapping memory */ 97 - if (!found) 98 - printk(KERN_CRIT "MC: Memory configuration mismatch " 99 - "(%08lx), expect Bus Error soon\n", 100 - bank[i].addr); 101 - } 102 - 103 - for (i = 0; i < ARRAY_SIZE(space); i++) 104 - if (space[i].size) 105 - add_memory_region(space[i].addr, space[i].size, 106 - BOOT_MEM_RAM); 107 71 } 72 + #endif 108 73 109 74 void __init sgimc_init(void) 110 75 { ··· 172 205 probe_memory(); 173 206 } 174 207 175 - void __init prom_meminit(void) {} 176 - void __init prom_free_prom_memory(void) 177 - { 178 208 #ifdef CONFIG_SGI_IP28 209 + void __init prom_cleanup(void) 210 + { 179 211 u32 mconfig1; 180 212 unsigned long flags; 181 213 spinlock_t lock; ··· 199 233 sgimc->mconfig1 = mconfig1; 200 234 iob(); 201 235 spin_unlock_irqrestore(&lock, flags); 202 - #endif 203 236 } 237 + #endif