| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * arch/arm/mach-tegra/gpio.c |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (c) 2010 Google, Inc |
|---|
| 6 | + * Copyright (c) 2011-2016, NVIDIA CORPORATION. All rights reserved. |
|---|
| 5 | 7 | * |
|---|
| 6 | 8 | * Author: |
|---|
| 7 | 9 | * Erik Gilling <konkers@google.com> |
|---|
| 8 | | - * |
|---|
| 9 | | - * This software is licensed under the terms of the GNU General Public |
|---|
| 10 | | - * License version 2, as published by the Free Software Foundation, and |
|---|
| 11 | | - * may be copied, distributed, and modified under those terms. |
|---|
| 12 | | - * |
|---|
| 13 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 14 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 15 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 16 | | - * GNU General Public License for more details. |
|---|
| 17 | | - * |
|---|
| 18 | 10 | */ |
|---|
| 19 | 11 | |
|---|
| 20 | 12 | #include <linux/err.h> |
|---|
| .. | .. |
|---|
| 104 | 96 | static inline void tegra_gpio_writel(struct tegra_gpio_info *tgi, |
|---|
| 105 | 97 | u32 val, u32 reg) |
|---|
| 106 | 98 | { |
|---|
| 107 | | - __raw_writel(val, tgi->regs + reg); |
|---|
| 99 | + writel_relaxed(val, tgi->regs + reg); |
|---|
| 108 | 100 | } |
|---|
| 109 | 101 | |
|---|
| 110 | 102 | static inline u32 tegra_gpio_readl(struct tegra_gpio_info *tgi, u32 reg) |
|---|
| 111 | 103 | { |
|---|
| 112 | | - return __raw_readl(tgi->regs + reg); |
|---|
| 104 | + return readl_relaxed(tgi->regs + reg); |
|---|
| 113 | 105 | } |
|---|
| 114 | 106 | |
|---|
| 115 | 107 | static unsigned int tegra_gpio_compose(unsigned int bank, unsigned int port, |
|---|
| .. | .. |
|---|
| 141 | 133 | |
|---|
| 142 | 134 | static int tegra_gpio_request(struct gpio_chip *chip, unsigned int offset) |
|---|
| 143 | 135 | { |
|---|
| 144 | | - return pinctrl_gpio_request(offset); |
|---|
| 136 | + return pinctrl_gpio_request(chip->base + offset); |
|---|
| 145 | 137 | } |
|---|
| 146 | 138 | |
|---|
| 147 | 139 | static void tegra_gpio_free(struct gpio_chip *chip, unsigned int offset) |
|---|
| 148 | 140 | { |
|---|
| 149 | 141 | struct tegra_gpio_info *tgi = gpiochip_get_data(chip); |
|---|
| 150 | 142 | |
|---|
| 151 | | - pinctrl_gpio_free(offset); |
|---|
| 143 | + pinctrl_gpio_free(chip->base + offset); |
|---|
| 152 | 144 | tegra_gpio_disable(tgi, offset); |
|---|
| 153 | 145 | } |
|---|
| 154 | 146 | |
|---|
| .. | .. |
|---|
| 176 | 168 | unsigned int offset) |
|---|
| 177 | 169 | { |
|---|
| 178 | 170 | struct tegra_gpio_info *tgi = gpiochip_get_data(chip); |
|---|
| 171 | + int ret; |
|---|
| 179 | 172 | |
|---|
| 180 | 173 | tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 0); |
|---|
| 181 | 174 | tegra_gpio_enable(tgi, offset); |
|---|
| 182 | | - return 0; |
|---|
| 175 | + |
|---|
| 176 | + ret = pinctrl_gpio_direction_input(chip->base + offset); |
|---|
| 177 | + if (ret < 0) |
|---|
| 178 | + dev_err(tgi->dev, |
|---|
| 179 | + "Failed to set pinctrl input direction of GPIO %d: %d", |
|---|
| 180 | + chip->base + offset, ret); |
|---|
| 181 | + |
|---|
| 182 | + return ret; |
|---|
| 183 | 183 | } |
|---|
| 184 | 184 | |
|---|
| 185 | 185 | static int tegra_gpio_direction_output(struct gpio_chip *chip, |
|---|
| .. | .. |
|---|
| 187 | 187 | int value) |
|---|
| 188 | 188 | { |
|---|
| 189 | 189 | struct tegra_gpio_info *tgi = gpiochip_get_data(chip); |
|---|
| 190 | + int ret; |
|---|
| 190 | 191 | |
|---|
| 191 | 192 | tegra_gpio_set(chip, offset, value); |
|---|
| 192 | 193 | tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 1); |
|---|
| 193 | 194 | tegra_gpio_enable(tgi, offset); |
|---|
| 194 | | - return 0; |
|---|
| 195 | + |
|---|
| 196 | + ret = pinctrl_gpio_direction_output(chip->base + offset); |
|---|
| 197 | + if (ret < 0) |
|---|
| 198 | + dev_err(tgi->dev, |
|---|
| 199 | + "Failed to set pinctrl output direction of GPIO %d: %d", |
|---|
| 200 | + chip->base + offset, ret); |
|---|
| 201 | + |
|---|
| 202 | + return ret; |
|---|
| 195 | 203 | } |
|---|
| 196 | 204 | |
|---|
| 197 | 205 | static int tegra_gpio_get_direction(struct gpio_chip *chip, |
|---|
| .. | .. |
|---|
| 207 | 215 | |
|---|
| 208 | 216 | oe = tegra_gpio_readl(tgi, GPIO_OE(tgi, offset)); |
|---|
| 209 | 217 | |
|---|
| 210 | | - return !(oe & pin_mask); |
|---|
| 218 | + if (oe & pin_mask) |
|---|
| 219 | + return GPIO_LINE_DIRECTION_OUT; |
|---|
| 220 | + |
|---|
| 221 | + return GPIO_LINE_DIRECTION_IN; |
|---|
| 211 | 222 | } |
|---|
| 212 | 223 | |
|---|
| 213 | 224 | static int tegra_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset, |
|---|
| .. | .. |
|---|
| 405 | 416 | #ifdef CONFIG_PM_SLEEP |
|---|
| 406 | 417 | static int tegra_gpio_resume(struct device *dev) |
|---|
| 407 | 418 | { |
|---|
| 408 | | - struct platform_device *pdev = to_platform_device(dev); |
|---|
| 409 | | - struct tegra_gpio_info *tgi = platform_get_drvdata(pdev); |
|---|
| 410 | | - unsigned long flags; |
|---|
| 419 | + struct tegra_gpio_info *tgi = dev_get_drvdata(dev); |
|---|
| 411 | 420 | unsigned int b, p; |
|---|
| 412 | | - |
|---|
| 413 | | - local_irq_save(flags); |
|---|
| 414 | 421 | |
|---|
| 415 | 422 | for (b = 0; b < tgi->bank_count; b++) { |
|---|
| 416 | 423 | struct tegra_gpio_bank *bank = &tgi->bank_info[b]; |
|---|
| .. | .. |
|---|
| 439 | 446 | } |
|---|
| 440 | 447 | } |
|---|
| 441 | 448 | |
|---|
| 442 | | - local_irq_restore(flags); |
|---|
| 443 | 449 | return 0; |
|---|
| 444 | 450 | } |
|---|
| 445 | 451 | |
|---|
| 446 | 452 | static int tegra_gpio_suspend(struct device *dev) |
|---|
| 447 | 453 | { |
|---|
| 448 | | - struct platform_device *pdev = to_platform_device(dev); |
|---|
| 449 | | - struct tegra_gpio_info *tgi = platform_get_drvdata(pdev); |
|---|
| 450 | | - unsigned long flags; |
|---|
| 454 | + struct tegra_gpio_info *tgi = dev_get_drvdata(dev); |
|---|
| 451 | 455 | unsigned int b, p; |
|---|
| 452 | 456 | |
|---|
| 453 | | - local_irq_save(flags); |
|---|
| 454 | 457 | for (b = 0; b < tgi->bank_count; b++) { |
|---|
| 455 | 458 | struct tegra_gpio_bank *bank = &tgi->bank_info[b]; |
|---|
| 456 | 459 | |
|---|
| .. | .. |
|---|
| 480 | 483 | GPIO_INT_ENB(tgi, gpio)); |
|---|
| 481 | 484 | } |
|---|
| 482 | 485 | } |
|---|
| 483 | | - local_irq_restore(flags); |
|---|
| 486 | + |
|---|
| 484 | 487 | return 0; |
|---|
| 485 | 488 | } |
|---|
| 486 | 489 | |
|---|
| .. | .. |
|---|
| 489 | 492 | struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d); |
|---|
| 490 | 493 | unsigned int gpio = d->hwirq; |
|---|
| 491 | 494 | u32 port, bit, mask; |
|---|
| 495 | + int err; |
|---|
| 496 | + |
|---|
| 497 | + err = irq_set_irq_wake(bank->irq, enable); |
|---|
| 498 | + if (err) |
|---|
| 499 | + return err; |
|---|
| 492 | 500 | |
|---|
| 493 | 501 | port = GPIO_PORT(gpio); |
|---|
| 494 | 502 | bit = GPIO_BIT(gpio); |
|---|
| .. | .. |
|---|
| 499 | 507 | else |
|---|
| 500 | 508 | bank->wake_enb[port] &= ~mask; |
|---|
| 501 | 509 | |
|---|
| 502 | | - return irq_set_irq_wake(bank->irq, enable); |
|---|
| 510 | + return 0; |
|---|
| 503 | 511 | } |
|---|
| 504 | 512 | #endif |
|---|
| 505 | 513 | |
|---|
| .. | .. |
|---|
| 536 | 544 | |
|---|
| 537 | 545 | static void tegra_gpio_debuginit(struct tegra_gpio_info *tgi) |
|---|
| 538 | 546 | { |
|---|
| 539 | | - (void) debugfs_create_file("tegra_gpio", 0444, |
|---|
| 540 | | - NULL, tgi, &tegra_dbg_gpio_fops); |
|---|
| 547 | + debugfs_create_file("tegra_gpio", 0444, NULL, tgi, |
|---|
| 548 | + &tegra_dbg_gpio_fops); |
|---|
| 541 | 549 | } |
|---|
| 542 | 550 | |
|---|
| 543 | 551 | #else |
|---|
| .. | .. |
|---|
| 549 | 557 | #endif |
|---|
| 550 | 558 | |
|---|
| 551 | 559 | static const struct dev_pm_ops tegra_gpio_pm_ops = { |
|---|
| 552 | | - SET_SYSTEM_SLEEP_PM_OPS(tegra_gpio_suspend, tegra_gpio_resume) |
|---|
| 560 | + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(tegra_gpio_suspend, tegra_gpio_resume) |
|---|
| 553 | 561 | }; |
|---|
| 554 | 562 | |
|---|
| 555 | 563 | static int tegra_gpio_probe(struct platform_device *pdev) |
|---|
| 556 | 564 | { |
|---|
| 557 | 565 | struct tegra_gpio_info *tgi; |
|---|
| 558 | | - struct resource *res; |
|---|
| 559 | 566 | struct tegra_gpio_bank *bank; |
|---|
| 560 | 567 | unsigned int gpio, i, j; |
|---|
| 561 | 568 | int ret; |
|---|
| .. | .. |
|---|
| 620 | 627 | |
|---|
| 621 | 628 | for (i = 0; i < tgi->bank_count; i++) { |
|---|
| 622 | 629 | ret = platform_get_irq(pdev, i); |
|---|
| 623 | | - if (ret < 0) { |
|---|
| 624 | | - dev_err(&pdev->dev, "Missing IRQ resource: %d\n", ret); |
|---|
| 630 | + if (ret < 0) |
|---|
| 625 | 631 | return ret; |
|---|
| 626 | | - } |
|---|
| 627 | 632 | |
|---|
| 628 | 633 | bank = &tgi->bank_info[i]; |
|---|
| 629 | 634 | bank->bank = i; |
|---|
| .. | .. |
|---|
| 631 | 636 | bank->tgi = tgi; |
|---|
| 632 | 637 | } |
|---|
| 633 | 638 | |
|---|
| 634 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 635 | | - tgi->regs = devm_ioremap_resource(&pdev->dev, res); |
|---|
| 639 | + tgi->regs = devm_platform_ioremap_resource(pdev, 0); |
|---|
| 636 | 640 | if (IS_ERR(tgi->regs)) |
|---|
| 637 | 641 | return PTR_ERR(tgi->regs); |
|---|
| 638 | 642 | |
|---|