.. | .. |
---|
| 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 | |
---|