^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // Exynos specific support for Samsung pinctrl/gpiolib driver with eint support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) // Copyright (c) 2012 Samsung Electronics Co., Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) // http://www.samsung.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) // Copyright (c) 2012 Linaro Ltd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) // http://www.linaro.org
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) // Author: Thomas Abraham <thomas.ab@samsung.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) // This file contains the Samsung Exynos specific information required by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) // the Samsung pinctrl/gpiolib driver. It also includes the implementation of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) // external gpio and wakeup interrupt support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/irqdomain.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/irqchip/chained_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/soc/samsung/exynos-pmu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/soc/samsung/exynos-regs-pmu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <dt-bindings/pinctrl/samsung.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include "pinctrl-samsung.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include "pinctrl-exynos.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct exynos_irq_chip {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct irq_chip chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) u32 eint_con;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) u32 eint_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) u32 eint_pend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) u32 *eint_wake_mask_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) u32 eint_wake_mask_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) void (*set_eint_wakeup_mask)(struct samsung_pinctrl_drv_data *drvdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct exynos_irq_chip *irq_chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static inline struct exynos_irq_chip *to_exynos_irq_chip(struct irq_chip *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return container_of(chip, struct exynos_irq_chip, chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static void exynos_irq_mask(struct irq_data *irqd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct irq_chip *chip = irq_data_get_irq_chip(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) unsigned int mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) spin_lock_irqsave(&bank->slock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) mask = readl(bank->eint_base + reg_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) mask |= 1 << irqd->hwirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) writel(mask, bank->eint_base + reg_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) spin_unlock_irqrestore(&bank->slock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static void exynos_irq_ack(struct irq_data *irqd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct irq_chip *chip = irq_data_get_irq_chip(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned long reg_pend = our_chip->eint_pend + bank->eint_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) writel(1 << irqd->hwirq, bank->eint_base + reg_pend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static void exynos_irq_unmask(struct irq_data *irqd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct irq_chip *chip = irq_data_get_irq_chip(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) unsigned int mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * Ack level interrupts right before unmask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * If we don't do this we'll get a double-interrupt. Level triggered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * interrupts must not fire an interrupt if the level is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * _currently_ active, even if it was active while the interrupt was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * masked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (irqd_get_trigger_type(irqd) & IRQ_TYPE_LEVEL_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) exynos_irq_ack(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) spin_lock_irqsave(&bank->slock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) mask = readl(bank->eint_base + reg_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) mask &= ~(1 << irqd->hwirq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) writel(mask, bank->eint_base + reg_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) spin_unlock_irqrestore(&bank->slock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct irq_chip *chip = irq_data_get_irq_chip(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) unsigned int con, trig_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) unsigned long reg_con = our_chip->eint_con + bank->eint_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) case IRQ_TYPE_EDGE_RISING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) trig_type = EXYNOS_EINT_EDGE_RISING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) case IRQ_TYPE_EDGE_FALLING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) trig_type = EXYNOS_EINT_EDGE_FALLING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) case IRQ_TYPE_EDGE_BOTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) trig_type = EXYNOS_EINT_EDGE_BOTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) case IRQ_TYPE_LEVEL_HIGH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) trig_type = EXYNOS_EINT_LEVEL_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) case IRQ_TYPE_LEVEL_LOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) trig_type = EXYNOS_EINT_LEVEL_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) pr_err("unsupported external interrupt type\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (type & IRQ_TYPE_EDGE_BOTH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) irq_set_handler_locked(irqd, handle_edge_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) irq_set_handler_locked(irqd, handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) con = readl(bank->eint_base + reg_con);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) con &= ~(EXYNOS_EINT_CON_MASK << shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) con |= trig_type << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) writel(con, bank->eint_base + reg_con);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static int exynos_irq_request_resources(struct irq_data *irqd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) const struct samsung_pin_bank_type *bank_type = bank->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) unsigned long reg_con, flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) unsigned int shift, mask, con;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) ret = gpiochip_lock_as_irq(&bank->gpio_chip, irqd->hwirq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) dev_err(bank->gpio_chip.parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) "unable to lock pin %s-%lu IRQ\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) bank->name, irqd->hwirq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) reg_con = bank->pctl_offset + bank_type->reg_offset[PINCFG_TYPE_FUNC];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) shift = irqd->hwirq * bank_type->fld_width[PINCFG_TYPE_FUNC];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) spin_lock_irqsave(&bank->slock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) con = readl(bank->pctl_base + reg_con);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) con &= ~(mask << shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) con |= EXYNOS_PIN_FUNC_EINT << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) writel(con, bank->pctl_base + reg_con);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) spin_unlock_irqrestore(&bank->slock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static void exynos_irq_release_resources(struct irq_data *irqd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) const struct samsung_pin_bank_type *bank_type = bank->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) unsigned long reg_con, flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) unsigned int shift, mask, con;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) reg_con = bank->pctl_offset + bank_type->reg_offset[PINCFG_TYPE_FUNC];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) shift = irqd->hwirq * bank_type->fld_width[PINCFG_TYPE_FUNC];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) spin_lock_irqsave(&bank->slock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) con = readl(bank->pctl_base + reg_con);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) con &= ~(mask << shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) con |= EXYNOS_PIN_FUNC_INPUT << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) writel(con, bank->pctl_base + reg_con);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) spin_unlock_irqrestore(&bank->slock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) gpiochip_unlock_as_irq(&bank->gpio_chip, irqd->hwirq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * irq_chip for gpio interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static const struct exynos_irq_chip exynos_gpio_irq_chip __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) .chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) .name = "exynos_gpio_irq_chip",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .irq_unmask = exynos_irq_unmask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) .irq_mask = exynos_irq_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .irq_ack = exynos_irq_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) .irq_set_type = exynos_irq_set_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) .irq_request_resources = exynos_irq_request_resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) .irq_release_resources = exynos_irq_release_resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) .eint_con = EXYNOS_GPIO_ECON_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) .eint_mask = EXYNOS_GPIO_EMASK_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) .eint_pend = EXYNOS_GPIO_EPEND_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /* eint_wake_mask_value not used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static int exynos_eint_irq_map(struct irq_domain *h, unsigned int virq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) irq_hw_number_t hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) struct samsung_pin_bank *b = h->host_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) irq_set_chip_data(virq, b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) irq_set_chip_and_handler(virq, &b->irq_chip->chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * irq domain callbacks for external gpio and wakeup interrupt controllers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static const struct irq_domain_ops exynos_eint_irqd_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .map = exynos_eint_irq_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) .xlate = irq_domain_xlate_twocell,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct samsung_pinctrl_drv_data *d = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct samsung_pin_bank *bank = d->pin_banks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) unsigned int svc, group, pin, virq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) svc = readl(bank->eint_base + EXYNOS_SVC_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) group = EXYNOS_SVC_GROUP(svc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) pin = svc & EXYNOS_SVC_NUM_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (!group)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) bank += (group - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) virq = irq_linear_revmap(bank->irq_domain, pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (!virq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) generic_handle_irq(virq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) struct exynos_eint_gpio_save {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) u32 eint_con;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) u32 eint_fltcon0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) u32 eint_fltcon1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) u32 eint_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * exynos_eint_gpio_init() - setup handling of external gpio interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * @d: driver data of samsung pinctrl driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) __init int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) struct samsung_pin_bank *bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) struct device *dev = d->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (!d->irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) dev_err(dev, "irq number not available\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) ret = devm_request_irq(dev, d->irq, exynos_eint_gpio_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 0, dev_name(dev), d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) dev_err(dev, "irq request failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) bank = d->pin_banks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) for (i = 0; i < d->nr_banks; ++i, ++bank) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (bank->eint_type != EINT_TYPE_GPIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) bank->irq_chip = devm_kmemdup(dev, &exynos_gpio_irq_chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) sizeof(*bank->irq_chip), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (!bank->irq_chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) goto err_domains;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) bank->irq_chip->chip.name = bank->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) bank->irq_domain = irq_domain_add_linear(bank->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) bank->nr_pins, &exynos_eint_irqd_ops, bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (!bank->irq_domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) dev_err(dev, "gpio irq domain add failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) ret = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) goto err_domains;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) bank->soc_priv = devm_kzalloc(d->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) sizeof(struct exynos_eint_gpio_save), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (!bank->soc_priv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) irq_domain_remove(bank->irq_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) goto err_domains;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) err_domains:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) for (--i, --bank; i >= 0; --i, --bank) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (bank->eint_type != EINT_TYPE_GPIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) irq_domain_remove(bank->irq_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static int exynos_wkup_irq_set_wake(struct irq_data *irqd, unsigned int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) struct irq_chip *chip = irq_data_get_irq_chip(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) unsigned long bit = 1UL << (2 * bank->eint_offset + irqd->hwirq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) pr_info("wake %s for irq %d\n", on ? "enabled" : "disabled", irqd->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (!on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) *our_chip->eint_wake_mask_value |= bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) *our_chip->eint_wake_mask_value &= ~bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) exynos_pinctrl_set_eint_wakeup_mask(struct samsung_pinctrl_drv_data *drvdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) struct exynos_irq_chip *irq_chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) struct regmap *pmu_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (!drvdata->retention_ctrl || !drvdata->retention_ctrl->priv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) dev_warn(drvdata->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) "No retention data configured bank with external wakeup interrupt. Wake-up mask will not be set.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) pmu_regs = drvdata->retention_ctrl->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) dev_info(drvdata->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) "Setting external wakeup interrupt mask: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) *irq_chip->eint_wake_mask_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) regmap_write(pmu_regs, irq_chip->eint_wake_mask_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) *irq_chip->eint_wake_mask_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) s5pv210_pinctrl_set_eint_wakeup_mask(struct samsung_pinctrl_drv_data *drvdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) struct exynos_irq_chip *irq_chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) void __iomem *clk_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (!drvdata->retention_ctrl || !drvdata->retention_ctrl->priv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) dev_warn(drvdata->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) "No retention data configured bank with external wakeup interrupt. Wake-up mask will not be set.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) clk_base = (void __iomem *) drvdata->retention_ctrl->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) __raw_writel(*irq_chip->eint_wake_mask_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) clk_base + irq_chip->eint_wake_mask_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static u32 eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * irq_chip for wakeup interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) static const struct exynos_irq_chip s5pv210_wkup_irq_chip __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) .chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) .name = "s5pv210_wkup_irq_chip",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) .irq_unmask = exynos_irq_unmask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) .irq_mask = exynos_irq_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) .irq_ack = exynos_irq_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) .irq_set_type = exynos_irq_set_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) .irq_set_wake = exynos_wkup_irq_set_wake,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) .irq_request_resources = exynos_irq_request_resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) .irq_release_resources = exynos_irq_release_resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) .eint_con = EXYNOS_WKUP_ECON_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) .eint_mask = EXYNOS_WKUP_EMASK_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) .eint_pend = EXYNOS_WKUP_EPEND_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) .eint_wake_mask_value = &eint_wake_mask_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) /* Only differences with exynos4210_wkup_irq_chip: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) .eint_wake_mask_reg = S5PV210_EINT_WAKEUP_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) .set_eint_wakeup_mask = s5pv210_pinctrl_set_eint_wakeup_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) static const struct exynos_irq_chip exynos4210_wkup_irq_chip __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) .chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) .name = "exynos4210_wkup_irq_chip",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) .irq_unmask = exynos_irq_unmask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) .irq_mask = exynos_irq_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) .irq_ack = exynos_irq_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) .irq_set_type = exynos_irq_set_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) .irq_set_wake = exynos_wkup_irq_set_wake,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) .irq_request_resources = exynos_irq_request_resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) .irq_release_resources = exynos_irq_release_resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) .eint_con = EXYNOS_WKUP_ECON_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) .eint_mask = EXYNOS_WKUP_EMASK_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) .eint_pend = EXYNOS_WKUP_EPEND_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) .eint_wake_mask_value = &eint_wake_mask_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) .eint_wake_mask_reg = EXYNOS_EINT_WAKEUP_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) .set_eint_wakeup_mask = exynos_pinctrl_set_eint_wakeup_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) static const struct exynos_irq_chip exynos7_wkup_irq_chip __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) .chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) .name = "exynos7_wkup_irq_chip",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) .irq_unmask = exynos_irq_unmask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) .irq_mask = exynos_irq_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) .irq_ack = exynos_irq_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) .irq_set_type = exynos_irq_set_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) .irq_set_wake = exynos_wkup_irq_set_wake,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) .irq_request_resources = exynos_irq_request_resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) .irq_release_resources = exynos_irq_release_resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) .eint_con = EXYNOS7_WKUP_ECON_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) .eint_mask = EXYNOS7_WKUP_EMASK_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) .eint_pend = EXYNOS7_WKUP_EPEND_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) .eint_wake_mask_value = &eint_wake_mask_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) .eint_wake_mask_reg = EXYNOS5433_EINT_WAKEUP_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) .set_eint_wakeup_mask = exynos_pinctrl_set_eint_wakeup_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) /* list of external wakeup controllers supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static const struct of_device_id exynos_wkup_irq_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) { .compatible = "samsung,s5pv210-wakeup-eint",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) .data = &s5pv210_wkup_irq_chip },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) { .compatible = "samsung,exynos4210-wakeup-eint",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) .data = &exynos4210_wkup_irq_chip },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) { .compatible = "samsung,exynos7-wakeup-eint",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) .data = &exynos7_wkup_irq_chip },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) /* interrupt handler for wakeup interrupts 0..15 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) static void exynos_irq_eint0_15(struct irq_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) struct exynos_weint_data *eintd = irq_desc_get_handler_data(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) struct samsung_pin_bank *bank = eintd->bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) struct irq_chip *chip = irq_desc_get_chip(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) int eint_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) chained_irq_enter(chip, desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) eint_irq = irq_linear_revmap(bank->irq_domain, eintd->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) generic_handle_irq(eint_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) chained_irq_exit(chip, desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) static inline void exynos_irq_demux_eint(unsigned int pend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) struct irq_domain *domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) unsigned int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) while (pend) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) irq = fls(pend) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) generic_handle_irq(irq_find_mapping(domain, irq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) pend &= ~(1 << irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) /* interrupt handler for wakeup interrupt 16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) static void exynos_irq_demux_eint16_31(struct irq_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) struct irq_chip *chip = irq_desc_get_chip(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) struct exynos_muxed_weint_data *eintd = irq_desc_get_handler_data(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) unsigned int pend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) unsigned int mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) chained_irq_enter(chip, desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) for (i = 0; i < eintd->nr_banks; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) struct samsung_pin_bank *b = eintd->banks[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) pend = readl(b->eint_base + b->irq_chip->eint_pend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) + b->eint_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) mask = readl(b->eint_base + b->irq_chip->eint_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) + b->eint_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) exynos_irq_demux_eint(pend & ~mask, b->irq_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) chained_irq_exit(chip, desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) * exynos_eint_wkup_init() - setup handling of external wakeup interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * @d: driver data of samsung pinctrl driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) struct device *dev = d->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) struct device_node *wkup_np = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) struct samsung_pin_bank *bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) struct exynos_weint_data *weint_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) struct exynos_muxed_weint_data *muxed_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) const struct exynos_irq_chip *irq_chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) unsigned int muxed_banks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) int idx, irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) for_each_child_of_node(dev->of_node, np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) const struct of_device_id *match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) match = of_match_node(exynos_wkup_irq_ids, np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (match) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) irq_chip = match->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) wkup_np = np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (!wkup_np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) bank = d->pin_banks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) for (i = 0; i < d->nr_banks; ++i, ++bank) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (bank->eint_type != EINT_TYPE_WKUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) bank->irq_chip = devm_kmemdup(dev, irq_chip, sizeof(*irq_chip),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) if (!bank->irq_chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) of_node_put(wkup_np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) bank->irq_chip->chip.name = bank->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) bank->irq_domain = irq_domain_add_linear(bank->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) bank->nr_pins, &exynos_eint_irqd_ops, bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (!bank->irq_domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) dev_err(dev, "wkup irq domain add failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) of_node_put(wkup_np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (!of_find_property(bank->of_node, "interrupts", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) bank->eint_type = EINT_TYPE_WKUP_MUX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) ++muxed_banks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) weint_data = devm_kcalloc(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) bank->nr_pins, sizeof(*weint_data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (!weint_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) of_node_put(wkup_np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) for (idx = 0; idx < bank->nr_pins; ++idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) irq = irq_of_parse_and_map(bank->of_node, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (!irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) dev_err(dev, "irq number for eint-%s-%d not found\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) bank->name, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) weint_data[idx].irq = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) weint_data[idx].bank = bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) irq_set_chained_handler_and_data(irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) exynos_irq_eint0_15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) &weint_data[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (!muxed_banks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) of_node_put(wkup_np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) irq = irq_of_parse_and_map(wkup_np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) of_node_put(wkup_np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) if (!irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) dev_err(dev, "irq number for muxed EINTs not found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) muxed_data = devm_kzalloc(dev, sizeof(*muxed_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) + muxed_banks*sizeof(struct samsung_pin_bank *), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (!muxed_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) irq_set_chained_handler_and_data(irq, exynos_irq_demux_eint16_31,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) muxed_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) bank = d->pin_banks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) for (i = 0; i < d->nr_banks; ++i, ++bank) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (bank->eint_type != EINT_TYPE_WKUP_MUX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) muxed_data->banks[idx++] = bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) muxed_data->nr_banks = muxed_banks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) static void exynos_pinctrl_suspend_bank(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) struct samsung_pinctrl_drv_data *drvdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) struct samsung_pin_bank *bank)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) struct exynos_eint_gpio_save *save = bank->soc_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) void __iomem *regs = bank->eint_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) + bank->eint_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) + 2 * bank->eint_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) + 2 * bank->eint_offset + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) save->eint_mask = readl(regs + bank->irq_chip->eint_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) + bank->eint_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) pr_debug("%s: save con %#010x\n", bank->name, save->eint_con);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) pr_debug("%s: save fltcon0 %#010x\n", bank->name, save->eint_fltcon0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) pr_debug("%s: save fltcon1 %#010x\n", bank->name, save->eint_fltcon1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) pr_debug("%s: save mask %#010x\n", bank->name, save->eint_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) struct samsung_pin_bank *bank = drvdata->pin_banks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) struct exynos_irq_chip *irq_chip = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) for (i = 0; i < drvdata->nr_banks; ++i, ++bank) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if (bank->eint_type == EINT_TYPE_GPIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) exynos_pinctrl_suspend_bank(drvdata, bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) else if (bank->eint_type == EINT_TYPE_WKUP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (!irq_chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) irq_chip = bank->irq_chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) irq_chip->set_eint_wakeup_mask(drvdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) irq_chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) static void exynos_pinctrl_resume_bank(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) struct samsung_pinctrl_drv_data *drvdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) struct samsung_pin_bank *bank)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) struct exynos_eint_gpio_save *save = bank->soc_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) void __iomem *regs = bank->eint_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) pr_debug("%s: con %#010x => %#010x\n", bank->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) readl(regs + EXYNOS_GPIO_ECON_OFFSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) + bank->eint_offset), save->eint_con);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) + 2 * bank->eint_offset), save->eint_fltcon0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) + 2 * bank->eint_offset + 4), save->eint_fltcon1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) pr_debug("%s: mask %#010x => %#010x\n", bank->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) readl(regs + bank->irq_chip->eint_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) + bank->eint_offset), save->eint_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) + bank->eint_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) + 2 * bank->eint_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) + 2 * bank->eint_offset + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) writel(save->eint_mask, regs + bank->irq_chip->eint_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) + bank->eint_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) struct samsung_pin_bank *bank = drvdata->pin_banks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) for (i = 0; i < drvdata->nr_banks; ++i, ++bank)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (bank->eint_type == EINT_TYPE_GPIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) exynos_pinctrl_resume_bank(drvdata, bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) static void exynos_retention_enable(struct samsung_pinctrl_drv_data *drvdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (drvdata->retention_ctrl->refcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) atomic_inc(drvdata->retention_ctrl->refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) static void exynos_retention_disable(struct samsung_pinctrl_drv_data *drvdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) struct samsung_retention_ctrl *ctrl = drvdata->retention_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct regmap *pmu_regs = ctrl->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if (ctrl->refcnt && !atomic_dec_and_test(ctrl->refcnt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) for (i = 0; i < ctrl->nr_regs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) regmap_write(pmu_regs, ctrl->regs[i], ctrl->value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) struct samsung_retention_ctrl *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) exynos_retention_init(struct samsung_pinctrl_drv_data *drvdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) const struct samsung_retention_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) struct samsung_retention_ctrl *ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) struct regmap *pmu_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) ctrl = devm_kzalloc(drvdata->dev, sizeof(*ctrl), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (!ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) pmu_regs = exynos_get_pmu_regmap();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (IS_ERR(pmu_regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) return ERR_CAST(pmu_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) ctrl->priv = pmu_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) ctrl->regs = data->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) ctrl->nr_regs = data->nr_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) ctrl->value = data->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) ctrl->refcnt = data->refcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) ctrl->enable = exynos_retention_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) ctrl->disable = exynos_retention_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) /* Ensure that retention is disabled on driver init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) for (i = 0; i < ctrl->nr_regs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) regmap_write(pmu_regs, ctrl->regs[i], ctrl->value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) return ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) }