linux/drivers/gpio/gpio-tps65218.c
<<
>>
Prefs
   1/*
   2 * Copyright 2015 Verifone Int.
   3 *
   4 * Author: Nicolas Saenz Julienne <nicolassaenzj@gmail.com>
   5 *
   6 * This program is free software; you can redistribute it and/or modify i t
   7 * under  the terms of the GNU General  Public License as published by th e
   8 * Free Software Foundation;  either version 2 of the License, or (at you r
   9 * option) any later version.
  10 *
  11 * This driver is based on the gpio-tps65912 implementation.
  12 */
  13
  14#include <linux/kernel.h>
  15#include <linux/module.h>
  16#include <linux/errno.h>
  17#include <linux/gpio/driver.h>
  18#include <linux/platform_device.h>
  19#include <linux/regmap.h>
  20#include <linux/mfd/tps65218.h>
  21
  22struct tps65218_gpio {
  23        struct tps65218 *tps65218;
  24        struct gpio_chip gpio_chip;
  25};
  26
  27static int tps65218_gpio_get(struct gpio_chip *gc, unsigned offset)
  28{
  29        struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc);
  30        struct tps65218 *tps65218 = tps65218_gpio->tps65218;
  31        unsigned int val;
  32        int ret;
  33
  34        ret = regmap_read(tps65218->regmap, TPS65218_REG_ENABLE2, &val);
  35        if (ret)
  36                return ret;
  37
  38        return !!(val & (TPS65218_ENABLE2_GPIO1 << offset));
  39}
  40
  41static void tps65218_gpio_set(struct gpio_chip *gc, unsigned offset,
  42                              int value)
  43{
  44        struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc);
  45        struct tps65218 *tps65218 = tps65218_gpio->tps65218;
  46
  47        if (value)
  48                tps65218_set_bits(tps65218, TPS65218_REG_ENABLE2,
  49                                  TPS65218_ENABLE2_GPIO1 << offset,
  50                                  TPS65218_ENABLE2_GPIO1 << offset,
  51                                  TPS65218_PROTECT_L1);
  52        else
  53                tps65218_clear_bits(tps65218, TPS65218_REG_ENABLE2,
  54                                    TPS65218_ENABLE2_GPIO1 << offset,
  55                                    TPS65218_PROTECT_L1);
  56}
  57
  58static int tps65218_gpio_output(struct gpio_chip *gc, unsigned offset,
  59                                int value)
  60{
  61        /* Only drives GPOs */
  62        tps65218_gpio_set(gc, offset, value);
  63        return 0;
  64}
  65
  66static int tps65218_gpio_input(struct gpio_chip *gc, unsigned offset)
  67{
  68        return -EPERM;
  69}
  70
  71static int tps65218_gpio_request(struct gpio_chip *gc, unsigned offset)
  72{
  73        struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc);
  74        struct tps65218 *tps65218 = tps65218_gpio->tps65218;
  75        int ret;
  76
  77        if (gpiochip_line_is_open_source(gc, offset)) {
  78                dev_err(gc->parent, "can't work as open source\n");
  79                return -EINVAL;
  80        }
  81
  82        switch (offset) {
  83        case 0:
  84                if (!gpiochip_line_is_open_drain(gc, offset)) {
  85                        dev_err(gc->parent, "GPO1 works only as open drain\n");
  86                        return -EINVAL;
  87                }
  88
  89                /* Disable sequencer for GPO1 */
  90                ret = tps65218_clear_bits(tps65218, TPS65218_REG_SEQ7,
  91                                          TPS65218_SEQ7_GPO1_SEQ_MASK,
  92                                          TPS65218_PROTECT_L1);
  93                if (ret)
  94                        return ret;
  95
  96                /* Setup GPO1 */
  97                ret = tps65218_clear_bits(tps65218, TPS65218_REG_CONFIG1,
  98                                          TPS65218_CONFIG1_IO1_SEL,
  99                                          TPS65218_PROTECT_L1);
 100                if (ret)
 101                        return ret;
 102
 103                break;
 104        case 1:
 105                /* Setup GPO2 */
 106                ret = tps65218_clear_bits(tps65218, TPS65218_REG_CONFIG1,
 107                                          TPS65218_CONFIG1_IO1_SEL,
 108                                          TPS65218_PROTECT_L1);
 109                if (ret)
 110                        return ret;
 111
 112                break;
 113
 114        case 2:
 115                if (!gpiochip_line_is_open_drain(gc, offset)) {
 116                        dev_err(gc->parent, "GPO3 works only as open drain\n");
 117                        return -EINVAL;
 118                }
 119
 120                /* Disable sequencer for GPO3 */
 121                ret = tps65218_clear_bits(tps65218, TPS65218_REG_SEQ7,
 122                                          TPS65218_SEQ7_GPO3_SEQ_MASK,
 123                                          TPS65218_PROTECT_L1);
 124                if (ret)
 125                        return ret;
 126
 127                /* Setup GPO3 */
 128                ret = tps65218_clear_bits(tps65218, TPS65218_REG_CONFIG2,
 129                                          TPS65218_CONFIG2_DC12_RST,
 130                                          TPS65218_PROTECT_L1);
 131                if (ret)
 132                        return ret;
 133
 134                break;
 135        default:
 136                return -EINVAL;
 137        }
 138
 139        return 0;
 140}
 141
 142static int tps65218_gpio_set_config(struct gpio_chip *gc, unsigned offset,
 143                                    unsigned long config)
 144{
 145        struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc);
 146        struct tps65218 *tps65218 = tps65218_gpio->tps65218;
 147        enum pin_config_param param = pinconf_to_config_param(config);
 148
 149        switch (offset) {
 150        case 0:
 151        case 2:
 152                /* GPO1 is hardwired to be open drain */
 153                if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN)
 154                        return 0;
 155                return -ENOTSUPP;
 156        case 1:
 157                /* GPO2 is push-pull by default, can be set as open drain. */
 158                if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN)
 159                        return tps65218_clear_bits(tps65218,
 160                                                   TPS65218_REG_CONFIG1,
 161                                                   TPS65218_CONFIG1_GPO2_BUF,
 162                                                   TPS65218_PROTECT_L1);
 163                if (param == PIN_CONFIG_DRIVE_PUSH_PULL)
 164                        return tps65218_set_bits(tps65218,
 165                                                 TPS65218_REG_CONFIG1,
 166                                                 TPS65218_CONFIG1_GPO2_BUF,
 167                                                 TPS65218_CONFIG1_GPO2_BUF,
 168                                                 TPS65218_PROTECT_L1);
 169                return -ENOTSUPP;
 170        default:
 171                break;
 172        }
 173        return -ENOTSUPP;
 174}
 175
 176static const struct gpio_chip template_chip = {
 177        .label                  = "gpio-tps65218",
 178        .owner                  = THIS_MODULE,
 179        .request                = tps65218_gpio_request,
 180        .direction_output       = tps65218_gpio_output,
 181        .direction_input        = tps65218_gpio_input,
 182        .get                    = tps65218_gpio_get,
 183        .set                    = tps65218_gpio_set,
 184        .set_config             = tps65218_gpio_set_config,
 185        .can_sleep              = true,
 186        .ngpio                  = 3,
 187        .base                   = -1,
 188};
 189
 190static int tps65218_gpio_probe(struct platform_device *pdev)
 191{
 192        struct tps65218 *tps65218 = dev_get_drvdata(pdev->dev.parent);
 193        struct tps65218_gpio *tps65218_gpio;
 194        int ret;
 195
 196        tps65218_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps65218_gpio),
 197                                     GFP_KERNEL);
 198        if (!tps65218_gpio)
 199                return -ENOMEM;
 200
 201        tps65218_gpio->tps65218 = tps65218;
 202        tps65218_gpio->gpio_chip = template_chip;
 203        tps65218_gpio->gpio_chip.parent = &pdev->dev;
 204#ifdef CONFIG_OF_GPIO
 205        tps65218_gpio->gpio_chip.of_node = pdev->dev.of_node;
 206#endif
 207
 208        ret = devm_gpiochip_add_data(&pdev->dev, &tps65218_gpio->gpio_chip,
 209                                     tps65218_gpio);
 210        if (ret < 0) {
 211                dev_err(&pdev->dev, "Failed to register gpiochip, %d\n", ret);
 212                return ret;
 213        }
 214
 215        platform_set_drvdata(pdev, tps65218_gpio);
 216
 217        return ret;
 218}
 219
 220static const struct of_device_id tps65218_dt_match[] = {
 221        { .compatible = "ti,tps65218-gpio" },
 222        {  }
 223};
 224MODULE_DEVICE_TABLE(of, tps65218_dt_match);
 225
 226static const struct platform_device_id tps65218_gpio_id_table[] = {
 227        { "tps65218-gpio", },
 228        { /* sentinel */ }
 229};
 230MODULE_DEVICE_TABLE(platform, tps65218_gpio_id_table);
 231
 232static struct platform_driver tps65218_gpio_driver = {
 233        .driver = {
 234                .name = "tps65218-gpio",
 235                .of_match_table = of_match_ptr(tps65218_dt_match)
 236        },
 237        .probe = tps65218_gpio_probe,
 238        .id_table = tps65218_gpio_id_table,
 239};
 240
 241module_platform_driver(tps65218_gpio_driver);
 242
 243MODULE_AUTHOR("Nicolas Saenz Julienne <nicolassaenzj@gmail.com>");
 244MODULE_DESCRIPTION("GPO interface for TPS65218 PMICs");
 245MODULE_LICENSE("GPL v2");
 246MODULE_ALIAS("platform:tps65218-gpio");
 247