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