Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }