Lines Matching +full:edge +full:- +full:offset
1 // SPDX-License-Identifier: GPL-2.0
3 * TQ-Systems TQMx86 PLD GPIO driver
23 #define TQMX86_NGPO 4 /* 0-3 - output */
24 #define TQMX86_NGPI 4 /* 4-7 - input */
25 #define TQMX86_DIR_INPUT_MASK 0xf0 /* 0-3 - output, 4-7 - input */
56 return ioread8(gd->io_base + reg); in tqmx86_gpio_read()
62 iowrite8(val, gd->io_base + reg); in tqmx86_gpio_write()
65 static int tqmx86_gpio_get(struct gpio_chip *chip, unsigned int offset) in tqmx86_gpio_get() argument
69 return !!(tqmx86_gpio_read(gpio, TQMX86_GPIOD) & BIT(offset)); in tqmx86_gpio_get()
72 static void tqmx86_gpio_set(struct gpio_chip *chip, unsigned int offset, in tqmx86_gpio_set() argument
78 raw_spin_lock_irqsave(&gpio->spinlock, flags); in tqmx86_gpio_set()
79 __assign_bit(offset, gpio->output, value); in tqmx86_gpio_set()
80 tqmx86_gpio_write(gpio, bitmap_get_value8(gpio->output, 0), TQMX86_GPIOD); in tqmx86_gpio_set()
81 raw_spin_unlock_irqrestore(&gpio->spinlock, flags); in tqmx86_gpio_set()
85 unsigned int offset) in tqmx86_gpio_direction_input() argument
88 if (BIT(offset) & TQMX86_DIR_INPUT_MASK) in tqmx86_gpio_direction_input()
91 return -EINVAL; in tqmx86_gpio_direction_input()
95 unsigned int offset, in tqmx86_gpio_direction_output() argument
99 if (BIT(offset) & TQMX86_DIR_INPUT_MASK) in tqmx86_gpio_direction_output()
100 return -EINVAL; in tqmx86_gpio_direction_output()
102 tqmx86_gpio_set(chip, offset, value); in tqmx86_gpio_direction_output()
107 unsigned int offset) in tqmx86_gpio_get_direction() argument
109 if (TQMX86_DIR_INPUT_MASK & BIT(offset)) in tqmx86_gpio_get_direction()
115 static void tqmx86_gpio_irq_config(struct tqmx86_gpio_data *gpio, int offset) in tqmx86_gpio_irq_config() argument
116 __must_hold(&gpio->spinlock) in tqmx86_gpio_irq_config()
120 if (gpio->irq_type[offset] & TQMX86_INT_UNMASKED) { in tqmx86_gpio_irq_config()
121 type = gpio->irq_type[offset] & TQMX86_GPII_MASK; in tqmx86_gpio_irq_config()
124 type = tqmx86_gpio_get(&gpio->chip, offset + TQMX86_NGPO) in tqmx86_gpio_irq_config()
130 gpiic &= ~(TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS)); in tqmx86_gpio_irq_config()
131 gpiic |= type << (offset * TQMX86_GPII_BITS); in tqmx86_gpio_irq_config()
137 unsigned int offset = (data->hwirq - TQMX86_NGPO); in tqmx86_gpio_irq_mask() local
142 raw_spin_lock_irqsave(&gpio->spinlock, flags); in tqmx86_gpio_irq_mask()
143 gpio->irq_type[offset] &= ~TQMX86_INT_UNMASKED; in tqmx86_gpio_irq_mask()
144 tqmx86_gpio_irq_config(gpio, offset); in tqmx86_gpio_irq_mask()
145 raw_spin_unlock_irqrestore(&gpio->spinlock, flags); in tqmx86_gpio_irq_mask()
147 gpiochip_disable_irq(&gpio->chip, irqd_to_hwirq(data)); in tqmx86_gpio_irq_mask()
152 unsigned int offset = (data->hwirq - TQMX86_NGPO); in tqmx86_gpio_irq_unmask() local
157 gpiochip_enable_irq(&gpio->chip, irqd_to_hwirq(data)); in tqmx86_gpio_irq_unmask()
159 raw_spin_lock_irqsave(&gpio->spinlock, flags); in tqmx86_gpio_irq_unmask()
160 gpio->irq_type[offset] |= TQMX86_INT_UNMASKED; in tqmx86_gpio_irq_unmask()
161 tqmx86_gpio_irq_config(gpio, offset); in tqmx86_gpio_irq_unmask()
162 raw_spin_unlock_irqrestore(&gpio->spinlock, flags); in tqmx86_gpio_irq_unmask()
169 unsigned int offset = (data->hwirq - TQMX86_NGPO); in tqmx86_gpio_irq_set_type() local
185 return -EINVAL; /* not supported */ in tqmx86_gpio_irq_set_type()
188 raw_spin_lock_irqsave(&gpio->spinlock, flags); in tqmx86_gpio_irq_set_type()
189 gpio->irq_type[offset] &= ~TQMX86_GPII_MASK; in tqmx86_gpio_irq_set_type()
190 gpio->irq_type[offset] |= new_type; in tqmx86_gpio_irq_set_type()
191 tqmx86_gpio_irq_config(gpio, offset); in tqmx86_gpio_irq_set_type()
192 raw_spin_unlock_irqrestore(&gpio->spinlock, flags); in tqmx86_gpio_irq_set_type()
213 raw_spin_lock_irqsave(&gpio->spinlock, flags); in tqmx86_gpio_irq_handler()
216 * Edge-both triggers are implemented by flipping the edge in tqmx86_gpio_irq_handler()
218 * either rising or falling edge triggers, but not both. in tqmx86_gpio_irq_handler()
221 * registers for rising and falling edge interrupts. GPIIC in tqmx86_gpio_irq_handler()
228 * In consequence, we can cleanly implement the edge-both in tqmx86_gpio_irq_handler()
231 * tqmx86_gpio_irq_config() - even if an edge arrives between in tqmx86_gpio_irq_handler()
235 if ((gpio->irq_type[i] & TQMX86_GPII_MASK) == TQMX86_INT_BOTH) in tqmx86_gpio_irq_handler()
238 raw_spin_unlock_irqrestore(&gpio->spinlock, flags); in tqmx86_gpio_irq_handler()
241 generic_handle_domain_irq(gpio->chip.irq.domain, in tqmx86_gpio_irq_handler()
267 /* Only GPIOs 4-7 are valid for interrupts. Clear the others */ in tqmx86_init_irq_valid_mask()
278 seq_printf(p, gc->label); in tqmx86_gpio_irq_print_chip()
292 struct device *dev = &pdev->dev; in tqmx86_gpio_probe()
301 if (irq < 0 && irq != -ENXIO) in tqmx86_gpio_probe()
306 dev_err(&pdev->dev, "Cannot get I/O\n"); in tqmx86_gpio_probe()
307 return -ENODEV; in tqmx86_gpio_probe()
310 io_base = devm_ioport_map(&pdev->dev, res->start, resource_size(res)); in tqmx86_gpio_probe()
312 return -ENOMEM; in tqmx86_gpio_probe()
316 return -ENOMEM; in tqmx86_gpio_probe()
318 raw_spin_lock_init(&gpio->spinlock); in tqmx86_gpio_probe()
319 gpio->io_base = io_base; in tqmx86_gpio_probe()
330 chip = &gpio->chip; in tqmx86_gpio_probe()
331 chip->label = "gpio-tqmx86"; in tqmx86_gpio_probe()
332 chip->owner = THIS_MODULE; in tqmx86_gpio_probe()
333 chip->can_sleep = false; in tqmx86_gpio_probe()
334 chip->base = -1; in tqmx86_gpio_probe()
335 chip->direction_input = tqmx86_gpio_direction_input; in tqmx86_gpio_probe()
336 chip->direction_output = tqmx86_gpio_direction_output; in tqmx86_gpio_probe()
337 chip->get_direction = tqmx86_gpio_get_direction; in tqmx86_gpio_probe()
338 chip->get = tqmx86_gpio_get; in tqmx86_gpio_probe()
339 chip->set = tqmx86_gpio_set; in tqmx86_gpio_probe()
340 chip->ngpio = TQMX86_NGPIO; in tqmx86_gpio_probe()
341 chip->parent = pdev->dev.parent; in tqmx86_gpio_probe()
343 pm_runtime_enable(&pdev->dev); in tqmx86_gpio_probe()
355 girq = &chip->irq; in tqmx86_gpio_probe()
357 girq->parent_handler = tqmx86_gpio_irq_handler; in tqmx86_gpio_probe()
358 girq->num_parents = 1; in tqmx86_gpio_probe()
359 girq->parents = devm_kcalloc(&pdev->dev, 1, in tqmx86_gpio_probe()
360 sizeof(*girq->parents), in tqmx86_gpio_probe()
362 if (!girq->parents) { in tqmx86_gpio_probe()
363 ret = -ENOMEM; in tqmx86_gpio_probe()
366 girq->parents[0] = irq; in tqmx86_gpio_probe()
367 girq->default_type = IRQ_TYPE_NONE; in tqmx86_gpio_probe()
368 girq->handler = handle_simple_irq; in tqmx86_gpio_probe()
369 girq->init_valid_mask = tqmx86_init_irq_valid_mask; in tqmx86_gpio_probe()
371 irq_domain_set_pm_device(girq->domain, dev); in tqmx86_gpio_probe()
381 chip->ngpio); in tqmx86_gpio_probe()
386 pm_runtime_disable(&pdev->dev); in tqmx86_gpio_probe()
393 .name = "tqmx86-gpio",
404 MODULE_ALIAS("platform:tqmx86-gpio");