Lines Matching +full:gpio +full:- +full:trigger

1 // SPDX-License-Identifier: GPL-2.0
3 * TQ-Systems TQMx86 PLD GPIO driver
12 #include <linux/gpio/driver.h>
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 */
27 #define TQMX86_GPIODD 0 /* GPIO Data Direction Register */
28 #define TQMX86_GPIOD 1 /* GPIO Data Register */
60 return ioread8(gd->io_base + reg); in tqmx86_gpio_read()
66 iowrite8(val, gd->io_base + reg); in tqmx86_gpio_write()
69 static void tqmx86_gpio_clrsetbits(struct tqmx86_gpio_data *gpio, in tqmx86_gpio_clrsetbits() argument
71 __must_hold(&gpio->spinlock) in tqmx86_gpio_clrsetbits()
73 u8 val = tqmx86_gpio_read(gpio, reg); in tqmx86_gpio_clrsetbits()
78 tqmx86_gpio_write(gpio, val, reg); in tqmx86_gpio_clrsetbits()
83 struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip); in tqmx86_gpio_get() local
85 return !!(tqmx86_gpio_read(gpio, TQMX86_GPIOD) & BIT(offset)); in tqmx86_gpio_get()
88 static void _tqmx86_gpio_set(struct tqmx86_gpio_data *gpio, unsigned int offset, in _tqmx86_gpio_set() argument
90 __must_hold(&gpio->spinlock) in _tqmx86_gpio_set()
92 __assign_bit(offset, gpio->output, value); in _tqmx86_gpio_set()
93 tqmx86_gpio_write(gpio, bitmap_get_value8(gpio->output, 0), TQMX86_GPIOD); in _tqmx86_gpio_set()
99 struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip); in tqmx86_gpio_set() local
101 guard(raw_spinlock_irqsave)(&gpio->spinlock); in tqmx86_gpio_set()
103 _tqmx86_gpio_set(gpio, offset, value); in tqmx86_gpio_set()
111 struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip); in tqmx86_gpio_direction_input() local
113 guard(raw_spinlock_irqsave)(&gpio->spinlock); in tqmx86_gpio_direction_input()
115 tqmx86_gpio_clrsetbits(gpio, BIT(offset), 0, TQMX86_GPIODD); in tqmx86_gpio_direction_input()
124 struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip); in tqmx86_gpio_direction_output() local
126 guard(raw_spinlock_irqsave)(&gpio->spinlock); in tqmx86_gpio_direction_output()
128 _tqmx86_gpio_set(gpio, offset, value); in tqmx86_gpio_direction_output()
129 tqmx86_gpio_clrsetbits(gpio, 0, BIT(offset), TQMX86_GPIODD); in tqmx86_gpio_direction_output()
137 struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip); in tqmx86_gpio_get_direction() local
140 val = tqmx86_gpio_read(gpio, TQMX86_GPIODD); in tqmx86_gpio_get_direction()
148 static void tqmx86_gpio_irq_config(struct tqmx86_gpio_data *gpio, int hwirq) in tqmx86_gpio_irq_config() argument
149 __must_hold(&gpio->spinlock) in tqmx86_gpio_irq_config()
152 int gpiic_irq = hwirq - TQMX86_NGPO; in tqmx86_gpio_irq_config()
154 if (gpio->irq_type[hwirq] & TQMX86_INT_UNMASKED) { in tqmx86_gpio_irq_config()
155 type = gpio->irq_type[hwirq] & TQMX86_INT_TRIG_MASK; in tqmx86_gpio_irq_config()
158 type = tqmx86_gpio_get(&gpio->chip, hwirq) in tqmx86_gpio_irq_config()
163 tqmx86_gpio_clrsetbits(gpio, in tqmx86_gpio_irq_config()
171 struct tqmx86_gpio_data *gpio = gpiochip_get_data( in tqmx86_gpio_irq_mask() local
174 scoped_guard(raw_spinlock_irqsave, &gpio->spinlock) { in tqmx86_gpio_irq_mask()
175 gpio->irq_type[data->hwirq] &= ~TQMX86_INT_UNMASKED; in tqmx86_gpio_irq_mask()
176 tqmx86_gpio_irq_config(gpio, data->hwirq); in tqmx86_gpio_irq_mask()
179 gpiochip_disable_irq(&gpio->chip, irqd_to_hwirq(data)); in tqmx86_gpio_irq_mask()
184 struct tqmx86_gpio_data *gpio = gpiochip_get_data( in tqmx86_gpio_irq_unmask() local
187 gpiochip_enable_irq(&gpio->chip, irqd_to_hwirq(data)); in tqmx86_gpio_irq_unmask()
189 guard(raw_spinlock_irqsave)(&gpio->spinlock); in tqmx86_gpio_irq_unmask()
191 gpio->irq_type[data->hwirq] |= TQMX86_INT_UNMASKED; in tqmx86_gpio_irq_unmask()
192 tqmx86_gpio_irq_config(gpio, data->hwirq); in tqmx86_gpio_irq_unmask()
197 struct tqmx86_gpio_data *gpio = gpiochip_get_data( in tqmx86_gpio_irq_set_type() local
213 return -EINVAL; /* not supported */ in tqmx86_gpio_irq_set_type()
216 guard(raw_spinlock_irqsave)(&gpio->spinlock); in tqmx86_gpio_irq_set_type()
218 gpio->irq_type[data->hwirq] &= ~TQMX86_INT_TRIG_MASK; in tqmx86_gpio_irq_set_type()
219 gpio->irq_type[data->hwirq] |= new_type; in tqmx86_gpio_irq_set_type()
220 tqmx86_gpio_irq_config(gpio, data->hwirq); in tqmx86_gpio_irq_set_type()
228 struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip); in tqmx86_gpio_irq_handler() local
236 irq_status = tqmx86_gpio_read(gpio, TQMX86_GPIIS); in tqmx86_gpio_irq_handler()
237 tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS); in tqmx86_gpio_irq_handler()
241 scoped_guard(raw_spinlock_irqsave, &gpio->spinlock) { in tqmx86_gpio_irq_handler()
246 * Edge-both triggers are implemented by flipping the in tqmx86_gpio_irq_handler()
247 * edge trigger after each interrupt, as the controller in tqmx86_gpio_irq_handler()
251 * Internally, the TQMx86 GPIO controller has separate in tqmx86_gpio_irq_handler()
258 * currently configured trigger. in tqmx86_gpio_irq_handler()
261 * edge-both trigger in software by first clearing the in tqmx86_gpio_irq_handler()
262 * interrupt and then setting the new trigger based on in tqmx86_gpio_irq_handler()
263 * the current GPIO input in tqmx86_gpio_irq_config() - in tqmx86_gpio_irq_handler()
265 * setting the trigger, we will have a new interrupt in tqmx86_gpio_irq_handler()
268 if ((gpio->irq_type[hwirq] & TQMX86_INT_TRIG_MASK) == in tqmx86_gpio_irq_handler()
270 tqmx86_gpio_irq_config(gpio, hwirq); in tqmx86_gpio_irq_handler()
275 generic_handle_domain_irq(gpio->chip.irq.domain, in tqmx86_gpio_irq_handler()
301 /* Only GPIOs 4-7 are valid for interrupts. Clear the others */ in tqmx86_init_irq_valid_mask()
312 seq_puts(p, gc->label); in tqmx86_gpio_irq_print_chip()
326 struct device *dev = &pdev->dev; in tqmx86_gpio_probe()
327 struct tqmx86_gpio_data *gpio; in tqmx86_gpio_probe() local
335 if (irq < 0 && irq != -ENXIO) in tqmx86_gpio_probe()
340 dev_err(&pdev->dev, "Cannot get I/O\n"); in tqmx86_gpio_probe()
341 return -ENODEV; in tqmx86_gpio_probe()
344 io_base = devm_ioport_map(&pdev->dev, res->start, resource_size(res)); in tqmx86_gpio_probe()
346 return -ENOMEM; in tqmx86_gpio_probe()
348 gpio = devm_kzalloc(dev, sizeof(*gpio), GFP_KERNEL); in tqmx86_gpio_probe()
349 if (!gpio) in tqmx86_gpio_probe()
350 return -ENOMEM; in tqmx86_gpio_probe()
352 raw_spin_lock_init(&gpio->spinlock); in tqmx86_gpio_probe()
353 gpio->io_base = io_base; in tqmx86_gpio_probe()
355 tqmx86_gpio_write(gpio, (u8)~TQMX86_DIR_INPUT_MASK, TQMX86_GPIODD); in tqmx86_gpio_probe()
362 tqmx86_gpio_write(gpio, 0, TQMX86_GPIOD); in tqmx86_gpio_probe()
364 chip = &gpio->chip; in tqmx86_gpio_probe()
365 chip->label = "gpio-tqmx86"; in tqmx86_gpio_probe()
366 chip->owner = THIS_MODULE; in tqmx86_gpio_probe()
367 chip->can_sleep = false; in tqmx86_gpio_probe()
368 chip->base = -1; in tqmx86_gpio_probe()
369 chip->direction_input = tqmx86_gpio_direction_input; in tqmx86_gpio_probe()
370 chip->direction_output = tqmx86_gpio_direction_output; in tqmx86_gpio_probe()
371 chip->get_direction = tqmx86_gpio_get_direction; in tqmx86_gpio_probe()
372 chip->get = tqmx86_gpio_get; in tqmx86_gpio_probe()
373 chip->set = tqmx86_gpio_set; in tqmx86_gpio_probe()
374 chip->ngpio = TQMX86_NGPIO; in tqmx86_gpio_probe()
375 chip->parent = pdev->dev.parent; in tqmx86_gpio_probe()
377 pm_runtime_enable(&pdev->dev); in tqmx86_gpio_probe()
383 tqmx86_gpio_write(gpio, 0, TQMX86_GPIIC); in tqmx86_gpio_probe()
386 irq_status = tqmx86_gpio_read(gpio, TQMX86_GPIIS); in tqmx86_gpio_probe()
387 tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS); in tqmx86_gpio_probe()
389 girq = &chip->irq; in tqmx86_gpio_probe()
391 girq->parent_handler = tqmx86_gpio_irq_handler; in tqmx86_gpio_probe()
392 girq->num_parents = 1; in tqmx86_gpio_probe()
393 girq->parents = devm_kcalloc(&pdev->dev, 1, in tqmx86_gpio_probe()
394 sizeof(*girq->parents), in tqmx86_gpio_probe()
396 if (!girq->parents) { in tqmx86_gpio_probe()
397 ret = -ENOMEM; in tqmx86_gpio_probe()
400 girq->parents[0] = irq; in tqmx86_gpio_probe()
401 girq->default_type = IRQ_TYPE_NONE; in tqmx86_gpio_probe()
402 girq->handler = handle_simple_irq; in tqmx86_gpio_probe()
403 girq->init_valid_mask = tqmx86_init_irq_valid_mask; in tqmx86_gpio_probe()
405 irq_domain_set_pm_device(girq->domain, dev); in tqmx86_gpio_probe()
408 ret = devm_gpiochip_add_data(dev, chip, gpio); in tqmx86_gpio_probe()
410 dev_err(dev, "Could not register GPIO chip\n"); in tqmx86_gpio_probe()
414 dev_info(dev, "GPIO functionality initialized with %d pins\n", in tqmx86_gpio_probe()
415 chip->ngpio); in tqmx86_gpio_probe()
420 pm_runtime_disable(&pdev->dev); in tqmx86_gpio_probe()
427 .name = "tqmx86-gpio",
435 MODULE_DESCRIPTION("TQMx86 PLD GPIO Driver");
438 MODULE_ALIAS("platform:tqmx86-gpio");