From patchwork Tue Jan 29 13:35:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Golaszewski X-Patchwork-Id: 10786279 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 19925139A for ; Tue, 29 Jan 2019 13:36:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 061CF29C88 for ; Tue, 29 Jan 2019 13:36:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EE1112AB2D; Tue, 29 Jan 2019 13:36:53 +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 3BD6929C88 for ; Tue, 29 Jan 2019 13:36:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728363AbfA2Ngr (ORCPT ); Tue, 29 Jan 2019 08:36:47 -0500 Received: from mail-wm1-f65.google.com ([209.85.128.65]:54742 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726270AbfA2NgJ (ORCPT ); Tue, 29 Jan 2019 08:36:09 -0500 Received: by mail-wm1-f65.google.com with SMTP id a62so17881073wmh.4 for ; Tue, 29 Jan 2019 05:36:07 -0800 (PST) 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=/NtEr31RJV4ToQ2tRfAYSzVrKcKJn/WGW2NzkW9zf+0=; b=ThmpKxynX/gbLWxgqw4+QSanF/mqkwu3SZbxhHlHTuRIaBw5C6Mq1EvzkvaEFlwacb tRpku6cv5M5zEf6bNlOfBOVpZatZWw5bSxWxzcLvjZjg2sBxsVw6ByLSSCeQ+tSpptBF VdhU76BfVtKzU1PXZtQQHGFgh35Hbbow/wsNe6kCmeEACOeXK42Swm+bg5h5rvnghdDn fxFAUQLKinn9Z617TUqAiixVqaWxWdKS21DWBKW0kVs9Wxgi6foUIEKGNcTZ3eREbMib RGf3xbFBaiSfSNxcjRd10E00vvs4gYvhXUmLSFE2hMCLeqpHRWeWV4AyrSzbFRsoXfyb LQuw== 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=/NtEr31RJV4ToQ2tRfAYSzVrKcKJn/WGW2NzkW9zf+0=; b=VoEasKSJfC8v+xAL5d3CuCgI4X9I7oGAJAvKnqaBj3zBFqZfKz5/Nx0cApM3s5EpID QDJ1Pf2BNuhAcEi75B9RfN+q2wJBTuppVqpV7ZrfsN2m4t8FLTE4HKfuZp8JzqLEjGmY jvHMVjfuoesNQ+f5APlmj+CUEtXhz7UAUHJuE04xo7xR8TL5Dnoy9r+I0sgBUtM2l0dC cQ8ZOOZ6OEPjtZ7N1pFpJBOdAEK9AusQ+n+t7o0VYfYRC3NkKeNL2ZTAXhJcMaE5L4jW ZCyMvwtCJlMbt/bgA7AAEwSwLu0Ew+0xzCk2ObuTQtUQmCm5//wjqMD3vQexfr7wOQ4I mk7A== X-Gm-Message-State: AJcUukcAHfxIVsbocYok5YjLyt4t8Emg1F+YgA2eOsQnzl1MkPMDnOe8 c0ByWTlaB9QzGBZmtitIOKoumQ== X-Google-Smtp-Source: ALg8bN7gKUNXfsgQEMbSW6az92dZfKQzq4kpS4FMGQSe05DTUivQqGk2jyM3Bw9ZKXW1nacM0B4BUg== X-Received: by 2002:a1c:b189:: with SMTP id a131mr22097217wmf.38.1548768966565; Tue, 29 Jan 2019 05:36:06 -0800 (PST) Received: from debian-brgl.home ([2a01:cb1d:af:5b00:6d6c:8493:1ab5:dad7]) by smtp.gmail.com with ESMTPSA id k128sm4367891wmd.37.2019.01.29.05.36.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 29 Jan 2019 05:36:05 -0800 (PST) From: Bartosz Golaszewski To: Rob Herring , Mark Rutland , Linus Walleij , Dmitry Torokhov , Jacek Anaszewski , Pavel Machek , Lee Jones , Sebastian Reichel , Liam Girdwood , Mark Brown , 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 v2 10/13] gpio: max77650: add GPIO support Date: Tue, 29 Jan 2019 14:35:42 +0100 Message-Id: <20190129133545.1931-12-brgl@bgdev.pl> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190129133545.1931-1-brgl@bgdev.pl> References: <20190129133545.1931-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 | 189 +++++++++++++++++++++++++++++++++++ 3 files changed, 197 insertions(+) create mode 100644 drivers/gpio/gpio-max77650.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b5a2845347ec..fb297fe5bfec 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1095,6 +1095,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 37628f8dbf70..8bdad50db822 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -78,6 +78,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..8382dd85c548 --- /dev/null +++ b/drivers/gpio/gpio-max77650.c @@ -0,0 +1,189 @@ +// 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; +}; + +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) +{ + /* + * TODO Add interrupt support. + * + * We first need to properly support hierarchical irqs in gpiolib + * and regmap irq_chip. + */ + return -EOPNOTSUPP; +} + +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->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");