| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * memory.c: memory initialisation code. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 1998 Harald Koerfgen, Frieder Streffer and Paul M. Antoine | 
					
						
							|  |  |  |  * Copyright (C) 2000, 2002  Maciej W. Rozycki | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #include <linux/init.h>
 | 
					
						
							|  |  |  | #include <linux/kernel.h>
 | 
					
						
							|  |  |  | #include <linux/mm.h>
 | 
					
						
							|  |  |  | #include <linux/bootmem.h>
 | 
					
						
							|  |  |  | #include <linux/types.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <asm/addrspace.h>
 | 
					
						
							|  |  |  | #include <asm/bootinfo.h>
 | 
					
						
							|  |  |  | #include <asm/dec/machtype.h>
 | 
					
						
							|  |  |  | #include <asm/dec/prom.h>
 | 
					
						
							|  |  |  | #include <asm/page.h>
 | 
					
						
							|  |  |  | #include <asm/sections.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-17 02:25:07 +02:00
										 |  |  | volatile unsigned long mem_err;		/* So we know an error occurred */ | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Probe memory in 4MB chunks, waiting for an error to tell us we've fallen | 
					
						
							| 
									
										
										
										
											2013-01-22 12:59:30 +01:00
										 |  |  |  * off the end of real memory.	Only suitable for the 2100/3100's (PMAX). | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define CHUNK_SIZE 0x400000
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void pmax_setup_memory_region(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	volatile unsigned char *memory_page, dummy; | 
					
						
							|  |  |  | 	char old_handler[0x80]; | 
					
						
							|  |  |  | 	extern char genexcept_early; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Install exception handler */ | 
					
						
							| 
									
										
										
										
											2005-06-16 20:30:54 +00:00
										 |  |  | 	memcpy(&old_handler, (void *)(CKSEG0 + 0x80), 0x80); | 
					
						
							|  |  |  | 	memcpy((void *)(CKSEG0 + 0x80), &genexcept_early, 0x80); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* read unmapped and uncached (KSEG1)
 | 
					
						
							|  |  |  | 	 * DECstations have at least 4MB RAM | 
					
						
							|  |  |  | 	 * Assume less than 480MB of RAM, as this is max for 5000/2xx | 
					
						
							|  |  |  | 	 * FIXME this should be replaced by the first free page! | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2005-06-16 20:30:54 +00:00
										 |  |  | 	for (memory_page = (unsigned char *)CKSEG1 + CHUNK_SIZE; | 
					
						
							|  |  |  | 	     mem_err == 0 && memory_page < (unsigned char *)CKSEG1 + 0x1e00000; | 
					
						
							| 
									
										
										
										
											2006-03-11 08:18:41 +00:00
										 |  |  | 	     memory_page += CHUNK_SIZE) { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		dummy = *memory_page; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-06-16 20:30:54 +00:00
										 |  |  | 	memcpy((void *)(CKSEG0 + 0x80), &old_handler, 0x80); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-06-16 20:30:54 +00:00
										 |  |  | 	add_memory_region(0, (unsigned long)memory_page - CKSEG1 - CHUNK_SIZE, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			  BOOT_MEM_RAM); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Use the REX prom calls to get hold of the memory bitmap, and thence | 
					
						
							|  |  |  |  * determine memory size. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static inline void rex_setup_memory_region(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i, bitmap_size; | 
					
						
							|  |  |  | 	unsigned long mem_start = 0, mem_size = 0; | 
					
						
							|  |  |  | 	memmap *bm; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* some free 64k */ | 
					
						
							| 
									
										
										
										
											2005-06-16 20:30:54 +00:00
										 |  |  | 	bm = (memmap *)CKSEG0ADDR(0x28000); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	bitmap_size = rex_getbitmap(bm); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < bitmap_size; i++) { | 
					
						
							|  |  |  | 		/* FIXME: very simplistically only add full sets of pages */ | 
					
						
							|  |  |  | 		if (bm->bitmap[i] == 0xff) | 
					
						
							|  |  |  | 			mem_size += (8 * bm->pagesize); | 
					
						
							|  |  |  | 		else if (!mem_size) | 
					
						
							|  |  |  | 			mem_start += (8 * bm->pagesize); | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			add_memory_region(mem_start, mem_size, BOOT_MEM_RAM); | 
					
						
							|  |  |  | 			mem_start += mem_size + (8 * bm->pagesize); | 
					
						
							|  |  |  | 			mem_size = 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (mem_size) | 
					
						
							|  |  |  | 		add_memory_region(mem_start, mem_size, BOOT_MEM_RAM); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void __init prom_meminit(u32 magic) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!prom_is_rex(magic)) | 
					
						
							|  |  |  | 		pmax_setup_memory_region(); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		rex_setup_memory_region(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-30 00:43:59 +09:00
										 |  |  | void __init prom_free_prom_memory(void) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-12-30 00:43:59 +09:00
										 |  |  | 	unsigned long end; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Free everything below the kernel itself but leave | 
					
						
							|  |  |  | 	 * the first page reserved for the exception handlers. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-31 18:19:07 +01:00
										 |  |  | #if IS_ENABLED(CONFIG_DECLANCE)
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Leave 128 KB reserved for Lance memory for | 
					
						
							|  |  |  | 	 * IOASIC DECstations. | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * XXX: save this address for use in dec_lance.c? | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	if (IOASIC) | 
					
						
							|  |  |  | 		end = __pa(&_text) - 0x00020000; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		end = __pa(&_text); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-30 00:43:59 +09:00
										 |  |  | 	free_init_pages("unused PROM memory", PAGE_SIZE, end); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } |