From patchwork Tue Feb 11 17:45:12 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Genoud X-Patchwork-Id: 3628691 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id D5A589F2D6 for ; Tue, 11 Feb 2014 17:51:59 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DDF4020165 for ; Tue, 11 Feb 2014 17:51:58 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A4310201F2 for ; Tue, 11 Feb 2014 17:51:57 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WDHUP-0003gU-5G; Tue, 11 Feb 2014 17:51:21 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WDHPW-0004FY-P7; Tue, 11 Feb 2014 17:46:18 +0000 Received: from mail-ea0-x22b.google.com ([2a00:1450:4013:c01::22b]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WDHPL-0004DL-FK for linux-arm-kernel@lists.infradead.org; Tue, 11 Feb 2014 17:46:10 +0000 Received: by mail-ea0-f171.google.com with SMTP id f15so3844542eak.2 for ; Tue, 11 Feb 2014 09:45:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=kxow5JjTPUISlDLC1vB4iLLLi4qzMDYENaVdXAWs/p4=; b=SMPYRSYm2eUB8ebbdrF71ZIxvEQOabq66W07mPitDmzyQS5XkaWsFiZFLPgQjtbxae 6oYDjXQAaV3Tq6B0NkqblC5DHkRhuhEVQA8xL8A55SEQPv7J9J3gSjAiCJm+19BH+lax 76IdF1vsp59hRr2KfsM151NR1FLM2mmFFHT4y1lXlC28TQT+V7m0HTekjQmkHvE7pLSR NSpDZKDN/wHtfA6cVMGLmeSv3btivYHPZszJJuDSy/r5Se0dCSexqRp/OXNep3fiGKfy cX90+8C+x88NbwOs517vTQZ+JvXwb8aVLCe7r7SHmPkyFgkG02HMXxBs3f+OydVjsNU0 er4Q== X-Received: by 10.15.43.141 with SMTP id x13mr45144092eev.35.1392140745451; Tue, 11 Feb 2014 09:45:45 -0800 (PST) Received: from lnx-rg.pr (lyon.paratronic.fr. [213.41.177.106]) by mx.google.com with ESMTPSA id x2sm69856818eeo.8.2014.02.11.09.45.43 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 11 Feb 2014 09:45:44 -0800 (PST) From: Richard Genoud To: Greg Kroah-Hartman Subject: [PATCH v2 1/4] tty/serial: Add GPIOLIB helpers for controlling modem lines Date: Tue, 11 Feb 2014 18:45:12 +0100 Message-Id: <1392140715-15295-2-git-send-email-richard.genoud@gmail.com> X-Mailer: git-send-email 1.8.5 In-Reply-To: <1392140715-15295-1-git-send-email-richard.genoud@gmail.com> References: <1392140715-15295-1-git-send-email-richard.genoud@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140211_124607_840946_27C46BDB X-CRM114-Status: GOOD ( 18.30 ) X-Spam-Score: -2.0 (--) Cc: Alexander Shiyan , Richard Genoud , Linus Walleij , Nicolas Ferre , linux-serial@vger.kernel.org, =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.7 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch add some helpers to control modem lines (CTS/RTS/DSR...) via GPIO. This will be useful for many boards which have a serial controller that only handle CTS/RTS pins (or even just RX/TX). Signed-off-by: Richard Genoud --- Documentation/serial/driver | 21 ++++++ drivers/tty/serial/Kconfig | 4 ++ drivers/tty/serial/Makefile | 3 + drivers/tty/serial/serial_mctrl_gpio.c | 113 +++++++++++++++++++++++++++++++++ drivers/tty/serial/serial_mctrl_gpio.h | 56 ++++++++++++++++ 5 files changed, 197 insertions(+) create mode 100644 drivers/tty/serial/serial_mctrl_gpio.c create mode 100644 drivers/tty/serial/serial_mctrl_gpio.h diff --git a/Documentation/serial/driver b/Documentation/serial/driver index c3a7689a90e6..b33f0f9e1b8e 100644 --- a/Documentation/serial/driver +++ b/Documentation/serial/driver @@ -429,3 +429,24 @@ thus: struct uart_port port; int my_stuff; }; + +Modem control lines via GPIO +---------------------------- + +Some helpers are provided in order to set/get modem control lines via GPIO. + +mctrl_gpio_init(dev, gpios): + This will get the {cts,rts,...}-gpios from device tree if they are + present and request them, set direction etc. + +mctrl_gpio_free(gpios): + This will free the requested gpios in mctrl_gpio_init(). + +mctrl_gpio_set(gpios, mctrl): + This will sets the gpios according to the mctrl state. + +mctrl_gpio_get(gpios, mctrl): + This will update mctrl with the gpios values. + +get_mctrl_gpio_name(mctrl_gpio_idx): + Returns a name associated to the GPIO modem line. diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index a3815eaed421..58c54d7eae53 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1509,4 +1509,8 @@ config SERIAL_ST_ASC_CONSOLE endmenu +config SERIAL_MCTRL_GPIO + def_bool y + depends on GPIOLIB + endif # TTY diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 3680854fef41..bcf31da267dd 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -87,3 +87,6 @@ obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o obj-$(CONFIG_SERIAL_ARC) += arc_uart.o obj-$(CONFIG_SERIAL_RP2) += rp2.o obj-$(CONFIG_SERIAL_FSL_LPUART) += fsl_lpuart.o + +# GPIOLIB helpers for modem control lines +obj-$(CONFIG_SERIAL_MCTRL_GPIO) += serial_mctrl_gpio.o diff --git a/drivers/tty/serial/serial_mctrl_gpio.c b/drivers/tty/serial/serial_mctrl_gpio.c new file mode 100644 index 000000000000..ddcc7538f487 --- /dev/null +++ b/drivers/tty/serial/serial_mctrl_gpio.c @@ -0,0 +1,113 @@ +/* + * Helpers for controlling modem lines via GPIO + * + * Copyright (C) 2014 Paratronic S.A. + * + */ + +#include +#include +#include + +#include "serial_mctrl_gpio.h" + +static const char *mctrl_gpio_of_names[UART_GPIO_MAX] = { + "cts", "dsr", "dcd", "ri", "rts", "dtr" +}; + +const char *get_mctrl_gpio_name(enum mctrl_gpio_idx idx) +{ + return mctrl_gpio_of_names[idx]; +} +EXPORT_SYMBOL_GPL(get_mctrl_gpio_name); + +void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl) +{ + if (!IS_ERR_OR_NULL(gpios->gpio[UART_GPIO_RTS])) + gpiod_set_value(gpios->gpio[UART_GPIO_RTS], + !!(mctrl & TIOCM_RTS)); + + if (!IS_ERR_OR_NULL(gpios->gpio[UART_GPIO_DTR])) + gpiod_set_value(gpios->gpio[UART_GPIO_DTR], + !!(mctrl & TIOCM_DTR)); +} +EXPORT_SYMBOL_GPL(mctrl_gpio_set); + +unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl) +{ + if (!IS_ERR_OR_NULL(gpios->gpio[UART_GPIO_CTS])) { + if (gpiod_get_value(gpios->gpio[UART_GPIO_CTS])) + *mctrl |= TIOCM_CTS; + else + *mctrl &= ~TIOCM_CTS; + } + + if (!IS_ERR_OR_NULL(gpios->gpio[UART_GPIO_DSR])) { + if (gpiod_get_value(gpios->gpio[UART_GPIO_DSR])) + *mctrl |= TIOCM_DSR; + else + *mctrl &= ~TIOCM_DSR; + } + + if (!IS_ERR_OR_NULL(gpios->gpio[UART_GPIO_RI])) { + if (gpiod_get_value(gpios->gpio[UART_GPIO_RI])) + *mctrl |= TIOCM_RI; + else + *mctrl &= ~TIOCM_RI; + } + + if (!IS_ERR_OR_NULL(gpios->gpio[UART_GPIO_DCD])) { + if (gpiod_get_value(gpios->gpio[UART_GPIO_DCD])) + *mctrl |= TIOCM_CD; + else + *mctrl &= ~TIOCM_CD; + } + + return *mctrl; +} +EXPORT_SYMBOL_GPL(mctrl_gpio_get); + +int mctrl_gpio_init(struct device *dev, struct mctrl_gpios *gpios) +{ + enum mctrl_gpio_idx i; + int err = 0; + int ret = 0; + + for (i = UART_GPIO_MIN; i < UART_GPIO_MAX; i++) { + gpios->gpio[i] = gpiod_get(dev, mctrl_gpio_of_names[i]); + + /* + * The GPIOs are maybe not all filled, + * this is not an error. + */ + if (IS_ERR_OR_NULL(gpios->gpio[i])) + continue; + + if (i < UART_GPIO_MAX_INPUT) + err = gpiod_direction_input(gpios->gpio[i]); + else + err = gpiod_direction_output(gpios->gpio[i], 0); + if (err) { + dev_err(dev, "Unable to set direction for %s GPIO", + mctrl_gpio_of_names[i]); + gpiod_put(gpios->gpio[i]); + gpios->gpio[i] = NULL; + ret--; + } + } + + return ret; +} +EXPORT_SYMBOL_GPL(mctrl_gpio_init); + +void mctrl_gpio_free(struct mctrl_gpios *gpios) +{ + enum mctrl_gpio_idx i; + + for (i = UART_GPIO_MIN; i < UART_GPIO_MAX; i++) + if (!IS_ERR_OR_NULL(gpios->gpio[i])) { + gpiod_put(gpios->gpio[i]); + gpios->gpio[i] = NULL; + } +} +EXPORT_SYMBOL_GPL(mctrl_gpio_free); diff --git a/drivers/tty/serial/serial_mctrl_gpio.h b/drivers/tty/serial/serial_mctrl_gpio.h new file mode 100644 index 000000000000..5b8be48f6442 --- /dev/null +++ b/drivers/tty/serial/serial_mctrl_gpio.h @@ -0,0 +1,56 @@ +/* + * Helpers for controlling modem lines via GPIO + * + * Copyright (C) 2014 Paratronic S.A. + * + */ + +#ifndef __SERIAL_MCTRL_GPIO__ +#define __SERIAL_MCTRL_GPIO__ + +#include + +enum mctrl_gpio_idx { + UART_GPIO_MIN = 0, + UART_GPIO_CTS = 0, + UART_GPIO_DSR = 1, + UART_GPIO_DCD = 2, + UART_GPIO_RI = 3, + UART_GPIO_MAX_INPUT = 4, + UART_GPIO_RTS = 4, + UART_GPIO_DTR = 5, + UART_GPIO_MAX, +}; + +struct mctrl_gpios { + struct gpio_desc *gpio[UART_GPIO_MAX]; +}; + +/* + * Names of the modem lines (cts, dsr, dcd...) + */ +const char *get_mctrl_gpio_name(enum mctrl_gpio_idx idx); + +/* + * Set state of the modem control output lines via GPIOs. + */ +void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl); + +/* + * Get state of the modem control output lines from GPIOs. + * The mctrl flags are updated and returned. + */ +unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl); + +/* + * Request and set direction of modem control lines GPIOs. + * Returns 0 if ok, -nb_err if setting direction failed. + */ +int mctrl_gpio_init(struct device *dev, struct mctrl_gpios *gpios); + +/* + * Free all modem control lines GPIOs + */ +void mctrl_gpio_free(struct mctrl_gpios *gpios); + +#endif