xref: /linux/arch/mips/dec/prom/memory.c (revision 3e4614e7)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * memory.c: memory initialisation code.
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Copyright (C) 1998 Harald Koerfgen, Frieder Streffer and Paul M. Antoine
61da177e4SLinus Torvalds  * Copyright (C) 2000, 2002  Maciej W. Rozycki
71da177e4SLinus Torvalds  */
81da177e4SLinus Torvalds #include <linux/init.h>
91da177e4SLinus Torvalds #include <linux/kernel.h>
101da177e4SLinus Torvalds #include <linux/mm.h>
1157c8a661SMike Rapoport #include <linux/memblock.h>
121da177e4SLinus Torvalds #include <linux/types.h>
131da177e4SLinus Torvalds 
141da177e4SLinus Torvalds #include <asm/addrspace.h>
151da177e4SLinus Torvalds #include <asm/dec/machtype.h>
161da177e4SLinus Torvalds #include <asm/dec/prom.h>
171da177e4SLinus Torvalds #include <asm/page.h>
181da177e4SLinus Torvalds #include <asm/sections.h>
191da177e4SLinus Torvalds 
201da177e4SLinus Torvalds 
21982f6ffeSRalf Baechle volatile unsigned long mem_err;		/* So we know an error occurred */
221da177e4SLinus Torvalds 
231da177e4SLinus Torvalds /*
241da177e4SLinus Torvalds  * Probe memory in 4MB chunks, waiting for an error to tell us we've fallen
251da177e4SLinus Torvalds  * off the end of real memory.  Only suitable for the 2100/3100's (PMAX).
261da177e4SLinus Torvalds  */
271da177e4SLinus Torvalds 
281da177e4SLinus Torvalds #define CHUNK_SIZE 0x400000
291da177e4SLinus Torvalds 
pmax_setup_memory_region(void)30*3e4614e7SThomas Bogendoerfer static __init void pmax_setup_memory_region(void)
311da177e4SLinus Torvalds {
321da177e4SLinus Torvalds 	volatile unsigned char *memory_page, dummy;
331da177e4SLinus Torvalds 	char old_handler[0x80];
341da177e4SLinus Torvalds 	extern char genexcept_early;
351da177e4SLinus Torvalds 
361da177e4SLinus Torvalds 	/* Install exception handler */
373bd4c902SMaciej W. Rozycki 	memcpy(&old_handler, (void *)(CKSEG0 + 0x80), 0x80);
383bd4c902SMaciej W. Rozycki 	memcpy((void *)(CKSEG0 + 0x80), &genexcept_early, 0x80);
391da177e4SLinus Torvalds 
401da177e4SLinus Torvalds 	/* read unmapped and uncached (KSEG1)
411da177e4SLinus Torvalds 	 * DECstations have at least 4MB RAM
421da177e4SLinus Torvalds 	 * Assume less than 480MB of RAM, as this is max for 5000/2xx
431da177e4SLinus Torvalds 	 * FIXME this should be replaced by the first free page!
441da177e4SLinus Torvalds 	 */
453bd4c902SMaciej W. Rozycki 	for (memory_page = (unsigned char *)CKSEG1 + CHUNK_SIZE;
463bd4c902SMaciej W. Rozycki 	     mem_err == 0 && memory_page < (unsigned char *)CKSEG1 + 0x1e00000;
471da177e4SLinus Torvalds 	     memory_page += CHUNK_SIZE) {
481da177e4SLinus Torvalds 		dummy = *memory_page;
491da177e4SLinus Torvalds 	}
503bd4c902SMaciej W. Rozycki 	memcpy((void *)(CKSEG0 + 0x80), &old_handler, 0x80);
511da177e4SLinus Torvalds 
52e7ae8d17SThomas Bogendoerfer 	memblock_add(0, (unsigned long)memory_page - CKSEG1 - CHUNK_SIZE);
531da177e4SLinus Torvalds }
541da177e4SLinus Torvalds 
551da177e4SLinus Torvalds /*
561da177e4SLinus Torvalds  * Use the REX prom calls to get hold of the memory bitmap, and thence
571da177e4SLinus Torvalds  * determine memory size.
581da177e4SLinus Torvalds  */
rex_setup_memory_region(void)59*3e4614e7SThomas Bogendoerfer static __init void rex_setup_memory_region(void)
601da177e4SLinus Torvalds {
611da177e4SLinus Torvalds 	int i, bitmap_size;
621da177e4SLinus Torvalds 	unsigned long mem_start = 0, mem_size = 0;
631da177e4SLinus Torvalds 	memmap *bm;
641da177e4SLinus Torvalds 
651da177e4SLinus Torvalds 	/* some free 64k */
663bd4c902SMaciej W. Rozycki 	bm = (memmap *)CKSEG0ADDR(0x28000);
671da177e4SLinus Torvalds 
681da177e4SLinus Torvalds 	bitmap_size = rex_getbitmap(bm);
691da177e4SLinus Torvalds 
701da177e4SLinus Torvalds 	for (i = 0; i < bitmap_size; i++) {
711da177e4SLinus Torvalds 		/* FIXME: very simplistically only add full sets of pages */
721da177e4SLinus Torvalds 		if (bm->bitmap[i] == 0xff)
731da177e4SLinus Torvalds 			mem_size += (8 * bm->pagesize);
741da177e4SLinus Torvalds 		else if (!mem_size)
751da177e4SLinus Torvalds 			mem_start += (8 * bm->pagesize);
761da177e4SLinus Torvalds 		else {
77e7ae8d17SThomas Bogendoerfer 			memblock_add(mem_start, mem_size);
781da177e4SLinus Torvalds 			mem_start += mem_size + (8 * bm->pagesize);
791da177e4SLinus Torvalds 			mem_size = 0;
801da177e4SLinus Torvalds 		}
811da177e4SLinus Torvalds 	}
821da177e4SLinus Torvalds 	if (mem_size)
83e7ae8d17SThomas Bogendoerfer 		memblock_add(mem_start, mem_size);
841da177e4SLinus Torvalds }
851da177e4SLinus Torvalds 
prom_meminit(u32 magic)861da177e4SLinus Torvalds void __init prom_meminit(u32 magic)
871da177e4SLinus Torvalds {
881da177e4SLinus Torvalds 	if (!prom_is_rex(magic))
891da177e4SLinus Torvalds 		pmax_setup_memory_region();
901da177e4SLinus Torvalds 	else
911da177e4SLinus Torvalds 		rex_setup_memory_region();
921da177e4SLinus Torvalds }
931da177e4SLinus Torvalds 
prom_free_prom_memory(void)94c44e8d5eSAtsushi Nemoto void __init prom_free_prom_memory(void)
951da177e4SLinus Torvalds {
96c44e8d5eSAtsushi Nemoto 	unsigned long end;
971da177e4SLinus Torvalds 
981da177e4SLinus Torvalds 	/*
991da177e4SLinus Torvalds 	 * Free everything below the kernel itself but leave
1001da177e4SLinus Torvalds 	 * the first page reserved for the exception handlers.
1011da177e4SLinus Torvalds 	 */
1021da177e4SLinus Torvalds 
103baf69e27SFlorian Fainelli #if IS_ENABLED(CONFIG_DECLANCE)
1041da177e4SLinus Torvalds 	/*
1051da177e4SLinus Torvalds 	 * Leave 128 KB reserved for Lance memory for
1061da177e4SLinus Torvalds 	 * IOASIC DECstations.
1071da177e4SLinus Torvalds 	 *
1081da177e4SLinus Torvalds 	 * XXX: save this address for use in dec_lance.c?
1091da177e4SLinus Torvalds 	 */
1101da177e4SLinus Torvalds 	if (IOASIC)
1111da177e4SLinus Torvalds 		end = __pa(&_text) - 0x00020000;
1121da177e4SLinus Torvalds 	else
1131da177e4SLinus Torvalds #endif
1141da177e4SLinus Torvalds 		end = __pa(&_text);
1151da177e4SLinus Torvalds 
116c44e8d5eSAtsushi Nemoto 	free_init_pages("unused PROM memory", PAGE_SIZE, end);
1171da177e4SLinus Torvalds }
118