diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index 6b1f323..e4ce15d 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -25,6 +25,8 @@
 #include <linux/dma-mapping.h>
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
 
 #include <asm/setup.h>
 #include <linux/io.h>
@@ -43,6 +45,7 @@
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
 #include <linux/i2c/at24.h>
+#include <linux/i2c/pcf857x.h>
 #include <linux/etherdevice.h>
 #include <mach/emac.h>
 
@@ -54,6 +57,169 @@ static struct davinci_board_config_kernel davinci_evm_config[] __initdata = {
 	{ DAVINCI_TAG_UART,     &davinci_evm_uart_config },
 };
 
+/* LEDS */
+
+static struct gpio_led evm_leds[] = {
+	{ .name = "DS1", .active_low = 1, },
+	{ .name = "DS2", .active_low = 1, },
+	{ .name = "DS3", .active_low = 1, },
+	{ .name = "DS4", .active_low = 1, },
+};
+
+static const struct gpio_led_platform_data evm_led_data = {
+	.num_leds = ARRAY_SIZE(evm_leds),
+	.leds     = evm_leds,
+};
+
+static struct platform_device *evm_led_dev;
+
+static int evm_led_setup(struct i2c_client *client, int gpio, unsigned int ngpio, void *c)
+{
+	struct gpio_led *leds = evm_leds;
+	int status;
+
+	while (ngpio--) {
+		leds->gpio = gpio++;
+		leds++;
+	};
+
+	evm_led_dev = platform_device_alloc("leds-gpio", 0);
+	platform_device_add_data(evm_led_dev, &evm_led_data, sizeof(evm_led_data));
+
+	evm_led_dev->dev.parent = &client->dev;
+	status = platform_device_add(evm_led_dev);
+	if (status < 0) {
+		platform_device_put(evm_led_dev);
+		evm_led_dev = NULL;
+	}
+	return status;
+}
+
+static int evm_led_teardown(struct i2c_client* client, int gpio, unsigned ngpio, void* c)
+{
+	if (evm_led_dev) {
+		platform_device_unregister(evm_led_dev);
+		evm_led_dev = NULL;
+	}
+	return 0;
+}
+
+static int evm_sw_gpio[4] = { -EINVAL, -EINVAL, -EINVAL, -EINVAL };
+
+static inline ssize_t
+evm_sw_show(struct device *d, struct device_attribute *a, char *buf, int gpio)
+{
+	char *s = gpio_get_value_cansleep(gpio) ? "on\n" : "off\n";
+
+	strcpy(buf, s);
+	return strlen(s);
+}
+
+#define SW_SHOW(id) \
+static ssize_t sw_show_##id(struct device* d, struct device_attribute *a, char *buf) \
+{ \
+	return evm_sw_show(d, a, buf, evm_sw_gpio[id]); \
+}
+
+
+SW_SHOW(0);
+SW_SHOW(1);
+SW_SHOW(2);
+SW_SHOW(3);
+
+static struct device_attribute sw_attrs[] = {
+	__ATTR(user_sw1, S_IRUGO, sw_show_0, NULL),
+	__ATTR(user_sw2, S_IRUGO, sw_show_1, NULL),
+	__ATTR(user_sw3, S_IRUGO, sw_show_2, NULL),
+	__ATTR(user_sw4, S_IRUGO, sw_show_3, NULL),
+};
+
+
+static int evm_sw_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c)
+{
+	int status;
+	int i;
+	char label[10];
+	
+	for (i = 0; i < 4; ++i) {
+		snprintf(label, 10, "user_sw%d", i);
+		status = gpio_request(gpio, label);
+		if (status)
+		{
+			goto out_free;
+		}
+		evm_sw_gpio[i] = gpio++;
+		
+		status = gpio_direction_input(evm_sw_gpio[i]);
+		if (status) {
+			gpio_free(evm_sw_gpio[i]);
+			evm_sw_gpio[i] = -EINVAL;
+			goto out_free;
+		}
+		
+		status = device_create_file(&client->dev, &sw_attrs[i]);
+		if (status) {
+			gpio_free(evm_sw_gpio[i]);
+			evm_sw_gpio[i] = -EINVAL;
+			goto out_free;
+		}
+	}
+	return status;
+out_free:
+	for (i = 0; i < 4; ++i) {
+		if (evm_sw_gpio[i] != -EINVAL) {
+			device_remove_file(&client->dev, &sw_attrs[i]);
+			gpio_free(evm_sw_gpio[i]);
+			evm_sw_gpio[i] = -EINVAL;
+		}
+	}
+	return status;
+}
+
+static int evm_sw_teardown(struct i2c_client *client, int gpio, unsigned ngpio, void *c)
+{
+	int i;
+
+	for (i = 0; i < 4; ++i) {
+		if (evm_sw_gpio[i] != -EINVAL) {
+			device_remove_file(&client->dev, &sw_attrs[i]);
+			gpio_free(evm_sw_gpio[i]);
+			evm_sw_gpio[i] = -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static int evm_pcf_setup(struct i2c_client *client, int gpio, unsigned int ngpio, void *c)
+{
+	int status;
+	
+	if (ngpio < 8)
+		return -EINVAL;
+
+	status = evm_sw_setup(client, gpio, 4, c);
+	if (status)
+		return status;
+	
+	return evm_led_setup(client, gpio+4, 4, c);
+}
+
+static int evm_pcf_teardown(struct i2c_client *client, int gpio, unsigned int ngpio, void *c)
+{
+	BUG_ON(ngpio < 8);
+
+	evm_sw_teardown(client, gpio, 4, c);
+	evm_led_teardown(client, gpio+4, 4, c);
+
+	return 0;
+}
+
+static struct pcf857x_platform_data pcf_data = {
+	.gpio_base	= DAVINCI_N_GPIO+1,
+	.setup		= evm_pcf_setup,
+	.teardown	= evm_pcf_teardown,
+};
+
 /* Most of this EEPROM is unused, but U-Boot uses some data:
  *  - 0x7f00, 6 bytes Ethernet Address
  *  - ... newer boards may have more
@@ -104,6 +270,10 @@ static struct i2c_board_info __initdata i2c_info[] =  {
 		I2C_BOARD_INFO("24c256", 0x50),
 		.platform_data  = &eeprom_info,
 	},
+	{
+		I2C_BOARD_INFO("pcf8574a", 0x38),
+		.platform_data	= &pcf_data,
+	},
 };
 
 static struct davinci_i2c_platform_data i2c_pdata = {
