Index: xr21v141x-lnx3.10-3.11/vizzini.c =================================================================== --- xr21v141x-lnx3.10-3.11.orig/vizzini.c 2014-05-02 12:20:07.972225646 -0500 +++ xr21v141x-lnx3.10-3.11/vizzini.c 2014-05-07 13:53:08.125405483 -0500 @@ -892,6 +892,35 @@ dev_dbg(&xr21v141x->control->dev, "vz_test_mode: selector=0x%02x\n", selector); return retval < 0 ? retval : 0; } +static int xr21v141x_set_rs485(struct xr21v141x *xr21v141x, struct serial_rs485 *rs485conf) { + int block = xr21v141x->block; + int result = 0; + unsigned int gpio_mode, flow = 0; + + xr21v141x->rs485 = *rs485conf; + + if (xr21v141x->rs485.flags & SER_RS485_ENABLED) { + dev_info(&xr21v141x->control->dev, "Enabling RS485"); + + /* enable auto tranceiver enable on transmit, TX active high */ + gpio_mode = UART_GPIO_MODE_SEL_XCVR_EN_ACT | UART_GPIO_MODE_XCVR_EN_POL; + result = vizzini_set_reg(xr21v141x, block, UART_GPIO_MODE, gpio_mode); + if (result < 0) + dev_err(&xr21v141x->control->dev, "Error setting auto trans enable"); + + /* half duplex rs485 */ + flow = UART_FLOW_HALF_DUPLEX; + result = vizzini_set_reg(xr21v141x, block, UART_FLOW, flow); + if (result < 0) + dev_err(&xr21v141x->control->dev, "Error setting half duplex"); + } else { + dev_info(&xr21v141x->control->dev, "Disabling RS485 - flow control off"); + vizzini_set_reg(xr21v141x, block, UART_GPIO_MODE, UART_GPIO_MODE_SEL_GPIO); + vizzini_set_reg(xr21v141x, block, UART_FLOW, UART_FLOW_MODE_NONE); + } + + return 0; +} static int xr21v141x_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) @@ -902,6 +931,8 @@ unsigned int block, reg, val, match, preciseflags, unicast, broadcast, flow, selector; char *data; + struct serial_rs485 rs485conf; + switch (cmd) { case TIOCGSERIAL: /* gets serial port data */ rv = get_serial_info(xr21v141x, (struct serial_struct __user *) arg); @@ -910,6 +941,39 @@ rv = set_serial_info(xr21v141x, (struct serial_struct __user *) arg); break; + case TIOCGRS485: + if (! arg) { + dev_err(&xr21v141x->control->dev, "%s - TIOCGRS485 arg invalid\n", __func__); + rv = -EFAULT; + break; + } + + if (copy_to_user((struct serial_rs485 *) arg, &(xr21v141x->rs485), sizeof(struct serial_rs485))) { + dev_err(&xr21v141x->control->dev, "%s - TIOCGRS485 copy_to_user fail\n", __func__); + rv = -EFAULT; + break; + } + rv = 0; + break; + + case TIOCSRS485: + if (! arg) { + dev_err(&xr21v141x->control->dev, "%s - TIOCSRS485 arg invalid\n", __func__); + rv = -EFAULT; + break; + } + + if (copy_from_user(&rs485conf, (struct serial_rs485 *) arg, sizeof(rs485conf))) { + dev_err(&xr21v141x->control->dev, "%s - TIOCSRS485 copy_from_user failed\n", __func__); + rv = -EFAULT; + break; + } + + vizzini_disable(xr21v141x); + rv = xr21v141x_set_rs485(xr21v141x, &rs485conf); + vizzini_enable(xr21v141x); + break; + case VZIOC_GET_REG: if (get_user(block, (int __user *)arg)) return -EFAULT; Index: xr21v141x-lnx3.10-3.11/vizzini.h =================================================================== --- xr21v141x-lnx3.10-3.11.orig/vizzini.h 2014-04-04 19:59:33.000000000 -0500 +++ xr21v141x-lnx3.10-3.11/vizzini.h 2014-05-02 12:20:08.028225647 -0500 @@ -282,7 +282,7 @@ #ifdef VIZZINI_IWA int iwa; #endif - + struct serial_rs485 rs485; }; #define CDC_DATA_INTERFACE_TYPE 0x0a