linux/drivers/gpio/gpio-lp3943.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * TI/National Semiconductor LP3943 GPIO driver
   4 *
   5 * Copyright 2013 Texas Instruments
   6 *
   7 * Author: Milo Kim <milo.kim@ti.com>
   8 */
   9
  10#include <linux/bitops.h>
  11#include <linux/err.h>
  12#include <linux/gpio/driver.h>
  13#include <linux/i2c.h>
  14#include <linux/mfd/lp3943.h>
  15#include <linux/module.h>
  16#include <linux/platform_device.h>
  17#include <linux/slab.h>
  18
  19enum lp3943_gpios {
  20        LP3943_GPIO1,
  21        LP3943_GPIO2,
  22        LP3943_GPIO3,
  23        LP3943_GPIO4,
  24        LP3943_GPIO5,
  25        LP3943_GPIO6,
  26        LP3943_GPIO7,
  27        LP3943_GPIO8,
  28        LP3943_GPIO9,
  29        LP3943_GPIO10,
  30        LP3943_GPIO11,
  31        LP3943_GPIO12,
  32        LP3943_GPIO13,
  33        LP3943_GPIO14,
  34        LP3943_GPIO15,
  35        LP3943_GPIO16,
  36        LP3943_MAX_GPIO,
  37};
  38
  39struct lp3943_gpio {
  40        struct gpio_chip chip;
  41        struct lp3943 *lp3943;
  42        u16 input_mask;         /* 1 = GPIO is input direction, 0 = output */
  43};
  44
  45static int lp3943_gpio_request(struct gpio_chip *chip, unsigned offset)
  46{
  47        struct lp3943_gpio *lp3943_gpio = gpiochip_get_data(chip);
  48        struct lp3943 *lp3943 = lp3943_gpio->lp3943;
  49
  50        /* Return an error if the pin is already assigned */
  51        if (test_and_set_bit(offset, &lp3943->pin_used))
  52                return -EBUSY;
  53
  54        return 0;
  55}
  56
  57static void lp3943_gpio_free(struct gpio_chip *chip, unsigned offset)
  58{
  59        struct lp3943_gpio *lp3943_gpio = gpiochip_get_data(chip);
  60        struct lp3943 *lp3943 = lp3943_gpio->lp3943;
  61
  62        clear_bit(offset, &lp3943->pin_used);
  63}
  64
  65static int lp3943_gpio_set_mode(struct lp3943_gpio *lp3943_gpio, u8 offset,
  66                                u8 val)
  67{
  68        struct lp3943 *lp3943 = lp3943_gpio->lp3943;
  69        const struct lp3943_reg_cfg *mux = lp3943->mux_cfg;
  70
  71        return lp3943_update_bits(lp3943, mux[offset].reg, mux[offset].mask,
  72                                  val << mux[offset].shift);
  73}
  74
  75static int lp3943_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
  76{
  77        struct lp3943_gpio *lp3943_gpio = gpiochip_get_data(chip);
  78
  79        lp3943_gpio->input_mask |= BIT(offset);
  80
  81        return lp3943_gpio_set_mode(lp3943_gpio, offset, LP3943_GPIO_IN);
  82}
  83
  84static int lp3943_get_gpio_in_status(struct lp3943_gpio *lp3943_gpio,
  85                                     struct gpio_chip *chip, unsigned offset)
  86{
  87        u8 addr, read;
  88        int err;
  89
  90        switch (offset) {
  91        case LP3943_GPIO1 ... LP3943_GPIO8:
  92                addr = LP3943_REG_GPIO_A;
  93                break;
  94        case LP3943_GPIO9 ... LP3943_GPIO16:
  95                addr = LP3943_REG_GPIO_B;
  96                offset = offset - 8;
  97                break;
  98        default:
  99                return -EINVAL;
 100        }
 101
 102        err = lp3943_read_byte(lp3943_gpio->lp3943, addr, &read);
 103        if (err)
 104                return err;
 105
 106        return !!(read & BIT(offset));
 107}
 108
 109static int lp3943_get_gpio_out_status(struct lp3943_gpio *lp3943_gpio,
 110                                      struct gpio_chip *chip, unsigned offset)
 111{
 112        struct lp3943 *lp3943 = lp3943_gpio->lp3943;
 113        const struct lp3943_reg_cfg *mux = lp3943->mux_cfg;
 114        u8 read;
 115        int err;
 116
 117        err = lp3943_read_byte(lp3943, mux[offset].reg, &read);
 118        if (err)
 119                return err;
 120
 121        read = (read & mux[offset].mask) >> mux[offset].shift;
 122
 123        if (read == LP3943_GPIO_OUT_HIGH)
 124                return 1;
 125        else if (read == LP3943_GPIO_OUT_LOW)
 126                return 0;
 127        else
 128                return -EINVAL;
 129}
 130
 131static int lp3943_gpio_get(struct gpio_chip *chip, unsigned offset)
 132{
 133        struct lp3943_gpio *lp3943_gpio = gpiochip_get_data(chip);
 134
 135        /*
 136         * Limitation:
 137         *   LP3943 doesn't have the GPIO direction register. It provides
 138         *   only input and output status registers.
 139         *   So, direction info is required to handle the 'get' operation.
 140         *   This variable is updated whenever the direction is changed and
 141         *   it is used here.
 142         */
 143
 144        if (lp3943_gpio->input_mask & BIT(offset))
 145                return lp3943_get_gpio_in_status(lp3943_gpio, chip, offset);
 146        else
 147                return lp3943_get_gpio_out_status(lp3943_gpio, chip, offset);
 148}
 149
 150static void lp3943_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 151{
 152        struct lp3943_gpio *lp3943_gpio = gpiochip_get_data(chip);
 153        u8 data;
 154
 155        if (value)
 156                data = LP3943_GPIO_OUT_HIGH;
 157        else
 158                data = LP3943_GPIO_OUT_LOW;
 159
 160        lp3943_gpio_set_mode(lp3943_gpio, offset, data);
 161}
 162
 163static int lp3943_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
 164                                        int value)
 165{
 166        struct lp3943_gpio *lp3943_gpio = gpiochip_get_data(chip);
 167
 168        lp3943_gpio_set(chip, offset, value);
 169        lp3943_gpio->input_mask &= ~BIT(offset);
 170
 171        return 0;
 172}
 173
 174static const struct gpio_chip lp3943_gpio_chip = {
 175        .label                  = "lp3943",
 176        .owner                  = THIS_MODULE,
 177        .request                = lp3943_gpio_request,
 178        .free                   = lp3943_gpio_free,
 179        .direction_input        = lp3943_gpio_direction_input,
 180        .get                    = lp3943_gpio_get,
 181        .direction_output       = lp3943_gpio_direction_output,
 182        .set                    = lp3943_gpio_set,
 183        .base                   = -1,
 184        .ngpio                  = LP3943_MAX_GPIO,
 185        .can_sleep              = 1,
 186};
 187
 188static int lp3943_gpio_probe(struct platform_device *pdev)
 189{
 190        struct lp3943 *lp3943 = dev_get_drvdata(pdev->dev.parent);
 191        struct lp3943_gpio *lp3943_gpio;
 192
 193        lp3943_gpio = devm_kzalloc(&pdev->dev, sizeof(*lp3943_gpio),
 194                                GFP_KERNEL);
 195        if (!lp3943_gpio)
 196                return -ENOMEM;
 197
 198        lp3943_gpio->lp3943 = lp3943;
 199        lp3943_gpio->chip = lp3943_gpio_chip;
 200        lp3943_gpio->chip.parent = &pdev->dev;
 201
 202        platform_set_drvdata(pdev, lp3943_gpio);
 203
 204        return devm_gpiochip_add_data(&pdev->dev, &lp3943_gpio->chip,
 205                                      lp3943_gpio);
 206}
 207
 208static const struct of_device_id lp3943_gpio_of_match[] = {
 209        { .compatible = "ti,lp3943-gpio", },
 210        { }
 211};
 212MODULE_DEVICE_TABLE(of, lp3943_gpio_of_match);
 213
 214static struct platform_driver lp3943_gpio_driver = {
 215        .probe = lp3943_gpio_probe,
 216        .driver = {
 217                .name = "lp3943-gpio",
 218                .of_match_table = lp3943_gpio_of_match,
 219        },
 220};
 221module_platform_driver(lp3943_gpio_driver);
 222
 223MODULE_DESCRIPTION("LP3943 GPIO driver");
 224MODULE_ALIAS("platform:lp3943-gpio");
 225MODULE_AUTHOR("Milo Kim");
 226MODULE_LICENSE("GPL");
 227