|  | /* | 
|  | * Carsten Langgaard, carstenl@mips.com | 
|  | * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved. | 
|  | * Portions copyright (C) 2009 Cisco Systems, Inc. | 
|  | * | 
|  | *  This program is free software; you can distribute it and/or modify it | 
|  | *  under the terms of the GNU General Public License (Version 2) as | 
|  | *  published by the Free Software Foundation. | 
|  | * | 
|  | *  This program is distributed in the hope it will be useful, but WITHOUT | 
|  | *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
|  | *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | 
|  | *  for more details. | 
|  | * | 
|  | *  You should have received a copy of the GNU General Public License along | 
|  | *  with this program; if not, write to the Free Software Foundation, Inc., | 
|  | *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | 
|  | * | 
|  | * Apparently originally from arch/mips/malta-memory.c. Modified to work | 
|  | * with the PowerTV bootloader. | 
|  | */ | 
|  | #include <linux/init.h> | 
|  | #include <linux/mm.h> | 
|  | #include <linux/bootmem.h> | 
|  | #include <linux/pfn.h> | 
|  | #include <linux/string.h> | 
|  |  | 
|  | #include <asm/bootinfo.h> | 
|  | #include <asm/page.h> | 
|  | #include <asm/sections.h> | 
|  |  | 
|  | #include <asm/mips-boards/prom.h> | 
|  |  | 
|  | #include "init.h" | 
|  |  | 
|  | /* Memory constants */ | 
|  | #define KIBIBYTE(n)		((n) * 1024)	/* Number of kibibytes */ | 
|  | #define MEBIBYTE(n)		((n) * KIBIBYTE(1024)) /* Number of mebibytes */ | 
|  | #define DEFAULT_MEMSIZE		MEBIBYTE(256)	/* If no memsize provided */ | 
|  | #define LOW_MEM_MAX		MEBIBYTE(252)	/* Max usable low mem */ | 
|  | #define RES_BOOTLDR_MEMSIZE	MEBIBYTE(1)	/* Memory reserved for bldr */ | 
|  | #define BOOT_MEM_SIZE		KIBIBYTE(256)	/* Memory reserved for bldr */ | 
|  | #define PHYS_MEM_START		0x10000000	/* Start of physical memory */ | 
|  |  | 
|  | char __initdata cmdline[COMMAND_LINE_SIZE]; | 
|  |  | 
|  | void __init prom_meminit(void) | 
|  | { | 
|  | char *memsize_str; | 
|  | unsigned long memsize = 0; | 
|  | unsigned int physend; | 
|  | char *ptr; | 
|  | int low_mem; | 
|  | int high_mem; | 
|  |  | 
|  | /* Check the command line first for a memsize directive */ | 
|  | strcpy(cmdline, arcs_cmdline); | 
|  | ptr = strstr(cmdline, "memsize="); | 
|  | if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' ')) | 
|  | ptr = strstr(ptr, " memsize="); | 
|  |  | 
|  | if (ptr) { | 
|  | memsize = memparse(ptr + 8, &ptr); | 
|  | } else { | 
|  | /* otherwise look in the environment */ | 
|  | memsize_str = prom_getenv("memsize"); | 
|  |  | 
|  | if (memsize_str != NULL) { | 
|  | pr_info("prom memsize = %s\n", memsize_str); | 
|  | memsize = simple_strtol(memsize_str, NULL, 0); | 
|  | } | 
|  |  | 
|  | if (memsize == 0) { | 
|  | if (_prom_memsize != 0) { | 
|  | memsize = _prom_memsize; | 
|  | pr_info("_prom_memsize = 0x%lx\n", memsize); | 
|  | /* add in memory that the bootloader doesn't | 
|  | * report */ | 
|  | memsize += BOOT_MEM_SIZE; | 
|  | } else { | 
|  | memsize = DEFAULT_MEMSIZE; | 
|  | pr_info("Memsize not passed by bootloader, " | 
|  | "defaulting to 0x%lx\n", memsize); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | physend = PFN_ALIGN(&_end) - 0x80000000; | 
|  | if (memsize > LOW_MEM_MAX) { | 
|  | low_mem = LOW_MEM_MAX; | 
|  | high_mem = memsize - low_mem; | 
|  | } else { | 
|  | low_mem = memsize; | 
|  | high_mem = 0; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * TODO: We will use the hard code for memory configuration until | 
|  | * the bootloader releases their device tree to us. | 
|  | */ | 
|  | /* | 
|  | * Add the memory reserved for use by the bootloader to the | 
|  | * memory map. | 
|  | */ | 
|  | add_memory_region(PHYS_MEM_START, RES_BOOTLDR_MEMSIZE, | 
|  | BOOT_MEM_RESERVED); | 
|  | #ifdef CONFIG_HIGHMEM_256_128 | 
|  | /* | 
|  | * Add memory in low for general use by the kernel and its friends | 
|  | * (like drivers, applications, etc). | 
|  | */ | 
|  | add_memory_region(PHYS_MEM_START + RES_BOOTLDR_MEMSIZE, | 
|  | LOW_MEM_MAX - RES_BOOTLDR_MEMSIZE, BOOT_MEM_RAM); | 
|  | /* | 
|  | * Add the memory reserved for reset vector. | 
|  | */ | 
|  | add_memory_region(0x1fc00000, MEBIBYTE(4), BOOT_MEM_RESERVED); | 
|  | /* | 
|  | * Add the memory reserved. | 
|  | */ | 
|  | add_memory_region(0x20000000, MEBIBYTE(1024 + 75), BOOT_MEM_RESERVED); | 
|  | /* | 
|  | * Add memory in high for general use by the kernel and its friends | 
|  | * (like drivers, applications, etc). | 
|  | * | 
|  | * 75MB is reserved for devices which are using the memory in high. | 
|  | */ | 
|  | add_memory_region(0x60000000 + MEBIBYTE(75), MEBIBYTE(128 - 75), | 
|  | BOOT_MEM_RAM); | 
|  | #elif defined CONFIG_HIGHMEM_128_128 | 
|  | /* | 
|  | * Add memory in low for general use by the kernel and its friends | 
|  | * (like drivers, applications, etc). | 
|  | */ | 
|  | add_memory_region(PHYS_MEM_START + RES_BOOTLDR_MEMSIZE, | 
|  | MEBIBYTE(128) - RES_BOOTLDR_MEMSIZE, BOOT_MEM_RAM); | 
|  | /* | 
|  | * Add the memory reserved. | 
|  | */ | 
|  | add_memory_region(PHYS_MEM_START + MEBIBYTE(128), | 
|  | MEBIBYTE(128 + 1024 + 75), BOOT_MEM_RESERVED); | 
|  | /* | 
|  | * Add memory in high for general use by the kernel and its friends | 
|  | * (like drivers, applications, etc). | 
|  | * | 
|  | * 75MB is reserved for devices which are using the memory in high. | 
|  | */ | 
|  | add_memory_region(0x60000000 + MEBIBYTE(75), MEBIBYTE(128 - 75), | 
|  | BOOT_MEM_RAM); | 
|  | #else | 
|  | /* Add low memory regions for either: | 
|  | *   - no-highmemory configuration case -OR- | 
|  | *   - highmemory "HIGHMEM_LOWBANK_ONLY" case | 
|  | */ | 
|  | /* | 
|  | * Add memory for general use by the kernel and its friends | 
|  | * (like drivers, applications, etc). | 
|  | */ | 
|  | add_memory_region(PHYS_MEM_START + RES_BOOTLDR_MEMSIZE, | 
|  | low_mem - RES_BOOTLDR_MEMSIZE, BOOT_MEM_RAM); | 
|  | /* | 
|  | * Add the memory reserved for reset vector. | 
|  | */ | 
|  | add_memory_region(0x1fc00000, MEBIBYTE(4), BOOT_MEM_RESERVED); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | void __init prom_free_prom_memory(void) | 
|  | { | 
|  | unsigned long addr; | 
|  | int i; | 
|  |  | 
|  | for (i = 0; i < boot_mem_map.nr_map; i++) { | 
|  | if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) | 
|  | continue; | 
|  |  | 
|  | addr = boot_mem_map.map[i].addr; | 
|  | free_init_pages("prom memory", | 
|  | addr, addr + boot_mem_map.map[i].size); | 
|  | } | 
|  | } |