linux/drivers/gpio/gpio-max77620.c
<<
>>
Prefs
   1/*
   2 * MAXIM MAX77620 GPIO driver
   3 *
   4 * Copyright (c) 2016, NVIDIA CORPORATION.  All rights reserved.
   5 *
   6 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms and conditions of the GNU General Public License,
   8 * version 2, as published by the Free Software Foundation.
   9 */
  10
  11#include <linux/gpio/driver.h>
  12#include <linux/interrupt.h>
  13#include <linux/mfd/max77620.h>
  14#include <linux/module.h>
  15#include <linux/platform_device.h>
  16#include <linux/regmap.h>
  17
  18#define GPIO_REG_ADDR(offset) (MAX77620_REG_GPIO0 + offset)
  19
  20struct max77620_gpio {
  21        struct gpio_chip        gpio_chip;
  22        struct regmap           *rmap;
  23        struct device           *dev;
  24        int                     gpio_irq;
  25        int                     irq_base;
  26        int                     gpio_base;
  27};
  28
  29static const struct regmap_irq max77620_gpio_irqs[] = {
  30        [0] = {
  31                .mask = MAX77620_IRQ_LVL2_GPIO_EDGE0,
  32                .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING,
  33                .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING,
  34                .reg_offset = 0,
  35                .type_reg_offset = 0,
  36        },
  37        [1] = {
  38                .mask = MAX77620_IRQ_LVL2_GPIO_EDGE1,
  39                .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING,
  40                .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING,
  41                .reg_offset = 0,
  42                .type_reg_offset = 1,
  43        },
  44        [2] = {
  45                .mask = MAX77620_IRQ_LVL2_GPIO_EDGE2,
  46                .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING,
  47                .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING,
  48                .reg_offset = 0,
  49                .type_reg_offset = 2,
  50        },
  51        [3] = {
  52                .mask = MAX77620_IRQ_LVL2_GPIO_EDGE3,
  53                .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING,
  54                .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING,
  55                .reg_offset = 0,
  56                .type_reg_offset = 3,
  57        },
  58        [4] = {
  59                .mask = MAX77620_IRQ_LVL2_GPIO_EDGE4,
  60                .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING,
  61                .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING,
  62                .reg_offset = 0,
  63                .type_reg_offset = 4,
  64        },
  65        [5] = {
  66                .mask = MAX77620_IRQ_LVL2_GPIO_EDGE5,
  67                .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING,
  68                .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING,
  69                .reg_offset = 0,
  70                .type_reg_offset = 5,
  71        },
  72        [6] = {
  73                .mask = MAX77620_IRQ_LVL2_GPIO_EDGE6,
  74                .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING,
  75                .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING,
  76                .reg_offset = 0,
  77                .type_reg_offset = 6,
  78        },
  79        [7] = {
  80                .mask = MAX77620_IRQ_LVL2_GPIO_EDGE7,
  81                .type_rising_mask = MAX77620_CNFG_GPIO_INT_RISING,
  82                .type_falling_mask = MAX77620_CNFG_GPIO_INT_FALLING,
  83                .reg_offset = 0,
  84                .type_reg_offset = 7,
  85        },
  86};
  87
  88static struct regmap_irq_chip max77620_gpio_irq_chip = {
  89        .name = "max77620-gpio",
  90        .irqs = max77620_gpio_irqs,
  91        .num_irqs = ARRAY_SIZE(max77620_gpio_irqs),
  92        .num_regs = 1,
  93        .num_type_reg = 8,
  94        .irq_reg_stride = 1,
  95        .type_reg_stride = 1,
  96        .status_base = MAX77620_REG_IRQ_LVL2_GPIO,
  97        .type_base = MAX77620_REG_GPIO0,
  98};
  99
 100static int max77620_gpio_dir_input(struct gpio_chip *gc, unsigned int offset)
 101{
 102        struct max77620_gpio *mgpio = gpiochip_get_data(gc);
 103        int ret;
 104
 105        ret = regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
 106                                 MAX77620_CNFG_GPIO_DIR_MASK,
 107                                 MAX77620_CNFG_GPIO_DIR_INPUT);
 108        if (ret < 0)
 109                dev_err(mgpio->dev, "CNFG_GPIOx dir update failed: %d\n", ret);
 110
 111        return ret;
 112}
 113
 114static int max77620_gpio_get(struct gpio_chip *gc, unsigned int offset)
 115{
 116        struct max77620_gpio *mgpio = gpiochip_get_data(gc);
 117        unsigned int val;
 118        int ret;
 119
 120        ret = regmap_read(mgpio->rmap, GPIO_REG_ADDR(offset), &val);
 121        if (ret < 0) {
 122                dev_err(mgpio->dev, "CNFG_GPIOx read failed: %d\n", ret);
 123                return ret;
 124        }
 125
 126        if  (val & MAX77620_CNFG_GPIO_DIR_MASK)
 127                return !!(val & MAX77620_CNFG_GPIO_INPUT_VAL_MASK);
 128        else
 129                return !!(val & MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK);
 130}
 131
 132static int max77620_gpio_dir_output(struct gpio_chip *gc, unsigned int offset,
 133                                    int value)
 134{
 135        struct max77620_gpio *mgpio = gpiochip_get_data(gc);
 136        u8 val;
 137        int ret;
 138
 139        val = (value) ? MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH :
 140                                MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW;
 141
 142        ret = regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
 143                                 MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK, val);
 144        if (ret < 0) {
 145                dev_err(mgpio->dev, "CNFG_GPIOx val update failed: %d\n", ret);
 146                return ret;
 147        }
 148
 149        ret = regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
 150                                 MAX77620_CNFG_GPIO_DIR_MASK,
 151                                 MAX77620_CNFG_GPIO_DIR_OUTPUT);
 152        if (ret < 0)
 153                dev_err(mgpio->dev, "CNFG_GPIOx dir update failed: %d\n", ret);
 154
 155        return ret;
 156}
 157
 158static int max77620_gpio_set_debounce(struct gpio_chip *gc,
 159                                      unsigned int offset,
 160                                      unsigned int debounce)
 161{
 162        struct max77620_gpio *mgpio = gpiochip_get_data(gc);
 163        u8 val;
 164        int ret;
 165
 166        switch (debounce) {
 167        case 0:
 168                val = MAX77620_CNFG_GPIO_DBNC_None;
 169                break;
 170        case 1 ... 8:
 171                val = MAX77620_CNFG_GPIO_DBNC_8ms;
 172                break;
 173        case 9 ... 16:
 174                val = MAX77620_CNFG_GPIO_DBNC_16ms;
 175                break;
 176        case 17 ... 32:
 177                val = MAX77620_CNFG_GPIO_DBNC_32ms;
 178                break;
 179        default:
 180                dev_err(mgpio->dev, "Illegal value %u\n", debounce);
 181                return -EINVAL;
 182        }
 183
 184        ret = regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
 185                                 MAX77620_CNFG_GPIO_DBNC_MASK, val);
 186        if (ret < 0)
 187                dev_err(mgpio->dev, "CNFG_GPIOx_DBNC update failed: %d\n", ret);
 188
 189        return ret;
 190}
 191
 192static void max77620_gpio_set(struct gpio_chip *gc, unsigned int offset,
 193                              int value)
 194{
 195        struct max77620_gpio *mgpio = gpiochip_get_data(gc);
 196        u8 val;
 197        int ret;
 198
 199        val = (value) ? MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH :
 200                                MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW;
 201
 202        ret = regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
 203                                 MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK, val);
 204        if (ret < 0)
 205                dev_err(mgpio->dev, "CNFG_GPIO_OUT update failed: %d\n", ret);
 206}
 207
 208static int max77620_gpio_set_single_ended(struct gpio_chip *gc,
 209                                          unsigned int offset,
 210                                          enum single_ended_mode mode)
 211{
 212        struct max77620_gpio *mgpio = gpiochip_get_data(gc);
 213
 214        switch (mode) {
 215        case LINE_MODE_OPEN_DRAIN:
 216                return regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
 217                                          MAX77620_CNFG_GPIO_DRV_MASK,
 218                                          MAX77620_CNFG_GPIO_DRV_OPENDRAIN);
 219        case LINE_MODE_PUSH_PULL:
 220                return regmap_update_bits(mgpio->rmap, GPIO_REG_ADDR(offset),
 221                                          MAX77620_CNFG_GPIO_DRV_MASK,
 222                                          MAX77620_CNFG_GPIO_DRV_PUSHPULL);
 223        default:
 224                break;
 225        }
 226
 227        return -ENOTSUPP;
 228}
 229
 230static int max77620_gpio_to_irq(struct gpio_chip *gc, unsigned int offset)
 231{
 232        struct max77620_gpio *mgpio = gpiochip_get_data(gc);
 233        struct max77620_chip *chip = dev_get_drvdata(mgpio->dev->parent);
 234
 235        return regmap_irq_get_virq(chip->gpio_irq_data, offset);
 236}
 237
 238static int max77620_gpio_probe(struct platform_device *pdev)
 239{
 240        struct max77620_chip *chip =  dev_get_drvdata(pdev->dev.parent);
 241        struct max77620_gpio *mgpio;
 242        int gpio_irq;
 243        int ret;
 244
 245        gpio_irq = platform_get_irq(pdev, 0);
 246        if (gpio_irq <= 0) {
 247                dev_err(&pdev->dev, "GPIO irq not available %d\n", gpio_irq);
 248                return -ENODEV;
 249        }
 250
 251        mgpio = devm_kzalloc(&pdev->dev, sizeof(*mgpio), GFP_KERNEL);
 252        if (!mgpio)
 253                return -ENOMEM;
 254
 255        mgpio->rmap = chip->rmap;
 256        mgpio->dev = &pdev->dev;
 257        mgpio->gpio_irq = gpio_irq;
 258
 259        mgpio->gpio_chip.label = pdev->name;
 260        mgpio->gpio_chip.parent = &pdev->dev;
 261        mgpio->gpio_chip.direction_input = max77620_gpio_dir_input;
 262        mgpio->gpio_chip.get = max77620_gpio_get;
 263        mgpio->gpio_chip.direction_output = max77620_gpio_dir_output;
 264        mgpio->gpio_chip.set_debounce = max77620_gpio_set_debounce;
 265        mgpio->gpio_chip.set = max77620_gpio_set;
 266        mgpio->gpio_chip.set_single_ended = max77620_gpio_set_single_ended;
 267        mgpio->gpio_chip.to_irq = max77620_gpio_to_irq;
 268        mgpio->gpio_chip.ngpio = MAX77620_GPIO_NR;
 269        mgpio->gpio_chip.can_sleep = 1;
 270        mgpio->gpio_chip.base = -1;
 271        mgpio->irq_base = -1;
 272#ifdef CONFIG_OF_GPIO
 273        mgpio->gpio_chip.of_node = pdev->dev.parent->of_node;
 274#endif
 275
 276        platform_set_drvdata(pdev, mgpio);
 277
 278        ret = devm_gpiochip_add_data(&pdev->dev, &mgpio->gpio_chip, mgpio);
 279        if (ret < 0) {
 280                dev_err(&pdev->dev, "gpio_init: Failed to add max77620_gpio\n");
 281                return ret;
 282        }
 283
 284        mgpio->gpio_base = mgpio->gpio_chip.base;
 285        ret = devm_regmap_add_irq_chip(&pdev->dev, chip->rmap, mgpio->gpio_irq,
 286                                       IRQF_ONESHOT, mgpio->irq_base,
 287                                       &max77620_gpio_irq_chip,
 288                                       &chip->gpio_irq_data);
 289        if (ret < 0) {
 290                dev_err(&pdev->dev, "Failed to add gpio irq_chip %d\n", ret);
 291                return ret;
 292        }
 293
 294        return 0;
 295}
 296
 297static const struct platform_device_id max77620_gpio_devtype[] = {
 298        { .name = "max77620-gpio", },
 299        {},
 300};
 301MODULE_DEVICE_TABLE(platform, max77620_gpio_devtype);
 302
 303static struct platform_driver max77620_gpio_driver = {
 304        .driver.name    = "max77620-gpio",
 305        .probe          = max77620_gpio_probe,
 306        .id_table       = max77620_gpio_devtype,
 307};
 308
 309module_platform_driver(max77620_gpio_driver);
 310
 311MODULE_DESCRIPTION("GPIO interface for MAX77620 and MAX20024 PMIC");
 312MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
 313MODULE_AUTHOR("Chaitanya Bandi <bandik@nvidia.com>");
 314MODULE_ALIAS("platform:max77620-gpio");
 315MODULE_LICENSE("GPL v2");
 316