summaryrefslogtreecommitdiffstats
path: root/target/linux/rdc/files-2.6.24
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/rdc/files-2.6.24')
-rw-r--r--target/linux/rdc/files-2.6.24/arch/i386/kernel/cpu/rdc.c24
-rw-r--r--target/linux/rdc/files-2.6.24/arch/i386/mach-rdc/Makefile5
-rw-r--r--target/linux/rdc/files-2.6.24/arch/i386/mach-rdc/gpio.c91
-rw-r--r--target/linux/rdc/files-2.6.24/arch/i386/mach-rdc/platform.c263
-rw-r--r--target/linux/rdc/files-2.6.24/arch/i386/mach-rdc/setup.c14
-rw-r--r--target/linux/rdc/files-2.6.24/arch/i386/mach-rdc/wdt.c272
-rw-r--r--target/linux/rdc/files-2.6.24/arch/x86/boot/compressed/LzmaDecode.c586
-rw-r--r--target/linux/rdc/files-2.6.24/arch/x86/boot/compressed/LzmaDecode.h100
-rw-r--r--target/linux/rdc/files-2.6.24/arch/x86/boot/compressed/lzma_misc.c345
-rw-r--r--target/linux/rdc/files-2.6.24/arch/x86/kernel/cpu/rdc.c24
-rw-r--r--target/linux/rdc/files-2.6.24/arch/x86/mach-rdc/Makefile5
-rw-r--r--target/linux/rdc/files-2.6.24/arch/x86/mach-rdc/gpio.c91
-rw-r--r--target/linux/rdc/files-2.6.24/arch/x86/mach-rdc/platform.c263
-rw-r--r--target/linux/rdc/files-2.6.24/arch/x86/mach-rdc/setup.c14
-rw-r--r--target/linux/rdc/files-2.6.24/arch/x86/mach-rdc/wdt.c272
-rw-r--r--target/linux/rdc/files-2.6.24/drivers/mtd/maps/imghdr.h25
-rw-r--r--target/linux/rdc/files-2.6.24/drivers/mtd/maps/rdc3210.c392
-rw-r--r--target/linux/rdc/files-2.6.24/drivers/net/r6040.c1412
-rw-r--r--target/linux/rdc/files-2.6.24/include/asm-i386/gpio.h6
-rw-r--r--target/linux/rdc/files-2.6.24/include/asm-i386/mach-generic/gpio.h15
-rw-r--r--target/linux/rdc/files-2.6.24/include/asm-i386/mach-rdc/gpio.h56
-rw-r--r--target/linux/rdc/files-2.6.24/include/asm-i386/mach-rdc/rdc321x_defs.h6
-rw-r--r--target/linux/rdc/files-2.6.24/include/asm-x86/gpio.h6
-rw-r--r--target/linux/rdc/files-2.6.24/include/asm-x86/mach-generic/gpio.h15
-rw-r--r--target/linux/rdc/files-2.6.24/include/asm-x86/mach-rdc/gpio.h56
-rw-r--r--target/linux/rdc/files-2.6.24/include/asm-x86/mach-rdc/rdc321x_defs.h6
26 files changed, 4364 insertions, 0 deletions
diff --git a/target/linux/rdc/files-2.6.24/arch/i386/kernel/cpu/rdc.c b/target/linux/rdc/files-2.6.24/arch/i386/kernel/cpu/rdc.c
new file mode 100644
index 000000000..f4b9083bf
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/arch/i386/kernel/cpu/rdc.c
@@ -0,0 +1,24 @@
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+
+#include "cpu.h"
+
+static struct cpu_dev rdc_cpu_dev __cpuinitdata = {
+ .c_vendor = "RDC",
+ .c_models = {
+ { .vendor = X86_VENDOR_RDC, .family = 4, .model_names =
+ {
+ [0] = "R861x(-G)",
+ }
+ },
+ },
+};
+
+int __init rdc_init_cpu(void)
+{
+ cpu_devs[X86_VENDOR_RDC] = &rdc_cpu_dev;
+ return 0;
+}
diff --git a/target/linux/rdc/files-2.6.24/arch/i386/mach-rdc/Makefile b/target/linux/rdc/files-2.6.24/arch/i386/mach-rdc/Makefile
new file mode 100644
index 000000000..5961bc791
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/arch/i386/mach-rdc/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the RDC321x specific parts of the kernel
+#
+obj-$(CONFIG_X86_RDC) := gpio.o platform.o wdt.o
+
diff --git a/target/linux/rdc/files-2.6.24/arch/i386/mach-rdc/gpio.c b/target/linux/rdc/files-2.6.24/arch/i386/mach-rdc/gpio.c
new file mode 100644
index 000000000..dbd03270f
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/arch/i386/mach-rdc/gpio.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2007, OpenWrt.org, Florian Fainelli <florian@openwrt.org>
+ * RDC321x architecture specific GPIO support
+ *
+ * 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/autoconf.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+
+#include <asm/mach-rdc/rdc321x_defs.h>
+
+static inline int rdc_gpio_is_valid(unsigned gpio)
+{
+ return (gpio <= RDC_MAX_GPIO);
+}
+
+static unsigned int rdc_gpio_read(unsigned gpio)
+{
+ unsigned int val;
+
+ val = 0x80000000 | (7 << 11) | ((gpio&0x20?0x84:0x48));
+ outl(val, RDC3210_CFGREG_ADDR);
+ udelay(10);
+ val = inl(RDC3210_CFGREG_DATA);
+ val |= (0x1 << (gpio & 0x1F));
+ outl(val, RDC3210_CFGREG_DATA);
+ udelay(10);
+ val = 0x80000000 | (7 << 11) | ((gpio&0x20?0x88:0x4C));
+ outl(val, RDC3210_CFGREG_ADDR);
+ udelay(10);
+ val = inl(RDC3210_CFGREG_DATA);
+
+ return val;
+}
+
+static void rdc_gpio_write(unsigned int val)
+{
+ if (val) {
+ outl(val, RDC3210_CFGREG_DATA);
+ udelay(10);
+ }
+}
+
+int rdc_gpio_get_value(unsigned gpio)
+{
+ if (rdc_gpio_is_valid(gpio))
+ return (int)rdc_gpio_read(gpio);
+ else
+ return -EINVAL;
+}
+EXPORT_SYMBOL(rdc_gpio_get_value);
+
+void rdc_gpio_set_value(unsigned gpio, int value)
+{
+ unsigned int val;
+
+ if (!rdc_gpio_is_valid(gpio))
+ return;
+
+ val = rdc_gpio_read(gpio);
+
+ if (value)
+ val &= ~(0x1 << (gpio & 0x1F));
+ else
+ val |= (0x1 << (gpio & 0x1F));
+
+ rdc_gpio_write(val);
+}
+EXPORT_SYMBOL(rdc_gpio_set_value);
+
+int rdc_gpio_direction_input(unsigned gpio)
+{
+ return 0;
+}
+EXPORT_SYMBOL(rdc_gpio_direction_input);
+
+int rdc_gpio_direction_output(unsigned gpio, int value)
+{
+ return 0;
+}
+EXPORT_SYMBOL(rdc_gpio_direction_output);
+
+
diff --git a/target/linux/rdc/files-2.6.24/arch/i386/mach-rdc/platform.c b/target/linux/rdc/files-2.6.24/arch/i386/mach-rdc/platform.c
new file mode 100644
index 000000000..86981f844
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/arch/i386/mach-rdc/platform.c
@@ -0,0 +1,263 @@
+/*
+ *
+ * Generic RDC321x platform devices
+ *
+ * Copyright (C) 2007-2008 OpenWrt.org
+ * Copyright (C) 2007 Florian Fainelli <florian@openwrt.org>
+ * Copyright (C) 2008 Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/version.h>
+#include <linux/leds.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/physmap.h>
+#include <linux/root_dev.h>
+#include <asm/gpio.h>
+
+/* Flash */
+#ifdef CONFIG_MTD_RDC3210
+static struct resource rdc_flash_resource[] = {
+ [0] = {
+ .start = (u32)-CONFIG_MTD_RDC3210_SIZE,
+ .end = (u32)-1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device rdc_flash_device = {
+ .name = "rdc321x-flash",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rdc_flash_resource),
+ .resource = rdc_flash_resource,
+};
+#else
+static struct mtd_partition rdc_flash_parts[15];
+
+static struct resource rdc_flash_resource = {
+ .end = (u32)-1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct physmap_flash_data rdc_flash_data = {
+ .parts = rdc_flash_parts,
+};
+
+static struct platform_device rdc_flash_device = {
+ .name = "physmap-flash",
+ .id = -1,
+ .resource = &rdc_flash_resource,
+ .num_resources = 1,
+ .dev.platform_data = &rdc_flash_data,
+};
+#endif
+
+/* LEDS */
+static struct gpio_led default_leds[] = {
+ { .name = "rdc321x:dmz", .gpio = 1, },
+};
+
+static struct gpio_led_platform_data rdc321x_led_data = {
+ .num_leds = ARRAY_SIZE(default_leds),
+ .leds = default_leds,
+};
+
+static struct platform_device rdc321x_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &rdc321x_led_data,
+ }
+};
+
+/* Watchdog */
+static struct platform_device rdc321x_wdt = {
+ .name = "rdc321x-wdt",
+ .id = -1,
+ .num_resources = 0,
+};
+
+/* Button */
+static struct gpio_keys_button rdc321x_gpio_btn[] = {
+ {
+ .gpio = 0,
+ .code = BTN_0,
+ .desc = "Reset",
+ .active_low = 1,
+ }
+};
+
+static struct gpio_keys_platform_data rdc321x_gpio_btn_data = {
+ .buttons = rdc321x_gpio_btn,
+ .nbuttons = ARRAY_SIZE(rdc321x_gpio_btn),
+};
+
+static struct platform_device rdc321x_button = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &rdc321x_gpio_btn_data,
+ }
+};
+
+static struct platform_device *rdc321x_devs[] = {
+ &rdc_flash_device,
+ &rdc321x_leds,
+ &rdc321x_wdt,
+ &rdc321x_button
+};
+
+static int probe_flash_start(struct map_info *the_map)
+{
+ struct mtd_info *res;
+
+ the_map->virt = ioremap(the_map->phys, the_map->size);
+ if (the_map->virt == NULL)
+ return 1;
+ for (the_map->bankwidth = 32; the_map->bankwidth; the_map->bankwidth
+ >>= 1) {
+ res = do_map_probe("cfi_probe", the_map);
+ if (res == NULL)
+ res = do_map_probe("jedec_probe", the_map);
+ if (res != NULL)
+ break;
+ }
+ iounmap(the_map->virt);
+ if (res != NULL)
+ the_map->phys = (u32)-(s32)(the_map->size = res->size);
+ return res == NULL;
+}
+
+static __init int rdc_board_setup(void)
+{
+#ifndef CONFIG_MTD_RDC3210
+ struct map_info rdc_map_info;
+ u32 the_header[4];
+
+ ROOT_DEV = 0;
+ rdc_map_info.name = rdc_flash_device.name;
+ rdc_map_info.phys = 0xff000000;
+ rdc_map_info.size = 0x1000000;
+ rdc_map_info.bankwidth = 2;
+ rdc_map_info.set_vpp = NULL;
+ simple_map_init(&rdc_map_info);
+ while (probe_flash_start(&rdc_map_info)) {
+ rdc_map_info.phys++;
+ if (--rdc_map_info.size)
+ panic("Not to be or to be: That"
+ " is not the question.");
+ }
+ rdc_flash_resource.start = rdc_map_info.phys;
+ rdc_flash_data.width = rdc_map_info.bankwidth;
+ rdc_map_info.virt = (u32)ioremap_nocache(rdc_map_info.phys, 0x10);
+ if (rdc_map_info.virt == NULL)
+ panic("Something's rotten in Denmark!");
+ the_header[0] = ((u32 *)rdc_map_info.virt)[0];
+ the_header[1] = ((u32 *)rdc_map_info.virt)[1];
+ the_header[2] = ((u32 *)rdc_map_info.virt)[2];
+ the_header[3] = ((u32 *)rdc_map_info.virt)[3];
+ iounmap(rdc_map_info.virt);
+ if (!memcmp(the_header, "GMTK", 4)) { /* Gemtek */
+ /* TODO */
+ } else if (!memcmp(the_header, "CSYS", 4)) { /* Sitecom */
+ /* TODO */
+ } else if (!memcmp(((u8 *)the_header) + 14, "Li", 2)) { /* AMIT */
+ rdc_flash_parts[0].name = "kernel_parthdr";
+ rdc_flash_parts[0].offset = 0;
+ rdc_flash_parts[0].size = 0x10;
+ rdc_flash_parts[1].name = "kernel";
+ rdc_flash_parts[1].offset = 0x10;
+ rdc_flash_parts[1].size = 0xffff0;
+ rdc_flash_parts[2].name = "rootfs_parthdr";
+ rdc_flash_parts[2].offset = 0x100000;
+ rdc_flash_parts[2].size = 0x10;
+ rdc_flash_parts[3].name = "rootfs";
+ rdc_flash_parts[3].offset = 0x100010;
+ rdc_flash_parts[3].size = rdc_map_info.size - 0x160010;
+ rdc_flash_parts[4].name = "config_parthdr";
+ rdc_flash_parts[4].offset = rdc_map_info.size - 0x60000;
+ rdc_flash_parts[4].size = 0x10;
+ rdc_flash_parts[5].name = "config";
+ rdc_flash_parts[5].offset = rdc_map_info.size - 0x5fff0;
+ rdc_flash_parts[5].size = 0xfff0;
+ rdc_flash_parts[6].name = "recoveryfs_parthdr";
+ rdc_flash_parts[6].offset = rdc_map_info.size - 0x50000;
+ rdc_flash_parts[6].size = 0x10;
+ rdc_flash_parts[7].name = "recoveryfs";
+ rdc_flash_parts[7].offset = rdc_map_info.size - 0x4fff0;
+ rdc_flash_parts[7].size = 0x3fff0;
+ rdc_flash_parts[8].name = "recovery_parthdr";
+ rdc_flash_parts[8].offset = rdc_map_info.size - 0x10000;
+ rdc_flash_parts[8].size = 0x10;
+ rdc_flash_parts[9].name = "recovery";
+ rdc_flash_parts[9].offset = rdc_map_info.size - 0xfff0;
+ rdc_flash_parts[9].size = 0x7ff0;
+ rdc_flash_parts[10].name = "productinfo_parthdr";
+ rdc_flash_parts[10].offset = rdc_map_info.size - 0x8000;
+ rdc_flash_parts[10].size = 0x10;
+ rdc_flash_parts[11].name = "productinfo";
+ rdc_flash_parts[11].offset = rdc_map_info.size - 0x7ff0;
+ rdc_flash_parts[11].size = 0x1ff0;
+ rdc_flash_parts[12].name = "bootloader_parthdr";
+ rdc_flash_parts[12].offset = rdc_map_info.size - 0x6000;
+ rdc_flash_parts[12].size = 0x10;
+ rdc_flash_parts[13].name = "bootloader";
+ rdc_flash_parts[13].offset = rdc_map_info.size - 0x5ff0;
+ rdc_flash_parts[13].size = 0x5ff0;
+ rdc_flash_parts[14].name = "everything";
+ rdc_flash_parts[14].offset = 0;
+ rdc_flash_parts[14].size = rdc_map_info.size;
+ rdc_flash_data.nr_parts = 15;
+ } else { /* ZyXEL */
+ rdc_flash_parts[0].name = "kernel";
+ rdc_flash_parts[0].offset = 0;
+ rdc_flash_parts[0].size = 0x100000;
+ rdc_flash_parts[1].name = "rootfs";
+ rdc_flash_parts[1].offset = 0x100000;
+ rdc_flash_parts[1].size = rdc_map_info.size - 0x140000;
+ rdc_flash_parts[2].name = "linux";
+ rdc_flash_parts[2].offset = 0;
+ rdc_flash_parts[2].size = rdc_map_info.size - 0x40000;
+ rdc_flash_parts[3].name = "config";
+ rdc_flash_parts[3].offset = rdc_map_info.size - 0x40000;
+ rdc_flash_parts[3].size = 0x10000;
+ rdc_flash_parts[4].name = "productinfo";
+ rdc_flash_parts[4].offset = rdc_map_info.size - 0x30000;
+ rdc_flash_parts[4].size = 0x10000;
+ rdc_flash_parts[5].name = "bootloader";
+ rdc_flash_parts[5].offset = rdc_map_info.size - 0x20000;
+ rdc_flash_parts[5].size = 0x20000;
+ rdc_flash_data.nr_parts = 6;
+ }
+#endif
+ return platform_add_devices(rdc321x_devs, ARRAY_SIZE(rdc321x_devs));
+}
+
+#ifdef CONFIG_MTD_RDC3210
+arch_initcall(rdc_board_setup);
+#else
+late_initcall(rdc_board_setup);
+#endif
diff --git a/target/linux/rdc/files-2.6.24/arch/i386/mach-rdc/setup.c b/target/linux/rdc/files-2.6.24/arch/i386/mach-rdc/setup.c
new file mode 100644
index 000000000..ad206c3d0
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/arch/i386/mach-rdc/setup.c
@@ -0,0 +1,14 @@
+/*
+ * Machine specific setup for generic
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/arch_hooks.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+
+char * __init machine_specific_memory_setup(void)
+{
+ return "RDC R-321x";
+}
diff --git a/target/linux/rdc/files-2.6.24/arch/i386/mach-rdc/wdt.c b/target/linux/rdc/files-2.6.24/arch/i386/mach-rdc/wdt.c
new file mode 100644
index 000000000..13b69f68a
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/arch/i386/mach-rdc/wdt.c
@@ -0,0 +1,272 @@
+/*
+ * RDC321x watchdog driver
+ *
+ * Copyright (C) 2007 Florian Fainelli <florian@openwrt.org>
+ *
+ * This driver is highly inspired from the cpu5_wdt driver
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/timer.h>
+#include <linux/completion.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/watchdog.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include <asm/mach-rdc/rdc321x_defs.h>
+
+#define RDC_WDT_MASK 0x80000000 /* Mask */
+#define RDC_WDT_EN 0x00800000 /* Enable bit */
+#define RDC_WDT_WTI 0x00200000 /* Generate a CPU reset/NMI/WDT irq when WDT timeout is reached */
+#define RDC_WDT_RST 0x00100000 /* Reset bit */
+#define RDC_WDT_WIF 0x00040000 /* WDT IRQ Flag */
+#define RDC_WDT_IRT 0x00000100 /* IRQ Routing table */
+#define RDC_WDT_CNT 0x00000001 /* WDT count */
+
+#define RDC_CLS_TMR 0x80003844 /* Clear timer */
+
+#define RDC_WDT_INTERVAL (HZ/10+1)
+
+int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static int ticks = 1000;
+
+/* some device data */
+
+static struct {
+ struct completion stop;
+ volatile int running;
+ struct timer_list timer;
+ volatile int queue;
+ int default_ticks;
+ unsigned long inuse;
+} rdc321x_wdt_device;
+
+/* generic helper functions */
+
+static void rdc321x_wdt_trigger(unsigned long unused)
+{
+ if( rdc321x_wdt_device.running )
+ ticks--;
+
+ /* keep watchdog alive */
+ outl(RDC_WDT_EN|inl(RDC3210_CFGREG_DATA), RDC3210_CFGREG_DATA);
+
+ /* requeue?? */
+ if (rdc321x_wdt_device.queue && ticks)
+ mod_timer(&rdc321x_wdt_device.timer, jiffies + RDC_WDT_INTERVAL);
+ else {
+ /* ticks doesn't matter anyway */
+ complete(&rdc321x_wdt_device.stop);
+ }
+
+}
+
+static void rdc321x_wdt_reset(void)
+{
+ ticks = rdc321x_wdt_device.default_ticks;
+}
+
+static void rdc321x_wdt_start(void)
+{
+ if (!rdc321x_wdt_device.queue) {
+ rdc321x_wdt_device.queue = 1;
+
+ /* Clear the timer */
+ outl(RDC_CLS_TMR, RDC3210_CFGREG_ADDR);
+
+ /* Enable watchdog and set the timeout to 81.92 us */
+ outl(RDC_WDT_EN|RDC_WDT_CNT, RDC3210_CFGREG_DATA);
+
+ mod_timer(&rdc321x_wdt_device.timer, jiffies + RDC_WDT_INTERVAL);
+ }
+
+ /* if process dies, counter is not decremented */
+ rdc321x_wdt_device.running++;
+}
+
+static int rdc321x_wdt_stop(void)
+{
+ if (rdc321x_wdt_device.running)
+ rdc321x_wdt_device.running = 0;
+
+ ticks = rdc321x_wdt_device.default_ticks;
+
+ return -EIO;
+}
+
+/* filesystem operations */
+
+static int rdc321x_wdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(0, &rdc321x_wdt_device.inuse))
+ return -EBUSY;
+
+ return nonseekable_open(inode, file);
+}
+
+static int rdc321x_wdt_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &rdc321x_wdt_device.inuse);
+ return 0;
+}
+
+static int rdc321x_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ unsigned int value;
+ static struct watchdog_info ident =
+ {
+ .options = WDIOF_CARDRESET,
+ .identity = "RDC321x WDT",
+ };
+
+ switch(cmd) {
+ case WDIOC_KEEPALIVE:
+ rdc321x_wdt_reset();
+ break;
+ case WDIOC_GETSTATUS:
+ /* Read the value from the DATA register */
+ value = inl(RDC3210_CFGREG_DATA);
+ if ( copy_to_user(argp, &value, sizeof(int)) )
+ return -EFAULT;
+ break;
+ case WDIOC_GETSUPPORT:
+ if ( copy_to_user(argp, &ident, sizeof(ident)) )
+ return -EFAULT;
+ break;
+ case WDIOC_SETOPTIONS:
+ if ( copy_from_user(&value, argp, sizeof(int)) )
+ return -EFAULT;
+ switch(value) {
+ case WDIOS_ENABLECARD:
+ rdc321x_wdt_start();
+ break;
+ case WDIOS_DISABLECARD:
+ return rdc321x_wdt_stop();
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+static ssize_t rdc321x_wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+ if ( !count )
+ return -EIO;
+
+ rdc321x_wdt_reset();
+
+ return count;
+}
+
+static const struct file_operations rdc321x_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .ioctl = rdc321x_wdt_ioctl,
+ .open = rdc321x_wdt_open,
+ .write = rdc321x_wdt_write,
+ .release = rdc321x_wdt_release,
+};
+
+static struct miscdevice rdc321x_wdt_misc = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &rdc321x_wdt_fops,
+};
+
+static int __devinit rdc321x_wdt_probe(struct platform_device *pdev)
+{
+ int err;
+
+ if ( (err = misc_register(&rdc321x_wdt_misc)) < 0 ) {
+ printk(KERN_ERR PFX "misc_register failed\n");
+ return err;
+ }
+
+ /* Reset the watchdog */
+ outl(RDC_WDT_RST, RDC3210_CFGREG_DATA);
+
+ init_completion(&rdc321x_wdt_device.stop);
+ rdc321x_wdt_device.queue = 0;
+
+ clear_bit(0, &rdc321x_wdt_device.inuse);
+
+ setup_timer(&rdc321x_wdt_device.timer, rdc321x_wdt_trigger, 0);
+
+ rdc321x_wdt_device.default_ticks = ticks;
+
+ printk(KERN_INFO PFX "init success\n");
+
+ return 0;
+}
+
+static int rdc321x_wdt_remove(struct platform_device *pdev)
+{
+ if (rdc321x_wdt_device.queue) {
+ rdc321x_wdt_device.queue = 0;
+ wait_for_completion(&rdc321x_wdt_device.stop);
+ }
+
+ misc_deregister(&rdc321x_wdt_misc);
+
+ return 0;
+}
+
+static struct platform_driver rdc321x_wdt_driver = {
+ .probe = rdc321x_wdt_probe,
+ .remove = rdc321x_wdt_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "rdc321x-wdt",
+ },
+};
+
+static int __init rdc321x_wdt_init(void)
+{
+ return platform_driver_register(&rdc321x_wdt_driver);
+}
+
+static void __exit rdc321x_wdt_exit(void)
+{
+ platform_driver_unregister(&rdc321x_wdt_driver);
+}
+
+module_init(rdc321x_wdt_init);
+module_exit(rdc321x_wdt_exit);
+
+MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
+MODULE_DESCRIPTION("RDC321x watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/target/linux/rdc/files-2.6.24/arch/x86/boot/compressed/LzmaDecode.c b/target/linux/rdc/files-2.6.24/arch/x86/boot/compressed/LzmaDecode.c
new file mode 100644
index 000000000..a17d6caab
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/arch/x86/boot/compressed/LzmaDecode.c
@@ -0,0 +1,586 @@
+/*
+ LzmaDecode.c
+ LZMA Decoder (optimized for Speed version)
+
+ LZMA SDK 4.17 Copyright (c) 1999-2005 Igor Pavlov (2005-04-05)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this Code, expressly permits you to
+ statically or dynamically link your Code (or bind by name) to the
+ interfaces of this file without subjecting your linked Code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaDecode.h"
+
+#ifndef Byte
+#define Byte unsigned char
+#endif
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_READ_BYTE (*Buffer++)
+
+#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
+ { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
+
+#ifdef _LZMA_IN_CB
+
+#define RC_TEST { if (Buffer == BufferLim) \
+ { UInt32 size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
+ BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
+
+#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
+
+#else
+
+#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
+
+#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
+
+#endif
+
+#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
+
+#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
+#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
+#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
+
+#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
+ { UpdateBit0(p); mi <<= 1; A0; } else \
+ { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
+
+#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
+
+#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
+ { int i = numLevels; res = 1; \
+ do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
+ res -= (1 << numLevels); }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+#ifdef _LZMA_OUT_READ
+
+typedef struct _LzmaVarState
+{
+ Byte *Buffer;
+ Byte *BufferLim;
+ UInt32 Range;
+ UInt32 Code;
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback;
+ #endif
+ Byte *Dictionary;
+ UInt32 DictionarySize;
+ UInt32 DictionaryPos;
+ UInt32 GlobalPos;
+ UInt32 Reps[4];
+ int lc;
+ int lp;
+ int pb;
+ int State;
+ int RemainLen;
+ Byte TempDictionary[4];
+} LzmaVarState;
+
+int LzmaDecoderInit(
+ unsigned char *buffer, UInt32 bufferSize,
+ int lc, int lp, int pb,
+ unsigned char *dictionary, UInt32 dictionarySize,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback
+ #else
+ unsigned char *inStream, UInt32 inSize
+ #endif
+ )
+{
+ Byte *Buffer;
+ Byte *BufferLim;
+ UInt32 Range;
+ UInt32 Code;
+ LzmaVarState *vs = (LzmaVarState *)buffer;
+ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
+ UInt32 i;
+ if (bufferSize < numProbs * sizeof(CProb) + sizeof(LzmaVarState))
+ return LZMA_RESULT_NOT_ENOUGH_MEM;
+ vs->Dictionary = dictionary;
+ vs->DictionarySize = dictionarySize;
+ vs->DictionaryPos = 0;
+ vs->GlobalPos = 0;
+ vs->Reps[0] = vs->Reps[1] = vs->Reps[2] = vs->Reps[3] = 1;
+ vs->lc = lc;
+ vs->lp = lp;
+ vs->pb = pb;
+ vs->State = 0;
+ vs->RemainLen = 0;
+ dictionary[dictionarySize - 1] = 0;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+
+ #ifdef _LZMA_IN_CB
+ RC_INIT;
+ #else
+ RC_INIT(inStream, inSize);
+ #endif
+ vs->Buffer = Buffer;
+ vs->BufferLim = BufferLim;
+ vs->Range = Range;
+ vs->Code = Code;
+ #ifdef _LZMA_IN_CB
+ vs->InCallback = InCallback;
+ #endif
+
+ return LZMA_RESULT_OK;
+}
+
+int LzmaDecode(unsigned char *buffer,
+ unsigned char *outStream, UInt32 outSize,
+ UInt32 *outSizeProcessed)
+{
+ LzmaVarState *vs = (LzmaVarState *)buffer;
+ Byte *Buffer = vs->Buffer;
+ Byte *BufferLim = vs->BufferLim;
+ UInt32 Range = vs->Range;
+ UInt32 Code = vs->Code;
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback = vs->InCallback;
+ #endif
+ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
+ int state = vs->State;
+ Byte previousByte;
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+ UInt32 nowPos = 0;
+ UInt32 posStateMask = (1 << (vs->pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->lp)) - 1;
+ int lc = vs->lc;
+ int len = vs->RemainLen;
+ UInt32 globalPos = vs->GlobalPos;
+
+ Byte *dictionary = vs->Dictionary;
+ UInt32 dictionarySize = vs->DictionarySize;
+ UInt32 dictionaryPos = vs->DictionaryPos;
+
+ Byte tempDictionary[4];
+ if (dictionarySize == 0)
+ {
+ dictionary = tempDictionary;
+ dictionarySize = 1;
+ tempDictionary[0] = vs->TempDictionary[0];
+ }
+
+ if (len == -1)
+ {
+ *outSizeProcessed = 0;
+ return LZMA_RESULT_OK;
+ }
+
+ while(len != 0 && nowPos < outSize)
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ }
+ if (dictionaryPos == 0)
+ previousByte = dictionary[dictionarySize - 1];
+ else
+ previousByte = dictionary[dictionaryPos - 1];
+#else
+
+int LzmaDecode(
+ Byte *buffer, UInt32 bufferSize,
+ int lc, int lp, int pb,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback,
+ #else
+ unsigned char *inStream, UInt32 inSize,
+ #endif
+ unsigned char *outStream, UInt32 outSize,
+ UInt32 *outSizeProcessed)
+{
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
+ CProb *p = (CProb *)buffer;
+
+ UInt32 i;
+ int state = 0;
+ Byte previousByte = 0;
+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+ UInt32 nowPos = 0;
+ UInt32 posStateMask = (1 << pb) - 1;
+ UInt32 literalPosMask = (1 << lp) - 1;
+ int len = 0;
+
+ Byte *Buffer;
+ Byte *BufferLim;
+ UInt32 Range;
+ UInt32 Code;
+
+ if (bufferSize < numProbs * sizeof(CProb))
+ return LZMA_RESULT_NOT_ENOUGH_MEM;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+
+
+ #ifdef _LZMA_IN_CB
+ RC_INIT;
+ #else
+ RC_INIT(inStream, inSize);
+ #endif
+#endif
+
+ *outSizeProcessed = 0;
+ while(nowPos < outSize)
+ {
+ CProb *prob;
+ UInt32 bound;
+ int posState = (int)(
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & posStateMask);
+
+ prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ int symbol = 1;
+ UpdateBit0(prob)
+ prob = p + Literal + (LZMA_LIT_SIZE *
+ (((
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state >= kNumLitStates)
+ {
+ int matchByte;
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ matchByte = dictionary[pos];
+ #else
+ matchByte = outStream[nowPos - rep0];
+ #endif
+ do
+ {
+ int bit;
+ CProb *probLit;
+ matchByte <<= 1;
+ bit = (matchByte & 0x100);
+ probLit = prob + 0x100 + bit + symbol;
+ RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
+ }
+ while (symbol < 0x100);
+ }
+ while (symbol < 0x100)
+ {
+ CProb *probLit = prob + symbol;
+ RC_GET_BIT(probLit, symbol)
+ }
+ previousByte = (Byte)symbol;
+
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #endif
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRep + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < kNumLitStates ? 0 : 3;
+ prob = p + LenCoder;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG0 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos;
+ #endif
+ UpdateBit0(prob);
+ if (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ == 0)
+ return LZMA_RESULT_DATA_ERROR;
+ state = state < kNumLitStates ? 9 : 11;
+ #ifdef _LZMA_OUT_READ
+ pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+ continue;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ UpdateBit1(prob);
+ prob = p + IsRepG1 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep1;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG2 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep2;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ state = state < kNumLitStates ? 8 : 11;
+ prob = p + RepLenCoder;
+ }
+ {
+ int numBits, offset;
+ CProb *probLen = prob + LenChoice;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenLow + (posState << kLenNumLowBits);
+ offset = 0;
+ numBits = kLenNumLowBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenChoice2;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenMid + (posState << kLenNumMidBits);
+ offset = kLenNumLowSymbols;
+ numBits = kLenNumMidBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenHigh;
+ offset = kLenNumLowSymbols + kLenNumMidSymbols;
+ numBits = kLenNumHighBits;
+ }
+ }
+ RangeDecoderBitTreeDecode(probLen, numBits, len);
+ len += offset;
+ }
+
+ if (state < 4)
+ {
+ int posSlot;
+ state += kNumLitStates;
+ prob = p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits);
+ RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = (2 | ((UInt32)posSlot & 1));
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 <<= numDirectBits;
+ prob = p + SpecPos + rep0 - posSlot - 1;
+ }
+ else
+ {
+ numDirectBits -= kNumAlignBits;
+ do
+ {
+ RC_NORMALIZE
+ Range >>= 1;
+ rep0 <<= 1;
+ if (Code >= Range)
+ {
+ Code -= Range;
+ rep0 |= 1;
+ }
+ }
+ while (--numDirectBits != 0);
+ prob = p + Align;
+ rep0 <<= kNumAlignBits;
+ numDirectBits = kNumAlignBits;
+ }
+ {
+ int i = 1;
+ int mi = 1;
+ do
+ {
+ CProb *prob3 = prob + mi;
+ RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
+ i <<= 1;
+ }
+ while(--numDirectBits != 0);
+ }
+ }
+ else
+ rep0 = posSlot;
+ if (++rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = -1;
+ break;
+ }
+ }
+
+ len += kMatchMinLen;
+ if (rep0 > nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos || rep0 > dictionarySize
+ #endif
+ )
+ return LZMA_RESULT_DATA_ERROR;
+ do
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ len--;
+ outStream[nowPos++] = previousByte;
+ }
+ while(len != 0 && nowPos < outSize);
+ }
+ }
+ RC_NORMALIZE;
+
+ #ifdef _LZMA_OUT_READ
+ vs->Buffer = Buffer;
+ vs->BufferLim = BufferLim;
+ vs->Range = Range;
+ vs->Code = Code;
+ vs->DictionaryPos = dictionaryPos;
+ vs->GlobalPos = globalPos + nowPos;
+ vs->Reps[0] = rep0;
+ vs->Reps[1] = rep1;
+ vs->Reps[2] = rep2;
+ vs->Reps[3] = rep3;
+ vs->State = state;
+ vs->RemainLen = len;
+ vs->TempDictionary[0] = tempDictionary[0];
+ #endif
+
+ *outSizeProcessed = nowPos;
+ return LZMA_RESULT_OK;
+}
diff --git a/target/linux/rdc/files-2.6.24/arch/x86/boot/compressed/LzmaDecode.h b/target/linux/rdc/files-2.6.24/arch/x86/boot/compressed/LzmaDecode.h
new file mode 100644
index 000000000..53677350a
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/arch/x86/boot/compressed/LzmaDecode.h
@@ -0,0 +1,100 @@
+/*
+ LzmaDecode.h
+ LZMA Decoder interface
+
+ LZMA SDK 4.16 Copyright (c) 1999-2005 Igor Pavlov (2005-03-18)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMADECODE_H
+#define __LZMADECODE_H
+
+/* #define _LZMA_IN_CB */
+/* Use callback for input data */
+
+/* #define _LZMA_OUT_READ */
+/* Use read function for output data */
+
+/* #define _LZMA_PROB32 */
+/* It can increase speed on some 32-bit CPUs,
+ but memory usage will be doubled in that case */
+
+/* #define _LZMA_LOC_OPT */
+/* Enable local speed optimizations inside code */
+
+#ifndef UInt32
+#ifdef _LZMA_UINT32_IS_ULONG
+#define UInt32 unsigned long
+#else
+#define UInt32 unsigned int
+#endif
+#endif
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb unsigned short
+#endif
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+#define LZMA_RESULT_NOT_ENOUGH_MEM 2
+
+#ifdef _LZMA_IN_CB
+typedef struct _ILzmaInCallback
+{
+ int (*Read)(void *object, unsigned char **buffer, UInt32 *bufferSize);
+} ILzmaInCallback;
+#endif
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+/*
+bufferSize = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)))* sizeof(CProb)
+bufferSize += 100 in case of _LZMA_OUT_READ
+by default CProb is unsigned short,
+but if specify _LZMA_PROB_32, CProb will be UInt32(unsigned int)
+*/
+
+#ifdef _LZMA_OUT_READ
+int LzmaDecoderInit(
+ unsigned char *buffer, UInt32 bufferSize,
+ int lc, int lp, int pb,
+ unsigned char *dictionary, UInt32 dictionarySize,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback
+ #else
+ unsigned char *inStream, UInt32 inSize
+ #endif
+);
+#endif
+
+int LzmaDecode(
+ unsigned char *buffer,
+ #ifndef _LZMA_OUT_READ
+ UInt32 bufferSize,
+ int lc, int lp, int pb,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback,
+ #else
+ unsigned char *inStream, UInt32 inSize,
+ #endif
+ #endif
+ unsigned char *outStream, UInt32 outSize,
+ UInt32 *outSizeProcessed);
+
+#endif
diff --git a/target/linux/rdc/files-2.6.24/arch/x86/boot/compressed/lzma_misc.c b/target/linux/rdc/files-2.6.24/arch/x86/boot/compressed/lzma_misc.c
new file mode 100644
index 000000000..bd74cb794
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/arch/x86/boot/compressed/lzma_misc.c
@@ -0,0 +1,345 @@
+/*
+ * lzma_misc.c
+ *
+ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
+ * puts by Nick Holloway 1993, better puts by Martin Mares 1995
+ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
+ *
+ * Decompress LZMA compressed vmlinuz
+ * Version 0.9 Copyright (c) Ming-Ching Tiew mctiew@yahoo.com
+ * Program adapted from misc.c for 2.6 kernel
+ * Forward ported to latest 2.6 version of misc.c by
+ * Felix Fietkau <nbd@openwrt.org>
+ */
+
+#undef CONFIG_PARAVIRT
+#include <linux/linkage.h>
+#include <linux/vmalloc.h>
+#include <linux/screen_info.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/boot.h>
+
+/* WARNING!!
+ * This code is compiled with -fPIC and it is relocated dynamically
+ * at run time, but no relocation processing is performed.
+ * This means that it is not safe to place pointers in static structures.
+ */
+
+/*
+ * Getting to provable safe in place decompression is hard.
+ * Worst case behaviours need to be analized.
+ * Background information:
+ *
+ * The file layout is:
+ * magic[2]
+ * method[1]
+ * flags[1]
+ * timestamp[4]
+ * extraflags[1]
+ * os[1]
+ * compressed data blocks[N]
+ * crc[4] orig_len[4]
+ *
+ * resulting in 18 bytes of non compressed data overhead.
+ *
+ * Files divided into blocks
+ * 1 bit (last block flag)
+ * 2 bits (block type)
+ *
+ * 1 block occurs every 32K -1 bytes or when there 50% compression has been achieved.
+ * The smallest block type encoding is always used.
+ *
+ * stored:
+ * 32 bits length in bytes.
+ *
+ * fixed:
+ * magic fixed tree.
+ * symbols.
+ *
+ * dynamic:
+ * dynamic tree encoding.
+ * symbols.
+ *
+ *
+ * The buffer for decompression in place is the length of the
+ * uncompressed data, plus a small amount extra to keep the algorithm safe.
+ * The compressed data is placed at the end of the buffer. The output
+ * pointer is placed at the start of the buffer and the input pointer
+ * is placed where the compressed data starts. Problems will occur
+ * when the output pointer overruns the input pointer.
+ *
+ * The output pointer can only overrun the input pointer if the input
+ * pointer is moving faster than the output pointer. A condition only
+ * triggered by data whose compressed form is larger than the uncompressed
+ * form.
+ *
+ * The worst case at the block level is a growth of the compressed data
+ * of 5 bytes per 32767 bytes.
+ *
+ * The worst case internal to a compressed block is very hard to figure.
+ * The worst case can at least be boundined by having one bit that represents
+ * 32764 bytes and then all of the rest of the bytes representing the very
+ * very last byte.
+ *
+ * All of which is enough to compute an amount of extra data that is required
+ * to be safe. To avoid problems at the block level allocating 5 extra bytes
+ * per 32767 bytes of data is sufficient. To avoind problems internal to a block
+ * adding an extra 32767 bytes (the worst case uncompressed block size) is
+ * sufficient, to ensure that in the worst case the decompressed data for
+ * block will stop the byte before the compressed data for a block begins.
+ * To avoid problems with the compressed data's meta information an extra 18
+ * bytes are needed. Leading to the formula:
+ *
+ * extra_bytes = (uncompressed_size >> 12) + 32768 + 18 + decompressor_size.
+ *
+ * Adding 8 bytes per 32K is a bit excessive but much easier to calculate.
+ * Adding 32768 instead of 32767 just makes for round numbers.
+ * Adding the decompressor_size is necessary as it musht live after all
+ * of the data as well. Last I measured the decompressor is about 14K.
+ * 10K of actuall data and 4K of bss.
+ *
+ */
+
+/*
+ * gzip declarations
+ */
+
+#define OF(args) args
+#define STATIC static
+
+#undef memcpy
+
+typedef unsigned char uch;
+typedef unsigned short ush;
+typedef unsigned long ulg;
+
+#define WSIZE 0x80000000 /* Window size must be at least 32k,
+ * and a power of two
+ * We don't actually have a window just
+ * a huge output buffer so I report
+ * a 2G windows size, as that should
+ * always be larger than our output buffer.
+ */
+
+static uch *inbuf; /* input buffer */
+static uch *window; /* Sliding window buffer, (and final output buffer) */
+
+static unsigned insize; /* valid bytes in inbuf */
+static unsigned inptr; /* index of next byte to be processed in inbuf */
+static unsigned long workspace;
+
+#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+
+/* Diagnostic functions */
+#ifdef DEBUG
+# define Assert(cond,msg) {if(!(cond)) error(msg);}
+# define Trace(x) fprintf x
+# define Tracev(x) {if (verbose) fprintf x ;}
+# define Tracevv(x) {if (verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+# define Assert(cond,msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+#endif
+
+static int fill_inbuf(void);
+
+/*
+ * This is set up by the setup-routine at boot-time
+ */
+static unsigned char *real_mode; /* Pointer to real-mode data */
+extern unsigned char input_data[];
+extern int input_len;
+
+static void error(char *x);
+static void *memcpy(void *dest, const void *src, unsigned n);
+
+#ifdef CONFIG_X86_NUMAQ
+void *xquad_portio;
+#endif
+
+static void* memcpy(void* dest, const void* src, unsigned n)
+{
+ int i;
+ char *d = (char *)dest, *s = (char *)src;
+
+ for (i=0;i<n;i++) d[i] = s[i];
+ return dest;
+}
+
+/* ===========================================================================
+ * Fill the input buffer. This is called only when the buffer is empty
+ * and at least one byte is really needed.
+ */
+static int fill_inbuf(void)
+{
+ error("ran out of input data");
+ return 0;
+}
+
+
+// When using LZMA in callback, the compressed length is not needed.
+// Otherwise you need a special version of lzma compression program
+// which will pad the compressed length in the header.
+#define _LZMA_IN_CB
+#include "LzmaDecode.h"
+#include "LzmaDecode.c"
+
+static int read_byte(void *object, unsigned char **buffer, UInt32 *bufferSize);
+
+static int early_serial_base = 0x3f8; /* ttyS0 */
+
+#define XMTRDY 0x20
+
+#define DLAB 0x80
+
+#define TXR 0 /* Transmit register (WRITE) */
+#define RXR 0 /* Receive register (READ) */
+#define IER 1 /* Interrupt Enable */
+#define IIR 2 /* Interrupt ID */
+#define FCR 2 /* FIFO control */
+#define LCR 3 /* Line control */
+#define MCR 4 /* Modem control */
+#define LSR 5 /* Line Status */
+#define MSR 6 /* Modem Status */
+#define DLL 0 /* Divisor Latch Low */
+#define DLH 1 /* Divisor latch High */
+
+static int early_serial_putc(unsigned char ch)
+{
+ unsigned timeout = 0xffff;
+ while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
+ cpu_relax();
+ outb(ch, early_serial_base + TXR);
+ return timeout ? 0 : -1;
+}
+
+static void early_serial_write(const char *s, unsigned n)
+{
+ while (*s && n-- > 0) {
+ if (*s == '\n')
+ early_serial_putc('\r');
+ early_serial_putc(*s);
+ s++;
+ }
+}
+
+#define DEFAULT_BAUD 38400
+
+static __init void early_serial_init(void)
+{
+ unsigned char c;
+ unsigned divisor;
+ unsigned baud = DEFAULT_BAUD;
+ char *e;
+
+ outb(0x3, early_serial_base + LCR); /* 8n1 */
+ outb(0, early_serial_base + IER); /* no interrupt */
+ outb(0, early_serial_base + FCR); /* no fifo */
+ outb(0x3, early_serial_base + MCR); /* DTR + RTS */
+
+ baud = DEFAULT_BAUD;
+
+ divisor = 115200 / baud;
+ c = inb(early_serial_base + LCR);
+ outb(c | DLAB, early_serial_base + LCR);
+ outb(divisor & 0xff, early_serial_base + DLL);
+ outb((divisor >> 8) & 0xff, early_serial_base + DLH);
+ outb(c & ~DLAB, early_serial_base + LCR);
+}
+
+/*
+ * Do the lzma decompression
+ * When using LZMA in callback, the end of input stream is automatically determined
+ */
+static int lzma_unzip(void)
+{
+
+ unsigned int i; /* temp value */
+ unsigned int lc; /* literal context bits */
+ unsigned int lp; /* literal pos state bits */
+ unsigned int pb; /* pos state bits */
+ unsigned int uncompressedSize = 0;
+ unsigned char* p;
+
+ ILzmaInCallback callback;
+ callback.Read = read_byte;
+
+ /* lzma args */
+ i = get_byte();
+ lc = i % 9, i = i / 9;
+ lp = i % 5, pb = i / 5;
+
+ /* skip dictionary size */
+ for (i = 0; i < 4; i++)
+ get_byte();
+ // get uncompressedSize
+ p= (char*)&uncompressedSize;
+ for (i = 0; i < 4; i++)
+ *p++ = get_byte();
+
+ //get compressedSize
+ for (i = 0; i < 4; i++)
+ get_byte();
+
+ // point it beyond uncompresedSize
+ //workspace = window + uncompressedSize;
+
+ /* decompress kernel */
+ if (LzmaDecode((unsigned char*)workspace, ~0, lc, lp, pb, &callback,
+ (unsigned char*)window, uncompressedSize, &i) == LZMA_RESULT_OK)
+ return 0;
+ else
+ return 1;
+}
+
+
+#ifdef _LZMA_IN_CB
+static int read_byte(void *object, unsigned char **buffer, UInt32 *bufferSize)
+{
+ static unsigned int i = 0;
+ static unsigned char val;
+ *bufferSize = 1;
+ val = get_byte();
+ *buffer = &val;
+ return LZMA_RESULT_OK;
+}
+#endif
+
+static void error(char *x)
+{
+ while(1); /* Halt */
+}
+
+asmlinkage void decompress_kernel(void *rmode, unsigned long end,
+ uch *input_data, unsigned long input_len, uch *output)
+{
+ real_mode = rmode;
+
+ window = output;
+ inbuf = input_data; /* Input buffer */
+ insize = input_len;
+ inptr = 0;
+
+ if ((u32)output & (CONFIG_PHYSICAL_ALIGN -1))
+ error("Destination address not CONFIG_PHYSICAL_ALIGN aligned");
+ if ((workspace = end) > ((-__PAGE_OFFSET-(512 <<20)-1) & 0x7fffffff))
+ error("Destination address too large");
+#ifndef CONFIG_RELOCATABLE
+ if ((u32)output != LOAD_PHYSICAL_ADDR)
+ error("Wrong destination address");
+#endif
+ early_serial_init();
+ early_serial_write("Uncompressing Linux\n", 512);
+ lzma_unzip();
+ early_serial_write("Done, booting\n", 512);
+ return;
+}
diff --git a/target/linux/rdc/files-2.6.24/arch/x86/kernel/cpu/rdc.c b/target/linux/rdc/files-2.6.24/arch/x86/kernel/cpu/rdc.c
new file mode 100644
index 000000000..f4b9083bf
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/arch/x86/kernel/cpu/rdc.c
@@ -0,0 +1,24 @@
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+
+#include "cpu.h"
+
+static struct cpu_dev rdc_cpu_dev __cpuinitdata = {
+ .c_vendor = "RDC",
+ .c_models = {
+ { .vendor = X86_VENDOR_RDC, .family = 4, .model_names =
+ {
+ [0] = "R861x(-G)",
+ }
+ },
+ },
+};
+
+int __init rdc_init_cpu(void)
+{
+ cpu_devs[X86_VENDOR_RDC] = &rdc_cpu_dev;
+ return 0;
+}
diff --git a/target/linux/rdc/files-2.6.24/arch/x86/mach-rdc/Makefile b/target/linux/rdc/files-2.6.24/arch/x86/mach-rdc/Makefile
new file mode 100644
index 000000000..5961bc791
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/arch/x86/mach-rdc/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the RDC321x specific parts of the kernel
+#
+obj-$(CONFIG_X86_RDC) := gpio.o platform.o wdt.o
+
diff --git a/target/linux/rdc/files-2.6.24/arch/x86/mach-rdc/gpio.c b/target/linux/rdc/files-2.6.24/arch/x86/mach-rdc/gpio.c
new file mode 100644
index 000000000..dbd03270f
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/arch/x86/mach-rdc/gpio.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2007, OpenWrt.org, Florian Fainelli <florian@openwrt.org>
+ * RDC321x architecture specific GPIO support
+ *
+ * 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/autoconf.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+
+#include <asm/mach-rdc/rdc321x_defs.h>
+
+static inline int rdc_gpio_is_valid(unsigned gpio)
+{
+ return (gpio <= RDC_MAX_GPIO);
+}
+
+static unsigned int rdc_gpio_read(unsigned gpio)
+{
+ unsigned int val;
+
+ val = 0x80000000 | (7 << 11) | ((gpio&0x20?0x84:0x48));
+ outl(val, RDC3210_CFGREG_ADDR);
+ udelay(10);
+ val = inl(RDC3210_CFGREG_DATA);
+ val |= (0x1 << (gpio & 0x1F));
+ outl(val, RDC3210_CFGREG_DATA);
+ udelay(10);
+ val = 0x80000000 | (7 << 11) | ((gpio&0x20?0x88:0x4C));
+ outl(val, RDC3210_CFGREG_ADDR);
+ udelay(10);
+ val = inl(RDC3210_CFGREG_DATA);
+
+ return val;
+}
+
+static void rdc_gpio_write(unsigned int val)
+{
+ if (val) {
+ outl(val, RDC3210_CFGREG_DATA);
+ udelay(10);
+ }
+}
+
+int rdc_gpio_get_value(unsigned gpio)
+{
+ if (rdc_gpio_is_valid(gpio))
+ return (int)rdc_gpio_read(gpio);
+ else
+ return -EINVAL;
+}
+EXPORT_SYMBOL(rdc_gpio_get_value);
+
+void rdc_gpio_set_value(unsigned gpio, int value)
+{
+ unsigned int val;
+
+ if (!rdc_gpio_is_valid(gpio))
+ return;
+
+ val = rdc_gpio_read(gpio);
+
+ if (value)
+ val &= ~(0x1 << (gpio & 0x1F));
+ else
+ val |= (0x1 << (gpio & 0x1F));
+
+ rdc_gpio_write(val);
+}
+EXPORT_SYMBOL(rdc_gpio_set_value);
+
+int rdc_gpio_direction_input(unsigned gpio)
+{
+ return 0;
+}
+EXPORT_SYMBOL(rdc_gpio_direction_input);
+
+int rdc_gpio_direction_output(unsigned gpio, int value)
+{
+ return 0;
+}
+EXPORT_SYMBOL(rdc_gpio_direction_output);
+
+
diff --git a/target/linux/rdc/files-2.6.24/arch/x86/mach-rdc/platform.c b/target/linux/rdc/files-2.6.24/arch/x86/mach-rdc/platform.c
new file mode 100644
index 000000000..86981f844
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/arch/x86/mach-rdc/platform.c
@@ -0,0 +1,263 @@
+/*
+ *
+ * Generic RDC321x platform devices
+ *
+ * Copyright (C) 2007-2008 OpenWrt.org
+ * Copyright (C) 2007 Florian Fainelli <florian@openwrt.org>
+ * Copyright (C) 2008 Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/version.h>
+#include <linux/leds.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/physmap.h>
+#include <linux/root_dev.h>
+#include <asm/gpio.h>
+
+/* Flash */
+#ifdef CONFIG_MTD_RDC3210
+static struct resource rdc_flash_resource[] = {
+ [0] = {
+ .start = (u32)-CONFIG_MTD_RDC3210_SIZE,
+ .end = (u32)-1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device rdc_flash_device = {
+ .name = "rdc321x-flash",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rdc_flash_resource),
+ .resource = rdc_flash_resource,
+};
+#else
+static struct mtd_partition rdc_flash_parts[15];
+
+static struct resource rdc_flash_resource = {
+ .end = (u32)-1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct physmap_flash_data rdc_flash_data = {
+ .parts = rdc_flash_parts,
+};
+
+static struct platform_device rdc_flash_device = {
+ .name = "physmap-flash",
+ .id = -1,
+ .resource = &rdc_flash_resource,
+ .num_resources = 1,
+ .dev.platform_data = &rdc_flash_data,
+};
+#endif
+
+/* LEDS */
+static struct gpio_led default_leds[] = {
+ { .name = "rdc321x:dmz", .gpio = 1, },
+};
+
+static struct gpio_led_platform_data rdc321x_led_data = {
+ .num_leds = ARRAY_SIZE(default_leds),
+ .leds = default_leds,
+};
+
+static struct platform_device rdc321x_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &rdc321x_led_data,
+ }
+};
+
+/* Watchdog */
+static struct platform_device rdc321x_wdt = {
+ .name = "rdc321x-wdt",
+ .id = -1,
+ .num_resources = 0,
+};
+
+/* Button */
+static struct gpio_keys_button rdc321x_gpio_btn[] = {
+ {
+ .gpio = 0,
+ .code = BTN_0,
+ .desc = "Reset",
+ .active_low = 1,
+ }
+};
+
+static struct gpio_keys_platform_data rdc321x_gpio_btn_data = {
+ .buttons = rdc321x_gpio_btn,
+ .nbuttons = ARRAY_SIZE(rdc321x_gpio_btn),
+};
+
+static struct platform_device rdc321x_button = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &rdc321x_gpio_btn_data,
+ }
+};
+
+static struct platform_device *rdc321x_devs[] = {
+ &rdc_flash_device,
+ &rdc321x_leds,
+ &rdc321x_wdt,
+ &rdc321x_button
+};
+
+static int probe_flash_start(struct map_info *the_map)
+{
+ struct mtd_info *res;
+
+ the_map->virt = ioremap(the_map->phys, the_map->size);
+ if (the_map->virt == NULL)
+ return 1;
+ for (the_map->bankwidth = 32; the_map->bankwidth; the_map->bankwidth
+ >>= 1) {
+ res = do_map_probe("cfi_probe", the_map);
+ if (res == NULL)
+ res = do_map_probe("jedec_probe", the_map);
+ if (res != NULL)
+ break;
+ }
+ iounmap(the_map->virt);
+ if (res != NULL)
+ the_map->phys = (u32)-(s32)(the_map->size = res->size);
+ return res == NULL;
+}
+
+static __init int rdc_board_setup(void)
+{
+#ifndef CONFIG_MTD_RDC3210
+ struct map_info rdc_map_info;
+ u32 the_header[4];
+
+ ROOT_DEV = 0;
+ rdc_map_info.name = rdc_flash_device.name;
+ rdc_map_info.phys = 0xff000000;
+ rdc_map_info.size = 0x1000000;
+ rdc_map_info.bankwidth = 2;
+ rdc_map_info.set_vpp = NULL;
+ simple_map_init(&rdc_map_info);
+ while (probe_flash_start(&rdc_map_info)) {
+ rdc_map_info.phys++;
+ if (--rdc_map_info.size)
+ panic("Not to be or to be: That"
+ " is not the question.");
+ }
+ rdc_flash_resource.start = rdc_map_info.phys;
+ rdc_flash_data.width = rdc_map_info.bankwidth;
+ rdc_map_info.virt = (u32)ioremap_nocache(rdc_map_info.phys, 0x10);
+ if (rdc_map_info.virt == NULL)
+ panic("Something's rotten in Denmark!");
+ the_header[0] = ((u32 *)rdc_map_info.virt)[0];
+ the_header[1] = ((u32 *)rdc_map_info.virt)[1];
+ the_header[2] = ((u32 *)rdc_map_info.virt)[2];
+ the_header[3] = ((u32 *)rdc_map_info.virt)[3];
+ iounmap(rdc_map_info.virt);
+ if (!memcmp(the_header, "GMTK", 4)) { /* Gemtek */
+ /* TODO */
+ } else if (!memcmp(the_header, "CSYS", 4)) { /* Sitecom */
+ /* TODO */
+ } else if (!memcmp(((u8 *)the_header) + 14, "Li", 2)) { /* AMIT */
+ rdc_flash_parts[0].name = "kernel_parthdr";
+ rdc_flash_parts[0].offset = 0;
+ rdc_flash_parts[0].size = 0x10;
+ rdc_flash_parts[1].name = "kernel";
+ rdc_flash_parts[1].offset = 0x10;
+ rdc_flash_parts[1].size = 0xffff0;
+ rdc_flash_parts[2].name = "rootfs_parthdr";
+ rdc_flash_parts[2].offset = 0x100000;
+ rdc_flash_parts[2].size = 0x10;
+ rdc_flash_parts[3].name = "rootfs";
+ rdc_flash_parts[3].offset = 0x100010;
+ rdc_flash_parts[3].size = rdc_map_info.size - 0x160010;
+ rdc_flash_parts[4].name = "config_parthdr";
+ rdc_flash_parts[4].offset = rdc_map_info.size - 0x60000;
+ rdc_flash_parts[4].size = 0x10;
+ rdc_flash_parts[5].name = "config";
+ rdc_flash_parts[5].offset = rdc_map_info.size - 0x5fff0;
+ rdc_flash_parts[5].size = 0xfff0;
+ rdc_flash_parts[6].name = "recoveryfs_parthdr";
+ rdc_flash_parts[6].offset = rdc_map_info.size - 0x50000;
+ rdc_flash_parts[6].size = 0x10;
+ rdc_flash_parts[7].name = "recoveryfs";
+ rdc_flash_parts[7].offset = rdc_map_info.size - 0x4fff0;
+ rdc_flash_parts[7].size = 0x3fff0;
+ rdc_flash_parts[8].name = "recovery_parthdr";
+ rdc_flash_parts[8].offset = rdc_map_info.size - 0x10000;
+ rdc_flash_parts[8].size = 0x10;
+ rdc_flash_parts[9].name = "recovery";
+ rdc_flash_parts[9].offset = rdc_map_info.size - 0xfff0;
+ rdc_flash_parts[9].size = 0x7ff0;
+ rdc_flash_parts[10].name = "productinfo_parthdr";
+ rdc_flash_parts[10].offset = rdc_map_info.size - 0x8000;
+ rdc_flash_parts[10].size = 0x10;
+ rdc_flash_parts[11].name = "productinfo";
+ rdc_flash_parts[11].offset = rdc_map_info.size - 0x7ff0;
+ rdc_flash_parts[11].size = 0x1ff0;
+ rdc_flash_parts[12].name = "bootloader_parthdr";
+ rdc_flash_parts[12].offset = rdc_map_info.size - 0x6000;
+ rdc_flash_parts[12].size = 0x10;
+ rdc_flash_parts[13].name = "bootloader";
+ rdc_flash_parts[13].offset = rdc_map_info.size - 0x5ff0;
+ rdc_flash_parts[13].size = 0x5ff0;
+ rdc_flash_parts[14].name = "everything";
+ rdc_flash_parts[14].offset = 0;
+ rdc_flash_parts[14].size = rdc_map_info.size;
+ rdc_flash_data.nr_parts = 15;
+ } else { /* ZyXEL */
+ rdc_flash_parts[0].name = "kernel";
+ rdc_flash_parts[0].offset = 0;
+ rdc_flash_parts[0].size = 0x100000;
+ rdc_flash_parts[1].name = "rootfs";
+ rdc_flash_parts[1].offset = 0x100000;
+ rdc_flash_parts[1].size = rdc_map_info.size - 0x140000;
+ rdc_flash_parts[2].name = "linux";
+ rdc_flash_parts[2].offset = 0;
+ rdc_flash_parts[2].size = rdc_map_info.size - 0x40000;
+ rdc_flash_parts[3].name = "config";
+ rdc_flash_parts[3].offset = rdc_map_info.size - 0x40000;
+ rdc_flash_parts[3].size = 0x10000;
+ rdc_flash_parts[4].name = "productinfo";
+ rdc_flash_parts[4].offset = rdc_map_info.size - 0x30000;
+ rdc_flash_parts[4].size = 0x10000;
+ rdc_flash_parts[5].name = "bootloader";
+ rdc_flash_parts[5].offset = rdc_map_info.size - 0x20000;
+ rdc_flash_parts[5].size = 0x20000;
+ rdc_flash_data.nr_parts = 6;
+ }
+#endif
+ return platform_add_devices(rdc321x_devs, ARRAY_SIZE(rdc321x_devs));
+}
+
+#ifdef CONFIG_MTD_RDC3210
+arch_initcall(rdc_board_setup);
+#else
+late_initcall(rdc_board_setup);
+#endif
diff --git a/target/linux/rdc/files-2.6.24/arch/x86/mach-rdc/setup.c b/target/linux/rdc/files-2.6.24/arch/x86/mach-rdc/setup.c
new file mode 100644
index 000000000..ad206c3d0
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/arch/x86/mach-rdc/setup.c
@@ -0,0 +1,14 @@
+/*
+ * Machine specific setup for generic
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/arch_hooks.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+
+char * __init machine_specific_memory_setup(void)
+{
+ return "RDC R-321x";
+}
diff --git a/target/linux/rdc/files-2.6.24/arch/x86/mach-rdc/wdt.c b/target/linux/rdc/files-2.6.24/arch/x86/mach-rdc/wdt.c
new file mode 100644
index 000000000..13b69f68a
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/arch/x86/mach-rdc/wdt.c
@@ -0,0 +1,272 @@
+/*
+ * RDC321x watchdog driver
+ *
+ * Copyright (C) 2007 Florian Fainelli <florian@openwrt.org>
+ *
+ * This driver is highly inspired from the cpu5_wdt driver
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/timer.h>
+#include <linux/completion.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/watchdog.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include <asm/mach-rdc/rdc321x_defs.h>
+
+#define RDC_WDT_MASK 0x80000000 /* Mask */
+#define RDC_WDT_EN 0x00800000 /* Enable bit */
+#define RDC_WDT_WTI 0x00200000 /* Generate a CPU reset/NMI/WDT irq when WDT timeout is reached */
+#define RDC_WDT_RST 0x00100000 /* Reset bit */
+#define RDC_WDT_WIF 0x00040000 /* WDT IRQ Flag */
+#define RDC_WDT_IRT 0x00000100 /* IRQ Routing table */
+#define RDC_WDT_CNT 0x00000001 /* WDT count */
+
+#define RDC_CLS_TMR 0x80003844 /* Clear timer */
+
+#define RDC_WDT_INTERVAL (HZ/10+1)
+
+int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static int ticks = 1000;
+
+/* some device data */
+
+static struct {
+ struct completion stop;
+ volatile int running;
+ struct timer_list timer;
+ volatile int queue;
+ int default_ticks;
+ unsigned long inuse;
+} rdc321x_wdt_device;
+
+/* generic helper functions */
+
+static void rdc321x_wdt_trigger(unsigned long unused)
+{
+ if( rdc321x_wdt_device.running )
+ ticks--;
+
+ /* keep watchdog alive */
+ outl(RDC_WDT_EN|inl(RDC3210_CFGREG_DATA), RDC3210_CFGREG_DATA);
+
+ /* requeue?? */
+ if (rdc321x_wdt_device.queue && ticks)
+ mod_timer(&rdc321x_wdt_device.timer, jiffies + RDC_WDT_INTERVAL);
+ else {
+ /* ticks doesn't matter anyway */
+ complete(&rdc321x_wdt_device.stop);
+ }
+
+}
+
+static void rdc321x_wdt_reset(void)
+{
+ ticks = rdc321x_wdt_device.default_ticks;
+}
+
+static void rdc321x_wdt_start(void)
+{
+ if (!rdc321x_wdt_device.queue) {
+ rdc321x_wdt_device.queue = 1;
+
+ /* Clear the timer */
+ outl(RDC_CLS_TMR, RDC3210_CFGREG_ADDR);
+
+ /* Enable watchdog and set the timeout to 81.92 us */
+ outl(RDC_WDT_EN|RDC_WDT_CNT, RDC3210_CFGREG_DATA);
+
+ mod_timer(&rdc321x_wdt_device.timer, jiffies + RDC_WDT_INTERVAL);
+ }
+
+ /* if process dies, counter is not decremented */
+ rdc321x_wdt_device.running++;
+}
+
+static int rdc321x_wdt_stop(void)
+{
+ if (rdc321x_wdt_device.running)
+ rdc321x_wdt_device.running = 0;
+
+ ticks = rdc321x_wdt_device.default_ticks;
+
+ return -EIO;
+}
+
+/* filesystem operations */
+
+static int rdc321x_wdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(0, &rdc321x_wdt_device.inuse))
+ return -EBUSY;
+
+ return nonseekable_open(inode, file);
+}
+
+static int rdc321x_wdt_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &rdc321x_wdt_device.inuse);
+ return 0;
+}
+
+static int rdc321x_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ unsigned int value;
+ static struct watchdog_info ident =
+ {
+ .options = WDIOF_CARDRESET,
+ .identity = "RDC321x WDT",
+ };
+
+ switch(cmd) {
+ case WDIOC_KEEPALIVE:
+ rdc321x_wdt_reset();
+ break;
+ case WDIOC_GETSTATUS:
+ /* Read the value from the DATA register */
+ value = inl(RDC3210_CFGREG_DATA);
+ if ( copy_to_user(argp, &value, sizeof(int)) )
+ return -EFAULT;
+ break;
+ case WDIOC_GETSUPPORT:
+ if ( copy_to_user(argp, &ident, sizeof(ident)) )
+ return -EFAULT;
+ break;
+ case WDIOC_SETOPTIONS:
+ if ( copy_from_user(&value, argp, sizeof(int)) )
+ return -EFAULT;
+ switch(value) {
+ case WDIOS_ENABLECARD:
+ rdc321x_wdt_start();
+ break;
+ case WDIOS_DISABLECARD:
+ return rdc321x_wdt_stop();
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+static ssize_t rdc321x_wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+ if ( !count )
+ return -EIO;
+
+ rdc321x_wdt_reset();
+
+ return count;
+}
+
+static const struct file_operations rdc321x_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .ioctl = rdc321x_wdt_ioctl,
+ .open = rdc321x_wdt_open,
+ .write = rdc321x_wdt_write,
+ .release = rdc321x_wdt_release,
+};
+
+static struct miscdevice rdc321x_wdt_misc = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &rdc321x_wdt_fops,
+};
+
+static int __devinit rdc321x_wdt_probe(struct platform_device *pdev)
+{
+ int err;
+
+ if ( (err = misc_register(&rdc321x_wdt_misc)) < 0 ) {
+ printk(KERN_ERR PFX "misc_register failed\n");
+ return err;
+ }
+
+ /* Reset the watchdog */
+ outl(RDC_WDT_RST, RDC3210_CFGREG_DATA);
+
+ init_completion(&rdc321x_wdt_device.stop);
+ rdc321x_wdt_device.queue = 0;
+
+ clear_bit(0, &rdc321x_wdt_device.inuse);
+
+ setup_timer(&rdc321x_wdt_device.timer, rdc321x_wdt_trigger, 0);
+
+ rdc321x_wdt_device.default_ticks = ticks;
+
+ printk(KERN_INFO PFX "init success\n");
+
+ return 0;
+}
+
+static int rdc321x_wdt_remove(struct platform_device *pdev)
+{
+ if (rdc321x_wdt_device.queue) {
+ rdc321x_wdt_device.queue = 0;
+ wait_for_completion(&rdc321x_wdt_device.stop);
+ }
+
+ misc_deregister(&rdc321x_wdt_misc);
+
+ return 0;
+}
+
+static struct platform_driver rdc321x_wdt_driver = {
+ .probe = rdc321x_wdt_probe,
+ .remove = rdc321x_wdt_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "rdc321x-wdt",
+ },
+};
+
+static int __init rdc321x_wdt_init(void)
+{
+ return platform_driver_register(&rdc321x_wdt_driver);
+}
+
+static void __exit rdc321x_wdt_exit(void)
+{
+ platform_driver_unregister(&rdc321x_wdt_driver);
+}
+
+module_init(rdc321x_wdt_init);
+module_exit(rdc321x_wdt_exit);
+
+MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
+MODULE_DESCRIPTION("RDC321x watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/target/linux/rdc/files-2.6.24/drivers/mtd/maps/imghdr.h b/target/linux/rdc/files-2.6.24/drivers/mtd/maps/imghdr.h
new file mode 100644
index 000000000..7232b7061
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/drivers/mtd/maps/imghdr.h
@@ -0,0 +1,25 @@
+#ifndef GT_IMGHDR_H
+#define GT_IMGHDR_H
+
+#define GTIMG_MAGIC "GMTK"
+
+/* Product ID */
+#define PID_RTL_AIRGO 1
+#define PID_RTL_RALINK 2
+#define PID_RDC_AIRGO 3
+#define PID_RDC_RALINK 5 /* White Lable */
+
+/* Gemtek */
+typedef struct
+{
+ u8 magic[4]; /* ASICII: GMTK */
+ u32 checksum; /* CRC32 */
+ u32 version; /* x.x.x.x */
+ u32 kernelsz; /* The size of the kernel image */
+ u32 imagesz; /* The length of this image file ( kernel + romfs + this header) */
+ u32 pid; /* Product ID */
+ u32 fastcksum; /* Partial CRC32 on (First(256), medium(256), last(512)) */
+ u32 reserved;
+}gt_imghdr_t;
+
+#endif
diff --git a/target/linux/rdc/files-2.6.24/drivers/mtd/maps/rdc3210.c b/target/linux/rdc/files-2.6.24/drivers/mtd/maps/rdc3210.c
new file mode 100644
index 000000000..e04bb99f1
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/drivers/mtd/maps/rdc3210.c
@@ -0,0 +1,392 @@
+/*******************************************************************
+ * Simple Flash mapping for RDC3210 *
+ * *
+ * 2005.03.23 *
+ * Dante Su (dante_su@gemtek.com.tw) *
+ * Copyright (C) 2005 Gemtek Corporation *
+ *******************************************************************/
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/autoconf.h>
+#include <linux/sched.h>
+#include <linux/squashfs_fs.h>
+
+static struct mtd_info *rdc3210_mtd;
+
+struct map_info rdc3210_map =
+{
+ .name = "RDC3210 Flash",
+ .size = CONFIG_MTD_RDC3210_SIZE,
+ .bankwidth = CONFIG_MTD_RDC3210_BUSWIDTH,
+};
+
+/* Dante: This is the default static mapping, however this is nothing but a hint. (Say dynamic mapping) */
+static struct mtd_partition rdc3210_parts[] =
+{
+#if CONFIG_MTD_RDC3210_SIZE == 0x400000
+ { name: "linux", offset: 0, size: 0x003C0000 }, /* 3840 KB = (Kernel + ROMFS) = (768 KB + 3072 KB) */
+ { name: "romfs", offset: 0x000C0000, size: 0x00300000 }, /* 3072 KB */
+ { name: "nvram", offset: 0x003C0000, size: 0x00010000 }, /* 64 KB */
+#ifdef CONFIG_MTD_RDC3210_FACTORY_PRESENT
+ { name: "factory", offset: 0x003D0000, size: 0x00010000 }, /* 64 KB */
+#endif
+ { name: "bootldr", offset: 0x003E0000, size: 0x00020000 }, /* 128 KB */
+#elif CONFIG_MTD_RDC3210_SIZE == 0x200000
+ { name: "linux", offset: 0x00008000, size: 0x001E8000 },
+ { name: "romfs", offset: 0x000C8000, size: 0x00128000 },
+ { name: "nvram", offset: 0x00000000, size: 0x00008000 }, /* 64 KB */
+#ifdef CONFIG_MTD_RDC3210_FACTORY_PRESENT
+#error Unsupported configuration!
+#endif
+ { name: "bootldr", offset: 0x001F0000, size: 0x00010000 },
+
+#elif CONFIG_MTD_RDC3210_SIZE == 0x800000
+ { name: "linux", offset: 0, size: 0x001F0000 }, /* 1984 KB */
+ { name: "config", offset: 0x001F0000, size: 0x00010000 }, /* 64 KB */
+ { name: "romfs", offset: 0x00200000, size: 0x005D0000 }, /* 5952 KB */
+#ifdef CONFIG_MTD_RDC3210_FACTORY_PRESENT
+ { name: "factory", offset: 0x007D0000, size: 0x00010000 }, /* 64 KB */
+#endif
+ { name: "bootldr", offset: 0x007E0000, size: 0x00010000 }, /* 64 KB */
+#else
+#error Unsupported configuration!
+#endif
+};
+
+static __u32 crctab[257] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+ 0
+};
+
+static __u32 crc32(__u8 * buf, __u32 len)
+{
+ register int i;
+ __u32 sum;
+ register __u32 s0;
+ s0 = ~0;
+ for (i = 0; i < len; i++) {
+ s0 = (s0 >> 8) ^ crctab[(__u8) (s0 & 0xFF) ^ buf[i]];
+ }
+ sum = ~s0;
+ return sum;
+}
+
+static void erase_callback(struct erase_info *done)
+{
+ wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
+ wake_up(wait_q);
+}
+
+static int erase_write (struct mtd_info *mtd, unsigned long pos,
+ int len, const char *buf)
+{
+ struct erase_info erase;
+ DECLARE_WAITQUEUE(wait, current);
+ wait_queue_head_t wait_q;
+ size_t retlen;
+ int ret;
+
+ /*
+ * First, let's erase the flash block.
+ */
+
+ init_waitqueue_head(&wait_q);
+ erase.mtd = mtd;
+ erase.callback = erase_callback;
+ erase.addr = pos;
+ erase.len = len;
+ erase.priv = (u_long)&wait_q;
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(&wait_q, &wait);
+
+ ret = mtd->erase(mtd, &erase);
+ if (ret) {
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&wait_q, &wait);
+ printk (KERN_WARNING "erase of region [0x%lx, 0x%x] "
+ "on \"%s\" failed\n",
+ pos, len, mtd->name);
+ return ret;
+ }
+
+ schedule(); /* Wait for erase to finish. */
+ remove_wait_queue(&wait_q, &wait);
+
+ /*
+ * Next, writhe data to flash.
+ */
+
+ ret = mtd->write (mtd, pos, len, &retlen, buf);
+ if (ret)
+ return ret;
+ if (retlen != len)
+ return -EIO;
+ return 0;
+}
+
+static int __init init_rdc3210_map(void)
+{
+ rdc3210_map.phys = -rdc3210_map.size;
+ printk(KERN_NOTICE "flash device: %x at %x\n", rdc3210_map.size, rdc3210_map.phys);
+
+#if CONFIG_MTD_RDC3210_SIZE == 0x800000
+ simple_map_init(&rdc3210_map);
+#endif
+
+ rdc3210_map.map_priv_1 = (unsigned long)(rdc3210_map.virt = ioremap_nocache(rdc3210_map.phys, rdc3210_map.size));
+
+ if (!rdc3210_map.map_priv_1)
+ {
+ printk("Failed to ioremap\n");
+ return -EIO;
+ }
+ rdc3210_mtd = do_map_probe("cfi_probe", &rdc3210_map);
+#ifdef CONFIG_MTD_RDC3210_STATIC_MAP /* Dante: This is for fixed map */
+ if (rdc3210_mtd)
+ {
+ rdc3210_mtd->owner = THIS_MODULE;
+ add_mtd_partitions(rdc3210_mtd, rdc3210_parts, sizeof(rdc3210_parts)/sizeof(rdc3210_parts[0]));
+ return 0;
+ }
+#else /* Dante: This is for dynamic mapping */
+
+#include "imghdr.h"
+
+ typedef struct {
+ u8 magic[4];
+ u32 kernelsz, ramdisksz;
+ u8 magic2[4];
+ u32 sz2;
+ }sc_imghdr_t;
+
+ if (rdc3210_mtd)
+ { // Dante
+ sc_imghdr_t *hdr2= (sc_imghdr_t *)(rdc3210_map.map_priv_1);
+ gt_imghdr_t *hdr = (gt_imghdr_t *)hdr2
+#ifdef CONFIG_MTD_RDC3210_ALLOW_JFFS2
+ , *ptmp
+#endif
+ ;
+ int len, tmp, tmp2, tmp3, tmp4, hdr_type = 0;
+
+ if(!memcmp(hdr->magic, GTIMG_MAGIC, 4))
+ {
+ hdr_type = 1;
+ tmp = hdr->kernelsz + sizeof(gt_imghdr_t);
+ tmp2 = rdc3210_mtd->erasesize;
+ tmp3 = ((tmp / 32) + ((tmp % 32) ? 1 : 0)) * 32;
+ tmp4 = ((tmp / tmp2) + ((tmp % tmp2) ? 1 : 0)) * tmp2;
+ }
+#ifndef CONFIG_MTD_RDC3210_ALLOW_JFFS2
+ else if (!memcmp(hdr2->magic, "CSYS", 4))
+ {
+ hdr_type = 2;
+ tmp = hdr2->ramdisksz + hdr2->kernelsz + sizeof(sc_imghdr_t);
+ tmp2 = rdc3210_mtd->erasesize;
+ tmp3 = ((tmp / 32) + ((tmp % 32) ? 1 : 0)) * 32;
+ tmp4 = ((tmp / tmp2) + ((tmp % tmp2) ? 1 : 0)) * tmp2;
+ }
+#endif
+ else
+ {
+ iounmap((void *)rdc3210_map.map_priv_1);
+ rdc3210_map.map_priv_1 = 0L;
+ rdc3210_map.virt = NULL;
+ printk("Invalid MAGIC for Firmware Image!!!\n");
+ return -EIO;
+ }
+#ifdef CONFIG_MTD_RDC3210_ALLOW_JFFS2
+ tmp = (tmp3 == tmp4) ? tmp4 + tmp2 : tmp4;
+ if ((ptmp = (gt_imghdr_t *)vmalloc(tmp)) == NULL)
+ {
+ iounmap((void *)rdc3210_map.map_priv_1);
+ rdc3210_map.map_priv_1 = 0L;
+ rdc3210_map.virt = NULL;
+ printk("Can't allocate 0x%08x for flash-reading buffer!\n", tmp);
+ return -ENOMEM;
+ }
+ if (rdc3210_mtd->read(rdc3210_mtd, 0, tmp, &len, (__u8 *)ptmp) || len != tmp)
+ {
+ vfree(ptmp);
+ iounmap((void *)rdc3210_map.map_priv_1);
+ rdc3210_map.map_priv_1 = 0L;
+ rdc3210_map.virt = NULL;
+ printk("Can't read that much flash! Read 0x%08x of it.\n", len);
+ return -EIO;
+ }
+#endif
+#ifdef CONFIG_MTD_RDC3210_FACTORY_PRESENT
+ /* 1. Adjust Redboot */
+ tmp = rdc3210_mtd->size - rdc3210_parts[4].size;
+ rdc3210_parts[4].offset = tmp - (tmp % tmp2);
+ rdc3210_parts[4].size = rdc3210_mtd->size - rdc3210_parts[4].offset;
+
+ /* 2. Adjust Factory Default */
+ tmp -= rdc3210_parts[3].size;
+ rdc3210_parts[3].offset = tmp - (tmp % tmp2);
+ rdc3210_parts[3].size = rdc3210_parts[4].offset - rdc3210_parts[3].offset;
+#else
+ /* 1. Adjust Redboot */
+ tmp = rdc3210_mtd->size - rdc3210_parts[3].size;
+ rdc3210_parts[3].offset = tmp - (tmp % tmp2);
+ rdc3210_parts[3].size = rdc3210_mtd->size - rdc3210_parts[3].offset;
+#endif
+ if (hdr_type == 1) {
+ /* 3. Adjust NVRAM */
+#ifdef CONFIG_MTD_RDC3210_ALLOW_JFFS2
+ if (*(__u32 *)(((unsigned char *)ptmp)+tmp3) == SQUASHFS_MAGIC)
+ {
+ len = 1;
+ tmp4 = tmp3;
+ tmp = hdr->imagesz;
+ rdc3210_parts[2].name = "rootfs_data";
+ rdc3210_parts[2].offset = rdc3210_parts[0].offset + (((tmp / tmp2) + ((tmp % tmp2) ? 1 : 0)) * tmp2);
+ }
+ else
+#else
+ tmp4 = tmp3;
+#endif
+ {
+ len = 0;
+ tmp -= rdc3210_parts[2].size;
+ rdc3210_parts[2].offset = tmp - (tmp % tmp2);
+ }
+ rdc3210_parts[2].size = rdc3210_parts[3].offset - rdc3210_parts[2].offset;
+ }
+ else if (hdr_type == 2)
+ {
+ len = 0;
+ tmp4 = tmp3;
+ }
+
+ /* 4. Adjust Linux (Kernel + ROMFS) */
+ rdc3210_parts[0].size = rdc3210_parts[len + hdr_type + 1].offset - rdc3210_parts[0].offset;
+
+ /* 5. Adjust ROMFS */
+ rdc3210_parts[1].offset = rdc3210_parts[0].offset + tmp4;
+ rdc3210_parts[1].size = rdc3210_parts[hdr_type + 1].offset - rdc3210_parts[1].offset;
+#ifdef CONFIG_MTD_RDC3210_ALLOW_JFFS2
+ if (!(hdr->reserved || len))
+ {
+ __u8 buf[1024];
+ ptmp->reserved = hdr->imagesz;
+ ptmp->imagesz = tmp4;
+ ptmp->checksum = ptmp->fastcksum = 0;
+ memcpy(buf, ptmp, 0x100);
+ memcpy(buf + 0x100, ((__u8 *)ptmp) + ((tmp4 >> 1) - ((tmp4 & 0x6) >> 1)), 0x100);
+ memcpy(buf + 0x200, ((__u8 *)ptmp) + (tmp4 - 0x200), 0x200);
+ ptmp->fastcksum = crc32(buf, sizeof(buf));
+ ptmp->checksum = crc32((__u8 *)ptmp, tmp4);
+ if (rdc3210_mtd->unlock) rdc3210_mtd->unlock(rdc3210_mtd, 0, tmp2);
+ if ((len = erase_write(rdc3210_mtd, 0, tmp2, (char *)ptmp)))
+ {
+ vfree(ptmp);
+ iounmap((void *)rdc3210_map.map_priv_1);
+ rdc3210_map.map_priv_1 = 0L;
+ rdc3210_map.virt = NULL;
+ printk("Couldn't erase! Got %d.\n", len);
+ return len;
+ }
+ if (rdc3210_mtd->sync) rdc3210_mtd->sync(rdc3210_mtd);
+ }
+ vfree(ptmp);
+#endif
+ rdc3210_mtd->owner = THIS_MODULE;
+ add_mtd_partitions(rdc3210_mtd, rdc3210_parts, sizeof(rdc3210_parts)/sizeof(rdc3210_parts[0]));
+ return 0;
+ }
+#endif
+ iounmap((void *)rdc3210_map.map_priv_1);
+ rdc3210_map.map_priv_1 = 0L;
+ rdc3210_map.virt = NULL;
+ return -ENXIO;
+}
+
+static void __exit cleanup_rdc3210_map(void)
+{
+ if (rdc3210_mtd)
+ {
+ del_mtd_partitions(rdc3210_mtd);
+ map_destroy(rdc3210_mtd);
+ }
+
+ if (rdc3210_map.map_priv_1)
+ {
+ iounmap((void *)rdc3210_map.map_priv_1);
+ rdc3210_map.map_priv_1 = 0L;
+ rdc3210_map.virt = NULL;
+ }
+}
+
+module_init(init_rdc3210_map);
+module_exit(cleanup_rdc3210_map);
diff --git a/target/linux/rdc/files-2.6.24/drivers/net/r6040.c b/target/linux/rdc/files-2.6.24/drivers/net/r6040.c
new file mode 100644
index 000000000..009600619
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/drivers/net/r6040.c
@@ -0,0 +1,1412 @@
+/*
+ * RDC R6040 Fast Ethernet MAC support
+ *
+ * Copyright (C) 2004 Sten Wang <sten.wang@rdc.com.tw>
+ * Copyright (C) 2007
+ * Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
+ * Florian Fainelli <florian@openwrt.org>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/crc32.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/uaccess.h>
+
+#include <asm/processor.h>
+
+#define DRV_NAME "r6040"
+#define DRV_VERSION "0.19"
+#define DRV_RELDATE "16Jun2008"
+
+/* define bits of a debug mask */
+#define DBG_PHY 0x00000001 /*!< show PHY read/write */
+#define DBG_FREE_BUFS 0x00000002 /*!< show calls to r6040_free_*bufs */
+#define DBG_RING 0x00000004 /*!< debug init./freeing of descr rings */
+#define DBG_RX_BUF 0x00000008 /*!< show alloc. of new rx buf (in IRQ context !) */
+#define DBG_TX_BUF 0x00000010 /*!< show arrival of new tx buf */
+#define DBG_TX_DONE 0x00000020 /*!< debug TX done */
+#define DBG_RX_DESCR 0x00000040 /*!< debug rx descr to be processed */
+#define DBG_RX_DATA 0x00000080 /*!< show some user data of incoming packet */
+#define DBG_EXIT 0x00000100 /*!< show exit code calls */
+#define DBG_INIT 0x00000200 /*!< show init. code calls */
+#define DBG_TX_RING_DUMP 0x00000400 /*!< dump the tx ring after creation */
+#define DBG_RX_RING_DUMP 0x00000800 /*!< dump the rx ring after creation */
+#define DBG_TX_DESCR 0x00001000 /*!< dump the setting of a descr for tx */
+#define DBG_TX_DATA 0x00002000 /*!< dump some tx data */
+#define DBG_IRQ 0x00004000 /*!< print inside the irq handler */
+#define DBG_POLL 0x00008000 /*!< dump info on poll procedure */
+#define DBG_MAC_ADDR 0x00010000 /*!< debug mac address setting */
+#define DBG_OPEN 0x00020000 /*!< debug open proc. */
+
+static int debug = 0;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "debug mask (-1 for all)");
+
+/* define which debugs are left in the code during compilation */
+#define DEBUG (-1) /* all debugs */
+
+#define dbg(l, f, ...) \
+ do { \
+ if ((DEBUG & l) && (debug & l)) { \
+ printk(KERN_INFO DRV_NAME " %s: " f, __FUNCTION__, ## __VA_ARGS__); \
+ } \
+ } while (0)
+
+#define err(f, ...) printk(KERN_WARNING DRV_NAME " %s: " f, __FUNCTION__, ## __VA_ARGS__)
+
+/* PHY CHIP Address */
+#define PHY1_ADDR 1 /* For MAC1 */
+#define PHY2_ADDR 3 /* For MAC2 */
+#define PHY_MODE 0x3100 /* PHY CHIP Register 0 */
+#define PHY_CAP 0x01E1 /* PHY CHIP Register 4 */
+
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT (6000 * HZ / 1000)
+
+/* RDC MAC I/O Size */
+#define R6040_IO_SIZE 256
+
+/* MAX RDC MAC */
+#define MAX_MAC 2
+
+/* MAC registers */
+#define MCR0 0x00 /* Control register 0 */
+#define MCR1 0x04 /* Control register 1 */
+#define MAC_RST 0x0001 /* Reset the MAC */
+#define MBCR 0x08 /* Bus control */
+#define MT_ICR 0x0C /* TX interrupt control */
+#define MR_ICR 0x10 /* RX interrupt control */
+#define MTPR 0x14 /* TX poll command register */
+#define MR_BSR 0x18 /* RX buffer size */
+#define MR_DCR 0x1A /* RX descriptor control */
+#define MLSR 0x1C /* Last status */
+#define MMDIO 0x20 /* MDIO control register */
+#define MDIO_WRITE 0x4000 /* MDIO write */
+#define MDIO_READ 0x2000 /* MDIO read */
+#define MMRD 0x24 /* MDIO read data register */
+#define MMWD 0x28 /* MDIO write data register */
+#define MTD_SA0 0x2C /* TX descriptor start address 0 */
+#define MTD_SA1 0x30 /* TX descriptor start address 1 */
+#define MRD_SA0 0x34 /* RX descriptor start address 0 */
+#define MRD_SA1 0x38 /* RX descriptor start address 1 */
+#define MISR 0x3C /* Status register */
+#define MIER 0x40 /* INT enable register */
+#define MSK_INT 0x0000 /* Mask off interrupts */
+#define RX_FINISH 0x0001 /* rx finished irq */
+#define RX_NO_DESC 0x0002 /* rx no descr. avail. irq */
+#define RX_FIFO_FULL 0x0004 /* rx fifo full irq */
+#define RX_EARLY 0x0008 /* rx early irq */
+#define TX_FINISH 0x0010 /* tx finished irq */
+#define TX_EARLY 0x0080 /* tx early irq */
+#define EVENT_OVRFL 0x0100 /* event counter overflow irq */
+#define LINK_CHANGED 0x0200 /* PHY link changed irq */
+
+#define ME_CISR 0x44 /* Event counter INT status */
+#define ME_CIER 0x48 /* Event counter INT enable */
+#define MR_CNT 0x50 /* Successfully received packet counter */
+#define ME_CNT0 0x52 /* Event counter 0 */
+#define ME_CNT1 0x54 /* Event counter 1 */
+#define ME_CNT2 0x56 /* Event counter 2 */
+#define ME_CNT3 0x58 /* Event counter 3 */
+#define MT_CNT 0x5A /* Successfully transmit packet counter */
+#define ME_CNT4 0x5C /* Event counter 4 */
+#define MP_CNT 0x5E /* Pause frame counter register */
+#define MAR0 0x60 /* Hash table 0 */
+#define MAR1 0x62 /* Hash table 1 */
+#define MAR2 0x64 /* Hash table 2 */
+#define MAR3 0x66 /* Hash table 3 */
+#define MID_0L 0x68 /* Multicast address MID0 Low */
+#define MID_0M 0x6A /* Multicast address MID0 Medium */
+#define MID_0H 0x6C /* Multicast address MID0 High */
+#define MID_1L 0x70 /* MID1 Low */
+#define MID_1M 0x72 /* MID1 Medium */
+#define MID_1H 0x74 /* MID1 High */
+#define MID_2L 0x78 /* MID2 Low */
+#define MID_2M 0x7A /* MID2 Medium */
+#define MID_2H 0x7C /* MID2 High */
+#define MID_3L 0x80 /* MID3 Low */
+#define MID_3M 0x82 /* MID3 Medium */
+#define MID_3H 0x84 /* MID3 High */
+#define PHY_CC 0x88 /* PHY status change configuration register */
+#define PHY_ST 0x8A /* PHY status register */
+#define MAC_SM 0xAC /* MAC status machine */
+#define MAC_ID 0xBE /* Identifier register */
+
+#define TX_DCNT 0x80 /* TX descriptor count */
+#define RX_DCNT 0x80 /* RX descriptor count */
+#define MAX_BUF_SIZE 0x600
+#define RX_DESC_SIZE (RX_DCNT * sizeof(struct r6040_descriptor))
+#define TX_DESC_SIZE (TX_DCNT * sizeof(struct r6040_descriptor))
+#define MBCR_DEFAULT 0x012A /* MAC Bus Control Register:
+ - wait 1 host clock until SDRAM bus request
+ becomes high priority
+ - RX FIFO: 32 byte
+ - TX FIFO: 64 byte
+ - FIFO transfer length: 16 byte */
+#define MCAST_MAX 4 /* Max number multicast addresses to filter */
+
+/* PHY settings */
+#define ICPLUS_PHY_ID 0x0243
+
+MODULE_AUTHOR("Sten Wang <sten.wang@rdc.com.tw>,"
+ "Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>,"
+ "Florian Fainelli <florian@openwrt.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("RDC R6040 NAPI PCI FastEthernet driver");
+
+/*! which rx interrupts do we allow */
+#define RX_INTS (RX_FIFO_FULL|RX_NO_DESC|RX_FINISH)
+/*! which tx interrupts do we allow */
+#define TX_INTS (TX_FINISH)
+#define INT_MASK (RX_INTS | TX_INTS)
+
+struct r6040_descriptor {
+ u16 status, len; /* 0-3 */
+ __le32 buf; /* 4-7 */
+ __le32 ndesc; /* 8-B */
+ u32 rev1; /* C-F */
+ char *vbufp; /* 10-13 */
+ struct r6040_descriptor *vndescp; /* 14-17 */
+ struct sk_buff *skb_ptr; /* 18-1B */
+ u32 rev2; /* 1C-1F */
+} __attribute__((aligned(32)));
+
+/*! defines for the status field in the r6040_descriptor */
+#define DESC_STATUS_OWNER_MAC (1<<15) /*!< if set the MAC is the owner of this descriptor */
+#define DESC_STATUS_RX_OK (1<<14) /*!< rx was successful */
+#define DESC_STATUS_RX_ERR (1<<11) /*!< rx PHY error */
+#define DESC_STATUS_RX_ERR_DRIBBLE (1<<10) /*!< rx dribble packet */
+#define DESC_STATUS_RX_ERR_BUFLEN (1<< 9) /*!< rx length exceeded buffer size */
+#define DESC_STATUS_RX_ERR_LONG (1<< 8) /*!< rx length > maximum packet length */
+#define DESC_STATUS_RX_ERR_RUNT (1<< 7) /*!< rx: packet length < 64 byte */
+#define DESC_STATUS_RX_ERR_CRC (1<< 6) /*!< rx: crc error */
+#define DESC_STATUS_RX_BROADCAST (1<< 5) /*!< rx: broadcast (no error) */
+#define DESC_STATUS_RX_MULTICAST (1<< 4) /*!< rx: multicast (no error) */
+#define DESC_STATUS_RX_MCH_HIT (1<< 3) /*!< rx: multicast hit in hash table (no error) */
+#define DESC_STATUS_RX_MIDH_HIT (1<< 2) /*!< rx: MID table hit (no error) */
+#define DESC_STATUS_RX_IDX_MID_MASK 3 /*!< rx: mask for the index of matched MIDx */
+
+struct r6040_private {
+ spinlock_t lock; /* driver lock */
+ struct timer_list timer;
+ struct pci_dev *pdev;
+ struct r6040_descriptor *rx_insert_ptr;
+ struct r6040_descriptor *rx_remove_ptr;
+ struct r6040_descriptor *tx_insert_ptr;
+ struct r6040_descriptor *tx_remove_ptr;
+ struct r6040_descriptor *rx_ring;
+ struct r6040_descriptor *tx_ring;
+ dma_addr_t rx_ring_dma;
+ dma_addr_t tx_ring_dma;
+ u16 tx_free_desc, phy_addr, phy_mode;
+ u16 mcr0, mcr1;
+ u16 switch_sig;
+ struct net_device *dev;
+ struct mii_if_info mii_if;
+ struct napi_struct napi;
+ void __iomem *base;
+};
+
+static char *parent = "wlan0";
+module_param(parent, charp, 0444);
+MODULE_PARM_DESC(parent, "Parent network device name to get the MAC address from");
+
+static u8 mac_base[ETH_ALEN] = {0,0x50,0xfc,2,3,4};
+module_param_array(mac_base, byte, NULL, 0444);
+MODULE_PARM_DESC(mac_base, "Starting MAC address");
+
+static int reverse = 1;
+module_param(reverse, invbool, 0444);
+MODULE_PARM_DESC(reverse, "Reverse card indices");
+
+static char version[] __devinitdata = DRV_NAME
+ ": RDC R6040 NAPI net driver,"
+ "version "DRV_VERSION " (" DRV_RELDATE ")";
+
+static int phy_table[] = { PHY1_ADDR, PHY2_ADDR };
+
+/* forward declarations */
+void r6040_multicast_list(struct net_device *dev);
+
+/* jal2: comment out to get more symbols for debugging */
+//#define STATIC static
+#define STATIC
+
+#if DEBUG
+/*! hexdump an memory area into a string. delim is taken as the delimiter between two bytes.
+ It is omitted if delim == '\0' */
+STATIC char *hex2str(void *addr, char *buf, int nr_bytes, int delim)
+{
+ unsigned char *src = addr;
+ char *outb = buf;
+
+#define BIN2HEXDIGIT(x) ((x) < 10 ? '0'+(x) : 'A'-10+(x))
+
+ while (nr_bytes > 0) {
+ *outb++ = BIN2HEXDIGIT(*src>>4);
+ *outb++ = BIN2HEXDIGIT(*src&0xf);
+ if (delim)
+ *outb++ = delim;
+ nr_bytes--;
+ src++;
+ }
+
+ if (delim)
+ outb--;
+ *outb = '\0';
+ return buf;
+}
+
+#endif /* #if DEBUG */
+
+/* Read a word data from PHY Chip */
+STATIC int phy_read(void __iomem *ioaddr, int phy_addr, int reg)
+{
+ int limit = 2048;
+ u16 cmd;
+ int rc;
+
+ iowrite16(MDIO_READ + reg + (phy_addr << 8), ioaddr + MMDIO);
+ /* Wait for the read bit to be cleared */
+ while (limit--) {
+ cmd = ioread16(ioaddr + MMDIO);
+ if (!(cmd & MDIO_READ))
+ break;
+ }
+
+ if (limit <= 0)
+ err("phy addr x%x reg x%x timed out\n",
+ phy_addr, reg);
+
+ rc=ioread16(ioaddr + MMRD);
+
+ dbg(DBG_PHY, "phy addr x%x reg x%x val x%x\n", phy_addr, reg, rc);
+ return rc;
+}
+
+/* Write a word data from PHY Chip */
+STATIC void phy_write(void __iomem *ioaddr, int phy_addr, int reg, u16 val)
+{
+ int limit = 2048;
+ u16 cmd;
+
+ dbg(DBG_PHY, "phy addr x%x reg x%x val x%x\n", phy_addr, reg, val);
+
+ iowrite16(val, ioaddr + MMWD);
+ /* Write the command to the MDIO bus */
+ iowrite16(MDIO_WRITE + reg + (phy_addr << 8), ioaddr + MMDIO);
+ /* Wait for the write bit to be cleared */
+ while (limit--) {
+ cmd = ioread16(ioaddr + MMDIO);
+ if (!(cmd & MDIO_WRITE))
+ break;
+ }
+ if (limit <= 0)
+ err("phy addr x%x reg x%x val x%x timed out\n",
+ phy_addr, reg, val);
+}
+
+STATIC int mdio_read(struct net_device *dev, int mii_id, int reg)
+{
+ struct r6040_private *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
+
+ return (phy_read(ioaddr, lp->phy_addr, reg));
+}
+
+STATIC void mdio_write(struct net_device *dev, int mii_id, int reg, int val)
+{
+ struct r6040_private *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
+
+ phy_write(ioaddr, lp->phy_addr, reg, val);
+}
+
+void r6040_free_txbufs(struct net_device *dev)
+{
+ struct r6040_private *lp = netdev_priv(dev);
+ int i;
+
+ dbg(DBG_FREE_BUFS, "ENTER\n");
+ for (i = 0; i < TX_DCNT; i++) {
+ if (lp->tx_insert_ptr->skb_ptr) {
+ pci_unmap_single(lp->pdev,
+ le32_to_cpu(lp->tx_insert_ptr->buf),
+ MAX_BUF_SIZE, PCI_DMA_TODEVICE);
+ dev_kfree_skb(lp->tx_insert_ptr->skb_ptr);
+ lp->tx_insert_ptr->skb_ptr = NULL;
+ }
+ lp->tx_insert_ptr = lp->tx_insert_ptr->vndescp;
+ }
+ dbg(DBG_FREE_BUFS, "EXIT\n");
+}
+
+/*! unmap and free all rx skb */
+void r6040_free_rxbufs(struct net_device *dev)
+{
+ struct r6040_private *lp = netdev_priv(dev);
+ int i;
+
+ dbg(DBG_FREE_BUFS, "ENTER\n");
+ for (i = 0; i < RX_DCNT; i++) {
+ if (lp->rx_insert_ptr->skb_ptr) {
+ pci_unmap_single(lp->pdev,
+ le32_to_cpu(lp->rx_insert_ptr->buf),
+ MAX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(lp->rx_insert_ptr->skb_ptr);
+ lp->rx_insert_ptr->skb_ptr = NULL;
+ }
+ lp->rx_insert_ptr = lp->rx_insert_ptr->vndescp;
+ }
+ dbg(DBG_FREE_BUFS, "EXIT\n");
+
+}
+
+void r6040_init_ring_desc(struct r6040_descriptor *desc_ring,
+ dma_addr_t desc_dma, int size)
+{
+ struct r6040_descriptor *desc = desc_ring;
+ dma_addr_t mapping = desc_dma;
+
+ dbg(DBG_RING, "desc_ring %p desc_dma %08x size x%x\n",
+ desc_ring, desc_dma, size);
+
+
+ while (size-- > 0) {
+ mapping += sizeof(*desc);
+ memset(desc, 0, sizeof(*desc));
+ desc->ndesc = cpu_to_le32(mapping);
+ desc->vndescp = desc + 1;
+ desc++;
+ }
+
+ /* last descriptor points to first one to close the descriptor ring */
+ desc--;
+ desc->ndesc = cpu_to_le32(desc_dma);
+ desc->vndescp = desc_ring;
+}
+
+#if (DEBUG & DBG_TX_RING_DUMP)
+/*! dump the tx ring to syslog */
+STATIC void
+dump_tx_ring(struct r6040_private *lp)
+{
+ int i;
+ struct r6040_descriptor *ptr;
+
+ printk(KERN_INFO "%s: nr_desc x%x tx_ring %p tx_ring_dma %08x "
+ "tx_insert %p tx_remove %p\n",
+ DRV_NAME, TX_DCNT, lp->tx_ring, lp->tx_ring_dma,
+ lp->tx_insert_ptr, lp->tx_remove_ptr);
+
+ if (lp->tx_ring) {
+ for(i=0, ptr=lp->tx_ring; i < TX_DCNT; i++, ptr++) {
+ printk(KERN_INFO "%s: %d. descr: status x%x len x%x "
+ "ndesc %08x vbufp %p vndescp %p skb_ptr %p\n",
+ DRV_NAME, i, ptr->status, ptr->len,
+ ptr->ndesc, ptr->vbufp, ptr->vndescp, ptr->skb_ptr);
+ }
+ }
+}
+#endif /* #if (DEBUG & DBG_TX_RING_DUMP) */
+
+void r6040_init_txbufs(struct net_device *dev)
+{
+ struct r6040_private *lp = netdev_priv(dev);
+
+ lp->tx_free_desc = TX_DCNT;
+
+ lp->tx_remove_ptr = lp->tx_insert_ptr = lp->tx_ring;
+ r6040_init_ring_desc(lp->tx_ring, lp->tx_ring_dma, TX_DCNT);
+
+#if (DEBUG & DBG_TX_RING_DUMP)
+ if (debug & DBG_TX_RING_DUMP) {
+ dump_tx_ring(lp);
+ }
+#endif
+}
+
+#if (DEBUG & DBG_RX_RING_DUMP)
+/*! dump the rx ring to syslog */
+STATIC void
+dump_rx_ring(struct r6040_private *lp)
+{
+ int i;
+ struct r6040_descriptor *ptr;
+
+ printk(KERN_INFO "%s: nr_desc x%x rx_ring %p rx_ring_dma %08x "
+ "rx_insert %p rx_remove %p\n",
+ DRV_NAME, RX_DCNT, lp->rx_ring, lp->rx_ring_dma,
+ lp->rx_insert_ptr, lp->rx_remove_ptr);
+
+ if (lp->rx_ring) {
+ for(i=0, ptr=lp->rx_ring; i < RX_DCNT; i++, ptr++) {
+ printk(KERN_INFO "%s: %d. descr: status x%x len x%x "
+ "ndesc %08x vbufp %p vndescp %p skb_ptr %p\n",
+ DRV_NAME, i, ptr->status, ptr->len,
+ ptr->ndesc, ptr->vbufp, ptr->vndescp, ptr->skb_ptr);
+ }
+ }
+}
+#endif /* #if (DEBUG & DBG_TX_RING_DUMP) */
+
+int r6040_alloc_rxbufs(struct net_device *dev)
+{
+ struct r6040_private *lp = netdev_priv(dev);
+ struct r6040_descriptor *desc;
+ struct sk_buff *skb;
+ int rc;
+
+ lp->rx_remove_ptr = lp->rx_insert_ptr = lp->rx_ring;
+ r6040_init_ring_desc(lp->rx_ring, lp->rx_ring_dma, RX_DCNT);
+
+ /* alloc skbs for the rx descriptors */
+ desc = lp->rx_ring;
+ do {
+ if (!(skb=netdev_alloc_skb(dev, MAX_BUF_SIZE))) {
+ err("failed to alloc skb for rx\n");
+ rc = -ENOMEM;
+ goto err_exit;
+ }
+ desc->skb_ptr = skb;
+ desc->buf = cpu_to_le32(pci_map_single(lp->pdev,
+ desc->skb_ptr->data,
+ MAX_BUF_SIZE, PCI_DMA_FROMDEVICE));
+ desc->status = DESC_STATUS_OWNER_MAC;
+ desc = desc->vndescp;
+ } while (desc != lp->rx_ring);
+
+#if (DEBUG & DBG_RX_RING_DUMP)
+ if (debug & DBG_RX_RING_DUMP) {
+ dump_rx_ring(lp);
+ }
+#endif
+
+ return 0;
+
+err_exit:
+ /* dealloc all previously allocated skb */
+ r6040_free_rxbufs(dev);
+ return rc;
+}
+
+/*! reset MAC and set all registers */
+void r6040_init_mac_regs(struct r6040_private *lp)
+{
+ void __iomem *ioaddr = lp->base;
+ int limit;
+ char obuf[3*ETH_ALEN] __attribute__ ((unused));
+
+ /* Mask Off Interrupt */
+ iowrite16(MSK_INT, ioaddr + MIER);
+
+ /* reset MAC */
+ iowrite16(MAC_RST, ioaddr + MCR1);
+ udelay(100);
+ limit=2048;
+ while ((ioread16(ioaddr + MCR1) & MAC_RST) && limit-- > 0);
+
+ /* Reset internal state machine */
+ iowrite16(2, ioaddr + MAC_SM);
+ iowrite16(0, ioaddr + MAC_SM);
+ udelay(5000);
+
+ /* Restore MAC Addresses */
+ r6040_multicast_list(lp->dev);
+
+ /* TODO: restore multcast and hash table */
+
+ /* MAC Bus Control Register */
+ iowrite16(MBCR_DEFAULT, ioaddr + MBCR);
+
+ /* Buffer Size Register */
+ iowrite16(MAX_BUF_SIZE, ioaddr + MR_BSR);
+
+ /* write tx ring start address */
+ iowrite16(lp->tx_ring_dma, ioaddr + MTD_SA0);
+ iowrite16(lp->tx_ring_dma >> 16, ioaddr + MTD_SA1);
+
+ /* write rx ring start address */
+ iowrite16(lp->rx_ring_dma, ioaddr + MRD_SA0);
+ iowrite16(lp->rx_ring_dma >> 16, ioaddr + MRD_SA1);
+
+ /* set interrupt waiting time and packet numbers */
+ iowrite16(0, ioaddr + MT_ICR);
+ iowrite16(0, ioaddr + MR_ICR);
+
+ /* enable interrupts */
+ iowrite16(INT_MASK, ioaddr + MIER);
+
+ /* enable tx and rx */
+ iowrite16(lp->mcr0 | 0x0002, ioaddr);
+
+ /* let TX poll the descriptors - we may got called by r6040_tx_timeout which has left
+ some unsent tx buffers */
+ iowrite16(0x01, ioaddr + MTPR);
+}
+
+void r6040_tx_timeout(struct net_device *dev)
+{
+ struct r6040_private *priv = netdev_priv(dev);
+ void __iomem *ioaddr = priv->base;
+
+ /* we read MISR, which clears on read (i.e. we may loose an RX interupt,
+ but this is an error anyhow ... */
+ printk(KERN_WARNING "%s: transmit timed out, int enable %4.4x "
+ "status %4.4x, PHY status %4.4x\n",
+ dev->name, ioread16(ioaddr + MIER),
+ ioread16(ioaddr + MISR),
+ mdio_read(dev, priv->mii_if.phy_id, MII_BMSR));
+
+ dev->stats.tx_errors++;
+
+ /* Reset MAC and re-init all registers */
+ r6040_init_mac_regs(priv);
+}
+
+struct net_device_stats *r6040_get_stats(struct net_device *dev)
+{
+ struct r6040_private *priv = netdev_priv(dev);
+ void __iomem *ioaddr = priv->base;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ dev->stats.rx_crc_errors += ioread8(ioaddr + ME_CNT1);
+ dev->stats.multicast += ioread8(ioaddr + ME_CNT0);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return &dev->stats;
+}
+
+/* Stop RDC MAC and Free the allocated resource */
+void r6040_down(struct net_device *dev)
+{
+ struct r6040_private *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
+ struct pci_dev *pdev = lp->pdev;
+ int limit = 2048;
+
+ dbg(DBG_EXIT, "ENTER\n");
+
+ /* Stop MAC */
+ iowrite16(MSK_INT, ioaddr + MIER); /* Mask Off Interrupt */
+ iowrite16(MAC_RST, ioaddr + MCR1); /* Reset RDC MAC */
+ udelay(100);
+ while ((ioread16(ioaddr+MCR1) & 1) && limit-- > 0);
+
+ if (limit <= 0)
+ err("timeout while waiting for reset done.\n");
+
+ free_irq(dev->irq, dev);
+
+ /* Free RX buffer */
+ r6040_free_rxbufs(dev);
+
+ /* Free TX buffer */
+ r6040_free_txbufs(dev);
+
+ /* Free Descriptor memory */
+ pci_free_consistent(pdev, RX_DESC_SIZE, lp->rx_ring, lp->rx_ring_dma);
+ pci_free_consistent(pdev, TX_DESC_SIZE, lp->tx_ring, lp->tx_ring_dma);
+
+ dbg(DBG_EXIT, "EXIT\n");
+}
+
+int r6040_close(struct net_device *dev)
+{
+ struct r6040_private *lp = netdev_priv(dev);
+
+ dbg(DBG_EXIT, "ENTER\n");
+
+ /* deleted timer */
+ del_timer_sync(&lp->timer);
+ spin_lock_irq(&lp->lock);
+ napi_disable(&lp->napi);
+ netif_stop_queue(dev);
+ r6040_down(dev);
+ spin_unlock_irq(&lp->lock);
+
+ dbg(DBG_EXIT, "EXIT\n");
+ return 0;
+}
+
+/* Status of PHY CHIP. Returns 0x8000 for full duplex, 0 for half duplex */
+STATIC int phy_mode_chk(struct net_device *dev)
+{
+ struct r6040_private *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
+ int phy_dat;
+
+ /* PHY Link Status Check */
+ phy_dat = phy_read(ioaddr, lp->phy_addr, 1);
+ if (!(phy_dat & 0x4))
+ phy_dat = 0x8000; /* Link Failed, full duplex */
+
+ /* PHY Chip Auto-Negotiation Status */
+ phy_dat = phy_read(ioaddr, lp->phy_addr, 1);
+ if (phy_dat & 0x0020) {
+ /* Auto Negotiation Mode */
+ phy_dat = phy_read(ioaddr, lp->phy_addr, 5);
+ phy_dat &= phy_read(ioaddr, lp->phy_addr, 4);
+ if (phy_dat & 0x140)
+ /* Force full duplex */
+ phy_dat = 0x8000;
+ else
+ phy_dat = 0;
+ } else {
+ /* Force Mode */
+ phy_dat = phy_read(ioaddr, lp->phy_addr, 0);
+ if (phy_dat & 0x100)
+ phy_dat = 0x8000;
+ else
+ phy_dat = 0x0000;
+ }
+
+ dbg(DBG_PHY, "RETURN x%x\n", phy_dat);
+ return phy_dat;
+};
+
+void r6040_set_carrier(struct mii_if_info *mii)
+{
+ if (phy_mode_chk(mii->dev)) {
+ /* autoneg is off: Link is always assumed to be up */
+ if (!netif_carrier_ok(mii->dev))
+ netif_carrier_on(mii->dev);
+ } else
+ phy_mode_chk(mii->dev);
+}
+
+int r6040_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ struct r6040_private *lp = netdev_priv(dev);
+ struct mii_ioctl_data *data = if_mii(rq);
+ int rc;
+
+ if (!netif_running(dev))
+ return -EINVAL;
+ spin_lock_irq(&lp->lock);
+ rc = generic_mii_ioctl(&lp->mii_if, data, cmd, NULL);
+ spin_unlock_irq(&lp->lock);
+ r6040_set_carrier(&lp->mii_if);
+ return rc;
+}
+
+int r6040_rx(struct net_device *dev, int limit)
+{
+ struct r6040_private *priv = netdev_priv(dev);
+ int count=0;
+ struct r6040_descriptor *descptr = priv->rx_remove_ptr;
+ struct sk_buff *skb_ptr, *new_skb;
+ char obuf[2*32+1] __attribute__ ((unused)); /* for debugging */
+
+ while (count < limit && !(descptr->status & DESC_STATUS_OWNER_MAC)) {
+ /* limit not reached and the descriptor belongs to the CPU */
+
+ dbg(DBG_RX_DESCR, "descptr %p status x%x data len x%x\n",
+ descptr, descptr->status, descptr->len);
+
+ /* Check for errors */
+ if (descptr->status & DESC_STATUS_RX_ERR) {
+
+ dev->stats.rx_errors++;
+
+ if (descptr->status & (DESC_STATUS_RX_ERR_DRIBBLE|
+ DESC_STATUS_RX_ERR_BUFLEN|
+ DESC_STATUS_RX_ERR_LONG|
+ DESC_STATUS_RX_ERR_RUNT)) {
+ /* packet too long or too short*/
+ dev->stats.rx_length_errors++;
+ }
+
+ if (descptr->status & DESC_STATUS_RX_ERR_CRC) {
+ dev->stats.rx_crc_errors++;
+ }
+ goto next_descr;
+ }
+
+ /* successful received packet */
+
+ /* first try to allocate new skb. If this fails
+ we drop the packet and leave the old skb there.*/
+ new_skb = netdev_alloc_skb(dev, MAX_BUF_SIZE);
+ if (!new_skb) {
+ dev->stats.rx_dropped++;
+ goto next_descr;
+ }
+ skb_ptr = descptr->skb_ptr;
+ skb_ptr->dev = priv->dev;
+ /* Do not count the CRC */
+ skb_put(skb_ptr, descptr->len - 4);
+ pci_unmap_single(priv->pdev, le32_to_cpu(descptr->buf),
+ MAX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ skb_ptr->protocol = eth_type_trans(skb_ptr, priv->dev);
+
+ dbg(DBG_RX_DATA, "rx len x%x: %s...\n",
+ descptr->len,
+ hex2str(skb_ptr->data, obuf, sizeof(obuf)/2, '\0'));
+
+ /* Send to upper layer */
+ netif_receive_skb(skb_ptr);
+ dev->last_rx = jiffies;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += (descptr->len-4);
+
+ /* put new skb into descriptor */
+ descptr->skb_ptr = new_skb;
+ descptr->buf = cpu_to_le32(pci_map_single(priv->pdev,
+ descptr->skb_ptr->data,
+ MAX_BUF_SIZE, PCI_DMA_FROMDEVICE));
+
+next_descr:
+ /* put the descriptor back to the MAC */
+ descptr->status = DESC_STATUS_OWNER_MAC;
+ descptr = descptr->vndescp;
+ count++; /* shall we count errors and dropped packets as well? */
+ } /* while (limit && !(descptr->status & DESC_STATUS_OWNER_MAC)) */
+
+ /* remember next descriptor to check for rx */
+ priv->rx_remove_ptr = descptr;
+
+ return count;
+}
+
+void r6040_tx(struct net_device *dev)
+{
+ struct r6040_private *priv = netdev_priv(dev);
+ struct r6040_descriptor *descptr;
+ void __iomem *ioaddr = priv->base;
+ struct sk_buff *skb_ptr;
+ u16 err;
+
+ spin_lock(&priv->lock);
+ descptr = priv->tx_remove_ptr;
+ while (priv->tx_free_desc < TX_DCNT) {
+ /* Check for errors */
+ err = ioread16(ioaddr + MLSR);
+
+ if (err & 0x0200)
+ dev->stats.rx_fifo_errors++;
+ if (err & (0x2000 | 0x4000))
+ dev->stats.tx_carrier_errors++;
+
+ dbg(DBG_TX_DONE, "descptr %p status x%x err x%x jiffies %lu\n",
+ descptr, descptr->status, err, jiffies);
+
+ if (descptr->status & 0x8000)
+ break; /* Not complete */
+ skb_ptr = descptr->skb_ptr;
+ pci_unmap_single(priv->pdev, le32_to_cpu(descptr->buf),
+ skb_ptr->len, PCI_DMA_TODEVICE);
+ /* Free buffer */
+ dev_kfree_skb_irq(skb_ptr);
+ descptr->skb_ptr = NULL;
+ /* To next descriptor */
+ descptr = descptr->vndescp;
+ priv->tx_free_desc++;
+ }
+ priv->tx_remove_ptr = descptr;
+
+ if (priv->tx_free_desc)
+ netif_wake_queue(dev);
+ spin_unlock(&priv->lock);
+}
+
+int r6040_poll(struct napi_struct *napi, int budget)
+{
+ struct r6040_private *priv =
+ container_of(napi, struct r6040_private, napi);
+ struct net_device *dev = priv->dev;
+ void __iomem *ioaddr = priv->base;
+ int work_done;
+
+ work_done = r6040_rx(dev, budget);
+
+ dbg(DBG_POLL, "budget x%x done x%x\n", budget, work_done);
+
+ if (work_done < budget) {
+ netif_rx_complete(dev, napi);
+ /* Enable RX interrupt */
+ iowrite16(ioread16(ioaddr + MIER) | RX_INTS, ioaddr + MIER);
+ }
+ return work_done;
+}
+
+/* The RDC interrupt handler. */
+irqreturn_t r6040_interrupt(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct r6040_private *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
+ u16 status;
+
+ /* Read MISR status and clear */
+ status = ioread16(ioaddr + MISR);
+
+ dbg(DBG_IRQ, "status x%x jiffies %lu\n", status, jiffies);
+
+ if (status == 0x0000 || status == 0xffff)
+ return IRQ_NONE;
+
+ /* rx early / rx finish interrupt
+ or rx descriptor unavail. */
+ if (status & RX_INTS) {
+ if (status & RX_NO_DESC) {
+ /* rx descriptor unavail. */
+ dev->stats.rx_dropped++;
+ dev->stats.rx_missed_errors++;
+ }
+ /* Mask off RX interrupts */
+ iowrite16(ioread16(ioaddr + MIER) & ~RX_INTS, ioaddr + MIER);
+ netif_rx_schedule(dev, &lp->napi);
+ }
+
+ /* rx FIFO full */
+ if (status & RX_FIFO_FULL) {
+ dev->stats.rx_fifo_errors++;
+ }
+
+ /* TX interrupt request */
+ if (status & 0x10)
+ r6040_tx(dev);
+
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+void r6040_poll_controller(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ r6040_interrupt(dev->irq, dev);
+ enable_irq(dev->irq);
+}
+#endif
+
+/* Init RDC MAC */
+int r6040_up(struct net_device *dev)
+{
+ struct r6040_private *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
+ int rc;
+
+ dbg(DBG_INIT, "ENTER\n");
+
+ /* Initialise and alloc RX/TX buffers */
+ r6040_init_txbufs(dev);
+ if ((rc=r6040_alloc_rxbufs(dev)))
+ return rc;
+
+ /* Read the PHY ID */
+ lp->switch_sig = phy_read(ioaddr, 0, 2);
+
+ if (lp->switch_sig == ICPLUS_PHY_ID) {
+ phy_write(ioaddr, 29, 31, 0x175C); /* Enable registers */
+ lp->phy_mode = 0x8000;
+ } else {
+ /* PHY Mode Check */
+ phy_write(ioaddr, lp->phy_addr, 4, PHY_CAP);
+ phy_write(ioaddr, lp->phy_addr, 0, PHY_MODE);
+
+ if (PHY_MODE == 0x3100)
+ lp->phy_mode = phy_mode_chk(dev);
+ else
+ lp->phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0;
+ }
+
+/* configure duplex mode */
+ lp->mcr0 |= lp->phy_mode;
+
+ /* improve performance (by RDC guys) */
+ phy_write(ioaddr, 30, 17, (phy_read(ioaddr, 30, 17) | 0x4000));
+ phy_write(ioaddr, 30, 17, ~((~phy_read(ioaddr, 30, 17)) | 0x2000));
+ phy_write(ioaddr, 0, 19, 0x0000);
+ phy_write(ioaddr, 0, 30, 0x01F0);
+
+ /* Reset MAC and init all registers */
+ r6040_init_mac_regs(lp);
+
+ return 0;
+}
+
+/*
+ A periodic timer routine
+ Polling PHY Chip Link Status
+*/
+void r6040_timer(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct r6040_private *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
+ u16 phy_mode;
+
+ /* Polling PHY Chip Status */
+ if (PHY_MODE == 0x3100)
+ phy_mode = phy_mode_chk(dev);
+ else
+ phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0;
+
+ if (phy_mode != lp->phy_mode) {
+ lp->phy_mode = phy_mode;
+ lp->mcr0 = (lp->mcr0 & 0x7fff) | phy_mode;
+ iowrite16(lp->mcr0, ioaddr);
+ printk(KERN_INFO "Link Change x%x \n", ioread16(ioaddr));
+ }
+
+ /* Timer active again */
+ mod_timer(&lp->timer, jiffies + round_jiffies(HZ));
+}
+
+int r6040_open(struct net_device *dev)
+{
+ struct r6040_private *lp = netdev_priv(dev);
+ int ret;
+
+ dbg(DBG_OPEN, "ENTER\n");
+ /* Request IRQ and Register interrupt handler */
+ ret = request_irq(dev->irq, &r6040_interrupt,
+ IRQF_SHARED, dev->name, dev);
+ if (ret)
+ return ret;
+
+ dbg(DBG_OPEN, "got irq %d\n", dev->irq);
+
+ /* Allocate Descriptor memory */
+ lp->rx_ring =
+ pci_alloc_consistent(lp->pdev, RX_DESC_SIZE, &lp->rx_ring_dma);
+ if (!lp->rx_ring)
+ return -ENOMEM;
+
+ dbg(DBG_OPEN, "allocated rx ring\n");
+
+ lp->tx_ring =
+ pci_alloc_consistent(lp->pdev, TX_DESC_SIZE, &lp->tx_ring_dma);
+ if (!lp->tx_ring) {
+ pci_free_consistent(lp->pdev, RX_DESC_SIZE, lp->rx_ring,
+ lp->rx_ring_dma);
+ return -ENOMEM;
+ }
+
+ dbg(DBG_OPEN, "allocated tx ring\n");
+
+ if ((ret=r6040_up(dev))) {
+ pci_free_consistent(lp->pdev, TX_DESC_SIZE, lp->tx_ring,
+ lp->tx_ring_dma);
+ pci_free_consistent(lp->pdev, RX_DESC_SIZE, lp->rx_ring,
+ lp->rx_ring_dma);
+ return ret;
+ }
+
+ napi_enable(&lp->napi);
+ netif_start_queue(dev);
+
+ /* set and active a timer process */
+ setup_timer(&lp->timer, r6040_timer, (unsigned long) dev);
+ if (lp->switch_sig != ICPLUS_PHY_ID)
+ mod_timer(&lp->timer, jiffies + HZ);
+ return 0;
+}
+
+int r6040_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct r6040_private *lp = netdev_priv(dev);
+ struct r6040_descriptor *descptr;
+ void __iomem *ioaddr = lp->base;
+ unsigned long flags;
+ int ret = NETDEV_TX_OK;
+
+ /* Critical Section */
+ spin_lock_irqsave(&lp->lock, flags);
+
+ /* TX resource check */
+ if (!lp->tx_free_desc) {
+ spin_unlock_irqrestore(&lp->lock, flags);
+ netif_stop_queue(dev);
+ printk(KERN_ERR DRV_NAME ": no tx descriptor\n");
+ ret = NETDEV_TX_BUSY;
+ return ret;
+ }
+
+ /* Statistic Counter */
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
+ /* Set TX descriptor & Transmit it */
+ lp->tx_free_desc--;
+ descptr = lp->tx_insert_ptr;
+ if (skb->len < MISR)
+ descptr->len = MISR;
+ else
+ descptr->len = skb->len;
+
+ descptr->skb_ptr = skb;
+ descptr->buf = cpu_to_le32(pci_map_single(lp->pdev,
+ skb->data, skb->len, PCI_DMA_TODEVICE));
+
+ dbg(DBG_TX_DESCR, "desc @ %p: len x%x buf %08x skb->data %p skb->len x%x jiffies %lu\n",
+ descptr, descptr->len, descptr->buf, skb->data, skb->len, jiffies);
+
+ {
+ char obuf[2*32+1];
+ dbg(DBG_TX_DATA, "tx len x%x: %s\n",
+ descptr->len, hex2str(skb->data, obuf, sizeof(obuf)/2, '\0'));
+ }
+
+ descptr->status = 0x8000;
+ /* Trigger the MAC to check the TX descriptor */
+ iowrite16(0x01, ioaddr + MTPR);
+ lp->tx_insert_ptr = descptr->vndescp;
+
+ /* If no tx resource, stop */
+ if (!lp->tx_free_desc)
+ netif_stop_queue(dev);
+
+ dev->trans_start = jiffies;
+ spin_unlock_irqrestore(&lp->lock, flags);
+ return ret;
+}
+
+/*! set MAC addresses and promiscous mode */
+void r6040_multicast_list(struct net_device *dev)
+{
+ struct r6040_private *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
+ u16 *adrp;
+ u16 reg;
+ unsigned long flags;
+ struct dev_mc_list *dmi = dev->mc_list;
+ int i;
+ char obuf[3*ETH_ALEN] __attribute__ ((unused));
+
+ /* MAC Address */
+ adrp = (u16 *)dev->dev_addr;
+ iowrite16(adrp[0], ioaddr + MID_0L);
+ iowrite16(adrp[1], ioaddr + MID_0M);
+ iowrite16(adrp[2], ioaddr + MID_0H);
+
+ dbg(DBG_MAC_ADDR, "%s: set MAC addr %s\n",
+ dev->name, hex2str(dev->dev_addr, obuf, ETH_ALEN, ':'));
+
+ /* Promiscous Mode */
+ spin_lock_irqsave(&lp->lock, flags);
+
+ /* Clear AMCP & PROM bits */
+ reg = ioread16(ioaddr) & ~0x0120;
+ if (dev->flags & IFF_PROMISC) {
+ reg |= 0x0020;
+ lp->mcr0 |= 0x0020;
+ }
+ /* Too many multicast addresses
+ * accept all traffic */
+ else if ((dev->mc_count > MCAST_MAX)
+ || (dev->flags & IFF_ALLMULTI))
+ reg |= 0x0020;
+
+ iowrite16(reg, ioaddr);
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ /* Build the hash table */
+ if (dev->mc_count > MCAST_MAX) {
+ u16 hash_table[4];
+ u32 crc;
+
+ for (i = 0; i < 4; i++)
+ hash_table[i] = 0;
+
+ for (i = 0; i < dev->mc_count; i++) {
+ char *addrs = dmi->dmi_addr;
+
+ dmi = dmi->next;
+
+ if (!(*addrs & 1))
+ continue;
+
+ crc = ether_crc_le(6, addrs);
+ crc >>= 26;
+ hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf));
+ }
+ /* Write the index of the hash table */
+ for (i = 0; i < 4; i++)
+ iowrite16(hash_table[i] << 14, ioaddr + MCR1);
+ /* Fill the MAC hash tables with their values */
+ iowrite16(hash_table[0], ioaddr + MAR0);
+ iowrite16(hash_table[1], ioaddr + MAR1);
+ iowrite16(hash_table[2], ioaddr + MAR2);
+ iowrite16(hash_table[3], ioaddr + MAR3);
+ }
+ /* Multicast Address 1~4 case */
+ for (i = 0, dmi; (i < dev->mc_count) && (i < MCAST_MAX); i++) {
+ adrp = (u16 *)dmi->dmi_addr;
+ iowrite16(adrp[0], ioaddr + MID_1L + 8*i);
+ iowrite16(adrp[1], ioaddr + MID_1M + 8*i);
+ iowrite16(adrp[2], ioaddr + MID_1H + 8*i);
+ dmi = dmi->next;
+ }
+ for (i = dev->mc_count; i < MCAST_MAX; i++) {
+ iowrite16(0xffff, ioaddr + MID_0L + 8*i);
+ iowrite16(0xffff, ioaddr + MID_0M + 8*i);
+ iowrite16(0xffff, ioaddr + MID_0H + 8*i);
+ }
+}
+
+STATIC void netdev_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct r6040_private *rp = netdev_priv(dev);
+
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ strcpy(info->bus_info, pci_name(rp->pdev));
+}
+
+STATIC int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct r6040_private *rp = netdev_priv(dev);
+ int rc;
+
+ spin_lock_irq(&rp->lock);
+ rc = mii_ethtool_gset(&rp->mii_if, cmd);
+ spin_unlock_irq(&rp->lock);
+
+ return rc;
+}
+
+STATIC int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct r6040_private *rp = netdev_priv(dev);
+ int rc;
+
+ spin_lock_irq(&rp->lock);
+ rc = mii_ethtool_sset(&rp->mii_if, cmd);
+ spin_unlock_irq(&rp->lock);
+ r6040_set_carrier(&rp->mii_if);
+
+ return rc;
+}
+
+STATIC u32 netdev_get_link(struct net_device *dev)
+{
+ struct r6040_private *rp = netdev_priv(dev);
+
+ return mii_link_ok(&rp->mii_if);
+}
+
+static struct ethtool_ops netdev_ethtool_ops = {
+ .get_drvinfo = netdev_get_drvinfo,
+ .get_settings = netdev_get_settings,
+ .set_settings = netdev_set_settings,
+ .get_link = netdev_get_link,
+};
+
+int __devinit r6040_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct net_device *dev, *parent_dev;
+ struct r6040_private *lp;
+ void __iomem *ioaddr;
+ int err, io_size = R6040_IO_SIZE;
+ static int card_idx = -1;
+ long pioaddr;
+
+ printk(KERN_INFO "%s\n", version);
+ printk(KERN_INFO DRV_NAME ": debug %x\n", debug);
+
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+
+ /* this should always be supported */
+ if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+ printk(KERN_ERR DRV_NAME "32-bit PCI DMA addresses"
+ "not supported by the card\n");
+ return -ENODEV;
+ }
+ if (pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
+ printk(KERN_ERR DRV_NAME "32-bit PCI DMA addresses"
+ "not supported by the card\n");
+ return -ENODEV;
+ }
+
+ /* IO Size check */
+ if (pci_resource_len(pdev, 0) < io_size) {
+ printk(KERN_ERR "Insufficient PCI resources, aborting\n");
+ return -EIO;
+ }
+
+ pioaddr = pci_resource_start(pdev, 0); /* IO map base address */
+ pci_set_master(pdev);
+
+ dev = alloc_etherdev(sizeof(struct r6040_private));
+ if (!dev) {
+ printk(KERN_ERR "Failed to allocate etherdev\n");
+ return -ENOMEM;
+ }
+ SET_NETDEV_DEV(dev, &pdev->dev);
+ lp = netdev_priv(dev);
+
+ if (pci_request_regions(pdev, DRV_NAME)) {
+ printk(KERN_ERR DRV_NAME ": Failed to request PCI regions\n");
+ err = -ENODEV;
+ goto err_out_disable;
+ }
+
+ ioaddr = pci_iomap(pdev, 0, io_size);
+ if (!ioaddr) {
+ printk(KERN_ERR "ioremap failed for device %s\n",
+ pci_name(pdev));
+ return -EIO;
+ }
+
+ /* Init system & device */
+ lp->base = ioaddr;
+ dev->irq = pdev->irq;
+
+ spin_lock_init(&lp->lock);
+ pci_set_drvdata(pdev, dev);
+
+ card_idx++;
+
+ /* Link new device into r6040_root_dev */
+ lp->pdev = pdev;
+
+ lp->dev = dev;
+
+ /* Init RDC private data */
+ lp->mcr0 = 0x1002;
+ lp->phy_addr = phy_table[card_idx];
+ lp->switch_sig = 0;
+
+ /* The RDC-specific entries in the device structure. */
+ dev->open = &r6040_open;
+ dev->hard_start_xmit = &r6040_start_xmit;
+ dev->stop = &r6040_close;
+ dev->get_stats = r6040_get_stats;
+ dev->set_multicast_list = &r6040_multicast_list;
+ dev->do_ioctl = &r6040_ioctl;
+ dev->ethtool_ops = &netdev_ethtool_ops;
+ dev->tx_timeout = &r6040_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+
+ /*
+ You must specify a netdevice with a "parent=" parameter, whose address
+ is copied, or an array of bytes comprising a literal address; otherwise
+ the (default) address of the Sitecom WL-153 bootloader is used.
+ */
+ memcpy(dev->dev_addr, mac_base, ETH_ALEN);
+ if (parent) {
+ parent_dev = __dev_get_by_name(&init_net, parent);
+ if (parent_dev)
+ memcpy(dev->dev_addr, parent_dev->dev_addr, ETH_ALEN);
+ }
+ dev->dev_addr[ETH_ALEN-1] += card_idx ^ reverse; /* + 0 or 1 */
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = r6040_poll_controller;
+#endif
+ netif_napi_add(dev, &lp->napi, r6040_poll, 64);
+ lp->mii_if.dev = dev;
+ lp->mii_if.mdio_read = mdio_read;
+ lp->mii_if.mdio_write = mdio_write;
+ lp->mii_if.phy_id = lp->phy_addr;
+ lp->mii_if.phy_id_mask = 0x1f;
+ lp->mii_if.reg_num_mask = 0x1f;
+
+ if (reverse && ((card_idx & 1) == 0) && (dev_alloc_name(dev, dev->name)
+ >= 0))
+ for (err = strlen(dev->name); err; err--) {
+ if (dev->name[err - 1]++ != '9')
+ break;
+ dev->name[err - 1] = '0';
+ }
+
+ /* Register net device. After this dev->name assign */
+ err = register_netdev(dev);
+ if (err) {
+ printk(KERN_ERR DRV_NAME ": Failed to register net device\n");
+ goto err_out_res;
+ }
+
+ dbg(DBG_INIT, "%s successfully registered\n", dev->name);
+ return 0;
+
+err_out_res:
+ pci_release_regions(pdev);
+err_out_disable:
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+ free_netdev(dev);
+
+ return err;
+}
+
+void __devexit r6040_remove_one(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+
+ unregister_netdev(dev);
+ pci_release_regions(pdev);
+ free_netdev(dev);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+}
+
+
+static struct pci_device_id r6040_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_RDC, 0x6040) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, r6040_pci_tbl);
+
+static struct pci_driver r6040_driver = {
+ .name = DRV_NAME,
+ .id_table = r6040_pci_tbl,
+ .probe = r6040_init_one,
+ .remove = __devexit_p(r6040_remove_one),
+};
+
+
+static int __init r6040_init(void)
+{
+ return pci_register_driver(&r6040_driver);
+}
+
+
+static void __exit r6040_cleanup(void)
+{
+ pci_unregister_driver(&r6040_driver);
+}
+
+module_init(r6040_init);
+module_exit(r6040_cleanup);
diff --git a/target/linux/rdc/files-2.6.24/include/asm-i386/gpio.h b/target/linux/rdc/files-2.6.24/include/asm-i386/gpio.h
new file mode 100644
index 000000000..ff87fca0c
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/include/asm-i386/gpio.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_I386_GPIO_H
+#define _ASM_I386_GPIO_H
+
+#include <gpio.h>
+
+#endif /* _ASM_I386_GPIO_H */
diff --git a/target/linux/rdc/files-2.6.24/include/asm-i386/mach-generic/gpio.h b/target/linux/rdc/files-2.6.24/include/asm-i386/mach-generic/gpio.h
new file mode 100644
index 000000000..5305dcb96
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/include/asm-i386/mach-generic/gpio.h
@@ -0,0 +1,15 @@
+#ifndef __ASM_MACH_GENERIC_GPIO_H
+#define __ASM_MACH_GENERIC_GPIO_H
+
+int gpio_request(unsigned gpio, const char *label);
+void gpio_free(unsigned gpio);
+int gpio_direction_input(unsigned gpio);
+int gpio_direction_output(unsigned gpio, int value);
+int gpio_get_value(unsigned gpio);
+void gpio_set_value(unsigned gpio, int value);
+int gpio_to_irq(unsigned gpio);
+int irq_to_gpio(unsigned irq);
+
+#include <asm-generic/gpio.h> /* cansleep wrappers */
+
+#endif /* __ASM_MACH_GENERIC_GPIO_H */
diff --git a/target/linux/rdc/files-2.6.24/include/asm-i386/mach-rdc/gpio.h b/target/linux/rdc/files-2.6.24/include/asm-i386/mach-rdc/gpio.h
new file mode 100644
index 000000000..2368bd758
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/include/asm-i386/mach-rdc/gpio.h
@@ -0,0 +1,56 @@
+#ifndef _RDC_GPIO_H
+#define _RDC_GPIO_H
+
+extern int rdc_gpio_get_value(unsigned gpio);
+extern void rdc_gpio_set_value(unsigned gpio, int value);
+extern int rdc_gpio_direction_input(unsigned gpio);
+extern int rdc_gpio_direction_output(unsigned gpio, int value);
+
+
+/* Wrappers for the arch-neutral GPIO API */
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+ /* Not yet implemented */
+ return 0;
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+ /* Not yet implemented */
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+ return rdc_gpio_direction_input(gpio);
+}
+
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+ return rdc_gpio_direction_output(gpio, value);
+}
+
+static inline int gpio_get_value(unsigned gpio)
+{
+ return rdc_gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+ rdc_gpio_set_value(gpio, value);
+}
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+ return gpio;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+ return irq;
+}
+
+/* For cansleep */
+#include <asm-generic/gpio.h>
+
+#endif /* _RDC_GPIO_H_ */
diff --git a/target/linux/rdc/files-2.6.24/include/asm-i386/mach-rdc/rdc321x_defs.h b/target/linux/rdc/files-2.6.24/include/asm-i386/mach-rdc/rdc321x_defs.h
new file mode 100644
index 000000000..838ba8f64
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/include/asm-i386/mach-rdc/rdc321x_defs.h
@@ -0,0 +1,6 @@
+#define PFX "rdc321x: "
+
+/* General purpose configuration and data registers */
+#define RDC3210_CFGREG_ADDR 0x0CF8
+#define RDC3210_CFGREG_DATA 0x0CFC
+#define RDC_MAX_GPIO 0x3A
diff --git a/target/linux/rdc/files-2.6.24/include/asm-x86/gpio.h b/target/linux/rdc/files-2.6.24/include/asm-x86/gpio.h
new file mode 100644
index 000000000..ff87fca0c
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/include/asm-x86/gpio.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_I386_GPIO_H
+#define _ASM_I386_GPIO_H
+
+#include <gpio.h>
+
+#endif /* _ASM_I386_GPIO_H */
diff --git a/target/linux/rdc/files-2.6.24/include/asm-x86/mach-generic/gpio.h b/target/linux/rdc/files-2.6.24/include/asm-x86/mach-generic/gpio.h
new file mode 100644
index 000000000..5305dcb96
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/include/asm-x86/mach-generic/gpio.h
@@ -0,0 +1,15 @@
+#ifndef __ASM_MACH_GENERIC_GPIO_H
+#define __ASM_MACH_GENERIC_GPIO_H
+
+int gpio_request(unsigned gpio, const char *label);
+void gpio_free(unsigned gpio);
+int gpio_direction_input(unsigned gpio);
+int gpio_direction_output(unsigned gpio, int value);
+int gpio_get_value(unsigned gpio);
+void gpio_set_value(unsigned gpio, int value);
+int gpio_to_irq(unsigned gpio);
+int irq_to_gpio(unsigned irq);
+
+#include <asm-generic/gpio.h> /* cansleep wrappers */
+
+#endif /* __ASM_MACH_GENERIC_GPIO_H */
diff --git a/target/linux/rdc/files-2.6.24/include/asm-x86/mach-rdc/gpio.h b/target/linux/rdc/files-2.6.24/include/asm-x86/mach-rdc/gpio.h
new file mode 100644
index 000000000..2368bd758
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/include/asm-x86/mach-rdc/gpio.h
@@ -0,0 +1,56 @@
+#ifndef _RDC_GPIO_H
+#define _RDC_GPIO_H
+
+extern int rdc_gpio_get_value(unsigned gpio);
+extern void rdc_gpio_set_value(unsigned gpio, int value);
+extern int rdc_gpio_direction_input(unsigned gpio);
+extern int rdc_gpio_direction_output(unsigned gpio, int value);
+
+
+/* Wrappers for the arch-neutral GPIO API */
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+ /* Not yet implemented */
+ return 0;
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+ /* Not yet implemented */
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+ return rdc_gpio_direction_input(gpio);
+}
+
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+ return rdc_gpio_direction_output(gpio, value);
+}
+
+static inline int gpio_get_value(unsigned gpio)
+{
+ return rdc_gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+ rdc_gpio_set_value(gpio, value);
+}
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+ return gpio;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+ return irq;
+}
+
+/* For cansleep */
+#include <asm-generic/gpio.h>
+
+#endif /* _RDC_GPIO_H_ */
diff --git a/target/linux/rdc/files-2.6.24/include/asm-x86/mach-rdc/rdc321x_defs.h b/target/linux/rdc/files-2.6.24/include/asm-x86/mach-rdc/rdc321x_defs.h
new file mode 100644
index 000000000..838ba8f64
--- /dev/null
+++ b/target/linux/rdc/files-2.6.24/include/asm-x86/mach-rdc/rdc321x_defs.h
@@ -0,0 +1,6 @@
+#define PFX "rdc321x: "
+
+/* General purpose configuration and data registers */
+#define RDC3210_CFGREG_ADDR 0x0CF8
+#define RDC3210_CFGREG_DATA 0x0CFC
+#define RDC_MAX_GPIO 0x3A