Lines Matching +full:a +full:- +full:gpio

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Driver for pcf857x, pca857x, and pca967x I2C GPIO expanders
8 #include <linux/gpio/driver.h>
62 * write register. Writing a "one" bit (to match the reset state) lets
63 * that pin be used as an input; it's not an open-drain model, but acts
64 * a bit like one. This is described as "quasi-bidirectional"; read the
67 * Many other I2C GPIO expander chips (like the pca953x models) have
85 /*-------------------------------------------------------------------------*/
87 /* Talk to 8-bit I/O expander */
99 /* Talk to 16-bit I/O expander */
121 /*-------------------------------------------------------------------------*/
125 struct pcf857x *gpio = gpiochip_get_data(chip); in pcf857x_input() local
128 mutex_lock(&gpio->lock); in pcf857x_input()
129 gpio->out |= (1 << offset); in pcf857x_input()
130 status = gpio->write(gpio->client, gpio->out); in pcf857x_input()
131 mutex_unlock(&gpio->lock); in pcf857x_input()
138 struct pcf857x *gpio = gpiochip_get_data(chip); in pcf857x_get() local
141 value = gpio->read(gpio->client); in pcf857x_get()
147 struct pcf857x *gpio = gpiochip_get_data(chip); in pcf857x_output() local
151 mutex_lock(&gpio->lock); in pcf857x_output()
153 gpio->out |= bit; in pcf857x_output()
155 gpio->out &= ~bit; in pcf857x_output()
156 status = gpio->write(gpio->client, gpio->out); in pcf857x_output()
157 mutex_unlock(&gpio->lock); in pcf857x_output()
167 /*-------------------------------------------------------------------------*/
171 struct pcf857x *gpio = data; in pcf857x_irq() local
174 status = gpio->read(gpio->client); in pcf857x_irq()
177 * call the interrupt handler iff gpio is used as in pcf857x_irq()
180 mutex_lock(&gpio->lock); in pcf857x_irq()
181 change = (gpio->status ^ status) & gpio->irq_enabled; in pcf857x_irq()
182 gpio->status = status; in pcf857x_irq()
183 mutex_unlock(&gpio->lock); in pcf857x_irq()
185 for_each_set_bit(i, &change, gpio->chip.ngpio) in pcf857x_irq()
186 handle_nested_irq(irq_find_mapping(gpio->chip.irq.domain, i)); in pcf857x_irq()
198 struct pcf857x *gpio = irq_data_get_irq_chip_data(data); in pcf857x_irq_set_wake() local
200 return irq_set_irq_wake(gpio->client->irq, on); in pcf857x_irq_set_wake()
205 struct pcf857x *gpio = irq_data_get_irq_chip_data(data); in pcf857x_irq_enable() local
207 gpio->irq_enabled |= (1 << data->hwirq); in pcf857x_irq_enable()
212 struct pcf857x *gpio = irq_data_get_irq_chip_data(data); in pcf857x_irq_disable() local
214 gpio->irq_enabled &= ~(1 << data->hwirq); in pcf857x_irq_disable()
219 struct pcf857x *gpio = irq_data_get_irq_chip_data(data); in pcf857x_irq_bus_lock() local
221 mutex_lock(&gpio->lock); in pcf857x_irq_bus_lock()
226 struct pcf857x *gpio = irq_data_get_irq_chip_data(data); in pcf857x_irq_bus_sync_unlock() local
228 mutex_unlock(&gpio->lock); in pcf857x_irq_bus_sync_unlock()
231 /*-------------------------------------------------------------------------*/
236 struct pcf857x_platform_data *pdata = dev_get_platdata(&client->dev); in pcf857x_probe()
237 struct device_node *np = client->dev.of_node; in pcf857x_probe()
238 struct pcf857x *gpio; in pcf857x_probe() local
243 of_property_read_u32(np, "lines-initial-states", &n_latch); in pcf857x_probe()
245 n_latch = pdata->n_latch; in pcf857x_probe()
247 dev_dbg(&client->dev, "no platform data\n"); in pcf857x_probe()
250 gpio = devm_kzalloc(&client->dev, sizeof(*gpio), GFP_KERNEL); in pcf857x_probe()
251 if (!gpio) in pcf857x_probe()
252 return -ENOMEM; in pcf857x_probe()
254 mutex_init(&gpio->lock); in pcf857x_probe()
256 gpio->chip.base = pdata ? pdata->gpio_base : -1; in pcf857x_probe()
257 gpio->chip.can_sleep = true; in pcf857x_probe()
258 gpio->chip.parent = &client->dev; in pcf857x_probe()
259 gpio->chip.owner = THIS_MODULE; in pcf857x_probe()
260 gpio->chip.get = pcf857x_get; in pcf857x_probe()
261 gpio->chip.set = pcf857x_set; in pcf857x_probe()
262 gpio->chip.direction_input = pcf857x_input; in pcf857x_probe()
263 gpio->chip.direction_output = pcf857x_output; in pcf857x_probe()
264 gpio->chip.ngpio = id->driver_data; in pcf857x_probe()
267 * these parts, notably for output. It has a low-resolution in pcf857x_probe()
272 /* 8574 addresses are 0x20..0x27; 8574a uses 0x38..0x3f; in pcf857x_probe()
273 * 9670, 9672, 9764, and 9764a use quite a variety. in pcf857x_probe()
275 * NOTE: we don't distinguish here between *4 and *4a parts. in pcf857x_probe()
277 if (gpio->chip.ngpio == 8) { in pcf857x_probe()
278 gpio->write = i2c_write_le8; in pcf857x_probe()
279 gpio->read = i2c_read_le8; in pcf857x_probe()
281 if (!i2c_check_functionality(client->adapter, in pcf857x_probe()
283 status = -EIO; in pcf857x_probe()
290 * the '75c doesn't have a current source pulling high. in pcf857x_probe()
291 * 9671, 9673, and 9765 use quite a variety of addresses. in pcf857x_probe()
295 } else if (gpio->chip.ngpio == 16) { in pcf857x_probe()
296 gpio->write = i2c_write_le16; in pcf857x_probe()
297 gpio->read = i2c_read_le16; in pcf857x_probe()
299 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) in pcf857x_probe()
300 status = -EIO; in pcf857x_probe()
307 dev_dbg(&client->dev, "unsupported number of gpios\n"); in pcf857x_probe()
308 status = -EINVAL; in pcf857x_probe()
314 gpio->chip.label = client->name; in pcf857x_probe()
316 gpio->client = client; in pcf857x_probe()
317 i2c_set_clientdata(client, gpio); in pcf857x_probe()
319 /* NOTE: these chips have strange "quasi-bidirectional" I/O pins. in pcf857x_probe()
320 * We can't actually know whether a pin is configured (a) as output in pcf857x_probe()
321 * and driving the signal low, or (b) as input and reporting a low in pcf857x_probe()
331 * our software copy of the "latch" then matches the chip's all-ones in pcf857x_probe()
334 gpio->out = ~n_latch; in pcf857x_probe()
335 gpio->status = gpio->out; in pcf857x_probe()
338 if (client->irq) { in pcf857x_probe()
341 gpio->irqchip.name = "pcf857x"; in pcf857x_probe()
342 gpio->irqchip.irq_enable = pcf857x_irq_enable; in pcf857x_probe()
343 gpio->irqchip.irq_disable = pcf857x_irq_disable; in pcf857x_probe()
344 gpio->irqchip.irq_ack = noop; in pcf857x_probe()
345 gpio->irqchip.irq_mask = noop; in pcf857x_probe()
346 gpio->irqchip.irq_unmask = noop; in pcf857x_probe()
347 gpio->irqchip.irq_set_wake = pcf857x_irq_set_wake; in pcf857x_probe()
348 gpio->irqchip.irq_bus_lock = pcf857x_irq_bus_lock; in pcf857x_probe()
349 gpio->irqchip.irq_bus_sync_unlock = pcf857x_irq_bus_sync_unlock; in pcf857x_probe()
351 status = devm_request_threaded_irq(&client->dev, client->irq, in pcf857x_probe()
354 dev_name(&client->dev), gpio); in pcf857x_probe()
358 girq = &gpio->chip.irq; in pcf857x_probe()
359 girq->chip = &gpio->irqchip; in pcf857x_probe()
361 girq->parent_handler = NULL; in pcf857x_probe()
362 girq->num_parents = 0; in pcf857x_probe()
363 girq->parents = NULL; in pcf857x_probe()
364 girq->default_type = IRQ_TYPE_NONE; in pcf857x_probe()
365 girq->handler = handle_level_irq; in pcf857x_probe()
366 girq->threaded = true; in pcf857x_probe()
369 status = devm_gpiochip_add_data(&client->dev, &gpio->chip, gpio); in pcf857x_probe()
376 if (pdata && pdata->setup) { in pcf857x_probe()
377 status = pdata->setup(client, in pcf857x_probe()
378 gpio->chip.base, gpio->chip.ngpio, in pcf857x_probe()
379 pdata->context); in pcf857x_probe()
381 dev_warn(&client->dev, "setup --> %d\n", status); in pcf857x_probe()
384 dev_info(&client->dev, "probed\n"); in pcf857x_probe()
389 dev_dbg(&client->dev, "probe error %d for '%s'\n", status, in pcf857x_probe()
390 client->name); in pcf857x_probe()
397 struct pcf857x_platform_data *pdata = dev_get_platdata(&client->dev); in pcf857x_remove()
398 struct pcf857x *gpio = i2c_get_clientdata(client); in pcf857x_remove() local
401 if (pdata && pdata->teardown) { in pcf857x_remove()
402 status = pdata->teardown(client, in pcf857x_remove()
403 gpio->chip.base, gpio->chip.ngpio, in pcf857x_remove()
404 pdata->context); in pcf857x_remove()
406 dev_err(&client->dev, "%s --> %d\n", in pcf857x_remove()
417 struct pcf857x *gpio = i2c_get_clientdata(client); in pcf857x_shutdown() local
420 gpio->write(gpio->client, BIT(gpio->chip.ngpio) - 1); in pcf857x_shutdown()