--- a/vizzini.c 2013-01-22 15:37:32.345592809 -0600 +++ b/vizzini.c 2013-01-29 14:27:04.550051817 -0600 @@ -186,6 +186,7 @@ #ifdef VIZZINI_IWA int iwa; #endif + struct serial_rs485 rs485; }; @@ -428,7 +429,41 @@ return -EINVAL; } +static int vizzini_set_rs485(struct usb_serial_port *port, struct serial_rs485 *rs485conf) +{ + struct vizzini_port_private *portdata = usb_get_serial_port_data(port); + int block = portdata->block; + int result = 0; + unsigned int gpio_mode, flow = 0; + + portdata->rs485 = *rs485conf; + + if (portdata->rs485.flags & SER_RS485_ENABLED) { + dev_info(&port->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(port, block, UART_GPIO_MODE, gpio_mode); + if (result < 0) + dev_err(&port->dev, "Error setting auto trans enable"); + + /* half duplex rs485 */ + flow = UART_FLOW_HALF_DUPLEX; + result = vizzini_set_reg(port, block, UART_FLOW, flow); + + if (result < 0) + dev_err(&port->dev, "Error setting half duplex"); + } + else { + dev_info(&port->dev, "Disabling RS485 - flow control off"); + vizzini_set_reg(port, block, UART_GPIO_MODE, UART_GPIO_MODE_SEL_GPIO); + vizzini_set_reg(port, block, UART_FLOW, UART_FLOW_MODE_NONE); + } + + return 0; +} static void vizzini_set_termios(struct tty_struct *tty_param, struct usb_serial_port *port, @@ -604,6 +639,7 @@ char *data; int result; struct serial_struct ss; + struct serial_rs485 rs485conf; if (debug) dev_dbg(&port->dev, "%s %08x\n", __func__, cmd); @@ -636,6 +672,36 @@ /* mutex_unlock(&config_mutex); */ break; + case TIOCGRS485: + if (!arg) { + dev_err(&port->dev, "%s - TIOCGRS485 arg invalid\n", __func__); + return -EFAULT; + } + if (copy_to_user((struct serial_rs485 *) arg, + &(portdata->rs485), + sizeof(struct serial_rs485))) { + dev_err(&port->dev, "%s - TIOCGRS485 copy_to_user fail\n", __func__); + return -EFAULT; + } + break; + + case TIOCSRS485: + dev_dbg(&port->dev, "%s TIOCSRS485\n", __func__); + if (!arg) { + return -EFAULT; + dev_err(&port->dev, "%s - TIOCSRS485 arg invalid\n", __func__); + } + if (copy_from_user(&rs485conf, (struct serial_rs485 *) arg, + sizeof(rs485conf))) { + dev_err(&port->dev, "%s - TIOCSRS485 copy_from_user fail\n", __func__); + return -EFAULT; + } + + vizzini_disable(port); + vizzini_set_rs485(port, &rs485conf); + vizzini_enable(port); + break; + case VZIOC_GET_REG: if (get_user(block, (int __user *)arg)) return -EFAULT;