Lines Matching +full:segment +full:- +full:gpios
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2011-2012 Avionic Design GmbH
17 #define GPIO_DDR(gpio) (0x00 << (gpio)->reg_shift)
18 #define GPIO_PLR(gpio) (0x01 << (gpio)->reg_shift)
19 #define GPIO_IER(gpio) (0x02 << (gpio)->reg_shift)
20 #define GPIO_ISR(gpio) (0x03 << (gpio)->reg_shift)
21 #define GPIO_PTR(gpio) (0x04 << (gpio)->reg_shift)
43 err = i2c_smbus_read_byte_data(adnp->client, offset); in adnp_read()
45 dev_err(adnp->gpio.parent, "%s failed: %d\n", in adnp_read()
58 err = i2c_smbus_write_byte_data(adnp->client, offset, value); in adnp_write()
60 dev_err(adnp->gpio.parent, "%s failed: %d\n", in adnp_write()
71 unsigned int reg = offset >> adnp->reg_shift; in adnp_gpio_get()
85 unsigned int reg = offset >> adnp->reg_shift; in __adnp_gpio_set()
106 guard(mutex)(&adnp->i2c_lock); in adnp_gpio_set()
114 unsigned int reg = offset >> adnp->reg_shift; in adnp_gpio_direction_input()
119 guard(mutex)(&adnp->i2c_lock); in adnp_gpio_direction_input()
136 return -EPERM; in adnp_gpio_direction_input()
145 unsigned int reg = offset >> adnp->reg_shift; in adnp_gpio_direction_output()
150 guard(mutex)(&adnp->i2c_lock); in adnp_gpio_direction_output()
167 return -EPERM; in adnp_gpio_direction_output()
177 unsigned int num_regs = 1 << adnp->reg_shift, i, j; in adnp_gpio_dbg_show()
183 scoped_guard(mutex, &adnp->i2c_lock) { in adnp_gpio_dbg_show()
203 unsigned int bit = (i << adnp->reg_shift) + j; in adnp_gpio_dbg_show()
232 num_regs = 1 << adnp->reg_shift; in adnp_irq()
235 unsigned int base = i << adnp->reg_shift, bit; in adnp_irq()
240 scoped_guard(mutex, &adnp->i2c_lock) { in adnp_irq()
255 changed = level ^ adnp->irq_level[i]; in adnp_irq()
257 /* compute edge-triggered interrupts */ in adnp_irq()
258 pending = changed & ((adnp->irq_fall[i] & ~level) | in adnp_irq()
259 (adnp->irq_rise[i] & level)); in adnp_irq()
261 /* add in level-triggered interrupts */ in adnp_irq()
262 pending |= (adnp->irq_high[i] & level) | in adnp_irq()
263 (adnp->irq_low[i] & ~level); in adnp_irq()
265 /* mask out non-pending and disabled interrupts */ in adnp_irq()
270 child_irq = irq_find_mapping(adnp->gpio.irq.domain, in adnp_irq()
283 unsigned int reg = d->hwirq >> adnp->reg_shift; in adnp_irq_mask()
284 unsigned int pos = d->hwirq & 7; in adnp_irq_mask()
286 adnp->irq_enable[reg] &= ~BIT(pos); in adnp_irq_mask()
294 unsigned int reg = d->hwirq >> adnp->reg_shift; in adnp_irq_unmask()
295 unsigned int pos = d->hwirq & 7; in adnp_irq_unmask()
298 adnp->irq_enable[reg] |= BIT(pos); in adnp_irq_unmask()
305 unsigned int reg = d->hwirq >> adnp->reg_shift; in adnp_irq_set_type()
306 unsigned int pos = d->hwirq & 7; in adnp_irq_set_type()
309 adnp->irq_rise[reg] |= BIT(pos); in adnp_irq_set_type()
311 adnp->irq_rise[reg] &= ~BIT(pos); in adnp_irq_set_type()
314 adnp->irq_fall[reg] |= BIT(pos); in adnp_irq_set_type()
316 adnp->irq_fall[reg] &= ~BIT(pos); in adnp_irq_set_type()
319 adnp->irq_high[reg] |= BIT(pos); in adnp_irq_set_type()
321 adnp->irq_high[reg] &= ~BIT(pos); in adnp_irq_set_type()
324 adnp->irq_low[reg] |= BIT(pos); in adnp_irq_set_type()
326 adnp->irq_low[reg] &= ~BIT(pos); in adnp_irq_set_type()
336 mutex_lock(&adnp->irq_lock); in adnp_irq_bus_lock()
343 unsigned int num_regs = 1 << adnp->reg_shift, i; in adnp_irq_bus_unlock()
345 scoped_guard(mutex, &adnp->i2c_lock) { in adnp_irq_bus_unlock()
348 adnp->irq_enable[i]); in adnp_irq_bus_unlock()
351 mutex_unlock(&adnp->irq_lock); in adnp_irq_bus_unlock()
355 .name = "gpio-adnp",
367 unsigned int num_regs = 1 << adnp->reg_shift, i; in adnp_irq_setup()
368 struct gpio_chip *chip = &adnp->gpio; in adnp_irq_setup()
371 mutex_init(&adnp->irq_lock); in adnp_irq_setup()
379 * each segment contains the corresponding bits for all interrupts. in adnp_irq_setup()
381 adnp->irq_enable = devm_kcalloc(chip->parent, num_regs, 6, in adnp_irq_setup()
383 if (!adnp->irq_enable) in adnp_irq_setup()
384 return -ENOMEM; in adnp_irq_setup()
386 adnp->irq_level = adnp->irq_enable + (num_regs * 1); in adnp_irq_setup()
387 adnp->irq_rise = adnp->irq_enable + (num_regs * 2); in adnp_irq_setup()
388 adnp->irq_fall = adnp->irq_enable + (num_regs * 3); in adnp_irq_setup()
389 adnp->irq_high = adnp->irq_enable + (num_regs * 4); in adnp_irq_setup()
390 adnp->irq_low = adnp->irq_enable + (num_regs * 5); in adnp_irq_setup()
397 err = adnp_read(adnp, GPIO_PLR(adnp) + i, &adnp->irq_level[i]); in adnp_irq_setup()
406 adnp->irq_enable[i] = 0x00; in adnp_irq_setup()
409 err = devm_request_threaded_irq(chip->parent, adnp->client->irq, in adnp_irq_setup()
412 dev_name(chip->parent), adnp); in adnp_irq_setup()
414 dev_err(chip->parent, "can't request IRQ#%d: %d\n", in adnp_irq_setup()
415 adnp->client->irq, err); in adnp_irq_setup()
425 struct gpio_chip *chip = &adnp->gpio; in adnp_gpio_setup()
428 adnp->reg_shift = get_count_order(num_gpios) - 3; in adnp_gpio_setup()
430 chip->direction_input = adnp_gpio_direction_input; in adnp_gpio_setup()
431 chip->direction_output = adnp_gpio_direction_output; in adnp_gpio_setup()
432 chip->get = adnp_gpio_get; in adnp_gpio_setup()
433 chip->set_rv = adnp_gpio_set; in adnp_gpio_setup()
434 chip->can_sleep = true; in adnp_gpio_setup()
437 chip->dbg_show = adnp_gpio_dbg_show; in adnp_gpio_setup()
439 chip->base = -1; in adnp_gpio_setup()
440 chip->ngpio = num_gpios; in adnp_gpio_setup()
441 chip->label = adnp->client->name; in adnp_gpio_setup()
442 chip->parent = &adnp->client->dev; in adnp_gpio_setup()
443 chip->owner = THIS_MODULE; in adnp_gpio_setup()
452 girq = &chip->irq; in adnp_gpio_setup()
456 girq->parent_handler = NULL; in adnp_gpio_setup()
457 girq->num_parents = 0; in adnp_gpio_setup()
458 girq->parents = NULL; in adnp_gpio_setup()
459 girq->default_type = IRQ_TYPE_NONE; in adnp_gpio_setup()
460 girq->handler = handle_simple_irq; in adnp_gpio_setup()
461 girq->threaded = true; in adnp_gpio_setup()
464 err = devm_gpiochip_add_data(&adnp->client->dev, chip, adnp); in adnp_gpio_setup()
473 struct device *dev = &client->dev; in adnp_i2c_probe()
478 err = device_property_read_u32(dev, "nr-gpios", &num_gpios); in adnp_i2c_probe()
482 adnp = devm_kzalloc(&client->dev, sizeof(*adnp), GFP_KERNEL); in adnp_i2c_probe()
484 return -ENOMEM; in adnp_i2c_probe()
486 err = devm_mutex_init(&client->dev, &adnp->i2c_lock); in adnp_i2c_probe()
490 adnp->client = client; in adnp_i2c_probe()
492 err = adnp_gpio_setup(adnp, num_gpios, device_property_read_bool(dev, "interrupt-controller")); in adnp_i2c_probe()
502 { "gpio-adnp" },
508 { .compatible = "ad,gpio-adnp", },
515 .name = "gpio-adnp",
523 MODULE_DESCRIPTION("Avionic Design N-bit GPIO expander");
524 MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");