linux/drivers/gpio/gpio-bd71828.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2// Copyright (C) 2018 ROHM Semiconductors
   3
   4#include <linux/gpio/driver.h>
   5#include <linux/mfd/rohm-bd71828.h>
   6#include <linux/module.h>
   7#include <linux/platform_device.h>
   8#include <linux/regmap.h>
   9
  10#define GPIO_OUT_REG(off) (BD71828_REG_GPIO_CTRL1 + (off))
  11#define HALL_GPIO_OFFSET 3
  12
  13struct bd71828_gpio {
  14        struct regmap *regmap;
  15        struct device *dev;
  16        struct gpio_chip gpio;
  17};
  18
  19static void bd71828_gpio_set(struct gpio_chip *chip, unsigned int offset,
  20                             int value)
  21{
  22        int ret;
  23        struct bd71828_gpio *bdgpio = gpiochip_get_data(chip);
  24        u8 val = (value) ? BD71828_GPIO_OUT_HI : BD71828_GPIO_OUT_LO;
  25
  26        /*
  27         * The HALL input pin can only be used as input. If this is the pin
  28         * we are dealing with - then we are done
  29         */
  30        if (offset == HALL_GPIO_OFFSET)
  31                return;
  32
  33        ret = regmap_update_bits(bdgpio->regmap, GPIO_OUT_REG(offset),
  34                                 BD71828_GPIO_OUT_MASK, val);
  35        if (ret)
  36                dev_err(bdgpio->dev, "Could not set gpio to %d\n", value);
  37}
  38
  39static int bd71828_gpio_get(struct gpio_chip *chip, unsigned int offset)
  40{
  41        int ret;
  42        unsigned int val;
  43        struct bd71828_gpio *bdgpio = gpiochip_get_data(chip);
  44
  45        if (offset == HALL_GPIO_OFFSET)
  46                ret = regmap_read(bdgpio->regmap, BD71828_REG_IO_STAT,
  47                                  &val);
  48        else
  49                ret = regmap_read(bdgpio->regmap, GPIO_OUT_REG(offset),
  50                                  &val);
  51        if (!ret)
  52                ret = (val & BD71828_GPIO_OUT_MASK);
  53
  54        return ret;
  55}
  56
  57static int bd71828_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
  58                                   unsigned long config)
  59{
  60        struct bd71828_gpio *bdgpio = gpiochip_get_data(chip);
  61
  62        if (offset == HALL_GPIO_OFFSET)
  63                return -ENOTSUPP;
  64
  65        switch (pinconf_to_config_param(config)) {
  66        case PIN_CONFIG_DRIVE_OPEN_DRAIN:
  67                return regmap_update_bits(bdgpio->regmap,
  68                                          GPIO_OUT_REG(offset),
  69                                          BD71828_GPIO_DRIVE_MASK,
  70                                          BD71828_GPIO_OPEN_DRAIN);
  71        case PIN_CONFIG_DRIVE_PUSH_PULL:
  72                return regmap_update_bits(bdgpio->regmap,
  73                                          GPIO_OUT_REG(offset),
  74                                          BD71828_GPIO_DRIVE_MASK,
  75                                          BD71828_GPIO_PUSH_PULL);
  76        default:
  77                break;
  78        }
  79        return -ENOTSUPP;
  80}
  81
  82static int bd71828_get_direction(struct gpio_chip *chip, unsigned int offset)
  83{
  84        /*
  85         * Pin usage is selected by OTP data. We can't read it runtime. Hence
  86         * we trust that if the pin is not excluded by "gpio-reserved-ranges"
  87         * the OTP configuration is set to OUT. (Other pins but HALL input pin
  88         * on BD71828 can't really be used for general purpose input - input
  89         * states are used for specific cases like regulator control or
  90         * PMIC_ON_REQ.
  91         */
  92        if (offset == HALL_GPIO_OFFSET)
  93                return GPIO_LINE_DIRECTION_IN;
  94
  95        return GPIO_LINE_DIRECTION_OUT;
  96}
  97
  98static int bd71828_probe(struct platform_device *pdev)
  99{
 100        struct device *dev = &pdev->dev;
 101        struct bd71828_gpio *bdgpio;
 102
 103        bdgpio = devm_kzalloc(dev, sizeof(*bdgpio), GFP_KERNEL);
 104        if (!bdgpio)
 105                return -ENOMEM;
 106
 107        bdgpio->dev = dev;
 108        bdgpio->gpio.parent = dev->parent;
 109        bdgpio->gpio.label = "bd71828-gpio";
 110        bdgpio->gpio.owner = THIS_MODULE;
 111        bdgpio->gpio.get_direction = bd71828_get_direction;
 112        bdgpio->gpio.set_config = bd71828_gpio_set_config;
 113        bdgpio->gpio.can_sleep = true;
 114        bdgpio->gpio.get = bd71828_gpio_get;
 115        bdgpio->gpio.set = bd71828_gpio_set;
 116        bdgpio->gpio.base = -1;
 117
 118        /*
 119         * See if we need some implementation to mark some PINs as
 120         * not controllable based on DT info or if core can handle
 121         * "gpio-reserved-ranges" and exclude them from control
 122         */
 123        bdgpio->gpio.ngpio = 4;
 124        bdgpio->gpio.of_node = dev->parent->of_node;
 125        bdgpio->regmap = dev_get_regmap(dev->parent, NULL);
 126        if (!bdgpio->regmap)
 127                return -ENODEV;
 128
 129        return devm_gpiochip_add_data(dev, &bdgpio->gpio, bdgpio);
 130}
 131
 132static struct platform_driver bd71828_gpio = {
 133        .driver = {
 134                .name = "bd71828-gpio"
 135        },
 136        .probe = bd71828_probe,
 137};
 138
 139module_platform_driver(bd71828_gpio);
 140
 141MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
 142MODULE_DESCRIPTION("BD71828 voltage regulator driver");
 143MODULE_LICENSE("GPL");
 144MODULE_ALIAS("platform:bd71828-gpio");
 145