--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -214,6 +214,34 @@
 				at91_set_gpio_value(AT91_PIN_PA21, 0);
 			else
 				at91_set_gpio_value(AT91_PIN_PA21, 1);
+
+			/*
+ 			 * FDL VersaLink adds GPIOS to provide full modem 
+			 * control on USART 0 - Drive DTR and RI pins manually
+ 			 */
+			if (mctrl & TIOCM_DTR)
+				at91_set_gpio_value(AT91_PIN_PB6, 0);
+			else
+				at91_set_gpio_value(AT91_PIN_PB6, 1);
+			if (mctrl & TIOCM_RI)
+				at91_set_gpio_value(AT91_PIN_PB7, 0);
+			else
+				at91_set_gpio_value(AT91_PIN_PB7, 1);
+		}
+
+		/*
+		 * FDL VersaLink adds GPIOS to provide full modem control on
+		 * USART 3 - Drive DTR and RI pins manually
+		 */
+		if (port->mapbase == AT91RM9200_BASE_US3) {
+			if (mctrl & TIOCM_DTR)
+				at91_set_gpio_value(AT91_PIN_PB29, 0);
+			else
+				at91_set_gpio_value(AT91_PIN_PB29, 1);
+			if (mctrl & TIOCM_RI)
+				at91_set_gpio_value(AT91_PIN_PB2, 0);
+			else
+				at91_set_gpio_value(AT91_PIN_PB2, 1);
 		}
 	}
 #endif
@@ -251,8 +279,10 @@
 	/*
 	 * The control signals are active low.
 	 */
-	if (!(status & ATMEL_US_DCD))
-		ret |= TIOCM_CD;
+
+	if (!(port->mapbase == AT91RM9200_BASE_US0 || port->mapbase == AT91RM9200_BASE_US3))
+		if (!(status & ATMEL_US_DCD))
+			ret |= TIOCM_CD;
 	if (!(status & ATMEL_US_CTS))
 		ret |= TIOCM_CTS;
 	if (!(status & ATMEL_US_DSR))
@@ -260,6 +290,16 @@
 	if (!(status & ATMEL_US_RI))
 		ret |= TIOCM_RI;
 
+	/*
+ 	 * Read the GPIO's for the FDL VersaLink special case
+	 */
+	if (port->mapbase == AT91RM9200_BASE_US0)
+		if (!(at91_get_gpio_value(AT91_PIN_PA19)))
+			ret |= TIOCM_CD;
+	if (port->mapbase == AT91RM9200_BASE_US3)
+		if (!(at91_get_gpio_value(AT91_PIN_PA24)))
+			ret |= TIOCM_CD;
+
 	return ret;
 }
 
@@ -453,6 +493,34 @@
 }
 
 /*
+ * USART0 DCD Interrupt handler
+ */
+
+static irqreturn_t atmel_u0_DCD_interrupt(int irq, void *dev_id)
+{
+	struct uart_port *port = dev_id;
+	int status = at91_get_gpio_value(irq);
+
+	uart_handle_dcd_change(port, !(status));
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * USART3 DCD Interrupt handler
+ */
+
+static irqreturn_t atmel_u3_DCD_interrupt(int irq, void *dev_id)
+{
+	struct uart_port *port = dev_id;
+	int status = at91_get_gpio_value(irq);
+
+	uart_handle_dcd_change(port, !(status));
+
+	return IRQ_HANDLED;
+}
+
+/*
  * receive interrupt handler.
  */
 static void
@@ -815,6 +883,23 @@
 		return retval;
 	}
 
+        if (port->mapbase == AT91RM9200_BASE_US0) {
+                retval = request_irq(AT91_PIN_PA19, atmel_u0_DCD_interrupt, 0, "atmel_serial", port);
+                if (retval) {
+                        printk("atmel_serial: atmel_startup - Can't get u0DCD irq\n");
+                        free_irq(port->irq, port);
+                        return retval;
+                }
+        }
+        if (port->mapbase == AT91RM9200_BASE_US3) {
+                retval = request_irq(AT91_PIN_PA24, atmel_u3_DCD_interrupt, 0, "atmel_serial", port);
+                if (retval) {
+                        printk("atmel_serial: atmel_startup - Can't get u3DCD irq\n");
+                        free_irq(port->irq, port);
+                        return retval;
+                }
+        }
+
 	/*
 	 * Initialize DMA (if necessary)
 	 */
@@ -834,6 +919,10 @@
 					kfree(atmel_port->pdc_rx[0].buf);
 				}
 				free_irq(port->irq, port);
+				if (port->mapbase == AT91RM9200_BASE_US0)
+					free_irq(AT91_PIN_PA19, port);
+				if (port->mapbase == AT91RM9200_BASE_US3)
+					free_irq(AT91_PIN_PA24, port);
 				return -ENOMEM;
 			}
 			pdc->dma_addr = dma_map_single(port->dev,
@@ -873,7 +962,11 @@
 		retval = atmel_open_hook(port);
 		if (retval) {
 			free_irq(port->irq, port);
-			return retval;
+			if (port->mapbase == AT91RM9200_BASE_US0)
+				free_irq(AT91_PIN_PA19, port);
+			if (port->mapbase == AT91RM9200_BASE_US3)
+				free_irq(AT91_PIN_PA24, port);
+ 			return retval;
 		}
 	}
 
@@ -947,6 +1040,10 @@
 	 * Free the interrupt
 	 */
 	free_irq(port->irq, port);
+	if (port->mapbase == AT91RM9200_BASE_US0)
+		free_irq(AT91_PIN_PA19, port);
+	if (port->mapbase == AT91RM9200_BASE_US3)
+		free_irq(AT91_PIN_PA24, port);
 
 	/*
 	 * If there is a specific "close" function (to unregister
