From patchwork Thu Jun 6 02:54:11 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Ji-Ze Hong (Peter Hong)" X-Patchwork-Id: 10978359 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 719B217D2 for ; Thu, 6 Jun 2019 02:55:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 629DF28762 for ; Thu, 6 Jun 2019 02:55:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 544CB28774; Thu, 6 Jun 2019 02:55:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9716F28762 for ; Thu, 6 Jun 2019 02:55:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726754AbfFFCyl (ORCPT ); Wed, 5 Jun 2019 22:54:41 -0400 Received: from mail-pl1-f193.google.com ([209.85.214.193]:44999 "EHLO mail-pl1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726454AbfFFCyk (ORCPT ); Wed, 5 Jun 2019 22:54:40 -0400 Received: by mail-pl1-f193.google.com with SMTP id c5so289736pll.11; Wed, 05 Jun 2019 19:54:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6/441xpEsHRHk+TPPpQ71vkACQ7btLdEQ1tga7+tI0Q=; b=RdR4iEgIl9owu3eEOHa9RP0NJwO3Qp8aS2WOU4rZppvATYtyLWkqkUum1CI3OIdLuk OIz22VDufEFjFnoHvTOXVSFLKwEhnwGmFKGUTZlUjNI7+OJCbNpq6N41n/i40LDEdAyF qWYxzaJrm5iAqR7dUc5DTOD8Fg2wiBuRBsB3oT4sNOt0kadD7Zui3iQi6FfyojOs85Jj YKHnR8O826Hmm3MnaNhfMCvCMHjAyQfg4Fjs5d+gJH3qLpNpbpgSWnq7x9s6UryC93zm QMPZ6CfJmgGDtcaTwaZC1n0PHOH+j3yrwQWfQTO3URWuljD0dqI3xLz9w2SMORl+blJM iqHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=6/441xpEsHRHk+TPPpQ71vkACQ7btLdEQ1tga7+tI0Q=; b=djzuO3Dl4l+JFmfP78PiAYZt8kGgSA5KgA7VHLeCrSVt30/4LFV0ea8PEtgtP590Ul OMH8kXA2TX8fXrWvDQhdxvgNNBhEoxlegxmQiowcmM4hWEQpGj+vOCcKO86ssaOOW7C3 KtAiBPsheAVCbTCq8dYMLJuN/wTDBAy3WdENDuehpocVQqKnXt6og6eI9WsMJH7bEyXe msTp+2wiz+xBLIrN/6jy0YyU7pBIWP9hLtPcoayA2diqU5K9XvTDbS8jh85peN+MY7mz e3+2bE0jcibX45xsy+L6EmWhGhha2o5ZINhH8QCLz+POV419412O7DmHsRj8qSHecntR vktw== X-Gm-Message-State: APjAAAVCUHhd/u77iTEirfQxQs+/Sb60S9GB92pQlD9TicI7JX4eYpIj cMKe2O51YRqFO39L3IZnITOljbla X-Google-Smtp-Source: APXvYqylosWyCIwVzbZaoOe/bP3PkZDEMeCJBNiHHokBgRXlgsbyLF7t72UbcXUdLOac+DJTFAY2hg== X-Received: by 2002:a17:902:ac85:: with SMTP id h5mr40728863plr.198.1559789679530; Wed, 05 Jun 2019 19:54:39 -0700 (PDT) Received: from localhost (59-120-186-245.HINET-IP.hinet.net. [59.120.186.245]) by smtp.gmail.com with ESMTPSA id b35sm312923pjc.15.2019.06.05.19.54.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 05 Jun 2019 19:54:38 -0700 (PDT) From: "Ji-Ze Hong (Peter Hong)" X-Google-Original-From: "Ji-Ze Hong (Peter Hong)" To: johan@kernel.org Cc: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, peter_hong@fintek.com.tw, "Ji-Ze Hong (Peter Hong)" Subject: [PATCH V1 1/6] USB: serial: f81232: Add F81534A support Date: Thu, 6 Jun 2019 10:54:11 +0800 Message-Id: <1559789656-15847-2-git-send-email-hpeter+linux_kernel@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1559789656-15847-1-git-send-email-hpeter+linux_kernel@gmail.com> References: <1559789656-15847-1-git-send-email-hpeter+linux_kernel@gmail.com> Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The Fintek F81532A/534A/535/536 is USB-to-2/4/8/12 serial ports device. It's most same with F81232, the UART device is difference as follow: 1. TX/RX bulk size is 128/512bytes 2. RX bulk layout change: F81232: [LSR(1Byte)+DATA(1Byte)][LSR(1Byte)+DATA(1Byte)]... F81534A:[LEN][Data.....][LSR] Signed-off-by: Ji-Ze Hong (Peter Hong) --- drivers/usb/serial/f81232.c | 153 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 144 insertions(+), 9 deletions(-) diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index 43fa1f0716b7..84efcc66aa56 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* * Fintek F81232 USB to serial adaptor driver + * Fintek F81532A/534A/535/536 USB to 2/4/8/12 serial adaptor driver * * Copyright (C) 2012 Greg Kroah-Hartman (gregkh@linuxfoundation.org) * Copyright (C) 2012 Linux Foundation @@ -22,7 +23,20 @@ #include static const struct usb_device_id id_table[] = { + /* F81232 */ { USB_DEVICE(0x1934, 0x0706) }, + + /* F81532A/534A/535/536 */ + { USB_DEVICE(0x2c42, 0x1602) }, /* In-Box 2 port UART device */ + { USB_DEVICE(0x2c42, 0x1604) }, /* In-Box 4 port UART device */ + { USB_DEVICE(0x2c42, 0x1605) }, /* In-Box 8 port UART device */ + { USB_DEVICE(0x2c42, 0x1606) }, /* In-Box 12 port UART device */ + { USB_DEVICE(0x2c42, 0x1608) }, /* Non-Flash type */ + + { USB_DEVICE(0x2c42, 0x1632) }, /* 2 port UART device */ + { USB_DEVICE(0x2c42, 0x1634) }, /* 4 port UART device */ + { USB_DEVICE(0x2c42, 0x1635) }, /* 8 port UART device */ + { USB_DEVICE(0x2c42, 0x1636) }, /* 12 port UART device */ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, id_table); @@ -61,15 +75,25 @@ MODULE_DEVICE_TABLE(usb, id_table); #define F81232_CLK_14_77_MHZ (BIT(1) | BIT(0)) #define F81232_CLK_MASK GENMASK(1, 0) +#define F81534A_MODE_CONF_REG 0x107 +#define F81534A_TRIGGER_MASK GENMASK(3, 2) +#define F81534A_TRIGGER_MULTPILE_4X BIT(3) +#define F81534A_FIFO_128BYTE (BIT(1) | BIT(0)) + +#define F81232_F81232_TYPE 1 +#define F81232_F81534A_TYPE 2 + struct f81232_private { struct mutex lock; u8 modem_control; u8 modem_status; u8 shadow_lcr; + u8 device_type; speed_t baud_base; struct work_struct lsr_work; struct work_struct interrupt_work; struct usb_serial_port *port; + void (*process_read_urb)(struct urb *urb); }; static u32 const baudrate_table[] = { 115200, 921600, 1152000, 1500000 }; @@ -376,6 +400,78 @@ static void f81232_process_read_urb(struct urb *urb) tty_flip_buffer_push(&port->port); } +static void f81534a_process_read_urb(struct urb *urb) +{ + struct usb_serial_port *port = urb->context; + struct f81232_private *priv = usb_get_serial_port_data(port); + unsigned char *data = urb->transfer_buffer; + char tty_flag; + unsigned int i; + u8 lsr; + u8 len; + + if (urb->status) { + dev_err(&port->dev, "urb->status: %d\n", urb->status); + return; + } + + if (!urb->actual_length) { + dev_err(&port->dev, "urb->actual_length == 0\n"); + return; + } + + len = data[0]; + if (len != urb->actual_length) { + dev_err(&port->dev, "len(%d) != urb->actual_length(%d)\n", len, + urb->actual_length); + return; + } + + /* bulk-in data: [LEN][Data.....][LSR] */ + tty_flag = TTY_NORMAL; + + lsr = data[len - 1]; + if (lsr & UART_LSR_BRK_ERROR_BITS) { + if (lsr & UART_LSR_BI) { + tty_flag = TTY_BREAK; + port->icount.brk++; + usb_serial_handle_break(port); + } else if (lsr & UART_LSR_PE) { + tty_flag = TTY_PARITY; + port->icount.parity++; + } else if (lsr & UART_LSR_FE) { + tty_flag = TTY_FRAME; + port->icount.frame++; + } + + if (lsr & UART_LSR_OE) { + port->icount.overrun++; + schedule_work(&priv->lsr_work); + tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); + } + } + + for (i = 1; i < urb->actual_length - 1; i++) { + if (port->port.console && port->sysrq) { + if (usb_serial_handle_sysrq_char(port, data[i])) + continue; + } + + tty_insert_flip_char(&port->port, data[i], tty_flag); + } + + tty_flip_buffer_push(&port->port); +} + +static void f81232_read_urb_proxy(struct urb *urb) +{ + struct usb_serial_port *port = urb->context; + struct f81232_private *priv = usb_get_serial_port_data(port); + + if (priv->process_read_urb) + priv->process_read_urb(urb); +} + static void f81232_break_ctl(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; @@ -487,13 +583,28 @@ static void f81232_set_baudrate(struct tty_struct *tty, static int f81232_port_enable(struct usb_serial_port *port) { + struct f81232_private *port_priv = usb_get_serial_port_data(port); u8 val; int status; - /* fifo on, trigger8, clear TX/RX*/ - val = UART_FCR_TRIGGER_8 | UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | - UART_FCR_CLEAR_XMIT; + if (port_priv->device_type != F81232_F81232_TYPE) { + val = F81534A_TRIGGER_MULTPILE_4X | F81534A_FIFO_128BYTE; + status = f81232_set_mask_register(port, F81534A_MODE_CONF_REG, + F81534A_TRIGGER_MASK | F81534A_FIFO_128BYTE, + val); + if (status) { + dev_err(&port->dev, "failed to set MODE_CONF_REG: %d\n", + status); + return status; + } + + val = UART_FCR_TRIGGER_14; + } else { + val = UART_FCR_TRIGGER_8; + } + /* fifo on, clear TX/RX */ + val |= UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT; status = f81232_set_register(port, FIFO_CONTROL_REGISTER, val); if (status) { dev_err(&port->dev, "%s failed to set FCR: %d\n", @@ -631,6 +742,16 @@ static int f81232_tiocmset(struct tty_struct *tty, return f81232_set_mctrl(port, set, clear); } +static void f81232_detect_device_type(struct usb_serial_port *port) +{ + struct f81232_private *port_priv = usb_get_serial_port_data(port); + + if (port->serial->dev->descriptor.idProduct == 0x0706) + port_priv->device_type = F81232_F81232_TYPE; + else + port_priv->device_type = F81232_F81534A_TYPE; +} + static int f81232_open(struct tty_struct *tty, struct usb_serial_port *port) { int result; @@ -731,6 +852,7 @@ static void f81232_lsr_worker(struct work_struct *work) static int f81232_port_probe(struct usb_serial_port *port) { struct f81232_private *priv; + int status = 0; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) @@ -741,11 +863,26 @@ static int f81232_port_probe(struct usb_serial_port *port) INIT_WORK(&priv->lsr_work, f81232_lsr_worker); usb_set_serial_port_data(port, priv); + f81232_detect_device_type(port); port->port.drain_delay = 256; priv->port = port; - return 0; + switch (priv->device_type) { + case F81232_F81534A_TYPE: + priv->process_read_urb = f81534a_process_read_urb; + break; + + case F81232_F81232_TYPE: + priv->process_read_urb = f81232_process_read_urb; + break; + + default: + status = -ENODEV; + break; + } + + return status; } static int f81232_port_remove(struct usb_serial_port *port) @@ -797,12 +934,10 @@ static int f81232_resume(struct usb_serial *serial) static struct usb_serial_driver f81232_device = { .driver = { .owner = THIS_MODULE, - .name = "f81232", + .name = "f81232/f81534a", }, .id_table = id_table, .num_ports = 1, - .bulk_in_size = 256, - .bulk_out_size = 256, .open = f81232_open, .close = f81232_close, .dtr_rts = f81232_dtr_rts, @@ -813,7 +948,7 @@ static struct usb_serial_driver f81232_device = { .tiocmget = f81232_tiocmget, .tiocmset = f81232_tiocmset, .tiocmiwait = usb_serial_generic_tiocmiwait, - .process_read_urb = f81232_process_read_urb, + .process_read_urb = f81232_read_urb_proxy, .read_int_callback = f81232_read_int_callback, .port_probe = f81232_port_probe, .port_remove = f81232_port_remove, @@ -828,7 +963,7 @@ static struct usb_serial_driver * const serial_drivers[] = { module_usb_serial_driver(serial_drivers, id_table); -MODULE_DESCRIPTION("Fintek F81232 USB to serial adaptor driver"); +MODULE_DESCRIPTION("Fintek F81232/532A/534A/535/536 USB to serial driver"); MODULE_AUTHOR("Greg Kroah-Hartman "); MODULE_AUTHOR("Peter Hong "); MODULE_LICENSE("GPL v2"); From patchwork Thu Jun 6 02:54:12 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Ji-Ze Hong (Peter Hong)" X-Patchwork-Id: 10978349 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5D1051398 for ; Thu, 6 Jun 2019 02:54:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4D6FF28765 for ; Thu, 6 Jun 2019 02:54:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4130628780; Thu, 6 Jun 2019 02:54:45 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E2FCE28765 for ; Thu, 6 Jun 2019 02:54:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726788AbfFFCyn (ORCPT ); Wed, 5 Jun 2019 22:54:43 -0400 Received: from mail-pg1-f193.google.com ([209.85.215.193]:34914 "EHLO mail-pg1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726454AbfFFCym (ORCPT ); Wed, 5 Jun 2019 22:54:42 -0400 Received: by mail-pg1-f193.google.com with SMTP id s27so461661pgl.2; Wed, 05 Jun 2019 19:54:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=HMdqjqPKlxZQSHzx3Vn6pFK3iI06XFWAA0ObiWucrNs=; b=n6aPPAjV2esjw71uUNRUWQ0y5OX5FNS/1B5WVGujyXMaNz97deNQ1jbfjOy8x+AaKg KUYokjGoWKFvwItK4mQ2GEdiOy8E65DAIcSvLTvxVujz0SzPP/wHyfvY+LaRDbAKuKqk LEtmrtXQyaBc65NSFS5r1pwx8d+nWra9kXI0faD8bfH2wf+SGmVGvL1S6L1o2OgUJIFN 6qewCDT/qFgAFY0ftyKetmucBFHQ2tze2sRe0so2OaTGUKXqgT9mK4W20A1wRGgNSkna srJ7IR0ndDnOYTEJKQdUURueIVmb3VdMNgIdjtdkDk59y7hstFkUnC1SoHxRjo0QL6pF 0DqQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=HMdqjqPKlxZQSHzx3Vn6pFK3iI06XFWAA0ObiWucrNs=; b=Xo4YdhcKkt7HmKIGWYid3Rj+b2iMhF3Rll5rusBdAYC8rJzfE/R1XjG80SFG/QO4e0 H/swV+9WHQ2VC1Pw/1CxhsjdOcSZWuZ69B6/ajKhu8zLJtGi0Wz05Iw+q0rIE/JoL4lz 7IR3FDvKQOjGUVN6dABo+okG7cfRrsn9I7LFKb/0osYHo6sQkbnjHbmkVa5In6mXZ48U uDkBhBlAZaL7PVDYa43U7XFqm0VdEReJQ31QlG8105bqDhmrlH0Mq4cQAQ5zS5u/kPbM lMuMuO9vf2rj4HNh+3dwxSTYTk2NtS6mv4iN9Crr617V2i7V5PYnjEVocvJdVxWV2y6k 9BJA== X-Gm-Message-State: APjAAAX46+ITsHTF/kOhoP9g+7N7AX7T4c08fMAZ1aq6Qhwb5oGeVQ7y /7q1E1tu+v6/hu/Pv3IsIwg= X-Google-Smtp-Source: APXvYqxdk0Pgojj1778F7NNQY+CQC6CofKEglMnXj8YYwzXJ5uWMkqFDfSJsRKJeiXTLy5G0Et8hrw== X-Received: by 2002:aa7:910e:: with SMTP id 14mr50636742pfh.153.1559789681892; Wed, 05 Jun 2019 19:54:41 -0700 (PDT) Received: from localhost (59-120-186-245.HINET-IP.hinet.net. [59.120.186.245]) by smtp.gmail.com with ESMTPSA id e20sm304083pfi.35.2019.06.05.19.54.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 05 Jun 2019 19:54:41 -0700 (PDT) From: "Ji-Ze Hong (Peter Hong)" X-Google-Original-From: "Ji-Ze Hong (Peter Hong)" To: johan@kernel.org Cc: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, peter_hong@fintek.com.tw, "Ji-Ze Hong (Peter Hong)" Subject: [PATCH V1 2/6] USB: serial: f81232: Force F81534A with RS232 mode Date: Thu, 6 Jun 2019 10:54:12 +0800 Message-Id: <1559789656-15847-3-git-send-email-hpeter+linux_kernel@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1559789656-15847-1-git-send-email-hpeter+linux_kernel@gmail.com> References: <1559789656-15847-1-git-send-email-hpeter+linux_kernel@gmail.com> Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Force F81534A series UARTs with RS232 mode in port_probe(). Signed-off-by: Ji-Ze Hong (Peter Hong) --- drivers/usb/serial/f81232.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index 84efcc66aa56..75dfc0b9ef30 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -83,12 +83,22 @@ MODULE_DEVICE_TABLE(usb, id_table); #define F81232_F81232_TYPE 1 #define F81232_F81534A_TYPE 2 +/* Serial port self GPIO control, 2bytes [control&output data][input data] */ +#define F81534A_GPIO_REG 0x10e +#define F81534A_GPIO_MODE2_DIR BIT(6) /* 1: input, 0: output */ +#define F81534A_GPIO_MODE1_DIR BIT(5) +#define F81534A_GPIO_MODE0_DIR BIT(4) +#define F81534A_GPIO_MODE2_OUTPUT BIT(2) +#define F81534A_GPIO_MODE1_OUTPUT BIT(1) +#define F81534A_GPIO_MODE0_OUTPUT BIT(0) + struct f81232_private { struct mutex lock; u8 modem_control; u8 modem_status; u8 shadow_lcr; u8 device_type; + u8 gpio_mode; speed_t baud_base; struct work_struct lsr_work; struct work_struct interrupt_work; @@ -871,6 +881,11 @@ static int f81232_port_probe(struct usb_serial_port *port) switch (priv->device_type) { case F81232_F81534A_TYPE: priv->process_read_urb = f81534a_process_read_urb; + priv->gpio_mode = F81534A_GPIO_MODE2_DIR; + + /* tri-state with pull-high, default RS232 Mode */ + status = f81232_set_register(port, F81534A_GPIO_REG, + priv->gpio_mode); break; case F81232_F81232_TYPE: From patchwork Thu Jun 6 02:54:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Ji-Ze Hong (Peter Hong)" X-Patchwork-Id: 10978351 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0418717D2 for ; Thu, 6 Jun 2019 02:54:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EA4D028762 for ; Thu, 6 Jun 2019 02:54:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DEF3528774; Thu, 6 Jun 2019 02:54:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0C85F28762 for ; Thu, 6 Jun 2019 02:54:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726820AbfFFCyt (ORCPT ); Wed, 5 Jun 2019 22:54:49 -0400 Received: from mail-pg1-f194.google.com ([209.85.215.194]:36594 "EHLO mail-pg1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726454AbfFFCyq (ORCPT ); Wed, 5 Jun 2019 22:54:46 -0400 Received: by mail-pg1-f194.google.com with SMTP id a3so460786pgb.3; Wed, 05 Jun 2019 19:54:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ICKBhKiZHRuK25W4lcIycKKRNXDv1c9lm2aVXCsX6zM=; b=aHC5mM/DHFs2zQ3zvh9RP7NxAkd9n84pqPpEz6MF5YaWY6k2T8/6KTeWs7bizvYvgf R7UPs62bRZEhrpMYs1IHdygqcb1hqwOy7106WZ70FqLlwFWH0D7OrnMUvcgXtQwg2BeA BBAlLsaBFj3FP/rGx7imp6Zg9OnanzaIzZ8du1YcHpM32pKzIzPPGbJ7TTEEjpmFzXsL sOmvZ12yLkxzoxMtJTr/81pyxYIXjajStJ0L0CJYrMiF2rjCTSShfIuRiGKEd39TZXgA pO0UM3hfokFBNTQcF8VdMnXMMrTnFDgahZZCz4vszyJcNo6N1hgy4OiUmDh9e2OaMHyp Ar+w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ICKBhKiZHRuK25W4lcIycKKRNXDv1c9lm2aVXCsX6zM=; b=Q9VY00zkWiQcwRGiXRYEgpMnmtrRM09WgdQq2bWUmOFNU+TI4r6fGZ/YuHFSSWlMy9 gkG9pi+c3CUuWKnV7zq5DetUlvCA9iZbpu0FCOSN40KUcN83qd0Jo6Q8RegFflm2kOOU X3hi3yONBhW0wVy3HQEHqLscLZXL0Z7kb6C98RARSzWcm44fo+xaHUUAfC8/InIQot1w zDXHsHEZ/U13gyO/hIDEZG628+4FQQPPT8Gbr2DZEzDsLK/ehjU/Ah9fUQY6Ct1wY3LP gc3gexx8Rlej5QfrcLaeFO5BGSCCoV8BKcbdsS4JKFQzNF5vxh1+qGE+LeIug8kEBBZm S9yw== X-Gm-Message-State: APjAAAWl7jSUYAx6Vg7GYhy36OfmAkEySLcWA/DqITdX0ao5Ima/eAjn 8rQ33xoEc2cGIG1dyjauKto= X-Google-Smtp-Source: APXvYqzgYUhXCTtDSeVd1Zy01PWMxTAD+rlBfLVn3tf+5xgQA5IE7Uqtj9Y3i1t1hhLJ5+X7aHyCBw== X-Received: by 2002:a17:90a:6505:: with SMTP id i5mr48080029pjj.47.1559789684685; Wed, 05 Jun 2019 19:54:44 -0700 (PDT) Received: from localhost (59-120-186-245.HINET-IP.hinet.net. [59.120.186.245]) by smtp.gmail.com with ESMTPSA id f13sm330613pje.11.2019.06.05.19.54.43 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 05 Jun 2019 19:54:44 -0700 (PDT) From: "Ji-Ze Hong (Peter Hong)" X-Google-Original-From: "Ji-Ze Hong (Peter Hong)" To: johan@kernel.org Cc: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, peter_hong@fintek.com.tw, "Ji-Ze Hong (Peter Hong)" Subject: [PATCH V1 3/6] USB: serial: f81232: Add generator for F81534A Date: Thu, 6 Jun 2019 10:54:13 +0800 Message-Id: <1559789656-15847-4-git-send-email-hpeter+linux_kernel@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1559789656-15847-1-git-send-email-hpeter+linux_kernel@gmail.com> References: <1559789656-15847-1-git-send-email-hpeter+linux_kernel@gmail.com> Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The Fintek F81534A series is contains 1 HUB / 1 GPIO device / n UARTs, but the UART is default disable and need enabled by GPIO device(2c42/16F8). When F81534A plug to host, we can only see 1 HUB & 1 GPIO device, add GPIO device USB interface to device_list and trigger generate worker, f81534a_generate_worker to run f81534a_ctrl_generate_ports(). The operation in f81534a_ctrl_generate_ports() as following: 1: Write 0x8fff to F81534A_CMD_ENABLE_PORT register for enable all UART device. 2: Read port existence & current status from F81534A_CMD_PORT_STATUS register. the higher 16bit will indicate the UART existence. If the UART is existence, we'll check it GPIO mode as long as not default value (default is all input mode). 3: 1 GPIO device will check with max 15s and check next GPIO device when timeout. (F81534A_CTRL_RETRY * F81534A_CTRL_TIMER) Signed-off-by: Ji-Ze Hong (Peter Hong) --- drivers/usb/serial/f81232.c | 356 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 355 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index 75dfc0b9ef30..e9470fb0d691 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -41,6 +41,12 @@ static const struct usb_device_id id_table[] = { }; MODULE_DEVICE_TABLE(usb, id_table); +static const struct usb_device_id f81534a_ctrl_id_table[] = { + { USB_DEVICE(0x2c42, 0x16f8) }, /* Global control device */ + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, f81534a_ctrl_id_table); + /* Maximum baudrate for F81232 */ #define F81232_MAX_BAUDRATE 1500000 #define F81232_DEF_BAUDRATE 9600 @@ -49,6 +55,10 @@ MODULE_DEVICE_TABLE(usb, id_table); #define F81232_REGISTER_REQUEST 0xa0 #define F81232_GET_REGISTER 0xc0 #define F81232_SET_REGISTER 0x40 +#define F81534A_REGISTER_REQUEST F81232_REGISTER_REQUEST +#define F81534A_GET_REGISTER F81232_GET_REGISTER +#define F81534A_SET_REGISTER F81232_SET_REGISTER +#define F81534A_ACCESS_REG_RETRY 2 #define SERIAL_BASE_ADDRESS 0x0120 #define RECEIVE_BUFFER_REGISTER (0x00 + SERIAL_BASE_ADDRESS) @@ -83,6 +93,10 @@ MODULE_DEVICE_TABLE(usb, id_table); #define F81232_F81232_TYPE 1 #define F81232_F81534A_TYPE 2 +#define F81534A_MAX_PORT 12 +#define F81534A_CTRL_TIMER 1000 +#define F81534A_CTRL_RETRY 15 + /* Serial port self GPIO control, 2bytes [control&output data][input data] */ #define F81534A_GPIO_REG 0x10e #define F81534A_GPIO_MODE2_DIR BIT(6) /* 1: input, 0: output */ @@ -92,6 +106,16 @@ MODULE_DEVICE_TABLE(usb, id_table); #define F81534A_GPIO_MODE1_OUTPUT BIT(1) #define F81534A_GPIO_MODE0_OUTPUT BIT(0) +#define F81534A_CMD_ENABLE_PORT 0x116 +#define F81534A_CMD_PORT_STATUS 0x117 + +/* + * Control device global GPIO control, + * 2bytes [control&output data][input data] + */ +#define F81534A_CTRL_GPIO_REG 0x1601 +#define F81534A_CTRL_GPIO_MAX_PIN 3 + struct f81232_private { struct mutex lock; u8 modem_control; @@ -106,10 +130,27 @@ struct f81232_private { void (*process_read_urb)(struct urb *urb); }; +struct f81534a_ctrl_private { + struct usb_interface *intf; + struct mutex lock; + int device_idx; +}; + +struct f81534a_device { + struct list_head list; + struct usb_interface *intf; + int check_index; + int check_retry; +}; + static u32 const baudrate_table[] = { 115200, 921600, 1152000, 1500000 }; static u8 const clock_table[] = { F81232_CLK_1_846_MHZ, F81232_CLK_14_77_MHZ, F81232_CLK_18_46_MHZ, F81232_CLK_24_MHZ }; +struct delayed_work f81534a_generate_worker; +static DEFINE_MUTEX(device_mutex); +static LIST_HEAD(device_list); + static int calc_baud_divisor(speed_t baudrate, speed_t clockrate) { if (!baudrate) @@ -859,6 +900,281 @@ static void f81232_lsr_worker(struct work_struct *work) dev_warn(&port->dev, "read LSR failed: %d\n", status); } +static int f81534a_ctrl_get_register(struct usb_device *dev, u16 reg, u16 size, + void *val) +{ + int retry = F81534A_ACCESS_REG_RETRY; + int status; + u8 *tmp; + + tmp = kmalloc(size, GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + while (retry--) { + status = usb_control_msg(dev, + usb_rcvctrlpipe(dev, 0), + F81534A_REGISTER_REQUEST, + F81534A_GET_REGISTER, + reg, + 0, + tmp, + size, + USB_CTRL_GET_TIMEOUT); + if (status != size) { + status = usb_translate_errors(status); + if (status == -EIO) + continue; + + status = -EIO; + } else { + status = 0; + memcpy(val, tmp, size); + } + + break; + } + + if (status) { + dev_err(&dev->dev, "get reg: %x, failed status: %d\n", reg, + status); + } + + kfree(tmp); + return status; +} + +static int f81534a_ctrl_set_register(struct usb_device *dev, u16 reg, u16 size, + void *val) +{ + int retry = F81534A_ACCESS_REG_RETRY; + int status; + u8 *tmp; + + tmp = kmalloc(size, GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + memcpy(tmp, val, size); + + while (retry--) { + status = usb_control_msg(dev, + usb_sndctrlpipe(dev, 0), + F81534A_REGISTER_REQUEST, + F81534A_SET_REGISTER, + reg, + 0, + tmp, + size, + USB_CTRL_SET_TIMEOUT); + if (status != size) { + status = usb_translate_errors(status); + if (status == -EIO) + continue; + + status = -EIO; + } else { + status = 0; + } + + break; + } + + if (status) { + dev_err(&dev->dev, "set ctrl reg: %x, failed status: %d\n", reg, + status); + } + + kfree(tmp); + return status; +} + +static int f81534a_ctrl_generate_ports(struct usb_interface *intf, + struct f81534a_device *device) +{ + struct usb_device *dev = interface_to_usbdev(intf); + uint32_t port_status; + u8 enable[2]; + u8 tmp; + u8 mask; + int status; + + /* enable all ports */ + mask = F81534A_GPIO_MODE2_DIR | F81534A_GPIO_MODE1_DIR | + F81534A_GPIO_MODE0_DIR; + enable[0] = 0xff; + enable[1] = 0x8f; + + status = f81534a_ctrl_set_register(dev, F81534A_CMD_ENABLE_PORT, + sizeof(enable), enable); + if (status) { + dev_warn(&dev->dev, "set CMD_ENABLE_PORT failed: %d\n", status); + return status; + } + + /* get port state */ + status = f81534a_ctrl_get_register(dev, + F81534A_CMD_PORT_STATUS, sizeof(port_status), + &port_status); + if (status) { + dev_warn(&dev->dev, "get CMD_PORT_STATUS failed: %d\n", status); + return status; + } + + port_status >>= 16; + + for (; device->check_index < F81534A_MAX_PORT; ++device->check_index) { + /* check port is exist, skip when not exist */ + if (!(port_status & BIT(device->check_index))) + continue; + + /* + * All gpio for a port is default to input mode. It'll change + * to RS232 mode after f81232_port_probe()/f81534a_port_init() + * (2 output 0 & 1 input with pull high). + */ + status = f81534a_ctrl_get_register(dev, + F81534A_CTRL_GPIO_REG + + device->check_index, sizeof(tmp), &tmp); + if (status) { + dev_warn(&dev->dev, "get CTRL_GPIO_REG failed: %d\n", + status); + return status; + } + + /* Check port had inited by f81232_port_probe() */ + if ((tmp & mask) == mask) + break; + } + + if (device->check_index < F81534A_MAX_PORT) + return -EAGAIN; + + return 0; +} + +static void f81534a_ctrl_generate_worker(struct work_struct *work) +{ + struct f81534a_device *device; + int status; + + mutex_lock(&device_mutex); + list_for_each_entry(device, &device_list, list) { + if (device->check_index >= F81534A_MAX_PORT) + continue; + + if (device->check_retry >= F81534A_CTRL_RETRY) + continue; + + device->check_retry++; + + status = f81534a_ctrl_generate_ports(device->intf, device); + if (status == -EAGAIN) { + dev_dbg(&device->intf->dev, "delayed generating: %d\n", + device->check_retry); + + schedule_delayed_work(&f81534a_generate_worker, + msecs_to_jiffies(F81534A_CTRL_TIMER)); + break; + } else if (!status) { + /* make this device generated */ + device->check_index = F81534A_MAX_PORT; + + dev_dbg(&device->intf->dev, "generated complete\n"); + } else { + /* skip this device to generate */ + device->check_index = F81534A_MAX_PORT; + + dev_err(&device->intf->dev, + "error: %d, do next device generate\n", + status); + } + } + + mutex_unlock(&device_mutex); +} + +static int f81534a_ctrl_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct f81534a_ctrl_private *priv; + struct f81534a_device *device; + + priv = devm_kzalloc(&intf->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + device = devm_kzalloc(&intf->dev, sizeof(*device), GFP_KERNEL); + if (!device) + return -ENOMEM; + + mutex_init(&priv->lock); + usb_set_intfdata(intf, priv); + + INIT_LIST_HEAD(&device->list); + device->intf = intf; + + mutex_lock(&device_mutex); + list_add_tail(&device->list, &device_list); + mutex_unlock(&device_mutex); + + dev = usb_get_dev(dev); + schedule_delayed_work(&f81534a_generate_worker, + msecs_to_jiffies(F81534A_CTRL_TIMER)); + + return 0; +} + +static void f81534a_ctrl_disconnect(struct usb_interface *intf) +{ + struct f81534a_ctrl_private *priv; + struct f81534a_device *device; + struct usb_device *dev; + + mutex_lock(&device_mutex); + + list_for_each_entry(device, &device_list, list) { + if (device->intf == intf) { + list_del(&device->list); + + priv = usb_get_intfdata(intf); + dev = interface_to_usbdev(intf); + usb_put_dev(dev); + break; + } + } + + mutex_unlock(&device_mutex); +} + +static int f81534a_ctrl_suspend(struct usb_interface *intf, + pm_message_t message) +{ + struct f81534a_device *device; + + flush_delayed_work(&f81534a_generate_worker); + + mutex_lock(&device_mutex); + + list_for_each_entry(device, &device_list, list) { + device->check_index = 0; + device->check_retry = 0; + } + + mutex_unlock(&device_mutex); + + return 0; +} + +static int f81534a_ctrl_resume(struct usb_interface *intf) +{ + schedule_delayed_work(&f81534a_generate_worker, + msecs_to_jiffies(F81534A_CTRL_TIMER)); + + return 0; +} + static int f81232_port_probe(struct usb_serial_port *port) { struct f81232_private *priv; @@ -976,7 +1292,45 @@ static struct usb_serial_driver * const serial_drivers[] = { NULL, }; -module_usb_serial_driver(serial_drivers, id_table); +static struct usb_driver f81534a_ctrl_driver = { + .name = "f81534a_ctrl", + .id_table = f81534a_ctrl_id_table, + .probe = f81534a_ctrl_probe, + .disconnect = f81534a_ctrl_disconnect, + .suspend = f81534a_ctrl_suspend, + .resume = f81534a_ctrl_resume, +}; + +static int __init f81232_init(void) +{ + int status; + + INIT_DELAYED_WORK(&f81534a_generate_worker, + f81534a_ctrl_generate_worker); + + status = usb_register_driver(&f81534a_ctrl_driver, THIS_MODULE, + KBUILD_MODNAME); + if (status) + return status; + + status = usb_serial_register_drivers(serial_drivers, KBUILD_MODNAME, + id_table); + if (status) { + usb_deregister(&f81534a_ctrl_driver); + return status; + } + + return 0; +} + +static void __exit f81232_exit(void) +{ + usb_serial_deregister_drivers(serial_drivers); + usb_deregister(&f81534a_ctrl_driver); +} + +module_init(f81232_init); +module_exit(f81232_exit); MODULE_DESCRIPTION("Fintek F81232/532A/534A/535/536 USB to serial driver"); MODULE_AUTHOR("Greg Kroah-Hartman "); From patchwork Thu Jun 6 02:54:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Ji-Ze Hong (Peter Hong)" X-Patchwork-Id: 10978357 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0B3961398 for ; Thu, 6 Jun 2019 02:55:12 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F012C28762 for ; Thu, 6 Jun 2019 02:55:11 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E04CE28774; Thu, 6 Jun 2019 02:55:11 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8FA1028762 for ; Thu, 6 Jun 2019 02:55:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726809AbfFFCys (ORCPT ); Wed, 5 Jun 2019 22:54:48 -0400 Received: from mail-pf1-f196.google.com ([209.85.210.196]:38362 "EHLO mail-pf1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726805AbfFFCyr (ORCPT ); Wed, 5 Jun 2019 22:54:47 -0400 Received: by mail-pf1-f196.google.com with SMTP id a186so543383pfa.5; Wed, 05 Jun 2019 19:54:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Yl9bICfQdMFLxb1DttR8RqORrTiqyN8JdwYLjgX91/U=; b=AfeSAnTeQRCB0nQnwoi0e2piWSTUtDfJENIhV6jJu2HPPJpQ0mkit5uQyY5cEGeRTF uoAviqx/roHxPu8k39BFpM+Wyasp5tDLVRAjFHj5M9PpfhAGjU3OaGBEpywiV0GnY7Iq qh5J7HFukS/axAwtTyNsyjKLg4oJEMmQHhPtTi2r9w57DHj5VcMFTaMFznE4M4bqvi3l Ah2AbuWfDNMorXQtTbZ10vyYOK05Om6Wa4trmyLmZOy2MBaqXEXWQesvmpXtrZW2nOIr gbwbC9ZFOEhq7XzMC2L7rkBXTRQ5PjbHfST3veO5Kt+aZ/iLwVzzQ+VQnAbVFp2N4VqI tmsg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Yl9bICfQdMFLxb1DttR8RqORrTiqyN8JdwYLjgX91/U=; b=mRtM0LmkxYapXROvhKi/0mPKhku6QhYLNPd76UGXEMa7P3CUzO8ainX7XN+gBtiw0v oy4tSig737bXTHksm8nWM+WhVJ9/oe6r7xrHG6Ua/pvRxGkumFvv135ExZbDQ+ZGDUB7 rvxhsU/EsyqJcNgg0oVmuXEcDxG4+Nod5zvGHNpZfstHRghqAc3ywRDLgGIyabQobLyX rEAbCCs53GhBvwwUtTx5cwf6mJpQz5DuZuybLQ30lhG/x/tAKvOIGu56wiMvVRAIp0p9 e+xNBWug8TRXCjK8tc0sFVIjxM8iqyhxC8RMQLEmPT1hkgBozfj2PWGQS8FXWNEyW8+V EhHQ== X-Gm-Message-State: APjAAAUd9qOAr2iNWvddxXR6HWJ8gZGa5y5TdcTV2AeCew+RbYtKmP24 +IGHqkvJ6ubIw13s7AOEvOM= X-Google-Smtp-Source: APXvYqy2rUstADv8drRPFZ9GFWCTnuXiSrB7oUOQdtpkib17Pl/1rxa61EWeJO9oresXcW7yuYU3oQ== X-Received: by 2002:a63:161b:: with SMTP id w27mr1091510pgl.338.1559789686950; Wed, 05 Jun 2019 19:54:46 -0700 (PDT) Received: from localhost (59-120-186-245.HINET-IP.hinet.net. [59.120.186.245]) by smtp.gmail.com with ESMTPSA id n21sm294331pff.92.2019.06.05.19.54.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 05 Jun 2019 19:54:46 -0700 (PDT) From: "Ji-Ze Hong (Peter Hong)" X-Google-Original-From: "Ji-Ze Hong (Peter Hong)" To: johan@kernel.org Cc: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, peter_hong@fintek.com.tw, "Ji-Ze Hong (Peter Hong)" Subject: [PATCH V1 4/6] USB: serial: f81232: Add tx_empty function Date: Thu, 6 Jun 2019 10:54:14 +0800 Message-Id: <1559789656-15847-5-git-send-email-hpeter+linux_kernel@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1559789656-15847-1-git-send-email-hpeter+linux_kernel@gmail.com> References: <1559789656-15847-1-git-send-email-hpeter+linux_kernel@gmail.com> Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add tx_empty() function for F81232 & F81534A series. Signed-off-by: Ji-Ze Hong (Peter Hong) --- drivers/usb/serial/f81232.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index e9470fb0d691..7d1ec8f9d168 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -850,6 +850,24 @@ static void f81232_dtr_rts(struct usb_serial_port *port, int on) f81232_set_mctrl(port, 0, TIOCM_DTR | TIOCM_RTS); } +static bool f81232_tx_empty(struct usb_serial_port *port) +{ + int status; + u8 tmp; + u8 both_empty = UART_LSR_TEMT | UART_LSR_THRE; + + status = f81232_get_register(port, LINE_STATUS_REGISTER, &tmp); + if (status) { + dev_err(&port->dev, "get LSR status failed: %d\n", status); + return false; + } + + if ((tmp & both_empty) != both_empty) + return false; + + return true; +} + static int f81232_carrier_raised(struct usb_serial_port *port) { u8 msr; @@ -1279,6 +1297,7 @@ static struct usb_serial_driver f81232_device = { .tiocmget = f81232_tiocmget, .tiocmset = f81232_tiocmset, .tiocmiwait = usb_serial_generic_tiocmiwait, + .tx_empty = f81232_tx_empty, .process_read_urb = f81232_read_urb_proxy, .read_int_callback = f81232_read_int_callback, .port_probe = f81232_port_probe, From patchwork Thu Jun 6 02:54:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Ji-Ze Hong (Peter Hong)" X-Patchwork-Id: 10978355 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BC2881398 for ; Thu, 6 Jun 2019 02:55:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ADE5F28762 for ; Thu, 6 Jun 2019 02:55:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A050B28774; Thu, 6 Jun 2019 02:55:04 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 920EE28762 for ; Thu, 6 Jun 2019 02:55:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726855AbfFFCzC (ORCPT ); Wed, 5 Jun 2019 22:55:02 -0400 Received: from mail-pf1-f195.google.com ([209.85.210.195]:46789 "EHLO mail-pf1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726836AbfFFCyu (ORCPT ); Wed, 5 Jun 2019 22:54:50 -0400 Received: by mail-pf1-f195.google.com with SMTP id y11so517854pfm.13; Wed, 05 Jun 2019 19:54:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ysY+52fXMYI7MZwAXhhPIwcn7G+33VLkTlff+m5jejA=; b=KsA3nuu4Ro2foXc43IhBKNFQ7rh67P0KGHzmxz7m9f/oV3mj7ycORtzRX3NxCkXvMa cnH+kU33bbdJFQH1sRpyEbZFsN0xgho3dosKvHh9GqSu6XIxONAE7jCDR23WL7AFI+Mn XnxgM38THM+qU08dKGHSUHiEen1LWyv5I4Yb3GXNCo5KWYtBdhPJg0VeIKQMM/JNrK0J Tb6+rGF3jOhz/QZW348OfG9Rnld9PwO3DLPXFahWKNHLI5Ep+vlvCTnhd36pn46uTDEH twZWqIupF7avQ+L4KQvOP4g53S8WEdJgvEn0VtCKfnmMfPNw+6uQhsI3W+tbBOWOmqFv FQXg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ysY+52fXMYI7MZwAXhhPIwcn7G+33VLkTlff+m5jejA=; b=Cx5pc33xI6zdX67rdaLVsy0VaR0P4GuUMVpuKR4SdKux3TRAXbH+NVnrvMt2wTMQmd UWTxzeKi2joAw/NvKvbqsaANmV5pZWrPkXKfoITAtJWHHv3F8Wv7nZ2nA5yHc8haJyLP SUYA/E26AwJTnIbzoFtCmwd7kCNhQvHxrKg3fFb9QpB1jpBkowDz0N+g2YsJ7ueeaZXN afwzvFMjhkn9d4xlf55yBr6GUFGV3v3Oo5kOmFK9T1STB4rSTW7IzkWmQ1dN9rSkYciT Widz5qaH5n/3ZXopGQr5kDZRkmHfSeiIEh2km4eRPFNwKv7r7VFHCmSCwSaIxFpAm2FC kerQ== X-Gm-Message-State: APjAAAWBty0d6EtN6kQyl59mq/FnlB9qzsSYvU9yFB5sEo7H4KOqGP/U y/MzJULayu+ISb/cfP8he7E= X-Google-Smtp-Source: APXvYqzYYI/fIy/eRjqqtSlAUlZEkTA+bhjkS7lyv59ClWfmPjdn/8fEQuzHeoXxTJrVhY+fNJWrRg== X-Received: by 2002:a17:90a:a616:: with SMTP id c22mr48684484pjq.46.1559789689688; Wed, 05 Jun 2019 19:54:49 -0700 (PDT) Received: from localhost (59-120-186-245.HINET-IP.hinet.net. [59.120.186.245]) by smtp.gmail.com with ESMTPSA id 10sm290548pfh.179.2019.06.05.19.54.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 05 Jun 2019 19:54:48 -0700 (PDT) From: "Ji-Ze Hong (Peter Hong)" X-Google-Original-From: "Ji-Ze Hong (Peter Hong)" To: johan@kernel.org Cc: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, peter_hong@fintek.com.tw, "Ji-Ze Hong (Peter Hong)" Subject: [PATCH V1 5/6] USB: serial: f81232: Use devm_kzalloc Date: Thu, 6 Jun 2019 10:54:15 +0800 Message-Id: <1559789656-15847-6-git-send-email-hpeter+linux_kernel@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1559789656-15847-1-git-send-email-hpeter+linux_kernel@gmail.com> References: <1559789656-15847-1-git-send-email-hpeter+linux_kernel@gmail.com> Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Use devm_kzalloc() to replace kzalloc(). Signed-off-by: Ji-Ze Hong (Peter Hong) --- drivers/usb/serial/f81232.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index 7d1ec8f9d168..708d85c7d822 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -1198,7 +1198,7 @@ static int f81232_port_probe(struct usb_serial_port *port) struct f81232_private *priv; int status = 0; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); + priv = devm_kzalloc(&port->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -1234,16 +1234,6 @@ static int f81232_port_probe(struct usb_serial_port *port) return status; } -static int f81232_port_remove(struct usb_serial_port *port) -{ - struct f81232_private *priv; - - priv = usb_get_serial_port_data(port); - kfree(priv); - - return 0; -} - static int f81232_suspend(struct usb_serial *serial, pm_message_t message) { struct usb_serial_port *port = serial->port[0]; @@ -1301,7 +1291,6 @@ static struct usb_serial_driver f81232_device = { .process_read_urb = f81232_read_urb_proxy, .read_int_callback = f81232_read_int_callback, .port_probe = f81232_port_probe, - .port_remove = f81232_port_remove, .suspend = f81232_suspend, .resume = f81232_resume, }; From patchwork Thu Jun 6 02:54:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Ji-Ze Hong (Peter Hong)" X-Patchwork-Id: 10978353 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6030F17D2 for ; Thu, 6 Jun 2019 02:55:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4FA6428762 for ; Thu, 6 Jun 2019 02:55:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 41BFC28774; Thu, 6 Jun 2019 02:55:01 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A172B28762 for ; Thu, 6 Jun 2019 02:55:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726872AbfFFCyz (ORCPT ); Wed, 5 Jun 2019 22:54:55 -0400 Received: from mail-pg1-f194.google.com ([209.85.215.194]:39130 "EHLO mail-pg1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726855AbfFFCyw (ORCPT ); Wed, 5 Jun 2019 22:54:52 -0400 Received: by mail-pg1-f194.google.com with SMTP id 196so451730pgc.6; Wed, 05 Jun 2019 19:54:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=9qzxTtSrBQ5yiYZWANHKeD1gxX9yGCs4JtFgEEpNmLc=; b=NFHl48wdu8H54gDe3MgtK+zK2XtWsCKvwwV4Z+4p726sGav4e8v8zMWQwVrl1cRGb9 S7uALOI2m3zWMVTxlKjFikWCCqtFYOWDsJeLI80Y2Tt21PAdXLJ8/8RmiVQnlmfHTTfK 8oYbbIakk0wEep88Dui7DYGOGxIGJBRtGZ4zmKeFKsVtvMV+b+cPpaDXpSxYefBkQ7SQ UZITjleVI2SJoFqkTRHUR6ROdY1vEn26K/w71xDpwgqH71LE6ui+33E1A4awEkXZ8pu0 rWv5GsuZ3u82xTjIH8jQk1g+dOKMeGhxfx7SDyEPTx7fY9qJQ02nhfEnCLSbtj8Fx2Ad WW0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=9qzxTtSrBQ5yiYZWANHKeD1gxX9yGCs4JtFgEEpNmLc=; b=YlXQyJoc95fuHK8Cz/3jhWBOFK/HOptdtb4FoRHkdF2yaarzphazFFhi5yPlaKxlru ZsUlsiLtdOMi6Yu9bIsMH2Yh+c5bXro+D+Rki01xkISls1kuUNLIIlKDzxbxoQZJUMNg qA6X+X8VjsYhNGk3zkC4FRgSO6i+yQdGtZhEe0um91eheg1v1+FPCH4otabv7p5zhpUE L7ZApYvaZDq545QZdG72bKegDhhgsFgI6wtzLqQ4qfwouBOXnv4DhPzW0A18XVtH3z6U 2Zwvzbz4bOtXzIWPEawm184kYAlSJLogZa6LKBnJxL6xO6qDpAhffUeDoS3shVl8wwII 8B5A== X-Gm-Message-State: APjAAAW2wqc2QmGwf0YNeHvrIYRyoWLjwRdcOk02CWdIGnmBTg9PwvEb PXbebgg8BvjXYeLAgNoyC9E= X-Google-Smtp-Source: APXvYqyvH2xV0j/BKNa3c3je66CbNvcNM+2U5qvxAcIIW8NMYNcHuH5hfA7X7p8VPs7YkggkXMn98Q== X-Received: by 2002:a62:3006:: with SMTP id w6mr48521974pfw.159.1559789691779; Wed, 05 Jun 2019 19:54:51 -0700 (PDT) Received: from localhost (59-120-186-245.HINET-IP.hinet.net. [59.120.186.245]) by smtp.gmail.com with ESMTPSA id j14sm304049pfe.10.2019.06.05.19.54.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 05 Jun 2019 19:54:51 -0700 (PDT) From: "Ji-Ze Hong (Peter Hong)" X-Google-Original-From: "Ji-Ze Hong (Peter Hong)" To: johan@kernel.org Cc: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, peter_hong@fintek.com.tw, "Ji-Ze Hong (Peter Hong)" Subject: [PATCH V1 6/6] USB: serial: f81232: Add gpiolib to GPIO device Date: Thu, 6 Jun 2019 10:54:16 +0800 Message-Id: <1559789656-15847-7-git-send-email-hpeter+linux_kernel@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1559789656-15847-1-git-send-email-hpeter+linux_kernel@gmail.com> References: <1559789656-15847-1-git-send-email-hpeter+linux_kernel@gmail.com> Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The Fintek F81534A series contains 3 GPIOs per UART and The max GPIOs is 12x3 = 36 GPIOs. Signed-off-by: Ji-Ze Hong (Peter Hong) --- drivers/usb/serial/f81232.c | 210 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index 708d85c7d822..a53240bc164a 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -132,6 +133,7 @@ struct f81232_private { struct f81534a_ctrl_private { struct usb_interface *intf; + struct gpio_chip chip; struct mutex lock; int device_idx; }; @@ -1007,6 +1009,204 @@ static int f81534a_ctrl_set_register(struct usb_device *dev, u16 reg, u16 size, return status; } +static int f81534a_ctrl_set_mask_register(struct usb_device *dev, u16 reg, + u8 mask, u8 val) +{ + int status; + u8 tmp; + + status = f81534a_ctrl_get_register(dev, reg, 1, &tmp); + if (status) + return status; + + + tmp = (tmp & ~mask) | (val & mask); + + status = f81534a_ctrl_set_register(dev, reg, 1, &tmp); + if (status) + return status; + + return 0; +} + +#ifdef CONFIG_GPIOLIB +static int f81534a_gpio_get(struct gpio_chip *chip, unsigned int gpio_num) +{ + struct f81534a_ctrl_private *priv = gpiochip_get_data(chip); + struct usb_interface *intf = priv->intf; + struct usb_device *dev = interface_to_usbdev(intf); + int status; + u8 tmp[2]; + int set; + int idx; + + set = gpio_num / F81534A_CTRL_GPIO_MAX_PIN; + idx = gpio_num % F81534A_CTRL_GPIO_MAX_PIN; + + status = mutex_lock_interruptible(&priv->lock); + if (status) + return -EINTR; + + status = f81534a_ctrl_get_register(dev, F81534A_CTRL_GPIO_REG + set, + sizeof(tmp), tmp); + if (status) { + mutex_unlock(&priv->lock); + return status; + } + + mutex_unlock(&priv->lock); + + return !!(tmp[1] & BIT(idx)); +} + +static int f81534a_gpio_direction_in(struct gpio_chip *chip, + unsigned int gpio_num) +{ + struct f81534a_ctrl_private *priv = gpiochip_get_data(chip); + struct usb_interface *intf = priv->intf; + struct usb_device *dev = interface_to_usbdev(intf); + int status; + int set; + int idx; + u8 mask; + + set = gpio_num / F81534A_CTRL_GPIO_MAX_PIN; + idx = gpio_num % F81534A_CTRL_GPIO_MAX_PIN; + mask = F81534A_GPIO_MODE0_DIR << idx; + + status = mutex_lock_interruptible(&priv->lock); + if (status) + return -EINTR; + + status = f81534a_ctrl_set_mask_register(dev, F81534A_CTRL_GPIO_REG + + set, mask, mask); + if (status) { + mutex_unlock(&priv->lock); + return status; + } + + mutex_unlock(&priv->lock); + + return 0; +} + +static int f81534a_gpio_direction_out(struct gpio_chip *chip, + unsigned int gpio_num, int val) +{ + struct f81534a_ctrl_private *priv = gpiochip_get_data(chip); + struct usb_interface *intf = priv->intf; + struct usb_device *dev = interface_to_usbdev(intf); + int status; + int set; + int idx; + u8 mask; + u8 data; + + set = gpio_num / F81534A_CTRL_GPIO_MAX_PIN; + idx = gpio_num % F81534A_CTRL_GPIO_MAX_PIN; + mask = (F81534A_GPIO_MODE0_DIR << idx) | BIT(idx); + data = val ? BIT(idx) : 0; + + status = mutex_lock_interruptible(&priv->lock); + if (status) + return -EINTR; + + status = f81534a_ctrl_set_mask_register(dev, F81534A_CTRL_GPIO_REG + + set, mask, data); + if (status) { + mutex_unlock(&priv->lock); + return status; + } + + mutex_unlock(&priv->lock); + + return 0; +} + +static void f81534a_gpio_set(struct gpio_chip *chip, unsigned int gpio_num, + int val) +{ + f81534a_gpio_direction_out(chip, gpio_num, val); +} + +static int f81534a_gpio_get_direction(struct gpio_chip *chip, + unsigned int gpio_num) +{ + struct f81534a_ctrl_private *priv = gpiochip_get_data(chip); + struct usb_interface *intf = priv->intf; + struct usb_device *dev = interface_to_usbdev(intf); + int status; + u8 tmp[2]; + int set; + int idx; + u8 mask; + + set = gpio_num / F81534A_CTRL_GPIO_MAX_PIN; + idx = gpio_num % F81534A_CTRL_GPIO_MAX_PIN; + mask = F81534A_GPIO_MODE0_DIR << idx; + + status = mutex_lock_interruptible(&priv->lock); + if (status) + return -EINTR; + + status = f81534a_ctrl_get_register(dev, F81534A_CTRL_GPIO_REG + set, + sizeof(tmp), tmp); + if (status) { + mutex_unlock(&priv->lock); + return status; + } + + mutex_unlock(&priv->lock); + + if (tmp[0] & mask) + return GPIOF_DIR_IN; + + return GPIOF_DIR_OUT; +} + +static int f81534a_prepare_gpio(struct usb_interface *intf) +{ + struct f81534a_ctrl_private *priv = usb_get_intfdata(intf); + int status; + + priv->chip.parent = &intf->dev; + priv->chip.owner = THIS_MODULE; + priv->chip.get_direction = f81534a_gpio_get_direction, + priv->chip.get = f81534a_gpio_get; + priv->chip.direction_input = f81534a_gpio_direction_in; + priv->chip.set = f81534a_gpio_set; + priv->chip.direction_output = f81534a_gpio_direction_out; + priv->chip.label = "f81534a"; + /* M0(SD)/M1/M2 */ + priv->chip.ngpio = F81534A_CTRL_GPIO_MAX_PIN * F81534A_MAX_PORT; + priv->chip.base = -1; + + priv->intf = intf; + mutex_init(&priv->lock); + + status = devm_gpiochip_add_data(&intf->dev, &priv->chip, priv); + if (status) { + dev_err(&intf->dev, "%s: failed: %d\n", __func__, status); + return status; + } + + return 0; +} +#else +static int f81534a_prepare_gpio(struct usb_interface *intf) +{ + dev_warn(&intf->dev, "CONFIG_GPIOLIB is not enabled\n"); + dev_warn(&intf->dev, "The GPIOLIB interface will not register\n"); + + return 0; +} +#endif + +static int f81534a_release_gpio(struct usb_interface *intf) +{ + return 0; +} + static int f81534a_ctrl_generate_ports(struct usb_interface *intf, struct f81534a_device *device) { @@ -1118,6 +1318,7 @@ static int f81534a_ctrl_probe(struct usb_interface *intf, struct usb_device *dev = interface_to_usbdev(intf); struct f81534a_ctrl_private *priv; struct f81534a_device *device; + int status; priv = devm_kzalloc(&intf->dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -1130,6 +1331,10 @@ static int f81534a_ctrl_probe(struct usb_interface *intf, mutex_init(&priv->lock); usb_set_intfdata(intf, priv); + status = f81534a_prepare_gpio(intf); + if (status) + return status; + INIT_LIST_HEAD(&device->list); device->intf = intf; @@ -1158,6 +1363,11 @@ static void f81534a_ctrl_disconnect(struct usb_interface *intf) priv = usb_get_intfdata(intf); dev = interface_to_usbdev(intf); + + mutex_lock(&priv->lock); + f81534a_release_gpio(intf); + mutex_unlock(&priv->lock); + usb_put_dev(dev); break; }