Merge branch 'pxa-tosa' into pxa

Conflicts:

	arch/arm/mach-pxa/Kconfig
	arch/arm/mach-pxa/tosa.c
	arch/arm/mach-pxa/spitz.c
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 1a7ceb8..7f9664d 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -310,4 +310,13 @@
 	default BACKLIGHT_PWM
 	help
 	  Enable support for PXA2xx/PXA3xx PWM controllers
+
+config TOSA_BT
+	tristate "Control the state of built-in bluetooth chip on Sharp SL-6000"
+	depends on MACH_TOSA
+	select RFKILL
+	help
+	  This is a simple driver that is able to control
+	  the state of built in bluetooth chip on tosa.
+
 endif
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 0865236..b282412 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -4,7 +4,7 @@
 
 # Common support (must be linked before board specific support)
 obj-y				+= clock.o devices.o generic.o irq.o dma.o \
-				   time.o gpio.o
+				   time.o gpio.o reset.o
 obj-$(CONFIG_PM)		+= pm.o sleep.o standby.o
 obj-$(CONFIG_CPU_FREQ)		+= cpu-pxa.o
 
@@ -61,3 +61,5 @@
 ifeq ($(CONFIG_PCI),y)
 obj-$(CONFIG_MACH_ARMCORE) += cm-x270-pci.o
 endif
+
+obj-$(CONFIG_TOSA_BT)		+= tosa-bt.o
diff --git a/arch/arm/mach-pxa/reset.c b/arch/arm/mach-pxa/reset.c
new file mode 100644
index 0000000..9d39dea
--- /dev/null
+++ b/arch/arm/mach-pxa/reset.c
@@ -0,0 +1,96 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <asm/io.h>
+#include <asm/proc-fns.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-regs.h>
+
+static void do_hw_reset(void);
+
+static int reset_gpio = -1;
+
+int init_gpio_reset(int gpio)
+{
+	int rc;
+
+	rc = gpio_request(gpio, "reset generator");
+	if (rc) {
+		printk(KERN_ERR "Can't request reset_gpio\n");
+		goto out;
+	}
+
+	rc = gpio_direction_input(gpio);
+	if (rc) {
+		printk(KERN_ERR "Can't configure reset_gpio for input\n");
+		gpio_free(gpio);
+		goto out;
+	}
+
+out:
+	if (!rc)
+		reset_gpio = gpio;
+
+	return rc;
+}
+
+/*
+ * Trigger GPIO reset.
+ * This covers various types of logic connecting gpio pin
+ * to RESET pins (nRESET or GPIO_RESET):
+ */
+static void do_gpio_reset(void)
+{
+	BUG_ON(reset_gpio == -1);
+
+	/* drive it low */
+	gpio_direction_output(reset_gpio, 0);
+	mdelay(2);
+	/* rising edge or drive high */
+	gpio_set_value(reset_gpio, 1);
+	mdelay(2);
+	/* falling edge */
+	gpio_set_value(reset_gpio, 0);
+
+	/* give it some time */
+	mdelay(10);
+
+	WARN_ON(1);
+	/* fallback */
+	do_hw_reset();
+}
+
+static void do_hw_reset(void)
+{
+	/* Initialize the watchdog and let it fire */
+	OWER = OWER_WME;
+	OSSR = OSSR_M3;
+	OSMR3 = OSCR + 368640;	/* ... in 100 ms */
+}
+
+void arch_reset(char mode)
+{
+	if (cpu_is_pxa2xx())
+		RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
+
+	switch (mode) {
+	case 's':
+		/* Jump into ROM at address 0 */
+		cpu_reset(0);
+		break;
+	case 'h':
+		do_hw_reset();
+		break;
+	case 'g':
+		do_gpio_reset();
+		break;
+	}
+}
+
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index e7d0fcd..d58c3e9 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -38,6 +38,7 @@
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/pxa2xx-regs.h>
 #include <asm/arch/pxa2xx-gpio.h>
+#include <asm/arch/pxa27x-udc.h>
 #include <asm/arch/irda.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/ohci.h>
@@ -529,11 +530,7 @@
 
 static void spitz_poweroff(void)
 {
-	pxa_gpio_mode(SPITZ_GPIO_ON_RESET | GPIO_OUT);
-	GPSR(SPITZ_GPIO_ON_RESET) = GPIO_bit(SPITZ_GPIO_ON_RESET);
-
-	mdelay(1000);
-	arm_machine_restart('h');
+	arm_machine_restart('g');
 }
 
 static void spitz_restart(char mode)
@@ -547,6 +544,7 @@
 
 static void __init common_init(void)
 {
+	init_gpio_reset(SPITZ_GPIO_ON_RESET);
 	pm_power_off = spitz_poweroff;
 	arm_pm_restart = spitz_restart;
 
diff --git a/arch/arm/mach-pxa/tosa-bt.c b/arch/arm/mach-pxa/tosa-bt.c
new file mode 100644
index 0000000..7d85054
--- /dev/null
+++ b/arch/arm/mach-pxa/tosa-bt.c
@@ -0,0 +1,150 @@
+/*
+ * Bluetooth built-in chip control
+ *
+ * Copyright (c) 2008 Dmitry Baryshkov
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/rfkill.h>
+
+#include <asm/arch/tosa_bt.h>
+
+static void tosa_bt_on(struct tosa_bt_data *data)
+{
+	gpio_set_value(data->gpio_reset, 0);
+	gpio_set_value(data->gpio_pwr, 1);
+	gpio_set_value(data->gpio_reset, 1);
+	mdelay(20);
+	gpio_set_value(data->gpio_reset, 0);
+}
+
+static void tosa_bt_off(struct tosa_bt_data *data)
+{
+	gpio_set_value(data->gpio_reset, 1);
+	mdelay(10);
+	gpio_set_value(data->gpio_pwr, 0);
+	gpio_set_value(data->gpio_reset, 0);
+}
+
+static int tosa_bt_toggle_radio(void *data, enum rfkill_state state)
+{
+	pr_info("BT_RADIO going: %s\n",
+			state == RFKILL_STATE_ON ? "on" : "off");
+
+	if (state == RFKILL_STATE_ON) {
+		pr_info("TOSA_BT: going ON\n");
+		tosa_bt_on(data);
+	} else {
+		pr_info("TOSA_BT: going OFF\n");
+		tosa_bt_off(data);
+	}
+	return 0;
+}
+
+static int tosa_bt_probe(struct platform_device *dev)
+{
+	int rc;
+	struct rfkill *rfk;
+
+	struct tosa_bt_data *data = dev->dev.platform_data;
+
+	rc = gpio_request(data->gpio_reset, "Bluetooth reset");
+	if (rc)
+		goto err_reset;
+	rc = gpio_direction_output(data->gpio_reset, 0);
+	if (rc)
+		goto err_reset_dir;
+	rc = gpio_request(data->gpio_pwr, "Bluetooth power");
+	if (rc)
+		goto err_pwr;
+	rc = gpio_direction_output(data->gpio_pwr, 0);
+	if (rc)
+		goto err_pwr_dir;
+
+	rfk = rfkill_allocate(&dev->dev, RFKILL_TYPE_BLUETOOTH);
+	if (!rfk) {
+		rc = -ENOMEM;
+		goto err_rfk_alloc;
+	}
+
+	rfk->name = "tosa-bt";
+	rfk->toggle_radio = tosa_bt_toggle_radio;
+	rfk->data = data;
+#ifdef CONFIG_RFKILL_LEDS
+	rfk->led_trigger.name = "tosa-bt";
+#endif
+
+	rc = rfkill_register(rfk);
+	if (rc)
+		goto err_rfkill;
+
+	platform_set_drvdata(dev, rfk);
+
+	return 0;
+
+err_rfkill:
+	if (rfk)
+		rfkill_free(rfk);
+	rfk = NULL;
+err_rfk_alloc:
+	tosa_bt_off(data);
+err_pwr_dir:
+	gpio_free(data->gpio_pwr);
+err_pwr:
+err_reset_dir:
+	gpio_free(data->gpio_reset);
+err_reset:
+	return rc;
+}
+
+static int __devexit tosa_bt_remove(struct platform_device *dev)
+{
+	struct tosa_bt_data *data = dev->dev.platform_data;
+	struct rfkill *rfk = platform_get_drvdata(dev);
+
+	platform_set_drvdata(dev, NULL);
+
+	if (rfk)
+		rfkill_unregister(rfk);
+	rfk = NULL;
+
+	tosa_bt_off(data);
+
+	gpio_free(data->gpio_pwr);
+	gpio_free(data->gpio_reset);
+
+	return 0;
+}
+
+static struct platform_driver tosa_bt_driver = {
+	.probe = tosa_bt_probe,
+	.remove = __devexit_p(tosa_bt_remove),
+
+	.driver = {
+		.name = "tosa-bt",
+		.owner = THIS_MODULE,
+	},
+};
+
+
+static int __init tosa_bt_init(void)
+{
+	return platform_driver_register(&tosa_bt_driver);
+}
+
+static void __exit tosa_bt_exit(void)
+{
+	platform_driver_unregister(&tosa_bt_driver);
+}
+
+module_init(tosa_bt_init);
+module_exit(tosa_bt_exit);
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index ab4a9f5..2d49de5 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -18,30 +18,31 @@
 #include <linux/major.h>
 #include <linux/fs.h>
 #include <linux/interrupt.h>
-#include <linux/mmc/host.h>
-#include <linux/pm.h>
 #include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/mmc/host.h>
+#include <linux/mfd/tc6393xb.h>
+#include <linux/mfd/tmio.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/pm.h>
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
 #include <linux/gpio.h>
+#include <linux/pda_power.h>
+#include <linux/rfkill.h>
 
 #include <asm/setup.h>
-#include <asm/memory.h>
 #include <asm/mach-types.h>
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/arch/pxa-regs.h>
 #include <asm/arch/pxa2xx-regs.h>
 #include <asm/arch/mfp-pxa25x.h>
 #include <asm/arch/irda.h>
 #include <asm/arch/i2c.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/udc.h>
+#include <asm/arch/tosa_bt.h>
 
 #include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
 #include <asm/arch/tosa.h>
 
 #include <asm/hardware/scoop.h>
@@ -86,7 +87,7 @@
 	GPIO6_MMC_CLK,
 	GPIO8_MMC_CS0,
 	GPIO9_GPIO, /* Detect */
-	// GPIO10 nSD_INT
+	GPIO10_GPIO, /* nSD_INT */
 
 	/* CF */
 	GPIO13_GPIO, /* CD_IRQ */
@@ -124,29 +125,25 @@
 	GPIO44_BTUART_CTS,
 	GPIO45_BTUART_RTS,
 
-	/* IrDA */
-	GPIO46_STUART_RXD,
-	GPIO47_STUART_TXD,
-
 	/* Keybd */
-	GPIO58_GPIO,
-	GPIO59_GPIO,
-	GPIO60_GPIO,
-	GPIO61_GPIO,
-	GPIO62_GPIO,
-	GPIO63_GPIO,
-	GPIO64_GPIO,
-	GPIO65_GPIO,
-	GPIO66_GPIO,
-	GPIO67_GPIO,
-	GPIO68_GPIO,
-	GPIO69_GPIO,
-	GPIO70_GPIO,
-	GPIO71_GPIO,
-	GPIO72_GPIO,
-	GPIO73_GPIO,
-	GPIO74_GPIO,
-	GPIO75_GPIO,
+	GPIO58_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO59_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO60_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO61_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO62_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO63_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO64_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO65_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO66_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO67_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO68_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO69_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO70_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO71_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO72_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO73_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO74_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO75_GPIO | MFP_LPM_DRIVE_LOW,
 
 	/* SPI */
 	GPIO81_SSP2_CLK_OUT,
@@ -154,6 +151,17 @@
 	GPIO83_SSP2_TXD,
 };
 
+static unsigned long tosa_pin_irda_off[] = {
+	GPIO46_STUART_RXD,
+	GPIO47_GPIO | MFP_LPM_DRIVE_LOW,
+};
+
+static unsigned long tosa_pin_irda_on[] = {
+	GPIO46_STUART_RXD,
+	GPIO47_STUART_TXD,
+};
+
+
 /*
  * SCOOP Device
  */
@@ -249,6 +257,15 @@
 
 	tosa_mci_platform_data.detect_delay = msecs_to_jiffies(250);
 
+	err = gpio_request(TOSA_GPIO_nSD_DETECT, "MMC/SD card detect");
+	if (err) {
+		printk(KERN_ERR "tosa_mci_init: can't request nSD_DETECT gpio\n");
+		goto err_gpio_detect;
+	}
+	err = gpio_direction_input(TOSA_GPIO_nSD_DETECT);
+	if (err)
+		goto err_gpio_detect_dir;
+
 	err = request_irq(TOSA_IRQ_GPIO_nSD_DETECT, tosa_detect_int,
 			  IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 				"MMC/SD card detect", data);
@@ -257,7 +274,7 @@
 		goto err_irq;
 	}
 
-	err = gpio_request(TOSA_GPIO_SD_WP, "sd_wp");
+	err = gpio_request(TOSA_GPIO_SD_WP, "SD Write Protect");
 	if (err) {
 		printk(KERN_ERR "tosa_mci_init: can't request SD_WP gpio\n");
 		goto err_gpio_wp;
@@ -266,7 +283,7 @@
 	if (err)
 		goto err_gpio_wp_dir;
 
-	err = gpio_request(TOSA_GPIO_PWR_ON, "sd_pwr");
+	err = gpio_request(TOSA_GPIO_PWR_ON, "SD Power");
 	if (err) {
 		printk(KERN_ERR "tosa_mci_init: can't request SD_PWR gpio\n");
 		goto err_gpio_pwr;
@@ -275,8 +292,20 @@
 	if (err)
 		goto err_gpio_pwr_dir;
 
+	err = gpio_request(TOSA_GPIO_nSD_INT, "SD Int");
+	if (err) {
+		printk(KERN_ERR "tosa_mci_init: can't request SD_PWR gpio\n");
+		goto err_gpio_int;
+	}
+	err = gpio_direction_input(TOSA_GPIO_nSD_INT);
+	if (err)
+		goto err_gpio_int_dir;
+
 	return 0;
 
+err_gpio_int_dir:
+	gpio_free(TOSA_GPIO_nSD_INT);
+err_gpio_int:
 err_gpio_pwr_dir:
 	gpio_free(TOSA_GPIO_PWR_ON);
 err_gpio_pwr:
@@ -285,6 +314,9 @@
 err_gpio_wp:
 	free_irq(TOSA_IRQ_GPIO_nSD_DETECT, data);
 err_irq:
+err_gpio_detect_dir:
+	gpio_free(TOSA_GPIO_nSD_DETECT);
+err_gpio_detect:
 	return err;
 }
 
@@ -306,9 +338,11 @@
 
 static void tosa_mci_exit(struct device *dev, void *data)
 {
+	gpio_free(TOSA_GPIO_nSD_INT);
 	gpio_free(TOSA_GPIO_PWR_ON);
 	gpio_free(TOSA_GPIO_SD_WP);
 	free_irq(TOSA_IRQ_GPIO_nSD_DETECT, data);
+	gpio_free(TOSA_GPIO_nSD_DETECT);
 }
 
 static struct pxamci_platform_data tosa_mci_platform_data = {
@@ -322,29 +356,55 @@
 /*
  * Irda
  */
+static void tosa_irda_transceiver_mode(struct device *dev, int mode)
+{
+	if (mode & IR_OFF) {
+		gpio_set_value(TOSA_GPIO_IR_POWERDWN, 0);
+		pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_irda_off));
+		gpio_direction_output(TOSA_GPIO_IRDA_TX, 0);
+	} else {
+		pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_irda_on));
+		gpio_set_value(TOSA_GPIO_IR_POWERDWN, 1);
+	}
+}
+
 static int tosa_irda_startup(struct device *dev)
 {
 	int ret;
 
+	ret = gpio_request(TOSA_GPIO_IRDA_TX, "IrDA TX");
+	if (ret)
+		goto err_tx;
+	ret = gpio_direction_output(TOSA_GPIO_IRDA_TX, 0);
+	if (ret)
+		goto err_tx_dir;
+
 	ret = gpio_request(TOSA_GPIO_IR_POWERDWN, "IrDA powerdown");
 	if (ret)
-		return ret;
+		goto err_pwr;
 
 	ret = gpio_direction_output(TOSA_GPIO_IR_POWERDWN, 0);
 	if (ret)
-		gpio_free(TOSA_GPIO_IR_POWERDWN);
+		goto err_pwr_dir;
 
+	tosa_irda_transceiver_mode(dev, IR_SIRMODE | IR_OFF);
+
+	return 0;
+
+err_pwr_dir:
+	gpio_free(TOSA_GPIO_IR_POWERDWN);
+err_pwr:
+err_tx_dir:
+	gpio_free(TOSA_GPIO_IRDA_TX);
+err_tx:
 	return ret;
-	}
+}
 
 static void tosa_irda_shutdown(struct device *dev)
 {
+	tosa_irda_transceiver_mode(dev, IR_SIRMODE | IR_OFF);
 	gpio_free(TOSA_GPIO_IR_POWERDWN);
-}
-
-static void tosa_irda_transceiver_mode(struct device *dev, int mode)
-{
-	gpio_set_value(TOSA_GPIO_IR_POWERDWN, !(mode & IR_OFF));
+	gpio_free(TOSA_GPIO_IRDA_TX);
 }
 
 static struct pxaficp_platform_data tosa_ficp_platform_data = {
@@ -355,6 +415,70 @@
 };
 
 /*
+ * Tosa AC IN
+ */
+static int tosa_power_init(struct device *dev)
+{
+	int ret = gpio_request(TOSA_GPIO_AC_IN, "ac in");
+	if (ret)
+		goto err_gpio_req;
+
+	ret = gpio_direction_input(TOSA_GPIO_AC_IN);
+	if (ret)
+		goto err_gpio_in;
+
+	return 0;
+
+err_gpio_in:
+	gpio_free(TOSA_GPIO_AC_IN);
+err_gpio_req:
+	return ret;
+}
+
+static void tosa_power_exit(struct device *dev)
+{
+	gpio_free(TOSA_GPIO_AC_IN);
+}
+
+static int tosa_power_ac_online(void)
+{
+	return gpio_get_value(TOSA_GPIO_AC_IN) == 0;
+}
+
+static char *tosa_ac_supplied_to[] = {
+	"main-battery",
+	"backup-battery",
+	"jacket-battery",
+};
+
+static struct pda_power_pdata tosa_power_data = {
+	.init			= tosa_power_init,
+	.is_ac_online		= tosa_power_ac_online,
+	.exit			= tosa_power_exit,
+	.supplied_to		= tosa_ac_supplied_to,
+	.num_supplicants	= ARRAY_SIZE(tosa_ac_supplied_to),
+};
+
+static struct resource tosa_power_resource[] = {
+	{
+		.name		= "ac",
+		.start		= gpio_to_irq(TOSA_GPIO_AC_IN),
+		.end		= gpio_to_irq(TOSA_GPIO_AC_IN),
+		.flags		= IORESOURCE_IRQ |
+				  IORESOURCE_IRQ_HIGHEDGE |
+				  IORESOURCE_IRQ_LOWEDGE,
+	},
+};
+
+static struct platform_device tosa_power_device = {
+	.name			= "pda-power",
+	.id			= -1,
+	.dev.platform_data	= &tosa_power_data,
+	.resource		= tosa_power_resource,
+	.num_resources		= ARRAY_SIZE(tosa_power_resource),
+};
+
+/*
  * Tosa Keyboard
  */
 static struct platform_device tosakbd_device = {
@@ -439,7 +563,7 @@
 	},
 	{
 		.name			= "tosa:blue:bluetooth",
-		.default_trigger	= "none",
+		.default_trigger	= "tosa-bt",
 		.gpio			= TOSA_GPIO_BT_LED,
 	},
 };
@@ -457,21 +581,184 @@
 	},
 };
 
+/*
+ * Toshiba Mobile IO Controller
+ */
+static struct resource tc6393xb_resources[] = {
+	[0] = {
+		.start	= TOSA_LCDC_PHYS,
+		.end	= TOSA_LCDC_PHYS + 0x3ffffff,
+		.flags	= IORESOURCE_MEM,
+	},
+
+	[1] = {
+		.start	= TOSA_IRQ_GPIO_TC6393XB_INT,
+		.end	= TOSA_IRQ_GPIO_TC6393XB_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+
+static int tosa_tc6393xb_enable(struct platform_device *dev)
+{
+	int rc;
+
+	rc = gpio_request(TOSA_GPIO_TC6393XB_REST_IN, "tc6393xb #pclr");
+	if (rc)
+		goto err_req_pclr;
+	rc = gpio_request(TOSA_GPIO_TC6393XB_SUSPEND, "tc6393xb #suspend");
+	if (rc)
+		goto err_req_suspend;
+	rc = gpio_request(TOSA_GPIO_TC6393XB_L3V_ON, "l3v");
+	if (rc)
+		goto err_req_l3v;
+	rc = gpio_direction_output(TOSA_GPIO_TC6393XB_L3V_ON, 0);
+	if (rc)
+		goto err_dir_l3v;
+	rc = gpio_direction_output(TOSA_GPIO_TC6393XB_SUSPEND, 0);
+	if (rc)
+		goto err_dir_suspend;
+	rc = gpio_direction_output(TOSA_GPIO_TC6393XB_REST_IN, 0);
+	if (rc)
+		goto err_dir_pclr;
+
+	mdelay(1);
+
+	gpio_set_value(TOSA_GPIO_TC6393XB_SUSPEND, 1);
+
+	mdelay(10);
+
+	gpio_set_value(TOSA_GPIO_TC6393XB_REST_IN, 1);
+	gpio_set_value(TOSA_GPIO_TC6393XB_L3V_ON, 1);
+
+	return 0;
+err_dir_pclr:
+err_dir_suspend:
+err_dir_l3v:
+	gpio_free(TOSA_GPIO_TC6393XB_L3V_ON);
+err_req_l3v:
+	gpio_free(TOSA_GPIO_TC6393XB_SUSPEND);
+err_req_suspend:
+	gpio_free(TOSA_GPIO_TC6393XB_REST_IN);
+err_req_pclr:
+	return rc;
+}
+
+static int tosa_tc6393xb_disable(struct platform_device *dev)
+{
+	gpio_free(TOSA_GPIO_TC6393XB_L3V_ON);
+	gpio_free(TOSA_GPIO_TC6393XB_SUSPEND);
+	gpio_free(TOSA_GPIO_TC6393XB_REST_IN);
+
+	return 0;
+}
+
+static int tosa_tc6393xb_resume(struct platform_device *dev)
+{
+	gpio_set_value(TOSA_GPIO_TC6393XB_SUSPEND, 1);
+	mdelay(10);
+	gpio_set_value(TOSA_GPIO_TC6393XB_L3V_ON, 1);
+	mdelay(10);
+
+	return 0;
+}
+
+static int tosa_tc6393xb_suspend(struct platform_device *dev)
+{
+	gpio_set_value(TOSA_GPIO_TC6393XB_L3V_ON, 0);
+	gpio_set_value(TOSA_GPIO_TC6393XB_SUSPEND, 0);
+	return 0;
+}
+
+static struct mtd_partition tosa_nand_partition[] = {
+	{
+		.name	= "smf",
+		.offset	= 0,
+		.size	= 7 * 1024 * 1024,
+	},
+	{
+		.name	= "root",
+		.offset	= MTDPART_OFS_APPEND,
+		.size	= 28 * 1024 * 1024,
+	},
+	{
+		.name	= "home",
+		.offset	= MTDPART_OFS_APPEND,
+		.size	= MTDPART_SIZ_FULL,
+	},
+};
+
+static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
+
+static struct nand_bbt_descr tosa_tc6393xb_nand_bbt = {
+	.options	= 0,
+	.offs		= 4,
+	.len		= 2,
+	.pattern	= scan_ff_pattern
+};
+
+static struct tmio_nand_data tosa_tc6393xb_nand_config = {
+	.num_partitions	= ARRAY_SIZE(tosa_nand_partition),
+	.partition	= tosa_nand_partition,
+	.badblock_pattern = &tosa_tc6393xb_nand_bbt,
+};
+
+static struct tc6393xb_platform_data tosa_tc6393xb_setup = {
+	.scr_pll2cr	= 0x0cc1,
+	.scr_gper	= 0x3300,
+	.scr_gpo_dsr	=
+		TOSA_TC6393XB_GPIO_BIT(TOSA_GPIO_CARD_VCC_ON),
+	.scr_gpo_doecr	=
+		TOSA_TC6393XB_GPIO_BIT(TOSA_GPIO_CARD_VCC_ON),
+
+	.irq_base	= IRQ_BOARD_START,
+	.gpio_base	= TOSA_TC6393XB_GPIO_BASE,
+
+	.enable		= tosa_tc6393xb_enable,
+	.disable	= tosa_tc6393xb_disable,
+	.suspend	= tosa_tc6393xb_suspend,
+	.resume		= tosa_tc6393xb_resume,
+
+	.nand_data	= &tosa_tc6393xb_nand_config,
+};
+
+
+static struct platform_device tc6393xb_device = {
+	.name	= "tc6393xb",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &tosa_tc6393xb_setup,
+	},
+	.num_resources	= ARRAY_SIZE(tc6393xb_resources),
+	.resource	= tc6393xb_resources,
+};
+
+static struct tosa_bt_data tosa_bt_data = {
+	.gpio_pwr	= TOSA_GPIO_BT_PWR_EN,
+	.gpio_reset	= TOSA_GPIO_BT_RESET,
+};
+
+static struct platform_device tosa_bt_device = {
+	.name	= "tosa-bt",
+	.id	= -1,
+	.dev.platform_data = &tosa_bt_data,
+};
+
+
 static struct platform_device *devices[] __initdata = {
 	&tosascoop_device,
 	&tosascoop_jc_device,
+	&tc6393xb_device,
+	&tosa_power_device,
 	&tosakbd_device,
 	&tosa_gpio_keys_device,
 	&tosaled_device,
+	&tosa_bt_device,
 };
 
 static void tosa_poweroff(void)
 {
-	gpio_direction_output(TOSA_GPIO_ON_RESET, 0);
-	gpio_set_value(TOSA_GPIO_ON_RESET, 1);
-
-	mdelay(1000);
-	arm_machine_restart('h');
+	arm_machine_restart('g');
 }
 
 static void tosa_restart(char mode)
@@ -485,10 +772,15 @@
 
 static void __init tosa_init(void)
 {
+	int dummy;
+
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_config));
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_irda_off));
 	gpio_set_wake(MFP_PIN_GPIO1, 1);
 	/* We can't pass to gpio-keys since it will drop the Reset altfunc */
 
+	init_gpio_reset(TOSA_GPIO_ON_RESET);
+
 	pm_power_off = tosa_poweroff;
 	arm_pm_restart = tosa_restart;
 
@@ -497,6 +789,10 @@
 	/* enable batt_fault */
 	PMCR = 0x01;
 
+	dummy = gpiochip_reserve(TOSA_SCOOP_GPIO_BASE, 12);
+	dummy = gpiochip_reserve(TOSA_SCOOP_JC_GPIO_BASE, 12);
+	dummy = gpiochip_reserve(TOSA_TC6393XB_GPIO_BASE, 16);
+
 	pxa_set_mci_info(&tosa_mci_platform_data);
 	pxa_set_udc_info(&udc_info);
 	pxa_set_ficp_info(&tosa_ficp_platform_data);