diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-02-22 10:00:46 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-02-22 10:00:46 -0800 |
commit | 882d6edfc45cd2b6e33cf973eab9a1ae1dbad5d1 (patch) | |
tree | 034ebc487adeb29cef2c546b5e0b61d70a3bc339 /drivers/gpio/gpio-wcove.c | |
parent | 0328b5f2ef4af8ba060e64baa928c94037e7308f (diff) | |
parent | a8002a35935aaefcd6a42ad3289f62bab947f2ca (diff) |
Merge tag 'gpio-updates-for-v5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux
Pull gpio updates from Bartosz Golaszewski:
"It's been a relatively calm release cycle and we're actually removing
more code than we're adding.
Summary:
- new driver for the Toshiba Visconti platform
- rework of interrupt handling in gpio-tegra
- updates for GPIO selftests: we're now using the character device to
perform the subsystem checks
- support for a new rcar variant + some code refactoring
- refactoring of gpio-ep93xx
- SPDX License identifier has been updated in the uapi header so that
userspace programs bundling it can become fully REUSE-compliant
- improvements to pwm handling in gpio-mvebu
- support for interrupt handling and power management for gpio-xilinx
as well as some code refactoring
- support for a new chip variant in gpio-pca953x
- removal of drivers: zte xs & intel-mid and removal of leftovers
from intel-msic
- impovements to intel drivers pulled from Andy Shevchenko
- improvements to the gpio-aggregator virtual GPIO driver
- and several minor tweaks and fixes to code and documentation all
over the place"
* tag 'gpio-updates-for-v5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: (71 commits)
gpio: pcf857x: Fix missing first interrupt
gpio: ep93xx: refactor base IRQ number
gpio: ep93xx: refactor ep93xx_gpio_add_bank
gpio: ep93xx: Fix typo s/hierarchial/hierarchical
gpio: ep93xx: drop to_irq binding
gpio: ep93xx: Fix wrong irq numbers in port F
gpio: uapi: use the preferred SPDX license identifier
gpio: gpio-xilinx: Add check if width exceeds 32
gpio: gpio-xilinx: Add support for suspend and resume
gpio: gpio-xilinx: Add interrupt support
gpio: gpio-xilinx: Reduce spinlock array to array
gpio: gpio-xilinx: Simplify with dev_err_probe()
gpio: msic: Drop driver from Makefile
gpio: wcove: Split out to_ireg() helper and deduplicate the code
gpio: wcove: Switch to use regmap_set_bits(), regmap_clear_bits()
gpio: wcove: Get rid of error prone casting in IRQ handler
gpio: intel-mid: Remove driver for deprecated platform
gpio: msic: Remove driver for deprecated platform
gpio: aggregator: Remove trailing comma in terminator entries
gpio: aggregator: Use compound literal from the header
...
Diffstat (limited to 'drivers/gpio/gpio-wcove.c')
-rw-r--r-- | drivers/gpio/gpio-wcove.c | 65 |
1 files changed, 33 insertions, 32 deletions
diff --git a/drivers/gpio/gpio-wcove.c b/drivers/gpio/gpio-wcove.c index b5fbba5a783a..a19eeef6cf1e 100644 --- a/drivers/gpio/gpio-wcove.c +++ b/drivers/gpio/gpio-wcove.c @@ -73,6 +73,8 @@ enum ctrl_register { CTRL_IN, CTRL_OUT, + IRQ_STATUS, + IRQ_MASK, }; /* @@ -112,22 +114,29 @@ static inline int to_reg(int gpio, enum ctrl_register reg_type) return reg; } -static void wcove_update_irq_mask(struct wcove_gpio *wg, int gpio) +static inline int to_ireg(int gpio, enum ctrl_register type, unsigned int *mask) { - unsigned int reg, mask; + unsigned int reg = type == IRQ_STATUS ? IRQ_STATUS_BASE : IRQ_MASK_BASE; if (gpio < GROUP0_NR_IRQS) { - reg = IRQ_MASK_BASE; - mask = BIT(gpio % GROUP0_NR_IRQS); + reg += 0; + *mask = BIT(gpio); } else { - reg = IRQ_MASK_BASE + 1; - mask = BIT((gpio - GROUP0_NR_IRQS) % GROUP1_NR_IRQS); + reg += 1; + *mask = BIT(gpio - GROUP0_NR_IRQS); } + return reg; +} + +static void wcove_update_irq_mask(struct wcove_gpio *wg, int gpio) +{ + unsigned int mask, reg = to_ireg(gpio, IRQ_MASK, &mask); + if (wg->set_irq_mask) - regmap_update_bits(wg->regmap, reg, mask, mask); + regmap_set_bits(wg->regmap, reg, mask); else - regmap_update_bits(wg->regmap, reg, mask, 0); + regmap_clear_bits(wg->regmap, reg, mask); } static void wcove_update_irq_ctrl(struct wcove_gpio *wg, int gpio) @@ -207,9 +216,9 @@ static void wcove_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value) return; if (value) - regmap_update_bits(wg->regmap, reg, 1, 1); + regmap_set_bits(wg->regmap, reg, 1); else - regmap_update_bits(wg->regmap, reg, 1, 0); + regmap_clear_bits(wg->regmap, reg, 1); } static int wcove_gpio_set_config(struct gpio_chip *chip, unsigned int gpio, @@ -324,7 +333,8 @@ static struct irq_chip wcove_irqchip = { static irqreturn_t wcove_gpio_irq_handler(int irq, void *data) { struct wcove_gpio *wg = (struct wcove_gpio *)data; - unsigned int pending, virq, gpio, mask, offset; + unsigned int virq, gpio; + unsigned long pending; u8 p[2]; if (regmap_bulk_read(wg->regmap, IRQ_STATUS_BASE, p, 2)) { @@ -339,15 +349,12 @@ static irqreturn_t wcove_gpio_irq_handler(int irq, void *data) /* Iterate until no interrupt is pending */ while (pending) { /* One iteration is for all pending bits */ - for_each_set_bit(gpio, (const unsigned long *)&pending, - WCOVE_GPIO_NUM) { - offset = (gpio > GROUP0_NR_IRQS) ? 1 : 0; - mask = (offset == 1) ? BIT(gpio - GROUP0_NR_IRQS) : - BIT(gpio); + for_each_set_bit(gpio, &pending, WCOVE_GPIO_NUM) { + unsigned int mask, reg = to_ireg(gpio, IRQ_STATUS, &mask); + virq = irq_find_mapping(wg->chip.irq.domain, gpio); handle_nested_irq(virq); - regmap_update_bits(wg->regmap, IRQ_STATUS_BASE + offset, - mask, mask); + regmap_set_bits(wg->regmap, reg, mask); } /* Next iteration */ @@ -367,30 +374,26 @@ static void wcove_gpio_dbg_show(struct seq_file *s, { unsigned int ctlo, ctli, irq_mask, irq_status; struct wcove_gpio *wg = gpiochip_get_data(chip); - int gpio, offset, group, ret = 0; + int gpio, mask, ret = 0; for (gpio = 0; gpio < WCOVE_GPIO_NUM; gpio++) { - group = gpio < GROUP0_NR_IRQS ? 0 : 1; ret += regmap_read(wg->regmap, to_reg(gpio, CTRL_OUT), &ctlo); ret += regmap_read(wg->regmap, to_reg(gpio, CTRL_IN), &ctli); - ret += regmap_read(wg->regmap, IRQ_MASK_BASE + group, - &irq_mask); - ret += regmap_read(wg->regmap, IRQ_STATUS_BASE + group, - &irq_status); + ret += regmap_read(wg->regmap, to_ireg(gpio, IRQ_MASK, &mask), &irq_mask); + ret += regmap_read(wg->regmap, to_ireg(gpio, IRQ_STATUS, &mask), &irq_status); if (ret) { pr_err("Failed to read registers: ctrl out/in or irq status/mask\n"); break; } - offset = gpio % 8; seq_printf(s, " gpio-%-2d %s %s %s %s ctlo=%2x,%s %s\n", gpio, ctlo & CTLO_DIR_OUT ? "out" : "in ", ctli & 0x1 ? "hi" : "lo", ctli & CTLI_INTCNT_NE ? "fall" : " ", ctli & CTLI_INTCNT_PE ? "rise" : " ", ctlo, - irq_mask & BIT(offset) ? "mask " : "unmask", - irq_status & BIT(offset) ? "pending" : " "); + irq_mask & mask ? "mask " : "unmask", + irq_status & mask ? "pending" : " "); } } @@ -434,7 +437,7 @@ static int wcove_gpio_probe(struct platform_device *pdev) wg->chip.get_direction = wcove_gpio_get_direction; wg->chip.get = wcove_gpio_get; wg->chip.set = wcove_gpio_set; - wg->chip.set_config = wcove_gpio_set_config, + wg->chip.set_config = wcove_gpio_set_config; wg->chip.base = -1; wg->chip.ngpio = WCOVE_VGPIO_NUM; wg->chip.can_sleep = true; @@ -473,14 +476,12 @@ static int wcove_gpio_probe(struct platform_device *pdev) } /* Enable GPIO0 interrupts */ - ret = regmap_update_bits(wg->regmap, IRQ_MASK_BASE, GPIO_IRQ0_MASK, - 0x00); + ret = regmap_clear_bits(wg->regmap, IRQ_MASK_BASE + 0, GPIO_IRQ0_MASK); if (ret) return ret; /* Enable GPIO1 interrupts */ - ret = regmap_update_bits(wg->regmap, IRQ_MASK_BASE + 1, GPIO_IRQ1_MASK, - 0x00); + ret = regmap_clear_bits(wg->regmap, IRQ_MASK_BASE + 1, GPIO_IRQ1_MASK); if (ret) return ret; |