linux/arch/mips/fw/arc/memory.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * memory.c: PROM library functions for acquiring/using memory descriptors
   4 *           given to us from the ARCS firmware.
   5 *
   6 * Copyright (C) 1996 by David S. Miller
   7 * Copyright (C) 1999, 2000, 2001 by Ralf Baechle
   8 * Copyright (C) 1999, 2000 by Silicon Graphics, Inc.
   9 *
  10 * PROM library functions for acquiring/using memory descriptors given to us
  11 * from the ARCS firmware.  This is only used when CONFIG_ARC_MEMORY is set
  12 * because on some machines like SGI IP27 the ARC memory configuration data
  13 * completely bogus and alternate easier to use mechanisms are available.
  14 */
  15#include <linux/init.h>
  16#include <linux/kernel.h>
  17#include <linux/types.h>
  18#include <linux/sched.h>
  19#include <linux/mm.h>
  20#include <linux/memblock.h>
  21#include <linux/swap.h>
  22
  23#include <asm/sgialib.h>
  24#include <asm/page.h>
  25#include <asm/bootinfo.h>
  26
  27#undef DEBUG
  28
  29#define MAX_PROM_MEM 5
  30static phys_addr_t prom_mem_base[MAX_PROM_MEM] __initdata;
  31static phys_addr_t prom_mem_size[MAX_PROM_MEM] __initdata;
  32static unsigned int nr_prom_mem __initdata;
  33
  34/*
  35 * For ARC firmware memory functions the unit of meassuring memory is always
  36 * a 4k page of memory
  37 */
  38#define ARC_PAGE_SHIFT  12
  39
  40struct linux_mdesc * __init ArcGetMemoryDescriptor(struct linux_mdesc *Current)
  41{
  42        return (struct linux_mdesc *) ARC_CALL1(get_mdesc, Current);
  43}
  44
  45#ifdef DEBUG /* convenient for debugging */
  46static char *arcs_mtypes[8] = {
  47        "Exception Block",
  48        "ARCS Romvec Page",
  49        "Free/Contig RAM",
  50        "Generic Free RAM",
  51        "Bad Memory",
  52        "Standalone Program Pages",
  53        "ARCS Temp Storage Area",
  54        "ARCS Permanent Storage Area"
  55};
  56
  57static char *arc_mtypes[8] = {
  58        "Exception Block",
  59        "SystemParameterBlock",
  60        "FreeMemory",
  61        "Bad Memory",
  62        "LoadedProgram",
  63        "FirmwareTemporary",
  64        "FirmwarePermanent",
  65        "FreeContiguous"
  66};
  67#define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] \
  68                                                : arc_mtypes[a.arc]
  69#endif
  70
  71enum {
  72        mem_free, mem_prom_used, mem_reserved
  73};
  74
  75static inline int memtype_classify_arcs(union linux_memtypes type)
  76{
  77        switch (type.arcs) {
  78        case arcs_fcontig:
  79        case arcs_free:
  80                return mem_free;
  81        case arcs_atmp:
  82                return mem_prom_used;
  83        case arcs_eblock:
  84        case arcs_rvpage:
  85        case arcs_bmem:
  86        case arcs_prog:
  87        case arcs_aperm:
  88                return mem_reserved;
  89        default:
  90                BUG();
  91        }
  92        while(1);                               /* Nuke warning.  */
  93}
  94
  95static inline int memtype_classify_arc(union linux_memtypes type)
  96{
  97        switch (type.arc) {
  98        case arc_free:
  99        case arc_fcontig:
 100                return mem_free;
 101        case arc_atmp:
 102                return mem_prom_used;
 103        case arc_eblock:
 104        case arc_rvpage:
 105        case arc_bmem:
 106        case arc_prog:
 107        case arc_aperm:
 108                return mem_reserved;
 109        default:
 110                BUG();
 111        }
 112        while(1);                               /* Nuke warning.  */
 113}
 114
 115static int __init prom_memtype_classify(union linux_memtypes type)
 116{
 117        if (prom_flags & PROM_FLAG_ARCS)        /* SGI is ``different'' ... */
 118                return memtype_classify_arcs(type);
 119
 120        return memtype_classify_arc(type);
 121}
 122
 123void __weak __init prom_meminit(void)
 124{
 125        struct linux_mdesc *p;
 126
 127#ifdef DEBUG
 128        int i = 0;
 129
 130        printk("ARCS MEMORY DESCRIPTOR dump:\n");
 131        p = ArcGetMemoryDescriptor(PROM_NULL_MDESC);
 132        while(p) {
 133                printk("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n",
 134                       i, p, p->base, p->pages, mtypes(p->type));
 135                p = ArcGetMemoryDescriptor(p);
 136                i++;
 137        }
 138#endif
 139
 140        nr_prom_mem = 0;
 141        p = PROM_NULL_MDESC;
 142        while ((p = ArcGetMemoryDescriptor(p))) {
 143                unsigned long base, size;
 144                long type;
 145
 146                base = p->base << ARC_PAGE_SHIFT;
 147                size = p->pages << ARC_PAGE_SHIFT;
 148                type = prom_memtype_classify(p->type);
 149
 150                /* ignore mirrored RAM on IP28/IP30 */
 151                if (base < PHYS_OFFSET)
 152                        continue;
 153
 154                memblock_add(base, size);
 155
 156                if (type == mem_reserved)
 157                        memblock_reserve(base, size);
 158
 159                if (type == mem_prom_used) {
 160                        memblock_reserve(base, size);
 161                        if (nr_prom_mem >= 5) {
 162                                pr_err("Too many ROM DATA regions");
 163                                continue;
 164                        }
 165                        prom_mem_base[nr_prom_mem] = base;
 166                        prom_mem_size[nr_prom_mem] = size;
 167                        nr_prom_mem++;
 168                }
 169        }
 170}
 171
 172void __weak __init prom_cleanup(void)
 173{
 174}
 175
 176void __init prom_free_prom_memory(void)
 177{
 178        int i;
 179
 180        if (prom_flags & PROM_FLAG_DONT_FREE_TEMP)
 181                return;
 182
 183        for (i = 0; i < nr_prom_mem; i++) {
 184                free_init_pages("prom memory",
 185                        prom_mem_base[i], prom_mem_base[i] + prom_mem_size[i]);
 186        }
 187        /*
 188         * at this point it isn't safe to call PROM functions
 189         * give platforms a way to do PROM cleanups
 190         */
 191        prom_cleanup();
 192}
 193