+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2012 The Chromium OS Authors.
- * SPDX-License-Identifier: GPL-2.0+
*/
/*
uint16_t use_sel;
uint16_t io_sel;
uint16_t lvl;
+ u32 lvl_write_cache;
+ bool use_lvl_write_cache;
};
#define GPIO_USESEL_OFFSET(x) (x)
#define GPIO_IOSEL_OFFSET(x) (x + 4)
#define GPIO_LVL_OFFSET(x) (x + 8)
-static int _ich6_gpio_set_value(uint16_t base, unsigned offset, int value)
+static int _ich6_gpio_set_value(struct ich6_bank_priv *bank, unsigned offset,
+ int value)
{
u32 val;
- val = inl(base);
+ if (bank->use_lvl_write_cache)
+ val = bank->lvl_write_cache;
+ else
+ val = inl(bank->lvl);
+
if (value)
val |= (1UL << offset);
else
val &= ~(1UL << offset);
- outl(val, base);
+ outl(val, bank->lvl);
+ if (bank->use_lvl_write_cache)
+ bank->lvl_write_cache = val;
return 0;
}
if (ret)
return ret;
- offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
+ offset = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "reg", -1);
if (offset == -1) {
debug("%s: Invalid register offset %d\n", __func__, offset);
return -EINVAL;
}
plat->offset = offset;
plat->base_addr = gpiobase + offset;
- plat->bank_name = fdt_getprop(gd->fdt_blob, dev->of_offset,
+ plat->bank_name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
"bank-name", NULL);
return 0;
struct ich6_bank_platdata *plat = dev_get_platdata(dev);
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
struct ich6_bank_priv *bank = dev_get_priv(dev);
+ const void *prop;
uc_priv->gpio_count = GPIO_PER_BANK;
uc_priv->bank_name = plat->bank_name;
bank->io_sel = plat->base_addr + 4;
bank->lvl = plat->base_addr + 8;
+ prop = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
+ "use-lvl-write-cache", NULL);
+ if (prop)
+ bank->use_lvl_write_cache = true;
+ else
+ bank->use_lvl_write_cache = false;
+ bank->lvl_write_cache = 0;
+
return 0;
}
if (ret)
return ret;
- return _ich6_gpio_set_value(bank->lvl, offset, value);
+ return _ich6_gpio_set_value(bank, offset, value);
}
static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
int r;
tmplong = inl(bank->lvl);
+ if (bank->use_lvl_write_cache)
+ tmplong |= bank->lvl_write_cache;
r = (tmplong & (1UL << offset)) ? 1 : 0;
return r;
}
int value)
{
struct ich6_bank_priv *bank = dev_get_priv(dev);
- return _ich6_gpio_set_value(bank->lvl, offset, value);
+ return _ich6_gpio_set_value(bank, offset, value);
}
static int ich6_gpio_get_function(struct udevice *dev, unsigned offset)