Index: target/linux/rdc/sitecom/config-2.6.30
===================================================================
--- target/linux/rdc/sitecom/config-2.6.30	(revision 19797)
+++ target/linux/rdc/sitecom/config-2.6.30	(working copy)
@@ -1,2 +0,0 @@
-# CONFIG_MTD_R8610 is not set
-# CONFIG_MTD_RDC3210 is not set
Index: target/linux/rdc/files-2.6.30/arch/x86/include/asm/rdc321x_gpio.h
===================================================================
--- target/linux/rdc/files-2.6.30/arch/x86/include/asm/rdc321x_gpio.h	(revision 19797)
+++ target/linux/rdc/files-2.6.30/arch/x86/include/asm/rdc321x_gpio.h	(working copy)
@@ -1,16 +0,0 @@
-#ifndef _ASM_X86_MACH_RDC321X_GPIO_H
-#define _ASM_X86_MACH_RDC321X_GPIO_H
-
-#include <linux/kernel.h>
-
-#define gpio_to_irq(gpio)       NULL
-
-#define gpio_get_value __gpio_get_value
-#define gpio_set_value __gpio_set_value
-
-#define gpio_cansleep __gpio_cansleep
-
-/* For cansleep */
-#include <asm-generic/gpio.h>
-
-#endif /* _ASM_X86_MACH_RDC321X_GPIO_H */
Index: target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/platform.c
===================================================================
--- target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/platform.c	(revision 19797)
+++ target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/platform.c	(working copy)
@@ -29,15 +29,13 @@
 #include <linux/platform_device.h>
 #include <linux/version.h>
 #include <linux/leds.h>
-#include <linux/gpio_keys.h>
+#include <linux/gpio_buttons.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/rdc321x_gpio.h>
-
 /* Flash */
 #ifdef CONFIG_MTD_R8610
 #define CONFIG_MTD_RDC3210 1
@@ -82,6 +80,12 @@
 	{ .name = "rdc321x:dmz", .gpio = 1, .active_low = 1},
 };
 
+static struct gpio_led sitecom_leds[] = {
+	{ .name = "rdc321x:power", .gpio = 15, .active_low = 1},
+	{ .name = "rdc321x:usb0", .gpio = 0, .active_low = 1},
+	{ .name = "rdc321x:usb1", .gpio = 1, .active_low = 1},
+};
+
 static struct gpio_led_platform_data rdc321x_led_data = {
 	.num_leds = ARRAY_SIZE(default_leds),
 	.leds = default_leds,
@@ -103,22 +107,22 @@
 };
 
 /* Button */
-static struct gpio_keys_button rdc321x_gpio_btn[] = {
+static struct gpio_button rdc321x_gpio_btn[] = {
 	{
-		.gpio = 0,
+		.gpio = 6,
 		.code = BTN_0,
 		.desc = "Reset",
 		.active_low = 1,
 	}
 };
 
-static struct gpio_keys_platform_data rdc321x_gpio_btn_data = {
+static struct gpio_buttons_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",
+	.name = "gpio-buttons",
 	.id = -1,
 	.dev = {
 		.platform_data = &rdc321x_gpio_btn_data,
@@ -211,6 +215,9 @@
 		rdc_flash_parts[5].offset = rdc_flash_parts[0].size;
 		rdc_flash_parts[5].size = 0x10000;
 		rdc_flash_data.nr_parts = 6;
+		
+		rdc321x_led_data.num_leds = ARRAY_SIZE(sitecom_leds);
+		rdc321x_led_data.leds = sitecom_leds;
 	} else if (!memcmp(((u8 *)the_header) + 14, "Li", 2)) {	/* AMIT */
 		rdc_flash_parts[0].name = "kernel_parthdr";
 		rdc_flash_parts[0].offset = 0;
Index: target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/reboot.c
===================================================================
--- target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/reboot.c	(revision 0)
+++ target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/reboot.c	(revision 0)
@@ -0,0 +1,44 @@
+/*
+ *  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 <asm/reboot.h>
+#include <asm/io.h>
+
+static void rdc321x_reset(void)
+{
+	unsigned i;
+
+	/* write to southbridge config register 0x41
+	   enable pci reset on cpu reset, make internal port 0x92 writeable
+	   and switch port 0x92 to internal */
+	outl(0x80003840, 0xCF8);
+	i = inl(0xCFC);
+	i |= 0x1600;
+	outl(i, 0xCFC);
+
+	/* soft reset */
+	outb(1, 0x92);
+}
+
+static int __init rdc_setup_reset(void)
+{
+	machine_ops.emergency_restart = rdc321x_reset;
+	return 0;
+}
+
+arch_initcall(rdc_setup_reset);
Index: target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/pci.c
===================================================================
--- target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/pci.c	(revision 0)
+++ target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/pci.c	(revision 0)
@@ -0,0 +1,400 @@
+/*
+ * RDC321x southbrige driver
+ *
+ * Copyright (C) 2007 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/timer.h>
+#include <linux/watchdog.h>
+#include <linux/uaccess.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/gpio.h>
+
+
+#include <asm/rdc321x_defs.h>
+
+#define RDC321X_WDT_REG	0x00000044
+
+#define RDC_WDT_EN	0x00800000 /* Enable bit */
+#define RDC_WDT_WDTIRQ	0x00400000 /* Create WDT IRQ before CPU reset */
+#define RDC_WDT_NMIIRQ	0x00200000 /* Create NMI IRQ before CPU reset */
+#define RDC_WDT_RST	0x00100000 /* Reset wdt */
+#define RDC_WDT_NIF	0x00080000 /* NMI interrupt occured */
+#define RDC_WDT_WIF	0x00040000 /* WDT interrupt occured */
+#define RDC_WDT_IRT	0x00000700 /* IRQ Routing table */
+#define RDC_WDT_CNT	0x0000007F /* WDT count */
+
+/* default counter value (2.34 s) */
+#define RDC_WDT_DFLT_CNT 0x00000040
+
+#define RDC_WDT_SETUP (RDC_WDT_EN | RDC_WDT_NMIIRQ | RDC_WDT_RST | RDC_WDT_DFLT_CNT)
+
+/* some device data */
+static struct {
+	struct pci_dev *sb;
+	
+	//wdt
+	struct timer_list timer;
+	int seconds_left;
+	int total_seconds;
+	bool inuse;
+	bool running;
+	bool close_expected;
+	
+	//gpio
+	spinlock_t gpio_lock;
+	u32 gpio_data_reg[2];
+} rdc321x_sb_priv;
+
+static struct watchdog_info ident = {
+	.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+	.identity = "RDC321x WDT",
+};
+
+/* generic helper functions */
+static void rdc321x_wdt_timer(unsigned long unused)
+{
+	if (!rdc321x_sb_priv.running) {
+		pci_write_config_dword(rdc321x_sb_priv.sb, RDC321X_WDT_REG, 0);
+		return;
+	}
+	
+	rdc321x_sb_priv.seconds_left--;
+	
+	if (rdc321x_sb_priv.seconds_left < 1)
+		return;
+	
+	pci_write_config_dword(rdc321x_sb_priv.sb, RDC321X_WDT_REG, RDC_WDT_SETUP);
+
+	mod_timer(&rdc321x_sb_priv.timer, HZ*2 + jiffies);
+}
+
+static void rdc321x_wdt_reset(void)
+{
+	rdc321x_sb_priv.seconds_left = rdc321x_sb_priv.total_seconds;
+}
+
+static void rdc321x_wdt_start(void)
+{
+	if (rdc321x_sb_priv.running)
+		return;
+	
+	rdc321x_sb_priv.seconds_left = rdc321x_sb_priv.total_seconds;
+	
+	rdc321x_sb_priv.running = true;
+	
+	rdc321x_wdt_timer(0);
+	
+	return;
+}
+
+static int rdc321x_wdt_stop(void)
+{
+	if (WATCHDOG_NOWAYOUT)
+		return -ENOSYS;
+	
+	rdc321x_sb_priv.running = false;	
+	
+	return 0;
+}
+
+/* filesystem operations */
+static int rdc321x_wdt_open(struct inode *inode, struct file *file)
+{
+	if (xchg(&rdc321x_sb_priv.inuse, true))
+		return -EBUSY;
+
+	return nonseekable_open(inode, file);
+}
+
+static int rdc321x_wdt_release(struct inode *inode, struct file *file)
+{
+	if (rdc321x_sb_priv.close_expected)
+		rdc321x_wdt_stop();
+		
+	rdc321x_sb_priv.inuse = false;
+	
+	return 0;
+}
+
+static long rdc321x_wdt_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+	int value;
+
+	switch (cmd) {
+		case WDIOC_KEEPALIVE:
+			rdc321x_wdt_reset();
+			break;
+		case WDIOC_GETSUPPORT:
+			if (copy_to_user(argp, &ident, sizeof(ident)))
+				return -EFAULT;
+			break;
+		case WDIOC_SETTIMEOUT:
+			if (copy_from_user(&rdc321x_sb_priv.total_seconds, argp, sizeof(int)))
+				return -EFAULT;
+			rdc321x_sb_priv.seconds_left = rdc321x_sb_priv.total_seconds;
+			break;
+		case WDIOC_GETTIMEOUT:
+			if (copy_to_user(argp, &rdc321x_sb_priv.total_seconds, sizeof(int)))
+				return -EFAULT;
+			break;
+		case WDIOC_GETTIMELEFT:
+			if (copy_to_user(argp, &rdc321x_sb_priv.seconds_left, sizeof(int)))
+				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 -EINVAL;
+	}
+	return 0;
+}
+
+static ssize_t rdc321x_wdt_write(struct file *file, const char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	size_t i;
+  
+	if (!count)
+		return -EIO;
+	
+	rdc321x_sb_priv.close_expected = false;
+	
+	for (i = 0; i != count; i++) {
+		char c;
+		
+		if (get_user(c, buf + i))
+			return -EFAULT;
+		
+		if (c == 'V') {
+			rdc321x_sb_priv.close_expected = true;
+			break;
+		}
+	}
+
+	rdc321x_wdt_reset();
+
+	return count;
+}
+
+static const struct file_operations rdc321x_wdt_fops = {
+	.llseek		= no_llseek,
+	.unlocked_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_init(void)
+{
+	int err;
+  
+	err = pci_write_config_dword(rdc321x_sb_priv.sb, RDC321X_WDT_REG, 0);
+	if (err)
+		return err;
+	
+	rdc321x_wdt_misc.parent = &rdc321x_sb_priv.sb->dev;
+
+	rdc321x_sb_priv.running = false;
+	rdc321x_sb_priv.close_expected = false;
+	rdc321x_sb_priv.inuse = 0;
+	setup_timer(&rdc321x_sb_priv.timer, rdc321x_wdt_timer, 0);
+	rdc321x_sb_priv.total_seconds = 100;
+
+	err = misc_register(&rdc321x_wdt_misc);
+	if (err < 0) {
+		printk(KERN_ERR PFX "watchdog: misc_register failed\n");
+		return err;
+	}
+	
+	panic_on_unrecovered_nmi = 1;
+  
+	printk(KERN_INFO PFX "watchdog init success\n");
+
+	return 0;
+}
+
+/* read GPIO pin */
+static int rdc_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
+{
+	u32 value = 0;
+	int reg;
+	
+	reg = gpio < 32 ? RDC321X_GPIO_DATA_REG1 : RDC321X_GPIO_DATA_REG2;
+
+	spin_lock(&rdc321x_sb_priv.gpio_lock);
+	pci_write_config_dword(rdc321x_sb_priv.sb, reg, rdc321x_sb_priv.gpio_data_reg[gpio < 32 ? 0 : 1]);
+	pci_read_config_dword(rdc321x_sb_priv.sb, reg, &value);
+	spin_unlock(&rdc321x_sb_priv.gpio_lock);
+
+	return (1 << (gpio & 0x1f)) & value ? 1 : 0;
+}
+
+static void rdc_gpio_set_value_impl(struct gpio_chip *chip,
+				unsigned gpio, int value)
+{
+	int reg = (gpio < 32) ? 0 : 1;
+
+	if (value)
+		rdc321x_sb_priv.gpio_data_reg[reg] |= 1 << (gpio & 0x1f);
+	else
+		rdc321x_sb_priv.gpio_data_reg[reg] &= ~(1 << (gpio & 0x1f));
+	
+	pci_write_config_dword(rdc321x_sb_priv.sb,
+			       reg ? RDC321X_GPIO_DATA_REG2 : RDC321X_GPIO_DATA_REG1,
+			       rdc321x_sb_priv.gpio_data_reg[reg]);
+}
+
+/* set GPIO pin to value */
+static void rdc_gpio_set_value(struct gpio_chip *chip,
+				unsigned gpio, int value)
+{
+	spin_lock(&rdc321x_sb_priv.gpio_lock);
+	rdc_gpio_set_value_impl(chip, gpio, value);
+	spin_unlock(&rdc321x_sb_priv.gpio_lock);
+}
+
+static int rdc_gpio_config(struct gpio_chip *chip,
+				unsigned gpio, int value)
+{
+	int err;
+	u32 reg;
+  
+	spin_lock(&rdc321x_sb_priv.gpio_lock);
+	err = pci_read_config_dword(rdc321x_sb_priv.sb,
+			gpio < 32 ? RDC321X_GPIO_CTRL_REG1 : RDC321X_GPIO_CTRL_REG2,
+			&reg);
+	if (err)
+		goto unlock;
+	
+	reg |= 1 << (gpio & 0x1f);
+	
+	err = pci_write_config_dword(rdc321x_sb_priv.sb,
+			gpio < 32 ? RDC321X_GPIO_CTRL_REG1 : RDC321X_GPIO_CTRL_REG2,
+			reg);
+	if (err)
+		goto unlock;
+
+	rdc_gpio_set_value_impl(chip, gpio, value);
+	
+unlock:
+	spin_unlock(&rdc321x_sb_priv.gpio_lock);
+
+	return err;
+}
+
+/* configure GPIO pin as input */
+static int rdc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+	return rdc_gpio_config(chip, gpio, 1);
+}
+
+static struct gpio_chip rdc321x_gpio_chip = {
+	.label			= "rdc321x-gpio",
+	.direction_input	= rdc_gpio_direction_input,
+	.direction_output	= rdc_gpio_config,
+	.get			= rdc_gpio_get_value,
+	.set			= rdc_gpio_set_value,
+	.base			= 0,
+	.ngpio			= RDC321X_MAX_GPIO,
+};
+
+/* initially setup the 2 copies of the gpio data registers.
+   This function is called before the platform setup code. */
+static int __devinit rdc321x_gpio_setup(void)
+{
+	int err;
+
+	/* this might not be, what others (BIOS, bootloader, etc.)
+	   wrote to these registers before, but it's a good guess. Still
+	   better than just using 0xffffffff. */
+	err = pci_read_config_dword(rdc321x_sb_priv.sb, RDC321X_GPIO_DATA_REG1, &rdc321x_sb_priv.gpio_data_reg[0]);
+	if (err)
+		return err;
+	err = pci_read_config_dword(rdc321x_sb_priv.sb, RDC321X_GPIO_DATA_REG2, &rdc321x_sb_priv.gpio_data_reg[1]);
+	if (err)
+		return err;
+	
+	rdc321x_gpio_chip.dev = &rdc321x_sb_priv.sb->dev;
+	
+	spin_lock_init(&rdc321x_sb_priv.gpio_lock);
+
+	printk(KERN_INFO "rdc321x: registering %d GPIOs\n", rdc321x_gpio_chip.ngpio);
+	return gpiochip_add(&rdc321x_gpio_chip);
+}
+
+static int __devinit rdc321x_sb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	int err;
+	
+	err = pci_enable_device(pdev);
+	if (err)
+		return err;
+	
+	rdc321x_sb_priv.sb = pdev;
+	
+	err = rdc321x_wdt_init();
+	if (err)
+		return err;
+	
+	err = rdc321x_gpio_setup();
+	return err;	
+}
+
+
+static struct pci_device_id rdc321x_sb_table[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6030) },
+	{}
+};
+
+static struct pci_driver rdc321x_sb_driver = {
+	.name = "RDC3210 Southbridge",
+	.id_table = rdc321x_sb_table,
+	.probe = rdc321x_sb_probe
+};
+
+static int __init rdc321x_sb_init(void)
+{
+	return pci_register_driver(&rdc321x_sb_driver);
+}
+
+device_initcall(rdc321x_sb_init);
Index: target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/Makefile
===================================================================
--- target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/Makefile	(revision 19797)
+++ target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/Makefile	(working copy)
@@ -1,5 +1,5 @@
 #
 # Makefile for the RDC321x specific parts of the kernel
 #
-obj-$(CONFIG_X86_RDC321X)        := gpio.o platform.o
+obj-$(CONFIG_X86_RDC321X)        := pci.o platform.o reboot.o
 
Index: target/linux/rdc/config-2.6.30
===================================================================
--- target/linux/rdc/config-2.6.30	(revision 19797)
+++ target/linux/rdc/config-2.6.30	(working copy)
@@ -280,7 +280,7 @@
 CONFIG_X86_POPAD_OK=y
 # CONFIG_X86_PPRO_FENCE is not set
 CONFIG_X86_RDC321X=y
-CONFIG_X86_REBOOTFIXUPS=y
+# CONFIG_X86_REBOOTFIXUPS is not set
 # CONFIG_X86_RESERVE_LOW_64K is not set
 # CONFIG_X86_UP_APIC is not set
 # CONFIG_X86_VERBOSE_BOOTUP is not set
@@ -288,3 +288,5 @@
 CONFIG_X86_XADD=y
 CONFIG_X86=y
 # CONFIG_ZONE_DMA32 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_LEDS_TRIGGER_TIMER=y
Index: target/linux/rdc/Makefile
===================================================================
--- target/linux/rdc/Makefile	(revision 19797)
+++ target/linux/rdc/Makefile	(working copy)
@@ -17,7 +17,8 @@
 
 include $(INCLUDE_DIR)/target.mk
 
-DEFAULT_PACKAGES += wpad-mini kmod-rdc321x-wdt kmod-r6040
+DEFAULT_PACKAGES += wpad-mini kmod-r6040 kmod-input-core \
+		    kmod-input-polldev kmod-input-gpio-buttons kmod-button-hotplug
 
 define Target/Description
         Build firmware images for RDC321x based routers
