diff -Naur linux-2.6.25.maxim/drivers/misc/classes/char/gpio_char.c linux-2.6.25.at91-20080908/drivers/misc/classes/char/gpio_char.c
--- linux-2.6.25.maxim/drivers/misc/classes/char/gpio_char.c	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/drivers/misc/classes/char/gpio_char.c	2008-09-05 18:10:37.000000000 -0500
@@ -0,0 +1,207 @@
+/**
+ * A character device interface to gpio devices. Part of the GPIO class.
+ * 
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/cdev.h>
+#include <linux/class/gpio.h>
+#include <linux/class/char/gpio_char.h>
+#include <asm/uaccess.h>
+
+static int gpio_major =    GPIO_MAJOR;
+static int gpio_minor =    0;
+static int gpio_num_devs = GPIO_MAX_DEVS;
+
+struct gpio_char_dev {
+    gpio_t *gpio;
+    struct cdev cdev;
+};
+
+//#define DEBUG_GC
+
+#ifdef DEBUG_GC
+#define DPRINTK(string, args...) printk("gpio_char: " string, ##args)
+#else
+#define DPRINTK(string, args...)
+#endif
+
+/* function prototypes */
+static int gpio_char_ioctl(struct inode *inode, struct file *file,
+		unsigned int cmd, unsigned long arg);
+static int gpio_char_open(struct inode *inode, struct file *file);
+static int gpio_char_release(struct inode *inode, struct file *file);
+static int gpio_char_setup_cdev(struct gpio_char_dev *dev);
+
+/* struct for fops declarations */
+static const struct file_operations gpio_char_fops =
+{ 
+    .ioctl   = gpio_char_ioctl, 
+    .open    = gpio_char_open,
+    .release = gpio_char_release,
+};
+
+static int gpio_char_open(struct inode *inode, struct file *file)
+{
+    struct gpio_char_dev *dev; /* device information */
+    DPRINTK("gpio_char_open\n");
+    dev = container_of(inode->i_cdev, struct gpio_char_dev, cdev);
+    file->private_data = dev;
+    return 0;
+}
+
+static int gpio_char_release(struct inode *inode, struct file *file)
+{
+    DPRINTK("gpio_char_release\n");
+    /* nothing to do here */
+    return 0;
+}
+
+static int gpio_char_ioctl(struct inode *inode, struct file *file,
+        unsigned int cmd, unsigned long arg)
+{
+    struct gpio_char_dev *dev = container_of(inode->i_cdev, struct gpio_char_dev, cdev);
+    gpio_t *gpio = dev->gpio;
+    gpio_data kmem[1];
+    int ret;
+    
+    /* make sure that this command is indeed one of gpio_char's */
+    if (_IOC_TYPE(cmd) != CHAR_CLASS_GPIO)
+        return -ENOTTY;
+    
+    switch(cmd)
+    {
+    case DDRREAD:
+        DPRINTK("DDRREAD ioctl\n");
+        if (gpio->ddr_read)
+            kmem[0] = atomic_gpio_ddr_read(gpio);
+        else
+            return -EFAULT;
+        return (copy_to_user((void *)arg, kmem, sizeof(gpio_data)) == 0 ) ? 0 : -EFAULT;
+        break;
+    case DDRWRITE:
+        DPRINTK("DDRWRITE ioctl\n");
+        if (copy_from_user(kmem, (void *)arg, sizeof(gpio_data)) != 0)
+            return -EFAULT;
+        if (gpio->ddr_write)
+            atomic_gpio_ddr_write(gpio, kmem[0]);
+        else 
+            return -EFAULT;
+        return 0;
+        break;
+    case DATAREAD:
+        DPRINTK("DATAREAD ioctl\n");
+        if (gpio->data_read)
+            kmem[0] = atomic_gpio_data_read(gpio);
+        else
+            return -EFAULT;
+        return (copy_to_user((void *)arg, kmem, sizeof(gpio_data)) == 0 ) ? 0 : -EFAULT;
+        break;
+    case DATAWRITE:
+        DPRINTK("DATAWRITE ioctl\n");
+        if (copy_from_user(kmem, (void *)arg, sizeof(gpio_data)) != 0)
+            return -EFAULT;
+        if (gpio->data_write)
+            atomic_gpio_data_write(gpio, kmem[0]);
+        else {
+            DPRINTK("error: invalid data_write\n");
+            return -EFAULT;
+        }
+        return 0;
+        break;
+    case INDEXREAD:
+        DPRINTK("INDEXREAD ioctl\n");
+        if (gpio->index_read)
+            kmem[0] = atomic_gpio_index_read(gpio);
+        else
+            return -EFAULT;
+        return (copy_to_user((void *)arg, kmem, sizeof(gpio_data)) == 0 ) ? 0 : -EFAULT;
+        break;
+    case INDEXWRITE:
+        DPRINTK("INDEXWRITE ioctl\n");
+        if ((ret = copy_from_user(kmem, (void __user *)arg, sizeof(gpio_data))) != 0) {
+            DPRINTK("copy_from_user returned error: %d bytes not copied\n", ret);
+            return -EFAULT;
+        }
+        if (gpio->index_write)
+            atomic_gpio_index_write(gpio, kmem[0]);
+        else {
+            DPRINTK("invalid index_write command\n");
+            return -EFAULT;
+        }
+        return 0;
+        break;
+    default :
+        DPRINTK("ioctl: no such command\n");
+        return -ENOTTY;
+    } /* END switch(cmd) */
+    DPRINTK("Invalid state, broke out of switch\n");
+    return -EFAULT; /* Error, we should never reach here */    
+}
+
+/* initialize the character interface -- called by gpio class on init */
+
+int gpio_char_init(void)
+{
+    int result;
+    dev_t dev = 0;
+    DPRINTK("gpio_char_init\n");
+    /* dynamic and static character device allocation */
+    if (gpio_major) {
+        dev = MKDEV(gpio_major, gpio_minor);
+        result = register_chrdev_region(dev, gpio_num_devs, "gpio_char");
+    }
+    else {
+        result = alloc_chrdev_region(&dev, gpio_minor, 
+                gpio_num_devs, "gpio_char");
+        gpio_major = MAJOR(dev);
+    }
+    if (result < 0)
+        printk(KERN_WARNING "gpio_char: can't get major %d, err %d\n", gpio_major,result);
+    
+    return result;
+}
+
+/* registers the actual char device, called by create when invoked by gpio class */
+
+static int gpio_char_setup_cdev(struct gpio_char_dev *dev)
+{
+    static int index = 0;
+    int err, devno = MKDEV(gpio_major, gpio_minor + index);
+    
+    DPRINTK("gpio_char_setup_cdev\n");
+    
+    cdev_init(&dev->cdev, &gpio_char_fops);
+    dev->cdev.owner = THIS_MODULE; /* not sure if this is still valid */
+    dev->cdev.ops = &gpio_char_fops;
+    err = cdev_add(&dev->cdev, devno, 1);
+    if (err)
+        printk(KERN_NOTICE "gpio_char: Error %d adding gpio_char%d\n", err, index);
+    
+    index++;
+    return devno;
+}
+
+/* create and register a new char device */
+
+int gpio_char_create(struct gpio_s *gpio)
+{
+    struct gpio_char_dev *chardev = kmalloc(sizeof(struct gpio_char_dev),GFP_KERNEL);
+    DPRINTK("gpio_char_create\n");
+    if (!chardev) {
+        printk(KERN_NOTICE "Error allocating memory\n");
+        return -ENOMEM;
+    }
+    chardev->gpio = gpio;
+    
+    return gpio_char_setup_cdev(chardev);
+}
diff -Naur linux-2.6.25.maxim/drivers/misc/classes/char/Makefile linux-2.6.25.at91-20080908/drivers/misc/classes/char/Makefile
--- linux-2.6.25.maxim/drivers/misc/classes/char/Makefile	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/drivers/misc/classes/char/Makefile	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,6 @@
+#
+# Makefile for the misc char classes
+#
+
+obj-$(CONFIG_GPIOCLASS_CHAR)	+= gpio_char.o
+obj-$(CONFIG_SPICLASS_CHAR)		+= spi_char.o
\ No newline at end of file
diff -Naur linux-2.6.25.maxim/drivers/misc/classes/char/spi_char.c linux-2.6.25.at91-20080908/drivers/misc/classes/char/spi_char.c
--- linux-2.6.25.maxim/drivers/misc/classes/char/spi_char.c	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/drivers/misc/classes/char/spi_char.c	2008-09-05 18:10:37.000000000 -0500
@@ -0,0 +1,224 @@
+/**
+ * A character device interface to spi devices. Part of the SPI class.
+ * 
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/cdev.h>
+#include <linux/class/spi.h>
+#include <linux/class/char/spi_char.h>
+#include <asm/uaccess.h>
+
+static int spi_major =    SPI_MAJOR;
+static int spi_minor =    0;
+static int spi_num_devs = SPI_MAX_DEVS;
+
+struct spi_char_dev {
+    spi_t *spi;
+    struct cdev cdev;
+};
+
+//#define DEBUG_SC
+
+#ifdef DEBUG_SC
+#define DPRINTK(string, args...) printk("spi_char: " string, ##args)
+#else
+#define DPRINTK(string, args...)
+#endif
+
+/* function prototypes */
+static int spi_char_ioctl(struct inode *inode, struct file *file,
+		unsigned int cmd, unsigned long arg);
+static int spi_char_open(struct inode *inode, struct file *file);
+static int spi_char_release(struct inode *inode, struct file *file);
+static int spi_char_setup_cdev(struct spi_char_dev *dev);
+
+/* struct for fops declarations */
+static const struct file_operations spi_char_fops =
+{ 
+    .ioctl   = spi_char_ioctl, 
+    .open    = spi_char_open,
+    .release = spi_char_release,
+};
+
+static int spi_char_open(struct inode *inode, struct file *file)
+{
+    struct spi_char_dev *dev; /* device information */
+    DPRINTK("spi_char_open\n");
+    /* TODO: This may or may not be necessary */
+    dev = container_of(inode->i_cdev, struct spi_char_dev, cdev);
+    file->private_data = dev;
+    return 0;
+}
+
+static int spi_char_release(struct inode *inode, struct file *file)
+{
+    DPRINTK("spi_char_release\n");
+    /* nothing to do here */
+    return 0;
+}
+
+static int spi_char_ioctl(struct inode *inode, struct file *file,
+        unsigned int cmd, unsigned long arg)
+{
+    struct spi_char_dev *dev = container_of(inode->i_cdev, struct spi_char_dev, cdev);
+    spi_t *spi = dev->spi;
+    spi_control kmem[1];
+    
+    /* make sure that this command is indeed one of spi_char's */
+    if (_IOC_TYPE(cmd) != CHAR_CLASS_SPI)
+        return -ENOTTY;
+    
+    switch(cmd)
+    {
+    case XMIT:{
+    	spi_transfer_t *t=NULL;
+    	spi_data *buf=NULL;
+    	int errval=0;
+        DPRINTK("XMIT ioctl\n");
+        if (!spi->xmit)return -EFAULT;//method not available
+        t = kmalloc(sizeof(spi_transfer_t), GFP_KERNEL);
+        if (copy_from_user(t, (void *)arg, sizeof(spi_transfer_t)) != 0){errval=-EFAULT;goto cleanup;}
+        if(t->size==0)return 0;//not an error, but nothing to do
+        if((t->miso)||(t->mosi))buf = kmalloc(t->size,GFP_KERNEL);
+        if(t->mosi)if (copy_from_user(buf, t->mosi, t->size) != 0){errval=-EFAULT;goto cleanup;}
+        if(atomic_spi_xmit(spi,t->mosi?buf:NULL,t->miso?buf:NULL,t->size)!=0){errval=-EFAULT;goto cleanup;}
+        if(t->miso)if(copy_to_user(t->miso, buf, t->size)!= 0 ){errval=-EFAULT;goto cleanup;}
+cleanup:
+        if(buf)kfree(buf);
+        if(t)kfree(t);
+        return errval;
+        break;
+    }
+    case CONFREAD:
+        DPRINTK("CONFREAD ioctl\n");
+        if (spi->confread)
+            kmem[0] = atomic_spi_conf_read(spi);
+        else
+            return -EFAULT;
+        return (copy_to_user((void *)arg, kmem, sizeof(spi_control)) == 0 ) ? 0 : -EFAULT;
+        break;
+    case CONFWRITE:
+        DPRINTK("CONFWRITE ioctl\n");
+        if (copy_from_user(kmem, (void *)arg, sizeof(spi_control)) != 0)
+            return -EFAULT;
+        if (spi->confwrite)
+            atomic_spi_conf_write(spi, kmem[0]);
+        else 
+            return -EFAULT;
+        return 0;
+        break;
+    case SPEEDREAD:
+        DPRINTK("SPEEDREAD ioctl\n");
+        if (spi->speedread)
+            kmem[0] = atomic_spi_speed_read(spi);
+        else
+            return -EFAULT;
+        return (copy_to_user((void *)arg, kmem, sizeof(spi_control)) == 0 ) ? 0 : -EFAULT;
+        break;
+    case SPEEDWRITE:
+        DPRINTK("SPEEDWRITE ioctl\n");
+        if (copy_from_user(kmem, (void *)arg, sizeof(spi_control)) != 0)
+            return -EFAULT;
+        if (spi->speedwrite)
+            atomic_spi_speed_write(spi, kmem[0]);
+        else {
+            DPRINTK("error: invalid speed write\n");
+            return -EFAULT;
+        }
+        return 0;
+        break;
+    case TIPREAD:
+        DPRINTK("TIPREAD ioctl\n");
+        if (spi->tip)
+            kmem[0] = atomic_spi_tip_read(spi);
+        else
+            return -EFAULT;
+        return (copy_to_user((void *)arg, kmem, sizeof(spi_control)) == 0 ) ? 0 : -EFAULT;
+        break;
+    case TIPWRITE:
+        DPRINTK("TIPWRITE ioctl\n");
+        if (copy_from_user(kmem, (void *)arg, sizeof(spi_control)) != 0)
+            return -EFAULT;
+        if (spi->tip)
+            atomic_spi_tip_write(spi, kmem[0]);
+        else {
+            DPRINTK("error: invalid speed write\n");
+            return -EFAULT;
+        }
+        return 0;
+        break;
+    default :
+        DPRINTK("ioctl: no such command\n");
+        return -ENOTTY;
+    } /* END switch(cmd) */
+    DPRINTK("Invalid state, broke out of switch\n");
+    return -EFAULT; /* Error, we should never reach here */    
+}
+
+/* initialize the character interface -- called by spi class on init */
+
+int spi_char_init(void)
+{
+    int result;
+    dev_t dev = 0;
+    DPRINTK("spi_char_init\n");
+    /* dynamic and static character device allocation */
+    if (spi_major) {
+        dev = MKDEV(spi_major, spi_minor);
+        result = register_chrdev_region(dev, spi_num_devs, "spi_char");
+    }
+    else {
+        result = alloc_chrdev_region(&dev, spi_minor, 
+                spi_num_devs, "spi_char");
+        spi_major = MAJOR(dev);
+    }
+    if (result < 0)
+        printk(KERN_WARNING "spi_char: can't get major %d, err %d\n", spi_major,result);
+    
+    return result;
+}
+
+/* registers the actual char device, called by create when invoked by spi class */
+
+static int spi_char_setup_cdev(struct spi_char_dev *dev)
+{
+    static int index = 0;
+    int err, devno = MKDEV(spi_major, spi_minor + index);
+    
+    DPRINTK("spi_char_setup_cdev\n");
+    
+    cdev_init(&dev->cdev, &spi_char_fops);
+    dev->cdev.owner = THIS_MODULE;
+    dev->cdev.ops = &spi_char_fops;
+    err = cdev_add(&dev->cdev, devno, 1);
+    if (err)
+        printk(KERN_NOTICE "spi_char: Error %d adding spi_char%d\n", err, index);
+    
+    index++;
+    return devno;
+}
+
+/* create and register a new char device */
+
+int spi_char_create(struct spi_s *spi)
+{
+    struct spi_char_dev *chardev = kmalloc(sizeof(struct spi_char_dev),GFP_KERNEL);
+    DPRINTK("spi_char_create\n");
+    if (!chardev) {
+        printk(KERN_NOTICE "Error allocating memory\n");
+        return -ENOMEM;
+    }
+    chardev->spi = spi;
+    
+    return spi_char_setup_cdev(chardev);
+}
diff -Naur linux-2.6.25.maxim/drivers/misc/classes/gpio.c linux-2.6.25.at91-20080908/drivers/misc/classes/gpio.c
--- linux-2.6.25.maxim/drivers/misc/classes/gpio.c	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/drivers/misc/classes/gpio.c	2008-09-05 18:10:37.000000000 -0500
@@ -0,0 +1,180 @@
+/**
+ * A class for simple gpio ports
+ * Several types of general purpose devices are available 
+ * which all export the same basic functionity 
+ * through different underlying methods
+ * This class can also be used to export simple interfaces
+ * to an 8 bit port into user space
+ */
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/ctype.h>
+#include <linux/kdev_t.h>
+#include <linux/chelper.h>
+#include <linux/class/gpio.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_GPIOCLASS_RTDM
+#include <rtdm/rtdm_driver.h>
+#include <linux/class/rtdm/gpio_rtdm.h>
+#define ATOMIC(a) RTDM_EXECUTE_ATOMICALLY(a)
+#else
+#define ATOMIC(a) a
+#endif //CONFIG_GPIOCLASS_RTDM
+
+#ifdef CONFIG_GPIOCLASS_CHAR
+#include <linux/class/char/gpio_char.h>
+#endif
+
+/************************************************************
+ * the global device class
+ */
+static struct class *gpioclass = NULL;
+
+struct class *gpio_declare(void){
+	if(!gpioclass){
+		printk("registering GPIO class\n");
+		gpioclass=class_create(THIS_MODULE,"gpio");
+#ifdef CONFIG_GPIOCLASS_CHAR
+		gpio_char_init();
+#endif
+	}
+	return gpioclass;
+}
+
+/***************************************************************************
+ * typical low level methods for accessing 8 bit ports
+ */
+
+int  gpio_ddr_write8(gpio_t *gpio, gpio_data data){iowrite8(data,gpio->ddr+gpio->index);return 0;}
+
+int  gpio_data_write8(gpio_t *gpio, gpio_data data){iowrite8(data,gpio->data+gpio->index);gpio->shadow=data;return 0;}
+
+int  gpio_index_write(gpio_t *gpio, gpio_data data){data = (data>gpio->range)?gpio->range:data;gpio->index = data;return 0;}
+
+int  gpio_empty_write(gpio_t *gpio, gpio_data data){return 0;}
+
+gpio_data gpio_ddr_read8(gpio_t *gpio){return ioread8(gpio->ddr+gpio->index);}
+
+gpio_data gpio_data_read8(gpio_t *gpio){return ioread8(gpio->data+gpio->index);}
+
+gpio_data gpio_index_read(gpio_t *gpio){return gpio->index;}
+
+gpio_data gpio_shadow_read8(gpio_t *gpio){return gpio->shadow;}
+
+gpio_data gpio_ff_read(gpio_t *gpio){return 0xff;}
+
+gpio_data gpio_zero_read(gpio_t *gpio){return 0;}
+
+/***************************************************************************
+ * Atomic method wrappers
+ */
+int atomic_gpio_ddr_write(gpio_t *gpio,gpio_data data){
+	ATOMIC(gpio->ddr_write(gpio,data);)
+	return 0;
+}
+
+gpio_data atomic_gpio_ddr_read(gpio_t *gpio){
+	gpio_data retval;
+	ATOMIC(retval = gpio->ddr_read(gpio);)
+	return retval;
+}
+
+int atomic_gpio_data_write(gpio_t *gpio,gpio_data data){
+	ATOMIC(gpio->data_write(gpio,data);)
+	return 0;
+}
+
+gpio_data atomic_gpio_data_read(gpio_t *gpio){
+	gpio_data retval;
+	ATOMIC(retval = gpio->data_read(gpio);)
+	return retval;
+}
+
+int atomic_gpio_index_write(gpio_t *gpio,gpio_data data){
+	ATOMIC(gpio->index_write(gpio,data);)
+	return 0;
+}
+
+gpio_data atomic_gpio_index_read(gpio_t *gpio){
+	gpio_data retval;
+	ATOMIC(retval = gpio->index_read(gpio);)
+	return retval;
+}
+
+/***************************************************************************
+ * gpio sysfs operations
+ */
+#ifdef CONFIG_GPIOCLASS_SYSFS
+static ssize_t gpio_data_store(struct class_device *cls, const char *buf,size_t count){
+	size_t size;
+	gpio_t *gpio = cls->class_data;
+	gpio_data data = sfs_getint(buf,count,&size);
+	atomic_gpio_data_write(gpio, data);
+	return size;
+}
+
+static ssize_t gpio_ddr_store(struct class_device *cls, const char *buf,size_t count){
+	size_t size;
+	gpio_t *gpio = cls->class_data;
+	gpio_data data = sfs_getint(buf,count,&size);
+	atomic_gpio_ddr_write(gpio, data);
+	return size;
+}
+
+static ssize_t gpio_index_store(struct class_device *cls, const char *buf,size_t count){
+	size_t size;
+	gpio_t *gpio = cls->class_data;
+	gpio_data data = sfs_getint(buf,count,&size);
+	atomic_gpio_index_write(gpio, data);
+	return size;
+}
+
+static ssize_t gpio_data_show(struct class_device *cls, char *buf){
+	gpio_t *gpio = cls->class_data;
+	return sprintf(buf,"%x\r\n",atomic_gpio_data_read(gpio));
+}
+
+static ssize_t gpio_ddr_show(struct class_device *cls, char *buf){
+	gpio_t *gpio = cls->class_data;
+	return sprintf(buf,"%x\r\n",atomic_gpio_ddr_read(gpio));
+}
+
+static ssize_t gpio_index_show(struct class_device *cls, char *buf){
+	gpio_t *gpio = cls->class_data;
+	return sprintf(buf,"%x\r\n",atomic_gpio_index_read(gpio));
+}
+
+static CLASS_DEVICE_ATTR(ddr,S_IRUGO|S_IWUGO,gpio_ddr_show,gpio_ddr_store);
+static CLASS_DEVICE_ATTR(data,S_IRUGO|S_IWUGO,gpio_data_show,gpio_data_store);
+static CLASS_DEVICE_ATTR(index,S_IRUGO|S_IWUGO,gpio_index_show,gpio_index_store);
+#endif //CONFIG_GPIOCLASS_SYSFS
+
+/***************************************************************************
+ * class instantiation
+ */
+struct class_device *gpio_register_class_device(gpio_t *gpio){		
+	struct class *gpio_master = gpio_declare();
+	struct class_device *dev;	
+	dev_t devnum = MKDEV(0, 0);
+
+#ifdef CONFIG_GPIOCLASS_CHAR
+	devnum = gpio_char_create(gpio);
+#endif	
+
+	dev = class_device_create(gpio_master, NULL, devnum, NULL, gpio->name);
+	dev->class_data = gpio;	
+
+#ifdef CONFIG_GPIOCLASS_SYSFS
+	if((gpio->ddr_write)&&(gpio->ddr_read))class_device_create_file(dev,&class_device_attr_ddr);
+	if((gpio->data_write)&&(gpio->data_read))class_device_create_file(dev,&class_device_attr_data);
+	if((gpio->index_write)&&(gpio->index_read))class_device_create_file(dev,&class_device_attr_index);
+#endif	 
+
+#ifdef CONFIG_GPIOCLASS_RTDM
+	rt_gpio_device_create(gpio);
+#endif
+
+	return dev;			
+}
diff -Naur linux-2.6.25.maxim/drivers/misc/classes/Kconfig linux-2.6.25.at91-20080908/drivers/misc/classes/Kconfig
--- linux-2.6.25.maxim/drivers/misc/classes/Kconfig	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/drivers/misc/classes/Kconfig	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,94 @@
+#
+# Input device configuration
+#
+
+menu "misc device classes"
+
+config GPIOCLASS
+        bool "GPIO class"
+        ---help---
+	  This is a set of classes for general purpose io ports.
+	  These devices typically contain a data register, 
+	  which holds the current state of the pins, and a ddr register, 
+	  which sets the pin to input or output, 0 or 1 respectively 
+
+config GPIOCLASS_SYSFS
+		depends on SYSFS && GPIOCLASS
+        bool "sysfs interface"
+        ---help---
+	  enables a sysfs interface to the gpio class
+
+config GPIOCLASS_RTDM 
+		depends on XENO_SKIN_RTDM && GPIOCLASS
+        bool "rtdm interface"
+        ---help---
+	  enables a Xenomai RTDM interface to the gpio class
+	  
+config GPIOCLASS_CHAR
+		depends on GPIOCLASS
+		bool "char interface"
+		---help---
+		Enables a character device interface to the GPIO class.
+
+config PWMCLASS
+        bool "PWM class"
+        ---help---
+	  This is a set of classes for pulse width modulation.
+	  It allows the creation of pwm classes which can be configured
+	  through sysfs. PWM devices typically contain a 
+	  duty and frequency configuration register.
+	  
+config PWMCLASS_SYSFS
+		depends on SYSFS && PWMCLASS
+        bool "sysfs interface"
+        ---help---
+	  enables a sysfs interface to the pwm class
+
+config PWMCLASS_RTDM 
+		depends on XENO_SKIN_RTDM && PWMCLASS
+        bool "rtdm interface"
+        ---help---
+	  enables a Xenomai RTDM interface to the pwm class	  
+	  
+config MMCCLASS
+        bool "SPI/MMC class based driver"
+        ---help---
+        A MMC/SD class for transferring MMC information to a block driver layer.
+        Designed for providing board specific syncronizations 
+        between periodic spi devices and mmc block devices.
+        This class allows the mach to orchistrate low level spi interactions.   
+        
+config SPICLASS
+        bool "SPI class"
+        ---help---
+	  This is a set of classes for SPI interfaces.
+	  It allows the creation of spi classes which can be configured
+	  through sysfs.SPI devices typically contain a 
+	  speed and flags register, a method for locking the bus, 
+	  and a bidirectional "xmit" method     
+
+config SPICLASS_SYSFS
+		depends on SYSFS && SPICLASS
+        bool "sysfs interface"
+        ---help---
+	  enables a sysfs interface to the spi class
+
+config SPICLASS_CHAR
+		depends on SPICLASS
+		bool "char interface"
+		---help---
+		Enables a character device interface to the spi class.
+
+config LSI2ESC
+        depends on SPICLASS
+        bool "Linux SPI Interface to EMAC SPI Class interface"
+        ---help---
+        Enables a generic interface between the Linux SPI
+        driver and the EMAC SPI Class. Boards with an SPI controller
+        driver can use this to define generic access to a device
+        through the EMAC SPI class.
+        
+endmenu
+
+
+
diff -Naur linux-2.6.25.maxim/drivers/misc/classes/Makefile linux-2.6.25.at91-20080908/drivers/misc/classes/Makefile
--- linux-2.6.25.maxim/drivers/misc/classes/Makefile	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/drivers/misc/classes/Makefile	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,13 @@
+#
+# Makefile for the misc classes
+#
+
+EXTRA_CFLAGS += -Iinclude/xenomai
+obj-$(CONFIG_GPIOCLASS)		+= gpio.o
+obj-$(CONFIG_PWMCLASS)		+= pwm.o
+obj-$(CONFIG_MMCCLASS)		+= mmc.o
+obj-$(CONFIG_SPICLASS)		+= spi.o
+obj-$(CONFIG_LSI2ESC)       += spi_interface.o
+mmc-y := mmcprot.o mmcblock.o
+obj-y += rtdm/
+obj-y += char/
diff -Naur linux-2.6.25.maxim/drivers/misc/classes/mmcblock.c linux-2.6.25.at91-20080908/drivers/misc/classes/mmcblock.c
--- linux-2.6.25.maxim/drivers/misc/classes/mmcblock.c	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/drivers/misc/classes/mmcblock.c	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,269 @@
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+
+#include <linux/kernel.h>	
+#include <linux/slab.h>		
+#include <linux/fs.h>		
+#include <linux/errno.h>	
+#include <linux/types.h>	
+#include <linux/fcntl.h>	
+#include <linux/hdreg.h>	
+#include <linux/genhd.h>
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>	
+#include <linux/bio.h>
+#include <linux/timer.h>
+
+#include <linux/class/mmcprot.h>
+#include <linux/class/mmcblock.h>
+
+/***************************************************************************
+ * External Functions from mcf_mmc_prot
+ ***************************************************************************/
+#define DEVICE_NAME "mmc"
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+#define MAJOR_NR 121
+
+/*
+ * We can tweak our hardware sector size, but the kernel talks to us
+ * in terms of small sectors, always.
+ */
+#define KERNEL_SECTOR_SIZE	512
+
+MODULE_AUTHOR("N.Z. Gustavson <ngustavson@emacinc.com");
+MODULE_DESCRIPTION("Driver for MMC/SD Cards");
+
+#define MMC_MINORS 16
+
+/**
+ * Block transfer implementation for the mmc/sd 
+ * This is the base hardware transfer function for all block driver calls.
+ */
+static inline int mmctransfer(mmcslot_t *s, unsigned long sector,
+		unsigned long nsect, char *buffer, int write){
+			
+	unsigned long offset = sector*KERNEL_SECTOR_SIZE;
+	unsigned long nbytes = nsect*KERNEL_SECTOR_SIZE;		
+	unsigned long blocks = nbytes/s->card.blocklength;
+	
+	MMCBDEBUG("mmc transfer\n");
+	MMCBDEBUG("mmc sector %lu\n",sector);
+	MMCBDEBUG("mmc nsect %lu\n",nsect);
+	MMCBDEBUG("mmc nbytes %lu\n",nbytes);
+    MMCBDEBUG("s->card.blocklength %u\n",s->card.blocklength);
+	
+	if ((offset + nbytes) > s->card.size) {
+		printk ("Beyond-end write (%ld %ld)\n", offset, nbytes);
+		return -1;
+	}
+	
+	if (blocks==0) {
+		printk ("Device blocklength>%u not supported\n",KERNEL_SECTOR_SIZE);
+		return -1;
+	}
+		
+	if (write)
+		return(WRITE_MULTIPLE_BLOCK(s,offset, buffer, s->card.blocklength, blocks));
+	else
+		return(READ_MULTIPLE_BLOCK(s,offset,buffer,s->card.blocklength,blocks));	
+}
+
+/**
+ * request implementation
+ */
+void mmc_request(request_queue_t *q){
+		
+	struct request *req;		
+	MMCBDEBUG("mmc_request\n"); 
+	
+		while ((req = elv_next_request(q)) != NULL) {
+			mmcslot_t *s = req->rq_disk->private_data;				
+				
+		if (!(s->state&READY)){
+			printk("Device is not currently valid\n");
+			end_request(req, 0);
+			continue;
+		}
+		
+		if (!blk_fs_request(req)) {
+			MMCBDEBUG (KERN_NOTICE "Skip non-fs request\n");
+			end_request(req, 0);
+			continue;
+		}
+					
+			if((mmctransfer(s, req->sector, req->current_nr_sectors,
+					req->buffer, rq_data_dir(req)))<0){
+				MMCBDEBUG ("transfer failed\n");							
+				end_request(req,0);//failure				
+				}
+			else{
+				MMCBDEBUG ("transfer success\n");
+				end_request(req,1);	//success	
+			}			
+		}	
+	MMCBDEBUG("mmc_request end\n");
+	}
+
+
+/******************************************************************************
+ * Removable media support
+ ******************************************************************************/
+static int mmc_check_media_change(struct gendisk *gd){
+mmcslot_t *s = gd->private_data;
+return(s->state&CHANGED ? 1:0);		
+}
+
+static int mmc_revalidate(struct gendisk *gd){
+mmcslot_t *s = gd->private_data;
+if (s->state==(CHANGED|VALID)){
+	int err;
+	printk("MMC media change detected, reinitializing\n");
+	if((err=mmcinit(s))<0){
+		printk("failed to initialize card\n");
+		s->state = INVALID;
+		return err;
+	}
+	set_capacity(gd, s->card.sectors*(s->card.blocklength/KERNEL_SECTOR_SIZE));
+	MMCBDEBUG("set capacity to %u\n",s->card.sectors*(s->card.blocklength/KERNEL_SECTOR_SIZE));
+	MMCBDEBUG("sectors=%u\n",s->card.sectors);
+	MMCBDEBUG("CSIZE=%u\n",s->card.CSD.C_SIZE);
+	MMCBDEBUG("CMULT=%u\n",s->card.CSD.C_SIZE_MULT);
+	s->state = VALID|READY;	
+}
+return -ENODEV;
+}
+
+/******************************************************************************
+ * Standard block driver file operations
+ ******************************************************************************/
+/**
+ * block device open 
+ */
+static int mmc_open(struct inode *inode, struct file *filp){
+	mmcslot_t *s = inode->i_bdev->bd_disk->private_data;
+	//struct gendisk *gd = s->private_data;	
+	
+	MMCBDEBUG("mmc_open\n"); 
+	
+	filp->private_data = s;
+	checkmedia_stop(s);
+	spin_lock(&s->lock); 
+	check_disk_change(inode->i_bdev);
+	if (!(s->state&READY)){
+			printk ("%s device not ready\n",s->name);
+			spin_unlock(&s->lock);
+			if(!s->users)checkmedia_start(s);//if no users remain, begin checking for media change again.
+			return -ENODEV;
+		}
+		
+	s->users++;
+	spin_unlock(&s->lock);		
+	return 0;
+}
+
+static int mmc_release(struct inode *inode, struct file *filp)
+{
+	mmcslot_t *s = inode->i_bdev->bd_disk->private_data;
+	MMCBDEBUG("mmc_release - getting lock\n"); 
+	spin_lock(&s->lock);
+	MMCBDEBUG("obtained lock\n"); 
+	s->users--;
+	if(!s->users)checkmedia_start(s);//if no users remain, begin checking for media change again.
+	spin_unlock(&s->lock);
+	MMCBDEBUG("released lock\n"); 
+	return 0;
+}
+
+static int mmc_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	struct hd_geometry geometry;
+	//mmcslot_t *s = filp->private_data;
+	struct block_device *bdev = inode->i_bdev;
+	mmcslot_t *s = inode->i_bdev->bd_disk->private_data;
+	
+	if(!bdev){MMCBDEBUG("block device doesn't exist\n");return -EINVAL;}
+	if(!s){MMCBDEBUG("mmcslot doesn't exist\n");return -EINVAL;}
+	
+	MMCBDEBUG("mmc_ioctl\n"); 
+	
+	if (!(s->state&READY)){
+			printk ("Device is not currently valid\n");
+			return -ENODEV;
+		}
+	
+	if (cmd == BLKGETSIZE)
+	{
+		MMCBDEBUG("   BLKGETSIZE\n");
+		if (!arg) return -EINVAL;
+		if (copy_to_user((long *) arg, (long *) &s->card.blocklength, sizeof(s->card.blocklength))) return -EFAULT;
+		return 0;
+	}
+	else if (cmd == HDIO_GETGEO)
+	{
+		MMCBDEBUG("   HDIO_GETGEO\n");
+		if (!arg) return -EINVAL;
+		
+		geometry.cylinders	= get_capacity(bdev->bd_disk) / (4 * 16);
+		geometry.heads	= 4;
+		geometry.sectors	= 16;
+		geometry.start	= get_start_sect(bdev);
+		
+		if (copy_to_user((void *) arg, &geometry, sizeof(geometry))) return -EFAULT;
+		return 0;
+	}
+	else return -ENOTTY; /* unknown command */
+}
+
+static struct block_device_operations mmc_bdops = {
+	.owner           		= THIS_MODULE,
+	.open						=  mmc_open,
+	.release					=  mmc_release,
+	.ioctl 						=  mmc_ioctl,
+	.media_changed	= mmc_check_media_change,
+	.revalidate_disk	= mmc_revalidate,
+};
+/******************************************************************************
+ * driver initializations
+ ******************************************************************************/
+
+int mmc_diskize(mmcslot_t *s){
+	struct gendisk *gd = alloc_disk(MMC_MINORS);		
+	
+	MMCBDEBUG("setup device %s\n",s->name);	
+			 
+	gd->private_data =  s;
+	gd->major = MAJOR_NR;
+	gd->first_minor = s->slotnumber*MMC_MINORS;
+	gd->fops = &mmc_bdops;
+	gd->flags = GENHD_FL_REMOVABLE;
+	
+	if((gd->queue=blk_init_queue(mmc_request,&s->lock))==NULL){
+		printk("couldn't init block queue\n");
+		return -1;
+	}
+			
+	blk_queue_hardsect_size(gd->queue,s->card.blocklength);
+	gd->queue->queuedata = s;
+	snprintf (gd->disk_name, 32, s->name);
+
+	s->disk = gd;
+
+	add_disk(gd); 
+		
+	return 0;
+}
+
+int mmc_bdriver_init(void)
+{
+	register_blkdev(MAJOR_NR, DEVICE_NAME);
+	MMCBDEBUG("mmc block driver registered\n");
+	return 0;
+}
+
+void mmc_bdriver_exit(void)
+{
+	MMCBDEBUG("mmc block driver removed\n");	
+}
diff -Naur linux-2.6.25.maxim/drivers/misc/classes/mmcprot.c linux-2.6.25.at91-20080908/drivers/misc/classes/mmcprot.c
--- linux-2.6.25.maxim/drivers/misc/classes/mmcprot.c	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/drivers/misc/classes/mmcprot.c	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,601 @@
+#define EXPORT_SYMTAB
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/wait.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/class/mmcprot.h>
+#include <linux/class/mmcblock.h>
+
+#define DRV_MODULE_NAME 	"mmc"
+#define DRV_MODULE_VERSION 	"1.0"
+
+//#define MMCHARDERROR
+#ifdef MMCHARDERROR
+//debugging error, hard lock to find signal error via scope
+#define MMCERROR(err)	{printk("%s:MMCERR %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); while (1);}
+#else
+//return an error value on invalid communication.
+#define MMCERROR(err)	{return -err;}
+#endif
+
+
+static void checkmedia(unsigned long ptr){
+	mmcslot_t *s  = (mmcslot_t *)ptr;
+	//MMCDEBUG("checking media\n");
+	
+	if(!s->carddetect){s->state = INVALID;return;}//if cardetect is not implemented just return.
+	{
+	mmcslot_t *s = (mmcslot_t *)ptr;
+	int state = (s->carddetect(s))?VALID:INVALID;
+	if(state!=(s->state&VALID)){//state change
+  		printk("Multimedia card %s\n",state==VALID ? "inserted":"removed");	
+  		s->state = state|CHANGED;				  			
+	}
+	mod_timer(&s->timer,jiffies + HZ);//reset to probe next scheduler period	
+	}
+}
+
+
+void checkmedia_start(mmcslot_t *s){
+	setup_timer(&s->timer,checkmedia,(unsigned long)s);//make sure timer is initialized
+	checkmedia((unsigned long)s);//check immediately and reschedule
+}
+
+void checkmedia_stop(mmcslot_t *s){
+	del_timer_sync(&s->timer);//turn off the media check
+}
+
+
+
+static int mmcprot_probe(struct platform_device *pdev){	
+	if (pdev == NULL){MMCDEBUG("no platform device found\n");return -ENODEV;}
+	
+	{
+		mmcslot_t *s = pdev->dev.platform_data;
+		mmc_bdriver_init();//initialize block driver layer.
+		spin_lock_init(&s->lock);
+		s->card.blocklength = 512;//this could theoretically change dynamically, although in practice all cards use 512	
+		
+		MMCDEBUG("setting up timer\n");
+		checkmedia_start(s);
+		mmc_diskize(s);//setup a disk based upon this platform device.
+	}
+	
+	return 0;
+}
+
+//driver currently has no removal method.
+static struct platform_driver mmcprot_driver = {
+	.probe		= mmcprot_probe,
+	.driver		= {
+		.name	= "mmc",
+	},
+};
+
+static int __init mmcprot_init_module(void)
+{
+	printk(KERN_INFO DRV_MODULE_NAME " version " DRV_MODULE_VERSION " loading\n");
+	return platform_driver_register(&mmcprot_driver);
+}
+
+static void __exit mmcprot_cleanup_module(void)
+{
+	platform_driver_unregister(&mmcprot_driver);
+}
+
+module_init(mmcprot_init_module);
+module_exit(mmcprot_cleanup_module);
+
+/**********************************************************************************
+ * MMC transfer protocols
+ */
+
+/**
+	 * Fake CRC7. Currently the CRC is unused so
+	 * hard coded to 0x95 for the first(and only used)
+	 * CRC value
+	 * @param array array to calculate the CRC7 on
+	 * @return
+	 */
+static int CRC7(u8 *array){
+			return 0x95;
+		}
+
+/**
+	 * MMC packet building function
+	 * This function builds the command, clears and clears the remaining
+	 * frame which will be filled by the xmit function.
+	 * @param frame an array object to packetize
+	 * @param framelen size of the frame
+	 * @param command command index number
+	 * @param arg1 first arguement, high bits 31:16
+	 * @param arg2 second arguement, low bits 15:0
+	 * @param response number of response bits expected
+	 * @return 0
+	 */
+static int packetize(u8 *frame, int framelen, int command, int arg1, int arg2){
+		int START_BIT = 0;//MSB is zero
+		int TRANSMISSION_BIT = 0x40;
+		int STOP_BIT = 0x01;				
+		int bytenum;
+		
+		MMCDEBUG("packetize\n");
+		
+		frame[0] = (u8)((command|START_BIT|TRANSMISSION_BIT)&(0xff));
+		frame[1] = (u8)((arg1>>8)&(0xff));
+		frame[2] = (u8)((arg1)&(0xff));
+		frame[3] = (u8)((arg2>>8)&(0xff));
+		frame[4] = (u8)((arg2)&(0xff));
+		frame[5] = (u8)(CRC7(frame)|STOP_BIT);
+		
+		for(bytenum=COMMAND_LENGTH;bytenum<framelen;bytenum++)frame[bytenum] = (u8)0xff;
+	
+		return 0;
+	}
+
+/**
+	 * move the received response into int format
+	 * @param Rnum 1,2 or 5 number of bytes received
+	 * @param frame packet frame array
+	 * @param bytestart index of the Rx data in the frame
+	 * @return The response in int format
+	 */
+static int get_response(int Rnum, char *frame, int bytestart){
+		//int Rx = frame[bytestart];
+		u8 Rx = frame[bytestart];
+		MMCDEBUG("get_response Rnum = %x bytestart=%x\n",Rnum, bytestart);
+		
+		switch(Rnum){
+		case 1://standard command/response
+			//do nothing data already read
+		break;
+		case 2://two byte response
+			Rx<<=8;
+			Rx|=frame[bytestart+1];
+		break;
+		case 5:// five byte response,currently only the READ_OCR command uses this.
+			Rx = frame[bytestart+1];
+			Rx<<=8;
+			Rx |= frame[bytestart+2];
+			Rx<<=8;
+			Rx |= frame[bytestart+3];
+			Rx<<=8;
+			Rx |= frame[bytestart+4];
+			Rx<<=8;
+		break;	
+			}
+		return Rx;
+	}	
+
+/**
+ * Wait functions, read a short burst of data, then if nothing has arrived yet, sleep for
+ * a clock tick and try again with an eventual timeout.
+ */	
+	
+	/**
+	 * wait until the MMC returns a non-zero result
+	 * assumes pre-existing tip
+	 * @return 1
+	 */
+#define POLLNUMBER 100	 
+	 
+static int busy_wait(mmcslot_t *s){
+		int tickloop;
+		int shortloop;
+		u8 status=0;
+		
+		s->exchange(s,NULL, &status, 1);
+			
+		for(tickloop=0;tickloop<100;tickloop++){
+			for(shortloop=0;shortloop<POLLNUMBER;shortloop++){
+				s->exchange(s,NULL, &status, 1);	
+				if(status==0xff){
+					s->exchange(s,NULL, &status, 1);	;
+					return 1;//success
+				}						
+			}
+		set_current_state(TASK_INTERRUPTIBLE);//may want to shorten this.
+	 	schedule_timeout(HZ/100 ? HZ/100 : 1);
+		}
+			MMCERROR(1);//error
+	}
+
+/**
+ * delay loop that waits for an Rxtoken
+ * assumes pre-existing tip
+ * @return 1 if successful
+ */	
+ 
+static int wait_for_Rxtoken(mmcslot_t *s) {
+	u8 status=0;
+	int BR_START_TOKEN = 0xFE;//MMC token for data start
+	int tickloop;
+	int shortloop;
+		
+	for(tickloop=0;tickloop<100;tickloop++){
+	 	for(shortloop=0;shortloop<POLLNUMBER;shortloop++){	 		
+			s->exchange(s,NULL, &status, 1);
+			if(status==(u8)BR_START_TOKEN)
+				return 1;
+			}
+	 	set_current_state(TASK_INTERRUPTIBLE);
+	 	schedule_timeout(HZ/100 ? HZ/100 : 1);
+	 	}
+		MMCERROR(1);
+		
+		return 1;
+}
+
+
+/**
+	 * interprete the command response and throw exceptions as appropriate
+	 * @param response the byte containing the response
+	 * @return 0 if nothing is wrong
+	 */
+	static int CommandResponse(int response){				
+		if(response==0){
+			MMCDEBUG("command successful\n");
+			return 0;//no problems command succeeded
+		}
+		
+		printk("command error\n");
+		
+		if((response&MMCCOM_IDLE)!=0)
+			printk("idle\n");
+		if((response&MMCCOM_ERASE_RES)!=0)
+			printk("erase reset\n");
+		if((response&MMCCOM_ILLEGAL)!=0)
+			printk("illegal\n");
+		if((response&MMCCOM_CRC)!=0)
+			printk("crc\n");
+		if((response&MMCCOM_ERASE_SEQ)!=0)
+			printk("erase sequence\n");		
+		if((response&MMCCOM_ADDRESS)!=0)
+			printk("address\n");
+		if((response&MMCCOM_PARAMETER)!=0)
+			printk("parameter\n");
+		
+		MMCERROR(1);				
+	}
+/**
+ * interprete the data response and throw exceptions as appropriate
+ * @param response the byte containing the response
+ * @return 0 if nothing is wrong
+ */
+ 	static int DataResponse(int response){
+		//System.out.println("response="+response);
+		
+		switch(response&MMCDAT_D_RESPONSE_MASK){
+		case MMCDAT_DATA_ACC:
+			//System.out.println("Data accepted");
+			return 0;//data was accepted, no need to complain
+		case MMCDAT_CRC_ERR:
+			printk("CRC error\n");
+			MMCERROR(1);
+		case MMCDAT_WRITE_ERR:
+			printk("Write error\n");
+			MMCERROR(1);
+		default:
+			printk("Communications error\n");
+			MMCERROR(1);
+		}
+		
+		MMCERROR(1);
+	}	
+
+/**
+	 * General purpose method for tranceiving a command/response
+	 * to the MMC
+	 * @param command command index, see table below
+	 * @param arg1 first arguement, high bits 31:16
+	 * @param arg2 second arguement, low bits 15:0
+	 * @param blocking block before returning?
+	 * @param response number of response bits expected
+	 * @return the command response
+	 */
+int mmctransaction(mmcslot_t *s, int command, int arg1, int arg2,int blocking,int response){ 
+		int Rx;
+		int bytenum;
+		
+		int framelen = COMMAND_LENGTH+Ncr_MAX+response;		
+		unsigned char readbuff[COMMAND_LENGTH+Ncr_MAX+MAX_RESPONSE];				
+		unsigned char writebuff[COMMAND_LENGTH+Ncr_MAX+MAX_RESPONSE];	
+						
+		packetize(writebuff,(COMMAND_LENGTH+Ncr_MAX+response),command,arg1,arg2);
+		
+		if((s->tip(s,TRUE))<0)MMCERROR(1);//could not obtain the bus
+			
+		MMCDEBUG("xmit\n");s->exchange(s,writebuff, readbuff, framelen);
+				
+		MMCDEBUG("interprete\n");
+		//locate and interprete the data
+		for(bytenum=COMMAND_LENGTH;bytenum<framelen;bytenum++)
+			if(readbuff[bytenum]!=(u8)0xff)
+				break;
+		
+		if(bytenum==(framelen)){
+			MMCDEBUG("no command response received\n");
+			s->tip(s,FALSE);
+			MMCERROR(1);
+			}
+			
+		MMCDEBUG("get_response\n");
+		Rx = get_response(response,readbuff,bytenum);
+		
+		if(blocking)busy_wait(s);
+		
+		s->tip(s,FALSE);//use caution inlining this as it turns off the transaction upon returning
+		return Rx;
+		
+	}
+
+/**
+	 * Block Read transaction
+	 * @param command - the initiating command
+	 * @param arg1 - arg1 of the initiating command
+	 * @param arg2 - arg2 of the initiating command
+	 * @param response - response size 
+	 * @param data - buffer to move received data into
+	 * @param blocknum - number of blocks to read
+	 * @param blocksize - size of blocks
+	 * @param Nac - Nac timing parameter
+	 * @return the total number of blocks read
+	 * 
+	 * major guts rewrite to accomodate new SPI bus method.
+	 * 
+	 */
+int mmcblockread(mmcslot_t *s, int command, int arg1, int arg2,int response, u8 *data,int blocksize, int blocknum,int Nac){
+		u8 frame[COMMAND_LENGTH+Ncr_MAX+MAX_RESPONSE];
+		int block;//current block being parsed
+		int frame_index;//frame index		
+		int Rx;
+		u8 CRC[CRC_LENGTH];
+		u8 commandbuffer[COMMAND_LENGTH];
+		
+		MMCDEBUG("BlockRead\n");	
+				
+		packetize(commandbuffer,COMMAND_LENGTH,command,arg1,arg2);
+
+		if((s->tip(s,TRUE))<0)MMCERROR(1);//could not obtain the bus
+		s->exchange(s,commandbuffer, frame, sizeof(commandbuffer));
+		
+		//new broken up method cannot grab response within single xmit as it can 
+		//accidentally pull data. 
+		//Check the bytes as they are tranceived instead
+		MMCDEBUG("exchange response\n");
+		for(frame_index=COMMAND_LENGTH;frame_index<(COMMAND_LENGTH+Ncr_MAX+response);frame_index++){	
+			s->exchange(s,NULL,&frame[frame_index],1);
+			if(frame[frame_index]!=(u8)0xff)break;//go ahead and interprete the response
+		}
+			
+		if(frame_index==(COMMAND_LENGTH+Ncr_MAX+response)){
+			printk("MMC READ:no command response received\n");
+			s->tip(s,FALSE);
+			MMCERROR(1);
+			}
+			
+		Rx = get_response(response,frame,frame_index);
+		
+		if(CommandResponse(Rx)<0){
+			printk("MMC_READ:command response error, Rx=%x\n",Rx);
+			s->tip(s,FALSE);
+			MMCERROR(1);//error
+		}
+		
+		MMCDEBUG("wait for rx token\n");
+		for(block=0;block<blocknum;block++){	
+			if(wait_for_Rxtoken(s)<0){
+				printk("MMC_READ:No Rx token received\n");
+				s->tip(s,FALSE);
+				MMCERROR(1);//error
+			}
+			
+			MMCDEBUG("exchange data block %u\n",block);	
+			//retrieve a block of data, passing null to tx assumes 0xff transmission
+			s->exchange(s,NULL,&data[block*blocksize],blocksize);
+			s->exchange(s,NULL,CRC,CRC_LENGTH);//not currently used
+											
+			}
+		
+		//Send extra 8 char NEC	
+		s->exchange(s,NULL, NULL,8);
+			
+		if(command==18)STOP_TRANSMISSION(s);//end open ended read		
+		s->tip(s,FALSE);		
+		return blocknum;
+		}
+
+	/**
+	 * Write Blocks of data;
+	 * @param command command index to initiate the transfer
+	 * @param arg1 first arguement to the command
+	 * @param arg2 second arguement to the commmand
+	 * @param response number of responses expected
+	 * @param data buffer holding the data to be transmitted
+	 * @param blocknum number of blocks
+	 * @param blocksize size of the blocks
+	 * @param Nwr timing parameter, typically 1
+	 * @return
+	 */
+int mmcblockwrite(mmcslot_t *s,int command, int arg1, int arg2, int response, u8 *data, int blocksize, int blocknum,int Nwr){		
+		int block;
+		int dataresponse;
+		u8 BW_STOP_TOKEN = 0xFD;	
+		u8 BW_START_TOKEN = 0xFD;
+		u8 commandbuffer[COMMAND_LENGTH+MAX_NWR+MAX_RESPONSE];
+		u8 responsebuffer[DATA_RESPONSE_LENGTH+CRC_LENGTH];
+		int index;
+
+		MMCDEBUG("BlockWrite:cmd %x arg1 %x arg2 %x size %x num%x\n",command,arg1,arg2,blocksize,blocknum);					
+				
+		//use the start correct token for single or multiple writes		
+		if(command==25)
+			BW_START_TOKEN = 0xFc;
+		else
+			BW_START_TOKEN = 0xFe;
+		
+		//transmit command and the first and possibly only block	
+		packetize(commandbuffer,sizeof(commandbuffer),command,arg1,arg2);
+			
+		if((s->tip(s,TRUE))<0)MMCERROR(1);//could not obtain the bus
+		//a simpler command exchange than read, is there a reason read doesn't use this?		
+		s->exchange(s,commandbuffer, NULL, COMMAND_LENGTH);
+		
+		for(index=COMMAND_LENGTH;
+		index<(COMMAND_LENGTH+MAX_NWR+MAX_RESPONSE);index++){
+			s->exchange(s,NULL, &commandbuffer[index], 1);
+			if(commandbuffer[index]!=(u8)0xff)break;//go ahead and interprete the response
+		}
+			
+		if(index==(COMMAND_LENGTH+MAX_NWR+MAX_RESPONSE)){
+			printk("MMC BWRITE:no command response received\n");
+			s->tip(s,FALSE);
+			MMCERROR(1);
+			}
+			
+		index = get_response(response,commandbuffer,index);
+		
+		if((CommandResponse(index))<0){
+			printk("MMC BWRITE command response error\n");
+			s->tip(s,FALSE);
+			MMCERROR(1);//error
+		}	
+		
+		s->exchange(s,NULL, NULL, 1);//NWR delay
+
+		for(block=0;block<blocknum;block++){
+			//send start token
+			s->exchange(s,&BW_START_TOKEN, NULL, START_TOKEN_LENGTH);
+			
+			//send data
+			s->exchange(s,&data[block*blocksize], NULL, blocksize);
+
+			//read dataresponse
+			s->exchange(s,NULL, responsebuffer, (DATA_RESPONSE_LENGTH+CRC_LENGTH));
+
+			dataresponse = responsebuffer[CRC_LENGTH];//gloss over the CRC for now	
+			if(DataResponse(dataresponse)<0){
+				 printk("MMC Data Response error\n");
+				s->tip(s,FALSE);
+				MMCERROR(1);//error
+			}
+			MMCDEBUG("Block %u\n",block);					
+			busy_wait(s);//wait for completion
+		}		
+
+		//send the end transmit command if it's a multiple block write(open ended)
+		if(command==25){
+			//send stop token
+			s->exchange(s,&BW_STOP_TOKEN, NULL, 1);				
+			busy_wait(s);
+		}		
+		
+		s->tip(s,FALSE);
+		return blocknum;
+	}
+
+
+/**
+	 * Initialize the MMC interface and the SPI interface controlling it.
+	 * Also read out the registers into shadow variables.
+	 */	
+int mmcinit(mmcslot_t *s){
+		u8 RegisterBuff[16];
+		int response,iteration,mult;
+		
+		s->setspeed(s,100000);//set spi speed to low for initial configuration as an spi device
+		
+		s->card.blocklength = 512;/*default, change later if appropriate*/
+
+		s->tip(s,FALSE);
+		mdelay(1);//make sure transaction has been off for at least 1ms
+		if((s->tip(s,TRUE))<0)MMCERROR(1);//could not obtain the bus, this may need to be a retry
+		s->exchange(s,NULL, NULL,72);//send string of NULLS (0xff for MMC/SD) to clear out the card
+		s->tip(s,FALSE);
+		
+		MMCDEBUG("GO_IDLE_STATE\n");
+		GO_IDLE_STATE(s);//reset and start SPI mode
+		
+		for(iteration=0;iteration<1000;iteration++){
+			MMCDEBUG("SEND_OP_COND\n");
+			response = SEND_OP_COND(s);//read OCR, a wait should be inserted here until the OCR indicates ready.
+			MMCDEBUG("response = %d\n",response);
+			if(response==0)
+				break;		
+		}		
+		
+		if(iteration==100){
+			s->state=INVALID;
+			s->tip(s,FALSE);
+			MMCERROR(1);
+		}
+
+		MMCDEBUG("SEND_CID\n");
+				
+		if(SEND_CID(s,RegisterBuff)<0){
+			printk("MMC: no CID register found\n");
+			s->state=INVALID;
+			s->tip(s,FALSE);
+			MMCERROR(1);
+		}
+		else
+			parse_CID(&s->card.CID,RegisterBuff);	
+
+		MMCDEBUG("SEND_CSD\n");
+		
+		if(SEND_CSD(s,RegisterBuff)<0){
+			s->state=INVALID;
+			s->tip(s,FALSE);
+			MMCERROR(1);
+		}
+			
+		parse_CSD(&s->card.CSD,RegisterBuff);		
+		
+		s->card.blocklength = (1<<(s->card.CSD.READ_BL_LEN));
+		s->card.sectors = s->card.CSD.C_SIZE+1;
+		MMCDEBUG("set sectors to %u\n",s->card.sectors);
+		mult = 1<<(s->card.CSD.C_SIZE_MULT+2);
+		MMCDEBUG("mult=%u\n",mult);		
+		s->card.sectors*=mult;
+		MMCDEBUG("set sectors to %u\n",s->card.sectors);
+		s->card.size = s->card.blocklength*s->card.sectors;
+		
+		switch(s->card.CSD.TRAN_SPEED&7){
+			case 1:
+			s->card.speed = 1000000;
+			break;
+			
+			case 2:			
+			s->card.speed = 10000000;//can't go faster than 10M
+			break;
+			
+			case 3:			
+			s->card.speed = 100000000;//can't go faster than 100M
+			break;
+			
+			default:
+			s->card.speed = 100000;
+			break;
+		}
+		s->setspeed(s,s->card.speed);//turn the socket speed up to the maximum the card can handle
+		
+	printk("MMC card detected: %s\n",s->card.CID.Product_name);
+	printk("revision: %u.%u\n",((s->card.CID.Product_revision&0xf0)>>4),(s->card.CID.Product_revision&0x0f));
+	printk("serial#: %lu\n",s->card.CID.Product_serial_number);	
+	printk("Block Length=%u\n",s->card.blocklength);	
+	printk("Size =%lu\n",s->card.size);	
+	printk("Speed=%lu\n",s->card.speed);
+		
+	s->state=VALID;
+	s->tip(s,FALSE);
+	return 0;											
+}
diff -Naur linux-2.6.25.maxim/drivers/misc/classes/pwm.c linux-2.6.25.at91-20080908/drivers/misc/classes/pwm.c
--- linux-2.6.25.maxim/drivers/misc/classes/pwm.c	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/drivers/misc/classes/pwm.c	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,194 @@
+/**
+ * A class for simple pwm ports
+ * Several types of devices are available 
+ * which all export the same basic functionity 
+ * through differnet underlying methods
+ */
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/ctype.h>
+#include <linux/kdev_t.h>
+#include <linux/chelper.h>
+#include <linux/class/pwm.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_PWMCLASS_RTDM
+#include <rtdm/rtdm_driver.h>
+#include <linux/class/rtdm/pwm_rtdm.h>
+#define ATOMIC(a) RTDM_EXECUTE_ATOMICALLY(a)
+#else
+#define ATOMIC(a) a
+#endif //CONFIG_PWMCLASS_RTDM
+
+/************************************************************
+ * the global device class
+ */
+static struct class *pwmclass = NULL;
+
+struct class *pwm_declare(void){
+	if(!pwmclass){
+		printk("registering PWM class\n");
+		pwmclass=class_create(THIS_MODULE,"pwm");
+	}
+return pwmclass;
+}
+
+/***************************************************************************
+ * typical low level methods
+ */
+
+/** need to ajust this to use a clock method rather than getsysclock 
+static inline int us2reg(__u32 *value, int Mhz){
+		switch(get_sclk()){
+			case 66000000:{
+				const __u32 regmax = (0xffff/66);
+				if(*value>regmax)*value=regmax;
+				else *value*=66;
+				// pwms seem to do funny things when zeros are written to period or width;
+				if(*value==0)*value=1;
+				return 0;
+			}
+			default:return SYSCLOCK_UNSUPPORTED;
+	}
+}
+
+static inline int reg2us(__u32 *value){
+		switch(get_sclk()){
+			case 66000000:
+				*value/=66;
+				return 0;		
+			default:return SYSCLOCK_UNSUPPORTED;
+	}
+}
+*/ 
+ 
+int  pwm_widthus_write8(pwm_t *pwm, pwm_data data){iowrite8(data,pwm->widthus);return 0;}
+
+int  pwm_widthus_write16(pwm_t *pwm, pwm_data data){iowrite16(data,pwm->widthus);return 0;}
+
+int  pwm_periodus_write8(pwm_t *pwm, pwm_data data){iowrite8(data,pwm->periodus);return 0;}
+
+int  pwm_periodus_write16(pwm_t *pwm, pwm_data data){iowrite16(data,pwm->periodus);return 0;}
+
+int  pwm_empty_write(pwm_t *pwm, pwm_data data){return 0;}
+
+pwm_data pwm_widthus_read8(pwm_t *pwm){return ioread8(pwm->widthus);}
+
+pwm_data pwm_widthus_read16(pwm_t *pwm){return ioread16(pwm->widthus);}
+
+pwm_data pwm_periodus_read8(pwm_t *pwm){return ioread8(pwm->periodus);}
+
+pwm_data pwm_periodus_read16(pwm_t *pwm){return ioread16(pwm->periodus);}
+
+pwm_data pwm_widthusshadow_read(pwm_t *pwm){return pwm->widthus_shadow;}
+
+pwm_data pwm_ff_read(pwm_t *pwm){return 0xff;}
+	
+pwm_data pwm_zero_read(pwm_t *pwm){return 0;}
+
+/***************************************************************************
+ * Atomic method wrappers
+ */
+int atomic_pwm_widthus_write(pwm_t *pwm,pwm_data data){
+	ATOMIC(pwm->widthus_write(pwm,data);)
+	return 0;
+}
+	
+int atomic_pwm_periodus_write(pwm_t *pwm,pwm_data data){
+	ATOMIC(pwm->periodus_write(pwm,data);)
+	return 0;
+}
+
+int atomic_pwm_invert_write(pwm_t *pwm,pwm_data data){
+	ATOMIC(pwm->invert_write(pwm,data);)
+	return 0;
+}	
+	
+pwm_data atomic_pwm_widthus_read(pwm_t *pwm){
+	pwm_data retval;
+	ATOMIC(retval = pwm->widthus_read(pwm);)
+	return retval;
+}
+
+pwm_data atomic_pwm_periodus_read(pwm_t *pwm){
+	pwm_data retval;
+	ATOMIC(retval = pwm->periodus_read(pwm);)
+	return retval;
+}
+
+pwm_data atomic_pwm_invert_read(pwm_t *pwm){
+	pwm_data retval;
+	ATOMIC(retval = pwm->invert_read(pwm);)
+	return retval;
+}
+
+/************************************************************************************
+ * gpio sysfs operations
+ */
+#ifdef CONFIG_PWMCLASS_SYSFS
+
+static ssize_t pwm_widthus_store(struct class_device *cls, const char *buf,size_t count){
+	size_t size;
+	pwm_t *pwm = cls->class_data;
+	pwm_data data = sfs_getint(buf,count,&size);
+	atomic_pwm_widthus_write(pwm, data);
+	return size;
+}
+
+static ssize_t pwm_periodus_store(struct class_device *cls, const char *buf,size_t count){
+	size_t size;
+	pwm_t *pwm = cls->class_data;
+	pwm_data data = sfs_getint(buf,count,&size);
+	atomic_pwm_periodus_write(pwm, data);
+	return size;
+}
+
+static ssize_t pwm_invert_store(struct class_device *cls, const char *buf,size_t count){
+	size_t size;
+	pwm_t *pwm = cls->class_data;
+	pwm_data data = sfs_getint(buf,count,&size);
+	atomic_pwm_invert_write(pwm, data);
+	return size;
+}
+
+static ssize_t pwm_widthus_show(struct class_device *cls, char *buf){
+	pwm_t *pwm = cls->class_data;
+	return sprintf(buf,"%u\r\n",atomic_pwm_widthus_read(pwm));
+}
+
+static ssize_t pwm_periodus_show(struct class_device *cls, char *buf){
+	pwm_t *pwm = cls->class_data;
+	return sprintf(buf,"%u\r\n",atomic_pwm_periodus_read(pwm));
+}
+
+static ssize_t pwm_invert_show(struct class_device *cls, char *buf){
+	pwm_t *pwm = cls->class_data;
+	return sprintf(buf,"%x\r\n",atomic_pwm_invert_read(pwm));
+}
+
+static CLASS_DEVICE_ATTR(widthus,S_IRUGO|S_IWUGO,pwm_widthus_show,pwm_widthus_store);
+static CLASS_DEVICE_ATTR(periodus,S_IRUGO|S_IWUGO,pwm_periodus_show,pwm_periodus_store);
+static CLASS_DEVICE_ATTR(inversion,S_IRUGO|S_IWUGO,pwm_invert_show,pwm_invert_store);
+
+#endif //CONFIG_PWMCLASS_SYSFS
+/***************************************************************************
+* class instantiation
+*/
+struct class_device *pwm_register_class_device(pwm_t *pwm){		
+	struct class *pwm_master = pwm_declare();
+	struct class_device *dev = class_device_create(pwm_master, NULL, MKDEV(0, 0), NULL, pwm->name);
+	dev->class_data = pwm;
+
+#ifdef CONFIG_PWMCLASS_SYSFS
+	if((pwm->widthus_write)&&(pwm->widthus_read))class_device_create_file(dev,&class_device_attr_widthus);
+	if((pwm->periodus_write)&&(pwm->periodus_read))class_device_create_file(dev,&class_device_attr_periodus);
+	if((pwm->invert_write)&&(pwm->invert_read))class_device_create_file(dev,&class_device_attr_inversion);
+#endif	 
+	 
+#ifdef CONFIG_PWMCLASS_RTDM
+	rt_pwm_device_create(pwm);
+#endif 
+
+	return dev;			
+}
diff -Naur linux-2.6.25.maxim/drivers/misc/classes/rtdm/gpio_rtdm.c linux-2.6.25.at91-20080908/drivers/misc/classes/rtdm/gpio_rtdm.c
--- linux-2.6.25.maxim/drivers/misc/classes/rtdm/gpio_rtdm.c	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/drivers/misc/classes/rtdm/gpio_rtdm.c	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,99 @@
+/**
+ * A class for simple gpio ports
+ * Several types of general purpose devices are available 
+ * which all export the same basic functionity 
+ * through differenet underlying methods
+ * This class can also be used to export simple interfaces
+ * to an 8 bit port into user space
+ */
+
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/class/gpio.h>
+#include <linux/class/rtdm/gpio_rtdm.h>
+#include <rtdm/rtdm_driver.h>
+
+typedef struct rtgpio_device_s {
+struct rtdm_device rtd;
+gpio_t *gpio;//pointer to parent gpio structure.
+}rtgpio_device_t; 
+
+static int rt_gpio_open(struct rtdm_dev_context *context,
+                  rtdm_user_info_t *user_info, int oflags){
+    return 0;
+}
+
+static int rt_gpio_close(struct rtdm_dev_context *context,
+                   rtdm_user_info_t *user_info){
+return 0;
+}
+
+static int rt_gpio_ioctl(struct rtdm_dev_context *context,
+                   rtdm_user_info_t *user_info, int request, void *umem){
+    rtgpio_device_t *dev = container_of(context->device,rtgpio_device_t,rtd);
+    gpio_t *gpio = dev->gpio;
+       
+    gpio_data kmem[1];
+             
+	switch(request){
+	case DDRREAD:
+	if(gpio->ddr_read) kmem[0] = atomic_gpio_ddr_read(gpio);
+	else return -2;
+	return rtdm_safe_copy_to_user (user_info, umem, kmem, sizeof(gpio_data));		
+	
+	case DDRWRITE:
+	rtdm_safe_copy_from_user (user_info, kmem, umem, sizeof(gpio_data));	
+	if(gpio->ddr_write) atomic_gpio_ddr_write(gpio,kmem[0]);
+	else return -2;
+	return 0;
+	
+	case DATAREAD:
+	if(gpio->data_read)kmem[0] = atomic_gpio_data_read(gpio);
+	else return -2;
+	return rtdm_safe_copy_to_user (user_info, umem, kmem, sizeof(gpio_data));
+	
+	case DATAWRITE:
+	rtdm_safe_copy_from_user (user_info, kmem, umem, sizeof(gpio_data));	
+	if(gpio->data_write)atomic_gpio_data_write(gpio,kmem[0]);	
+	else return -2;
+	return 0;
+	}             
+                   	                 	
+return -1;//no such op, need to find the right op code for this.
+}
+
+
+static const struct rtdm_device __initdata device_tmpl = {
+    struct_version:     RTDM_DEVICE_STRUCT_VER,
+
+    device_flags:       RTDM_NAMED_DEVICE | RTDM_EXCLUSIVE,
+    device_name:        "",
+    open_rt:            rt_gpio_open,
+    ops: {
+        close_rt:      	rt_gpio_close,
+        ioctl_rt:       rt_gpio_ioctl,
+    },
+    device_class:       RTDM_CLASS_GPIO,
+    driver_name:        "gpio_rtd",
+    driver_version:     RTDM_DRIVER_VER(1, 0, 0),
+    peripheral_name:    "gpio",
+    provider_name:      "EMAC.Inc",
+};
+
+
+int rt_gpio_device_create(struct gpio_s *gpio){
+		rtgpio_device_t *dev = kmalloc(sizeof(rtgpio_device_t),GFP_KERNEL);
+		dev->gpio = gpio;
+		memcpy(&dev->rtd, &device_tmpl, sizeof(struct rtdm_device));
+		strncpy(dev->rtd.device_name, dev->gpio->name, RTDM_MAX_DEVNAME_LEN);
+		dev->rtd.device_sub_class = dev->gpio->subclass;
+		dev->rtd.proc_name = dev->gpio->name;
+		if(rtdm_dev_register(&dev->rtd)){
+			printk("couldn't register rtgpio device %s\n",dev->rtd.device_name);	
+			kfree(dev);
+			return -1;
+		}
+	return 	0;	
+}
+
+
diff -Naur linux-2.6.25.maxim/drivers/misc/classes/rtdm/Makefile linux-2.6.25.at91-20080908/drivers/misc/classes/rtdm/Makefile
--- linux-2.6.25.maxim/drivers/misc/classes/rtdm/Makefile	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/drivers/misc/classes/rtdm/Makefile	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,8 @@
+#
+# Makefile for the misc classes
+#
+
+EXTRA_CFLAGS += -D__IN_XENOMAI__ -Iinclude/xenomai 
+obj-$(CONFIG_GPIOCLASS_RTDM)	+= gpio_rtdm.o
+obj-$(CONFIG_PWMCLASS_RTDM)		+= pwm_rtdm.o
+
diff -Naur linux-2.6.25.maxim/drivers/misc/classes/rtdm/pwm_rtdm.c linux-2.6.25.at91-20080908/drivers/misc/classes/rtdm/pwm_rtdm.c
--- linux-2.6.25.maxim/drivers/misc/classes/rtdm/pwm_rtdm.c	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/drivers/misc/classes/rtdm/pwm_rtdm.c	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,95 @@
+/**
+ * A rtdm interface for pwm classes
+ */
+
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/class/pwm.h>
+#include <linux/class/pwm.h>
+#include <linux/class/rtdm/pwm_rtdm.h>
+#include <rtdm/rtdm_driver.h>
+
+typedef struct rtpwm_device_s {
+struct rtdm_device rtd;
+pwm_t *pwm;//pointer to parent pwm structure.
+}rtpwm_device_t; 
+
+static int rt_pwm_open(struct rtdm_dev_context *context,
+                  rtdm_user_info_t *user_info, int oflags){
+    return 0;
+}
+
+static int rt_pwm_close(struct rtdm_dev_context *context,
+                   rtdm_user_info_t *user_info){
+return 0;
+}
+
+static int rt_pwm_ioctl(struct rtdm_dev_context *context,
+                   rtdm_user_info_t *user_info, int request, void *umem){
+    rtpwm_device_t *dev = container_of(context->device,rtpwm_device_t,rtd);
+    pwm_t *pwm = dev->pwm;
+       
+    pwm_data kmem[1];
+             
+	switch(request){
+	case PERIODUSREAD:
+	if(pwm->periodus_read) kmem[0] = atomic_pwm_periodus_read(pwm);
+	else return -2;
+	return rtdm_safe_copy_to_user (user_info, umem, kmem, sizeof(pwm_data));		
+	
+	case PERIODUSWRITE:
+	rtdm_safe_copy_from_user (user_info, kmem, umem, sizeof(pwm_data));	
+	if(pwm->periodus_write) atomic_pwm_periodus_write(pwm,kmem[0]);
+	else return -2;
+	return 0;
+	
+	case WIDTHUSREAD:
+	if(pwm->widthus_read)kmem[0] = atomic_pwm_widthus_read(pwm);
+	else return -2;
+	return rtdm_safe_copy_to_user (user_info, umem, kmem, sizeof(pwm_data));
+	
+	case WIDTHUSWRITE:
+	rtdm_safe_copy_from_user (user_info, kmem, umem, sizeof(pwm_data));	
+	if(pwm->widthus_write)atomic_pwm_widthus_write(pwm,kmem[0]);	
+	else return -2;
+	return 0;
+	}             
+                   	                 	
+return -1;//no such op, need to find the right op code for this.
+}
+
+
+static const struct rtdm_device __initdata device_tmpl = {
+    struct_version:     RTDM_DEVICE_STRUCT_VER,
+
+    device_flags:       RTDM_NAMED_DEVICE | RTDM_EXCLUSIVE,
+    device_name:        "",
+    open_rt:            rt_pwm_open,
+    ops: {
+        close_rt:      	rt_pwm_close,
+        ioctl_rt:       rt_pwm_ioctl,
+    },
+    device_class:       RTDM_CLASS_PWM,
+    driver_name:        "pwm_rtd",
+    driver_version:     RTDM_DRIVER_VER(1, 0, 0),
+    peripheral_name:    "pwm",
+    provider_name:      "EMAC.Inc",
+};
+
+
+int rt_pwm_device_create(struct pwm_s *pwm){
+		rtpwm_device_t *dev = kmalloc(sizeof(rtpwm_device_t),GFP_KERNEL);
+		dev->pwm = pwm;
+		memcpy(&dev->rtd, &device_tmpl, sizeof(struct rtdm_device));
+		strncpy(dev->rtd.device_name, dev->pwm->name, RTDM_MAX_DEVNAME_LEN);
+		dev->rtd.device_sub_class = dev->pwm->subclass;
+		dev->rtd.proc_name = dev->pwm->name;
+		if(rtdm_dev_register(&dev->rtd)){
+			printk("couldn't register rtpwm device %s\n",dev->rtd.device_name);	
+			kfree(dev);
+			return -1;
+		}
+	return 	0;	
+}
+
+
diff -Naur linux-2.6.25.maxim/drivers/misc/classes/spi.c linux-2.6.25.at91-20080908/drivers/misc/classes/spi.c
--- linux-2.6.25.maxim/drivers/misc/classes/spi.c	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/drivers/misc/classes/spi.c	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,211 @@
+/**
+ * A class for simple gpio ports
+ * Several types of general purpose devices are available 
+ * which all export the same basic functionity 
+ * through different underlying methods
+ * This class can also be used to export simple interfaces
+ * to an 8 bit port into user space
+ */
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/ctype.h>
+#include <linux/kdev_t.h>
+#include <linux/chelper.h>
+#include <linux/class/spi.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_SPICLASS_RTDM
+#include <rtdm/rtdm_driver.h>
+#include <linux/class/rtdm/spi_rtdm.h>
+#define ATOMIC(a) RTDM_EXECUTE_ATOMICALLY(a)
+#else
+#define ATOMIC(a) a
+#endif //CONFIG_GPIOCLASS_RTDM
+
+#ifdef CONFIG_SPICLASS_CHAR
+#include <linux/class/char/spi_char.h>
+#endif
+
+/************************************************************
+ * the global device class
+ */
+static struct class *spiclass = NULL;
+
+struct class *spi_declare(void){
+	if(!spiclass){
+		printk("registering GPIO class\n");
+		spiclass=class_create(THIS_MODULE,"spi");
+#ifdef CONFIG_SPICLASS_CHAR
+		spi_char_init();
+#endif
+	}
+	return spiclass;
+}
+
+/***************************************************************************
+ * Atomic method wrappers
+ */
+int atomic_spi_tip(struct spi_s *s,int ofs){
+	spi_data retval;
+	ATOMIC(retval = s->tip(s,ofs);)
+	return retval;
+}
+
+int atomic_spi_xmit(struct spi_s *s,u8 *mosi, u8 *miso, int size){
+	ATOMIC(s->xmit(s,mosi, miso, size);)
+	return 0;
+}
+
+int atomic_spi_tip_write(struct spi_s *s,spi_control config){
+	ATOMIC(s->tip(s,(config>0));)
+	return 0;
+}
+
+spi_control atomic_spi_tip_read(struct spi_s *s){
+	spi_data retval;
+	ATOMIC(retval = s->tip(s,TIPSTATUS);)
+	return (retval>0);
+}
+
+int atomic_spi_conf_write(struct spi_s *s,spi_control config){
+	ATOMIC(s->confwrite(s, config);)
+	return 0;
+}
+
+spi_control atomic_spi_conf_read(struct spi_s *s){
+	spi_control retval;
+	ATOMIC(retval = s->confread(s);)
+	return retval;
+}
+
+int atomic_spi_speed_write(struct spi_s *s,spi_control speed){
+	ATOMIC(s->speedwrite(s, speed);)
+	return 0;
+}
+
+spi_control atomic_spi_speed_read(struct spi_s *s){
+	spi_control retval;
+	ATOMIC(retval = s->speedread(s);)
+	return retval;
+}
+
+
+/***************************************************************************
+ * gpio sysfs operations
+ */
+#ifdef CONFIG_SPICLASS_SYSFS
+#define SPIXMITDELIM ","
+
+static ssize_t spi_xmit_store(struct class_device *cls, const char *buf,size_t count){
+	spi_t *s = cls->class_data;
+	size_t size;	
+	//atomic_spi_tip(s,TIPON);
+	if(s->buf){kfree(s->buf);s->bsize=0;} /* this is not safe unless buf is set to NULL on init */
+	//worst case allocation, char-delim-char-delim = count/2 * 4 bytes per word
+	s->buf = kmalloc(count*2, GFP_KERNEL);
+	s->bsize = sfs_getstream(buf,count,&size,SPIXMITDELIM,s->buf);
+	{
+	int i;
+	printk("%s-data: ",__FUNCTION__);
+	for(i=0;i<s->bsize;i++)printk("0x%x ",s->buf[i]);
+	printk("\n");
+	}
+	atomic_spi_xmit(s,s->buf, s->buf, s->bsize);
+	//atomic_spi_tip(s,TIPOFF);
+
+	return size;
+}
+
+static ssize_t spi_xmit_show(struct class_device *cls, char *buf){
+	spi_t *s = cls->class_data;
+	int chars=0;
+	int i;
+	
+	for(i=0;i<s->bsize;i++){
+		if(chars>=(PAGE_SIZE-10)){
+			chars+=sprintf(&buf[chars],"...OVF");
+			return chars;
+		}
+		if(i)chars+=sprintf(&buf[chars],SPIXMITDELIM);
+		chars+=sprintf(&buf[chars],"%x",s->buf[i]);
+	}
+	chars+=sprintf(&buf[chars],"\n");
+	return chars;
+}
+
+static ssize_t spi_flags_store(struct class_device *cls, const char *buf,size_t count){
+	size_t size;
+	spi_t *s = cls->class_data;
+	spi_control data = sfs_getint(buf,count,&size);
+	atomic_spi_conf_write(s, data);
+	return size;
+}
+
+static ssize_t spi_flags_show(struct class_device *cls, char *buf){
+	spi_t *s = cls->class_data;
+	return sprintf(buf,"%x\r\n",atomic_spi_conf_read(s));
+}	
+
+static ssize_t spi_speed_store(struct class_device *cls, const char *buf,size_t count){
+	size_t size;
+	spi_t *s = cls->class_data;
+	spi_control data = sfs_getint(buf,count,&size);
+	atomic_spi_speed_write(s, data);
+	return size;
+}
+
+static ssize_t spi_speed_show(struct class_device *cls, char *buf){
+	spi_t *s = cls->class_data;
+	return sprintf(buf,"%d\r\n",atomic_spi_speed_read(s));
+}	
+
+static ssize_t spi_tip_store(struct class_device *cls, const char *buf,size_t count){
+	size_t size;
+	spi_t *s = cls->class_data;
+	spi_data data = sfs_getint(buf,count,&size);
+	atomic_spi_tip_write(s,data);
+	return size;
+}
+
+static ssize_t spi_tip_show(struct class_device *cls, char *buf){
+	spi_t *s = cls->class_data;
+	return sprintf(buf,"%x\r\n",(atomic_spi_tip_read(s)));
+}
+
+static CLASS_DEVICE_ATTR(xmit,S_IRUGO|S_IWUGO,spi_xmit_show,spi_xmit_store);
+static CLASS_DEVICE_ATTR(tip,S_IRUGO|S_IWUGO,spi_tip_show,spi_tip_store);
+static CLASS_DEVICE_ATTR(speed,S_IRUGO|S_IWUGO,spi_speed_show,spi_speed_store);
+static CLASS_DEVICE_ATTR(conf,S_IRUGO|S_IWUGO,spi_flags_show,spi_flags_store);
+#endif //CONFIG_SPICLASS_SYSFS
+/***************************************************************************
+* class instantiation
+*/
+struct class_device *spi_register_class_device(spi_t *s){		
+struct class *spi_master = spi_declare();
+struct class_device *dev;	
+dev_t devnum = MKDEV(0, 0);
+
+#ifdef CONFIG_SPICLASS_CHAR
+devnum = spi_char_create(s);
+#endif	
+	
+dev = class_device_create(spi_master, NULL, devnum, NULL, s->name);
+dev->class_data = s;
+
+s->bsize = 0;
+s->buf = NULL;
+
+#ifdef CONFIG_SPICLASS_SYSFS
+	if(s->xmit)class_device_create_file(dev,&class_device_attr_xmit);
+	if(s->tip)class_device_create_file(dev,&class_device_attr_tip);
+	if((s->speedwrite)&&(s->speedread))class_device_create_file(dev,&class_device_attr_speed);
+	if((s->confwrite)&&(s->confread))class_device_create_file(dev,&class_device_attr_conf);
+	#endif	 
+
+#ifdef CONFIG_SPICLASS_RTDM
+	rt_spi_device_create(s);
+#endif
+
+return dev;			
+}
diff -Naur linux-2.6.25.maxim/drivers/misc/classes/spi_interface.c linux-2.6.25.at91-20080908/drivers/misc/classes/spi_interface.c
--- linux-2.6.25.maxim/drivers/misc/classes/spi_interface.c	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/drivers/misc/classes/spi_interface.c	2008-07-25 11:34:54.000000000 -0500
@@ -0,0 +1,259 @@
+#include <linux/class/spi_interface.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/spi/spi.h>
+
+/**
+ * Provides an interface betwee the Linux SPI interface and the
+ * EMAC SPI class (lsi2esc).
+ * 
+ * Copyright (C) 2007, EMAC Inc
+ */
+
+//#define DEBUG_LSI
+
+#ifdef DEBUG_LSI
+#define DPRINTK(string, args...) printk("lsi2esc: " string, ##args)
+#else
+#define DPRINTK(string, args...)
+#endif
+
+
+/**
+ * function to set/clear a transfer-in-progrees for
+ * the given device. This function should be implemented
+ * by the driver itself to make sure that the same device
+ * is being accessed and as such this function does nothing
+ */
+int lsi2esc_spi_tip(struct spi_s *s, int ofs)
+{
+    DPRINTK("lsi2esc_spi_tip\n");
+    return 0;
+}
+
+/**
+ * function to transfer data on the SPI bus
+ * Data is written/read using an spi_sync call which causes
+ * the chip select to remain active throughout the entire transfer
+ * but also requires that the available size of the buffers is the
+ * sum of the write data plus the read data. i.e. to write an 8 bit
+ * command and read a 8 bit response the response would be stored in
+ * the last 8 bits of a 16 bit miso, the data to be written would need
+ * to be placed in the top 8 bits of a 16 bit mosi.
+ * Assumptions: MOSI and MISO can be the same buffer,
+ * if MOSI is NULL 0xFF is transmitted, if MISO is NULL
+ * received data is discarded, there is no limit on buffer
+ * size but both buffers must be the same size if they both exist.
+ * 
+ * @param s the EMAC SPI class device to tranfer data on
+ * @param mosi the transmit buffer (master->slave)
+ * @param miso the receive buffer (slave->master)
+ * @param size the size of the data to transfer
+ * @return 0 or negative error code
+ */ 
+int lsi2esc_spi_xmit(struct spi_s *s, u8 *mosi, u8 *miso, int size)
+{
+    int result = 0;
+    u8 *local_mosi = mosi;
+    u8 *local_miso = miso;
+    struct spi_message msg;
+    struct spi_transfer msg_xfer =
+    {
+        .cs_change  = 0, /* hold cs for entire transfer */
+    };
+  
+    DPRINTK("lsi2esc_spi_xmit %d bytes\n", size);
+    
+    if (!local_mosi) {
+        if (!(local_mosi = kmalloc(size, GFP_KERNEL)))
+            return -ENOMEM;
+        memset(local_mosi, 0xFF, size);
+    }
+    if (!local_miso) {
+        /* data is discarded, but a buffer must exist */
+        if (!(local_miso = kmalloc(size, GFP_KERNEL)))
+            return -ENOMEM;
+    }
+#ifdef DEBUG_LSI
+    int temp_size;
+    for(temp_size = size; temp_size > 0; temp_size--) {
+        DPRINTK("mosi[%d] = 0x%X\n", temp_size-1, mosi ? mosi[temp_size-1] : 0);
+    }
+#endif
+    spi_message_init(&msg);
+    msg_xfer.tx_buf = local_mosi;
+    msg_xfer.rx_buf = local_miso;
+    msg_xfer.len = size;
+    spi_message_add_tail(&msg_xfer, &msg);
+    
+    result = spi_sync(s->lsi, &msg);
+    
+#ifdef DEBUG_LSI
+    for(temp_size = size; temp_size > 0; temp_size--) {
+        DPRINTK("miso[%d] = 0x%X\n", temp_size-1, local_miso ? local_miso[temp_size-1] : 0);
+    }
+#endif
+
+    if (!mosi)
+        kfree(local_mosi);
+    if (!miso)
+        kfree(local_miso);
+
+    return result;    
+}
+
+/**
+ * function to read the current configuration settings
+ * @param s the EMAC SPI class device to read from
+ * @return the current configuration
+ */
+spi_control lsi2esc_spi_confread(struct spi_s *s)
+{
+    spi_control flags = 0;
+    DPRINTK("lsi2esc_spi_confread\n");
+
+    flags = s->lsi->mode; /* SPI and SPICL same here */
+
+    DPRINTK("bits_per_word = %d\n", s->lsi->bits_per_word);
+    if (s->lsi->bits_per_word == 8)
+        flags |= SPICL_EIGHTBIT; /* actually does nothing */
+    else if (s->lsi->bits_per_word == 10)
+        flags |= SPICL_TENBIT;
+    else if (s->lsi->bits_per_word == 12)
+        flags |= SPICL_TWELVEBIT;
+    else if (s->lsi->bits_per_word == 16)
+        flags |= SPICL_SIXTEENBIT;
+    
+    return flags;
+}
+
+/**
+ * function to change the current configuration settings
+ * @param s the EMAC SPI class device to configure
+ * @param config the new configuration to write
+ * @return 0 or the result of spi_setup
+ */
+int lsi2esc_spi_confwrite(struct spi_s *s, spi_control config)
+{
+    DPRINTK("lsi2esc_spi_confwrite: %d\n", config);
+    
+    /* set the mode */
+    s->lsi->mode = 0;
+    if (config & SPI_CPOL)
+        s->lsi->mode |= SPI_CPOL;
+    if (config & SPI_CPHA)
+        s->lsi->mode |= SPI_CPHA;
+    
+    /* explicitly set the bits per word if specified
+     * otherwise leave unchanged */
+    if (config & SPICL_EIGHTBIT)
+        s->lsi->bits_per_word = 8;
+    else if (config & SPICL_TENBIT)
+        s->lsi->bits_per_word = 10;
+    else if (config & SPICL_TWELVEBIT)
+        s->lsi->bits_per_word = 12;
+    else if (config & SPICL_SIXTEENBIT)
+        s->lsi->bits_per_word = 16;
+    
+    return spi_setup(s->lsi);
+}
+
+/**
+ * function to get the current speed settings
+ * @param s the EMAC SPI class device
+ * @return the speed setting of the associated spi_device
+ */
+spi_control lsi2esc_spi_speedread(struct spi_s *s)
+{
+    DPRINTK("lsi2esc_spi_speedread\n");
+    return s->lsi->max_speed_hz;    
+}
+
+/**
+ * function to change the speed settings
+ * @param s the EMAC SPI class device
+ * @param speed the new speed to set
+ */
+int lsi2esc_spi_speedwrite(struct spi_s *s, spi_control speed)
+{
+    DPRINTK("lsi2esc_spi_speedwrite\n");
+    s->lsi->max_speed_hz = speed;
+    /* error checking and adjustment must be provided by
+     * the SPI controller driver to use this directly */
+    return spi_setup(s->lsi);
+}
+
+/******************************************************************************/
+
+/**
+ * The lsi2esc interface actually acts like an SPI protocol driver.
+ * It fakes as an SPI device, but performs generic access to SPI
+ * only through the EMAC class interface rather than device specific
+ * access. The following section provides the SPI protocol driver
+ * code.
+ */
+
+/**
+ * probe function to initialize the interface
+ */
+
+static int __devinit lsi2esc_probe(struct spi_device *spi)
+{
+    struct spi_s *esc;
+    /* the platform data of dev must be set to the spi_t in
+     * the board specific file */
+    /* kind of creates a loop... but thats OK */
+    esc = spi->dev.platform_data;
+    esc->lsi = spi;
+
+    if (!esc)
+        return -ENODEV;
+    if (!spi_register_class_device(esc))
+        return -ENOMEM;
+
+    return 0;    
+}
+
+/**
+ * remove function to provide a clean exit
+ */
+
+static int __devexit lsi2esc_remove(struct spi_device *spi)
+{
+    /* nothing to do here */
+    return 0;
+}
+
+static struct spi_driver lsi2esc_driver = {
+    .driver = {
+        .name   = "lsi2esc",
+        .bus    = &spi_bus_type,
+        .owner  = THIS_MODULE,
+    },
+    .probe  = lsi2esc_probe,
+    .remove = __devexit_p(lsi2esc_remove),
+};
+
+static __init int lsi2esc_init(void)
+{
+    DPRINTK("Registering LSI2ESC SPI driver\n");
+    return spi_register_driver(&lsi2esc_driver);
+}
+
+static __exit void lsi2esc_exit(void)
+{
+    spi_unregister_driver(&lsi2esc_driver);
+}
+
+module_init(lsi2esc_init);
+module_exit(lsi2esc_exit);
+
+MODULE_AUTHOR("EMAC.Inc (support@emacinc.com)");
+MODULE_DESCRIPTION("Generic EMAC SPI class to Linux SPI Interface Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+// EOF
diff -Naur linux-2.6.25.maxim/drivers/misc/Kconfig linux-2.6.25.at91-20080908/drivers/misc/Kconfig
--- linux-2.6.25.maxim/drivers/misc/Kconfig	2008-04-16 21:49:44.000000000 -0500
+++ linux-2.6.25.at91-20080908/drivers/misc/Kconfig	2008-07-24 11:43:16.000000000 -0500
@@ -327,4 +327,6 @@
 	  driver (SCSI/ATA) which supports enclosures
 	  or a SCSI enclosure device (SES) to use these services.
 
+source "drivers/misc/classes/Kconfig"
+
 endif # MISC_DEVICES
diff -Naur linux-2.6.25.maxim/drivers/misc/Makefile linux-2.6.25.at91-20080908/drivers/misc/Makefile
--- linux-2.6.25.maxim/drivers/misc/Makefile	2008-04-16 21:49:44.000000000 -0500
+++ linux-2.6.25.at91-20080908/drivers/misc/Makefile	2008-07-24 11:43:16.000000000 -0500
@@ -22,3 +22,4 @@
 obj-$(CONFIG_EEPROM_93CX6)	+= eeprom_93cx6.o
 obj-$(CONFIG_INTEL_MENLOW)	+= intel_menlow.o
 obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
+obj-y				+= classes/
diff -Naur linux-2.6.25.maxim/include/linux/chelper.h linux-2.6.25.at91-20080908/include/linux/chelper.h
--- linux-2.6.25.maxim/include/linux/chelper.h	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/include/linux/chelper.h	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,71 @@
+#ifndef CHELPER_H_
+#define CHELPER_H_
+
+#include <asm/io.h>
+
+/************************************************************
+ * helper functions
+ */
+ 
+ static inline ssize_t sfs_getint(const char *buf,size_t count,size_t *size){
+ 	char *endp;
+	u32 data = simple_strtoul(buf,&endp,0);	
+	*size = (size_t)(endp - buf);
+	if (*endp && isspace(*endp))(*size)++;
+	if (*size != count)*size = -EINVAL;
+	return data;
+ }
+
+ /** 
+  * converts a stream of separated integers into an allocated array.
+  * returns the number of integers converted
+  * stores the number of characters converted to integers in size
+  */
+ static inline  int sfs_getstream(const char *buf,size_t count,size_t *size,const char *delim,u8 *data){
+	char *tokenstring = strcpy(kmalloc(count,GFP_KERNEL),buf);
+	char *mark = tokenstring;
+	char *endp;
+	char *token;
+	int index=0;
+	
+	//printk("%s - mark:%s\n",__FUNCTION__,mark);
+	
+	while((token=strsep(&mark, delim))!=NULL){
+		//printk("mark:%s\n",mark);
+		data[index++] = simple_strtoul(token,&endp,0);
+	}
+		
+	*size = (size_t)(endp - tokenstring);
+	if (*endp && isspace(*endp))(*size)++;
+	if (*size != count)*size = -EINVAL;
+	
+	//printk("size = %d\n",*size);
+	
+	kfree(tokenstring);
+	return index;
+ }
+ 
+ 
+/**
+ * depreciated
+ */
+static inline ssize_t store8(const char *buf,size_t count,void *address,u8 *shadow){
+	size_t size;
+	u8 data = sfs_getint(buf,count,&size);
+	if(address)iowrite8(data,address);
+	if(shadow)*shadow=data;
+	return size;
+}
+
+/**
+ * depreciated
+ */
+static inline ssize_t store16(const char *buf,size_t count,void *address,u16 *shadow){
+	size_t size;
+	u16 data = sfs_getint(buf,count,&size);
+	if(address)iowrite16(data,address);
+	if(shadow)*shadow=data;
+	return size;
+}
+
+#endif /*CHELPER_H_*/
diff -Naur linux-2.6.25.maxim/include/linux/class/char/gpio_char.h linux-2.6.25.at91-20080908/include/linux/class/char/gpio_char.h
--- linux-2.6.25.maxim/include/linux/class/char/gpio_char.h	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/include/linux/class/char/gpio_char.h	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,31 @@
+#ifndef GPIO_CHAR_H_
+#define GPIO_CHAR_H_
+
+#ifdef __KERNEL__
+int gpio_char_init(void);
+int gpio_char_create(struct gpio_s *gpio);
+
+#ifndef GPIO_MAJOR
+#define GPIO_MAJOR 0
+#endif
+
+/* we use the max_devs define to register a region on init */
+#define GPIO_MAX_DEVS 15
+#endif /*__KERNEL__*/
+
+/* This header defines the ioctl commands */
+#include <linux/class/rtdm/gpio_rtdm.h>
+
+#define CHAR_CLASS_GPIO RTDM_CLASS_GPIO
+/* the following are defined in gpio_rtdm.h */
+/*
+ * #define DDRREAD         _IOR(RTDM_CLASS_GPIO,0,char)
+ * #define DDRWRITE        _IOW(RTDM_CLASS_GPIO,0,char)
+ * #define DATAREAD        _IOR(RTDM_CLASS_GPIO,1,char)
+ * #define DATAWRITE       _IOW(RTDM_CLASS_GPIO,1,char)
+ // additions for the char driver
+ * #define INDEXREAD       _IOR(RTDM_CLASS_GPIO,2,char)
+ * #define INDEXWRITE      _IOW(RTDM_CLASS_GPIO,2,char)
+ */
+
+#endif /*GPIO_CHAR_H_*/
diff -Naur linux-2.6.25.maxim/include/linux/class/char/spi_char.h linux-2.6.25.at91-20080908/include/linux/class/char/spi_char.h
--- linux-2.6.25.maxim/include/linux/class/char/spi_char.h	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/include/linux/class/char/spi_char.h	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,27 @@
+#ifndef SPI_CHAR_H_
+#define SPI_CHAR_H_
+
+#ifdef __KERNEL__
+int spi_char_init(void);
+int spi_char_create(struct spi_s *spi);
+
+#ifndef SPI_MAJOR
+#define SPI_MAJOR 0
+#endif
+
+/* we use the max_devs define to register a region on init */
+#define SPI_MAX_DEVS 15
+#endif /*__KERNEL__*/
+
+typedef struct spi_transfer_s{
+	spi_data *mosi;
+	spi_data *miso;
+	ssize_t size;
+}spi_transfer_t;
+
+/* This header defines the ioctl commands */
+#include <linux/class/rtdm/spi_rtdm.h>
+
+#define CHAR_CLASS_SPI RTDM_CLASS_SPI
+
+#endif /*SPI_CHAR_H_*/
diff -Naur linux-2.6.25.maxim/include/linux/class/gpio.h linux-2.6.25.at91-20080908/include/linux/class/gpio.h
--- linux-2.6.25.maxim/include/linux/class/gpio.h	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/include/linux/class/gpio.h	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,198 @@
+#ifndef GPIO_H_
+#define GPIO_H_
+
+#include <linux/autoconf.h>
+#include <linux/device.h>
+
+#ifdef CONFIG_GPIOCLASS	
+
+typedef u32 gpio_data;
+
+/**********************
+ * gpio class structure
+ */
+typedef struct gpio_s{
+	const char *name;
+	int subclass;
+	gpio_data index;
+	gpio_data range;
+	void *ddr;
+	void *data;
+	gpio_data shadow;
+	gpio_data (*data_read)(struct gpio_s *gpio);
+	int (*data_write)(struct gpio_s *gpio,gpio_data data);
+	gpio_data (*ddr_read)(struct gpio_s *gpio);	
+	int (*ddr_write)(struct gpio_s *gpio,gpio_data data);
+	gpio_data (*index_read)(struct gpio_s *gpio);	
+	int (*index_write)(struct gpio_s *gpio,gpio_data data);
+}gpio_t;
+
+#define GPIO_BASECLASNUM	0xA0
+#define GPIO_SUBCLASS 	(GPIO_BASECLASNUM+0)
+#define GPI_SUBCLASS 	(GPIO_BASECLASNUM+1)
+#define GPO_SUBCLASS 	(GPIO_BASECLASNUM+2)
+
+/***************************************************************************
+ * typical low level methods for accessing 8 bit ports
+ */
+int  gpio_ddr_write8(gpio_t *gpio, gpio_data data);
+int  gpio_data_write8(gpio_t *gpio, gpio_data data);
+int  gpio_index_write(gpio_t *gpio, gpio_data data);
+int  gpio_empty_write(gpio_t *gpio, gpio_data data);
+gpio_data gpio_ddr_read8(gpio_t *gpio);
+gpio_data gpio_data_read8(gpio_t *gpio);
+gpio_data gpio_index_read(gpio_t *gpio);
+gpio_data gpio_shadow_read8(gpio_t *gpio);
+gpio_data gpio_ff_read(gpio_t *gpio);
+gpio_data gpio_zero_read(gpio_t *gpio);
+
+/***************************************************************************
+ * initial class declaration, doesn't hurt to call it mulitiple times,
+ * automatically checked during device instantiation 
+ */
+struct class *gpio_declare(void);
+
+/***************************************************************************
+* class instantiation
+*/
+struct class_device *gpio_register_class_device(gpio_t *gpio);
+
+
+/***************************************************************************
+ * atomic method wrappers
+ * these should be used for all method calls to maintain sychronization across the
+ * various interfaces
+ */
+int atomic_gpio_ddr_write(gpio_t *gpio,gpio_data data);
+gpio_data atomic_gpio_ddr_read(gpio_t *gpio);
+int atomic_gpio_data_write(gpio_t *gpio,gpio_data data);
+gpio_data atomic_gpio_data_read(gpio_t *gpio);
+int atomic_gpio_index_write(gpio_t *gpio,gpio_data data);
+gpio_data atomic_gpio_index_read(gpio_t *gpio);
+
+
+/************************************************************************************
+ * full gpio ports, 
+ * bit configurable gpio ports with a bidirectional data register
+ * if the data register or ddr are NULL their interfaces are not created.
+ */
+static inline struct class_device *gpio_device_create(void *data, void *ddr,const char *name){
+	gpio_t *gpio = kmalloc(sizeof(gpio_t),GFP_KERNEL);
+	memset(gpio,0,sizeof(gpio_t));
+	gpio->name = name;
+	gpio->subclass = GPIO_SUBCLASS;
+	gpio->ddr = ddr;
+	gpio->data = data;
+	gpio->shadow = 0;	
+	gpio->data_write = gpio_data_write8;
+    gpio->data_read = gpio_data_read8;
+    
+    if(ddr){
+    	gpio->ddr_write = gpio_ddr_write8;
+    	gpio->ddr_read = gpio_ddr_read8;
+	}
+	printk("registering gpio device: %s\n",name);
+    return gpio_register_class_device(gpio);
+}
+
+/* create a gpio_s struct and initialize for gpio port without registering it */
+
+static inline struct gpio_s *gpio_device_create_unregistered(void *data, void *ddr,const char *name){
+    gpio_t *gpio = kmalloc(sizeof(gpio_t),GFP_KERNEL);
+    memset(gpio,0,sizeof(gpio_t));
+    gpio->name = name;
+    gpio->subclass = GPIO_SUBCLASS;
+    gpio->ddr = ddr;
+    gpio->data = data;
+    gpio->shadow = 0;   
+    gpio->data_write = gpio_data_write8;
+    gpio->data_read = gpio_data_read8;
+    
+    if(ddr){
+        gpio->ddr_write = gpio_ddr_write8;
+        gpio->ddr_read = gpio_ddr_read8;
+    }
+    return gpio;
+}
+
+/************************************************************************************
+ * shadow gpo ports, 
+ * these ports are write only and have no register to read back the current state
+ * a shadow port is therefore created to keep track of the current state in software.
+ * this is not as complete an implementation from a hardware standpoint as a user can only
+ * see the hardware changes if a rogue process if it "plays fair" and modifies the shadow register.
+ * It is, however, much cheaper from a gate implementation standpoint and probably just fine for
+ * most applications.
+ */
+ 
+static inline struct class_device *gpo_device_create(void *data,const char *name){
+	gpio_t *gpio = kmalloc(sizeof(gpio_t),GFP_KERNEL);
+	memset(gpio,0,sizeof(gpio_t));
+	gpio->name = name;
+	gpio->subclass = GPO_SUBCLASS;
+	gpio->data = data;
+	gpio->shadow = 0;
+	gpio->data_write = gpio_data_write8;
+    gpio->data_read = gpio_shadow_read8;
+    gpio->ddr_write = gpio_empty_write;
+    gpio->ddr_read = gpio_ff_read;
+    printk("registering gpo device: %s\n",name);
+    return gpio_register_class_device(gpio);
+}
+
+static inline struct gpio_s *gpo_device_create_unregistered(void *data, const char *name)
+{
+    gpio_t *gpio = kmalloc(sizeof(gpio_t),GFP_KERNEL);
+    memset(gpio,0,sizeof(gpio_t));
+    gpio->name = name;
+    gpio->subclass = GPO_SUBCLASS;
+    gpio->data = data;
+    gpio->shadow = 0;
+    gpio->data_write = gpio_data_write8;
+    gpio->data_read = gpio_shadow_read8;
+    gpio->ddr_write = gpio_empty_write;
+    gpio->ddr_read = gpio_ff_read;
+    return gpio;
+}
+
+
+/************************************************************************************
+ * gpi ports, gpi ports are functionally the same as gpio input only ports,
+ * but their ddr ports are not implemented in hardware 
+ * and are assumed based upon the PLD key. 
+ * This is a cheaper gate implementation. 
+ */
+static inline struct class_device *gpi_device_create(void *data,const char *name){
+	gpio_t *gpio = kmalloc(sizeof(gpio_t),GFP_KERNEL);
+	memset(gpio,0,sizeof(gpio_t));
+	gpio->name = name;
+	gpio->subclass = GPI_SUBCLASS;
+	gpio->data = data;
+	gpio->shadow = 0;
+	gpio->data_write = gpio_empty_write;
+    gpio->data_read = gpio_data_read8;
+    gpio->ddr_write = gpio_empty_write;
+    gpio->ddr_read = gpio_zero_read;
+    printk("registering gpi device: %s\n",name);
+    return gpio_register_class_device(gpio);
+}
+
+/* create a gpio_s struct and initialize for gpi port without registering it */
+
+static inline struct gpio_s *gpi_device_create_unregistered(void *data,const char *name){
+    gpio_t *gpio = kmalloc(sizeof(gpio_t),GFP_KERNEL);
+    memset(gpio,0,sizeof(gpio_t));
+    gpio->name = name;
+    gpio->subclass = GPI_SUBCLASS;
+    gpio->data = data;
+    gpio->shadow = 0;
+    gpio->data_write = gpio_empty_write;
+    gpio->data_read = gpio_data_read8;
+    gpio->ddr_write = gpio_empty_write;
+    gpio->ddr_read = gpio_zero_read;
+    return gpio;
+}   
+
+#endif
+
+#endif /*GPIO_H_*/
diff -Naur linux-2.6.25.maxim/include/linux/class/mmcblock.h linux-2.6.25.at91-20080908/include/linux/class/mmcblock.h
--- linux-2.6.25.maxim/include/linux/class/mmcblock.h	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/include/linux/class/mmcblock.h	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,19 @@
+#ifndef MMCBLOCK_H_
+#define MMCBLOCK_H_
+
+//#define MMCB_DEBUG 
+ 
+#undef MMCBDEBUG
+#ifdef MMCB_DEBUG
+	#define MMCBDEBUG(x...)  {printk("%s(): %d ",__PRETTY_FUNCTION__, __LINE__);printk(x);}
+#else
+	#define MMCBDEBUG(x...)	do { } while (0)
+#endif 
+
+int mmc_bdriver_init(void);
+void mmc_bdriver_exit(void);
+int mmc_diskize(mmcslot_t *s);
+void checkmedia_start(mmcslot_t *s);
+void checkmedia_stop(mmcslot_t *s);
+
+#endif /*MMCBLOCK_H_*/
diff -Naur linux-2.6.25.maxim/include/linux/class/mmcprot.h linux-2.6.25.at91-20080908/include/linux/class/mmcprot.h
--- linux-2.6.25.maxim/include/linux/class/mmcprot.h	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/include/linux/class/mmcprot.h	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,388 @@
+#ifndef MMCPROT_H_
+#define MMCPROT_H_
+
+#include <linux/types.h>
+#include <linux/timer.h>
+
+#define INVALID		0
+#define VALID		1
+#define CHANGED		2
+#define READY		4
+
+#define TRUE		1
+#define FALSE		(!TRUE)
+
+/**
+ * Debug statement defines
+ */
+ 
+//#define MMC_DEBUG 
+ 
+#undef MMCDEBUG
+#ifdef MMC_DEBUG
+#define MMCDEBUG(fmt, args...) printk(fmt"\n", ## args)
+#else 
+#define MMCDEBUG(fmt, args...) 
+#endif
+
+//packet defines
+#define MAX_RESPONSE 5
+#define CRC_LENGTH  2	
+#define START_TOKEN_LENGTH 1
+#define BR_STOP_TOKEN 0xFD
+#define DATA_RESPONSE_LENGTH  1
+#define MAX_NWR 8
+#define COMMAND_LENGTH  6
+#define Ncr_MAX  8
+		
+//command response defines		
+#define MMCCOM_IDLE  0x01
+#define MMCCOM_ERASE_RES  0x02
+#define MMCCOM_ILLEGAL  0x04
+#define MMCCOM_CRC  0x08
+#define MMCCOM_ERASE_SEQ  0x10
+#define MMCCOM_ADDRESS  0x20
+#define MMCCOM_PARAMETER  0x40
+
+//data responses
+#define MMCDAT_D_RESPONSE_MASK  0x1F
+#define MMCDAT_DATA_ACC  0x05
+#define MMCDAT_CRC_ERR 0x0B
+#define MMCDAT_WRITE_ERR 0x0D	
+
+typedef struct CSD_register{
+		int	SPEC_VERS;
+		int	TAAC;
+		int	NSAC;
+		int	TRAN_SPEED;
+		int	CCC;
+		int	READ_BL_LEN;
+		int	READ_BL_PARTIAL;
+		int	WRITE_BLK_MISALIGN;
+		int	READ_BLK_MISALIGN;
+		int	DSR_IMP;
+		int	C_SIZE;
+		int	VDD_R_CURR_MIN;
+		int	VDD_R_CURR_MAX;
+		int	VDD_W_CURR_MIN;
+		int	VDD_W_CURR_MAX;
+		int	C_SIZE_MULT;
+		int	ERASE_GRP_SIZE;
+		int	ERASE_GRP_MULT;
+		int	WP_GRP_SIZE;
+		int	WP_GRP_ENABLE;
+		int	DEFAULT_ECC;
+		int	R2W_FACTOR;
+		int	WRITE_BL_LEN;
+		int	WRITE_BL_PARTIAL;
+		int	FILE_FORMAT_GRP;
+		int	COPY;
+		int	PERM_WRITE_PROTECT;
+		int	TMP_WRITE_PROTECT;
+		int	FILE_FORMAT;
+		int	ECC;
+		int	CRC;	
+	}CSD_register;	
+
+typedef struct CID_register{
+		int Manufacturer_ID; 
+		int OEM_Application_ID; 
+		char Product_name[7]; 
+		int Product_revision;
+		long Product_serial_number; 
+		int Manufacturing_date; 			   							  		
+	}CID_register;
+
+typedef struct cardinfo_s {
+	unsigned int blocklength;
+	unsigned int sectors;
+	unsigned long size;
+	unsigned long speed;//maximum clock speed of the card
+	unsigned int media_detect;
+	CSD_register CSD;
+	CID_register CID;
+}cardinfo_t;
+
+#define MAXSLOTNUM 4
+
+enum MMCMETHODS {
+    MMCCD		= 0,
+	MMCWP,
+	MMCTP,
+	MMCEX,
+	MMCSS,
+};
+
+typedef struct mmcslot_s {
+	int slotnumber;
+	const char *name;
+	int users;
+	int state;
+	cardinfo_t card;
+	spinlock_t lock;
+	struct gendisk *disk;
+	struct timer_list timer;
+	int (*carddetect)(struct mmcslot_s *s);
+	int (*writeprotect)(struct mmcslot_s *s);
+	int (*tip)(struct mmcslot_s *s,int onoff);//declare transfer in progress true/false (moves chip select, potentially turns off the clock)
+	int (*exchange)(struct mmcslot_s *s,u8 *mosi, u8 *miso, int size);//bidirectional transfer
+	int (*setspeed)(struct mmcslot_s *s,unsigned long speed);
+	void *pd[5];//individual private data pointers for methods
+}mmcslot_t;
+
+
+/**
+ * Prototypes for the core functions
+ */
+int mmcinit(mmcslot_t *s);
+mmcslot_t *mmcgetslot(int i);
+int mmcreleaseslot(mmcslot_t *s);
+int mmctransaction(mmcslot_t *s, int command, int arg1, int arg2,int blocking,int response);
+int mmcblockread(mmcslot_t *s, int command, int arg1, int arg2,int response, u8 *data,int blocksize, int blocknum,int Nac);
+int mmcblockwrite(mmcslot_t *s,int command, int arg1, int arg2, int response, u8 *data, int blocksize, int blocknum,int Nwr);
+
+#define CARDREGTOP 15
+
+static inline int parse_CSD(CSD_register *reg, u8 *CSD){
+		reg->SPEC_VERS= (CSD[CARDREGTOP-15]&0x3C)>>2;
+		reg->TAAC= CSD[CARDREGTOP-14];
+		reg->NSAC= CSD[CARDREGTOP-13];
+		reg->TRAN_SPEED= CSD[CARDREGTOP-12];
+		reg->CCC= ((CSD[CARDREGTOP-11])<<4)|((CSD[CARDREGTOP-10]&0xf0)>>4);
+		reg->READ_BL_LEN= (CSD[CARDREGTOP-10]&0x0f);
+		reg->READ_BL_PARTIAL= (CSD[CARDREGTOP-9]&0x80>>7);
+		reg->WRITE_BLK_MISALIGN= (CSD[CARDREGTOP-9]&0x40>>6);
+		reg->READ_BLK_MISALIGN= (CSD[CARDREGTOP-9]&0x20>>5);
+		reg->DSR_IMP= (CSD[CARDREGTOP-9]&0x10>>4);
+		reg->C_SIZE= ((CSD[CARDREGTOP-9]&0x03)<<10)|(CSD[CARDREGTOP-8]<<2)|((CSD[CARDREGTOP-7]&0xC0)>>6);		
+		reg->VDD_R_CURR_MIN= (CSD[CARDREGTOP-7]&0x38)>>3;
+		reg->VDD_R_CURR_MAX= (CSD[CARDREGTOP-7]&0x07);
+		reg->VDD_W_CURR_MIN= (CSD[CARDREGTOP-6]&0xE0)>>5;
+		reg->VDD_W_CURR_MAX= (CSD[CARDREGTOP-6]&0x1C)>>2;
+		reg->C_SIZE_MULT= ((CSD[CARDREGTOP-6]&0x03)<<1)|((CSD[CARDREGTOP-5]&0x80)>>7);
+		reg->ERASE_GRP_SIZE= (CSD[CARDREGTOP-5]&0x7c)>>2;
+		reg->ERASE_GRP_MULT= ((CSD[CARDREGTOP-5]&0x03)<<3)|((CSD[CARDREGTOP-4]&0xe0)>>5);
+		reg->WP_GRP_SIZE= (CSD[CARDREGTOP-4]&0x1f);
+		reg->WP_GRP_ENABLE= (CSD[CARDREGTOP-3]&0x80)>>7;;
+		reg->DEFAULT_ECC= (CSD[CARDREGTOP-3]&0x60)>>5;
+		reg->R2W_FACTOR= (CSD[CARDREGTOP-3]&0x8c)>>2;
+		reg->WRITE_BL_LEN= ((CSD[CARDREGTOP-3]&0x03)<<2)|((CSD[CARDREGTOP-2]&0xc0)>>6);
+		reg->WRITE_BL_PARTIAL= (CSD[CARDREGTOP-2]&0x20)>>5;
+		reg->FILE_FORMAT_GRP= (CSD[CARDREGTOP-1]&0x80)>>7;
+		reg->COPY= (CSD[CARDREGTOP-1]&0x40)>>6;
+		reg->PERM_WRITE_PROTECT= (CSD[CARDREGTOP-1]&0x20)>>5;
+		reg->TMP_WRITE_PROTECT= (CSD[CARDREGTOP-1]&0x10)>>4;
+		reg->FILE_FORMAT= (CSD[CARDREGTOP-1]&0x0C)>>2 ;
+		reg->ECC= CSD[CARDREGTOP-1]&0x03;
+		reg->CRC= CSD[CARDREGTOP-0]&0xfe;	
+		return 0;
+	}
+
+
+static inline int parse_CID(CID_register *reg,u8 *CSD){
+		reg->Manufacturer_ID = CSD[CARDREGTOP-15]; 
+		reg->OEM_Application_ID = (CSD[CARDREGTOP-14]<<8)|(CSD[CARDREGTOP-13]); 		
+		reg->Product_name[5] = CSD[CARDREGTOP-7]; 
+		reg->Product_name[4] = CSD[CARDREGTOP-8]; 
+		reg->Product_name[3] = CSD[CARDREGTOP-9]; 
+		reg->Product_name[2] = CSD[CARDREGTOP-10]; 
+		reg->Product_name[1] = CSD[CARDREGTOP-11];
+		reg->Product_name[0] = CSD[CARDREGTOP-12];
+		reg->Product_name[6] = 0;//NULL termination for string manipulation
+		reg->Product_revision = CSD[CARDREGTOP-6];
+		reg->Product_serial_number = ((long)CSD[CARDREGTOP-5]<<24)|(((long)CSD[CARDREGTOP-4]<<16)&
+			0xff0000)|(((long)CSD[CARDREGTOP-3]<<8)&0xff00)|(((long)CSD[CARDREGTOP-2])&0xff); 
+		reg->Manufacturing_date = CSD[CARDREGTOP-1]; 
+		return 0;
+	}
+
+
+/**
+ * MMC Commands
+ * -----------------------------------------------------------------------------
+ */
+
+/**
+ * resets the MultiMedia card
+ */
+#define GO_IDLE_STATE(dev)	mmctransaction(dev,0,0,0,0,1)												
+/**
+ * activates the card's initialization process
+ * @return command response
+ */
+#define	SEND_OP_COND(dev)	mmctransaction(dev,1,0,0,0,1)
+/**
+ * Asks the selected card to send its cardspecific data (CSD)
+ * @param data a 16 bit array to store the CSD register in
+ * @return the command response
+ */
+#define SEND_CSD(dev,data)  mmcblockread(dev,9,0,0,1,data,16,1,8 )
+/**
+ * asks the selected card to send its card identification (CID)
+ * @param data data a 16 bit array to store the CID register in
+ * @return
+ */
+#define SEND_CID(dev,data)  mmcblockread(dev,10,0,0,1,data,16,1, 8)
+/**
+ * Stop transmission on multiple block read 
+ * automatically called by the READ_MULTIPLE_BLOCK function
+ * @return command response
+ */
+#define STOP_TRANSMISSION(dev) mmctransaction(dev,12,0,0,0,1)
+/**
+ * Asks the selected card to send its status register
+ * This is an untested command 
+ * @return command response(in this case status)
+ */
+#define SEND_STATUS(dev) mmctransaction(dev,13,0,0,0,2)
+/**
+ * selects a block length (in bytes) for all following 
+ * block operations (read and write)1
+ * this is an untested command
+ * @param arg1 top half of block length
+ * @param arg2 bottom half of block length
+ * @return command response
+ */
+#define SET_BLOCKLEN(dev,arg1,arg2) mmctransaction(dev,16,arg1,arg2,0,1)
+/**
+ * reads a block of the size selected by the SET_BLOCKLEN command2
+ * changing the block size outside of the default has not been tested
+ * @param address the byte address to start the read at(block aligned)
+ * @param data array to move the data into
+ * @param blocksize size of the blocks. If it hasn't been modified with SET_BLOCKLEN this will be BLOCKLEN
+ * @return 1
+ */
+#define READ_SINGLE_BLOCK(dev,address,data,blocksize) mmcblockread(dev,17,(int)(address>>16),(int)(address&0xffff),1, data,blocksize,1,8 )
+/**
+ * continuously transfers data blocks from card to host until interrupted by a 
+ * stop command or the requested number of data blocks transmitted
+ * Currently this command is implemented to automatically stop transmission after the 
+ * number of blocks specified by blocknum is read
+ * @param address starting block aligned byte address
+ * @param data array to transfer the data into linearly
+ * @param blocksize size of the blocks. If it hasn't been modified with 
+ * SET_BLOCKLEN this will be BLOCKLEN
+ * @param blocknum number of blocks to read
+ * @return the number of blocks read
+ */
+#define READ_MULTIPLE_BLOCK(dev,address,data,blocksize,blocknum) mmcblockread(dev,18,(int)(address>>16),(int)(address&0xffff),1,data,blocksize,blocknum,8)
+/**
+ * Defines the number of blocks which are going to be transferred in the immediately exceeding multiple block read or write command.
+ * this command is untested, and probably won't work with the current read/write
+ * implementation
+ * @param number of blocks
+ * @return command response
+ */
+#define SET_BLOCK_COUNT(dev,arg1) mmctransaction(dev,23,arg1,0,0,1)
+/**
+ * writes a block of the size selected by the SET_BLOCKLEN command
+ * if BLOCKLEN has not been set, then the default is used (read from the CSD)
+ * @param address starting block aligned byte address
+ * @param data linear data array to write
+ * @param blocksize size of the blocks. 
+ * @return 1
+ */
+#define	WRITE_BLOCK(dev,address,data,blocksize)	mmcblockwrite(dev,24,(int)(address>>16),(int)(address&0xffff),1,data,blocksize,1,1)
+/**
+ * continuously writes blocks of data until a "Stop Tran" Token or the requested number of blocks received.
+ * stop tran is automatically thrown by the method when the requested
+ * number of blocks has been written
+ * @param address address starting block aligned byte address
+ * @param data linear data array to write
+ * @param blocksize size of the blocks. If it hasn't been modified with SET_BLOCKLEN this will be BLOCKLEN
+ * @param blocknum number of blocks to write
+ * @return number of blocks written
+ */
+#define WRITE_MULTIPLE_BLOCK(dev,address, data, blocksize, blocknum) mmcblockwrite(dev,25,(int)(address>>16),(int)(address&0xffff),1,data,blocksize,blocknum,1)
+/**
+ * programming of the programmable bits of the CSD
+ * not currently supported
+ * probably a write_block method, but more research will
+ * be needed.
+ * @return command response
+ */
+#define PROGRAM_CSD(dev) mmctransaction(dev,27,0,0,0,1)
+/**
+ * if the card has write protection this command sets the write protection bit of the addressed group.
+ * The properties of write protection are coded in the card specific data (WP_GRP_SIZE).
+ * untested
+ * @param arg1 high address bits
+ * @param arg2 low address bits
+ * @return command response
+ */
+#define SET_WRITE_PROT(dev,arg1, arg2) mmctransaction(dev,28,arg1,arg2,0,1)
+/**
+ * if the card has write protection this command clears the write protection bit of the addressed group
+ * untested
+ * @param arg1 high address bits
+ * @param arg2 low address bits
+ * @return command response
+ */
+#define CLR_WRITE_PROT(dev,arg1, arg2) mmctransaction(dev,29,arg1,arg2,true,1)
+/**
+ * "if the card has write protection this command asks the card to send the status of the write protection bits 
+ * untested
+ * @param arg1 high address bits
+ * @param arg2 low address bits
+ * @return command response
+ */
+#define SEND_WRITE_PROT(dev,arg1, arg2) mmctransaction(dev,30,arg1,arg2,0,1)
+/**
+ * sets the address of the first erase group within a range to be selected for erase
+ * untested
+ * @param arg1 high address bits
+ * @param arg2 low address bits
+ * @return command response
+ */
+#define TAG_ERASE_GROUP_START(dev,arg1, arg2) mmctransaction(dev,35,arg1,arg2,0,1)
+/**
+ * erases all previously selected erase groups  
+ * untested
+ * @param arg1 high address bits
+ * @param arg2 low address bits
+ * @return command response
+ */
+#define	ERASE(dev,arg1,arg2) mmctransaction(dev,38,arg1,arg2,1,1)	
+/**
+ * used to Set/Reset the Password or lock/unlock the card. 
+ * The size of the Data Block is defined by the SET_BLOCK_LEN command.
+ * untested 
+ * @param arg1 high address bits
+ * @param arg2 low address bits
+ * @return command response
+ */
+#define	LOCK_UNLOCK(dev,arg1,arg2) mmctransaction(dev,42,arg1,arg2,1,1)
+/**
+ * defines to the card that the next command is an application specific command 
+ * rather than a standard command
+ * untested
+ * @param arg1 see data sheet
+ * @return command response
+ */
+#define	APP_CMD(dev,arg1) mmctransaction(dev,55,arg1,0,false,1)
+/**
+ * used either to transfer a data block to the card or to get a data block from 
+ * the card for general purpose / application specific commands. The size of the 
+ * data block is defined by the SET_BLOCK_LEN command.
+ * untested
+ * @param arg1 high address bits
+ * @param arg2 low address bits
+ * @return command response
+ */
+#define GEN_CMD(dev,arg1, arg2)	mmctransaction(dev,56,arg1,arg2,true,1)
+/**
+ * reads the OCR register of a card 
+ * untested as status bits are returned in the command response of all mmctransactions
+ * @return command response
+ */
+#define READ_OCR(dev) mmctransaction(dev,58,0,0,0,5)
+/**
+ * "turns the CRC option on or off. A ?1? in the CRC option bit will turn the option on, a ?0? will turn it off"
+ * CRC's are currently unsupported, turning on the CRC option will break all further mmctransaction until a reset
+ * @param arg1 see data sheet
+ * @param arg2 see data sheet
+ * @return command response
+ */
+#define CRC_ON_OFF(dev,arg1,arg2) mmctransaction(dev,59,arg1,arg2,0,1)
+
+#endif /*MMCPROT_H_*/
diff -Naur linux-2.6.25.maxim/include/linux/class/pwm.h linux-2.6.25.at91-20080908/include/linux/class/pwm.h
--- linux-2.6.25.maxim/include/linux/class/pwm.h	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/include/linux/class/pwm.h	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,69 @@
+#ifndef PWM_H_
+#define PWM_H_
+#include <linux/autoconf.h>
+#include <linux/device.h>
+
+
+#ifdef CONFIG_PWMCLASS
+
+//SUBCLASS assignment currently unused and arbitrary
+#define PWMD_SUBCLASS 77 
+
+typedef u32 pwm_data;
+
+/**********************
+ * pwm class structure
+ */
+typedef struct pwm_s{
+	const char *name;
+	int subclass;
+	void *widthus;
+	void *periodus;
+	void *control;
+	pwm_data widthus_shadow;
+	pwm_data periodus_shadow;
+	pwm_data (*widthus_read)(struct pwm_s *pwm);//width us
+	int (*widthus_write)(struct pwm_s *pwm,pwm_data data);
+	pwm_data (*periodus_read)(struct pwm_s *pwm);	//period us
+	int (*periodus_write)(struct pwm_s *pwm,pwm_data data);
+	pwm_data (*invert_read)(struct pwm_s *pwm);	//pulse inversion
+	int (*invert_write)(struct pwm_s *pwm,pwm_data data);
+	pwm_data (*read_pwmclock)(struct pwm_s *pwm);
+	int (*write_pwmclock)(struct pwm_s *pwm,pwm_data data);
+}pwm_t;
+
+
+struct class *pwm_declare(void);
+struct class_device *pwm_register_class_device(pwm_t *pwm);
+
+/***************************************************************************
+ * typical low level methods
+ */
+int  pwm_widthus_write8(pwm_t *pwm, pwm_data data);
+int  pwm_widthus_write16(pwm_t *pwm, pwm_data data);
+int  pwm_periodus_write8(pwm_t *pwm, pwm_data data);
+int  pwm_periodus_write16(pwm_t *pwm, pwm_data data);
+int  pwm_empty_write(pwm_t *pwm, pwm_data data);
+pwm_data pwm_widthus_read8(pwm_t *pwm);
+pwm_data pwm_widthus_read16(pwm_t *pwm);
+pwm_data pwm_periodus_read8(pwm_t *pwm);
+pwm_data pwm_periodus_read16(pwm_t *pwm);
+pwm_data pwm_ff_read(pwm_t *pwm);
+pwm_data pwm_zero_read(pwm_t *pwm);
+pwm_data pwm_widthusshadow_read(pwm_t *pwm);
+
+/***************************************************************************
+ * atomic method wrappers
+ * these should be used for all method calls to maintain sychronization across the
+ * various interfaces
+ */
+int atomic_pwm_widthus_write(pwm_t *pwm,pwm_data data);
+int atomic_pwm_periodus_write(pwm_t *pwm,pwm_data data);
+int atomic_pwm_invert_write(pwm_t *pwm,pwm_data data);
+pwm_data atomic_pwm_widthus_read(pwm_t *pwm);
+pwm_data atomic_pwm_periodus_read(pwm_t *pwm);
+pwm_data atomic_pwm_invert_read(pwm_t *pwm);
+
+#endif //CONFIG_PWMCLASS
+
+#endif /*PWM_H_*/
diff -Naur linux-2.6.25.maxim/include/linux/class/rtdm/gpio_rtdm.h linux-2.6.25.at91-20080908/include/linux/class/rtdm/gpio_rtdm.h
--- linux-2.6.25.maxim/include/linux/class/rtdm/gpio_rtdm.h	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/include/linux/class/rtdm/gpio_rtdm.h	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,21 @@
+#ifndef GPIO_RTDM_H_
+#define GPIO_RTDM_H_
+
+#include <linux/ioctl.h>
+
+//arbitrary assignment, come back to this later
+#define RTDM_CLASS_GPIO 0x80 
+
+#ifdef __KERNEL__	
+int rt_gpio_device_create(struct gpio_s *gpio);
+#endif//__KERNEL__
+
+#define DDRREAD			_IOR(RTDM_CLASS_GPIO,0,char)
+#define DDRWRITE 		_IOW(RTDM_CLASS_GPIO,0,char)
+#define DATAREAD		_IOR(RTDM_CLASS_GPIO,1,char)
+#define DATAWRITE 		_IOW(RTDM_CLASS_GPIO,1,char)
+/* additions for the char driver */
+#define INDEXREAD       _IOR(RTDM_CLASS_GPIO,2,char)
+#define INDEXWRITE      _IOW(RTDM_CLASS_GPIO,2,char)
+
+#endif //GPIO_RTDM_H_
diff -Naur linux-2.6.25.maxim/include/linux/class/rtdm/pwm_rtdm.h linux-2.6.25.at91-20080908/include/linux/class/rtdm/pwm_rtdm.h
--- linux-2.6.25.maxim/include/linux/class/rtdm/pwm_rtdm.h	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/include/linux/class/rtdm/pwm_rtdm.h	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,18 @@
+#ifndef PWM_RTDM_H_
+#define PWM_RTDM_H_
+
+#include <linux/ioctl.h>
+
+//arbitrary assignment, come back to this later
+#define RTDM_CLASS_PWM 0x90 
+
+#ifdef __KERNEL__	
+int rt_pwm_device_create(struct pwm_s *pwm);
+#endif//__KERNEL__
+
+#define PERIODUSREAD		_IOR(RTDM_CLASS_PWM,0,char)
+#define PERIODUSWRITE 		_IOW(RTDM_CLASS_PWM,0,char)
+#define WIDTHUSREAD			_IOR(RTDM_CLASS_PWM,1,char)
+#define WIDTHUSWRITE 		_IOW(RTDM_CLASS_PWM,1,char)
+
+#endif //PWM_RTDM_H_
diff -Naur linux-2.6.25.maxim/include/linux/class/rtdm/spi_rtdm.h linux-2.6.25.at91-20080908/include/linux/class/rtdm/spi_rtdm.h
--- linux-2.6.25.maxim/include/linux/class/rtdm/spi_rtdm.h	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/include/linux/class/rtdm/spi_rtdm.h	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,21 @@
+#ifndef SPI_RTDM_H_
+#define SPI_RTDM_H_
+
+#include <linux/ioctl.h>
+
+//arbitrary assignment, come back to this later
+#define RTDM_CLASS_SPI 0x90 
+
+#ifdef __KERNEL__	
+int rt_spi_device_create(struct spi_s *spi);
+#endif//__KERNEL__
+
+#define CONFREAD		_IOR(RTDM_CLASS_SPI,0,spi_control)
+#define CONFWRITE		_IOW(RTDM_CLASS_SPI,0,spi_control)
+#define SPEEDREAD		_IOR(RTDM_CLASS_SPI,1,spi_control)
+#define SPEEDWRITE		_IOW(RTDM_CLASS_SPI,1,spi_control)
+#define TIPREAD			_IOR(RTDM_CLASS_SPI,2,spi_control)
+#define TIPWRITE		_IOW(RTDM_CLASS_SPI,2,spi_control)
+#define XMIT			_IOW(RTDM_CLASS_SPI,3,spi_transfer_t)
+
+#endif //SPI_RTDM_H_
diff -Naur linux-2.6.25.maxim/include/linux/class/spi.h linux-2.6.25.at91-20080908/include/linux/class/spi.h
--- linux-2.6.25.maxim/include/linux/class/spi.h	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/include/linux/class/spi.h	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,85 @@
+#ifndef SPI_H_
+#define SPI_H_
+#include <linux/autoconf.h>
+#include <linux/device.h>
+#if defined(CONFIG_LSI2ESC)
+#include <linux/spi/spi.h>
+#endif
+
+#ifdef CONFIG_SPICLASS	
+
+#define SPICL_CPHA			(0x01)
+#define SPICL_CPOL			(0x02)
+/* common bit settings -- should be mutually exclusive */
+/* it would be possible to let 8 bit mode be 0x00 and let
+ * this be the default, but this does not work well for the
+ * LSI2ESC interface as the default controller setting is to
+ * leave bits_per_word set to 0. Leave 8 bit as an explicit
+ * setting. */
+#define SPICL_EIGHTBIT		(0x04) /* 8 bit is default */
+#define SPICL_TENBIT        (0x08) /* 10 bits per transfer */ 
+#define SPICL_TWELVEBIT     (0x10) /* 12 bits per transfer */
+#define SPICL_SIXTEENBIT    (0x20) /* 16 bits per transfer */
+
+typedef u8 spi_data;
+typedef u32 spi_control;
+
+//control definitions for the tip function
+#define TIPOFF		0
+#define TIPON		1
+#define TIPSTATUS	2
+
+/**********************
+ * spi class structure
+ */
+typedef struct spi_s{
+	const char *name;
+	int subclass;
+	spi_data *buf; 
+	int bsize;
+	/* if the SPI interface is used there needs to be a pointer to
+	 * the associated spi_device struct used by the Linux SPI layer
+	 */
+#if defined(CONFIG_LSI2ESC)
+	struct spi_device *lsi;
+#endif
+	int (*tip)(struct spi_s *s,int ofs);//declare transfer in process, for locking purposes
+	int (*xmit)(struct spi_s *s,u8 *mosi, u8 *miso, int size);
+	int (*confwrite)(struct spi_s *s,spi_control config);
+	spi_control (*confread)(struct spi_s *s);
+	int (*speedwrite)(struct spi_s *s,spi_control speed);
+	spi_control (*speedread)(struct spi_s *s);
+}spi_t;
+
+#define SPI_BASECLASNUM	0xC0
+#define SPI_SUBCLASS 	(SPI_BASECLASNUM+0)
+
+/***************************************************************************
+ * initial class declaration, doesn't hurt to call it mulitiple times,
+ * automatically checked during device instantiation 
+ */
+struct class *spi_declare(void);
+
+/***************************************************************************
+* class instantiation
+*/
+struct class_device *spi_register_class_device(spi_t *s);
+
+
+/***************************************************************************
+ * atomic method wrappers
+ * these should be used for all method calls to maintain sychronization across the
+ * various interfaces
+ */
+int atomic_spi_xmit(struct spi_s *s,u8 *mosi, u8 *miso, int size);
+int atomic_spi_conf_write(struct spi_s *s,spi_control config);
+spi_control atomic_spi_conf_read(struct spi_s *s);
+int atomic_spi_speed_write(struct spi_s *s,spi_control config);
+spi_control atomic_spi_speed_read(struct spi_s *s);
+int atomic_spi_tip_write(struct spi_s *s,spi_control config);
+spi_control atomic_spi_tip_read(struct spi_s *s);
+
+
+#endif
+
+#endif /*SPI_H_*/
diff -Naur linux-2.6.25.maxim/include/linux/class/spi_interface.h linux-2.6.25.at91-20080908/include/linux/class/spi_interface.h
--- linux-2.6.25.maxim/include/linux/class/spi_interface.h	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/include/linux/class/spi_interface.h	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,28 @@
+#ifndef SPI_INTERFACE_H_
+#define SPI_INTERFACE_H_
+
+/**
+ * Provides an interface between the SPI class
+ * driver and the Linux SPI layer for devices that
+ * already implement a device specific driver and
+ * register this interface in the mach.
+ * Naming convention:
+ * Linux SPI Interface: lsi
+ * EMAC SPI Class: esc
+ * -> lsi2esc
+ * 
+ * Copyright (C) 2007, EMAC Inc
+ */
+
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+#include <linux/class/spi.h>
+
+int lsi2esc_spi_tip(struct spi_s *s,int ofs);
+int lsi2esc_spi_xmit(struct spi_s *s, u8 *mosi, u8 *miso, int size);
+int lsi2esc_spi_confwrite(struct spi_s *s, spi_control config);
+spi_control lsi2esc_spi_confread(struct spi_s *s);
+int lsi2esc_spi_speedwrite(struct spi_s *s, spi_control speed);
+spi_control lsi2esc_spi_speedread(struct spi_s *s);
+
+#endif /*SPI_INTERFACE_H_*/
