.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * Intel Whiskey Cove PMIC GPIO Driver |
---|
3 | 4 | * |
---|
4 | 5 | * This driver is written based on gpio-crystalcove.c |
---|
5 | 6 | * |
---|
6 | 7 | * Copyright (C) 2016 Intel Corporation. All rights reserved. |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or |
---|
9 | | - * modify it under the terms of the GNU General Public License version |
---|
10 | | - * 2 as published by the Free Software Foundation. |
---|
11 | | - * |
---|
12 | | - * This program is distributed in the hope that it will be useful, |
---|
13 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
15 | | - * GNU General Public License for more details. |
---|
16 | 8 | */ |
---|
17 | 9 | |
---|
18 | 10 | #include <linux/bitops.h> |
---|
19 | | -#include <linux/module.h> |
---|
20 | | -#include <linux/interrupt.h> |
---|
21 | 11 | #include <linux/gpio/driver.h> |
---|
| 12 | +#include <linux/interrupt.h> |
---|
22 | 13 | #include <linux/mfd/intel_soc_pmic.h> |
---|
| 14 | +#include <linux/module.h> |
---|
23 | 15 | #include <linux/platform_device.h> |
---|
24 | 16 | #include <linux/regmap.h> |
---|
25 | 17 | #include <linux/seq_file.h> |
---|
26 | 18 | |
---|
27 | 19 | /* |
---|
28 | 20 | * Whiskey Cove PMIC has 13 physical GPIO pins divided into 3 banks: |
---|
29 | | - * Bank 0: Pin 0 - 6 |
---|
30 | | - * Bank 1: Pin 7 - 10 |
---|
31 | | - * Bank 2: Pin 11 -12 |
---|
| 21 | + * Bank 0: Pin 0 - 6 |
---|
| 22 | + * Bank 1: Pin 7 - 10 |
---|
| 23 | + * Bank 2: Pin 11 - 12 |
---|
32 | 24 | * Each pin has one output control register and one input control register. |
---|
33 | 25 | */ |
---|
34 | 26 | #define BANK0_NR_PINS 7 |
---|
.. | .. |
---|
75 | 67 | #define CTLO_RVAL_50KDOWN (2 << 1) |
---|
76 | 68 | #define CTLO_RVAL_50KUP (3 << 1) |
---|
77 | 69 | |
---|
78 | | -#define CTLO_INPUT_SET (CTLO_DRV_CMOS | CTLO_DRV_REN | CTLO_RVAL_2KUP) |
---|
79 | | -#define CTLO_OUTPUT_SET (CTLO_DIR_OUT | CTLO_INPUT_SET) |
---|
| 70 | +#define CTLO_INPUT_SET (CTLO_DRV_CMOS | CTLO_DRV_REN | CTLO_RVAL_2KUP) |
---|
| 71 | +#define CTLO_OUTPUT_SET (CTLO_DIR_OUT | CTLO_INPUT_SET) |
---|
80 | 72 | |
---|
81 | 73 | enum ctrl_register { |
---|
82 | 74 | CTRL_IN, |
---|
.. | .. |
---|
105 | 97 | bool set_irq_mask; |
---|
106 | 98 | }; |
---|
107 | 99 | |
---|
108 | | -static inline unsigned int to_reg(int gpio, enum ctrl_register reg_type) |
---|
| 100 | +static inline int to_reg(int gpio, enum ctrl_register reg_type) |
---|
109 | 101 | { |
---|
110 | 102 | unsigned int reg; |
---|
111 | 103 | |
---|
.. | .. |
---|
178 | 170 | int ret, reg = to_reg(gpio, CTRL_OUT); |
---|
179 | 171 | |
---|
180 | 172 | if (reg < 0) |
---|
181 | | - return 0; |
---|
| 173 | + return GPIO_LINE_DIRECTION_OUT; |
---|
182 | 174 | |
---|
183 | 175 | ret = regmap_read(wg->regmap, reg, &val); |
---|
184 | 176 | if (ret) |
---|
185 | 177 | return ret; |
---|
186 | 178 | |
---|
187 | | - return !(val & CTLO_DIR_OUT); |
---|
| 179 | + if (val & CTLO_DIR_OUT) |
---|
| 180 | + return GPIO_LINE_DIRECTION_OUT; |
---|
| 181 | + |
---|
| 182 | + return GPIO_LINE_DIRECTION_IN; |
---|
188 | 183 | } |
---|
189 | 184 | |
---|
190 | 185 | static int wcove_gpio_get(struct gpio_chip *chip, unsigned int gpio) |
---|
.. | .. |
---|
203 | 198 | return val & 0x1; |
---|
204 | 199 | } |
---|
205 | 200 | |
---|
206 | | -static void wcove_gpio_set(struct gpio_chip *chip, |
---|
207 | | - unsigned int gpio, int value) |
---|
| 201 | +static void wcove_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value) |
---|
208 | 202 | { |
---|
209 | 203 | struct wcove_gpio *wg = gpiochip_get_data(chip); |
---|
210 | 204 | int reg = to_reg(gpio, CTRL_OUT); |
---|
.. | .. |
---|
406 | 400 | struct wcove_gpio *wg; |
---|
407 | 401 | int virq, ret, irq; |
---|
408 | 402 | struct device *dev; |
---|
| 403 | + struct gpio_irq_chip *girq; |
---|
409 | 404 | |
---|
410 | 405 | /* |
---|
411 | 406 | * This gpio platform device is created by a mfd device (see |
---|
.. | .. |
---|
448 | 443 | wg->dev = dev; |
---|
449 | 444 | wg->regmap = pmic->regmap; |
---|
450 | 445 | |
---|
451 | | - ret = devm_gpiochip_add_data(dev, &wg->chip, wg); |
---|
452 | | - if (ret) { |
---|
453 | | - dev_err(dev, "Failed to add gpiochip: %d\n", ret); |
---|
454 | | - return ret; |
---|
455 | | - } |
---|
456 | | - |
---|
457 | | - ret = gpiochip_irqchip_add_nested(&wg->chip, &wcove_irqchip, 0, |
---|
458 | | - handle_simple_irq, IRQ_TYPE_NONE); |
---|
459 | | - if (ret) { |
---|
460 | | - dev_err(dev, "Failed to add irqchip: %d\n", ret); |
---|
461 | | - return ret; |
---|
462 | | - } |
---|
463 | | - |
---|
464 | 446 | virq = regmap_irq_get_virq(wg->regmap_irq_chip, irq); |
---|
465 | 447 | if (virq < 0) { |
---|
466 | 448 | dev_err(dev, "Failed to get virq by irq %d\n", irq); |
---|
467 | 449 | return virq; |
---|
468 | 450 | } |
---|
469 | 451 | |
---|
470 | | - ret = devm_request_threaded_irq(dev, virq, NULL, |
---|
471 | | - wcove_gpio_irq_handler, IRQF_ONESHOT, pdev->name, wg); |
---|
| 452 | + girq = &wg->chip.irq; |
---|
| 453 | + girq->chip = &wcove_irqchip; |
---|
| 454 | + /* This will let us handle the parent IRQ in the driver */ |
---|
| 455 | + girq->parent_handler = NULL; |
---|
| 456 | + girq->num_parents = 0; |
---|
| 457 | + girq->parents = NULL; |
---|
| 458 | + girq->default_type = IRQ_TYPE_NONE; |
---|
| 459 | + girq->handler = handle_simple_irq; |
---|
| 460 | + girq->threaded = true; |
---|
| 461 | + |
---|
| 462 | + ret = devm_request_threaded_irq(dev, virq, NULL, wcove_gpio_irq_handler, |
---|
| 463 | + IRQF_ONESHOT, pdev->name, wg); |
---|
472 | 464 | if (ret) { |
---|
473 | 465 | dev_err(dev, "Failed to request irq %d\n", virq); |
---|
474 | 466 | return ret; |
---|
475 | 467 | } |
---|
476 | 468 | |
---|
477 | | - gpiochip_set_nested_irqchip(&wg->chip, &wcove_irqchip, virq); |
---|
| 469 | + ret = devm_gpiochip_add_data(dev, &wg->chip, wg); |
---|
| 470 | + if (ret) { |
---|
| 471 | + dev_err(dev, "Failed to add gpiochip: %d\n", ret); |
---|
| 472 | + return ret; |
---|
| 473 | + } |
---|
478 | 474 | |
---|
479 | 475 | /* Enable GPIO0 interrupts */ |
---|
480 | 476 | ret = regmap_update_bits(wg->regmap, IRQ_MASK_BASE, GPIO_IRQ0_MASK, |
---|