diff -urN -X /home/arm/dontdiff_tml_arm /home/download/kernels/linux-2.4.19-rmk2-vanilla/drivers/ssi/ps5mx_ssi.c linux-2.4.19-rmk2/drivers/ssi/ps5mx_ssi.c
diff -urN -X /home/arm/dontdiff_tml_arm /home/download/kernels/linux-2.4.19-rmk2-vanilla/drivers/ssi/ps5mx_ssi.c linux-2.4.19-rmk2/drivers/ssi/ps5mx_ssi.c
--- /home/download/kernels/linux-2.4.19-rmk2-vanilla/drivers/ssi/ps5mx_ssi.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.19-rmk2/drivers/ssi/ps5mx_ssi.c	2002-10-02 22:07:30.000000000 -0700
@@ -0,0 +1,213 @@
+/*
+ *  linux/drivers/ssi/ps5mx_ssi.c
+ *
+ * SSI bus driver for the Psion 5MX SSI bus.
+ * 
+ * Copyright (c) 2001 Shane R. Nay (shane@minirl.com)
+ * Based on the clps driver.  Opted to
+ * do interupt based writers/readers.
+ *
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+
+#include <asm/mach-types.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/hardware/psionw.h>
+
+#include "ssi_bus.h"
+#include "ssi_dev.h"
+
+#define TX_QUEUE_SIZE 16 /* Must be some 2^n */
+
+struct ssi5mx_txdat {
+	u_int head;
+	u_int tail;
+	u_int buf[TX_QUEUE_SIZE];
+};
+
+static struct ssi5mx_txdat* queue;
+
+static void add_txqueue(u_int dat) {
+	unsigned long flags;
+	int head=queue->head;
+	save_flags(flags);  /* No save_and_cli..?, what gives linux-arm? */
+	cli();
+	queue->buf[head]=dat;
+	if(head != (queue->tail-1)&(TX_QUEUE_SIZE-1)) {
+		head++;
+		head &= (TX_QUEUE_SIZE-1);
+	}
+	queue->head=head;
+	restore_flags(flags);
+}
+
+/* Always happens in ISR, no need to deal with concurrency */
+static u_int pop_txqueue(void) {
+	u_int ret;
+	ret=queue->buf[queue->tail];
+	queue->tail=(queue->tail+1) & (TX_QUEUE_SIZE-1);
+	return ret;
+}
+
+#define IS_EMPTY(queue) queue->head==queue->tail
+
+
+/*
+ * NE on PS5mx.
+ */
+static void ssi5mx_select_id(int id)
+{
+
+}
+
+/*
+ * Select the specified device.
+ * NE on 5mx yet. SRN
+ *
+ * App notes when done:
+ * Need to implement switch for SPI proto type, and do a switch()
+ * based on that to write different things to the SSCR0 control
+ * register.  Right now, only thing on is the National Microwire
+ * ADC, so it is initialized accordingly.
+ */
+static int ssi5mx_select(struct ssi_bus *bus, struct ssi_dev *dev)
+{
+	return 0;
+
+}
+
+static void ssi5mx_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct ssi_bus *bus = (struct ssi_bus *)dev_id;
+	u_int sssr;
+	sssr=psionw_readl(SSSR);
+	/* Do recieve first */
+	while(sssr & 1<<2) {
+		ssi_core_rcv(bus, psionw_readl(SSDR));
+		sssr=psionw_readl(SSSR);
+	}
+	/* Do transmit of queued data */
+	while((!(IS_EMPTY(queue))) && (sssr & 1<<1)) {
+		psionw_writel(pop_txqueue(),SSDR);
+		sssr=psionw_readl(SSSR);
+	}
+	/* Finally, yank tx empty interrupt if our TX queue is empty */
+	if(IS_EMPTY(queue)) {
+		sssr=psionw_readl(SSCR1);
+		sssr &= ~(0x2); /* Remove fifo'ing, and Transmit queue empty */
+		psionw_writel(sssr,SSCR1);
+	}
+}
+
+/*
+ * Every transmission follows with a reciept.  So we
+ * have to enable the bus interrupt for transmission if
+ * necessary, and queue up the bottom half transmissions
+ * and the later bottom have reciepts.
+ */
+static int ssi5mx_trans(struct ssi_bus *bus, u_int data)
+{
+	if(IS_EMPTY(queue)) {
+		/* Startup transmit irq after adding to queue */
+		u_int sssr;
+		add_txqueue(data);
+		sssr=psionw_readl(SSCR1);
+		sssr |= 0x2;
+		psionw_writel(sssr,SSCR1);
+		return 0;
+	}
+	add_txqueue(data);
+
+	return 0;
+}
+
+#ifdef CONFIG_SSI_ADC7843
+void init_adc7843(struct ssi_bus*);
+#endif
+
+/*
+ * Initialise the SSI bus.
+ */
+static int ssi5mx_bus_init(struct ssi_bus *bus)
+{
+	int retval;
+	u_int sssr;
+
+	retval = request_irq(IRQ_SSEOTI, ssi5mx_int, 0, "ssi5mx", bus);
+	if (retval)
+		return retval;
+	if((queue = kmalloc(sizeof(*queue), GFP_KERNEL))==NULL)
+	{
+		printk(KERN_ERR "ssi5mx: no queue memory.\n");
+		return -ENOMEM;
+	}
+	memset(queue,0,sizeof(*queue));
+	printk("5mx SSI bus initialized\n");
+	ssi5mx_select(bus, NULL);
+	psionw_writel(0x0,SSSR);
+	psionw_writel(0xff2b,SSCR0);
+	psionw_writel(0x1,SSCR1);
+	sssr=psionw_readl(SSCR0);
+	sssr|=1<<7;
+	psionw_writel(sssr,SSCR0);
+	/* Welcome to the old days of module/filesystem
+	   intialization.  Okay, I don't see a better
+	   way to do this at this exact juncture,
+	   and I really want to write a driver not a
+	   bus..., so... SRN
+	*/
+#ifdef CONFIG_SSI_ADC7843
+	init_adc7843(bus);
+#endif
+	return 0;
+}
+
+static void ssi5mx_bus_exit(struct ssi_bus *bus)
+{
+	u_int sssr;
+	ssi5mx_select(bus, NULL);
+	sssr=psionw_readl(SSCR0);
+	sssr &= ~(1<<7);
+	psionw_writel(sssr,SSCR0);
+
+	free_irq(IRQ_SSEOTI, bus);
+}
+
+void ssi5mx_powerdown(int lock)
+{
+	psionw_writel(psionw_readl(SSCR0) & ~(1<<7), SSCR0);
+}
+
+void ssi5mx_powerup(int lock)
+{
+	psionw_writel(psionw_readl(SSCR0) | (1<<7), SSCR0);
+}
+
+static struct ssi_bus psionw_ssi5mx_bus = {
+        name:	"psionw_ssi5mx",
+        init:	ssi5mx_bus_init,
+        exit:	ssi5mx_bus_exit,
+        select:	ssi5mx_select,
+        trans:	ssi5mx_trans,
+        };
+
+static int __init psionw_ssi5mx_init(void)
+{
+	return ssi_register_bus(&psionw_ssi5mx_bus);
+}
+
+static void __exit psionw_ssi5mx_exit(void)
+{
+	ssi_unregister_bus(&psionw_ssi5mx_bus);
+}
+
+module_init(psionw_ssi5mx_init);
+module_exit(psionw_ssi5mx_exit);
