Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * memory.c: PROM library functions for acquiring/using memory descriptors
0004  *       given to us from the ARCS firmware.
0005  *
0006  * Copyright (C) 1996 by David S. Miller
0007  * Copyright (C) 1999, 2000, 2001 by Ralf Baechle
0008  * Copyright (C) 1999, 2000 by Silicon Graphics, Inc.
0009  *
0010  * PROM library functions for acquiring/using memory descriptors given to us
0011  * from the ARCS firmware.  This is only used when CONFIG_ARC_MEMORY is set
0012  * because on some machines like SGI IP27 the ARC memory configuration data
0013  * completely bogus and alternate easier to use mechanisms are available.
0014  */
0015 #include <linux/init.h>
0016 #include <linux/kernel.h>
0017 #include <linux/types.h>
0018 #include <linux/sched.h>
0019 #include <linux/mm.h>
0020 #include <linux/memblock.h>
0021 #include <linux/swap.h>
0022 
0023 #include <asm/sgialib.h>
0024 #include <asm/page.h>
0025 #include <asm/bootinfo.h>
0026 
0027 #undef DEBUG
0028 
0029 #define MAX_PROM_MEM 5
0030 static phys_addr_t prom_mem_base[MAX_PROM_MEM] __initdata;
0031 static phys_addr_t prom_mem_size[MAX_PROM_MEM] __initdata;
0032 static unsigned int nr_prom_mem __initdata;
0033 
0034 /*
0035  * For ARC firmware memory functions the unit of measuring memory is always
0036  * a 4k page of memory
0037  */
0038 #define ARC_PAGE_SHIFT  12
0039 
0040 struct linux_mdesc * __init ArcGetMemoryDescriptor(struct linux_mdesc *Current)
0041 {
0042     return (struct linux_mdesc *) ARC_CALL1(get_mdesc, Current);
0043 }
0044 
0045 #ifdef DEBUG /* convenient for debugging */
0046 static char *arcs_mtypes[8] = {
0047     "Exception Block",
0048     "ARCS Romvec Page",
0049     "Free/Contig RAM",
0050     "Generic Free RAM",
0051     "Bad Memory",
0052     "Standalone Program Pages",
0053     "ARCS Temp Storage Area",
0054     "ARCS Permanent Storage Area"
0055 };
0056 
0057 static char *arc_mtypes[8] = {
0058     "Exception Block",
0059     "SystemParameterBlock",
0060     "FreeMemory",
0061     "Bad Memory",
0062     "LoadedProgram",
0063     "FirmwareTemporary",
0064     "FirmwarePermanent",
0065     "FreeContiguous"
0066 };
0067 #define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] \
0068                         : arc_mtypes[a.arc]
0069 #endif
0070 
0071 enum {
0072     mem_free, mem_prom_used, mem_reserved
0073 };
0074 
0075 static inline int memtype_classify_arcs(union linux_memtypes type)
0076 {
0077     switch (type.arcs) {
0078     case arcs_fcontig:
0079     case arcs_free:
0080         return mem_free;
0081     case arcs_atmp:
0082         return mem_prom_used;
0083     case arcs_eblock:
0084     case arcs_rvpage:
0085     case arcs_bmem:
0086     case arcs_prog:
0087     case arcs_aperm:
0088         return mem_reserved;
0089     default:
0090         BUG();
0091     }
0092     while(1);               /* Nuke warning.  */
0093 }
0094 
0095 static inline int memtype_classify_arc(union linux_memtypes type)
0096 {
0097     switch (type.arc) {
0098     case arc_free:
0099     case arc_fcontig:
0100         return mem_free;
0101     case arc_atmp:
0102         return mem_prom_used;
0103     case arc_eblock:
0104     case arc_rvpage:
0105     case arc_bmem:
0106     case arc_prog:
0107     case arc_aperm:
0108         return mem_reserved;
0109     default:
0110         BUG();
0111     }
0112     while(1);               /* Nuke warning.  */
0113 }
0114 
0115 static int __init prom_memtype_classify(union linux_memtypes type)
0116 {
0117     if (prom_flags & PROM_FLAG_ARCS)    /* SGI is ``different'' ... */
0118         return memtype_classify_arcs(type);
0119 
0120     return memtype_classify_arc(type);
0121 }
0122 
0123 void __weak __init prom_meminit(void)
0124 {
0125     struct linux_mdesc *p;
0126 
0127 #ifdef DEBUG
0128     int i = 0;
0129 
0130     printk("ARCS MEMORY DESCRIPTOR dump:\n");
0131     p = ArcGetMemoryDescriptor(PROM_NULL_MDESC);
0132     while(p) {
0133         printk("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n",
0134                i, p, p->base, p->pages, mtypes(p->type));
0135         p = ArcGetMemoryDescriptor(p);
0136         i++;
0137     }
0138 #endif
0139 
0140     nr_prom_mem = 0;
0141     p = PROM_NULL_MDESC;
0142     while ((p = ArcGetMemoryDescriptor(p))) {
0143         unsigned long base, size;
0144         long type;
0145 
0146         base = p->base << ARC_PAGE_SHIFT;
0147         size = p->pages << ARC_PAGE_SHIFT;
0148         type = prom_memtype_classify(p->type);
0149 
0150         /* ignore mirrored RAM on IP28/IP30 */
0151         if (base < PHYS_OFFSET)
0152             continue;
0153 
0154         memblock_add(base, size);
0155 
0156         if (type == mem_reserved)
0157             memblock_reserve(base, size);
0158 
0159         if (type == mem_prom_used) {
0160             memblock_reserve(base, size);
0161             if (nr_prom_mem >= 5) {
0162                 pr_err("Too many ROM DATA regions");
0163                 continue;
0164             }
0165             prom_mem_base[nr_prom_mem] = base;
0166             prom_mem_size[nr_prom_mem] = size;
0167             nr_prom_mem++;
0168         }
0169     }
0170 }
0171 
0172 void __weak __init prom_cleanup(void)
0173 {
0174 }
0175 
0176 void __init prom_free_prom_memory(void)
0177 {
0178     int i;
0179 
0180     if (prom_flags & PROM_FLAG_DONT_FREE_TEMP)
0181         return;
0182 
0183     for (i = 0; i < nr_prom_mem; i++) {
0184         free_init_pages("prom memory",
0185             prom_mem_base[i], prom_mem_base[i] + prom_mem_size[i]);
0186     }
0187     /*
0188      * at this point it isn't safe to call PROM functions
0189      * give platforms a way to do PROM cleanups
0190      */
0191     prom_cleanup();
0192 }