@ -22,16 +22,54 @@
# include <linux/kernel.h>
# include <linux/kernel.h>
# include <linux/serial.h>
# include <linux/serial.h>
# include <linux/serial_core.h>
# include <linux/serial_core.h>
# include <linux/random.h>
# include <asm/bootinfo.h>
# include <asm/bootinfo.h>
# include <asm/irq_cpu.h>
# include <asm/irq_cpu.h>
# include <asm/io.h>
# include <asm/io.h>
# include <ar531x.h>
# include <ar531x.h>
char * board_config , * radio_config ;
char * board_config = NULL ;
char * radio_config = NULL ;
int broken_boarddata = 0 ;
extern int early_serial_setup ( struct uart_port * port ) ;
extern int early_serial_setup ( struct uart_port * port ) ;
static u8 * find_board_config ( char * flash_limit )
static inline bool
check_radio_magic ( unsigned char * addr )
{
addr + = 0x7a ; /* offset for flash magic */
if ( ( addr [ 0 ] = = 0x5a ) & & ( addr [ 1 ] = = 0xa5 ) ) {
return 1 ;
}
return 0 ;
}
static inline bool
check_board_data ( unsigned char * flash_limit , unsigned char * addr , bool broken )
{
/* config magic found */
if ( * ( int * ) addr = = 0x35333132 )
return 1 ;
if ( ! broken )
return 0 ;
if ( check_radio_magic ( addr + 0xf8 ) )
radio_config = addr + 0xf8 ;
if ( ( addr < flash_limit + 0x10000 ) & &
check_radio_magic ( addr + 0x10000 ) )
radio_config = addr + 0x10000 ;
if ( radio_config ) {
/* broken board data detected, use radio data to find the offset,
* user will fix this */
broken_boarddata = 1 ;
return 1 ;
}
return 0 ;
}
static u8 * find_board_config ( char * flash_limit , bool broken )
{
{
char * addr ;
char * addr ;
int found = 0 ;
int found = 0 ;
@ -40,17 +78,14 @@ static u8 *find_board_config(char *flash_limit)
addr > = ( char * ) ( flash_limit - 0x30000 ) ;
addr > = ( char * ) ( flash_limit - 0x30000 ) ;
addr - = 0x1000 ) {
addr - = 0x1000 ) {
if ( * ( int * ) addr = = 0x35333131 ) {
if ( check_board_data ( flash_limit , addr , broken ) ) {
/* config magic found */
found = 1 ;
found = 1 ;
break ;
break ;
}
}
}
}
if ( ! found ) {
if ( ! found )
printk ( " WARNING: No board configuration data found! \n " ) ;
addr = NULL ;
addr = NULL ;
}
return addr ;
return addr ;
}
}
@ -58,7 +93,7 @@ static u8 *find_board_config(char *flash_limit)
static u8 * find_radio_config ( char * flash_limit , char * board_config )
static u8 * find_radio_config ( char * flash_limit , char * board_config )
{
{
int dataFound ;
int dataFound ;
u32 radio_config ;
char * radio_config ;
/*
/*
* Now find the start of Radio Configuration data , using heuristics :
* Now find the start of Radio Configuration data , using heuristics :
@ -66,10 +101,11 @@ static u8 *find_radio_config(char *flash_limit, char *board_config)
* at a time until we find non - 0xffffffff .
* at a time until we find non - 0xffffffff .
*/
*/
dataFound = 0 ;
dataFound = 0 ;
for ( radio_config = ( u32 ) board_config + 0x1000 ;
for ( radio_config = board_config + 0x1000 ;
( radio_config < ( u32 ) flash_limit ) ;
( radio_config < flash_limit ) ;
radio_config + = 0x1000 ) {
radio_config + = 0x1000 ) {
if ( * ( int * ) radio_config ! = 0xffffffff ) {
if ( ( * ( u32 * ) radio_config ! = 0xffffffff ) & &
check_radio_magic ( radio_config ) ) {
dataFound = 1 ;
dataFound = 1 ;
break ;
break ;
}
}
@ -77,10 +113,11 @@ static u8 *find_radio_config(char *flash_limit, char *board_config)
# ifdef CONFIG_ATHEROS_AR5315
# ifdef CONFIG_ATHEROS_AR5315
if ( ! dataFound ) { /* AR2316 relocates radio config to new location */
if ( ! dataFound ) { /* AR2316 relocates radio config to new location */
for ( radio_config = ( u32 ) board_config + 0xf8 ;
for ( radio_config = board_config + 0xf8 ;
( radio_config < ( u32 ) flash_limit - 0x1000 + 0xf8 ) ;
( radio_config < flash_limit - 0x1000 + 0xf8 ) ;
radio_config + = 0x1000 ) {
radio_config + = 0x1000 ) {
if ( * ( int * ) radio_config ! = 0xffffffff ) {
if ( ( * ( u32 * ) radio_config ! = 0xffffffff ) & &
check_radio_magic ( radio_config ) ) {
dataFound = 1 ;
dataFound = 1 ;
break ;
break ;
}
}
@ -98,6 +135,7 @@ static u8 *find_radio_config(char *flash_limit, char *board_config)
int __init ar531x_find_config ( char * flash_limit )
int __init ar531x_find_config ( char * flash_limit )
{
{
struct ar531x_boarddata * bd ;
unsigned int rcfg_size ;
unsigned int rcfg_size ;
char * bcfg , * rcfg ;
char * bcfg , * rcfg ;
@ -105,23 +143,45 @@ int __init ar531x_find_config(char *flash_limit)
* spiflash driver , accessing the mapped memory directly is no
* spiflash driver , accessing the mapped memory directly is no
* longer safe */
* longer safe */
bcfg = find_board_config ( flash_limit ) ;
bcfg = find_board_config ( flash_limit , false ) ;
if ( ! bcfg )
if ( ! bcfg )
bcfg = find_board_config ( flash_limit , true ) ;
if ( ! bcfg ) {
printk ( " WARNING: No board configuration data found! \n " ) ;
return - ENODEV ;
return - ENODEV ;
}
board_config = kzalloc ( BOARD_CONFIG_BUFSZ , GFP_KERNEL ) ;
board_config = kzalloc ( BOARD_CONFIG_BUFSZ , GFP_KERNEL ) ;
memcpy ( board_config , bcfg , 0x100 ) ;
memcpy ( board_config , bcfg , 0x100 ) ;
if ( broken_boarddata ) {
printk ( " WARNING: broken board data detected \n " ) ;
bd = ( struct ar531x_boarddata * ) board_config ;
if ( ! memcmp ( bd - > enet0Mac , " \x00 \x00 \x00 \x00 \x00 \x00 " , 6 ) ) {
printk ( " Fixing up empty mac addresses \n " ) ;
bd - > enet0Mac [ 1 ] = 0x13 ;
bd - > enet0Mac [ 2 ] = 0x37 ;
get_random_bytes ( bd - > enet0Mac + 3 , 3 ) ;
bd - > wlan0Mac [ 1 ] = 0x13 ;
bd - > wlan0Mac [ 2 ] = 0x37 ;
get_random_bytes ( bd - > wlan0Mac + 3 , 3 ) ;
}
}
/* Radio config starts 0x100 bytes after board config, regardless
/* Radio config starts 0x100 bytes after board config, regardless
* of what the physical layout on the flash chip looks like */
* of what the physical layout on the flash chip looks like */
rcfg = find_radio_config ( flash_limit , bcfg ) ;
if ( radio_config )
rcfg = radio_config ;
else
rcfg = find_radio_config ( flash_limit , bcfg ) ;
if ( ! rcfg )
if ( ! rcfg )
return - ENODEV ;
return - ENODEV ;
radio_config = board_config + 0x100 + ( ( rcfg - bcfg ) & 0xfff ) ;
radio_config = board_config + 0x100 + ( ( rcfg - bcfg ) & 0xfff ) ;
printk ( " Radio config found at offset 0x%x(0x%x) \n " , rcfg - bcfg , radio_config - board_config ) ;
printk ( " Radio config found at offset 0x%x(0x%x) \n " , rcfg - bcfg , radio_config - board_config ) ;
rcfg_size = BOARD_CONFIG_BUFSZ - ( ( 0x100 + rcfg - bcfg ) & ( BOARD_CONFIG_BUFSZ - 1 ) ) ;
rcfg_size = BOARD_CONFIG_BUFSZ - ( radio_config - board_config ) ;
memcpy ( radio_config , rcfg , rcfg_size ) ;
memcpy ( radio_config , rcfg , rcfg_size ) ;
return 0 ;
return 0 ;