root/drivers/gpio/gpio-bd70528.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. bd70528_set_debounce
  2. bd70528_get_direction
  3. bd70528_gpio_set_config
  4. bd70528_direction_input
  5. bd70528_gpio_set
  6. bd70528_direction_output
  7. bd70528_gpio_get_o
  8. bd70528_gpio_get_i
  9. bd70528_gpio_get
  10. bd70528_probe

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

/* [<][>][^][v][top][bottom][index][help] */