mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-11-03 14:34:27 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			162 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			162 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
--- a/drivers/serial/atmel_serial.c
 | 
						|
+++ b/drivers/serial/atmel_serial.c
 | 
						|
@@ -214,6 +214,34 @@ static void atmel_set_mctrl(struct uart_
 | 
						|
 				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 @@ static u_int atmel_get_mctrl(struct uart
 | 
						|
 	/*
 | 
						|
 	 * 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 @@ static u_int atmel_get_mctrl(struct uart
 | 
						|
 	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 @@ static void atmel_tx_chars(struct uart_p
 | 
						|
 }
 | 
						|
 
 | 
						|
 /*
 | 
						|
+ * 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 @@ static int atmel_startup(struct uart_por
 | 
						|
 		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 @@ static int atmel_startup(struct uart_por
 | 
						|
 					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 @@ static int atmel_startup(struct uart_por
 | 
						|
 		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 @@ static void atmel_shutdown(struct uart_p
 | 
						|
 	 * 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
 |