**************************************************************
*Adds auto-rts capability on com1 for the SoM-9260M.
*This was added to comply with the Integry's DEN specification which requires auto-flow *control
*
*This was done by adding a second control bit to the "rtstest" class. 
*setting bit 0x02 causing the com1 to go into auto-flow control mode, setting RTS high *during serial port transmissions. In this mode you can still read back the current state *of the RTS line on bit0, but can't set it (because then it wouldn't be auto controlled). *If the auto bit is cleared the rts line goes back into manual mode and can be set and *cleared by writing 1 or 0. Reading the class's data reads the current register states *and interpretes it back into these bits.
*
*The rtstest class has been renamed rtsctl since it is no longer only for testing *purposes.
*
*Note that this will not actually implement auto-flow control on the DEN0 without wire *modification as this board does not currently have RTS physically connected.
*
*To enable this feature, connect RTS to pin 26 of the PLD U3.
*
*RTS will then selectively control 485 transmissions based upon the configurated mode.
*
*Note: also adds prototypes for some of the Integry's LED functions to remove build *warnings
*
*Author: ngustavson
*Date: 2007-10-31 11:12:05 -0500 (Wed, 31 Oct 2007)
*New Revision: 406
**************************************************************
diff -uprN linux-2.6.20-at92_e1.3.1/arch/arm/mach-at91rm9200/at91sam9260_devices.c linux-2.6.20.AT91_svn/arch/arm/mach-at91rm9200/at91sam9260_devices.c
--- linux-2.6.20-at92_e1.3.1/arch/arm/mach-at91rm9200/at91sam9260_devices.c	2007-11-08 10:42:36.000000000 -0500
+++ linux-2.6.20.AT91_svn/arch/arm/mach-at91rm9200/at91sam9260_devices.c	2007-10-31 12:12:05.000000000 -0400
@@ -12,6 +12,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
+
 #include <linux/platform_device.h>
 
 #include <asm/arch/board.h>
@@ -19,9 +20,10 @@
 #include <asm/arch/at91sam9260.h>
 #include <asm/arch/at91sam926x_mc.h>
 #include <asm/arch/at91sam9260_matrix.h>
-
 #include <asm/arch/at91_pmc.h>
 
+#include <asm/mach/serial_at91.h>
+
 #include "generic.h"
 
 #define SZ_512	0x00000200
@@ -899,9 +901,20 @@ void __init at91_add_device_serial(void)
 			platform_device_register(at91_uarts[i]);
 	}
 }
+
+//if available, calls the serial driver for a given channel to set auto485 mode
+int at91_auto485_serial(int channel,int fos){
+	struct uart_port *port = NULL;
+	if(channel>ATMEL_MAX_UART)return -1;
+	if(at91_uarts[channel]==NULL)return -2;
+	if((port=platform_get_drvdata(at91_uarts[channel]))==NULL)return -3;
+	return atmel_auto485(port,fos);
+}
+
 #else
 void __init at91_init_serial(struct at91_uart_config *config) {}
 void __init at91_add_device_serial(void) {}
+int at91_auto485_serial(int channel,int onoff) {return 0;}
 #endif
 
 
@@ -921,6 +934,7 @@ static int __init at91_add_standard_devi
  */
 int at91_self_refresh(unsigned state){
 	at91_sys_write(AT91_SDRAMC_LPR, AT91_SDRAMC_LPCB_SELF_REFRESH);
+	return 0;
 }
 
 /**
@@ -928,10 +942,12 @@ int at91_self_refresh(unsigned state){
  */
 int at91_lp_disable(unsigned state){
 	at91_sys_write(AT91_SDRAMC_LPR, AT91_SDRAMC_LPCB_DISABLE);
+	return 0;
 }
 
 int at91_stopclock(unsigned state){
 	at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK);
+	return 0;
 }
 
 	
diff -uprN linux-2.6.20-at92_e1.3.1/arch/arm/mach-at91rm9200/board-som9260m.c linux-2.6.20.AT91_svn/arch/arm/mach-at91rm9200/board-som9260m.c
--- linux-2.6.20-at92_e1.3.1/arch/arm/mach-at91rm9200/board-som9260m.c	2007-11-08 10:42:36.000000000 -0500
+++ linux-2.6.20.AT91_svn/arch/arm/mach-at91rm9200/board-som9260m.c	2007-10-31 12:12:05.000000000 -0400
@@ -46,7 +46,6 @@
 #include "generic.h"
 #include "atod-som9260m.h"
 
-
 /*
  * Serial port configuration.
  *    0 .. 5 = USART0 .. USART5
@@ -376,21 +375,45 @@ static inline void at91_add_device_ecore
 
 /************************************************************/
 #ifdef CONFIG_RTSCLS
+#define GPIOBIT			0
+#define AUTORTSBIT		1
+#define GPIOMASK		(1<<GPIOBIT)
+#define AUTORTSMASK		(1<<AUTORTSBIT)
+#define RS485CHANNEL 	1
 
+/**
+ * set the rts line manually or put it in auto mode.
+ * bit 1 (0x02) is the auto rts control 0-off 1-on
+ * bit 0 (0x01) is the state of the pin, this cannot be set manually while in auto mode.
+ */
 static int rts_data_write(struct gpio_s *gpio,gpio_data data){
-	at91_set_gpio_output(AT91_PIN_PB28,(char)data);
+	if(data&AUTORTSMASK){
+		at91_set_A_periph(AT91_PIN_PB28, 1);//return RTS to primary functionality
+		at91_auto485_serial(RS485CHANNEL,1);//call down into the driver to enable RTS auto toggle
+		}
+	else {
+		at91_auto485_serial(RS485CHANNEL,0);//Auto control off
+		at91_set_gpio_output(AT91_PIN_PB28,(char)(data&GPIOMASK));//set data manually
+	}
 	return 0;
 }
 
-static gpio_data rts_data_read(struct gpio_s *gpio)
-	return at91_get_gpio_value(AT91_PIN_PB28);
+/**
+ * returns the current auto flow control state and 
+ * state of the pins by reading the hardware registers.
+ */
+static gpio_data rts_data_read(struct gpio_s *gpio){
+	return (at91_get_gpio_value(AT91_PIN_PB28)|(at91_auto485_serial(RS485CHANNEL,2)<<AUTORTSBIT));
 }
 
-static inline void som9260m_rtscls(void){
+/**
+ * Create gpio rts interface through boardspec
+ */
+static inline struct class_device *som9260m_rtscls(void){
 	gpio_t *gpio = kmalloc(sizeof(gpio_t),GFP_KERNEL);
 	memset(gpio,0,sizeof(gpio_t));
 	at91_set_gpio_output(AT91_PIN_PB28,1);//rts line
-	gpio->name = "rtstest";
+	gpio->name = "rtsctl";
 	gpio->subclass = GPIO_SUBCLASS;
 	gpio->data_write = rts_data_write;
 	gpio->data_read = rts_data_read;
@@ -411,7 +434,7 @@ static gpio_data physw_read(struct gpio_
 	return at91_get_gpio_value(AT91_PIN_PA31);
 }
 
-static inline void som9260m_physw(void){
+static inline struct class_device *som9260m_physw(void){
 	gpio_t *gpio = kmalloc(sizeof(gpio_t),GFP_KERNEL);
 	memset(gpio,0,sizeof(gpio_t));
 	at91_set_gpio_output(AT91_PIN_PB28,1);//rts line
diff -uprN linux-2.6.20-at92_e1.3.1/arch/arm/mach-at91rm9200/generic.h linux-2.6.20.AT91_svn/arch/arm/mach-at91rm9200/generic.h
--- linux-2.6.20-at92_e1.3.1/arch/arm/mach-at91rm9200/generic.h	2007-11-08 10:42:36.000000000 -0500
+++ linux-2.6.20.AT91_svn/arch/arm/mach-at91rm9200/generic.h	2007-10-31 12:12:05.000000000 -0400
@@ -38,6 +38,13 @@ extern void at91_irq_resume(void);
 extern int at91_self_refresh(unsigned state);//NZG
 extern int at91_lp_disable(unsigned state);
 
+/*Uarts*/
+extern int at91_auto485_serial(int channel,int fos);
+
+/*LEDs*/
+int som9260m_led_init(void);
+struct class_device *som9260m_led_class_create(const char *name);
+
  /* GPIO */
 #define AT91RM9200_PQFP		3	/* AT91RM9200 PQFP package has 3 banks */
 #define AT91RM9200_BGA		4	/* AT91RM9200 BGA package has 4 banks */
diff -uprN linux-2.6.20-at92_e1.3.1/drivers/serial/atmel_serial.c linux-2.6.20.AT91_svn/drivers/serial/atmel_serial.c
--- linux-2.6.20-at92_e1.3.1/drivers/serial/atmel_serial.c	2007-11-08 10:42:35.000000000 -0500
+++ linux-2.6.20.AT91_svn/drivers/serial/atmel_serial.c	2007-10-31 12:12:05.000000000 -0400
@@ -1218,6 +1218,21 @@ static int __devexit atmel_serial_remove
 	return ret;
 }
 
+int atmel_auto485(struct uart_port *port,int fos){
+	unsigned int mode = UART_GET_MR(port);
+	
+	//printk("setting auto rts, current mode is %x\n",mode);
+	
+	if(fos==2)
+		return(((mode&ATMEL_US_USMODE_RS485)!=0));//return status option
+	mode = (fos ? (mode|ATMEL_US_USMODE_RS485):(mode&(~ATMEL_US_USMODE_RS485)));
+	
+	//printk("setting new mode to %x\n",mode);
+	UART_PUT_MR(port, mode);
+	return fos;
+}
+
+
 static struct platform_driver atmel_serial_driver = {
 	.probe		= atmel_serial_probe,
 	.remove		= __devexit_p(atmel_serial_remove),
diff -uprN linux-2.6.20-at92_e1.3.1/include/asm-arm/mach/serial_at91.h linux-2.6.20.AT91_svn/include/asm-arm/mach/serial_at91.h
--- linux-2.6.20-at92_e1.3.1/include/asm-arm/mach/serial_at91.h	2007-02-04 13:44:54.000000000 -0500
+++ linux-2.6.20.AT91_svn/include/asm-arm/mach/serial_at91.h	2007-10-31 12:12:05.000000000 -0400
@@ -26,8 +26,10 @@ struct atmel_port_fns {
 
 #if defined(CONFIG_SERIAL_ATMEL)
 void atmel_register_uart_fns(struct atmel_port_fns *fns);
+int atmel_auto485(struct uart_port *port,int fos);//auto 485 off/on/status
 #else
 #define atmel_register_uart_fns(fns) do { } while (0)
+int atmel_auto485(struct uart_port *port,int ofs) do { } while (0)
 #endif
 
 
