diff -BNburp /home/jeroen/carambola/linux-2.6.39.4-with-1w//arch/mips/ralink/rt305x/mach-carambola.c linux-2.6.39.4//arch/mips/ralink/rt305x/mach-carambola.c
--- /home/jeroen/carambola/linux-2.6.39.4-with-1w//arch/mips/ralink/rt305x/mach-carambola.c	2012-04-11 16:11:17.000000000 +0200
+++ linux-2.6.39.4//arch/mips/ralink/rt305x/mach-carambola.c	2012-04-11 21:24:53.000000000 +0200
@@ -18,6 +18,8 @@
 #include <asm/mach-ralink/machine.h>
 #include <asm/mach-ralink/rt305x.h>
 #include <asm/mach-ralink/rt305x_regs.h>
+#include <asm/mach-ralink/common.h>
+#include <asm/mach-ralink/ramips_gpio.h>
 #include <asm/sizes.h>
 #include <linux/i2c.h>
 #include <linux/i2c-gpio.h>
@@ -121,8 +123,110 @@ static struct platform_device *carambola
 #endif
 };
 
+
+struct  carambola_gpio_mode_struct {
+	const char *name;
+	const int value;
+};
+
+static const struct carambola_gpio_mode_struct carambola_gpio_modes[]={
+	{"UARTF", RT305X_GPIO_MODE_UARTF},
+	{"PCM+UARTF", RT305X_GPIO_MODE_PCM_UARTF},
+	{"PCM+I2S", RT305X_GPIO_MODE_PCM_I2S},
+	{"I2S+UARTF", RT305X_GPIO_MODE_I2S_UARTF},
+	{"PCM+GPIO", RT305X_GPIO_MODE_PCM_GPIO},
+	{"GPIO+UARTF", RT305X_GPIO_MODE_GPIO_UARTF},
+	{"GPIO+I2S", RT305X_GPIO_MODE_GPIO_I2S},
+	{"GPIO", RT305X_GPIO_MODE_GPIO},
+	{NULL, 0}
+};
+
+//Reserves or frees a gpu, depending on the value of doreserve
+static void carambola_gpio_free_reserve(int first, int last, int doreserve) {
+	for (; first <= last; first++)
+		if (doreserve) gpio_request(first, "reserved"); else gpio_free(first);
+}
+
+static ssize_t carambola_uart1_mode_show(struct device *dev, struct device_attribute *attr, char *buf) {
+	int x=0;
+	int mode=(rt305x_sysc_rr(SYSC_REG_GPIO_MODE)>>RT305X_GPIO_MODE_UART0_SHIFT)&RT305X_GPIO_MODE_UART0_MASK;
+	while (carambola_gpio_modes[x].name!=NULL && carambola_gpio_modes[x].value!=mode) x++;
+	if (carambola_gpio_modes[x].name==NULL) return 0; //shouldn't happen
+	return scnprintf(buf, PAGE_SIZE, "%s\n", carambola_gpio_modes[x].name);
+}
+
+static ssize_t carambola_uart1_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
+	int x=0;
+	int mode=rt305x_sysc_rr(SYSC_REG_GPIO_MODE);
+	while (carambola_gpio_modes[x].name!=NULL && strncmp(carambola_gpio_modes[x].name, buf, strlen(carambola_gpio_modes[x].name))!=0 ) x++;
+	if (carambola_gpio_modes[x].name==NULL) return -EINVAL;
+	mode&=~(RT305X_GPIO_MODE_UART0_MASK<<RT305X_GPIO_MODE_UART0_SHIFT); //Mask off old mode bits
+	mode|=carambola_gpio_modes[x].value<<RT305X_GPIO_MODE_UART0_SHIFT;
+	rt305x_sysc_wr(mode, SYSC_REG_GPIO_MODE);
+	//ToDo: We oughtta free/reserve the GPIOS for whatever mode is selected...
+	return count;
+}
+
+static ssize_t carambola_uart2_mode_show(struct device *dev, struct device_attribute *attr, char *buf) {
+	int mode=rt305x_sysc_rr(SYSC_REG_GPIO_MODE);
+	if (mode&RT305X_GPIO_MODE_UART1) return scnprintf(buf, PAGE_SIZE, "GPIO\n"); else return scnprintf(buf, PAGE_SIZE, "UART\n"); 
+}
+
+static ssize_t carambola_uart2_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
+	int mode=rt305x_sysc_rr(SYSC_REG_GPIO_MODE);
+	int b=-1;
+	if (strncmp(buf, "0", 1)==0 || strncmp(buf, "UART", 4)==0) b=0;
+	if (strncmp(buf, "1", 1)==0 || strncmp(buf, "GPIO", 4)==0) b=RT305X_GPIO_MODE_UART1;
+	if (b==-1) return -EINVAL;
+	carambola_gpio_free_reserve(RT305X_GPIO_UART1_TXD, RT305X_GPIO_UART1_RXD, b);
+	mode=(mode&~RT305X_GPIO_MODE_UART1)|b;
+	rt305x_sysc_wr(mode, SYSC_REG_GPIO_MODE);
+	return count;
+}
+
+static ssize_t carambola_spi_mode_show(struct device *dev, struct device_attribute *attr, char *buf) {
+	int mode=rt305x_sysc_rr(SYSC_REG_GPIO_MODE);
+	if (mode&RT305X_GPIO_MODE_SPI) return scnprintf(buf, PAGE_SIZE, "GPIO\n"); else return scnprintf(buf, PAGE_SIZE, "SPI\n"); 
+}
+
+static ssize_t carambola_spi_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
+	int mode=rt305x_sysc_rr(SYSC_REG_GPIO_MODE);
+	int b=-1;
+	if (strncmp(buf, "0", 1)==0 || strncmp(buf, "SPI", 3)==0) b=0;
+	if (strncmp(buf, "1", 1)==0 || strncmp(buf, "GPIO", 4)==0) b=RT305X_GPIO_MODE_SPI;
+	if (b==-1) return -EINVAL;
+	carambola_gpio_free_reserve(RT305X_GPIO_SPI_EN, RT305X_GPIO_SPI_CLK, b);
+	mode=(mode&~RT305X_GPIO_MODE_SPI)|b;
+	rt305x_sysc_wr(mode, SYSC_REG_GPIO_MODE);
+	return count;
+}
+
+static ssize_t carambola_jtag_mode_show(struct device *dev, struct device_attribute *attr, char *buf) {
+	int mode=rt305x_sysc_rr(SYSC_REG_GPIO_MODE);
+	if (mode&RT305X_GPIO_MODE_JTAG) return scnprintf(buf, PAGE_SIZE, "GPIO\n"); else return scnprintf(buf, PAGE_SIZE, "JTAG\n"); 
+}
+
+static ssize_t carambola_jtag_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
+	int mode=rt305x_sysc_rr(SYSC_REG_GPIO_MODE);
+	int b=-1;
+	if (strncmp(buf, "0", 1)==0 || strncmp(buf, "JTAG", 4)==0) b=0;
+	if (strncmp(buf, "1", 1)==0 || strncmp(buf, "GPIO", 4)==0) b=RT305X_GPIO_MODE_JTAG;
+	if (b==-1) return -EINVAL;
+	carambola_gpio_free_reserve(RT305X_GPIO_JTAG_TDO, RT305X_GPIO_JTAG_TDI, b);
+	mode=(mode&~RT305X_GPIO_MODE_JTAG)|b;
+	rt305x_sysc_wr(mode, SYSC_REG_GPIO_MODE);
+	return count;
+}
+
+static DEVICE_ATTR(uart1_mode, S_IRUGO|S_IWUGO, carambola_uart1_mode_show, carambola_uart1_mode_store);
+static DEVICE_ATTR(uart2_mode, S_IRUGO|S_IWUGO, carambola_uart2_mode_show, carambola_uart2_mode_store);
+static DEVICE_ATTR(spi_mode, S_IRUGO|S_IWUGO, carambola_spi_mode_show, carambola_spi_mode_store);
+static DEVICE_ATTR(jtag_mode, S_IRUGO|S_IWUGO, carambola_jtag_mode_show, carambola_jtag_mode_store);
+
+
 static void __init carambola_init(void)
 {
+	struct kobject *carambola_kobj;
 	rt305x_gpio_init((RT305X_GPIO_MODE_GPIO << RT305X_GPIO_MODE_UART0_SHIFT) |
 			 RT305X_GPIO_MODE_I2C);
 	carambola_register_gpiodev();
@@ -134,6 +238,11 @@ static void __init carambola_init(void)
 	rt305x_register_wifi();
 	rt305x_register_wdt();
 	rt305x_register_usb();
+	carambola_kobj=kobject_create_and_add("carambola", NULL);
+	sysfs_create_file(carambola_kobj, &dev_attr_uart1_mode.attr);
+	sysfs_create_file(carambola_kobj, &dev_attr_uart2_mode.attr);
+	sysfs_create_file(carambola_kobj, &dev_attr_spi_mode.attr);
+	sysfs_create_file(carambola_kobj, &dev_attr_jtag_mode.attr);
 }
 
 MIPS_MACHINE(RAMIPS_MACH_CARAMBOLA, "CARAMBOLA", "CARAMBOLA",
