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