[ARM] 2897/2: PXA2xx IRDA support

Patch from Nicolas Pitre

This is the PXA2xx common IRDA driver, plus platform support
for Lubbock and Mainstone.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Acked-by: Jean Tourrilhes <jt@hpl.hp.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 218eb96..3248bc9 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -34,6 +34,7 @@
 #include <asm/arch/udc.h>
 #include <asm/arch/pxafb.h>
 #include <asm/arch/mmc.h>
+#include <asm/arch/irda.h>
 #include <asm/arch/i2c.h>
 
 #include "generic.h"
@@ -301,6 +302,22 @@
 	.num_resources	= ARRAY_SIZE(i2s_resources),
 };
 
+static u64 pxaficp_dmamask = ~(u32)0;
+
+static struct platform_device pxaficp_device = {
+	.name		= "pxa2xx-ir",
+	.id		= -1,
+	.dev		= {
+		.dma_mask = &pxaficp_dmamask,
+		.coherent_dma_mask = 0xffffffff,
+	},
+};
+
+void __init pxa_set_ficp_info(struct pxaficp_platform_data *info)
+{
+	pxaficp_device.dev.platform_data = info;
+}
+
 static struct platform_device *devices[] __initdata = {
 	&pxamci_device,
 	&udc_device,
@@ -308,6 +325,7 @@
 	&ffuart_device,
 	&btuart_device,
 	&stuart_device,
+	&pxaficp_device,
 	&i2c_device,
 	&i2s_device,
 };
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 69abc7f..beccf45 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -35,6 +35,7 @@
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/lubbock.h>
 #include <asm/arch/udc.h>
+#include <asm/arch/irda.h>
 #include <asm/arch/pxafb.h>
 #include <asm/arch/mmc.h>
 
@@ -237,11 +238,30 @@
 	.init 		= lubbock_mci_init,
 };
 
+static void lubbock_irda_transceiver_mode(struct device *dev, int mode)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	if (mode & IR_SIRMODE) {
+		LUB_MISC_WR &= ~(1 << 4);
+	} else if (mode & IR_FIRMODE) {
+		LUB_MISC_WR |= 1 << 4;
+	}
+	local_irq_restore(flags);
+}
+
+static struct pxaficp_platform_data lubbock_ficp_platform_data = {
+	.transceiver_cap  = IR_SIRMODE | IR_FIRMODE,
+	.transceiver_mode = lubbock_irda_transceiver_mode,
+};
+
 static void __init lubbock_init(void)
 {
 	pxa_set_udc_info(&udc_info);
 	set_pxa_fb_info(&sharp_lm8v31);
 	pxa_set_mci_info(&lubbock_mci_platform_data);
+	pxa_set_ficp_info(&lubbock_ficp_platform_data);
 	(void) platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 8b4a216..a48c640 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -37,6 +37,7 @@
 #include <asm/arch/audio.h>
 #include <asm/arch/pxafb.h>
 #include <asm/arch/mmc.h>
+#include <asm/arch/irda.h>
 
 #include "generic.h"
 
@@ -294,6 +295,29 @@
 	.exit		= mainstone_mci_exit,
 };
 
+static void mainstone_irda_transceiver_mode(struct device *dev, int mode)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	if (mode & IR_SIRMODE) {
+		MST_MSCWR1 &= ~MST_MSCWR1_IRDA_FIR;
+	} else if (mode & IR_FIRMODE) {
+		MST_MSCWR1 |= MST_MSCWR1_IRDA_FIR;
+	}
+	if (mode & IR_OFF) {
+		MST_MSCWR1 = (MST_MSCWR1 & ~MST_MSCWR1_IRDA_MASK) | MST_MSCWR1_IRDA_OFF;
+	} else {
+		MST_MSCWR1 = (MST_MSCWR1 & ~MST_MSCWR1_IRDA_MASK) | MST_MSCWR1_IRDA_FULL;
+	}
+	local_irq_restore(flags);
+}
+
+static struct pxaficp_platform_data mainstone_ficp_platform_data = {
+	.transceiver_cap  = IR_SIRMODE | IR_FIRMODE | IR_OFF,
+	.transceiver_mode = mainstone_irda_transceiver_mode,
+};
+
 static void __init mainstone_init(void)
 {
 	/*
@@ -313,6 +337,7 @@
 		set_pxa_fb_info(&toshiba_ltm035a776c);
 
 	pxa_set_mci_info(&mainstone_mci_platform_data);
+	pxa_set_ficp_info(&mainstone_ficp_platform_data);
 }