2005-04-16 15:20:36 -07:00
/*
2013-03-25 15:05:40 -05:00
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
2005-04-16 15:20:36 -07:00
*
* PROM library functions for acquiring / using memory descriptors given to
* us from the YAMON .
2013-03-25 15:05:40 -05:00
*
* Copyright ( C ) 1999 , 2000 , 2012 MIPS Technologies , Inc .
* All rights reserved .
* Authors : Carsten Langgaard < carstenl @ mips . com >
* Steven J . Hill < sjhill @ mips . com >
2005-04-16 15:20:36 -07:00
*/
# include <linux/init.h>
# include <linux/bootmem.h>
2005-07-14 15:57:16 +00:00
# include <linux/string.h>
2005-04-16 15:20:36 -07:00
# include <asm/bootinfo.h>
2014-07-14 12:37:39 +01:00
# include <asm/maar.h>
2006-04-03 10:17:21 +01:00
# include <asm/sections.h>
2013-03-25 14:47:05 -05:00
# include <asm/fw/fw.h>
2005-04-16 15:20:36 -07:00
2013-03-25 14:47:05 -05:00
static fw_memblock_t mdesc [ FW_MAX_MEMBLOCKS ] ;
2005-04-16 15:20:36 -07:00
2013-01-22 12:59:30 +01:00
/* determined physical memory size, not overridden by command line args */
2006-07-03 17:02:35 +01:00
unsigned long physical_memsize = 0L ;
2014-01-15 13:55:07 +00:00
fw_memblock_t * __init fw_getmdesc ( int eva )
2005-04-16 15:20:36 -07:00
{
2014-05-23 13:31:32 +01:00
char * memsize_str , * ememsize_str = NULL , * ptr ;
2014-06-04 22:53:02 +02:00
unsigned long memsize = 0 , ememsize = 0 ;
2009-10-13 23:43:24 +03:00
static char cmdline [ COMMAND_LINE_SIZE ] __initdata ;
2013-03-25 15:05:40 -05:00
int tmp ;
2005-04-16 15:20:36 -07:00
2006-07-03 17:02:35 +01:00
/* otherwise look in the environment */
2014-01-15 13:55:07 +00:00
2013-03-25 14:47:05 -05:00
memsize_str = fw_getenv ( " memsize " ) ;
2014-08-18 15:04:11 +01:00
if ( memsize_str ) {
tmp = kstrtoul ( memsize_str , 0 , & memsize ) ;
if ( tmp )
pr_warn ( " Failed to read the 'memsize' env variable. \n " ) ;
}
2014-01-15 13:55:07 +00:00
if ( eva ) {
/* Look for ememsize for EVA */
ememsize_str = fw_getenv ( " ememsize " ) ;
2014-08-18 15:04:11 +01:00
if ( ememsize_str ) {
tmp = kstrtoul ( ememsize_str , 0 , & ememsize ) ;
if ( tmp )
pr_warn ( " Failed to read the 'ememsize' env variable. \n " ) ;
}
2014-01-15 13:55:07 +00:00
}
if ( ! memsize & & ! ememsize ) {
2013-03-25 15:05:40 -05:00
pr_warn ( " memsize not set in YAMON, set to default (32Mb) \n " ) ;
2006-07-03 17:02:35 +01:00
physical_memsize = 0x02000000 ;
} else {
2014-01-15 13:55:07 +00:00
/* If ememsize is set, then set physical_memsize to that */
physical_memsize = ememsize ? : memsize ;
2005-04-16 15:20:36 -07:00
}
2006-06-06 10:57:09 +01:00
# ifdef CONFIG_CPU_BIG_ENDIAN
2006-07-03 17:02:35 +01:00
/* SOC-it swaps, or perhaps doesn't swap, when DMA'ing the last
word of physical memory */
physical_memsize - = PAGE_SIZE ;
2006-06-06 10:57:09 +01:00
# endif
2006-07-03 17:02:35 +01:00
/* Check the command line for a memsize directive that overrides
the physical / default amount */
strcpy ( cmdline , arcs_cmdline ) ;
ptr = strstr ( cmdline , " memsize= " ) ;
if ( ptr & & ( ptr ! = cmdline ) & & ( * ( ptr - 1 ) ! = ' ' ) )
ptr = strstr ( ptr , " memsize= " ) ;
2014-01-15 13:55:07 +00:00
/* And now look for ememsize */
if ( eva ) {
ptr = strstr ( cmdline , " ememsize= " ) ;
if ( ptr & & ( ptr ! = cmdline ) & & ( * ( ptr - 1 ) ! = ' ' ) )
ptr = strstr ( ptr , " ememsize= " ) ;
}
2006-07-03 17:02:35 +01:00
if ( ptr )
2014-01-15 13:55:07 +00:00
memsize = memparse ( ptr + 8 + ( eva ? 1 : 0 ) , & ptr ) ;
2006-07-03 17:02:35 +01:00
else
memsize = physical_memsize ;
2014-01-15 13:55:07 +00:00
/* Last 64K for HIGHMEM arithmetics */
if ( memsize > 0x7fff0000 )
memsize = 0x7fff0000 ;
2005-04-16 15:20:36 -07:00
memset ( mdesc , 0 , sizeof ( mdesc ) ) ;
2013-03-25 14:47:05 -05:00
mdesc [ 0 ] . type = fw_dontuse ;
2014-01-15 14:13:05 +00:00
mdesc [ 0 ] . base = PHYS_OFFSET ;
2005-04-16 15:20:36 -07:00
mdesc [ 0 ] . size = 0x00001000 ;
2013-03-25 14:47:05 -05:00
mdesc [ 1 ] . type = fw_code ;
2014-01-15 14:13:05 +00:00
mdesc [ 1 ] . base = mdesc [ 0 ] . base + 0x00001000UL ;
2005-04-16 15:20:36 -07:00
mdesc [ 1 ] . size = 0x000ef000 ;
/*
* The area 0x000f0000 - 0x000fffff is allocated for BIOS memory by the
* south bridge and PCI access always forwarded to the ISA Bus and
* BIOSCS # is always generated .
* This mean that this area can ' t be used as DMA memory for PCI
* devices .
*/
2013-03-25 14:47:05 -05:00
mdesc [ 2 ] . type = fw_dontuse ;
2014-01-15 14:13:05 +00:00
mdesc [ 2 ] . base = mdesc [ 0 ] . base + 0x000f0000UL ;
2005-04-16 15:20:36 -07:00
mdesc [ 2 ] . size = 0x00010000 ;
2013-03-25 14:47:05 -05:00
mdesc [ 3 ] . type = fw_dontuse ;
2014-01-15 14:13:05 +00:00
mdesc [ 3 ] . base = mdesc [ 0 ] . base + 0x00100000UL ;
2013-03-25 15:05:40 -05:00
mdesc [ 3 ] . size = CPHYSADDR ( PFN_ALIGN ( ( unsigned long ) & _end ) ) -
2014-01-15 14:13:05 +00:00
0x00100000UL ;
2005-04-16 15:20:36 -07:00
2013-03-25 14:47:05 -05:00
mdesc [ 4 ] . type = fw_free ;
2014-01-15 14:13:05 +00:00
mdesc [ 4 ] . base = mdesc [ 0 ] . base + CPHYSADDR ( PFN_ALIGN ( & _end ) ) ;
mdesc [ 4 ] . size = memsize - CPHYSADDR ( mdesc [ 4 ] . base ) ;
2005-04-16 15:20:36 -07:00
return & mdesc [ 0 ] ;
}
2014-01-15 14:07:57 +00:00
static void free_init_pages_eva_malta ( void * begin , void * end )
{
free_init_pages ( " unused kernel " , __pa_symbol ( ( unsigned long * ) begin ) ,
__pa_symbol ( ( unsigned long * ) end ) ) ;
}
2013-03-25 14:47:05 -05:00
static int __init fw_memtype_classify ( unsigned int type )
2005-04-16 15:20:36 -07:00
{
switch ( type ) {
2013-03-25 14:47:05 -05:00
case fw_free :
2005-04-16 15:20:36 -07:00
return BOOT_MEM_RAM ;
2013-03-25 14:47:05 -05:00
case fw_code :
2005-04-16 15:20:36 -07:00
return BOOT_MEM_ROM_DATA ;
default :
return BOOT_MEM_RESERVED ;
}
}
2013-03-25 14:47:05 -05:00
void __init fw_meminit ( void )
2005-04-16 15:20:36 -07:00
{
2013-03-25 14:47:05 -05:00
fw_memblock_t * p ;
2005-04-16 15:20:36 -07:00
2014-01-15 13:55:07 +00:00
p = fw_getmdesc ( config_enabled ( CONFIG_EVA ) ) ;
2014-01-15 14:07:57 +00:00
free_init_pages_eva = ( config_enabled ( CONFIG_EVA ) ?
free_init_pages_eva_malta : NULL ) ;
2005-04-16 15:20:36 -07:00
while ( p - > size ) {
long type ;
unsigned long base , size ;
2013-03-25 14:47:05 -05:00
type = fw_memtype_classify ( p - > type ) ;
2005-04-16 15:20:36 -07:00
base = p - > base ;
size = p - > size ;
add_memory_region ( base , size , type ) ;
2013-01-22 12:59:30 +01:00
p + + ;
2005-04-16 15:20:36 -07:00
}
}
2006-12-30 00:43:59 +09:00
void __init prom_free_prom_memory ( void )
2005-04-16 15:20:36 -07:00
{
unsigned long addr ;
int i ;
for ( i = 0 ; i < boot_mem_map . nr_map ; i + + ) {
if ( boot_mem_map . map [ i ] . type ! = BOOT_MEM_ROM_DATA )
continue ;
2006-12-30 00:43:59 +09:00
addr = boot_mem_map . map [ i ] . addr ;
2013-03-25 15:05:40 -05:00
free_init_pages ( " YAMON memory " ,
2006-12-30 00:43:59 +09:00
addr , addr + boot_mem_map . map [ i ] . size ) ;
2005-04-16 15:20:36 -07:00
}
}
2014-07-14 12:37:39 +01:00
unsigned platform_maar_init ( unsigned num_pairs )
{
phys_addr_t mem_end = ( physical_memsize & ~ 0xffffull ) - 1 ;
struct maar_config cfg [ ] = {
/* DRAM preceding I/O */
{ 0x00000000 , 0x0fffffff , MIPS_MAAR_S } ,
/* DRAM following I/O */
{ 0x20000000 , mem_end , MIPS_MAAR_S } ,
/* DRAM alias in upper half of physical */
{ 0x80000000 , 0x80000000 + mem_end , MIPS_MAAR_S } ,
} ;
unsigned i , num_cfg = ARRAY_SIZE ( cfg ) ;
/* If DRAM fits before I/O, drop the region following it */
if ( physical_memsize < = 0x10000000 ) {
num_cfg - - ;
for ( i = 1 ; i < num_cfg ; i + + )
cfg [ i ] = cfg [ i + 1 ] ;
}
return maar_config ( cfg , num_cfg , num_pairs ) ;
}