|
@@ -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);
|
|
|
}
|
|
@@ -851,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)
|
|
@@ -892,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;
|