Lines Matching +full:edge +full:- +full:offset

1 // SPDX-License-Identifier: GPL-2.0+
8 // Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
86 .edge_sel_reg = -EINVAL,
101 .edge_sel_reg = -EINVAL,
123 #define GPIO_DR (port->hwdata->dr_reg)
124 #define GPIO_GDIR (port->hwdata->gdir_reg)
125 #define GPIO_PSR (port->hwdata->psr_reg)
126 #define GPIO_ICR1 (port->hwdata->icr1_reg)
127 #define GPIO_ICR2 (port->hwdata->icr2_reg)
128 #define GPIO_IMR (port->hwdata->imr_reg)
129 #define GPIO_ISR (port->hwdata->isr_reg)
130 #define GPIO_EDGE_SEL (port->hwdata->edge_sel_reg)
132 #define GPIO_INT_LOW_LEV (port->hwdata->low_level)
133 #define GPIO_INT_HIGH_LEV (port->hwdata->high_level)
134 #define GPIO_INT_RISE_EDGE (port->hwdata->rise_edge)
135 #define GPIO_INT_FALL_EDGE (port->hwdata->fall_edge)
139 { .compatible = "fsl,imx1-gpio", .data = &imx1_imx21_gpio_hwdata },
140 { .compatible = "fsl,imx21-gpio", .data = &imx1_imx21_gpio_hwdata },
141 { .compatible = "fsl,imx31-gpio", .data = &imx31_gpio_hwdata },
142 { .compatible = "fsl,imx35-gpio", .data = &imx35_gpio_hwdata },
143 { .compatible = "fsl,imx7d-gpio", .data = &imx35_gpio_hwdata },
144 { .compatible = "fsl,imx8dxl-gpio", .data = &imx35_gpio_hwdata },
145 { .compatible = "fsl,imx8qm-gpio", .data = &imx35_gpio_hwdata },
146 { .compatible = "fsl,imx8qxp-gpio", .data = &imx35_gpio_hwdata },
163 struct mxc_gpio_port *port = gc->private; in gpio_set_irq_type()
166 u32 gpio_idx = d->hwirq; in gpio_set_irq_type()
167 int edge; in gpio_set_irq_type() local
168 void __iomem *reg = port->base; in gpio_set_irq_type()
170 port->both_edges &= ~(1 << gpio_idx); in gpio_set_irq_type()
173 edge = GPIO_INT_RISE_EDGE; in gpio_set_irq_type()
176 edge = GPIO_INT_FALL_EDGE; in gpio_set_irq_type()
180 edge = GPIO_INT_BOTH_EDGES; in gpio_set_irq_type()
182 val = port->gc.get(&port->gc, gpio_idx); in gpio_set_irq_type()
184 edge = GPIO_INT_LOW_LEV; in gpio_set_irq_type()
187 edge = GPIO_INT_HIGH_LEV; in gpio_set_irq_type()
190 port->both_edges |= 1 << gpio_idx; in gpio_set_irq_type()
194 edge = GPIO_INT_LOW_LEV; in gpio_set_irq_type()
197 edge = GPIO_INT_HIGH_LEV; in gpio_set_irq_type()
200 return -EINVAL; in gpio_set_irq_type()
203 raw_spin_lock_irqsave(&port->gc.bgpio_lock, flags); in gpio_set_irq_type()
206 val = readl(port->base + GPIO_EDGE_SEL); in gpio_set_irq_type()
207 if (edge == GPIO_INT_BOTH_EDGES) in gpio_set_irq_type()
209 port->base + GPIO_EDGE_SEL); in gpio_set_irq_type()
212 port->base + GPIO_EDGE_SEL); in gpio_set_irq_type()
215 if (edge != GPIO_INT_BOTH_EDGES) { in gpio_set_irq_type()
219 writel(val | (edge << (bit << 1)), reg); in gpio_set_irq_type()
222 writel(1 << gpio_idx, port->base + GPIO_ISR); in gpio_set_irq_type()
223 port->pad_type[gpio_idx] = type; in gpio_set_irq_type()
225 raw_spin_unlock_irqrestore(&port->gc.bgpio_lock, flags); in gpio_set_irq_type()
227 return port->gc.direction_input(&port->gc, gpio_idx); in gpio_set_irq_type()
232 void __iomem *reg = port->base; in mxc_flip_edge()
235 int edge; in mxc_flip_edge() local
237 raw_spin_lock_irqsave(&port->gc.bgpio_lock, flags); in mxc_flip_edge()
242 edge = (val >> (bit << 1)) & 3; in mxc_flip_edge()
244 if (edge == GPIO_INT_HIGH_LEV) { in mxc_flip_edge()
245 edge = GPIO_INT_LOW_LEV; in mxc_flip_edge()
247 } else if (edge == GPIO_INT_LOW_LEV) { in mxc_flip_edge()
248 edge = GPIO_INT_HIGH_LEV; in mxc_flip_edge()
252 gpio, edge); in mxc_flip_edge()
255 writel(val | (edge << (bit << 1)), reg); in mxc_flip_edge()
258 raw_spin_unlock_irqrestore(&port->gc.bgpio_lock, flags); in mxc_flip_edge()
265 int irqoffset = fls(irq_stat) - 1; in mxc_gpio_irq_handler()
267 if (port->both_edges & (1 << irqoffset)) in mxc_gpio_irq_handler()
270 generic_handle_domain_irq(port->domain, irqoffset); in mxc_gpio_irq_handler()
283 if (port->is_pad_wakeup) in mx3_gpio_irq_handler()
288 irq_stat = readl(port->base + GPIO_ISR) & readl(port->base + GPIO_IMR); in mx3_gpio_irq_handler()
306 irq_msk = readl(port->base + GPIO_IMR); in mx2_gpio_irq_handler()
310 irq_stat = readl(port->base + GPIO_ISR) & irq_msk; in mx2_gpio_irq_handler()
318 * Set interrupt number "irq" in the GPIO as a wake-up source.
320 * wake-up enabled. When system is suspended, only selected GPIO interrupts
321 * need to have wake-up enabled.
323 * @param enable enable as wake-up if equal to non-zero
329 struct mxc_gpio_port *port = gc->private; in gpio_set_wake_irq()
330 u32 gpio_idx = d->hwirq; in gpio_set_wake_irq()
334 if (port->irq_high && (gpio_idx >= 16)) in gpio_set_wake_irq()
335 ret = enable_irq_wake(port->irq_high); in gpio_set_wake_irq()
337 ret = enable_irq_wake(port->irq); in gpio_set_wake_irq()
338 port->wakeup_pads |= (1 << gpio_idx); in gpio_set_wake_irq()
340 if (port->irq_high && (gpio_idx >= 16)) in gpio_set_wake_irq()
341 ret = disable_irq_wake(port->irq_high); in gpio_set_wake_irq()
343 ret = disable_irq_wake(port->irq); in gpio_set_wake_irq()
344 port->wakeup_pads &= ~(1 << gpio_idx); in gpio_set_wake_irq()
356 gc = devm_irq_alloc_generic_chip(port->dev, "gpio-mxc", 1, irq_base, in mxc_gpio_init_gc()
357 port->base, handle_level_irq); in mxc_gpio_init_gc()
359 return -ENOMEM; in mxc_gpio_init_gc()
360 gc->private = port; in mxc_gpio_init_gc()
362 ct = gc->chip_types; in mxc_gpio_init_gc()
363 ct->chip.irq_ack = irq_gc_ack_set_bit; in mxc_gpio_init_gc()
364 ct->chip.irq_mask = irq_gc_mask_clr_bit; in mxc_gpio_init_gc()
365 ct->chip.irq_unmask = irq_gc_mask_set_bit; in mxc_gpio_init_gc()
366 ct->chip.irq_set_type = gpio_set_irq_type; in mxc_gpio_init_gc()
367 ct->chip.irq_set_wake = gpio_set_wake_irq; in mxc_gpio_init_gc()
368 ct->chip.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND; in mxc_gpio_init_gc()
369 ct->regs.ack = GPIO_ISR; in mxc_gpio_init_gc()
370 ct->regs.mask = GPIO_IMR; in mxc_gpio_init_gc()
372 rv = devm_irq_setup_generic_chip(port->dev, gc, IRQ_MSK(32), in mxc_gpio_init_gc()
379 static int mxc_gpio_to_irq(struct gpio_chip *gc, unsigned offset) in mxc_gpio_to_irq() argument
383 return irq_find_mapping(port->domain, offset); in mxc_gpio_to_irq()
386 static int mxc_gpio_request(struct gpio_chip *chip, unsigned int offset) in mxc_gpio_request() argument
390 ret = gpiochip_generic_request(chip, offset); in mxc_gpio_request()
394 return pm_runtime_resume_and_get(chip->parent); in mxc_gpio_request()
397 static void mxc_gpio_free(struct gpio_chip *chip, unsigned int offset) in mxc_gpio_free() argument
399 gpiochip_generic_free(chip, offset); in mxc_gpio_free()
400 pm_runtime_put(chip->parent); in mxc_gpio_free()
406 irq_set_chained_handler_and_data(port->irq, port->mx_irq_handler, port); in mxc_update_irq_chained_handler()
408 irq_set_chained_handler_and_data(port->irq, NULL, NULL); in mxc_update_irq_chained_handler()
411 if (port->irq_high > 0) { in mxc_update_irq_chained_handler()
413 irq_set_chained_handler_and_data(port->irq_high, in mxc_update_irq_chained_handler()
414 port->mx_irq_handler, in mxc_update_irq_chained_handler()
417 irq_set_chained_handler_and_data(port->irq_high, NULL, NULL); in mxc_update_irq_chained_handler()
423 struct device_node *np = pdev->dev.of_node; in mxc_gpio_probe()
429 port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL); in mxc_gpio_probe()
431 return -ENOMEM; in mxc_gpio_probe()
433 port->dev = &pdev->dev; in mxc_gpio_probe()
434 port->hwdata = device_get_match_data(&pdev->dev); in mxc_gpio_probe()
436 port->base = devm_platform_ioremap_resource(pdev, 0); in mxc_gpio_probe()
437 if (IS_ERR(port->base)) in mxc_gpio_probe()
438 return PTR_ERR(port->base); in mxc_gpio_probe()
445 port->irq_high = platform_get_irq(pdev, 1); in mxc_gpio_probe()
446 if (port->irq_high < 0) in mxc_gpio_probe()
447 port->irq_high = 0; in mxc_gpio_probe()
450 port->irq = platform_get_irq(pdev, 0); in mxc_gpio_probe()
451 if (port->irq < 0) in mxc_gpio_probe()
452 return port->irq; in mxc_gpio_probe()
455 port->clk = devm_clk_get_optional_enabled(&pdev->dev, NULL); in mxc_gpio_probe()
456 if (IS_ERR(port->clk)) in mxc_gpio_probe()
457 return PTR_ERR(port->clk); in mxc_gpio_probe()
459 if (of_device_is_compatible(np, "fsl,imx7d-gpio")) in mxc_gpio_probe()
460 port->power_off = true; in mxc_gpio_probe()
462 pm_runtime_get_noresume(&pdev->dev); in mxc_gpio_probe()
463 pm_runtime_set_active(&pdev->dev); in mxc_gpio_probe()
464 pm_runtime_enable(&pdev->dev); in mxc_gpio_probe()
467 writel(0, port->base + GPIO_IMR); in mxc_gpio_probe()
468 writel(~0, port->base + GPIO_ISR); in mxc_gpio_probe()
470 if (of_device_is_compatible(np, "fsl,imx21-gpio")) { in mxc_gpio_probe()
476 port->irq_high = -1; in mxc_gpio_probe()
477 port->mx_irq_handler = mx2_gpio_irq_handler; in mxc_gpio_probe()
479 port->mx_irq_handler = mx3_gpio_irq_handler; in mxc_gpio_probe()
482 err = bgpio_init(&port->gc, &pdev->dev, 4, in mxc_gpio_probe()
483 port->base + GPIO_PSR, in mxc_gpio_probe()
484 port->base + GPIO_DR, NULL, in mxc_gpio_probe()
485 port->base + GPIO_GDIR, NULL, in mxc_gpio_probe()
490 port->gc.request = mxc_gpio_request; in mxc_gpio_probe()
491 port->gc.free = mxc_gpio_free; in mxc_gpio_probe()
492 port->gc.to_irq = mxc_gpio_to_irq; in mxc_gpio_probe()
493 port->gc.base = (pdev->id < 0) ? of_alias_get_id(np, "gpio") * 32 : in mxc_gpio_probe()
494 pdev->id * 32; in mxc_gpio_probe()
496 err = devm_gpiochip_add_data(&pdev->dev, &port->gc, port); in mxc_gpio_probe()
500 irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0, 32, numa_node_id()); in mxc_gpio_probe()
506 port->domain = irq_domain_add_legacy(np, 32, irq_base, 0, in mxc_gpio_probe()
508 if (!port->domain) { in mxc_gpio_probe()
509 err = -ENODEV; in mxc_gpio_probe()
513 irq_domain_set_pm_device(port->domain, &pdev->dev); in mxc_gpio_probe()
515 /* gpio-mxc can be a generic irq chip */ in mxc_gpio_probe()
520 list_add_tail(&port->node, &mxc_gpio_ports); in mxc_gpio_probe()
523 pm_runtime_put_autosuspend(&pdev->dev); in mxc_gpio_probe()
528 irq_domain_remove(port->domain); in mxc_gpio_probe()
530 pm_runtime_disable(&pdev->dev); in mxc_gpio_probe()
531 pm_runtime_put_noidle(&pdev->dev); in mxc_gpio_probe()
532 dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err); in mxc_gpio_probe()
538 if (!port->power_off) in mxc_gpio_save_regs()
541 port->gpio_saved_reg.icr1 = readl(port->base + GPIO_ICR1); in mxc_gpio_save_regs()
542 port->gpio_saved_reg.icr2 = readl(port->base + GPIO_ICR2); in mxc_gpio_save_regs()
543 port->gpio_saved_reg.imr = readl(port->base + GPIO_IMR); in mxc_gpio_save_regs()
544 port->gpio_saved_reg.gdir = readl(port->base + GPIO_GDIR); in mxc_gpio_save_regs()
545 port->gpio_saved_reg.edge_sel = readl(port->base + GPIO_EDGE_SEL); in mxc_gpio_save_regs()
546 port->gpio_saved_reg.dr = readl(port->base + GPIO_DR); in mxc_gpio_save_regs()
551 if (!port->power_off) in mxc_gpio_restore_regs()
554 writel(port->gpio_saved_reg.icr1, port->base + GPIO_ICR1); in mxc_gpio_restore_regs()
555 writel(port->gpio_saved_reg.icr2, port->base + GPIO_ICR2); in mxc_gpio_restore_regs()
556 writel(port->gpio_saved_reg.imr, port->base + GPIO_IMR); in mxc_gpio_restore_regs()
557 writel(port->gpio_saved_reg.gdir, port->base + GPIO_GDIR); in mxc_gpio_restore_regs()
558 writel(port->gpio_saved_reg.edge_sel, port->base + GPIO_EDGE_SEL); in mxc_gpio_restore_regs()
559 writel(port->gpio_saved_reg.dr, port->base + GPIO_DR); in mxc_gpio_restore_regs()
563 unsigned int offset, unsigned long conf) in mxc_gpio_generic_config() argument
565 struct device_node *np = port->dev->of_node; in mxc_gpio_generic_config()
567 if (of_device_is_compatible(np, "fsl,imx8dxl-gpio") || in mxc_gpio_generic_config()
568 of_device_is_compatible(np, "fsl,imx8qxp-gpio") || in mxc_gpio_generic_config()
569 of_device_is_compatible(np, "fsl,imx8qm-gpio")) in mxc_gpio_generic_config()
570 return (gpiochip_generic_config(&port->gc, offset, conf) == 0); in mxc_gpio_generic_config()
594 if ((port->wakeup_pads & (1 << i))) { in mxc_gpio_set_pad_wakeup()
595 type = port->pad_type[i]; in mxc_gpio_set_pad_wakeup()
612 clk_disable_unprepare(port->clk); in mxc_gpio_runtime_suspend()
624 ret = clk_prepare_enable(port->clk); in mxc_gpio_runtime_resume()
640 if (port->wakeup_pads > 0) in mxc_gpio_noirq_suspend()
641 port->is_pad_wakeup = mxc_gpio_set_pad_wakeup(port, true); in mxc_gpio_noirq_suspend()
651 if (port->wakeup_pads > 0) in mxc_gpio_noirq_resume()
653 port->is_pad_wakeup = false; in mxc_gpio_noirq_resume()
670 ret = clk_prepare_enable(port->clk); in mxc_gpio_syscore_suspend()
674 clk_disable_unprepare(port->clk); in mxc_gpio_syscore_suspend()
687 ret = clk_prepare_enable(port->clk); in mxc_gpio_syscore_resume()
693 clk_disable_unprepare(port->clk); in mxc_gpio_syscore_resume()
704 .name = "gpio-mxc",