linux/drivers/gpio/gpio-bd70528.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2// Copyright (C) 2018 ROHM Semiconductors
   3// gpio-bd70528.c ROHM BD70528MWV gpio driver
   4
   5#include <linux/gpio/driver.h>
   6#include <linux/mfd/rohm-bd70528.h>
   7#include <linux/module.h>
   8#include <linux/platform_device.h>
   9#include <linux/regmap.h>
  10
  11#define GPIO_IN_REG(offset) (BD70528_REG_GPIO1_IN + (offset) * 2)
  12#define GPIO_OUT_REG(offset) (BD70528_REG_GPIO1_OUT + (offset) * 2)
  13
  14struct bd70528_gpio {
  15        struct rohm_regmap_dev chip;
  16        struct gpio_chip gpio;
  17};
  18
  19static int bd70528_set_debounce(struct bd70528_gpio *bdgpio,
  20                                unsigned int offset, unsigned int debounce)
  21{
  22        u8 val;
  23
  24        switch (debounce) {
  25        case 0:
  26                val = BD70528_DEBOUNCE_DISABLE;
  27                break;
  28        case 1 ... 15000:
  29                val = BD70528_DEBOUNCE_15MS;
  30                break;
  31        case 15001 ... 30000:
  32                val = BD70528_DEBOUNCE_30MS;
  33                break;
  34        case 30001 ... 50000:
  35                val = BD70528_DEBOUNCE_50MS;
  36                break;
  37        default:
  38                dev_err(bdgpio->chip.dev,
  39                        "Invalid debounce value %u\n", debounce);
  40                return -EINVAL;
  41        }
  42        return regmap_update_bits(bdgpio->chip.regmap, GPIO_IN_REG(offset),
  43                                 BD70528_DEBOUNCE_MASK, val);
  44}
  45
  46static int bd70528_get_direction(struct gpio_chip *chip, unsigned int offset)
  47{
  48        struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
  49        int val, ret;
  50
  51        /* Do we need to do something to IRQs here? */
  52        ret = regmap_read(bdgpio->chip.regmap, GPIO_OUT_REG(offset), &val);
  53        if (ret) {
  54                dev_err(bdgpio->chip.dev, "Could not read gpio direction\n");
  55                return ret;
  56        }
  57        if (val & BD70528_GPIO_OUT_EN_MASK)
  58                return GPIO_LINE_DIRECTION_OUT;
  59
  60        return GPIO_LINE_DIRECTION_IN;
  61}
  62
  63static int bd70528_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
  64                                   unsigned long config)
  65{
  66        struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
  67
  68        switch (pinconf_to_config_param(config)) {
  69        case PIN_CONFIG_DRIVE_OPEN_DRAIN:
  70                return regmap_update_bits(bdgpio->chip.regmap,
  71                                          GPIO_OUT_REG(offset),
  72                                          BD70528_GPIO_DRIVE_MASK,
  73                                          BD70528_GPIO_OPEN_DRAIN);
  74                break;
  75        case PIN_CONFIG_DRIVE_PUSH_PULL:
  76                return regmap_update_bits(bdgpio->chip.regmap,
  77                                          GPIO_OUT_REG(offset),
  78                                          BD70528_GPIO_DRIVE_MASK,
  79                                          BD70528_GPIO_PUSH_PULL);
  80                break;
  81        case PIN_CONFIG_INPUT_DEBOUNCE:
  82                return bd70528_set_debounce(bdgpio, offset,
  83                                            pinconf_to_config_argument(config));
  84                break;
  85        default:
  86                break;
  87        }
  88        return -ENOTSUPP;
  89}
  90
  91static int bd70528_direction_input(struct gpio_chip *chip, unsigned int offset)
  92{
  93        struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
  94
  95        /* Do we need to do something to IRQs here? */
  96        return regmap_update_bits(bdgpio->chip.regmap, GPIO_OUT_REG(offset),
  97                                 BD70528_GPIO_OUT_EN_MASK,
  98                                 BD70528_GPIO_OUT_DISABLE);
  99}
 100
 101static void bd70528_gpio_set(struct gpio_chip *chip, unsigned int offset,
 102                             int value)
 103{
 104        int ret;
 105        struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
 106        u8 val = (value) ? BD70528_GPIO_OUT_HI : BD70528_GPIO_OUT_LO;
 107
 108        ret = regmap_update_bits(bdgpio->chip.regmap, GPIO_OUT_REG(offset),
 109                                 BD70528_GPIO_OUT_MASK, val);
 110        if (ret)
 111                dev_err(bdgpio->chip.dev, "Could not set gpio to %d\n", value);
 112}
 113
 114static int bd70528_direction_output(struct gpio_chip *chip, unsigned int offset,
 115                                    int value)
 116{
 117        struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
 118
 119        bd70528_gpio_set(chip, offset, value);
 120        return regmap_update_bits(bdgpio->chip.regmap, GPIO_OUT_REG(offset),
 121                                 BD70528_GPIO_OUT_EN_MASK,
 122                                 BD70528_GPIO_OUT_ENABLE);
 123}
 124
 125#define GPIO_IN_STATE_MASK(offset) (BD70528_GPIO_IN_STATE_BASE << (offset))
 126
 127static int bd70528_gpio_get_o(struct bd70528_gpio *bdgpio, unsigned int offset)
 128{
 129        int ret;
 130        unsigned int val;
 131
 132        ret = regmap_read(bdgpio->chip.regmap, GPIO_OUT_REG(offset), &val);
 133        if (!ret)
 134                ret = !!(val & BD70528_GPIO_OUT_MASK);
 135        else
 136                dev_err(bdgpio->chip.dev, "GPIO (out) state read failed\n");
 137
 138        return ret;
 139}
 140
 141static int bd70528_gpio_get_i(struct bd70528_gpio *bdgpio, unsigned int offset)
 142{
 143        unsigned int val;
 144        int ret;
 145
 146        ret = regmap_read(bdgpio->chip.regmap, BD70528_REG_GPIO_STATE, &val);
 147
 148        if (!ret)
 149                ret = !(val & GPIO_IN_STATE_MASK(offset));
 150        else
 151                dev_err(bdgpio->chip.dev, "GPIO (in) state read failed\n");
 152
 153        return ret;
 154}
 155
 156static int bd70528_gpio_get(struct gpio_chip *chip, unsigned int offset)
 157{
 158        int ret;
 159        struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
 160
 161        /*
 162         * There is a race condition where someone might be changing the
 163         * GPIO direction after we get it but before we read the value. But
 164         * application design where GPIO direction may be changed just when
 165         * we read GPIO value would be pointless as reader could not know
 166         * whether the returned high/low state is caused by input or output.
 167         * Or then there must be other ways to mitigate the issue. Thus
 168         * locking would make no sense.
 169         */
 170        ret = bd70528_get_direction(chip, offset);
 171        if (ret == GPIO_LINE_DIRECTION_OUT)
 172                ret = bd70528_gpio_get_o(bdgpio, offset);
 173        else if (ret == GPIO_LINE_DIRECTION_IN)
 174                ret = bd70528_gpio_get_i(bdgpio, offset);
 175        else
 176                dev_err(bdgpio->chip.dev, "failed to read GPIO direction\n");
 177
 178        return ret;
 179}
 180
 181static int bd70528_probe(struct platform_device *pdev)
 182{
 183        struct bd70528_gpio *bdgpio;
 184        struct rohm_regmap_dev *bd70528;
 185        int ret;
 186
 187        bd70528 = dev_get_drvdata(pdev->dev.parent);
 188        if (!bd70528) {
 189                dev_err(&pdev->dev, "No MFD driver data\n");
 190                return -EINVAL;
 191        }
 192
 193        bdgpio = devm_kzalloc(&pdev->dev, sizeof(*bdgpio),
 194                              GFP_KERNEL);
 195        if (!bdgpio)
 196                return -ENOMEM;
 197        bdgpio->chip.dev = &pdev->dev;
 198        bdgpio->gpio.parent = pdev->dev.parent;
 199        bdgpio->gpio.label = "bd70528-gpio";
 200        bdgpio->gpio.owner = THIS_MODULE;
 201        bdgpio->gpio.get_direction = bd70528_get_direction;
 202        bdgpio->gpio.direction_input = bd70528_direction_input;
 203        bdgpio->gpio.direction_output = bd70528_direction_output;
 204        bdgpio->gpio.set_config = bd70528_gpio_set_config;
 205        bdgpio->gpio.can_sleep = true;
 206        bdgpio->gpio.get = bd70528_gpio_get;
 207        bdgpio->gpio.set = bd70528_gpio_set;
 208        bdgpio->gpio.ngpio = 4;
 209        bdgpio->gpio.base = -1;
 210#ifdef CONFIG_OF_GPIO
 211        bdgpio->gpio.of_node = pdev->dev.parent->of_node;
 212#endif
 213        bdgpio->chip.regmap = bd70528->regmap;
 214
 215        ret = devm_gpiochip_add_data(&pdev->dev, &bdgpio->gpio,
 216                                     bdgpio);
 217        if (ret)
 218                dev_err(&pdev->dev, "gpio_init: Failed to add bd70528-gpio\n");
 219
 220        return ret;
 221}
 222
 223static struct platform_driver bd70528_gpio = {
 224        .driver = {
 225                .name = "bd70528-gpio"
 226        },
 227        .probe = bd70528_probe,
 228};
 229
 230module_platform_driver(bd70528_gpio);
 231
 232MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
 233MODULE_DESCRIPTION("BD70528 voltage regulator driver");
 234MODULE_LICENSE("GPL");
 235MODULE_ALIAS("platform:bd70528-gpio");
 236