summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpio-aspeed.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-08 20:31:52 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-08 20:31:52 +0300
commitea125dedbc14b305307889c40d74d564c4419851 (patch)
tree0f11a7256b5fa0871ff323521f00f3a55a7ccb65 /drivers/gpio/gpio-aspeed.c
parentfdea70d26a471e002f2afc3a48821323b699f1e6 (diff)
parent6310b930ccbba55168f30b610fae681d73bd7bd2 (diff)
downloadlinux-ea125dedbc14b305307889c40d74d564c4419851.tar.xz
Merge tag 'gpio-v4.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO updates from Linus Walleij: "This is the bulk of GPIO changes for the v4.18 development cycle. Core changes: - We have killed off VLA from the core library and all drivers. The background should be clear for everyone at this point: https://lwn.net/Articles/749064/ Also I just don't like VLA's, kernel developers hate it when compilers do things behind their back. It's as simple as that. I'm sorry that they even slipped in to begin with. Kudos to Laura Abbott for exorcising them. - Support GPIO hogs in machines/board files. New drivers and chip support: - R-Car r8a77470 (RZ/G1C) - R-Car r8a77965 (M3-N) - R-Car r8a77990 (E3) - PCA953x driver improvements to accomodate more variants. Improvements and new features: - Support one interrupt per line on port A in the DesignWare dwapb driver. Misc: - Random cleanups, right header files in the drivers, some size optimizations etc" * tag 'gpio-v4.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (73 commits) gpio: davinci: fix build warning when !CONFIG_OF gpio: dwapb: Fix rework support for 1 interrupt per port A GPIO gpio: pxa: Include the right header gpio: pl061: Include the right header gpio: pch: Include the right header gpio: pcf857x: Include the right header gpio: pca953x: Include the right header gpio: palmas: Include the right header gpio: omap: Include the right header gpio: octeon: Include the right header gpio: mxs: Switch to SPDX identifier gpio: Remove VLA from stmpe driver gpio: mxc: Switch to SPDX identifier gpio: mxc: add clock operation gpio: Remove VLA from gpiolib gpio: aspeed: Use a cache of output data registers gpio: aspeed: Set output latch before changing direction gpio: pca953x: fix address calculation for pcal6524 gpio: pca953x: define masks for addressing common and extended registers gpio: pca953x: set the PCA_PCAL flag also when matching by DT ...
Diffstat (limited to 'drivers/gpio/gpio-aspeed.c')
-rw-r--r--drivers/gpio/gpio-aspeed.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
index 6f693b7d5220..5e89f1c74a33 100644
--- a/drivers/gpio/gpio-aspeed.c
+++ b/drivers/gpio/gpio-aspeed.c
@@ -54,6 +54,8 @@ struct aspeed_gpio {
u8 *offset_timer;
unsigned int timer_users[4];
struct clk *clk;
+
+ u32 *dcache;
};
struct aspeed_gpio_bank {
@@ -231,12 +233,13 @@ static void __aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
u32 reg;
addr = bank_val_reg(gpio, bank, GPIO_DATA);
- reg = ioread32(addr);
+ reg = gpio->dcache[GPIO_BANK(offset)];
if (val)
reg |= GPIO_BIT(offset);
else
reg &= ~GPIO_BIT(offset);
+ gpio->dcache[GPIO_BANK(offset)] = reg;
iowrite32(reg, addr);
}
@@ -287,11 +290,10 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc,
spin_lock_irqsave(&gpio->lock, flags);
+ __aspeed_gpio_set(gc, offset, val);
reg = ioread32(bank_val_reg(gpio, bank, GPIO_DIR));
iowrite32(reg | GPIO_BIT(offset), bank_val_reg(gpio, bank, GPIO_DIR));
- __aspeed_gpio_set(gc, offset, val);
-
spin_unlock_irqrestore(&gpio->lock, flags);
return 0;
@@ -852,7 +854,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
const struct of_device_id *gpio_id;
struct aspeed_gpio *gpio;
struct resource *res;
- int rc;
+ int rc, i, banks;
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio)
@@ -893,6 +895,20 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
gpio->chip.base = -1;
gpio->chip.irq.need_valid_mask = true;
+ /* Allocate a cache of the output registers */
+ banks = gpio->config->nr_gpios >> 5;
+ gpio->dcache = devm_kzalloc(&pdev->dev,
+ sizeof(u32) * banks, GFP_KERNEL);
+ if (!gpio->dcache)
+ return -ENOMEM;
+
+ /* Populate it with initial values read from the HW */
+ for (i = 0; i < banks; i++) {
+ const struct aspeed_gpio_bank *bank = &aspeed_gpio_banks[i];
+ gpio->dcache[i] = ioread32(gpio->base + bank->val_regs +
+ GPIO_DATA);
+ }
+
rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
if (rc < 0)
return rc;