File Index
Files and directories
Sign in
FILE

gpio-tps65218.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpio/gpio-tps65218.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Copyright 2015 Verifone Int.
  4 *
  5 * Author: Nicolas Saenz Julienne <nicolassaenzj@gmail.com>
  6 *
  7 * This driver is based on the gpio-tps65912 implementation.
  8 */
  9
 10#include <linux/kernel.h>
 11#include <linux/module.h>
 12#include <linux/errno.h>
 13#include <linux/gpio/driver.h>
 14#include <linux/platform_device.h>
 15#include <linux/regmap.h>
 16#include <linux/mfd/tps65218.h>
 17
 18struct tps65218_gpio {
 19	struct tps65218 *tps65218;
 20	struct gpio_chip gpio_chip;
 21};
 22
 23static int tps65218_gpio_get(struct gpio_chip *gc, unsigned offset)
 24{
 25	struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc);
 26	struct tps65218 *tps65218 = tps65218_gpio->tps65218;
 27	unsigned int val;
 28	int ret;
 29
 30	ret = regmap_read(tps65218->regmap, TPS65218_REG_ENABLE2, &val);
 31	if (ret)
 32		return ret;
 33
 34	return !!(val & (TPS65218_ENABLE2_GPIO1 << offset));
 35}
 36
 37static int tps65218_gpio_set(struct gpio_chip *gc, unsigned int offset,
 38			     int value)
 39{
 40	struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc);
 41	struct tps65218 *tps65218 = tps65218_gpio->tps65218;
 42
 43	if (value)
 44		return tps65218_set_bits(tps65218, TPS65218_REG_ENABLE2,
 45					 TPS65218_ENABLE2_GPIO1 << offset,
 46					 TPS65218_ENABLE2_GPIO1 << offset,
 47					 TPS65218_PROTECT_L1);
 48
 49	return tps65218_clear_bits(tps65218, TPS65218_REG_ENABLE2,
 50				   TPS65218_ENABLE2_GPIO1 << offset,
 51				   TPS65218_PROTECT_L1);
 52}
 53
 54static int tps65218_gpio_output(struct gpio_chip *gc, unsigned offset,
 55				int value)
 56{
 57	/* Only drives GPOs */
 58	return tps65218_gpio_set(gc, offset, value);
 59}
 60
 61static int tps65218_gpio_request(struct gpio_chip *gc, unsigned offset)
 62{
 63	struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc);
 64	struct tps65218 *tps65218 = tps65218_gpio->tps65218;
 65	int ret;
 66
 67	if (gpiochip_line_is_open_source(gc, offset)) {
 68		dev_err(gc->parent, "can't work as open source\n");
 69		return -EINVAL;
 70	}
 71
 72	switch (offset) {
 73	case 0:
 74		if (!gpiochip_line_is_open_drain(gc, offset)) {
 75			dev_err(gc->parent, "GPO1 works only as open drain\n");
 76			return -EINVAL;
 77		}
 78
 79		/* Disable sequencer for GPO1 */
 80		ret = tps65218_clear_bits(tps65218, TPS65218_REG_SEQ7,
 81					  TPS65218_SEQ7_GPO1_SEQ_MASK,
 82					  TPS65218_PROTECT_L1);
 83		if (ret)
 84			return ret;
 85
 86		/* Setup GPO1 */
 87		ret = tps65218_clear_bits(tps65218, TPS65218_REG_CONFIG1,
 88					  TPS65218_CONFIG1_IO1_SEL,
 89					  TPS65218_PROTECT_L1);
 90		if (ret)
 91			return ret;
 92
 93		break;
 94	case 1:
 95		/* Setup GPO2 */
 96		ret = tps65218_clear_bits(tps65218, TPS65218_REG_CONFIG1,
 97					  TPS65218_CONFIG1_IO1_SEL,
 98					  TPS65218_PROTECT_L1);
 99		if (ret)
100			return ret;
101
102		break;
103
104	case 2:
105		if (!gpiochip_line_is_open_drain(gc, offset)) {
106			dev_err(gc->parent, "GPO3 works only as open drain\n");
107			return -EINVAL;
108		}
109
110		/* Disable sequencer for GPO3 */
111		ret = tps65218_clear_bits(tps65218, TPS65218_REG_SEQ7,
112					  TPS65218_SEQ7_GPO3_SEQ_MASK,
113					  TPS65218_PROTECT_L1);
114		if (ret)
115			return ret;
116
117		/* Setup GPO3 */
118		ret = tps65218_clear_bits(tps65218, TPS65218_REG_CONFIG2,
119					  TPS65218_CONFIG2_DC12_RST,
120					  TPS65218_PROTECT_L1);
121		if (ret)
122			return ret;
123
124		break;
125	default:
126		return -EINVAL;
127	}
128
129	return 0;
130}
131
132static int tps65218_gpio_set_config(struct gpio_chip *gc, unsigned offset,
133				    unsigned long config)
134{
135	struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc);
136	struct tps65218 *tps65218 = tps65218_gpio->tps65218;
137	enum pin_config_param param = pinconf_to_config_param(config);
138
139	switch (offset) {
140	case 0:
141	case 2:
142		/* GPO1 is hardwired to be open drain */
143		if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN)
144			return 0;
145		return -ENOTSUPP;
146	case 1:
147		/* GPO2 is push-pull by default, can be set as open drain. */
148		if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN)
149			return tps65218_clear_bits(tps65218,
150						   TPS65218_REG_CONFIG1,
151						   TPS65218_CONFIG1_GPO2_BUF,
152						   TPS65218_PROTECT_L1);
153		if (param == PIN_CONFIG_DRIVE_PUSH_PULL)
154			return tps65218_set_bits(tps65218,
155						 TPS65218_REG_CONFIG1,
156						 TPS65218_CONFIG1_GPO2_BUF,
157						 TPS65218_CONFIG1_GPO2_BUF,
158						 TPS65218_PROTECT_L1);
159		return -ENOTSUPP;
160	default:
161		break;
162	}
163	return -ENOTSUPP;
164}
165
166static const struct gpio_chip template_chip = {
167	.label			= "gpio-tps65218",
168	.owner			= THIS_MODULE,
169	.request		= tps65218_gpio_request,
170	.direction_output	= tps65218_gpio_output,
171	.get			= tps65218_gpio_get,
172	.set			= tps65218_gpio_set,
173	.set_config		= tps65218_gpio_set_config,
174	.can_sleep		= true,
175	.ngpio			= 3,
176	.base			= -1,
177};
178
179static int tps65218_gpio_probe(struct platform_device *pdev)
180{
181	struct tps65218 *tps65218 = dev_get_drvdata(pdev->dev.parent);
182	struct tps65218_gpio *tps65218_gpio;
183
184	tps65218_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps65218_gpio),
185				     GFP_KERNEL);
186	if (!tps65218_gpio)
187		return -ENOMEM;
188
189	tps65218_gpio->tps65218 = tps65218;
190	tps65218_gpio->gpio_chip = template_chip;
191	tps65218_gpio->gpio_chip.parent = &pdev->dev;
192
193	return devm_gpiochip_add_data(&pdev->dev, &tps65218_gpio->gpio_chip,
194				      tps65218_gpio);
195}
196
197static const struct of_device_id tps65218_dt_match[] = {
198	{ .compatible = "ti,tps65218-gpio" },
199	{  }
200};
201MODULE_DEVICE_TABLE(of, tps65218_dt_match);
202
203static const struct platform_device_id tps65218_gpio_id_table[] = {
204	{ "tps65218-gpio", },
205	{ /* sentinel */ }
206};
207MODULE_DEVICE_TABLE(platform, tps65218_gpio_id_table);
208
209static struct platform_driver tps65218_gpio_driver = {
210	.driver = {
211		.name = "tps65218-gpio",
212		.of_match_table = tps65218_dt_match,
213	},
214	.probe = tps65218_gpio_probe,
215	.id_table = tps65218_gpio_id_table,
216};
217
218module_platform_driver(tps65218_gpio_driver);
219
220MODULE_AUTHOR("Nicolas Saenz Julienne <nicolassaenzj@gmail.com>");
221MODULE_DESCRIPTION("GPO interface for TPS65218 PMICs");
222MODULE_LICENSE("GPL v2");
~/ Read-only file preview.