mirror of https://github.com/hak5/openwrt.git
parent
51f7953734
commit
093fd3da26
|
@ -0,0 +1,331 @@
|
|||
/*
|
||||
* ADM5120 generic GPIO API support via GPIOLIB
|
||||
*
|
||||
* Copyright (C) 2007-2008 Gabor Juhos <juhosg@openwrt.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/autoconf.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <asm/addrspace.h>
|
||||
|
||||
#include <asm/mach-adm5120/adm5120_defs.h>
|
||||
#include <asm/mach-adm5120/adm5120_info.h>
|
||||
#include <asm/mach-adm5120/adm5120_switch.h>
|
||||
|
||||
#define GPIO_REG(r) (void __iomem *)(KSEG1ADDR(ADM5120_SWITCH_BASE) + r)
|
||||
|
||||
struct gpio1_desc {
|
||||
void __iomem *reg; /* register address */
|
||||
u8 iv_shift; /* shift amount for input bit */
|
||||
u8 mode_shift; /* shift amount for mode bits */
|
||||
};
|
||||
|
||||
#define GPIO1_DESC(p, l) { \
|
||||
.reg = GPIO_REG(SWITCH_REG_PORT0_LED + ((p) * 4)), \
|
||||
.iv_shift = LED0_IV_SHIFT + (l), \
|
||||
.mode_shift = (l) * 4 \
|
||||
}
|
||||
|
||||
static struct gpio1_desc gpio1_table[15] = {
|
||||
GPIO1_DESC(0, 0), GPIO1_DESC(0, 1), GPIO1_DESC(0, 2),
|
||||
GPIO1_DESC(1, 0), GPIO1_DESC(1, 1), GPIO1_DESC(1, 2),
|
||||
GPIO1_DESC(2, 0), GPIO1_DESC(2, 1), GPIO1_DESC(2, 2),
|
||||
GPIO1_DESC(3, 0), GPIO1_DESC(3, 1), GPIO1_DESC(3, 2),
|
||||
GPIO1_DESC(4, 0), GPIO1_DESC(4, 1), GPIO1_DESC(4, 2)
|
||||
};
|
||||
|
||||
static u32 gpio_conf2;
|
||||
|
||||
int adm5120_gpio_to_irq(unsigned gpio)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (gpio) {
|
||||
case ADM5120_GPIO_PIN2:
|
||||
ret = ADM5120_IRQ_GPIO2;
|
||||
break;
|
||||
case ADM5120_GPIO_PIN4:
|
||||
ret = ADM5120_IRQ_GPIO4;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(adm5120_gpio_to_irq);
|
||||
|
||||
int adm5120_irq_to_gpio(unsigned irq)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (irq) {
|
||||
case ADM5120_IRQ_GPIO2:
|
||||
ret = ADM5120_GPIO_PIN2;
|
||||
break;
|
||||
case ADM5120_IRQ_GPIO4:
|
||||
ret = ADM5120_GPIO_PIN4;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(adm5120_irq_to_gpio);
|
||||
|
||||
/*
|
||||
* Helpers for GPIO lines in GPIO_CONF0 register
|
||||
*/
|
||||
#define PIN_IM(p) ((1 << GPIO_CONF0_IM_SHIFT) << p)
|
||||
#define PIN_IV(p) ((1 << GPIO_CONF0_IV_SHIFT) << p)
|
||||
#define PIN_OE(p) ((1 << GPIO_CONF0_OE_SHIFT) << p)
|
||||
#define PIN_OV(p) ((1 << GPIO_CONF0_OV_SHIFT) << p)
|
||||
|
||||
int __adm5120_gpio0_get_value(unsigned offset)
|
||||
{
|
||||
void __iomem **reg;
|
||||
u32 t;
|
||||
|
||||
reg = GPIO_REG(SWITCH_REG_GPIO_CONF0);
|
||||
|
||||
t = __raw_readl(reg);
|
||||
if ((t & PIN_IM(offset)) != 0)
|
||||
t &= PIN_IV(offset);
|
||||
else
|
||||
t &= PIN_OV(offset);
|
||||
|
||||
return (t) ? 1 : 0;
|
||||
}
|
||||
EXPORT_SYMBOL(__adm5120_gpio0_get_value);
|
||||
|
||||
void __adm5120_gpio0_set_value(unsigned offset, int value)
|
||||
{
|
||||
void __iomem **reg;
|
||||
u32 t;
|
||||
|
||||
reg = GPIO_REG(SWITCH_REG_GPIO_CONF0);
|
||||
|
||||
t = __raw_readl(reg);
|
||||
if (value == 0)
|
||||
t &= ~(PIN_OV(offset));
|
||||
else
|
||||
t |= PIN_OV(offset);
|
||||
|
||||
__raw_writel(t, reg);
|
||||
}
|
||||
EXPORT_SYMBOL(__adm5120_gpio0_set_value);
|
||||
|
||||
static int adm5120_gpio0_get_value(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
return __adm5120_gpio0_get_value(offset);
|
||||
}
|
||||
|
||||
static void adm5120_gpio0_set_value(struct gpio_chip *chip,
|
||||
unsigned offset, int value)
|
||||
{
|
||||
__adm5120_gpio0_set_value(offset, value);
|
||||
}
|
||||
|
||||
static int adm5120_gpio0_direction_input(struct gpio_chip *chip,
|
||||
unsigned offset)
|
||||
{
|
||||
void __iomem **reg;
|
||||
u32 t;
|
||||
|
||||
reg = GPIO_REG(SWITCH_REG_GPIO_CONF0);
|
||||
|
||||
t = __raw_readl(reg);
|
||||
t &= ~(PIN_OE(offset));
|
||||
t |= PIN_IM(offset);
|
||||
__raw_writel(t, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adm5120_gpio0_direction_output(struct gpio_chip *chip,
|
||||
unsigned offset, int value)
|
||||
{
|
||||
void __iomem **reg;
|
||||
u32 t;
|
||||
|
||||
reg = GPIO_REG(SWITCH_REG_GPIO_CONF0);
|
||||
|
||||
t = __raw_readl(reg);
|
||||
t &= ~(PIN_IM(offset) | PIN_OV(offset));
|
||||
t |= PIN_OE(offset);
|
||||
|
||||
if (value)
|
||||
t |= PIN_OV(offset);
|
||||
|
||||
__raw_writel(t, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct gpio_chip adm5120_gpio0_chip = {
|
||||
.label = "adm5120 gpio0",
|
||||
.get = adm5120_gpio0_get_value,
|
||||
.set = adm5120_gpio0_set_value,
|
||||
.direction_input = adm5120_gpio0_direction_input,
|
||||
.direction_output = adm5120_gpio0_direction_output,
|
||||
.base = ADM5120_GPIO_PIN0,
|
||||
.ngpio = ADM5120_GPIO_PIN7 - ADM5120_GPIO_PIN0 + 1,
|
||||
};
|
||||
|
||||
int __adm5120_gpio1_get_value(unsigned offset)
|
||||
{
|
||||
void __iomem **reg;
|
||||
u32 t, m;
|
||||
|
||||
reg = gpio1_table[offset].reg;
|
||||
|
||||
t = __raw_readl(reg);
|
||||
m = (t >> gpio1_table[offset].mode_shift) & LED_MODE_MASK;
|
||||
if (m == LED_MODE_INPUT)
|
||||
return (t >> gpio1_table[offset].iv_shift) & 1;
|
||||
|
||||
if (m == LED_MODE_OUT_LOW)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL(__adm5120_gpio1_get_value);
|
||||
|
||||
void __adm5120_gpio1_set_value(unsigned offset, int value)
|
||||
{
|
||||
void __iomem **reg;
|
||||
u32 t, s;
|
||||
|
||||
reg = gpio1_table[offset].reg;
|
||||
s = gpio1_table[offset].mode_shift;
|
||||
|
||||
t = __raw_readl(reg);
|
||||
t &= ~(LED_MODE_MASK << s);
|
||||
|
||||
switch (value) {
|
||||
case ADM5120_GPIO_LOW:
|
||||
t |= (LED_MODE_OUT_LOW << s);
|
||||
break;
|
||||
case ADM5120_GPIO_FLASH:
|
||||
case ADM5120_GPIO_LINK:
|
||||
case ADM5120_GPIO_SPEED:
|
||||
case ADM5120_GPIO_DUPLEX:
|
||||
case ADM5120_GPIO_ACT:
|
||||
case ADM5120_GPIO_COLL:
|
||||
case ADM5120_GPIO_LINK_ACT:
|
||||
case ADM5120_GPIO_DUPLEX_COLL:
|
||||
case ADM5120_GPIO_10M_ACT:
|
||||
case ADM5120_GPIO_100M_ACT:
|
||||
t |= ((value & LED_MODE_MASK) << s);
|
||||
break;
|
||||
default:
|
||||
t |= (LED_MODE_OUT_HIGH << s);
|
||||
break;
|
||||
}
|
||||
|
||||
__raw_writel(t, reg);
|
||||
}
|
||||
EXPORT_SYMBOL(__adm5120_gpio1_set_value);
|
||||
|
||||
static int adm5120_gpio1_get_value(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
return __adm5120_gpio1_get_value(offset);
|
||||
}
|
||||
|
||||
static void adm5120_gpio1_set_value(struct gpio_chip *chip,
|
||||
unsigned offset, int value)
|
||||
{
|
||||
__adm5120_gpio1_set_value(offset, value);
|
||||
}
|
||||
|
||||
static int adm5120_gpio1_direction_input(struct gpio_chip *chip,
|
||||
unsigned offset)
|
||||
{
|
||||
void __iomem **reg;
|
||||
u32 t;
|
||||
|
||||
reg = gpio1_table[offset].reg;
|
||||
t = __raw_readl(reg);
|
||||
t &= ~(LED_MODE_MASK << gpio1_table[offset].mode_shift);
|
||||
__raw_writel(t, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adm5120_gpio1_direction_output(struct gpio_chip *chip,
|
||||
unsigned offset, int value)
|
||||
{
|
||||
__adm5120_gpio1_set_value(offset, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct gpio_chip adm5120_gpio1_chip = {
|
||||
.label = "adm5120 gpio1",
|
||||
.get = adm5120_gpio1_get_value,
|
||||
.set = adm5120_gpio1_set_value,
|
||||
.direction_input = adm5120_gpio1_direction_input,
|
||||
.direction_output = adm5120_gpio1_direction_output,
|
||||
.base = ADM5120_GPIO_P0L0,
|
||||
.ngpio = ADM5120_GPIO_P4L2 - ADM5120_GPIO_P0L0 + 1,
|
||||
};
|
||||
|
||||
void __init adm5120_gpio_csx0_enable(void)
|
||||
{
|
||||
gpio_conf2 |= GPIO_CONF2_CSX0;
|
||||
SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, gpio_conf2);
|
||||
|
||||
gpio_request(ADM5120_GPIO_PIN1, "CSX0");
|
||||
}
|
||||
|
||||
void __init adm5120_gpio_csx1_enable(void)
|
||||
{
|
||||
gpio_conf2 |= GPIO_CONF2_CSX1;
|
||||
SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, gpio_conf2);
|
||||
|
||||
gpio_request(ADM5120_GPIO_PIN3, "CSX1");
|
||||
}
|
||||
|
||||
void __init adm5120_gpio_ew_enable(void)
|
||||
{
|
||||
gpio_conf2 |= GPIO_CONF2_EW;
|
||||
SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, gpio_conf2);
|
||||
|
||||
gpio_request(ADM5120_GPIO_PIN0, "EW");
|
||||
}
|
||||
|
||||
void __init adm5120_gpio_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, gpio_conf2);
|
||||
|
||||
if (adm5120_package_pqfp()) {
|
||||
gpiochip_reserve(ADM5120_GPIO_PIN4, 4);
|
||||
adm5120_gpio0_chip.ngpio = 4;
|
||||
}
|
||||
|
||||
err = gpiochip_add(&adm5120_gpio0_chip);
|
||||
if (err)
|
||||
panic("cannot add ADM5120 GPIO0 chip, error=%d", err);
|
||||
|
||||
err = gpiochip_add(&adm5120_gpio1_chip);
|
||||
if (err)
|
||||
panic("cannot add ADM5120 GPIO1 chip, error=%d", err);
|
||||
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* ZyXEL's Bootbase specific prom routines
|
||||
*
|
||||
* Copyright (C) 2007-2008 Gabor Juhos <juhosg@openwrt.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/autoconf.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include <asm/mach-adm5120/adm5120_defs.h>
|
||||
#include <prom/zynos.h>
|
||||
#include "prom_read.h"
|
||||
|
||||
#define ZYNOS_INFO_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x3F90)
|
||||
#define ZYNOS_HDBG_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x4000)
|
||||
#define BOOTEXT_ADDR_MIN KSEG1ADDR(ADM5120_SRAM0_BASE)
|
||||
#define BOOTEXT_ADDR_MAX (BOOTEXT_ADDR_MIN + (2*1024*1024))
|
||||
|
||||
static int bootbase_found;
|
||||
static struct zynos_board_info *board_info;
|
||||
|
||||
struct bootbase_info bootbase_info;
|
||||
|
||||
static inline int bootbase_dbgarea_present(u8 *data)
|
||||
{
|
||||
u32 t;
|
||||
|
||||
t = prom_read_be32(data+5);
|
||||
if (t != ZYNOS_MAGIC_DBGAREA1)
|
||||
return 0;
|
||||
|
||||
t = prom_read_be32(data+9);
|
||||
if (t != ZYNOS_MAGIC_DBGAREA2)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline u32 bootbase_get_bootext_addr(void)
|
||||
{
|
||||
return prom_read_be32(&board_info->bootext_addr);
|
||||
}
|
||||
|
||||
static inline void bootbase_get_mac(u8 *mac)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
mac[i] = board_info->mac[i];
|
||||
}
|
||||
|
||||
static inline u16 bootbase_get_vendor_id(void)
|
||||
{
|
||||
#define CHECK_VENDOR(n) (strnicmp(board_info->vendor, (n), strlen(n)) == 0)
|
||||
unsigned char vendor[ZYNOS_NAME_LEN];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ZYNOS_NAME_LEN; i++)
|
||||
vendor[i] = board_info->vendor[i];
|
||||
|
||||
if CHECK_VENDOR(ZYNOS_VENDOR_ZYXEL)
|
||||
return ZYNOS_VENDOR_ID_ZYXEL;
|
||||
|
||||
if CHECK_VENDOR(ZYNOS_VENDOR_DLINK)
|
||||
return ZYNOS_VENDOR_ID_DLINK;
|
||||
|
||||
if CHECK_VENDOR(ZYNOS_VENDOR_LUCENT)
|
||||
return ZYNOS_VENDOR_ID_LUCENT;
|
||||
|
||||
if CHECK_VENDOR(ZYNOS_VENDOR_NETGEAR)
|
||||
return ZYNOS_VENDOR_ID_NETGEAR;
|
||||
|
||||
return ZYNOS_VENDOR_ID_OTHER;
|
||||
}
|
||||
|
||||
static inline u16 bootbase_get_board_id(void)
|
||||
{
|
||||
return prom_read_be16(&board_info->board_id);
|
||||
}
|
||||
|
||||
int __init bootbase_present(void)
|
||||
{
|
||||
u32 t;
|
||||
|
||||
if (bootbase_found)
|
||||
goto out;
|
||||
|
||||
/* check presence of the dbgarea */
|
||||
if (bootbase_dbgarea_present((u8 *)ZYNOS_HDBG_ADDR) == 0)
|
||||
goto out;
|
||||
|
||||
board_info = (struct zynos_board_info *)(ZYNOS_INFO_ADDR);
|
||||
|
||||
/* check for a valid BootExt address */
|
||||
t = bootbase_get_bootext_addr();
|
||||
if ((t < BOOTEXT_ADDR_MIN) || (t > BOOTEXT_ADDR_MAX))
|
||||
goto out;
|
||||
|
||||
bootbase_info.vendor_id = bootbase_get_vendor_id();
|
||||
bootbase_info.board_id = bootbase_get_board_id();
|
||||
bootbase_get_mac(bootbase_info.mac);
|
||||
|
||||
bootbase_found = 1;
|
||||
|
||||
out:
|
||||
return bootbase_found;
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Compex's MyLoader specific prom routines
|
||||
*
|
||||
* Copyright (C) 2007-2008 Gabor Juhos <juhosg@openwrt.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/autoconf.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include <asm/mach-adm5120/adm5120_defs.h>
|
||||
#include <prom/myloader.h>
|
||||
#include "prom_read.h"
|
||||
|
||||
#define SYS_PARAMS_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x0F000)
|
||||
#define BOARD_PARAMS_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x0F800)
|
||||
#define PART_TABLE_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x10000)
|
||||
|
||||
static int myloader_found;
|
||||
|
||||
struct myloader_info myloader_info;
|
||||
|
||||
int __init myloader_present(void)
|
||||
{
|
||||
struct mylo_system_params *sysp;
|
||||
struct mylo_board_params *boardp;
|
||||
struct mylo_partition_table *parts;
|
||||
int i;
|
||||
|
||||
if (myloader_found)
|
||||
goto out;
|
||||
|
||||
sysp = (struct mylo_system_params *)(SYS_PARAMS_ADDR);
|
||||
boardp = (struct mylo_board_params *)(BOARD_PARAMS_ADDR);
|
||||
parts = (struct mylo_partition_table *)(PART_TABLE_ADDR);
|
||||
|
||||
/* Check for some magic numbers */
|
||||
if ((le32_to_cpu(sysp->magic) != MYLO_MAGIC_SYS_PARAMS) ||
|
||||
(le32_to_cpu(boardp->magic) != MYLO_MAGIC_BOARD_PARAMS) ||
|
||||
(le32_to_cpu(parts->magic) != MYLO_MAGIC_PARTITIONS))
|
||||
goto out;
|
||||
|
||||
myloader_info.vid = le32_to_cpu(sysp->vid);
|
||||
myloader_info.did = le32_to_cpu(sysp->did);
|
||||
myloader_info.svid = le32_to_cpu(sysp->svid);
|
||||
myloader_info.sdid = le32_to_cpu(sysp->sdid);
|
||||
|
||||
for (i = 0; i < MYLO_ETHADDR_COUNT; i++) {
|
||||
int j;
|
||||
for (j = 0; j < 6; j++)
|
||||
myloader_info.macs[i][j] = boardp->addr[i].mac[j];
|
||||
}
|
||||
|
||||
myloader_found = 1;
|
||||
|
||||
out:
|
||||
return myloader_found;
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Mikrotik's RouterBOOT specific prom routines
|
||||
*
|
||||
* Copyright (C) 2007-2008 Gabor Juhos <juhosg@openwrt.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/autoconf.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/addrspace.h>
|
||||
|
||||
#include <asm/mach-adm5120/adm5120_defs.h>
|
||||
#include <prom/routerboot.h>
|
||||
#include "prom_read.h"
|
||||
|
||||
struct rb_hard_settings rb_hs;
|
||||
static int rb_found;
|
||||
|
||||
static int __init routerboot_load_hs(u8 *buf, u16 buflen)
|
||||
{
|
||||
u16 id, len;
|
||||
|
||||
memset(&rb_hs, 0, sizeof(rb_hs));
|
||||
|
||||
if (buflen < 4)
|
||||
return -1;
|
||||
|
||||
if (prom_read_le32(buf) != RB_MAGIC_HARD)
|
||||
return -1;
|
||||
|
||||
/* skip magic value */
|
||||
buf += 4;
|
||||
buflen -= 4;
|
||||
|
||||
while (buflen > 2) {
|
||||
id = prom_read_le16(buf);
|
||||
buf += 2;
|
||||
buflen -= 2;
|
||||
if (id == RB_ID_TERMINATOR || buflen < 2)
|
||||
break;
|
||||
|
||||
len = prom_read_le16(buf);
|
||||
buf += 2;
|
||||
buflen -= 2;
|
||||
|
||||
if (buflen < len)
|
||||
break;
|
||||
|
||||
switch (id) {
|
||||
case RB_ID_BIOS_VERSION:
|
||||
rb_hs.bios_ver = (char *)buf;
|
||||
break;
|
||||
case RB_ID_BOARD_NAME:
|
||||
rb_hs.name = (char *)buf;
|
||||
break;
|
||||
case RB_ID_MEMORY_SIZE:
|
||||
rb_hs.mem_size = prom_read_le32(buf);
|
||||
break;
|
||||
case RB_ID_MAC_ADDRESS_COUNT:
|
||||
rb_hs.mac_count = prom_read_le32(buf);
|
||||
break;
|
||||
case RB_ID_MAC_ADDRESS_PACK:
|
||||
if ((len / RB_MAC_SIZE) > 0)
|
||||
rb_hs.mac_base = buf;
|
||||
break;
|
||||
}
|
||||
|
||||
buf += len;
|
||||
buflen -= len;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define RB_BS_OFFS 0x14
|
||||
#define RB_OFFS_MAX (128*1024)
|
||||
|
||||
int __init routerboot_present(void)
|
||||
{
|
||||
struct rb_bios_settings *bs;
|
||||
u8 *base;
|
||||
u32 off, len;
|
||||
|
||||
if (rb_found)
|
||||
goto out;
|
||||
|
||||
base = (u8 *)KSEG1ADDR(ADM5120_SRAM0_BASE);
|
||||
bs = (struct rb_bios_settings *)(base + RB_BS_OFFS);
|
||||
|
||||
off = prom_read_le32(&bs->hs_offs);
|
||||
len = prom_read_le32(&bs->hs_size);
|
||||
if (off > RB_OFFS_MAX)
|
||||
goto out;
|
||||
|
||||
if (routerboot_load_hs(base+off, len) != 0)
|
||||
goto out;
|
||||
|
||||
rb_found = 1;
|
||||
|
||||
out:
|
||||
return rb_found;
|
||||
}
|
||||
|
||||
char *routerboot_get_boardname(void)
|
||||
{
|
||||
if (rb_found == 0)
|
||||
return NULL;
|
||||
|
||||
return rb_hs.name;
|
||||
}
|
|
@ -0,0 +1,331 @@
|
|||
/*
|
||||
* ADM5120 generic GPIO API support via GPIOLIB
|
||||
*
|
||||
* Copyright (C) 2007-2008 Gabor Juhos <juhosg@openwrt.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/autoconf.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <asm/addrspace.h>
|
||||
|
||||
#include <asm/mach-adm5120/adm5120_defs.h>
|
||||
#include <asm/mach-adm5120/adm5120_info.h>
|
||||
#include <asm/mach-adm5120/adm5120_switch.h>
|
||||
|
||||
#define GPIO_REG(r) (void __iomem *)(KSEG1ADDR(ADM5120_SWITCH_BASE) + r)
|
||||
|
||||
struct gpio1_desc {
|
||||
void __iomem *reg; /* register address */
|
||||
u8 iv_shift; /* shift amount for input bit */
|
||||
u8 mode_shift; /* shift amount for mode bits */
|
||||
};
|
||||
|
||||
#define GPIO1_DESC(p, l) { \
|
||||
.reg = GPIO_REG(SWITCH_REG_PORT0_LED + ((p) * 4)), \
|
||||
.iv_shift = LED0_IV_SHIFT + (l), \
|
||||
.mode_shift = (l) * 4 \
|
||||
}
|
||||
|
||||
static struct gpio1_desc gpio1_table[15] = {
|
||||
GPIO1_DESC(0, 0), GPIO1_DESC(0, 1), GPIO1_DESC(0, 2),
|
||||
GPIO1_DESC(1, 0), GPIO1_DESC(1, 1), GPIO1_DESC(1, 2),
|
||||
GPIO1_DESC(2, 0), GPIO1_DESC(2, 1), GPIO1_DESC(2, 2),
|
||||
GPIO1_DESC(3, 0), GPIO1_DESC(3, 1), GPIO1_DESC(3, 2),
|
||||
GPIO1_DESC(4, 0), GPIO1_DESC(4, 1), GPIO1_DESC(4, 2)
|
||||
};
|
||||
|
||||
static u32 gpio_conf2;
|
||||
|
||||
int adm5120_gpio_to_irq(unsigned gpio)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (gpio) {
|
||||
case ADM5120_GPIO_PIN2:
|
||||
ret = ADM5120_IRQ_GPIO2;
|
||||
break;
|
||||
case ADM5120_GPIO_PIN4:
|
||||
ret = ADM5120_IRQ_GPIO4;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(adm5120_gpio_to_irq);
|
||||
|
||||
int adm5120_irq_to_gpio(unsigned irq)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (irq) {
|
||||
case ADM5120_IRQ_GPIO2:
|
||||
ret = ADM5120_GPIO_PIN2;
|
||||
break;
|
||||
case ADM5120_IRQ_GPIO4:
|
||||
ret = ADM5120_GPIO_PIN4;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(adm5120_irq_to_gpio);
|
||||
|
||||
/*
|
||||
* Helpers for GPIO lines in GPIO_CONF0 register
|
||||
*/
|
||||
#define PIN_IM(p) ((1 << GPIO_CONF0_IM_SHIFT) << p)
|
||||
#define PIN_IV(p) ((1 << GPIO_CONF0_IV_SHIFT) << p)
|
||||
#define PIN_OE(p) ((1 << GPIO_CONF0_OE_SHIFT) << p)
|
||||
#define PIN_OV(p) ((1 << GPIO_CONF0_OV_SHIFT) << p)
|
||||
|
||||
int __adm5120_gpio0_get_value(unsigned offset)
|
||||
{
|
||||
void __iomem **reg;
|
||||
u32 t;
|
||||
|
||||
reg = GPIO_REG(SWITCH_REG_GPIO_CONF0);
|
||||
|
||||
t = __raw_readl(reg);
|
||||
if ((t & PIN_IM(offset)) != 0)
|
||||
t &= PIN_IV(offset);
|
||||
else
|
||||
t &= PIN_OV(offset);
|
||||
|
||||
return (t) ? 1 : 0;
|
||||
}
|
||||
EXPORT_SYMBOL(__adm5120_gpio0_get_value);
|
||||
|
||||
void __adm5120_gpio0_set_value(unsigned offset, int value)
|
||||
{
|
||||
void __iomem **reg;
|
||||
u32 t;
|
||||
|
||||
reg = GPIO_REG(SWITCH_REG_GPIO_CONF0);
|
||||
|
||||
t = __raw_readl(reg);
|
||||
if (value == 0)
|
||||
t &= ~(PIN_OV(offset));
|
||||
else
|
||||
t |= PIN_OV(offset);
|
||||
|
||||
__raw_writel(t, reg);
|
||||
}
|
||||
EXPORT_SYMBOL(__adm5120_gpio0_set_value);
|
||||
|
||||
static int adm5120_gpio0_get_value(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
return __adm5120_gpio0_get_value(offset);
|
||||
}
|
||||
|
||||
static void adm5120_gpio0_set_value(struct gpio_chip *chip,
|
||||
unsigned offset, int value)
|
||||
{
|
||||
__adm5120_gpio0_set_value(offset, value);
|
||||
}
|
||||
|
||||
static int adm5120_gpio0_direction_input(struct gpio_chip *chip,
|
||||
unsigned offset)
|
||||
{
|
||||
void __iomem **reg;
|
||||
u32 t;
|
||||
|
||||
reg = GPIO_REG(SWITCH_REG_GPIO_CONF0);
|
||||
|
||||
t = __raw_readl(reg);
|
||||
t &= ~(PIN_OE(offset));
|
||||
t |= PIN_IM(offset);
|
||||
__raw_writel(t, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adm5120_gpio0_direction_output(struct gpio_chip *chip,
|
||||
unsigned offset, int value)
|
||||
{
|
||||
void __iomem **reg;
|
||||
u32 t;
|
||||
|
||||
reg = GPIO_REG(SWITCH_REG_GPIO_CONF0);
|
||||
|
||||
t = __raw_readl(reg);
|
||||
t &= ~(PIN_IM(offset) | PIN_OV(offset));
|
||||
t |= PIN_OE(offset);
|
||||
|
||||
if (value)
|
||||
t |= PIN_OV(offset);
|
||||
|
||||
__raw_writel(t, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct gpio_chip adm5120_gpio0_chip = {
|
||||
.label = "adm5120 gpio0",
|
||||
.get = adm5120_gpio0_get_value,
|
||||
.set = adm5120_gpio0_set_value,
|
||||
.direction_input = adm5120_gpio0_direction_input,
|
||||
.direction_output = adm5120_gpio0_direction_output,
|
||||
.base = ADM5120_GPIO_PIN0,
|
||||
.ngpio = ADM5120_GPIO_PIN7 - ADM5120_GPIO_PIN0 + 1,
|
||||
};
|
||||
|
||||
int __adm5120_gpio1_get_value(unsigned offset)
|
||||
{
|
||||
void __iomem **reg;
|
||||
u32 t, m;
|
||||
|
||||
reg = gpio1_table[offset].reg;
|
||||
|
||||
t = __raw_readl(reg);
|
||||
m = (t >> gpio1_table[offset].mode_shift) & LED_MODE_MASK;
|
||||
if (m == LED_MODE_INPUT)
|
||||
return (t >> gpio1_table[offset].iv_shift) & 1;
|
||||
|
||||
if (m == LED_MODE_OUT_LOW)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL(__adm5120_gpio1_get_value);
|
||||
|
||||
void __adm5120_gpio1_set_value(unsigned offset, int value)
|
||||
{
|
||||
void __iomem **reg;
|
||||
u32 t, s;
|
||||
|
||||
reg = gpio1_table[offset].reg;
|
||||
s = gpio1_table[offset].mode_shift;
|
||||
|
||||
t = __raw_readl(reg);
|
||||
t &= ~(LED_MODE_MASK << s);
|
||||
|
||||
switch (value) {
|
||||
case ADM5120_GPIO_LOW:
|
||||
t |= (LED_MODE_OUT_LOW << s);
|
||||
break;
|
||||
case ADM5120_GPIO_FLASH:
|
||||
case ADM5120_GPIO_LINK:
|
||||
case ADM5120_GPIO_SPEED:
|
||||
case ADM5120_GPIO_DUPLEX:
|
||||
case ADM5120_GPIO_ACT:
|
||||
case ADM5120_GPIO_COLL:
|
||||
case ADM5120_GPIO_LINK_ACT:
|
||||
case ADM5120_GPIO_DUPLEX_COLL:
|
||||
case ADM5120_GPIO_10M_ACT:
|
||||
case ADM5120_GPIO_100M_ACT:
|
||||
t |= ((value & LED_MODE_MASK) << s);
|
||||
break;
|
||||
default:
|
||||
t |= (LED_MODE_OUT_HIGH << s);
|
||||
break;
|
||||
}
|
||||
|
||||
__raw_writel(t, reg);
|
||||
}
|
||||
EXPORT_SYMBOL(__adm5120_gpio1_set_value);
|
||||
|
||||
static int adm5120_gpio1_get_value(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
return __adm5120_gpio1_get_value(offset);
|
||||
}
|
||||
|
||||
static void adm5120_gpio1_set_value(struct gpio_chip *chip,
|
||||
unsigned offset, int value)
|
||||
{
|
||||
__adm5120_gpio1_set_value(offset, value);
|
||||
}
|
||||
|
||||
static int adm5120_gpio1_direction_input(struct gpio_chip *chip,
|
||||
unsigned offset)
|
||||
{
|
||||
void __iomem **reg;
|
||||
u32 t;
|
||||
|
||||
reg = gpio1_table[offset].reg;
|
||||
t = __raw_readl(reg);
|
||||
t &= ~(LED_MODE_MASK << gpio1_table[offset].mode_shift);
|
||||
__raw_writel(t, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adm5120_gpio1_direction_output(struct gpio_chip *chip,
|
||||
unsigned offset, int value)
|
||||
{
|
||||
__adm5120_gpio1_set_value(offset, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct gpio_chip adm5120_gpio1_chip = {
|
||||
.label = "adm5120 gpio1",
|
||||
.get = adm5120_gpio1_get_value,
|
||||
.set = adm5120_gpio1_set_value,
|
||||
.direction_input = adm5120_gpio1_direction_input,
|
||||
.direction_output = adm5120_gpio1_direction_output,
|
||||
.base = ADM5120_GPIO_P0L0,
|
||||
.ngpio = ADM5120_GPIO_P4L2 - ADM5120_GPIO_P0L0 + 1,
|
||||
};
|
||||
|
||||
void __init adm5120_gpio_csx0_enable(void)
|
||||
{
|
||||
gpio_conf2 |= GPIO_CONF2_CSX0;
|
||||
SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, gpio_conf2);
|
||||
|
||||
gpio_request(ADM5120_GPIO_PIN1, "CSX0");
|
||||
}
|
||||
|
||||
void __init adm5120_gpio_csx1_enable(void)
|
||||
{
|
||||
gpio_conf2 |= GPIO_CONF2_CSX1;
|
||||
SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, gpio_conf2);
|
||||
|
||||
gpio_request(ADM5120_GPIO_PIN3, "CSX1");
|
||||
}
|
||||
|
||||
void __init adm5120_gpio_ew_enable(void)
|
||||
{
|
||||
gpio_conf2 |= GPIO_CONF2_EW;
|
||||
SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, gpio_conf2);
|
||||
|
||||
gpio_request(ADM5120_GPIO_PIN0, "EW");
|
||||
}
|
||||
|
||||
void __init adm5120_gpio_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, gpio_conf2);
|
||||
|
||||
if (adm5120_package_pqfp()) {
|
||||
gpiochip_reserve(ADM5120_GPIO_PIN4, 4);
|
||||
adm5120_gpio0_chip.ngpio = 4;
|
||||
}
|
||||
|
||||
err = gpiochip_add(&adm5120_gpio0_chip);
|
||||
if (err)
|
||||
panic("cannot add ADM5120 GPIO0 chip, error=%d", err);
|
||||
|
||||
err = gpiochip_add(&adm5120_gpio1_chip);
|
||||
if (err)
|
||||
panic("cannot add ADM5120 GPIO1 chip, error=%d", err);
|
||||
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* ZyXEL's Bootbase specific prom routines
|
||||
*
|
||||
* Copyright (C) 2007-2008 Gabor Juhos <juhosg@openwrt.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/autoconf.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include <asm/mach-adm5120/adm5120_defs.h>
|
||||
#include <prom/zynos.h>
|
||||
#include "prom_read.h"
|
||||
|
||||
#define ZYNOS_INFO_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x3F90)
|
||||
#define ZYNOS_HDBG_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x4000)
|
||||
#define BOOTEXT_ADDR_MIN KSEG1ADDR(ADM5120_SRAM0_BASE)
|
||||
#define BOOTEXT_ADDR_MAX (BOOTEXT_ADDR_MIN + (2*1024*1024))
|
||||
|
||||
static int bootbase_found;
|
||||
static struct zynos_board_info *board_info;
|
||||
|
||||
struct bootbase_info bootbase_info;
|
||||
|
||||
static inline int bootbase_dbgarea_present(u8 *data)
|
||||
{
|
||||
u32 t;
|
||||
|
||||
t = prom_read_be32(data+5);
|
||||
if (t != ZYNOS_MAGIC_DBGAREA1)
|
||||
return 0;
|
||||
|
||||
t = prom_read_be32(data+9);
|
||||
if (t != ZYNOS_MAGIC_DBGAREA2)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline u32 bootbase_get_bootext_addr(void)
|
||||
{
|
||||
return prom_read_be32(&board_info->bootext_addr);
|
||||
}
|
||||
|
||||
static inline void bootbase_get_mac(u8 *mac)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
mac[i] = board_info->mac[i];
|
||||
}
|
||||
|
||||
static inline u16 bootbase_get_vendor_id(void)
|
||||
{
|
||||
#define CHECK_VENDOR(n) (strnicmp(board_info->vendor, (n), strlen(n)) == 0)
|
||||
unsigned char vendor[ZYNOS_NAME_LEN];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ZYNOS_NAME_LEN; i++)
|
||||
vendor[i] = board_info->vendor[i];
|
||||
|
||||
if CHECK_VENDOR(ZYNOS_VENDOR_ZYXEL)
|
||||
return ZYNOS_VENDOR_ID_ZYXEL;
|
||||
|
||||
if CHECK_VENDOR(ZYNOS_VENDOR_DLINK)
|
||||
return ZYNOS_VENDOR_ID_DLINK;
|
||||
|
||||
if CHECK_VENDOR(ZYNOS_VENDOR_LUCENT)
|
||||
return ZYNOS_VENDOR_ID_LUCENT;
|
||||
|
||||
if CHECK_VENDOR(ZYNOS_VENDOR_NETGEAR)
|
||||
return ZYNOS_VENDOR_ID_NETGEAR;
|
||||
|
||||
return ZYNOS_VENDOR_ID_OTHER;
|
||||
}
|
||||
|
||||
static inline u16 bootbase_get_board_id(void)
|
||||
{
|
||||
return prom_read_be16(&board_info->board_id);
|
||||
}
|
||||
|
||||
int __init bootbase_present(void)
|
||||
{
|
||||
u32 t;
|
||||
|
||||
if (bootbase_found)
|
||||
goto out;
|
||||
|
||||
/* check presence of the dbgarea */
|
||||
if (bootbase_dbgarea_present((u8 *)ZYNOS_HDBG_ADDR) == 0)
|
||||
goto out;
|
||||
|
||||
board_info = (struct zynos_board_info *)(ZYNOS_INFO_ADDR);
|
||||
|
||||
/* check for a valid BootExt address */
|
||||
t = bootbase_get_bootext_addr();
|
||||
if ((t < BOOTEXT_ADDR_MIN) || (t > BOOTEXT_ADDR_MAX))
|
||||
goto out;
|
||||
|
||||
bootbase_info.vendor_id = bootbase_get_vendor_id();
|
||||
bootbase_info.board_id = bootbase_get_board_id();
|
||||
bootbase_get_mac(bootbase_info.mac);
|
||||
|
||||
bootbase_found = 1;
|
||||
|
||||
out:
|
||||
return bootbase_found;
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Compex's MyLoader specific prom routines
|
||||
*
|
||||
* Copyright (C) 2007-2008 Gabor Juhos <juhosg@openwrt.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/autoconf.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include <asm/mach-adm5120/adm5120_defs.h>
|
||||
#include <prom/myloader.h>
|
||||
#include "prom_read.h"
|
||||
|
||||
#define SYS_PARAMS_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x0F000)
|
||||
#define BOARD_PARAMS_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x0F800)
|
||||
#define PART_TABLE_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x10000)
|
||||
|
||||
static int myloader_found;
|
||||
|
||||
struct myloader_info myloader_info;
|
||||
|
||||
int __init myloader_present(void)
|
||||
{
|
||||
struct mylo_system_params *sysp;
|
||||
struct mylo_board_params *boardp;
|
||||
struct mylo_partition_table *parts;
|
||||
int i;
|
||||
|
||||
if (myloader_found)
|
||||
goto out;
|
||||
|
||||
sysp = (struct mylo_system_params *)(SYS_PARAMS_ADDR);
|
||||
boardp = (struct mylo_board_params *)(BOARD_PARAMS_ADDR);
|
||||
parts = (struct mylo_partition_table *)(PART_TABLE_ADDR);
|
||||
|
||||
/* Check for some magic numbers */
|
||||
if ((le32_to_cpu(sysp->magic) != MYLO_MAGIC_SYS_PARAMS) ||
|
||||
(le32_to_cpu(boardp->magic) != MYLO_MAGIC_BOARD_PARAMS) ||
|
||||
(le32_to_cpu(parts->magic) != MYLO_MAGIC_PARTITIONS))
|
||||
goto out;
|
||||
|
||||
myloader_info.vid = le32_to_cpu(sysp->vid);
|
||||
myloader_info.did = le32_to_cpu(sysp->did);
|
||||
myloader_info.svid = le32_to_cpu(sysp->svid);
|
||||
myloader_info.sdid = le32_to_cpu(sysp->sdid);
|
||||
|
||||
for (i = 0; i < MYLO_ETHADDR_COUNT; i++) {
|
||||
int j;
|
||||
for (j = 0; j < 6; j++)
|
||||
myloader_info.macs[i][j] = boardp->addr[i].mac[j];
|
||||
}
|
||||
|
||||
myloader_found = 1;
|
||||
|
||||
out:
|
||||
return myloader_found;
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Mikrotik's RouterBOOT specific prom routines
|
||||
*
|
||||
* Copyright (C) 2007-2008 Gabor Juhos <juhosg@openwrt.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/autoconf.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/addrspace.h>
|
||||
|
||||
#include <asm/mach-adm5120/adm5120_defs.h>
|
||||
#include <prom/routerboot.h>
|
||||
#include "prom_read.h"
|
||||
|
||||
struct rb_hard_settings rb_hs;
|
||||
static int rb_found;
|
||||
|
||||
static int __init routerboot_load_hs(u8 *buf, u16 buflen)
|
||||
{
|
||||
u16 id, len;
|
||||
|
||||
memset(&rb_hs, 0, sizeof(rb_hs));
|
||||
|
||||
if (buflen < 4)
|
||||
return -1;
|
||||
|
||||
if (prom_read_le32(buf) != RB_MAGIC_HARD)
|
||||
return -1;
|
||||
|
||||
/* skip magic value */
|
||||
buf += 4;
|
||||
buflen -= 4;
|
||||
|
||||
while (buflen > 2) {
|
||||
id = prom_read_le16(buf);
|
||||
buf += 2;
|
||||
buflen -= 2;
|
||||
if (id == RB_ID_TERMINATOR || buflen < 2)
|
||||
break;
|
||||
|
||||
len = prom_read_le16(buf);
|
||||
buf += 2;
|
||||
buflen -= 2;
|
||||
|
||||
if (buflen < len)
|
||||
break;
|
||||
|
||||
switch (id) {
|
||||
case RB_ID_BIOS_VERSION:
|
||||
rb_hs.bios_ver = (char *)buf;
|
||||
break;
|
||||
case RB_ID_BOARD_NAME:
|
||||
rb_hs.name = (char *)buf;
|
||||
break;
|
||||
case RB_ID_MEMORY_SIZE:
|
||||
rb_hs.mem_size = prom_read_le32(buf);
|
||||
break;
|
||||
case RB_ID_MAC_ADDRESS_COUNT:
|
||||
rb_hs.mac_count = prom_read_le32(buf);
|
||||
break;
|
||||
case RB_ID_MAC_ADDRESS_PACK:
|
||||
if ((len / RB_MAC_SIZE) > 0)
|
||||
rb_hs.mac_base = buf;
|
||||
break;
|
||||
}
|
||||
|
||||
buf += len;
|
||||
buflen -= len;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define RB_BS_OFFS 0x14
|
||||
#define RB_OFFS_MAX (128*1024)
|
||||
|
||||
int __init routerboot_present(void)
|
||||
{
|
||||
struct rb_bios_settings *bs;
|
||||
u8 *base;
|
||||
u32 off, len;
|
||||
|
||||
if (rb_found)
|
||||
goto out;
|
||||
|
||||
base = (u8 *)KSEG1ADDR(ADM5120_SRAM0_BASE);
|
||||
bs = (struct rb_bios_settings *)(base + RB_BS_OFFS);
|
||||
|
||||
off = prom_read_le32(&bs->hs_offs);
|
||||
len = prom_read_le32(&bs->hs_size);
|
||||
if (off > RB_OFFS_MAX)
|
||||
goto out;
|
||||
|
||||
if (routerboot_load_hs(base+off, len) != 0)
|
||||
goto out;
|
||||
|
||||
rb_found = 1;
|
||||
|
||||
out:
|
||||
return rb_found;
|
||||
}
|
||||
|
||||
char *routerboot_get_boardname(void)
|
||||
{
|
||||
if (rb_found == 0)
|
||||
return NULL;
|
||||
|
||||
return rb_hs.name;
|
||||
}
|
Loading…
Reference in New Issue