diff -Naur linux-2.6.25.maxim/drivers/ioex/boardspec.c linux-2.6.25.at91-20080908/drivers/ioex/boardspec.c
--- linux-2.6.25.maxim/drivers/ioex/boardspec.c	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/drivers/ioex/boardspec.c	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,52 @@
+ /***************************************************************************
+                          		boardspec.c    
+			Registration of board specific classes & devices. 
+			Registers and calls a function pointer from the arch's platform device
+			Important in that it allows for a proper module loading order, which may be
+			required as some methods call other modules (specifically Xenamai)             
+                             -------------------
+	author				 : NZG
+    begin                : Tue May 15 2007
+    copyright          	 : (C) 2007 by EMAC.Inc
+    email                : support@emacinc.com
+ ***************************************************************************/
+#include <linux/kernel.h>
+#include <linux/autoconf.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/ioex/ecoreex.h>
+#include <linux/platform_device.h>
+#include <asm/io.h> 
+ 
+#define DRV_MODULE_NAME 	"boardspec"
+#define DRV_MODULE_VERSION 	"1.0"
+
+static int boardspec_probe(struct platform_device *pdev){
+	int (*device_init)(void);
+	if (pdev == NULL)return -ENODEV;
+	device_init = pdev->dev.platform_data;
+	return device_init();
+}
+
+//driver currently has no removal method.
+static struct platform_driver boardspec_driver = {
+	.probe		= boardspec_probe,
+	.driver		= {
+		.name	= "boardspec",
+	},
+};
+
+static int __init boardspec_init_module(void)
+{
+	printk(KERN_INFO DRV_MODULE_NAME " version " DRV_MODULE_VERSION " loading\n");
+	return platform_driver_register(&boardspec_driver);
+}
+
+static void __exit boardspec_cleanup_module(void)
+{
+	platform_driver_unregister(&boardspec_driver);
+}
+
+
+module_init(boardspec_init_module);
+module_exit(boardspec_cleanup_module);
diff -Naur linux-2.6.25.maxim/drivers/ioex/ecoreex.c linux-2.6.25.at91-20080908/drivers/ioex/ecoreex.c
--- linux-2.6.25.maxim/drivers/ioex/ecoreex.c	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/drivers/ioex/ecoreex.c	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,540 @@
+/***************************************************************************
+                          		ecoreex.c    
+					EMAC soft cores device registration             
+                             -------------------
+	author				 : NZG
+    rewrite              : Tue May 15 2007
+    copyright          	 : (C) 2007 by EMAC.Inc
+    email                : support@emacinc.com
+ ***************************************************************************/
+ 
+#include <linux/kernel.h>
+#include <linux/autoconf.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/class/gpio.h>
+#include <linux/class/pwm.h>
+#include <linux/class/mmcprot.h>
+#include <linux/ioex/ecoreex.h>
+#include <linux/ioex/pwmd.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+
+/*********************************************************************/
+#ifdef CONFIG_ECOREEX_HWMS
+#define CPLD_HWMS_NAME "HWMS GPI/O expansion R1.0"
+#define CPLD_HWMS 0xC0
+
+/**
+ * handler currently just indicates the that interrupt was handled and returns
+ */
+static irqreturn_t hwms_interrupt(int irq, void *na){
+    return IRQ_HANDLED;
+}
+
+static inline int CPLD_HWMS_map(unsigned long phys_addr, u8 *virt_addr, 
+        unsigned long size, const char *name, struct ecoreex_data *data)
+{   
+    gpio_t *gpio_counter;
+    gpio_t *gpio_control;
+    
+    if (request_mem_region(phys_addr, size, name) == NULL) {
+        printk("Could not obtain physical memory at %lx for EMAC core\n", phys_addr);
+        iounmap(virt_addr);
+    }
+    gpio_declare();
+    
+    gpio_control = gpio_device_create_unregistered(&virt_addr[0], NULL, "control");
+    ecoreex_setup_data_access(data->e_access, gpio_control);
+    /* no index read or write for the control -- only one register */
+    gpio_control->index_write = NULL;
+    gpio_control->index_read = NULL; 
+    
+    gpio_counter = gpio_device_create_unregistered(&virt_addr[1], NULL, "counter");
+    gpio_counter->index_write = gpio_index_write;
+    gpio_counter->index_read = gpio_index_read;
+    gpio_counter->range = 1;
+    ecoreex_setup_data_access(data->e_access, gpio_counter);
+    
+    gpio_register_class_device(gpio_control);
+    gpio_register_class_device(gpio_counter);
+    
+    /*
+     * Allocate the IRQ
+     */
+    if(data->irq){
+        int err = request_irq(data->irq, hwms_interrupt,IRQT_RISING,name, NULL);
+        if(err<0)
+            printk("ecoreex request for irq %d failed with %d\n",data->irq,err);
+        //printk("ecoreex request for irq %d failed\n",e->irq);
+
+        else set_irq_wake(data->irq,1);//if the board provides an irq, register it to wake up pm.
+    }
+
+    return 0;
+}
+
+#endif /* CONFIG_ECOREEX_HWMS */
+
+
+#ifdef CONFIG_ECOREEX_SOM150
+#define CPLD_SOM150_NAME "EMAC SoM-150ES GPI/O expansion R1.0"
+#define CPLD_SOM150 0xC0
+
+/**
+ * handler currently just indicates the that interrupt was handled and returns
+ */
+static irqreturn_t som150_interrupt(int irq, void *na){
+    return IRQ_HANDLED;
+}
+
+static inline int CPLD_SOM150_map(unsigned long phys_addr, u8 *virt_addr, 
+        unsigned long size, const char *name, struct ecoreex_data *data)
+{   
+    gpio_t *gpio_lcd;
+    gpio_t *gpio_porta;
+    gpio_t *gpio_portb;
+    gpio_t *gpio_portc;
+    gpio_t *gpio_keypad;
+    gpio_t *gpio_gpout;
+    gpio_t *gpio_gpin;    
+
+    if (request_mem_region(phys_addr, size, name) == NULL) {
+        printk("Could not obtain physical memory at %lx for EMAC core\n", phys_addr);
+        iounmap(virt_addr);
+    }
+    gpio_declare();
+    
+    
+    
+    gpio_lcd = gpio_device_create_unregistered(&virt_addr[0], NULL, "lcd");
+    gpio_lcd->index_write = gpio_index_write;
+    gpio_lcd->index_read = gpio_index_read;
+    gpio_lcd->range = 1;
+    ecoreex_setup_data_access(data->e_access, gpio_lcd);
+    
+  
+    gpio_porta = gpio_device_create_unregistered(&virt_addr[2], NULL, "porta");
+    gpio_porta->index_write = gpio_index_write;
+    gpio_porta->index_read = gpio_index_read;
+    gpio_porta->range = 1;
+    ecoreex_setup_data_access(data->e_access, gpio_porta);
+    
+    gpio_portb = gpio_device_create_unregistered(&virt_addr[4], NULL, "portb");
+    gpio_portb->index_write = gpio_index_write;
+    gpio_portb->index_read = gpio_index_read;
+    gpio_portb->range = 1;
+    ecoreex_setup_data_access(data->e_access, gpio_portb);
+       
+    gpio_portc = gpio_device_create_unregistered(&virt_addr[6], NULL, "portc");
+    gpio_portc->index_write = gpio_index_write;
+    gpio_portc->index_read = gpio_index_read;
+    gpio_portc->range = 1;
+    ecoreex_setup_data_access(data->e_access, gpio_portc);
+    
+    gpio_keypad = gpio_device_create_unregistered(&virt_addr[8], NULL, "keypad");
+    gpio_keypad->index_write = NULL;
+    gpio_keypad->index_read = NULL;
+    ecoreex_setup_data_access(data->e_access, gpio_keypad);
+    
+    gpio_gpout = gpio_device_create_unregistered(&virt_addr[9], NULL, "gpout");
+    gpio_gpout->index_write = NULL;
+    gpio_gpout->index_read = NULL;
+    ecoreex_setup_data_access(data->e_access, gpio_gpout);
+    
+    gpio_gpin = gpio_device_create_unregistered(&virt_addr[10], NULL, "gpin");
+    gpio_gpin->index_write = NULL;
+    gpio_gpin->index_read = NULL;
+    ecoreex_setup_data_access(data->e_access, gpio_gpin);
+    
+    gpio_register_class_device(gpio_lcd);
+    gpio_register_class_device(gpio_porta);
+    gpio_register_class_device(gpio_portb);
+    gpio_register_class_device(gpio_portc);
+    gpio_register_class_device(gpio_keypad);
+    gpio_register_class_device(gpio_gpout);
+    gpio_register_class_device(gpio_gpin);
+
+    /*
+     * Allocate the IRQ
+     */
+    if(data->irq){
+        int err = request_irq(data->irq, som150_interrupt,IRQT_RISING,name, NULL);
+        if(err<0)
+            printk("ecoreex request for irq %d failed with %d\n",data->irq,err);
+        else set_irq_wake(data->irq,1);//if the board provides an irq, register it to wake up pm.
+    }
+
+    return 0;
+}
+
+#endif /* CONFIG_ECOREEX_SOM150 */
+
+//---------------------------------------------------------------------------------
+#ifdef CONFIG_ECOREEX_TGPIO
+#define CPLD_BASE_NAME "iPac GPI/O expansion R1.0" 
+#define CPLD_BASE 0xA0
+
+#define CPLD_BASE_NAME_11 "iPac GPI/O expansion R1.1" 
+#define CPLD_BASE_11 0xA3
+
+static inline int CPLD_BASE_map(unsigned long phys_addr,u8 *virt_addr,unsigned long size,const char *name){
+	
+	if(request_mem_region(phys_addr,size,name)==NULL){
+		printk("could not obtain physical memory at %lx for EMAC core\n",phys_addr);
+		iounmap(virt_addr);
+		return -1;
+		}			
+	//add appropriate class devices for this version to the system
+	printk("%s detected at %lx\n",name,phys_addr);
+
+#ifdef CONFIG_GPIOCLASS
+	gpio_declare();
+	gpio_device_create(&virt_addr[0], &virt_addr[1],"portw");
+	gpio_device_create(&virt_addr[2], &virt_addr[3],"portx");
+	gpio_device_create(&virt_addr[4], &virt_addr[5],"porty");
+	gpio_device_create(&virt_addr[6], &virt_addr[7],"portz");
+#endif
+				
+return 0;
+}
+#endif //CONFIG_ECOREEX_TGPIO
+//---------------------------------------------------------------------------------
+#ifdef CONFIG_ECOREEX_SGPWM
+#define CPLD_GPWM_NAME "iPac Shadow GPI/O & PWM expansion R1.0"
+#define CPLD_GPWM 0xA1
+
+#define CPLD_GPWM_NAME_11 "iPac Shadow GPI/O & PWM expansion R1.1"
+#define CPLD_GPWM_11 0xA2
+
+#define CPLD_GPWM_NAME_12 "iPac Shadow GPI/O & PWM expansion R1.2"
+#define CPLD_GPWM_12 0xA4
+
+static int gpwm_carddetect(mmcslot_t *s){
+	u8 status = atomic_gpio_data_read(s->pd[MMCCD]);
+	return (status&1)?0:1;
+}
+
+static int gpwm_writeprotect(mmcslot_t *s){
+	u8 status = atomic_gpio_data_read(s->pd[MMCWP]);
+	return (status&2)?1:0;
+}
+
+static inline int CPLD_GPWM_map(unsigned long phys_addr,u8 *virt_addr,unsigned long size,const char *name,struct ecoreex_data *e){
+	if(request_mem_region(phys_addr,size,name)==NULL){
+		printk("could not obtain physical memory at %lx for EMAC core\n",phys_addr);
+		iounmap(virt_addr);
+		return -1;
+		}
+	
+	printk("%s detected at %lx\n",name,phys_addr);			
+	//add appropriate class devices for this version to the system
+
+#ifdef CONFIG_GPIOCLASS	
+{
+	struct class_device *status = gpi_device_create(&virt_addr[6],"status");
+	gpi_device_create(&virt_addr[0],"portw");
+	gpo_device_create(&virt_addr[1],"portx");
+	gpo_device_create(&virt_addr[2],"porty");
+	gpi_device_create(&virt_addr[3],"portz");
+	gpo_device_create(&virt_addr[7],"control");
+	 
+	if(e->mmcslot){//implement MMC CD and WP functions
+		e->mmcslot->carddetect = gpwm_carddetect;
+		e->mmcslot->writeprotect = gpwm_writeprotect;
+		e->mmcslot->pd[MMCWP]=e->mmcslot->pd[MMCCD]=status->class_data;//pass back gpio class structures
+	}
+}
+#endif	//CONFIG_GPIOCLASS
+
+#ifdef CONFIG_PWMCLASS
+	pwmd_device_create(&virt_addr[4],"gpwma",e->read_periodusa);
+	pwmd_device_create(&virt_addr[5],"gpwmb",e->read_periodusa);
+#endif	
+
+
+
+return 0;
+}
+
+#endif //CONFIG_ECOREEX_SGPWM
+
+//---------------------------------------------------------------------------------
+#ifdef CONFIG_ECOREEX_GCMB
+#define CPLD_GCMB_NAME_10 "GCMB CPLD expansion R1.0"
+#define CPLD_GCMB 0xB0
+
+static inline int CPLD_GCMB_map(unsigned long phys_addr,u8 *virt_addr,unsigned long size,const char *name){
+	
+	if(request_mem_region(phys_addr,size,name)==NULL){
+		printk("could not obtain physical memory at %lx for EMAC core\n",phys_addr);
+		iounmap(virt_addr);
+		return -1;
+		}
+	
+	printk("%s detected at %lx\n",name,phys_addr);			
+	//add appropriate class devices for this version to the system
+
+#ifdef CONFIG_GPIOCLASS	
+	gpio_declare();
+	gpo_device_create(&virt_addr[0],"dlais321");
+	gpi_device_create(&virt_addr[4],"rlwc3210");
+	gpio_device_create(&virt_addr[2], NULL,"spi_7730");
+#endif	//CONFIG_GPIOCLASS
+
+return 0;
+}
+
+#endif //CONFIG_ECOREEX_GCMB
+
+//---------------------------------------------------------------------------------
+#ifdef CONFIG_ECOREEX_DENM
+#define CPLD_DENM_NAME_12 "DENM CPLD expansion R1.2/R1.3"
+#define CPLD_DENM_NAME_14 "DENM CPLD expansion R1.4"
+#define CPLD_DENM_NAME_15 "DENM CPLD expansion R1.5"
+#define CPLD_DENM_NAME_16 "DENM CPLD expansion R1.6"
+#define CPLD_DENM_NAME_17 "DENM CPLD expansion R1.7"
+#define CPLD_DENM_NAME_18 "DENM CPLD expansion R1.8"
+#define CPLD_DENM_NAME_19 "DENM CPLD expansion R1.9"
+#define CPLD_DENM 0x92
+#define CPLD_DENM14 0x93
+#define CPLD_DENM15 0x94
+#define CPLD_DENM16 0x95
+#define CPLD_DENM17 0x98
+#define CPLD_DENM18 0x99
+#define CPLD_DENM19 0x9A
+
+static inline int CPLD_DENM_map(unsigned long phys_addr,u8 *virt_addr,unsigned long size,const char *name){
+	
+	if(request_mem_region(phys_addr,size,name)==NULL){
+		printk("could not obtain physical memory at %lx for EMAC core\n",phys_addr);
+		iounmap(virt_addr);
+		return -1;
+		}
+	
+	printk("%s detected at %lx\n",name,phys_addr);			
+	//add appropriate class devices for this version to the system
+
+#ifdef CONFIG_GPIOCLASS	
+	gpio_declare();
+	gpi_device_create(&virt_addr[2],"counter0");
+	gpi_device_create(&virt_addr[4],"counter1");
+	gpi_device_create(&virt_addr[5],"counter2");
+	gpi_device_create(&virt_addr[8],"counter3");
+	gpi_device_create(&virt_addr[10],"counter4");
+	gpi_device_create(&virt_addr[12],"counter5");
+	gpi_device_create(&virt_addr[14],"ct543210");
+	
+	gpo_device_create(&virt_addr[16],"oxrs4321");
+	gpo_device_create(&virt_addr[17],"xxrt321b");
+	
+	gpio_device_create(&virt_addr[3], NULL,"rollover");
+#endif	//CONFIG_GPIOCLASS
+
+return 0;
+}
+
+static inline int CPLD_DENM14_map(unsigned long phys_addr,u8 *virt_addr,unsigned long size,const char *name){
+	
+	if(request_mem_region(phys_addr,size,name)==NULL){
+		printk("could not obtain physical memory at %lx for EMAC core\n",phys_addr);
+		iounmap(virt_addr);
+		return -1;
+		}
+	
+	printk("%s detected at %lx\n",name,phys_addr);			
+	//add appropriate class devices for this version to the system
+
+#ifdef CONFIG_GPIOCLASS	
+	gpio_declare();
+	gpi_device_create(&virt_addr[2],"counter0");
+	gpi_device_create(&virt_addr[4],"counter1");
+	gpi_device_create(&virt_addr[6],"counter2");
+	gpi_device_create(&virt_addr[8],"counter3");
+	gpi_device_create(&virt_addr[10],"counter4");
+	gpi_device_create(&virt_addr[12],"counter5");
+	gpi_device_create(&virt_addr[14],"ct543210");
+	
+	gpio_device_create(&virt_addr[16],NULL,"oxrs4321");
+	gpio_device_create(&virt_addr[17],NULL,"xxrt321b");
+	gpio_device_create(&virt_addr[3], NULL,"rollover");
+	gpo_device_create(&virt_addr[1],"debounce");
+	
+#endif	//CONFIG_GPIOCLASS
+
+return 0;
+}
+
+/**
+ * handler currently just indicates the that interrupt was handled and returns
+ */
+static irqreturn_t denm_interrupt(int irq, void *na){
+	//printk("denm interrupt\n");
+	return IRQ_HANDLED;
+}
+
+
+static inline int CPLD_DENM15_map(unsigned long phys_addr,u8 *virt_addr,unsigned long size,const char *name,struct ecoreex_data *e){
+	
+	if(request_mem_region(phys_addr,size,name)==NULL){
+		printk("could not obtain physical memory at %lx for EMAC core\n",phys_addr);
+		iounmap(virt_addr);
+		return -1;
+		}
+	
+	printk("%s detected at %lx\n",name,phys_addr);			
+	//add appropriate class devices for this version to the system
+
+#ifdef CONFIG_GPIOCLASS	
+	gpio_declare();
+	gpi_device_create(&virt_addr[2],"counter0");
+	gpi_device_create(&virt_addr[4],"counter1");
+	gpi_device_create(&virt_addr[6],"counter2");
+	gpi_device_create(&virt_addr[8],"counter3");
+	gpi_device_create(&virt_addr[10],"counter4");
+	gpi_device_create(&virt_addr[12],"counter5");
+	gpi_device_create(&virt_addr[14],"ct543210");
+	
+	gpio_device_create(&virt_addr[16],NULL,"oxrs4321");
+	gpio_device_create(&virt_addr[17],NULL,"xxrt321b");
+	gpio_device_create(&virt_addr[3], NULL,"rollover");
+	gpio_device_create(&virt_addr[1],NULL,"debounce");
+	
+	/*
+		 * Allocate the IRQ
+		 */
+	if(e->irq){
+		int err = request_irq(e->irq, denm_interrupt,IRQT_RISING,name, NULL);
+		if(err<0)
+			printk("ecoreex request for irq %d failed with %d\n",e->irq,err);
+			//printk("ecoreex request for irq %d failed\n",e->irq);
+		
+		else set_irq_wake(e->irq,1);//if the board provides an irq, register it to wake up pm.
+	}
+	
+#endif	//CONFIG_GPIOCLASS
+
+return 0;
+}
+
+#endif //CONFIG_ECOREEX_DENM
+
+/************************************************************
+ * core mappings based upon a key
+ */
+static inline void map_core(unsigned long phys_addr, unsigned long size, struct ecoreex_data *data)
+{
+    u8 *virt_addr = ioremap_nocache(phys_addr,size);
+    int version = VERSION_KEY;
+    
+    if(virt_addr==NULL)printk("could not remap physical memory at %lx for EMAC core\n",phys_addr);
+    else{
+        if (VERSION_KEY == -1)
+            version =ioread8(&virt_addr[data->key_offset]);
+        //    version = data->e_access->ecoreex_key_read(data->key_offset, virt_addr);
+        /* else the version is predefined */
+		printk("EMAC core version %x detected at %lx\n",version,phys_addr+data->key_offset );
+		switch(version){
+#ifdef CONFIG_ECOREEX_HWMS
+        case CPLD_HWMS:
+            CPLD_HWMS_map(phys_addr, virt_addr, size, CPLD_HWMS_NAME, data);
+        break;
+#endif
+#ifdef CONFIG_ECOREEX_SOM150
+        case CPLD_SOM150:
+            CPLD_SOM150_map(phys_addr, virt_addr, size, CPLD_SOM150_NAME, data);
+        break;
+#endif
+			//-----------------------------------------------------------
+			#ifdef CONFIG_ECOREEX_TGPIO
+			case CPLD_BASE:
+				CPLD_BASE_map(phys_addr,virt_addr,size,CPLD_BASE_NAME);
+			break;
+			case CPLD_BASE_11:
+				CPLD_BASE_map(phys_addr,virt_addr,size,CPLD_BASE_NAME_11);
+			break;
+			#endif //CONFIG_ECOREEX_TGPIO
+			//-----------------------------------------------------------
+			#ifdef CONFIG_ECOREEX_SGPWM
+			case CPLD_GPWM:
+				CPLD_GPWM_map(phys_addr,virt_addr,size,CPLD_GPWM_NAME,data);
+			break;
+			case CPLD_GPWM_11:
+				CPLD_GPWM_map(phys_addr,virt_addr,size,CPLD_GPWM_NAME_11,data);
+			break;
+			case CPLD_GPWM_12:
+				CPLD_GPWM_map(phys_addr,virt_addr,size,CPLD_GPWM_NAME_12,data);
+			break;
+			#endif //CONFIG_ECOREEX_SGPWM
+			//-----------------------------------------------------------
+			#ifdef CONFIG_ECOREEX_GCMB
+			case CPLD_GCMB:
+				CPLD_GCMB_map(phys_addr,virt_addr,size,CPLD_GCMB_NAME_10);
+			break;
+			#endif //CONFIG_ECOREEX_GCMB
+			//-----------------------------------------------------------			
+			#ifdef CONFIG_ECOREEX_DENM
+			case CPLD_DENM:
+				CPLD_DENM_map(phys_addr,virt_addr,size,CPLD_DENM_NAME_12);
+			break;
+			case CPLD_DENM14:
+				CPLD_DENM14_map(phys_addr,virt_addr,size,CPLD_DENM_NAME_14);
+			break;
+			case CPLD_DENM15:
+				CPLD_DENM15_map(phys_addr,virt_addr,size,CPLD_DENM_NAME_15,data);
+			break;
+			case CPLD_DENM16:
+				CPLD_DENM15_map(phys_addr,virt_addr,size,CPLD_DENM_NAME_16,data);	
+			break;
+			case CPLD_DENM17:
+				CPLD_DENM15_map(phys_addr,virt_addr,size,CPLD_DENM_NAME_17,data);	
+			break;
+			case CPLD_DENM18:
+				CPLD_DENM15_map(phys_addr,virt_addr,size,CPLD_DENM_NAME_18,data);	
+			break;
+			case CPLD_DENM19:
+				CPLD_DENM15_map(phys_addr,virt_addr,size,CPLD_DENM_NAME_19,data);	
+			break;			
+			#endif //CONFIG_ECOREEX_DENM
+			//--------------------------------------------------------
+			
+			default://unrecognized CPLD or no CPLD available, silently fail and the physical memory region
+				iounmap(virt_addr);
+			}
+		}
+}
+
+static int ecoreex_probe(struct platform_device *pdev){
+	//printk("ecoreex_probe\n");	
+	if (pdev == NULL)return -ENODEV;
+	map_core(pdev->resource->start,(pdev->resource->end-pdev->resource->start+1),pdev->dev.platform_data);
+	return 0;
+}
+
+//driver currently has no removal method.
+static struct platform_driver ecoreex_driver = {
+	.probe		= ecoreex_probe,
+	.driver		= {
+		.name	= "ecoreex",
+	},
+};
+
+#define DRV_MODULE_NAME 	"ecoreex"
+#define DRV_MODULE_VERSION 	"1.2"
+static int __init ecoreex_init_module(void)
+{
+	printk(KERN_INFO DRV_MODULE_NAME " version " DRV_MODULE_VERSION " loading\n");
+	return platform_driver_register(&ecoreex_driver);
+}
+
+static void __exit ecoreex_cleanup_module(void)
+{
+	platform_driver_unregister(&ecoreex_driver);
+}
+
+module_init(ecoreex_init_module);
+module_exit(ecoreex_cleanup_module);
+
diff -Naur linux-2.6.25.maxim/drivers/ioex/Kconfig linux-2.6.25.at91-20080908/drivers/ioex/Kconfig
--- linux-2.6.25.maxim/drivers/ioex/Kconfig	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/drivers/ioex/Kconfig	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,72 @@
+#
+# IO expansion configuration
+#
+
+menu "IO expansion"
+
+config ECOREEX
+        tristate "EMAC cores"
+        ---help---
+        Provides autodetection and support for PLD cores following the EMAC 
+        format, which uses a device key to communicate the expansion devices available to 
+        the kernel.       
+
+config ECOREEX_TGPIO
+		depends on ECOREEX
+        bool "iPac True GPI/O expansion R1.0"
+        ---help---
+        Provides autodetection and support for the iPac GPI/O expansion
+
+config ECOREEX_SGPWM
+		depends on ECOREEX
+        bool "iPac Shadow GPI/O & PWM expansion R1.0"
+        ---help---
+        Provides autodetection and support for the iPac Shadow GPI/O & PWM expansion
+
+config ECOREEX_GCMB
+		depends on ECOREEX
+        bool "GCMB expansion I/O"
+        ---help---
+        Provides autodetection and support for the GCMB expansion
+
+config ECOREEX_DENM
+		depends on ECOREEX
+        bool "DENM expansion I/O"
+        ---help---
+        Provides autodetection and support for the DENM expansion       
+
+config ECOREEX_HWMS
+        depends on ECOREEX
+        bool "Armstrong HWMS expansion I/O"
+        ---help---
+        Provides support for the Armstrong HWMS PLD
+
+config ECOREEX_SOM150
+        depends on ECOREEX
+        bool "EMAC SoM-150-ES expansion I/O"
+        ---help---
+        Provides support for the EMAC SoM-150-ES PLD
+
+config ECOREEX_KEY
+        depends on ECOREEX
+        bool "Define static version key"
+        ---help---
+        Disable auto-detection of the PLD core by defining the version key
+
+config ECOREEX_STATIC_KEY
+        depends on ECOREEX_KEY
+        hex "Version key"
+        default "0xC0"
+        ---help---
+        Set the static version key for the PLD core 
+
+config BOARDSPEC
+        tristate "board devices"
+        ---help---
+        Provides registration of devices provided by the mach. 
+
+endmenu
+
+
+
+
diff -Naur linux-2.6.25.maxim/drivers/ioex/Makefile linux-2.6.25.at91-20080908/drivers/ioex/Makefile
--- linux-2.6.25.maxim/drivers/ioex/Makefile	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/drivers/ioex/Makefile	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,10 @@
+#
+# Makefile for the ioex devices
+#
+
+# Each configuration option enables a list of files.
+
+obj-$(CONFIG_ECOREEX)		+= ecoreex.o
+obj-$(CONFIG_BOARDSPEC)		+= boardspec.o
+obj-y						+= pwmd.o
+
diff -Naur linux-2.6.25.maxim/drivers/ioex/pwmd.c linux-2.6.25.at91-20080908/drivers/ioex/pwmd.c
--- linux-2.6.25.maxim/drivers/ioex/pwmd.c	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/drivers/ioex/pwmd.c	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,105 @@
+/**
+ * PWMD's 
+ * pwmd's modulate an external frequency, 
+ * this frequency is passed in as method, which is used to calcuate the widthus
+ * when written or read.
+*/
+
+#include <linux/class/pwm.h>
+#include <asm/io.h>
+
+#define PWMD_PWM_SUBCLASS 93
+
+#define REGMAX 255
+#define PERIODMAX ((0xffffffff)/(REGMAX))
+
+//internal errors
+#define SYSCLOCK_UNSUPPORTED	-2
+
+/**
+ * methods using a shadow register to set the periodus.
+ */
+static pwm_data pwmd_clock_read(struct pwm_s *pwm){
+	return pwm->periodus_shadow;
+}
+
+static int pwmd_clock_write(struct pwm_s *pwm,pwm_data clock){
+	if(!clock)clock=1;
+	if(clock>PERIODMAX)clock=PERIODMAX;//to prevent overflows
+	pwm->periodus_shadow = clock;
+	return 0;
+}
+
+static inline int us2reg(__u32 *value,__u32 periodus_in){
+	if(periodus_in)*value/=periodus_in;
+	//if the input period is zero written value has no effect and will be interpreted as zero in any case.
+	if(*value>REGMAX)*value=REGMAX;
+	return 0;
+}
+
+static inline int reg2us(__u32 *value,__u32 periodus_in){
+	*value*=periodus_in;
+	return 0;		
+}
+
+static int pwmd_widthus_write(struct pwm_s *pwm, pwm_data width){
+	pwm->widthus_shadow = width;
+	if(us2reg(&width,pwm->read_pwmclock(pwm))==SYSCLOCK_UNSUPPORTED)
+		{printk("sysclock unsupported\n");return SYSCLOCK_UNSUPPORTED;}
+	
+	iowrite16((u16)width,pwm->widthus);
+	return 0;
+}
+
+static pwm_data pwmd_widthus_read(struct pwm_s *pwm){
+	__u32 width = pwm->widthus_shadow;
+	
+	if(reg2us(&width,pwm->read_pwmclock(pwm))==SYSCLOCK_UNSUPPORTED)
+		{printk("sysclock unsupported\n");return SYSCLOCK_UNSUPPORTED;}
+		
+	return (width);
+}
+
+static pwm_data pwmd_periodus_read(struct pwm_s *pwm){
+	__u32 period = 0xff;
+	
+	if(reg2us(&period,pwm->read_pwmclock(pwm))==SYSCLOCK_UNSUPPORTED)
+		{printk("sysclock unsupported\n");return SYSCLOCK_UNSUPPORTED;}
+		
+	return (period); 
+}
+
+static int pwmd_periodus_write(struct pwm_s *pwm, pwm_data periodus){
+	pwmd_clock_write(pwm,periodus/REGMAX);
+	return 0;
+}
+
+struct class_device *pwmd_device_create(
+ void *widthus,
+ const char *name,
+ pwm_data (*read_pwmclock)(pwm_t *pwm)){
+	
+	pwm_t *pwm = kmalloc(sizeof(pwm_t),GFP_KERNEL);
+	memset(pwm,0,sizeof(pwm_t));
+	pwm->name = name;
+	pwm->subclass = PWMD_PWM_SUBCLASS;
+
+	pwm->widthus = widthus;
+	
+	pwm->widthus_write = pwmd_widthus_write;
+    pwm->widthus_read = pwmd_widthus_read;
+    pwm->periodus_read = pwmd_periodus_read;
+    
+	if(pwm->read_pwmclock)
+		pwm->periodus_write = pwm_empty_write;
+	else{
+		pwm->read_pwmclock = pwmd_clock_read;
+    	pwm->periodus_write = pwmd_periodus_write;
+    	pwmd_clock_write(pwm,1);
+	}
+	printk("registering pwmd device: %s\n",name);
+
+    return pwm_register_class_device(pwm);
+}
+
+
diff -Naur linux-2.6.25.maxim/drivers/Kconfig linux-2.6.25.at91-20080908/drivers/Kconfig
--- linux-2.6.25.maxim/drivers/Kconfig	2008-04-16 21:49:44.000000000 -0500
+++ linux-2.6.25.at91-20080908/drivers/Kconfig	2008-07-24 11:43:16.000000000 -0500
@@ -46,6 +46,8 @@
 
 source "drivers/input/Kconfig"
 
+source "drivers/ioex/Kconfig"
+
 source "drivers/char/Kconfig"
 
 source "drivers/i2c/Kconfig"
diff -Naur linux-2.6.25.maxim/drivers/Makefile linux-2.6.25.at91-20080908/drivers/Makefile
--- linux-2.6.25.maxim/drivers/Makefile	2008-04-16 21:49:44.000000000 -0500
+++ linux-2.6.25.at91-20080908/drivers/Makefile	2008-07-24 11:43:16.000000000 -0500
@@ -28,7 +28,7 @@
 obj-$(CONFIG_FB_I810)           += video/i810/
 obj-$(CONFIG_FB_INTEL)          += video/intelfb/
 
-obj-y				+= serial/
+obj-y				+= serial/ ioex/
 obj-$(CONFIG_PARPORT)		+= parport/
 obj-y				+= base/ block/ misc/ mfd/ net/ media/
 obj-$(CONFIG_NUBUS)		+= nubus/
diff -Naur linux-2.6.25.maxim/include/linux/ioex/ecoreex.h linux-2.6.25.at91-20080908/include/linux/ioex/ecoreex.h
--- linux-2.6.25.maxim/include/linux/ioex/ecoreex.h	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/include/linux/ioex/ecoreex.h	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,62 @@
+#ifndef ECOREEX_H_
+#define ECOREEX_H_
+
+#include <linux/class/pwm.h>
+#include <linux/class/gpio.h>
+#include <linux/class/mmcprot.h>
+
+
+#ifdef CONFIG_ECOREEX_KEY
+#define VERSION_KEY CONFIG_ECOREEX_STATIC_KEY
+#else
+#define VERSION_KEY -1
+#endif
+
+/* Use this structure to specify read/write commands
+ * that differ from the direct ioread/write functions
+ * in the gpio class. If these members are not specified,
+ * the corresponding gpio function will be used as the
+ * default
+ */
+struct ecoreex_access_s
+{
+    gpio_data (*ecoreex_data_read)(struct gpio_s *gpio);
+    int (*ecoreex_data_write)(struct gpio_s *gpio,gpio_data data);
+    gpio_data (*ecoreex_ddr_read)(struct gpio_s *gpio); 
+    int (*ecoreex_ddr_write)(struct gpio_s *gpio,gpio_data data);
+    gpio_data (*ecoreex_index_read)(struct gpio_s *gpio);   
+    int (*ecoreex_index_write)(struct gpio_s *gpio,gpio_data data);
+    u8 (*ecoreex_key_read)(u8 index, u8 *virt_addr); /* function to read the key offset -- defaults to ioread8 */
+};
+
+struct ecoreex_data
+{
+    int key_offset;
+#ifdef CONFIG_PWMCLASS
+    __u32 (*read_periodusa)(pwm_t *pwm);//a pwm input clock, defined as a period to minimize calculation
+#endif
+    mmcslot_t *mmcslot;//structure for implementing mmc connections.
+    unsigned int irq;
+    struct ecoreex_access_s *e_access;  
+};
+
+static inline u8 ecoreex_default_key_read(u8 index, u8 *virt_addr)
+{
+    return ioread8(&(virt_addr[index]));
+}
+
+static inline int ecoreex_setup_data_access(struct ecoreex_access_s *e_access, struct gpio_s *gpio)
+{
+    if (!e_access || !gpio) return -1;
+    if (e_access->ecoreex_data_read) gpio->data_read = e_access->ecoreex_data_read;
+    if (e_access->ecoreex_data_write) gpio->data_write = e_access->ecoreex_data_write;
+    if (e_access->ecoreex_ddr_read) gpio->ddr_read = e_access->ecoreex_ddr_read;
+    if (e_access->ecoreex_ddr_write) gpio->ddr_write = e_access->ecoreex_ddr_write;
+    if (e_access->ecoreex_index_read) gpio->index_read = e_access->ecoreex_index_read;
+    if (e_access->ecoreex_index_write) gpio->index_write = e_access->ecoreex_index_write;
+    if (!e_access->ecoreex_key_read) e_access->ecoreex_key_read = ecoreex_default_key_read;
+    
+    return 0;
+}
+
+#endif /*ECOREEX_H_*/
diff -Naur linux-2.6.25.maxim/include/linux/ioex/pwmd.h linux-2.6.25.at91-20080908/include/linux/ioex/pwmd.h
--- linux-2.6.25.maxim/include/linux/ioex/pwmd.h	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.25.at91-20080908/include/linux/ioex/pwmd.h	2008-07-24 11:43:16.000000000 -0500
@@ -0,0 +1,6 @@
+#ifndef PWMD_H_
+#define PWMD_H_
+
+struct class_device *pwmd_device_create(void *widthus,const char *name,pwm_data (*read_pwmclock)(pwm_t *pwm));
+
+#endif /*PWMD_H_*/
