From patchwork Tue Apr 23 09:04:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Golaszewski X-Patchwork-Id: 10912395 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 793961515 for ; Tue, 23 Apr 2019 09:05:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 687142873C for ; Tue, 23 Apr 2019 09:05:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 646E9200E5; Tue, 23 Apr 2019 09:05:15 +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=-7.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,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 895CE200E5 for ; Tue, 23 Apr 2019 09:05:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727302AbfDWJFN (ORCPT ); Tue, 23 Apr 2019 05:05:13 -0400 Received: from mail-wr1-f67.google.com ([209.85.221.67]:44504 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727283AbfDWJFM (ORCPT ); Tue, 23 Apr 2019 05:05:12 -0400 Received: by mail-wr1-f67.google.com with SMTP id c5so10299870wrs.11 for ; Tue, 23 Apr 2019 02:05:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bgdev-pl.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=yGw5YilbSP88yNY2O1thS+S3CD6jvEmYujvzOlhreok=; b=kqIrh3QkBua6pzb8F8WD7kn10cfCJFB92vaTwd5TblOE/U+V+TNR1Yy0J7/cYyKzZX 3Lqd13CiT8QOXRYDzaSDJJJId5KteEv7t/uu+L365LHq437lIHAoKj3nBWzNTfrJ6os1 j7GKfDbijFMuQxfCHQ9CnoZnp6Mz4hXWz8Ktq0V5YtTxmbZs9AsihrZC4GRQMeB9RE47 ipJ6/gZctnvqm9bPz3bjGl0qkLoaoKm1PNIbVuBaFkA1BHfuu8baV2k01OnTGzzQypZm Kh3dSBwDmW0gYVYK87BJYbuC/BZpe7vibdxuQduHA44uO/+kZY0THjNwsROe1b6zh2el 999w== 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:mime-version:content-transfer-encoding; bh=yGw5YilbSP88yNY2O1thS+S3CD6jvEmYujvzOlhreok=; b=oU4lyEqgYp1x060Af7eyDRl7ky92uahoVEtmAOaV6kGfNBOsuDp+wImJ2rUh90bc6m eciTwWFNZFOAPedB0ttEYRWgWuXxXLA+wWowCScvZfPlEHu2Zm+bslShcGy0L6IcOQ/1 oTWvhhnhFNUhOeCX6ogXVEA+lulCJ4351k4r0xJjQ6pBxkkOGkwywa3rhGd9+KJWy1HH ORQYIYCf/u7G0QA9N2QdPP4mzG9tJGA3P//xhWjYMlFV9iCa7zFZdBhGzGFpDSIJzpwx CBWWrKKh/y0WjHBCX7iNr3YA8KRytBWgpIt1Ned3Zqsi8CSb9q0hDkMqJFrmHiApSZce URTw== X-Gm-Message-State: APjAAAU00hp0xEE8BQqqFSdX5OxcfD89TcHNbfimuPvLnWu+5xnMJsY3 MhgRYhCnP8M9FfjQu8aYyfCECw== X-Google-Smtp-Source: APXvYqxFp9Brdjt1h08wBVcHu7pq6ZDmhXua1hUXCTBNEUN5lmj2jQEQtHu4tAsKw1yJBSZoNHajcw== X-Received: by 2002:a05:6000:2:: with SMTP id h2mr17324605wrx.76.1556010310550; Tue, 23 Apr 2019 02:05:10 -0700 (PDT) Received: from localhost.localdomain (aputeaux-684-1-25-101.w90-86.abo.wanadoo.fr. [90.86.250.101]) by smtp.gmail.com with ESMTPSA id v190sm15360434wme.18.2019.04.23.02.05.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 23 Apr 2019 02:05:09 -0700 (PDT) From: Bartosz Golaszewski To: Rob Herring , Mark Rutland , Linus Walleij , Dmitry Torokhov , Jacek Anaszewski , Pavel Machek , Lee Jones , Sebastian Reichel , Liam Girdwood , Greg Kroah-Hartman Cc: linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, linux-input@vger.kernel.org, linux-leds@vger.kernel.org, linux-pm@vger.kernel.org, Bartosz Golaszewski Subject: [PATCH v10 08/11] gpio: max77650: add GPIO support Date: Tue, 23 Apr 2019 11:04:48 +0200 Message-Id: <20190423090451.23711-9-brgl@bgdev.pl> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190423090451.23711-1-brgl@bgdev.pl> References: <20190423090451.23711-1-brgl@bgdev.pl> MIME-Version: 1.0 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Bartosz Golaszewski Add GPIO support for max77650 mfd device. This PMIC exposes a single GPIO line. Signed-off-by: Bartosz Golaszewski Reviewed-by: Linus Walleij --- drivers/gpio/Kconfig | 7 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-max77650.c | 190 +++++++++++++++++++++++++++++++++++ 3 files changed, 198 insertions(+) create mode 100644 drivers/gpio/gpio-max77650.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 3f50526a771f..c4f912104440 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1112,6 +1112,13 @@ config GPIO_MAX77620 driver also provides interrupt support for each of the gpios. Say yes here to enable the max77620 to be used as gpio controller. +config GPIO_MAX77650 + tristate "Maxim MAX77650/77651 GPIO support" + depends on MFD_MAX77650 + help + GPIO driver for MAX77650/77651 PMIC from Maxim Semiconductor. + These chips have a single pin that can be configured as GPIO. + config GPIO_MSIC bool "Intel MSIC mixed signal gpio support" depends on (X86 || COMPILE_TEST) && MFD_INTEL_MSIC diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 54d55274b93a..075722d8317d 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -80,6 +80,7 @@ obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o obj-$(CONFIG_GPIO_MAX77620) += gpio-max77620.o +obj-$(CONFIG_GPIO_MAX77650) += gpio-max77650.o obj-$(CONFIG_GPIO_MB86S7X) += gpio-mb86s7x.o obj-$(CONFIG_GPIO_MENZ127) += gpio-menz127.o obj-$(CONFIG_GPIO_MERRIFIELD) += gpio-merrifield.o diff --git a/drivers/gpio/gpio-max77650.c b/drivers/gpio/gpio-max77650.c new file mode 100644 index 000000000000..3f03f4e8956c --- /dev/null +++ b/drivers/gpio/gpio-max77650.c @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2018 BayLibre SAS +// Author: Bartosz Golaszewski +// +// GPIO driver for MAXIM 77650/77651 charger/power-supply. + +#include +#include +#include +#include +#include +#include + +#define MAX77650_GPIO_DIR_MASK BIT(0) +#define MAX77650_GPIO_INVAL_MASK BIT(1) +#define MAX77650_GPIO_DRV_MASK BIT(2) +#define MAX77650_GPIO_OUTVAL_MASK BIT(3) +#define MAX77650_GPIO_DEBOUNCE_MASK BIT(4) + +#define MAX77650_GPIO_DIR_OUT 0x00 +#define MAX77650_GPIO_DIR_IN BIT(0) +#define MAX77650_GPIO_OUT_LOW 0x00 +#define MAX77650_GPIO_OUT_HIGH BIT(3) +#define MAX77650_GPIO_DRV_OPEN_DRAIN 0x00 +#define MAX77650_GPIO_DRV_PUSH_PULL BIT(2) +#define MAX77650_GPIO_DEBOUNCE BIT(4) + +#define MAX77650_GPIO_DIR_BITS(_reg) \ + ((_reg) & MAX77650_GPIO_DIR_MASK) +#define MAX77650_GPIO_INVAL_BITS(_reg) \ + (((_reg) & MAX77650_GPIO_INVAL_MASK) >> 1) + +struct max77650_gpio_chip { + struct regmap *map; + struct gpio_chip gc; + int irq; +}; + +static int max77650_gpio_direction_input(struct gpio_chip *gc, + unsigned int offset) +{ + struct max77650_gpio_chip *chip = gpiochip_get_data(gc); + + return regmap_update_bits(chip->map, + MAX77650_REG_CNFG_GPIO, + MAX77650_GPIO_DIR_MASK, + MAX77650_GPIO_DIR_IN); +} + +static int max77650_gpio_direction_output(struct gpio_chip *gc, + unsigned int offset, int value) +{ + struct max77650_gpio_chip *chip = gpiochip_get_data(gc); + int mask, regval; + + mask = MAX77650_GPIO_DIR_MASK | MAX77650_GPIO_OUTVAL_MASK; + regval = value ? MAX77650_GPIO_OUT_HIGH : MAX77650_GPIO_OUT_LOW; + regval |= MAX77650_GPIO_DIR_OUT; + + return regmap_update_bits(chip->map, + MAX77650_REG_CNFG_GPIO, mask, regval); +} + +static void max77650_gpio_set_value(struct gpio_chip *gc, + unsigned int offset, int value) +{ + struct max77650_gpio_chip *chip = gpiochip_get_data(gc); + int rv, regval; + + regval = value ? MAX77650_GPIO_OUT_HIGH : MAX77650_GPIO_OUT_LOW; + + rv = regmap_update_bits(chip->map, MAX77650_REG_CNFG_GPIO, + MAX77650_GPIO_OUTVAL_MASK, regval); + if (rv) + dev_err(gc->parent, "cannot set GPIO value: %d\n", rv); +} + +static int max77650_gpio_get_value(struct gpio_chip *gc, + unsigned int offset) +{ + struct max77650_gpio_chip *chip = gpiochip_get_data(gc); + unsigned int val; + int rv; + + rv = regmap_read(chip->map, MAX77650_REG_CNFG_GPIO, &val); + if (rv) + return rv; + + return MAX77650_GPIO_INVAL_BITS(val); +} + +static int max77650_gpio_get_direction(struct gpio_chip *gc, + unsigned int offset) +{ + struct max77650_gpio_chip *chip = gpiochip_get_data(gc); + unsigned int val; + int rv; + + rv = regmap_read(chip->map, MAX77650_REG_CNFG_GPIO, &val); + if (rv) + return rv; + + return MAX77650_GPIO_DIR_BITS(val); +} + +static int max77650_gpio_set_config(struct gpio_chip *gc, + unsigned int offset, unsigned long cfg) +{ + struct max77650_gpio_chip *chip = gpiochip_get_data(gc); + + switch (pinconf_to_config_param(cfg)) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + return regmap_update_bits(chip->map, + MAX77650_REG_CNFG_GPIO, + MAX77650_GPIO_DRV_MASK, + MAX77650_GPIO_DRV_OPEN_DRAIN); + case PIN_CONFIG_DRIVE_PUSH_PULL: + return regmap_update_bits(chip->map, + MAX77650_REG_CNFG_GPIO, + MAX77650_GPIO_DRV_MASK, + MAX77650_GPIO_DRV_PUSH_PULL); + case PIN_CONFIG_INPUT_DEBOUNCE: + return regmap_update_bits(chip->map, + MAX77650_REG_CNFG_GPIO, + MAX77650_GPIO_DEBOUNCE_MASK, + MAX77650_GPIO_DEBOUNCE); + default: + return -ENOTSUPP; + } +} + +static int max77650_gpio_to_irq(struct gpio_chip *gc, unsigned int offset) +{ + struct max77650_gpio_chip *chip = gpiochip_get_data(gc); + + return chip->irq; +} + +static int max77650_gpio_probe(struct platform_device *pdev) +{ + struct max77650_gpio_chip *chip; + struct device *dev, *parent; + struct i2c_client *i2c; + + dev = &pdev->dev; + parent = dev->parent; + i2c = to_i2c_client(parent); + + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->map = dev_get_regmap(parent, NULL); + if (!chip->map) + return -ENODEV; + + chip->irq = platform_get_irq_byname(pdev, "GPI"); + if (chip->irq < 0) + return chip->irq; + + chip->gc.base = -1; + chip->gc.ngpio = 1; + chip->gc.label = i2c->name; + chip->gc.parent = dev; + chip->gc.owner = THIS_MODULE; + chip->gc.can_sleep = true; + + chip->gc.direction_input = max77650_gpio_direction_input; + chip->gc.direction_output = max77650_gpio_direction_output; + chip->gc.set = max77650_gpio_set_value; + chip->gc.get = max77650_gpio_get_value; + chip->gc.get_direction = max77650_gpio_get_direction; + chip->gc.set_config = max77650_gpio_set_config; + chip->gc.to_irq = max77650_gpio_to_irq; + + return devm_gpiochip_add_data(dev, &chip->gc, chip); +} + +static struct platform_driver max77650_gpio_driver = { + .driver = { + .name = "max77650-gpio", + }, + .probe = max77650_gpio_probe, +}; +module_platform_driver(max77650_gpio_driver); + +MODULE_DESCRIPTION("MAXIM 77650/77651 GPIO driver"); +MODULE_AUTHOR("Bartosz Golaszewski "); +MODULE_LICENSE("GPL v2");