[U-Boot] [PATCH 1/2] x86: gpio: Make x86-pinctrl subnode of ich6-gpio

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


Instead of having x86-pinctrl work separately from ich6-gpio have it
work underneath ich6-gpio. This removes redundant configuration and will
allow the addition of shared bank settings in future commits.

Signed-off-by: George McCollister <george.mccollister at gmail.com>
---
 arch/x86/dts/minnowmax.dts                         |  96 +++++++++---------
 arch/x86/include/asm/gpio.h                        |   1 -
 board/intel/minnowmax/minnowmax.c                  |   9 +-
 doc/device-tree-bindings/gpio/intel,ich6-gpio.txt  |  14 +++
 .../gpio/intel,x86-pinctrl.txt                     |  17 ++--
 drivers/gpio/intel_ich6_gpio.c                     | 107 ++++++++-------------
 6 files changed, 118 insertions(+), 126 deletions(-)
 create mode 100644 doc/device-tree-bindings/gpio/intel,ich6-gpio.txt

diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
index e917f0f..79ac26d 100644
--- a/arch/x86/dts/minnowmax.dts
+++ b/arch/x86/dts/minnowmax.dts
@@ -26,54 +26,6 @@
 		silent_console = <0>;
 	};
 
-	pch_pinctrl {
-		compatible = "intel,x86-pinctrl";
-		io-base = <0x4c>;
-
-		/* GPIO E0 */
-		soc_gpio_s5_0 at 0 {
-			gpio-offset = <0x80 0>;
-			pad-offset = <0x1d0>;
-			mode-gpio;
-			output-value = <0>;
-			direction = <PIN_OUTPUT>;
-		};
-
-		/* GPIO E1 */
-		soc_gpio_s5_1 at 0 {
-			gpio-offset = <0x80 1>;
-			pad-offset = <0x210>;
-			mode-gpio;
-			output-value = <0>;
-			direction = <PIN_OUTPUT>;
-		};
-
-		/* GPIO E2 */
-		soc_gpio_s5_2 at 0 {
-			gpio-offset = <0x80 2>;
-			pad-offset = <0x1e0>;
-			mode-gpio;
-			output-value = <0>;
-			direction = <PIN_OUTPUT>;
-		};
-
-		pin_usb_host_en0 at 0 {
-			gpio-offset = <0x80 8>;
-			pad-offset = <0x260>;
-			mode-gpio;
-			output-value = <1>;
-			direction = <PIN_OUTPUT>;
-		};
-
-		pin_usb_host_en1 at 0 {
-			gpio-offset = <0x80 9>;
-			pad-offset = <0x250>;
-			mode-gpio;
-			output-value = <1>;
-			direction = <PIN_OUTPUT>;
-		};
-	};
-
 	gpioa {
 		compatible = "intel,ich6-gpio";
 		u-boot,dm-pre-reloc;
@@ -107,6 +59,54 @@
 		u-boot,dm-pre-reloc;
 		reg = <0x80 0x20>;
 		bank-name = "E";
+
+		pch_pinctrl at 0 {
+			compatible = "intel,x86-pinctrl";
+			io-base = <0x4c>;
+
+			/* GPIO E0 */
+			soc_gpio_s5_0 at 0 {
+				gpio-offset = <0>;
+				pad-offset = <0x1d0>;
+				mode-gpio;
+				output-value = <0>;
+				direction = <PIN_OUTPUT>;
+			};
+
+			/* GPIO E1 */
+			soc_gpio_s5_1 at 0 {
+				gpio-offset = <1>;
+				pad-offset = <0x210>;
+				mode-gpio;
+				output-value = <0>;
+				direction = <PIN_OUTPUT>;
+			};
+
+			/* GPIO E2 */
+			soc_gpio_s5_2 at 0 {
+				gpio-offset = <2>;
+				pad-offset = <0x1e0>;
+				mode-gpio;
+				output-value = <0>;
+				direction = <PIN_OUTPUT>;
+			};
+
+			pin_usb_host_en0 at 0 {
+				gpio-offset = <8>;
+				pad-offset = <0x260>;
+				mode-gpio;
+				output-value = <1>;
+				direction = <PIN_OUTPUT>;
+			};
+
+			pin_usb_host_en1 at 0 {
+				gpio-offset = <9>;
+				pad-offset = <0x250>;
+				mode-gpio;
+				output-value = <1>;
+				direction = <PIN_OUTPUT>;
+			};
+		};
 	};
 
 	gpiof {
diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h
index ed85b08..1099427 100644
--- a/arch/x86/include/asm/gpio.h
+++ b/arch/x86/include/asm/gpio.h
@@ -147,7 +147,6 @@ struct pch_gpio_map {
 	} set3;
 };
 
-int gpio_ich6_pinctrl_init(void);
 void setup_pch_gpios(u16 gpiobase, const struct pch_gpio_map *gpio);
 void ich_gpio_set_gpio_map(const struct pch_gpio_map *map);
 
diff --git a/board/intel/minnowmax/minnowmax.c b/board/intel/minnowmax/minnowmax.c
index 44e5bf4..ae06cc4 100644
--- a/board/intel/minnowmax/minnowmax.c
+++ b/board/intel/minnowmax/minnowmax.c
@@ -5,12 +5,17 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <asm/gpio.h>
 
 int arch_early_init_r(void)
 {
-	/* do the pin-muxing */
-	gpio_ich6_pinctrl_init();
+	struct udevice *dev;
+
+	/* Force initialization of gpio so initial states are set correctly. */
+	for (uclass_first_device(UCLASS_GPIO, &dev);
+	     dev;
+	     uclass_next_device(&dev));
 
 	return 0;
 }
diff --git a/doc/device-tree-bindings/gpio/intel,ich6-gpio.txt b/doc/device-tree-bindings/gpio/intel,ich6-gpio.txt
new file mode 100644
index 0000000..23345b2
--- /dev/null
+++ b/doc/device-tree-bindings/gpio/intel,ich6-gpio.txt
@@ -0,0 +1,14 @@
+Intel x86 GPIO controller
+
+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.
+
+Example:
+gpioa {
+	compatible = "intel,ich6-gpio";
+	u-boot,dm-pre-reloc;
+	reg = <0 0x20>;
+	bank-name = "A";
+};
diff --git a/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt b/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
index 45ab1af..eb9c8da 100644
--- a/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
+++ b/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
@@ -1,7 +1,7 @@
-Intel x86 PINCTRL/GPIO controller
+Intel x86 PINCTRL
 
-Pin-muxing on x86 can be described with a node for the PINCTRL master
-node and a set of child nodes for each pin on the SoC.
+Pin-muxing on x86 can be described under each GPIO bank with a node for the
+PINCTRL master node and a set of child nodes for each pin on the SoC.
 
 The PINCTRL master node requires the following properties:
 - compatible : "intel,x86-pinctrl"
@@ -9,13 +9,12 @@ The PINCTRL master node requires the following properties:
 Pin nodes must be children of the pinctrl master node and can
 contain the following properties:
 - pad-offset        - (required) offset in the IOBASE for the pin to configured.
-- gpio-offset       - (required) offset in the GPIOBASE for the pin to configured and
-					also the bit shift in this register.
-- mode-gpio			- (optional) standalone property to force the pin into GPIO mode.
-- mode-func			- (optional) function number to assign to the pin. if 'mode-gpio'
+- gpio-offset       - (required) bit shift in the GPIO register.
+- mode-gpio         - (optional) standalone property to force the pin into GPIO mode.
+- mode-func         - (optional) function number to assign to the pin. if 'mode-gpio'
 					is set, this property will be ignored.
 in case of 'mode-gpio' property set:
-- output-value		- (optional) this set the default output value of the GPIO.
+- output-value      - (optional) this set the default output value of the GPIO.
 - direction         - (optional) this set the direction of the gpio.
 - pull-str          - (optional) this set the pull strength of the pin.
 - pull-assign       - (optional) this set the pull assignement (up/down) of the pin.
@@ -23,7 +22,7 @@ in case of 'mode-gpio' property set:
 Example:
 
 pin_usb_host_en0 at 0 {
-    gpio-offset = <0x80 8>;
+    gpio-offset = <8>;
     pad-offset = <0x260>;
     mode-gpio;
     output-value = <1>;
diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
index 67bf0a2..18420f3 100644
--- a/drivers/gpio/intel_ich6_gpio.c
+++ b/drivers/gpio/intel_ich6_gpio.c
@@ -41,15 +41,11 @@ DECLARE_GLOBAL_DATA_PTR;
 
 struct ich6_bank_priv {
 	/* These are I/O addresses */
-	uint16_t use_sel;
-	uint16_t io_sel;
-	uint16_t lvl;
+	u16 use_sel;
+	u16 io_sel;
+	u16 lvl;
 };
 
-#define GPIO_USESEL_OFFSET(x)	(x)
-#define GPIO_IOSEL_OFFSET(x)	(x + 4)
-#define GPIO_LVL_OFFSET(x)	(x + 8)
-
 #define IOPAD_MODE_MASK				0x7
 #define IOPAD_PULL_ASSIGN_SHIFT		7
 #define IOPAD_PULL_ASSIGN_MASK		(0x3 << IOPAD_PULL_ASSIGN_SHIFT)
@@ -147,92 +143,90 @@ static int gpio_ich6_get_base(unsigned long base)
 	return tmplong & 1 ? tmplong & ~3 : tmplong & ~15;
 }
 
-static int _ich6_gpio_set_value(uint16_t base, unsigned offset, int value)
+
+static int ich6_gpio_set_value(struct udevice *dev, unsigned offset,
+			       int value)
 {
+	struct ich6_bank_priv *bank = dev_get_priv(dev);
 	u32 val;
 
-	val = inl(base);
+	val = inl(bank->lvl);
 	if (value)
 		val |= (1UL << offset);
 	else
 		val &= ~(1UL << offset);
-	outl(val, base);
+	outl(val, bank->lvl);
 
 	return 0;
 }
 
-static int _ich6_gpio_set_function(uint16_t base, unsigned offset, int func)
+static int ich6_gpio_set_function(struct udevice *dev, unsigned offset,
+				  int func)
 {
+	struct ich6_bank_priv *bank = dev_get_priv(dev);
 	u32 val;
 
 	if (func) {
-		val = inl(base);
+		val = inl(bank->use_sel);
 		val |= (1UL << offset);
-		outl(val, base);
+		outl(val, bank->use_sel);
 	} else {
-		val = inl(base);
+		val = inl(bank->use_sel);
 		val &= ~(1UL << offset);
-		outl(val, base);
+		outl(val, bank->use_sel);
 	}
 
 	return 0;
 }
 
-static int _ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir)
+static int ich6_gpio_set_direction(struct udevice *dev, unsigned offset,
+				   int dir)
 {
+	struct ich6_bank_priv *bank = dev_get_priv(dev);
 	u32 val;
 
 	if (!dir) {
-		val = inl(base);
+		val = inl(bank->io_sel);
 		val |= (1UL << offset);
-		outl(val, base);
+		outl(val, bank->io_sel);
 	} else {
-		val = inl(base);
+		val = inl(bank->io_sel);
 		val &= ~(1UL << offset);
-		outl(val, base);
+		outl(val, bank->io_sel);
 	}
 
 	return 0;
 }
 
-static int _gpio_ich6_pinctrl_cfg_pin(s32 gpiobase, s32 iobase, int pin_node)
+static int _gpio_ich6_pinctrl_cfg_pin(struct udevice *dev, s32 iobase,
+		int pin_node)
 {
-	u32 gpio_offset[2];
+	int gpio_offset;
 	int pad_offset;
 	int val;
-	int ret;
 	const void *prop;
 
 	/*
 	 * GPIO node is not mandatory, so we only do the
 	 * pinmuxing if the node exist.
 	 */
-	ret = fdtdec_get_int_array(gd->fdt_blob, pin_node, "gpio-offset",
-			     gpio_offset, 2);
-	if (!ret) {
+	gpio_offset = fdtdec_get_int(gd->fdt_blob, pin_node, "gpio-offset", -1);
+	if (gpio_offset != -1) {
 		/* Do we want to force the GPIO mode? */
 		prop = fdt_getprop(gd->fdt_blob, pin_node, "mode-gpio",
 				      NULL);
 		if (prop)
-			_ich6_gpio_set_function(GPIO_USESEL_OFFSET
-						(gpiobase) +
-						gpio_offset[0],
-						gpio_offset[1], 1);
+			ich6_gpio_set_function(dev, gpio_offset, 1);
 
 		val =
 		    fdtdec_get_int(gd->fdt_blob, pin_node, "direction", -1);
 		if (val != -1)
-			_ich6_gpio_set_direction(GPIO_IOSEL_OFFSET
-						 (gpiobase) +
-						 gpio_offset[0],
-						 gpio_offset[1], val);
+			ich6_gpio_set_direction(dev, gpio_offset, val);
 
 		val =
 		    fdtdec_get_int(gd->fdt_blob, pin_node, "output-value", -1);
 		if (val != -1)
-			_ich6_gpio_set_value(GPIO_LVL_OFFSET(gpiobase)
-					     + gpio_offset[0],
-					     gpio_offset[1], val);
+			ich6_gpio_set_value(dev, gpio_offset, val);
 	}
 
 	/* if iobase is present, let's configure the pad */
@@ -286,30 +280,19 @@ static int _gpio_ich6_pinctrl_cfg_pin(s32 gpiobase, s32 iobase, int pin_node)
 	return 0;
 }
 
-int gpio_ich6_pinctrl_init(void)
+static int gpio_ich6_pinctrl_init(struct udevice *dev)
 {
 	int pin_node;
 	int node;
 	int ret;
-	int gpiobase;
 	int iobase_offset;
 	int iobase = -1;
-
-	/*
-	 * Get the memory/io base address to configure every pins.
-	 * IOBASE is used to configure the mode/pads
-	 * GPIOBASE is used to configure the direction and default value
-	 */
-	gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
-	if (gpiobase < 0) {
-		debug("%s: invalid GPIOBASE address (%08x)\n", __func__,
-		      gpiobase);
-		return -EINVAL;
-	}
+	int depth = 0;
 
 	/* This is not an error to not have a pinctrl node */
 	node =
-	    fdtdec_next_compatible(gd->fdt_blob, 0, COMPAT_INTEL_X86_PINCTRL);
+	    fdtdec_next_compatible_subnode(gd->fdt_blob, dev->of_offset,
+			    COMPAT_INTEL_X86_PINCTRL, &depth);
 	if (node <= 0) {
 		debug("%s: no pinctrl node\n", __func__);
 		return 0;
@@ -335,7 +318,7 @@ int gpio_ich6_pinctrl_init(void)
 	     pin_node > 0;
 	     pin_node = fdt_next_subnode(gd->fdt_blob, pin_node)) {
 		/* Configure the pin */
-		ret = _gpio_ich6_pinctrl_cfg_pin(gpiobase, iobase, pin_node);
+		ret = _gpio_ich6_pinctrl_cfg_pin(dev, iobase, pin_node);
 		if (ret != 0) {
 			debug("%s: invalid configuration for the pin %d\n",
 			      __func__, pin_node);
@@ -382,6 +365,8 @@ static int ich6_gpio_probe(struct udevice *dev)
 	bank->io_sel = plat->base_addr + 4;
 	bank->lvl = plat->base_addr + 8;
 
+	gpio_ich6_pinctrl_init(dev);
+
 	return 0;
 }
 
@@ -408,22 +393,19 @@ static int ich6_gpio_request(struct udevice *dev, unsigned offset,
 
 static int ich6_gpio_direction_input(struct udevice *dev, unsigned offset)
 {
-	struct ich6_bank_priv *bank = dev_get_priv(dev);
-
-	return _ich6_gpio_set_direction(bank->io_sel, offset, 0);
+	return ich6_gpio_set_direction(dev, offset, 0);
 }
 
 static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
 				       int value)
 {
 	int ret;
-	struct ich6_bank_priv *bank = dev_get_priv(dev);
 
-	ret = _ich6_gpio_set_direction(bank->io_sel, offset, 1);
+	ret = ich6_gpio_set_direction(dev, offset, 1);
 	if (ret)
 		return ret;
 
-	return _ich6_gpio_set_value(bank->lvl, offset, value);
+	return ich6_gpio_set_value(dev, offset, value);
 }
 
 static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
@@ -437,13 +419,6 @@ static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
 	return r;
 }
 
-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);
-}
-
 static int ich6_gpio_get_function(struct udevice *dev, unsigned offset)
 {
 	struct ich6_bank_priv *bank = dev_get_priv(dev);
-- 
2.5.0



More information about the U-Boot mailing list