Lines Matching +full:s3c64xx +full:- +full:wakeup +full:- +full:eint
1 // SPDX-License-Identifier: GPL-2.0+
3 // S3C64xx specific support for pinctrl-samsung driver.
7 // Based on pinctrl-exynos.c, please see the file for original copyrights.
9 // This file contains the Samsung S3C64xx specific information required by the
11 // external gpio and wakeup interrupt support.
24 #include "pinctrl-samsung.h"
31 /* External GPIO and wakeup interrupt related definitions */
57 /* S3C64xx specific external interrupt trigger types */
116 .eint_mask = (1 << (pins)) - 1, \
140 .eint_mask = (1 << (pins)) - 1, \
194 .eint_mask = (1 << (pins)) - 1, \
200 * struct s3c64xx_eint0_data - EINT0 common data
212 * struct s3c64xx_eint0_domain_data - EINT0 per-domain data
222 * struct s3c64xx_eint_gpio_data - GPIO EINT data
224 * @domains: array of domains related to EINT interrupt groups
232 * Common functions for S3C64xx EINT configuration
256 return -EINVAL; in s3c64xx_irq_get_trigger()
264 unsigned int *pud_val = drvdata->pud_val; in s3c64xx_pud_value_init()
273 /* Edge- and level-triggered interrupts need different handlers */ in s3c64xx_irq_set_handler()
283 const struct samsung_pin_bank_type *bank_type = bank->type; in s3c64xx_irq_set_function()
291 reg = d->virt_base + bank->pctl_offset; in s3c64xx_irq_set_function()
293 if (bank_type->fld_width[PINCFG_TYPE_FUNC] * shift >= 32) { in s3c64xx_irq_set_function()
294 /* 4-bit bank type with 2 con regs */ in s3c64xx_irq_set_function()
296 shift -= 8; in s3c64xx_irq_set_function()
299 shift = shift * bank_type->fld_width[PINCFG_TYPE_FUNC]; in s3c64xx_irq_set_function()
300 mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1; in s3c64xx_irq_set_function()
302 raw_spin_lock_irqsave(&bank->slock, flags); in s3c64xx_irq_set_function()
306 val |= bank->eint_func << shift; in s3c64xx_irq_set_function()
309 raw_spin_unlock_irqrestore(&bank->slock, flags); in s3c64xx_irq_set_function()
313 * Functions for EINT GPIO configuration (EINT groups 1-9)
319 struct samsung_pinctrl_drv_data *d = bank->drvdata; in s3c64xx_gpio_irq_set_mask()
320 unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq; in s3c64xx_gpio_irq_set_mask()
321 void __iomem *reg = d->virt_base + EINTMASK_REG(bank->eint_offset); in s3c64xx_gpio_irq_set_mask()
345 struct samsung_pinctrl_drv_data *d = bank->drvdata; in s3c64xx_gpio_irq_ack()
346 unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq; in s3c64xx_gpio_irq_ack()
347 void __iomem *reg = d->virt_base + EINTPEND_REG(bank->eint_offset); in s3c64xx_gpio_irq_ack()
355 struct samsung_pinctrl_drv_data *d = bank->drvdata; in s3c64xx_gpio_irq_set_type()
364 return -EINVAL; in s3c64xx_gpio_irq_set_type()
370 reg = d->virt_base + EINTCON_REG(bank->eint_offset); in s3c64xx_gpio_irq_set_type()
371 shift = EINT_OFFS(bank->eint_offset) + irqd->hwirq; in s3c64xx_gpio_irq_set_type()
379 s3c64xx_irq_set_function(d, bank, irqd->hwirq); in s3c64xx_gpio_irq_set_type()
398 struct samsung_pin_bank *bank = h->host_data; in s3c64xx_gpio_irq_map()
400 if (!(bank->eint_mask & (1 << hw))) in s3c64xx_gpio_irq_map()
401 return -EINVAL; in s3c64xx_gpio_irq_map()
422 struct samsung_pinctrl_drv_data *drvdata = data->drvdata; in s3c64xx_eint_gpio_irq()
432 svc = readl(drvdata->virt_base + SERVICE_REG); in s3c64xx_eint_gpio_irq()
444 pin -= 8; in s3c64xx_eint_gpio_irq()
447 ret = generic_handle_domain_irq(data->domains[group], pin); in s3c64xx_eint_gpio_irq()
449 * Something must be really wrong if an unmapped EINT in s3c64xx_eint_gpio_irq()
459 * s3c64xx_eint_gpio_init() - setup handling of external gpio interrupts.
466 struct device *dev = d->dev; in s3c64xx_eint_gpio_init()
470 if (!d->irq) { in s3c64xx_eint_gpio_init()
472 return -EINVAL; in s3c64xx_eint_gpio_init()
476 bank = d->pin_banks; in s3c64xx_eint_gpio_init()
477 for (i = 0; i < d->nr_banks; ++i, ++bank) { in s3c64xx_eint_gpio_init()
481 if (bank->eint_type != EINT_TYPE_GPIO) in s3c64xx_eint_gpio_init()
484 mask = bank->eint_mask; in s3c64xx_eint_gpio_init()
487 bank->irq_domain = irq_domain_create_linear(bank->fwnode, in s3c64xx_eint_gpio_init()
489 if (!bank->irq_domain) { in s3c64xx_eint_gpio_init()
491 return -ENXIO; in s3c64xx_eint_gpio_init()
500 return -ENOMEM; in s3c64xx_eint_gpio_init()
501 data->drvdata = d; in s3c64xx_eint_gpio_init()
503 bank = d->pin_banks; in s3c64xx_eint_gpio_init()
505 for (i = 0; i < d->nr_banks; ++i, ++bank) { in s3c64xx_eint_gpio_init()
506 if (bank->eint_type != EINT_TYPE_GPIO) in s3c64xx_eint_gpio_init()
509 data->domains[nr_domains++] = bank->irq_domain; in s3c64xx_eint_gpio_init()
512 irq_set_chained_handler_and_data(d->irq, s3c64xx_eint_gpio_irq, data); in s3c64xx_eint_gpio_init()
518 * Functions for configuration of EINT0 wake-up interrupts
525 struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata; in s3c64xx_eint0_irq_set_mask()
528 val = readl(d->virt_base + EINT0MASK_REG); in s3c64xx_eint0_irq_set_mask()
530 val |= 1 << ddata->eints[irqd->hwirq]; in s3c64xx_eint0_irq_set_mask()
532 val &= ~(1 << ddata->eints[irqd->hwirq]); in s3c64xx_eint0_irq_set_mask()
533 writel(val, d->virt_base + EINT0MASK_REG); in s3c64xx_eint0_irq_set_mask()
550 struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata; in s3c64xx_eint0_irq_ack()
552 writel(1 << ddata->eints[irqd->hwirq], in s3c64xx_eint0_irq_ack()
553 d->virt_base + EINT0PEND_REG); in s3c64xx_eint0_irq_ack()
560 struct samsung_pin_bank *bank = ddata->bank; in s3c64xx_eint0_irq_set_type()
561 struct samsung_pinctrl_drv_data *d = bank->drvdata; in s3c64xx_eint0_irq_set_type()
570 return -EINVAL; in s3c64xx_eint0_irq_set_type()
576 reg = d->virt_base + EINT0CON0_REG; in s3c64xx_eint0_irq_set_type()
577 shift = ddata->eints[irqd->hwirq]; in s3c64xx_eint0_irq_set_type()
580 shift -= EINT_MAX_PER_REG; in s3c64xx_eint0_irq_set_type()
589 s3c64xx_irq_set_function(d, bank, irqd->hwirq); in s3c64xx_eint0_irq_set_type()
595 * irq_chip for wakeup interrupts
609 struct samsung_pinctrl_drv_data *drvdata = data->drvdata; in s3c64xx_irq_demux_eint()
614 pend = readl(drvdata->virt_base + EINT0PEND_REG); in s3c64xx_irq_demux_eint()
615 mask = readl(drvdata->virt_base + EINT0MASK_REG); in s3c64xx_irq_demux_eint()
624 irq = fls(pend) - 1; in s3c64xx_irq_demux_eint()
626 ret = generic_handle_domain_irq(data->domains[irq], data->pins[irq]); in s3c64xx_irq_demux_eint()
628 * Something must be really wrong if an unmapped EINT in s3c64xx_irq_demux_eint()
667 struct s3c64xx_eint0_domain_data *ddata = h->host_data; in s3c64xx_eint0_irq_map()
668 struct samsung_pin_bank *bank = ddata->bank; in s3c64xx_eint0_irq_map()
670 if (!(bank->eint_mask & (1 << hw))) in s3c64xx_eint0_irq_map()
671 return -EINVAL; in s3c64xx_eint0_irq_map()
681 * irq domain callbacks for external wakeup interrupt controller.
688 /* list of external wakeup controllers supported */
690 { .compatible = "samsung,s3c64xx-wakeup-eint", },
695 * s3c64xx_eint_eint0_init() - setup handling of external wakeup interrupts.
700 struct device *dev = d->dev; in s3c64xx_eint_eint0_init()
707 for_each_child_of_node(dev->of_node, np) { in s3c64xx_eint_eint0_init()
714 return -ENODEV; in s3c64xx_eint_eint0_init()
719 return -ENOMEM; in s3c64xx_eint_eint0_init()
721 data->drvdata = d; in s3c64xx_eint_eint0_init()
728 dev_err(dev, "failed to get wakeup EINT IRQ %d\n", i); in s3c64xx_eint_eint0_init()
730 return -ENXIO; in s3c64xx_eint_eint0_init()
739 bank = d->pin_banks; in s3c64xx_eint_eint0_init()
740 for (i = 0; i < d->nr_banks; ++i, ++bank) { in s3c64xx_eint_eint0_init()
747 if (bank->eint_type != EINT_TYPE_WKUP) in s3c64xx_eint_eint0_init()
750 mask = bank->eint_mask; in s3c64xx_eint_eint0_init()
756 return -ENOMEM; in s3c64xx_eint_eint0_init()
757 ddata->bank = bank; in s3c64xx_eint_eint0_init()
759 bank->irq_domain = irq_domain_create_linear(bank->fwnode, in s3c64xx_eint_eint0_init()
761 if (!bank->irq_domain) { in s3c64xx_eint_eint0_init()
763 return -ENXIO; in s3c64xx_eint_eint0_init()
766 irq = bank->eint_offset; in s3c64xx_eint_eint0_init()
767 mask = bank->eint_mask; in s3c64xx_eint_eint0_init()
771 data->domains[irq] = bank->irq_domain; in s3c64xx_eint_eint0_init()
772 data->pins[irq] = pin; in s3c64xx_eint_eint0_init()
773 ddata->eints[pin] = irq; in s3c64xx_eint_eint0_init()
781 /* pin banks of s3c64xx pin-controller 0 */
803 * Samsung pinctrl driver data for S3C64xx SoC. S3C64xx SoC includes
804 * one gpio/pin-mux/pinconfig controller.
808 /* pin-controller instance 1 data */