linux/drivers/gpio/gpio-wm831x.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * gpiolib support for Wolfson WM831x PMICs
   4 *
   5 * Copyright 2009 Wolfson Microelectronics PLC.
   6 *
   7 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
   8 *
   9 */
  10
  11#include <linux/kernel.h>
  12#include <linux/slab.h>
  13#include <linux/module.h>
  14#include <linux/gpio/driver.h>
  15#include <linux/mfd/core.h>
  16#include <linux/platform_device.h>
  17#include <linux/seq_file.h>
  18
  19#include <linux/mfd/wm831x/core.h>
  20#include <linux/mfd/wm831x/pdata.h>
  21#include <linux/mfd/wm831x/gpio.h>
  22#include <linux/mfd/wm831x/irq.h>
  23
  24struct wm831x_gpio {
  25        struct wm831x *wm831x;
  26        struct gpio_chip gpio_chip;
  27};
  28
  29static int wm831x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
  30{
  31        struct wm831x_gpio *wm831x_gpio = gpiochip_get_data(chip);
  32        struct wm831x *wm831x = wm831x_gpio->wm831x;
  33        int val = WM831X_GPN_DIR;
  34
  35        if (wm831x->has_gpio_ena)
  36                val |= WM831X_GPN_TRI;
  37
  38        return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
  39                               WM831X_GPN_DIR | WM831X_GPN_TRI |
  40                               WM831X_GPN_FN_MASK, val);
  41}
  42
  43static int wm831x_gpio_get(struct gpio_chip *chip, unsigned offset)
  44{
  45        struct wm831x_gpio *wm831x_gpio = gpiochip_get_data(chip);
  46        struct wm831x *wm831x = wm831x_gpio->wm831x;
  47        int ret;
  48
  49        ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL);
  50        if (ret < 0)
  51                return ret;
  52
  53        if (ret & 1 << offset)
  54                return 1;
  55        else
  56                return 0;
  57}
  58
  59static void wm831x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
  60{
  61        struct wm831x_gpio *wm831x_gpio = gpiochip_get_data(chip);
  62        struct wm831x *wm831x = wm831x_gpio->wm831x;
  63
  64        wm831x_set_bits(wm831x, WM831X_GPIO_LEVEL, 1 << offset,
  65                        value << offset);
  66}
  67
  68static int wm831x_gpio_direction_out(struct gpio_chip *chip,
  69                                     unsigned offset, int value)
  70{
  71        struct wm831x_gpio *wm831x_gpio = gpiochip_get_data(chip);
  72        struct wm831x *wm831x = wm831x_gpio->wm831x;
  73        int val = 0;
  74        int ret;
  75
  76        if (wm831x->has_gpio_ena)
  77                val |= WM831X_GPN_TRI;
  78
  79        ret = wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
  80                              WM831X_GPN_DIR | WM831X_GPN_TRI |
  81                              WM831X_GPN_FN_MASK, val);
  82        if (ret < 0)
  83                return ret;
  84
  85        /* Can only set GPIO state once it's in output mode */
  86        wm831x_gpio_set(chip, offset, value);
  87
  88        return 0;
  89}
  90
  91static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
  92{
  93        struct wm831x_gpio *wm831x_gpio = gpiochip_get_data(chip);
  94        struct wm831x *wm831x = wm831x_gpio->wm831x;
  95
  96        return irq_create_mapping(wm831x->irq_domain,
  97                                  WM831X_IRQ_GPIO_1 + offset);
  98}
  99
 100static int wm831x_gpio_set_debounce(struct wm831x *wm831x, unsigned offset,
 101                                    unsigned debounce)
 102{
 103        int reg = WM831X_GPIO1_CONTROL + offset;
 104        int ret, fn;
 105
 106        ret = wm831x_reg_read(wm831x, reg);
 107        if (ret < 0)
 108                return ret;
 109
 110        switch (ret & WM831X_GPN_FN_MASK) {
 111        case 0:
 112        case 1:
 113                break;
 114        default:
 115                /* Not in GPIO mode */
 116                return -EBUSY;
 117        }
 118
 119        if (debounce >= 32 && debounce <= 64)
 120                fn = 0;
 121        else if (debounce >= 4000 && debounce <= 8000)
 122                fn = 1;
 123        else
 124                return -EINVAL;
 125
 126        return wm831x_set_bits(wm831x, reg, WM831X_GPN_FN_MASK, fn);
 127}
 128
 129static int wm831x_set_config(struct gpio_chip *chip, unsigned int offset,
 130                             unsigned long config)
 131{
 132        struct wm831x_gpio *wm831x_gpio = gpiochip_get_data(chip);
 133        struct wm831x *wm831x = wm831x_gpio->wm831x;
 134        int reg = WM831X_GPIO1_CONTROL + offset;
 135
 136        switch (pinconf_to_config_param(config)) {
 137        case PIN_CONFIG_DRIVE_OPEN_DRAIN:
 138                return wm831x_set_bits(wm831x, reg,
 139                                       WM831X_GPN_OD_MASK, WM831X_GPN_OD);
 140        case PIN_CONFIG_DRIVE_PUSH_PULL:
 141                return wm831x_set_bits(wm831x, reg,
 142                                       WM831X_GPN_OD_MASK, 0);
 143        case PIN_CONFIG_INPUT_DEBOUNCE:
 144                return wm831x_gpio_set_debounce(wm831x, offset,
 145                        pinconf_to_config_argument(config));
 146        default:
 147                break;
 148        }
 149
 150        return -ENOTSUPP;
 151}
 152
 153#ifdef CONFIG_DEBUG_FS
 154static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 155{
 156        struct wm831x_gpio *wm831x_gpio = gpiochip_get_data(chip);
 157        struct wm831x *wm831x = wm831x_gpio->wm831x;
 158        int i, tristated;
 159
 160        for (i = 0; i < chip->ngpio; i++) {
 161                int gpio = i + chip->base;
 162                int reg;
 163                const char *label, *pull, *powerdomain;
 164
 165                /* We report the GPIO even if it's not requested since
 166                 * we're also reporting things like alternate
 167                 * functions which apply even when the GPIO is not in
 168                 * use as a GPIO.
 169                 */
 170                label = gpiochip_is_requested(chip, i);
 171                if (!label)
 172                        label = "Unrequested";
 173
 174                seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label);
 175
 176                reg = wm831x_reg_read(wm831x, WM831X_GPIO1_CONTROL + i);
 177                if (reg < 0) {
 178                        dev_err(wm831x->dev,
 179                                "GPIO control %d read failed: %d\n",
 180                                gpio, reg);
 181                        seq_putc(s, '\n');
 182                        continue;
 183                }
 184
 185                switch (reg & WM831X_GPN_PULL_MASK) {
 186                case WM831X_GPIO_PULL_NONE:
 187                        pull = "nopull";
 188                        break;
 189                case WM831X_GPIO_PULL_DOWN:
 190                        pull = "pulldown";
 191                        break;
 192                case WM831X_GPIO_PULL_UP:
 193                        pull = "pullup";
 194                        break;
 195                default:
 196                        pull = "INVALID PULL";
 197                        break;
 198                }
 199
 200                switch (i + 1) {
 201                case 1 ... 3:
 202                case 7 ... 9:
 203                        if (reg & WM831X_GPN_PWR_DOM)
 204                                powerdomain = "VPMIC";
 205                        else
 206                                powerdomain = "DBVDD";
 207                        break;
 208
 209                case 4 ... 6:
 210                case 10 ... 12:
 211                        if (reg & WM831X_GPN_PWR_DOM)
 212                                powerdomain = "SYSVDD";
 213                        else
 214                                powerdomain = "DBVDD";
 215                        break;
 216
 217                case 13 ... 16:
 218                        powerdomain = "TPVDD";
 219                        break;
 220
 221                default:
 222                        BUG();
 223                        break;
 224                }
 225
 226                tristated = reg & WM831X_GPN_TRI;
 227                if (wm831x->has_gpio_ena)
 228                        tristated = !tristated;
 229
 230                seq_printf(s, " %s %s %s %s%s\n"
 231                           "                                  %s%s (0x%4x)\n",
 232                           reg & WM831X_GPN_DIR ? "in" : "out",
 233                           wm831x_gpio_get(chip, i) ? "high" : "low",
 234                           pull,
 235                           powerdomain,
 236                           reg & WM831X_GPN_POL ? "" : " inverted",
 237                           reg & WM831X_GPN_OD ? "open-drain" : "push-pull",
 238                           tristated ? " tristated" : "",
 239                           reg);
 240        }
 241}
 242#else
 243#define wm831x_gpio_dbg_show NULL
 244#endif
 245
 246static const struct gpio_chip template_chip = {
 247        .label                  = "wm831x",
 248        .owner                  = THIS_MODULE,
 249        .direction_input        = wm831x_gpio_direction_in,
 250        .get                    = wm831x_gpio_get,
 251        .direction_output       = wm831x_gpio_direction_out,
 252        .set                    = wm831x_gpio_set,
 253        .to_irq                 = wm831x_gpio_to_irq,
 254        .set_config             = wm831x_set_config,
 255        .dbg_show               = wm831x_gpio_dbg_show,
 256        .can_sleep              = true,
 257};
 258
 259static int wm831x_gpio_probe(struct platform_device *pdev)
 260{
 261        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
 262        struct wm831x_pdata *pdata = &wm831x->pdata;
 263        struct wm831x_gpio *wm831x_gpio;
 264
 265        wm831x_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm831x_gpio),
 266                                   GFP_KERNEL);
 267        if (wm831x_gpio == NULL)
 268                return -ENOMEM;
 269
 270        wm831x_gpio->wm831x = wm831x;
 271        wm831x_gpio->gpio_chip = template_chip;
 272        wm831x_gpio->gpio_chip.ngpio = wm831x->num_gpio;
 273        wm831x_gpio->gpio_chip.parent = &pdev->dev;
 274        if (pdata && pdata->gpio_base)
 275                wm831x_gpio->gpio_chip.base = pdata->gpio_base;
 276        else
 277                wm831x_gpio->gpio_chip.base = -1;
 278#ifdef CONFIG_OF_GPIO
 279        wm831x_gpio->gpio_chip.of_node = wm831x->dev->of_node;
 280#endif
 281
 282        return devm_gpiochip_add_data(&pdev->dev, &wm831x_gpio->gpio_chip, wm831x_gpio);
 283}
 284
 285static struct platform_driver wm831x_gpio_driver = {
 286        .driver.name    = "wm831x-gpio",
 287        .probe          = wm831x_gpio_probe,
 288};
 289
 290static int __init wm831x_gpio_init(void)
 291{
 292        return platform_driver_register(&wm831x_gpio_driver);
 293}
 294subsys_initcall(wm831x_gpio_init);
 295
 296static void __exit wm831x_gpio_exit(void)
 297{
 298        platform_driver_unregister(&wm831x_gpio_driver);
 299}
 300module_exit(wm831x_gpio_exit);
 301
 302MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 303MODULE_DESCRIPTION("GPIO interface for WM831x PMICs");
 304MODULE_LICENSE("GPL");
 305MODULE_ALIAS("platform:wm831x-gpio");
 306