2010-06-08 21:06:01 +04:00
/*
* BCM947xx nvram variable access
*
* Copyright ( C ) 2005 Broadcom Corporation
* Copyright ( C ) 2006 Felix Fietkau < nbd @ openwrt . org >
2011-05-11 01:31:32 +04:00
* Copyright ( C ) 2010 - 2011 Hauke Mehrtens < hauke @ hauke - m . de >
2010-06-08 21:06:01 +04:00
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation ; either version 2 of the License , or ( at your
* option ) any later version .
*/
# include <linux/init.h>
# include <linux/types.h>
# include <linux/module.h>
# include <linux/ssb/ssb.h>
# include <linux/kernel.h>
# include <linux/string.h>
# include <asm/addrspace.h>
# include <asm/mach-bcm47xx/nvram.h>
# include <asm/mach-bcm47xx/bcm47xx.h>
static char nvram_buf [ NVRAM_SPACE ] ;
/* Probe for NVRAM header */
2011-05-11 01:31:32 +04:00
static void early_nvram_init ( void )
2010-06-08 21:06:01 +04:00
{
2011-07-23 03:20:13 +04:00
# ifdef CONFIG_BCM47XX_SSB
2011-07-23 03:20:12 +04:00
struct ssb_mipscore * mcore_ssb ;
2011-07-23 03:20:14 +04:00
# endif
# ifdef CONFIG_BCM47XX_BCMA
struct bcma_drv_cc * bcma_cc ;
2011-07-23 03:20:13 +04:00
# endif
2010-06-08 21:06:01 +04:00
struct nvram_header * header ;
int i ;
2011-07-23 03:20:12 +04:00
u32 base = 0 ;
u32 lim = 0 ;
u32 off ;
2010-06-08 21:06:01 +04:00
u32 * src , * dst ;
2011-07-23 03:20:12 +04:00
switch ( bcm47xx_bus_type ) {
2011-07-23 03:20:13 +04:00
# ifdef CONFIG_BCM47XX_SSB
2011-07-23 03:20:12 +04:00
case BCM47XX_BUS_TYPE_SSB :
mcore_ssb = & bcm47xx_bus . ssb . mipscore ;
base = mcore_ssb - > flash_window ;
lim = mcore_ssb - > flash_window_size ;
break ;
2011-07-23 03:20:14 +04:00
# endif
# ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA :
bcma_cc = & bcm47xx_bus . bcma . bus . drv_cc ;
base = bcma_cc - > pflash . window ;
lim = bcma_cc - > pflash . window_size ;
break ;
2011-07-23 03:20:13 +04:00
# endif
2011-07-23 03:20:12 +04:00
}
2010-06-08 21:06:01 +04:00
off = FLASH_MIN ;
while ( off < = lim ) {
/* Windowed flash access */
header = ( struct nvram_header * )
KSEG1ADDR ( base + off - NVRAM_SPACE ) ;
if ( header - > magic = = NVRAM_HEADER )
goto found ;
off < < = 1 ;
}
/* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
header = ( struct nvram_header * ) KSEG1ADDR ( base + 4096 ) ;
if ( header - > magic = = NVRAM_HEADER )
goto found ;
header = ( struct nvram_header * ) KSEG1ADDR ( base + 1024 ) ;
if ( header - > magic = = NVRAM_HEADER )
goto found ;
return ;
found :
src = ( u32 * ) header ;
dst = ( u32 * ) nvram_buf ;
for ( i = 0 ; i < sizeof ( struct nvram_header ) ; i + = 4 )
* dst + + = * src + + ;
for ( ; i < header - > len & & i < NVRAM_SPACE ; i + = 4 )
* dst + + = le32_to_cpu ( * src + + ) ;
}
int nvram_getenv ( char * name , char * val , size_t val_len )
{
char * var , * value , * end , * eq ;
if ( ! name )
2010-08-03 01:56:22 +04:00
return NVRAM_ERR_INV_PARAM ;
2010-06-08 21:06:01 +04:00
if ( ! nvram_buf [ 0 ] )
early_nvram_init ( ) ;
/* Look for name=value and return value */
var = & nvram_buf [ sizeof ( struct nvram_header ) ] ;
end = nvram_buf + sizeof ( nvram_buf ) - 2 ;
end [ 0 ] = end [ 1 ] = ' \0 ' ;
for ( ; * var ; var = value + strlen ( value ) + 1 ) {
eq = strchr ( var , ' = ' ) ;
if ( ! eq )
break ;
value = eq + 1 ;
if ( ( eq - var ) = = strlen ( name ) & &
strncmp ( var , name , ( eq - var ) ) = = 0 ) {
snprintf ( val , val_len , " %s " , value ) ;
return 0 ;
}
}
2010-08-03 01:56:22 +04:00
return NVRAM_ERR_ENVNOTFOUND ;
2010-06-08 21:06:01 +04:00
}
EXPORT_SYMBOL ( nvram_getenv ) ;