From patchwork Sun May 14 19:51:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Rosin X-Patchwork-Id: 762161 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3wQvRL1TLzz9sCX for ; Mon, 15 May 2017 05:49:02 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1759600AbdENTtB (ORCPT ); Sun, 14 May 2017 15:49:01 -0400 Received: from mail.lysator.liu.se ([130.236.254.3]:33926 "EHLO mail.lysator.liu.se" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1759594AbdENTtA (ORCPT ); Sun, 14 May 2017 15:49:00 -0400 Received: from mail.lysator.liu.se (localhost [127.0.0.1]) by mail.lysator.liu.se (Postfix) with ESMTP id AC8CC4004E; Sun, 14 May 2017 21:48:57 +0200 (CEST) Received: from orc.lan (81-224-171-159-no95.tbcn.telia.com [81.224.171.159]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.lysator.liu.se (Postfix) with ESMTPSA id 7B75B4001B; Sun, 14 May 2017 21:48:56 +0200 (CEST) From: Peter Rosin To: linux-kernel@vger.kernel.org, Greg Kroah-Hartman Cc: Peter Rosin , Wolfram Sang , Rob Herring , Mark Rutland , Jonathan Cameron , Hartmut Knaack , Lars-Peter Clausen , Peter Meerwald-Stadler , Jonathan Corbet , linux-i2c@vger.kernel.org, devicetree@vger.kernel.org, linux-iio@vger.kernel.org, linux-doc@vger.kernel.org, Andrew Morton , Colin Ian King , Paul Gortmaker , Philipp Zabel , kernel@pengutronix.de Subject: [PATCH v15 04/13] mux: gpio: add mux controller driver for gpio based multiplexers Date: Sun, 14 May 2017 21:51:07 +0200 Message-Id: <1494791476-14599-5-git-send-email-peda@lysator.liu.se> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1494791476-14599-1-git-send-email-peda@lysator.liu.se> References: <1494791476-14599-1-git-send-email-peda@lysator.liu.se> X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org From: Peter Rosin The driver builds a single multiplexer controller using a number of gpio pins. For N pins, there will be 2^N possible multiplexer states. The GPIO pins can be connected (by the hardware) to several multiplexers, which in that case will be operated in parallel. Reviewed-by: Jonathan Cameron Signed-off-by: Peter Rosin Reviewed-by: Philipp Zabel --- drivers/mux/Kconfig | 18 ++++++++ drivers/mux/Makefile | 1 + drivers/mux/mux-gpio.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 drivers/mux/mux-gpio.c diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig index 23ab2cde83b1..738670aaecb7 100644 --- a/drivers/mux/Kconfig +++ b/drivers/mux/Kconfig @@ -14,3 +14,21 @@ menuconfig MULTIPLEXER To compile the subsystem as a module, choose M here: the module will be called mux-core. + +if MULTIPLEXER + +config MUX_GPIO + tristate "GPIO-controlled Multiplexer" + depends on GPIOLIB || COMPILE_TEST + help + GPIO-controlled Multiplexer controller. + + The driver builds a single multiplexer controller using a number + of gpio pins. For N pins, there will be 2^N possible multiplexer + states. The GPIO pins can be connected (by the hardware) to several + multiplexers, which in that case will be operated in parallel. + + To compile the driver as a module, choose M here: the module will + be called mux-gpio. + +endif diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile index 09f0299e109d..bb16953f6290 100644 --- a/drivers/mux/Makefile +++ b/drivers/mux/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_MULTIPLEXER) += mux-core.o +obj-$(CONFIG_MUX_GPIO) += mux-gpio.o diff --git a/drivers/mux/mux-gpio.c b/drivers/mux/mux-gpio.c new file mode 100644 index 000000000000..468bf1709606 --- /dev/null +++ b/drivers/mux/mux-gpio.c @@ -0,0 +1,114 @@ +/* + * GPIO-controlled multiplexer driver + * + * Copyright (C) 2017 Axentia Technologies AB + * + * Author: Peter Rosin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +struct mux_gpio { + struct gpio_descs *gpios; + int *val; +}; + +static int mux_gpio_set(struct mux_control *mux, int state) +{ + struct mux_gpio *mux_gpio = mux_chip_priv(mux->chip); + int i; + + for (i = 0; i < mux_gpio->gpios->ndescs; i++) + mux_gpio->val[i] = (state >> i) & 1; + + gpiod_set_array_value_cansleep(mux_gpio->gpios->ndescs, + mux_gpio->gpios->desc, + mux_gpio->val); + + return 0; +} + +static const struct mux_control_ops mux_gpio_ops = { + .set = mux_gpio_set, +}; + +static const struct of_device_id mux_gpio_dt_ids[] = { + { .compatible = "gpio-mux", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mux_gpio_dt_ids); + +static int mux_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mux_chip *mux_chip; + struct mux_gpio *mux_gpio; + int pins; + s32 idle_state; + int ret; + + pins = gpiod_count(dev, "mux"); + if (pins < 0) + return pins; + + mux_chip = devm_mux_chip_alloc(dev, 1, sizeof(*mux_gpio) + + pins * sizeof(*mux_gpio->val)); + if (IS_ERR(mux_chip)) + return PTR_ERR(mux_chip); + + mux_gpio = mux_chip_priv(mux_chip); + mux_gpio->val = (int *)(mux_gpio + 1); + mux_chip->ops = &mux_gpio_ops; + + mux_gpio->gpios = devm_gpiod_get_array(dev, "mux", GPIOD_OUT_LOW); + if (IS_ERR(mux_gpio->gpios)) { + ret = PTR_ERR(mux_gpio->gpios); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get gpios\n"); + return ret; + } + WARN_ON(pins != mux_gpio->gpios->ndescs); + mux_chip->mux->states = 1 << pins; + + ret = device_property_read_u32(dev, "idle-state", (u32 *)&idle_state); + if (ret >= 0 && idle_state != MUX_IDLE_AS_IS) { + if (idle_state < 0 || idle_state >= mux_chip->mux->states) { + dev_err(dev, "invalid idle-state %u\n", idle_state); + return -EINVAL; + } + + mux_chip->mux->idle_state = idle_state; + } + + ret = devm_mux_chip_register(dev, mux_chip); + if (ret < 0) + return ret; + + dev_info(dev, "%u-way mux-controller registered\n", + mux_chip->mux->states); + + return 0; +} + +static struct platform_driver mux_gpio_driver = { + .driver = { + .name = "gpio-mux", + .of_match_table = of_match_ptr(mux_gpio_dt_ids), + }, + .probe = mux_gpio_probe, +}; +module_platform_driver(mux_gpio_driver); + +MODULE_DESCRIPTION("GPIO-controlled multiplexer driver"); +MODULE_AUTHOR("Peter Rosin "); +MODULE_LICENSE("GPL v2");