diff --git a/target/linux/ixp4xx/patches-2.6.28/020-gateworks_i2c_pld.patch b/target/linux/ixp4xx/patches-2.6.28/020-gateworks_i2c_pld.patch
new file mode 100644
index 0000000000000000000000000000000000000000..6a9f65f896c1686e0441d18ef2a6a3c02c38daec
--- /dev/null
+++ b/target/linux/ixp4xx/patches-2.6.28/020-gateworks_i2c_pld.patch
@@ -0,0 +1,420 @@
+--- /dev/null
++++ b/drivers/gpio/gw_i2c_pld.c
+@@ -0,0 +1,370 @@
++/*
++ * Gateworks I2C PLD GPIO expander
++ *
++ * Copyright (C) 2009 Gateworks Corporation
++ *
++ * 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/kernel.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/i2c/gw_i2c_pld.h>
++#include <asm/gpio.h>
++
++static const struct i2c_device_id gw_i2c_pld_id[] = {
++	{ "gw_i2c_pld", 8 },
++	{ }
++};
++MODULE_DEVICE_TABLE(i2c, gw_i2c_pld_id);
++
++/*
++ * The Gateworks I2C PLD chip only expose one read and one
++ * write register.  Writing a "one" bit (to match the reset state) lets
++ * that pin be used as an input. It is an open-drain model.
++ */
++
++struct gw_i2c_pld {
++	struct gpio_chip	chip;
++	struct i2c_client	*client;
++	unsigned		out;		/* software latch */
++};
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * The Gateworks I2C PLD chip does not properly send the acknowledge bit
++ * thus we cannot use standard i2c_smbus functions. We have recreated
++ * our own here, but we still use the mutex_lock to lock the i2c_bus
++ * as the device still exists on the I2C bus.
++*/
++
++#define PLD_SCL_GPIO 6
++#define PLD_SDA_GPIO 7
++
++#define SCL_LO()  gpio_line_set(PLD_SCL_GPIO, IXP4XX_GPIO_LOW)
++#define SCL_HI()  gpio_line_set(PLD_SCL_GPIO, IXP4XX_GPIO_HIGH)
++#define SCL_EN()  gpio_line_config(PLD_SCL_GPIO, IXP4XX_GPIO_OUT)
++#define SDA_LO()  gpio_line_set(PLD_SDA_GPIO, IXP4XX_GPIO_LOW)
++#define SDA_HI()  gpio_line_set(PLD_SDA_GPIO, IXP4XX_GPIO_HIGH)
++#define SDA_EN()  gpio_line_config(PLD_SDA_GPIO, IXP4XX_GPIO_OUT)
++#define SDA_DIS() gpio_line_config(PLD_SDA_GPIO, IXP4XX_GPIO_IN)
++#define SDA_IN(x) gpio_line_get(PLD_SDA_GPIO, &x);
++
++static int i2c_pld_write_byte(int address, int byte)
++{
++	int i;
++
++	address = (address << 1) & ~0x1;
++
++	SDA_HI();
++	SDA_EN();
++	SCL_EN();
++	SCL_HI();
++	SDA_LO();
++	SCL_LO();
++
++	for (i = 7; i >= 0; i--)
++	{
++		if (address & (1 << i))
++			SDA_HI();
++		else
++			SDA_LO();
++
++		SCL_HI();
++		SCL_LO();
++	}
++
++	SDA_DIS();
++	SCL_HI();
++	SDA_IN(i);
++	SCL_LO();
++	SDA_EN();
++
++	for (i = 7; i >= 0; i--)
++	{
++		if (byte & (1 << i))
++      SDA_HI();
++		else
++			SDA_LO();
++		SCL_HI();
++		SCL_LO();
++	}
++
++	SDA_DIS();
++	SCL_HI();
++	SDA_IN(i);
++	SCL_LO();
++
++	SDA_HI();
++	SDA_EN();
++
++	SDA_LO();
++	SCL_HI();
++	SDA_HI();
++	SCL_LO();
++	SCL_HI();
++
++	return 0;
++}
++
++static unsigned int i2c_pld_read_byte(int address)
++{
++	int i = 0, byte = 0;
++	int bit;
++
++	address = (address << 1) | 0x1;
++
++	SDA_HI();
++	SDA_EN();
++	SCL_EN();
++	SCL_HI();
++	SDA_LO();
++	SCL_LO();
++
++	for (i = 7; i >= 0; i--)
++	{
++		if (address & (1 << i))
++			SDA_HI();
++		else
++			SDA_LO();
++
++		SCL_HI();
++		SCL_LO();
++	}
++
++	SDA_DIS();
++	SCL_HI();
++	SDA_IN(i);
++	SCL_LO();
++	SDA_EN();
++
++	SDA_DIS();
++	for (i = 7; i >= 0; i--)
++	{
++		SCL_HI();
++		SDA_IN(bit);
++		byte |= bit << i;
++		SCL_LO();
++	}
++
++	SDA_LO();
++	SCL_HI();
++	SDA_HI();
++	SCL_LO();
++	SCL_HI();
++
++	return byte;
++}
++
++
++static int gw_i2c_pld_input8(struct gpio_chip *chip, unsigned offset)
++{
++	int ret;
++	struct gw_i2c_pld *gpio = container_of(chip, struct gw_i2c_pld, chip);
++	struct i2c_adapter *adap = gpio->client->adapter;
++	
++	if (in_atomic() || irqs_disabled()) {
++		ret = mutex_trylock(&adap->bus_lock);
++		if (!ret)
++			/* I2C activity is ongoing. */
++			return -EAGAIN;
++	} else {
++		mutex_lock_nested(&adap->bus_lock, adap->level);
++	}
++
++	gpio->out |= (1 << offset);
++
++	ret = i2c_pld_write_byte(gpio->client->addr, gpio->out);
++
++	mutex_unlock(&adap->bus_lock);
++
++	return ret;
++}
++
++static int gw_i2c_pld_get8(struct gpio_chip *chip, unsigned offset)
++{
++	int ret;
++	s32	value;
++	struct gw_i2c_pld *gpio = container_of(chip, struct gw_i2c_pld, chip);
++	struct i2c_adapter *adap = gpio->client->adapter;
++	
++	if (in_atomic() || irqs_disabled()) {
++		ret = mutex_trylock(&adap->bus_lock);
++		if (!ret)
++			/* I2C activity is ongoing. */
++			return -EAGAIN;
++	} else {
++		mutex_lock_nested(&adap->bus_lock, adap->level);
++	}
++
++	value = i2c_pld_read_byte(gpio->client->addr);
++
++	mutex_unlock(&adap->bus_lock);
++
++	return (value < 0) ? 0 : (value & (1 << offset));
++}
++
++static int gw_i2c_pld_output8(struct gpio_chip *chip, unsigned offset, int value)
++{
++	int ret;
++
++	struct gw_i2c_pld *gpio = container_of(chip, struct gw_i2c_pld, chip);
++	struct i2c_adapter *adap = gpio->client->adapter;
++
++	unsigned bit = 1 << offset;
++	
++	if (in_atomic() || irqs_disabled()) {
++		ret = mutex_trylock(&adap->bus_lock);
++		if (!ret)
++			/* I2C activity is ongoing. */
++			return -EAGAIN;
++	} else {
++		mutex_lock_nested(&adap->bus_lock, adap->level);
++	}
++
++
++	if (value)
++		gpio->out |= bit;
++	else
++		gpio->out &= ~bit;
++
++	ret = i2c_pld_write_byte(gpio->client->addr, gpio->out);
++
++	mutex_unlock(&adap->bus_lock);
++
++	return ret;
++}
++
++static void gw_i2c_pld_set8(struct gpio_chip *chip, unsigned offset, int value)
++{
++	gw_i2c_pld_output8(chip, offset, value);
++}
++
++/*-------------------------------------------------------------------------*/
++
++static int gw_i2c_pld_probe(struct i2c_client *client,
++			 const struct i2c_device_id *id)
++{
++	struct gw_i2c_pld_platform_data	*pdata;
++	struct gw_i2c_pld *gpio;
++	int status;
++
++	pdata = client->dev.platform_data;
++	if (!pdata)
++		return -ENODEV;
++
++	/* Allocate, initialize, and register this gpio_chip. */
++	gpio = kzalloc(sizeof *gpio, GFP_KERNEL);
++	if (!gpio)
++		return -ENOMEM;
++
++	gpio->chip.base = pdata->gpio_base;
++	gpio->chip.can_sleep = 1;
++	gpio->chip.dev = &client->dev;
++	gpio->chip.owner = THIS_MODULE;
++
++	gpio->chip.ngpio = pdata->nr_gpio;
++	gpio->chip.direction_input = gw_i2c_pld_input8;
++	gpio->chip.get = gw_i2c_pld_get8;
++	gpio->chip.direction_output = gw_i2c_pld_output8;
++	gpio->chip.set = gw_i2c_pld_set8;
++
++	gpio->chip.label = client->name;
++
++	gpio->client = client;
++	i2c_set_clientdata(client, gpio);
++
++	gpio->out = 0xFF;
++
++	status = gpiochip_add(&gpio->chip);
++	if (status < 0)
++		goto fail;
++
++	dev_info(&client->dev, "gpios %d..%d on a %s%s\n",
++			gpio->chip.base,
++			gpio->chip.base + gpio->chip.ngpio - 1,
++			client->name,
++			client->irq ? " (irq ignored)" : "");
++
++	/* Let platform code set up the GPIOs and their users.
++	 * Now is the first time anyone could use them.
++	 */
++	if (pdata->setup) {
++		status = pdata->setup(client,
++				gpio->chip.base, gpio->chip.ngpio,
++				pdata->context);
++		if (status < 0)
++			dev_warn(&client->dev, "setup --> %d\n", status);
++	}
++
++	return 0;
++
++fail:
++	dev_dbg(&client->dev, "probe error %d for '%s'\n",
++			status, client->name);
++	kfree(gpio);
++	return status;
++}
++
++static int gw_i2c_pld_remove(struct i2c_client *client)
++{
++	struct gw_i2c_pld_platform_data	*pdata = client->dev.platform_data;
++	struct gw_i2c_pld *gpio = i2c_get_clientdata(client);
++	int				status = 0;
++
++	if (pdata->teardown) {
++		status = pdata->teardown(client,
++				gpio->chip.base, gpio->chip.ngpio,
++				pdata->context);
++		if (status < 0) {
++			dev_err(&client->dev, "%s --> %d\n",
++					"teardown", status);
++			return status;
++		}
++	}
++
++	status = gpiochip_remove(&gpio->chip);
++	if (status == 0)
++		kfree(gpio);
++	else
++		dev_err(&client->dev, "%s --> %d\n", "remove", status);
++	return status;
++}
++
++static struct i2c_driver gw_i2c_pld_driver = {
++	.driver = {
++		.name	= "gw_i2c_pld",
++		.owner	= THIS_MODULE,
++	},
++	.probe	= gw_i2c_pld_probe,
++	.remove	= gw_i2c_pld_remove,
++	.id_table = gw_i2c_pld_id,
++};
++
++static int __init gw_i2c_pld_init(void)
++{
++	return i2c_add_driver(&gw_i2c_pld_driver);
++}
++module_init(gw_i2c_pld_init);
++
++static void __exit gw_i2c_pld_exit(void)
++{
++	i2c_del_driver(&gw_i2c_pld_driver);
++}
++module_exit(gw_i2c_pld_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Chris Lang");
+--- a/drivers/gpio/Kconfig
++++ b/drivers/gpio/Kconfig
+@@ -160,6 +160,14 @@ config GPIO_BT8XX
+ 
+ 	  If unsure, say N.
+ 
++config GPIO_GW_I2C_PLD
++	tristate "Gateworks I2C PLD GPIO Expander"
++	depends on I2C
++	help
++		Say yes here to provide access to the Gateworks I2C PLD GPIO
++		Expander. This is used at least on the GW2358-4.
++
++
+ comment "SPI GPIO expanders:"
+ 
+ config GPIO_MAX7301
+--- a/drivers/gpio/Makefile
++++ b/drivers/gpio/Makefile
+@@ -12,3 +12,4 @@ obj-$(CONFIG_GPIO_PCF857X)	+= pcf857x.o
+ obj-$(CONFIG_GPIO_TWL4030)	+= twl4030-gpio.o
+ obj-$(CONFIG_GPIO_XILINX)	+= xilinx_gpio.o
+ obj-$(CONFIG_GPIO_BT8XX)	+= bt8xxgpio.o
++obj-$(CONFIG_GPIO_GW_I2C_PLD)	+= gw_i2c_pld.o
+--- /dev/null
++++ b/include/linux/i2c/gw_i2c_pld.h
+@@ -0,0 +1,20 @@
++#ifndef __LINUX_GW_I2C_PLD_H
++#define __LINUX_GW_I2C_PLD_H
++
++/**
++ * The Gateworks I2C PLD Implements an additional 8 bits of GPIO through the PLD
++ */
++
++struct gw_i2c_pld_platform_data {
++	unsigned gpio_base;
++	unsigned nr_gpio;
++	int		(*setup)(struct i2c_client *client,
++					int gpio, unsigned ngpio,
++					void *context);
++	int		(*teardown)(struct i2c_client *client,
++					int gpio, unsigned ngpio,
++					void *context);
++	void		*context;
++};
++
++#endif /* __LINUX_GW_I2C_PLD_H */
diff --git a/target/linux/ixp4xx/patches-2.6.28/193-cambria_pld_gpio.patch b/target/linux/ixp4xx/patches-2.6.28/193-cambria_pld_gpio.patch
new file mode 100644
index 0000000000000000000000000000000000000000..299630f1719366904b126013e6bb3f6aadb0afbf
--- /dev/null
+++ b/target/linux/ixp4xx/patches-2.6.28/193-cambria_pld_gpio.patch
@@ -0,0 +1,107 @@
+--- a/arch/arm/mach-ixp4xx/cambria-setup.c
++++ b/arch/arm/mach-ixp4xx/cambria-setup.c
+@@ -12,11 +12,14 @@
+  */
+ 
+ #include <linux/device.h>
++#include <linux/gpio_buttons.h>
+ #include <linux/i2c.h>
+ #include <linux/i2c-gpio.h>
+ #include <linux/i2c/at24.h>
++#include <linux/i2c/gw_i2c_pld.h>
+ #include <linux/if_ether.h>
+ #include <linux/init.h>
++#include <linux/input.h>
+ #include <linux/kernel.h>
+ #include <linux/leds.h>
+ #include <linux/memory.h>
+@@ -323,6 +326,39 @@ static struct platform_device cambria_us
+ 	},
+ };
+ 
++static struct gw_i2c_pld_platform_data gw_i2c_pld_data0 = {
++	.gpio_base	= 16,
++	.nr_gpio	= 8,
++};
++
++static struct gw_i2c_pld_platform_data gw_i2c_pld_data1 = {
++	.gpio_base	= 24,
++	.nr_gpio	= 2,
++};
++
++
++static struct gpio_button cambria_gpio_buttons[] = {
++	{
++		.desc		= "user",
++		.type		= EV_KEY,
++		.code		= BTN_0,
++		.threshold	= 2,
++		.gpio		= 25,
++	}
++};
++
++static struct gpio_buttons_platform_data cambria_gpio_buttons_data = {
++	.poll_interval	= 500,
++	.nbuttons	= 1,
++	.buttons	= cambria_gpio_buttons,	
++};
++
++static struct platform_device cambria_gpio_buttons_device = {
++	.name			= "gpio-buttons",
++	.id			= -1,
++	.dev.platform_data	= &cambria_gpio_buttons_data,
++};
++
+ static struct platform_device *cambria_devices[] __initdata = {
+ 	&cambria_i2c_gpio,
+ 	&cambria_flash,
+@@ -331,6 +367,11 @@ static struct platform_device *cambria_d
+ 
+ static void __init cambria_gw23xx_setup(void)
+ {
++	cambria_gpio_resources[0].start = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) |\
++																		(1 << 5) | (1 << 8) | (1 << 9) | (1 << 12);
++	cambria_gpio_resources[0].end = cambria_gpio_resources[0].start;
++
++	platform_device_register(&cambria_gpio);
+ 	platform_device_register(&cambria_npec_device);
+ 	platform_device_register(&cambria_npea_device);
+ }
+@@ -377,7 +418,8 @@ static void __init cambria_gw2358_setup(
+ 	cambria_optional_uart_data[1].membase	= (void __iomem *)ioremap(0x53F80000, 0x0fff);
+ 	cambria_optional_uart_data[1].irq		= IRQ_IXP4XX_GPIO4;
+ 
+-	cambria_gpio_resources[0].start = (1 << 14);
++	cambria_gpio_resources[0].start = (1 << 14) | (1 << 16) | (1 << 17) | (1 << 18) |\
++																		(1 << 19) | (1 << 20) | (1 << 24) | (1 << 25);
+ 	cambria_gpio_resources[0].end = cambria_gpio_resources[0].start;
+ 
+ 	platform_device_register(&cambria_gpio);
+@@ -391,7 +433,12 @@ static void __init cambria_gw2358_setup(
+ 
+ 	platform_device_register(&cambria_pata);
+ 
++	cambria_gpio_leds[0].gpio = 24;
++	platform_device_register(&cambria_gpio_leds_device);
++
+ 	platform_device_register(&cambria_latch_leds_device);
++
++	platform_device_register(&cambria_gpio_buttons_device);
+ }
+ 
+ static struct cambria_board_info cambria_boards[] __initdata = {
+@@ -460,6 +507,14 @@ static struct i2c_board_info __initdata 
+ 		I2C_BOARD_INFO("24c08", 0x51),
+ 		.platform_data	= &cambria_eeprom_info
+ 	},
++	{
++		I2C_BOARD_INFO("gw_i2c_pld", 0x56),
++		.platform_data	= &gw_i2c_pld_data0,
++	},
++	{
++		I2C_BOARD_INFO("gw_i2c_pld", 0x57),
++		.platform_data	= &gw_i2c_pld_data1,
++	},
+ };
+ 
+ static void __init cambria_init(void)