diff options
Diffstat (limited to 'target/linux/at91/patches-2.6.21/008-fdl-serial.patch')
-rw-r--r-- | target/linux/at91/patches-2.6.21/008-fdl-serial.patch | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/target/linux/at91/patches-2.6.21/008-fdl-serial.patch b/target/linux/at91/patches-2.6.21/008-fdl-serial.patch new file mode 100644 index 0000000000..42589197be --- /dev/null +++ b/target/linux/at91/patches-2.6.21/008-fdl-serial.patch @@ -0,0 +1,160 @@ +--- linux-2.6.21.1.orig/drivers/serial/atmel_serial.c 2007-05-28 12:22:29.000000000 +0200 ++++ linux-2.6.21.1/drivers/serial/atmel_serial.c 2007-05-28 16:39:09.000000000 +0200 +@@ -174,7 +174,35 @@ + 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 + +@@ -211,8 +239,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)) +@@ -220,6 +250,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; + } + +@@ -511,6 +551,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; ++} ++ ++/* + * Interrupt handler + */ + static irqreturn_t atmel_interrupt(int irq, void *dev_id) +@@ -587,6 +655,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) + */ +@@ -603,6 +688,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, pdc->buf, PDC_BUFFER_SIZE, DMA_FROM_DEVICE); +@@ -636,6 +725,10 @@ + retval = atmel_open_hook(port); + if (retval) { + 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 retval; + } + } +@@ -701,6 +794,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 |