summaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r--drivers/usb/serial/xr_serial.c45
1 files changed, 37 insertions, 8 deletions
diff --git a/drivers/usb/serial/xr_serial.c b/drivers/usb/serial/xr_serial.c
index f5087a8b6c86..542c1dc060cc 100644
--- a/drivers/usb/serial/xr_serial.c
+++ b/drivers/usb/serial/xr_serial.c
@@ -532,7 +532,6 @@ static void xr_set_termios(struct tty_struct *tty,
static int xr_open(struct tty_struct *tty, struct usb_serial_port *port)
{
- u8 gpio_dir;
int ret;
ret = xr_uart_enable(port);
@@ -541,13 +540,6 @@ static int xr_open(struct tty_struct *tty, struct usb_serial_port *port)
return ret;
}
- /*
- * Configure DTR and RTS as outputs and RI, CD, DSR and CTS as
- * inputs.
- */
- gpio_dir = XR21V141X_GPIO_DTR | XR21V141X_GPIO_RTS;
- xr_set_reg_uart(port, XR21V141X_REG_GPIO_DIR, gpio_dir);
-
/* Setup termios */
if (tty)
xr_set_termios(tty, port, NULL);
@@ -596,10 +588,38 @@ static int xr_probe(struct usb_serial *serial, const struct usb_device_id *id)
return 0;
}
+static int xr_gpio_init(struct usb_serial_port *port)
+{
+ u8 mask, mode;
+ int ret;
+
+ /* Configure all pins as GPIO. */
+ mode = 0;
+ ret = xr_set_reg_uart(port, XR21V141X_REG_GPIO_MODE, mode);
+ if (ret)
+ return ret;
+
+ /*
+ * Configure DTR and RTS as outputs and make sure they are deasserted
+ * (active low), and configure RI, CD, DSR and CTS as inputs.
+ */
+ mask = XR21V141X_GPIO_DTR | XR21V141X_GPIO_RTS;
+ ret = xr_set_reg_uart(port, XR21V141X_REG_GPIO_DIR, mask);
+ if (ret)
+ return ret;
+
+ ret = xr_set_reg_uart(port, XR21V141X_REG_GPIO_SET, mask);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static int xr_port_probe(struct usb_serial_port *port)
{
struct usb_interface_descriptor *desc;
struct xr_data *data;
+ int ret;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
@@ -610,7 +630,16 @@ static int xr_port_probe(struct usb_serial_port *port)
usb_set_serial_port_data(port, data);
+ ret = xr_gpio_init(port);
+ if (ret)
+ goto err_free;
+
return 0;
+
+err_free:
+ kfree(data);
+
+ return ret;
}
static void xr_port_remove(struct usb_serial_port *port)