11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * License. See the file "COPYING" in the main directory of this archive 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for more details. 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1995 Linus Torvalds 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1995 Waldorf Electronics 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 01, 02, 03 Ralf Baechle 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1996 Stoned Elipot 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1999 Silicon Graphics, Inc. 1120d60d9973c3b441902b0a3f4f6f7e7ade08f77dMaciej W. Rozycki * Copyright (C) 2000, 2001, 2002, 2007 Maciej W. Rozycki 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 1573bc256d47a23272ce1dd50b4de64a0ff23d01f1Paul Gortmaker#include <linux/export.h> 16894673ee6122a3ce1958e1fe096901ba5356a96bJon Smirl#include <linux/screen_info.h> 179d15ffc824a90842b16592f3a960836841bd6c58Tejun Heo#include <linux/memblock.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bootmem.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/initrd.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/root_dev.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/highmem.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/console.h> 2322a9835c350782a5c3257343713932af3ac92ee0Dave Hansen#include <linux/pfn.h> 246312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto#include <linux/debugfs.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/addrspace.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/bootinfo.h> 2820d60d9973c3b441902b0a3f4f6f7e7ade08f77dMaciej W. Rozycki#include <asm/bugs.h> 29ec74e361f1e71a2498e48b62abdc4bd8d2423354Ralf Baechle#include <asm/cache.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/cpu.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/sections.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/setup.h> 3387353d8ac39c52784da605ecbe965ecdfad609adRalf Baechle#include <asm/smp-ops.h> 34f2ffa5ab74f4dfd598860f96ca37a71c4d0a28a8Dezhong Diao#include <asm/prom.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36ec74e361f1e71a2498e48b62abdc4bd8d2423354Ralf Baechlestruct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly; 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(cpu_data); 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_VT 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct screen_info screen_info; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Despite it's name this variable is even if we don't have PCI 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned int PCI_DMA_BUS_IS_PHYS; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(PCI_DMA_BUS_IS_PHYS); 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Setup information 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * These are initialized so they are in the .data section 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 56ec74e361f1e71a2498e48b62abdc4bd8d2423354Ralf Baechleunsigned long mips_machtype __read_mostly = MACH_UNKNOWN; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(mips_machtype); 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct boot_mem_map boot_mem_map; 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 626acc7d485c24c00e111c61b2e6dff9180faebcaeDmitri Vorobievstatic char __initdata command_line[COMMAND_LINE_SIZE]; 636acc7d485c24c00e111c61b2e6dff9180faebcaeDmitri Vorobievchar __initdata arcs_cmdline[COMMAND_LINE_SIZE]; 646acc7d485c24c00e111c61b2e6dff9180faebcaeDmitri Vorobiev 656acc7d485c24c00e111c61b2e6dff9180faebcaeDmitri Vorobiev#ifdef CONFIG_CMDLINE_BOOL 666acc7d485c24c00e111c61b2e6dff9180faebcaeDmitri Vorobievstatic char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE; 676acc7d485c24c00e111c61b2e6dff9180faebcaeDmitri Vorobiev#endif 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mips_io_port_base is the begin of the address space to which x86 style 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * I/O ports are mapped. 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 731befdd5536e1500371f7f884d0f0ae528a519333David Daneyconst unsigned long mips_io_port_base = -1; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(mips_io_port_base); 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct resource code_resource = { .name = "Kernel code", }; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct resource data_resource = { .name = "Kernel data", }; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init add_memory_region(phys_t start, phys_t size, long type) 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int x = boot_mem_map.nr_map; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct boot_mem_map_entry *prev = boot_mem_map.map + x - 1; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 84b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu /* Sanity check */ 85b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (start + size < start) { 86a64ae7a2256b56bbd2830749c580fa533b69758cMike Crowe pr_warning("Trying to add an invalid memory region, skipped\n"); 87b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu return; 88b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu } 89b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Try to merge with previous entry if any. This is far less than 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * perfect but is sufficient for most real world cases. 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (x && prev->addr + prev->size == start && prev->type == type) { 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev->size += size; 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (x == BOOT_MEM_MAP_MAX) { 100a64ae7a2256b56bbd2830749c580fa533b69758cMike Crowe pr_err("Ooops! Too many entries in the memory map!\n"); 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds boot_mem_map.map[x].addr = start; 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds boot_mem_map.map[x].size = size; 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds boot_mem_map.map[x].type = type; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds boot_mem_map.nr_map++; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init print_memory_map(void) 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const int field = 2 * sizeof(unsigned long); 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < boot_mem_map.nr_map; i++) { 116a64ae7a2256b56bbd2830749c580fa533b69758cMike Crowe printk(KERN_INFO " memory: %0*Lx @ %0*Lx ", 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds field, (unsigned long long) boot_mem_map.map[i].size, 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds field, (unsigned long long) boot_mem_map.map[i].addr); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (boot_mem_map.map[i].type) { 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BOOT_MEM_RAM: 122a64ae7a2256b56bbd2830749c580fa533b69758cMike Crowe printk(KERN_CONT "(usable)\n"); 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12443064c0c8ee2ada8edd421520c633584d648e100David Daney case BOOT_MEM_INIT_RAM: 12543064c0c8ee2ada8edd421520c633584d648e100David Daney printk(KERN_CONT "(usable after init)\n"); 12643064c0c8ee2ada8edd421520c633584d648e100David Daney break; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BOOT_MEM_ROM_DATA: 128a64ae7a2256b56bbd2830749c580fa533b69758cMike Crowe printk(KERN_CONT "(ROM data)\n"); 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BOOT_MEM_RESERVED: 131a64ae7a2256b56bbd2830749c580fa533b69758cMike Crowe printk(KERN_CONT "(reserved)\n"); 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 134a64ae7a2256b56bbd2830749c580fa533b69758cMike Crowe printk(KERN_CONT "type %lu\n", boot_mem_map.map[i].type); 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 140d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu/* 141d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu * Manage initrd 142d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu */ 143d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#ifdef CONFIG_BLK_DEV_INITRD 144d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 145a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huustatic int __init rd_start_early(char *p) 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 147a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu unsigned long start = memparse(p, &p); 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 149875d43e72b5bf22161a81de7554f88eccf8a51aeRalf Baechle#ifdef CONFIG_64BIT 150a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu /* Guess if the sign extension was forgotten by bootloader */ 151a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu if (start < XKPHYS) 152a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu start = (int)start; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 154a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu initrd_start = start; 155a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu initrd_end += start; 156a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu return 0; 157a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu} 158a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huuearly_param("rd_start", rd_start_early); 159a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu 160a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huustatic int __init rd_size_early(char *p) 161a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu{ 162a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu initrd_end += memparse(p, &p); 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 165a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huuearly_param("rd_size", rd_size_early); 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 167a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu/* it returns the next free pfn after initrd */ 168d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huustatic unsigned long __init init_initrd(void) 169d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu{ 170a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu unsigned long end; 171d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 172d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu /* 173a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu * Board specific code or command line parser should have 174a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu * already set up initrd_start and initrd_end. In these cases 175a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu * perfom sanity checks and use them if all looks good. 176d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu */ 17732028f1f7bce32e72183129dc55fc23656e7081cRalf Baechle if (!initrd_start || initrd_end <= initrd_start) 178a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu goto disable; 179a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu 180a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu if (initrd_start & ~PAGE_MASK) { 181a64ae7a2256b56bbd2830749c580fa533b69758cMike Crowe pr_err("initrd start must be page aligned\n"); 182a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu goto disable; 183d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu } 184a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu if (initrd_start < PAGE_OFFSET) { 185a64ae7a2256b56bbd2830749c580fa533b69758cMike Crowe pr_err("initrd start < PAGE_OFFSET\n"); 186a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu goto disable; 187a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu } 188a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu 189a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu /* 190a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu * Sanitize initrd addresses. For example firmware 191a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu * can't guess if they need to pass them through 192a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu * 64-bits values if the kernel has been built in pure 193a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu * 32-bit. We need also to switch from KSEG0 to XKPHYS 194a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu * addresses now, so the code can now safely use __pa(). 195a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu */ 196a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu end = __pa(initrd_end); 197a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu initrd_end = (unsigned long)__va(end); 198a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu initrd_start = (unsigned long)__va(__pa(initrd_start)); 199a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu 200a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu ROOT_DEV = Root_RAM0; 201a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu return PFN_UP(end); 202a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huudisable: 203a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu initrd_start = 0; 204a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu initrd_end = 0; 205a7837b76b6de932c31d0b7c71176ca8d1213a3ceFranck Bui-Huu return 0; 206d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu} 207d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 208d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huustatic void __init finalize_initrd(void) 209d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu{ 210d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu unsigned long size = initrd_end - initrd_start; 211d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 212d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu if (size == 0) { 213d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu printk(KERN_INFO "Initrd not found or empty"); 214d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu goto disable; 215d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu } 216d4df6d4e7a66b7a9bd57f5dc7d80d6b55dc12dbbFranck Bui-Huu if (__pa(initrd_end) > PFN_PHYS(max_low_pfn)) { 217a64ae7a2256b56bbd2830749c580fa533b69758cMike Crowe printk(KERN_ERR "Initrd extends beyond end of memory"); 218d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu goto disable; 219d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu } 220d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 22172a7fe3967dbf86cb34e24fbf1d957fe24d2f246Bernhard Walle reserve_bootmem(__pa(initrd_start), size, BOOTMEM_DEFAULT); 222d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu initrd_below_start_ok = 1; 223d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 224a64ae7a2256b56bbd2830749c580fa533b69758cMike Crowe pr_info("Initial ramdisk at: 0x%lx (%lu bytes)\n", 225a64ae7a2256b56bbd2830749c580fa533b69758cMike Crowe initrd_start, size); 226d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu return; 227d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huudisable: 228a64ae7a2256b56bbd2830749c580fa533b69758cMike Crowe printk(KERN_CONT " - disabling initrd\n"); 229d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu initrd_start = 0; 230d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu initrd_end = 0; 231d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu} 232d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 233d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#else /* !CONFIG_BLK_DEV_INITRD */ 234d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 2359ba126cfbf505f4d5b39ed294cedd241321c7a91Ralf Baechlestatic unsigned long __init init_initrd(void) 2369ba126cfbf505f4d5b39ed294cedd241321c7a91Ralf Baechle{ 2379ba126cfbf505f4d5b39ed294cedd241321c7a91Ralf Baechle return 0; 2389ba126cfbf505f4d5b39ed294cedd241321c7a91Ralf Baechle} 2399ba126cfbf505f4d5b39ed294cedd241321c7a91Ralf Baechle 240d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#define finalize_initrd() do {} while (0) 241d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 242d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#endif 243d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 244b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu/* 245b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * Initialize the bootmem allocator. It also setup initrd related data 246b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * if needed. 247b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu */ 248d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#ifdef CONFIG_SGI_IP27 249d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 250b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huustatic void __init bootmem_init(void) 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 252d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu init_initrd(); 253d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu finalize_initrd(); 254d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu} 255d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 256d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#else /* !CONFIG_SGI_IP27 */ 257d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 258d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huustatic void __init bootmem_init(void) 259d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu{ 260e452e94e21e8f4a3c2ff045b301ca21c1f6d03bfAtsushi Nemoto unsigned long reserved_end; 261db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu unsigned long mapstart = ~0UL; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long bootmap_size; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 266d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu * Init any data related to initrd. It's a nop if INITRD is 267d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu * not selected. Once that done we can determine the low bound 268d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu * of usable memory. 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 27012e22e8e60add9e1ccd61509ab7fd6fc1c214c52Ralf Baechle reserved_end = max(init_initrd(), 27112e22e8e60add9e1ccd61509ab7fd6fc1c214c52Ralf Baechle (unsigned long) PFN_UP(__pa_symbol(&_end))); 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 273b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu /* 274db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu * max_low_pfn is not a number of pages. The number of pages 275db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu * of the system is given by 'max_low_pfn - min_low_pfn'. 276db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu */ 277db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu min_low_pfn = ~0UL; 278db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu max_low_pfn = 0; 279db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu 280db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu /* 281b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * Find the highest page frame number we have available. 282b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu */ 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < boot_mem_map.nr_map; i++) { 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long start, end; 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (boot_mem_map.map[i].type != BOOT_MEM_RAM) 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = PFN_UP(boot_mem_map.map[i].addr); 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = PFN_DOWN(boot_mem_map.map[i].addr 291b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu + boot_mem_map.map[i].size); 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 293db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu if (end > max_low_pfn) 294db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu max_low_pfn = end; 295db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu if (start < min_low_pfn) 296db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu min_low_pfn = start; 297b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (end <= reserved_end) 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 299b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (start >= mapstart) 300b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu continue; 301b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu mapstart = max(reserved_end, start); 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 304db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu if (min_low_pfn >= max_low_pfn) 305db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu panic("Incorrect memory mapping !!!"); 3066f284a2ce7b8bc49cb8455b1763357897a899abbFranck Bui-Huu if (min_low_pfn > ARCH_PFN_OFFSET) { 307a64ae7a2256b56bbd2830749c580fa533b69758cMike Crowe pr_info("Wasting %lu bytes for tracking %lu unused pages\n", 308a64ae7a2256b56bbd2830749c580fa533b69758cMike Crowe (min_low_pfn - ARCH_PFN_OFFSET) * sizeof(struct page), 309a64ae7a2256b56bbd2830749c580fa533b69758cMike Crowe min_low_pfn - ARCH_PFN_OFFSET); 3106f284a2ce7b8bc49cb8455b1763357897a899abbFranck Bui-Huu } else if (min_low_pfn < ARCH_PFN_OFFSET) { 311a64ae7a2256b56bbd2830749c580fa533b69758cMike Crowe pr_info("%lu free pages won't be used\n", 312a64ae7a2256b56bbd2830749c580fa533b69758cMike Crowe ARCH_PFN_OFFSET - min_low_pfn); 313db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu } 3146f284a2ce7b8bc49cb8455b1763357897a899abbFranck Bui-Huu min_low_pfn = ARCH_PFN_OFFSET; 315db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Determine low and high memory ranges 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 319dc3bf3532bf7240cf117b8ecf3d16526810eba6aRalf Baechle max_pfn = max_low_pfn; 320db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu if (max_low_pfn > PFN_DOWN(HIGHMEM_START)) { 321b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu#ifdef CONFIG_HIGHMEM 322b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu highstart_pfn = PFN_DOWN(HIGHMEM_START); 323db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu highend_pfn = max_low_pfn; 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 325db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu max_low_pfn = PFN_DOWN(HIGHMEM_START); 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 329b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * Initialize the boot-time allocator with low memory only. 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 331db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu bootmap_size = init_bootmem_node(NODE_DATA(0), mapstart, 332db84dc61552ae0d198a8133d28b80c3838930ba8Franck Bui-Huu min_low_pfn, max_low_pfn); 333cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle 334cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle 335cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle for (i = 0; i < boot_mem_map.nr_map; i++) { 336cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle unsigned long start, end; 337cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle 338cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle start = PFN_UP(boot_mem_map.map[i].addr); 339cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle end = PFN_DOWN(boot_mem_map.map[i].addr 340cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle + boot_mem_map.map[i].size); 341cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle 342e452e94e21e8f4a3c2ff045b301ca21c1f6d03bfAtsushi Nemoto if (start <= min_low_pfn) 343e452e94e21e8f4a3c2ff045b301ca21c1f6d03bfAtsushi Nemoto start = min_low_pfn; 344cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle if (start >= end) 345cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle continue; 346cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle 347cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle#ifndef CONFIG_HIGHMEM 348cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle if (end > max_low_pfn) 349cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle end = max_low_pfn; 350cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle 351cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle /* 352cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle * ... finally, is the area going away? 353cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle */ 354cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle if (end <= start) 355cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle continue; 356cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle#endif 357cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle 3589d15ffc824a90842b16592f3a960836841bd6c58Tejun Heo memblock_add_node(PFN_PHYS(start), PFN_PHYS(end - start), 0); 359cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle } 360cce335ae47e231398269fb05fa48e0e9cbf289e0Ralf Baechle 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Register fully available low RAM pages with the bootmem allocator. 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < boot_mem_map.nr_map; i++) { 365b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu unsigned long start, end, size; 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36743064c0c8ee2ada8edd421520c633584d648e100David Daney start = PFN_UP(boot_mem_map.map[i].addr); 36843064c0c8ee2ada8edd421520c633584d648e100David Daney end = PFN_DOWN(boot_mem_map.map[i].addr 36943064c0c8ee2ada8edd421520c633584d648e100David Daney + boot_mem_map.map[i].size); 37043064c0c8ee2ada8edd421520c633584d648e100David Daney 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Reserve usable memory. 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 37443064c0c8ee2ada8edd421520c633584d648e100David Daney switch (boot_mem_map.map[i].type) { 37543064c0c8ee2ada8edd421520c633584d648e100David Daney case BOOT_MEM_RAM: 37643064c0c8ee2ada8edd421520c633584d648e100David Daney break; 37743064c0c8ee2ada8edd421520c633584d648e100David Daney case BOOT_MEM_INIT_RAM: 37843064c0c8ee2ada8edd421520c633584d648e100David Daney memory_present(0, start, end); 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 38043064c0c8ee2ada8edd421520c633584d648e100David Daney default: 38143064c0c8ee2ada8edd421520c633584d648e100David Daney /* Not usable memory */ 38243064c0c8ee2ada8edd421520c633584d648e100David Daney continue; 38343064c0c8ee2ada8edd421520c633584d648e100David Daney } 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 386b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * We are rounding up the start address of usable memory 387b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * and at the end of the usable range downwards. 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 389b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (start >= max_low_pfn) 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 391b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (start < reserved_end) 392b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu start = reserved_end; 393b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (end > max_low_pfn) 394b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu end = max_low_pfn; 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 397b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * ... finally, is the area going away? 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 399b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu if (end <= start) 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 401b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu size = end - start; 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Register lowmem ranges */ 404b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu free_bootmem(PFN_PHYS(start), size << PAGE_SHIFT); 405b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu memory_present(0, start, end); 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 408b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu /* 409b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu * Reserve the bootmap memory. 410b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu */ 41172a7fe3967dbf86cb34e24fbf1d957fe24d2f246Bernhard Walle reserve_bootmem(PFN_PHYS(mapstart), bootmap_size, BOOTMEM_DEFAULT); 412b6f1f0dea1469e0c956eb89399916d60dd2a3808Franck Bui-Huu 413d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu /* 414d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu * Reserve initrd memory if needed. 415d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu */ 416d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu finalize_initrd(); 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 419d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu#endif /* CONFIG_SGI_IP27 */ 420d2043ca8484d434201816267c0e23c5999df6cfdFranck Bui-Huu 4212925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle/* 422603e82edf78ad6c0f836023f8db585620211947bJoe Perches * arch_mem_init - initialize memory management subsystem 4232925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * 4242925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * o plat_mem_setup() detects the memory configuration and will record detected 4252925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * memory areas using add_memory_region. 4262925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * 4272925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * At this stage the memory configuration of the system is known to the 428603e82edf78ad6c0f836023f8db585620211947bJoe Perches * kernel but generic memory management system is still entirely uninitialized. 4292925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * 4302925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * o bootmem_init() 4312925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * o sparse_init() 4322925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * o paging_init() 4332925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * 4342925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * At this stage the bootmem allocator is ready to use. 4352925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * 4362925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * NOTE: historically plat_mem_setup did the entire platform initialization. 4372925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * This was rather impractical because it meant plat_mem_setup had to 4382925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * get away without any kind of memory allocator. To keep old code from 4392925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * breaking plat_setup was just renamed to plat_setup and a second platform 4402925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle * initialization hook for anything else was introduced. 4412925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle */ 4422925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle 443982f6ffeeed5ef6104cfd72e517ff9e7a9270fdaRalf Baechlestatic int usermem __initdata; 444a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu 445a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huustatic int __init early_parse_mem(char *p) 446a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu{ 447a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu unsigned long start, size; 448a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu 449a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu /* 450a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu * If a user specifies memory size, we 451a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu * blow away any automatically generated 452a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu * size. 453a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu */ 454a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu if (usermem == 0) { 455a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu boot_mem_map.nr_map = 0; 456a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu usermem = 1; 457a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu } 458a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu start = 0; 459a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu size = memparse(p, &p); 460a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu if (*p == '@') 461a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu start = memparse(p + 1, &p); 462a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu 463a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu add_memory_region(start, size, BOOT_MEM_RAM); 464a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu return 0; 465a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu} 466a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huuearly_param("mem", early_parse_mem); 4672925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle 4682925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechlestatic void __init arch_mem_init(char **cmdline_p) 4692925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle{ 47043064c0c8ee2ada8edd421520c633584d648e100David Daney phys_t init_mem, init_end, init_size; 47143064c0c8ee2ada8edd421520c633584d648e100David Daney 472a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu extern void plat_mem_setup(void); 473a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu 4742925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle /* call board setup routine */ 4752925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle plat_mem_setup(); 4762925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle 47743064c0c8ee2ada8edd421520c633584d648e100David Daney init_mem = PFN_UP(__pa_symbol(&__init_begin)) << PAGE_SHIFT; 47843064c0c8ee2ada8edd421520c633584d648e100David Daney init_end = PFN_DOWN(__pa_symbol(&__init_end)) << PAGE_SHIFT; 47943064c0c8ee2ada8edd421520c633584d648e100David Daney init_size = init_end - init_mem; 48043064c0c8ee2ada8edd421520c633584d648e100David Daney if (init_size) { 48143064c0c8ee2ada8edd421520c633584d648e100David Daney /* Make sure it is in the boot_mem_map */ 48243064c0c8ee2ada8edd421520c633584d648e100David Daney int i, found; 48343064c0c8ee2ada8edd421520c633584d648e100David Daney found = 0; 48443064c0c8ee2ada8edd421520c633584d648e100David Daney for (i = 0; i < boot_mem_map.nr_map; i++) { 48543064c0c8ee2ada8edd421520c633584d648e100David Daney if (init_mem >= boot_mem_map.map[i].addr && 48643064c0c8ee2ada8edd421520c633584d648e100David Daney init_mem < (boot_mem_map.map[i].addr + 48743064c0c8ee2ada8edd421520c633584d648e100David Daney boot_mem_map.map[i].size)) { 48843064c0c8ee2ada8edd421520c633584d648e100David Daney found = 1; 48943064c0c8ee2ada8edd421520c633584d648e100David Daney break; 49043064c0c8ee2ada8edd421520c633584d648e100David Daney } 49143064c0c8ee2ada8edd421520c633584d648e100David Daney } 49243064c0c8ee2ada8edd421520c633584d648e100David Daney if (!found) 49343064c0c8ee2ada8edd421520c633584d648e100David Daney add_memory_region(init_mem, init_size, 49443064c0c8ee2ada8edd421520c633584d648e100David Daney BOOT_MEM_INIT_RAM); 49543064c0c8ee2ada8edd421520c633584d648e100David Daney } 49643064c0c8ee2ada8edd421520c633584d648e100David Daney 497a64ae7a2256b56bbd2830749c580fa533b69758cMike Crowe pr_info("Determined physical RAM map:\n"); 498a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu print_memory_map(); 499a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu 5006acc7d485c24c00e111c61b2e6dff9180faebcaeDmitri Vorobiev#ifdef CONFIG_CMDLINE_BOOL 5016acc7d485c24c00e111c61b2e6dff9180faebcaeDmitri Vorobiev#ifdef CONFIG_CMDLINE_OVERRIDE 5026acc7d485c24c00e111c61b2e6dff9180faebcaeDmitri Vorobiev strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); 5036acc7d485c24c00e111c61b2e6dff9180faebcaeDmitri Vorobiev#else 5046acc7d485c24c00e111c61b2e6dff9180faebcaeDmitri Vorobiev if (builtin_cmdline[0]) { 5056acc7d485c24c00e111c61b2e6dff9180faebcaeDmitri Vorobiev strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE); 5066acc7d485c24c00e111c61b2e6dff9180faebcaeDmitri Vorobiev strlcat(arcs_cmdline, builtin_cmdline, COMMAND_LINE_SIZE); 5076acc7d485c24c00e111c61b2e6dff9180faebcaeDmitri Vorobiev } 5086acc7d485c24c00e111c61b2e6dff9180faebcaeDmitri Vorobiev strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE); 5096acc7d485c24c00e111c61b2e6dff9180faebcaeDmitri Vorobiev#endif 5106acc7d485c24c00e111c61b2e6dff9180faebcaeDmitri Vorobiev#else 5116acc7d485c24c00e111c61b2e6dff9180faebcaeDmitri Vorobiev strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE); 5126acc7d485c24c00e111c61b2e6dff9180faebcaeDmitri Vorobiev#endif 5136acc7d485c24c00e111c61b2e6dff9180faebcaeDmitri Vorobiev strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); 5142925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle 5152925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle *cmdline_p = command_line; 5162925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle 517a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu parse_early_param(); 518a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu 519a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu if (usermem) { 520a64ae7a2256b56bbd2830749c580fa533b69758cMike Crowe pr_info("User-defined physical RAM map:\n"); 521a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu print_memory_map(); 522a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu } 523a09fc446fb6d541281d9559fe7215d7c0d3cc9ceFranck Bui-Huu 5242925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle bootmem_init(); 525f2ffa5ab74f4dfd598860f96ca37a71c4d0a28a8Dezhong Diao device_tree_init(); 5262925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle sparse_init(); 527ee71b7d2f834d5e4b3a43001b2fa88743ed71a2cDavid Daney plat_swiotlb_setup(); 5282925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle paging_init(); 5292925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle} 5302925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle 5318df32c636e785069ba7d223ceb9b72c182902295Franck Bui-Huustatic void __init resource_init(void) 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5356adb5fe7020e8f99d27da932157ea27325df9263Ralf Baechle if (UNCAC_BASE != IO_BASE) 5366adb5fe7020e8f99d27da932157ea27325df9263Ralf Baechle return; 5376adb5fe7020e8f99d27da932157ea27325df9263Ralf Baechle 538f5bffe3a9bcd6e5319b5fd3a8109625f8638425aFranck Bui-Huu code_resource.start = __pa_symbol(&_text); 539f5bffe3a9bcd6e5319b5fd3a8109625f8638425aFranck Bui-Huu code_resource.end = __pa_symbol(&_etext) - 1; 540f5bffe3a9bcd6e5319b5fd3a8109625f8638425aFranck Bui-Huu data_resource.start = __pa_symbol(&_etext); 541f5bffe3a9bcd6e5319b5fd3a8109625f8638425aFranck Bui-Huu data_resource.end = __pa_symbol(&_edata) - 1; 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Request address space for all standard RAM. 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < boot_mem_map.nr_map; i++) { 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct resource *res; 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long start, end; 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = boot_mem_map.map[i].addr; 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = boot_mem_map.map[i].addr + boot_mem_map.map[i].size - 1; 5521c6fd44d7ed3d105b2eaa29d72b415ca51e40d32Franck Bui-Huu if (start >= HIGHMEM_START) 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 5541c6fd44d7ed3d105b2eaa29d72b415ca51e40d32Franck Bui-Huu if (end >= HIGHMEM_START) 5551c6fd44d7ed3d105b2eaa29d72b415ca51e40d32Franck Bui-Huu end = HIGHMEM_START - 1; 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res = alloc_bootmem(sizeof(struct resource)); 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (boot_mem_map.map[i].type) { 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BOOT_MEM_RAM: 56043064c0c8ee2ada8edd421520c633584d648e100David Daney case BOOT_MEM_INIT_RAM: 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BOOT_MEM_ROM_DATA: 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->name = "System RAM"; 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BOOT_MEM_RESERVED: 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->name = "reserved"; 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->start = start; 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->end = end; 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds request_resource(&iomem_resource, res); 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We don't know which RAM region contains kernel data, 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * so we try it repeatedly and let the resource manager 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * test it. 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds request_resource(res, &code_resource); 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds request_resource(res, &data_resource); 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init setup_arch(char **cmdline_p) 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpu_probe(); 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prom_init(); 58936a885306fdf7bb557c773309c993bfb2d0d693cRalf Baechle 59036a885306fdf7bb557c773309c993bfb2d0d693cRalf Baechle#ifdef CONFIG_EARLY_PRINTK 59107cdb78436d52416a582e645b9afb6e26f986bc9Dmitri Vorobiev setup_early_printk(); 59236a885306fdf7bb557c773309c993bfb2d0d693cRalf Baechle#endif 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpu_report(); 59420d60d9973c3b441902b0a3f4f6f7e7ade08f77dMaciej W. Rozycki check_bugs_early(); 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(CONFIG_VT) 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(CONFIG_VGA_CONSOLE) 598e0daad449c5195fa4552c60392eeee4e5c58d31cRalf Baechle conswitchp = &vga_con; 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#elif defined(CONFIG_DUMMY_CONSOLE) 600e0daad449c5195fa4552c60392eeee4e5c58d31cRalf Baechle conswitchp = &dummy_con; 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6042925aba4223f4532e85f0c6f64584b3e0b2849c3Ralf Baechle arch_mem_init(cmdline_p); 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resource_init(); 6079b6695a8adfe0916e81ddd810a5b9db3eb8b0e46Ralf Baechle plat_smp_setup(); 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 61069a6c312e5ebb2e929ceb67e6246e2d9314f1d29Atsushi Nemotounsigned long kernelsp[NR_CPUS]; 61169a6c312e5ebb2e929ceb67e6246e2d9314f1d29Atsushi Nemotounsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3; 6126312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto 6136312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto#ifdef CONFIG_DEBUG_FS 6146312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemotostruct dentry *mips_debugfs_dir; 6156312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemotostatic int __init debugfs_mips(void) 6166312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto{ 6176312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto struct dentry *d; 6186312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto 6196312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto d = debugfs_create_dir("mips", NULL); 620b517531ce53794f2a2eae1fff1d1216b9db4da9fZhaolei if (!d) 621b517531ce53794f2a2eae1fff1d1216b9db4da9fZhaolei return -ENOMEM; 6226312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto mips_debugfs_dir = d; 6236312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto return 0; 6246312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto} 6256312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemotoarch_initcall(debugfs_mips); 6266312e0ee45236b6882cd26b2ccc167b1b91646fcAtsushi Nemoto#endif 627