linux/drivers/gpio/gpio-tps68470.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * GPIO driver for TPS68470 PMIC
   4 *
   5 * Copyright (C) 2017 Intel Corporation
   6 *
   7 * Authors:
   8 *      Antti Laakso <antti.laakso@intel.com>
   9 *      Tianshu Qiu <tian.shu.qiu@intel.com>
  10 *      Jian Xu Zheng <jian.xu.zheng@intel.com>
  11 *      Yuning Pu <yuning.pu@intel.com>
  12 */
  13
  14#include <linux/gpio/driver.h>
  15#include <linux/mfd/tps68470.h>
  16#include <linux/module.h>
  17#include <linux/platform_device.h>
  18#include <linux/regmap.h>
  19
  20#define TPS68470_N_LOGIC_OUTPUT 3
  21#define TPS68470_N_REGULAR_GPIO 7
  22#define TPS68470_N_GPIO (TPS68470_N_LOGIC_OUTPUT + TPS68470_N_REGULAR_GPIO)
  23
  24struct tps68470_gpio_data {
  25        struct regmap *tps68470_regmap;
  26        struct gpio_chip gc;
  27};
  28
  29static int tps68470_gpio_get(struct gpio_chip *gc, unsigned int offset)
  30{
  31        struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
  32        struct regmap *regmap = tps68470_gpio->tps68470_regmap;
  33        unsigned int reg = TPS68470_REG_GPDO;
  34        int val, ret;
  35
  36        if (offset >= TPS68470_N_REGULAR_GPIO) {
  37                offset -= TPS68470_N_REGULAR_GPIO;
  38                reg = TPS68470_REG_SGPO;
  39        }
  40
  41        ret = regmap_read(regmap, reg, &val);
  42        if (ret) {
  43                dev_err(tps68470_gpio->gc.parent, "reg 0x%x read failed\n",
  44                        TPS68470_REG_SGPO);
  45                return ret;
  46        }
  47        return !!(val & BIT(offset));
  48}
  49
  50static int tps68470_gpio_get_direction(struct gpio_chip *gc,
  51                                       unsigned int offset)
  52{
  53        struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
  54        struct regmap *regmap = tps68470_gpio->tps68470_regmap;
  55        int val, ret;
  56
  57        /* rest are always outputs */
  58        if (offset >= TPS68470_N_REGULAR_GPIO)
  59                return GPIO_LINE_DIRECTION_OUT;
  60
  61        ret = regmap_read(regmap, TPS68470_GPIO_CTL_REG_A(offset), &val);
  62        if (ret) {
  63                dev_err(tps68470_gpio->gc.parent, "reg 0x%x read failed\n",
  64                        TPS68470_GPIO_CTL_REG_A(offset));
  65                return ret;
  66        }
  67
  68        val &= TPS68470_GPIO_MODE_MASK;
  69        return val >= TPS68470_GPIO_MODE_OUT_CMOS ? GPIO_LINE_DIRECTION_OUT :
  70                                                    GPIO_LINE_DIRECTION_IN;
  71}
  72
  73static void tps68470_gpio_set(struct gpio_chip *gc, unsigned int offset,
  74                                int value)
  75{
  76        struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
  77        struct regmap *regmap = tps68470_gpio->tps68470_regmap;
  78        unsigned int reg = TPS68470_REG_GPDO;
  79
  80        if (offset >= TPS68470_N_REGULAR_GPIO) {
  81                reg = TPS68470_REG_SGPO;
  82                offset -= TPS68470_N_REGULAR_GPIO;
  83        }
  84
  85        regmap_update_bits(regmap, reg, BIT(offset), value ? BIT(offset) : 0);
  86}
  87
  88static int tps68470_gpio_output(struct gpio_chip *gc, unsigned int offset,
  89                                int value)
  90{
  91        struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
  92        struct regmap *regmap = tps68470_gpio->tps68470_regmap;
  93
  94        /* rest are always outputs */
  95        if (offset >= TPS68470_N_REGULAR_GPIO)
  96                return 0;
  97
  98        /* Set the initial value */
  99        tps68470_gpio_set(gc, offset, value);
 100
 101        return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset),
 102                                 TPS68470_GPIO_MODE_MASK,
 103                                 TPS68470_GPIO_MODE_OUT_CMOS);
 104}
 105
 106static int tps68470_gpio_input(struct gpio_chip *gc, unsigned int offset)
 107{
 108        struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
 109        struct regmap *regmap = tps68470_gpio->tps68470_regmap;
 110
 111        /* rest are always outputs */
 112        if (offset >= TPS68470_N_REGULAR_GPIO)
 113                return -EINVAL;
 114
 115        return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset),
 116                                   TPS68470_GPIO_MODE_MASK, 0x00);
 117}
 118
 119static const char *tps68470_names[TPS68470_N_GPIO] = {
 120        "gpio.0", "gpio.1", "gpio.2", "gpio.3",
 121        "gpio.4", "gpio.5", "gpio.6",
 122        "s_enable", "s_idle", "s_resetn",
 123};
 124
 125static int tps68470_gpio_probe(struct platform_device *pdev)
 126{
 127        struct tps68470_gpio_data *tps68470_gpio;
 128        int ret;
 129
 130        tps68470_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps68470_gpio),
 131                                     GFP_KERNEL);
 132        if (!tps68470_gpio)
 133                return -ENOMEM;
 134
 135        tps68470_gpio->tps68470_regmap = dev_get_drvdata(pdev->dev.parent);
 136        tps68470_gpio->gc.label = "tps68470-gpio";
 137        tps68470_gpio->gc.owner = THIS_MODULE;
 138        tps68470_gpio->gc.direction_input = tps68470_gpio_input;
 139        tps68470_gpio->gc.direction_output = tps68470_gpio_output;
 140        tps68470_gpio->gc.get = tps68470_gpio_get;
 141        tps68470_gpio->gc.get_direction = tps68470_gpio_get_direction;
 142        tps68470_gpio->gc.set = tps68470_gpio_set;
 143        tps68470_gpio->gc.can_sleep = true;
 144        tps68470_gpio->gc.names = tps68470_names;
 145        tps68470_gpio->gc.ngpio = TPS68470_N_GPIO;
 146        tps68470_gpio->gc.base = -1;
 147        tps68470_gpio->gc.parent = &pdev->dev;
 148
 149        ret = devm_gpiochip_add_data(&pdev->dev, &tps68470_gpio->gc,
 150                                     tps68470_gpio);
 151        if (ret < 0) {
 152                dev_err(&pdev->dev, "Failed to register gpio_chip: %d\n", ret);
 153                return ret;
 154        }
 155
 156        platform_set_drvdata(pdev, tps68470_gpio);
 157
 158        return ret;
 159}
 160
 161static struct platform_driver tps68470_gpio_driver = {
 162        .driver = {
 163                   .name = "tps68470-gpio",
 164        },
 165        .probe = tps68470_gpio_probe,
 166};
 167
 168builtin_platform_driver(tps68470_gpio_driver)
 169