linux 串口驱动 atmel_set_mctrl何时调用,Linux下的atmel usart 485模式的patch

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

#define FIOQSIZE 0x545E

+#define TIOCSRS485 0x5461

+

#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..df2ed84 100644

--- a/arch/arm/mach-at91/include/mach/board.h

+++ b/arch/arm/mach-at91/include/mach/board.h

@@ -39,6 +39,7 @@

#include

#include

#include

+#include

struct at91_udc_data {

@@ -143,9 +144,10 @@

extern struct platform_device *atmel_default_c*****ole_device;

extern void __init __deprecated at91_init_serial(struct at91_uart_config *config);

struct atmel_uart_data {

- short use_dma_tx;

- short use_dma_rx;

- void __iomem *regs;

+ shortuse_dma_tx;

+ shortuse_dma_rx;

+ void __iomem *regs;

+ struct serial_rs485 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..039cd65 100644

--- a/drivers/serial/atmel_serial.c

+++ b/drivers/serial/atmel_serial.c

@@ -38,6 +38,7 @@

#include

#include

#include

+#include

#include

@@ -59,6 +60,9 @@

#include

+static void atmel_start_rx(struct uart_port *port);

+static void atmel_stop_rx(struct uart_port *port);

+

#ifdef CONFIG_SERIAL_ATMEL_TTYAT

#define UART_PUT_PTCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)

@@ -147,6 +152,9 @@

struct atmel_uart_port {

unsigned int irq_status_prev;

struct circ_buf rx_ring;

+

+ struct serial_rs485 rs485;

+ unsigned int tx_done_mask;

};

static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];

@@ -187,6 +195,81 @@

static bool atmel_use_dma_tx(struct uart_port *port)

}

#endif

+

+void atmel_config_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);

+

+

+ mode &= ~ATMEL_US_USMODE;

+

+ atmel_port->rs485 = *rs485conf;

+

+ if (rs485conf->flags & SER_RS485_ENABLED) {

+ 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;

+ } else {

+ 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;

+ }

+ 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) & ATMEL_US_USMODE;

+ return snprintf(buf, PAGE_SIZE, "%u\n", current_mode);

+}

+

+static ssize_t set_rs485(struct device *dev, struct device_attribute *attr,

+ c*****t 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)

+ return -EINVAL;

+

+ value = !!(simple_strtoul(buf, NULL, 0));

+

+ if (value) {

+ rs485conf.flags |= SER_RS485_ENABLED;

+

+ rs485conf.delay_rts_before_send = 0x00000004;

+ } else {

+ rs485conf.flags &= ~SER_RS485_ENABLED;

+ }

+

+ atmel_config_rs485(port, &rs485conf);

+

+ return strnlen(buf, PAGE_SIZE);

+}

+

+static DEVICE_ATTR(rs485, 0644, show_rs485, set_rs485);

+

@@ -202,6 +285,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 +320,17 @@

static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)

mode |= ATMEL_US_CHMODE_LOC_LOOP;

else

mode |= ATMEL_US_CHMODE_NORMAL;

+

+

+ mode &= ~ATMEL_US_USMODE;

+

+ if (atmel_port->rs485.flags & SER_RS485_ENABLED) {

+ dev_dbg(port->dev, "Setting 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, "Setting UART to RS232\n");

+ }

UART_PUT_MR(port, mode);

}

@@ -268,12 +363,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)) {

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);

+ }

+

+ UART_PUT_IDR(port, atmel_port->tx_done_mask);

+

+ if (atmel_port->rs485.flags & SER_RS485_ENABLED)

+ atmel_start_rx(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)

return;

- UART_PUT_IER(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE);

+ if (atmel_port->rs485.flags & SER_RS485_ENABLED)

+atmel_stop_rx(port);

+

UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);

- } else

- UART_PUT_IER(port, ATMEL_US_TXRDY);

+ }

+

+ UART_PUT_IER(port, atmel_port->tx_done_mask);

+}

+

+

+static void atmel_start_rx(struct uart_port *port)

+{

+ UART_PUT_CR(port, ATMEL_US_RSTSTA);

+

+ if (atmel_use_dma_rx(port)) {

+

+ 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);

+ }

}

UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS);

- UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);

- } else

+ UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |

+port->read_status_mask);

+ } else {

UART_PUT_IDR(port, ATMEL_US_RXRDY);

+ }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值