|
@@ -46,22 +46,31 @@ struct ich6_bank_priv {
|
|
|
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;
|
|
|
}
|
|
@@ -112,6 +121,7 @@ static int ich6_gpio_probe(struct udevice *dev)
|
|
|
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;
|
|
@@ -119,6 +129,14 @@ static int ich6_gpio_probe(struct udevice *dev)
|
|
|
bank->io_sel = plat->base_addr + 4;
|
|
|
bank->lvl = plat->base_addr + 8;
|
|
|
|
|
|
+ prop = fdt_getprop(gd->fdt_blob, dev->of_offset,
|
|
|
+ "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;
|
|
|
}
|
|
|
|
|
@@ -160,7 +178,7 @@ static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
|
|
|
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)
|
|
@@ -170,6 +188,8 @@ 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;
|
|
|
}
|
|
@@ -178,7 +198,7 @@ static int ich6_gpio_set_value(struct udevice *dev, unsigned offset,
|
|
|
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)
|