821 lines · c
1// SPDX-License-Identifier: GPL-2.0+2//3// S3C64xx specific support for pinctrl-samsung driver.4//5// Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>6//7// Based on pinctrl-exynos.c, please see the file for original copyrights.8//9// This file contains the Samsung S3C64xx specific information required by the10// the Samsung pinctrl/gpiolib driver. It also includes the implementation of11// external gpio and wakeup interrupt support.12 13#include <linux/init.h>14#include <linux/device.h>15#include <linux/interrupt.h>16#include <linux/irqdomain.h>17#include <linux/irq.h>18#include <linux/of_irq.h>19#include <linux/io.h>20#include <linux/irqchip/chained_irq.h>21#include <linux/slab.h>22#include <linux/err.h>23 24#include "pinctrl-samsung.h"25 26#define NUM_EINT0 2827#define NUM_EINT0_IRQ 428#define EINT_MAX_PER_REG 1629#define EINT_MAX_PER_GROUP 1630 31/* External GPIO and wakeup interrupt related definitions */32#define SVC_GROUP_SHIFT 433#define SVC_GROUP_MASK 0xf34#define SVC_NUM_MASK 0xf35#define SVC_GROUP(x) ((x >> SVC_GROUP_SHIFT) & \36 SVC_GROUP_MASK)37 38#define EINT12CON_REG 0x20039#define EINT12MASK_REG 0x24040#define EINT12PEND_REG 0x26041 42#define EINT_OFFS(i) ((i) % (2 * EINT_MAX_PER_GROUP))43#define EINT_GROUP(i) ((i) / EINT_MAX_PER_GROUP)44#define EINT_REG(g) (4 * ((g) / 2))45 46#define EINTCON_REG(i) (EINT12CON_REG + EINT_REG(EINT_GROUP(i)))47#define EINTMASK_REG(i) (EINT12MASK_REG + EINT_REG(EINT_GROUP(i)))48#define EINTPEND_REG(i) (EINT12PEND_REG + EINT_REG(EINT_GROUP(i)))49 50#define SERVICE_REG 0x28451#define SERVICEPEND_REG 0x28852 53#define EINT0CON0_REG 0x90054#define EINT0MASK_REG 0x92055#define EINT0PEND_REG 0x92456 57/* S3C64xx specific external interrupt trigger types */58#define EINT_LEVEL_LOW 059#define EINT_LEVEL_HIGH 160#define EINT_EDGE_FALLING 261#define EINT_EDGE_RISING 462#define EINT_EDGE_BOTH 663#define EINT_CON_MASK 0xF64#define EINT_CON_LEN 465 66#define S3C_PIN_PULL_DISABLE 067#define S3C_PIN_PULL_DOWN 168#define S3C_PIN_PULL_UP 269 70static const struct samsung_pin_bank_type bank_type_4bit_off = {71 .fld_width = { 4, 1, 2, 0, 2, 2, },72 .reg_offset = { 0x00, 0x04, 0x08, 0, 0x0c, 0x10, },73};74 75static const struct samsung_pin_bank_type bank_type_4bit_alive = {76 .fld_width = { 4, 1, 2, },77 .reg_offset = { 0x00, 0x04, 0x08, },78};79 80static const struct samsung_pin_bank_type bank_type_4bit2_off = {81 .fld_width = { 4, 1, 2, 0, 2, 2, },82 .reg_offset = { 0x00, 0x08, 0x0c, 0, 0x10, 0x14, },83};84 85static const struct samsung_pin_bank_type bank_type_4bit2_alive = {86 .fld_width = { 4, 1, 2, },87 .reg_offset = { 0x00, 0x08, 0x0c, },88};89 90static const struct samsung_pin_bank_type bank_type_2bit_off = {91 .fld_width = { 2, 1, 2, 0, 2, 2, },92 .reg_offset = { 0x00, 0x04, 0x08, 0, 0x0c, 0x10, },93};94 95static const struct samsung_pin_bank_type bank_type_2bit_alive = {96 .fld_width = { 2, 1, 2, },97 .reg_offset = { 0x00, 0x04, 0x08, },98};99 100#define PIN_BANK_4BIT(pins, reg, id) \101 { \102 .type = &bank_type_4bit_off, \103 .pctl_offset = reg, \104 .nr_pins = pins, \105 .eint_type = EINT_TYPE_NONE, \106 .name = id \107 }108 109#define PIN_BANK_4BIT_EINTG(pins, reg, id, eoffs) \110 { \111 .type = &bank_type_4bit_off, \112 .pctl_offset = reg, \113 .nr_pins = pins, \114 .eint_type = EINT_TYPE_GPIO, \115 .eint_func = 7, \116 .eint_mask = (1 << (pins)) - 1, \117 .eint_offset = eoffs, \118 .name = id \119 }120 121#define PIN_BANK_4BIT_EINTW(pins, reg, id, eoffs, emask) \122 { \123 .type = &bank_type_4bit_alive,\124 .pctl_offset = reg, \125 .nr_pins = pins, \126 .eint_type = EINT_TYPE_WKUP, \127 .eint_func = 3, \128 .eint_mask = emask, \129 .eint_offset = eoffs, \130 .name = id \131 }132 133#define PIN_BANK_4BIT2_EINTG(pins, reg, id, eoffs) \134 { \135 .type = &bank_type_4bit2_off, \136 .pctl_offset = reg, \137 .nr_pins = pins, \138 .eint_type = EINT_TYPE_GPIO, \139 .eint_func = 7, \140 .eint_mask = (1 << (pins)) - 1, \141 .eint_offset = eoffs, \142 .name = id \143 }144 145#define PIN_BANK_4BIT2_EINTW(pins, reg, id, eoffs, emask) \146 { \147 .type = &bank_type_4bit2_alive,\148 .pctl_offset = reg, \149 .nr_pins = pins, \150 .eint_type = EINT_TYPE_WKUP, \151 .eint_func = 3, \152 .eint_mask = emask, \153 .eint_offset = eoffs, \154 .name = id \155 }156 157#define PIN_BANK_4BIT2_ALIVE(pins, reg, id) \158 { \159 .type = &bank_type_4bit2_alive,\160 .pctl_offset = reg, \161 .nr_pins = pins, \162 .eint_type = EINT_TYPE_NONE, \163 .name = id \164 }165 166#define PIN_BANK_2BIT(pins, reg, id) \167 { \168 .type = &bank_type_2bit_off, \169 .pctl_offset = reg, \170 .nr_pins = pins, \171 .eint_type = EINT_TYPE_NONE, \172 .name = id \173 }174 175#define PIN_BANK_2BIT_EINTG(pins, reg, id, eoffs, emask) \176 { \177 .type = &bank_type_2bit_off, \178 .pctl_offset = reg, \179 .nr_pins = pins, \180 .eint_type = EINT_TYPE_GPIO, \181 .eint_func = 3, \182 .eint_mask = emask, \183 .eint_offset = eoffs, \184 .name = id \185 }186 187#define PIN_BANK_2BIT_EINTW(pins, reg, id, eoffs) \188 { \189 .type = &bank_type_2bit_alive,\190 .pctl_offset = reg, \191 .nr_pins = pins, \192 .eint_type = EINT_TYPE_WKUP, \193 .eint_func = 2, \194 .eint_mask = (1 << (pins)) - 1, \195 .eint_offset = eoffs, \196 .name = id \197 }198 199/**200 * struct s3c64xx_eint0_data - EINT0 common data201 * @drvdata: pin controller driver data202 * @domains: IRQ domains of particular EINT0 interrupts203 * @pins: pin offsets inside of banks of particular EINT0 interrupts204 */205struct s3c64xx_eint0_data {206 struct samsung_pinctrl_drv_data *drvdata;207 struct irq_domain *domains[NUM_EINT0];208 u8 pins[NUM_EINT0];209};210 211/**212 * struct s3c64xx_eint0_domain_data - EINT0 per-domain data213 * @bank: pin bank related to the domain214 * @eints: EINT0 interrupts related to the domain215 */216struct s3c64xx_eint0_domain_data {217 struct samsung_pin_bank *bank;218 u8 eints[];219};220 221/**222 * struct s3c64xx_eint_gpio_data - GPIO EINT data223 * @drvdata: pin controller driver data224 * @domains: array of domains related to EINT interrupt groups225 */226struct s3c64xx_eint_gpio_data {227 struct samsung_pinctrl_drv_data *drvdata;228 struct irq_domain *domains[];229};230 231/*232 * Common functions for S3C64xx EINT configuration233 */234 235static int s3c64xx_irq_get_trigger(unsigned int type)236{237 int trigger;238 239 switch (type) {240 case IRQ_TYPE_EDGE_RISING:241 trigger = EINT_EDGE_RISING;242 break;243 case IRQ_TYPE_EDGE_FALLING:244 trigger = EINT_EDGE_FALLING;245 break;246 case IRQ_TYPE_EDGE_BOTH:247 trigger = EINT_EDGE_BOTH;248 break;249 case IRQ_TYPE_LEVEL_HIGH:250 trigger = EINT_LEVEL_HIGH;251 break;252 case IRQ_TYPE_LEVEL_LOW:253 trigger = EINT_LEVEL_LOW;254 break;255 default:256 return -EINVAL;257 }258 259 return trigger;260}261 262static void s3c64xx_pud_value_init(struct samsung_pinctrl_drv_data *drvdata)263{264 unsigned int *pud_val = drvdata->pud_val;265 266 pud_val[PUD_PULL_DISABLE] = S3C_PIN_PULL_DISABLE;267 pud_val[PUD_PULL_DOWN] = S3C_PIN_PULL_DOWN;268 pud_val[PUD_PULL_UP] = S3C_PIN_PULL_UP;269}270 271static void s3c64xx_irq_set_handler(struct irq_data *d, unsigned int type)272{273 /* Edge- and level-triggered interrupts need different handlers */274 if (type & IRQ_TYPE_EDGE_BOTH)275 irq_set_handler_locked(d, handle_edge_irq);276 else277 irq_set_handler_locked(d, handle_level_irq);278}279 280static void s3c64xx_irq_set_function(struct samsung_pinctrl_drv_data *d,281 struct samsung_pin_bank *bank, int pin)282{283 const struct samsung_pin_bank_type *bank_type = bank->type;284 unsigned long flags;285 void __iomem *reg;286 u8 shift;287 u32 mask;288 u32 val;289 290 /* Make sure that pin is configured as interrupt */291 reg = d->virt_base + bank->pctl_offset;292 shift = pin;293 if (bank_type->fld_width[PINCFG_TYPE_FUNC] * shift >= 32) {294 /* 4-bit bank type with 2 con regs */295 reg += 4;296 shift -= 8;297 }298 299 shift = shift * bank_type->fld_width[PINCFG_TYPE_FUNC];300 mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;301 302 raw_spin_lock_irqsave(&bank->slock, flags);303 304 val = readl(reg);305 val &= ~(mask << shift);306 val |= bank->eint_func << shift;307 writel(val, reg);308 309 raw_spin_unlock_irqrestore(&bank->slock, flags);310}311 312/*313 * Functions for EINT GPIO configuration (EINT groups 1-9)314 */315 316static inline void s3c64xx_gpio_irq_set_mask(struct irq_data *irqd, bool mask)317{318 struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);319 struct samsung_pinctrl_drv_data *d = bank->drvdata;320 unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;321 void __iomem *reg = d->virt_base + EINTMASK_REG(bank->eint_offset);322 u32 val;323 324 val = readl(reg);325 if (mask)326 val |= 1 << index;327 else328 val &= ~(1 << index);329 writel(val, reg);330}331 332static void s3c64xx_gpio_irq_unmask(struct irq_data *irqd)333{334 s3c64xx_gpio_irq_set_mask(irqd, false);335}336 337static void s3c64xx_gpio_irq_mask(struct irq_data *irqd)338{339 s3c64xx_gpio_irq_set_mask(irqd, true);340}341 342static void s3c64xx_gpio_irq_ack(struct irq_data *irqd)343{344 struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);345 struct samsung_pinctrl_drv_data *d = bank->drvdata;346 unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;347 void __iomem *reg = d->virt_base + EINTPEND_REG(bank->eint_offset);348 349 writel(1 << index, reg);350}351 352static int s3c64xx_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)353{354 struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);355 struct samsung_pinctrl_drv_data *d = bank->drvdata;356 void __iomem *reg;357 int trigger;358 u8 shift;359 u32 val;360 361 trigger = s3c64xx_irq_get_trigger(type);362 if (trigger < 0) {363 pr_err("unsupported external interrupt type\n");364 return -EINVAL;365 }366 367 s3c64xx_irq_set_handler(irqd, type);368 369 /* Set up interrupt trigger */370 reg = d->virt_base + EINTCON_REG(bank->eint_offset);371 shift = EINT_OFFS(bank->eint_offset) + irqd->hwirq;372 shift = 4 * (shift / 4); /* 4 EINTs per trigger selector */373 374 val = readl(reg);375 val &= ~(EINT_CON_MASK << shift);376 val |= trigger << shift;377 writel(val, reg);378 379 s3c64xx_irq_set_function(d, bank, irqd->hwirq);380 381 return 0;382}383 384/*385 * irq_chip for gpio interrupts.386 */387static struct irq_chip s3c64xx_gpio_irq_chip = {388 .name = "GPIO",389 .irq_unmask = s3c64xx_gpio_irq_unmask,390 .irq_mask = s3c64xx_gpio_irq_mask,391 .irq_ack = s3c64xx_gpio_irq_ack,392 .irq_set_type = s3c64xx_gpio_irq_set_type,393};394 395static int s3c64xx_gpio_irq_map(struct irq_domain *h, unsigned int virq,396 irq_hw_number_t hw)397{398 struct samsung_pin_bank *bank = h->host_data;399 400 if (!(bank->eint_mask & (1 << hw)))401 return -EINVAL;402 403 irq_set_chip_and_handler(virq,404 &s3c64xx_gpio_irq_chip, handle_level_irq);405 irq_set_chip_data(virq, bank);406 407 return 0;408}409 410/*411 * irq domain callbacks for external gpio interrupt controller.412 */413static const struct irq_domain_ops s3c64xx_gpio_irqd_ops = {414 .map = s3c64xx_gpio_irq_map,415 .xlate = irq_domain_xlate_twocell,416};417 418static void s3c64xx_eint_gpio_irq(struct irq_desc *desc)419{420 struct irq_chip *chip = irq_desc_get_chip(desc);421 struct s3c64xx_eint_gpio_data *data = irq_desc_get_handler_data(desc);422 struct samsung_pinctrl_drv_data *drvdata = data->drvdata;423 424 chained_irq_enter(chip, desc);425 426 do {427 unsigned int svc;428 unsigned int group;429 unsigned int pin;430 int ret;431 432 svc = readl(drvdata->virt_base + SERVICE_REG);433 group = SVC_GROUP(svc);434 pin = svc & SVC_NUM_MASK;435 436 if (!group)437 break;438 439 /* Group 1 is used for two pin banks */440 if (group == 1) {441 if (pin < 8)442 group = 0;443 else444 pin -= 8;445 }446 447 ret = generic_handle_domain_irq(data->domains[group], pin);448 /*449 * Something must be really wrong if an unmapped EINT450 * was unmasked...451 */452 BUG_ON(ret);453 } while (1);454 455 chained_irq_exit(chip, desc);456}457 458/**459 * s3c64xx_eint_gpio_init() - setup handling of external gpio interrupts.460 * @d: driver data of samsung pinctrl driver.461 */462static int s3c64xx_eint_gpio_init(struct samsung_pinctrl_drv_data *d)463{464 struct s3c64xx_eint_gpio_data *data;465 struct samsung_pin_bank *bank;466 struct device *dev = d->dev;467 unsigned int nr_domains;468 unsigned int i;469 470 if (!d->irq) {471 dev_err(dev, "irq number not available\n");472 return -EINVAL;473 }474 475 nr_domains = 0;476 bank = d->pin_banks;477 for (i = 0; i < d->nr_banks; ++i, ++bank) {478 unsigned int nr_eints;479 unsigned int mask;480 481 if (bank->eint_type != EINT_TYPE_GPIO)482 continue;483 484 mask = bank->eint_mask;485 nr_eints = fls(mask);486 487 bank->irq_domain = irq_domain_create_linear(bank->fwnode,488 nr_eints, &s3c64xx_gpio_irqd_ops, bank);489 if (!bank->irq_domain) {490 dev_err(dev, "gpio irq domain add failed\n");491 return -ENXIO;492 }493 494 ++nr_domains;495 }496 497 data = devm_kzalloc(dev, struct_size(data, domains, nr_domains),498 GFP_KERNEL);499 if (!data)500 return -ENOMEM;501 data->drvdata = d;502 503 bank = d->pin_banks;504 nr_domains = 0;505 for (i = 0; i < d->nr_banks; ++i, ++bank) {506 if (bank->eint_type != EINT_TYPE_GPIO)507 continue;508 509 data->domains[nr_domains++] = bank->irq_domain;510 }511 512 irq_set_chained_handler_and_data(d->irq, s3c64xx_eint_gpio_irq, data);513 514 return 0;515}516 517/*518 * Functions for configuration of EINT0 wake-up interrupts519 */520 521static inline void s3c64xx_eint0_irq_set_mask(struct irq_data *irqd, bool mask)522{523 struct s3c64xx_eint0_domain_data *ddata =524 irq_data_get_irq_chip_data(irqd);525 struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;526 u32 val;527 528 val = readl(d->virt_base + EINT0MASK_REG);529 if (mask)530 val |= 1 << ddata->eints[irqd->hwirq];531 else532 val &= ~(1 << ddata->eints[irqd->hwirq]);533 writel(val, d->virt_base + EINT0MASK_REG);534}535 536static void s3c64xx_eint0_irq_unmask(struct irq_data *irqd)537{538 s3c64xx_eint0_irq_set_mask(irqd, false);539}540 541static void s3c64xx_eint0_irq_mask(struct irq_data *irqd)542{543 s3c64xx_eint0_irq_set_mask(irqd, true);544}545 546static void s3c64xx_eint0_irq_ack(struct irq_data *irqd)547{548 struct s3c64xx_eint0_domain_data *ddata =549 irq_data_get_irq_chip_data(irqd);550 struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;551 552 writel(1 << ddata->eints[irqd->hwirq],553 d->virt_base + EINT0PEND_REG);554}555 556static int s3c64xx_eint0_irq_set_type(struct irq_data *irqd, unsigned int type)557{558 struct s3c64xx_eint0_domain_data *ddata =559 irq_data_get_irq_chip_data(irqd);560 struct samsung_pin_bank *bank = ddata->bank;561 struct samsung_pinctrl_drv_data *d = bank->drvdata;562 void __iomem *reg;563 int trigger;564 u8 shift;565 u32 val;566 567 trigger = s3c64xx_irq_get_trigger(type);568 if (trigger < 0) {569 pr_err("unsupported external interrupt type\n");570 return -EINVAL;571 }572 573 s3c64xx_irq_set_handler(irqd, type);574 575 /* Set up interrupt trigger */576 reg = d->virt_base + EINT0CON0_REG;577 shift = ddata->eints[irqd->hwirq];578 if (shift >= EINT_MAX_PER_REG) {579 reg += 4;580 shift -= EINT_MAX_PER_REG;581 }582 shift = EINT_CON_LEN * (shift / 2);583 584 val = readl(reg);585 val &= ~(EINT_CON_MASK << shift);586 val |= trigger << shift;587 writel(val, reg);588 589 s3c64xx_irq_set_function(d, bank, irqd->hwirq);590 591 return 0;592}593 594/*595 * irq_chip for wakeup interrupts596 */597static struct irq_chip s3c64xx_eint0_irq_chip = {598 .name = "EINT0",599 .irq_unmask = s3c64xx_eint0_irq_unmask,600 .irq_mask = s3c64xx_eint0_irq_mask,601 .irq_ack = s3c64xx_eint0_irq_ack,602 .irq_set_type = s3c64xx_eint0_irq_set_type,603};604 605static inline void s3c64xx_irq_demux_eint(struct irq_desc *desc, u32 range)606{607 struct irq_chip *chip = irq_desc_get_chip(desc);608 struct s3c64xx_eint0_data *data = irq_desc_get_handler_data(desc);609 struct samsung_pinctrl_drv_data *drvdata = data->drvdata;610 unsigned int pend, mask;611 612 chained_irq_enter(chip, desc);613 614 pend = readl(drvdata->virt_base + EINT0PEND_REG);615 mask = readl(drvdata->virt_base + EINT0MASK_REG);616 617 pend = pend & range & ~mask;618 pend &= range;619 620 while (pend) {621 unsigned int irq;622 int ret;623 624 irq = fls(pend) - 1;625 pend &= ~(1 << irq);626 ret = generic_handle_domain_irq(data->domains[irq], data->pins[irq]);627 /*628 * Something must be really wrong if an unmapped EINT629 * was unmasked...630 */631 BUG_ON(ret);632 }633 634 chained_irq_exit(chip, desc);635}636 637static void s3c64xx_demux_eint0_3(struct irq_desc *desc)638{639 s3c64xx_irq_demux_eint(desc, 0xf);640}641 642static void s3c64xx_demux_eint4_11(struct irq_desc *desc)643{644 s3c64xx_irq_demux_eint(desc, 0xff0);645}646 647static void s3c64xx_demux_eint12_19(struct irq_desc *desc)648{649 s3c64xx_irq_demux_eint(desc, 0xff000);650}651 652static void s3c64xx_demux_eint20_27(struct irq_desc *desc)653{654 s3c64xx_irq_demux_eint(desc, 0xff00000);655}656 657static irq_flow_handler_t s3c64xx_eint0_handlers[NUM_EINT0_IRQ] = {658 s3c64xx_demux_eint0_3,659 s3c64xx_demux_eint4_11,660 s3c64xx_demux_eint12_19,661 s3c64xx_demux_eint20_27,662};663 664static int s3c64xx_eint0_irq_map(struct irq_domain *h, unsigned int virq,665 irq_hw_number_t hw)666{667 struct s3c64xx_eint0_domain_data *ddata = h->host_data;668 struct samsung_pin_bank *bank = ddata->bank;669 670 if (!(bank->eint_mask & (1 << hw)))671 return -EINVAL;672 673 irq_set_chip_and_handler(virq,674 &s3c64xx_eint0_irq_chip, handle_level_irq);675 irq_set_chip_data(virq, ddata);676 677 return 0;678}679 680/*681 * irq domain callbacks for external wakeup interrupt controller.682 */683static const struct irq_domain_ops s3c64xx_eint0_irqd_ops = {684 .map = s3c64xx_eint0_irq_map,685 .xlate = irq_domain_xlate_twocell,686};687 688/* list of external wakeup controllers supported */689static const struct of_device_id s3c64xx_eint0_irq_ids[] = {690 { .compatible = "samsung,s3c64xx-wakeup-eint", },691 { }692};693 694/**695 * s3c64xx_eint_eint0_init() - setup handling of external wakeup interrupts.696 * @d: driver data of samsung pinctrl driver.697 */698static int s3c64xx_eint_eint0_init(struct samsung_pinctrl_drv_data *d)699{700 struct device *dev = d->dev;701 struct device_node *eint0_np = NULL;702 struct device_node *np;703 struct samsung_pin_bank *bank;704 struct s3c64xx_eint0_data *data;705 unsigned int i;706 707 for_each_child_of_node(dev->of_node, np) {708 if (of_match_node(s3c64xx_eint0_irq_ids, np)) {709 eint0_np = np;710 break;711 }712 }713 if (!eint0_np)714 return -ENODEV;715 716 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);717 if (!data) {718 of_node_put(eint0_np);719 return -ENOMEM;720 }721 data->drvdata = d;722 723 for (i = 0; i < NUM_EINT0_IRQ; ++i) {724 unsigned int irq;725 726 irq = irq_of_parse_and_map(eint0_np, i);727 if (!irq) {728 dev_err(dev, "failed to get wakeup EINT IRQ %d\n", i);729 of_node_put(eint0_np);730 return -ENXIO;731 }732 733 irq_set_chained_handler_and_data(irq,734 s3c64xx_eint0_handlers[i],735 data);736 }737 of_node_put(eint0_np);738 739 bank = d->pin_banks;740 for (i = 0; i < d->nr_banks; ++i, ++bank) {741 struct s3c64xx_eint0_domain_data *ddata;742 unsigned int nr_eints;743 unsigned int mask;744 unsigned int irq;745 unsigned int pin;746 747 if (bank->eint_type != EINT_TYPE_WKUP)748 continue;749 750 mask = bank->eint_mask;751 nr_eints = fls(mask);752 753 ddata = devm_kzalloc(dev,754 sizeof(*ddata) + nr_eints, GFP_KERNEL);755 if (!ddata)756 return -ENOMEM;757 ddata->bank = bank;758 759 bank->irq_domain = irq_domain_create_linear(bank->fwnode,760 nr_eints, &s3c64xx_eint0_irqd_ops, ddata);761 if (!bank->irq_domain) {762 dev_err(dev, "wkup irq domain add failed\n");763 return -ENXIO;764 }765 766 irq = bank->eint_offset;767 mask = bank->eint_mask;768 for (pin = 0; mask; ++pin, mask >>= 1) {769 if (!(mask & 1))770 continue;771 data->domains[irq] = bank->irq_domain;772 data->pins[irq] = pin;773 ddata->eints[pin] = irq;774 ++irq;775 }776 }777 778 return 0;779}780 781/* pin banks of s3c64xx pin-controller 0 */782static const struct samsung_pin_bank_data s3c64xx_pin_banks0[] __initconst = {783 PIN_BANK_4BIT_EINTG(8, 0x000, "gpa", 0),784 PIN_BANK_4BIT_EINTG(7, 0x020, "gpb", 8),785 PIN_BANK_4BIT_EINTG(8, 0x040, "gpc", 16),786 PIN_BANK_4BIT_EINTG(5, 0x060, "gpd", 32),787 PIN_BANK_4BIT(5, 0x080, "gpe"),788 PIN_BANK_2BIT_EINTG(16, 0x0a0, "gpf", 48, 0x3fff),789 PIN_BANK_4BIT_EINTG(7, 0x0c0, "gpg", 64),790 PIN_BANK_4BIT2_EINTG(10, 0x0e0, "gph", 80),791 PIN_BANK_2BIT(16, 0x100, "gpi"),792 PIN_BANK_2BIT(12, 0x120, "gpj"),793 PIN_BANK_4BIT2_ALIVE(16, 0x800, "gpk"),794 PIN_BANK_4BIT2_EINTW(15, 0x810, "gpl", 16, 0x7f00),795 PIN_BANK_4BIT_EINTW(6, 0x820, "gpm", 23, 0x1f),796 PIN_BANK_2BIT_EINTW(16, 0x830, "gpn", 0),797 PIN_BANK_2BIT_EINTG(16, 0x140, "gpo", 96, 0xffff),798 PIN_BANK_2BIT_EINTG(15, 0x160, "gpp", 112, 0x7fff),799 PIN_BANK_2BIT_EINTG(9, 0x180, "gpq", 128, 0x1ff),800};801 802/*803 * Samsung pinctrl driver data for S3C64xx SoC. S3C64xx SoC includes804 * one gpio/pin-mux/pinconfig controller.805 */806static const struct samsung_pin_ctrl s3c64xx_pin_ctrl[] __initconst = {807 {808 /* pin-controller instance 1 data */809 .pin_banks = s3c64xx_pin_banks0,810 .nr_banks = ARRAY_SIZE(s3c64xx_pin_banks0),811 .eint_gpio_init = s3c64xx_eint_gpio_init,812 .eint_wkup_init = s3c64xx_eint_eint0_init,813 .pud_value_init = s3c64xx_pud_value_init,814 },815};816 817const struct samsung_pinctrl_of_match_data s3c64xx_of_data __initconst = {818 .ctrl = s3c64xx_pin_ctrl,819 .num_ctrl = ARRAY_SIZE(s3c64xx_pin_ctrl),820};821