Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * memory.c: memory initialisation code.
0004  *
0005  * Copyright (C) 1998 Harald Koerfgen, Frieder Streffer and Paul M. Antoine
0006  * Copyright (C) 2000, 2002  Maciej W. Rozycki
0007  */
0008 #include <linux/init.h>
0009 #include <linux/kernel.h>
0010 #include <linux/mm.h>
0011 #include <linux/memblock.h>
0012 #include <linux/types.h>
0013 
0014 #include <asm/addrspace.h>
0015 #include <asm/dec/machtype.h>
0016 #include <asm/dec/prom.h>
0017 #include <asm/page.h>
0018 #include <asm/sections.h>
0019 
0020 
0021 volatile unsigned long mem_err;     /* So we know an error occurred */
0022 
0023 /*
0024  * Probe memory in 4MB chunks, waiting for an error to tell us we've fallen
0025  * off the end of real memory.  Only suitable for the 2100/3100's (PMAX).
0026  */
0027 
0028 #define CHUNK_SIZE 0x400000
0029 
0030 static __init void pmax_setup_memory_region(void)
0031 {
0032     volatile unsigned char *memory_page, dummy;
0033     char old_handler[0x80];
0034     extern char genexcept_early;
0035 
0036     /* Install exception handler */
0037     memcpy(&old_handler, (void *)(CKSEG0 + 0x80), 0x80);
0038     memcpy((void *)(CKSEG0 + 0x80), &genexcept_early, 0x80);
0039 
0040     /* read unmapped and uncached (KSEG1)
0041      * DECstations have at least 4MB RAM
0042      * Assume less than 480MB of RAM, as this is max for 5000/2xx
0043      * FIXME this should be replaced by the first free page!
0044      */
0045     for (memory_page = (unsigned char *)CKSEG1 + CHUNK_SIZE;
0046          mem_err == 0 && memory_page < (unsigned char *)CKSEG1 + 0x1e00000;
0047          memory_page += CHUNK_SIZE) {
0048         dummy = *memory_page;
0049     }
0050     memcpy((void *)(CKSEG0 + 0x80), &old_handler, 0x80);
0051 
0052     memblock_add(0, (unsigned long)memory_page - CKSEG1 - CHUNK_SIZE);
0053 }
0054 
0055 /*
0056  * Use the REX prom calls to get hold of the memory bitmap, and thence
0057  * determine memory size.
0058  */
0059 static __init void rex_setup_memory_region(void)
0060 {
0061     int i, bitmap_size;
0062     unsigned long mem_start = 0, mem_size = 0;
0063     memmap *bm;
0064 
0065     /* some free 64k */
0066     bm = (memmap *)CKSEG0ADDR(0x28000);
0067 
0068     bitmap_size = rex_getbitmap(bm);
0069 
0070     for (i = 0; i < bitmap_size; i++) {
0071         /* FIXME: very simplistically only add full sets of pages */
0072         if (bm->bitmap[i] == 0xff)
0073             mem_size += (8 * bm->pagesize);
0074         else if (!mem_size)
0075             mem_start += (8 * bm->pagesize);
0076         else {
0077             memblock_add(mem_start, mem_size);
0078             mem_start += mem_size + (8 * bm->pagesize);
0079             mem_size = 0;
0080         }
0081     }
0082     if (mem_size)
0083         memblock_add(mem_start, mem_size);
0084 }
0085 
0086 void __init prom_meminit(u32 magic)
0087 {
0088     if (!prom_is_rex(magic))
0089         pmax_setup_memory_region();
0090     else
0091         rex_setup_memory_region();
0092 }
0093 
0094 void __init prom_free_prom_memory(void)
0095 {
0096     unsigned long end;
0097 
0098     /*
0099      * Free everything below the kernel itself but leave
0100      * the first page reserved for the exception handlers.
0101      */
0102 
0103 #if IS_ENABLED(CONFIG_DECLANCE)
0104     /*
0105      * Leave 128 KB reserved for Lance memory for
0106      * IOASIC DECstations.
0107      *
0108      * XXX: save this address for use in dec_lance.c?
0109      */
0110     if (IOASIC)
0111         end = __pa(&_text) - 0x00020000;
0112     else
0113 #endif
0114         end = __pa(&_text);
0115 
0116     free_init_pages("unused PROM memory", PAGE_SIZE, end);
0117 }