From patchwork Wed Aug 30 18:21:00 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: s.abhisit@gmail.com X-Patchwork-Id: 807847 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="FQlSMBU9"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3xjDN53lBfz9s7M for ; Thu, 31 Aug 2017 04:21:09 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752721AbdH3SVI (ORCPT ); Wed, 30 Aug 2017 14:21:08 -0400 Received: from mail-pg0-f67.google.com ([74.125.83.67]:35157 "EHLO mail-pg0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752719AbdH3SVH (ORCPT ); Wed, 30 Aug 2017 14:21:07 -0400 Received: by mail-pg0-f67.google.com with SMTP id r133so5617653pgr.2; Wed, 30 Aug 2017 11:21:07 -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; bh=HyTR5OVbOmMdH66rVaEr7qW5JJvq5gu2JkbmDVMNo3g=; b=FQlSMBU9Ujdj34U4OCQQPpdwDGiRcSraThnrfzbsaXuTzlS+3hIbp/xuxIaXl4ClOS +qC9LlfRzUoH+EC8K9bZTF16xw7g5NJHHHP5a7/WZ5EVjP1QHm65Gg2NkRkGryNs5Zem EK1bjI6OIxNtD3VJpSRxd9VzCqq4xkmVbiZRwnFzfNOSWJNcmdNrbY6WOtAX8ec5HK69 03ns3IrWC29o6M3wjJYr4QEgMHZaCcEcMOyRAfcu5CvEdWn8LtQvCq203J6TWX0kQQ5D MqNX97gtpyR/r0Ab6GFtictUDzKC+cz9uxcA/jKYkBDDy80c7INVJIJE2deV+fUO+HmK Dmog== 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; bh=HyTR5OVbOmMdH66rVaEr7qW5JJvq5gu2JkbmDVMNo3g=; b=SzW9MtZNT1v6Zq6DKQncEn3DZZ1vx+h33O8ILykhZSUtNmpaHVT2o1yPgqJaYa5iC1 beubt1Q7aLIDxx9cMBgewjiagvi3LsJ8lpwNdPzNHqKVLhsriea5dXV1ZNXgzVGfQu2Q xOh6w0JBxHMYOpqCsAG7TYfFaxwKbap2N2pgkwkxXpf1pWW7bXq8DwCzRGZLa7AhbpkC Xnq80cIecFI9KPPjWLr2q0UKRxHamv8flAZHZyNFqGVAWWMYmWHPxcSb2eFoQxKcEOlj r8AgoS9dNyce5fBPlzT/GZQ5hRsi0ARoChT69SHd1YGaKCJwbqa5IQEgXEuGNJBZE1tG /NGQ== X-Gm-Message-State: AHYfb5gx33kC3NFsCbyQ1+tttIpW8BODPi4nsrCYwhDW3z9sUOiQ9Zo7 NXBQo4RIihK+Bg== X-Received: by 10.98.248.2 with SMTP id d2mr2553674pfh.336.1504117266454; Wed, 30 Aug 2017 11:21:06 -0700 (PDT) Received: from localhost.localdomain ([2403:6200:8810:83fb::3]) by smtp.gmail.com with ESMTPSA id p71sm11708854pfl.56.2017.08.30.11.21.02 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Wed, 30 Aug 2017 11:21:05 -0700 (PDT) From: s.abhisit@gmail.com To: linus.walleij@linaro.org Cc: linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, pmeerw@pmeerw.net, Jonathan.Cameron@huawei.com, jacopo@jmondi.org, lars@metafoo.de, Abhisit Sangjan Subject: [PATCH 4/5] lmp92001: mfd: gpio: Add support LMP92001 Date: Thu, 31 Aug 2017 01:21:00 +0700 Message-Id: <20170830182100.9311-1-s.abhisit@gmail.com> X-Mailer: git-send-email 2.13.0 Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: Abhisit Sangjan TI LMP92001 Analog System Monitor and Controller 8-bit GPIOs. 12 DACs with 12-bit resolution. The GPIOs and DACs are shared port function with Cy function pin to take control the pin suddenly from external hardware. DAC's referance voltage selectable for Internal/External. 16 + 1 ADCs with 12-bit resolution. Built-in internal Temperature Sensor on channel 17. Window Comparator Function is supported on channel 1-3 and 9-11 for monitoring with interrupt signal (pending to implement for interrupt). ADC's referance voltage selectable for Internal/External. Signed-off-by: Abhisit Sangjan --- drivers/gpio/Kconfig | 7 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-lmp92001.c | 202 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 210 insertions(+) create mode 100644 drivers/gpio/gpio-lmp92001.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 461d6fc3688b..5962ea0d6745 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -948,6 +948,13 @@ config GPIO_KEMPLD This driver can also be built as a module. If so, the module will be called gpio-kempld. +config GPIO_LMP92001 + tristate "LMP92001 GPIOs" + depends on MFD_LMP92001 + help + Say yes here to access the GPIO signals of TI LMP92001 Analog System + Monitor and Controller. + config GPIO_LP3943 tristate "TI/National Semiconductor LP3943 GPIO expander" depends on MFD_LP3943 diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index a9fda6c55113..560d59c67758 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -62,6 +62,7 @@ obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o obj-$(CONFIG_GPIO_INTEL_MID) += gpio-intel-mid.o +obj-$(CONFIG_GPIO_LMP92001) += gpio-lmp92001.o obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o obj-$(CONFIG_GPIO_LPC18XX) += gpio-lpc18xx.o diff --git a/drivers/gpio/gpio-lmp92001.c b/drivers/gpio/gpio-lmp92001.c new file mode 100644 index 000000000000..4079e362e9b3 --- /dev/null +++ b/drivers/gpio/gpio-lmp92001.c @@ -0,0 +1,202 @@ +/* + * gpio-lmp92001.c - Support for TI LMP92001 GPIOs + * + * Copyright 2016-2017 Celestica Ltd. + * + * Author: Abhisit Sangjan + * + * Inspired by wm831x driver. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include + +#include + +struct lmp92001_gpio { + struct lmp92001 *lmp92001; + struct gpio_chip gpio_chip; +}; + +static int lmp92001_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +{ + struct lmp92001_gpio *lmp92001_gpio = gpiochip_get_data(chip); + struct lmp92001 *lmp92001 = lmp92001_gpio->lmp92001; + unsigned int val; + int ret; + + ret = regmap_read(lmp92001->regmap, LMP92001_CGPO, &val); + if (ret < 0) + return ret; + + return !!(val & BIT(offset)); +} + +static int lmp92001_gpio_direction_in(struct gpio_chip *chip, unsigned offset) +{ + struct lmp92001_gpio *lmp92001_gpio = gpiochip_get_data(chip); + struct lmp92001 *lmp92001 = lmp92001_gpio->lmp92001; + + return regmap_update_bits(lmp92001->regmap, LMP92001_CGPO, BIT(offset), + BIT(offset)); +} + +static int lmp92001_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct lmp92001_gpio *lmp92001_gpio = gpiochip_get_data(chip); + struct lmp92001 *lmp92001 = lmp92001_gpio->lmp92001; + unsigned int val, sgen; + + /* + * Does the GPIO input mode? + * Does the GPIO set? + * Reading indicated logic level. + * Clear indicated logic level. + */ + regmap_read(lmp92001->regmap, LMP92001_CGPO, &val); + if ((val >> offset) & BIT(0)) { + regmap_read(lmp92001->regmap, LMP92001_SGEN, &sgen); + if (sgen & SGEN_GPI) { + regmap_read(lmp92001->regmap, LMP92001_SGPI, &val); + regmap_update_bits(lmp92001->regmap, LMP92001_CGPO, + 0xFF, val); + } + } + + return !!(val & BIT(offset)); +} + +static int lmp92001_gpio_direction_out(struct gpio_chip *chip, unsigned offset, + int value) +{ + struct lmp92001_gpio *lmp92001_gpio = gpiochip_get_data(chip); + struct lmp92001 *lmp92001 = lmp92001_gpio->lmp92001; + + return regmap_update_bits(lmp92001->regmap, LMP92001_CGPO, BIT(offset), + 0 /* 0 << offset */); +} + +static void lmp92001_gpio_set(struct gpio_chip *chip, unsigned offset, + int value) +{ + struct lmp92001_gpio *lmp92001_gpio = gpiochip_get_data(chip); + struct lmp92001 *lmp92001 = lmp92001_gpio->lmp92001; + + regmap_update_bits(lmp92001->regmap, LMP92001_CGPO, BIT(offset), + value << offset); +} + +#ifdef CONFIG_DEBUG_FS +static void lmp92001_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) +{ + struct lmp92001_gpio *lmp92001_gpio = gpiochip_get_data(chip); + struct lmp92001 *lmp92001 = lmp92001_gpio->lmp92001; + int i, gpio; + unsigned int cgpo; + const char *label, *dir, *logic; + + for (i = 0; i < chip->ngpio; i++) { + gpio = i + chip->base; + + label = gpiochip_is_requested(chip, i); + if (!label) + continue; + + regmap_read(lmp92001->regmap, LMP92001_CGPO, &cgpo); + if ((cgpo >> i) & BIT(0)) + dir = "in"; + else + dir = "out"; + + if (lmp92001_gpio_get(chip, i)) + logic = "hi"; + else + logic = "lo"; + + seq_printf(s, " gpio-%-3d (%-20.20s) %-3.3s %-2.2s\n", + gpio, label, dir, logic); + } +} +#else +#define lmp92001_gpio_dbg_show NULL +#endif + +static struct gpio_chip lmp92001_gpio_chip = { + .label = "lmp92001", + .owner = THIS_MODULE, + .get_direction = lmp92001_gpio_get_direction, + .direction_input = lmp92001_gpio_direction_in, + .get = lmp92001_gpio_get, + .direction_output = lmp92001_gpio_direction_out, + .set = lmp92001_gpio_set, + .dbg_show = lmp92001_gpio_dbg_show, +}; + +static int lmp92001_gpio_probe(struct platform_device *pdev) +{ + struct lmp92001 *lmp92001 = dev_get_drvdata(pdev->dev.parent); + struct lmp92001_gpio *lmp92001_gpio; + int ret; + + lmp92001_gpio = devm_kzalloc(&pdev->dev, sizeof(*lmp92001_gpio), + GFP_KERNEL); + if (!lmp92001_gpio) + return -ENOMEM; + + lmp92001_gpio->lmp92001 = lmp92001; + lmp92001_gpio->gpio_chip = lmp92001_gpio_chip; + lmp92001_gpio->gpio_chip.ngpio = 8; + lmp92001_gpio->gpio_chip.parent = &pdev->dev; + lmp92001_gpio->gpio_chip.base = -1; + + ret = devm_gpiochip_add_data(&pdev->dev, &lmp92001_gpio->gpio_chip, + lmp92001_gpio); + if (ret < 0) { + dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, lmp92001_gpio); + + return ret; +} + +static int lmp92001_gpio_remove(struct platform_device *pdev) +{ + return 0; +} + +static struct platform_driver lmp92001_gpio_driver = { + .driver.name = "lmp92001-gpio", + .probe = lmp92001_gpio_probe, + .remove = lmp92001_gpio_remove, +}; + +static int __init lmp92001_gpio_init(void) +{ + return platform_driver_register(&lmp92001_gpio_driver); +} +subsys_initcall(lmp92001_gpio_init); + +static void __exit lmp92001_gpio_exit(void) +{ + platform_driver_unregister(&lmp92001_gpio_driver); +} +module_exit(lmp92001_gpio_exit); + +MODULE_AUTHOR("Abhisit Sangjan "); +MODULE_DESCRIPTION("GPIO interface for TI LMP92001"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:lmp92001-gpio");