Lines Matching +full:irq +full:- +full:can +full:- +full:wake
1 // SPDX-License-Identifier: GPL-2.0-only
4 * managing 32 pins with alternate functions. It can also handle the STA2X11
7 * The GPIO chips are shared with pinctrl-nomadik if used; it needs access for
10 * This driver also handles the mobileye,eyeq5-gpio compatible. It is an STA2X11
13 * wake and alternate function registers. It is NOT compatible with
14 * pinctrl-nomadik.
19 * Copyright (C) 2011-2013 Linus Walleij <linus.walleij@linaro.org>
36 #include <linux/gpio/gpio-nomadik.h>
48 if (WARN_ON(nmk_chip->is_mobileye_soc)) in __nmk_gpio_set_slpm()
51 slpm = readl(nmk_chip->addr + NMK_GPIO_SLPC); in __nmk_gpio_set_slpm()
56 writel(slpm, nmk_chip->addr + NMK_GPIO_SLPC); in __nmk_gpio_set_slpm()
63 writel(BIT(offset), nmk_chip->addr + NMK_GPIO_DATS); in __nmk_gpio_set_output()
65 writel(BIT(offset), nmk_chip->addr + NMK_GPIO_DATC); in __nmk_gpio_set_output()
71 writel(BIT(offset), nmk_chip->addr + NMK_GPIO_DIRS); in __nmk_gpio_make_output()
75 /* IRQ functions */
82 clk_enable(nmk_chip->clk); in nmk_gpio_irq_ack()
83 writel(BIT(d->hwirq), nmk_chip->addr + NMK_GPIO_IC); in nmk_gpio_irq_ack()
84 clk_disable(nmk_chip->clk); in nmk_gpio_irq_ack()
89 WAKE, enumerator
104 rimscval = &nmk_chip->rimsc; in __nmk_gpio_irq_modify()
105 fimscval = &nmk_chip->fimsc; in __nmk_gpio_irq_modify()
108 if (WARN_ON(nmk_chip->is_mobileye_soc)) in __nmk_gpio_irq_modify()
112 rimscval = &nmk_chip->rwimsc; in __nmk_gpio_irq_modify()
113 fimscval = &nmk_chip->fwimsc; in __nmk_gpio_irq_modify()
117 if (nmk_chip->edge_rising & BIT(offset)) { in __nmk_gpio_irq_modify()
122 writel(*rimscval, nmk_chip->addr + rimscreg); in __nmk_gpio_irq_modify()
124 if (nmk_chip->edge_falling & BIT(offset)) { in __nmk_gpio_irq_modify()
129 writel(*fimscval, nmk_chip->addr + fimscreg); in __nmk_gpio_irq_modify()
137 if (WARN_ON(nmk_chip->is_mobileye_soc)) in __nmk_gpio_set_wake()
145 if (nmk_chip->sleepmode && on) { in __nmk_gpio_set_wake()
150 __nmk_gpio_irq_modify(nmk_chip, offset, WAKE, on); in __nmk_gpio_set_wake()
158 clk_enable(nmk_chip->clk); in nmk_gpio_irq_maskunmask()
160 spin_lock(&nmk_chip->lock); in nmk_gpio_irq_maskunmask()
162 __nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, enable); in nmk_gpio_irq_maskunmask()
164 if (!nmk_chip->is_mobileye_soc && !(nmk_chip->real_wake & BIT(d->hwirq))) in nmk_gpio_irq_maskunmask()
165 __nmk_gpio_set_wake(nmk_chip, d->hwirq, enable); in nmk_gpio_irq_maskunmask()
167 spin_unlock(&nmk_chip->lock); in nmk_gpio_irq_maskunmask()
169 clk_disable(nmk_chip->clk); in nmk_gpio_irq_maskunmask()
197 if (nmk_chip->is_mobileye_soc) in nmk_gpio_irq_set_wake()
198 return -ENXIO; in nmk_gpio_irq_set_wake()
200 clk_enable(nmk_chip->clk); in nmk_gpio_irq_set_wake()
202 spin_lock(&nmk_chip->lock); in nmk_gpio_irq_set_wake()
205 __nmk_gpio_set_wake(nmk_chip, d->hwirq, on); in nmk_gpio_irq_set_wake()
208 nmk_chip->real_wake |= BIT(d->hwirq); in nmk_gpio_irq_set_wake()
210 nmk_chip->real_wake &= ~BIT(d->hwirq); in nmk_gpio_irq_set_wake()
212 spin_unlock(&nmk_chip->lock); in nmk_gpio_irq_set_wake()
214 clk_disable(nmk_chip->clk); in nmk_gpio_irq_set_wake()
224 bool wake = irqd_is_wakeup_set(d); in nmk_gpio_irq_set_type() local
228 return -EINVAL; in nmk_gpio_irq_set_type()
230 return -EINVAL; in nmk_gpio_irq_set_type()
232 clk_enable(nmk_chip->clk); in nmk_gpio_irq_set_type()
233 spin_lock_irqsave(&nmk_chip->lock, flags); in nmk_gpio_irq_set_type()
236 __nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, false); in nmk_gpio_irq_set_type()
238 if (!nmk_chip->is_mobileye_soc && (enabled || wake)) in nmk_gpio_irq_set_type()
239 __nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, false); in nmk_gpio_irq_set_type()
241 nmk_chip->edge_rising &= ~BIT(d->hwirq); in nmk_gpio_irq_set_type()
243 nmk_chip->edge_rising |= BIT(d->hwirq); in nmk_gpio_irq_set_type()
245 nmk_chip->edge_falling &= ~BIT(d->hwirq); in nmk_gpio_irq_set_type()
247 nmk_chip->edge_falling |= BIT(d->hwirq); in nmk_gpio_irq_set_type()
250 __nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, true); in nmk_gpio_irq_set_type()
252 if (!nmk_chip->is_mobileye_soc && (enabled || wake)) in nmk_gpio_irq_set_type()
253 __nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, true); in nmk_gpio_irq_set_type()
255 spin_unlock_irqrestore(&nmk_chip->lock, flags); in nmk_gpio_irq_set_type()
256 clk_disable(nmk_chip->clk); in nmk_gpio_irq_set_type()
266 clk_enable(nmk_chip->clk); in nmk_gpio_irq_startup()
277 clk_disable(nmk_chip->clk); in nmk_gpio_irq_shutdown()
280 static irqreturn_t nmk_gpio_irq_handler(int irq, void *dev_id) in nmk_gpio_irq_handler() argument
283 struct gpio_chip *chip = &nmk_chip->chip; in nmk_gpio_irq_handler()
284 unsigned long mask = GENMASK(chip->ngpio - 1, 0); in nmk_gpio_irq_handler()
288 clk_enable(nmk_chip->clk); in nmk_gpio_irq_handler()
290 status = readl(nmk_chip->addr + NMK_GPIO_IS); in nmk_gpio_irq_handler()
294 writel(status & ~mask, nmk_chip->addr + NMK_GPIO_IC); in nmk_gpio_irq_handler()
296 clk_disable(nmk_chip->clk); in nmk_gpio_irq_handler()
298 for_each_set_bit(bit, &status, chip->ngpio) in nmk_gpio_irq_handler()
299 generic_handle_domain_irq_safe(chip->irq.domain, bit); in nmk_gpio_irq_handler()
311 clk_enable(nmk_chip->clk); in nmk_gpio_get_dir()
313 dir = readl(nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset); in nmk_gpio_get_dir()
315 clk_disable(nmk_chip->clk); in nmk_gpio_get_dir()
327 clk_enable(nmk_chip->clk); in nmk_gpio_make_input()
329 writel(BIT(offset), nmk_chip->addr + NMK_GPIO_DIRC); in nmk_gpio_make_input()
331 clk_disable(nmk_chip->clk); in nmk_gpio_make_input()
341 clk_enable(nmk_chip->clk); in nmk_gpio_get_input()
343 value = !!(readl(nmk_chip->addr + NMK_GPIO_DAT) & BIT(offset)); in nmk_gpio_get_input()
345 clk_disable(nmk_chip->clk); in nmk_gpio_get_input()
355 clk_enable(nmk_chip->clk); in nmk_gpio_set_output()
359 clk_disable(nmk_chip->clk); in nmk_gpio_set_output()
367 clk_enable(nmk_chip->clk); in nmk_gpio_make_output()
371 clk_disable(nmk_chip->clk); in nmk_gpio_make_output()
383 if (nmk_chip->is_mobileye_soc) in nmk_gpio_get_mode()
386 clk_enable(nmk_chip->clk); in nmk_gpio_get_mode()
388 afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & BIT(offset); in nmk_gpio_get_mode()
389 bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & BIT(offset); in nmk_gpio_get_mode()
391 clk_disable(nmk_chip->clk); in nmk_gpio_get_mode()
420 clk_enable(nmk_chip->clk); in nmk_gpio_dbg_show_one()
421 is_out = !!(readl(nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset)); in nmk_gpio_dbg_show_one()
422 pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & BIT(offset)); in nmk_gpio_dbg_show_one()
423 data_out = !!(readl(nmk_chip->addr + NMK_GPIO_DAT) & BIT(offset)); in nmk_gpio_dbg_show_one()
431 seq_printf(s, " gpio-%-3d (%-20.20s) out %s %s", in nmk_gpio_dbg_show_one()
437 int irq = chip->to_irq(chip, offset); in nmk_gpio_dbg_show_one() local
445 seq_printf(s, " gpio-%-3d (%-20.20s) in %s %s", in nmk_gpio_dbg_show_one()
458 if (irq > 0 && irq_has_action(irq)) { in nmk_gpio_dbg_show_one()
460 bool wake; in nmk_gpio_dbg_show_one() local
462 if (nmk_chip->edge_rising & BIT(offset)) in nmk_gpio_dbg_show_one()
463 trigger = "edge-rising"; in nmk_gpio_dbg_show_one()
464 else if (nmk_chip->edge_falling & BIT(offset)) in nmk_gpio_dbg_show_one()
465 trigger = "edge-falling"; in nmk_gpio_dbg_show_one()
467 trigger = "edge-undefined"; in nmk_gpio_dbg_show_one()
469 wake = !!(nmk_chip->real_wake & BIT(offset)); in nmk_gpio_dbg_show_one()
471 seq_printf(s, " irq-%d %s%s", in nmk_gpio_dbg_show_one()
472 irq, trigger, wake ? " wakeup" : ""); in nmk_gpio_dbg_show_one()
475 clk_disable(nmk_chip->clk); in nmk_gpio_dbg_show_one()
480 unsigned int i, gpio = chip->base; in nmk_gpio_dbg_show()
482 for (i = 0; i < chip->ngpio; i++, gpio++) { in nmk_gpio_dbg_show()
505 struct device *dev = &pdev->dev; in nmk_gpio_populate_chip()
518 return ERR_PTR(-ENODEV); in nmk_gpio_populate_chip()
522 if (device_property_read_u32(gpio_dev, "gpio-bank", &id)) { in nmk_gpio_populate_chip()
523 dev_err(dev, "populate: gpio-bank property not found\n"); in nmk_gpio_populate_chip()
525 return ERR_PTR(-EINVAL); in nmk_gpio_populate_chip()
532 return ERR_PTR(-EINVAL); in nmk_gpio_populate_chip()
545 return ERR_PTR(-ENOMEM); in nmk_gpio_populate_chip()
553 nmk_chip->is_mobileye_soc = device_is_compatible(gpio_dev, in nmk_gpio_populate_chip()
554 "mobileye,eyeq5-gpio"); in nmk_gpio_populate_chip()
555 nmk_chip->bank = id; in nmk_gpio_populate_chip()
556 chip = &nmk_chip->chip; in nmk_gpio_populate_chip()
557 chip->base = -1; in nmk_gpio_populate_chip()
558 chip->ngpio = ngpio; in nmk_gpio_populate_chip()
559 chip->label = dev_name(gpio_dev); in nmk_gpio_populate_chip()
560 chip->parent = gpio_dev; in nmk_gpio_populate_chip()
569 nmk_chip->addr = base; in nmk_gpio_populate_chip()
578 nmk_chip->clk = clk; in nmk_gpio_populate_chip()
593 * only support sharing this reset with other gpio-nomadik devices that in nmk_gpio_populate_chip()
617 seq_printf(p, "nmk%u-%u-%u", nmk_chip->bank, in nmk_gpio_irq_print_chip()
618 gc->base, gc->base + gc->ngpio - 1); in nmk_gpio_irq_print_chip()
636 struct device *dev = &pdev->dev; in nmk_gpio_probe()
641 int irq; in nmk_gpio_probe() local
651 device_property_read_bool(dev, "st,supports-sleepmode"); in nmk_gpio_probe()
654 pdev->id = nmk_chip->bank; in nmk_gpio_probe()
656 irq = platform_get_irq(pdev, 0); in nmk_gpio_probe()
657 if (irq < 0) in nmk_gpio_probe()
658 return irq; in nmk_gpio_probe()
661 * The virt address in nmk_chip->addr is in the nomadik register space, in nmk_gpio_probe()
662 * so we can simply convert the resource address, without remapping in nmk_gpio_probe()
664 nmk_chip->sleepmode = supports_sleepmode; in nmk_gpio_probe()
665 spin_lock_init(&nmk_chip->lock); in nmk_gpio_probe()
667 chip = &nmk_chip->chip; in nmk_gpio_probe()
668 chip->parent = dev; in nmk_gpio_probe()
669 chip->request = gpiochip_generic_request; in nmk_gpio_probe()
670 chip->free = gpiochip_generic_free; in nmk_gpio_probe()
671 chip->get_direction = nmk_gpio_get_dir; in nmk_gpio_probe()
672 chip->direction_input = nmk_gpio_make_input; in nmk_gpio_probe()
673 chip->get = nmk_gpio_get_input; in nmk_gpio_probe()
674 chip->direction_output = nmk_gpio_make_output; in nmk_gpio_probe()
675 chip->set = nmk_gpio_set_output; in nmk_gpio_probe()
676 chip->dbg_show = nmk_gpio_dbg_show; in nmk_gpio_probe()
677 chip->can_sleep = false; in nmk_gpio_probe()
678 chip->owner = THIS_MODULE; in nmk_gpio_probe()
680 girq = &chip->irq; in nmk_gpio_probe()
682 girq->parent_handler = NULL; in nmk_gpio_probe()
683 girq->num_parents = 0; in nmk_gpio_probe()
684 girq->parents = NULL; in nmk_gpio_probe()
685 girq->default_type = IRQ_TYPE_NONE; in nmk_gpio_probe()
686 girq->handler = handle_edge_irq; in nmk_gpio_probe()
688 ret = devm_request_irq(dev, irq, nmk_gpio_irq_handler, IRQF_SHARED, in nmk_gpio_probe()
691 dev_err(dev, "failed requesting IRQ\n"); in nmk_gpio_probe()
695 if (!nmk_chip->is_mobileye_soc) { in nmk_gpio_probe()
696 clk_enable(nmk_chip->clk); in nmk_gpio_probe()
697 nmk_chip->lowemi = readl_relaxed(nmk_chip->addr + NMK_GPIO_LOWEMI); in nmk_gpio_probe()
698 clk_disable(nmk_chip->clk); in nmk_gpio_probe()
713 { .compatible = "st,nomadik-gpio", },
714 { .compatible = "mobileye,eyeq5-gpio", },
720 .name = "nomadik-gpio",