xref: /openbmc/linux/drivers/gpio/gpio-tps68470.c (revision 5a7adc6c)
1ca34b4f0SRajmohan Mani // SPDX-License-Identifier: GPL-2.0
2275b13a6SRajmohan Mani /*
3275b13a6SRajmohan Mani  * GPIO driver for TPS68470 PMIC
4275b13a6SRajmohan Mani  *
5275b13a6SRajmohan Mani  * Copyright (C) 2017 Intel Corporation
6275b13a6SRajmohan Mani  *
7275b13a6SRajmohan Mani  * Authors:
8275b13a6SRajmohan Mani  *	Antti Laakso <antti.laakso@intel.com>
9275b13a6SRajmohan Mani  *	Tianshu Qiu <tian.shu.qiu@intel.com>
10275b13a6SRajmohan Mani  *	Jian Xu Zheng <jian.xu.zheng@intel.com>
11275b13a6SRajmohan Mani  *	Yuning Pu <yuning.pu@intel.com>
12275b13a6SRajmohan Mani  */
13275b13a6SRajmohan Mani 
14275b13a6SRajmohan Mani #include <linux/gpio/driver.h>
15275b13a6SRajmohan Mani #include <linux/mfd/tps68470.h>
16275b13a6SRajmohan Mani #include <linux/module.h>
17275b13a6SRajmohan Mani #include <linux/platform_device.h>
18275b13a6SRajmohan Mani #include <linux/regmap.h>
19275b13a6SRajmohan Mani 
20275b13a6SRajmohan Mani #define TPS68470_N_LOGIC_OUTPUT	3
21275b13a6SRajmohan Mani #define TPS68470_N_REGULAR_GPIO	7
22275b13a6SRajmohan Mani #define TPS68470_N_GPIO	(TPS68470_N_LOGIC_OUTPUT + TPS68470_N_REGULAR_GPIO)
23275b13a6SRajmohan Mani 
24275b13a6SRajmohan Mani struct tps68470_gpio_data {
25275b13a6SRajmohan Mani 	struct regmap *tps68470_regmap;
26275b13a6SRajmohan Mani 	struct gpio_chip gc;
27275b13a6SRajmohan Mani };
28275b13a6SRajmohan Mani 
tps68470_gpio_get(struct gpio_chip * gc,unsigned int offset)29275b13a6SRajmohan Mani static int tps68470_gpio_get(struct gpio_chip *gc, unsigned int offset)
30275b13a6SRajmohan Mani {
31275b13a6SRajmohan Mani 	struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
32275b13a6SRajmohan Mani 	struct regmap *regmap = tps68470_gpio->tps68470_regmap;
33275b13a6SRajmohan Mani 	unsigned int reg = TPS68470_REG_GPDO;
34275b13a6SRajmohan Mani 	int val, ret;
35275b13a6SRajmohan Mani 
36275b13a6SRajmohan Mani 	if (offset >= TPS68470_N_REGULAR_GPIO) {
37275b13a6SRajmohan Mani 		offset -= TPS68470_N_REGULAR_GPIO;
38275b13a6SRajmohan Mani 		reg = TPS68470_REG_SGPO;
39275b13a6SRajmohan Mani 	}
40275b13a6SRajmohan Mani 
41275b13a6SRajmohan Mani 	ret = regmap_read(regmap, reg, &val);
42275b13a6SRajmohan Mani 	if (ret) {
43275b13a6SRajmohan Mani 		dev_err(tps68470_gpio->gc.parent, "reg 0x%x read failed\n",
44275b13a6SRajmohan Mani 			TPS68470_REG_SGPO);
45275b13a6SRajmohan Mani 		return ret;
46275b13a6SRajmohan Mani 	}
47275b13a6SRajmohan Mani 	return !!(val & BIT(offset));
48275b13a6SRajmohan Mani }
49275b13a6SRajmohan Mani 
tps68470_gpio_get_direction(struct gpio_chip * gc,unsigned int offset)50275b13a6SRajmohan Mani static int tps68470_gpio_get_direction(struct gpio_chip *gc,
51275b13a6SRajmohan Mani 				       unsigned int offset)
52275b13a6SRajmohan Mani {
53275b13a6SRajmohan Mani 	struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
54275b13a6SRajmohan Mani 	struct regmap *regmap = tps68470_gpio->tps68470_regmap;
55275b13a6SRajmohan Mani 	int val, ret;
56275b13a6SRajmohan Mani 
57275b13a6SRajmohan Mani 	/* rest are always outputs */
58275b13a6SRajmohan Mani 	if (offset >= TPS68470_N_REGULAR_GPIO)
59e42615ecSMatti Vaittinen 		return GPIO_LINE_DIRECTION_OUT;
60275b13a6SRajmohan Mani 
61275b13a6SRajmohan Mani 	ret = regmap_read(regmap, TPS68470_GPIO_CTL_REG_A(offset), &val);
62275b13a6SRajmohan Mani 	if (ret) {
63275b13a6SRajmohan Mani 		dev_err(tps68470_gpio->gc.parent, "reg 0x%x read failed\n",
64275b13a6SRajmohan Mani 			TPS68470_GPIO_CTL_REG_A(offset));
65275b13a6SRajmohan Mani 		return ret;
66275b13a6SRajmohan Mani 	}
67275b13a6SRajmohan Mani 
68275b13a6SRajmohan Mani 	val &= TPS68470_GPIO_MODE_MASK;
69e42615ecSMatti Vaittinen 	return val >= TPS68470_GPIO_MODE_OUT_CMOS ? GPIO_LINE_DIRECTION_OUT :
70e42615ecSMatti Vaittinen 						    GPIO_LINE_DIRECTION_IN;
71275b13a6SRajmohan Mani }
72275b13a6SRajmohan Mani 
tps68470_gpio_set(struct gpio_chip * gc,unsigned int offset,int value)73275b13a6SRajmohan Mani static void tps68470_gpio_set(struct gpio_chip *gc, unsigned int offset,
74275b13a6SRajmohan Mani 				int value)
75275b13a6SRajmohan Mani {
76275b13a6SRajmohan Mani 	struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
77275b13a6SRajmohan Mani 	struct regmap *regmap = tps68470_gpio->tps68470_regmap;
78275b13a6SRajmohan Mani 	unsigned int reg = TPS68470_REG_GPDO;
79275b13a6SRajmohan Mani 
80275b13a6SRajmohan Mani 	if (offset >= TPS68470_N_REGULAR_GPIO) {
81275b13a6SRajmohan Mani 		reg = TPS68470_REG_SGPO;
82275b13a6SRajmohan Mani 		offset -= TPS68470_N_REGULAR_GPIO;
83275b13a6SRajmohan Mani 	}
84275b13a6SRajmohan Mani 
85275b13a6SRajmohan Mani 	regmap_update_bits(regmap, reg, BIT(offset), value ? BIT(offset) : 0);
86275b13a6SRajmohan Mani }
87275b13a6SRajmohan Mani 
tps68470_gpio_output(struct gpio_chip * gc,unsigned int offset,int value)88275b13a6SRajmohan Mani static int tps68470_gpio_output(struct gpio_chip *gc, unsigned int offset,
89275b13a6SRajmohan Mani 				int value)
90275b13a6SRajmohan Mani {
91275b13a6SRajmohan Mani 	struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
92275b13a6SRajmohan Mani 	struct regmap *regmap = tps68470_gpio->tps68470_regmap;
93275b13a6SRajmohan Mani 
94*5a7adc6cSHans de Goede 	/* Set the initial value */
95*5a7adc6cSHans de Goede 	tps68470_gpio_set(gc, offset, value);
96*5a7adc6cSHans de Goede 
97275b13a6SRajmohan Mani 	/* rest are always outputs */
98275b13a6SRajmohan Mani 	if (offset >= TPS68470_N_REGULAR_GPIO)
99275b13a6SRajmohan Mani 		return 0;
100275b13a6SRajmohan Mani 
101275b13a6SRajmohan Mani 	return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset),
102275b13a6SRajmohan Mani 				 TPS68470_GPIO_MODE_MASK,
103275b13a6SRajmohan Mani 				 TPS68470_GPIO_MODE_OUT_CMOS);
104275b13a6SRajmohan Mani }
105275b13a6SRajmohan Mani 
tps68470_gpio_input(struct gpio_chip * gc,unsigned int offset)106275b13a6SRajmohan Mani static int tps68470_gpio_input(struct gpio_chip *gc, unsigned int offset)
107275b13a6SRajmohan Mani {
108275b13a6SRajmohan Mani 	struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
109275b13a6SRajmohan Mani 	struct regmap *regmap = tps68470_gpio->tps68470_regmap;
110275b13a6SRajmohan Mani 
111275b13a6SRajmohan Mani 	/* rest are always outputs */
112275b13a6SRajmohan Mani 	if (offset >= TPS68470_N_REGULAR_GPIO)
113275b13a6SRajmohan Mani 		return -EINVAL;
114275b13a6SRajmohan Mani 
115275b13a6SRajmohan Mani 	return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset),
116275b13a6SRajmohan Mani 				   TPS68470_GPIO_MODE_MASK, 0x00);
117275b13a6SRajmohan Mani }
118275b13a6SRajmohan Mani 
119275b13a6SRajmohan Mani static const char *tps68470_names[TPS68470_N_GPIO] = {
120275b13a6SRajmohan Mani 	"gpio.0", "gpio.1", "gpio.2", "gpio.3",
121275b13a6SRajmohan Mani 	"gpio.4", "gpio.5", "gpio.6",
122275b13a6SRajmohan Mani 	"s_enable", "s_idle", "s_resetn",
123275b13a6SRajmohan Mani };
124275b13a6SRajmohan Mani 
tps68470_gpio_probe(struct platform_device * pdev)125275b13a6SRajmohan Mani static int tps68470_gpio_probe(struct platform_device *pdev)
126275b13a6SRajmohan Mani {
127275b13a6SRajmohan Mani 	struct tps68470_gpio_data *tps68470_gpio;
128275b13a6SRajmohan Mani 
129275b13a6SRajmohan Mani 	tps68470_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps68470_gpio),
130275b13a6SRajmohan Mani 				     GFP_KERNEL);
131275b13a6SRajmohan Mani 	if (!tps68470_gpio)
132275b13a6SRajmohan Mani 		return -ENOMEM;
133275b13a6SRajmohan Mani 
134275b13a6SRajmohan Mani 	tps68470_gpio->tps68470_regmap = dev_get_drvdata(pdev->dev.parent);
135275b13a6SRajmohan Mani 	tps68470_gpio->gc.label = "tps68470-gpio";
136275b13a6SRajmohan Mani 	tps68470_gpio->gc.owner = THIS_MODULE;
137275b13a6SRajmohan Mani 	tps68470_gpio->gc.direction_input = tps68470_gpio_input;
138275b13a6SRajmohan Mani 	tps68470_gpio->gc.direction_output = tps68470_gpio_output;
139275b13a6SRajmohan Mani 	tps68470_gpio->gc.get = tps68470_gpio_get;
140275b13a6SRajmohan Mani 	tps68470_gpio->gc.get_direction = tps68470_gpio_get_direction;
141275b13a6SRajmohan Mani 	tps68470_gpio->gc.set = tps68470_gpio_set;
142275b13a6SRajmohan Mani 	tps68470_gpio->gc.can_sleep = true;
143275b13a6SRajmohan Mani 	tps68470_gpio->gc.names = tps68470_names;
144275b13a6SRajmohan Mani 	tps68470_gpio->gc.ngpio = TPS68470_N_GPIO;
145275b13a6SRajmohan Mani 	tps68470_gpio->gc.base = -1;
146275b13a6SRajmohan Mani 	tps68470_gpio->gc.parent = &pdev->dev;
147275b13a6SRajmohan Mani 
14891d594b2SAlexandru Ardelean 	return devm_gpiochip_add_data(&pdev->dev, &tps68470_gpio->gc, tps68470_gpio);
149275b13a6SRajmohan Mani }
150275b13a6SRajmohan Mani 
151275b13a6SRajmohan Mani static struct platform_driver tps68470_gpio_driver = {
152275b13a6SRajmohan Mani 	.driver = {
153275b13a6SRajmohan Mani 		   .name = "tps68470-gpio",
154275b13a6SRajmohan Mani 	},
155275b13a6SRajmohan Mani 	.probe = tps68470_gpio_probe,
156275b13a6SRajmohan Mani };
157a1ce76e8SHans de Goede module_platform_driver(tps68470_gpio_driver);
158275b13a6SRajmohan Mani 
159a1ce76e8SHans de Goede MODULE_ALIAS("platform:tps68470-gpio");
160a1ce76e8SHans de Goede MODULE_DESCRIPTION("GPIO driver for TPS68470 PMIC");
161a1ce76e8SHans de Goede MODULE_LICENSE("GPL v2");
162