xref: /openbmc/linux/drivers/gpio/gpio-ts4900.c (revision e91d0f05)
187ba5badSKris Bahnsen // SPDX-License-Identifier: GPL-2.0
29c668632SLucile Quirion /*
39c668632SLucile Quirion  * Digital I/O driver for Technologic Systems I2C FPGA Core
49c668632SLucile Quirion  *
503fe0035SMark Featherston  * Copyright (C) 2015, 2018 Technologic Systems
69c668632SLucile Quirion  * Copyright (C) 2016 Savoir-Faire Linux
79c668632SLucile Quirion  */
89c668632SLucile Quirion 
99c668632SLucile Quirion #include <linux/gpio/driver.h>
109c668632SLucile Quirion #include <linux/i2c.h>
11*e91d0f05SRob Herring #include <linux/of.h>
129c668632SLucile Quirion #include <linux/module.h>
139c668632SLucile Quirion #include <linux/regmap.h>
149c668632SLucile Quirion 
159c668632SLucile Quirion #define DEFAULT_PIN_NUMBER	32
169c668632SLucile Quirion /*
179c668632SLucile Quirion  * Register bits used by the GPIO device
189c668632SLucile Quirion  * Some boards, such as TS-7970 do not have a separate input bit
199c668632SLucile Quirion  */
209c668632SLucile Quirion #define TS4900_GPIO_OE		0x01
219c668632SLucile Quirion #define TS4900_GPIO_OUT		0x02
229c668632SLucile Quirion #define TS4900_GPIO_IN		0x04
239c668632SLucile Quirion #define TS7970_GPIO_IN		0x02
249c668632SLucile Quirion 
259c668632SLucile Quirion struct ts4900_gpio_priv {
269c668632SLucile Quirion 	struct regmap *regmap;
279c668632SLucile Quirion 	struct gpio_chip gpio_chip;
289c668632SLucile Quirion 	unsigned int input_bit;
299c668632SLucile Quirion };
309c668632SLucile Quirion 
ts4900_gpio_get_direction(struct gpio_chip * chip,unsigned int offset)319c668632SLucile Quirion static int ts4900_gpio_get_direction(struct gpio_chip *chip,
329c668632SLucile Quirion 				     unsigned int offset)
339c668632SLucile Quirion {
349c668632SLucile Quirion 	struct ts4900_gpio_priv *priv = gpiochip_get_data(chip);
359c668632SLucile Quirion 	unsigned int reg;
369c668632SLucile Quirion 
379c668632SLucile Quirion 	regmap_read(priv->regmap, offset, &reg);
389c668632SLucile Quirion 
39e42615ecSMatti Vaittinen 	if (reg & TS4900_GPIO_OE)
40e42615ecSMatti Vaittinen 		return GPIO_LINE_DIRECTION_OUT;
41e42615ecSMatti Vaittinen 
42e42615ecSMatti Vaittinen 	return GPIO_LINE_DIRECTION_IN;
439c668632SLucile Quirion }
449c668632SLucile Quirion 
ts4900_gpio_direction_input(struct gpio_chip * chip,unsigned int offset)459c668632SLucile Quirion static int ts4900_gpio_direction_input(struct gpio_chip *chip,
469c668632SLucile Quirion 				       unsigned int offset)
479c668632SLucile Quirion {
489c668632SLucile Quirion 	struct ts4900_gpio_priv *priv = gpiochip_get_data(chip);
499c668632SLucile Quirion 
50576892a8SKris Bahnsen 	/*
51576892a8SKris Bahnsen 	 * Only clear the OE bit here, requires a RMW. Prevents a potential issue
52576892a8SKris Bahnsen 	 * with OE and DAT getting to the physical pin at different times.
539c668632SLucile Quirion 	 */
5403fe0035SMark Featherston 	return regmap_update_bits(priv->regmap, offset, TS4900_GPIO_OE, 0);
559c668632SLucile Quirion }
569c668632SLucile Quirion 
ts4900_gpio_direction_output(struct gpio_chip * chip,unsigned int offset,int value)579c668632SLucile Quirion static int ts4900_gpio_direction_output(struct gpio_chip *chip,
589c668632SLucile Quirion 					unsigned int offset, int value)
599c668632SLucile Quirion {
609c668632SLucile Quirion 	struct ts4900_gpio_priv *priv = gpiochip_get_data(chip);
6103fe0035SMark Featherston 	unsigned int reg;
629c668632SLucile Quirion 	int ret;
639c668632SLucile Quirion 
64576892a8SKris Bahnsen 	/*
65576892a8SKris Bahnsen 	 * If changing from an input to an output, we need to first set the
66576892a8SKris Bahnsen 	 * GPIO's DAT bit to what is requested and then set the OE bit. This
67576892a8SKris Bahnsen 	 * prevents a glitch that can occur on the IO line.
6803fe0035SMark Featherston 	 */
6903fe0035SMark Featherston 	regmap_read(priv->regmap, offset, &reg);
7003fe0035SMark Featherston 	if (!(reg & TS4900_GPIO_OE)) {
7103fe0035SMark Featherston 		if (value)
7203fe0035SMark Featherston 			reg = TS4900_GPIO_OUT;
7303fe0035SMark Featherston 		else
7403fe0035SMark Featherston 			reg &= ~TS4900_GPIO_OUT;
7503fe0035SMark Featherston 
7603fe0035SMark Featherston 		regmap_write(priv->regmap, offset, reg);
7703fe0035SMark Featherston 	}
7803fe0035SMark Featherston 
799c668632SLucile Quirion 	if (value)
809c668632SLucile Quirion 		ret = regmap_write(priv->regmap, offset, TS4900_GPIO_OE |
819c668632SLucile Quirion 							 TS4900_GPIO_OUT);
829c668632SLucile Quirion 	else
839c668632SLucile Quirion 		ret = regmap_write(priv->regmap, offset, TS4900_GPIO_OE);
849c668632SLucile Quirion 
859c668632SLucile Quirion 	return ret;
869c668632SLucile Quirion }
879c668632SLucile Quirion 
ts4900_gpio_get(struct gpio_chip * chip,unsigned int offset)889c668632SLucile Quirion static int ts4900_gpio_get(struct gpio_chip *chip, unsigned int offset)
899c668632SLucile Quirion {
909c668632SLucile Quirion 	struct ts4900_gpio_priv *priv = gpiochip_get_data(chip);
919c668632SLucile Quirion 	unsigned int reg;
929c668632SLucile Quirion 
939c668632SLucile Quirion 	regmap_read(priv->regmap, offset, &reg);
949c668632SLucile Quirion 
959c668632SLucile Quirion 	return !!(reg & priv->input_bit);
969c668632SLucile Quirion }
979c668632SLucile Quirion 
ts4900_gpio_set(struct gpio_chip * chip,unsigned int offset,int value)989c668632SLucile Quirion static void ts4900_gpio_set(struct gpio_chip *chip, unsigned int offset,
999c668632SLucile Quirion 			    int value)
1009c668632SLucile Quirion {
1019c668632SLucile Quirion 	struct ts4900_gpio_priv *priv = gpiochip_get_data(chip);
1029c668632SLucile Quirion 
1039c668632SLucile Quirion 	if (value)
1049c668632SLucile Quirion 		regmap_update_bits(priv->regmap, offset, TS4900_GPIO_OUT,
1059c668632SLucile Quirion 				   TS4900_GPIO_OUT);
1069c668632SLucile Quirion 	else
1079c668632SLucile Quirion 		regmap_update_bits(priv->regmap, offset, TS4900_GPIO_OUT, 0);
1089c668632SLucile Quirion }
1099c668632SLucile Quirion 
1109c668632SLucile Quirion static const struct regmap_config ts4900_regmap_config = {
1119c668632SLucile Quirion 	.reg_bits = 16,
1129c668632SLucile Quirion 	.val_bits = 8,
1139c668632SLucile Quirion };
1149c668632SLucile Quirion 
115e35b5ab0SJulia Lawall static const struct gpio_chip template_chip = {
1169c668632SLucile Quirion 	.label			= "ts4900-gpio",
1179c668632SLucile Quirion 	.owner			= THIS_MODULE,
1189c668632SLucile Quirion 	.get_direction		= ts4900_gpio_get_direction,
1199c668632SLucile Quirion 	.direction_input	= ts4900_gpio_direction_input,
1209c668632SLucile Quirion 	.direction_output	= ts4900_gpio_direction_output,
1219c668632SLucile Quirion 	.get			= ts4900_gpio_get,
1229c668632SLucile Quirion 	.set			= ts4900_gpio_set,
1239c668632SLucile Quirion 	.base			= -1,
1249c668632SLucile Quirion 	.can_sleep		= true,
1259c668632SLucile Quirion };
1269c668632SLucile Quirion 
1279c668632SLucile Quirion static const struct of_device_id ts4900_gpio_of_match_table[] = {
1289c668632SLucile Quirion 	{
1299c668632SLucile Quirion 		.compatible = "technologic,ts4900-gpio",
1309c668632SLucile Quirion 		.data = (void *)TS4900_GPIO_IN,
1319c668632SLucile Quirion 	}, {
1329c668632SLucile Quirion 		.compatible = "technologic,ts7970-gpio",
1339c668632SLucile Quirion 		.data = (void *)TS7970_GPIO_IN,
1349c668632SLucile Quirion 	},
1359c668632SLucile Quirion 	{ /* sentinel */ },
1369c668632SLucile Quirion };
1379c668632SLucile Quirion MODULE_DEVICE_TABLE(of, ts4900_gpio_of_match_table);
1389c668632SLucile Quirion 
ts4900_gpio_probe(struct i2c_client * client)139bf08ce13SStephen Kitt static int ts4900_gpio_probe(struct i2c_client *client)
1409c668632SLucile Quirion {
1419c668632SLucile Quirion 	struct ts4900_gpio_priv *priv;
1429c668632SLucile Quirion 	u32 ngpio;
1439c668632SLucile Quirion 	int ret;
1449c668632SLucile Quirion 
1459c668632SLucile Quirion 	if (of_property_read_u32(client->dev.of_node, "ngpios", &ngpio))
1469c668632SLucile Quirion 		ngpio = DEFAULT_PIN_NUMBER;
1479c668632SLucile Quirion 
1489c668632SLucile Quirion 	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
1499c668632SLucile Quirion 	if (!priv)
1509c668632SLucile Quirion 		return -ENOMEM;
1519c668632SLucile Quirion 
1529c668632SLucile Quirion 	priv->gpio_chip = template_chip;
1539c668632SLucile Quirion 	priv->gpio_chip.label = "ts4900-gpio";
1549c668632SLucile Quirion 	priv->gpio_chip.ngpio = ngpio;
1559c668632SLucile Quirion 	priv->gpio_chip.parent = &client->dev;
15681317c5aSThierry Reding 	priv->input_bit = (uintptr_t)of_device_get_match_data(&client->dev);
1579c668632SLucile Quirion 
1589c668632SLucile Quirion 	priv->regmap = devm_regmap_init_i2c(client, &ts4900_regmap_config);
1599c668632SLucile Quirion 	if (IS_ERR(priv->regmap)) {
1609c668632SLucile Quirion 		ret = PTR_ERR(priv->regmap);
1619c668632SLucile Quirion 		dev_err(&client->dev, "Failed to allocate register map: %d\n",
1629c668632SLucile Quirion 			ret);
1639c668632SLucile Quirion 		return ret;
1649c668632SLucile Quirion 	}
1659c668632SLucile Quirion 
1669c668632SLucile Quirion 	ret = devm_gpiochip_add_data(&client->dev, &priv->gpio_chip, priv);
1679c668632SLucile Quirion 	if (ret < 0) {
1689c668632SLucile Quirion 		dev_err(&client->dev, "Unable to register gpiochip\n");
1699c668632SLucile Quirion 		return ret;
1709c668632SLucile Quirion 	}
1719c668632SLucile Quirion 
1729c668632SLucile Quirion 	i2c_set_clientdata(client, priv);
1739c668632SLucile Quirion 
1749c668632SLucile Quirion 	return 0;
1759c668632SLucile Quirion }
1769c668632SLucile Quirion 
1779c668632SLucile Quirion static const struct i2c_device_id ts4900_gpio_id_table[] = {
1789c668632SLucile Quirion 	{ "ts4900-gpio", },
1799c668632SLucile Quirion 	{ /* sentinel */ }
1809c668632SLucile Quirion };
1819c668632SLucile Quirion MODULE_DEVICE_TABLE(i2c, ts4900_gpio_id_table);
1829c668632SLucile Quirion 
1839c668632SLucile Quirion static struct i2c_driver ts4900_gpio_driver = {
1849c668632SLucile Quirion 	.driver = {
1859c668632SLucile Quirion 		.name = "ts4900-gpio",
1869c668632SLucile Quirion 		.of_match_table = ts4900_gpio_of_match_table,
1879c668632SLucile Quirion 	},
188b41cabb7SUwe Kleine-König 	.probe = ts4900_gpio_probe,
1899c668632SLucile Quirion 	.id_table = ts4900_gpio_id_table,
1909c668632SLucile Quirion };
1919c668632SLucile Quirion module_i2c_driver(ts4900_gpio_driver);
1929c668632SLucile Quirion 
1939c668632SLucile Quirion MODULE_AUTHOR("Technologic Systems");
1949c668632SLucile Quirion MODULE_DESCRIPTION("GPIO interface for Technologic Systems I2C-FPGA core");
1959c668632SLucile Quirion MODULE_LICENSE("GPL");
196