Index: linux/drivers/pcmcia/sa1100_collie.c
===================================================================
--- /dev/null
+++ linux/drivers/pcmcia/sa1100_collie.c
@@ -0,0 +1,215 @@
+/*
+ * drivers/pcmcia/sa1100_collie.c
+ *
+ * PCMCIA implementation routines for Collie
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+#include <asm/delay.h>
+#include <asm/arch/collie.h>
+#include <asm/hardware/scoop.h>
+
+#include "sa1100_generic.h"
+
+static unsigned short keep_vs[2];
+#define	NO_KEEP_VS 0x0001
+
+static struct pcmcia_irqs irqs[] = {
+	{ 1, COLLIE_IRQ_GPIO_CF_CD, "CF_CD"},
+};
+
+static void collie_pcmcia_init_reset(void)
+{
+	reset_scoop();
+	keep_vs[0] = NO_KEEP_VS;
+}
+
+static int collie_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+	int ret;
+	
+	/* set COLLIE_GPIO_CF_CD & COLLIE_GPIO_CF_IRQ as inputs */
+	GPDR &= ~(COLLIE_GPIO_CF_CD|COLLIE_GPIO_CF_IRQ);
+
+	/* Set transition detect */
+	set_irq_type(COLLIE_IRQ_GPIO_CF_IRQ, IRQT_FALLING);
+
+	ret = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	
+	if (ret)
+		return ret;
+	
+	/* enable interrupt */
+	write_scoop_reg(SCOOP_IMR, 0x00C0);
+	write_scoop_reg(SCOOP_MCR, 0x0101);
+	keep_vs[0] = keep_vs[1] = NO_KEEP_VS;
+
+	return 0;
+}
+
+static void collie_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+
+	/* CF_BUS_OFF */
+	collie_pcmcia_init_reset();
+}
+
+static void
+collie_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
+{
+	unsigned short cpr, csr;
+
+	cpr = read_scoop_reg(SCOOP_CPR);
+	//COLLIE_SCP_REG_CDR = 0x0002;
+	write_scoop_reg(SCOOP_IRM, 0x00FF);
+	write_scoop_reg(SCOOP_ISR, 0x0000);
+	write_scoop_reg(SCOOP_IRM, 0x0000);
+	csr = read_scoop_reg(SCOOP_CSR);
+	if( csr & 0x0004 ){
+		/* card eject */
+		write_scoop_reg(SCOOP_CDR, 0x0000);
+		keep_vs[0] = NO_KEEP_VS;
+	}
+	else if( !(keep_vs[0] & NO_KEEP_VS) ){
+		/* keep vs1,vs2 */
+		write_scoop_reg(SCOOP_CDR, 0x0000);
+		csr |= keep_vs[0];
+	}
+	else if( cpr & 0x0003 ){
+		/* power on */
+		write_scoop_reg(SCOOP_CDR, 0x0000);
+		keep_vs[0] = (csr & 0x00C0);
+	}
+	else{	/* card detect */
+		write_scoop_reg(SCOOP_CDR, 0x0002);
+	}
+
+	state->detect = (csr & 0x0004)? 0:1;
+	state->ready  = (csr & 0x0002)? 1:0;
+	state->bvd1   = (csr & 0x0010)? 1:0;
+	state->bvd2   = (csr & 0x0020)? 1:0;
+	state->wrprot = (csr & 0x0008)? 1:0;
+	state->vs_3v  = (csr & 0x0040)? 0:1;
+	state->vs_Xv  = (csr & 0x0080)? 0:1;
+
+	if( (cpr & 0x0080) && ((cpr & 0x8040) != 0x8040) ){
+		printk(KERN_ERR "%s(): CPR=%04X, Low voltage!\n",
+			__FUNCTION__, cpr);
+	}
+
+}
+
+static int 
+collie_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) 
+{
+	unsigned long flags;
+	unsigned short cpr, ncpr, ccr, nccr, mcr, nmcr, imr, nimr;
+
+	switch( state->Vcc ){
+	case	0:	break;
+	case 	33:	break;
+	case	50:	break;
+	default:
+		printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
+			__FUNCTION__, state->Vcc);
+		return -1;
+	}
+	if( (state->Vpp!=state->Vcc) && (state->Vpp!=0) ){
+		printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n",
+			__FUNCTION__, state->Vpp);
+		return -1;
+	}
+
+	local_irq_save(flags);
+
+	nmcr = (mcr = read_scoop_reg(SCOOP_MCR)) & ~0x0010;
+	ncpr = (cpr = read_scoop_reg(SCOOP_CPR)) & ~0x0083;
+	nccr = (ccr = read_scoop_reg(SCOOP_CCR)) & ~0x0080;
+	nimr = (imr = read_scoop_reg(SCOOP_IMR)) & ~0x003E;
+
+	ncpr |= (state->Vcc == 33) ? 0x0001: 
+		(state->Vcc == 50) ? 0x0002:
+		0;
+	/* the 2.5 tree on linux-cl.bkbits.net had this code
+	nccr = ((state->flags & SS_RESET) ? (nccr | 0x0080) : (nccr &= ~0x0080));
+	ncpr = ((state->flags & SS_OUTPUT_ENA) ? (ncpr | 0x0080) : (ncpr &= ~0x0080)); */
+
+	nmcr |= (state->flags&SS_IOCARD)? 0x0010: 0;
+	ncpr |= (state->flags&SS_OUTPUT_ENA)? 0x0080: 0;
+	nccr |= (state->flags&SS_RESET)? 0x0080: 0;
+	nimr |=	((skt->status&SS_DETECT) ? 0x0004: 0)|
+		((skt->status&SS_READY)  ? 0x0002: 0)|
+		((skt->status&SS_BATDEAD)? 0x0010: 0)|
+		((skt->status&SS_BATWARN)? 0x0020: 0)|
+		((skt->status&SS_STSCHG) ? 0x0010: 0)|
+		((skt->status&SS_WRPROT) ? 0x0008: 0);
+
+	if (mcr != nmcr) write_scoop_reg(SCOOP_MCR, nmcr);
+	if (cpr != ncpr) write_scoop_reg(SCOOP_CPR, ncpr);
+	if (ccr != nccr) write_scoop_reg(SCOOP_CCR, nccr);
+	if (imr != nimr) write_scoop_reg(SCOOP_IMR, nimr);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+/*
+ * Enable card status IRQs on (re-)initialisation.  This can
+ * be called at initialisation, power management event, or
+ * pcmcia event.
+ */
+static void collie_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+{
+	soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+
+	 /* We need to disable SS_OUTPUT_ENA here. */
+	write_scoop_reg(SCOOP_CPR, read_scoop_reg(SCOOP_CPR) & ~0x0080)
+}
+
+static void collie_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
+{
+	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+
+	 /* We need to disable SS_OUTPUT_ENA here. */
+	write_scoop_reg(SCOOP_CPR, read_scoop_reg(SCOOP_CPR) & ~0x0080)
+}
+
+struct pcmcia_low_level collie_pcmcia_ops = { 
+	.owner			= THIS_MODULE,
+
+	.hw_init		= collie_pcmcia_hw_init,
+	.hw_shutdown		= collie_pcmcia_hw_shutdown,
+
+	.socket_state		= collie_pcmcia_socket_state,
+	.configure_socket	= collie_pcmcia_configure_socket,
+
+	.socket_init		= collie_pcmcia_socket_init,
+	.socket_suspend		= collie_pcmcia_socket_suspend,
+};
+
+
+int __init pcmcia_collie_init(struct device *dev)
+{
+	int ret = -ENODEV;
+
+	if (machine_is_collie())
+		ret = sa11xx_drv_pcmcia_probe(dev, &collie_pcmcia_ops, 1, 1);
+
+	return ret;
+}
Index: linux/drivers/pcmcia/Makefile
===================================================================
--- linux.orig/drivers/pcmcia/Makefile
+++ linux/drivers/pcmcia/Makefile
@@ -58,6 +58,7 @@
 sa1100_cs-$(CONFIG_SA1100_H3600)		+= sa1100_h3600.o
 sa1100_cs-$(CONFIG_SA1100_SHANNON)		+= sa1100_shannon.o
 sa1100_cs-$(CONFIG_SA1100_SIMPAD)		+= sa1100_simpad.o
+sa1100_cs-$(CONFIG_SA1100_COLLIE)		+= sa1100_collie.o
 
 pxa2xx_cs-$(CONFIG_ARCH_LUBBOCK)		+= pxa2xx_lubbock.o sa1111_generic.o
 pxa2xx_cs-$(CONFIG_MACH_MAINSTONE)		+= pxa2xx_mainstone.o
Index: linux/drivers/pcmcia/sa1100_generic.c
===================================================================
--- linux.orig/drivers/pcmcia/sa1100_generic.c
+++ linux/drivers/pcmcia/sa1100_generic.c
@@ -48,6 +48,9 @@
 #ifdef CONFIG_SA1100_CERF
 	pcmcia_cerf_init,
 #endif
+#ifdef CONFIG_SA1100_COLLIE
+	pcmcia_collie_init,
+#endif
 #ifdef CONFIG_SA1100_H3600
 	pcmcia_h3600_init,
 #endif
Index: linux/drivers/pcmcia/sa1100_generic.h
===================================================================
--- linux.orig/drivers/pcmcia/sa1100_generic.h
+++ linux/drivers/pcmcia/sa1100_generic.h
@@ -8,6 +8,7 @@
 extern int pcmcia_assabet_init(struct device *);
 extern int pcmcia_badge4_init(struct device *);
 extern int pcmcia_cerf_init(struct device *);
+extern int pcmcia_collie_init(struct device *);
 extern int pcmcia_flexanet_init(struct device *);
 extern int pcmcia_freebird_init(struct device *);
 extern int pcmcia_gcplus_init(struct device *);
