Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 //
0003 // S3C64xx specific support for pinctrl-samsung driver.
0004 //
0005 // Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
0006 //
0007 // Based on pinctrl-exynos.c, please see the file for original copyrights.
0008 //
0009 // This file contains the Samsung S3C64xx specific information required by the
0010 // the Samsung pinctrl/gpiolib driver. It also includes the implementation of
0011 // external gpio and wakeup interrupt support.
0012 
0013 #include <linux/init.h>
0014 #include <linux/device.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/irqdomain.h>
0017 #include <linux/irq.h>
0018 #include <linux/of_irq.h>
0019 #include <linux/io.h>
0020 #include <linux/irqchip/chained_irq.h>
0021 #include <linux/slab.h>
0022 #include <linux/err.h>
0023 
0024 #include "pinctrl-samsung.h"
0025 
0026 #define NUM_EINT0       28
0027 #define NUM_EINT0_IRQ       4
0028 #define EINT_MAX_PER_REG    16
0029 #define EINT_MAX_PER_GROUP  16
0030 
0031 /* External GPIO and wakeup interrupt related definitions */
0032 #define SVC_GROUP_SHIFT     4
0033 #define SVC_GROUP_MASK      0xf
0034 #define SVC_NUM_MASK        0xf
0035 #define SVC_GROUP(x)        ((x >> SVC_GROUP_SHIFT) & \
0036                         SVC_GROUP_MASK)
0037 
0038 #define EINT12CON_REG       0x200
0039 #define EINT12MASK_REG      0x240
0040 #define EINT12PEND_REG      0x260
0041 
0042 #define EINT_OFFS(i)        ((i) % (2 * EINT_MAX_PER_GROUP))
0043 #define EINT_GROUP(i)       ((i) / EINT_MAX_PER_GROUP)
0044 #define EINT_REG(g)     (4 * ((g) / 2))
0045 
0046 #define EINTCON_REG(i)      (EINT12CON_REG + EINT_REG(EINT_GROUP(i)))
0047 #define EINTMASK_REG(i)     (EINT12MASK_REG + EINT_REG(EINT_GROUP(i)))
0048 #define EINTPEND_REG(i)     (EINT12PEND_REG + EINT_REG(EINT_GROUP(i)))
0049 
0050 #define SERVICE_REG     0x284
0051 #define SERVICEPEND_REG     0x288
0052 
0053 #define EINT0CON0_REG       0x900
0054 #define EINT0MASK_REG       0x920
0055 #define EINT0PEND_REG       0x924
0056 
0057 /* S3C64xx specific external interrupt trigger types */
0058 #define EINT_LEVEL_LOW      0
0059 #define EINT_LEVEL_HIGH     1
0060 #define EINT_EDGE_FALLING   2
0061 #define EINT_EDGE_RISING    4
0062 #define EINT_EDGE_BOTH      6
0063 #define EINT_CON_MASK       0xF
0064 #define EINT_CON_LEN        4
0065 
0066 static const struct samsung_pin_bank_type bank_type_4bit_off = {
0067     .fld_width = { 4, 1, 2, 0, 2, 2, },
0068     .reg_offset = { 0x00, 0x04, 0x08, 0, 0x0c, 0x10, },
0069 };
0070 
0071 static const struct samsung_pin_bank_type bank_type_4bit_alive = {
0072     .fld_width = { 4, 1, 2, },
0073     .reg_offset = { 0x00, 0x04, 0x08, },
0074 };
0075 
0076 static const struct samsung_pin_bank_type bank_type_4bit2_off = {
0077     .fld_width = { 4, 1, 2, 0, 2, 2, },
0078     .reg_offset = { 0x00, 0x08, 0x0c, 0, 0x10, 0x14, },
0079 };
0080 
0081 static const struct samsung_pin_bank_type bank_type_4bit2_alive = {
0082     .fld_width = { 4, 1, 2, },
0083     .reg_offset = { 0x00, 0x08, 0x0c, },
0084 };
0085 
0086 static const struct samsung_pin_bank_type bank_type_2bit_off = {
0087     .fld_width = { 2, 1, 2, 0, 2, 2, },
0088     .reg_offset = { 0x00, 0x04, 0x08, 0, 0x0c, 0x10, },
0089 };
0090 
0091 static const struct samsung_pin_bank_type bank_type_2bit_alive = {
0092     .fld_width = { 2, 1, 2, },
0093     .reg_offset = { 0x00, 0x04, 0x08, },
0094 };
0095 
0096 #define PIN_BANK_4BIT(pins, reg, id)            \
0097     {                       \
0098         .type       = &bank_type_4bit_off,  \
0099         .pctl_offset    = reg,          \
0100         .nr_pins    = pins,         \
0101         .eint_type  = EINT_TYPE_NONE,   \
0102         .name       = id            \
0103     }
0104 
0105 #define PIN_BANK_4BIT_EINTG(pins, reg, id, eoffs)   \
0106     {                       \
0107         .type       = &bank_type_4bit_off,  \
0108         .pctl_offset    = reg,          \
0109         .nr_pins    = pins,         \
0110         .eint_type  = EINT_TYPE_GPIO,   \
0111         .eint_func  = 7,            \
0112         .eint_mask  = (1 << (pins)) - 1,    \
0113         .eint_offset    = eoffs,        \
0114         .name       = id            \
0115     }
0116 
0117 #define PIN_BANK_4BIT_EINTW(pins, reg, id, eoffs, emask) \
0118     {                       \
0119         .type       = &bank_type_4bit_alive,\
0120         .pctl_offset    = reg,          \
0121         .nr_pins    = pins,         \
0122         .eint_type  = EINT_TYPE_WKUP,   \
0123         .eint_func  = 3,            \
0124         .eint_mask  = emask,        \
0125         .eint_offset    = eoffs,        \
0126         .name       = id            \
0127     }
0128 
0129 #define PIN_BANK_4BIT2_EINTG(pins, reg, id, eoffs)  \
0130     {                       \
0131         .type       = &bank_type_4bit2_off, \
0132         .pctl_offset    = reg,          \
0133         .nr_pins    = pins,         \
0134         .eint_type  = EINT_TYPE_GPIO,   \
0135         .eint_func  = 7,            \
0136         .eint_mask  = (1 << (pins)) - 1,    \
0137         .eint_offset    = eoffs,        \
0138         .name       = id            \
0139     }
0140 
0141 #define PIN_BANK_4BIT2_EINTW(pins, reg, id, eoffs, emask) \
0142     {                       \
0143         .type       = &bank_type_4bit2_alive,\
0144         .pctl_offset    = reg,          \
0145         .nr_pins    = pins,         \
0146         .eint_type  = EINT_TYPE_WKUP,   \
0147         .eint_func  = 3,            \
0148         .eint_mask  = emask,        \
0149         .eint_offset    = eoffs,        \
0150         .name       = id            \
0151     }
0152 
0153 #define PIN_BANK_4BIT2_ALIVE(pins, reg, id)     \
0154     {                       \
0155         .type       = &bank_type_4bit2_alive,\
0156         .pctl_offset    = reg,          \
0157         .nr_pins    = pins,         \
0158         .eint_type  = EINT_TYPE_NONE,   \
0159         .name       = id            \
0160     }
0161 
0162 #define PIN_BANK_2BIT(pins, reg, id)            \
0163     {                       \
0164         .type       = &bank_type_2bit_off,  \
0165         .pctl_offset    = reg,          \
0166         .nr_pins    = pins,         \
0167         .eint_type  = EINT_TYPE_NONE,   \
0168         .name       = id            \
0169     }
0170 
0171 #define PIN_BANK_2BIT_EINTG(pins, reg, id, eoffs, emask) \
0172     {                       \
0173         .type       = &bank_type_2bit_off,  \
0174         .pctl_offset    = reg,          \
0175         .nr_pins    = pins,         \
0176         .eint_type  = EINT_TYPE_GPIO,   \
0177         .eint_func  = 3,            \
0178         .eint_mask  = emask,        \
0179         .eint_offset    = eoffs,        \
0180         .name       = id            \
0181     }
0182 
0183 #define PIN_BANK_2BIT_EINTW(pins, reg, id, eoffs)   \
0184     {                       \
0185         .type       = &bank_type_2bit_alive,\
0186         .pctl_offset    = reg,          \
0187         .nr_pins    = pins,         \
0188         .eint_type  = EINT_TYPE_WKUP,   \
0189         .eint_func  = 2,            \
0190         .eint_mask  = (1 << (pins)) - 1,    \
0191         .eint_offset    = eoffs,        \
0192         .name       = id            \
0193     }
0194 
0195 /**
0196  * struct s3c64xx_eint0_data - EINT0 common data
0197  * @drvdata: pin controller driver data
0198  * @domains: IRQ domains of particular EINT0 interrupts
0199  * @pins: pin offsets inside of banks of particular EINT0 interrupts
0200  */
0201 struct s3c64xx_eint0_data {
0202     struct samsung_pinctrl_drv_data *drvdata;
0203     struct irq_domain *domains[NUM_EINT0];
0204     u8 pins[NUM_EINT0];
0205 };
0206 
0207 /**
0208  * struct s3c64xx_eint0_domain_data - EINT0 per-domain data
0209  * @bank: pin bank related to the domain
0210  * @eints: EINT0 interrupts related to the domain
0211  */
0212 struct s3c64xx_eint0_domain_data {
0213     struct samsung_pin_bank *bank;
0214     u8 eints[];
0215 };
0216 
0217 /**
0218  * struct s3c64xx_eint_gpio_data - GPIO EINT data
0219  * @drvdata: pin controller driver data
0220  * @domains: array of domains related to EINT interrupt groups
0221  */
0222 struct s3c64xx_eint_gpio_data {
0223     struct samsung_pinctrl_drv_data *drvdata;
0224     struct irq_domain *domains[];
0225 };
0226 
0227 /*
0228  * Common functions for S3C64xx EINT configuration
0229  */
0230 
0231 static int s3c64xx_irq_get_trigger(unsigned int type)
0232 {
0233     int trigger;
0234 
0235     switch (type) {
0236     case IRQ_TYPE_EDGE_RISING:
0237         trigger = EINT_EDGE_RISING;
0238         break;
0239     case IRQ_TYPE_EDGE_FALLING:
0240         trigger = EINT_EDGE_FALLING;
0241         break;
0242     case IRQ_TYPE_EDGE_BOTH:
0243         trigger = EINT_EDGE_BOTH;
0244         break;
0245     case IRQ_TYPE_LEVEL_HIGH:
0246         trigger = EINT_LEVEL_HIGH;
0247         break;
0248     case IRQ_TYPE_LEVEL_LOW:
0249         trigger = EINT_LEVEL_LOW;
0250         break;
0251     default:
0252         return -EINVAL;
0253     }
0254 
0255     return trigger;
0256 }
0257 
0258 static void s3c64xx_irq_set_handler(struct irq_data *d, unsigned int type)
0259 {
0260     /* Edge- and level-triggered interrupts need different handlers */
0261     if (type & IRQ_TYPE_EDGE_BOTH)
0262         irq_set_handler_locked(d, handle_edge_irq);
0263     else
0264         irq_set_handler_locked(d, handle_level_irq);
0265 }
0266 
0267 static void s3c64xx_irq_set_function(struct samsung_pinctrl_drv_data *d,
0268                     struct samsung_pin_bank *bank, int pin)
0269 {
0270     const struct samsung_pin_bank_type *bank_type = bank->type;
0271     unsigned long flags;
0272     void __iomem *reg;
0273     u8 shift;
0274     u32 mask;
0275     u32 val;
0276 
0277     /* Make sure that pin is configured as interrupt */
0278     reg = d->virt_base + bank->pctl_offset;
0279     shift = pin;
0280     if (bank_type->fld_width[PINCFG_TYPE_FUNC] * shift >= 32) {
0281         /* 4-bit bank type with 2 con regs */
0282         reg += 4;
0283         shift -= 8;
0284     }
0285 
0286     shift = shift * bank_type->fld_width[PINCFG_TYPE_FUNC];
0287     mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
0288 
0289     raw_spin_lock_irqsave(&bank->slock, flags);
0290 
0291     val = readl(reg);
0292     val &= ~(mask << shift);
0293     val |= bank->eint_func << shift;
0294     writel(val, reg);
0295 
0296     raw_spin_unlock_irqrestore(&bank->slock, flags);
0297 }
0298 
0299 /*
0300  * Functions for EINT GPIO configuration (EINT groups 1-9)
0301  */
0302 
0303 static inline void s3c64xx_gpio_irq_set_mask(struct irq_data *irqd, bool mask)
0304 {
0305     struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
0306     struct samsung_pinctrl_drv_data *d = bank->drvdata;
0307     unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
0308     void __iomem *reg = d->virt_base + EINTMASK_REG(bank->eint_offset);
0309     u32 val;
0310 
0311     val = readl(reg);
0312     if (mask)
0313         val |= 1 << index;
0314     else
0315         val &= ~(1 << index);
0316     writel(val, reg);
0317 }
0318 
0319 static void s3c64xx_gpio_irq_unmask(struct irq_data *irqd)
0320 {
0321     s3c64xx_gpio_irq_set_mask(irqd, false);
0322 }
0323 
0324 static void s3c64xx_gpio_irq_mask(struct irq_data *irqd)
0325 {
0326     s3c64xx_gpio_irq_set_mask(irqd, true);
0327 }
0328 
0329 static void s3c64xx_gpio_irq_ack(struct irq_data *irqd)
0330 {
0331     struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
0332     struct samsung_pinctrl_drv_data *d = bank->drvdata;
0333     unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
0334     void __iomem *reg = d->virt_base + EINTPEND_REG(bank->eint_offset);
0335 
0336     writel(1 << index, reg);
0337 }
0338 
0339 static int s3c64xx_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
0340 {
0341     struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
0342     struct samsung_pinctrl_drv_data *d = bank->drvdata;
0343     void __iomem *reg;
0344     int trigger;
0345     u8 shift;
0346     u32 val;
0347 
0348     trigger = s3c64xx_irq_get_trigger(type);
0349     if (trigger < 0) {
0350         pr_err("unsupported external interrupt type\n");
0351         return -EINVAL;
0352     }
0353 
0354     s3c64xx_irq_set_handler(irqd, type);
0355 
0356     /* Set up interrupt trigger */
0357     reg = d->virt_base + EINTCON_REG(bank->eint_offset);
0358     shift = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
0359     shift = 4 * (shift / 4); /* 4 EINTs per trigger selector */
0360 
0361     val = readl(reg);
0362     val &= ~(EINT_CON_MASK << shift);
0363     val |= trigger << shift;
0364     writel(val, reg);
0365 
0366     s3c64xx_irq_set_function(d, bank, irqd->hwirq);
0367 
0368     return 0;
0369 }
0370 
0371 /*
0372  * irq_chip for gpio interrupts.
0373  */
0374 static struct irq_chip s3c64xx_gpio_irq_chip = {
0375     .name       = "GPIO",
0376     .irq_unmask = s3c64xx_gpio_irq_unmask,
0377     .irq_mask   = s3c64xx_gpio_irq_mask,
0378     .irq_ack    = s3c64xx_gpio_irq_ack,
0379     .irq_set_type   = s3c64xx_gpio_irq_set_type,
0380 };
0381 
0382 static int s3c64xx_gpio_irq_map(struct irq_domain *h, unsigned int virq,
0383                     irq_hw_number_t hw)
0384 {
0385     struct samsung_pin_bank *bank = h->host_data;
0386 
0387     if (!(bank->eint_mask & (1 << hw)))
0388         return -EINVAL;
0389 
0390     irq_set_chip_and_handler(virq,
0391                 &s3c64xx_gpio_irq_chip, handle_level_irq);
0392     irq_set_chip_data(virq, bank);
0393 
0394     return 0;
0395 }
0396 
0397 /*
0398  * irq domain callbacks for external gpio interrupt controller.
0399  */
0400 static const struct irq_domain_ops s3c64xx_gpio_irqd_ops = {
0401     .map    = s3c64xx_gpio_irq_map,
0402     .xlate  = irq_domain_xlate_twocell,
0403 };
0404 
0405 static void s3c64xx_eint_gpio_irq(struct irq_desc *desc)
0406 {
0407     struct irq_chip *chip = irq_desc_get_chip(desc);
0408     struct s3c64xx_eint_gpio_data *data = irq_desc_get_handler_data(desc);
0409     struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
0410 
0411     chained_irq_enter(chip, desc);
0412 
0413     do {
0414         unsigned int svc;
0415         unsigned int group;
0416         unsigned int pin;
0417         int ret;
0418 
0419         svc = readl(drvdata->virt_base + SERVICE_REG);
0420         group = SVC_GROUP(svc);
0421         pin = svc & SVC_NUM_MASK;
0422 
0423         if (!group)
0424             break;
0425 
0426         /* Group 1 is used for two pin banks */
0427         if (group == 1) {
0428             if (pin < 8)
0429                 group = 0;
0430             else
0431                 pin -= 8;
0432         }
0433 
0434         ret = generic_handle_domain_irq(data->domains[group], pin);
0435         /*
0436          * Something must be really wrong if an unmapped EINT
0437          * was unmasked...
0438          */
0439         BUG_ON(ret);
0440     } while (1);
0441 
0442     chained_irq_exit(chip, desc);
0443 }
0444 
0445 /**
0446  * s3c64xx_eint_gpio_init() - setup handling of external gpio interrupts.
0447  * @d: driver data of samsung pinctrl driver.
0448  */
0449 static int s3c64xx_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
0450 {
0451     struct s3c64xx_eint_gpio_data *data;
0452     struct samsung_pin_bank *bank;
0453     struct device *dev = d->dev;
0454     unsigned int nr_domains;
0455     unsigned int i;
0456 
0457     if (!d->irq) {
0458         dev_err(dev, "irq number not available\n");
0459         return -EINVAL;
0460     }
0461 
0462     nr_domains = 0;
0463     bank = d->pin_banks;
0464     for (i = 0; i < d->nr_banks; ++i, ++bank) {
0465         unsigned int nr_eints;
0466         unsigned int mask;
0467 
0468         if (bank->eint_type != EINT_TYPE_GPIO)
0469             continue;
0470 
0471         mask = bank->eint_mask;
0472         nr_eints = fls(mask);
0473 
0474         bank->irq_domain = irq_domain_create_linear(bank->fwnode,
0475                     nr_eints, &s3c64xx_gpio_irqd_ops, bank);
0476         if (!bank->irq_domain) {
0477             dev_err(dev, "gpio irq domain add failed\n");
0478             return -ENXIO;
0479         }
0480 
0481         ++nr_domains;
0482     }
0483 
0484     data = devm_kzalloc(dev, struct_size(data, domains, nr_domains),
0485                 GFP_KERNEL);
0486     if (!data)
0487         return -ENOMEM;
0488     data->drvdata = d;
0489 
0490     bank = d->pin_banks;
0491     nr_domains = 0;
0492     for (i = 0; i < d->nr_banks; ++i, ++bank) {
0493         if (bank->eint_type != EINT_TYPE_GPIO)
0494             continue;
0495 
0496         data->domains[nr_domains++] = bank->irq_domain;
0497     }
0498 
0499     irq_set_chained_handler_and_data(d->irq, s3c64xx_eint_gpio_irq, data);
0500 
0501     return 0;
0502 }
0503 
0504 /*
0505  * Functions for configuration of EINT0 wake-up interrupts
0506  */
0507 
0508 static inline void s3c64xx_eint0_irq_set_mask(struct irq_data *irqd, bool mask)
0509 {
0510     struct s3c64xx_eint0_domain_data *ddata =
0511                     irq_data_get_irq_chip_data(irqd);
0512     struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
0513     u32 val;
0514 
0515     val = readl(d->virt_base + EINT0MASK_REG);
0516     if (mask)
0517         val |= 1 << ddata->eints[irqd->hwirq];
0518     else
0519         val &= ~(1 << ddata->eints[irqd->hwirq]);
0520     writel(val, d->virt_base + EINT0MASK_REG);
0521 }
0522 
0523 static void s3c64xx_eint0_irq_unmask(struct irq_data *irqd)
0524 {
0525     s3c64xx_eint0_irq_set_mask(irqd, false);
0526 }
0527 
0528 static void s3c64xx_eint0_irq_mask(struct irq_data *irqd)
0529 {
0530     s3c64xx_eint0_irq_set_mask(irqd, true);
0531 }
0532 
0533 static void s3c64xx_eint0_irq_ack(struct irq_data *irqd)
0534 {
0535     struct s3c64xx_eint0_domain_data *ddata =
0536                     irq_data_get_irq_chip_data(irqd);
0537     struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
0538 
0539     writel(1 << ddata->eints[irqd->hwirq],
0540                     d->virt_base + EINT0PEND_REG);
0541 }
0542 
0543 static int s3c64xx_eint0_irq_set_type(struct irq_data *irqd, unsigned int type)
0544 {
0545     struct s3c64xx_eint0_domain_data *ddata =
0546                     irq_data_get_irq_chip_data(irqd);
0547     struct samsung_pin_bank *bank = ddata->bank;
0548     struct samsung_pinctrl_drv_data *d = bank->drvdata;
0549     void __iomem *reg;
0550     int trigger;
0551     u8 shift;
0552     u32 val;
0553 
0554     trigger = s3c64xx_irq_get_trigger(type);
0555     if (trigger < 0) {
0556         pr_err("unsupported external interrupt type\n");
0557         return -EINVAL;
0558     }
0559 
0560     s3c64xx_irq_set_handler(irqd, type);
0561 
0562     /* Set up interrupt trigger */
0563     reg = d->virt_base + EINT0CON0_REG;
0564     shift = ddata->eints[irqd->hwirq];
0565     if (shift >= EINT_MAX_PER_REG) {
0566         reg += 4;
0567         shift -= EINT_MAX_PER_REG;
0568     }
0569     shift = EINT_CON_LEN * (shift / 2);
0570 
0571     val = readl(reg);
0572     val &= ~(EINT_CON_MASK << shift);
0573     val |= trigger << shift;
0574     writel(val, reg);
0575 
0576     s3c64xx_irq_set_function(d, bank, irqd->hwirq);
0577 
0578     return 0;
0579 }
0580 
0581 /*
0582  * irq_chip for wakeup interrupts
0583  */
0584 static struct irq_chip s3c64xx_eint0_irq_chip = {
0585     .name       = "EINT0",
0586     .irq_unmask = s3c64xx_eint0_irq_unmask,
0587     .irq_mask   = s3c64xx_eint0_irq_mask,
0588     .irq_ack    = s3c64xx_eint0_irq_ack,
0589     .irq_set_type   = s3c64xx_eint0_irq_set_type,
0590 };
0591 
0592 static inline void s3c64xx_irq_demux_eint(struct irq_desc *desc, u32 range)
0593 {
0594     struct irq_chip *chip = irq_desc_get_chip(desc);
0595     struct s3c64xx_eint0_data *data = irq_desc_get_handler_data(desc);
0596     struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
0597     unsigned int pend, mask;
0598 
0599     chained_irq_enter(chip, desc);
0600 
0601     pend = readl(drvdata->virt_base + EINT0PEND_REG);
0602     mask = readl(drvdata->virt_base + EINT0MASK_REG);
0603 
0604     pend = pend & range & ~mask;
0605     pend &= range;
0606 
0607     while (pend) {
0608         unsigned int irq;
0609         int ret;
0610 
0611         irq = fls(pend) - 1;
0612         pend &= ~(1 << irq);
0613         ret = generic_handle_domain_irq(data->domains[irq], data->pins[irq]);
0614         /*
0615          * Something must be really wrong if an unmapped EINT
0616          * was unmasked...
0617          */
0618         BUG_ON(ret);
0619     }
0620 
0621     chained_irq_exit(chip, desc);
0622 }
0623 
0624 static void s3c64xx_demux_eint0_3(struct irq_desc *desc)
0625 {
0626     s3c64xx_irq_demux_eint(desc, 0xf);
0627 }
0628 
0629 static void s3c64xx_demux_eint4_11(struct irq_desc *desc)
0630 {
0631     s3c64xx_irq_demux_eint(desc, 0xff0);
0632 }
0633 
0634 static void s3c64xx_demux_eint12_19(struct irq_desc *desc)
0635 {
0636     s3c64xx_irq_demux_eint(desc, 0xff000);
0637 }
0638 
0639 static void s3c64xx_demux_eint20_27(struct irq_desc *desc)
0640 {
0641     s3c64xx_irq_demux_eint(desc, 0xff00000);
0642 }
0643 
0644 static irq_flow_handler_t s3c64xx_eint0_handlers[NUM_EINT0_IRQ] = {
0645     s3c64xx_demux_eint0_3,
0646     s3c64xx_demux_eint4_11,
0647     s3c64xx_demux_eint12_19,
0648     s3c64xx_demux_eint20_27,
0649 };
0650 
0651 static int s3c64xx_eint0_irq_map(struct irq_domain *h, unsigned int virq,
0652                     irq_hw_number_t hw)
0653 {
0654     struct s3c64xx_eint0_domain_data *ddata = h->host_data;
0655     struct samsung_pin_bank *bank = ddata->bank;
0656 
0657     if (!(bank->eint_mask & (1 << hw)))
0658         return -EINVAL;
0659 
0660     irq_set_chip_and_handler(virq,
0661                 &s3c64xx_eint0_irq_chip, handle_level_irq);
0662     irq_set_chip_data(virq, ddata);
0663 
0664     return 0;
0665 }
0666 
0667 /*
0668  * irq domain callbacks for external wakeup interrupt controller.
0669  */
0670 static const struct irq_domain_ops s3c64xx_eint0_irqd_ops = {
0671     .map    = s3c64xx_eint0_irq_map,
0672     .xlate  = irq_domain_xlate_twocell,
0673 };
0674 
0675 /* list of external wakeup controllers supported */
0676 static const struct of_device_id s3c64xx_eint0_irq_ids[] = {
0677     { .compatible = "samsung,s3c64xx-wakeup-eint", },
0678     { }
0679 };
0680 
0681 /**
0682  * s3c64xx_eint_eint0_init() - setup handling of external wakeup interrupts.
0683  * @d: driver data of samsung pinctrl driver.
0684  */
0685 static int s3c64xx_eint_eint0_init(struct samsung_pinctrl_drv_data *d)
0686 {
0687     struct device *dev = d->dev;
0688     struct device_node *eint0_np = NULL;
0689     struct device_node *np;
0690     struct samsung_pin_bank *bank;
0691     struct s3c64xx_eint0_data *data;
0692     unsigned int i;
0693 
0694     for_each_child_of_node(dev->of_node, np) {
0695         if (of_match_node(s3c64xx_eint0_irq_ids, np)) {
0696             eint0_np = np;
0697             break;
0698         }
0699     }
0700     if (!eint0_np)
0701         return -ENODEV;
0702 
0703     data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
0704     if (!data) {
0705         of_node_put(eint0_np);
0706         return -ENOMEM;
0707     }
0708     data->drvdata = d;
0709 
0710     for (i = 0; i < NUM_EINT0_IRQ; ++i) {
0711         unsigned int irq;
0712 
0713         irq = irq_of_parse_and_map(eint0_np, i);
0714         if (!irq) {
0715             dev_err(dev, "failed to get wakeup EINT IRQ %d\n", i);
0716             of_node_put(eint0_np);
0717             return -ENXIO;
0718         }
0719 
0720         irq_set_chained_handler_and_data(irq,
0721                          s3c64xx_eint0_handlers[i],
0722                          data);
0723     }
0724     of_node_put(eint0_np);
0725 
0726     bank = d->pin_banks;
0727     for (i = 0; i < d->nr_banks; ++i, ++bank) {
0728         struct s3c64xx_eint0_domain_data *ddata;
0729         unsigned int nr_eints;
0730         unsigned int mask;
0731         unsigned int irq;
0732         unsigned int pin;
0733 
0734         if (bank->eint_type != EINT_TYPE_WKUP)
0735             continue;
0736 
0737         mask = bank->eint_mask;
0738         nr_eints = fls(mask);
0739 
0740         ddata = devm_kzalloc(dev,
0741                 sizeof(*ddata) + nr_eints, GFP_KERNEL);
0742         if (!ddata)
0743             return -ENOMEM;
0744         ddata->bank = bank;
0745 
0746         bank->irq_domain = irq_domain_create_linear(bank->fwnode,
0747                 nr_eints, &s3c64xx_eint0_irqd_ops, ddata);
0748         if (!bank->irq_domain) {
0749             dev_err(dev, "wkup irq domain add failed\n");
0750             return -ENXIO;
0751         }
0752 
0753         irq = bank->eint_offset;
0754         mask = bank->eint_mask;
0755         for (pin = 0; mask; ++pin, mask >>= 1) {
0756             if (!(mask & 1))
0757                 continue;
0758             data->domains[irq] = bank->irq_domain;
0759             data->pins[irq] = pin;
0760             ddata->eints[pin] = irq;
0761             ++irq;
0762         }
0763     }
0764 
0765     return 0;
0766 }
0767 
0768 /* pin banks of s3c64xx pin-controller 0 */
0769 static const struct samsung_pin_bank_data s3c64xx_pin_banks0[] __initconst = {
0770     PIN_BANK_4BIT_EINTG(8, 0x000, "gpa", 0),
0771     PIN_BANK_4BIT_EINTG(7, 0x020, "gpb", 8),
0772     PIN_BANK_4BIT_EINTG(8, 0x040, "gpc", 16),
0773     PIN_BANK_4BIT_EINTG(5, 0x060, "gpd", 32),
0774     PIN_BANK_4BIT(5, 0x080, "gpe"),
0775     PIN_BANK_2BIT_EINTG(16, 0x0a0, "gpf", 48, 0x3fff),
0776     PIN_BANK_4BIT_EINTG(7, 0x0c0, "gpg", 64),
0777     PIN_BANK_4BIT2_EINTG(10, 0x0e0, "gph", 80),
0778     PIN_BANK_2BIT(16, 0x100, "gpi"),
0779     PIN_BANK_2BIT(12, 0x120, "gpj"),
0780     PIN_BANK_4BIT2_ALIVE(16, 0x800, "gpk"),
0781     PIN_BANK_4BIT2_EINTW(15, 0x810, "gpl", 16, 0x7f00),
0782     PIN_BANK_4BIT_EINTW(6, 0x820, "gpm", 23, 0x1f),
0783     PIN_BANK_2BIT_EINTW(16, 0x830, "gpn", 0),
0784     PIN_BANK_2BIT_EINTG(16, 0x140, "gpo", 96, 0xffff),
0785     PIN_BANK_2BIT_EINTG(15, 0x160, "gpp", 112, 0x7fff),
0786     PIN_BANK_2BIT_EINTG(9, 0x180, "gpq", 128, 0x1ff),
0787 };
0788 
0789 /*
0790  * Samsung pinctrl driver data for S3C64xx SoC. S3C64xx SoC includes
0791  * one gpio/pin-mux/pinconfig controller.
0792  */
0793 static const struct samsung_pin_ctrl s3c64xx_pin_ctrl[] __initconst = {
0794     {
0795         /* pin-controller instance 1 data */
0796         .pin_banks  = s3c64xx_pin_banks0,
0797         .nr_banks   = ARRAY_SIZE(s3c64xx_pin_banks0),
0798         .eint_gpio_init = s3c64xx_eint_gpio_init,
0799         .eint_wkup_init = s3c64xx_eint_eint0_init,
0800     },
0801 };
0802 
0803 const struct samsung_pinctrl_of_match_data s3c64xx_of_data __initconst = {
0804     .ctrl       = s3c64xx_pin_ctrl,
0805     .num_ctrl   = ARRAY_SIZE(s3c64xx_pin_ctrl),
0806 };