All of lore.kernel.org
 help / color / mirror / Atom feed
diff for duplicates of <4BA335A8.1000205@evidence.eu.com>

diff --git a/a/1.txt b/N1/1.txt
index e90b14f..c0c8fe0 100644
--- a/a/1.txt
+++ b/N1/1.txt
@@ -9,11 +9,3 @@ Feedback (comments, suggestions, further testing) is welcome.
 Many thanks,
 
            Claudio
-
--------------- next part --------------
-A non-text attachment was scrubbed...
-Name: atmel_serial_rs485.patch
-Type: text/x-patch
-Size: 15692 bytes
-Desc: not available
-URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20100319/fbb49b36/attachment-0001.bin>
diff --git a/N1/2.hdr b/N1/2.hdr
new file mode 100644
index 0000000..ff1d333
--- /dev/null
+++ b/N1/2.hdr
@@ -0,0 +1,5 @@
+Content-Type: text/x-patch;
+ name="atmel_serial_rs485.patch"
+Content-Transfer-Encoding: 7bit
+Content-Disposition: inline;
+ filename="atmel_serial_rs485.patch"
diff --git a/N1/2.txt b/N1/2.txt
new file mode 100644
index 0000000..9d8b221
--- /dev/null
+++ b/N1/2.txt
@@ -0,0 +1,501 @@
+atmel_serial: RS485 support
+
+Signed-off-by: Claudio Scordino <claudio@evidence.eu.com>
+Signed-off-by: Michael Trimarchi <michael@evidence.eu.com>
+Signed-off-by: Rick Bronson <rick@efn.org>
+Signed-off-by: Sebastian Heutling <Sebastian.Heutling@who-ing.de>
+---
+ arch/arm/include/asm/ioctls.h           |    2 +
+ arch/arm/mach-at91/include/mach/board.h |    4 +
+ drivers/serial/atmel_serial.c           |  247 ++++++++++++++++++++++++++-----
+ 3 files changed, 218 insertions(+), 35 deletions(-)
+
+diff --git a/arch/arm/include/asm/ioctls.h b/arch/arm/include/asm/ioctls.h
+index a91d8a1..82f2177 100644
+--- a/arch/arm/include/asm/ioctls.h
++++ b/arch/arm/include/asm/ioctls.h
+@@ -70,6 +70,8 @@
+ #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
+ #define FIOQSIZE	0x545E
+ 
++#define TIOCSRS485	0x5461
++
+ /* Used for packet mode */
+ #define TIOCPKT_DATA		 0
+ #define TIOCPKT_FLUSHREAD	 1
+diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
+index ceaec6c..21f1308 100644
+--- a/arch/arm/mach-at91/include/mach/board.h
++++ b/arch/arm/mach-at91/include/mach/board.h
+@@ -39,6 +39,7 @@
+ #include <linux/usb/atmel_usba_udc.h>
+ #include <linux/atmel-mci.h>
+ #include <sound/atmel-ac97c.h>
++#include <linux/serial.h>
+ 
+  /* USB Device */
+ struct at91_udc_data {
+@@ -146,6 +147,9 @@ struct atmel_uart_data {
+ 	short		use_dma_tx;	/* use transmit DMA? */
+ 	short		use_dma_rx;	/* use receive DMA? */
+ 	void __iomem	*regs;		/* virtual base address, if any */
++	struct serial_rs485	rs485;		/* this flag specifies
++						   if the uart must be used
++						   as RS485 */
+ };
+ extern void __init at91_add_device_serial(void);
+ 
+diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
+index 2c9bf9b..21bf3a8 100644
+--- a/drivers/serial/atmel_serial.c
++++ b/drivers/serial/atmel_serial.c
+@@ -38,6 +38,7 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/atmel_pdc.h>
+ #include <linux/atmel_serial.h>
++#include <linux/uaccess.h>
+ 
+ #include <asm/io.h>
+ 
+@@ -59,6 +60,9 @@
+ 
+ #include <linux/serial_core.h>
+ 
++static void atmel_start_rx(struct uart_port *port);
++static void atmel_stop_rx(struct uart_port *port);
++
+ #ifdef CONFIG_SERIAL_ATMEL_TTYAT
+ 
+ /* Use device name ttyAT, major 204 and minor 154-169.  This is necessary if we
+@@ -93,6 +97,7 @@
+ #define UART_GET_BRGR(port)	__raw_readl((port)->membase + ATMEL_US_BRGR)
+ #define UART_PUT_BRGR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_BRGR)
+ #define UART_PUT_RTOR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_RTOR)
++#define UART_PUT_TTGR(port, v)	__raw_writel(v, (port)->membase + ATMEL_US_TTGR)
+ 
+  /* PDC registers */
+ #define UART_PUT_PTCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)
+@@ -147,6 +152,16 @@ struct atmel_uart_port {
+ 	unsigned int		irq_status_prev;
+ 
+ 	struct circ_buf		rx_ring;
++
++	struct serial_rs485	rs485;		/* this flag specifies
++						   if the uart must be used
++						   as RS485 */
++	/* Fields related to interrupts:
++	   if (rs485)		= ATMEL_US_TXEMPTY
++	   else if (use_dma_tx)	= ATMEL_US_ENDTX | ATMEL_US_TXBUFE
++	   else			= ATMEL_US_TXRDY;
++	 */
++	unsigned int		tx_done_mask;
+ };
+ 
+ static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
+@@ -187,6 +202,85 @@ static bool atmel_use_dma_tx(struct uart_port *port)
+ }
+ #endif
+ 
++/* Enable or disable the rs485 support */
++void atmel_enable_disable_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
++{
++	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
++	unsigned long flags;
++	unsigned int mode;
++
++	spin_lock_irqsave(&port->lock, flags);
++
++	mode = UART_GET_MR(port);
++
++	/* Resetting serial mode to RS232 (0x0) */
++	mode &= ~ATMEL_US_USMODE;
++
++	atmel_port->rs485 = *rs485conf;
++
++	if (!(rs485conf->flags & SER_RS485_ENABLED)) {
++		dev_dbg(port->dev, "Setting UART to RS232\n");
++		if (atmel_use_dma_tx(port))
++			atmel_port->tx_done_mask = ATMEL_US_ENDTX | ATMEL_US_TXBUFE;
++		else
++			atmel_port->tx_done_mask = ATMEL_US_TXRDY;
++	} else {
++		dev_dbg(port->dev, "Setting UART to RS485\n");
++		atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
++		UART_PUT_TTGR(port, rs485conf->delay_rts_before_send);
++		mode |= ATMEL_US_USMODE_RS485;
++	}
++	UART_PUT_MR(port, mode);
++
++	spin_unlock_irqrestore(&port->lock, flags);
++}
++
++
++static ssize_t show_rs485(struct device *dev, struct device_attribute *attr, \
++			   char *buf)
++{
++	struct platform_device *pdev = to_platform_device(dev);
++	struct uart_port *port = platform_get_drvdata(pdev);
++	unsigned int current_mode;
++
++	current_mode = UART_GET_MR(port);
++	current_mode &= ATMEL_US_USMODE;
++	return snprintf(buf, PAGE_SIZE, "%u\n", current_mode);
++}
++
++static ssize_t set_rs485(struct device *dev, struct device_attribute *attr, \
++			  const char *buf, size_t len)
++{
++	struct platform_device *pdev = to_platform_device(dev);
++	struct uart_port *port = platform_get_drvdata(pdev);
++	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
++	struct serial_rs485 rs485conf = atmel_port->rs485;
++	unsigned int value;
++
++	if (buf == NULL)
++		goto err;
++
++	value = simple_strtoul(buf, NULL, 10);
++
++	if ((value != 0) && (value != 1))
++		goto err;
++
++	if (!value) {
++		rs485conf.flags &= ~(SER_RS485_ENABLED);
++	} else {
++		rs485conf.flags |= SER_RS485_ENABLED;
++		/* 0x4 is the normal reset value. */
++		rs485conf.delay_rts_before_send = 0x00000004;
++	}
++
++	atmel_enable_disable_rs485(port, &rs485conf);
++
++err:
++	return strnlen(buf, PAGE_SIZE);
++}
++
++static DEVICE_ATTR(rs485, 0644, show_rs485, set_rs485);
++
+ /*
+  * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty.
+  */
+@@ -202,6 +296,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
+ {
+ 	unsigned int control = 0;
+ 	unsigned int mode;
++	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+ 
+ #ifdef CONFIG_ARCH_AT91RM9200
+ 	if (cpu_is_at91rm9200()) {
+@@ -236,6 +331,16 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
+ 		mode |= ATMEL_US_CHMODE_LOC_LOOP;
+ 	else
+ 		mode |= ATMEL_US_CHMODE_NORMAL;
++
++	/* Resetting serial mode to RS232 (0x0) */
++	mode &= ~ATMEL_US_USMODE;
++
++	if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
++		dev_dbg(port->dev, "Keeping UART to RS485\n");
++		UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send);
++		mode |= ATMEL_US_USMODE_RS485;
++	} else
++		dev_dbg(port->dev, "Keeping UART to RS232\n");
+ 	UART_PUT_MR(port, mode);
+ }
+ 
+@@ -268,12 +373,17 @@ static u_int atmel_get_mctrl(struct uart_port *port)
+  */
+ static void atmel_stop_tx(struct uart_port *port)
+ {
++	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
++
+ 	if (atmel_use_dma_tx(port)) {
+ 		/* disable PDC transmit */
+ 		UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
+-		UART_PUT_IDR(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE);
+-	} else
+-		UART_PUT_IDR(port, ATMEL_US_TXRDY);
++	}
++	/* Disable interrupts */
++	UART_PUT_IDR(port, atmel_port->tx_done_mask);
++
++	if (atmel_port->rs485.flags & SER_RS485_ENABLED)
++		atmel_start_rx(port);
+ }
+ 
+ /*
+@@ -281,17 +391,22 @@ static void atmel_stop_tx(struct uart_port *port)
+  */
+ static void atmel_start_tx(struct uart_port *port)
+ {
++	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
++
+ 	if (atmel_use_dma_tx(port)) {
+ 		if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN)
+ 			/* The transmitter is already running.  Yes, we
+ 			   really need this.*/
+ 			return;
+ 
+-		UART_PUT_IER(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE);
++		if (atmel_port->rs485.flags & SER_RS485_ENABLED)
++			atmel_stop_rx(port);
++
+ 		/* re-enable PDC transmit */
+ 		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
+-	} else
+-		UART_PUT_IER(port, ATMEL_US_TXRDY);
++	}
++	/* Enable interrupts */
++	UART_PUT_IER(port, atmel_port->tx_done_mask);
+ }
+ 
+ /*
+@@ -302,12 +417,28 @@ static void atmel_stop_rx(struct uart_port *port)
+ 	if (atmel_use_dma_rx(port)) {
+ 		/* disable PDC receive */
+ 		UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS);
+-		UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
++		UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT | port->read_status_mask);
+ 	} else
+ 		UART_PUT_IDR(port, ATMEL_US_RXRDY);
+ }
+ 
+ /*
++ * start receiving - port is in process of being opened.
++ */
++static void atmel_start_rx(struct uart_port *port)
++{
++	UART_PUT_CR(port, ATMEL_US_RSTSTA);  /* reset status and receiver */
++
++	if (atmel_use_dma_rx(port)) {
++		/* enable PDC controller */
++		UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT | port->read_status_mask);
++		UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
++	} else
++		UART_PUT_IER(port, ATMEL_US_RXRDY);
++}
++
++
++/*
+  * Enable modem status interrupts
+  */
+ static void atmel_enable_ms(struct uart_port *port)
+@@ -428,8 +559,9 @@ static void atmel_rx_chars(struct uart_port *port)
+ static void atmel_tx_chars(struct uart_port *port)
+ {
+ 	struct circ_buf *xmit = &port->state->xmit;
++	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+ 
+-	if (port->x_char && UART_GET_CSR(port) & ATMEL_US_TXRDY) {
++	if (port->x_char && UART_GET_CSR(port) & atmel_port->tx_done_mask) {
+ 		UART_PUT_CHAR(port, port->x_char);
+ 		port->icount.tx++;
+ 		port->x_char = 0;
+@@ -437,7 +569,7 @@ static void atmel_tx_chars(struct uart_port *port)
+ 	if (uart_circ_empty(xmit) || uart_tx_stopped(port))
+ 		return;
+ 
+-	while (UART_GET_CSR(port) & ATMEL_US_TXRDY) {
++	while (UART_GET_CSR(port) & atmel_port->tx_done_mask) {
+ 		UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
+ 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ 		port->icount.tx++;
+@@ -449,7 +581,8 @@ static void atmel_tx_chars(struct uart_port *port)
+ 		uart_write_wakeup(port);
+ 
+ 	if (!uart_circ_empty(xmit))
+-		UART_PUT_IER(port, ATMEL_US_TXRDY);
++		/* Enable interrupts */
++		UART_PUT_IER(port, atmel_port->tx_done_mask);
+ }
+ 
+ /*
+@@ -501,18 +634,10 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending)
+ {
+ 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+ 
+-	if (atmel_use_dma_tx(port)) {
+-		/* PDC transmit */
+-		if (pending & (ATMEL_US_ENDTX | ATMEL_US_TXBUFE)) {
+-			UART_PUT_IDR(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE);
+-			tasklet_schedule(&atmel_port->tasklet);
+-		}
+-	} else {
+-		/* Interrupt transmit */
+-		if (pending & ATMEL_US_TXRDY) {
+-			UART_PUT_IDR(port, ATMEL_US_TXRDY);
+-			tasklet_schedule(&atmel_port->tasklet);
+-		}
++	if (pending & atmel_port->tx_done_mask) {
++		/* Either PDC or interrupt transmission */
++		UART_PUT_IDR(port, atmel_port->tx_done_mask);
++		tasklet_schedule(&atmel_port->tasklet);
+ 	}
+ }
+ 
+@@ -590,9 +715,15 @@ static void atmel_tx_dma(struct uart_port *port)
+ 
+ 		UART_PUT_TPR(port, pdc->dma_addr + xmit->tail);
+ 		UART_PUT_TCR(port, count);
+-		/* re-enable PDC transmit and interrupts */
++		/* re-enable PDC transmit */
+ 		UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
+-		UART_PUT_IER(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE);
++		/* Enable interrupts */
++		UART_PUT_IER(port, atmel_port->tx_done_mask);
++	} else {
++		if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
++			/* DMA done, stop TX, start RX for RS485 */
++			atmel_start_rx(port);
++		}
+ 	}
+ 
+ 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+@@ -1017,6 +1148,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
+ {
+ 	unsigned long flags;
+ 	unsigned int mode, imr, quot, baud;
++	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+ 
+ 	/* Get current mode register */
+ 	mode = UART_GET_MR(port) & ~(ATMEL_US_USCLKS | ATMEL_US_CHRL
+@@ -1115,6 +1247,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
+ 	/* disable receiver and transmitter */
+ 	UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
+ 
++	/* Resetting serial mode to RS232 (0x0) */
++	mode &= ~ATMEL_US_USMODE;
++
++	if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
++		dev_dbg(port->dev, "Keeping UART to RS485\n");
++		UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send);
++		mode |= ATMEL_US_USMODE_RS485;
++	} else
++		dev_dbg(port->dev, "Keeping UART to RS232\n");
++
+ 	/* set the parity, stop bits and data size */
+ 	UART_PUT_MR(port, mode);
+ 
+@@ -1231,6 +1373,31 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
+ }
+ #endif
+ 
++static int atmel_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)
++{
++
++	switch (cmd) {
++	case TIOCSRS485:
++		{
++			struct serial_rs485 rs485conf;
++			if (copy_from_user(&rs485conf, (struct serial_rs485 *) arg,
++						sizeof(rs485conf)))
++				return -EFAULT;
++
++			dev_dbg(port->dev, "enable e/o disable rs485\n");
++
++			atmel_enable_disable_rs485(port, &rs485conf);
++		}
++		break;
++
++	default:
++		return -ENOIOCTLCMD;
++	}
++	return 0;
++}
++
++
++
+ static struct uart_ops atmel_pops = {
+ 	.tx_empty	= atmel_tx_empty,
+ 	.set_mctrl	= atmel_set_mctrl,
+@@ -1250,6 +1417,7 @@ static struct uart_ops atmel_pops = {
+ 	.config_port	= atmel_config_port,
+ 	.verify_port	= atmel_verify_port,
+ 	.pm		= atmel_serial_pm,
++	.ioctl		= atmel_ioctl,
+ #ifdef CONFIG_CONSOLE_POLL
+ 	.poll_get_char	= atmel_poll_get_char,
+ 	.poll_put_char	= atmel_poll_put_char,
+@@ -1265,13 +1433,12 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
+ 	struct uart_port *port = &atmel_port->uart;
+ 	struct atmel_uart_data *data = pdev->dev.platform_data;
+ 
+-	port->iotype	= UPIO_MEM;
+-	port->flags	= UPF_BOOT_AUTOCONF;
+-	port->ops	= &atmel_pops;
+-	port->fifosize	= 1;
+-	port->line	= pdev->id;
+-	port->dev	= &pdev->dev;
+-
++	port->iotype		= UPIO_MEM;
++	port->flags		= UPF_BOOT_AUTOCONF;
++	port->ops		= &atmel_pops;
++	port->fifosize		= 1;
++	port->line		= pdev->id;
++	port->dev		= &pdev->dev;
+ 	port->mapbase	= pdev->resource[0].start;
+ 	port->irq	= pdev->resource[1].start;
+ 
+@@ -1299,8 +1466,15 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
+ 
+ 	atmel_port->use_dma_rx = data->use_dma_rx;
+ 	atmel_port->use_dma_tx = data->use_dma_tx;
+-	if (atmel_use_dma_tx(port))
++	atmel_port->rs485	= data->rs485;
++	/* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */
++	if (atmel_port->rs485.flags & SER_RS485_ENABLED)
++		atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
++	else if (atmel_use_dma_tx(port)) {
+ 		port->fifosize = PDC_BUFFER_SIZE;
++		atmel_port->tx_done_mask = ATMEL_US_ENDTX | ATMEL_US_TXBUFE;
++	} else
++		atmel_port->tx_done_mask = ATMEL_US_TXRDY;
+ }
+ 
+ /*
+@@ -1334,6 +1508,7 @@ static void atmel_console_putchar(struct uart_port *port, int ch)
+ static void atmel_console_write(struct console *co, const char *s, u_int count)
+ {
+ 	struct uart_port *port = &atmel_ports[co->index].uart;
++	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+ 	unsigned int status, imr;
+ 	unsigned int pdc_tx;
+ 
+@@ -1341,7 +1516,7 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
+ 	 * First, save IMR and then disable interrupts
+ 	 */
+ 	imr = UART_GET_IMR(port);
+-	UART_PUT_IDR(port, ATMEL_US_RXRDY | ATMEL_US_TXRDY);
++	UART_PUT_IDR(port, ATMEL_US_RXRDY | atmel_port->tx_done_mask);
+ 
+ 	/* Store PDC transmit status and disable it */
+ 	pdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN;
+@@ -1355,7 +1530,7 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
+ 	 */
+ 	do {
+ 		status = UART_GET_CSR(port);
+-	} while (!(status & ATMEL_US_TXRDY));
++	} while (!(status & atmel_port->tx_done_mask));
+ 
+ 	/* Restore PDC transmit status */
+ 	if (pdc_tx)
+@@ -1587,7 +1762,7 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev)
+ 	device_init_wakeup(&pdev->dev, 1);
+ 	platform_set_drvdata(pdev, port);
+ 
+-	return 0;
++	return device_create_file(&(pdev->dev), &dev_attr_rs485);
+ 
+ err_add_port:
+ 	kfree(port->rx_ring.buf);
+@@ -1619,6 +1794,8 @@ static int __devexit atmel_serial_remove(struct platform_device *pdev)
+ 
+ 	clk_put(atmel_port->clk);
+ 
++	device_remove_file(&(pdev->dev), &dev_attr_rs485);
++
+ 	return ret;
+ }
+ 
+-- 
+1.6.0.4
diff --git a/a/content_digest b/N1/content_digest
index 470739e..1a8c47f 100644
--- a/a/content_digest
+++ b/N1/content_digest
@@ -1,8 +1,15 @@
- "From\0claudio@evidence.eu.com (Claudio Scordino)\0"
+ "From\0Claudio Scordino <claudio@evidence.eu.com>\0"
  "Subject\0[PATCH] atmel_serial: Atmel RS485 support\0"
  "Date\0Fri, 19 Mar 2010 09:28:24 +0100\0"
- "To\0linux-arm-kernel@lists.infradead.org\0"
- "\00:1\0"
+ "To\0Linux Kernel <linux-kernel@vger.kernel.org>\0"
+ "Cc\0linux-arm-kernel <linux-arm-kernel@lists.infradead.org>"
+  John Nicholls <john@thinlinx.com>
+  Rick Bronson <rick@efn.org>
+  Sebastian Heutling <Sebastian.Heutling@who-ing.de>
+  michael trimarchi <michael@evidence.eu.com>
+  alan@lxorguk.ukuu.org.uk
+ " kernel@arm.linux.org.uk\0"
+ "\01:1\0"
  "b\0"
  "Hi all,\n"
  "\n"
@@ -14,14 +21,510 @@
  "\n"
  "Many thanks,\n"
  "\n"
- "           Claudio\n"
+            Claudio
+ "\01:2\0"
+ "fn\0atmel_serial_rs485.patch\0"
+ "b\0"
+ "atmel_serial: RS485 support\n"
+ "\n"
+ "Signed-off-by: Claudio Scordino <claudio@evidence.eu.com>\n"
+ "Signed-off-by: Michael Trimarchi <michael@evidence.eu.com>\n"
+ "Signed-off-by: Rick Bronson <rick@efn.org>\n"
+ "Signed-off-by: Sebastian Heutling <Sebastian.Heutling@who-ing.de>\n"
+ "---\n"
+ " arch/arm/include/asm/ioctls.h           |    2 +\n"
+ " arch/arm/mach-at91/include/mach/board.h |    4 +\n"
+ " drivers/serial/atmel_serial.c           |  247 ++++++++++++++++++++++++++-----\n"
+ " 3 files changed, 218 insertions(+), 35 deletions(-)\n"
  "\n"
- "-------------- next part --------------\n"
- "A non-text attachment was scrubbed...\n"
- "Name: atmel_serial_rs485.patch\n"
- "Type: text/x-patch\n"
- "Size: 15692 bytes\n"
- "Desc: not available\n"
- URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20100319/fbb49b36/attachment-0001.bin>
+ "diff --git a/arch/arm/include/asm/ioctls.h b/arch/arm/include/asm/ioctls.h\n"
+ "index a91d8a1..82f2177 100644\n"
+ "--- a/arch/arm/include/asm/ioctls.h\n"
+ "+++ b/arch/arm/include/asm/ioctls.h\n"
+ "@@ -70,6 +70,8 @@\n"
+ " #define TIOCGICOUNT\t0x545D\t/* read serial port inline interrupt counts */\n"
+ " #define FIOQSIZE\t0x545E\n"
+ " \n"
+ "+#define TIOCSRS485\t0x5461\n"
+ "+\n"
+ " /* Used for packet mode */\n"
+ " #define TIOCPKT_DATA\t\t 0\n"
+ " #define TIOCPKT_FLUSHREAD\t 1\n"
+ "diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h\n"
+ "index ceaec6c..21f1308 100644\n"
+ "--- a/arch/arm/mach-at91/include/mach/board.h\n"
+ "+++ b/arch/arm/mach-at91/include/mach/board.h\n"
+ "@@ -39,6 +39,7 @@\n"
+ " #include <linux/usb/atmel_usba_udc.h>\n"
+ " #include <linux/atmel-mci.h>\n"
+ " #include <sound/atmel-ac97c.h>\n"
+ "+#include <linux/serial.h>\n"
+ " \n"
+ "  /* USB Device */\n"
+ " struct at91_udc_data {\n"
+ "@@ -146,6 +147,9 @@ struct atmel_uart_data {\n"
+ " \tshort\t\tuse_dma_tx;\t/* use transmit DMA? */\n"
+ " \tshort\t\tuse_dma_rx;\t/* use receive DMA? */\n"
+ " \tvoid __iomem\t*regs;\t\t/* virtual base address, if any */\n"
+ "+\tstruct serial_rs485\trs485;\t\t/* this flag specifies\n"
+ "+\t\t\t\t\t\t   if the uart must be used\n"
+ "+\t\t\t\t\t\t   as RS485 */\n"
+ " };\n"
+ " extern void __init at91_add_device_serial(void);\n"
+ " \n"
+ "diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c\n"
+ "index 2c9bf9b..21bf3a8 100644\n"
+ "--- a/drivers/serial/atmel_serial.c\n"
+ "+++ b/drivers/serial/atmel_serial.c\n"
+ "@@ -38,6 +38,7 @@\n"
+ " #include <linux/dma-mapping.h>\n"
+ " #include <linux/atmel_pdc.h>\n"
+ " #include <linux/atmel_serial.h>\n"
+ "+#include <linux/uaccess.h>\n"
+ " \n"
+ " #include <asm/io.h>\n"
+ " \n"
+ "@@ -59,6 +60,9 @@\n"
+ " \n"
+ " #include <linux/serial_core.h>\n"
+ " \n"
+ "+static void atmel_start_rx(struct uart_port *port);\n"
+ "+static void atmel_stop_rx(struct uart_port *port);\n"
+ "+\n"
+ " #ifdef CONFIG_SERIAL_ATMEL_TTYAT\n"
+ " \n"
+ " /* Use device name ttyAT, major 204 and minor 154-169.  This is necessary if we\n"
+ "@@ -93,6 +97,7 @@\n"
+ " #define UART_GET_BRGR(port)\t__raw_readl((port)->membase + ATMEL_US_BRGR)\n"
+ " #define UART_PUT_BRGR(port,v)\t__raw_writel(v, (port)->membase + ATMEL_US_BRGR)\n"
+ " #define UART_PUT_RTOR(port,v)\t__raw_writel(v, (port)->membase + ATMEL_US_RTOR)\n"
+ "+#define UART_PUT_TTGR(port, v)\t__raw_writel(v, (port)->membase + ATMEL_US_TTGR)\n"
+ " \n"
+ "  /* PDC registers */\n"
+ " #define UART_PUT_PTCR(port,v)\t__raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)\n"
+ "@@ -147,6 +152,16 @@ struct atmel_uart_port {\n"
+ " \tunsigned int\t\tirq_status_prev;\n"
+ " \n"
+ " \tstruct circ_buf\t\trx_ring;\n"
+ "+\n"
+ "+\tstruct serial_rs485\trs485;\t\t/* this flag specifies\n"
+ "+\t\t\t\t\t\t   if the uart must be used\n"
+ "+\t\t\t\t\t\t   as RS485 */\n"
+ "+\t/* Fields related to interrupts:\n"
+ "+\t   if (rs485)\t\t= ATMEL_US_TXEMPTY\n"
+ "+\t   else if (use_dma_tx)\t= ATMEL_US_ENDTX | ATMEL_US_TXBUFE\n"
+ "+\t   else\t\t\t= ATMEL_US_TXRDY;\n"
+ "+\t */\n"
+ "+\tunsigned int\t\ttx_done_mask;\n"
+ " };\n"
+ " \n"
+ " static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];\n"
+ "@@ -187,6 +202,85 @@ static bool atmel_use_dma_tx(struct uart_port *port)\n"
+ " }\n"
+ " #endif\n"
+ " \n"
+ "+/* Enable or disable the rs485 support */\n"
+ "+void atmel_enable_disable_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)\n"
+ "+{\n"
+ "+\tstruct atmel_uart_port *atmel_port = to_atmel_uart_port(port);\n"
+ "+\tunsigned long flags;\n"
+ "+\tunsigned int mode;\n"
+ "+\n"
+ "+\tspin_lock_irqsave(&port->lock, flags);\n"
+ "+\n"
+ "+\tmode = UART_GET_MR(port);\n"
+ "+\n"
+ "+\t/* Resetting serial mode to RS232 (0x0) */\n"
+ "+\tmode &= ~ATMEL_US_USMODE;\n"
+ "+\n"
+ "+\tatmel_port->rs485 = *rs485conf;\n"
+ "+\n"
+ "+\tif (!(rs485conf->flags & SER_RS485_ENABLED)) {\n"
+ "+\t\tdev_dbg(port->dev, \"Setting UART to RS232\\n\");\n"
+ "+\t\tif (atmel_use_dma_tx(port))\n"
+ "+\t\t\tatmel_port->tx_done_mask = ATMEL_US_ENDTX | ATMEL_US_TXBUFE;\n"
+ "+\t\telse\n"
+ "+\t\t\tatmel_port->tx_done_mask = ATMEL_US_TXRDY;\n"
+ "+\t} else {\n"
+ "+\t\tdev_dbg(port->dev, \"Setting UART to RS485\\n\");\n"
+ "+\t\tatmel_port->tx_done_mask = ATMEL_US_TXEMPTY;\n"
+ "+\t\tUART_PUT_TTGR(port, rs485conf->delay_rts_before_send);\n"
+ "+\t\tmode |= ATMEL_US_USMODE_RS485;\n"
+ "+\t}\n"
+ "+\tUART_PUT_MR(port, mode);\n"
+ "+\n"
+ "+\tspin_unlock_irqrestore(&port->lock, flags);\n"
+ "+}\n"
+ "+\n"
+ "+\n"
+ "+static ssize_t show_rs485(struct device *dev, struct device_attribute *attr, \\\n"
+ "+\t\t\t   char *buf)\n"
+ "+{\n"
+ "+\tstruct platform_device *pdev = to_platform_device(dev);\n"
+ "+\tstruct uart_port *port = platform_get_drvdata(pdev);\n"
+ "+\tunsigned int current_mode;\n"
+ "+\n"
+ "+\tcurrent_mode = UART_GET_MR(port);\n"
+ "+\tcurrent_mode &= ATMEL_US_USMODE;\n"
+ "+\treturn snprintf(buf, PAGE_SIZE, \"%u\\n\", current_mode);\n"
+ "+}\n"
+ "+\n"
+ "+static ssize_t set_rs485(struct device *dev, struct device_attribute *attr, \\\n"
+ "+\t\t\t  const char *buf, size_t len)\n"
+ "+{\n"
+ "+\tstruct platform_device *pdev = to_platform_device(dev);\n"
+ "+\tstruct uart_port *port = platform_get_drvdata(pdev);\n"
+ "+\tstruct atmel_uart_port *atmel_port = to_atmel_uart_port(port);\n"
+ "+\tstruct serial_rs485 rs485conf = atmel_port->rs485;\n"
+ "+\tunsigned int value;\n"
+ "+\n"
+ "+\tif (buf == NULL)\n"
+ "+\t\tgoto err;\n"
+ "+\n"
+ "+\tvalue = simple_strtoul(buf, NULL, 10);\n"
+ "+\n"
+ "+\tif ((value != 0) && (value != 1))\n"
+ "+\t\tgoto err;\n"
+ "+\n"
+ "+\tif (!value) {\n"
+ "+\t\trs485conf.flags &= ~(SER_RS485_ENABLED);\n"
+ "+\t} else {\n"
+ "+\t\trs485conf.flags |= SER_RS485_ENABLED;\n"
+ "+\t\t/* 0x4 is the normal reset value. */\n"
+ "+\t\trs485conf.delay_rts_before_send = 0x00000004;\n"
+ "+\t}\n"
+ "+\n"
+ "+\tatmel_enable_disable_rs485(port, &rs485conf);\n"
+ "+\n"
+ "+err:\n"
+ "+\treturn strnlen(buf, PAGE_SIZE);\n"
+ "+}\n"
+ "+\n"
+ "+static DEVICE_ATTR(rs485, 0644, show_rs485, set_rs485);\n"
+ "+\n"
+ " /*\n"
+ "  * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty.\n"
+ "  */\n"
+ "@@ -202,6 +296,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)\n"
+ " {\n"
+ " \tunsigned int control = 0;\n"
+ " \tunsigned int mode;\n"
+ "+\tstruct atmel_uart_port *atmel_port = to_atmel_uart_port(port);\n"
+ " \n"
+ " #ifdef CONFIG_ARCH_AT91RM9200\n"
+ " \tif (cpu_is_at91rm9200()) {\n"
+ "@@ -236,6 +331,16 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)\n"
+ " \t\tmode |= ATMEL_US_CHMODE_LOC_LOOP;\n"
+ " \telse\n"
+ " \t\tmode |= ATMEL_US_CHMODE_NORMAL;\n"
+ "+\n"
+ "+\t/* Resetting serial mode to RS232 (0x0) */\n"
+ "+\tmode &= ~ATMEL_US_USMODE;\n"
+ "+\n"
+ "+\tif (atmel_port->rs485.flags & SER_RS485_ENABLED) {\n"
+ "+\t\tdev_dbg(port->dev, \"Keeping UART to RS485\\n\");\n"
+ "+\t\tUART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send);\n"
+ "+\t\tmode |= ATMEL_US_USMODE_RS485;\n"
+ "+\t} else\n"
+ "+\t\tdev_dbg(port->dev, \"Keeping UART to RS232\\n\");\n"
+ " \tUART_PUT_MR(port, mode);\n"
+ " }\n"
+ " \n"
+ "@@ -268,12 +373,17 @@ static u_int atmel_get_mctrl(struct uart_port *port)\n"
+ "  */\n"
+ " static void atmel_stop_tx(struct uart_port *port)\n"
+ " {\n"
+ "+\tstruct atmel_uart_port *atmel_port = to_atmel_uart_port(port);\n"
+ "+\n"
+ " \tif (atmel_use_dma_tx(port)) {\n"
+ " \t\t/* disable PDC transmit */\n"
+ " \t\tUART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);\n"
+ "-\t\tUART_PUT_IDR(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE);\n"
+ "-\t} else\n"
+ "-\t\tUART_PUT_IDR(port, ATMEL_US_TXRDY);\n"
+ "+\t}\n"
+ "+\t/* Disable interrupts */\n"
+ "+\tUART_PUT_IDR(port, atmel_port->tx_done_mask);\n"
+ "+\n"
+ "+\tif (atmel_port->rs485.flags & SER_RS485_ENABLED)\n"
+ "+\t\tatmel_start_rx(port);\n"
+ " }\n"
+ " \n"
+ " /*\n"
+ "@@ -281,17 +391,22 @@ static void atmel_stop_tx(struct uart_port *port)\n"
+ "  */\n"
+ " static void atmel_start_tx(struct uart_port *port)\n"
+ " {\n"
+ "+\tstruct atmel_uart_port *atmel_port = to_atmel_uart_port(port);\n"
+ "+\n"
+ " \tif (atmel_use_dma_tx(port)) {\n"
+ " \t\tif (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN)\n"
+ " \t\t\t/* The transmitter is already running.  Yes, we\n"
+ " \t\t\t   really need this.*/\n"
+ " \t\t\treturn;\n"
+ " \n"
+ "-\t\tUART_PUT_IER(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE);\n"
+ "+\t\tif (atmel_port->rs485.flags & SER_RS485_ENABLED)\n"
+ "+\t\t\tatmel_stop_rx(port);\n"
+ "+\n"
+ " \t\t/* re-enable PDC transmit */\n"
+ " \t\tUART_PUT_PTCR(port, ATMEL_PDC_TXTEN);\n"
+ "-\t} else\n"
+ "-\t\tUART_PUT_IER(port, ATMEL_US_TXRDY);\n"
+ "+\t}\n"
+ "+\t/* Enable interrupts */\n"
+ "+\tUART_PUT_IER(port, atmel_port->tx_done_mask);\n"
+ " }\n"
+ " \n"
+ " /*\n"
+ "@@ -302,12 +417,28 @@ static void atmel_stop_rx(struct uart_port *port)\n"
+ " \tif (atmel_use_dma_rx(port)) {\n"
+ " \t\t/* disable PDC receive */\n"
+ " \t\tUART_PUT_PTCR(port, ATMEL_PDC_RXTDIS);\n"
+ "-\t\tUART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);\n"
+ "+\t\tUART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT | port->read_status_mask);\n"
+ " \t} else\n"
+ " \t\tUART_PUT_IDR(port, ATMEL_US_RXRDY);\n"
+ " }\n"
+ " \n"
+ " /*\n"
+ "+ * start receiving - port is in process of being opened.\n"
+ "+ */\n"
+ "+static void atmel_start_rx(struct uart_port *port)\n"
+ "+{\n"
+ "+\tUART_PUT_CR(port, ATMEL_US_RSTSTA);  /* reset status and receiver */\n"
+ "+\n"
+ "+\tif (atmel_use_dma_rx(port)) {\n"
+ "+\t\t/* enable PDC controller */\n"
+ "+\t\tUART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT | port->read_status_mask);\n"
+ "+\t\tUART_PUT_PTCR(port, ATMEL_PDC_RXTEN);\n"
+ "+\t} else\n"
+ "+\t\tUART_PUT_IER(port, ATMEL_US_RXRDY);\n"
+ "+}\n"
+ "+\n"
+ "+\n"
+ "+/*\n"
+ "  * Enable modem status interrupts\n"
+ "  */\n"
+ " static void atmel_enable_ms(struct uart_port *port)\n"
+ "@@ -428,8 +559,9 @@ static void atmel_rx_chars(struct uart_port *port)\n"
+ " static void atmel_tx_chars(struct uart_port *port)\n"
+ " {\n"
+ " \tstruct circ_buf *xmit = &port->state->xmit;\n"
+ "+\tstruct atmel_uart_port *atmel_port = to_atmel_uart_port(port);\n"
+ " \n"
+ "-\tif (port->x_char && UART_GET_CSR(port) & ATMEL_US_TXRDY) {\n"
+ "+\tif (port->x_char && UART_GET_CSR(port) & atmel_port->tx_done_mask) {\n"
+ " \t\tUART_PUT_CHAR(port, port->x_char);\n"
+ " \t\tport->icount.tx++;\n"
+ " \t\tport->x_char = 0;\n"
+ "@@ -437,7 +569,7 @@ static void atmel_tx_chars(struct uart_port *port)\n"
+ " \tif (uart_circ_empty(xmit) || uart_tx_stopped(port))\n"
+ " \t\treturn;\n"
+ " \n"
+ "-\twhile (UART_GET_CSR(port) & ATMEL_US_TXRDY) {\n"
+ "+\twhile (UART_GET_CSR(port) & atmel_port->tx_done_mask) {\n"
+ " \t\tUART_PUT_CHAR(port, xmit->buf[xmit->tail]);\n"
+ " \t\txmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);\n"
+ " \t\tport->icount.tx++;\n"
+ "@@ -449,7 +581,8 @@ static void atmel_tx_chars(struct uart_port *port)\n"
+ " \t\tuart_write_wakeup(port);\n"
+ " \n"
+ " \tif (!uart_circ_empty(xmit))\n"
+ "-\t\tUART_PUT_IER(port, ATMEL_US_TXRDY);\n"
+ "+\t\t/* Enable interrupts */\n"
+ "+\t\tUART_PUT_IER(port, atmel_port->tx_done_mask);\n"
+ " }\n"
+ " \n"
+ " /*\n"
+ "@@ -501,18 +634,10 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending)\n"
+ " {\n"
+ " \tstruct atmel_uart_port *atmel_port = to_atmel_uart_port(port);\n"
+ " \n"
+ "-\tif (atmel_use_dma_tx(port)) {\n"
+ "-\t\t/* PDC transmit */\n"
+ "-\t\tif (pending & (ATMEL_US_ENDTX | ATMEL_US_TXBUFE)) {\n"
+ "-\t\t\tUART_PUT_IDR(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE);\n"
+ "-\t\t\ttasklet_schedule(&atmel_port->tasklet);\n"
+ "-\t\t}\n"
+ "-\t} else {\n"
+ "-\t\t/* Interrupt transmit */\n"
+ "-\t\tif (pending & ATMEL_US_TXRDY) {\n"
+ "-\t\t\tUART_PUT_IDR(port, ATMEL_US_TXRDY);\n"
+ "-\t\t\ttasklet_schedule(&atmel_port->tasklet);\n"
+ "-\t\t}\n"
+ "+\tif (pending & atmel_port->tx_done_mask) {\n"
+ "+\t\t/* Either PDC or interrupt transmission */\n"
+ "+\t\tUART_PUT_IDR(port, atmel_port->tx_done_mask);\n"
+ "+\t\ttasklet_schedule(&atmel_port->tasklet);\n"
+ " \t}\n"
+ " }\n"
+ " \n"
+ "@@ -590,9 +715,15 @@ static void atmel_tx_dma(struct uart_port *port)\n"
+ " \n"
+ " \t\tUART_PUT_TPR(port, pdc->dma_addr + xmit->tail);\n"
+ " \t\tUART_PUT_TCR(port, count);\n"
+ "-\t\t/* re-enable PDC transmit and interrupts */\n"
+ "+\t\t/* re-enable PDC transmit */\n"
+ " \t\tUART_PUT_PTCR(port, ATMEL_PDC_TXTEN);\n"
+ "-\t\tUART_PUT_IER(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE);\n"
+ "+\t\t/* Enable interrupts */\n"
+ "+\t\tUART_PUT_IER(port, atmel_port->tx_done_mask);\n"
+ "+\t} else {\n"
+ "+\t\tif (atmel_port->rs485.flags & SER_RS485_ENABLED) {\n"
+ "+\t\t\t/* DMA done, stop TX, start RX for RS485 */\n"
+ "+\t\t\tatmel_start_rx(port);\n"
+ "+\t\t}\n"
+ " \t}\n"
+ " \n"
+ " \tif (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)\n"
+ "@@ -1017,6 +1148,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,\n"
+ " {\n"
+ " \tunsigned long flags;\n"
+ " \tunsigned int mode, imr, quot, baud;\n"
+ "+\tstruct atmel_uart_port *atmel_port = to_atmel_uart_port(port);\n"
+ " \n"
+ " \t/* Get current mode register */\n"
+ " \tmode = UART_GET_MR(port) & ~(ATMEL_US_USCLKS | ATMEL_US_CHRL\n"
+ "@@ -1115,6 +1247,16 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,\n"
+ " \t/* disable receiver and transmitter */\n"
+ " \tUART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS);\n"
+ " \n"
+ "+\t/* Resetting serial mode to RS232 (0x0) */\n"
+ "+\tmode &= ~ATMEL_US_USMODE;\n"
+ "+\n"
+ "+\tif (atmel_port->rs485.flags & SER_RS485_ENABLED) {\n"
+ "+\t\tdev_dbg(port->dev, \"Keeping UART to RS485\\n\");\n"
+ "+\t\tUART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send);\n"
+ "+\t\tmode |= ATMEL_US_USMODE_RS485;\n"
+ "+\t} else\n"
+ "+\t\tdev_dbg(port->dev, \"Keeping UART to RS232\\n\");\n"
+ "+\n"
+ " \t/* set the parity, stop bits and data size */\n"
+ " \tUART_PUT_MR(port, mode);\n"
+ " \n"
+ "@@ -1231,6 +1373,31 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)\n"
+ " }\n"
+ " #endif\n"
+ " \n"
+ "+static int atmel_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)\n"
+ "+{\n"
+ "+\n"
+ "+\tswitch (cmd) {\n"
+ "+\tcase TIOCSRS485:\n"
+ "+\t\t{\n"
+ "+\t\t\tstruct serial_rs485 rs485conf;\n"
+ "+\t\t\tif (copy_from_user(&rs485conf, (struct serial_rs485 *) arg,\n"
+ "+\t\t\t\t\t\tsizeof(rs485conf)))\n"
+ "+\t\t\t\treturn -EFAULT;\n"
+ "+\n"
+ "+\t\t\tdev_dbg(port->dev, \"enable e/o disable rs485\\n\");\n"
+ "+\n"
+ "+\t\t\tatmel_enable_disable_rs485(port, &rs485conf);\n"
+ "+\t\t}\n"
+ "+\t\tbreak;\n"
+ "+\n"
+ "+\tdefault:\n"
+ "+\t\treturn -ENOIOCTLCMD;\n"
+ "+\t}\n"
+ "+\treturn 0;\n"
+ "+}\n"
+ "+\n"
+ "+\n"
+ "+\n"
+ " static struct uart_ops atmel_pops = {\n"
+ " \t.tx_empty\t= atmel_tx_empty,\n"
+ " \t.set_mctrl\t= atmel_set_mctrl,\n"
+ "@@ -1250,6 +1417,7 @@ static struct uart_ops atmel_pops = {\n"
+ " \t.config_port\t= atmel_config_port,\n"
+ " \t.verify_port\t= atmel_verify_port,\n"
+ " \t.pm\t\t= atmel_serial_pm,\n"
+ "+\t.ioctl\t\t= atmel_ioctl,\n"
+ " #ifdef CONFIG_CONSOLE_POLL\n"
+ " \t.poll_get_char\t= atmel_poll_get_char,\n"
+ " \t.poll_put_char\t= atmel_poll_put_char,\n"
+ "@@ -1265,13 +1433,12 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,\n"
+ " \tstruct uart_port *port = &atmel_port->uart;\n"
+ " \tstruct atmel_uart_data *data = pdev->dev.platform_data;\n"
+ " \n"
+ "-\tport->iotype\t= UPIO_MEM;\n"
+ "-\tport->flags\t= UPF_BOOT_AUTOCONF;\n"
+ "-\tport->ops\t= &atmel_pops;\n"
+ "-\tport->fifosize\t= 1;\n"
+ "-\tport->line\t= pdev->id;\n"
+ "-\tport->dev\t= &pdev->dev;\n"
+ "-\n"
+ "+\tport->iotype\t\t= UPIO_MEM;\n"
+ "+\tport->flags\t\t= UPF_BOOT_AUTOCONF;\n"
+ "+\tport->ops\t\t= &atmel_pops;\n"
+ "+\tport->fifosize\t\t= 1;\n"
+ "+\tport->line\t\t= pdev->id;\n"
+ "+\tport->dev\t\t= &pdev->dev;\n"
+ " \tport->mapbase\t= pdev->resource[0].start;\n"
+ " \tport->irq\t= pdev->resource[1].start;\n"
+ " \n"
+ "@@ -1299,8 +1466,15 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,\n"
+ " \n"
+ " \tatmel_port->use_dma_rx = data->use_dma_rx;\n"
+ " \tatmel_port->use_dma_tx = data->use_dma_tx;\n"
+ "-\tif (atmel_use_dma_tx(port))\n"
+ "+\tatmel_port->rs485\t= data->rs485;\n"
+ "+\t/* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */\n"
+ "+\tif (atmel_port->rs485.flags & SER_RS485_ENABLED)\n"
+ "+\t\tatmel_port->tx_done_mask = ATMEL_US_TXEMPTY;\n"
+ "+\telse if (atmel_use_dma_tx(port)) {\n"
+ " \t\tport->fifosize = PDC_BUFFER_SIZE;\n"
+ "+\t\tatmel_port->tx_done_mask = ATMEL_US_ENDTX | ATMEL_US_TXBUFE;\n"
+ "+\t} else\n"
+ "+\t\tatmel_port->tx_done_mask = ATMEL_US_TXRDY;\n"
+ " }\n"
+ " \n"
+ " /*\n"
+ "@@ -1334,6 +1508,7 @@ static void atmel_console_putchar(struct uart_port *port, int ch)\n"
+ " static void atmel_console_write(struct console *co, const char *s, u_int count)\n"
+ " {\n"
+ " \tstruct uart_port *port = &atmel_ports[co->index].uart;\n"
+ "+\tstruct atmel_uart_port *atmel_port = to_atmel_uart_port(port);\n"
+ " \tunsigned int status, imr;\n"
+ " \tunsigned int pdc_tx;\n"
+ " \n"
+ "@@ -1341,7 +1516,7 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)\n"
+ " \t * First, save IMR and then disable interrupts\n"
+ " \t */\n"
+ " \timr = UART_GET_IMR(port);\n"
+ "-\tUART_PUT_IDR(port, ATMEL_US_RXRDY | ATMEL_US_TXRDY);\n"
+ "+\tUART_PUT_IDR(port, ATMEL_US_RXRDY | atmel_port->tx_done_mask);\n"
+ " \n"
+ " \t/* Store PDC transmit status and disable it */\n"
+ " \tpdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN;\n"
+ "@@ -1355,7 +1530,7 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)\n"
+ " \t */\n"
+ " \tdo {\n"
+ " \t\tstatus = UART_GET_CSR(port);\n"
+ "-\t} while (!(status & ATMEL_US_TXRDY));\n"
+ "+\t} while (!(status & atmel_port->tx_done_mask));\n"
+ " \n"
+ " \t/* Restore PDC transmit status */\n"
+ " \tif (pdc_tx)\n"
+ "@@ -1587,7 +1762,7 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev)\n"
+ " \tdevice_init_wakeup(&pdev->dev, 1);\n"
+ " \tplatform_set_drvdata(pdev, port);\n"
+ " \n"
+ "-\treturn 0;\n"
+ "+\treturn device_create_file(&(pdev->dev), &dev_attr_rs485);\n"
+ " \n"
+ " err_add_port:\n"
+ " \tkfree(port->rx_ring.buf);\n"
+ "@@ -1619,6 +1794,8 @@ static int __devexit atmel_serial_remove(struct platform_device *pdev)\n"
+ " \n"
+ " \tclk_put(atmel_port->clk);\n"
+ " \n"
+ "+\tdevice_remove_file(&(pdev->dev), &dev_attr_rs485);\n"
+ "+\n"
+ " \treturn ret;\n"
+ " }\n"
+ " \n"
+ "-- \n"
+ 1.6.0.4
 
-c90d2542b7c859c0180d4e1f987a4cd6f1230ff3e1bd113ea158491e03b583af
+7e0101e2f0e2af7afa7cf9c11c18c072ad1d49e8215d38a5a9a71f34f3a65c74

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.