Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 //
0003 // Exynos specific support for Samsung pinctrl/gpiolib driver with eint support.
0004 //
0005 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
0006 //      http://www.samsung.com
0007 // Copyright (c) 2012 Linaro Ltd
0008 //      http://www.linaro.org
0009 //
0010 // Author: Thomas Abraham <thomas.ab@samsung.com>
0011 //
0012 // This file contains the Samsung Exynos specific information required by the
0013 // the Samsung pinctrl/gpiolib driver. It also includes the implementation of
0014 // external gpio and wakeup interrupt support.
0015 
0016 #include <linux/device.h>
0017 #include <linux/interrupt.h>
0018 #include <linux/irqdomain.h>
0019 #include <linux/irq.h>
0020 #include <linux/irqchip/chained_irq.h>
0021 #include <linux/of.h>
0022 #include <linux/of_irq.h>
0023 #include <linux/slab.h>
0024 #include <linux/spinlock.h>
0025 #include <linux/regmap.h>
0026 #include <linux/err.h>
0027 #include <linux/soc/samsung/exynos-pmu.h>
0028 #include <linux/soc/samsung/exynos-regs-pmu.h>
0029 
0030 #include "pinctrl-samsung.h"
0031 #include "pinctrl-exynos.h"
0032 
0033 struct exynos_irq_chip {
0034     struct irq_chip chip;
0035 
0036     u32 eint_con;
0037     u32 eint_mask;
0038     u32 eint_pend;
0039     u32 *eint_wake_mask_value;
0040     u32 eint_wake_mask_reg;
0041     void (*set_eint_wakeup_mask)(struct samsung_pinctrl_drv_data *drvdata,
0042                      struct exynos_irq_chip *irq_chip);
0043 };
0044 
0045 static inline struct exynos_irq_chip *to_exynos_irq_chip(struct irq_chip *chip)
0046 {
0047     return container_of(chip, struct exynos_irq_chip, chip);
0048 }
0049 
0050 static void exynos_irq_mask(struct irq_data *irqd)
0051 {
0052     struct irq_chip *chip = irq_data_get_irq_chip(irqd);
0053     struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
0054     struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
0055     unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
0056     unsigned int mask;
0057     unsigned long flags;
0058 
0059     raw_spin_lock_irqsave(&bank->slock, flags);
0060 
0061     mask = readl(bank->eint_base + reg_mask);
0062     mask |= 1 << irqd->hwirq;
0063     writel(mask, bank->eint_base + reg_mask);
0064 
0065     raw_spin_unlock_irqrestore(&bank->slock, flags);
0066 }
0067 
0068 static void exynos_irq_ack(struct irq_data *irqd)
0069 {
0070     struct irq_chip *chip = irq_data_get_irq_chip(irqd);
0071     struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
0072     struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
0073     unsigned long reg_pend = our_chip->eint_pend + bank->eint_offset;
0074 
0075     writel(1 << irqd->hwirq, bank->eint_base + reg_pend);
0076 }
0077 
0078 static void exynos_irq_unmask(struct irq_data *irqd)
0079 {
0080     struct irq_chip *chip = irq_data_get_irq_chip(irqd);
0081     struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
0082     struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
0083     unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
0084     unsigned int mask;
0085     unsigned long flags;
0086 
0087     /*
0088      * Ack level interrupts right before unmask
0089      *
0090      * If we don't do this we'll get a double-interrupt.  Level triggered
0091      * interrupts must not fire an interrupt if the level is not
0092      * _currently_ active, even if it was active while the interrupt was
0093      * masked.
0094      */
0095     if (irqd_get_trigger_type(irqd) & IRQ_TYPE_LEVEL_MASK)
0096         exynos_irq_ack(irqd);
0097 
0098     raw_spin_lock_irqsave(&bank->slock, flags);
0099 
0100     mask = readl(bank->eint_base + reg_mask);
0101     mask &= ~(1 << irqd->hwirq);
0102     writel(mask, bank->eint_base + reg_mask);
0103 
0104     raw_spin_unlock_irqrestore(&bank->slock, flags);
0105 }
0106 
0107 static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
0108 {
0109     struct irq_chip *chip = irq_data_get_irq_chip(irqd);
0110     struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
0111     struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
0112     unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq;
0113     unsigned int con, trig_type;
0114     unsigned long reg_con = our_chip->eint_con + bank->eint_offset;
0115 
0116     switch (type) {
0117     case IRQ_TYPE_EDGE_RISING:
0118         trig_type = EXYNOS_EINT_EDGE_RISING;
0119         break;
0120     case IRQ_TYPE_EDGE_FALLING:
0121         trig_type = EXYNOS_EINT_EDGE_FALLING;
0122         break;
0123     case IRQ_TYPE_EDGE_BOTH:
0124         trig_type = EXYNOS_EINT_EDGE_BOTH;
0125         break;
0126     case IRQ_TYPE_LEVEL_HIGH:
0127         trig_type = EXYNOS_EINT_LEVEL_HIGH;
0128         break;
0129     case IRQ_TYPE_LEVEL_LOW:
0130         trig_type = EXYNOS_EINT_LEVEL_LOW;
0131         break;
0132     default:
0133         pr_err("unsupported external interrupt type\n");
0134         return -EINVAL;
0135     }
0136 
0137     if (type & IRQ_TYPE_EDGE_BOTH)
0138         irq_set_handler_locked(irqd, handle_edge_irq);
0139     else
0140         irq_set_handler_locked(irqd, handle_level_irq);
0141 
0142     con = readl(bank->eint_base + reg_con);
0143     con &= ~(EXYNOS_EINT_CON_MASK << shift);
0144     con |= trig_type << shift;
0145     writel(con, bank->eint_base + reg_con);
0146 
0147     return 0;
0148 }
0149 
0150 static int exynos_irq_request_resources(struct irq_data *irqd)
0151 {
0152     struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
0153     const struct samsung_pin_bank_type *bank_type = bank->type;
0154     unsigned long reg_con, flags;
0155     unsigned int shift, mask, con;
0156     int ret;
0157 
0158     ret = gpiochip_lock_as_irq(&bank->gpio_chip, irqd->hwirq);
0159     if (ret) {
0160         dev_err(bank->gpio_chip.parent,
0161             "unable to lock pin %s-%lu IRQ\n",
0162             bank->name, irqd->hwirq);
0163         return ret;
0164     }
0165 
0166     reg_con = bank->pctl_offset + bank_type->reg_offset[PINCFG_TYPE_FUNC];
0167     shift = irqd->hwirq * bank_type->fld_width[PINCFG_TYPE_FUNC];
0168     mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
0169 
0170     raw_spin_lock_irqsave(&bank->slock, flags);
0171 
0172     con = readl(bank->pctl_base + reg_con);
0173     con &= ~(mask << shift);
0174     con |= EXYNOS_PIN_CON_FUNC_EINT << shift;
0175     writel(con, bank->pctl_base + reg_con);
0176 
0177     raw_spin_unlock_irqrestore(&bank->slock, flags);
0178 
0179     return 0;
0180 }
0181 
0182 static void exynos_irq_release_resources(struct irq_data *irqd)
0183 {
0184     struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
0185     const struct samsung_pin_bank_type *bank_type = bank->type;
0186     unsigned long reg_con, flags;
0187     unsigned int shift, mask, con;
0188 
0189     reg_con = bank->pctl_offset + bank_type->reg_offset[PINCFG_TYPE_FUNC];
0190     shift = irqd->hwirq * bank_type->fld_width[PINCFG_TYPE_FUNC];
0191     mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
0192 
0193     raw_spin_lock_irqsave(&bank->slock, flags);
0194 
0195     con = readl(bank->pctl_base + reg_con);
0196     con &= ~(mask << shift);
0197     con |= PIN_CON_FUNC_INPUT << shift;
0198     writel(con, bank->pctl_base + reg_con);
0199 
0200     raw_spin_unlock_irqrestore(&bank->slock, flags);
0201 
0202     gpiochip_unlock_as_irq(&bank->gpio_chip, irqd->hwirq);
0203 }
0204 
0205 /*
0206  * irq_chip for gpio interrupts.
0207  */
0208 static const struct exynos_irq_chip exynos_gpio_irq_chip __initconst = {
0209     .chip = {
0210         .name = "exynos_gpio_irq_chip",
0211         .irq_unmask = exynos_irq_unmask,
0212         .irq_mask = exynos_irq_mask,
0213         .irq_ack = exynos_irq_ack,
0214         .irq_set_type = exynos_irq_set_type,
0215         .irq_request_resources = exynos_irq_request_resources,
0216         .irq_release_resources = exynos_irq_release_resources,
0217     },
0218     .eint_con = EXYNOS_GPIO_ECON_OFFSET,
0219     .eint_mask = EXYNOS_GPIO_EMASK_OFFSET,
0220     .eint_pend = EXYNOS_GPIO_EPEND_OFFSET,
0221     /* eint_wake_mask_value not used */
0222 };
0223 
0224 static int exynos_eint_irq_map(struct irq_domain *h, unsigned int virq,
0225                     irq_hw_number_t hw)
0226 {
0227     struct samsung_pin_bank *b = h->host_data;
0228 
0229     irq_set_chip_data(virq, b);
0230     irq_set_chip_and_handler(virq, &b->irq_chip->chip,
0231                     handle_level_irq);
0232     return 0;
0233 }
0234 
0235 /*
0236  * irq domain callbacks for external gpio and wakeup interrupt controllers.
0237  */
0238 static const struct irq_domain_ops exynos_eint_irqd_ops = {
0239     .map    = exynos_eint_irq_map,
0240     .xlate  = irq_domain_xlate_twocell,
0241 };
0242 
0243 static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
0244 {
0245     struct samsung_pinctrl_drv_data *d = data;
0246     struct samsung_pin_bank *bank = d->pin_banks;
0247     unsigned int svc, group, pin;
0248     int ret;
0249 
0250     svc = readl(bank->eint_base + EXYNOS_SVC_OFFSET);
0251     group = EXYNOS_SVC_GROUP(svc);
0252     pin = svc & EXYNOS_SVC_NUM_MASK;
0253 
0254     if (!group)
0255         return IRQ_HANDLED;
0256     bank += (group - 1);
0257 
0258     ret = generic_handle_domain_irq(bank->irq_domain, pin);
0259     if (ret)
0260         return IRQ_NONE;
0261 
0262     return IRQ_HANDLED;
0263 }
0264 
0265 struct exynos_eint_gpio_save {
0266     u32 eint_con;
0267     u32 eint_fltcon0;
0268     u32 eint_fltcon1;
0269     u32 eint_mask;
0270 };
0271 
0272 /*
0273  * exynos_eint_gpio_init() - setup handling of external gpio interrupts.
0274  * @d: driver data of samsung pinctrl driver.
0275  */
0276 __init int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
0277 {
0278     struct samsung_pin_bank *bank;
0279     struct device *dev = d->dev;
0280     int ret;
0281     int i;
0282 
0283     if (!d->irq) {
0284         dev_err(dev, "irq number not available\n");
0285         return -EINVAL;
0286     }
0287 
0288     ret = devm_request_irq(dev, d->irq, exynos_eint_gpio_irq,
0289                     0, dev_name(dev), d);
0290     if (ret) {
0291         dev_err(dev, "irq request failed\n");
0292         return -ENXIO;
0293     }
0294 
0295     bank = d->pin_banks;
0296     for (i = 0; i < d->nr_banks; ++i, ++bank) {
0297         if (bank->eint_type != EINT_TYPE_GPIO)
0298             continue;
0299 
0300         bank->irq_chip = devm_kmemdup(dev, &exynos_gpio_irq_chip,
0301                        sizeof(*bank->irq_chip), GFP_KERNEL);
0302         if (!bank->irq_chip) {
0303             ret = -ENOMEM;
0304             goto err_domains;
0305         }
0306         bank->irq_chip->chip.name = bank->name;
0307 
0308         bank->irq_domain = irq_domain_create_linear(bank->fwnode,
0309                 bank->nr_pins, &exynos_eint_irqd_ops, bank);
0310         if (!bank->irq_domain) {
0311             dev_err(dev, "gpio irq domain add failed\n");
0312             ret = -ENXIO;
0313             goto err_domains;
0314         }
0315 
0316         bank->soc_priv = devm_kzalloc(d->dev,
0317             sizeof(struct exynos_eint_gpio_save), GFP_KERNEL);
0318         if (!bank->soc_priv) {
0319             irq_domain_remove(bank->irq_domain);
0320             ret = -ENOMEM;
0321             goto err_domains;
0322         }
0323 
0324     }
0325 
0326     return 0;
0327 
0328 err_domains:
0329     for (--i, --bank; i >= 0; --i, --bank) {
0330         if (bank->eint_type != EINT_TYPE_GPIO)
0331             continue;
0332         irq_domain_remove(bank->irq_domain);
0333     }
0334 
0335     return ret;
0336 }
0337 
0338 static int exynos_wkup_irq_set_wake(struct irq_data *irqd, unsigned int on)
0339 {
0340     struct irq_chip *chip = irq_data_get_irq_chip(irqd);
0341     struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
0342     struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
0343     unsigned long bit = 1UL << (2 * bank->eint_offset + irqd->hwirq);
0344 
0345     pr_info("wake %s for irq %u (%s-%lu)\n", on ? "enabled" : "disabled",
0346         irqd->irq, bank->name, irqd->hwirq);
0347 
0348     if (!on)
0349         *our_chip->eint_wake_mask_value |= bit;
0350     else
0351         *our_chip->eint_wake_mask_value &= ~bit;
0352 
0353     return 0;
0354 }
0355 
0356 static void
0357 exynos_pinctrl_set_eint_wakeup_mask(struct samsung_pinctrl_drv_data *drvdata,
0358                     struct exynos_irq_chip *irq_chip)
0359 {
0360     struct regmap *pmu_regs;
0361 
0362     if (!drvdata->retention_ctrl || !drvdata->retention_ctrl->priv) {
0363         dev_warn(drvdata->dev,
0364              "No retention data configured bank with external wakeup interrupt. Wake-up mask will not be set.\n");
0365         return;
0366     }
0367 
0368     pmu_regs = drvdata->retention_ctrl->priv;
0369     dev_info(drvdata->dev,
0370          "Setting external wakeup interrupt mask: 0x%x\n",
0371          *irq_chip->eint_wake_mask_value);
0372 
0373     regmap_write(pmu_regs, irq_chip->eint_wake_mask_reg,
0374              *irq_chip->eint_wake_mask_value);
0375 }
0376 
0377 static void
0378 s5pv210_pinctrl_set_eint_wakeup_mask(struct samsung_pinctrl_drv_data *drvdata,
0379                     struct exynos_irq_chip *irq_chip)
0380 
0381 {
0382     void __iomem *clk_base;
0383 
0384     if (!drvdata->retention_ctrl || !drvdata->retention_ctrl->priv) {
0385         dev_warn(drvdata->dev,
0386              "No retention data configured bank with external wakeup interrupt. Wake-up mask will not be set.\n");
0387         return;
0388     }
0389 
0390 
0391     clk_base = (void __iomem *) drvdata->retention_ctrl->priv;
0392 
0393     __raw_writel(*irq_chip->eint_wake_mask_value,
0394              clk_base + irq_chip->eint_wake_mask_reg);
0395 }
0396 
0397 static u32 eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED;
0398 /*
0399  * irq_chip for wakeup interrupts
0400  */
0401 static const struct exynos_irq_chip s5pv210_wkup_irq_chip __initconst = {
0402     .chip = {
0403         .name = "s5pv210_wkup_irq_chip",
0404         .irq_unmask = exynos_irq_unmask,
0405         .irq_mask = exynos_irq_mask,
0406         .irq_ack = exynos_irq_ack,
0407         .irq_set_type = exynos_irq_set_type,
0408         .irq_set_wake = exynos_wkup_irq_set_wake,
0409         .irq_request_resources = exynos_irq_request_resources,
0410         .irq_release_resources = exynos_irq_release_resources,
0411     },
0412     .eint_con = EXYNOS_WKUP_ECON_OFFSET,
0413     .eint_mask = EXYNOS_WKUP_EMASK_OFFSET,
0414     .eint_pend = EXYNOS_WKUP_EPEND_OFFSET,
0415     .eint_wake_mask_value = &eint_wake_mask_value,
0416     /* Only differences with exynos4210_wkup_irq_chip: */
0417     .eint_wake_mask_reg = S5PV210_EINT_WAKEUP_MASK,
0418     .set_eint_wakeup_mask = s5pv210_pinctrl_set_eint_wakeup_mask,
0419 };
0420 
0421 static const struct exynos_irq_chip exynos4210_wkup_irq_chip __initconst = {
0422     .chip = {
0423         .name = "exynos4210_wkup_irq_chip",
0424         .irq_unmask = exynos_irq_unmask,
0425         .irq_mask = exynos_irq_mask,
0426         .irq_ack = exynos_irq_ack,
0427         .irq_set_type = exynos_irq_set_type,
0428         .irq_set_wake = exynos_wkup_irq_set_wake,
0429         .irq_request_resources = exynos_irq_request_resources,
0430         .irq_release_resources = exynos_irq_release_resources,
0431     },
0432     .eint_con = EXYNOS_WKUP_ECON_OFFSET,
0433     .eint_mask = EXYNOS_WKUP_EMASK_OFFSET,
0434     .eint_pend = EXYNOS_WKUP_EPEND_OFFSET,
0435     .eint_wake_mask_value = &eint_wake_mask_value,
0436     .eint_wake_mask_reg = EXYNOS_EINT_WAKEUP_MASK,
0437     .set_eint_wakeup_mask = exynos_pinctrl_set_eint_wakeup_mask,
0438 };
0439 
0440 static const struct exynos_irq_chip exynos7_wkup_irq_chip __initconst = {
0441     .chip = {
0442         .name = "exynos7_wkup_irq_chip",
0443         .irq_unmask = exynos_irq_unmask,
0444         .irq_mask = exynos_irq_mask,
0445         .irq_ack = exynos_irq_ack,
0446         .irq_set_type = exynos_irq_set_type,
0447         .irq_set_wake = exynos_wkup_irq_set_wake,
0448         .irq_request_resources = exynos_irq_request_resources,
0449         .irq_release_resources = exynos_irq_release_resources,
0450     },
0451     .eint_con = EXYNOS7_WKUP_ECON_OFFSET,
0452     .eint_mask = EXYNOS7_WKUP_EMASK_OFFSET,
0453     .eint_pend = EXYNOS7_WKUP_EPEND_OFFSET,
0454     .eint_wake_mask_value = &eint_wake_mask_value,
0455     .eint_wake_mask_reg = EXYNOS5433_EINT_WAKEUP_MASK,
0456     .set_eint_wakeup_mask = exynos_pinctrl_set_eint_wakeup_mask,
0457 };
0458 
0459 /* list of external wakeup controllers supported */
0460 static const struct of_device_id exynos_wkup_irq_ids[] = {
0461     { .compatible = "samsung,s5pv210-wakeup-eint",
0462             .data = &s5pv210_wkup_irq_chip },
0463     { .compatible = "samsung,exynos4210-wakeup-eint",
0464             .data = &exynos4210_wkup_irq_chip },
0465     { .compatible = "samsung,exynos7-wakeup-eint",
0466             .data = &exynos7_wkup_irq_chip },
0467     { .compatible = "samsung,exynos850-wakeup-eint",
0468             .data = &exynos7_wkup_irq_chip },
0469     { .compatible = "samsung,exynosautov9-wakeup-eint",
0470             .data = &exynos7_wkup_irq_chip },
0471     { }
0472 };
0473 
0474 /* interrupt handler for wakeup interrupts 0..15 */
0475 static void exynos_irq_eint0_15(struct irq_desc *desc)
0476 {
0477     struct exynos_weint_data *eintd = irq_desc_get_handler_data(desc);
0478     struct samsung_pin_bank *bank = eintd->bank;
0479     struct irq_chip *chip = irq_desc_get_chip(desc);
0480 
0481     chained_irq_enter(chip, desc);
0482 
0483     generic_handle_domain_irq(bank->irq_domain, eintd->irq);
0484 
0485     chained_irq_exit(chip, desc);
0486 }
0487 
0488 static inline void exynos_irq_demux_eint(unsigned int pend,
0489                         struct irq_domain *domain)
0490 {
0491     unsigned int irq;
0492 
0493     while (pend) {
0494         irq = fls(pend) - 1;
0495         generic_handle_domain_irq(domain, irq);
0496         pend &= ~(1 << irq);
0497     }
0498 }
0499 
0500 /* interrupt handler for wakeup interrupt 16 */
0501 static void exynos_irq_demux_eint16_31(struct irq_desc *desc)
0502 {
0503     struct irq_chip *chip = irq_desc_get_chip(desc);
0504     struct exynos_muxed_weint_data *eintd = irq_desc_get_handler_data(desc);
0505     unsigned int pend;
0506     unsigned int mask;
0507     int i;
0508 
0509     chained_irq_enter(chip, desc);
0510 
0511     for (i = 0; i < eintd->nr_banks; ++i) {
0512         struct samsung_pin_bank *b = eintd->banks[i];
0513         pend = readl(b->eint_base + b->irq_chip->eint_pend
0514                 + b->eint_offset);
0515         mask = readl(b->eint_base + b->irq_chip->eint_mask
0516                 + b->eint_offset);
0517         exynos_irq_demux_eint(pend & ~mask, b->irq_domain);
0518     }
0519 
0520     chained_irq_exit(chip, desc);
0521 }
0522 
0523 /*
0524  * exynos_eint_wkup_init() - setup handling of external wakeup interrupts.
0525  * @d: driver data of samsung pinctrl driver.
0526  */
0527 __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
0528 {
0529     struct device *dev = d->dev;
0530     struct device_node *wkup_np = NULL;
0531     struct device_node *np;
0532     struct samsung_pin_bank *bank;
0533     struct exynos_weint_data *weint_data;
0534     struct exynos_muxed_weint_data *muxed_data;
0535     const struct exynos_irq_chip *irq_chip;
0536     unsigned int muxed_banks = 0;
0537     unsigned int i;
0538     int idx, irq;
0539 
0540     for_each_child_of_node(dev->of_node, np) {
0541         const struct of_device_id *match;
0542 
0543         match = of_match_node(exynos_wkup_irq_ids, np);
0544         if (match) {
0545             irq_chip = match->data;
0546             wkup_np = np;
0547             break;
0548         }
0549     }
0550     if (!wkup_np)
0551         return -ENODEV;
0552 
0553     bank = d->pin_banks;
0554     for (i = 0; i < d->nr_banks; ++i, ++bank) {
0555         if (bank->eint_type != EINT_TYPE_WKUP)
0556             continue;
0557 
0558         bank->irq_chip = devm_kmemdup(dev, irq_chip, sizeof(*irq_chip),
0559                           GFP_KERNEL);
0560         if (!bank->irq_chip) {
0561             of_node_put(wkup_np);
0562             return -ENOMEM;
0563         }
0564         bank->irq_chip->chip.name = bank->name;
0565 
0566         bank->irq_domain = irq_domain_create_linear(bank->fwnode,
0567                 bank->nr_pins, &exynos_eint_irqd_ops, bank);
0568         if (!bank->irq_domain) {
0569             dev_err(dev, "wkup irq domain add failed\n");
0570             of_node_put(wkup_np);
0571             return -ENXIO;
0572         }
0573 
0574         if (!fwnode_property_present(bank->fwnode, "interrupts")) {
0575             bank->eint_type = EINT_TYPE_WKUP_MUX;
0576             ++muxed_banks;
0577             continue;
0578         }
0579 
0580         weint_data = devm_kcalloc(dev,
0581                       bank->nr_pins, sizeof(*weint_data),
0582                       GFP_KERNEL);
0583         if (!weint_data) {
0584             of_node_put(wkup_np);
0585             return -ENOMEM;
0586         }
0587 
0588         for (idx = 0; idx < bank->nr_pins; ++idx) {
0589             irq = irq_of_parse_and_map(to_of_node(bank->fwnode), idx);
0590             if (!irq) {
0591                 dev_err(dev, "irq number for eint-%s-%d not found\n",
0592                             bank->name, idx);
0593                 continue;
0594             }
0595             weint_data[idx].irq = idx;
0596             weint_data[idx].bank = bank;
0597             irq_set_chained_handler_and_data(irq,
0598                              exynos_irq_eint0_15,
0599                              &weint_data[idx]);
0600         }
0601     }
0602 
0603     if (!muxed_banks) {
0604         of_node_put(wkup_np);
0605         return 0;
0606     }
0607 
0608     irq = irq_of_parse_and_map(wkup_np, 0);
0609     of_node_put(wkup_np);
0610     if (!irq) {
0611         dev_err(dev, "irq number for muxed EINTs not found\n");
0612         return 0;
0613     }
0614 
0615     muxed_data = devm_kzalloc(dev, sizeof(*muxed_data)
0616         + muxed_banks*sizeof(struct samsung_pin_bank *), GFP_KERNEL);
0617     if (!muxed_data)
0618         return -ENOMEM;
0619 
0620     irq_set_chained_handler_and_data(irq, exynos_irq_demux_eint16_31,
0621                      muxed_data);
0622 
0623     bank = d->pin_banks;
0624     idx = 0;
0625     for (i = 0; i < d->nr_banks; ++i, ++bank) {
0626         if (bank->eint_type != EINT_TYPE_WKUP_MUX)
0627             continue;
0628 
0629         muxed_data->banks[idx++] = bank;
0630     }
0631     muxed_data->nr_banks = muxed_banks;
0632 
0633     return 0;
0634 }
0635 
0636 static void exynos_pinctrl_suspend_bank(
0637                 struct samsung_pinctrl_drv_data *drvdata,
0638                 struct samsung_pin_bank *bank)
0639 {
0640     struct exynos_eint_gpio_save *save = bank->soc_priv;
0641     void __iomem *regs = bank->eint_base;
0642 
0643     save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
0644                         + bank->eint_offset);
0645     save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
0646                         + 2 * bank->eint_offset);
0647     save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
0648                         + 2 * bank->eint_offset + 4);
0649     save->eint_mask = readl(regs + bank->irq_chip->eint_mask
0650                         + bank->eint_offset);
0651 
0652     pr_debug("%s: save     con %#010x\n", bank->name, save->eint_con);
0653     pr_debug("%s: save fltcon0 %#010x\n", bank->name, save->eint_fltcon0);
0654     pr_debug("%s: save fltcon1 %#010x\n", bank->name, save->eint_fltcon1);
0655     pr_debug("%s: save    mask %#010x\n", bank->name, save->eint_mask);
0656 }
0657 
0658 void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
0659 {
0660     struct samsung_pin_bank *bank = drvdata->pin_banks;
0661     struct exynos_irq_chip *irq_chip = NULL;
0662     int i;
0663 
0664     for (i = 0; i < drvdata->nr_banks; ++i, ++bank) {
0665         if (bank->eint_type == EINT_TYPE_GPIO)
0666             exynos_pinctrl_suspend_bank(drvdata, bank);
0667         else if (bank->eint_type == EINT_TYPE_WKUP) {
0668             if (!irq_chip) {
0669                 irq_chip = bank->irq_chip;
0670                 irq_chip->set_eint_wakeup_mask(drvdata,
0671                                    irq_chip);
0672             }
0673         }
0674     }
0675 }
0676 
0677 static void exynos_pinctrl_resume_bank(
0678                 struct samsung_pinctrl_drv_data *drvdata,
0679                 struct samsung_pin_bank *bank)
0680 {
0681     struct exynos_eint_gpio_save *save = bank->soc_priv;
0682     void __iomem *regs = bank->eint_base;
0683 
0684     pr_debug("%s:     con %#010x => %#010x\n", bank->name,
0685             readl(regs + EXYNOS_GPIO_ECON_OFFSET
0686             + bank->eint_offset), save->eint_con);
0687     pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
0688             readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
0689             + 2 * bank->eint_offset), save->eint_fltcon0);
0690     pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
0691             readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
0692             + 2 * bank->eint_offset + 4), save->eint_fltcon1);
0693     pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
0694             readl(regs + bank->irq_chip->eint_mask
0695             + bank->eint_offset), save->eint_mask);
0696 
0697     writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
0698                         + bank->eint_offset);
0699     writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
0700                         + 2 * bank->eint_offset);
0701     writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
0702                         + 2 * bank->eint_offset + 4);
0703     writel(save->eint_mask, regs + bank->irq_chip->eint_mask
0704                         + bank->eint_offset);
0705 }
0706 
0707 void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
0708 {
0709     struct samsung_pin_bank *bank = drvdata->pin_banks;
0710     int i;
0711 
0712     for (i = 0; i < drvdata->nr_banks; ++i, ++bank)
0713         if (bank->eint_type == EINT_TYPE_GPIO)
0714             exynos_pinctrl_resume_bank(drvdata, bank);
0715 }
0716 
0717 static void exynos_retention_enable(struct samsung_pinctrl_drv_data *drvdata)
0718 {
0719     if (drvdata->retention_ctrl->refcnt)
0720         atomic_inc(drvdata->retention_ctrl->refcnt);
0721 }
0722 
0723 static void exynos_retention_disable(struct samsung_pinctrl_drv_data *drvdata)
0724 {
0725     struct samsung_retention_ctrl *ctrl = drvdata->retention_ctrl;
0726     struct regmap *pmu_regs = ctrl->priv;
0727     int i;
0728 
0729     if (ctrl->refcnt && !atomic_dec_and_test(ctrl->refcnt))
0730         return;
0731 
0732     for (i = 0; i < ctrl->nr_regs; i++)
0733         regmap_write(pmu_regs, ctrl->regs[i], ctrl->value);
0734 }
0735 
0736 struct samsung_retention_ctrl *
0737 exynos_retention_init(struct samsung_pinctrl_drv_data *drvdata,
0738               const struct samsung_retention_data *data)
0739 {
0740     struct samsung_retention_ctrl *ctrl;
0741     struct regmap *pmu_regs;
0742     int i;
0743 
0744     ctrl = devm_kzalloc(drvdata->dev, sizeof(*ctrl), GFP_KERNEL);
0745     if (!ctrl)
0746         return ERR_PTR(-ENOMEM);
0747 
0748     pmu_regs = exynos_get_pmu_regmap();
0749     if (IS_ERR(pmu_regs))
0750         return ERR_CAST(pmu_regs);
0751 
0752     ctrl->priv = pmu_regs;
0753     ctrl->regs = data->regs;
0754     ctrl->nr_regs = data->nr_regs;
0755     ctrl->value = data->value;
0756     ctrl->refcnt = data->refcnt;
0757     ctrl->enable = exynos_retention_enable;
0758     ctrl->disable = exynos_retention_disable;
0759 
0760     /* Ensure that retention is disabled on driver init */
0761     for (i = 0; i < ctrl->nr_regs; i++)
0762         regmap_write(pmu_regs, ctrl->regs[i], ctrl->value);
0763 
0764     return ctrl;
0765 }