linux/arch/mips/mti-malta/malta-memory.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * PROM library functions for acquiring/using memory descriptors given to
   7 * us from the YAMON.
   8 *
   9 * Copyright (C) 1999,2000,2012  MIPS Technologies, Inc.
  10 * All rights reserved.
  11 * Authors: Carsten Langgaard <carstenl@mips.com>
  12 *          Steven J. Hill <sjhill@mips.com>
  13 */
  14#include <linux/init.h>
  15#include <linux/bootmem.h>
  16#include <linux/string.h>
  17
  18#include <asm/bootinfo.h>
  19#include <asm/maar.h>
  20#include <asm/sections.h>
  21#include <asm/fw/fw.h>
  22
  23static fw_memblock_t mdesc[FW_MAX_MEMBLOCKS];
  24
  25/* determined physical memory size, not overridden by command line args  */
  26unsigned long physical_memsize = 0L;
  27
  28fw_memblock_t * __init fw_getmdesc(int eva)
  29{
  30        char *memsize_str, *ememsize_str = NULL, *ptr;
  31        unsigned long memsize = 0, ememsize = 0;
  32        static char cmdline[COMMAND_LINE_SIZE] __initdata;
  33        int tmp;
  34
  35        /* otherwise look in the environment */
  36
  37        memsize_str = fw_getenv("memsize");
  38        if (memsize_str) {
  39                tmp = kstrtoul(memsize_str, 0, &memsize);
  40                if (tmp)
  41                        pr_warn("Failed to read the 'memsize' env variable.\n");
  42        }
  43        if (eva) {
  44        /* Look for ememsize for EVA */
  45                ememsize_str = fw_getenv("ememsize");
  46                if (ememsize_str) {
  47                        tmp = kstrtoul(ememsize_str, 0, &ememsize);
  48                        if (tmp)
  49                                pr_warn("Failed to read the 'ememsize' env variable.\n");
  50                }
  51        }
  52        if (!memsize && !ememsize) {
  53                pr_warn("memsize not set in YAMON, set to default (32Mb)\n");
  54                physical_memsize = 0x02000000;
  55        } else {
  56                /* If ememsize is set, then set physical_memsize to that */
  57                physical_memsize = ememsize ? : memsize;
  58        }
  59
  60#ifdef CONFIG_CPU_BIG_ENDIAN
  61        /* SOC-it swaps, or perhaps doesn't swap, when DMA'ing the last
  62           word of physical memory */
  63        physical_memsize -= PAGE_SIZE;
  64#endif
  65
  66        /* Check the command line for a memsize directive that overrides
  67           the physical/default amount */
  68        strcpy(cmdline, arcs_cmdline);
  69        ptr = strstr(cmdline, "memsize=");
  70        if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
  71                ptr = strstr(ptr, " memsize=");
  72        /* And now look for ememsize */
  73        if (eva) {
  74                ptr = strstr(cmdline, "ememsize=");
  75                if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
  76                        ptr = strstr(ptr, " ememsize=");
  77        }
  78
  79        if (ptr)
  80                memsize = memparse(ptr + 8 + (eva ? 1 : 0), &ptr);
  81        else
  82                memsize = physical_memsize;
  83
  84        /* Last 64K for HIGHMEM arithmetics */
  85        if (memsize > 0x7fff0000)
  86                memsize = 0x7fff0000;
  87
  88        memset(mdesc, 0, sizeof(mdesc));
  89
  90        mdesc[0].type = fw_dontuse;
  91        mdesc[0].base = PHYS_OFFSET;
  92        mdesc[0].size = 0x00001000;
  93
  94        mdesc[1].type = fw_code;
  95        mdesc[1].base = mdesc[0].base + 0x00001000UL;
  96        mdesc[1].size = 0x000ef000;
  97
  98        /*
  99         * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the
 100         * south bridge and PCI access always forwarded to the ISA Bus and
 101         * BIOSCS# is always generated.
 102         * This mean that this area can't be used as DMA memory for PCI
 103         * devices.
 104         */
 105        mdesc[2].type = fw_dontuse;
 106        mdesc[2].base = mdesc[0].base + 0x000f0000UL;
 107        mdesc[2].size = 0x00010000;
 108
 109        mdesc[3].type = fw_dontuse;
 110        mdesc[3].base = mdesc[0].base + 0x00100000UL;
 111        mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) -
 112                0x00100000UL;
 113
 114        mdesc[4].type = fw_free;
 115        mdesc[4].base = mdesc[0].base + CPHYSADDR(PFN_ALIGN(&_end));
 116        mdesc[4].size = memsize - CPHYSADDR(mdesc[4].base);
 117
 118        return &mdesc[0];
 119}
 120
 121static void free_init_pages_eva_malta(void *begin, void *end)
 122{
 123        free_init_pages("unused kernel", __pa_symbol((unsigned long *)begin),
 124                        __pa_symbol((unsigned long *)end));
 125}
 126
 127static int __init fw_memtype_classify(unsigned int type)
 128{
 129        switch (type) {
 130        case fw_free:
 131                return BOOT_MEM_RAM;
 132        case fw_code:
 133                return BOOT_MEM_ROM_DATA;
 134        default:
 135                return BOOT_MEM_RESERVED;
 136        }
 137}
 138
 139void __init fw_meminit(void)
 140{
 141        fw_memblock_t *p;
 142
 143        p = fw_getmdesc(config_enabled(CONFIG_EVA));
 144        free_init_pages_eva = (config_enabled(CONFIG_EVA) ?
 145                               free_init_pages_eva_malta : NULL);
 146
 147        while (p->size) {
 148                long type;
 149                unsigned long base, size;
 150
 151                type = fw_memtype_classify(p->type);
 152                base = p->base;
 153                size = p->size;
 154
 155                add_memory_region(base, size, type);
 156                p++;
 157        }
 158}
 159
 160void __init prom_free_prom_memory(void)
 161{
 162        unsigned long addr;
 163        int i;
 164
 165        for (i = 0; i < boot_mem_map.nr_map; i++) {
 166                if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
 167                        continue;
 168
 169                addr = boot_mem_map.map[i].addr;
 170                free_init_pages("YAMON memory",
 171                                addr, addr + boot_mem_map.map[i].size);
 172        }
 173}
 174
 175unsigned platform_maar_init(unsigned num_pairs)
 176{
 177        phys_addr_t mem_end = (physical_memsize & ~0xffffull) - 1;
 178        struct maar_config cfg[] = {
 179                /* DRAM preceding I/O */
 180                { 0x00000000, 0x0fffffff, MIPS_MAAR_S },
 181
 182                /* DRAM following I/O */
 183                { 0x20000000, mem_end, MIPS_MAAR_S },
 184
 185                /* DRAM alias in upper half of physical */
 186                { 0x80000000, 0x80000000 + mem_end, MIPS_MAAR_S },
 187        };
 188        unsigned i, num_cfg = ARRAY_SIZE(cfg);
 189
 190        /* If DRAM fits before I/O, drop the region following it */
 191        if (physical_memsize <= 0x10000000) {
 192                num_cfg--;
 193                for (i = 1; i < num_cfg; i++)
 194                        cfg[i] = cfg[i + 1];
 195        }
 196
 197        return maar_config(cfg, num_cfg, num_pairs);
 198}
 199