Re: [PATCH v3 08/11] gpio: max77650: add GPIO support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



pt., 1 lut 2019 o 10:48 Bartosz Golaszewski <brgl@xxxxxxxx> napisał(a):
>
> From: Bartosz Golaszewski <bgolaszewski@xxxxxxxxxxxx>
>
> Add GPIO support for max77650 mfd device. This PMIC exposes a single
> GPIO line.
>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@xxxxxxxxxxxx>
> ---
>  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 <bgolaszewski@xxxxxxxxxxxx>
> +//
> +// GPIO driver for MAXIM 77650/77651 charger/power-supply.
> +
> +#include <linux/gpio/driver.h>
> +#include <linux/i2c.h>
> +#include <linux/mfd/max77650.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +#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 <bgolaszewski@xxxxxxxxxxxx>");
> +MODULE_LICENSE("GPL v2");
> --
> 2.20.1
>

I forgot to collect the tag, but Linus left his Reviewed-by:.

Bart




[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux