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>
35 #include <linux/gpio/gpio-nomadik.h>
47 if (WARN_ON(nmk_chip->is_mobileye_soc)) in __nmk_gpio_set_slpm()
50 slpm = readl(nmk_chip->addr + NMK_GPIO_SLPC); in __nmk_gpio_set_slpm()
55 writel(slpm, nmk_chip->addr + NMK_GPIO_SLPC); in __nmk_gpio_set_slpm()
62 writel(BIT(offset), nmk_chip->addr + NMK_GPIO_DATS); in __nmk_gpio_set_output()
64 writel(BIT(offset), nmk_chip->addr + NMK_GPIO_DATC); in __nmk_gpio_set_output()
70 writel(BIT(offset), nmk_chip->addr + NMK_GPIO_DIRS); in __nmk_gpio_make_output()
74 /* IRQ functions */
81 clk_enable(nmk_chip->clk); in nmk_gpio_irq_ack()
82 writel(BIT(d->hwirq), nmk_chip->addr + NMK_GPIO_IC); in nmk_gpio_irq_ack()
83 clk_disable(nmk_chip->clk); in nmk_gpio_irq_ack()
88 WAKE, enumerator
103 rimscval = &nmk_chip->rimsc; in __nmk_gpio_irq_modify()
104 fimscval = &nmk_chip->fimsc; in __nmk_gpio_irq_modify()
107 if (WARN_ON(nmk_chip->is_mobileye_soc)) in __nmk_gpio_irq_modify()
111 rimscval = &nmk_chip->rwimsc; in __nmk_gpio_irq_modify()
112 fimscval = &nmk_chip->fwimsc; in __nmk_gpio_irq_modify()
116 if (nmk_chip->edge_rising & BIT(offset)) { in __nmk_gpio_irq_modify()
121 writel(*rimscval, nmk_chip->addr + rimscreg); in __nmk_gpio_irq_modify()
123 if (nmk_chip->edge_falling & BIT(offset)) { in __nmk_gpio_irq_modify()
128 writel(*fimscval, nmk_chip->addr + fimscreg); in __nmk_gpio_irq_modify()
136 if (WARN_ON(nmk_chip->is_mobileye_soc)) in __nmk_gpio_set_wake()
144 if (nmk_chip->sleepmode && on) { in __nmk_gpio_set_wake()
149 __nmk_gpio_irq_modify(nmk_chip, offset, WAKE, on); in __nmk_gpio_set_wake()
157 clk_enable(nmk_chip->clk); in nmk_gpio_irq_maskunmask()
159 spin_lock(&nmk_chip->lock); in nmk_gpio_irq_maskunmask()
161 __nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, enable); in nmk_gpio_irq_maskunmask()
163 if (!nmk_chip->is_mobileye_soc && !(nmk_chip->real_wake & BIT(d->hwirq))) in nmk_gpio_irq_maskunmask()
164 __nmk_gpio_set_wake(nmk_chip, d->hwirq, enable); in nmk_gpio_irq_maskunmask()
166 spin_unlock(&nmk_chip->lock); in nmk_gpio_irq_maskunmask()
168 clk_disable(nmk_chip->clk); in nmk_gpio_irq_maskunmask()
196 if (nmk_chip->is_mobileye_soc) in nmk_gpio_irq_set_wake()
197 return -ENXIO; in nmk_gpio_irq_set_wake()
199 clk_enable(nmk_chip->clk); in nmk_gpio_irq_set_wake()
201 spin_lock(&nmk_chip->lock); in nmk_gpio_irq_set_wake()
204 __nmk_gpio_set_wake(nmk_chip, d->hwirq, on); in nmk_gpio_irq_set_wake()
207 nmk_chip->real_wake |= BIT(d->hwirq); in nmk_gpio_irq_set_wake()
209 nmk_chip->real_wake &= ~BIT(d->hwirq); in nmk_gpio_irq_set_wake()
211 spin_unlock(&nmk_chip->lock); in nmk_gpio_irq_set_wake()
213 clk_disable(nmk_chip->clk); in nmk_gpio_irq_set_wake()
223 bool wake = irqd_is_wakeup_set(d); in nmk_gpio_irq_set_type() local
227 return -EINVAL; in nmk_gpio_irq_set_type()
229 return -EINVAL; in nmk_gpio_irq_set_type()
231 clk_enable(nmk_chip->clk); in nmk_gpio_irq_set_type()
232 spin_lock_irqsave(&nmk_chip->lock, flags); in nmk_gpio_irq_set_type()
235 __nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, false); in nmk_gpio_irq_set_type()
237 if (!nmk_chip->is_mobileye_soc && (enabled || wake)) in nmk_gpio_irq_set_type()
238 __nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, false); in nmk_gpio_irq_set_type()
240 nmk_chip->edge_rising &= ~BIT(d->hwirq); in nmk_gpio_irq_set_type()
242 nmk_chip->edge_rising |= BIT(d->hwirq); in nmk_gpio_irq_set_type()
244 nmk_chip->edge_falling &= ~BIT(d->hwirq); in nmk_gpio_irq_set_type()
246 nmk_chip->edge_falling |= BIT(d->hwirq); in nmk_gpio_irq_set_type()
249 __nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, true); in nmk_gpio_irq_set_type()
251 if (!nmk_chip->is_mobileye_soc && (enabled || wake)) in nmk_gpio_irq_set_type()
252 __nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, true); in nmk_gpio_irq_set_type()
254 spin_unlock_irqrestore(&nmk_chip->lock, flags); in nmk_gpio_irq_set_type()
255 clk_disable(nmk_chip->clk); in nmk_gpio_irq_set_type()
265 clk_enable(nmk_chip->clk); in nmk_gpio_irq_startup()
276 clk_disable(nmk_chip->clk); in nmk_gpio_irq_shutdown()
279 static irqreturn_t nmk_gpio_irq_handler(int irq, void *dev_id) in nmk_gpio_irq_handler() argument
282 struct gpio_chip *chip = &nmk_chip->chip; in nmk_gpio_irq_handler()
283 unsigned long mask = GENMASK(chip->ngpio - 1, 0); in nmk_gpio_irq_handler()
287 clk_enable(nmk_chip->clk); in nmk_gpio_irq_handler()
289 status = readl(nmk_chip->addr + NMK_GPIO_IS); in nmk_gpio_irq_handler()
293 writel(status & ~mask, nmk_chip->addr + NMK_GPIO_IC); in nmk_gpio_irq_handler()
295 clk_disable(nmk_chip->clk); in nmk_gpio_irq_handler()
297 for_each_set_bit(bit, &status, chip->ngpio) in nmk_gpio_irq_handler()
298 generic_handle_domain_irq_safe(chip->irq.domain, bit); in nmk_gpio_irq_handler()
310 clk_enable(nmk_chip->clk); in nmk_gpio_get_dir()
312 dir = readl(nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset); in nmk_gpio_get_dir()
314 clk_disable(nmk_chip->clk); in nmk_gpio_get_dir()
326 clk_enable(nmk_chip->clk); in nmk_gpio_make_input()
328 writel(BIT(offset), nmk_chip->addr + NMK_GPIO_DIRC); in nmk_gpio_make_input()
330 clk_disable(nmk_chip->clk); in nmk_gpio_make_input()
340 clk_enable(nmk_chip->clk); in nmk_gpio_get_input()
342 value = !!(readl(nmk_chip->addr + NMK_GPIO_DAT) & BIT(offset)); in nmk_gpio_get_input()
344 clk_disable(nmk_chip->clk); in nmk_gpio_get_input()
354 clk_enable(nmk_chip->clk); in nmk_gpio_set_output()
358 clk_disable(nmk_chip->clk); in nmk_gpio_set_output()
366 clk_enable(nmk_chip->clk); in nmk_gpio_make_output()
370 clk_disable(nmk_chip->clk); in nmk_gpio_make_output()
382 if (nmk_chip->is_mobileye_soc) in nmk_gpio_get_mode()
385 clk_enable(nmk_chip->clk); in nmk_gpio_get_mode()
387 afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & BIT(offset); in nmk_gpio_get_mode()
388 bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & BIT(offset); in nmk_gpio_get_mode()
390 clk_disable(nmk_chip->clk); in nmk_gpio_get_mode()
419 clk_enable(nmk_chip->clk); in nmk_gpio_dbg_show_one()
420 is_out = !!(readl(nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset)); in nmk_gpio_dbg_show_one()
421 pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & BIT(offset)); in nmk_gpio_dbg_show_one()
422 data_out = !!(readl(nmk_chip->addr + NMK_GPIO_DAT) & BIT(offset)); in nmk_gpio_dbg_show_one()
430 seq_printf(s, " gpio-%-3d (%-20.20s) out %s %s", in nmk_gpio_dbg_show_one()
436 int irq = chip->to_irq(chip, offset); in nmk_gpio_dbg_show_one() local
444 seq_printf(s, " gpio-%-3d (%-20.20s) in %s %s", in nmk_gpio_dbg_show_one()
457 if (irq > 0 && irq_has_action(irq)) { in nmk_gpio_dbg_show_one()
459 bool wake; in nmk_gpio_dbg_show_one() local
461 if (nmk_chip->edge_rising & BIT(offset)) in nmk_gpio_dbg_show_one()
462 trigger = "edge-rising"; in nmk_gpio_dbg_show_one()
463 else if (nmk_chip->edge_falling & BIT(offset)) in nmk_gpio_dbg_show_one()
464 trigger = "edge-falling"; in nmk_gpio_dbg_show_one()
466 trigger = "edge-undefined"; in nmk_gpio_dbg_show_one()
468 wake = !!(nmk_chip->real_wake & BIT(offset)); in nmk_gpio_dbg_show_one()
470 seq_printf(s, " irq-%d %s%s", in nmk_gpio_dbg_show_one()
471 irq, trigger, wake ? " wakeup" : ""); in nmk_gpio_dbg_show_one()
474 clk_disable(nmk_chip->clk); in nmk_gpio_dbg_show_one()
479 unsigned int i, gpio = chip->base; in nmk_gpio_dbg_show()
481 for (i = 0; i < chip->ngpio; i++, gpio++) { in nmk_gpio_dbg_show()
504 struct device *dev = &pdev->dev; in nmk_gpio_populate_chip()
517 return ERR_PTR(-ENODEV); in nmk_gpio_populate_chip()
521 if (device_property_read_u32(gpio_dev, "gpio-bank", &id)) { in nmk_gpio_populate_chip()
522 dev_err(dev, "populate: gpio-bank property not found\n"); in nmk_gpio_populate_chip()
524 return ERR_PTR(-EINVAL); in nmk_gpio_populate_chip()
531 return ERR_PTR(-EINVAL); in nmk_gpio_populate_chip()
544 return ERR_PTR(-ENOMEM); in nmk_gpio_populate_chip()
552 nmk_chip->is_mobileye_soc = device_is_compatible(gpio_dev, in nmk_gpio_populate_chip()
553 "mobileye,eyeq5-gpio"); in nmk_gpio_populate_chip()
554 nmk_chip->bank = id; in nmk_gpio_populate_chip()
555 chip = &nmk_chip->chip; in nmk_gpio_populate_chip()
556 chip->base = -1; in nmk_gpio_populate_chip()
557 chip->ngpio = ngpio; in nmk_gpio_populate_chip()
558 chip->label = dev_name(gpio_dev); in nmk_gpio_populate_chip()
559 chip->parent = gpio_dev; in nmk_gpio_populate_chip()
568 nmk_chip->addr = base; in nmk_gpio_populate_chip()
577 nmk_chip->clk = clk; in nmk_gpio_populate_chip()
592 * only support sharing this reset with other gpio-nomadik devices that in nmk_gpio_populate_chip()
616 seq_printf(p, "nmk%u-%u-%u", nmk_chip->bank, in nmk_gpio_irq_print_chip()
617 gc->base, gc->base + gc->ngpio - 1); in nmk_gpio_irq_print_chip()
635 struct device *dev = &pdev->dev; in nmk_gpio_probe()
640 int irq; in nmk_gpio_probe() local
650 device_property_read_bool(dev, "st,supports-sleepmode"); in nmk_gpio_probe()
653 pdev->id = nmk_chip->bank; in nmk_gpio_probe()
655 irq = platform_get_irq(pdev, 0); in nmk_gpio_probe()
656 if (irq < 0) in nmk_gpio_probe()
657 return irq; in nmk_gpio_probe()
660 * The virt address in nmk_chip->addr is in the nomadik register space, in nmk_gpio_probe()
661 * so we can simply convert the resource address, without remapping in nmk_gpio_probe()
663 nmk_chip->sleepmode = supports_sleepmode; in nmk_gpio_probe()
664 spin_lock_init(&nmk_chip->lock); in nmk_gpio_probe()
666 chip = &nmk_chip->chip; in nmk_gpio_probe()
667 chip->parent = dev; in nmk_gpio_probe()
668 chip->request = gpiochip_generic_request; in nmk_gpio_probe()
669 chip->free = gpiochip_generic_free; in nmk_gpio_probe()
670 chip->get_direction = nmk_gpio_get_dir; in nmk_gpio_probe()
671 chip->direction_input = nmk_gpio_make_input; in nmk_gpio_probe()
672 chip->get = nmk_gpio_get_input; in nmk_gpio_probe()
673 chip->direction_output = nmk_gpio_make_output; in nmk_gpio_probe()
674 chip->set = nmk_gpio_set_output; in nmk_gpio_probe()
675 chip->dbg_show = nmk_gpio_dbg_show; in nmk_gpio_probe()
676 chip->can_sleep = false; in nmk_gpio_probe()
677 chip->owner = THIS_MODULE; in nmk_gpio_probe()
679 girq = &chip->irq; in nmk_gpio_probe()
681 girq->parent_handler = NULL; in nmk_gpio_probe()
682 girq->num_parents = 0; in nmk_gpio_probe()
683 girq->parents = NULL; in nmk_gpio_probe()
684 girq->default_type = IRQ_TYPE_NONE; in nmk_gpio_probe()
685 girq->handler = handle_edge_irq; in nmk_gpio_probe()
687 ret = devm_request_irq(dev, irq, nmk_gpio_irq_handler, IRQF_SHARED, in nmk_gpio_probe()
690 dev_err(dev, "failed requesting IRQ\n"); in nmk_gpio_probe()
694 if (!nmk_chip->is_mobileye_soc) { in nmk_gpio_probe()
695 clk_enable(nmk_chip->clk); in nmk_gpio_probe()
696 nmk_chip->lowemi = readl_relaxed(nmk_chip->addr + NMK_GPIO_LOWEMI); in nmk_gpio_probe()
697 clk_disable(nmk_chip->clk); in nmk_gpio_probe()
712 { .compatible = "st,nomadik-gpio", },
713 { .compatible = "mobileye,eyeq5-gpio", },
719 .name = "nomadik-gpio",