xref: /openbmc/linux/drivers/gpio/gpio-tps68470.c (revision 275b13a6)
1275b13a6SRajmohan Mani /*
2275b13a6SRajmohan Mani  * GPIO driver for TPS68470 PMIC
3275b13a6SRajmohan Mani  *
4275b13a6SRajmohan Mani  * Copyright (C) 2017 Intel Corporation
5275b13a6SRajmohan Mani  *
6275b13a6SRajmohan Mani  * Authors:
7275b13a6SRajmohan Mani  *	Antti Laakso <antti.laakso@intel.com>
8275b13a6SRajmohan Mani  *	Tianshu Qiu <tian.shu.qiu@intel.com>
9275b13a6SRajmohan Mani  *	Jian Xu Zheng <jian.xu.zheng@intel.com>
10275b13a6SRajmohan Mani  *	Yuning Pu <yuning.pu@intel.com>
11275b13a6SRajmohan Mani  *
12275b13a6SRajmohan Mani  * This program is free software; you can redistribute it and/or
13275b13a6SRajmohan Mani  * modify it under the terms of the GNU General Public License as
14275b13a6SRajmohan Mani  * published by the Free Software Foundation version 2.
15275b13a6SRajmohan Mani  *
16275b13a6SRajmohan Mani  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
17275b13a6SRajmohan Mani  * kind, whether express or implied; without even the implied warranty
18275b13a6SRajmohan Mani  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19275b13a6SRajmohan Mani  * GNU General Public License for more details.
20275b13a6SRajmohan Mani  */
21275b13a6SRajmohan Mani 
22275b13a6SRajmohan Mani #include <linux/gpio/driver.h>
23275b13a6SRajmohan Mani #include <linux/mfd/tps68470.h>
24275b13a6SRajmohan Mani #include <linux/module.h>
25275b13a6SRajmohan Mani #include <linux/platform_device.h>
26275b13a6SRajmohan Mani #include <linux/regmap.h>
27275b13a6SRajmohan Mani 
28275b13a6SRajmohan Mani #define TPS68470_N_LOGIC_OUTPUT	3
29275b13a6SRajmohan Mani #define TPS68470_N_REGULAR_GPIO	7
30275b13a6SRajmohan Mani #define TPS68470_N_GPIO	(TPS68470_N_LOGIC_OUTPUT + TPS68470_N_REGULAR_GPIO)
31275b13a6SRajmohan Mani 
32275b13a6SRajmohan Mani struct tps68470_gpio_data {
33275b13a6SRajmohan Mani 	struct regmap *tps68470_regmap;
34275b13a6SRajmohan Mani 	struct gpio_chip gc;
35275b13a6SRajmohan Mani };
36275b13a6SRajmohan Mani 
37275b13a6SRajmohan Mani static int tps68470_gpio_get(struct gpio_chip *gc, unsigned int offset)
38275b13a6SRajmohan Mani {
39275b13a6SRajmohan Mani 	struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
40275b13a6SRajmohan Mani 	struct regmap *regmap = tps68470_gpio->tps68470_regmap;
41275b13a6SRajmohan Mani 	unsigned int reg = TPS68470_REG_GPDO;
42275b13a6SRajmohan Mani 	int val, ret;
43275b13a6SRajmohan Mani 
44275b13a6SRajmohan Mani 	if (offset >= TPS68470_N_REGULAR_GPIO) {
45275b13a6SRajmohan Mani 		offset -= TPS68470_N_REGULAR_GPIO;
46275b13a6SRajmohan Mani 		reg = TPS68470_REG_SGPO;
47275b13a6SRajmohan Mani 	}
48275b13a6SRajmohan Mani 
49275b13a6SRajmohan Mani 	ret = regmap_read(regmap, reg, &val);
50275b13a6SRajmohan Mani 	if (ret) {
51275b13a6SRajmohan Mani 		dev_err(tps68470_gpio->gc.parent, "reg 0x%x read failed\n",
52275b13a6SRajmohan Mani 			TPS68470_REG_SGPO);
53275b13a6SRajmohan Mani 		return ret;
54275b13a6SRajmohan Mani 	}
55275b13a6SRajmohan Mani 	return !!(val & BIT(offset));
56275b13a6SRajmohan Mani }
57275b13a6SRajmohan Mani 
58275b13a6SRajmohan Mani /* Return 0 if output, 1 if input */
59275b13a6SRajmohan Mani static int tps68470_gpio_get_direction(struct gpio_chip *gc,
60275b13a6SRajmohan Mani 				       unsigned int offset)
61275b13a6SRajmohan Mani {
62275b13a6SRajmohan Mani 	struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
63275b13a6SRajmohan Mani 	struct regmap *regmap = tps68470_gpio->tps68470_regmap;
64275b13a6SRajmohan Mani 	int val, ret;
65275b13a6SRajmohan Mani 
66275b13a6SRajmohan Mani 	/* rest are always outputs */
67275b13a6SRajmohan Mani 	if (offset >= TPS68470_N_REGULAR_GPIO)
68275b13a6SRajmohan Mani 		return 0;
69275b13a6SRajmohan Mani 
70275b13a6SRajmohan Mani 	ret = regmap_read(regmap, TPS68470_GPIO_CTL_REG_A(offset), &val);
71275b13a6SRajmohan Mani 	if (ret) {
72275b13a6SRajmohan Mani 		dev_err(tps68470_gpio->gc.parent, "reg 0x%x read failed\n",
73275b13a6SRajmohan Mani 			TPS68470_GPIO_CTL_REG_A(offset));
74275b13a6SRajmohan Mani 		return ret;
75275b13a6SRajmohan Mani 	}
76275b13a6SRajmohan Mani 
77275b13a6SRajmohan Mani 	val &= TPS68470_GPIO_MODE_MASK;
78275b13a6SRajmohan Mani 	return val >= TPS68470_GPIO_MODE_OUT_CMOS ? 0 : 1;
79275b13a6SRajmohan Mani }
80275b13a6SRajmohan Mani 
81275b13a6SRajmohan Mani static void tps68470_gpio_set(struct gpio_chip *gc, unsigned int offset,
82275b13a6SRajmohan Mani 				int value)
83275b13a6SRajmohan Mani {
84275b13a6SRajmohan Mani 	struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
85275b13a6SRajmohan Mani 	struct regmap *regmap = tps68470_gpio->tps68470_regmap;
86275b13a6SRajmohan Mani 	unsigned int reg = TPS68470_REG_GPDO;
87275b13a6SRajmohan Mani 
88275b13a6SRajmohan Mani 	if (offset >= TPS68470_N_REGULAR_GPIO) {
89275b13a6SRajmohan Mani 		reg = TPS68470_REG_SGPO;
90275b13a6SRajmohan Mani 		offset -= TPS68470_N_REGULAR_GPIO;
91275b13a6SRajmohan Mani 	}
92275b13a6SRajmohan Mani 
93275b13a6SRajmohan Mani 	regmap_update_bits(regmap, reg, BIT(offset), value ? BIT(offset) : 0);
94275b13a6SRajmohan Mani }
95275b13a6SRajmohan Mani 
96275b13a6SRajmohan Mani static int tps68470_gpio_output(struct gpio_chip *gc, unsigned int offset,
97275b13a6SRajmohan Mani 				int value)
98275b13a6SRajmohan Mani {
99275b13a6SRajmohan Mani 	struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
100275b13a6SRajmohan Mani 	struct regmap *regmap = tps68470_gpio->tps68470_regmap;
101275b13a6SRajmohan Mani 
102275b13a6SRajmohan Mani 	/* rest are always outputs */
103275b13a6SRajmohan Mani 	if (offset >= TPS68470_N_REGULAR_GPIO)
104275b13a6SRajmohan Mani 		return 0;
105275b13a6SRajmohan Mani 
106275b13a6SRajmohan Mani 	/* Set the initial value */
107275b13a6SRajmohan Mani 	tps68470_gpio_set(gc, offset, value);
108275b13a6SRajmohan Mani 
109275b13a6SRajmohan Mani 	return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset),
110275b13a6SRajmohan Mani 				 TPS68470_GPIO_MODE_MASK,
111275b13a6SRajmohan Mani 				 TPS68470_GPIO_MODE_OUT_CMOS);
112275b13a6SRajmohan Mani }
113275b13a6SRajmohan Mani 
114275b13a6SRajmohan Mani static int tps68470_gpio_input(struct gpio_chip *gc, unsigned int offset)
115275b13a6SRajmohan Mani {
116275b13a6SRajmohan Mani 	struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
117275b13a6SRajmohan Mani 	struct regmap *regmap = tps68470_gpio->tps68470_regmap;
118275b13a6SRajmohan Mani 
119275b13a6SRajmohan Mani 	/* rest are always outputs */
120275b13a6SRajmohan Mani 	if (offset >= TPS68470_N_REGULAR_GPIO)
121275b13a6SRajmohan Mani 		return -EINVAL;
122275b13a6SRajmohan Mani 
123275b13a6SRajmohan Mani 	return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset),
124275b13a6SRajmohan Mani 				   TPS68470_GPIO_MODE_MASK, 0x00);
125275b13a6SRajmohan Mani }
126275b13a6SRajmohan Mani 
127275b13a6SRajmohan Mani static const char *tps68470_names[TPS68470_N_GPIO] = {
128275b13a6SRajmohan Mani 	"gpio.0", "gpio.1", "gpio.2", "gpio.3",
129275b13a6SRajmohan Mani 	"gpio.4", "gpio.5", "gpio.6",
130275b13a6SRajmohan Mani 	"s_enable", "s_idle", "s_resetn",
131275b13a6SRajmohan Mani };
132275b13a6SRajmohan Mani 
133275b13a6SRajmohan Mani static int tps68470_gpio_probe(struct platform_device *pdev)
134275b13a6SRajmohan Mani {
135275b13a6SRajmohan Mani 	struct tps68470_gpio_data *tps68470_gpio;
136275b13a6SRajmohan Mani 	int ret;
137275b13a6SRajmohan Mani 
138275b13a6SRajmohan Mani 	tps68470_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps68470_gpio),
139275b13a6SRajmohan Mani 				     GFP_KERNEL);
140275b13a6SRajmohan Mani 	if (!tps68470_gpio)
141275b13a6SRajmohan Mani 		return -ENOMEM;
142275b13a6SRajmohan Mani 
143275b13a6SRajmohan Mani 	tps68470_gpio->tps68470_regmap = dev_get_drvdata(pdev->dev.parent);
144275b13a6SRajmohan Mani 	tps68470_gpio->gc.label = "tps68470-gpio";
145275b13a6SRajmohan Mani 	tps68470_gpio->gc.owner = THIS_MODULE;
146275b13a6SRajmohan Mani 	tps68470_gpio->gc.direction_input = tps68470_gpio_input;
147275b13a6SRajmohan Mani 	tps68470_gpio->gc.direction_output = tps68470_gpio_output;
148275b13a6SRajmohan Mani 	tps68470_gpio->gc.get = tps68470_gpio_get;
149275b13a6SRajmohan Mani 	tps68470_gpio->gc.get_direction = tps68470_gpio_get_direction;
150275b13a6SRajmohan Mani 	tps68470_gpio->gc.set = tps68470_gpio_set;
151275b13a6SRajmohan Mani 	tps68470_gpio->gc.can_sleep = true;
152275b13a6SRajmohan Mani 	tps68470_gpio->gc.names = tps68470_names;
153275b13a6SRajmohan Mani 	tps68470_gpio->gc.ngpio = TPS68470_N_GPIO;
154275b13a6SRajmohan Mani 	tps68470_gpio->gc.base = -1;
155275b13a6SRajmohan Mani 	tps68470_gpio->gc.parent = &pdev->dev;
156275b13a6SRajmohan Mani 
157275b13a6SRajmohan Mani 	ret = devm_gpiochip_add_data(&pdev->dev, &tps68470_gpio->gc,
158275b13a6SRajmohan Mani 				     tps68470_gpio);
159275b13a6SRajmohan Mani 	if (ret < 0) {
160275b13a6SRajmohan Mani 		dev_err(&pdev->dev, "Failed to register gpio_chip: %d\n", ret);
161275b13a6SRajmohan Mani 		return ret;
162275b13a6SRajmohan Mani 	}
163275b13a6SRajmohan Mani 
164275b13a6SRajmohan Mani 	platform_set_drvdata(pdev, tps68470_gpio);
165275b13a6SRajmohan Mani 
166275b13a6SRajmohan Mani 	return ret;
167275b13a6SRajmohan Mani }
168275b13a6SRajmohan Mani 
169275b13a6SRajmohan Mani static struct platform_driver tps68470_gpio_driver = {
170275b13a6SRajmohan Mani 	.driver = {
171275b13a6SRajmohan Mani 		   .name = "tps68470-gpio",
172275b13a6SRajmohan Mani 	},
173275b13a6SRajmohan Mani 	.probe = tps68470_gpio_probe,
174275b13a6SRajmohan Mani };
175275b13a6SRajmohan Mani 
176275b13a6SRajmohan Mani builtin_platform_driver(tps68470_gpio_driver)
177