adm5120: update files-2.6.33 and files-2.6.34

SVN-Revision: 21398
This commit is contained in:
Alexandros C. Couloumbis 2010-05-08 08:15:40 +00:00
parent 51f7953734
commit 093fd3da26
8 changed files with 1282 additions and 0 deletions

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}