2008-07-14 09:59:21 +02:00
/*
2009-06-16 10:30:52 +02:00
* Copyright IBM Corp . 2008 , 2009
*
* Author ( s ) : Heiko Carstens < heiko . carstens @ de . ibm . com >
2008-07-14 09:59:21 +02:00
*/
# include <linux/kernel.h>
# include <linux/module.h>
2014-01-29 18:16:01 +01:00
# include <linux/memblock.h>
# include <linux/init.h>
# include <linux/debugfs.h>
# include <linux/seq_file.h>
2008-07-14 09:59:21 +02:00
# include <asm/ipl.h>
# include <asm/sclp.h>
# include <asm/setup.h>
2014-01-29 18:16:01 +01:00
# define CHUNK_READ_WRITE 0
# define CHUNK_READ_ONLY 1
static inline void memblock_physmem_add ( phys_addr_t start , phys_addr_t size )
{
memblock_add_range ( & memblock . memory , start , size , 0 , 0 ) ;
memblock_add_range ( & memblock . physmem , start , size , 0 , 0 ) ;
}
void __init detect_memory_memblock ( void )
2008-07-14 09:59:21 +02:00
{
2015-12-31 10:07:21 +01:00
unsigned long memsize , rnmax , rzm , addr , size ;
2014-01-29 18:16:01 +01:00
int type ;
2008-07-14 09:59:21 +02:00
2015-05-06 13:18:59 +02:00
rzm = sclp . rzm ;
rnmax = sclp . rnmax ;
2008-07-14 09:59:21 +02:00
memsize = rzm * rnmax ;
if ( ! rzm )
2015-12-31 10:07:21 +01:00
rzm = 1UL < < 17 ;
2014-01-29 18:16:01 +01:00
max_physmem_end = memsize ;
addr = 0 ;
/* keep memblock lists close to the kernel */
memblock_set_bottom_up ( true ) ;
2008-07-14 09:59:21 +02:00
do {
size = 0 ;
type = tprot ( addr ) ;
do {
size + = rzm ;
2014-01-29 18:16:01 +01:00
if ( max_physmem_end & & addr + size > = max_physmem_end )
2008-07-14 09:59:21 +02:00
break ;
} while ( type = = tprot ( addr + size ) ) ;
if ( type = = CHUNK_READ_WRITE | | type = = CHUNK_READ_ONLY ) {
2014-01-29 18:16:01 +01:00
if ( max_physmem_end & & ( addr + size > max_physmem_end ) )
size = max_physmem_end - addr ;
memblock_physmem_add ( addr , size ) ;
2008-07-14 09:59:21 +02:00
}
addr + = size ;
2014-01-29 18:16:01 +01:00
} while ( addr < max_physmem_end ) ;
memblock_set_bottom_up ( false ) ;
if ( ! max_physmem_end )
max_physmem_end = memblock_end_of_DRAM ( ) ;
2011-10-30 15:16:40 +01:00
}