linux/drivers/pinctrl/samsung/pinctrl-exynos.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2//
   3// Exynos specific support for Samsung pinctrl/gpiolib driver with eint support.
   4//
   5// Copyright (c) 2012 Samsung Electronics Co., Ltd.
   6//              http://www.samsung.com
   7// Copyright (c) 2012 Linaro Ltd
   8//              http://www.linaro.org
   9//
  10// Author: Thomas Abraham <thomas.ab@samsung.com>
  11//
  12// This file contains the Samsung Exynos specific information required by the
  13// the Samsung pinctrl/gpiolib driver. It also includes the implementation of
  14// external gpio and wakeup interrupt support.
  15
  16#include <linux/device.h>
  17#include <linux/interrupt.h>
  18#include <linux/irqdomain.h>
  19#include <linux/irq.h>
  20#include <linux/irqchip/chained_irq.h>
  21#include <linux/of.h>
  22#include <linux/of_irq.h>
  23#include <linux/slab.h>
  24#include <linux/spinlock.h>
  25#include <linux/regmap.h>
  26#include <linux/err.h>
  27#include <linux/soc/samsung/exynos-pmu.h>
  28#include <linux/soc/samsung/exynos-regs-pmu.h>
  29
  30#include <dt-bindings/pinctrl/samsung.h>
  31
  32#include "pinctrl-samsung.h"
  33#include "pinctrl-exynos.h"
  34
  35struct exynos_irq_chip {
  36        struct irq_chip chip;
  37
  38        u32 eint_con;
  39        u32 eint_mask;
  40        u32 eint_pend;
  41        u32 *eint_wake_mask_value;
  42        u32 eint_wake_mask_reg;
  43        void (*set_eint_wakeup_mask)(struct samsung_pinctrl_drv_data *drvdata,
  44                                     struct exynos_irq_chip *irq_chip);
  45};
  46
  47static inline struct exynos_irq_chip *to_exynos_irq_chip(struct irq_chip *chip)
  48{
  49        return container_of(chip, struct exynos_irq_chip, chip);
  50}
  51
  52static void exynos_irq_mask(struct irq_data *irqd)
  53{
  54        struct irq_chip *chip = irq_data_get_irq_chip(irqd);
  55        struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
  56        struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
  57        unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
  58        unsigned int mask;
  59        unsigned long flags;
  60
  61        raw_spin_lock_irqsave(&bank->slock, flags);
  62
  63        mask = readl(bank->eint_base + reg_mask);
  64        mask |= 1 << irqd->hwirq;
  65        writel(mask, bank->eint_base + reg_mask);
  66
  67        raw_spin_unlock_irqrestore(&bank->slock, flags);
  68}
  69
  70static void exynos_irq_ack(struct irq_data *irqd)
  71{
  72        struct irq_chip *chip = irq_data_get_irq_chip(irqd);
  73        struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
  74        struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
  75        unsigned long reg_pend = our_chip->eint_pend + bank->eint_offset;
  76
  77        writel(1 << irqd->hwirq, bank->eint_base + reg_pend);
  78}
  79
  80static void exynos_irq_unmask(struct irq_data *irqd)
  81{
  82        struct irq_chip *chip = irq_data_get_irq_chip(irqd);
  83        struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
  84        struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
  85        unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
  86        unsigned int mask;
  87        unsigned long flags;
  88
  89        /*
  90         * Ack level interrupts right before unmask
  91         *
  92         * If we don't do this we'll get a double-interrupt.  Level triggered
  93         * interrupts must not fire an interrupt if the level is not
  94         * _currently_ active, even if it was active while the interrupt was
  95         * masked.
  96         */
  97        if (irqd_get_trigger_type(irqd) & IRQ_TYPE_LEVEL_MASK)
  98                exynos_irq_ack(irqd);
  99
 100        raw_spin_lock_irqsave(&bank->slock, flags);
 101
 102        mask = readl(bank->eint_base + reg_mask);
 103        mask &= ~(1 << irqd->hwirq);
 104        writel(mask, bank->eint_base + reg_mask);
 105
 106        raw_spin_unlock_irqrestore(&bank->slock, flags);
 107}
 108
 109static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
 110{
 111        struct irq_chip *chip = irq_data_get_irq_chip(irqd);
 112        struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
 113        struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
 114        unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq;
 115        unsigned int con, trig_type;
 116        unsigned long reg_con = our_chip->eint_con + bank->eint_offset;
 117
 118        switch (type) {
 119        case IRQ_TYPE_EDGE_RISING:
 120                trig_type = EXYNOS_EINT_EDGE_RISING;
 121                break;
 122        case IRQ_TYPE_EDGE_FALLING:
 123                trig_type = EXYNOS_EINT_EDGE_FALLING;
 124                break;
 125        case IRQ_TYPE_EDGE_BOTH:
 126                trig_type = EXYNOS_EINT_EDGE_BOTH;
 127                break;
 128        case IRQ_TYPE_LEVEL_HIGH:
 129                trig_type = EXYNOS_EINT_LEVEL_HIGH;
 130                break;
 131        case IRQ_TYPE_LEVEL_LOW:
 132                trig_type = EXYNOS_EINT_LEVEL_LOW;
 133                break;
 134        default:
 135                pr_err("unsupported external interrupt type\n");
 136                return -EINVAL;
 137        }
 138
 139        if (type & IRQ_TYPE_EDGE_BOTH)
 140                irq_set_handler_locked(irqd, handle_edge_irq);
 141        else
 142                irq_set_handler_locked(irqd, handle_level_irq);
 143
 144        con = readl(bank->eint_base + reg_con);
 145        con &= ~(EXYNOS_EINT_CON_MASK << shift);
 146        con |= trig_type << shift;
 147        writel(con, bank->eint_base + reg_con);
 148
 149        return 0;
 150}
 151
 152static int exynos_irq_request_resources(struct irq_data *irqd)
 153{
 154        struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
 155        const struct samsung_pin_bank_type *bank_type = bank->type;
 156        unsigned long reg_con, flags;
 157        unsigned int shift, mask, con;
 158        int ret;
 159
 160        ret = gpiochip_lock_as_irq(&bank->gpio_chip, irqd->hwirq);
 161        if (ret) {
 162                dev_err(bank->gpio_chip.parent,
 163                        "unable to lock pin %s-%lu IRQ\n",
 164                        bank->name, irqd->hwirq);
 165                return ret;
 166        }
 167
 168        reg_con = bank->pctl_offset + bank_type->reg_offset[PINCFG_TYPE_FUNC];
 169        shift = irqd->hwirq * bank_type->fld_width[PINCFG_TYPE_FUNC];
 170        mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
 171
 172        raw_spin_lock_irqsave(&bank->slock, flags);
 173
 174        con = readl(bank->pctl_base + reg_con);
 175        con &= ~(mask << shift);
 176        con |= EXYNOS_PIN_FUNC_EINT << shift;
 177        writel(con, bank->pctl_base + reg_con);
 178
 179        raw_spin_unlock_irqrestore(&bank->slock, flags);
 180
 181        return 0;
 182}
 183
 184static void exynos_irq_release_resources(struct irq_data *irqd)
 185{
 186        struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
 187        const struct samsung_pin_bank_type *bank_type = bank->type;
 188        unsigned long reg_con, flags;
 189        unsigned int shift, mask, con;
 190
 191        reg_con = bank->pctl_offset + bank_type->reg_offset[PINCFG_TYPE_FUNC];
 192        shift = irqd->hwirq * bank_type->fld_width[PINCFG_TYPE_FUNC];
 193        mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
 194
 195        raw_spin_lock_irqsave(&bank->slock, flags);
 196
 197        con = readl(bank->pctl_base + reg_con);
 198        con &= ~(mask << shift);
 199        con |= EXYNOS_PIN_FUNC_INPUT << shift;
 200        writel(con, bank->pctl_base + reg_con);
 201
 202        raw_spin_unlock_irqrestore(&bank->slock, flags);
 203
 204        gpiochip_unlock_as_irq(&bank->gpio_chip, irqd->hwirq);
 205}
 206
 207/*
 208 * irq_chip for gpio interrupts.
 209 */
 210static const struct exynos_irq_chip exynos_gpio_irq_chip __initconst = {
 211        .chip = {
 212                .name = "exynos_gpio_irq_chip",
 213                .irq_unmask = exynos_irq_unmask,
 214                .irq_mask = exynos_irq_mask,
 215                .irq_ack = exynos_irq_ack,
 216                .irq_set_type = exynos_irq_set_type,
 217                .irq_request_resources = exynos_irq_request_resources,
 218                .irq_release_resources = exynos_irq_release_resources,
 219        },
 220        .eint_con = EXYNOS_GPIO_ECON_OFFSET,
 221        .eint_mask = EXYNOS_GPIO_EMASK_OFFSET,
 222        .eint_pend = EXYNOS_GPIO_EPEND_OFFSET,
 223        /* eint_wake_mask_value not used */
 224};
 225
 226static int exynos_eint_irq_map(struct irq_domain *h, unsigned int virq,
 227                                        irq_hw_number_t hw)
 228{
 229        struct samsung_pin_bank *b = h->host_data;
 230
 231        irq_set_chip_data(virq, b);
 232        irq_set_chip_and_handler(virq, &b->irq_chip->chip,
 233                                        handle_level_irq);
 234        return 0;
 235}
 236
 237/*
 238 * irq domain callbacks for external gpio and wakeup interrupt controllers.
 239 */
 240static const struct irq_domain_ops exynos_eint_irqd_ops = {
 241        .map    = exynos_eint_irq_map,
 242        .xlate  = irq_domain_xlate_twocell,
 243};
 244
 245static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
 246{
 247        struct samsung_pinctrl_drv_data *d = data;
 248        struct samsung_pin_bank *bank = d->pin_banks;
 249        unsigned int svc, group, pin;
 250        int ret;
 251
 252        svc = readl(bank->eint_base + EXYNOS_SVC_OFFSET);
 253        group = EXYNOS_SVC_GROUP(svc);
 254        pin = svc & EXYNOS_SVC_NUM_MASK;
 255
 256        if (!group)
 257                return IRQ_HANDLED;
 258        bank += (group - 1);
 259
 260        ret = generic_handle_domain_irq(bank->irq_domain, pin);
 261        if (ret)
 262                return IRQ_NONE;
 263
 264        return IRQ_HANDLED;
 265}
 266
 267struct exynos_eint_gpio_save {
 268        u32 eint_con;
 269        u32 eint_fltcon0;
 270        u32 eint_fltcon1;
 271        u32 eint_mask;
 272};
 273
 274/*
 275 * exynos_eint_gpio_init() - setup handling of external gpio interrupts.
 276 * @d: driver data of samsung pinctrl driver.
 277 */
 278__init int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
 279{
 280        struct samsung_pin_bank *bank;
 281        struct device *dev = d->dev;
 282        int ret;
 283        int i;
 284
 285        if (!d->irq) {
 286                dev_err(dev, "irq number not available\n");
 287                return -EINVAL;
 288        }
 289
 290        ret = devm_request_irq(dev, d->irq, exynos_eint_gpio_irq,
 291                                        0, dev_name(dev), d);
 292        if (ret) {
 293                dev_err(dev, "irq request failed\n");
 294                return -ENXIO;
 295        }
 296
 297        bank = d->pin_banks;
 298        for (i = 0; i < d->nr_banks; ++i, ++bank) {
 299                if (bank->eint_type != EINT_TYPE_GPIO)
 300                        continue;
 301
 302                bank->irq_chip = devm_kmemdup(dev, &exynos_gpio_irq_chip,
 303                                           sizeof(*bank->irq_chip), GFP_KERNEL);
 304                if (!bank->irq_chip) {
 305                        ret = -ENOMEM;
 306                        goto err_domains;
 307                }
 308                bank->irq_chip->chip.name = bank->name;
 309
 310                bank->irq_domain = irq_domain_add_linear(bank->of_node,
 311                                bank->nr_pins, &exynos_eint_irqd_ops, bank);
 312                if (!bank->irq_domain) {
 313                        dev_err(dev, "gpio irq domain add failed\n");
 314                        ret = -ENXIO;
 315                        goto err_domains;
 316                }
 317
 318                bank->soc_priv = devm_kzalloc(d->dev,
 319                        sizeof(struct exynos_eint_gpio_save), GFP_KERNEL);
 320                if (!bank->soc_priv) {
 321                        irq_domain_remove(bank->irq_domain);
 322                        ret = -ENOMEM;
 323                        goto err_domains;
 324                }
 325
 326        }
 327
 328        return 0;
 329
 330err_domains:
 331        for (--i, --bank; i >= 0; --i, --bank) {
 332                if (bank->eint_type != EINT_TYPE_GPIO)
 333                        continue;
 334                irq_domain_remove(bank->irq_domain);
 335        }
 336
 337        return ret;
 338}
 339
 340static int exynos_wkup_irq_set_wake(struct irq_data *irqd, unsigned int on)
 341{
 342        struct irq_chip *chip = irq_data_get_irq_chip(irqd);
 343        struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
 344        struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
 345        unsigned long bit = 1UL << (2 * bank->eint_offset + irqd->hwirq);
 346
 347        pr_info("wake %s for irq %d\n", on ? "enabled" : "disabled", irqd->irq);
 348
 349        if (!on)
 350                *our_chip->eint_wake_mask_value |= bit;
 351        else
 352                *our_chip->eint_wake_mask_value &= ~bit;
 353
 354        return 0;
 355}
 356
 357static void
 358exynos_pinctrl_set_eint_wakeup_mask(struct samsung_pinctrl_drv_data *drvdata,
 359                                    struct exynos_irq_chip *irq_chip)
 360{
 361        struct regmap *pmu_regs;
 362
 363        if (!drvdata->retention_ctrl || !drvdata->retention_ctrl->priv) {
 364                dev_warn(drvdata->dev,
 365                         "No retention data configured bank with external wakeup interrupt. Wake-up mask will not be set.\n");
 366                return;
 367        }
 368
 369        pmu_regs = drvdata->retention_ctrl->priv;
 370        dev_info(drvdata->dev,
 371                 "Setting external wakeup interrupt mask: 0x%x\n",
 372                 *irq_chip->eint_wake_mask_value);
 373
 374        regmap_write(pmu_regs, irq_chip->eint_wake_mask_reg,
 375                     *irq_chip->eint_wake_mask_value);
 376}
 377
 378static void
 379s5pv210_pinctrl_set_eint_wakeup_mask(struct samsung_pinctrl_drv_data *drvdata,
 380                                    struct exynos_irq_chip *irq_chip)
 381
 382{
 383        void __iomem *clk_base;
 384
 385        if (!drvdata->retention_ctrl || !drvdata->retention_ctrl->priv) {
 386                dev_warn(drvdata->dev,
 387                         "No retention data configured bank with external wakeup interrupt. Wake-up mask will not be set.\n");
 388                return;
 389        }
 390
 391
 392        clk_base = (void __iomem *) drvdata->retention_ctrl->priv;
 393
 394        __raw_writel(*irq_chip->eint_wake_mask_value,
 395                     clk_base + irq_chip->eint_wake_mask_reg);
 396}
 397
 398static u32 eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED;
 399/*
 400 * irq_chip for wakeup interrupts
 401 */
 402static const struct exynos_irq_chip s5pv210_wkup_irq_chip __initconst = {
 403        .chip = {
 404                .name = "s5pv210_wkup_irq_chip",
 405                .irq_unmask = exynos_irq_unmask,
 406                .irq_mask = exynos_irq_mask,
 407                .irq_ack = exynos_irq_ack,
 408                .irq_set_type = exynos_irq_set_type,
 409                .irq_set_wake = exynos_wkup_irq_set_wake,
 410                .irq_request_resources = exynos_irq_request_resources,
 411                .irq_release_resources = exynos_irq_release_resources,
 412        },
 413        .eint_con = EXYNOS_WKUP_ECON_OFFSET,
 414        .eint_mask = EXYNOS_WKUP_EMASK_OFFSET,
 415        .eint_pend = EXYNOS_WKUP_EPEND_OFFSET,
 416        .eint_wake_mask_value = &eint_wake_mask_value,
 417        /* Only differences with exynos4210_wkup_irq_chip: */
 418        .eint_wake_mask_reg = S5PV210_EINT_WAKEUP_MASK,
 419        .set_eint_wakeup_mask = s5pv210_pinctrl_set_eint_wakeup_mask,
 420};
 421
 422static const struct exynos_irq_chip exynos4210_wkup_irq_chip __initconst = {
 423        .chip = {
 424                .name = "exynos4210_wkup_irq_chip",
 425                .irq_unmask = exynos_irq_unmask,
 426                .irq_mask = exynos_irq_mask,
 427                .irq_ack = exynos_irq_ack,
 428                .irq_set_type = exynos_irq_set_type,
 429                .irq_set_wake = exynos_wkup_irq_set_wake,
 430                .irq_request_resources = exynos_irq_request_resources,
 431                .irq_release_resources = exynos_irq_release_resources,
 432        },
 433        .eint_con = EXYNOS_WKUP_ECON_OFFSET,
 434        .eint_mask = EXYNOS_WKUP_EMASK_OFFSET,
 435        .eint_pend = EXYNOS_WKUP_EPEND_OFFSET,
 436        .eint_wake_mask_value = &eint_wake_mask_value,
 437        .eint_wake_mask_reg = EXYNOS_EINT_WAKEUP_MASK,
 438        .set_eint_wakeup_mask = exynos_pinctrl_set_eint_wakeup_mask,
 439};
 440
 441static const struct exynos_irq_chip exynos7_wkup_irq_chip __initconst = {
 442        .chip = {
 443                .name = "exynos7_wkup_irq_chip",
 444                .irq_unmask = exynos_irq_unmask,
 445                .irq_mask = exynos_irq_mask,
 446                .irq_ack = exynos_irq_ack,
 447                .irq_set_type = exynos_irq_set_type,
 448                .irq_set_wake = exynos_wkup_irq_set_wake,
 449                .irq_request_resources = exynos_irq_request_resources,
 450                .irq_release_resources = exynos_irq_release_resources,
 451        },
 452        .eint_con = EXYNOS7_WKUP_ECON_OFFSET,
 453        .eint_mask = EXYNOS7_WKUP_EMASK_OFFSET,
 454        .eint_pend = EXYNOS7_WKUP_EPEND_OFFSET,
 455        .eint_wake_mask_value = &eint_wake_mask_value,
 456        .eint_wake_mask_reg = EXYNOS5433_EINT_WAKEUP_MASK,
 457        .set_eint_wakeup_mask = exynos_pinctrl_set_eint_wakeup_mask,
 458};
 459
 460/* list of external wakeup controllers supported */
 461static const struct of_device_id exynos_wkup_irq_ids[] = {
 462        { .compatible = "samsung,s5pv210-wakeup-eint",
 463                        .data = &s5pv210_wkup_irq_chip },
 464        { .compatible = "samsung,exynos4210-wakeup-eint",
 465                        .data = &exynos4210_wkup_irq_chip },
 466        { .compatible = "samsung,exynos7-wakeup-eint",
 467                        .data = &exynos7_wkup_irq_chip },
 468        { }
 469};
 470
 471/* interrupt handler for wakeup interrupts 0..15 */
 472static void exynos_irq_eint0_15(struct irq_desc *desc)
 473{
 474        struct exynos_weint_data *eintd = irq_desc_get_handler_data(desc);
 475        struct samsung_pin_bank *bank = eintd->bank;
 476        struct irq_chip *chip = irq_desc_get_chip(desc);
 477
 478        chained_irq_enter(chip, desc);
 479
 480        generic_handle_domain_irq(bank->irq_domain, eintd->irq);
 481
 482        chained_irq_exit(chip, desc);
 483}
 484
 485static inline void exynos_irq_demux_eint(unsigned int pend,
 486                                                struct irq_domain *domain)
 487{
 488        unsigned int irq;
 489
 490        while (pend) {
 491                irq = fls(pend) - 1;
 492                generic_handle_domain_irq(domain, irq);
 493                pend &= ~(1 << irq);
 494        }
 495}
 496
 497/* interrupt handler for wakeup interrupt 16 */
 498static void exynos_irq_demux_eint16_31(struct irq_desc *desc)
 499{
 500        struct irq_chip *chip = irq_desc_get_chip(desc);
 501        struct exynos_muxed_weint_data *eintd = irq_desc_get_handler_data(desc);
 502        unsigned int pend;
 503        unsigned int mask;
 504        int i;
 505
 506        chained_irq_enter(chip, desc);
 507
 508        for (i = 0; i < eintd->nr_banks; ++i) {
 509                struct samsung_pin_bank *b = eintd->banks[i];
 510                pend = readl(b->eint_base + b->irq_chip->eint_pend
 511                                + b->eint_offset);
 512                mask = readl(b->eint_base + b->irq_chip->eint_mask
 513                                + b->eint_offset);
 514                exynos_irq_demux_eint(pend & ~mask, b->irq_domain);
 515        }
 516
 517        chained_irq_exit(chip, desc);
 518}
 519
 520/*
 521 * exynos_eint_wkup_init() - setup handling of external wakeup interrupts.
 522 * @d: driver data of samsung pinctrl driver.
 523 */
 524__init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
 525{
 526        struct device *dev = d->dev;
 527        struct device_node *wkup_np = NULL;
 528        struct device_node *np;
 529        struct samsung_pin_bank *bank;
 530        struct exynos_weint_data *weint_data;
 531        struct exynos_muxed_weint_data *muxed_data;
 532        const struct exynos_irq_chip *irq_chip;
 533        unsigned int muxed_banks = 0;
 534        unsigned int i;
 535        int idx, irq;
 536
 537        for_each_child_of_node(dev->of_node, np) {
 538                const struct of_device_id *match;
 539
 540                match = of_match_node(exynos_wkup_irq_ids, np);
 541                if (match) {
 542                        irq_chip = match->data;
 543                        wkup_np = np;
 544                        break;
 545                }
 546        }
 547        if (!wkup_np)
 548                return -ENODEV;
 549
 550        bank = d->pin_banks;
 551        for (i = 0; i < d->nr_banks; ++i, ++bank) {
 552                if (bank->eint_type != EINT_TYPE_WKUP)
 553                        continue;
 554
 555                bank->irq_chip = devm_kmemdup(dev, irq_chip, sizeof(*irq_chip),
 556                                              GFP_KERNEL);
 557                if (!bank->irq_chip) {
 558                        of_node_put(wkup_np);
 559                        return -ENOMEM;
 560                }
 561                bank->irq_chip->chip.name = bank->name;
 562
 563                bank->irq_domain = irq_domain_add_linear(bank->of_node,
 564                                bank->nr_pins, &exynos_eint_irqd_ops, bank);
 565                if (!bank->irq_domain) {
 566                        dev_err(dev, "wkup irq domain add failed\n");
 567                        of_node_put(wkup_np);
 568                        return -ENXIO;
 569                }
 570
 571                if (!of_find_property(bank->of_node, "interrupts", NULL)) {
 572                        bank->eint_type = EINT_TYPE_WKUP_MUX;
 573                        ++muxed_banks;
 574                        continue;
 575                }
 576
 577                weint_data = devm_kcalloc(dev,
 578                                          bank->nr_pins, sizeof(*weint_data),
 579                                          GFP_KERNEL);
 580                if (!weint_data) {
 581                        of_node_put(wkup_np);
 582                        return -ENOMEM;
 583                }
 584
 585                for (idx = 0; idx < bank->nr_pins; ++idx) {
 586                        irq = irq_of_parse_and_map(bank->of_node, idx);
 587                        if (!irq) {
 588                                dev_err(dev, "irq number for eint-%s-%d not found\n",
 589                                                        bank->name, idx);
 590                                continue;
 591                        }
 592                        weint_data[idx].irq = idx;
 593                        weint_data[idx].bank = bank;
 594                        irq_set_chained_handler_and_data(irq,
 595                                                         exynos_irq_eint0_15,
 596                                                         &weint_data[idx]);
 597                }
 598        }
 599
 600        if (!muxed_banks) {
 601                of_node_put(wkup_np);
 602                return 0;
 603        }
 604
 605        irq = irq_of_parse_and_map(wkup_np, 0);
 606        of_node_put(wkup_np);
 607        if (!irq) {
 608                dev_err(dev, "irq number for muxed EINTs not found\n");
 609                return 0;
 610        }
 611
 612        muxed_data = devm_kzalloc(dev, sizeof(*muxed_data)
 613                + muxed_banks*sizeof(struct samsung_pin_bank *), GFP_KERNEL);
 614        if (!muxed_data)
 615                return -ENOMEM;
 616
 617        irq_set_chained_handler_and_data(irq, exynos_irq_demux_eint16_31,
 618                                         muxed_data);
 619
 620        bank = d->pin_banks;
 621        idx = 0;
 622        for (i = 0; i < d->nr_banks; ++i, ++bank) {
 623                if (bank->eint_type != EINT_TYPE_WKUP_MUX)
 624                        continue;
 625
 626                muxed_data->banks[idx++] = bank;
 627        }
 628        muxed_data->nr_banks = muxed_banks;
 629
 630        return 0;
 631}
 632
 633static void exynos_pinctrl_suspend_bank(
 634                                struct samsung_pinctrl_drv_data *drvdata,
 635                                struct samsung_pin_bank *bank)
 636{
 637        struct exynos_eint_gpio_save *save = bank->soc_priv;
 638        void __iomem *regs = bank->eint_base;
 639
 640        save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
 641                                                + bank->eint_offset);
 642        save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
 643                                                + 2 * bank->eint_offset);
 644        save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
 645                                                + 2 * bank->eint_offset + 4);
 646        save->eint_mask = readl(regs + bank->irq_chip->eint_mask
 647                                                + bank->eint_offset);
 648
 649        pr_debug("%s: save     con %#010x\n", bank->name, save->eint_con);
 650        pr_debug("%s: save fltcon0 %#010x\n", bank->name, save->eint_fltcon0);
 651        pr_debug("%s: save fltcon1 %#010x\n", bank->name, save->eint_fltcon1);
 652        pr_debug("%s: save    mask %#010x\n", bank->name, save->eint_mask);
 653}
 654
 655void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
 656{
 657        struct samsung_pin_bank *bank = drvdata->pin_banks;
 658        struct exynos_irq_chip *irq_chip = NULL;
 659        int i;
 660
 661        for (i = 0; i < drvdata->nr_banks; ++i, ++bank) {
 662                if (bank->eint_type == EINT_TYPE_GPIO)
 663                        exynos_pinctrl_suspend_bank(drvdata, bank);
 664                else if (bank->eint_type == EINT_TYPE_WKUP) {
 665                        if (!irq_chip) {
 666                                irq_chip = bank->irq_chip;
 667                                irq_chip->set_eint_wakeup_mask(drvdata,
 668                                                               irq_chip);
 669                        }
 670                }
 671        }
 672}
 673
 674static void exynos_pinctrl_resume_bank(
 675                                struct samsung_pinctrl_drv_data *drvdata,
 676                                struct samsung_pin_bank *bank)
 677{
 678        struct exynos_eint_gpio_save *save = bank->soc_priv;
 679        void __iomem *regs = bank->eint_base;
 680
 681        pr_debug("%s:     con %#010x => %#010x\n", bank->name,
 682                        readl(regs + EXYNOS_GPIO_ECON_OFFSET
 683                        + bank->eint_offset), save->eint_con);
 684        pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name,
 685                        readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
 686                        + 2 * bank->eint_offset), save->eint_fltcon0);
 687        pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
 688                        readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
 689                        + 2 * bank->eint_offset + 4), save->eint_fltcon1);
 690        pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
 691                        readl(regs + bank->irq_chip->eint_mask
 692                        + bank->eint_offset), save->eint_mask);
 693
 694        writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
 695                                                + bank->eint_offset);
 696        writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET
 697                                                + 2 * bank->eint_offset);
 698        writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
 699                                                + 2 * bank->eint_offset + 4);
 700        writel(save->eint_mask, regs + bank->irq_chip->eint_mask
 701                                                + bank->eint_offset);
 702}
 703
 704void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
 705{
 706        struct samsung_pin_bank *bank = drvdata->pin_banks;
 707        int i;
 708
 709        for (i = 0; i < drvdata->nr_banks; ++i, ++bank)
 710                if (bank->eint_type == EINT_TYPE_GPIO)
 711                        exynos_pinctrl_resume_bank(drvdata, bank);
 712}
 713
 714static void exynos_retention_enable(struct samsung_pinctrl_drv_data *drvdata)
 715{
 716        if (drvdata->retention_ctrl->refcnt)
 717                atomic_inc(drvdata->retention_ctrl->refcnt);
 718}
 719
 720static void exynos_retention_disable(struct samsung_pinctrl_drv_data *drvdata)
 721{
 722        struct samsung_retention_ctrl *ctrl = drvdata->retention_ctrl;
 723        struct regmap *pmu_regs = ctrl->priv;
 724        int i;
 725
 726        if (ctrl->refcnt && !atomic_dec_and_test(ctrl->refcnt))
 727                return;
 728
 729        for (i = 0; i < ctrl->nr_regs; i++)
 730                regmap_write(pmu_regs, ctrl->regs[i], ctrl->value);
 731}
 732
 733struct samsung_retention_ctrl *
 734exynos_retention_init(struct samsung_pinctrl_drv_data *drvdata,
 735                      const struct samsung_retention_data *data)
 736{
 737        struct samsung_retention_ctrl *ctrl;
 738        struct regmap *pmu_regs;
 739        int i;
 740
 741        ctrl = devm_kzalloc(drvdata->dev, sizeof(*ctrl), GFP_KERNEL);
 742        if (!ctrl)
 743                return ERR_PTR(-ENOMEM);
 744
 745        pmu_regs = exynos_get_pmu_regmap();
 746        if (IS_ERR(pmu_regs))
 747                return ERR_CAST(pmu_regs);
 748
 749        ctrl->priv = pmu_regs;
 750        ctrl->regs = data->regs;
 751        ctrl->nr_regs = data->nr_regs;
 752        ctrl->value = data->value;
 753        ctrl->refcnt = data->refcnt;
 754        ctrl->enable = exynos_retention_enable;
 755        ctrl->disable = exynos_retention_disable;
 756
 757        /* Ensure that retention is disabled on driver init */
 758        for (i = 0; i < ctrl->nr_regs; i++)
 759                regmap_write(pmu_regs, ctrl->regs[i], ctrl->value);
 760
 761        return ctrl;
 762}
 763