162 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * GPIO driver for TPS68470 PMIC4 *5 * Copyright (C) 2017 Intel Corporation6 *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 321#define TPS68470_N_REGULAR_GPIO 722#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 /* Set the initial value */95 tps68470_gpio_set(gc, offset, value);96 97 /* rest are always outputs */98 if (offset >= TPS68470_N_REGULAR_GPIO)99 return 0;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 129 tps68470_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps68470_gpio),130 GFP_KERNEL);131 if (!tps68470_gpio)132 return -ENOMEM;133 134 tps68470_gpio->tps68470_regmap = dev_get_drvdata(pdev->dev.parent);135 tps68470_gpio->gc.label = "tps68470-gpio";136 tps68470_gpio->gc.owner = THIS_MODULE;137 tps68470_gpio->gc.direction_input = tps68470_gpio_input;138 tps68470_gpio->gc.direction_output = tps68470_gpio_output;139 tps68470_gpio->gc.get = tps68470_gpio_get;140 tps68470_gpio->gc.get_direction = tps68470_gpio_get_direction;141 tps68470_gpio->gc.set = tps68470_gpio_set;142 tps68470_gpio->gc.can_sleep = true;143 tps68470_gpio->gc.names = tps68470_names;144 tps68470_gpio->gc.ngpio = TPS68470_N_GPIO;145 tps68470_gpio->gc.base = -1;146 tps68470_gpio->gc.parent = &pdev->dev;147 148 return devm_gpiochip_add_data(&pdev->dev, &tps68470_gpio->gc, tps68470_gpio);149}150 151static struct platform_driver tps68470_gpio_driver = {152 .driver = {153 .name = "tps68470-gpio",154 },155 .probe = tps68470_gpio_probe,156};157module_platform_driver(tps68470_gpio_driver);158 159MODULE_ALIAS("platform:tps68470-gpio");160MODULE_DESCRIPTION("GPIO driver for TPS68470 PMIC");161MODULE_LICENSE("GPL v2");162