18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Driver for pcf857x, pca857x, and pca967x I2C GPIO expanders
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2007 David Brownell
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/gpio/driver.h>
98c2ecf20Sopenharmony_ci#include <linux/i2c.h>
108c2ecf20Sopenharmony_ci#include <linux/platform_data/pcf857x.h>
118c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
128c2ecf20Sopenharmony_ci#include <linux/irq.h>
138c2ecf20Sopenharmony_ci#include <linux/irqdomain.h>
148c2ecf20Sopenharmony_ci#include <linux/kernel.h>
158c2ecf20Sopenharmony_ci#include <linux/module.h>
168c2ecf20Sopenharmony_ci#include <linux/of.h>
178c2ecf20Sopenharmony_ci#include <linux/of_device.h>
188c2ecf20Sopenharmony_ci#include <linux/slab.h>
198c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistatic const struct i2c_device_id pcf857x_id[] = {
238c2ecf20Sopenharmony_ci	{ "pcf8574", 8 },
248c2ecf20Sopenharmony_ci	{ "pcf8574a", 8 },
258c2ecf20Sopenharmony_ci	{ "pca8574", 8 },
268c2ecf20Sopenharmony_ci	{ "pca9670", 8 },
278c2ecf20Sopenharmony_ci	{ "pca9672", 8 },
288c2ecf20Sopenharmony_ci	{ "pca9674", 8 },
298c2ecf20Sopenharmony_ci	{ "pcf8575", 16 },
308c2ecf20Sopenharmony_ci	{ "pca8575", 16 },
318c2ecf20Sopenharmony_ci	{ "pca9671", 16 },
328c2ecf20Sopenharmony_ci	{ "pca9673", 16 },
338c2ecf20Sopenharmony_ci	{ "pca9675", 16 },
348c2ecf20Sopenharmony_ci	{ "max7328", 8 },
358c2ecf20Sopenharmony_ci	{ "max7329", 8 },
368c2ecf20Sopenharmony_ci	{ }
378c2ecf20Sopenharmony_ci};
388c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, pcf857x_id);
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci#ifdef CONFIG_OF
418c2ecf20Sopenharmony_cistatic const struct of_device_id pcf857x_of_table[] = {
428c2ecf20Sopenharmony_ci	{ .compatible = "nxp,pcf8574" },
438c2ecf20Sopenharmony_ci	{ .compatible = "nxp,pcf8574a" },
448c2ecf20Sopenharmony_ci	{ .compatible = "nxp,pca8574" },
458c2ecf20Sopenharmony_ci	{ .compatible = "nxp,pca9670" },
468c2ecf20Sopenharmony_ci	{ .compatible = "nxp,pca9672" },
478c2ecf20Sopenharmony_ci	{ .compatible = "nxp,pca9674" },
488c2ecf20Sopenharmony_ci	{ .compatible = "nxp,pcf8575" },
498c2ecf20Sopenharmony_ci	{ .compatible = "nxp,pca8575" },
508c2ecf20Sopenharmony_ci	{ .compatible = "nxp,pca9671" },
518c2ecf20Sopenharmony_ci	{ .compatible = "nxp,pca9673" },
528c2ecf20Sopenharmony_ci	{ .compatible = "nxp,pca9675" },
538c2ecf20Sopenharmony_ci	{ .compatible = "maxim,max7328" },
548c2ecf20Sopenharmony_ci	{ .compatible = "maxim,max7329" },
558c2ecf20Sopenharmony_ci	{ }
568c2ecf20Sopenharmony_ci};
578c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, pcf857x_of_table);
588c2ecf20Sopenharmony_ci#endif
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci/*
618c2ecf20Sopenharmony_ci * The pcf857x, pca857x, and pca967x chips only expose one read and one
628c2ecf20Sopenharmony_ci * write register.  Writing a "one" bit (to match the reset state) lets
638c2ecf20Sopenharmony_ci * that pin be used as an input; it's not an open-drain model, but acts
648c2ecf20Sopenharmony_ci * a bit like one.  This is described as "quasi-bidirectional"; read the
658c2ecf20Sopenharmony_ci * chip documentation for details.
668c2ecf20Sopenharmony_ci *
678c2ecf20Sopenharmony_ci * Many other I2C GPIO expander chips (like the pca953x models) have
688c2ecf20Sopenharmony_ci * more complex register models and more conventional circuitry using
698c2ecf20Sopenharmony_ci * push/pull drivers.  They often use the same 0x20..0x27 addresses as
708c2ecf20Sopenharmony_ci * pcf857x parts, making the "legacy" I2C driver model problematic.
718c2ecf20Sopenharmony_ci */
728c2ecf20Sopenharmony_cistruct pcf857x {
738c2ecf20Sopenharmony_ci	struct gpio_chip	chip;
748c2ecf20Sopenharmony_ci	struct irq_chip		irqchip;
758c2ecf20Sopenharmony_ci	struct i2c_client	*client;
768c2ecf20Sopenharmony_ci	struct mutex		lock;		/* protect 'out' */
778c2ecf20Sopenharmony_ci	unsigned		out;		/* software latch */
788c2ecf20Sopenharmony_ci	unsigned		status;		/* current status */
798c2ecf20Sopenharmony_ci	unsigned		irq_enabled;	/* enabled irqs */
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	int (*write)(struct i2c_client *client, unsigned data);
828c2ecf20Sopenharmony_ci	int (*read)(struct i2c_client *client);
838c2ecf20Sopenharmony_ci};
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci/*-------------------------------------------------------------------------*/
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci/* Talk to 8-bit I/O expander */
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_cistatic int i2c_write_le8(struct i2c_client *client, unsigned data)
908c2ecf20Sopenharmony_ci{
918c2ecf20Sopenharmony_ci	return i2c_smbus_write_byte(client, data);
928c2ecf20Sopenharmony_ci}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_cistatic int i2c_read_le8(struct i2c_client *client)
958c2ecf20Sopenharmony_ci{
968c2ecf20Sopenharmony_ci	return (int)i2c_smbus_read_byte(client);
978c2ecf20Sopenharmony_ci}
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci/* Talk to 16-bit I/O expander */
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_cistatic int i2c_write_le16(struct i2c_client *client, unsigned word)
1028c2ecf20Sopenharmony_ci{
1038c2ecf20Sopenharmony_ci	u8 buf[2] = { word & 0xff, word >> 8, };
1048c2ecf20Sopenharmony_ci	int status;
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	status = i2c_master_send(client, buf, 2);
1078c2ecf20Sopenharmony_ci	return (status < 0) ? status : 0;
1088c2ecf20Sopenharmony_ci}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_cistatic int i2c_read_le16(struct i2c_client *client)
1118c2ecf20Sopenharmony_ci{
1128c2ecf20Sopenharmony_ci	u8 buf[2];
1138c2ecf20Sopenharmony_ci	int status;
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	status = i2c_master_recv(client, buf, 2);
1168c2ecf20Sopenharmony_ci	if (status < 0)
1178c2ecf20Sopenharmony_ci		return status;
1188c2ecf20Sopenharmony_ci	return (buf[1] << 8) | buf[0];
1198c2ecf20Sopenharmony_ci}
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci/*-------------------------------------------------------------------------*/
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_cistatic int pcf857x_input(struct gpio_chip *chip, unsigned offset)
1248c2ecf20Sopenharmony_ci{
1258c2ecf20Sopenharmony_ci	struct pcf857x	*gpio = gpiochip_get_data(chip);
1268c2ecf20Sopenharmony_ci	int		status;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	mutex_lock(&gpio->lock);
1298c2ecf20Sopenharmony_ci	gpio->out |= (1 << offset);
1308c2ecf20Sopenharmony_ci	status = gpio->write(gpio->client, gpio->out);
1318c2ecf20Sopenharmony_ci	mutex_unlock(&gpio->lock);
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	return status;
1348c2ecf20Sopenharmony_ci}
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_cistatic int pcf857x_get(struct gpio_chip *chip, unsigned offset)
1378c2ecf20Sopenharmony_ci{
1388c2ecf20Sopenharmony_ci	struct pcf857x	*gpio = gpiochip_get_data(chip);
1398c2ecf20Sopenharmony_ci	int		value;
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	value = gpio->read(gpio->client);
1428c2ecf20Sopenharmony_ci	return (value < 0) ? value : !!(value & (1 << offset));
1438c2ecf20Sopenharmony_ci}
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_cistatic int pcf857x_output(struct gpio_chip *chip, unsigned offset, int value)
1468c2ecf20Sopenharmony_ci{
1478c2ecf20Sopenharmony_ci	struct pcf857x	*gpio = gpiochip_get_data(chip);
1488c2ecf20Sopenharmony_ci	unsigned	bit = 1 << offset;
1498c2ecf20Sopenharmony_ci	int		status;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	mutex_lock(&gpio->lock);
1528c2ecf20Sopenharmony_ci	if (value)
1538c2ecf20Sopenharmony_ci		gpio->out |= bit;
1548c2ecf20Sopenharmony_ci	else
1558c2ecf20Sopenharmony_ci		gpio->out &= ~bit;
1568c2ecf20Sopenharmony_ci	status = gpio->write(gpio->client, gpio->out);
1578c2ecf20Sopenharmony_ci	mutex_unlock(&gpio->lock);
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	return status;
1608c2ecf20Sopenharmony_ci}
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_cistatic void pcf857x_set(struct gpio_chip *chip, unsigned offset, int value)
1638c2ecf20Sopenharmony_ci{
1648c2ecf20Sopenharmony_ci	pcf857x_output(chip, offset, value);
1658c2ecf20Sopenharmony_ci}
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci/*-------------------------------------------------------------------------*/
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_cistatic irqreturn_t pcf857x_irq(int irq, void *data)
1708c2ecf20Sopenharmony_ci{
1718c2ecf20Sopenharmony_ci	struct pcf857x  *gpio = data;
1728c2ecf20Sopenharmony_ci	unsigned long change, i, status;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	status = gpio->read(gpio->client);
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	/*
1778c2ecf20Sopenharmony_ci	 * call the interrupt handler iff gpio is used as
1788c2ecf20Sopenharmony_ci	 * interrupt source, just to avoid bad irqs
1798c2ecf20Sopenharmony_ci	 */
1808c2ecf20Sopenharmony_ci	mutex_lock(&gpio->lock);
1818c2ecf20Sopenharmony_ci	change = (gpio->status ^ status) & gpio->irq_enabled;
1828c2ecf20Sopenharmony_ci	gpio->status = status;
1838c2ecf20Sopenharmony_ci	mutex_unlock(&gpio->lock);
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	for_each_set_bit(i, &change, gpio->chip.ngpio)
1868c2ecf20Sopenharmony_ci		handle_nested_irq(irq_find_mapping(gpio->chip.irq.domain, i));
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
1898c2ecf20Sopenharmony_ci}
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci/*
1928c2ecf20Sopenharmony_ci * NOP functions
1938c2ecf20Sopenharmony_ci */
1948c2ecf20Sopenharmony_cistatic void noop(struct irq_data *data) { }
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_cistatic int pcf857x_irq_set_wake(struct irq_data *data, unsigned int on)
1978c2ecf20Sopenharmony_ci{
1988c2ecf20Sopenharmony_ci	struct pcf857x *gpio = irq_data_get_irq_chip_data(data);
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	return irq_set_irq_wake(gpio->client->irq, on);
2018c2ecf20Sopenharmony_ci}
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_cistatic void pcf857x_irq_enable(struct irq_data *data)
2048c2ecf20Sopenharmony_ci{
2058c2ecf20Sopenharmony_ci	struct pcf857x *gpio = irq_data_get_irq_chip_data(data);
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	gpio->irq_enabled |= (1 << data->hwirq);
2088c2ecf20Sopenharmony_ci}
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_cistatic void pcf857x_irq_disable(struct irq_data *data)
2118c2ecf20Sopenharmony_ci{
2128c2ecf20Sopenharmony_ci	struct pcf857x *gpio = irq_data_get_irq_chip_data(data);
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	gpio->irq_enabled &= ~(1 << data->hwirq);
2158c2ecf20Sopenharmony_ci}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_cistatic void pcf857x_irq_bus_lock(struct irq_data *data)
2188c2ecf20Sopenharmony_ci{
2198c2ecf20Sopenharmony_ci	struct pcf857x *gpio = irq_data_get_irq_chip_data(data);
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	mutex_lock(&gpio->lock);
2228c2ecf20Sopenharmony_ci}
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_cistatic void pcf857x_irq_bus_sync_unlock(struct irq_data *data)
2258c2ecf20Sopenharmony_ci{
2268c2ecf20Sopenharmony_ci	struct pcf857x *gpio = irq_data_get_irq_chip_data(data);
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	mutex_unlock(&gpio->lock);
2298c2ecf20Sopenharmony_ci}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci/*-------------------------------------------------------------------------*/
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_cistatic int pcf857x_probe(struct i2c_client *client,
2348c2ecf20Sopenharmony_ci			 const struct i2c_device_id *id)
2358c2ecf20Sopenharmony_ci{
2368c2ecf20Sopenharmony_ci	struct pcf857x_platform_data	*pdata = dev_get_platdata(&client->dev);
2378c2ecf20Sopenharmony_ci	struct device_node		*np = client->dev.of_node;
2388c2ecf20Sopenharmony_ci	struct pcf857x			*gpio;
2398c2ecf20Sopenharmony_ci	unsigned int			n_latch = 0;
2408c2ecf20Sopenharmony_ci	int				status;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_OF) && np)
2438c2ecf20Sopenharmony_ci		of_property_read_u32(np, "lines-initial-states", &n_latch);
2448c2ecf20Sopenharmony_ci	else if (pdata)
2458c2ecf20Sopenharmony_ci		n_latch = pdata->n_latch;
2468c2ecf20Sopenharmony_ci	else
2478c2ecf20Sopenharmony_ci		dev_dbg(&client->dev, "no platform data\n");
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	/* Allocate, initialize, and register this gpio_chip. */
2508c2ecf20Sopenharmony_ci	gpio = devm_kzalloc(&client->dev, sizeof(*gpio), GFP_KERNEL);
2518c2ecf20Sopenharmony_ci	if (!gpio)
2528c2ecf20Sopenharmony_ci		return -ENOMEM;
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	mutex_init(&gpio->lock);
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	gpio->chip.base			= pdata ? pdata->gpio_base : -1;
2578c2ecf20Sopenharmony_ci	gpio->chip.can_sleep		= true;
2588c2ecf20Sopenharmony_ci	gpio->chip.parent		= &client->dev;
2598c2ecf20Sopenharmony_ci	gpio->chip.owner		= THIS_MODULE;
2608c2ecf20Sopenharmony_ci	gpio->chip.get			= pcf857x_get;
2618c2ecf20Sopenharmony_ci	gpio->chip.set			= pcf857x_set;
2628c2ecf20Sopenharmony_ci	gpio->chip.direction_input	= pcf857x_input;
2638c2ecf20Sopenharmony_ci	gpio->chip.direction_output	= pcf857x_output;
2648c2ecf20Sopenharmony_ci	gpio->chip.ngpio		= id->driver_data;
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	/* NOTE:  the OnSemi jlc1562b is also largely compatible with
2678c2ecf20Sopenharmony_ci	 * these parts, notably for output.  It has a low-resolution
2688c2ecf20Sopenharmony_ci	 * DAC instead of pin change IRQs; and its inputs can be the
2698c2ecf20Sopenharmony_ci	 * result of comparators.
2708c2ecf20Sopenharmony_ci	 */
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	/* 8574 addresses are 0x20..0x27; 8574a uses 0x38..0x3f;
2738c2ecf20Sopenharmony_ci	 * 9670, 9672, 9764, and 9764a use quite a variety.
2748c2ecf20Sopenharmony_ci	 *
2758c2ecf20Sopenharmony_ci	 * NOTE: we don't distinguish here between *4 and *4a parts.
2768c2ecf20Sopenharmony_ci	 */
2778c2ecf20Sopenharmony_ci	if (gpio->chip.ngpio == 8) {
2788c2ecf20Sopenharmony_ci		gpio->write	= i2c_write_le8;
2798c2ecf20Sopenharmony_ci		gpio->read	= i2c_read_le8;
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci		if (!i2c_check_functionality(client->adapter,
2828c2ecf20Sopenharmony_ci				I2C_FUNC_SMBUS_BYTE))
2838c2ecf20Sopenharmony_ci			status = -EIO;
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci		/* fail if there's no chip present */
2868c2ecf20Sopenharmony_ci		else
2878c2ecf20Sopenharmony_ci			status = i2c_smbus_read_byte(client);
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	/* '75/'75c addresses are 0x20..0x27, just like the '74;
2908c2ecf20Sopenharmony_ci	 * the '75c doesn't have a current source pulling high.
2918c2ecf20Sopenharmony_ci	 * 9671, 9673, and 9765 use quite a variety of addresses.
2928c2ecf20Sopenharmony_ci	 *
2938c2ecf20Sopenharmony_ci	 * NOTE: we don't distinguish here between '75 and '75c parts.
2948c2ecf20Sopenharmony_ci	 */
2958c2ecf20Sopenharmony_ci	} else if (gpio->chip.ngpio == 16) {
2968c2ecf20Sopenharmony_ci		gpio->write	= i2c_write_le16;
2978c2ecf20Sopenharmony_ci		gpio->read	= i2c_read_le16;
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci		if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
3008c2ecf20Sopenharmony_ci			status = -EIO;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci		/* fail if there's no chip present */
3038c2ecf20Sopenharmony_ci		else
3048c2ecf20Sopenharmony_ci			status = i2c_read_le16(client);
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	} else {
3078c2ecf20Sopenharmony_ci		dev_dbg(&client->dev, "unsupported number of gpios\n");
3088c2ecf20Sopenharmony_ci		status = -EINVAL;
3098c2ecf20Sopenharmony_ci	}
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	if (status < 0)
3128c2ecf20Sopenharmony_ci		goto fail;
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	gpio->chip.label = client->name;
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	gpio->client = client;
3178c2ecf20Sopenharmony_ci	i2c_set_clientdata(client, gpio);
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	/* NOTE:  these chips have strange "quasi-bidirectional" I/O pins.
3208c2ecf20Sopenharmony_ci	 * We can't actually know whether a pin is configured (a) as output
3218c2ecf20Sopenharmony_ci	 * and driving the signal low, or (b) as input and reporting a low
3228c2ecf20Sopenharmony_ci	 * value ... without knowing the last value written since the chip
3238c2ecf20Sopenharmony_ci	 * came out of reset (if any).  We can't read the latched output.
3248c2ecf20Sopenharmony_ci	 *
3258c2ecf20Sopenharmony_ci	 * In short, the only reliable solution for setting up pin direction
3268c2ecf20Sopenharmony_ci	 * is to do it explicitly.  The setup() method can do that, but it
3278c2ecf20Sopenharmony_ci	 * may cause transient glitching since it can't know the last value
3288c2ecf20Sopenharmony_ci	 * written (some pins may need to be driven low).
3298c2ecf20Sopenharmony_ci	 *
3308c2ecf20Sopenharmony_ci	 * Using n_latch avoids that trouble.  When left initialized to zero,
3318c2ecf20Sopenharmony_ci	 * our software copy of the "latch" then matches the chip's all-ones
3328c2ecf20Sopenharmony_ci	 * reset state.  Otherwise it flags pins to be driven low.
3338c2ecf20Sopenharmony_ci	 */
3348c2ecf20Sopenharmony_ci	gpio->out = ~n_latch;
3358c2ecf20Sopenharmony_ci	gpio->status = gpio->read(gpio->client);
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	/* Enable irqchip if we have an interrupt */
3388c2ecf20Sopenharmony_ci	if (client->irq) {
3398c2ecf20Sopenharmony_ci		struct gpio_irq_chip *girq;
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci		gpio->irqchip.name = "pcf857x";
3428c2ecf20Sopenharmony_ci		gpio->irqchip.irq_enable = pcf857x_irq_enable;
3438c2ecf20Sopenharmony_ci		gpio->irqchip.irq_disable = pcf857x_irq_disable;
3448c2ecf20Sopenharmony_ci		gpio->irqchip.irq_ack = noop;
3458c2ecf20Sopenharmony_ci		gpio->irqchip.irq_mask = noop;
3468c2ecf20Sopenharmony_ci		gpio->irqchip.irq_unmask = noop;
3478c2ecf20Sopenharmony_ci		gpio->irqchip.irq_set_wake = pcf857x_irq_set_wake;
3488c2ecf20Sopenharmony_ci		gpio->irqchip.irq_bus_lock = pcf857x_irq_bus_lock;
3498c2ecf20Sopenharmony_ci		gpio->irqchip.irq_bus_sync_unlock = pcf857x_irq_bus_sync_unlock;
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci		status = devm_request_threaded_irq(&client->dev, client->irq,
3528c2ecf20Sopenharmony_ci					NULL, pcf857x_irq, IRQF_ONESHOT |
3538c2ecf20Sopenharmony_ci					IRQF_TRIGGER_FALLING | IRQF_SHARED,
3548c2ecf20Sopenharmony_ci					dev_name(&client->dev), gpio);
3558c2ecf20Sopenharmony_ci		if (status)
3568c2ecf20Sopenharmony_ci			goto fail;
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci		girq = &gpio->chip.irq;
3598c2ecf20Sopenharmony_ci		girq->chip = &gpio->irqchip;
3608c2ecf20Sopenharmony_ci		/* This will let us handle the parent IRQ in the driver */
3618c2ecf20Sopenharmony_ci		girq->parent_handler = NULL;
3628c2ecf20Sopenharmony_ci		girq->num_parents = 0;
3638c2ecf20Sopenharmony_ci		girq->parents = NULL;
3648c2ecf20Sopenharmony_ci		girq->default_type = IRQ_TYPE_NONE;
3658c2ecf20Sopenharmony_ci		girq->handler = handle_level_irq;
3668c2ecf20Sopenharmony_ci		girq->threaded = true;
3678c2ecf20Sopenharmony_ci	}
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	status = devm_gpiochip_add_data(&client->dev, &gpio->chip, gpio);
3708c2ecf20Sopenharmony_ci	if (status < 0)
3718c2ecf20Sopenharmony_ci		goto fail;
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	/* Let platform code set up the GPIOs and their users.
3748c2ecf20Sopenharmony_ci	 * Now is the first time anyone could use them.
3758c2ecf20Sopenharmony_ci	 */
3768c2ecf20Sopenharmony_ci	if (pdata && pdata->setup) {
3778c2ecf20Sopenharmony_ci		status = pdata->setup(client,
3788c2ecf20Sopenharmony_ci				gpio->chip.base, gpio->chip.ngpio,
3798c2ecf20Sopenharmony_ci				pdata->context);
3808c2ecf20Sopenharmony_ci		if (status < 0)
3818c2ecf20Sopenharmony_ci			dev_warn(&client->dev, "setup --> %d\n", status);
3828c2ecf20Sopenharmony_ci	}
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	dev_info(&client->dev, "probed\n");
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci	return 0;
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_cifail:
3898c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "probe error %d for '%s'\n", status,
3908c2ecf20Sopenharmony_ci		client->name);
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	return status;
3938c2ecf20Sopenharmony_ci}
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_cistatic int pcf857x_remove(struct i2c_client *client)
3968c2ecf20Sopenharmony_ci{
3978c2ecf20Sopenharmony_ci	struct pcf857x_platform_data	*pdata = dev_get_platdata(&client->dev);
3988c2ecf20Sopenharmony_ci	struct pcf857x			*gpio = i2c_get_clientdata(client);
3998c2ecf20Sopenharmony_ci	int				status = 0;
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	if (pdata && pdata->teardown) {
4028c2ecf20Sopenharmony_ci		status = pdata->teardown(client,
4038c2ecf20Sopenharmony_ci				gpio->chip.base, gpio->chip.ngpio,
4048c2ecf20Sopenharmony_ci				pdata->context);
4058c2ecf20Sopenharmony_ci		if (status < 0) {
4068c2ecf20Sopenharmony_ci			dev_err(&client->dev, "%s --> %d\n",
4078c2ecf20Sopenharmony_ci					"teardown", status);
4088c2ecf20Sopenharmony_ci			return status;
4098c2ecf20Sopenharmony_ci		}
4108c2ecf20Sopenharmony_ci	}
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	return status;
4138c2ecf20Sopenharmony_ci}
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_cistatic void pcf857x_shutdown(struct i2c_client *client)
4168c2ecf20Sopenharmony_ci{
4178c2ecf20Sopenharmony_ci	struct pcf857x *gpio = i2c_get_clientdata(client);
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	/* Drive all the I/O lines high */
4208c2ecf20Sopenharmony_ci	gpio->write(gpio->client, BIT(gpio->chip.ngpio) - 1);
4218c2ecf20Sopenharmony_ci}
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_cistatic struct i2c_driver pcf857x_driver = {
4248c2ecf20Sopenharmony_ci	.driver = {
4258c2ecf20Sopenharmony_ci		.name	= "pcf857x",
4268c2ecf20Sopenharmony_ci		.of_match_table = of_match_ptr(pcf857x_of_table),
4278c2ecf20Sopenharmony_ci	},
4288c2ecf20Sopenharmony_ci	.probe	= pcf857x_probe,
4298c2ecf20Sopenharmony_ci	.remove	= pcf857x_remove,
4308c2ecf20Sopenharmony_ci	.shutdown = pcf857x_shutdown,
4318c2ecf20Sopenharmony_ci	.id_table = pcf857x_id,
4328c2ecf20Sopenharmony_ci};
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_cistatic int __init pcf857x_init(void)
4358c2ecf20Sopenharmony_ci{
4368c2ecf20Sopenharmony_ci	return i2c_add_driver(&pcf857x_driver);
4378c2ecf20Sopenharmony_ci}
4388c2ecf20Sopenharmony_ci/* register after i2c postcore initcall and before
4398c2ecf20Sopenharmony_ci * subsys initcalls that may rely on these GPIOs
4408c2ecf20Sopenharmony_ci */
4418c2ecf20Sopenharmony_cisubsys_initcall(pcf857x_init);
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_cistatic void __exit pcf857x_exit(void)
4448c2ecf20Sopenharmony_ci{
4458c2ecf20Sopenharmony_ci	i2c_del_driver(&pcf857x_driver);
4468c2ecf20Sopenharmony_ci}
4478c2ecf20Sopenharmony_cimodule_exit(pcf857x_exit);
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
4508c2ecf20Sopenharmony_ciMODULE_AUTHOR("David Brownell");
451