mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2025-02-20 09:24:43 +02:00
atheros: clean up the board data detection code and attempt to boot the kernel even when the board data was not found (radio data still needs to be present)
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@13006 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
parent
ace7dddc4c
commit
998577a6b4
@ -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 */
|
||||||
|
|
||||||
|
if (radio_config)
|
||||||
|
rcfg = radio_config;
|
||||||
|
else
|
||||||
rcfg = find_radio_config(flash_limit, bcfg);
|
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user