[U-Boot] [PATCH 2/2] x86: gpio: Add use-lvl-write-cache to fix baytrail

George McCollister george.mccollister at gmail.com
Wed Oct 7 17:29:51 CEST 2015


Add a device-tree property use-lvl-write-cache that will cause writes to
lvl to be cached instead of read from lvl before each write. This is
required on some platforms that have the register implemented as dual
read/write (such as Baytrail).

Prior to this fix the blue USB port on the Minnowboard Max was unusable
since USB_HOST_EN0 was set high then immediately set low when
USB_HOST_EN1 was written.

Signed-off-by: George McCollister <george.mccollister at gmail.com>
---
 arch/x86/dts/minnowmax.dts                        |  6 ++++++
 doc/device-tree-bindings/gpio/intel,ich6-gpio.txt |  5 +++++
 drivers/gpio/intel_ich6_gpio.c                    | 20 +++++++++++++++++++-
 3 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
index 79ac26d..5a76c8e 100644
--- a/arch/x86/dts/minnowmax.dts
+++ b/arch/x86/dts/minnowmax.dts
@@ -31,6 +31,7 @@
 		u-boot,dm-pre-reloc;
 		reg = <0 0x20>;
 		bank-name = "A";
+		use-lvl-write-cache;
 	};
 
 	gpiob {
@@ -38,6 +39,7 @@
 		u-boot,dm-pre-reloc;
 		reg = <0x20 0x20>;
 		bank-name = "B";
+		use-lvl-write-cache;
 	};
 
 	gpioc {
@@ -45,6 +47,7 @@
 		u-boot,dm-pre-reloc;
 		reg = <0x40 0x20>;
 		bank-name = "C";
+		use-lvl-write-cache;
 	};
 
 	gpiod {
@@ -52,6 +55,7 @@
 		u-boot,dm-pre-reloc;
 		reg = <0x60 0x20>;
 		bank-name = "D";
+		use-lvl-write-cache;
 	};
 
 	gpioe {
@@ -59,6 +63,7 @@
 		u-boot,dm-pre-reloc;
 		reg = <0x80 0x20>;
 		bank-name = "E";
+		use-lvl-write-cache;
 
 		pch_pinctrl at 0 {
 			compatible = "intel,x86-pinctrl";
@@ -114,6 +119,7 @@
 		u-boot,dm-pre-reloc;
 		reg = <0xA0 0x20>;
 		bank-name = "F";
+		use-lvl-write-cache;
 	};
 
 	chosen {
diff --git a/doc/device-tree-bindings/gpio/intel,ich6-gpio.txt b/doc/device-tree-bindings/gpio/intel,ich6-gpio.txt
index 23345b2..dbdcff4 100644
--- a/doc/device-tree-bindings/gpio/intel,ich6-gpio.txt
+++ b/doc/device-tree-bindings/gpio/intel,ich6-gpio.txt
@@ -4,6 +4,10 @@ Each GPIO bank node can have the following properties:
 - compatible          - (required) must be set to "intel,x86-pinctrl"
 - reg                 - (required) GPIO offset and length.
 - bank-name           - (required) Name of the bank.
+- use-lvl-write-cache - (optional) Cache last value written to lvl and use it
+                                   the next time lvl is written instead of
+                                   reading lvl prior to writing. Required
+                                   for some platforms (Baytrail).
 
 Example:
 gpioa {
@@ -11,4 +15,5 @@ gpioa {
 	u-boot,dm-pre-reloc;
 	reg = <0 0x20>;
 	bank-name = "A";
+	use-lvl-write-cache;
 };
diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
index 18420f3..b239ab5 100644
--- a/drivers/gpio/intel_ich6_gpio.c
+++ b/drivers/gpio/intel_ich6_gpio.c
@@ -44,6 +44,8 @@ struct ich6_bank_priv {
 	u16 use_sel;
 	u16 io_sel;
 	u16 lvl;
+	u32 lvl_write_cache;
+	bool use_lvl_write_cache;
 };
 
 #define IOPAD_MODE_MASK				0x7
@@ -150,12 +152,17 @@ static int ich6_gpio_set_value(struct udevice *dev, unsigned offset,
 	struct ich6_bank_priv *bank = dev_get_priv(dev);
 	u32 val;
 
-	val = inl(bank->lvl);
+	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, bank->lvl);
+	if (bank->use_lvl_write_cache)
+		bank->lvl_write_cache = val;
 
 	return 0;
 }
@@ -353,6 +360,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;
 
 	if (gd->arch.gpio_map) {
 		setup_pch_gpios(plat->base_addr, gd->arch.gpio_map);
@@ -365,6 +373,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;
+
 	gpio_ich6_pinctrl_init(dev);
 
 	return 0;
@@ -415,6 +431,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;
 }
-- 
2.5.0



More information about the U-Boot mailing list