All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/4] x86: support of pin-muxing from device tree
@ 2015-04-23 16:16 Gabriel Huau
  2015-04-23 16:16 ` [U-Boot] [PATCH 1/4] x86: baytrail: fix the GPIOBASE address Gabriel Huau
                   ` (13 more replies)
  0 siblings, 14 replies; 61+ messages in thread
From: Gabriel Huau @ 2015-04-23 16:16 UTC (permalink / raw)
  To: u-boot

This serie of patches adds the support of pin-muxing from the device tree through
different properties. I have put two example to enable the USB Host on the
minnowboard max.

The support of the call to 'setup_pch_gpios' is still supported and
only the minnowboard has been tested with the device tree implementation.

Because the GPIO and IO base register ares different, I have also defined
some proxy function to set the function/value and direction of the GPIO as
the GPIO register can override some registers in the IO.

Gabriel Huau (4):
  x86: baytrail: fix the GPIOBASE address
  x86: minnowmax: add GPIO banks in the device tree
  x86: gpio: add pinctrl support from the device tree
  x86: minnowmax: initialize the pin-muxing from device tree

 arch/x86/dts/minnowmax.dts                |  63 +++++++++
 arch/x86/include/asm/arch-baytrail/gpio.h |   3 +-
 arch/x86/include/asm/gpio.h               |   1 +
 board/intel/minnowmax/minnowmax.c         |   9 ++
 drivers/gpio/intel_ich6_gpio.c            | 222 ++++++++++++++++++++++++++----
 include/configs/minnowmax.h               |   1 +
 include/dt-bindings/gpio/gpio.h           |  20 +++
 7 files changed, 292 insertions(+), 27 deletions(-)

-- 
2.1.4

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 1/4] x86: baytrail: fix the GPIOBASE address
  2015-04-23 16:16 [U-Boot] [PATCH 0/4] x86: support of pin-muxing from device tree Gabriel Huau
@ 2015-04-23 16:16 ` Gabriel Huau
  2015-04-24  1:40   ` Bin Meng
                     ` (2 more replies)
  2015-04-23 16:16 ` [U-Boot] [PATCH 2/4] x86: minnowmax: add GPIO banks in the device tree Gabriel Huau
                   ` (12 subsequent siblings)
  13 siblings, 3 replies; 61+ messages in thread
From: Gabriel Huau @ 2015-04-23 16:16 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
---
 arch/x86/include/asm/arch-baytrail/gpio.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/arch-baytrail/gpio.h b/arch/x86/include/asm/arch-baytrail/gpio.h
index ab4e059..4e8987c 100644
--- a/arch/x86/include/asm/arch-baytrail/gpio.h
+++ b/arch/x86/include/asm/arch-baytrail/gpio.h
@@ -8,6 +8,6 @@
 #define _X86_ARCH_GPIO_H_
 
 /* Where in config space is the register that points to the GPIO registers? */
-#define PCI_CFG_GPIOBASE 0x44
+#define PCI_CFG_GPIOBASE 0x48
 
 #endif /* _X86_ARCH_GPIO_H_ */
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 2/4] x86: minnowmax: add GPIO banks in the device tree
  2015-04-23 16:16 [U-Boot] [PATCH 0/4] x86: support of pin-muxing from device tree Gabriel Huau
  2015-04-23 16:16 ` [U-Boot] [PATCH 1/4] x86: baytrail: fix the GPIOBASE address Gabriel Huau
@ 2015-04-23 16:16 ` Gabriel Huau
  2015-04-24  2:03   ` Bin Meng
                     ` (4 more replies)
  2015-04-23 16:16 ` [U-Boot] [PATCH 3/4] x86: gpio: add pinctrl support from " Gabriel Huau
                   ` (11 subsequent siblings)
  13 siblings, 5 replies; 61+ messages in thread
From: Gabriel Huau @ 2015-04-23 16:16 UTC (permalink / raw)
  To: u-boot

There is 6 banks:
    4 banks for CORE: available in S0 mode
    2 banks for SUS (Suspend): available in S0-S5 mode

Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
---
 arch/x86/dts/minnowmax.dts | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
index 8f34369..c73e421 100644
--- a/arch/x86/dts/minnowmax.dts
+++ b/arch/x86/dts/minnowmax.dts
@@ -21,6 +21,48 @@
 		silent_console = <0>;
 	};
 
+	gpioa {
+		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
+		reg = <0 0x20>;
+		bank-name = "A";
+	};
+
+	gpiob {
+		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
+		reg = <0x20 0x20>;
+		bank-name = "B";
+	};
+
+	gpioc {
+		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
+		reg = <0x40 0x20>;
+		bank-name = "C";
+	};
+
+	gpiod {
+		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
+		reg = <0x60 0x20>;
+		bank-name = "D";
+	};
+
+	gpioe {
+		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
+		reg = <0x80 0x20>;
+		bank-name = "E";
+	};
+
+	gpiof {
+		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
+		reg = <0xA0 0x20>;
+		bank-name = "F";
+	};
+
 	chosen {
 		stdout-path = "/serial";
 	};
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 3/4] x86: gpio: add pinctrl support from the device tree
  2015-04-23 16:16 [U-Boot] [PATCH 0/4] x86: support of pin-muxing from device tree Gabriel Huau
  2015-04-23 16:16 ` [U-Boot] [PATCH 1/4] x86: baytrail: fix the GPIOBASE address Gabriel Huau
  2015-04-23 16:16 ` [U-Boot] [PATCH 2/4] x86: minnowmax: add GPIO banks in the device tree Gabriel Huau
@ 2015-04-23 16:16 ` Gabriel Huau
  2015-04-24  3:14   ` Bin Meng
                     ` (5 more replies)
  2015-04-23 16:16 ` [U-Boot] [PATCH 4/4] x86: minnowmax: initialize the pin-muxing from " Gabriel Huau
                   ` (10 subsequent siblings)
  13 siblings, 6 replies; 61+ messages in thread
From: Gabriel Huau @ 2015-04-23 16:16 UTC (permalink / raw)
  To: u-boot

A set of properties has been defined for the device tree to select for
each pin the pull/func/default output configuration.

The offset for the PAD needs to be provided and if a GPIO needs to be
configured, his offset needs to be provided as well.

Here is an example:
pin_usb_host_en0 at 0 {
    gpio-offset = <0x80 8>;
    pad-offset = <0x260>;
    mode-gpio;
    output-value = <1>;
    direction = <PIN_OUTPUT>;
};

Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
---
 arch/x86/dts/minnowmax.dts                |  21 +++
 arch/x86/include/asm/arch-baytrail/gpio.h |   1 +
 arch/x86/include/asm/gpio.h               |   1 +
 drivers/gpio/intel_ich6_gpio.c            | 222 ++++++++++++++++++++++++++----
 include/dt-bindings/gpio/gpio.h           |  20 +++
 5 files changed, 239 insertions(+), 26 deletions(-)

diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
index c73e421..3936e21 100644
--- a/arch/x86/dts/minnowmax.dts
+++ b/arch/x86/dts/minnowmax.dts
@@ -6,6 +6,8 @@
 
 /dts-v1/;
 
+#include <dt-bindings/gpio/gpio.h>
+
 /include/ "skeleton.dtsi"
 /include/ "serial.dtsi"
 
@@ -21,6 +23,25 @@
 		silent_console = <0>;
 	};
 
+	pch_pinctrl {
+		compatible = "intel,ich6-pinctrl";
+		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 = <0x258>;
+			mode-gpio;
+			output-value = <1>;
+			direction = <PIN_OUTPUT>;
+		};
+	};
+
 	gpioa {
 		compatible = "intel,ich6-gpio";
 		u-boot,dm-pre-reloc;
diff --git a/arch/x86/include/asm/arch-baytrail/gpio.h b/arch/x86/include/asm/arch-baytrail/gpio.h
index 4e8987c..85a65a8 100644
--- a/arch/x86/include/asm/arch-baytrail/gpio.h
+++ b/arch/x86/include/asm/arch-baytrail/gpio.h
@@ -9,5 +9,6 @@
 
 /* Where in config space is the register that points to the GPIO registers? */
 #define PCI_CFG_GPIOBASE 0x48
+#define PCI_CFG_IOBASE   0x4c
 
 #endif /* _X86_ARCH_GPIO_H_ */
diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h
index 1099427..ed85b08 100644
--- a/arch/x86/include/asm/gpio.h
+++ b/arch/x86/include/asm/gpio.h
@@ -147,6 +147,7 @@ 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/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
index 7e679a0..a110d5b 100644
--- a/drivers/gpio/intel_ich6_gpio.c
+++ b/drivers/gpio/intel_ich6_gpio.c
@@ -44,21 +44,32 @@ struct ich6_bank_priv {
 	uint16_t 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_MASK		0x3
+#define IOPAD_PULL_ASSIGN_SHIFT		7
+#define IOPAD_PULL_STRENGTH_MASK	0x3
+#define IOPAD_PULL_STRENGTH_SHIFT	9
+
+static int __ich6_gpio_set_value(uint16_t base, unsigned offset, int value);
+static int __ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir);
+static int __ich6_gpio_set_function(uint16_t base, unsigned offset, int func);
+
 /* TODO: Move this to device tree, or platform data */
 void ich_gpio_set_gpio_map(const struct pch_gpio_map *map)
 {
 	gd->arch.gpio_map = map;
 }
 
-static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
+static int gpio_ich6_get_base(unsigned long base)
 {
-	struct ich6_bank_platdata *plat = dev_get_platdata(dev);
 	pci_dev_t pci_dev;			/* handle for 0:1f:0 */
 	u8 tmpbyte;
 	u16 tmpword;
 	u32 tmplong;
-	u16 gpiobase;
-	int offset;
 
 	/* Where should it be? */
 	pci_dev = PCI_BDF(0, 0x1f, 0);
@@ -123,9 +134,9 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
 	 * while on the Ivybridge the bit0 is used to indicate it is an
 	 * I/O space.
 	 */
-	tmplong = x86_pci_read_config32(pci_dev, PCI_CFG_GPIOBASE);
+	tmplong = x86_pci_read_config32(pci_dev, base);
 	if (tmplong == 0x00000000 || tmplong == 0xffffffff) {
-		debug("%s: unexpected GPIOBASE value\n", __func__);
+		debug("%s: unexpected BASE value\n", __func__);
 		return -ENODEV;
 	}
 
@@ -135,7 +146,138 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
 	 * at the offset that we just read. Bit 0 indicates that it's
 	 * an I/O address, not a memory address, so mask that off.
 	 */
-	gpiobase = tmplong & 0xfffe;
+	return tmplong & 0xfffc;
+}
+
+int gpio_ich6_pinctrl_init(void)
+{
+	int pin_node;
+	int node;
+	u32 iobase;
+	u32 gpiobase;
+
+	/*
+	 * 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
+	 */
+	iobase = gpio_ich6_get_base(PCI_CFG_IOBASE);
+	if (iobase < 0) {
+		debug("%s: invalid IOBASE address (%08x)\n", __func__, iobase);
+		return -EINVAL;
+	}
+
+	gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
+	if (iobase < 0) {
+		debug("%s: invalid IOBASE address (%08x)\n", __func__, iobase);
+		return -EINVAL;
+	}
+
+	/* This is not an error to not have a pinctrl node */
+	node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
+					     "intel,ich6-pinctrl");
+	if (node < 0)
+		return 0;
+
+	for (pin_node = fdt_first_subnode(gd->fdt_blob, node);
+	     pin_node > 0;
+	     pin_node = fdt_next_subnode(gd->fdt_blob, pin_node)) {
+		u32 gpio_offset[2] = { -1, -1 };
+		u32 pad_offset;
+		u32 tmplong;
+		const void *tmpnode;
+
+		/*
+		 * The offset for the same pin for the IOBASE and GPIOBASE are
+		 * different, so instead of maintaining a lookup table,
+		 * the device tree should provide directly the correct
+		 * value for both mapping.
+		 */
+		pad_offset = fdtdec_get_int(gd->fdt_blob, pin_node,
+					    "pad-offset", -1);
+		if (pad_offset == -1) {
+			debug("%s: Invalid register io offset %d\n",
+			      __func__, pad_offset);
+			return -EINVAL;
+		}
+
+		/*
+		 * GPIO node is not mandatory, so we only do the
+		 * pinmuxing if the node exist.
+		 */
+		fdtdec_get_int_array(gd->fdt_blob, pin_node,
+				     "gpio-offset", gpio_offset, 2);
+		if (gpio_offset[0] != -1) {
+			/* Do we want to force the GPIO mode? */
+			tmpnode = fdt_getprop(gd->fdt_blob, pin_node,
+					      "mode-gpio", NULL);
+			if (tmpnode)
+				__ich6_gpio_set_function(GPIO_USESEL_OFFSET
+							 (gpiobase) +
+							 gpio_offset[0],
+							 gpio_offset[1], 1);
+
+			tmplong =
+			    fdtdec_get_int(gd->fdt_blob, pin_node, "direction",
+					   -1);
+			if (tmplong != -1)
+				__ich6_gpio_set_direction(GPIO_IOSEL_OFFSET
+							  (gpiobase) +
+							  gpio_offset[0],
+							  gpio_offset[1],
+							  tmplong);
+
+			tmplong =
+			    fdtdec_get_int(gd->fdt_blob, pin_node,
+					   "output-value", -1);
+			if (tmplong != -1)
+				__ich6_gpio_set_value(GPIO_LVL_OFFSET(gpiobase)
+						      + gpio_offset[0],
+						      gpio_offset[1], tmplong);
+		}
+
+		/*
+		 * Do we need to set a specific function mode?
+		 * If someone put also 'mode-gpio', this option will
+		 * be just ignored by the controller
+		 */
+		tmplong =
+		    fdtdec_get_int(gd->fdt_blob, pin_node, "mode-func", -1);
+		if (tmplong != -1)
+			clrsetbits_le32(iobase + pad_offset, IOPAD_MODE_MASK,
+					tmplong);
+
+		/* Configure the pull-up/down if needed */
+		tmplong =
+		    fdtdec_get_int(gd->fdt_blob, pin_node, "pull-assign", -1);
+		if (tmplong != -1)
+			clrsetbits_le32(iobase + pad_offset,
+					IOPAD_PULL_ASSIGN_MASK <<
+					IOPAD_PULL_ASSIGN_SHIFT,
+					tmplong << IOPAD_PULL_ASSIGN_SHIFT);
+
+		tmplong =
+		    fdtdec_get_int(gd->fdt_blob, pin_node, "pull-strength", -1);
+		if (tmplong != -1)
+			clrsetbits_le32(iobase + pad_offset,
+					IOPAD_PULL_STRENGTH_MASK <<
+					IOPAD_PULL_STRENGTH_SHIFT,
+					tmplong << IOPAD_PULL_STRENGTH_SHIFT);
+
+		debug("%s: pad cfg [0x%x]: %08x\n", __func__, pad_offset,
+		      readl(iobase + pad_offset));
+	}
+
+	return 0;
+}
+
+static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ich6_bank_platdata *plat = dev_get_platdata(dev);
+	u16 gpiobase;
+	int offset;
+
+	gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
 	offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
 	if (offset == -1) {
 		debug("%s: Invalid register offset %d\n", __func__, offset);
@@ -189,33 +331,56 @@ static int ich6_gpio_request(struct udevice *dev, unsigned offset,
 	return 0;
 }
 
-static int ich6_gpio_direction_input(struct udevice *dev, unsigned offset)
+static int __ich6_gpio_set_function(uint16_t base, unsigned offset, int func)
 {
-	struct ich6_bank_priv *bank = dev_get_priv(dev);
 	u32 tmplong;
 
-	tmplong = inl(bank->io_sel);
-	tmplong |= (1UL << offset);
-	outl(bank->io_sel, tmplong);
+	if (func) {
+		tmplong = inl(base);
+		tmplong |= (1UL << offset);
+		outl(tmplong, base);
+	} else {
+		tmplong = inl(base);
+		tmplong &= ~(1UL << offset);
+		outl(tmplong, base);
+	}
+
 	return 0;
 }
 
-static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
-				       int value)
+static int __ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir)
 {
-	struct ich6_bank_priv *bank = dev_get_priv(dev);
 	u32 tmplong;
 
-	gpio_set_value(offset, value);
+	if (!dir) {
+		tmplong = inl(base);
+		tmplong |= (1UL << offset);
+		outl(tmplong, base);
+	} else {
+		tmplong = inl(base);
+		tmplong &= ~(1UL << offset);
+		outl(tmplong, base);
+	}
 
-	tmplong = inl(bank->io_sel);
-	tmplong &= ~(1UL << offset);
-	outl(bank->io_sel, tmplong);
 	return 0;
 }
 
-static int ich6_gpio_get_value(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(inl(bank->io_sel), offset, 0);
+}
+
+static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
+		int value)
+{
+	struct ich6_bank_priv *bank = dev_get_priv(dev);
+
+	return __ich6_gpio_set_direction(inl(bank->io_sel), offset, 1);
+}
 
+static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
 {
 	struct ich6_bank_priv *bank = dev_get_priv(dev);
 	u32 tmplong;
@@ -226,21 +391,26 @@ 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)
+static int __ich6_gpio_set_value(uint16_t base, unsigned offset, int value)
 {
-	struct ich6_bank_priv *bank = dev_get_priv(dev);
 	u32 tmplong;
-
-	tmplong = inl(bank->lvl);
+	tmplong = inl(base);
 	if (value)
 		tmplong |= (1UL << offset);
 	else
 		tmplong &= ~(1UL << offset);
-	outl(bank->lvl, tmplong);
+	outl(tmplong, base);
+
 	return 0;
 }
 
+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);
diff --git a/include/dt-bindings/gpio/gpio.h b/include/dt-bindings/gpio/gpio.h
index e6b1e0a..49d437c 100644
--- a/include/dt-bindings/gpio/gpio.h
+++ b/include/dt-bindings/gpio/gpio.h
@@ -12,4 +12,24 @@
 #define GPIO_ACTIVE_HIGH 0
 #define GPIO_ACTIVE_LOW 1
 
+#define GPIO_MODE_NATIVE	0
+#define GPIO_MODE_GPIO		1
+
+#define GPIO_MODE_FUNC0	0
+#define GPIO_MODE_FUNC1	1
+#define GPIO_MODE_FUNC2	2
+#define GPIO_MODE_FUNC4	4
+#define GPIO_MODE_FUNC5	5
+#define GPIO_MODE_FUNC6	6
+
+#define PIN_INPUT		0
+#define PIN_OUTPUT		1
+
+#define PIN_INPUT_NOPULL	0
+#define PIN_INPUT_PULLUP	1
+#define PIN_INPUT_PULLDOWN	2
+
+#define PULL_STR_2K		0
+#define PULL_STR_20K	2
+
 #endif
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 4/4] x86: minnowmax: initialize the pin-muxing from device tree
  2015-04-23 16:16 [U-Boot] [PATCH 0/4] x86: support of pin-muxing from device tree Gabriel Huau
                   ` (2 preceding siblings ...)
  2015-04-23 16:16 ` [U-Boot] [PATCH 3/4] x86: gpio: add pinctrl support from " Gabriel Huau
@ 2015-04-23 16:16 ` Gabriel Huau
  2015-04-24  3:37   ` Simon Glass
                     ` (3 more replies)
  2015-04-23 16:45 ` [U-Boot] unassigned-patches/138: [PATCH 3/4] x86: gpio: add pinctrl support from the " u-boot at bugs.denx.de
                   ` (9 subsequent siblings)
  13 siblings, 4 replies; 61+ messages in thread
From: Gabriel Huau @ 2015-04-23 16:16 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
---
 board/intel/minnowmax/minnowmax.c | 9 +++++++++
 include/configs/minnowmax.h       | 1 +
 2 files changed, 10 insertions(+)

diff --git a/board/intel/minnowmax/minnowmax.c b/board/intel/minnowmax/minnowmax.c
index 6e82b16..60dd2bb 100644
--- a/board/intel/minnowmax/minnowmax.c
+++ b/board/intel/minnowmax/minnowmax.c
@@ -7,6 +7,7 @@
 #include <common.h>
 #include <asm/ibmpc.h>
 #include <asm/pnp_def.h>
+#include <asm/gpio.h>
 #include <netdev.h>
 #include <smsc_lpc47m.h>
 
@@ -14,6 +15,14 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+int arch_early_init_r(void)
+{
+	/* do the pin-muxing */
+	gpio_ich6_pinctrl_init();
+
+	return 0;
+}
+
 int board_early_init_f(void)
 {
 	lpc47m_enable_serial(SERIAL_DEV, UART0_BASE);
diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h
index 823e051..3c7b266 100644
--- a/include/configs/minnowmax.h
+++ b/include/configs/minnowmax.h
@@ -15,6 +15,7 @@
 
 #define CONFIG_SYS_MONITOR_LEN		(1 << 20)
 #define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_ARCH_EARLY_INIT_R
 
 #define CONFIG_NR_DRAM_BANKS		1
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [U-Boot] unassigned-patches/139: [PATCH 1/4] x86: baytrail: fix the GPIOBASE address
  2015-04-23 16:16 [U-Boot] [PATCH 0/4] x86: support of pin-muxing from device tree Gabriel Huau
                   ` (5 preceding siblings ...)
  2015-04-23 16:45 ` [U-Boot] unassigned-patches/140: [PATCH 2/4] x86: minnowmax: add GPIO banks in " u-boot at bugs.denx.de
@ 2015-04-23 16:45 ` u-boot at bugs.denx.de
  2015-04-23 16:55 ` [U-Boot] unassigned-patches/142: [PATCH 0/4] x86: support of pin-muxing from device tree u-boot at bugs.denx.de
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 61+ messages in thread
From: u-boot at bugs.denx.de @ 2015-04-23 16:45 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>

---
Added to GNATS database as unassigned-patches/139
>Responsible:    patch-coord
>Message-Id:     <1429805775-1809-2-git-send-email-contact@huau-gabriel.fr>
>In-Reply-To:    <1429805775-1809-1-git-send-email-contact@huau-gabriel.fr>
>References:     <1429805775-1809-1-git-send-email-contact@huau-gabriel.fr>
>Patch-Date:     Thu Apr 23 18:16:12 +0200 2015
---
 arch/x86/include/asm/arch-baytrail/gpio.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/arch-baytrail/gpio.h b/arch/x86/include/asm/arch-baytrail/gpio.h
index ab4e059..4e8987c 100644
--- a/arch/x86/include/asm/arch-baytrail/gpio.h
+++ b/arch/x86/include/asm/arch-baytrail/gpio.h
@@ -8,6 +8,6 @@
 #define _X86_ARCH_GPIO_H_
 
 /* Where in config space is the register that points to the GPIO registers? */
-#define PCI_CFG_GPIOBASE 0x44
+#define PCI_CFG_GPIOBASE 0x48
 
 #endif /* _X86_ARCH_GPIO_H_ */
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [U-Boot] unassigned-patches/138: [PATCH 3/4] x86: gpio: add pinctrl support from the device tree
  2015-04-23 16:16 [U-Boot] [PATCH 0/4] x86: support of pin-muxing from device tree Gabriel Huau
                   ` (3 preceding siblings ...)
  2015-04-23 16:16 ` [U-Boot] [PATCH 4/4] x86: minnowmax: initialize the pin-muxing from " Gabriel Huau
@ 2015-04-23 16:45 ` u-boot at bugs.denx.de
  2015-04-23 16:45 ` [U-Boot] unassigned-patches/140: [PATCH 2/4] x86: minnowmax: add GPIO banks in " u-boot at bugs.denx.de
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 61+ messages in thread
From: u-boot at bugs.denx.de @ 2015-04-23 16:45 UTC (permalink / raw)
  To: u-boot

A set of properties has been defined for the device tree to select for
each pin the pull/func/default output configuration.

The offset for the PAD needs to be provided and if a GPIO needs to be
configured, his offset needs to be provided as well.

Here is an example:
pin_usb_host_en0 at 0 {
    gpio-offset = <0x80 8>;
    pad-offset = <0x260>;
    mode-gpio;
    output-value = <1>;
    direction = <PIN_OUTPUT>;
};

Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>

---
Added to GNATS database as unassigned-patches/138
>Responsible:    patch-coord
>Message-Id:     <1429805775-1809-4-git-send-email-contact@huau-gabriel.fr>
>In-Reply-To:    <1429805775-1809-1-git-send-email-contact@huau-gabriel.fr>
>References:     <1429805775-1809-1-git-send-email-contact@huau-gabriel.fr>
>Patch-Date:     Thu Apr 23 18:16:14 +0200 2015
---
 arch/x86/dts/minnowmax.dts                |  21 +++
 arch/x86/include/asm/arch-baytrail/gpio.h |   1 +
 arch/x86/include/asm/gpio.h               |   1 +
 drivers/gpio/intel_ich6_gpio.c            | 222 ++++++++++++++++++++++++++----
 include/dt-bindings/gpio/gpio.h           |  20 +++
 5 files changed, 239 insertions(+), 26 deletions(-)

diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
index c73e421..3936e21 100644
--- a/arch/x86/dts/minnowmax.dts
+++ b/arch/x86/dts/minnowmax.dts
@@ -6,6 +6,8 @@
 
 /dts-v1/;
 
+#include <dt-bindings/gpio/gpio.h>
+
 /include/ "skeleton.dtsi"
 /include/ "serial.dtsi"
 
@@ -21,6 +23,25 @@
 		silent_console = <0>;
 	};
 
+	pch_pinctrl {
+		compatible = "intel,ich6-pinctrl";
+		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 = <0x258>;
+			mode-gpio;
+			output-value = <1>;
+			direction = <PIN_OUTPUT>;
+		};
+	};
+
 	gpioa {
 		compatible = "intel,ich6-gpio";
 		u-boot,dm-pre-reloc;
diff --git a/arch/x86/include/asm/arch-baytrail/gpio.h b/arch/x86/include/asm/arch-baytrail/gpio.h
index 4e8987c..85a65a8 100644
--- a/arch/x86/include/asm/arch-baytrail/gpio.h
+++ b/arch/x86/include/asm/arch-baytrail/gpio.h
@@ -9,5 +9,6 @@
 
 /* Where in config space is the register that points to the GPIO registers? */
 #define PCI_CFG_GPIOBASE 0x48
+#define PCI_CFG_IOBASE   0x4c
 
 #endif /* _X86_ARCH_GPIO_H_ */
diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h
index 1099427..ed85b08 100644
--- a/arch/x86/include/asm/gpio.h
+++ b/arch/x86/include/asm/gpio.h
@@ -147,6 +147,7 @@ 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/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
index 7e679a0..a110d5b 100644
--- a/drivers/gpio/intel_ich6_gpio.c
+++ b/drivers/gpio/intel_ich6_gpio.c
@@ -44,21 +44,32 @@ struct ich6_bank_priv {
 	uint16_t 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_MASK		0x3
+#define IOPAD_PULL_ASSIGN_SHIFT		7
+#define IOPAD_PULL_STRENGTH_MASK	0x3
+#define IOPAD_PULL_STRENGTH_SHIFT	9
+
+static int __ich6_gpio_set_value(uint16_t base, unsigned offset, int value);
+static int __ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir);
+static int __ich6_gpio_set_function(uint16_t base, unsigned offset, int func);
+
 /* TODO: Move this to device tree, or platform data */
 void ich_gpio_set_gpio_map(const struct pch_gpio_map *map)
 {
 	gd->arch.gpio_map = map;
 }
 
-static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
+static int gpio_ich6_get_base(unsigned long base)
 {
-	struct ich6_bank_platdata *plat = dev_get_platdata(dev);
 	pci_dev_t pci_dev;			/* handle for 0:1f:0 */
 	u8 tmpbyte;
 	u16 tmpword;
 	u32 tmplong;
-	u16 gpiobase;
-	int offset;
 
 	/* Where should it be? */
 	pci_dev = PCI_BDF(0, 0x1f, 0);
@@ -123,9 +134,9 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
 	 * while on the Ivybridge the bit0 is used to indicate it is an
 	 * I/O space.
 	 */
-	tmplong = x86_pci_read_config32(pci_dev, PCI_CFG_GPIOBASE);
+	tmplong = x86_pci_read_config32(pci_dev, base);
 	if (tmplong == 0x00000000 || tmplong == 0xffffffff) {
-		debug("%s: unexpected GPIOBASE value\n", __func__);
+		debug("%s: unexpected BASE value\n", __func__);
 		return -ENODEV;
 	}
 
@@ -135,7 +146,138 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
 	 * at the offset that we just read. Bit 0 indicates that it's
 	 * an I/O address, not a memory address, so mask that off.
 	 */
-	gpiobase = tmplong & 0xfffe;
+	return tmplong & 0xfffc;
+}
+
+int gpio_ich6_pinctrl_init(void)
+{
+	int pin_node;
+	int node;
+	u32 iobase;
+	u32 gpiobase;
+
+	/*
+	 * 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
+	 */
+	iobase = gpio_ich6_get_base(PCI_CFG_IOBASE);
+	if (iobase < 0) {
+		debug("%s: invalid IOBASE address (%08x)\n", __func__, iobase);
+		return -EINVAL;
+	}
+
+	gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
+	if (iobase < 0) {
+		debug("%s: invalid IOBASE address (%08x)\n", __func__, iobase);
+		return -EINVAL;
+	}
+
+	/* This is not an error to not have a pinctrl node */
+	node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
+					     "intel,ich6-pinctrl");
+	if (node < 0)
+		return 0;
+
+	for (pin_node = fdt_first_subnode(gd->fdt_blob, node);
+	     pin_node > 0;
+	     pin_node = fdt_next_subnode(gd->fdt_blob, pin_node)) {
+		u32 gpio_offset[2] = { -1, -1 };
+		u32 pad_offset;
+		u32 tmplong;
+		const void *tmpnode;
+
+		/*
+		 * The offset for the same pin for the IOBASE and GPIOBASE are
+		 * different, so instead of maintaining a lookup table,
+		 * the device tree should provide directly the correct
+		 * value for both mapping.
+		 */
+		pad_offset = fdtdec_get_int(gd->fdt_blob, pin_node,
+					    "pad-offset", -1);
+		if (pad_offset == -1) {
+			debug("%s: Invalid register io offset %d\n",
+			      __func__, pad_offset);
+			return -EINVAL;
+		}
+
+		/*
+		 * GPIO node is not mandatory, so we only do the
+		 * pinmuxing if the node exist.
+		 */
+		fdtdec_get_int_array(gd->fdt_blob, pin_node,
+				     "gpio-offset", gpio_offset, 2);
+		if (gpio_offset[0] != -1) {
+			/* Do we want to force the GPIO mode? */
+			tmpnode = fdt_getprop(gd->fdt_blob, pin_node,
+					      "mode-gpio", NULL);
+			if (tmpnode)
+				__ich6_gpio_set_function(GPIO_USESEL_OFFSET
+							 (gpiobase) +
+							 gpio_offset[0],
+							 gpio_offset[1], 1);
+
+			tmplong =
+			    fdtdec_get_int(gd->fdt_blob, pin_node, "direction",
+					   -1);
+			if (tmplong != -1)
+				__ich6_gpio_set_direction(GPIO_IOSEL_OFFSET
+							  (gpiobase) +
+							  gpio_offset[0],
+							  gpio_offset[1],
+							  tmplong);
+
+			tmplong =
+			    fdtdec_get_int(gd->fdt_blob, pin_node,
+					   "output-value", -1);
+			if (tmplong != -1)
+				__ich6_gpio_set_value(GPIO_LVL_OFFSET(gpiobase)
+						      + gpio_offset[0],
+						      gpio_offset[1], tmplong);
+		}
+
+		/*
+		 * Do we need to set a specific function mode?
+		 * If someone put also 'mode-gpio', this option will
+		 * be just ignored by the controller
+		 */
+		tmplong =
+		    fdtdec_get_int(gd->fdt_blob, pin_node, "mode-func", -1);
+		if (tmplong != -1)
+			clrsetbits_le32(iobase + pad_offset, IOPAD_MODE_MASK,
+					tmplong);
+
+		/* Configure the pull-up/down if needed */
+		tmplong =
+		    fdtdec_get_int(gd->fdt_blob, pin_node, "pull-assign", -1);
+		if (tmplong != -1)
+			clrsetbits_le32(iobase + pad_offset,
+					IOPAD_PULL_ASSIGN_MASK <<
+					IOPAD_PULL_ASSIGN_SHIFT,
+					tmplong << IOPAD_PULL_ASSIGN_SHIFT);
+
+		tmplong =
+		    fdtdec_get_int(gd->fdt_blob, pin_node, "pull-strength", -1);
+		if (tmplong != -1)
+			clrsetbits_le32(iobase + pad_offset,
+					IOPAD_PULL_STRENGTH_MASK <<
+					IOPAD_PULL_STRENGTH_SHIFT,
+					tmplong << IOPAD_PULL_STRENGTH_SHIFT);
+
+		debug("%s: pad cfg [0x%x]: %08x\n", __func__, pad_offset,
+		      readl(iobase + pad_offset));
+	}
+
+	return 0;
+}
+
+static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ich6_bank_platdata *plat = dev_get_platdata(dev);
+	u16 gpiobase;
+	int offset;
+
+	gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
 	offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
 	if (offset == -1) {
 		debug("%s: Invalid register offset %d\n", __func__, offset);
@@ -189,33 +331,56 @@ static int ich6_gpio_request(struct udevice *dev, unsigned offset,
 	return 0;
 }
 
-static int ich6_gpio_direction_input(struct udevice *dev, unsigned offset)
+static int __ich6_gpio_set_function(uint16_t base, unsigned offset, int func)
 {
-	struct ich6_bank_priv *bank = dev_get_priv(dev);
 	u32 tmplong;
 
-	tmplong = inl(bank->io_sel);
-	tmplong |= (1UL << offset);
-	outl(bank->io_sel, tmplong);
+	if (func) {
+		tmplong = inl(base);
+		tmplong |= (1UL << offset);
+		outl(tmplong, base);
+	} else {
+		tmplong = inl(base);
+		tmplong &= ~(1UL << offset);
+		outl(tmplong, base);
+	}
+
 	return 0;
 }
 
-static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
-				       int value)
+static int __ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir)
 {
-	struct ich6_bank_priv *bank = dev_get_priv(dev);
 	u32 tmplong;
 
-	gpio_set_value(offset, value);
+	if (!dir) {
+		tmplong = inl(base);
+		tmplong |= (1UL << offset);
+		outl(tmplong, base);
+	} else {
+		tmplong = inl(base);
+		tmplong &= ~(1UL << offset);
+		outl(tmplong, base);
+	}
 
-	tmplong = inl(bank->io_sel);
-	tmplong &= ~(1UL << offset);
-	outl(bank->io_sel, tmplong);
 	return 0;
 }
 
-static int ich6_gpio_get_value(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(inl(bank->io_sel), offset, 0);
+}
+
+static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
+		int value)
+{
+	struct ich6_bank_priv *bank = dev_get_priv(dev);
+
+	return __ich6_gpio_set_direction(inl(bank->io_sel), offset, 1);
+}
 
+static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
 {
 	struct ich6_bank_priv *bank = dev_get_priv(dev);
 	u32 tmplong;
@@ -226,21 +391,26 @@ 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)
+static int __ich6_gpio_set_value(uint16_t base, unsigned offset, int value)
 {
-	struct ich6_bank_priv *bank = dev_get_priv(dev);
 	u32 tmplong;
-
-	tmplong = inl(bank->lvl);
+	tmplong = inl(base);
 	if (value)
 		tmplong |= (1UL << offset);
 	else
 		tmplong &= ~(1UL << offset);
-	outl(bank->lvl, tmplong);
+	outl(tmplong, base);
+
 	return 0;
 }
 
+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);
diff --git a/include/dt-bindings/gpio/gpio.h b/include/dt-bindings/gpio/gpio.h
index e6b1e0a..49d437c 100644
--- a/include/dt-bindings/gpio/gpio.h
+++ b/include/dt-bindings/gpio/gpio.h
@@ -12,4 +12,24 @@
 #define GPIO_ACTIVE_HIGH 0
 #define GPIO_ACTIVE_LOW 1
 
+#define GPIO_MODE_NATIVE	0
+#define GPIO_MODE_GPIO		1
+
+#define GPIO_MODE_FUNC0	0
+#define GPIO_MODE_FUNC1	1
+#define GPIO_MODE_FUNC2	2
+#define GPIO_MODE_FUNC4	4
+#define GPIO_MODE_FUNC5	5
+#define GPIO_MODE_FUNC6	6
+
+#define PIN_INPUT		0
+#define PIN_OUTPUT		1
+
+#define PIN_INPUT_NOPULL	0
+#define PIN_INPUT_PULLUP	1
+#define PIN_INPUT_PULLDOWN	2
+
+#define PULL_STR_2K		0
+#define PULL_STR_20K	2
+
 #endif
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [U-Boot] unassigned-patches/140: [PATCH 2/4] x86: minnowmax: add GPIO banks in the device tree
  2015-04-23 16:16 [U-Boot] [PATCH 0/4] x86: support of pin-muxing from device tree Gabriel Huau
                   ` (4 preceding siblings ...)
  2015-04-23 16:45 ` [U-Boot] unassigned-patches/138: [PATCH 3/4] x86: gpio: add pinctrl support from the " u-boot at bugs.denx.de
@ 2015-04-23 16:45 ` u-boot at bugs.denx.de
  2015-04-23 16:45 ` [U-Boot] unassigned-patches/139: [PATCH 1/4] x86: baytrail: fix the GPIOBASE address u-boot at bugs.denx.de
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 61+ messages in thread
From: u-boot at bugs.denx.de @ 2015-04-23 16:45 UTC (permalink / raw)
  To: u-boot

There is 6 banks:
    4 banks for CORE: available in S0 mode
    2 banks for SUS (Suspend): available in S0-S5 mode

Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>

---
Added to GNATS database as unassigned-patches/140
>Responsible:    patch-coord
>Message-Id:     <1429805775-1809-3-git-send-email-contact@huau-gabriel.fr>
>In-Reply-To:    <1429805775-1809-1-git-send-email-contact@huau-gabriel.fr>
>References:     <1429805775-1809-1-git-send-email-contact@huau-gabriel.fr>
>Patch-Date:     Thu Apr 23 18:16:13 +0200 2015
---
 arch/x86/dts/minnowmax.dts | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
index 8f34369..c73e421 100644
--- a/arch/x86/dts/minnowmax.dts
+++ b/arch/x86/dts/minnowmax.dts
@@ -21,6 +21,48 @@
 		silent_console = <0>;
 	};
 
+	gpioa {
+		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
+		reg = <0 0x20>;
+		bank-name = "A";
+	};
+
+	gpiob {
+		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
+		reg = <0x20 0x20>;
+		bank-name = "B";
+	};
+
+	gpioc {
+		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
+		reg = <0x40 0x20>;
+		bank-name = "C";
+	};
+
+	gpiod {
+		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
+		reg = <0x60 0x20>;
+		bank-name = "D";
+	};
+
+	gpioe {
+		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
+		reg = <0x80 0x20>;
+		bank-name = "E";
+	};
+
+	gpiof {
+		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
+		reg = <0xA0 0x20>;
+		bank-name = "F";
+	};
+
 	chosen {
 		stdout-path = "/serial";
 	};
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [U-Boot] unassigned-patches/142: [PATCH 0/4] x86: support of pin-muxing from device tree
  2015-04-23 16:16 [U-Boot] [PATCH 0/4] x86: support of pin-muxing from device tree Gabriel Huau
                   ` (6 preceding siblings ...)
  2015-04-23 16:45 ` [U-Boot] unassigned-patches/139: [PATCH 1/4] x86: baytrail: fix the GPIOBASE address u-boot at bugs.denx.de
@ 2015-04-23 16:55 ` u-boot at bugs.denx.de
  2015-04-23 16:55 ` [U-Boot] unassigned-patches/143: [PATCH 4/4] x86: minnowmax: initialize the " u-boot at bugs.denx.de
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 61+ messages in thread
From: u-boot at bugs.denx.de @ 2015-04-23 16:55 UTC (permalink / raw)
  To: u-boot

This serie of patches adds the support of pin-muxing from the device tree through
different properties. I have put two example to enable the USB Host on the
minnowboard max.

The support of the call to 'setup_pch_gpios' is still supported and
only the minnowboard has been tested with the device tree implementation.

Because the GPIO and IO base register ares different, I have also defined
some proxy function to set the function/value and direction of the GPIO as
the GPIO register can override some registers in the IO.

Gabriel Huau (4):
  x86: baytrail: fix the GPIOBASE address
  x86: minnowmax: add GPIO banks in the device tree
  x86: gpio: add pinctrl support from the device tree
  x86: minnowmax: initialize the pin-muxing from device tree

 arch/x86/dts/minnowmax.dts                |  63 +++++++++
 arch/x86/include/asm/arch-baytrail/gpio.h |   3 +-
 arch/x86/include/asm/gpio.h               |   1 +
 board/intel/minnowmax/minnowmax.c         |   9 ++
 drivers/gpio/intel_ich6_gpio.c            | 222 ++++++++++++++++++++++++++----
 include/configs/minnowmax.h               |   1 +
 include/dt-bindings/gpio/gpio.h           |  20 +++
 7 files changed, 292 insertions(+), 27 deletions(-)

--
2.1.4

---
Added to GNATS database as unassigned-patches/142
>Responsible:    patch-coord
>Message-Id:     <1429805775-1809-1-git-send-email-contact@huau-gabriel.fr>
>In-Reply-To:    
>References:     
>Patch-Date:     Thu Apr 23 18:16:11 +0200 2015

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] unassigned-patches/143: [PATCH 4/4] x86: minnowmax: initialize the pin-muxing from device tree
  2015-04-23 16:16 [U-Boot] [PATCH 0/4] x86: support of pin-muxing from device tree Gabriel Huau
                   ` (7 preceding siblings ...)
  2015-04-23 16:55 ` [U-Boot] unassigned-patches/142: [PATCH 0/4] x86: support of pin-muxing from device tree u-boot at bugs.denx.de
@ 2015-04-23 16:55 ` u-boot at bugs.denx.de
  2015-04-24  3:23 ` [U-Boot] [PATCH 0/4] x86: support of " Bin Meng
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 61+ messages in thread
From: u-boot at bugs.denx.de @ 2015-04-23 16:55 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>

---
Added to GNATS database as unassigned-patches/143
>Responsible:    patch-coord
>Message-Id:     <1429805775-1809-5-git-send-email-contact@huau-gabriel.fr>
>In-Reply-To:    <1429805775-1809-1-git-send-email-contact@huau-gabriel.fr>
>References:     <1429805775-1809-1-git-send-email-contact@huau-gabriel.fr>
>Patch-Date:     Thu Apr 23 18:16:15 +0200 2015
---
 board/intel/minnowmax/minnowmax.c | 9 +++++++++
 include/configs/minnowmax.h       | 1 +
 2 files changed, 10 insertions(+)

diff --git a/board/intel/minnowmax/minnowmax.c b/board/intel/minnowmax/minnowmax.c
index 6e82b16..60dd2bb 100644
--- a/board/intel/minnowmax/minnowmax.c
+++ b/board/intel/minnowmax/minnowmax.c
@@ -7,6 +7,7 @@
 #include <common.h>
 #include <asm/ibmpc.h>
 #include <asm/pnp_def.h>
+#include <asm/gpio.h>
 #include <netdev.h>
 #include <smsc_lpc47m.h>
 
@@ -14,6 +15,14 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+int arch_early_init_r(void)
+{
+	/* do the pin-muxing */
+	gpio_ich6_pinctrl_init();
+
+	return 0;
+}
+
 int board_early_init_f(void)
 {
 	lpc47m_enable_serial(SERIAL_DEV, UART0_BASE);
diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h
index 823e051..3c7b266 100644
--- a/include/configs/minnowmax.h
+++ b/include/configs/minnowmax.h
@@ -15,6 +15,7 @@
 
 #define CONFIG_SYS_MONITOR_LEN		(1 << 20)
 #define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_ARCH_EARLY_INIT_R
 
 #define CONFIG_NR_DRAM_BANKS		1
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 1/4] x86: baytrail: fix the GPIOBASE address
  2015-04-23 16:16 ` [U-Boot] [PATCH 1/4] x86: baytrail: fix the GPIOBASE address Gabriel Huau
@ 2015-04-24  1:40   ` Bin Meng
  2015-04-24  3:25     ` Simon Glass
  2015-04-25 20:14   ` [U-Boot] [PATCH 1/5 v2] " Gabriel Huau
  2015-04-25 20:16   ` [U-Boot] [PATCH 1/4 v3] " Gabriel Huau
  2 siblings, 1 reply; 61+ messages in thread
From: Bin Meng @ 2015-04-24  1:40 UTC (permalink / raw)
  To: u-boot

On Fri, Apr 24, 2015 at 12:16 AM, Gabriel Huau <contact@huau-gabriel.fr> wrote:
> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
> ---
>  arch/x86/include/asm/arch-baytrail/gpio.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/x86/include/asm/arch-baytrail/gpio.h b/arch/x86/include/asm/arch-baytrail/gpio.h
> index ab4e059..4e8987c 100644
> --- a/arch/x86/include/asm/arch-baytrail/gpio.h
> +++ b/arch/x86/include/asm/arch-baytrail/gpio.h
> @@ -8,6 +8,6 @@
>  #define _X86_ARCH_GPIO_H_
>
>  /* Where in config space is the register that points to the GPIO registers? */
> -#define PCI_CFG_GPIOBASE 0x44
> +#define PCI_CFG_GPIOBASE 0x48
>
>  #endif /* _X86_ARCH_GPIO_H_ */
> --

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 2/4] x86: minnowmax: add GPIO banks in the device tree
  2015-04-23 16:16 ` [U-Boot] [PATCH 2/4] x86: minnowmax: add GPIO banks in the device tree Gabriel Huau
@ 2015-04-24  2:03   ` Bin Meng
  2015-04-24  3:26   ` Simon Glass
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 61+ messages in thread
From: Bin Meng @ 2015-04-24  2:03 UTC (permalink / raw)
  To: u-boot

Hi Gabriel,

On Fri, Apr 24, 2015 at 12:16 AM, Gabriel Huau <contact@huau-gabriel.fr> wrote:
> There is 6 banks:

There are

>     4 banks for CORE: available in S0 mode
>     2 banks for SUS (Suspend): available in S0-S5 mode
>
> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
> ---
>  arch/x86/dts/minnowmax.dts | 42 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 42 insertions(+)
>
> diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
> index 8f34369..c73e421 100644
> --- a/arch/x86/dts/minnowmax.dts
> +++ b/arch/x86/dts/minnowmax.dts
> @@ -21,6 +21,48 @@
>                 silent_console = <0>;
>         };
>
> +       gpioa {
> +               compatible = "intel,ich6-gpio";
> +               u-boot,dm-pre-reloc;
> +               reg = <0 0x20>;
> +               bank-name = "A";
> +       };
> +
> +       gpiob {
> +               compatible = "intel,ich6-gpio";
> +               u-boot,dm-pre-reloc;
> +               reg = <0x20 0x20>;
> +               bank-name = "B";
> +       };
> +
> +       gpioc {
> +               compatible = "intel,ich6-gpio";
> +               u-boot,dm-pre-reloc;
> +               reg = <0x40 0x20>;
> +               bank-name = "C";
> +       };
> +
> +       gpiod {
> +               compatible = "intel,ich6-gpio";
> +               u-boot,dm-pre-reloc;
> +               reg = <0x60 0x20>;
> +               bank-name = "D";
> +       };
> +
> +       gpioe {
> +               compatible = "intel,ich6-gpio";
> +               u-boot,dm-pre-reloc;
> +               reg = <0x80 0x20>;
> +               bank-name = "E";
> +       };
> +
> +       gpiof {
> +               compatible = "intel,ich6-gpio";
> +               u-boot,dm-pre-reloc;
> +               reg = <0xA0 0x20>;
> +               bank-name = "F";
> +       };
> +
>         chosen {
>                 stdout-path = "/serial";
>         };
> --

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 3/4] x86: gpio: add pinctrl support from the device tree
  2015-04-23 16:16 ` [U-Boot] [PATCH 3/4] x86: gpio: add pinctrl support from " Gabriel Huau
@ 2015-04-24  3:14   ` Bin Meng
  2015-04-24 14:32     ` Gabriel Huau
  2015-04-24  3:35   ` Simon Glass
                     ` (4 subsequent siblings)
  5 siblings, 1 reply; 61+ messages in thread
From: Bin Meng @ 2015-04-24  3:14 UTC (permalink / raw)
  To: u-boot

Hi Gabriel,

On Fri, Apr 24, 2015 at 12:16 AM, Gabriel Huau <contact@huau-gabriel.fr> wrote:
> A set of properties has been defined for the device tree to select for
> each pin the pull/func/default output configuration.
>
> The offset for the PAD needs to be provided and if a GPIO needs to be
> configured, his offset needs to be provided as well.
>
> Here is an example:
> pin_usb_host_en0 at 0 {
>     gpio-offset = <0x80 8>;
>     pad-offset = <0x260>;
>     mode-gpio;
>     output-value = <1>;
>     direction = <PIN_OUTPUT>;
> };
>
> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
> ---
>  arch/x86/dts/minnowmax.dts                |  21 +++
>  arch/x86/include/asm/arch-baytrail/gpio.h |   1 +
>  arch/x86/include/asm/gpio.h               |   1 +
>  drivers/gpio/intel_ich6_gpio.c            | 222 ++++++++++++++++++++++++++----
>  include/dt-bindings/gpio/gpio.h           |  20 +++
>  5 files changed, 239 insertions(+), 26 deletions(-)
>
> diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
> index c73e421..3936e21 100644
> --- a/arch/x86/dts/minnowmax.dts
> +++ b/arch/x86/dts/minnowmax.dts
> @@ -6,6 +6,8 @@
>
>  /dts-v1/;
>
> +#include <dt-bindings/gpio/gpio.h>
> +
>  /include/ "skeleton.dtsi"
>  /include/ "serial.dtsi"
>
> @@ -21,6 +23,25 @@
>                 silent_console = <0>;
>         };
>
> +       pch_pinctrl {
> +               compatible = "intel,ich6-pinctrl";

I guess the prefix 'ich6' is debatable.

> +               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 = <0x258>;
> +                       mode-gpio;
> +                       output-value = <1>;
> +                       direction = <PIN_OUTPUT>;
> +               };
> +       };
> +
>         gpioa {
>                 compatible = "intel,ich6-gpio";
>                 u-boot,dm-pre-reloc;
> diff --git a/arch/x86/include/asm/arch-baytrail/gpio.h b/arch/x86/include/asm/arch-baytrail/gpio.h
> index 4e8987c..85a65a8 100644
> --- a/arch/x86/include/asm/arch-baytrail/gpio.h
> +++ b/arch/x86/include/asm/arch-baytrail/gpio.h
> @@ -9,5 +9,6 @@
>
>  /* Where in config space is the register that points to the GPIO registers? */
>  #define PCI_CFG_GPIOBASE 0x48
> +#define PCI_CFG_IOBASE   0x4c
>
>  #endif /* _X86_ARCH_GPIO_H_ */
> diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h
> index 1099427..ed85b08 100644
> --- a/arch/x86/include/asm/gpio.h
> +++ b/arch/x86/include/asm/gpio.h
> @@ -147,6 +147,7 @@ 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/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
> index 7e679a0..a110d5b 100644
> --- a/drivers/gpio/intel_ich6_gpio.c
> +++ b/drivers/gpio/intel_ich6_gpio.c
> @@ -44,21 +44,32 @@ struct ich6_bank_priv {
>         uint16_t 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_MASK         0x3
> +#define IOPAD_PULL_ASSIGN_SHIFT                7
> +#define IOPAD_PULL_STRENGTH_MASK       0x3
> +#define IOPAD_PULL_STRENGTH_SHIFT      9
> +
> +static int __ich6_gpio_set_value(uint16_t base, unsigned offset, int value);
> +static int __ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir);
> +static int __ich6_gpio_set_function(uint16_t base, unsigned offset, int func);
> +
>  /* TODO: Move this to device tree, or platform data */
>  void ich_gpio_set_gpio_map(const struct pch_gpio_map *map)
>  {
>         gd->arch.gpio_map = map;
>  }
>
> -static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
> +static int gpio_ich6_get_base(unsigned long base)
>  {
> -       struct ich6_bank_platdata *plat = dev_get_platdata(dev);
>         pci_dev_t pci_dev;                      /* handle for 0:1f:0 */
>         u8 tmpbyte;
>         u16 tmpword;
>         u32 tmplong;
> -       u16 gpiobase;
> -       int offset;
>
>         /* Where should it be? */
>         pci_dev = PCI_BDF(0, 0x1f, 0);
> @@ -123,9 +134,9 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>          * while on the Ivybridge the bit0 is used to indicate it is an
>          * I/O space.
>          */
> -       tmplong = x86_pci_read_config32(pci_dev, PCI_CFG_GPIOBASE);
> +       tmplong = x86_pci_read_config32(pci_dev, base);
>         if (tmplong == 0x00000000 || tmplong == 0xffffffff) {
> -               debug("%s: unexpected GPIOBASE value\n", __func__);
> +               debug("%s: unexpected BASE value\n", __func__);
>                 return -ENODEV;
>         }
>
> @@ -135,7 +146,138 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>          * at the offset that we just read. Bit 0 indicates that it's
>          * an I/O address, not a memory address, so mask that off.
>          */
> -       gpiobase = tmplong & 0xfffe;
> +       return tmplong & 0xfffc;
> +}
> +
> +int gpio_ich6_pinctrl_init(void)
> +{
> +       int pin_node;
> +       int node;
> +       u32 iobase;
> +       u32 gpiobase;
> +
> +       /*
> +        * 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
> +        */
> +       iobase = gpio_ich6_get_base(PCI_CFG_IOBASE);

I believe this breaks other x86 boards as PCI_CFG_IOBASE is baytrail-specific.

> +       if (iobase < 0) {
> +               debug("%s: invalid IOBASE address (%08x)\n", __func__, iobase);
> +               return -EINVAL;
> +       }
> +
> +       gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
> +       if (iobase < 0) {
> +               debug("%s: invalid IOBASE address (%08x)\n", __func__, iobase);
> +               return -EINVAL;
> +       }
> +
> +       /* This is not an error to not have a pinctrl node */
> +       node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
> +                                            "intel,ich6-pinctrl");
> +       if (node < 0)
> +               return 0;
> +
> +       for (pin_node = fdt_first_subnode(gd->fdt_blob, node);
> +            pin_node > 0;
> +            pin_node = fdt_next_subnode(gd->fdt_blob, pin_node)) {
> +               u32 gpio_offset[2] = { -1, -1 };
> +               u32 pad_offset;
> +               u32 tmplong;
> +               const void *tmpnode;
> +
> +               /*
> +                * The offset for the same pin for the IOBASE and GPIOBASE are
> +                * different, so instead of maintaining a lookup table,
> +                * the device tree should provide directly the correct
> +                * value for both mapping.
> +                */
> +               pad_offset = fdtdec_get_int(gd->fdt_blob, pin_node,
> +                                           "pad-offset", -1);
> +               if (pad_offset == -1) {
> +                       debug("%s: Invalid register io offset %d\n",
> +                             __func__, pad_offset);
> +                       return -EINVAL;
> +               }
> +
> +               /*
> +                * GPIO node is not mandatory, so we only do the
> +                * pinmuxing if the node exist.
> +                */
> +               fdtdec_get_int_array(gd->fdt_blob, pin_node,
> +                                    "gpio-offset", gpio_offset, 2);
> +               if (gpio_offset[0] != -1) {
> +                       /* Do we want to force the GPIO mode? */
> +                       tmpnode = fdt_getprop(gd->fdt_blob, pin_node,
> +                                             "mode-gpio", NULL);
> +                       if (tmpnode)
> +                               __ich6_gpio_set_function(GPIO_USESEL_OFFSET
> +                                                        (gpiobase) +
> +                                                        gpio_offset[0],
> +                                                        gpio_offset[1], 1);
> +
> +                       tmplong =
> +                           fdtdec_get_int(gd->fdt_blob, pin_node, "direction",
> +                                          -1);
> +                       if (tmplong != -1)
> +                               __ich6_gpio_set_direction(GPIO_IOSEL_OFFSET
> +                                                         (gpiobase) +
> +                                                         gpio_offset[0],
> +                                                         gpio_offset[1],
> +                                                         tmplong);
> +
> +                       tmplong =
> +                           fdtdec_get_int(gd->fdt_blob, pin_node,
> +                                          "output-value", -1);
> +                       if (tmplong != -1)
> +                               __ich6_gpio_set_value(GPIO_LVL_OFFSET(gpiobase)
> +                                                     + gpio_offset[0],
> +                                                     gpio_offset[1], tmplong);
> +               }
> +
> +               /*
> +                * Do we need to set a specific function mode?
> +                * If someone put also 'mode-gpio', this option will
> +                * be just ignored by the controller
> +                */
> +               tmplong =
> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "mode-func", -1);
> +               if (tmplong != -1)
> +                       clrsetbits_le32(iobase + pad_offset, IOPAD_MODE_MASK,
> +                                       tmplong);
> +
> +               /* Configure the pull-up/down if needed */
> +               tmplong =
> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "pull-assign", -1);
> +               if (tmplong != -1)
> +                       clrsetbits_le32(iobase + pad_offset,
> +                                       IOPAD_PULL_ASSIGN_MASK <<
> +                                       IOPAD_PULL_ASSIGN_SHIFT,
> +                                       tmplong << IOPAD_PULL_ASSIGN_SHIFT);
> +
> +               tmplong =
> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "pull-strength", -1);
> +               if (tmplong != -1)
> +                       clrsetbits_le32(iobase + pad_offset,
> +                                       IOPAD_PULL_STRENGTH_MASK <<
> +                                       IOPAD_PULL_STRENGTH_SHIFT,
> +                                       tmplong << IOPAD_PULL_STRENGTH_SHIFT);
> +
> +               debug("%s: pad cfg [0x%x]: %08x\n", __func__, pad_offset,
> +                     readl(iobase + pad_offset));
> +       }
> +
> +       return 0;
> +}
> +
> +static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
> +{
> +       struct ich6_bank_platdata *plat = dev_get_platdata(dev);
> +       u16 gpiobase;
> +       int offset;
> +
> +       gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
>         offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
>         if (offset == -1) {
>                 debug("%s: Invalid register offset %d\n", __func__, offset);
> @@ -189,33 +331,56 @@ static int ich6_gpio_request(struct udevice *dev, unsigned offset,
>         return 0;
>  }
>
> -static int ich6_gpio_direction_input(struct udevice *dev, unsigned offset)
> +static int __ich6_gpio_set_function(uint16_t base, unsigned offset, int func)
>  {
> -       struct ich6_bank_priv *bank = dev_get_priv(dev);
>         u32 tmplong;
>
> -       tmplong = inl(bank->io_sel);
> -       tmplong |= (1UL << offset);
> -       outl(bank->io_sel, tmplong);
> +       if (func) {
> +               tmplong = inl(base);
> +               tmplong |= (1UL << offset);
> +               outl(tmplong, base);
> +       } else {
> +               tmplong = inl(base);
> +               tmplong &= ~(1UL << offset);
> +               outl(tmplong, base);
> +       }
> +
>         return 0;
>  }
>
> -static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
> -                                      int value)
> +static int __ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir)
>  {
> -       struct ich6_bank_priv *bank = dev_get_priv(dev);
>         u32 tmplong;
>
> -       gpio_set_value(offset, value);
> +       if (!dir) {
> +               tmplong = inl(base);
> +               tmplong |= (1UL << offset);
> +               outl(tmplong, base);
> +       } else {
> +               tmplong = inl(base);
> +               tmplong &= ~(1UL << offset);
> +               outl(tmplong, base);
> +       }
>
> -       tmplong = inl(bank->io_sel);
> -       tmplong &= ~(1UL << offset);
> -       outl(bank->io_sel, tmplong);
>         return 0;
>  }
>
> -static int ich6_gpio_get_value(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(inl(bank->io_sel), offset, 0);
> +}
> +
> +static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
> +               int value)
> +{
> +       struct ich6_bank_priv *bank = dev_get_priv(dev);
> +
> +       return __ich6_gpio_set_direction(inl(bank->io_sel), offset, 1);
> +}
>
> +static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
>  {
>         struct ich6_bank_priv *bank = dev_get_priv(dev);
>         u32 tmplong;
> @@ -226,21 +391,26 @@ 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)
> +static int __ich6_gpio_set_value(uint16_t base, unsigned offset, int value)
>  {
> -       struct ich6_bank_priv *bank = dev_get_priv(dev);
>         u32 tmplong;
> -
> -       tmplong = inl(bank->lvl);
> +       tmplong = inl(base);
>         if (value)
>                 tmplong |= (1UL << offset);
>         else
>                 tmplong &= ~(1UL << offset);
> -       outl(bank->lvl, tmplong);
> +       outl(tmplong, base);
> +
>         return 0;
>  }
>
> +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);
> diff --git a/include/dt-bindings/gpio/gpio.h b/include/dt-bindings/gpio/gpio.h
> index e6b1e0a..49d437c 100644
> --- a/include/dt-bindings/gpio/gpio.h
> +++ b/include/dt-bindings/gpio/gpio.h
> @@ -12,4 +12,24 @@
>  #define GPIO_ACTIVE_HIGH 0
>  #define GPIO_ACTIVE_LOW 1
>
> +#define GPIO_MODE_NATIVE       0
> +#define GPIO_MODE_GPIO         1
> +
> +#define GPIO_MODE_FUNC0        0
> +#define GPIO_MODE_FUNC1        1
> +#define GPIO_MODE_FUNC2        2
> +#define GPIO_MODE_FUNC4        4
> +#define GPIO_MODE_FUNC5        5
> +#define GPIO_MODE_FUNC6        6
> +
> +#define PIN_INPUT              0
> +#define PIN_OUTPUT             1
> +
> +#define PIN_INPUT_NOPULL       0
> +#define PIN_INPUT_PULLUP       1
> +#define PIN_INPUT_PULLDOWN     2
> +
> +#define PULL_STR_2K            0
> +#define PULL_STR_20K   2
> +
>  #endif
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 0/4] x86: support of pin-muxing from device tree
  2015-04-23 16:16 [U-Boot] [PATCH 0/4] x86: support of pin-muxing from device tree Gabriel Huau
                   ` (8 preceding siblings ...)
  2015-04-23 16:55 ` [U-Boot] unassigned-patches/143: [PATCH 4/4] x86: minnowmax: initialize the " u-boot at bugs.denx.de
@ 2015-04-24  3:23 ` Bin Meng
  2015-04-24 14:40   ` Gabriel Huau
  2015-04-24 17:55   ` [U-Boot] unassigned-patches/151: " u-boot at bugs.denx.de
  2015-04-24  5:05 ` [U-Boot] unassigned-patches/148: " u-boot at bugs.denx.de
                   ` (3 subsequent siblings)
  13 siblings, 2 replies; 61+ messages in thread
From: Bin Meng @ 2015-04-24  3:23 UTC (permalink / raw)
  To: u-boot

Hi Gabriel,

On Fri, Apr 24, 2015 at 12:16 AM, Gabriel Huau <contact@huau-gabriel.fr> wrote:
> This serie of patches adds the support of pin-muxing from the device tree through
> different properties. I have put two example to enable the USB Host on the
> minnowboard max.
>
> The support of the call to 'setup_pch_gpios' is still supported and
> only the minnowboard has been tested with the device tree implementation.
>
> Because the GPIO and IO base register ares different, I have also defined
> some proxy function to set the function/value and direction of the GPIO as
> the GPIO register can override some registers in the IO.
>
> Gabriel Huau (4):
>   x86: baytrail: fix the GPIOBASE address
>   x86: minnowmax: add GPIO banks in the device tree
>   x86: gpio: add pinctrl support from the device tree
>   x86: minnowmax: initialize the pin-muxing from device tree
>
>  arch/x86/dts/minnowmax.dts                |  63 +++++++++
>  arch/x86/include/asm/arch-baytrail/gpio.h |   3 +-
>  arch/x86/include/asm/gpio.h               |   1 +
>  board/intel/minnowmax/minnowmax.c         |   9 ++
>  drivers/gpio/intel_ich6_gpio.c            | 222 ++++++++++++++++++++++++++----
>  include/configs/minnowmax.h               |   1 +
>  include/dt-bindings/gpio/gpio.h           |  20 +++
>  7 files changed, 292 insertions(+), 27 deletions(-)
>
> --

Thanks for these patches! Just a general comment, you don't need send
emails to u-boot-patches at bugs.denx.de, and always include a simple
sentence in the commit message :)

Regards,
Bin

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 1/4] x86: baytrail: fix the GPIOBASE address
  2015-04-24  1:40   ` Bin Meng
@ 2015-04-24  3:25     ` Simon Glass
  0 siblings, 0 replies; 61+ messages in thread
From: Simon Glass @ 2015-04-24  3:25 UTC (permalink / raw)
  To: u-boot

Hi Gabriel,

On 23 April 2015 at 19:40, Bin Meng <bmeng.cn@gmail.com> wrote:
> On Fri, Apr 24, 2015 at 12:16 AM, Gabriel Huau <contact@huau-gabriel.fr> wrote:
>> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>

Can you please add a commit message?

>> ---
>>  arch/x86/include/asm/arch-baytrail/gpio.h | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/arch/x86/include/asm/arch-baytrail/gpio.h b/arch/x86/include/asm/arch-baytrail/gpio.h
>> index ab4e059..4e8987c 100644
>> --- a/arch/x86/include/asm/arch-baytrail/gpio.h
>> +++ b/arch/x86/include/asm/arch-baytrail/gpio.h
>> @@ -8,6 +8,6 @@
>>  #define _X86_ARCH_GPIO_H_
>>
>>  /* Where in config space is the register that points to the GPIO registers? */
>> -#define PCI_CFG_GPIOBASE 0x44
>> +#define PCI_CFG_GPIOBASE 0x48
>>
>>  #endif /* _X86_ARCH_GPIO_H_ */
>> --
>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

Regards,
Simon

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 2/4] x86: minnowmax: add GPIO banks in the device tree
  2015-04-23 16:16 ` [U-Boot] [PATCH 2/4] x86: minnowmax: add GPIO banks in the device tree Gabriel Huau
  2015-04-24  2:03   ` Bin Meng
@ 2015-04-24  3:26   ` Simon Glass
  2015-04-24  5:05   ` [U-Boot] unassigned-patches/146: " u-boot at bugs.denx.de
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 61+ messages in thread
From: Simon Glass @ 2015-04-24  3:26 UTC (permalink / raw)
  To: u-boot

On 23 April 2015 at 10:16, Gabriel Huau <contact@huau-gabriel.fr> wrote:
> There is 6 banks:
>     4 banks for CORE: available in S0 mode
>     2 banks for SUS (Suspend): available in S0-S5 mode
>
> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
> ---
>  arch/x86/dts/minnowmax.dts | 42 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 42 insertions(+)

Acked-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 3/4] x86: gpio: add pinctrl support from the device tree
  2015-04-23 16:16 ` [U-Boot] [PATCH 3/4] x86: gpio: add pinctrl support from " Gabriel Huau
  2015-04-24  3:14   ` Bin Meng
@ 2015-04-24  3:35   ` Simon Glass
  2015-04-24 14:37     ` Gabriel Huau
  2015-04-24 17:55     ` [U-Boot] unassigned-patches/150: " u-boot at bugs.denx.de
  2015-04-24  4:40   ` [U-Boot] unassigned-patches/144: " u-boot at bugs.denx.de
                     ` (3 subsequent siblings)
  5 siblings, 2 replies; 61+ messages in thread
From: Simon Glass @ 2015-04-24  3:35 UTC (permalink / raw)
  To: u-boot

Hi,

On 23 April 2015 at 10:16, Gabriel Huau <contact@huau-gabriel.fr> wrote:
> A set of properties has been defined for the device tree to select for
> each pin the pull/func/default output configuration.
>
> The offset for the PAD needs to be provided and if a GPIO needs to be
> configured, his offset needs to be provided as well.
>
> Here is an example:
> pin_usb_host_en0 at 0 {
>     gpio-offset = <0x80 8>;
>     pad-offset = <0x260>;
>     mode-gpio;
>     output-value = <1>;
>     direction = <PIN_OUTPUT>;
> };
>
> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
> ---
>  arch/x86/dts/minnowmax.dts                |  21 +++
>  arch/x86/include/asm/arch-baytrail/gpio.h |   1 +
>  arch/x86/include/asm/gpio.h               |   1 +
>  drivers/gpio/intel_ich6_gpio.c            | 222 ++++++++++++++++++++++++++----
>  include/dt-bindings/gpio/gpio.h           |  20 +++
>  5 files changed, 239 insertions(+), 26 deletions(-)
>
> diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
> index c73e421..3936e21 100644
> --- a/arch/x86/dts/minnowmax.dts
> +++ b/arch/x86/dts/minnowmax.dts
> @@ -6,6 +6,8 @@
>
>  /dts-v1/;
>
> +#include <dt-bindings/gpio/gpio.h>
> +
>  /include/ "skeleton.dtsi"
>  /include/ "serial.dtsi"
>
> @@ -21,6 +23,25 @@
>                 silent_console = <0>;
>         };
>
> +       pch_pinctrl {
> +               compatible = "intel,ich6-pinctrl";

Make sure you use tabs for indenting here.

You should create a binding file to describe your binding - in
doc/device-tree-bindings.

> +               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 = <0x258>;
> +                       mode-gpio;
> +                       output-value = <1>;
> +                       direction = <PIN_OUTPUT>;
> +               };
> +       };
> +
>         gpioa {
>                 compatible = "intel,ich6-gpio";
>                 u-boot,dm-pre-reloc;
> diff --git a/arch/x86/include/asm/arch-baytrail/gpio.h b/arch/x86/include/asm/arch-baytrail/gpio.h
> index 4e8987c..85a65a8 100644
> --- a/arch/x86/include/asm/arch-baytrail/gpio.h
> +++ b/arch/x86/include/asm/arch-baytrail/gpio.h
> @@ -9,5 +9,6 @@
>
>  /* Where in config space is the register that points to the GPIO registers? */
>  #define PCI_CFG_GPIOBASE 0x48
> +#define PCI_CFG_IOBASE   0x4c
>
>  #endif /* _X86_ARCH_GPIO_H_ */
> diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h
> index 1099427..ed85b08 100644
> --- a/arch/x86/include/asm/gpio.h
> +++ b/arch/x86/include/asm/gpio.h
> @@ -147,6 +147,7 @@ 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/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
> index 7e679a0..a110d5b 100644
> --- a/drivers/gpio/intel_ich6_gpio.c
> +++ b/drivers/gpio/intel_ich6_gpio.c
> @@ -44,21 +44,32 @@ struct ich6_bank_priv {
>         uint16_t lvl;
>  };
>
> +#define GPIO_USESEL_OFFSET(x) (x)
> +#define GPIO_IOSEL_OFFSET(x) (x + 4)
> +#define GPIO_LVL_OFFSET(x) (x + 8)

Comments on the above

> +
> +#define IOPAD_MODE_MASK                                0x7
> +#define IOPAD_PULL_ASSIGN_MASK         0x3
> +#define IOPAD_PULL_ASSIGN_SHIFT                7

Can you make the mask value an actual valid mask, like:

 +#define IOPAD_PULL_ASSIGN_MASK         (0x3 << IOPAD_PULL_ASSIGN_SHIFT)

> +#define IOPAD_PULL_STRENGTH_MASK       0x3
> +#define IOPAD_PULL_STRENGTH_SHIFT      9
> +
> +static int __ich6_gpio_set_value(uint16_t base, unsigned offset, int value);

Can you reorder the functions to avoid the need for these forward
declarations? Also only one underscore prefix please.

> +static int __ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir);
> +static int __ich6_gpio_set_function(uint16_t base, unsigned offset, int func);
> +
>  /* TODO: Move this to device tree, or platform data */
>  void ich_gpio_set_gpio_map(const struct pch_gpio_map *map)
>  {
>         gd->arch.gpio_map = map;
>  }
>
> -static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
> +static int gpio_ich6_get_base(unsigned long base)
>  {
> -       struct ich6_bank_platdata *plat = dev_get_platdata(dev);
>         pci_dev_t pci_dev;                      /* handle for 0:1f:0 */
>         u8 tmpbyte;
>         u16 tmpword;
>         u32 tmplong;
> -       u16 gpiobase;
> -       int offset;
>
>         /* Where should it be? */
>         pci_dev = PCI_BDF(0, 0x1f, 0);
> @@ -123,9 +134,9 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>          * while on the Ivybridge the bit0 is used to indicate it is an
>          * I/O space.
>          */
> -       tmplong = x86_pci_read_config32(pci_dev, PCI_CFG_GPIOBASE);

Can the base come from the device tree somewhere? E.g.

pch {
    gpio {
       reg = <some value>;

There is something like this in chromebook_link.dts.

> +       tmplong = x86_pci_read_config32(pci_dev, base);
>         if (tmplong == 0x00000000 || tmplong == 0xffffffff) {
> -               debug("%s: unexpected GPIOBASE value\n", __func__);
> +               debug("%s: unexpected BASE value\n", __func__);
>                 return -ENODEV;
>         }
>
> @@ -135,7 +146,138 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>          * at the offset that we just read. Bit 0 indicates that it's
>          * an I/O address, not a memory address, so mask that off.
>          */
> -       gpiobase = tmplong & 0xfffe;
> +       return tmplong & 0xfffc;
> +}
> +
> +int gpio_ich6_pinctrl_init(void)
> +{
> +       int pin_node;
> +       int node;
> +       u32 iobase;
> +       u32 gpiobase;
> +
> +       /*
> +        * 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
> +        */
> +       iobase = gpio_ich6_get_base(PCI_CFG_IOBASE);
> +       if (iobase < 0) {
> +               debug("%s: invalid IOBASE address (%08x)\n", __func__, iobase);
> +               return -EINVAL;
> +       }
> +
> +       gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
> +       if (iobase < 0) {
> +               debug("%s: invalid IOBASE address (%08x)\n", __func__, iobase);
> +               return -EINVAL;
> +       }
> +
> +       /* This is not an error to not have a pinctrl node */
> +       node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
> +                                            "intel,ich6-pinctrl");
> +       if (node < 0)
> +               return 0;

Probably this should move to driver model, but let's worry about that later.
> +
> +       for (pin_node = fdt_first_subnode(gd->fdt_blob, node);
> +            pin_node > 0;
> +            pin_node = fdt_next_subnode(gd->fdt_blob, pin_node)) {
> +               u32 gpio_offset[2] = { -1, -1 };
> +               u32 pad_offset;
> +               u32 tmplong;
> +               const void *tmpnode;
> +
> +               /*
> +                * The offset for the same pin for the IOBASE and GPIOBASE are
> +                * different, so instead of maintaining a lookup table,
> +                * the device tree should provide directly the correct
> +                * value for both mapping.
> +                */
> +               pad_offset = fdtdec_get_int(gd->fdt_blob, pin_node,
> +                                           "pad-offset", -1);
> +               if (pad_offset == -1) {
> +                       debug("%s: Invalid register io offset %d\n",
> +                             __func__, pad_offset);
> +                       return -EINVAL;
> +               }
> +
> +               /*
> +                * GPIO node is not mandatory, so we only do the
> +                * pinmuxing if the node exist.
> +                */
> +               fdtdec_get_int_array(gd->fdt_blob, pin_node,
> +                                    "gpio-offset", gpio_offset, 2);
> +               if (gpio_offset[0] != -1) {

Can you move this block into its own function without too much trouble?

> +                       /* Do we want to force the GPIO mode? */
> +                       tmpnode = fdt_getprop(gd->fdt_blob, pin_node,
> +                                             "mode-gpio", NULL);
> +                       if (tmpnode)
> +                               __ich6_gpio_set_function(GPIO_USESEL_OFFSET
> +                                                        (gpiobase) +
> +                                                        gpio_offset[0],
> +                                                        gpio_offset[1], 1);
> +
> +                       tmplong =
> +                           fdtdec_get_int(gd->fdt_blob, pin_node, "direction",
> +                                          -1);
> +                       if (tmplong != -1)

But tmplong is unsigned.

> +                               __ich6_gpio_set_direction(GPIO_IOSEL_OFFSET
> +                                                         (gpiobase) +
> +                                                         gpio_offset[0],
> +                                                         gpio_offset[1],
> +                                                         tmplong);
> +
> +                       tmplong =
> +                           fdtdec_get_int(gd->fdt_blob, pin_node,
> +                                          "output-value", -1);
> +                       if (tmplong != -1)
> +                               __ich6_gpio_set_value(GPIO_LVL_OFFSET(gpiobase)
> +                                                     + gpio_offset[0],
> +                                                     gpio_offset[1], tmplong);
> +               }
> +
> +               /*
> +                * Do we need to set a specific function mode?
> +                * If someone put also 'mode-gpio', this option will
> +                * be just ignored by the controller
> +                */
> +               tmplong =
> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "mode-func", -1);
> +               if (tmplong != -1)
> +                       clrsetbits_le32(iobase + pad_offset, IOPAD_MODE_MASK,
> +                                       tmplong);
> +
> +               /* Configure the pull-up/down if needed */
> +               tmplong =
> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "pull-assign", -1);
> +               if (tmplong != -1)
> +                       clrsetbits_le32(iobase + pad_offset,
> +                                       IOPAD_PULL_ASSIGN_MASK <<
> +                                       IOPAD_PULL_ASSIGN_SHIFT,
> +                                       tmplong << IOPAD_PULL_ASSIGN_SHIFT);
> +
> +               tmplong =
> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "pull-strength", -1);
> +               if (tmplong != -1)
> +                       clrsetbits_le32(iobase + pad_offset,
> +                                       IOPAD_PULL_STRENGTH_MASK <<
> +                                       IOPAD_PULL_STRENGTH_SHIFT,
> +                                       tmplong << IOPAD_PULL_STRENGTH_SHIFT);
> +
> +               debug("%s: pad cfg [0x%x]: %08x\n", __func__, pad_offset,
> +                     readl(iobase + pad_offset));
> +       }
> +
> +       return 0;
> +}
> +
> +static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
> +{
> +       struct ich6_bank_platdata *plat = dev_get_platdata(dev);
> +       u16 gpiobase;
> +       int offset;
> +
> +       gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
>         offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
>         if (offset == -1) {
>                 debug("%s: Invalid register offset %d\n", __func__, offset);
> @@ -189,33 +331,56 @@ static int ich6_gpio_request(struct udevice *dev, unsigned offset,
>         return 0;
>  }
>
> -static int ich6_gpio_direction_input(struct udevice *dev, unsigned offset)
> +static int __ich6_gpio_set_function(uint16_t base, unsigned offset, int func)
>  {
> -       struct ich6_bank_priv *bank = dev_get_priv(dev);
>         u32 tmplong;
>
> -       tmplong = inl(bank->io_sel);
> -       tmplong |= (1UL << offset);
> -       outl(bank->io_sel, tmplong);
> +       if (func) {
> +               tmplong = inl(base);
> +               tmplong |= (1UL << offset);
> +               outl(tmplong, base);
> +       } else {
> +               tmplong = inl(base);
> +               tmplong &= ~(1UL << offset);
> +               outl(tmplong, base);
> +       }
> +
>         return 0;
>  }
>
> -static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
> -                                      int value)
> +static int __ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir)
>  {
> -       struct ich6_bank_priv *bank = dev_get_priv(dev);
>         u32 tmplong;
>
> -       gpio_set_value(offset, value);
> +       if (!dir) {
> +               tmplong = inl(base);
> +               tmplong |= (1UL << offset);
> +               outl(tmplong, base);
> +       } else {
> +               tmplong = inl(base);
> +               tmplong &= ~(1UL << offset);
> +               outl(tmplong, base);
> +       }
>
> -       tmplong = inl(bank->io_sel);
> -       tmplong &= ~(1UL << offset);
> -       outl(bank->io_sel, tmplong);
>         return 0;
>  }
>
> -static int ich6_gpio_get_value(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(inl(bank->io_sel), offset, 0);
> +}
> +
> +static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
> +               int value)
> +{
> +       struct ich6_bank_priv *bank = dev_get_priv(dev);
> +
> +       return __ich6_gpio_set_direction(inl(bank->io_sel), offset, 1);
> +}
>
> +static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
>  {
>         struct ich6_bank_priv *bank = dev_get_priv(dev);
>         u32 tmplong;
> @@ -226,21 +391,26 @@ 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)
> +static int __ich6_gpio_set_value(uint16_t base, unsigned offset, int value)
>  {
> -       struct ich6_bank_priv *bank = dev_get_priv(dev);
>         u32 tmplong;
> -
> -       tmplong = inl(bank->lvl);
> +       tmplong = inl(base);
>         if (value)
>                 tmplong |= (1UL << offset);
>         else
>                 tmplong &= ~(1UL << offset);
> -       outl(bank->lvl, tmplong);
> +       outl(tmplong, base);
> +
>         return 0;
>  }
>
> +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);
> diff --git a/include/dt-bindings/gpio/gpio.h b/include/dt-bindings/gpio/gpio.h
> index e6b1e0a..49d437c 100644
> --- a/include/dt-bindings/gpio/gpio.h
> +++ b/include/dt-bindings/gpio/gpio.h
> @@ -12,4 +12,24 @@
>  #define GPIO_ACTIVE_HIGH 0
>  #define GPIO_ACTIVE_LOW 1
>
> +#define GPIO_MODE_NATIVE       0
> +#define GPIO_MODE_GPIO         1
> +
> +#define GPIO_MODE_FUNC0        0
> +#define GPIO_MODE_FUNC1        1
> +#define GPIO_MODE_FUNC2        2
> +#define GPIO_MODE_FUNC4        4
> +#define GPIO_MODE_FUNC5        5
> +#define GPIO_MODE_FUNC6        6

Can we use an enum for these? They mostly count up.

> +
> +#define PIN_INPUT              0
> +#define PIN_OUTPUT             1
> +
> +#define PIN_INPUT_NOPULL       0
> +#define PIN_INPUT_PULLUP       1
> +#define PIN_INPUT_PULLDOWN     2
> +
> +#define PULL_STR_2K            0
> +#define PULL_STR_20K   2
> +
>  #endif
> --
> 2.1.4
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 4/4] x86: minnowmax: initialize the pin-muxing from device tree
  2015-04-23 16:16 ` [U-Boot] [PATCH 4/4] x86: minnowmax: initialize the pin-muxing from " Gabriel Huau
@ 2015-04-24  3:37   ` Simon Glass
  2015-04-24  4:45   ` [U-Boot] unassigned-patches/145: " u-boot at bugs.denx.de
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 61+ messages in thread
From: Simon Glass @ 2015-04-24  3:37 UTC (permalink / raw)
  To: u-boot

Hi Grabriel,

On 23 April 2015 at 10:16, Gabriel Huau <contact@huau-gabriel.fr> wrote:

<commit message here>

> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
> ---
>  board/intel/minnowmax/minnowmax.c | 9 +++++++++
>  include/configs/minnowmax.h       | 1 +
>  2 files changed, 10 insertions(+)
>
> diff --git a/board/intel/minnowmax/minnowmax.c b/board/intel/minnowmax/minnowmax.c
> index 6e82b16..60dd2bb 100644
> --- a/board/intel/minnowmax/minnowmax.c
> +++ b/board/intel/minnowmax/minnowmax.c
> @@ -7,6 +7,7 @@
>  #include <common.h>
>  #include <asm/ibmpc.h>
>  #include <asm/pnp_def.h>
> +#include <asm/gpio.h>

This should go up one line I think, for ordering.

>  #include <netdev.h>
>  #include <smsc_lpc47m.h>
>
> @@ -14,6 +15,14 @@
>
>  DECLARE_GLOBAL_DATA_PTR;
>
> +int arch_early_init_r(void)
> +{
> +       /* do the pin-muxing */
> +       gpio_ich6_pinctrl_init();
> +
> +       return 0;
> +}
> +
>  int board_early_init_f(void)
>  {
>         lpc47m_enable_serial(SERIAL_DEV, UART0_BASE);
> diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h
> index 823e051..3c7b266 100644
> --- a/include/configs/minnowmax.h
> +++ b/include/configs/minnowmax.h
> @@ -15,6 +15,7 @@
>
>  #define CONFIG_SYS_MONITOR_LEN         (1 << 20)
>  #define CONFIG_BOARD_EARLY_INIT_F
> +#define CONFIG_ARCH_EARLY_INIT_R
>
>  #define CONFIG_NR_DRAM_BANKS           1
>
> --
> 2.1.4
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] unassigned-patches/144: Re: [PATCH 3/4] x86: gpio: add pinctrl support from the device tree
  2015-04-23 16:16 ` [U-Boot] [PATCH 3/4] x86: gpio: add pinctrl support from " Gabriel Huau
  2015-04-24  3:14   ` Bin Meng
  2015-04-24  3:35   ` Simon Glass
@ 2015-04-24  4:40   ` u-boot at bugs.denx.de
  2015-04-25 20:17   ` [U-Boot] [PATCH 3/4 v2] " Gabriel Huau
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 61+ messages in thread
From: u-boot at bugs.denx.de @ 2015-04-24  4:40 UTC (permalink / raw)
  To: u-boot

Hi,

On 23 April 2015 at 10:16, Gabriel Huau <contact@huau-gabriel.fr> wrote:
> A set of properties has been defined for the device tree to select for
> each pin the pull/func/default output configuration.
>
> The offset for the PAD needs to be provided and if a GPIO needs to be
> configured, his offset needs to be provided as well.
>
> Here is an example:
> pin_usb_host_en0 at 0 {
>     gpio-offset = <0x80 8>;
>     pad-offset = <0x260>;
>     mode-gpio;
>     output-value = <1>;
>     direction = <PIN_OUTPUT>;
> };
>
> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
> ---
>  arch/x86/dts/minnowmax.dts                |  21 +++
>  arch/x86/include/asm/arch-baytrail/gpio.h |   1 +
>  arch/x86/include/asm/gpio.h               |   1 +
>  drivers/gpio/intel_ich6_gpio.c            | 222 ++++++++++++++++++++++++++----
>  include/dt-bindings/gpio/gpio.h           |  20 +++
>  5 files changed, 239 insertions(+), 26 deletions(-)
>
> diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
> index c73e421..3936e21 100644
> --- a/arch/x86/dts/minnowmax.dts
> +++ b/arch/x86/dts/minnowmax.dts
> @@ -6,6 +6,8 @@
>
>  /dts-v1/;
>
> +#include <dt-bindings/gpio/gpio.h>
> +
>  /include/ "skeleton.dtsi"
>  /include/ "serial.dtsi"
>
> @@ -21,6 +23,25 @@
>                 silent_console = <0>;
>         };
>
> +       pch_pinctrl {
> +               compatible = "intel,ich6-pinctrl";

Make sure you use tabs for indenting here.

You should create a binding file to describe your binding - in
doc/device-tree-bindings.

> +               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 = <0x258>;
> +                       mode-gpio;
> +                       output-value = <1>;
> +                       direction = <PIN_OUTPUT>;
> +               };
> +       };
> +
>         gpioa {
>                 compatible = "intel,ich6-gpio";
>                 u-boot,dm-pre-reloc;
> diff --git a/arch/x86/include/asm/arch-baytrail/gpio.h b/arch/x86/include/asm/arch-baytrail/gpio.h
> index 4e8987c..85a65a8 100644
> --- a/arch/x86/include/asm/arch-baytrail/gpio.h
> +++ b/arch/x86/include/asm/arch-baytrail/gpio.h
> @@ -9,5 +9,6 @@
>
>  /* Where in config space is the register that points to the GPIO registers? */
>  #define PCI_CFG_GPIOBASE 0x48
> +#define PCI_CFG_IOBASE   0x4c
>
>  #endif /* _X86_ARCH_GPIO_H_ */
> diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h
> index 1099427..ed85b08 100644
> --- a/arch/x86/include/asm/gpio.h
> +++ b/arch/x86/include/asm/gpio.h
> @@ -147,6 +147,7 @@ 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/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
> index 7e679a0..a110d5b 100644
> --- a/drivers/gpio/intel_ich6_gpio.c
> +++ b/drivers/gpio/intel_ich6_gpio.c
> @@ -44,21 +44,32 @@ struct ich6_bank_priv {
>         uint16_t lvl;
>  };
>
> +#define GPIO_USESEL_OFFSET(x) (x)
> +#define GPIO_IOSEL_OFFSET(x) (x + 4)
> +#define GPIO_LVL_OFFSET(x) (x + 8)

Comments on the above

> +
> +#define IOPAD_MODE_MASK                                0x7
> +#define IOPAD_PULL_ASSIGN_MASK         0x3
> +#define IOPAD_PULL_ASSIGN_SHIFT                7

Can you make the mask value an actual valid mask, like:

 +#define IOPAD_PULL_ASSIGN_MASK         (0x3 << IOPAD_PULL_ASSIGN_SHIFT)

> +#define IOPAD_PULL_STRENGTH_MASK       0x3
> +#define IOPAD_PULL_STRENGTH_SHIFT      9
> +
> +static int __ich6_gpio_set_value(uint16_t base, unsigned offset, int value);

Can you reorder the functions to avoid the need for these forward
declarations? Also only one underscore prefix please.

> +static int __ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir);
> +static int __ich6_gpio_set_function(uint16_t base, unsigned offset, int func);
> +
>  /* TODO: Move this to device tree, or platform data */
>  void ich_gpio_set_gpio_map(const struct pch_gpio_map *map)
>  {
>         gd->arch.gpio_map = map;
>  }
>
> -static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
> +static int gpio_ich6_get_base(unsigned long base)
>  {
> -       struct ich6_bank_platdata *plat = dev_get_platdata(dev);
>         pci_dev_t pci_dev;                      /* handle for 0:1f:0 */
>         u8 tmpbyte;
>         u16 tmpword;
>         u32 tmplong;
> -       u16 gpiobase;
> -       int offset;
>
>         /* Where should it be? */
>         pci_dev = PCI_BDF(0, 0x1f, 0);
> @@ -123,9 +134,9 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>          * while on the Ivybridge the bit0 is used to indicate it is an
>          * I/O space.
>          */
> -       tmplong = x86_pci_read_config32(pci_dev, PCI_CFG_GPIOBASE);

Can the base come from the device tree somewhere? E.g.

pch {
    gpio {
       reg = <some value>;

There is something like this in chromebook_link.dts.

> +       tmplong = x86_pci_read_config32(pci_dev, base);
>         if (tmplong == 0x00000000 || tmplong == 0xffffffff) {
> -               debug("%s: unexpected GPIOBASE value\n", __func__);
> +               debug("%s: unexpected BASE value\n", __func__);
>                 return -ENODEV;
>         }
>
> @@ -135,7 +146,138 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>          * at the offset that we just read. Bit 0 indicates that it's
>          * an I/O address, not a memory address, so mask that off.
>          */
> -       gpiobase = tmplong & 0xfffe;
> +       return tmplong & 0xfffc;
> +}
> +
> +int gpio_ich6_pinctrl_init(void)
> +{
> +       int pin_node;
> +       int node;
> +       u32 iobase;
> +       u32 gpiobase;
> +
> +       /*
> +        * 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
> +        */
> +       iobase = gpio_ich6_get_base(PCI_CFG_IOBASE);
> +       if (iobase < 0) {
> +               debug("%s: invalid IOBASE address (%08x)\n", __func__, iobase);
> +               return -EINVAL;
> +       }
> +
> +       gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
> +       if (iobase < 0) {
> +               debug("%s: invalid IOBASE address (%08x)\n", __func__, iobase);
> +               return -EINVAL;
> +       }
> +
> +       /* This is not an error to not have a pinctrl node */
> +       node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
> +                                            "intel,ich6-pinctrl");
> +       if (node < 0)
> +               return 0;

Probably this should move to driver model, but let's worry about that later.
> +
> +       for (pin_node = fdt_first_subnode(gd->fdt_blob, node);
> +            pin_node > 0;
> +            pin_node = fdt_next_subnode(gd->fdt_blob, pin_node)) {
> +               u32 gpio_offset[2] = { -1, -1 };
> +               u32 pad_offset;
> +               u32 tmplong;
> +               const void *tmpnode;
> +
> +               /*
> +                * The offset for the same pin for the IOBASE and GPIOBASE are
> +                * different, so instead of maintaining a lookup table,
> +                * the device tree should provide directly the correct
> +                * value for both mapping.
> +                */
> +               pad_offset = fdtdec_get_int(gd->fdt_blob, pin_node,
> +                                           "pad-offset", -1);
> +               if (pad_offset == -1) {
> +                       debug("%s: Invalid register io offset %d\n",
> +                             __func__, pad_offset);
> +                       return -EINVAL;
> +               }
> +
> +               /*
> +                * GPIO node is not mandatory, so we only do the
> +                * pinmuxing if the node exist.
> +                */
> +               fdtdec_get_int_array(gd->fdt_blob, pin_node,
> +                                    "gpio-offset", gpio_offset, 2);
> +               if (gpio_offset[0] != -1) {

Can you move this block into its own function without too much trouble?

> +                       /* Do we want to force the GPIO mode? */
> +                       tmpnode = fdt_getprop(gd->fdt_blob, pin_node,
> +                                             "mode-gpio", NULL);
> +                       if (tmpnode)
> +                               __ich6_gpio_set_function(GPIO_USESEL_OFFSET
> +                                                        (gpiobase) +
> +                                                        gpio_offset[0],
> +                                                        gpio_offset[1], 1);
> +
> +                       tmplong =
> +                           fdtdec_get_int(gd->fdt_blob, pin_node, "direction",
> +                                          -1);
> +                       if (tmplong != -1)

But tmplong is unsigned.

> +                               __ich6_gpio_set_direction(GPIO_IOSEL_OFFSET
> +                                                         (gpiobase) +
> +                                                         gpio_offset[0],
> +                                                         gpio_offset[1],
> +                                                         tmplong);
> +
> +                       tmplong =
> +                           fdtdec_get_int(gd->fdt_blob, pin_node,
> +                                          "output-value", -1);
> +                       if (tmplong != -1)
> +                               __ich6_gpio_set_value(GPIO_LVL_OFFSET(gpiobase)
> +                                                     + gpio_offset[0],
> +                                                     gpio_offset[1], tmplong);
> +               }
> +
> +               /*
> +                * Do we need to set a specific function mode?
> +                * If someone put also 'mode-gpio', this option will
> +                * be just ignored by the controller
> +                */
> +               tmplong =
> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "mode-func", -1);
> +               if (tmplong != -1)
> +                       clrsetbits_le32(iobase + pad_offset, IOPAD_MODE_MASK,
> +                                       tmplong);
> +
> +               /* Configure the pull-up/down if needed */
> +               tmplong =
> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "pull-assign", -1);
> +               if (tmplong != -1)
> +                       clrsetbits_le32(iobase + pad_offset,
> +                                       IOPAD_PULL_ASSIGN_MASK <<
> +                                       IOPAD_PULL_ASSIGN_SHIFT,
> +                                       tmplong << IOPAD_PULL_ASSIGN_SHIFT);
> +
> +               tmplong =
> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "pull-strength", -1);
> +               if (tmplong != -1)
> +                       clrsetbits_le32(iobase + pad_offset,
> +                                       IOPAD_PULL_STRENGTH_MASK <<
> +                                       IOPAD_PULL_STRENGTH_SHIFT,
> +                                       tmplong << IOPAD_PULL_STRENGTH_SHIFT);
> +
> +               debug("%s: pad cfg [0x%x]: %08x\n", __func__, pad_offset,
> +                     readl(iobase + pad_offset));
> +       }
> +
> +       return 0;
> +}
> +
> +static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
> +{
> +       struct ich6_bank_platdata *plat = dev_get_platdata(dev);
> +       u16 gpiobase;
> +       int offset;
> +
> +       gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
>         offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
>         if (offset == -1) {
>                 debug("%s: Invalid register offset %d\n", __func__, offset);
> @@ -189,33 +331,56 @@ static int ich6_gpio_request(struct udevice *dev, unsigned offset,
>         return 0;
>  }
>
> -static int ich6_gpio_direction_input(struct udevice *dev, unsigned offset)
> +static int __ich6_gpio_set_function(uint16_t base, unsigned offset, int func)
>  {
> -       struct ich6_bank_priv *bank = dev_get_priv(dev);
>         u32 tmplong;
>
> -       tmplong = inl(bank->io_sel);
> -       tmplong |= (1UL << offset);
> -       outl(bank->io_sel, tmplong);
> +       if (func) {
> +               tmplong = inl(base);
> +               tmplong |= (1UL << offset);
> +               outl(tmplong, base);
> +       } else {
> +               tmplong = inl(base);
> +               tmplong &= ~(1UL << offset);
> +               outl(tmplong, base);
> +       }
> +
>         return 0;
>  }
>
> -static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
> -                                      int value)
> +static int __ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir)
>  {
> -       struct ich6_bank_priv *bank = dev_get_priv(dev);
>         u32 tmplong;
>
> -       gpio_set_value(offset, value);
> +       if (!dir) {
> +               tmplong = inl(base);
> +               tmplong |= (1UL << offset);
> +               outl(tmplong, base);
> +       } else {
> +               tmplong = inl(base);
> +               tmplong &= ~(1UL << offset);
> +               outl(tmplong, base);
> +       }
>
> -       tmplong = inl(bank->io_sel);
> -       tmplong &= ~(1UL << offset);
> -       outl(bank->io_sel, tmplong);
>         return 0;
>  }
>
> -static int ich6_gpio_get_value(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(inl(bank->io_sel), offset, 0);
> +}
> +
> +static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
> +               int value)
> +{
> +       struct ich6_bank_priv *bank = dev_get_priv(dev);
> +
> +       return __ich6_gpio_set_direction(inl(bank->io_sel), offset, 1);
> +}
>
> +static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
>  {
>         struct ich6_bank_priv *bank = dev_get_priv(dev);
>         u32 tmplong;
> @@ -226,21 +391,26 @@ 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)
> +static int __ich6_gpio_set_value(uint16_t base, unsigned offset, int value)
>  {
> -       struct ich6_bank_priv *bank = dev_get_priv(dev);
>         u32 tmplong;
> -
> -       tmplong = inl(bank->lvl);
> +       tmplong = inl(base);
>         if (value)
>                 tmplong |= (1UL << offset);
>         else
>                 tmplong &= ~(1UL << offset);
> -       outl(bank->lvl, tmplong);
> +       outl(tmplong, base);
> +
>         return 0;
>  }
>
> +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);
> diff --git a/include/dt-bindings/gpio/gpio.h b/include/dt-bindings/gpio/gpio.h
> index e6b1e0a..49d437c 100644
> --- a/include/dt-bindings/gpio/gpio.h
> +++ b/include/dt-bindings/gpio/gpio.h
> @@ -12,4 +12,24 @@
>  #define GPIO_ACTIVE_HIGH 0
>  #define GPIO_ACTIVE_LOW 1
>
> +#define GPIO_MODE_NATIVE       0
> +#define GPIO_MODE_GPIO         1
> +
> +#define GPIO_MODE_FUNC0        0
> +#define GPIO_MODE_FUNC1        1
> +#define GPIO_MODE_FUNC2        2
> +#define GPIO_MODE_FUNC4        4
> +#define GPIO_MODE_FUNC5        5
> +#define GPIO_MODE_FUNC6        6

Can we use an enum for these? They mostly count up.

> +
> +#define PIN_INPUT              0
> +#define PIN_OUTPUT             1
> +
> +#define PIN_INPUT_NOPULL       0
> +#define PIN_INPUT_PULLUP       1
> +#define PIN_INPUT_PULLDOWN     2
> +
> +#define PULL_STR_2K            0
> +#define PULL_STR_20K   2
> +
>  #endif
> --
> 2.1.4
>

Regards,
Simon

---
Added to GNATS database as unassigned-patches/144
>Responsible:    patch-coord
>Message-Id:     <CAPnjgZ38cPE1h6EBg-ffdtOA4FhTdgTx8u1VS5yMpv9Ynik-KA@mail.gmail.com>
>In-Reply-To:    <1429805775-1809-4-git-send-email-contact@huau-gabriel.fr>
>References:     <1429805775-1809-1-git-send-email-contact@huau-gabriel.fr>	<1429805775-1809-4-git-send-email-contact@huau-gabriel.fr>
>Patch-Date:     Fri Apr 24 05:35:00 +0200 2015

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] unassigned-patches/145: Re: [PATCH 4/4] x86: minnowmax: initialize the pin-muxing from device tree
  2015-04-23 16:16 ` [U-Boot] [PATCH 4/4] x86: minnowmax: initialize the pin-muxing from " Gabriel Huau
  2015-04-24  3:37   ` Simon Glass
@ 2015-04-24  4:45   ` u-boot at bugs.denx.de
  2015-04-25 20:18   ` [U-Boot] [PATCH 4/4 v2] " Gabriel Huau
  2015-05-12  6:18   ` [U-Boot] [PATCH v3 4/4] " Gabriel Huau
  3 siblings, 0 replies; 61+ messages in thread
From: u-boot at bugs.denx.de @ 2015-04-24  4:45 UTC (permalink / raw)
  To: u-boot

Hi Grabriel,

On 23 April 2015 at 10:16, Gabriel Huau <contact@huau-gabriel.fr> wrote:

<commit message here>

> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
> ---
>  board/intel/minnowmax/minnowmax.c | 9 +++++++++
>  include/configs/minnowmax.h       | 1 +
>  2 files changed, 10 insertions(+)
>
> diff --git a/board/intel/minnowmax/minnowmax.c b/board/intel/minnowmax/minnowmax.c
> index 6e82b16..60dd2bb 100644
> --- a/board/intel/minnowmax/minnowmax.c
> +++ b/board/intel/minnowmax/minnowmax.c
> @@ -7,6 +7,7 @@
>  #include <common.h>
>  #include <asm/ibmpc.h>
>  #include <asm/pnp_def.h>
> +#include <asm/gpio.h>

This should go up one line I think, for ordering.

>  #include <netdev.h>
>  #include <smsc_lpc47m.h>
>
> @@ -14,6 +15,14 @@
>
>  DECLARE_GLOBAL_DATA_PTR;
>
> +int arch_early_init_r(void)
> +{
> +       /* do the pin-muxing */
> +       gpio_ich6_pinctrl_init();
> +
> +       return 0;
> +}
> +
>  int board_early_init_f(void)
>  {
>         lpc47m_enable_serial(SERIAL_DEV, UART0_BASE);
> diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h
> index 823e051..3c7b266 100644
> --- a/include/configs/minnowmax.h
> +++ b/include/configs/minnowmax.h
> @@ -15,6 +15,7 @@
>
>  #define CONFIG_SYS_MONITOR_LEN         (1 << 20)
>  #define CONFIG_BOARD_EARLY_INIT_F
> +#define CONFIG_ARCH_EARLY_INIT_R
>
>  #define CONFIG_NR_DRAM_BANKS           1
>
> --
> 2.1.4
>

Regards,
Simon

---
Added to GNATS database as unassigned-patches/145
>Responsible:    patch-coord
>Message-Id:     <CAPnjgZ1djEV3BHjoLysmc-O+KSsvN7rrn=S=qXEyUYwpErwNiQ@mail.gmail.com>
>In-Reply-To:    <1429805775-1809-5-git-send-email-contact@huau-gabriel.fr>
>References:     <1429805775-1809-1-git-send-email-contact@huau-gabriel.fr>	<1429805775-1809-5-git-send-email-contact@huau-gabriel.fr>
>Patch-Date:     Fri Apr 24 05:37:28 +0200 2015

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] unassigned-patches/146: Re: [PATCH 2/4] x86: minnowmax: add GPIO banks in the device tree
  2015-04-23 16:16 ` [U-Boot] [PATCH 2/4] x86: minnowmax: add GPIO banks in the device tree Gabriel Huau
  2015-04-24  2:03   ` Bin Meng
  2015-04-24  3:26   ` Simon Glass
@ 2015-04-24  5:05   ` u-boot at bugs.denx.de
  2015-04-24  5:05   ` [U-Boot] unassigned-patches/147: " u-boot at bugs.denx.de
  2015-04-25 20:16   ` [U-Boot] [PATCH 2/4 v2] " Gabriel Huau
  4 siblings, 0 replies; 61+ messages in thread
From: u-boot at bugs.denx.de @ 2015-04-24  5:05 UTC (permalink / raw)
  To: u-boot

Hi Gabriel,

On Fri, Apr 24, 2015 at 12:16 AM, Gabriel Huau <contact@huau-gabriel.fr> wrote:
> There is 6 banks:

There are

>     4 banks for CORE: available in S0 mode
>     2 banks for SUS (Suspend): available in S0-S5 mode
>
> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
> ---
>  arch/x86/dts/minnowmax.dts | 42 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 42 insertions(+)
>
> diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
> index 8f34369..c73e421 100644
> --- a/arch/x86/dts/minnowmax.dts
> +++ b/arch/x86/dts/minnowmax.dts
> @@ -21,6 +21,48 @@
>                 silent_console = <0>;
>         };
>
> +       gpioa {
> +               compatible = "intel,ich6-gpio";
> +               u-boot,dm-pre-reloc;
> +               reg = <0 0x20>;
> +               bank-name = "A";
> +       };
> +
> +       gpiob {
> +               compatible = "intel,ich6-gpio";
> +               u-boot,dm-pre-reloc;
> +               reg = <0x20 0x20>;
> +               bank-name = "B";
> +       };
> +
> +       gpioc {
> +               compatible = "intel,ich6-gpio";
> +               u-boot,dm-pre-reloc;
> +               reg = <0x40 0x20>;
> +               bank-name = "C";
> +       };
> +
> +       gpiod {
> +               compatible = "intel,ich6-gpio";
> +               u-boot,dm-pre-reloc;
> +               reg = <0x60 0x20>;
> +               bank-name = "D";
> +       };
> +
> +       gpioe {
> +               compatible = "intel,ich6-gpio";
> +               u-boot,dm-pre-reloc;
> +               reg = <0x80 0x20>;
> +               bank-name = "E";
> +       };
> +
> +       gpiof {
> +               compatible = "intel,ich6-gpio";
> +               u-boot,dm-pre-reloc;
> +               reg = <0xA0 0x20>;
> +               bank-name = "F";
> +       };
> +
>         chosen {
>                 stdout-path = "/serial";
>         };
> --

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

---
Added to GNATS database as unassigned-patches/146
>Responsible:    patch-coord
>Message-Id:     <CAEUhbmXfHVYw79-NxfjT3ykpuiYSp0-k+WN518qWteTJoytx3Q@mail.gmail.com>
>In-Reply-To:    <1429805775-1809-3-git-send-email-contact@huau-gabriel.fr>
>References:     <1429805775-1809-1-git-send-email-contact@huau-gabriel.fr>	<1429805775-1809-3-git-send-email-contact@huau-gabriel.fr>
>Patch-Date:     Fri Apr 24 04:03:19 +0200 2015

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] unassigned-patches/147: Re: [PATCH 2/4] x86: minnowmax: add GPIO banks in the device tree
  2015-04-23 16:16 ` [U-Boot] [PATCH 2/4] x86: minnowmax: add GPIO banks in the device tree Gabriel Huau
                     ` (2 preceding siblings ...)
  2015-04-24  5:05   ` [U-Boot] unassigned-patches/146: " u-boot at bugs.denx.de
@ 2015-04-24  5:05   ` u-boot at bugs.denx.de
  2015-04-25 20:16   ` [U-Boot] [PATCH 2/4 v2] " Gabriel Huau
  4 siblings, 0 replies; 61+ messages in thread
From: u-boot at bugs.denx.de @ 2015-04-24  5:05 UTC (permalink / raw)
  To: u-boot

On 23 April 2015 at 10:16, Gabriel Huau <contact@huau-gabriel.fr> wrote:
> There is 6 banks:
>     4 banks for CORE: available in S0 mode
>     2 banks for SUS (Suspend): available in S0-S5 mode
>
> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
> ---
>  arch/x86/dts/minnowmax.dts | 42 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 42 insertions(+)

Acked-by: Simon Glass <sjg@chromium.org>

---
Added to GNATS database as unassigned-patches/147
>Responsible:    patch-coord
>Message-Id:     <CAPnjgZ2nJnkhFvLuxW01YX1B1u8HKTGPA=dLwOHhpDjv9iDs=A@mail.gmail.com>
>In-Reply-To:    <1429805775-1809-3-git-send-email-contact@huau-gabriel.fr>
>References:     <1429805775-1809-1-git-send-email-contact@huau-gabriel.fr>	<1429805775-1809-3-git-send-email-contact@huau-gabriel.fr>
>Patch-Date:     Fri Apr 24 05:26:17 +0200 2015

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] unassigned-patches/148: Re: [PATCH 0/4] x86: support of pin-muxing from device tree
  2015-04-23 16:16 [U-Boot] [PATCH 0/4] x86: support of pin-muxing from device tree Gabriel Huau
                   ` (9 preceding siblings ...)
  2015-04-24  3:23 ` [U-Boot] [PATCH 0/4] x86: support of " Bin Meng
@ 2015-04-24  5:05 ` u-boot at bugs.denx.de
  2015-05-12  6:10 ` [U-Boot] [PATCH v3 3/4] x86: gpio: add pinctrl support from the " Gabriel Huau
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 61+ messages in thread
From: u-boot at bugs.denx.de @ 2015-04-24  5:05 UTC (permalink / raw)
  To: u-boot

Hi Gabriel,

On Fri, Apr 24, 2015 at 12:16 AM, Gabriel Huau <contact@huau-gabriel.fr> wrote:
> This serie of patches adds the support of pin-muxing from the device tree through
> different properties. I have put two example to enable the USB Host on the
> minnowboard max.
>
> The support of the call to 'setup_pch_gpios' is still supported and
> only the minnowboard has been tested with the device tree implementation.
>
> Because the GPIO and IO base register ares different, I have also defined
> some proxy function to set the function/value and direction of the GPIO as
> the GPIO register can override some registers in the IO.
>
> Gabriel Huau (4):
>   x86: baytrail: fix the GPIOBASE address
>   x86: minnowmax: add GPIO banks in the device tree
>   x86: gpio: add pinctrl support from the device tree
>   x86: minnowmax: initialize the pin-muxing from device tree
>
>  arch/x86/dts/minnowmax.dts                |  63 +++++++++
>  arch/x86/include/asm/arch-baytrail/gpio.h |   3 +-
>  arch/x86/include/asm/gpio.h               |   1 +
>  board/intel/minnowmax/minnowmax.c         |   9 ++
>  drivers/gpio/intel_ich6_gpio.c            | 222 ++++++++++++++++++++++++++----
>  include/configs/minnowmax.h               |   1 +
>  include/dt-bindings/gpio/gpio.h           |  20 +++
>  7 files changed, 292 insertions(+), 27 deletions(-)
>
> --

Thanks for these patches! Just a general comment, you don't need send
emails to u-boot-patches at bugs.denx.de, and always include a simple
sentence in the commit message :)

Regards,
Bin

---
Added to GNATS database as unassigned-patches/148
>Responsible:    patch-coord
>Message-Id:     <CAEUhbmVTxF6NKX62O0JWXaTyYdbSqduv7SyYEw7jC-XqUjjKTQ@mail.gmail.com>
>In-Reply-To:    <1429805775-1809-1-git-send-email-contact@huau-gabriel.fr>
>References:     <1429805775-1809-1-git-send-email-contact@huau-gabriel.fr>
>Patch-Date:     Fri Apr 24 05:23:35 +0200 2015

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 3/4] x86: gpio: add pinctrl support from the device tree
  2015-04-24  3:14   ` Bin Meng
@ 2015-04-24 14:32     ` Gabriel Huau
  0 siblings, 0 replies; 61+ messages in thread
From: Gabriel Huau @ 2015-04-24 14:32 UTC (permalink / raw)
  To: u-boot

On 04/23/2015 08:14 PM, Bin Meng wrote:
> Hi Gabriel,
>
> On Fri, Apr 24, 2015 at 12:16 AM, Gabriel Huau <contact@huau-gabriel.fr> wrote:
>> A set of properties has been defined for the device tree to select for
>> each pin the pull/func/default output configuration.
>>
>> The offset for the PAD needs to be provided and if a GPIO needs to be
>> configured, his offset needs to be provided as well.
>>
>> Here is an example:
>> pin_usb_host_en0 at 0 {
>>      gpio-offset = <0x80 8>;
>>      pad-offset = <0x260>;
>>      mode-gpio;
>>      output-value = <1>;
>>      direction = <PIN_OUTPUT>;
>> };
>>
>> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
>> ---
>>   arch/x86/dts/minnowmax.dts                |  21 +++
>>   arch/x86/include/asm/arch-baytrail/gpio.h |   1 +
>>   arch/x86/include/asm/gpio.h               |   1 +
>>   drivers/gpio/intel_ich6_gpio.c            | 222 ++++++++++++++++++++++++++----
>>   include/dt-bindings/gpio/gpio.h           |  20 +++
>>   5 files changed, 239 insertions(+), 26 deletions(-)
>>
>> diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
>> index c73e421..3936e21 100644
>> --- a/arch/x86/dts/minnowmax.dts
>> +++ b/arch/x86/dts/minnowmax.dts
>> @@ -6,6 +6,8 @@
>>
>>   /dts-v1/;
>>
>> +#include <dt-bindings/gpio/gpio.h>
>> +
>>   /include/ "skeleton.dtsi"
>>   /include/ "serial.dtsi"
>>
>> @@ -21,6 +23,25 @@
>>                  silent_console = <0>;
>>          };
>>
>> +       pch_pinctrl {
>> +               compatible = "intel,ich6-pinctrl";
> I guess the prefix 'ich6' is debatable.
>

I hesitated with 'x86' but I'm open to any suggestion.

>> +               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 = <0x258>;
>> +                       mode-gpio;
>> +                       output-value = <1>;
>> +                       direction = <PIN_OUTPUT>;
>> +               };
>> +       };
>> +
>>          gpioa {
>>                  compatible = "intel,ich6-gpio";
>>                  u-boot,dm-pre-reloc;
>> diff --git a/arch/x86/include/asm/arch-baytrail/gpio.h b/arch/x86/include/asm/arch-baytrail/gpio.h
>> index 4e8987c..85a65a8 100644
>> --- a/arch/x86/include/asm/arch-baytrail/gpio.h
>> +++ b/arch/x86/include/asm/arch-baytrail/gpio.h
>> @@ -9,5 +9,6 @@
>>
>>   /* Where in config space is the register that points to the GPIO registers? */
>>   #define PCI_CFG_GPIOBASE 0x48
>> +#define PCI_CFG_IOBASE   0x4c
>>
>>   #endif /* _X86_ARCH_GPIO_H_ */
>> diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h
>> index 1099427..ed85b08 100644
>> --- a/arch/x86/include/asm/gpio.h
>> +++ b/arch/x86/include/asm/gpio.h
>> @@ -147,6 +147,7 @@ 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/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
>> index 7e679a0..a110d5b 100644
>> --- a/drivers/gpio/intel_ich6_gpio.c
>> +++ b/drivers/gpio/intel_ich6_gpio.c
>> @@ -44,21 +44,32 @@ struct ich6_bank_priv {
>>          uint16_t 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_MASK         0x3
>> +#define IOPAD_PULL_ASSIGN_SHIFT                7
>> +#define IOPAD_PULL_STRENGTH_MASK       0x3
>> +#define IOPAD_PULL_STRENGTH_SHIFT      9
>> +
>> +static int __ich6_gpio_set_value(uint16_t base, unsigned offset, int value);
>> +static int __ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir);
>> +static int __ich6_gpio_set_function(uint16_t base, unsigned offset, int func);
>> +
>>   /* TODO: Move this to device tree, or platform data */
>>   void ich_gpio_set_gpio_map(const struct pch_gpio_map *map)
>>   {
>>          gd->arch.gpio_map = map;
>>   }
>>
>> -static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>> +static int gpio_ich6_get_base(unsigned long base)
>>   {
>> -       struct ich6_bank_platdata *plat = dev_get_platdata(dev);
>>          pci_dev_t pci_dev;                      /* handle for 0:1f:0 */
>>          u8 tmpbyte;
>>          u16 tmpword;
>>          u32 tmplong;
>> -       u16 gpiobase;
>> -       int offset;
>>
>>          /* Where should it be? */
>>          pci_dev = PCI_BDF(0, 0x1f, 0);
>> @@ -123,9 +134,9 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>>           * while on the Ivybridge the bit0 is used to indicate it is an
>>           * I/O space.
>>           */
>> -       tmplong = x86_pci_read_config32(pci_dev, PCI_CFG_GPIOBASE);
>> +       tmplong = x86_pci_read_config32(pci_dev, base);
>>          if (tmplong == 0x00000000 || tmplong == 0xffffffff) {
>> -               debug("%s: unexpected GPIOBASE value\n", __func__);
>> +               debug("%s: unexpected BASE value\n", __func__);
>>                  return -ENODEV;
>>          }
>>
>> @@ -135,7 +146,138 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>>           * at the offset that we just read. Bit 0 indicates that it's
>>           * an I/O address, not a memory address, so mask that off.
>>           */
>> -       gpiobase = tmplong & 0xfffe;
>> +       return tmplong & 0xfffc;
>> +}
>> +
>> +int gpio_ich6_pinctrl_init(void)
>> +{
>> +       int pin_node;
>> +       int node;
>> +       u32 iobase;
>> +       u32 gpiobase;
>> +
>> +       /*
>> +        * 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
>> +        */
>> +       iobase = gpio_ich6_get_base(PCI_CFG_IOBASE);
> I believe this breaks other x86 boards as PCI_CFG_IOBASE is baytrail-specific.

Well ... good point :). As Simon suggested, I might put the IOBASE into 
the device tree.

>> +       if (iobase < 0) {
>> +               debug("%s: invalid IOBASE address (%08x)\n", __func__, iobase);
>> +               return -EINVAL;
>> +       }
>> +
>> +       gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
>> +       if (iobase < 0) {
>> +               debug("%s: invalid IOBASE address (%08x)\n", __func__, iobase);
>> +               return -EINVAL;
>> +       }
>> +
>> +       /* This is not an error to not have a pinctrl node */
>> +       node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
>> +                                            "intel,ich6-pinctrl");
>> +       if (node < 0)
>> +               return 0;
>> +
>> +       for (pin_node = fdt_first_subnode(gd->fdt_blob, node);
>> +            pin_node > 0;
>> +            pin_node = fdt_next_subnode(gd->fdt_blob, pin_node)) {
>> +               u32 gpio_offset[2] = { -1, -1 };
>> +               u32 pad_offset;
>> +               u32 tmplong;
>> +               const void *tmpnode;
>> +
>> +               /*
>> +                * The offset for the same pin for the IOBASE and GPIOBASE are
>> +                * different, so instead of maintaining a lookup table,
>> +                * the device tree should provide directly the correct
>> +                * value for both mapping.
>> +                */
>> +               pad_offset = fdtdec_get_int(gd->fdt_blob, pin_node,
>> +                                           "pad-offset", -1);
>> +               if (pad_offset == -1) {
>> +                       debug("%s: Invalid register io offset %d\n",
>> +                             __func__, pad_offset);
>> +                       return -EINVAL;
>> +               }
>> +
>> +               /*
>> +                * GPIO node is not mandatory, so we only do the
>> +                * pinmuxing if the node exist.
>> +                */
>> +               fdtdec_get_int_array(gd->fdt_blob, pin_node,
>> +                                    "gpio-offset", gpio_offset, 2);
>> +               if (gpio_offset[0] != -1) {
>> +                       /* Do we want to force the GPIO mode? */
>> +                       tmpnode = fdt_getprop(gd->fdt_blob, pin_node,
>> +                                             "mode-gpio", NULL);
>> +                       if (tmpnode)
>> +                               __ich6_gpio_set_function(GPIO_USESEL_OFFSET
>> +                                                        (gpiobase) +
>> +                                                        gpio_offset[0],
>> +                                                        gpio_offset[1], 1);
>> +
>> +                       tmplong =
>> +                           fdtdec_get_int(gd->fdt_blob, pin_node, "direction",
>> +                                          -1);
>> +                       if (tmplong != -1)
>> +                               __ich6_gpio_set_direction(GPIO_IOSEL_OFFSET
>> +                                                         (gpiobase) +
>> +                                                         gpio_offset[0],
>> +                                                         gpio_offset[1],
>> +                                                         tmplong);
>> +
>> +                       tmplong =
>> +                           fdtdec_get_int(gd->fdt_blob, pin_node,
>> +                                          "output-value", -1);
>> +                       if (tmplong != -1)
>> +                               __ich6_gpio_set_value(GPIO_LVL_OFFSET(gpiobase)
>> +                                                     + gpio_offset[0],
>> +                                                     gpio_offset[1], tmplong);
>> +               }
>> +
>> +               /*
>> +                * Do we need to set a specific function mode?
>> +                * If someone put also 'mode-gpio', this option will
>> +                * be just ignored by the controller
>> +                */
>> +               tmplong =
>> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "mode-func", -1);
>> +               if (tmplong != -1)
>> +                       clrsetbits_le32(iobase + pad_offset, IOPAD_MODE_MASK,
>> +                                       tmplong);
>> +
>> +               /* Configure the pull-up/down if needed */
>> +               tmplong =
>> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "pull-assign", -1);
>> +               if (tmplong != -1)
>> +                       clrsetbits_le32(iobase + pad_offset,
>> +                                       IOPAD_PULL_ASSIGN_MASK <<
>> +                                       IOPAD_PULL_ASSIGN_SHIFT,
>> +                                       tmplong << IOPAD_PULL_ASSIGN_SHIFT);
>> +
>> +               tmplong =
>> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "pull-strength", -1);
>> +               if (tmplong != -1)
>> +                       clrsetbits_le32(iobase + pad_offset,
>> +                                       IOPAD_PULL_STRENGTH_MASK <<
>> +                                       IOPAD_PULL_STRENGTH_SHIFT,
>> +                                       tmplong << IOPAD_PULL_STRENGTH_SHIFT);
>> +
>> +               debug("%s: pad cfg [0x%x]: %08x\n", __func__, pad_offset,
>> +                     readl(iobase + pad_offset));
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>> +{
>> +       struct ich6_bank_platdata *plat = dev_get_platdata(dev);
>> +       u16 gpiobase;
>> +       int offset;
>> +
>> +       gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
>>          offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
>>          if (offset == -1) {
>>                  debug("%s: Invalid register offset %d\n", __func__, offset);
>> @@ -189,33 +331,56 @@ static int ich6_gpio_request(struct udevice *dev, unsigned offset,
>>          return 0;
>>   }
>>
>> -static int ich6_gpio_direction_input(struct udevice *dev, unsigned offset)
>> +static int __ich6_gpio_set_function(uint16_t base, unsigned offset, int func)
>>   {
>> -       struct ich6_bank_priv *bank = dev_get_priv(dev);
>>          u32 tmplong;
>>
>> -       tmplong = inl(bank->io_sel);
>> -       tmplong |= (1UL << offset);
>> -       outl(bank->io_sel, tmplong);
>> +       if (func) {
>> +               tmplong = inl(base);
>> +               tmplong |= (1UL << offset);
>> +               outl(tmplong, base);
>> +       } else {
>> +               tmplong = inl(base);
>> +               tmplong &= ~(1UL << offset);
>> +               outl(tmplong, base);
>> +       }
>> +
>>          return 0;
>>   }
>>
>> -static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
>> -                                      int value)
>> +static int __ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir)
>>   {
>> -       struct ich6_bank_priv *bank = dev_get_priv(dev);
>>          u32 tmplong;
>>
>> -       gpio_set_value(offset, value);
>> +       if (!dir) {
>> +               tmplong = inl(base);
>> +               tmplong |= (1UL << offset);
>> +               outl(tmplong, base);
>> +       } else {
>> +               tmplong = inl(base);
>> +               tmplong &= ~(1UL << offset);
>> +               outl(tmplong, base);
>> +       }
>>
>> -       tmplong = inl(bank->io_sel);
>> -       tmplong &= ~(1UL << offset);
>> -       outl(bank->io_sel, tmplong);
>>          return 0;
>>   }
>>
>> -static int ich6_gpio_get_value(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(inl(bank->io_sel), offset, 0);
>> +}
>> +
>> +static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
>> +               int value)
>> +{
>> +       struct ich6_bank_priv *bank = dev_get_priv(dev);
>> +
>> +       return __ich6_gpio_set_direction(inl(bank->io_sel), offset, 1);
>> +}
>>
>> +static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
>>   {
>>          struct ich6_bank_priv *bank = dev_get_priv(dev);
>>          u32 tmplong;
>> @@ -226,21 +391,26 @@ 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)
>> +static int __ich6_gpio_set_value(uint16_t base, unsigned offset, int value)
>>   {
>> -       struct ich6_bank_priv *bank = dev_get_priv(dev);
>>          u32 tmplong;
>> -
>> -       tmplong = inl(bank->lvl);
>> +       tmplong = inl(base);
>>          if (value)
>>                  tmplong |= (1UL << offset);
>>          else
>>                  tmplong &= ~(1UL << offset);
>> -       outl(bank->lvl, tmplong);
>> +       outl(tmplong, base);
>> +
>>          return 0;
>>   }
>>
>> +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);
>> diff --git a/include/dt-bindings/gpio/gpio.h b/include/dt-bindings/gpio/gpio.h
>> index e6b1e0a..49d437c 100644
>> --- a/include/dt-bindings/gpio/gpio.h
>> +++ b/include/dt-bindings/gpio/gpio.h
>> @@ -12,4 +12,24 @@
>>   #define GPIO_ACTIVE_HIGH 0
>>   #define GPIO_ACTIVE_LOW 1
>>
>> +#define GPIO_MODE_NATIVE       0
>> +#define GPIO_MODE_GPIO         1
>> +
>> +#define GPIO_MODE_FUNC0        0
>> +#define GPIO_MODE_FUNC1        1
>> +#define GPIO_MODE_FUNC2        2
>> +#define GPIO_MODE_FUNC4        4
>> +#define GPIO_MODE_FUNC5        5
>> +#define GPIO_MODE_FUNC6        6
>> +
>> +#define PIN_INPUT              0
>> +#define PIN_OUTPUT             1
>> +
>> +#define PIN_INPUT_NOPULL       0
>> +#define PIN_INPUT_PULLUP       1
>> +#define PIN_INPUT_PULLDOWN     2
>> +
>> +#define PULL_STR_2K            0
>> +#define PULL_STR_20K   2
>> +
>>   #endif
>> --
> Regards,
> Bin

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 3/4] x86: gpio: add pinctrl support from the device tree
  2015-04-24  3:35   ` Simon Glass
@ 2015-04-24 14:37     ` Gabriel Huau
  2015-04-24 17:55     ` [U-Boot] unassigned-patches/150: " u-boot at bugs.denx.de
  1 sibling, 0 replies; 61+ messages in thread
From: Gabriel Huau @ 2015-04-24 14:37 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 04/23/2015 08:35 PM, Simon Glass wrote:
> Hi,
>
> On 23 April 2015 at 10:16, Gabriel Huau <contact@huau-gabriel.fr> wrote:
>> A set of properties has been defined for the device tree to select for
>> each pin the pull/func/default output configuration.
>>
>> The offset for the PAD needs to be provided and if a GPIO needs to be
>> configured, his offset needs to be provided as well.
>>
>> Here is an example:
>> pin_usb_host_en0 at 0 {
>>      gpio-offset = <0x80 8>;
>>      pad-offset = <0x260>;
>>      mode-gpio;
>>      output-value = <1>;
>>      direction = <PIN_OUTPUT>;
>> };
>>
>> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
>> ---
>>   arch/x86/dts/minnowmax.dts                |  21 +++
>>   arch/x86/include/asm/arch-baytrail/gpio.h |   1 +
>>   arch/x86/include/asm/gpio.h               |   1 +
>>   drivers/gpio/intel_ich6_gpio.c            | 222 ++++++++++++++++++++++++++----
>>   include/dt-bindings/gpio/gpio.h           |  20 +++
>>   5 files changed, 239 insertions(+), 26 deletions(-)
>>
>> diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
>> index c73e421..3936e21 100644
>> --- a/arch/x86/dts/minnowmax.dts
>> +++ b/arch/x86/dts/minnowmax.dts
>> @@ -6,6 +6,8 @@
>>
>>   /dts-v1/;
>>
>> +#include <dt-bindings/gpio/gpio.h>
>> +
>>   /include/ "skeleton.dtsi"
>>   /include/ "serial.dtsi"
>>
>> @@ -21,6 +23,25 @@
>>                  silent_console = <0>;
>>          };
>>
>> +       pch_pinctrl {
>> +               compatible = "intel,ich6-pinctrl";
> Make sure you use tabs for indenting here.
>
> You should create a binding file to describe your binding - in
> doc/device-tree-bindings.
>
>> +               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 = <0x258>;
>> +                       mode-gpio;
>> +                       output-value = <1>;
>> +                       direction = <PIN_OUTPUT>;
>> +               };
>> +       };
>> +
>>          gpioa {
>>                  compatible = "intel,ich6-gpio";
>>                  u-boot,dm-pre-reloc;
>> diff --git a/arch/x86/include/asm/arch-baytrail/gpio.h b/arch/x86/include/asm/arch-baytrail/gpio.h
>> index 4e8987c..85a65a8 100644
>> --- a/arch/x86/include/asm/arch-baytrail/gpio.h
>> +++ b/arch/x86/include/asm/arch-baytrail/gpio.h
>> @@ -9,5 +9,6 @@
>>
>>   /* Where in config space is the register that points to the GPIO registers? */
>>   #define PCI_CFG_GPIOBASE 0x48
>> +#define PCI_CFG_IOBASE   0x4c
>>
>>   #endif /* _X86_ARCH_GPIO_H_ */
>> diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h
>> index 1099427..ed85b08 100644
>> --- a/arch/x86/include/asm/gpio.h
>> +++ b/arch/x86/include/asm/gpio.h
>> @@ -147,6 +147,7 @@ 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/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
>> index 7e679a0..a110d5b 100644
>> --- a/drivers/gpio/intel_ich6_gpio.c
>> +++ b/drivers/gpio/intel_ich6_gpio.c
>> @@ -44,21 +44,32 @@ struct ich6_bank_priv {
>>          uint16_t lvl;
>>   };
>>
>> +#define GPIO_USESEL_OFFSET(x) (x)
>> +#define GPIO_IOSEL_OFFSET(x) (x + 4)
>> +#define GPIO_LVL_OFFSET(x) (x + 8)
> Comments on the above
>
>> +
>> +#define IOPAD_MODE_MASK                                0x7
>> +#define IOPAD_PULL_ASSIGN_MASK         0x3
>> +#define IOPAD_PULL_ASSIGN_SHIFT                7
> Can you make the mask value an actual valid mask, like:
>
>   +#define IOPAD_PULL_ASSIGN_MASK         (0x3 << IOPAD_PULL_ASSIGN_SHIFT)
>
>> +#define IOPAD_PULL_STRENGTH_MASK       0x3
>> +#define IOPAD_PULL_STRENGTH_SHIFT      9
>> +
>> +static int __ich6_gpio_set_value(uint16_t base, unsigned offset, int value);
> Can you reorder the functions to avoid the need for these forward
> declarations? Also only one underscore prefix please.
>
>> +static int __ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir);
>> +static int __ich6_gpio_set_function(uint16_t base, unsigned offset, int func);
>> +
>>   /* TODO: Move this to device tree, or platform data */
>>   void ich_gpio_set_gpio_map(const struct pch_gpio_map *map)
>>   {
>>          gd->arch.gpio_map = map;
>>   }
>>
>> -static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>> +static int gpio_ich6_get_base(unsigned long base)
>>   {
>> -       struct ich6_bank_platdata *plat = dev_get_platdata(dev);
>>          pci_dev_t pci_dev;                      /* handle for 0:1f:0 */
>>          u8 tmpbyte;
>>          u16 tmpword;
>>          u32 tmplong;
>> -       u16 gpiobase;
>> -       int offset;
>>
>>          /* Where should it be? */
>>          pci_dev = PCI_BDF(0, 0x1f, 0);
>> @@ -123,9 +134,9 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>>           * while on the Ivybridge the bit0 is used to indicate it is an
>>           * I/O space.
>>           */
>> -       tmplong = x86_pci_read_config32(pci_dev, PCI_CFG_GPIOBASE);
> Can the base come from the device tree somewhere? E.g.
>
> pch {
>      gpio {
>         reg = <some value>;
>
> There is something like this in chromebook_link.dts.

Sounds good and will answer to another issue to was breaking actually 
the other board ...

>> +       tmplong = x86_pci_read_config32(pci_dev, base);
>>          if (tmplong == 0x00000000 || tmplong == 0xffffffff) {
>> -               debug("%s: unexpected GPIOBASE value\n", __func__);
>> +               debug("%s: unexpected BASE value\n", __func__);
>>                  return -ENODEV;
>>          }
>>
>> @@ -135,7 +146,138 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>>           * at the offset that we just read. Bit 0 indicates that it's
>>           * an I/O address, not a memory address, so mask that off.
>>           */
>> -       gpiobase = tmplong & 0xfffe;
>> +       return tmplong & 0xfffc;
>> +}
>> +
>> +int gpio_ich6_pinctrl_init(void)
>> +{
>> +       int pin_node;
>> +       int node;
>> +       u32 iobase;
>> +       u32 gpiobase;
>> +
>> +       /*
>> +        * 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
>> +        */
>> +       iobase = gpio_ich6_get_base(PCI_CFG_IOBASE);
>> +       if (iobase < 0) {
>> +               debug("%s: invalid IOBASE address (%08x)\n", __func__, iobase);
>> +               return -EINVAL;
>> +       }
>> +
>> +       gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
>> +       if (iobase < 0) {
>> +               debug("%s: invalid IOBASE address (%08x)\n", __func__, iobase);
>> +               return -EINVAL;
>> +       }
>> +
>> +       /* This is not an error to not have a pinctrl node */
>> +       node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
>> +                                            "intel,ich6-pinctrl");
>> +       if (node < 0)
>> +               return 0;
> Probably this should move to driver model, but let's worry about that later.
Agreed, for the first version I would like to have an easy 
implementation that we can move to driver model later.
>> +
>> +       for (pin_node = fdt_first_subnode(gd->fdt_blob, node);
>> +            pin_node > 0;
>> +            pin_node = fdt_next_subnode(gd->fdt_blob, pin_node)) {
>> +               u32 gpio_offset[2] = { -1, -1 };
>> +               u32 pad_offset;
>> +               u32 tmplong;
>> +               const void *tmpnode;
>> +
>> +               /*
>> +                * The offset for the same pin for the IOBASE and GPIOBASE are
>> +                * different, so instead of maintaining a lookup table,
>> +                * the device tree should provide directly the correct
>> +                * value for both mapping.
>> +                */
>> +               pad_offset = fdtdec_get_int(gd->fdt_blob, pin_node,
>> +                                           "pad-offset", -1);
>> +               if (pad_offset == -1) {
>> +                       debug("%s: Invalid register io offset %d\n",
>> +                             __func__, pad_offset);
>> +                       return -EINVAL;
>> +               }
>> +
>> +               /*
>> +                * GPIO node is not mandatory, so we only do the
>> +                * pinmuxing if the node exist.
>> +                */
>> +               fdtdec_get_int_array(gd->fdt_blob, pin_node,
>> +                                    "gpio-offset", gpio_offset, 2);
>> +               if (gpio_offset[0] != -1) {
> Can you move this block into its own function without too much trouble?
Agreed.

>> +                       /* Do we want to force the GPIO mode? */
>> +                       tmpnode = fdt_getprop(gd->fdt_blob, pin_node,
>> +                                             "mode-gpio", NULL);
>> +                       if (tmpnode)
>> +                               __ich6_gpio_set_function(GPIO_USESEL_OFFSET
>> +                                                        (gpiobase) +
>> +                                                        gpio_offset[0],
>> +                                                        gpio_offset[1], 1);
>> +
>> +                       tmplong =
>> +                           fdtdec_get_int(gd->fdt_blob, pin_node, "direction",
>> +                                          -1);
>> +                       if (tmplong != -1)
> But tmplong is unsigned.

This is not how we do to never have an error? ;)

I'll do the modification.

>> +                               __ich6_gpio_set_direction(GPIO_IOSEL_OFFSET
>> +                                                         (gpiobase) +
>> +                                                         gpio_offset[0],
>> +                                                         gpio_offset[1],
>> +                                                         tmplong);
>> +
>> +                       tmplong =
>> +                           fdtdec_get_int(gd->fdt_blob, pin_node,
>> +                                          "output-value", -1);
>> +                       if (tmplong != -1)
>> +                               __ich6_gpio_set_value(GPIO_LVL_OFFSET(gpiobase)
>> +                                                     + gpio_offset[0],
>> +                                                     gpio_offset[1], tmplong);
>> +               }
>> +
>> +               /*
>> +                * Do we need to set a specific function mode?
>> +                * If someone put also 'mode-gpio', this option will
>> +                * be just ignored by the controller
>> +                */
>> +               tmplong =
>> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "mode-func", -1);
>> +               if (tmplong != -1)
>> +                       clrsetbits_le32(iobase + pad_offset, IOPAD_MODE_MASK,
>> +                                       tmplong);
>> +
>> +               /* Configure the pull-up/down if needed */
>> +               tmplong =
>> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "pull-assign", -1);
>> +               if (tmplong != -1)
>> +                       clrsetbits_le32(iobase + pad_offset,
>> +                                       IOPAD_PULL_ASSIGN_MASK <<
>> +                                       IOPAD_PULL_ASSIGN_SHIFT,
>> +                                       tmplong << IOPAD_PULL_ASSIGN_SHIFT);
>> +
>> +               tmplong =
>> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "pull-strength", -1);
>> +               if (tmplong != -1)
>> +                       clrsetbits_le32(iobase + pad_offset,
>> +                                       IOPAD_PULL_STRENGTH_MASK <<
>> +                                       IOPAD_PULL_STRENGTH_SHIFT,
>> +                                       tmplong << IOPAD_PULL_STRENGTH_SHIFT);
>> +
>> +               debug("%s: pad cfg [0x%x]: %08x\n", __func__, pad_offset,
>> +                     readl(iobase + pad_offset));
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>> +{
>> +       struct ich6_bank_platdata *plat = dev_get_platdata(dev);
>> +       u16 gpiobase;
>> +       int offset;
>> +
>> +       gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
>>          offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
>>          if (offset == -1) {
>>                  debug("%s: Invalid register offset %d\n", __func__, offset);
>> @@ -189,33 +331,56 @@ static int ich6_gpio_request(struct udevice *dev, unsigned offset,
>>          return 0;
>>   }
>>
>> -static int ich6_gpio_direction_input(struct udevice *dev, unsigned offset)
>> +static int __ich6_gpio_set_function(uint16_t base, unsigned offset, int func)
>>   {
>> -       struct ich6_bank_priv *bank = dev_get_priv(dev);
>>          u32 tmplong;
>>
>> -       tmplong = inl(bank->io_sel);
>> -       tmplong |= (1UL << offset);
>> -       outl(bank->io_sel, tmplong);
>> +       if (func) {
>> +               tmplong = inl(base);
>> +               tmplong |= (1UL << offset);
>> +               outl(tmplong, base);
>> +       } else {
>> +               tmplong = inl(base);
>> +               tmplong &= ~(1UL << offset);
>> +               outl(tmplong, base);
>> +       }
>> +
>>          return 0;
>>   }
>>
>> -static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
>> -                                      int value)
>> +static int __ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir)
>>   {
>> -       struct ich6_bank_priv *bank = dev_get_priv(dev);
>>          u32 tmplong;
>>
>> -       gpio_set_value(offset, value);
>> +       if (!dir) {
>> +               tmplong = inl(base);
>> +               tmplong |= (1UL << offset);
>> +               outl(tmplong, base);
>> +       } else {
>> +               tmplong = inl(base);
>> +               tmplong &= ~(1UL << offset);
>> +               outl(tmplong, base);
>> +       }
>>
>> -       tmplong = inl(bank->io_sel);
>> -       tmplong &= ~(1UL << offset);
>> -       outl(bank->io_sel, tmplong);
>>          return 0;
>>   }
>>
>> -static int ich6_gpio_get_value(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(inl(bank->io_sel), offset, 0);
>> +}
>> +
>> +static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
>> +               int value)
>> +{
>> +       struct ich6_bank_priv *bank = dev_get_priv(dev);
>> +
>> +       return __ich6_gpio_set_direction(inl(bank->io_sel), offset, 1);
>> +}
>>
>> +static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
>>   {
>>          struct ich6_bank_priv *bank = dev_get_priv(dev);
>>          u32 tmplong;
>> @@ -226,21 +391,26 @@ 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)
>> +static int __ich6_gpio_set_value(uint16_t base, unsigned offset, int value)
>>   {
>> -       struct ich6_bank_priv *bank = dev_get_priv(dev);
>>          u32 tmplong;
>> -
>> -       tmplong = inl(bank->lvl);
>> +       tmplong = inl(base);
>>          if (value)
>>                  tmplong |= (1UL << offset);
>>          else
>>                  tmplong &= ~(1UL << offset);
>> -       outl(bank->lvl, tmplong);
>> +       outl(tmplong, base);
>> +
>>          return 0;
>>   }
>>
>> +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);
>> diff --git a/include/dt-bindings/gpio/gpio.h b/include/dt-bindings/gpio/gpio.h
>> index e6b1e0a..49d437c 100644
>> --- a/include/dt-bindings/gpio/gpio.h
>> +++ b/include/dt-bindings/gpio/gpio.h
>> @@ -12,4 +12,24 @@
>>   #define GPIO_ACTIVE_HIGH 0
>>   #define GPIO_ACTIVE_LOW 1
>>
>> +#define GPIO_MODE_NATIVE       0
>> +#define GPIO_MODE_GPIO         1
>> +
>> +#define GPIO_MODE_FUNC0        0
>> +#define GPIO_MODE_FUNC1        1
>> +#define GPIO_MODE_FUNC2        2
>> +#define GPIO_MODE_FUNC4        4
>> +#define GPIO_MODE_FUNC5        5
>> +#define GPIO_MODE_FUNC6        6
> Can we use an enum for these? They mostly count up.

Agreed.

>> +
>> +#define PIN_INPUT              0
>> +#define PIN_OUTPUT             1
>> +
>> +#define PIN_INPUT_NOPULL       0
>> +#define PIN_INPUT_PULLUP       1
>> +#define PIN_INPUT_PULLDOWN     2
>> +
>> +#define PULL_STR_2K            0
>> +#define PULL_STR_20K   2
>> +
>>   #endif
>> --
>> 2.1.4
>>
> Regards,
> Simon

Regards,
Gabriel

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 0/4] x86: support of pin-muxing from device tree
  2015-04-24  3:23 ` [U-Boot] [PATCH 0/4] x86: support of " Bin Meng
@ 2015-04-24 14:40   ` Gabriel Huau
  2015-04-24 17:55   ` [U-Boot] unassigned-patches/151: " u-boot at bugs.denx.de
  1 sibling, 0 replies; 61+ messages in thread
From: Gabriel Huau @ 2015-04-24 14:40 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On 04/23/2015 08:23 PM, Bin Meng wrote:
> Hi Gabriel,
>
> On Fri, Apr 24, 2015 at 12:16 AM, Gabriel Huau <contact@huau-gabriel.fr> wrote:
>> This serie of patches adds the support of pin-muxing from the device tree through
>> different properties. I have put two example to enable the USB Host on the
>> minnowboard max.
>>
>> The support of the call to 'setup_pch_gpios' is still supported and
>> only the minnowboard has been tested with the device tree implementation.
>>
>> Because the GPIO and IO base register ares different, I have also defined
>> some proxy function to set the function/value and direction of the GPIO as
>> the GPIO register can override some registers in the IO.
>>
>> Gabriel Huau (4):
>>    x86: baytrail: fix the GPIOBASE address
>>    x86: minnowmax: add GPIO banks in the device tree
>>    x86: gpio: add pinctrl support from the device tree
>>    x86: minnowmax: initialize the pin-muxing from device tree
>>
>>   arch/x86/dts/minnowmax.dts                |  63 +++++++++
>>   arch/x86/include/asm/arch-baytrail/gpio.h |   3 +-
>>   arch/x86/include/asm/gpio.h               |   1 +
>>   board/intel/minnowmax/minnowmax.c         |   9 ++
>>   drivers/gpio/intel_ich6_gpio.c            | 222 ++++++++++++++++++++++++++----
>>   include/configs/minnowmax.h               |   1 +
>>   include/dt-bindings/gpio/gpio.h           |  20 +++
>>   7 files changed, 292 insertions(+), 27 deletions(-)
>>
>> --
> Thanks for these patches! Just a general comment, you don't need send
> emails to u-boot-patches at bugs.denx.de, and always include a simple
> sentence in the commit message :)
>
> Regards,
> Bin
That's why I received plenty of emails to tell me that my patches were 
not assigned :).
I'll do the modification for the next version, thank you for the 
feedback, I appreciate this.

Regards,
Gabriel

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] unassigned-patches/150: Re: [PATCH 3/4] x86: gpio: add pinctrl support from the device tree
  2015-04-24  3:35   ` Simon Glass
  2015-04-24 14:37     ` Gabriel Huau
@ 2015-04-24 17:55     ` u-boot at bugs.denx.de
  1 sibling, 0 replies; 61+ messages in thread
From: u-boot at bugs.denx.de @ 2015-04-24 17:55 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 04/23/2015 08:35 PM, Simon Glass wrote:
> Hi,
>
> On 23 April 2015 at 10:16, Gabriel Huau <contact@huau-gabriel.fr> wrote:
>> A set of properties has been defined for the device tree to select for
>> each pin the pull/func/default output configuration.
>>
>> The offset for the PAD needs to be provided and if a GPIO needs to be
>> configured, his offset needs to be provided as well.
>>
>> Here is an example:
>> pin_usb_host_en0 at 0 {
>>      gpio-offset = <0x80 8>;
>>      pad-offset = <0x260>;
>>      mode-gpio;
>>      output-value = <1>;
>>      direction = <PIN_OUTPUT>;
>> };
>>
>> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
>> ---
>>   arch/x86/dts/minnowmax.dts                |  21 +++
>>   arch/x86/include/asm/arch-baytrail/gpio.h |   1 +
>>   arch/x86/include/asm/gpio.h               |   1 +
>>   drivers/gpio/intel_ich6_gpio.c            | 222 ++++++++++++++++++++++++++----
>>   include/dt-bindings/gpio/gpio.h           |  20 +++
>>   5 files changed, 239 insertions(+), 26 deletions(-)
>>
>> diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
>> index c73e421..3936e21 100644
>> --- a/arch/x86/dts/minnowmax.dts
>> +++ b/arch/x86/dts/minnowmax.dts
>> @@ -6,6 +6,8 @@
>>
>>   /dts-v1/;
>>
>> +#include <dt-bindings/gpio/gpio.h>
>> +
>>   /include/ "skeleton.dtsi"
>>   /include/ "serial.dtsi"
>>
>> @@ -21,6 +23,25 @@
>>                  silent_console = <0>;
>>          };
>>
>> +       pch_pinctrl {
>> +               compatible = "intel,ich6-pinctrl";
> Make sure you use tabs for indenting here.
>
> You should create a binding file to describe your binding - in
> doc/device-tree-bindings.
>
>> +               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 = <0x258>;
>> +                       mode-gpio;
>> +                       output-value = <1>;
>> +                       direction = <PIN_OUTPUT>;
>> +               };
>> +       };
>> +
>>          gpioa {
>>                  compatible = "intel,ich6-gpio";
>>                  u-boot,dm-pre-reloc;
>> diff --git a/arch/x86/include/asm/arch-baytrail/gpio.h b/arch/x86/include/asm/arch-baytrail/gpio.h
>> index 4e8987c..85a65a8 100644
>> --- a/arch/x86/include/asm/arch-baytrail/gpio.h
>> +++ b/arch/x86/include/asm/arch-baytrail/gpio.h
>> @@ -9,5 +9,6 @@
>>
>>   /* Where in config space is the register that points to the GPIO registers? */
>>   #define PCI_CFG_GPIOBASE 0x48
>> +#define PCI_CFG_IOBASE   0x4c
>>
>>   #endif /* _X86_ARCH_GPIO_H_ */
>> diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h
>> index 1099427..ed85b08 100644
>> --- a/arch/x86/include/asm/gpio.h
>> +++ b/arch/x86/include/asm/gpio.h
>> @@ -147,6 +147,7 @@ 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/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
>> index 7e679a0..a110d5b 100644
>> --- a/drivers/gpio/intel_ich6_gpio.c
>> +++ b/drivers/gpio/intel_ich6_gpio.c
>> @@ -44,21 +44,32 @@ struct ich6_bank_priv {
>>          uint16_t lvl;
>>   };
>>
>> +#define GPIO_USESEL_OFFSET(x) (x)
>> +#define GPIO_IOSEL_OFFSET(x) (x + 4)
>> +#define GPIO_LVL_OFFSET(x) (x + 8)
> Comments on the above
>
>> +
>> +#define IOPAD_MODE_MASK                                0x7
>> +#define IOPAD_PULL_ASSIGN_MASK         0x3
>> +#define IOPAD_PULL_ASSIGN_SHIFT                7
> Can you make the mask value an actual valid mask, like:
>
>   +#define IOPAD_PULL_ASSIGN_MASK         (0x3 << IOPAD_PULL_ASSIGN_SHIFT)
>
>> +#define IOPAD_PULL_STRENGTH_MASK       0x3
>> +#define IOPAD_PULL_STRENGTH_SHIFT      9
>> +
>> +static int __ich6_gpio_set_value(uint16_t base, unsigned offset, int value);
> Can you reorder the functions to avoid the need for these forward
> declarations? Also only one underscore prefix please.
>
>> +static int __ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir);
>> +static int __ich6_gpio_set_function(uint16_t base, unsigned offset, int func);
>> +
>>   /* TODO: Move this to device tree, or platform data */
>>   void ich_gpio_set_gpio_map(const struct pch_gpio_map *map)
>>   {
>>          gd->arch.gpio_map = map;
>>   }
>>
>> -static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>> +static int gpio_ich6_get_base(unsigned long base)
>>   {
>> -       struct ich6_bank_platdata *plat = dev_get_platdata(dev);
>>          pci_dev_t pci_dev;                      /* handle for 0:1f:0 */
>>          u8 tmpbyte;
>>          u16 tmpword;
>>          u32 tmplong;
>> -       u16 gpiobase;
>> -       int offset;
>>
>>          /* Where should it be? */
>>          pci_dev = PCI_BDF(0, 0x1f, 0);
>> @@ -123,9 +134,9 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>>           * while on the Ivybridge the bit0 is used to indicate it is an
>>           * I/O space.
>>           */
>> -       tmplong = x86_pci_read_config32(pci_dev, PCI_CFG_GPIOBASE);
> Can the base come from the device tree somewhere? E.g.
>
> pch {
>      gpio {
>         reg = <some value>;
>
> There is something like this in chromebook_link.dts.

Sounds good and will answer to another issue to was breaking actually
the other board ...

>> +       tmplong = x86_pci_read_config32(pci_dev, base);
>>          if (tmplong == 0x00000000 || tmplong == 0xffffffff) {
>> -               debug("%s: unexpected GPIOBASE value\n", __func__);
>> +               debug("%s: unexpected BASE value\n", __func__);
>>                  return -ENODEV;
>>          }
>>
>> @@ -135,7 +146,138 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>>           * at the offset that we just read. Bit 0 indicates that it's
>>           * an I/O address, not a memory address, so mask that off.
>>           */
>> -       gpiobase = tmplong & 0xfffe;
>> +       return tmplong & 0xfffc;
>> +}
>> +
>> +int gpio_ich6_pinctrl_init(void)
>> +{
>> +       int pin_node;
>> +       int node;
>> +       u32 iobase;
>> +       u32 gpiobase;
>> +
>> +       /*
>> +        * 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
>> +        */
>> +       iobase = gpio_ich6_get_base(PCI_CFG_IOBASE);
>> +       if (iobase < 0) {
>> +               debug("%s: invalid IOBASE address (%08x)\n", __func__, iobase);
>> +               return -EINVAL;
>> +       }
>> +
>> +       gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
>> +       if (iobase < 0) {
>> +               debug("%s: invalid IOBASE address (%08x)\n", __func__, iobase);
>> +               return -EINVAL;
>> +       }
>> +
>> +       /* This is not an error to not have a pinctrl node */
>> +       node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
>> +                                            "intel,ich6-pinctrl");
>> +       if (node < 0)
>> +               return 0;
> Probably this should move to driver model, but let's worry about that later.
Agreed, for the first version I would like to have an easy
implementation that we can move to driver model later.
>> +
>> +       for (pin_node = fdt_first_subnode(gd->fdt_blob, node);
>> +            pin_node > 0;
>> +            pin_node = fdt_next_subnode(gd->fdt_blob, pin_node)) {
>> +               u32 gpio_offset[2] = { -1, -1 };
>> +               u32 pad_offset;
>> +               u32 tmplong;
>> +               const void *tmpnode;
>> +
>> +               /*
>> +                * The offset for the same pin for the IOBASE and GPIOBASE are
>> +                * different, so instead of maintaining a lookup table,
>> +                * the device tree should provide directly the correct
>> +                * value for both mapping.
>> +                */
>> +               pad_offset = fdtdec_get_int(gd->fdt_blob, pin_node,
>> +                                           "pad-offset", -1);
>> +               if (pad_offset == -1) {
>> +                       debug("%s: Invalid register io offset %d\n",
>> +                             __func__, pad_offset);
>> +                       return -EINVAL;
>> +               }
>> +
>> +               /*
>> +                * GPIO node is not mandatory, so we only do the
>> +                * pinmuxing if the node exist.
>> +                */
>> +               fdtdec_get_int_array(gd->fdt_blob, pin_node,
>> +                                    "gpio-offset", gpio_offset, 2);
>> +               if (gpio_offset[0] != -1) {
> Can you move this block into its own function without too much trouble?
Agreed.

>> +                       /* Do we want to force the GPIO mode? */
>> +                       tmpnode = fdt_getprop(gd->fdt_blob, pin_node,
>> +                                             "mode-gpio", NULL);
>> +                       if (tmpnode)
>> +                               __ich6_gpio_set_function(GPIO_USESEL_OFFSET
>> +                                                        (gpiobase) +
>> +                                                        gpio_offset[0],
>> +                                                        gpio_offset[1], 1);
>> +
>> +                       tmplong =
>> +                           fdtdec_get_int(gd->fdt_blob, pin_node, "direction",
>> +                                          -1);
>> +                       if (tmplong != -1)
> But tmplong is unsigned.

This is not how we do to never have an error? ;)

I'll do the modification.

>> +                               __ich6_gpio_set_direction(GPIO_IOSEL_OFFSET
>> +                                                         (gpiobase) +
>> +                                                         gpio_offset[0],
>> +                                                         gpio_offset[1],
>> +                                                         tmplong);
>> +
>> +                       tmplong =
>> +                           fdtdec_get_int(gd->fdt_blob, pin_node,
>> +                                          "output-value", -1);
>> +                       if (tmplong != -1)
>> +                               __ich6_gpio_set_value(GPIO_LVL_OFFSET(gpiobase)
>> +                                                     + gpio_offset[0],
>> +                                                     gpio_offset[1], tmplong);
>> +               }
>> +
>> +               /*
>> +                * Do we need to set a specific function mode?
>> +                * If someone put also 'mode-gpio', this option will
>> +                * be just ignored by the controller
>> +                */
>> +               tmplong =
>> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "mode-func", -1);
>> +               if (tmplong != -1)
>> +                       clrsetbits_le32(iobase + pad_offset, IOPAD_MODE_MASK,
>> +                                       tmplong);
>> +
>> +               /* Configure the pull-up/down if needed */
>> +               tmplong =
>> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "pull-assign", -1);
>> +               if (tmplong != -1)
>> +                       clrsetbits_le32(iobase + pad_offset,
>> +                                       IOPAD_PULL_ASSIGN_MASK <<
>> +                                       IOPAD_PULL_ASSIGN_SHIFT,
>> +                                       tmplong << IOPAD_PULL_ASSIGN_SHIFT);
>> +
>> +               tmplong =
>> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "pull-strength", -1);
>> +               if (tmplong != -1)
>> +                       clrsetbits_le32(iobase + pad_offset,
>> +                                       IOPAD_PULL_STRENGTH_MASK <<
>> +                                       IOPAD_PULL_STRENGTH_SHIFT,
>> +                                       tmplong << IOPAD_PULL_STRENGTH_SHIFT);
>> +
>> +               debug("%s: pad cfg [0x%x]: %08x\n", __func__, pad_offset,
>> +                     readl(iobase + pad_offset));
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>> +{
>> +       struct ich6_bank_platdata *plat = dev_get_platdata(dev);
>> +       u16 gpiobase;
>> +       int offset;
>> +
>> +       gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
>>          offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
>>          if (offset == -1) {
>>                  debug("%s: Invalid register offset %d\n", __func__, offset);
>> @@ -189,33 +331,56 @@ static int ich6_gpio_request(struct udevice *dev, unsigned offset,
>>          return 0;
>>   }
>>
>> -static int ich6_gpio_direction_input(struct udevice *dev, unsigned offset)
>> +static int __ich6_gpio_set_function(uint16_t base, unsigned offset, int func)
>>   {
>> -       struct ich6_bank_priv *bank = dev_get_priv(dev);
>>          u32 tmplong;
>>
>> -       tmplong = inl(bank->io_sel);
>> -       tmplong |= (1UL << offset);
>> -       outl(bank->io_sel, tmplong);
>> +       if (func) {
>> +               tmplong = inl(base);
>> +               tmplong |= (1UL << offset);
>> +               outl(tmplong, base);
>> +       } else {
>> +               tmplong = inl(base);
>> +               tmplong &= ~(1UL << offset);
>> +               outl(tmplong, base);
>> +       }
>> +
>>          return 0;
>>   }
>>
>> -static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
>> -                                      int value)
>> +static int __ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir)
>>   {
>> -       struct ich6_bank_priv *bank = dev_get_priv(dev);
>>          u32 tmplong;
>>
>> -       gpio_set_value(offset, value);
>> +       if (!dir) {
>> +               tmplong = inl(base);
>> +               tmplong |= (1UL << offset);
>> +               outl(tmplong, base);
>> +       } else {
>> +               tmplong = inl(base);
>> +               tmplong &= ~(1UL << offset);
>> +               outl(tmplong, base);
>> +       }
>>
>> -       tmplong = inl(bank->io_sel);
>> -       tmplong &= ~(1UL << offset);
>> -       outl(bank->io_sel, tmplong);
>>          return 0;
>>   }
>>
>> -static int ich6_gpio_get_value(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(inl(bank->io_sel), offset, 0);
>> +}
>> +
>> +static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
>> +               int value)
>> +{
>> +       struct ich6_bank_priv *bank = dev_get_priv(dev);
>> +
>> +       return __ich6_gpio_set_direction(inl(bank->io_sel), offset, 1);
>> +}
>>
>> +static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
>>   {
>>          struct ich6_bank_priv *bank = dev_get_priv(dev);
>>          u32 tmplong;
>> @@ -226,21 +391,26 @@ 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)
>> +static int __ich6_gpio_set_value(uint16_t base, unsigned offset, int value)
>>   {
>> -       struct ich6_bank_priv *bank = dev_get_priv(dev);
>>          u32 tmplong;
>> -
>> -       tmplong = inl(bank->lvl);
>> +       tmplong = inl(base);
>>          if (value)
>>                  tmplong |= (1UL << offset);
>>          else
>>                  tmplong &= ~(1UL << offset);
>> -       outl(bank->lvl, tmplong);
>> +       outl(tmplong, base);
>> +
>>          return 0;
>>   }
>>
>> +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);
>> diff --git a/include/dt-bindings/gpio/gpio.h b/include/dt-bindings/gpio/gpio.h
>> index e6b1e0a..49d437c 100644
>> --- a/include/dt-bindings/gpio/gpio.h
>> +++ b/include/dt-bindings/gpio/gpio.h
>> @@ -12,4 +12,24 @@
>>   #define GPIO_ACTIVE_HIGH 0
>>   #define GPIO_ACTIVE_LOW 1
>>
>> +#define GPIO_MODE_NATIVE       0
>> +#define GPIO_MODE_GPIO         1
>> +
>> +#define GPIO_MODE_FUNC0        0
>> +#define GPIO_MODE_FUNC1        1
>> +#define GPIO_MODE_FUNC2        2
>> +#define GPIO_MODE_FUNC4        4
>> +#define GPIO_MODE_FUNC5        5
>> +#define GPIO_MODE_FUNC6        6
> Can we use an enum for these? They mostly count up.

Agreed.

>> +
>> +#define PIN_INPUT              0
>> +#define PIN_OUTPUT             1
>> +
>> +#define PIN_INPUT_NOPULL       0
>> +#define PIN_INPUT_PULLUP       1
>> +#define PIN_INPUT_PULLDOWN     2
>> +
>> +#define PULL_STR_2K            0
>> +#define PULL_STR_20K   2
>> +
>>   #endif
>> --
>> 2.1.4
>>
> Regards,
> Simon

Regards,
Gabriel

---
Added to GNATS database as unassigned-patches/150
>Responsible:    patch-coord
>Message-Id:     <553A551D.60305@huau-gabriel.fr>
>In-Reply-To:    <CAPnjgZ38cPE1h6EBg-ffdtOA4FhTdgTx8u1VS5yMpv9Ynik-KA@mail.gmail.com>
>References:     <1429805775-1809-1-git-send-email-contact@huau-gabriel.fr>	<1429805775-1809-4-git-send-email-contact@huau-gabriel.fr> <CAPnjgZ38cPE1h6EBg-ffdtOA4FhTdgTx8u1VS5yMpv9Ynik-KA@mail.gmail.com>
>Patch-Date:     Fri Apr 24 16:37:17 +0200 2015

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] unassigned-patches/151: Re: [PATCH 0/4] x86: support of pin-muxing from device tree
  2015-04-24  3:23 ` [U-Boot] [PATCH 0/4] x86: support of " Bin Meng
  2015-04-24 14:40   ` Gabriel Huau
@ 2015-04-24 17:55   ` u-boot at bugs.denx.de
  1 sibling, 0 replies; 61+ messages in thread
From: u-boot at bugs.denx.de @ 2015-04-24 17:55 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On 04/23/2015 08:23 PM, Bin Meng wrote:
> Hi Gabriel,
>
> On Fri, Apr 24, 2015 at 12:16 AM, Gabriel Huau <contact@huau-gabriel.fr> wrote:
>> This serie of patches adds the support of pin-muxing from the device tree through
>> different properties. I have put two example to enable the USB Host on the
>> minnowboard max.
>>
>> The support of the call to 'setup_pch_gpios' is still supported and
>> only the minnowboard has been tested with the device tree implementation.
>>
>> Because the GPIO and IO base register ares different, I have also defined
>> some proxy function to set the function/value and direction of the GPIO as
>> the GPIO register can override some registers in the IO.
>>
>> Gabriel Huau (4):
>>    x86: baytrail: fix the GPIOBASE address
>>    x86: minnowmax: add GPIO banks in the device tree
>>    x86: gpio: add pinctrl support from the device tree
>>    x86: minnowmax: initialize the pin-muxing from device tree
>>
>>   arch/x86/dts/minnowmax.dts                |  63 +++++++++
>>   arch/x86/include/asm/arch-baytrail/gpio.h |   3 +-
>>   arch/x86/include/asm/gpio.h               |   1 +
>>   board/intel/minnowmax/minnowmax.c         |   9 ++
>>   drivers/gpio/intel_ich6_gpio.c            | 222 ++++++++++++++++++++++++++----
>>   include/configs/minnowmax.h               |   1 +
>>   include/dt-bindings/gpio/gpio.h           |  20 +++
>>   7 files changed, 292 insertions(+), 27 deletions(-)
>>
>> --
> Thanks for these patches! Just a general comment, you don't need send
> emails to u-boot-patches at bugs.denx.de, and always include a simple
> sentence in the commit message :)
>
> Regards,
> Bin
That's why I received plenty of emails to tell me that my patches were
not assigned :).
I'll do the modification for the next version, thank you for the
feedback, I appreciate this.

Regards,
Gabriel

---
Added to GNATS database as unassigned-patches/151
>Responsible:    patch-coord
>Message-Id:     <553A55C4.9080907@huau-gabriel.fr>
>In-Reply-To:    <CAEUhbmVTxF6NKX62O0JWXaTyYdbSqduv7SyYEw7jC-XqUjjKTQ@mail.gmail.com>
>References:     <1429805775-1809-1-git-send-email-contact@huau-gabriel.fr> <CAEUhbmVTxF6NKX62O0JWXaTyYdbSqduv7SyYEw7jC-XqUjjKTQ@mail.gmail.com>
>Patch-Date:     Fri Apr 24 16:40:04 +0200 2015

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 1/5 v2] x86: baytrail: fix the GPIOBASE address
  2015-04-23 16:16 ` [U-Boot] [PATCH 1/4] x86: baytrail: fix the GPIOBASE address Gabriel Huau
  2015-04-24  1:40   ` Bin Meng
@ 2015-04-25 20:14   ` Gabriel Huau
  2015-04-25 20:16   ` [U-Boot] [PATCH 1/4 v3] " Gabriel Huau
  2 siblings, 0 replies; 61+ messages in thread
From: Gabriel Huau @ 2015-04-25 20:14 UTC (permalink / raw)
  To: u-boot

The correct GPIOBASE address on the baytrail is 0x48

Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
---
Changes for v2:
	- Add a commit message

 arch/x86/include/asm/arch-baytrail/gpio.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/arch-baytrail/gpio.h b/arch/x86/include/asm/arch-baytrail/gpio.h
index ab4e059..4e8987c 100644
--- a/arch/x86/include/asm/arch-baytrail/gpio.h
+++ b/arch/x86/include/asm/arch-baytrail/gpio.h
@@ -8,6 +8,6 @@
 #define _X86_ARCH_GPIO_H_
 
 /* Where in config space is the register that points to the GPIO registers? */
-#define PCI_CFG_GPIOBASE 0x44
+#define PCI_CFG_GPIOBASE 0x48
 
 #endif /* _X86_ARCH_GPIO_H_ */
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 1/4 v3] x86: baytrail: fix the GPIOBASE address
  2015-04-23 16:16 ` [U-Boot] [PATCH 1/4] x86: baytrail: fix the GPIOBASE address Gabriel Huau
  2015-04-24  1:40   ` Bin Meng
  2015-04-25 20:14   ` [U-Boot] [PATCH 1/5 v2] " Gabriel Huau
@ 2015-04-25 20:16   ` Gabriel Huau
  2015-04-26 13:52     ` Bin Meng
  2 siblings, 1 reply; 61+ messages in thread
From: Gabriel Huau @ 2015-04-25 20:16 UTC (permalink / raw)
  To: u-boot

The correct GPIOBASE address on the baytrail is 0x48

Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
---
Changes for v2:
	- Add a commit message

Changes for v3:
	- Fix patch number

 arch/x86/include/asm/arch-baytrail/gpio.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/arch-baytrail/gpio.h b/arch/x86/include/asm/arch-baytrail/gpio.h
index ab4e059..4e8987c 100644
--- a/arch/x86/include/asm/arch-baytrail/gpio.h
+++ b/arch/x86/include/asm/arch-baytrail/gpio.h
@@ -8,6 +8,6 @@
 #define _X86_ARCH_GPIO_H_
 
 /* Where in config space is the register that points to the GPIO registers? */
-#define PCI_CFG_GPIOBASE 0x44
+#define PCI_CFG_GPIOBASE 0x48
 
 #endif /* _X86_ARCH_GPIO_H_ */
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 2/4 v2] x86: minnowmax: add GPIO banks in the device tree
  2015-04-23 16:16 ` [U-Boot] [PATCH 2/4] x86: minnowmax: add GPIO banks in the device tree Gabriel Huau
                     ` (3 preceding siblings ...)
  2015-04-24  5:05   ` [U-Boot] unassigned-patches/147: " u-boot at bugs.denx.de
@ 2015-04-25 20:16   ` Gabriel Huau
  2015-04-26 13:54     ` Bin Meng
  4 siblings, 1 reply; 61+ messages in thread
From: Gabriel Huau @ 2015-04-25 20:16 UTC (permalink / raw)
  To: u-boot

There are 6 banks:
    4 banks for CORE: available in S0 mode
    2 banks for SUS (Suspend): available in S0-S5 mode

Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
---
Changes for v2:
	- Fix typo in the commit message

 arch/x86/dts/minnowmax.dts | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
index 8f34369..c73e421 100644
--- a/arch/x86/dts/minnowmax.dts
+++ b/arch/x86/dts/minnowmax.dts
@@ -21,6 +21,48 @@
 		silent_console = <0>;
 	};
 
+	gpioa {
+		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
+		reg = <0 0x20>;
+		bank-name = "A";
+	};
+
+	gpiob {
+		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
+		reg = <0x20 0x20>;
+		bank-name = "B";
+	};
+
+	gpioc {
+		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
+		reg = <0x40 0x20>;
+		bank-name = "C";
+	};
+
+	gpiod {
+		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
+		reg = <0x60 0x20>;
+		bank-name = "D";
+	};
+
+	gpioe {
+		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
+		reg = <0x80 0x20>;
+		bank-name = "E";
+	};
+
+	gpiof {
+		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
+		reg = <0xA0 0x20>;
+		bank-name = "F";
+	};
+
 	chosen {
 		stdout-path = "/serial";
 	};
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 3/4 v2] x86: gpio: add pinctrl support from the device tree
  2015-04-23 16:16 ` [U-Boot] [PATCH 3/4] x86: gpio: add pinctrl support from " Gabriel Huau
                     ` (2 preceding siblings ...)
  2015-04-24  4:40   ` [U-Boot] unassigned-patches/144: " u-boot at bugs.denx.de
@ 2015-04-25 20:17   ` Gabriel Huau
  2015-04-28 13:53     ` Simon Glass
  2015-05-12  6:17   ` [U-Boot] [PATCH v3 3/4] " Gabriel Huau
  2015-05-26  5:27   ` [U-Boot] [PATCH v4 " Gabriel Huau
  5 siblings, 1 reply; 61+ messages in thread
From: Gabriel Huau @ 2015-04-25 20:17 UTC (permalink / raw)
  To: u-boot

Every pin can be configured now from the device tree. A dt-bindings
has been added to describe the different property available.

Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
---
Changes for v2:
	- Clean commit message
	- Rename compatible string 'ich6' to 'x86'
	- Fix coding style
	- Create a dt-bindinds documentation
	- Move x86-gpio defines to a specific header
	- Reorder the functions to avoid the need for forward declarations
	- Rename double underscore functions to only one
	- Create a specific function to configure one pin
	- Use a define to prevent build/support issues with other x86 CPU that
	doesn't have a IOBASE.

 arch/x86/dts/minnowmax.dts                         |  21 ++
 arch/x86/include/asm/arch-baytrail/gpio.h          |   1 +
 arch/x86/include/asm/gpio.h                        |   1 +
 .../gpio/intel,x86-pinctrl.txt                     |  31 +++
 drivers/gpio/intel_ich6_gpio.c                     | 234 ++++++++++++++++++---
 include/dt-bindings/gpio/x86-gpio.h                |  36 ++++
 6 files changed, 295 insertions(+), 29 deletions(-)
 create mode 100644 doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
 create mode 100644 include/dt-bindings/gpio/x86-gpio.h

diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
index c73e421..ea10963 100644
--- a/arch/x86/dts/minnowmax.dts
+++ b/arch/x86/dts/minnowmax.dts
@@ -6,6 +6,8 @@
 
 /dts-v1/;
 
+#include <dt-bindings/gpio/x86-gpio.h>
+
 /include/ "skeleton.dtsi"
 /include/ "serial.dtsi"
 
@@ -21,6 +23,25 @@
 		silent_console = <0>;
 	};
 
+	pch_pinctrl {
+		compatible = "intel,x86-pinctrl";
+		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 = <0x258>;
+			mode-gpio;
+			output-value = <1>;
+			direction = <PIN_OUTPUT>;
+		};
+	};
+
 	gpioa {
 		compatible = "intel,ich6-gpio";
 		u-boot,dm-pre-reloc;
diff --git a/arch/x86/include/asm/arch-baytrail/gpio.h b/arch/x86/include/asm/arch-baytrail/gpio.h
index 4e8987c..85a65a8 100644
--- a/arch/x86/include/asm/arch-baytrail/gpio.h
+++ b/arch/x86/include/asm/arch-baytrail/gpio.h
@@ -9,5 +9,6 @@
 
 /* Where in config space is the register that points to the GPIO registers? */
 #define PCI_CFG_GPIOBASE 0x48
+#define PCI_CFG_IOBASE   0x4c
 
 #endif /* _X86_ARCH_GPIO_H_ */
diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h
index 1099427..ed85b08 100644
--- a/arch/x86/include/asm/gpio.h
+++ b/arch/x86/include/asm/gpio.h
@@ -147,6 +147,7 @@ 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/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt b/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
new file mode 100644
index 0000000..45ab1af
--- /dev/null
+++ b/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
@@ -0,0 +1,31 @@
+Intel x86 PINCTRL/GPIO controller
+
+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.
+
+The PINCTRL master node requires the following properties:
+- compatible : "intel,x86-pinctrl"
+
+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'
+					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.
+- 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.
+
+Example:
+
+pin_usb_host_en0 at 0 {
+    gpio-offset = <0x80 8>;
+    pad-offset = <0x260>;
+    mode-gpio;
+    output-value = <1>;
+    direction = <PIN_OUTPUT>;
+};
diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
index 7e679a0..c18c60f 100644
--- a/drivers/gpio/intel_ich6_gpio.c
+++ b/drivers/gpio/intel_ich6_gpio.c
@@ -44,21 +44,28 @@ struct ich6_bank_priv {
 	uint16_t 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)
+#define IOPAD_PULL_STRENGTH_SHIFT	9
+#define IOPAD_PULL_STRENGTH_MASK	(0x3 << IOPAD_PULL_STRENGTH_SHIFT)
+
 /* TODO: Move this to device tree, or platform data */
 void ich_gpio_set_gpio_map(const struct pch_gpio_map *map)
 {
 	gd->arch.gpio_map = map;
 }
 
-static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
+static int gpio_ich6_get_base(unsigned long base)
 {
-	struct ich6_bank_platdata *plat = dev_get_platdata(dev);
 	pci_dev_t pci_dev;			/* handle for 0:1f:0 */
 	u8 tmpbyte;
 	u16 tmpword;
 	u32 tmplong;
-	u16 gpiobase;
-	int offset;
 
 	/* Where should it be? */
 	pci_dev = PCI_BDF(0, 0x1f, 0);
@@ -123,9 +130,9 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
 	 * while on the Ivybridge the bit0 is used to indicate it is an
 	 * I/O space.
 	 */
-	tmplong = x86_pci_read_config32(pci_dev, PCI_CFG_GPIOBASE);
+	tmplong = x86_pci_read_config32(pci_dev, base);
 	if (tmplong == 0x00000000 || tmplong == 0xffffffff) {
-		debug("%s: unexpected GPIOBASE value\n", __func__);
+		debug("%s: unexpected BASE value\n", __func__);
 		return -ENODEV;
 	}
 
@@ -135,7 +142,195 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
 	 * at the offset that we just read. Bit 0 indicates that it's
 	 * an I/O address, not a memory address, so mask that off.
 	 */
-	gpiobase = tmplong & 0xfffe;
+	return tmplong & 0xfffc;
+}
+
+static int _ich6_gpio_set_value(uint16_t base, unsigned offset, int value)
+{
+	u32 tmplong;
+	tmplong = inl(base);
+	if (value)
+		tmplong |= (1UL << offset);
+	else
+		tmplong &= ~(1UL << offset);
+	outl(tmplong, base);
+
+	return 0;
+}
+
+static int _ich6_gpio_set_function(uint16_t base, unsigned offset, int func)
+{
+	u32 tmplong;
+
+	if (func) {
+		tmplong = inl(base);
+		tmplong |= (1UL << offset);
+		outl(tmplong, base);
+	} else {
+		tmplong = inl(base);
+		tmplong &= ~(1UL << offset);
+		outl(tmplong, base);
+	}
+
+	return 0;
+}
+
+static int _ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir)
+{
+	u32 tmplong;
+
+	if (!dir) {
+		tmplong = inl(base);
+		tmplong |= (1UL << offset);
+		outl(tmplong, base);
+	} else {
+		tmplong = inl(base);
+		tmplong &= ~(1UL << offset);
+		outl(tmplong, base);
+	}
+
+	return 0;
+}
+
+static int _gpio_ich6_pinctrl_cfg_pin(u32 gpiobase, u32 iobase, int pin_node)
+{
+	u32 gpio_offset[2] = { -1, -1 };
+	u32 pad_offset;
+	int tmplong;
+	const void *tmpnode;
+
+	/*
+	 * GPIO node is not mandatory, so we only do the
+	 * pinmuxing if the node exist.
+	 */
+	fdtdec_get_int_array(gd->fdt_blob, pin_node, "gpio-offset",
+			     gpio_offset, 2);
+	if (gpio_offset[0] != -1) {
+		/* Do we want to force the GPIO mode? */
+		tmpnode = fdt_getprop(gd->fdt_blob, pin_node, "mode-gpio",
+				      NULL);
+		if (tmpnode)
+			_ich6_gpio_set_function(GPIO_USESEL_OFFSET
+						(gpiobase) +
+						gpio_offset[0],
+						gpio_offset[1], 1);
+
+		tmplong =
+		    fdtdec_get_int(gd->fdt_blob, pin_node, "direction", -1);
+		if (tmplong != -1)
+			_ich6_gpio_set_direction(GPIO_IOSEL_OFFSET
+						 (gpiobase) +
+						 gpio_offset[0],
+						 gpio_offset[1], tmplong);
+
+		tmplong =
+		    fdtdec_get_int(gd->fdt_blob, pin_node, "output-value", -1);
+		if (tmplong != -1)
+			_ich6_gpio_set_value(GPIO_LVL_OFFSET(gpiobase)
+					     + gpio_offset[0],
+					     gpio_offset[1], tmplong);
+	}
+#ifdef PCI_CFG_IOBASE
+	/*
+	 * The offset for the same pin for the IOBASE and GPIOBASE are
+	 * different, so instead of maintaining a lookup table,
+	 * the device tree should provide directly the correct
+	 * value for both mapping.
+	 */
+	pad_offset = fdtdec_get_int(gd->fdt_blob, pin_node, "pad-offset", -1);
+	if (pad_offset == -1) {
+		debug("%s: Invalid register io offset %d\n",
+		      __func__, pad_offset);
+		return -EINVAL;
+	}
+
+	/*
+	 * Do we need to set a specific function mode?
+	 * If someone put also 'mode-gpio', this option will
+	 * be just ignored by the controller
+	 */
+	tmplong = fdtdec_get_int(gd->fdt_blob, pin_node, "mode-func", -1);
+	if (tmplong != -1)
+		clrsetbits_le32(iobase + pad_offset, IOPAD_MODE_MASK, tmplong);
+
+	/* Configure the pull-up/down if needed */
+	tmplong = fdtdec_get_int(gd->fdt_blob, pin_node, "pull-assign", -1);
+	if (tmplong != -1)
+		clrsetbits_le32(iobase + pad_offset,
+				IOPAD_PULL_ASSIGN_MASK,
+				tmplong << IOPAD_PULL_ASSIGN_SHIFT);
+
+	tmplong = fdtdec_get_int(gd->fdt_blob, pin_node, "pull-strength", -1);
+	if (tmplong != -1)
+		clrsetbits_le32(iobase + pad_offset,
+				IOPAD_PULL_STRENGTH_MASK,
+				tmplong << IOPAD_PULL_STRENGTH_SHIFT);
+
+	debug("%s: pad cfg [0x%x]: %08x\n", __func__, pad_offset,
+	      readl(iobase + pad_offset));
+#endif
+
+	return 0;
+}
+
+int gpio_ich6_pinctrl_init(void)
+{
+	int pin_node;
+	int node;
+	int ret;
+	u32 gpiobase;
+	u32 iobase;
+
+#ifdef PCI_CFG_IOBASE
+	/*
+	 * 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
+	 */
+	iobase = gpio_ich6_get_base(PCI_CFG_IOBASE);
+	if (iobase < 0) {
+		debug("%s: invalid IOBASE address (%08x)\n", __func__, iobase);
+		return -EINVAL;
+	}
+#endif
+
+	gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
+	if (gpiobase < 0) {
+		debug("%s: invalid GPIOBASE address (%08x)\n", __func__,
+		      gpiobase);
+		return -EINVAL;
+	}
+
+	/* This is not an error to not have a pinctrl node */
+	node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
+					     "intel,x86-pinctrl");
+	if (node < 0) {
+		debug("%s: no pinctrl node\n", __func__);
+		return 0;
+	}
+
+	for (pin_node = fdt_first_subnode(gd->fdt_blob, node);
+	     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);
+		if (ret != 0) {
+			debug("%s: invalid configuration for the pin %d\n",
+			      __func__, pin_node);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ich6_bank_platdata *plat = dev_get_platdata(dev);
+	u16 gpiobase;
+	int offset;
+
+	gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
 	offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
 	if (offset == -1) {
 		debug("%s: Invalid register offset %d\n", __func__, offset);
@@ -192,30 +387,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);
-	u32 tmplong;
 
-	tmplong = inl(bank->io_sel);
-	tmplong |= (1UL << offset);
-	outl(bank->io_sel, tmplong);
-	return 0;
+	return _ich6_gpio_set_direction(inl(bank->io_sel), offset, 0);
 }
 
 static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
 				       int value)
 {
 	struct ich6_bank_priv *bank = dev_get_priv(dev);
-	u32 tmplong;
 
-	gpio_set_value(offset, value);
-
-	tmplong = inl(bank->io_sel);
-	tmplong &= ~(1UL << offset);
-	outl(bank->io_sel, tmplong);
-	return 0;
+	return _ich6_gpio_set_direction(inl(bank->io_sel), offset, 1);
 }
 
 static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
-
 {
 	struct ich6_bank_priv *bank = dev_get_priv(dev);
 	u32 tmplong;
@@ -230,15 +414,7 @@ static int ich6_gpio_set_value(struct udevice *dev, unsigned offset,
 			       int value)
 {
 	struct ich6_bank_priv *bank = dev_get_priv(dev);
-	u32 tmplong;
-
-	tmplong = inl(bank->lvl);
-	if (value)
-		tmplong |= (1UL << offset);
-	else
-		tmplong &= ~(1UL << offset);
-	outl(bank->lvl, tmplong);
-	return 0;
+	return _ich6_gpio_set_value(bank->lvl, offset, value);
 }
 
 static int ich6_gpio_get_function(struct udevice *dev, unsigned offset)
diff --git a/include/dt-bindings/gpio/x86-gpio.h b/include/dt-bindings/gpio/x86-gpio.h
new file mode 100644
index 0000000..103bd04
--- /dev/null
+++ b/include/dt-bindings/gpio/x86-gpio.h
@@ -0,0 +1,36 @@
+/*
+ * This header provides constants for binding nvidia,tegra*-gpio.
+ *
+ * The first cell in Tegra's GPIO specifier is the GPIO ID. The macros below
+ * provide names for this.
+ *
+ * The second cell contains standard flag values specified in gpio.h.
+ */
+
+#ifndef _DT_BINDINGS_GPIO_X86_GPIO_H
+#define _DT_BINDINGS_GPIO_X86_GPIO_H
+
+#include <dt-bindings/gpio/gpio.h>
+
+#define GPIO_MODE_NATIVE	0
+#define GPIO_MODE_GPIO		1
+
+#define GPIO_MODE_FUNC0	0
+#define GPIO_MODE_FUNC1	1
+#define GPIO_MODE_FUNC2	2
+#define GPIO_MODE_FUNC3	3
+#define GPIO_MODE_FUNC4	4
+#define GPIO_MODE_FUNC5	5
+#define GPIO_MODE_FUNC6	6
+
+#define PIN_INPUT		0
+#define PIN_OUTPUT		1
+
+#define PIN_INPUT_NOPULL	0
+#define PIN_INPUT_PULLUP	1
+#define PIN_INPUT_PULLDOWN	2
+
+#define PULL_STR_2K		0
+#define PULL_STR_20K	2
+
+#endif
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 4/4 v2] x86: minnowmax: initialize the pin-muxing from device tree
  2015-04-23 16:16 ` [U-Boot] [PATCH 4/4] x86: minnowmax: initialize the pin-muxing from " Gabriel Huau
  2015-04-24  3:37   ` Simon Glass
  2015-04-24  4:45   ` [U-Boot] unassigned-patches/145: " u-boot at bugs.denx.de
@ 2015-04-25 20:18   ` Gabriel Huau
  2015-04-28 13:53     ` Simon Glass
  2015-05-12  6:18   ` [U-Boot] [PATCH v3 4/4] " Gabriel Huau
  3 siblings, 1 reply; 61+ messages in thread
From: Gabriel Huau @ 2015-04-25 20:18 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
---
Changes for v2:
	- Fix ordering of include header

 board/intel/minnowmax/minnowmax.c | 9 +++++++++
 include/configs/minnowmax.h       | 1 +
 2 files changed, 10 insertions(+)

diff --git a/board/intel/minnowmax/minnowmax.c b/board/intel/minnowmax/minnowmax.c
index 6e82b16..0244d35 100644
--- a/board/intel/minnowmax/minnowmax.c
+++ b/board/intel/minnowmax/minnowmax.c
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <asm/gpio.h>
 #include <asm/ibmpc.h>
 #include <asm/pnp_def.h>
 #include <netdev.h>
@@ -14,6 +15,14 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+int arch_early_init_r(void)
+{
+	/* do the pin-muxing */
+	gpio_ich6_pinctrl_init();
+
+	return 0;
+}
+
 int board_early_init_f(void)
 {
 	lpc47m_enable_serial(SERIAL_DEV, UART0_BASE);
diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h
index 823e051..3c7b266 100644
--- a/include/configs/minnowmax.h
+++ b/include/configs/minnowmax.h
@@ -15,6 +15,7 @@
 
 #define CONFIG_SYS_MONITOR_LEN		(1 << 20)
 #define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_ARCH_EARLY_INIT_R
 
 #define CONFIG_NR_DRAM_BANKS		1
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 1/4 v3] x86: baytrail: fix the GPIOBASE address
  2015-04-25 20:16   ` [U-Boot] [PATCH 1/4 v3] " Gabriel Huau
@ 2015-04-26 13:52     ` Bin Meng
  2015-04-28 13:53       ` Simon Glass
  0 siblings, 1 reply; 61+ messages in thread
From: Bin Meng @ 2015-04-26 13:52 UTC (permalink / raw)
  To: u-boot

Hi Gabriel,

On Sun, Apr 26, 2015 at 4:16 AM, Gabriel Huau <contact@huau-gabriel.fr> wrote:
> The correct GPIOBASE address on the baytrail is 0x48
>
> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
> ---

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

Please edit your commit message in the v2 to include such tags like
Acked-by, Reviewed-by, etc so that we know the patch status.

> Changes for v2:
>         - Add a commit message
>
> Changes for v3:
>         - Fix patch number
>
>  arch/x86/include/asm/arch-baytrail/gpio.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/x86/include/asm/arch-baytrail/gpio.h b/arch/x86/include/asm/arch-baytrail/gpio.h
> index ab4e059..4e8987c 100644
> --- a/arch/x86/include/asm/arch-baytrail/gpio.h
> +++ b/arch/x86/include/asm/arch-baytrail/gpio.h
> @@ -8,6 +8,6 @@
>  #define _X86_ARCH_GPIO_H_
>
>  /* Where in config space is the register that points to the GPIO registers? */
> -#define PCI_CFG_GPIOBASE 0x44
> +#define PCI_CFG_GPIOBASE 0x48
>
>  #endif /* _X86_ARCH_GPIO_H_ */
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 2/4 v2] x86: minnowmax: add GPIO banks in the device tree
  2015-04-25 20:16   ` [U-Boot] [PATCH 2/4 v2] " Gabriel Huau
@ 2015-04-26 13:54     ` Bin Meng
  2015-04-28 13:53       ` Simon Glass
  0 siblings, 1 reply; 61+ messages in thread
From: Bin Meng @ 2015-04-26 13:54 UTC (permalink / raw)
  To: u-boot

On Sun, Apr 26, 2015 at 4:16 AM, Gabriel Huau <contact@huau-gabriel.fr> wrote:
> There are 6 banks:
>     4 banks for CORE: available in S0 mode
>     2 banks for SUS (Suspend): available in S0-S5 mode
>
> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
> ---
> Changes for v2:
>         - Fix typo in the commit message
>
>  arch/x86/dts/minnowmax.dts | 42 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 42 insertions(+)
>
> diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
> index 8f34369..c73e421 100644
> --- a/arch/x86/dts/minnowmax.dts
> +++ b/arch/x86/dts/minnowmax.dts
> @@ -21,6 +21,48 @@
>                 silent_console = <0>;
>         };
>
> +       gpioa {
> +               compatible = "intel,ich6-gpio";
> +               u-boot,dm-pre-reloc;
> +               reg = <0 0x20>;
> +               bank-name = "A";
> +       };
> +
> +       gpiob {
> +               compatible = "intel,ich6-gpio";
> +               u-boot,dm-pre-reloc;
> +               reg = <0x20 0x20>;
> +               bank-name = "B";
> +       };
> +
> +       gpioc {
> +               compatible = "intel,ich6-gpio";
> +               u-boot,dm-pre-reloc;
> +               reg = <0x40 0x20>;
> +               bank-name = "C";
> +       };
> +
> +       gpiod {
> +               compatible = "intel,ich6-gpio";
> +               u-boot,dm-pre-reloc;
> +               reg = <0x60 0x20>;
> +               bank-name = "D";
> +       };
> +
> +       gpioe {
> +               compatible = "intel,ich6-gpio";
> +               u-boot,dm-pre-reloc;
> +               reg = <0x80 0x20>;
> +               bank-name = "E";
> +       };
> +
> +       gpiof {
> +               compatible = "intel,ich6-gpio";
> +               u-boot,dm-pre-reloc;
> +               reg = <0xA0 0x20>;
> +               bank-name = "F";
> +       };
> +
>         chosen {
>                 stdout-path = "/serial";
>         };
> --

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 1/4 v3] x86: baytrail: fix the GPIOBASE address
  2015-04-26 13:52     ` Bin Meng
@ 2015-04-28 13:53       ` Simon Glass
  2015-04-28 15:39         ` Simon Glass
  0 siblings, 1 reply; 61+ messages in thread
From: Simon Glass @ 2015-04-28 13:53 UTC (permalink / raw)
  To: u-boot

On 26 April 2015 at 07:52, Bin Meng <bmeng.cn@gmail.com> wrote:
> Hi Gabriel,
>
> On Sun, Apr 26, 2015 at 4:16 AM, Gabriel Huau <contact@huau-gabriel.fr> wrote:
>> The correct GPIOBASE address on the baytrail is 0x48
>>
>> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
>> ---
>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

Acked-by: Simon Glass <sjg@chromium.org>

>
> Please edit your commit message in the v2 to include such tags like
> Acked-by, Reviewed-by, etc so that we know the patch status.

Also you could take a look at patman which automates the creation of
change lists, checking patches, etc.

>
>> Changes for v2:
>>         - Add a commit message
>>
>> Changes for v3:
>>         - Fix patch number
>>
>>  arch/x86/include/asm/arch-baytrail/gpio.h | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/arch/x86/include/asm/arch-baytrail/gpio.h b/arch/x86/include/asm/arch-baytrail/gpio.h
>> index ab4e059..4e8987c 100644
>> --- a/arch/x86/include/asm/arch-baytrail/gpio.h
>> +++ b/arch/x86/include/asm/arch-baytrail/gpio.h
>> @@ -8,6 +8,6 @@
>>  #define _X86_ARCH_GPIO_H_
>>
>>  /* Where in config space is the register that points to the GPIO registers? */
>> -#define PCI_CFG_GPIOBASE 0x44
>> +#define PCI_CFG_GPIOBASE 0x48
>>
>>  #endif /* _X86_ARCH_GPIO_H_ */
>> --
>
> Regards,
> Bin

Regards,
Simon

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 2/4 v2] x86: minnowmax: add GPIO banks in the device tree
  2015-04-26 13:54     ` Bin Meng
@ 2015-04-28 13:53       ` Simon Glass
  2015-04-28 15:39         ` Simon Glass
  0 siblings, 1 reply; 61+ messages in thread
From: Simon Glass @ 2015-04-28 13:53 UTC (permalink / raw)
  To: u-boot

On 26 April 2015 at 07:54, Bin Meng <bmeng.cn@gmail.com> wrote:
> On Sun, Apr 26, 2015 at 4:16 AM, Gabriel Huau <contact@huau-gabriel.fr> wrote:
>> There are 6 banks:
>>     4 banks for CORE: available in S0 mode
>>     2 banks for SUS (Suspend): available in S0-S5 mode
>>
>> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
>> ---
>> Changes for v2:
>>         - Fix typo in the commit message
>>
>>  arch/x86/dts/minnowmax.dts | 42 ++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 42 insertions(+)
>>
>> diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
>> index 8f34369..c73e421 100644
>> --- a/arch/x86/dts/minnowmax.dts
>> +++ b/arch/x86/dts/minnowmax.dts
>> @@ -21,6 +21,48 @@
>>                 silent_console = <0>;
>>         };
>>
>> +       gpioa {
>> +               compatible = "intel,ich6-gpio";
>> +               u-boot,dm-pre-reloc;
>> +               reg = <0 0x20>;
>> +               bank-name = "A";
>> +       };
>> +
>> +       gpiob {
>> +               compatible = "intel,ich6-gpio";
>> +               u-boot,dm-pre-reloc;
>> +               reg = <0x20 0x20>;
>> +               bank-name = "B";
>> +       };
>> +
>> +       gpioc {
>> +               compatible = "intel,ich6-gpio";
>> +               u-boot,dm-pre-reloc;
>> +               reg = <0x40 0x20>;
>> +               bank-name = "C";
>> +       };
>> +
>> +       gpiod {
>> +               compatible = "intel,ich6-gpio";
>> +               u-boot,dm-pre-reloc;
>> +               reg = <0x60 0x20>;
>> +               bank-name = "D";
>> +       };
>> +
>> +       gpioe {
>> +               compatible = "intel,ich6-gpio";
>> +               u-boot,dm-pre-reloc;
>> +               reg = <0x80 0x20>;
>> +               bank-name = "E";
>> +       };
>> +
>> +       gpiof {
>> +               compatible = "intel,ich6-gpio";
>> +               u-boot,dm-pre-reloc;
>> +               reg = <0xA0 0x20>;
>> +               bank-name = "F";
>> +       };
>> +
>>         chosen {
>>                 stdout-path = "/serial";
>>         };
>> --
>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

Acked-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 3/4 v2] x86: gpio: add pinctrl support from the device tree
  2015-04-25 20:17   ` [U-Boot] [PATCH 3/4 v2] " Gabriel Huau
@ 2015-04-28 13:53     ` Simon Glass
  2015-04-28 15:22       ` Stephen Warren
  2015-05-12  3:33       ` gabriel huau
  0 siblings, 2 replies; 61+ messages in thread
From: Simon Glass @ 2015-04-28 13:53 UTC (permalink / raw)
  To: u-boot

Hi Gabriel,

On 25 April 2015 at 14:17, Gabriel Huau <contact@huau-gabriel.fr> wrote:
> Every pin can be configured now from the device tree. A dt-bindings
> has been added to describe the different property available.
>
> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
> ---
> Changes for v2:
>         - Clean commit message
>         - Rename compatible string 'ich6' to 'x86'
>         - Fix coding style
>         - Create a dt-bindinds documentation
>         - Move x86-gpio defines to a specific header
>         - Reorder the functions to avoid the need for forward declarations
>         - Rename double underscore functions to only one
>         - Create a specific function to configure one pin
>         - Use a define to prevent build/support issues with other x86 CPU that
>         doesn't have a IOBASE.

I have a few minor comments below. Do you know how to access the GPIO
pings on the top connector of the Minnowboard MAX? I'd like to figure
out the pin names for those in U-Boot and that would allow me to test
a few things.

>
>  arch/x86/dts/minnowmax.dts                         |  21 ++
>  arch/x86/include/asm/arch-baytrail/gpio.h          |   1 +
>  arch/x86/include/asm/gpio.h                        |   1 +
>  .../gpio/intel,x86-pinctrl.txt                     |  31 +++
>  drivers/gpio/intel_ich6_gpio.c                     | 234 ++++++++++++++++++---
>  include/dt-bindings/gpio/x86-gpio.h                |  36 ++++
>  6 files changed, 295 insertions(+), 29 deletions(-)
>  create mode 100644 doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
>  create mode 100644 include/dt-bindings/gpio/x86-gpio.h
>
> diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
> index c73e421..ea10963 100644
> --- a/arch/x86/dts/minnowmax.dts
> +++ b/arch/x86/dts/minnowmax.dts
> @@ -6,6 +6,8 @@
>
>  /dts-v1/;
>
> +#include <dt-bindings/gpio/x86-gpio.h>
> +
>  /include/ "skeleton.dtsi"
>  /include/ "serial.dtsi"
>
> @@ -21,6 +23,25 @@
>                 silent_console = <0>;
>         };
>
> +       pch_pinctrl {
> +               compatible = "intel,x86-pinctrl";
> +               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 = <0x258>;
> +                       mode-gpio;
> +                       output-value = <1>;
> +                       direction = <PIN_OUTPUT>;
> +               };
> +       };
> +
>         gpioa {
>                 compatible = "intel,ich6-gpio";
>                 u-boot,dm-pre-reloc;
> diff --git a/arch/x86/include/asm/arch-baytrail/gpio.h b/arch/x86/include/asm/arch-baytrail/gpio.h
> index 4e8987c..85a65a8 100644
> --- a/arch/x86/include/asm/arch-baytrail/gpio.h
> +++ b/arch/x86/include/asm/arch-baytrail/gpio.h
> @@ -9,5 +9,6 @@
>
>  /* Where in config space is the register that points to the GPIO registers? */
>  #define PCI_CFG_GPIOBASE 0x48
> +#define PCI_CFG_IOBASE   0x4c

Can we put this in the device tree as a property of the pch_pinctrl
node? If you like we could do it later.

>
>  #endif /* _X86_ARCH_GPIO_H_ */
> diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h
> index 1099427..ed85b08 100644
> --- a/arch/x86/include/asm/gpio.h
> +++ b/arch/x86/include/asm/gpio.h
> @@ -147,6 +147,7 @@ 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/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt b/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
> new file mode 100644
> index 0000000..45ab1af
> --- /dev/null
> +++ b/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
> @@ -0,0 +1,31 @@
> +Intel x86 PINCTRL/GPIO controller
> +
> +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.
> +
> +The PINCTRL master node requires the following properties:
> +- compatible : "intel,x86-pinctrl"
> +
> +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'
> +                                       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.
> +- 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.
> +
> +Example:
> +
> +pin_usb_host_en0 at 0 {
> +    gpio-offset = <0x80 8>;
> +    pad-offset = <0x260>;
> +    mode-gpio;
> +    output-value = <1>;
> +    direction = <PIN_OUTPUT>;
> +};
> diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
> index 7e679a0..c18c60f 100644
> --- a/drivers/gpio/intel_ich6_gpio.c
> +++ b/drivers/gpio/intel_ich6_gpio.c
> @@ -44,21 +44,28 @@ struct ich6_bank_priv {
>         uint16_t lvl;
>  };
>
> +#define GPIO_USESEL_OFFSET(x)  (x)
> +#define GPIO_IOSEL_OFFSET(x)   (x + 4)
> +#define GPIO_LVL_OFFSET(x)             (x + 8)

Please align all of these values to the same tab column.

> +
> +#define IOPAD_MODE_MASK                                0x7
> +#define IOPAD_PULL_ASSIGN_SHIFT                7
> +#define IOPAD_PULL_ASSIGN_MASK         (0x3 << IOPAD_PULL_ASSIGN_SHIFT)
> +#define IOPAD_PULL_STRENGTH_SHIFT      9
> +#define IOPAD_PULL_STRENGTH_MASK       (0x3 << IOPAD_PULL_STRENGTH_SHIFT)
> +
>  /* TODO: Move this to device tree, or platform data */
>  void ich_gpio_set_gpio_map(const struct pch_gpio_map *map)
>  {
>         gd->arch.gpio_map = map;
>  }
>
> -static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
> +static int gpio_ich6_get_base(unsigned long base)
>  {
> -       struct ich6_bank_platdata *plat = dev_get_platdata(dev);
>         pci_dev_t pci_dev;                      /* handle for 0:1f:0 */
>         u8 tmpbyte;
>         u16 tmpword;
>         u32 tmplong;
> -       u16 gpiobase;
> -       int offset;
>
>         /* Where should it be? */
>         pci_dev = PCI_BDF(0, 0x1f, 0);
> @@ -123,9 +130,9 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>          * while on the Ivybridge the bit0 is used to indicate it is an
>          * I/O space.
>          */
> -       tmplong = x86_pci_read_config32(pci_dev, PCI_CFG_GPIOBASE);
> +       tmplong = x86_pci_read_config32(pci_dev, base);
>         if (tmplong == 0x00000000 || tmplong == 0xffffffff) {
> -               debug("%s: unexpected GPIOBASE value\n", __func__);
> +               debug("%s: unexpected BASE value\n", __func__);
>                 return -ENODEV;
>         }
>
> @@ -135,7 +142,195 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>          * at the offset that we just read. Bit 0 indicates that it's
>          * an I/O address, not a memory address, so mask that off.
>          */
> -       gpiobase = tmplong & 0xfffe;
> +       return tmplong & 0xfffc;
> +}
> +
> +static int _ich6_gpio_set_value(uint16_t base, unsigned offset, int value)
> +{
> +       u32 tmplong;

blank line here. Also can we use something like 'val' instead of
tmplong? I think calling a u32 'long' is confusing.

> +       tmplong = inl(base);
> +       if (value)
> +               tmplong |= (1UL << offset);
> +       else
> +               tmplong &= ~(1UL << offset);
> +       outl(tmplong, base);
> +
> +       return 0;
> +}
> +
> +static int _ich6_gpio_set_function(uint16_t base, unsigned offset, int func)
> +{
> +       u32 tmplong;
> +
> +       if (func) {
> +               tmplong = inl(base);
> +               tmplong |= (1UL << offset);
> +               outl(tmplong, base);
> +       } else {
> +               tmplong = inl(base);
> +               tmplong &= ~(1UL << offset);
> +               outl(tmplong, base);
> +       }
> +
> +       return 0;
> +}
> +
> +static int _ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir)
> +{
> +       u32 tmplong;
> +
> +       if (!dir) {
> +               tmplong = inl(base);
> +               tmplong |= (1UL << offset);
> +               outl(tmplong, base);
> +       } else {
> +               tmplong = inl(base);
> +               tmplong &= ~(1UL << offset);
> +               outl(tmplong, base);
> +       }
> +
> +       return 0;
> +}
> +
> +static int _gpio_ich6_pinctrl_cfg_pin(u32 gpiobase, u32 iobase, int pin_node)
> +{
> +       u32 gpio_offset[2] = { -1, -1 };
> +       u32 pad_offset;
> +       int tmplong;
> +       const void *tmpnode;

Perhaps 'prop' is a better name. It doesn't point to a node, but a
property of a node.

> +
> +       /*
> +        * GPIO node is not mandatory, so we only do the
> +        * pinmuxing if the node exist.
> +        */
> +       fdtdec_get_int_array(gd->fdt_blob, pin_node, "gpio-offset",
> +                            gpio_offset, 2);
> +       if (gpio_offset[0] != -1) {
> +               /* Do we want to force the GPIO mode? */
> +               tmpnode = fdt_getprop(gd->fdt_blob, pin_node, "mode-gpio",
> +                                     NULL);
> +               if (tmpnode)

{} around these multi-line blocks. If you use patman it will run
checkpatch for you.

> +                       _ich6_gpio_set_function(GPIO_USESEL_OFFSET
> +                                               (gpiobase) +
> +                                               gpio_offset[0],
> +                                               gpio_offset[1], 1);
> +
> +               tmplong =
> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "direction", -1);
> +               if (tmplong != -1)
> +                       _ich6_gpio_set_direction(GPIO_IOSEL_OFFSET
> +                                                (gpiobase) +
> +                                                gpio_offset[0],
> +                                                gpio_offset[1], tmplong);
> +
> +               tmplong =
> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "output-value", -1);
> +               if (tmplong != -1)
> +                       _ich6_gpio_set_value(GPIO_LVL_OFFSET(gpiobase)
> +                                            + gpio_offset[0],
> +                                            gpio_offset[1], tmplong);
> +       }
> +#ifdef PCI_CFG_IOBASE

We should avoid adding #ifdefs like this to the driver. Perhaps the
device tree can provide this property, or not? OK if you want to
tackle this in a follow-on patch.

> +       /*
> +        * The offset for the same pin for the IOBASE and GPIOBASE are
> +        * different, so instead of maintaining a lookup table,
> +        * the device tree should provide directly the correct
> +        * value for both mapping.
> +        */
> +       pad_offset = fdtdec_get_int(gd->fdt_blob, pin_node, "pad-offset", -1);
> +       if (pad_offset == -1) {
> +               debug("%s: Invalid register io offset %d\n",
> +                     __func__, pad_offset);
> +               return -EINVAL;
> +       }
> +
> +       /*
> +        * Do we need to set a specific function mode?
> +        * If someone put also 'mode-gpio', this option will
> +        * be just ignored by the controller
> +        */
> +       tmplong = fdtdec_get_int(gd->fdt_blob, pin_node, "mode-func", -1);
> +       if (tmplong != -1)
> +               clrsetbits_le32(iobase + pad_offset, IOPAD_MODE_MASK, tmplong);
> +
> +       /* Configure the pull-up/down if needed */
> +       tmplong = fdtdec_get_int(gd->fdt_blob, pin_node, "pull-assign", -1);
> +       if (tmplong != -1)
> +               clrsetbits_le32(iobase + pad_offset,

Can you create a local variable for (iobase + pad_offset) ?

> +                               IOPAD_PULL_ASSIGN_MASK,
> +                               tmplong << IOPAD_PULL_ASSIGN_SHIFT);
> +
> +       tmplong = fdtdec_get_int(gd->fdt_blob, pin_node, "pull-strength", -1);
> +       if (tmplong != -1)
> +               clrsetbits_le32(iobase + pad_offset,
> +                               IOPAD_PULL_STRENGTH_MASK,
> +                               tmplong << IOPAD_PULL_STRENGTH_SHIFT);
> +
> +       debug("%s: pad cfg [0x%x]: %08x\n", __func__, pad_offset,
> +             readl(iobase + pad_offset));
> +#endif
> +
> +       return 0;
> +}
> +
> +int gpio_ich6_pinctrl_init(void)
> +{
> +       int pin_node;
> +       int node;
> +       int ret;
> +       u32 gpiobase;
> +       u32 iobase;
> +
> +#ifdef PCI_CFG_IOBASE

If this block is #ifdef'd out then you will have an uninited variable
iobase, used below.

> +       /*
> +        * 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
> +        */
> +       iobase = gpio_ich6_get_base(PCI_CFG_IOBASE);
> +       if (iobase < 0) {
> +               debug("%s: invalid IOBASE address (%08x)\n", __func__, iobase);
> +               return -EINVAL;
> +       }
> +#endif
> +
> +       gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
> +       if (gpiobase < 0) {
> +               debug("%s: invalid GPIOBASE address (%08x)\n", __func__,
> +                     gpiobase);
> +               return -EINVAL;
> +       }
> +
> +       /* This is not an error to not have a pinctrl node */
> +       node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
> +                                            "intel,x86-pinctrl");

This should be added to the tables in fdtdec.c/h. Then use
fdtdec_next_compatible(). That file contains a list of all the
compatible strings we have in U-Boot and is an indicator of what needs
to be converted to driver model.

> +       if (node < 0) {
> +               debug("%s: no pinctrl node\n", __func__);
> +               return 0;
> +       }
> +
> +       for (pin_node = fdt_first_subnode(gd->fdt_blob, node);
> +            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);
> +               if (ret != 0) {
> +                       debug("%s: invalid configuration for the pin %d\n",
> +                             __func__, pin_node);
> +                       return ret;
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
> +{
> +       struct ich6_bank_platdata *plat = dev_get_platdata(dev);
> +       u16 gpiobase;
> +       int offset;
> +
> +       gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
>         offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
>         if (offset == -1) {
>                 debug("%s: Invalid register offset %d\n", __func__, offset);
> @@ -192,30 +387,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);
> -       u32 tmplong;
>
> -       tmplong = inl(bank->io_sel);
> -       tmplong |= (1UL << offset);
> -       outl(bank->io_sel, tmplong);
> -       return 0;
> +       return _ich6_gpio_set_direction(inl(bank->io_sel), offset, 0);
>  }
>
>  static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
>                                        int value)
>  {
>         struct ich6_bank_priv *bank = dev_get_priv(dev);
> -       u32 tmplong;
>
> -       gpio_set_value(offset, value);
> -
> -       tmplong = inl(bank->io_sel);
> -       tmplong &= ~(1UL << offset);
> -       outl(bank->io_sel, tmplong);
> -       return 0;
> +       return _ich6_gpio_set_direction(inl(bank->io_sel), offset, 1);
>  }
>
>  static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
> -
>  {
>         struct ich6_bank_priv *bank = dev_get_priv(dev);
>         u32 tmplong;
> @@ -230,15 +414,7 @@ static int ich6_gpio_set_value(struct udevice *dev, unsigned offset,
>                                int value)
>  {
>         struct ich6_bank_priv *bank = dev_get_priv(dev);
> -       u32 tmplong;
> -
> -       tmplong = inl(bank->lvl);
> -       if (value)
> -               tmplong |= (1UL << offset);
> -       else
> -               tmplong &= ~(1UL << offset);
> -       outl(bank->lvl, tmplong);
> -       return 0;
> +       return _ich6_gpio_set_value(bank->lvl, offset, value);
>  }
>
>  static int ich6_gpio_get_function(struct udevice *dev, unsigned offset)
> diff --git a/include/dt-bindings/gpio/x86-gpio.h b/include/dt-bindings/gpio/x86-gpio.h
> new file mode 100644
> index 0000000..103bd04
> --- /dev/null
> +++ b/include/dt-bindings/gpio/x86-gpio.h
> @@ -0,0 +1,36 @@
> +/*
> + * This header provides constants for binding nvidia,tegra*-gpio.
> + *
> + * The first cell in Tegra's GPIO specifier is the GPIO ID. The macros below
> + * provide names for this.
> + *
> + * The second cell contains standard flag values specified in gpio.h.
> + */
> +
> +#ifndef _DT_BINDINGS_GPIO_X86_GPIO_H
> +#define _DT_BINDINGS_GPIO_X86_GPIO_H
> +
> +#include <dt-bindings/gpio/gpio.h>
> +
> +#define GPIO_MODE_NATIVE       0
> +#define GPIO_MODE_GPIO         1
> +
> +#define GPIO_MODE_FUNC0        0
> +#define GPIO_MODE_FUNC1        1
> +#define GPIO_MODE_FUNC2        2
> +#define GPIO_MODE_FUNC3        3
> +#define GPIO_MODE_FUNC4        4
> +#define GPIO_MODE_FUNC5        5
> +#define GPIO_MODE_FUNC6        6

Please can you tab the numbers out to the same column?

> +
> +#define PIN_INPUT              0
> +#define PIN_OUTPUT             1
> +
> +#define PIN_INPUT_NOPULL       0
> +#define PIN_INPUT_PULLUP       1
> +#define PIN_INPUT_PULLDOWN     2
> +
> +#define PULL_STR_2K            0
> +#define PULL_STR_20K   2
> +
> +#endif
> --
> 2.1.4
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 4/4 v2] x86: minnowmax: initialize the pin-muxing from device tree
  2015-04-25 20:18   ` [U-Boot] [PATCH 4/4 v2] " Gabriel Huau
@ 2015-04-28 13:53     ` Simon Glass
  0 siblings, 0 replies; 61+ messages in thread
From: Simon Glass @ 2015-04-28 13:53 UTC (permalink / raw)
  To: u-boot

On 25 April 2015 at 14:18, Gabriel Huau <contact@huau-gabriel.fr> wrote:
> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
> ---
> Changes for v2:
>         - Fix ordering of include header
>
>  board/intel/minnowmax/minnowmax.c | 9 +++++++++
>  include/configs/minnowmax.h       | 1 +
>  2 files changed, 10 insertions(+)
>
> diff --git a/board/intel/minnowmax/minnowmax.c b/board/intel/minnowmax/minnowmax.c
> index 6e82b16..0244d35 100644
> --- a/board/intel/minnowmax/minnowmax.c
> +++ b/board/intel/minnowmax/minnowmax.c
> @@ -5,6 +5,7 @@
>   */
>
>  #include <common.h>
> +#include <asm/gpio.h>
>  #include <asm/ibmpc.h>
>  #include <asm/pnp_def.h>
>  #include <netdev.h>
> @@ -14,6 +15,14 @@
>
>  DECLARE_GLOBAL_DATA_PTR;
>
> +int arch_early_init_r(void)
> +{
> +       /* do the pin-muxing */
> +       gpio_ich6_pinctrl_init();
> +
> +       return 0;
> +}
> +
>  int board_early_init_f(void)
>  {
>         lpc47m_enable_serial(SERIAL_DEV, UART0_BASE);
> diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h
> index 823e051..3c7b266 100644
> --- a/include/configs/minnowmax.h
> +++ b/include/configs/minnowmax.h
> @@ -15,6 +15,7 @@
>
>  #define CONFIG_SYS_MONITOR_LEN         (1 << 20)
>  #define CONFIG_BOARD_EARLY_INIT_F
> +#define CONFIG_ARCH_EARLY_INIT_R
>
>  #define CONFIG_NR_DRAM_BANKS           1

Acked-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 3/4 v2] x86: gpio: add pinctrl support from the device tree
  2015-04-28 13:53     ` Simon Glass
@ 2015-04-28 15:22       ` Stephen Warren
  2015-05-12  3:34         ` gabriel huau
  2015-05-12  3:33       ` gabriel huau
  1 sibling, 1 reply; 61+ messages in thread
From: Stephen Warren @ 2015-04-28 15:22 UTC (permalink / raw)
  To: u-boot

On 04/28/2015 07:53 AM, Simon Glass wrote:
> Hi Gabriel,
>
> On 25 April 2015 at 14:17, Gabriel Huau <contact@huau-gabriel.fr> wrote:
>> Every pin can be configured now from the device tree. A dt-bindings
>> has been added to describe the different property available.

>> diff --git a/include/dt-bindings/gpio/x86-gpio.h b/include/dt-bindings/gpio/x86-gpio.h

>> +/*
>> + * This header provides constants for binding nvidia,tegra*-gpio.
>> + *
>> + * The first cell in Tegra's GPIO specifier is the GPIO ID. The macros below
>> + * provide names for this.

I think this comment needs updating.

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 1/4 v3] x86: baytrail: fix the GPIOBASE address
  2015-04-28 13:53       ` Simon Glass
@ 2015-04-28 15:39         ` Simon Glass
  0 siblings, 0 replies; 61+ messages in thread
From: Simon Glass @ 2015-04-28 15:39 UTC (permalink / raw)
  To: u-boot

On 28 April 2015 at 07:53, Simon Glass <sjg@chromium.org> wrote:
> On 26 April 2015 at 07:52, Bin Meng <bmeng.cn@gmail.com> wrote:
>> Hi Gabriel,
>>
>> On Sun, Apr 26, 2015 at 4:16 AM, Gabriel Huau <contact@huau-gabriel.fr> wrote:
>>> The correct GPIOBASE address on the baytrail is 0x48
>>>
>>> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
>>> ---
>>
>> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
>
> Acked-by: Simon Glass <sjg@chromium.org>

Applied to u-boot-x86, thanks!

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 2/4 v2] x86: minnowmax: add GPIO banks in the device tree
  2015-04-28 13:53       ` Simon Glass
@ 2015-04-28 15:39         ` Simon Glass
  0 siblings, 0 replies; 61+ messages in thread
From: Simon Glass @ 2015-04-28 15:39 UTC (permalink / raw)
  To: u-boot

On 28 April 2015 at 07:53, Simon Glass <sjg@chromium.org> wrote:
> On 26 April 2015 at 07:54, Bin Meng <bmeng.cn@gmail.com> wrote:
>> On Sun, Apr 26, 2015 at 4:16 AM, Gabriel Huau <contact@huau-gabriel.fr> wrote:
>>> There are 6 banks:
>>>     4 banks for CORE: available in S0 mode
>>>     2 banks for SUS (Suspend): available in S0-S5 mode
>>>
>>> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
>>> ---
>>> Changes for v2:
>>>         - Fix typo in the commit message
>>>
>>>  arch/x86/dts/minnowmax.dts | 42 ++++++++++++++++++++++++++++++++++++++++++
>>>  1 file changed, 42 insertions(+)

Applied to u-boot-x86, thanks!

>>>
>>> diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
>>> index 8f34369..c73e421 100644
>>> --- a/arch/x86/dts/minnowmax.dts
>>> +++ b/arch/x86/dts/minnowmax.dts
>>> @@ -21,6 +21,48 @@
>>>                 silent_console = <0>;
>>>         };
>>>
>>> +       gpioa {
>>> +               compatible = "intel,ich6-gpio";
>>> +               u-boot,dm-pre-reloc;
>>> +               reg = <0 0x20>;
>>> +               bank-name = "A";
>>> +       };
>>> +
>>> +       gpiob {
>>> +               compatible = "intel,ich6-gpio";
>>> +               u-boot,dm-pre-reloc;
>>> +               reg = <0x20 0x20>;
>>> +               bank-name = "B";
>>> +       };
>>> +
>>> +       gpioc {
>>> +               compatible = "intel,ich6-gpio";
>>> +               u-boot,dm-pre-reloc;
>>> +               reg = <0x40 0x20>;
>>> +               bank-name = "C";
>>> +       };
>>> +
>>> +       gpiod {
>>> +               compatible = "intel,ich6-gpio";
>>> +               u-boot,dm-pre-reloc;
>>> +               reg = <0x60 0x20>;
>>> +               bank-name = "D";
>>> +       };
>>> +
>>> +       gpioe {
>>> +               compatible = "intel,ich6-gpio";
>>> +               u-boot,dm-pre-reloc;
>>> +               reg = <0x80 0x20>;
>>> +               bank-name = "E";
>>> +       };
>>> +
>>> +       gpiof {
>>> +               compatible = "intel,ich6-gpio";
>>> +               u-boot,dm-pre-reloc;
>>> +               reg = <0xA0 0x20>;
>>> +               bank-name = "F";
>>> +       };
>>> +
>>>         chosen {
>>>                 stdout-path = "/serial";
>>>         };
>>> --
>>
>> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
>
> Acked-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 3/4 v2] x86: gpio: add pinctrl support from the device tree
  2015-04-28 13:53     ` Simon Glass
  2015-04-28 15:22       ` Stephen Warren
@ 2015-05-12  3:33       ` gabriel huau
  1 sibling, 0 replies; 61+ messages in thread
From: gabriel huau @ 2015-05-12  3:33 UTC (permalink / raw)
  To: u-boot

Hi Simon,

Sorry for the delay, I'm gonna provide a new version in the next few 
days but here is some answers to your question:

On 04/28/2015 06:53 AM, Simon Glass wrote:
> Hi Gabriel,
>
> On 25 April 2015 at 14:17, Gabriel Huau <contact@huau-gabriel.fr> wrote:
>> Every pin can be configured now from the device tree. A dt-bindings
>> has been added to describe the different property available.
>>
>> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
>> ---
>> Changes for v2:
>>          - Clean commit message
>>          - Rename compatible string 'ich6' to 'x86'
>>          - Fix coding style
>>          - Create a dt-bindinds documentation
>>          - Move x86-gpio defines to a specific header
>>          - Reorder the functions to avoid the need for forward declarations
>>          - Rename double underscore functions to only one
>>          - Create a specific function to configure one pin
>>          - Use a define to prevent build/support issues with other x86 CPU that
>>          doesn't have a IOBASE.
> I have a few minor comments below. Do you know how to access the GPIO
> pings on the top connector of the Minnowboard MAX? I'd like to figure
> out the pin names for those in U-Boot and that would allow me to test
> a few things.

You should be able to access SOC_GPIO_S5_0, SOC_GPIO_S5_1, SOC_GPIO_S5_2

GPIO_BASE should be 0x80 (respecting bit 0 1 and 2).
IO_BASE should be 0x1D0, 0x210, 0x1E0 (respect GPIO0, 1 and 2).

>>   arch/x86/dts/minnowmax.dts                         |  21 ++
>>   arch/x86/include/asm/arch-baytrail/gpio.h          |   1 +
>>   arch/x86/include/asm/gpio.h                        |   1 +
>>   .../gpio/intel,x86-pinctrl.txt                     |  31 +++
>>   drivers/gpio/intel_ich6_gpio.c                     | 234 ++++++++++++++++++---
>>   include/dt-bindings/gpio/x86-gpio.h                |  36 ++++
>>   6 files changed, 295 insertions(+), 29 deletions(-)
>>   create mode 100644 doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
>>   create mode 100644 include/dt-bindings/gpio/x86-gpio.h
>>
>> diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
>> index c73e421..ea10963 100644
>> --- a/arch/x86/dts/minnowmax.dts
>> +++ b/arch/x86/dts/minnowmax.dts
>> @@ -6,6 +6,8 @@
>>
>>   /dts-v1/;
>>
>> +#include <dt-bindings/gpio/x86-gpio.h>
>> +
>>   /include/ "skeleton.dtsi"
>>   /include/ "serial.dtsi"
>>
>> @@ -21,6 +23,25 @@
>>                  silent_console = <0>;
>>          };
>>
>> +       pch_pinctrl {
>> +               compatible = "intel,x86-pinctrl";
>> +               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 = <0x258>;
>> +                       mode-gpio;
>> +                       output-value = <1>;
>> +                       direction = <PIN_OUTPUT>;
>> +               };
>> +       };
>> +
>>          gpioa {
>>                  compatible = "intel,ich6-gpio";
>>                  u-boot,dm-pre-reloc;
>> diff --git a/arch/x86/include/asm/arch-baytrail/gpio.h b/arch/x86/include/asm/arch-baytrail/gpio.h
>> index 4e8987c..85a65a8 100644
>> --- a/arch/x86/include/asm/arch-baytrail/gpio.h
>> +++ b/arch/x86/include/asm/arch-baytrail/gpio.h
>> @@ -9,5 +9,6 @@
>>
>>   /* Where in config space is the register that points to the GPIO registers? */
>>   #define PCI_CFG_GPIOBASE 0x48
>> +#define PCI_CFG_IOBASE   0x4c
> Can we put this in the device tree as a property of the pch_pinctrl
> node? If you like we could do it later.
Yes, I will do the modification, I thought as a first version it would 
be easier to use a define but actually, a property is cleaner and also 
easy to implement.

>>   #endif /* _X86_ARCH_GPIO_H_ */
>> diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h
>> index 1099427..ed85b08 100644
>> --- a/arch/x86/include/asm/gpio.h
>> +++ b/arch/x86/include/asm/gpio.h
>> @@ -147,6 +147,7 @@ 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/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt b/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
>> new file mode 100644
>> index 0000000..45ab1af
>> --- /dev/null
>> +++ b/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
>> @@ -0,0 +1,31 @@
>> +Intel x86 PINCTRL/GPIO controller
>> +
>> +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.
>> +
>> +The PINCTRL master node requires the following properties:
>> +- compatible : "intel,x86-pinctrl"
>> +
>> +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'
>> +                                       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.
>> +- 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.
>> +
>> +Example:
>> +
>> +pin_usb_host_en0 at 0 {
>> +    gpio-offset = <0x80 8>;
>> +    pad-offset = <0x260>;
>> +    mode-gpio;
>> +    output-value = <1>;
>> +    direction = <PIN_OUTPUT>;
>> +};
>> diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
>> index 7e679a0..c18c60f 100644
>> --- a/drivers/gpio/intel_ich6_gpio.c
>> +++ b/drivers/gpio/intel_ich6_gpio.c
>> @@ -44,21 +44,28 @@ struct ich6_bank_priv {
>>          uint16_t lvl;
>>   };
>>
>> +#define GPIO_USESEL_OFFSET(x)  (x)
>> +#define GPIO_IOSEL_OFFSET(x)   (x + 4)
>> +#define GPIO_LVL_OFFSET(x)             (x + 8)
> Please align all of these values to the same tab column.
>
I will do.

>> +
>> +#define IOPAD_MODE_MASK                                0x7
>> +#define IOPAD_PULL_ASSIGN_SHIFT                7
>> +#define IOPAD_PULL_ASSIGN_MASK         (0x3 << IOPAD_PULL_ASSIGN_SHIFT)
>> +#define IOPAD_PULL_STRENGTH_SHIFT      9
>> +#define IOPAD_PULL_STRENGTH_MASK       (0x3 << IOPAD_PULL_STRENGTH_SHIFT)
>> +
>>   /* TODO: Move this to device tree, or platform data */
>>   void ich_gpio_set_gpio_map(const struct pch_gpio_map *map)
>>   {
>>          gd->arch.gpio_map = map;
>>   }
>>
>> -static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>> +static int gpio_ich6_get_base(unsigned long base)
>>   {
>> -       struct ich6_bank_platdata *plat = dev_get_platdata(dev);
>>          pci_dev_t pci_dev;                      /* handle for 0:1f:0 */
>>          u8 tmpbyte;
>>          u16 tmpword;
>>          u32 tmplong;
>> -       u16 gpiobase;
>> -       int offset;
>>
>>          /* Where should it be? */
>>          pci_dev = PCI_BDF(0, 0x1f, 0);
>> @@ -123,9 +130,9 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>>           * while on the Ivybridge the bit0 is used to indicate it is an
>>           * I/O space.
>>           */
>> -       tmplong = x86_pci_read_config32(pci_dev, PCI_CFG_GPIOBASE);
>> +       tmplong = x86_pci_read_config32(pci_dev, base);
>>          if (tmplong == 0x00000000 || tmplong == 0xffffffff) {
>> -               debug("%s: unexpected GPIOBASE value\n", __func__);
>> +               debug("%s: unexpected BASE value\n", __func__);
>>                  return -ENODEV;
>>          }
>>
>> @@ -135,7 +142,195 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>>           * at the offset that we just read. Bit 0 indicates that it's
>>           * an I/O address, not a memory address, so mask that off.
>>           */
>> -       gpiobase = tmplong & 0xfffe;
>> +       return tmplong & 0xfffc;
>> +}
>> +
>> +static int _ich6_gpio_set_value(uint16_t base, unsigned offset, int value)
>> +{
>> +       u32 tmplong;
> blank line here. Also can we use something like 'val' instead of
> tmplong? I think calling a u32 'long' is confusing.
Agreed, I was just trying to reuse the variable for some other property, 
but it was a bad idea as it also introduced some errors due to the sign 
of the type.

>> +       tmplong = inl(base);
>> +       if (value)
>> +               tmplong |= (1UL << offset);
>> +       else
>> +               tmplong &= ~(1UL << offset);
>> +       outl(tmplong, base);
>> +
>> +       return 0;
>> +}
>> +
>> +static int _ich6_gpio_set_function(uint16_t base, unsigned offset, int func)
>> +{
>> +       u32 tmplong;
>> +
>> +       if (func) {
>> +               tmplong = inl(base);
>> +               tmplong |= (1UL << offset);
>> +               outl(tmplong, base);
>> +       } else {
>> +               tmplong = inl(base);
>> +               tmplong &= ~(1UL << offset);
>> +               outl(tmplong, base);
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int _ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir)
>> +{
>> +       u32 tmplong;
>> +
>> +       if (!dir) {
>> +               tmplong = inl(base);
>> +               tmplong |= (1UL << offset);
>> +               outl(tmplong, base);
>> +       } else {
>> +               tmplong = inl(base);
>> +               tmplong &= ~(1UL << offset);
>> +               outl(tmplong, base);
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int _gpio_ich6_pinctrl_cfg_pin(u32 gpiobase, u32 iobase, int pin_node)
>> +{
>> +       u32 gpio_offset[2] = { -1, -1 };
>> +       u32 pad_offset;
>> +       int tmplong;
>> +       const void *tmpnode;
> Perhaps 'prop' is a better name. It doesn't point to a node, but a
> property of a node.
Agreed.

>> +
>> +       /*
>> +        * GPIO node is not mandatory, so we only do the
>> +        * pinmuxing if the node exist.
>> +        */
>> +       fdtdec_get_int_array(gd->fdt_blob, pin_node, "gpio-offset",
>> +                            gpio_offset, 2);
>> +       if (gpio_offset[0] != -1) {
>> +               /* Do we want to force the GPIO mode? */
>> +               tmpnode = fdt_getprop(gd->fdt_blob, pin_node, "mode-gpio",
>> +                                     NULL);
>> +               if (tmpnode)
> {} around these multi-line blocks. If you use patman it will run
> checkpatch for you.
>
Actually, I'm running checkpatch on all the patches all the time, I'm 
pretty surprised to have miss it. I will definitely try to use patman,

>> +                       _ich6_gpio_set_function(GPIO_USESEL_OFFSET
>> +                                               (gpiobase) +
>> +                                               gpio_offset[0],
>> +                                               gpio_offset[1], 1);
>> +
>> +               tmplong =
>> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "direction", -1);
>> +               if (tmplong != -1)
>> +                       _ich6_gpio_set_direction(GPIO_IOSEL_OFFSET
>> +                                                (gpiobase) +
>> +                                                gpio_offset[0],
>> +                                                gpio_offset[1], tmplong);
>> +
>> +               tmplong =
>> +                   fdtdec_get_int(gd->fdt_blob, pin_node, "output-value", -1);
>> +               if (tmplong != -1)
>> +                       _ich6_gpio_set_value(GPIO_LVL_OFFSET(gpiobase)
>> +                                            + gpio_offset[0],
>> +                                            gpio_offset[1], tmplong);
>> +       }
>> +#ifdef PCI_CFG_IOBASE
> We should avoid adding #ifdefs like this to the driver. Perhaps the
> device tree can provide this property, or not? OK if you want to
> tackle this in a follow-on patch.
No I think you are right, I can do the modification for the v3.

>> +       /*
>> +        * The offset for the same pin for the IOBASE and GPIOBASE are
>> +        * different, so instead of maintaining a lookup table,
>> +        * the device tree should provide directly the correct
>> +        * value for both mapping.
>> +        */
>> +       pad_offset = fdtdec_get_int(gd->fdt_blob, pin_node, "pad-offset", -1);
>> +       if (pad_offset == -1) {
>> +               debug("%s: Invalid register io offset %d\n",
>> +                     __func__, pad_offset);
>> +               return -EINVAL;
>> +       }
>> +
>> +       /*
>> +        * Do we need to set a specific function mode?
>> +        * If someone put also 'mode-gpio', this option will
>> +        * be just ignored by the controller
>> +        */
>> +       tmplong = fdtdec_get_int(gd->fdt_blob, pin_node, "mode-func", -1);
>> +       if (tmplong != -1)
>> +               clrsetbits_le32(iobase + pad_offset, IOPAD_MODE_MASK, tmplong);
>> +
>> +       /* Configure the pull-up/down if needed */
>> +       tmplong = fdtdec_get_int(gd->fdt_blob, pin_node, "pull-assign", -1);
>> +       if (tmplong != -1)
>> +               clrsetbits_le32(iobase + pad_offset,
> Can you create a local variable for (iobase + pad_offset) ?
I will do.

>> +                               IOPAD_PULL_ASSIGN_MASK,
>> +                               tmplong << IOPAD_PULL_ASSIGN_SHIFT);
>> +
>> +       tmplong = fdtdec_get_int(gd->fdt_blob, pin_node, "pull-strength", -1);
>> +       if (tmplong != -1)
>> +               clrsetbits_le32(iobase + pad_offset,
>> +                               IOPAD_PULL_STRENGTH_MASK,
>> +                               tmplong << IOPAD_PULL_STRENGTH_SHIFT);
>> +
>> +       debug("%s: pad cfg [0x%x]: %08x\n", __func__, pad_offset,
>> +             readl(iobase + pad_offset));
>> +#endif
>> +
>> +       return 0;
>> +}
>> +
>> +int gpio_ich6_pinctrl_init(void)
>> +{
>> +       int pin_node;
>> +       int node;
>> +       int ret;
>> +       u32 gpiobase;
>> +       u32 iobase;
>> +
>> +#ifdef PCI_CFG_IOBASE
> If this block is #ifdef'd out then you will have an uninited variable
> iobase, used below.
Right, as I'm going to move to a property, I will fix this error as well.

>> +       /*
>> +        * 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
>> +        */
>> +       iobase = gpio_ich6_get_base(PCI_CFG_IOBASE);
>> +       if (iobase < 0) {
>> +               debug("%s: invalid IOBASE address (%08x)\n", __func__, iobase);
>> +               return -EINVAL;
>> +       }
>> +#endif
>> +
>> +       gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
>> +       if (gpiobase < 0) {
>> +               debug("%s: invalid GPIOBASE address (%08x)\n", __func__,
>> +                     gpiobase);
>> +               return -EINVAL;
>> +       }
>> +
>> +       /* This is not an error to not have a pinctrl node */
>> +       node = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
>> +                                            "intel,x86-pinctrl");
> This should be added to the tables in fdtdec.c/h. Then use
> fdtdec_next_compatible(). That file contains a list of all the
> compatible strings we have in U-Boot and is an indicator of what needs
> to be converted to driver model.
Ok, make sense.

>> +       if (node < 0) {
>> +               debug("%s: no pinctrl node\n", __func__);
>> +               return 0;
>> +       }
>> +
>> +       for (pin_node = fdt_first_subnode(gd->fdt_blob, node);
>> +            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);
>> +               if (ret != 0) {
>> +                       debug("%s: invalid configuration for the pin %d\n",
>> +                             __func__, pin_node);
>> +                       return ret;
>> +               }
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>> +{
>> +       struct ich6_bank_platdata *plat = dev_get_platdata(dev);
>> +       u16 gpiobase;
>> +       int offset;
>> +
>> +       gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
>>          offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
>>          if (offset == -1) {
>>                  debug("%s: Invalid register offset %d\n", __func__, offset);
>> @@ -192,30 +387,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);
>> -       u32 tmplong;
>>
>> -       tmplong = inl(bank->io_sel);
>> -       tmplong |= (1UL << offset);
>> -       outl(bank->io_sel, tmplong);
>> -       return 0;
>> +       return _ich6_gpio_set_direction(inl(bank->io_sel), offset, 0);
>>   }
>>
>>   static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
>>                                         int value)
>>   {
>>          struct ich6_bank_priv *bank = dev_get_priv(dev);
>> -       u32 tmplong;
>>
>> -       gpio_set_value(offset, value);
>> -
>> -       tmplong = inl(bank->io_sel);
>> -       tmplong &= ~(1UL << offset);
>> -       outl(bank->io_sel, tmplong);
>> -       return 0;
>> +       return _ich6_gpio_set_direction(inl(bank->io_sel), offset, 1);
>>   }
>>
>>   static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
>> -
>>   {
>>          struct ich6_bank_priv *bank = dev_get_priv(dev);
>>          u32 tmplong;
>> @@ -230,15 +414,7 @@ static int ich6_gpio_set_value(struct udevice *dev, unsigned offset,
>>                                 int value)
>>   {
>>          struct ich6_bank_priv *bank = dev_get_priv(dev);
>> -       u32 tmplong;
>> -
>> -       tmplong = inl(bank->lvl);
>> -       if (value)
>> -               tmplong |= (1UL << offset);
>> -       else
>> -               tmplong &= ~(1UL << offset);
>> -       outl(bank->lvl, tmplong);
>> -       return 0;
>> +       return _ich6_gpio_set_value(bank->lvl, offset, value);
>>   }
>>
>>   static int ich6_gpio_get_function(struct udevice *dev, unsigned offset)
>> diff --git a/include/dt-bindings/gpio/x86-gpio.h b/include/dt-bindings/gpio/x86-gpio.h
>> new file mode 100644
>> index 0000000..103bd04
>> --- /dev/null
>> +++ b/include/dt-bindings/gpio/x86-gpio.h
>> @@ -0,0 +1,36 @@
>> +/*
>> + * This header provides constants for binding nvidia,tegra*-gpio.
>> + *
>> + * The first cell in Tegra's GPIO specifier is the GPIO ID. The macros below
>> + * provide names for this.
>> + *
>> + * The second cell contains standard flag values specified in gpio.h.
>> + */
>> +
>> +#ifndef _DT_BINDINGS_GPIO_X86_GPIO_H
>> +#define _DT_BINDINGS_GPIO_X86_GPIO_H
>> +
>> +#include <dt-bindings/gpio/gpio.h>
>> +
>> +#define GPIO_MODE_NATIVE       0
>> +#define GPIO_MODE_GPIO         1
>> +
>> +#define GPIO_MODE_FUNC0        0
>> +#define GPIO_MODE_FUNC1        1
>> +#define GPIO_MODE_FUNC2        2
>> +#define GPIO_MODE_FUNC3        3
>> +#define GPIO_MODE_FUNC4        4
>> +#define GPIO_MODE_FUNC5        5
>> +#define GPIO_MODE_FUNC6        6
> Please can you tab the numbers out to the same column?
I will do.

>> +
>> +#define PIN_INPUT              0
>> +#define PIN_OUTPUT             1
>> +
>> +#define PIN_INPUT_NOPULL       0
>> +#define PIN_INPUT_PULLUP       1
>> +#define PIN_INPUT_PULLDOWN     2
>> +
>> +#define PULL_STR_2K            0
>> +#define PULL_STR_20K   2
>> +
>> +#endif
>> --
>> 2.1.4
>>
> Regards,
> Simon
Regards,
Gabriel

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH 3/4 v2] x86: gpio: add pinctrl support from the device tree
  2015-04-28 15:22       ` Stephen Warren
@ 2015-05-12  3:34         ` gabriel huau
  0 siblings, 0 replies; 61+ messages in thread
From: gabriel huau @ 2015-05-12  3:34 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

Thanks for the feedback, I completely miss it, I will do the 
modification for the v3.

On 04/28/2015 08:22 AM, Stephen Warren wrote:
> On 04/28/2015 07:53 AM, Simon Glass wrote:
>> Hi Gabriel,
>>
>> On 25 April 2015 at 14:17, Gabriel Huau <contact@huau-gabriel.fr> wrote:
>>> Every pin can be configured now from the device tree. A dt-bindings
>>> has been added to describe the different property available.
>
>>> diff --git a/include/dt-bindings/gpio/x86-gpio.h 
>>> b/include/dt-bindings/gpio/x86-gpio.h
>
>>> +/*
>>> + * This header provides constants for binding nvidia,tegra*-gpio.
>>> + *
>>> + * The first cell in Tegra's GPIO specifier is the GPIO ID. The 
>>> macros below
>>> + * provide names for this.
>
> I think this comment needs updating.

Regards,
Gabriel

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH v3 3/4] x86: gpio: add pinctrl support from the device tree
  2015-04-23 16:16 [U-Boot] [PATCH 0/4] x86: support of pin-muxing from device tree Gabriel Huau
                   ` (10 preceding siblings ...)
  2015-04-24  5:05 ` [U-Boot] unassigned-patches/148: " u-boot at bugs.denx.de
@ 2015-05-12  6:10 ` Gabriel Huau
  2015-05-12  6:20   ` gabriel huau
  2015-05-12  6:12 ` [U-Boot] [PATCH v3 4/4] x86: minnowmax: initialize the pin-muxing from " Gabriel Huau
  2015-05-12  6:15 ` [U-Boot] [PATCH v3 3/4] x86: gpio: add pinctrl support from the " Gabriel Huau
  13 siblings, 1 reply; 61+ messages in thread
From: Gabriel Huau @ 2015-05-12  6:10 UTC (permalink / raw)
  To: u-boot

Every pin can be configured now from the device tree. A dt-bindings
has been added to describe the different property available.

Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>

---

Changes in v3:
    - Fix the dt-binding copyright header
    - Remove define for IOBASE and use a property
    - Fix issues with signed/unsigned variable type
    - Fix coding style
    - Add a compatible string for the driver

Changes in v2:
    - Clean commit message
    - Rename compatible string 'ich6' to 'x86'
    - Fix coding style
    - Create a dt-bindinds documentation
    - Move x86-gpio defines to a specific header
    - Reorder the functions to avoid the need for forward declarations
    - Rename double underscore functions to only one
    - Create a specific function to configure one pin
    - Use a define to prevent build/support issues with other x86 CPU that
    doesn't have a IOBASE.

 arch/x86/dts/minnowmax.dts                         |  23 ++
 arch/x86/include/asm/gpio.h                        |   1 +
 .../gpio/intel,x86-pinctrl.txt                     |  31 +++
 drivers/gpio/intel_ich6_gpio.c                     | 254 ++++++++++++++++++---
 include/dt-bindings/gpio/x86-gpio.h                |  31 +++
 include/fdtdec.h                                   |   1 +
 lib/fdtdec.c                                       |   1 +
 7 files changed, 312 insertions(+), 30 deletions(-)
 create mode 100644 doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
 create mode 100644 include/dt-bindings/gpio/x86-gpio.h

diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
index 7103bc5..bd21bfb 100644
--- a/arch/x86/dts/minnowmax.dts
+++ b/arch/x86/dts/minnowmax.dts
@@ -6,6 +6,8 @@
 
 /dts-v1/;
 
+#include <dt-bindings/gpio/x86-gpio.h>
+
 /include/ "skeleton.dtsi"
 /include/ "serial.dtsi"
 
@@ -22,6 +24,27 @@
 		silent_console = <0>;
 	};
 
+	pch_pinctrl {
+		compatible = "intel,x86-pinctrl";
+		io-base = <0x4c>;
+
+		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 = <0x258>;
+			mode-gpio;
+			output-value = <1>;
+			direction = <PIN_OUTPUT>;
+		};
+	};
+
 	gpioa {
 		compatible = "intel,ich6-gpio";
 		u-boot,dm-pre-reloc;
diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h
index 1099427..ed85b08 100644
--- a/arch/x86/include/asm/gpio.h
+++ b/arch/x86/include/asm/gpio.h
@@ -147,6 +147,7 @@ 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/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt b/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
new file mode 100644
index 0000000..45ab1af
--- /dev/null
+++ b/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
@@ -0,0 +1,31 @@
+Intel x86 PINCTRL/GPIO controller
+
+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.
+
+The PINCTRL master node requires the following properties:
+- compatible : "intel,x86-pinctrl"
+
+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'
+					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.
+- 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.
+
+Example:
+
+pin_usb_host_en0 at 0 {
+    gpio-offset = <0x80 8>;
+    pad-offset = <0x260>;
+    mode-gpio;
+    output-value = <1>;
+    direction = <PIN_OUTPUT>;
+};
diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
index 7e679a0..35e8197 100644
--- a/drivers/gpio/intel_ich6_gpio.c
+++ b/drivers/gpio/intel_ich6_gpio.c
@@ -44,21 +44,28 @@ struct ich6_bank_priv {
 	uint16_t 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)
+#define IOPAD_PULL_STRENGTH_SHIFT	9
+#define IOPAD_PULL_STRENGTH_MASK	(0x3 << IOPAD_PULL_STRENGTH_SHIFT)
+
 /* TODO: Move this to device tree, or platform data */
 void ich_gpio_set_gpio_map(const struct pch_gpio_map *map)
 {
 	gd->arch.gpio_map = map;
 }
 
-static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
+static int gpio_ich6_get_base(unsigned long base)
 {
-	struct ich6_bank_platdata *plat = dev_get_platdata(dev);
-	pci_dev_t pci_dev;			/* handle for 0:1f:0 */
+	pci_dev_t pci_dev;	/* handle for 0:1f:0 */
 	u8 tmpbyte;
 	u16 tmpword;
 	u32 tmplong;
-	u16 gpiobase;
-	int offset;
 
 	/* Where should it be? */
 	pci_dev = PCI_BDF(0, 0x1f, 0);
@@ -123,9 +130,9 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
 	 * while on the Ivybridge the bit0 is used to indicate it is an
 	 * I/O space.
 	 */
-	tmplong = x86_pci_read_config32(pci_dev, PCI_CFG_GPIOBASE);
+	tmplong = x86_pci_read_config32(pci_dev, base);
 	if (tmplong == 0x00000000 || tmplong == 0xffffffff) {
-		debug("%s: unexpected GPIOBASE value\n", __func__);
+		debug("%s: unexpected BASE value\n", __func__);
 		return -ENODEV;
 	}
 
@@ -135,7 +142,213 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
 	 * at the offset that we just read. Bit 0 indicates that it's
 	 * an I/O address, not a memory address, so mask that off.
 	 */
-	gpiobase = tmplong & 0xfffe;
+	return tmplong & 0xfffc;
+}
+
+static int _ich6_gpio_set_value(uint16_t base, unsigned offset, int value)
+{
+	u32 val;
+
+	val = inl(base);
+	if (value)
+		val |= (1UL << offset);
+	else
+		val &= ~(1UL << offset);
+	outl(val, base);
+
+	return 0;
+}
+
+static int _ich6_gpio_set_function(uint16_t base, unsigned offset, int func)
+{
+	u32 val;
+
+	if (func) {
+		val = inl(base);
+		val |= (1UL << offset);
+		outl(val, base);
+	} else {
+		val = inl(base);
+		val &= ~(1UL << offset);
+		outl(val, base);
+	}
+
+	return 0;
+}
+
+static int _ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir)
+{
+	u32 val;
+
+	if (!dir) {
+		val = inl(base);
+		val |= (1UL << offset);
+		outl(val, base);
+	} else {
+		val = inl(base);
+		val &= ~(1UL << offset);
+		outl(val, base);
+	}
+
+	return 0;
+}
+
+static int _gpio_ich6_pinctrl_cfg_pin(s32 gpiobase, s32 iobase, int pin_node)
+{
+	u32 gpio_offset[2];
+	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) {
+		/* 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);
+
+		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);
+
+		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);
+	}
+
+	/* if iobase is present, let's configure the pad */
+	if (iobase != -1) {
+		int iobase_addr;
+
+		/*
+		 * The offset for the same pin for the IOBASE and GPIOBASE are
+		 * different, so instead of maintaining a lookup table,
+		 * the device tree should provide directly the correct
+		 * value for both mapping.
+		 */
+		pad_offset =
+		    fdtdec_get_int(gd->fdt_blob, pin_node, "pad-offset", -1);
+		if (pad_offset == -1) {
+			debug("%s: Invalid register io offset %d\n",
+			      __func__, pad_offset);
+			return -EINVAL;
+		}
+
+		/* compute the absolute pad address */
+		iobase_addr = iobase + pad_offset;
+
+		/*
+		 * Do we need to set a specific function mode?
+		 * If someone put also 'mode-gpio', this option will
+		 * be just ignored by the controller
+		 */
+		val = fdtdec_get_int(gd->fdt_blob, pin_node, "mode-func", -1);
+		if (val != -1)
+			clrsetbits_le32(iobase_addr, IOPAD_MODE_MASK, val);
+
+		/* Configure the pull-up/down if needed */
+		val = fdtdec_get_int(gd->fdt_blob, pin_node, "pull-assign", -1);
+		if (val != -1)
+			clrsetbits_le32(iobase_addr,
+					IOPAD_PULL_ASSIGN_MASK,
+					val << IOPAD_PULL_ASSIGN_SHIFT);
+
+		val =
+		    fdtdec_get_int(gd->fdt_blob, pin_node, "pull-strength", -1);
+		if (val != -1)
+			clrsetbits_le32(iobase_addr,
+					IOPAD_PULL_STRENGTH_MASK,
+					val << IOPAD_PULL_STRENGTH_SHIFT);
+
+		debug("%s: pad cfg [0x%x]: %08x\n", __func__, pad_offset,
+		      readl(iobase_addr));
+	}
+
+	return 0;
+}
+
+int gpio_ich6_pinctrl_init(void)
+{
+	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;
+	}
+
+	/* This is not an error to not have a pinctrl node */
+	node =
+	    fdtdec_next_compatible(gd->fdt_blob, 0, COMPAT_INTEL_X86_PINCTRL);
+	if (node <= 0) {
+		debug("%s: no pinctrl node\n", __func__);
+		return 0;
+	}
+
+	/*
+	 * Get the IOBASE, this is not mandatory as this is not
+	 * supported by all the CPU
+	 */
+	iobase_offset = fdtdec_get_int(gd->fdt_blob, node, "io-offset", -1);
+	if (iobase_offset == -1) {
+		debug("%s: io-base offset not present\n", __func__);
+	} else {
+		iobase = gpio_ich6_get_base(iobase_offset);
+		if (iobase < 0) {
+			debug("%s: invalid IOBASE address (%08x)\n", __func__,
+			      iobase);
+			return -EINVAL;
+		}
+	}
+
+	for (pin_node = fdt_first_subnode(gd->fdt_blob, node);
+	     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);
+		if (ret != 0) {
+			debug("%s: invalid configuration for the pin %d\n",
+			      __func__, pin_node);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ich6_bank_platdata *plat = dev_get_platdata(dev);
+	u16 gpiobase;
+	int offset;
+
+	gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
 	offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
 	if (offset == -1) {
 		debug("%s: Invalid register offset %d\n", __func__, offset);
@@ -192,30 +405,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);
-	u32 tmplong;
 
-	tmplong = inl(bank->io_sel);
-	tmplong |= (1UL << offset);
-	outl(bank->io_sel, tmplong);
-	return 0;
+	return _ich6_gpio_set_direction(inl(bank->io_sel), offset, 0);
 }
 
 static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
 				       int value)
 {
 	struct ich6_bank_priv *bank = dev_get_priv(dev);
-	u32 tmplong;
 
-	gpio_set_value(offset, value);
-
-	tmplong = inl(bank->io_sel);
-	tmplong &= ~(1UL << offset);
-	outl(bank->io_sel, tmplong);
-	return 0;
+	return _ich6_gpio_set_direction(inl(bank->io_sel), offset, 1);
 }
 
 static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
-
 {
 	struct ich6_bank_priv *bank = dev_get_priv(dev);
 	u32 tmplong;
@@ -230,15 +432,7 @@ static int ich6_gpio_set_value(struct udevice *dev, unsigned offset,
 			       int value)
 {
 	struct ich6_bank_priv *bank = dev_get_priv(dev);
-	u32 tmplong;
-
-	tmplong = inl(bank->lvl);
-	if (value)
-		tmplong |= (1UL << offset);
-	else
-		tmplong &= ~(1UL << offset);
-	outl(bank->lvl, tmplong);
-	return 0;
+	return _ich6_gpio_set_value(bank->lvl, offset, value);
 }
 
 static int ich6_gpio_get_function(struct udevice *dev, unsigned offset)
diff --git a/include/dt-bindings/gpio/x86-gpio.h b/include/dt-bindings/gpio/x86-gpio.h
new file mode 100644
index 0000000..7f1de30
--- /dev/null
+++ b/include/dt-bindings/gpio/x86-gpio.h
@@ -0,0 +1,31 @@
+/*
+ * This header provides constants for binding intel,x86-pinctrl.
+ */
+
+#ifndef _DT_BINDINGS_GPIO_X86_GPIO_H
+#define _DT_BINDINGS_GPIO_X86_GPIO_H
+
+#include <dt-bindings/gpio/gpio.h>
+
+#define GPIO_MODE_NATIVE	0
+#define GPIO_MODE_GPIO		1
+
+#define GPIO_MODE_FUNC0	0
+#define GPIO_MODE_FUNC1	1
+#define GPIO_MODE_FUNC2	2
+#define GPIO_MODE_FUNC3	3
+#define GPIO_MODE_FUNC4	4
+#define GPIO_MODE_FUNC5	5
+#define GPIO_MODE_FUNC6	6
+
+#define PIN_INPUT	0
+#define PIN_OUTPUT	1
+
+#define PIN_INPUT_NOPULL	0
+#define PIN_INPUT_PULLUP	1
+#define PIN_INPUT_PULLDOWN	2
+
+#define PULL_STR_2K		0
+#define PULL_STR_20K	2
+
+#endif
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 6590470..5146ff1 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -175,6 +175,7 @@ enum fdt_compat_id {
 	COMPAT_AMS_AS3722,		/* AMS AS3722 PMIC */
 	COMPAT_INTEL_ICH_SPI,		/* Intel ICH7/9 SPI controller */
 	COMPAT_INTEL_QRK_MRC,		/* Intel Quark MRC */
+	COMPAT_INTEL_X86_PINCTRL,	/* Intel ICH7/9 pin control */
 	COMPAT_SOCIONEXT_XHCI,		/* Socionext UniPhier xHCI */
 	COMPAT_INTEL_PCH,		/* Intel PCH */
 
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 80b897a..6bdc270 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -74,6 +74,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(AMS_AS3722, "ams,as3722"),
 	COMPAT(INTEL_ICH_SPI, "intel,ich-spi"),
 	COMPAT(INTEL_QRK_MRC, "intel,quark-mrc"),
+	COMPAT(INTEL_X86_PINCTRL, "intel,x86-pinctrl"),
 	COMPAT(SOCIONEXT_XHCI, "socionext,uniphier-xhci"),
 	COMPAT(COMPAT_INTEL_PCH, "intel,bd82x6x"),
 };
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH v3 4/4] x86: minnowmax: initialize the pin-muxing from device tree
  2015-04-23 16:16 [U-Boot] [PATCH 0/4] x86: support of pin-muxing from device tree Gabriel Huau
                   ` (11 preceding siblings ...)
  2015-05-12  6:10 ` [U-Boot] [PATCH v3 3/4] x86: gpio: add pinctrl support from the " Gabriel Huau
@ 2015-05-12  6:12 ` Gabriel Huau
  2015-05-12  6:20   ` gabriel huau
  2015-05-12  6:15 ` [U-Boot] [PATCH v3 3/4] x86: gpio: add pinctrl support from the " Gabriel Huau
  13 siblings, 1 reply; 61+ messages in thread
From: Gabriel Huau @ 2015-05-12  6:12 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
Acked-by: Simon Glass <sjg@chromium.org>

---

Changes in v3:
    - Rebase to the origin/master

Changes in v2:
    - Fix ordering of include header

 board/intel/minnowmax/minnowmax.c | 9 +++++++++
 include/configs/minnowmax.h       | 1 +
 2 files changed, 10 insertions(+)

diff --git a/board/intel/minnowmax/minnowmax.c b/board/intel/minnowmax/minnowmax.c
index 1f5549a..383cae0 100644
--- a/board/intel/minnowmax/minnowmax.c
+++ b/board/intel/minnowmax/minnowmax.c
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <asm/gpio.h>
 #include <asm/ibmpc.h>
 #include <asm/pnp_def.h>
 #include <netdev.h>
@@ -12,6 +13,14 @@
 
 #define SERIAL_DEV PNP_DEV(0x2e, 4)
 
+int arch_early_init_r(void)
+{
+	/* do the pin-muxing */
+	gpio_ich6_pinctrl_init();
+
+	return 0;
+}
+
 int board_early_init_f(void)
 {
 	lpc47m_enable_serial(SERIAL_DEV, UART0_BASE, UART0_IRQ);
diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h
index eb35a50..547765d 100644
--- a/include/configs/minnowmax.h
+++ b/include/configs/minnowmax.h
@@ -15,6 +15,7 @@
 
 #define CONFIG_SYS_MONITOR_LEN		(1 << 20)
 #define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_ARCH_EARLY_INIT_R
 
 #define CONFIG_X86_SERIAL
 #define CONFIG_SMSC_LPC47M
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH v3 3/4] x86: gpio: add pinctrl support from the device tree
  2015-04-23 16:16 [U-Boot] [PATCH 0/4] x86: support of pin-muxing from device tree Gabriel Huau
                   ` (12 preceding siblings ...)
  2015-05-12  6:12 ` [U-Boot] [PATCH v3 4/4] x86: minnowmax: initialize the pin-muxing from " Gabriel Huau
@ 2015-05-12  6:15 ` Gabriel Huau
  2015-05-12  6:21   ` gabriel huau
  13 siblings, 1 reply; 61+ messages in thread
From: Gabriel Huau @ 2015-05-12  6:15 UTC (permalink / raw)
  To: u-boot

Every pin can be configured now from the device tree. A dt-bindings
has been added to describe the different property available.

Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>

---

Changes in v3:
    - Fix the dt-binding copyright header
    - Remove define for IOBASE and use a property
    - Fix issues with signed/unsigned variable type
    - Fix coding style
    - Add a compatible string for the driver

Changes in v2:
    - Clean commit message
    - Rename compatible string 'ich6' to 'x86'
    - Fix coding style
    - Create a dt-bindinds documentation
    - Move x86-gpio defines to a specific header
    - Reorder the functions to avoid the need for forward declarations
    - Rename double underscore functions to only one
    - Create a specific function to configure one pin
    - Use a define to prevent build/support issues with other x86 CPU that
    doesn't have a IOBASE.

 arch/x86/dts/minnowmax.dts                         |  23 ++
 arch/x86/include/asm/gpio.h                        |   1 +
 .../gpio/intel,x86-pinctrl.txt                     |  31 +++
 drivers/gpio/intel_ich6_gpio.c                     | 254 ++++++++++++++++++---
 include/dt-bindings/gpio/x86-gpio.h                |  31 +++
 include/fdtdec.h                                   |   1 +
 lib/fdtdec.c                                       |   1 +
 7 files changed, 312 insertions(+), 30 deletions(-)
 create mode 100644 doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
 create mode 100644 include/dt-bindings/gpio/x86-gpio.h

diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
index 7103bc5..bd21bfb 100644
--- a/arch/x86/dts/minnowmax.dts
+++ b/arch/x86/dts/minnowmax.dts
@@ -6,6 +6,8 @@
 
 /dts-v1/;
 
+#include <dt-bindings/gpio/x86-gpio.h>
+
 /include/ "skeleton.dtsi"
 /include/ "serial.dtsi"
 
@@ -22,6 +24,27 @@
 		silent_console = <0>;
 	};
 
+	pch_pinctrl {
+		compatible = "intel,x86-pinctrl";
+		io-base = <0x4c>;
+
+		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 = <0x258>;
+			mode-gpio;
+			output-value = <1>;
+			direction = <PIN_OUTPUT>;
+		};
+	};
+
 	gpioa {
 		compatible = "intel,ich6-gpio";
 		u-boot,dm-pre-reloc;
diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h
index 1099427..ed85b08 100644
--- a/arch/x86/include/asm/gpio.h
+++ b/arch/x86/include/asm/gpio.h
@@ -147,6 +147,7 @@ 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/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt b/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
new file mode 100644
index 0000000..45ab1af
--- /dev/null
+++ b/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
@@ -0,0 +1,31 @@
+Intel x86 PINCTRL/GPIO controller
+
+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.
+
+The PINCTRL master node requires the following properties:
+- compatible : "intel,x86-pinctrl"
+
+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'
+					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.
+- 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.
+
+Example:
+
+pin_usb_host_en0 at 0 {
+    gpio-offset = <0x80 8>;
+    pad-offset = <0x260>;
+    mode-gpio;
+    output-value = <1>;
+    direction = <PIN_OUTPUT>;
+};
diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
index 7e679a0..35e8197 100644
--- a/drivers/gpio/intel_ich6_gpio.c
+++ b/drivers/gpio/intel_ich6_gpio.c
@@ -44,21 +44,28 @@ struct ich6_bank_priv {
 	uint16_t 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)
+#define IOPAD_PULL_STRENGTH_SHIFT	9
+#define IOPAD_PULL_STRENGTH_MASK	(0x3 << IOPAD_PULL_STRENGTH_SHIFT)
+
 /* TODO: Move this to device tree, or platform data */
 void ich_gpio_set_gpio_map(const struct pch_gpio_map *map)
 {
 	gd->arch.gpio_map = map;
 }
 
-static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
+static int gpio_ich6_get_base(unsigned long base)
 {
-	struct ich6_bank_platdata *plat = dev_get_platdata(dev);
-	pci_dev_t pci_dev;			/* handle for 0:1f:0 */
+	pci_dev_t pci_dev;	/* handle for 0:1f:0 */
 	u8 tmpbyte;
 	u16 tmpword;
 	u32 tmplong;
-	u16 gpiobase;
-	int offset;
 
 	/* Where should it be? */
 	pci_dev = PCI_BDF(0, 0x1f, 0);
@@ -123,9 +130,9 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
 	 * while on the Ivybridge the bit0 is used to indicate it is an
 	 * I/O space.
 	 */
-	tmplong = x86_pci_read_config32(pci_dev, PCI_CFG_GPIOBASE);
+	tmplong = x86_pci_read_config32(pci_dev, base);
 	if (tmplong == 0x00000000 || tmplong == 0xffffffff) {
-		debug("%s: unexpected GPIOBASE value\n", __func__);
+		debug("%s: unexpected BASE value\n", __func__);
 		return -ENODEV;
 	}
 
@@ -135,7 +142,213 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
 	 * at the offset that we just read. Bit 0 indicates that it's
 	 * an I/O address, not a memory address, so mask that off.
 	 */
-	gpiobase = tmplong & 0xfffe;
+	return tmplong & 0xfffc;
+}
+
+static int _ich6_gpio_set_value(uint16_t base, unsigned offset, int value)
+{
+	u32 val;
+
+	val = inl(base);
+	if (value)
+		val |= (1UL << offset);
+	else
+		val &= ~(1UL << offset);
+	outl(val, base);
+
+	return 0;
+}
+
+static int _ich6_gpio_set_function(uint16_t base, unsigned offset, int func)
+{
+	u32 val;
+
+	if (func) {
+		val = inl(base);
+		val |= (1UL << offset);
+		outl(val, base);
+	} else {
+		val = inl(base);
+		val &= ~(1UL << offset);
+		outl(val, base);
+	}
+
+	return 0;
+}
+
+static int _ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir)
+{
+	u32 val;
+
+	if (!dir) {
+		val = inl(base);
+		val |= (1UL << offset);
+		outl(val, base);
+	} else {
+		val = inl(base);
+		val &= ~(1UL << offset);
+		outl(val, base);
+	}
+
+	return 0;
+}
+
+static int _gpio_ich6_pinctrl_cfg_pin(s32 gpiobase, s32 iobase, int pin_node)
+{
+	u32 gpio_offset[2];
+	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) {
+		/* 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);
+
+		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);
+
+		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);
+	}
+
+	/* if iobase is present, let's configure the pad */
+	if (iobase != -1) {
+		int iobase_addr;
+
+		/*
+		 * The offset for the same pin for the IOBASE and GPIOBASE are
+		 * different, so instead of maintaining a lookup table,
+		 * the device tree should provide directly the correct
+		 * value for both mapping.
+		 */
+		pad_offset =
+		    fdtdec_get_int(gd->fdt_blob, pin_node, "pad-offset", -1);
+		if (pad_offset == -1) {
+			debug("%s: Invalid register io offset %d\n",
+			      __func__, pad_offset);
+			return -EINVAL;
+		}
+
+		/* compute the absolute pad address */
+		iobase_addr = iobase + pad_offset;
+
+		/*
+		 * Do we need to set a specific function mode?
+		 * If someone put also 'mode-gpio', this option will
+		 * be just ignored by the controller
+		 */
+		val = fdtdec_get_int(gd->fdt_blob, pin_node, "mode-func", -1);
+		if (val != -1)
+			clrsetbits_le32(iobase_addr, IOPAD_MODE_MASK, val);
+
+		/* Configure the pull-up/down if needed */
+		val = fdtdec_get_int(gd->fdt_blob, pin_node, "pull-assign", -1);
+		if (val != -1)
+			clrsetbits_le32(iobase_addr,
+					IOPAD_PULL_ASSIGN_MASK,
+					val << IOPAD_PULL_ASSIGN_SHIFT);
+
+		val =
+		    fdtdec_get_int(gd->fdt_blob, pin_node, "pull-strength", -1);
+		if (val != -1)
+			clrsetbits_le32(iobase_addr,
+					IOPAD_PULL_STRENGTH_MASK,
+					val << IOPAD_PULL_STRENGTH_SHIFT);
+
+		debug("%s: pad cfg [0x%x]: %08x\n", __func__, pad_offset,
+		      readl(iobase_addr));
+	}
+
+	return 0;
+}
+
+int gpio_ich6_pinctrl_init(void)
+{
+	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;
+	}
+
+	/* This is not an error to not have a pinctrl node */
+	node =
+	    fdtdec_next_compatible(gd->fdt_blob, 0, COMPAT_INTEL_X86_PINCTRL);
+	if (node <= 0) {
+		debug("%s: no pinctrl node\n", __func__);
+		return 0;
+	}
+
+	/*
+	 * Get the IOBASE, this is not mandatory as this is not
+	 * supported by all the CPU
+	 */
+	iobase_offset = fdtdec_get_int(gd->fdt_blob, node, "io-offset", -1);
+	if (iobase_offset == -1) {
+		debug("%s: io-base offset not present\n", __func__);
+	} else {
+		iobase = gpio_ich6_get_base(iobase_offset);
+		if (iobase < 0) {
+			debug("%s: invalid IOBASE address (%08x)\n", __func__,
+			      iobase);
+			return -EINVAL;
+		}
+	}
+
+	for (pin_node = fdt_first_subnode(gd->fdt_blob, node);
+	     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);
+		if (ret != 0) {
+			debug("%s: invalid configuration for the pin %d\n",
+			      __func__, pin_node);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ich6_bank_platdata *plat = dev_get_platdata(dev);
+	u16 gpiobase;
+	int offset;
+
+	gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
 	offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
 	if (offset == -1) {
 		debug("%s: Invalid register offset %d\n", __func__, offset);
@@ -192,30 +405,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);
-	u32 tmplong;
 
-	tmplong = inl(bank->io_sel);
-	tmplong |= (1UL << offset);
-	outl(bank->io_sel, tmplong);
-	return 0;
+	return _ich6_gpio_set_direction(inl(bank->io_sel), offset, 0);
 }
 
 static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
 				       int value)
 {
 	struct ich6_bank_priv *bank = dev_get_priv(dev);
-	u32 tmplong;
 
-	gpio_set_value(offset, value);
-
-	tmplong = inl(bank->io_sel);
-	tmplong &= ~(1UL << offset);
-	outl(bank->io_sel, tmplong);
-	return 0;
+	return _ich6_gpio_set_direction(inl(bank->io_sel), offset, 1);
 }
 
 static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
-
 {
 	struct ich6_bank_priv *bank = dev_get_priv(dev);
 	u32 tmplong;
@@ -230,15 +432,7 @@ static int ich6_gpio_set_value(struct udevice *dev, unsigned offset,
 			       int value)
 {
 	struct ich6_bank_priv *bank = dev_get_priv(dev);
-	u32 tmplong;
-
-	tmplong = inl(bank->lvl);
-	if (value)
-		tmplong |= (1UL << offset);
-	else
-		tmplong &= ~(1UL << offset);
-	outl(bank->lvl, tmplong);
-	return 0;
+	return _ich6_gpio_set_value(bank->lvl, offset, value);
 }
 
 static int ich6_gpio_get_function(struct udevice *dev, unsigned offset)
diff --git a/include/dt-bindings/gpio/x86-gpio.h b/include/dt-bindings/gpio/x86-gpio.h
new file mode 100644
index 0000000..7f1de30
--- /dev/null
+++ b/include/dt-bindings/gpio/x86-gpio.h
@@ -0,0 +1,31 @@
+/*
+ * This header provides constants for binding intel,x86-pinctrl.
+ */
+
+#ifndef _DT_BINDINGS_GPIO_X86_GPIO_H
+#define _DT_BINDINGS_GPIO_X86_GPIO_H
+
+#include <dt-bindings/gpio/gpio.h>
+
+#define GPIO_MODE_NATIVE	0
+#define GPIO_MODE_GPIO		1
+
+#define GPIO_MODE_FUNC0	0
+#define GPIO_MODE_FUNC1	1
+#define GPIO_MODE_FUNC2	2
+#define GPIO_MODE_FUNC3	3
+#define GPIO_MODE_FUNC4	4
+#define GPIO_MODE_FUNC5	5
+#define GPIO_MODE_FUNC6	6
+
+#define PIN_INPUT	0
+#define PIN_OUTPUT	1
+
+#define PIN_INPUT_NOPULL	0
+#define PIN_INPUT_PULLUP	1
+#define PIN_INPUT_PULLDOWN	2
+
+#define PULL_STR_2K		0
+#define PULL_STR_20K	2
+
+#endif
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 6590470..5146ff1 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -175,6 +175,7 @@ enum fdt_compat_id {
 	COMPAT_AMS_AS3722,		/* AMS AS3722 PMIC */
 	COMPAT_INTEL_ICH_SPI,		/* Intel ICH7/9 SPI controller */
 	COMPAT_INTEL_QRK_MRC,		/* Intel Quark MRC */
+	COMPAT_INTEL_X86_PINCTRL,	/* Intel ICH7/9 pin control */
 	COMPAT_SOCIONEXT_XHCI,		/* Socionext UniPhier xHCI */
 	COMPAT_INTEL_PCH,		/* Intel PCH */
 
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 80b897a..6bdc270 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -74,6 +74,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(AMS_AS3722, "ams,as3722"),
 	COMPAT(INTEL_ICH_SPI, "intel,ich-spi"),
 	COMPAT(INTEL_QRK_MRC, "intel,quark-mrc"),
+	COMPAT(INTEL_X86_PINCTRL, "intel,x86-pinctrl"),
 	COMPAT(SOCIONEXT_XHCI, "socionext,uniphier-xhci"),
 	COMPAT(COMPAT_INTEL_PCH, "intel,bd82x6x"),
 };
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH v3 3/4] x86: gpio: add pinctrl support from the device tree
  2015-04-23 16:16 ` [U-Boot] [PATCH 3/4] x86: gpio: add pinctrl support from " Gabriel Huau
                     ` (3 preceding siblings ...)
  2015-04-25 20:17   ` [U-Boot] [PATCH 3/4 v2] " Gabriel Huau
@ 2015-05-12  6:17   ` Gabriel Huau
  2015-05-26  5:27   ` [U-Boot] [PATCH v4 " Gabriel Huau
  5 siblings, 0 replies; 61+ messages in thread
From: Gabriel Huau @ 2015-05-12  6:17 UTC (permalink / raw)
  To: u-boot

Every pin can be configured now from the device tree. A dt-bindings
has been added to describe the different property available.

Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>

---

Changes in v3:
    - Fix the dt-binding copyright header
    - Remove define for IOBASE and use a property
    - Fix issues with signed/unsigned variable type
    - Fix coding style
    - Add a compatible string for the driver

Changes in v2:
    - Clean commit message
    - Rename compatible string 'ich6' to 'x86'
    - Fix coding style
    - Create a dt-bindinds documentation
    - Move x86-gpio defines to a specific header
    - Reorder the functions to avoid the need for forward declarations
    - Rename double underscore functions to only one
    - Create a specific function to configure one pin
    - Use a define to prevent build/support issues with other x86 CPU that
    doesn't have a IOBASE.

 arch/x86/dts/minnowmax.dts                         |  23 ++
 arch/x86/include/asm/gpio.h                        |   1 +
 .../gpio/intel,x86-pinctrl.txt                     |  31 +++
 drivers/gpio/intel_ich6_gpio.c                     | 254 ++++++++++++++++++---
 include/dt-bindings/gpio/x86-gpio.h                |  31 +++
 include/fdtdec.h                                   |   1 +
 lib/fdtdec.c                                       |   1 +
 7 files changed, 312 insertions(+), 30 deletions(-)
 create mode 100644 doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
 create mode 100644 include/dt-bindings/gpio/x86-gpio.h

diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
index 7103bc5..bd21bfb 100644
--- a/arch/x86/dts/minnowmax.dts
+++ b/arch/x86/dts/minnowmax.dts
@@ -6,6 +6,8 @@
 
 /dts-v1/;
 
+#include <dt-bindings/gpio/x86-gpio.h>
+
 /include/ "skeleton.dtsi"
 /include/ "serial.dtsi"
 
@@ -22,6 +24,27 @@
 		silent_console = <0>;
 	};
 
+	pch_pinctrl {
+		compatible = "intel,x86-pinctrl";
+		io-base = <0x4c>;
+
+		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 = <0x258>;
+			mode-gpio;
+			output-value = <1>;
+			direction = <PIN_OUTPUT>;
+		};
+	};
+
 	gpioa {
 		compatible = "intel,ich6-gpio";
 		u-boot,dm-pre-reloc;
diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h
index 1099427..ed85b08 100644
--- a/arch/x86/include/asm/gpio.h
+++ b/arch/x86/include/asm/gpio.h
@@ -147,6 +147,7 @@ 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/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt b/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
new file mode 100644
index 0000000..45ab1af
--- /dev/null
+++ b/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
@@ -0,0 +1,31 @@
+Intel x86 PINCTRL/GPIO controller
+
+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.
+
+The PINCTRL master node requires the following properties:
+- compatible : "intel,x86-pinctrl"
+
+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'
+					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.
+- 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.
+
+Example:
+
+pin_usb_host_en0 at 0 {
+    gpio-offset = <0x80 8>;
+    pad-offset = <0x260>;
+    mode-gpio;
+    output-value = <1>;
+    direction = <PIN_OUTPUT>;
+};
diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
index 7e679a0..35e8197 100644
--- a/drivers/gpio/intel_ich6_gpio.c
+++ b/drivers/gpio/intel_ich6_gpio.c
@@ -44,21 +44,28 @@ struct ich6_bank_priv {
 	uint16_t 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)
+#define IOPAD_PULL_STRENGTH_SHIFT	9
+#define IOPAD_PULL_STRENGTH_MASK	(0x3 << IOPAD_PULL_STRENGTH_SHIFT)
+
 /* TODO: Move this to device tree, or platform data */
 void ich_gpio_set_gpio_map(const struct pch_gpio_map *map)
 {
 	gd->arch.gpio_map = map;
 }
 
-static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
+static int gpio_ich6_get_base(unsigned long base)
 {
-	struct ich6_bank_platdata *plat = dev_get_platdata(dev);
-	pci_dev_t pci_dev;			/* handle for 0:1f:0 */
+	pci_dev_t pci_dev;	/* handle for 0:1f:0 */
 	u8 tmpbyte;
 	u16 tmpword;
 	u32 tmplong;
-	u16 gpiobase;
-	int offset;
 
 	/* Where should it be? */
 	pci_dev = PCI_BDF(0, 0x1f, 0);
@@ -123,9 +130,9 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
 	 * while on the Ivybridge the bit0 is used to indicate it is an
 	 * I/O space.
 	 */
-	tmplong = x86_pci_read_config32(pci_dev, PCI_CFG_GPIOBASE);
+	tmplong = x86_pci_read_config32(pci_dev, base);
 	if (tmplong == 0x00000000 || tmplong == 0xffffffff) {
-		debug("%s: unexpected GPIOBASE value\n", __func__);
+		debug("%s: unexpected BASE value\n", __func__);
 		return -ENODEV;
 	}
 
@@ -135,7 +142,213 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
 	 * at the offset that we just read. Bit 0 indicates that it's
 	 * an I/O address, not a memory address, so mask that off.
 	 */
-	gpiobase = tmplong & 0xfffe;
+	return tmplong & 0xfffc;
+}
+
+static int _ich6_gpio_set_value(uint16_t base, unsigned offset, int value)
+{
+	u32 val;
+
+	val = inl(base);
+	if (value)
+		val |= (1UL << offset);
+	else
+		val &= ~(1UL << offset);
+	outl(val, base);
+
+	return 0;
+}
+
+static int _ich6_gpio_set_function(uint16_t base, unsigned offset, int func)
+{
+	u32 val;
+
+	if (func) {
+		val = inl(base);
+		val |= (1UL << offset);
+		outl(val, base);
+	} else {
+		val = inl(base);
+		val &= ~(1UL << offset);
+		outl(val, base);
+	}
+
+	return 0;
+}
+
+static int _ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir)
+{
+	u32 val;
+
+	if (!dir) {
+		val = inl(base);
+		val |= (1UL << offset);
+		outl(val, base);
+	} else {
+		val = inl(base);
+		val &= ~(1UL << offset);
+		outl(val, base);
+	}
+
+	return 0;
+}
+
+static int _gpio_ich6_pinctrl_cfg_pin(s32 gpiobase, s32 iobase, int pin_node)
+{
+	u32 gpio_offset[2];
+	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) {
+		/* 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);
+
+		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);
+
+		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);
+	}
+
+	/* if iobase is present, let's configure the pad */
+	if (iobase != -1) {
+		int iobase_addr;
+
+		/*
+		 * The offset for the same pin for the IOBASE and GPIOBASE are
+		 * different, so instead of maintaining a lookup table,
+		 * the device tree should provide directly the correct
+		 * value for both mapping.
+		 */
+		pad_offset =
+		    fdtdec_get_int(gd->fdt_blob, pin_node, "pad-offset", -1);
+		if (pad_offset == -1) {
+			debug("%s: Invalid register io offset %d\n",
+			      __func__, pad_offset);
+			return -EINVAL;
+		}
+
+		/* compute the absolute pad address */
+		iobase_addr = iobase + pad_offset;
+
+		/*
+		 * Do we need to set a specific function mode?
+		 * If someone put also 'mode-gpio', this option will
+		 * be just ignored by the controller
+		 */
+		val = fdtdec_get_int(gd->fdt_blob, pin_node, "mode-func", -1);
+		if (val != -1)
+			clrsetbits_le32(iobase_addr, IOPAD_MODE_MASK, val);
+
+		/* Configure the pull-up/down if needed */
+		val = fdtdec_get_int(gd->fdt_blob, pin_node, "pull-assign", -1);
+		if (val != -1)
+			clrsetbits_le32(iobase_addr,
+					IOPAD_PULL_ASSIGN_MASK,
+					val << IOPAD_PULL_ASSIGN_SHIFT);
+
+		val =
+		    fdtdec_get_int(gd->fdt_blob, pin_node, "pull-strength", -1);
+		if (val != -1)
+			clrsetbits_le32(iobase_addr,
+					IOPAD_PULL_STRENGTH_MASK,
+					val << IOPAD_PULL_STRENGTH_SHIFT);
+
+		debug("%s: pad cfg [0x%x]: %08x\n", __func__, pad_offset,
+		      readl(iobase_addr));
+	}
+
+	return 0;
+}
+
+int gpio_ich6_pinctrl_init(void)
+{
+	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;
+	}
+
+	/* This is not an error to not have a pinctrl node */
+	node =
+	    fdtdec_next_compatible(gd->fdt_blob, 0, COMPAT_INTEL_X86_PINCTRL);
+	if (node <= 0) {
+		debug("%s: no pinctrl node\n", __func__);
+		return 0;
+	}
+
+	/*
+	 * Get the IOBASE, this is not mandatory as this is not
+	 * supported by all the CPU
+	 */
+	iobase_offset = fdtdec_get_int(gd->fdt_blob, node, "io-offset", -1);
+	if (iobase_offset == -1) {
+		debug("%s: io-base offset not present\n", __func__);
+	} else {
+		iobase = gpio_ich6_get_base(iobase_offset);
+		if (iobase < 0) {
+			debug("%s: invalid IOBASE address (%08x)\n", __func__,
+			      iobase);
+			return -EINVAL;
+		}
+	}
+
+	for (pin_node = fdt_first_subnode(gd->fdt_blob, node);
+	     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);
+		if (ret != 0) {
+			debug("%s: invalid configuration for the pin %d\n",
+			      __func__, pin_node);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ich6_bank_platdata *plat = dev_get_platdata(dev);
+	u16 gpiobase;
+	int offset;
+
+	gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
 	offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
 	if (offset == -1) {
 		debug("%s: Invalid register offset %d\n", __func__, offset);
@@ -192,30 +405,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);
-	u32 tmplong;
 
-	tmplong = inl(bank->io_sel);
-	tmplong |= (1UL << offset);
-	outl(bank->io_sel, tmplong);
-	return 0;
+	return _ich6_gpio_set_direction(inl(bank->io_sel), offset, 0);
 }
 
 static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
 				       int value)
 {
 	struct ich6_bank_priv *bank = dev_get_priv(dev);
-	u32 tmplong;
 
-	gpio_set_value(offset, value);
-
-	tmplong = inl(bank->io_sel);
-	tmplong &= ~(1UL << offset);
-	outl(bank->io_sel, tmplong);
-	return 0;
+	return _ich6_gpio_set_direction(inl(bank->io_sel), offset, 1);
 }
 
 static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
-
 {
 	struct ich6_bank_priv *bank = dev_get_priv(dev);
 	u32 tmplong;
@@ -230,15 +432,7 @@ static int ich6_gpio_set_value(struct udevice *dev, unsigned offset,
 			       int value)
 {
 	struct ich6_bank_priv *bank = dev_get_priv(dev);
-	u32 tmplong;
-
-	tmplong = inl(bank->lvl);
-	if (value)
-		tmplong |= (1UL << offset);
-	else
-		tmplong &= ~(1UL << offset);
-	outl(bank->lvl, tmplong);
-	return 0;
+	return _ich6_gpio_set_value(bank->lvl, offset, value);
 }
 
 static int ich6_gpio_get_function(struct udevice *dev, unsigned offset)
diff --git a/include/dt-bindings/gpio/x86-gpio.h b/include/dt-bindings/gpio/x86-gpio.h
new file mode 100644
index 0000000..7f1de30
--- /dev/null
+++ b/include/dt-bindings/gpio/x86-gpio.h
@@ -0,0 +1,31 @@
+/*
+ * This header provides constants for binding intel,x86-pinctrl.
+ */
+
+#ifndef _DT_BINDINGS_GPIO_X86_GPIO_H
+#define _DT_BINDINGS_GPIO_X86_GPIO_H
+
+#include <dt-bindings/gpio/gpio.h>
+
+#define GPIO_MODE_NATIVE	0
+#define GPIO_MODE_GPIO		1
+
+#define GPIO_MODE_FUNC0	0
+#define GPIO_MODE_FUNC1	1
+#define GPIO_MODE_FUNC2	2
+#define GPIO_MODE_FUNC3	3
+#define GPIO_MODE_FUNC4	4
+#define GPIO_MODE_FUNC5	5
+#define GPIO_MODE_FUNC6	6
+
+#define PIN_INPUT	0
+#define PIN_OUTPUT	1
+
+#define PIN_INPUT_NOPULL	0
+#define PIN_INPUT_PULLUP	1
+#define PIN_INPUT_PULLDOWN	2
+
+#define PULL_STR_2K		0
+#define PULL_STR_20K	2
+
+#endif
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 6590470..5146ff1 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -175,6 +175,7 @@ enum fdt_compat_id {
 	COMPAT_AMS_AS3722,		/* AMS AS3722 PMIC */
 	COMPAT_INTEL_ICH_SPI,		/* Intel ICH7/9 SPI controller */
 	COMPAT_INTEL_QRK_MRC,		/* Intel Quark MRC */
+	COMPAT_INTEL_X86_PINCTRL,	/* Intel ICH7/9 pin control */
 	COMPAT_SOCIONEXT_XHCI,		/* Socionext UniPhier xHCI */
 	COMPAT_INTEL_PCH,		/* Intel PCH */
 
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 80b897a..6bdc270 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -74,6 +74,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(AMS_AS3722, "ams,as3722"),
 	COMPAT(INTEL_ICH_SPI, "intel,ich-spi"),
 	COMPAT(INTEL_QRK_MRC, "intel,quark-mrc"),
+	COMPAT(INTEL_X86_PINCTRL, "intel,x86-pinctrl"),
 	COMPAT(SOCIONEXT_XHCI, "socionext,uniphier-xhci"),
 	COMPAT(COMPAT_INTEL_PCH, "intel,bd82x6x"),
 };
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH v3 4/4] x86: minnowmax: initialize the pin-muxing from device tree
  2015-04-23 16:16 ` [U-Boot] [PATCH 4/4] x86: minnowmax: initialize the pin-muxing from " Gabriel Huau
                     ` (2 preceding siblings ...)
  2015-04-25 20:18   ` [U-Boot] [PATCH 4/4 v2] " Gabriel Huau
@ 2015-05-12  6:18   ` Gabriel Huau
  2015-06-04 15:17     ` Simon Glass
  3 siblings, 1 reply; 61+ messages in thread
From: Gabriel Huau @ 2015-05-12  6:18 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
Acked-by: Simon Glass <sjg@chromium.org>

---

Changes in v3:
    - Rebase to the origin/master

Changes in v2:
    - Fix ordering of include header

 board/intel/minnowmax/minnowmax.c | 9 +++++++++
 include/configs/minnowmax.h       | 1 +
 2 files changed, 10 insertions(+)

diff --git a/board/intel/minnowmax/minnowmax.c b/board/intel/minnowmax/minnowmax.c
index 1f5549a..383cae0 100644
--- a/board/intel/minnowmax/minnowmax.c
+++ b/board/intel/minnowmax/minnowmax.c
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <asm/gpio.h>
 #include <asm/ibmpc.h>
 #include <asm/pnp_def.h>
 #include <netdev.h>
@@ -12,6 +13,14 @@
 
 #define SERIAL_DEV PNP_DEV(0x2e, 4)
 
+int arch_early_init_r(void)
+{
+	/* do the pin-muxing */
+	gpio_ich6_pinctrl_init();
+
+	return 0;
+}
+
 int board_early_init_f(void)
 {
 	lpc47m_enable_serial(SERIAL_DEV, UART0_BASE, UART0_IRQ);
diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h
index eb35a50..547765d 100644
--- a/include/configs/minnowmax.h
+++ b/include/configs/minnowmax.h
@@ -15,6 +15,7 @@
 
 #define CONFIG_SYS_MONITOR_LEN		(1 << 20)
 #define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_ARCH_EARLY_INIT_R
 
 #define CONFIG_X86_SERIAL
 #define CONFIG_SMSC_LPC47M
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH v3 3/4] x86: gpio: add pinctrl support from the device tree
  2015-05-12  6:10 ` [U-Boot] [PATCH v3 3/4] x86: gpio: add pinctrl support from the " Gabriel Huau
@ 2015-05-12  6:20   ` gabriel huau
  0 siblings, 0 replies; 61+ messages in thread
From: gabriel huau @ 2015-05-12  6:20 UTC (permalink / raw)
  To: u-boot

Please ignore this email/patch, I put the wrong message id ...

On 05/11/2015 11:10 PM, Gabriel Huau wrote:
> Every pin can be configured now from the device tree. A dt-bindings
> has been added to describe the different property available.
>
> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
>
> ---
>
> Changes in v3:
>      - Fix the dt-binding copyright header
>      - Remove define for IOBASE and use a property
>      - Fix issues with signed/unsigned variable type
>      - Fix coding style
>      - Add a compatible string for the driver
>
> Changes in v2:
>      - Clean commit message
>      - Rename compatible string 'ich6' to 'x86'
>      - Fix coding style
>      - Create a dt-bindinds documentation
>      - Move x86-gpio defines to a specific header
>      - Reorder the functions to avoid the need for forward declarations
>      - Rename double underscore functions to only one
>      - Create a specific function to configure one pin
>      - Use a define to prevent build/support issues with other x86 CPU that
>      doesn't have a IOBASE.
>
>   arch/x86/dts/minnowmax.dts                         |  23 ++
>   arch/x86/include/asm/gpio.h                        |   1 +
>   .../gpio/intel,x86-pinctrl.txt                     |  31 +++
>   drivers/gpio/intel_ich6_gpio.c                     | 254 ++++++++++++++++++---
>   include/dt-bindings/gpio/x86-gpio.h                |  31 +++
>   include/fdtdec.h                                   |   1 +
>   lib/fdtdec.c                                       |   1 +
>   7 files changed, 312 insertions(+), 30 deletions(-)
>   create mode 100644 doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
>   create mode 100644 include/dt-bindings/gpio/x86-gpio.h
>
> diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
> index 7103bc5..bd21bfb 100644
> --- a/arch/x86/dts/minnowmax.dts
> +++ b/arch/x86/dts/minnowmax.dts
> @@ -6,6 +6,8 @@
>   
>   /dts-v1/;
>   
> +#include <dt-bindings/gpio/x86-gpio.h>
> +
>   /include/ "skeleton.dtsi"
>   /include/ "serial.dtsi"
>   
> @@ -22,6 +24,27 @@
>   		silent_console = <0>;
>   	};
>   
> +	pch_pinctrl {
> +		compatible = "intel,x86-pinctrl";
> +		io-base = <0x4c>;
> +
> +		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 = <0x258>;
> +			mode-gpio;
> +			output-value = <1>;
> +			direction = <PIN_OUTPUT>;
> +		};
> +	};
> +
>   	gpioa {
>   		compatible = "intel,ich6-gpio";
>   		u-boot,dm-pre-reloc;
> diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h
> index 1099427..ed85b08 100644
> --- a/arch/x86/include/asm/gpio.h
> +++ b/arch/x86/include/asm/gpio.h
> @@ -147,6 +147,7 @@ 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/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt b/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
> new file mode 100644
> index 0000000..45ab1af
> --- /dev/null
> +++ b/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
> @@ -0,0 +1,31 @@
> +Intel x86 PINCTRL/GPIO controller
> +
> +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.
> +
> +The PINCTRL master node requires the following properties:
> +- compatible : "intel,x86-pinctrl"
> +
> +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'
> +					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.
> +- 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.
> +
> +Example:
> +
> +pin_usb_host_en0 at 0 {
> +    gpio-offset = <0x80 8>;
> +    pad-offset = <0x260>;
> +    mode-gpio;
> +    output-value = <1>;
> +    direction = <PIN_OUTPUT>;
> +};
> diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
> index 7e679a0..35e8197 100644
> --- a/drivers/gpio/intel_ich6_gpio.c
> +++ b/drivers/gpio/intel_ich6_gpio.c
> @@ -44,21 +44,28 @@ struct ich6_bank_priv {
>   	uint16_t 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)
> +#define IOPAD_PULL_STRENGTH_SHIFT	9
> +#define IOPAD_PULL_STRENGTH_MASK	(0x3 << IOPAD_PULL_STRENGTH_SHIFT)
> +
>   /* TODO: Move this to device tree, or platform data */
>   void ich_gpio_set_gpio_map(const struct pch_gpio_map *map)
>   {
>   	gd->arch.gpio_map = map;
>   }
>   
> -static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
> +static int gpio_ich6_get_base(unsigned long base)
>   {
> -	struct ich6_bank_platdata *plat = dev_get_platdata(dev);
> -	pci_dev_t pci_dev;			/* handle for 0:1f:0 */
> +	pci_dev_t pci_dev;	/* handle for 0:1f:0 */
>   	u8 tmpbyte;
>   	u16 tmpword;
>   	u32 tmplong;
> -	u16 gpiobase;
> -	int offset;
>   
>   	/* Where should it be? */
>   	pci_dev = PCI_BDF(0, 0x1f, 0);
> @@ -123,9 +130,9 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>   	 * while on the Ivybridge the bit0 is used to indicate it is an
>   	 * I/O space.
>   	 */
> -	tmplong = x86_pci_read_config32(pci_dev, PCI_CFG_GPIOBASE);
> +	tmplong = x86_pci_read_config32(pci_dev, base);
>   	if (tmplong == 0x00000000 || tmplong == 0xffffffff) {
> -		debug("%s: unexpected GPIOBASE value\n", __func__);
> +		debug("%s: unexpected BASE value\n", __func__);
>   		return -ENODEV;
>   	}
>   
> @@ -135,7 +142,213 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>   	 * at the offset that we just read. Bit 0 indicates that it's
>   	 * an I/O address, not a memory address, so mask that off.
>   	 */
> -	gpiobase = tmplong & 0xfffe;
> +	return tmplong & 0xfffc;
> +}
> +
> +static int _ich6_gpio_set_value(uint16_t base, unsigned offset, int value)
> +{
> +	u32 val;
> +
> +	val = inl(base);
> +	if (value)
> +		val |= (1UL << offset);
> +	else
> +		val &= ~(1UL << offset);
> +	outl(val, base);
> +
> +	return 0;
> +}
> +
> +static int _ich6_gpio_set_function(uint16_t base, unsigned offset, int func)
> +{
> +	u32 val;
> +
> +	if (func) {
> +		val = inl(base);
> +		val |= (1UL << offset);
> +		outl(val, base);
> +	} else {
> +		val = inl(base);
> +		val &= ~(1UL << offset);
> +		outl(val, base);
> +	}
> +
> +	return 0;
> +}
> +
> +static int _ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir)
> +{
> +	u32 val;
> +
> +	if (!dir) {
> +		val = inl(base);
> +		val |= (1UL << offset);
> +		outl(val, base);
> +	} else {
> +		val = inl(base);
> +		val &= ~(1UL << offset);
> +		outl(val, base);
> +	}
> +
> +	return 0;
> +}
> +
> +static int _gpio_ich6_pinctrl_cfg_pin(s32 gpiobase, s32 iobase, int pin_node)
> +{
> +	u32 gpio_offset[2];
> +	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) {
> +		/* 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);
> +
> +		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);
> +
> +		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);
> +	}
> +
> +	/* if iobase is present, let's configure the pad */
> +	if (iobase != -1) {
> +		int iobase_addr;
> +
> +		/*
> +		 * The offset for the same pin for the IOBASE and GPIOBASE are
> +		 * different, so instead of maintaining a lookup table,
> +		 * the device tree should provide directly the correct
> +		 * value for both mapping.
> +		 */
> +		pad_offset =
> +		    fdtdec_get_int(gd->fdt_blob, pin_node, "pad-offset", -1);
> +		if (pad_offset == -1) {
> +			debug("%s: Invalid register io offset %d\n",
> +			      __func__, pad_offset);
> +			return -EINVAL;
> +		}
> +
> +		/* compute the absolute pad address */
> +		iobase_addr = iobase + pad_offset;
> +
> +		/*
> +		 * Do we need to set a specific function mode?
> +		 * If someone put also 'mode-gpio', this option will
> +		 * be just ignored by the controller
> +		 */
> +		val = fdtdec_get_int(gd->fdt_blob, pin_node, "mode-func", -1);
> +		if (val != -1)
> +			clrsetbits_le32(iobase_addr, IOPAD_MODE_MASK, val);
> +
> +		/* Configure the pull-up/down if needed */
> +		val = fdtdec_get_int(gd->fdt_blob, pin_node, "pull-assign", -1);
> +		if (val != -1)
> +			clrsetbits_le32(iobase_addr,
> +					IOPAD_PULL_ASSIGN_MASK,
> +					val << IOPAD_PULL_ASSIGN_SHIFT);
> +
> +		val =
> +		    fdtdec_get_int(gd->fdt_blob, pin_node, "pull-strength", -1);
> +		if (val != -1)
> +			clrsetbits_le32(iobase_addr,
> +					IOPAD_PULL_STRENGTH_MASK,
> +					val << IOPAD_PULL_STRENGTH_SHIFT);
> +
> +		debug("%s: pad cfg [0x%x]: %08x\n", __func__, pad_offset,
> +		      readl(iobase_addr));
> +	}
> +
> +	return 0;
> +}
> +
> +int gpio_ich6_pinctrl_init(void)
> +{
> +	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;
> +	}
> +
> +	/* This is not an error to not have a pinctrl node */
> +	node =
> +	    fdtdec_next_compatible(gd->fdt_blob, 0, COMPAT_INTEL_X86_PINCTRL);
> +	if (node <= 0) {
> +		debug("%s: no pinctrl node\n", __func__);
> +		return 0;
> +	}
> +
> +	/*
> +	 * Get the IOBASE, this is not mandatory as this is not
> +	 * supported by all the CPU
> +	 */
> +	iobase_offset = fdtdec_get_int(gd->fdt_blob, node, "io-offset", -1);
> +	if (iobase_offset == -1) {
> +		debug("%s: io-base offset not present\n", __func__);
> +	} else {
> +		iobase = gpio_ich6_get_base(iobase_offset);
> +		if (iobase < 0) {
> +			debug("%s: invalid IOBASE address (%08x)\n", __func__,
> +			      iobase);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	for (pin_node = fdt_first_subnode(gd->fdt_blob, node);
> +	     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);
> +		if (ret != 0) {
> +			debug("%s: invalid configuration for the pin %d\n",
> +			      __func__, pin_node);
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
> +{
> +	struct ich6_bank_platdata *plat = dev_get_platdata(dev);
> +	u16 gpiobase;
> +	int offset;
> +
> +	gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
>   	offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
>   	if (offset == -1) {
>   		debug("%s: Invalid register offset %d\n", __func__, offset);
> @@ -192,30 +405,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);
> -	u32 tmplong;
>   
> -	tmplong = inl(bank->io_sel);
> -	tmplong |= (1UL << offset);
> -	outl(bank->io_sel, tmplong);
> -	return 0;
> +	return _ich6_gpio_set_direction(inl(bank->io_sel), offset, 0);
>   }
>   
>   static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
>   				       int value)
>   {
>   	struct ich6_bank_priv *bank = dev_get_priv(dev);
> -	u32 tmplong;
>   
> -	gpio_set_value(offset, value);
> -
> -	tmplong = inl(bank->io_sel);
> -	tmplong &= ~(1UL << offset);
> -	outl(bank->io_sel, tmplong);
> -	return 0;
> +	return _ich6_gpio_set_direction(inl(bank->io_sel), offset, 1);
>   }
>   
>   static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
> -
>   {
>   	struct ich6_bank_priv *bank = dev_get_priv(dev);
>   	u32 tmplong;
> @@ -230,15 +432,7 @@ static int ich6_gpio_set_value(struct udevice *dev, unsigned offset,
>   			       int value)
>   {
>   	struct ich6_bank_priv *bank = dev_get_priv(dev);
> -	u32 tmplong;
> -
> -	tmplong = inl(bank->lvl);
> -	if (value)
> -		tmplong |= (1UL << offset);
> -	else
> -		tmplong &= ~(1UL << offset);
> -	outl(bank->lvl, tmplong);
> -	return 0;
> +	return _ich6_gpio_set_value(bank->lvl, offset, value);
>   }
>   
>   static int ich6_gpio_get_function(struct udevice *dev, unsigned offset)
> diff --git a/include/dt-bindings/gpio/x86-gpio.h b/include/dt-bindings/gpio/x86-gpio.h
> new file mode 100644
> index 0000000..7f1de30
> --- /dev/null
> +++ b/include/dt-bindings/gpio/x86-gpio.h
> @@ -0,0 +1,31 @@
> +/*
> + * This header provides constants for binding intel,x86-pinctrl.
> + */
> +
> +#ifndef _DT_BINDINGS_GPIO_X86_GPIO_H
> +#define _DT_BINDINGS_GPIO_X86_GPIO_H
> +
> +#include <dt-bindings/gpio/gpio.h>
> +
> +#define GPIO_MODE_NATIVE	0
> +#define GPIO_MODE_GPIO		1
> +
> +#define GPIO_MODE_FUNC0	0
> +#define GPIO_MODE_FUNC1	1
> +#define GPIO_MODE_FUNC2	2
> +#define GPIO_MODE_FUNC3	3
> +#define GPIO_MODE_FUNC4	4
> +#define GPIO_MODE_FUNC5	5
> +#define GPIO_MODE_FUNC6	6
> +
> +#define PIN_INPUT	0
> +#define PIN_OUTPUT	1
> +
> +#define PIN_INPUT_NOPULL	0
> +#define PIN_INPUT_PULLUP	1
> +#define PIN_INPUT_PULLDOWN	2
> +
> +#define PULL_STR_2K		0
> +#define PULL_STR_20K	2
> +
> +#endif
> diff --git a/include/fdtdec.h b/include/fdtdec.h
> index 6590470..5146ff1 100644
> --- a/include/fdtdec.h
> +++ b/include/fdtdec.h
> @@ -175,6 +175,7 @@ enum fdt_compat_id {
>   	COMPAT_AMS_AS3722,		/* AMS AS3722 PMIC */
>   	COMPAT_INTEL_ICH_SPI,		/* Intel ICH7/9 SPI controller */
>   	COMPAT_INTEL_QRK_MRC,		/* Intel Quark MRC */
> +	COMPAT_INTEL_X86_PINCTRL,	/* Intel ICH7/9 pin control */
>   	COMPAT_SOCIONEXT_XHCI,		/* Socionext UniPhier xHCI */
>   	COMPAT_INTEL_PCH,		/* Intel PCH */
>   
> diff --git a/lib/fdtdec.c b/lib/fdtdec.c
> index 80b897a..6bdc270 100644
> --- a/lib/fdtdec.c
> +++ b/lib/fdtdec.c
> @@ -74,6 +74,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
>   	COMPAT(AMS_AS3722, "ams,as3722"),
>   	COMPAT(INTEL_ICH_SPI, "intel,ich-spi"),
>   	COMPAT(INTEL_QRK_MRC, "intel,quark-mrc"),
> +	COMPAT(INTEL_X86_PINCTRL, "intel,x86-pinctrl"),
>   	COMPAT(SOCIONEXT_XHCI, "socionext,uniphier-xhci"),
>   	COMPAT(COMPAT_INTEL_PCH, "intel,bd82x6x"),
>   };

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH v3 4/4] x86: minnowmax: initialize the pin-muxing from device tree
  2015-05-12  6:12 ` [U-Boot] [PATCH v3 4/4] x86: minnowmax: initialize the pin-muxing from " Gabriel Huau
@ 2015-05-12  6:20   ` gabriel huau
  2015-05-20 14:21     ` Simon Glass
  0 siblings, 1 reply; 61+ messages in thread
From: gabriel huau @ 2015-05-12  6:20 UTC (permalink / raw)
  To: u-boot

Please ignore this email/patch, I put the wrong message id ...

On 05/11/2015 11:12 PM, Gabriel Huau wrote:
> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
> Acked-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v3:
>      - Rebase to the origin/master
>
> Changes in v2:
>      - Fix ordering of include header
>
>   board/intel/minnowmax/minnowmax.c | 9 +++++++++
>   include/configs/minnowmax.h       | 1 +
>   2 files changed, 10 insertions(+)
>
> diff --git a/board/intel/minnowmax/minnowmax.c b/board/intel/minnowmax/minnowmax.c
> index 1f5549a..383cae0 100644
> --- a/board/intel/minnowmax/minnowmax.c
> +++ b/board/intel/minnowmax/minnowmax.c
> @@ -5,6 +5,7 @@
>    */
>   
>   #include <common.h>
> +#include <asm/gpio.h>
>   #include <asm/ibmpc.h>
>   #include <asm/pnp_def.h>
>   #include <netdev.h>
> @@ -12,6 +13,14 @@
>   
>   #define SERIAL_DEV PNP_DEV(0x2e, 4)
>   
> +int arch_early_init_r(void)
> +{
> +	/* do the pin-muxing */
> +	gpio_ich6_pinctrl_init();
> +
> +	return 0;
> +}
> +
>   int board_early_init_f(void)
>   {
>   	lpc47m_enable_serial(SERIAL_DEV, UART0_BASE, UART0_IRQ);
> diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h
> index eb35a50..547765d 100644
> --- a/include/configs/minnowmax.h
> +++ b/include/configs/minnowmax.h
> @@ -15,6 +15,7 @@
>   
>   #define CONFIG_SYS_MONITOR_LEN		(1 << 20)
>   #define CONFIG_BOARD_EARLY_INIT_F
> +#define CONFIG_ARCH_EARLY_INIT_R
>   
>   #define CONFIG_X86_SERIAL
>   #define CONFIG_SMSC_LPC47M

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH v3 3/4] x86: gpio: add pinctrl support from the device tree
  2015-05-12  6:15 ` [U-Boot] [PATCH v3 3/4] x86: gpio: add pinctrl support from the " Gabriel Huau
@ 2015-05-12  6:21   ` gabriel huau
  0 siblings, 0 replies; 61+ messages in thread
From: gabriel huau @ 2015-05-12  6:21 UTC (permalink / raw)
  To: u-boot

Please ignore this email/patch, I put the wrong message id ...

On 05/11/2015 11:15 PM, Gabriel Huau wrote:
> Every pin can be configured now from the device tree. A dt-bindings
> has been added to describe the different property available.
>
> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
>
> ---
>
> Changes in v3:
>      - Fix the dt-binding copyright header
>      - Remove define for IOBASE and use a property
>      - Fix issues with signed/unsigned variable type
>      - Fix coding style
>      - Add a compatible string for the driver
>
> Changes in v2:
>      - Clean commit message
>      - Rename compatible string 'ich6' to 'x86'
>      - Fix coding style
>      - Create a dt-bindinds documentation
>      - Move x86-gpio defines to a specific header
>      - Reorder the functions to avoid the need for forward declarations
>      - Rename double underscore functions to only one
>      - Create a specific function to configure one pin
>      - Use a define to prevent build/support issues with other x86 CPU that
>      doesn't have a IOBASE.
>
>   arch/x86/dts/minnowmax.dts                         |  23 ++
>   arch/x86/include/asm/gpio.h                        |   1 +
>   .../gpio/intel,x86-pinctrl.txt                     |  31 +++
>   drivers/gpio/intel_ich6_gpio.c                     | 254 ++++++++++++++++++---
>   include/dt-bindings/gpio/x86-gpio.h                |  31 +++
>   include/fdtdec.h                                   |   1 +
>   lib/fdtdec.c                                       |   1 +
>   7 files changed, 312 insertions(+), 30 deletions(-)
>   create mode 100644 doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
>   create mode 100644 include/dt-bindings/gpio/x86-gpio.h
>
> diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
> index 7103bc5..bd21bfb 100644
> --- a/arch/x86/dts/minnowmax.dts
> +++ b/arch/x86/dts/minnowmax.dts
> @@ -6,6 +6,8 @@
>   
>   /dts-v1/;
>   
> +#include <dt-bindings/gpio/x86-gpio.h>
> +
>   /include/ "skeleton.dtsi"
>   /include/ "serial.dtsi"
>   
> @@ -22,6 +24,27 @@
>   		silent_console = <0>;
>   	};
>   
> +	pch_pinctrl {
> +		compatible = "intel,x86-pinctrl";
> +		io-base = <0x4c>;
> +
> +		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 = <0x258>;
> +			mode-gpio;
> +			output-value = <1>;
> +			direction = <PIN_OUTPUT>;
> +		};
> +	};
> +
>   	gpioa {
>   		compatible = "intel,ich6-gpio";
>   		u-boot,dm-pre-reloc;
> diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h
> index 1099427..ed85b08 100644
> --- a/arch/x86/include/asm/gpio.h
> +++ b/arch/x86/include/asm/gpio.h
> @@ -147,6 +147,7 @@ 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/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt b/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
> new file mode 100644
> index 0000000..45ab1af
> --- /dev/null
> +++ b/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
> @@ -0,0 +1,31 @@
> +Intel x86 PINCTRL/GPIO controller
> +
> +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.
> +
> +The PINCTRL master node requires the following properties:
> +- compatible : "intel,x86-pinctrl"
> +
> +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'
> +					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.
> +- 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.
> +
> +Example:
> +
> +pin_usb_host_en0 at 0 {
> +    gpio-offset = <0x80 8>;
> +    pad-offset = <0x260>;
> +    mode-gpio;
> +    output-value = <1>;
> +    direction = <PIN_OUTPUT>;
> +};
> diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
> index 7e679a0..35e8197 100644
> --- a/drivers/gpio/intel_ich6_gpio.c
> +++ b/drivers/gpio/intel_ich6_gpio.c
> @@ -44,21 +44,28 @@ struct ich6_bank_priv {
>   	uint16_t 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)
> +#define IOPAD_PULL_STRENGTH_SHIFT	9
> +#define IOPAD_PULL_STRENGTH_MASK	(0x3 << IOPAD_PULL_STRENGTH_SHIFT)
> +
>   /* TODO: Move this to device tree, or platform data */
>   void ich_gpio_set_gpio_map(const struct pch_gpio_map *map)
>   {
>   	gd->arch.gpio_map = map;
>   }
>   
> -static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
> +static int gpio_ich6_get_base(unsigned long base)
>   {
> -	struct ich6_bank_platdata *plat = dev_get_platdata(dev);
> -	pci_dev_t pci_dev;			/* handle for 0:1f:0 */
> +	pci_dev_t pci_dev;	/* handle for 0:1f:0 */
>   	u8 tmpbyte;
>   	u16 tmpword;
>   	u32 tmplong;
> -	u16 gpiobase;
> -	int offset;
>   
>   	/* Where should it be? */
>   	pci_dev = PCI_BDF(0, 0x1f, 0);
> @@ -123,9 +130,9 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>   	 * while on the Ivybridge the bit0 is used to indicate it is an
>   	 * I/O space.
>   	 */
> -	tmplong = x86_pci_read_config32(pci_dev, PCI_CFG_GPIOBASE);
> +	tmplong = x86_pci_read_config32(pci_dev, base);
>   	if (tmplong == 0x00000000 || tmplong == 0xffffffff) {
> -		debug("%s: unexpected GPIOBASE value\n", __func__);
> +		debug("%s: unexpected BASE value\n", __func__);
>   		return -ENODEV;
>   	}
>   
> @@ -135,7 +142,213 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
>   	 * at the offset that we just read. Bit 0 indicates that it's
>   	 * an I/O address, not a memory address, so mask that off.
>   	 */
> -	gpiobase = tmplong & 0xfffe;
> +	return tmplong & 0xfffc;
> +}
> +
> +static int _ich6_gpio_set_value(uint16_t base, unsigned offset, int value)
> +{
> +	u32 val;
> +
> +	val = inl(base);
> +	if (value)
> +		val |= (1UL << offset);
> +	else
> +		val &= ~(1UL << offset);
> +	outl(val, base);
> +
> +	return 0;
> +}
> +
> +static int _ich6_gpio_set_function(uint16_t base, unsigned offset, int func)
> +{
> +	u32 val;
> +
> +	if (func) {
> +		val = inl(base);
> +		val |= (1UL << offset);
> +		outl(val, base);
> +	} else {
> +		val = inl(base);
> +		val &= ~(1UL << offset);
> +		outl(val, base);
> +	}
> +
> +	return 0;
> +}
> +
> +static int _ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir)
> +{
> +	u32 val;
> +
> +	if (!dir) {
> +		val = inl(base);
> +		val |= (1UL << offset);
> +		outl(val, base);
> +	} else {
> +		val = inl(base);
> +		val &= ~(1UL << offset);
> +		outl(val, base);
> +	}
> +
> +	return 0;
> +}
> +
> +static int _gpio_ich6_pinctrl_cfg_pin(s32 gpiobase, s32 iobase, int pin_node)
> +{
> +	u32 gpio_offset[2];
> +	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) {
> +		/* 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);
> +
> +		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);
> +
> +		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);
> +	}
> +
> +	/* if iobase is present, let's configure the pad */
> +	if (iobase != -1) {
> +		int iobase_addr;
> +
> +		/*
> +		 * The offset for the same pin for the IOBASE and GPIOBASE are
> +		 * different, so instead of maintaining a lookup table,
> +		 * the device tree should provide directly the correct
> +		 * value for both mapping.
> +		 */
> +		pad_offset =
> +		    fdtdec_get_int(gd->fdt_blob, pin_node, "pad-offset", -1);
> +		if (pad_offset == -1) {
> +			debug("%s: Invalid register io offset %d\n",
> +			      __func__, pad_offset);
> +			return -EINVAL;
> +		}
> +
> +		/* compute the absolute pad address */
> +		iobase_addr = iobase + pad_offset;
> +
> +		/*
> +		 * Do we need to set a specific function mode?
> +		 * If someone put also 'mode-gpio', this option will
> +		 * be just ignored by the controller
> +		 */
> +		val = fdtdec_get_int(gd->fdt_blob, pin_node, "mode-func", -1);
> +		if (val != -1)
> +			clrsetbits_le32(iobase_addr, IOPAD_MODE_MASK, val);
> +
> +		/* Configure the pull-up/down if needed */
> +		val = fdtdec_get_int(gd->fdt_blob, pin_node, "pull-assign", -1);
> +		if (val != -1)
> +			clrsetbits_le32(iobase_addr,
> +					IOPAD_PULL_ASSIGN_MASK,
> +					val << IOPAD_PULL_ASSIGN_SHIFT);
> +
> +		val =
> +		    fdtdec_get_int(gd->fdt_blob, pin_node, "pull-strength", -1);
> +		if (val != -1)
> +			clrsetbits_le32(iobase_addr,
> +					IOPAD_PULL_STRENGTH_MASK,
> +					val << IOPAD_PULL_STRENGTH_SHIFT);
> +
> +		debug("%s: pad cfg [0x%x]: %08x\n", __func__, pad_offset,
> +		      readl(iobase_addr));
> +	}
> +
> +	return 0;
> +}
> +
> +int gpio_ich6_pinctrl_init(void)
> +{
> +	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;
> +	}
> +
> +	/* This is not an error to not have a pinctrl node */
> +	node =
> +	    fdtdec_next_compatible(gd->fdt_blob, 0, COMPAT_INTEL_X86_PINCTRL);
> +	if (node <= 0) {
> +		debug("%s: no pinctrl node\n", __func__);
> +		return 0;
> +	}
> +
> +	/*
> +	 * Get the IOBASE, this is not mandatory as this is not
> +	 * supported by all the CPU
> +	 */
> +	iobase_offset = fdtdec_get_int(gd->fdt_blob, node, "io-offset", -1);
> +	if (iobase_offset == -1) {
> +		debug("%s: io-base offset not present\n", __func__);
> +	} else {
> +		iobase = gpio_ich6_get_base(iobase_offset);
> +		if (iobase < 0) {
> +			debug("%s: invalid IOBASE address (%08x)\n", __func__,
> +			      iobase);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	for (pin_node = fdt_first_subnode(gd->fdt_blob, node);
> +	     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);
> +		if (ret != 0) {
> +			debug("%s: invalid configuration for the pin %d\n",
> +			      __func__, pin_node);
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
> +{
> +	struct ich6_bank_platdata *plat = dev_get_platdata(dev);
> +	u16 gpiobase;
> +	int offset;
> +
> +	gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
>   	offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
>   	if (offset == -1) {
>   		debug("%s: Invalid register offset %d\n", __func__, offset);
> @@ -192,30 +405,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);
> -	u32 tmplong;
>   
> -	tmplong = inl(bank->io_sel);
> -	tmplong |= (1UL << offset);
> -	outl(bank->io_sel, tmplong);
> -	return 0;
> +	return _ich6_gpio_set_direction(inl(bank->io_sel), offset, 0);
>   }
>   
>   static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
>   				       int value)
>   {
>   	struct ich6_bank_priv *bank = dev_get_priv(dev);
> -	u32 tmplong;
>   
> -	gpio_set_value(offset, value);
> -
> -	tmplong = inl(bank->io_sel);
> -	tmplong &= ~(1UL << offset);
> -	outl(bank->io_sel, tmplong);
> -	return 0;
> +	return _ich6_gpio_set_direction(inl(bank->io_sel), offset, 1);
>   }
>   
>   static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
> -
>   {
>   	struct ich6_bank_priv *bank = dev_get_priv(dev);
>   	u32 tmplong;
> @@ -230,15 +432,7 @@ static int ich6_gpio_set_value(struct udevice *dev, unsigned offset,
>   			       int value)
>   {
>   	struct ich6_bank_priv *bank = dev_get_priv(dev);
> -	u32 tmplong;
> -
> -	tmplong = inl(bank->lvl);
> -	if (value)
> -		tmplong |= (1UL << offset);
> -	else
> -		tmplong &= ~(1UL << offset);
> -	outl(bank->lvl, tmplong);
> -	return 0;
> +	return _ich6_gpio_set_value(bank->lvl, offset, value);
>   }
>   
>   static int ich6_gpio_get_function(struct udevice *dev, unsigned offset)
> diff --git a/include/dt-bindings/gpio/x86-gpio.h b/include/dt-bindings/gpio/x86-gpio.h
> new file mode 100644
> index 0000000..7f1de30
> --- /dev/null
> +++ b/include/dt-bindings/gpio/x86-gpio.h
> @@ -0,0 +1,31 @@
> +/*
> + * This header provides constants for binding intel,x86-pinctrl.
> + */
> +
> +#ifndef _DT_BINDINGS_GPIO_X86_GPIO_H
> +#define _DT_BINDINGS_GPIO_X86_GPIO_H
> +
> +#include <dt-bindings/gpio/gpio.h>
> +
> +#define GPIO_MODE_NATIVE	0
> +#define GPIO_MODE_GPIO		1
> +
> +#define GPIO_MODE_FUNC0	0
> +#define GPIO_MODE_FUNC1	1
> +#define GPIO_MODE_FUNC2	2
> +#define GPIO_MODE_FUNC3	3
> +#define GPIO_MODE_FUNC4	4
> +#define GPIO_MODE_FUNC5	5
> +#define GPIO_MODE_FUNC6	6
> +
> +#define PIN_INPUT	0
> +#define PIN_OUTPUT	1
> +
> +#define PIN_INPUT_NOPULL	0
> +#define PIN_INPUT_PULLUP	1
> +#define PIN_INPUT_PULLDOWN	2
> +
> +#define PULL_STR_2K		0
> +#define PULL_STR_20K	2
> +
> +#endif
> diff --git a/include/fdtdec.h b/include/fdtdec.h
> index 6590470..5146ff1 100644
> --- a/include/fdtdec.h
> +++ b/include/fdtdec.h
> @@ -175,6 +175,7 @@ enum fdt_compat_id {
>   	COMPAT_AMS_AS3722,		/* AMS AS3722 PMIC */
>   	COMPAT_INTEL_ICH_SPI,		/* Intel ICH7/9 SPI controller */
>   	COMPAT_INTEL_QRK_MRC,		/* Intel Quark MRC */
> +	COMPAT_INTEL_X86_PINCTRL,	/* Intel ICH7/9 pin control */
>   	COMPAT_SOCIONEXT_XHCI,		/* Socionext UniPhier xHCI */
>   	COMPAT_INTEL_PCH,		/* Intel PCH */
>   
> diff --git a/lib/fdtdec.c b/lib/fdtdec.c
> index 80b897a..6bdc270 100644
> --- a/lib/fdtdec.c
> +++ b/lib/fdtdec.c
> @@ -74,6 +74,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
>   	COMPAT(AMS_AS3722, "ams,as3722"),
>   	COMPAT(INTEL_ICH_SPI, "intel,ich-spi"),
>   	COMPAT(INTEL_QRK_MRC, "intel,quark-mrc"),
> +	COMPAT(INTEL_X86_PINCTRL, "intel,x86-pinctrl"),
>   	COMPAT(SOCIONEXT_XHCI, "socionext,uniphier-xhci"),
>   	COMPAT(COMPAT_INTEL_PCH, "intel,bd82x6x"),
>   };

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH v3 4/4] x86: minnowmax: initialize the pin-muxing from device tree
  2015-05-12  6:20   ` gabriel huau
@ 2015-05-20 14:21     ` Simon Glass
  2015-05-26  5:30       ` gabriel huau
  0 siblings, 1 reply; 61+ messages in thread
From: Simon Glass @ 2015-05-20 14:21 UTC (permalink / raw)
  To: u-boot

Hi Gabriel,

I have two patches in patchwork:

http://patchwork.ozlabs.org/patch/471146/
http://patchwork.ozlabs.org/patch/471147/

Are they the correct ones? Also do you know how to use the gpio
command to toggle a bin on the Minnowboard MAX header? I'd like to try
that.

Regards,
Simon


On 12 May 2015 at 00:20, gabriel huau <contact@huau-gabriel.fr> wrote:
> Please ignore this email/patch, I put the wrong message id ...
>
>
> On 05/11/2015 11:12 PM, Gabriel Huau wrote:
>>
>> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
>> Acked-by: Simon Glass <sjg@chromium.org>
>>
>> ---
>>
>> Changes in v3:
>>      - Rebase to the origin/master
>>
>> Changes in v2:
>>      - Fix ordering of include header
>>
>>   board/intel/minnowmax/minnowmax.c | 9 +++++++++
>>   include/configs/minnowmax.h       | 1 +
>>   2 files changed, 10 insertions(+)
>>
>> diff --git a/board/intel/minnowmax/minnowmax.c
>> b/board/intel/minnowmax/minnowmax.c
>> index 1f5549a..383cae0 100644
>> --- a/board/intel/minnowmax/minnowmax.c
>> +++ b/board/intel/minnowmax/minnowmax.c
>> @@ -5,6 +5,7 @@
>>    */
>>     #include <common.h>
>> +#include <asm/gpio.h>
>>   #include <asm/ibmpc.h>
>>   #include <asm/pnp_def.h>
>>   #include <netdev.h>
>> @@ -12,6 +13,14 @@
>>     #define SERIAL_DEV PNP_DEV(0x2e, 4)
>>   +int arch_early_init_r(void)
>> +{
>> +       /* do the pin-muxing */
>> +       gpio_ich6_pinctrl_init();
>> +
>> +       return 0;
>> +}
>> +
>>   int board_early_init_f(void)
>>   {
>>         lpc47m_enable_serial(SERIAL_DEV, UART0_BASE, UART0_IRQ);
>> diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h
>> index eb35a50..547765d 100644
>> --- a/include/configs/minnowmax.h
>> +++ b/include/configs/minnowmax.h
>> @@ -15,6 +15,7 @@
>>     #define CONFIG_SYS_MONITOR_LEN              (1 << 20)
>>   #define CONFIG_BOARD_EARLY_INIT_F
>> +#define CONFIG_ARCH_EARLY_INIT_R
>>     #define CONFIG_X86_SERIAL
>>   #define CONFIG_SMSC_LPC47M
>
>

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH v4 3/4] x86: gpio: add pinctrl support from the device tree
  2015-04-23 16:16 ` [U-Boot] [PATCH 3/4] x86: gpio: add pinctrl support from " Gabriel Huau
                     ` (4 preceding siblings ...)
  2015-05-12  6:17   ` [U-Boot] [PATCH v3 3/4] " Gabriel Huau
@ 2015-05-26  5:27   ` Gabriel Huau
  2015-06-04 15:17     ` Simon Glass
  5 siblings, 1 reply; 61+ messages in thread
From: Gabriel Huau @ 2015-05-26  5:27 UTC (permalink / raw)
  To: u-boot

Every pin can be configured now from the device tree. A dt-bindings
has been added to describe the different property available.

Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
---

Changes in v4:
    - Rebase modification on latest update
    - Fix typo to read the io-base
    - Fix direction_output function to set the value

Changes in v3:
    - Fix the dt-binding copyright header
    - Remove define for IOBASE and use a property
    - Fix issues with signed/unsigned variable type
    - Fix coding style
    - Add a compatible string for the driver

Changes in v2:
    - Clean commit message
    - Rename compatible string 'ich6' to 'x86'
    - Fix coding style
    - Create a dt-bindinds documentation
    - Move x86-gpio defines to a specific header
    - Reorder the functions to avoid the need for forward declarations
    - Rename double underscore functions to only one
    - Create a specific function to configure one pin
    - Use a define to prevent build/support issues with other x86 CPU that
    doesn't have a IOBASE.

 arch/x86/dts/minnowmax.dts                         |  23 ++
 arch/x86/include/asm/gpio.h                        |   1 +
 .../gpio/intel,x86-pinctrl.txt                     |  31 +++
 drivers/gpio/intel_ich6_gpio.c                     | 257 ++++++++++++++++++---
 include/dt-bindings/gpio/x86-gpio.h                |  31 +++
 include/fdtdec.h                                   |   1 +
 lib/fdtdec.c                                       |   1 +
 7 files changed, 317 insertions(+), 28 deletions(-)
 create mode 100644 doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
 create mode 100644 include/dt-bindings/gpio/x86-gpio.h

diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
index 7103bc5..bd21bfb 100644
--- a/arch/x86/dts/minnowmax.dts
+++ b/arch/x86/dts/minnowmax.dts
@@ -6,6 +6,8 @@
 
 /dts-v1/;
 
+#include <dt-bindings/gpio/x86-gpio.h>
+
 /include/ "skeleton.dtsi"
 /include/ "serial.dtsi"
 
@@ -22,6 +24,27 @@
 		silent_console = <0>;
 	};
 
+	pch_pinctrl {
+		compatible = "intel,x86-pinctrl";
+		io-base = <0x4c>;
+
+		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 = <0x258>;
+			mode-gpio;
+			output-value = <1>;
+			direction = <PIN_OUTPUT>;
+		};
+	};
+
 	gpioa {
 		compatible = "intel,ich6-gpio";
 		u-boot,dm-pre-reloc;
diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h
index 1099427..ed85b08 100644
--- a/arch/x86/include/asm/gpio.h
+++ b/arch/x86/include/asm/gpio.h
@@ -147,6 +147,7 @@ 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/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt b/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
new file mode 100644
index 0000000..45ab1af
--- /dev/null
+++ b/doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
@@ -0,0 +1,31 @@
+Intel x86 PINCTRL/GPIO controller
+
+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.
+
+The PINCTRL master node requires the following properties:
+- compatible : "intel,x86-pinctrl"
+
+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'
+					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.
+- 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.
+
+Example:
+
+pin_usb_host_en0 at 0 {
+    gpio-offset = <0x80 8>;
+    pad-offset = <0x260>;
+    mode-gpio;
+    output-value = <1>;
+    direction = <PIN_OUTPUT>;
+};
diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
index 7e679a0..8a108f3 100644
--- a/drivers/gpio/intel_ich6_gpio.c
+++ b/drivers/gpio/intel_ich6_gpio.c
@@ -44,21 +44,28 @@ struct ich6_bank_priv {
 	uint16_t 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)
+#define IOPAD_PULL_STRENGTH_SHIFT	9
+#define IOPAD_PULL_STRENGTH_MASK	(0x3 << IOPAD_PULL_STRENGTH_SHIFT)
+
 /* TODO: Move this to device tree, or platform data */
 void ich_gpio_set_gpio_map(const struct pch_gpio_map *map)
 {
 	gd->arch.gpio_map = map;
 }
 
-static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
+static int gpio_ich6_get_base(unsigned long base)
 {
-	struct ich6_bank_platdata *plat = dev_get_platdata(dev);
 	pci_dev_t pci_dev;			/* handle for 0:1f:0 */
 	u8 tmpbyte;
 	u16 tmpword;
 	u32 tmplong;
-	u16 gpiobase;
-	int offset;
 
 	/* Where should it be? */
 	pci_dev = PCI_BDF(0, 0x1f, 0);
@@ -123,9 +130,9 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
 	 * while on the Ivybridge the bit0 is used to indicate it is an
 	 * I/O space.
 	 */
-	tmplong = x86_pci_read_config32(pci_dev, PCI_CFG_GPIOBASE);
+	tmplong = x86_pci_read_config32(pci_dev, base);
 	if (tmplong == 0x00000000 || tmplong == 0xffffffff) {
-		debug("%s: unexpected GPIOBASE value\n", __func__);
+		debug("%s: unexpected BASE value\n", __func__);
 		return -ENODEV;
 	}
 
@@ -135,7 +142,215 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
 	 * at the offset that we just read. Bit 0 indicates that it's
 	 * an I/O address, not a memory address, so mask that off.
 	 */
-	gpiobase = tmplong & 0xfffe;
+	return tmplong & 0xfffc;
+}
+
+static int _ich6_gpio_set_value(uint16_t base, unsigned offset, int value)
+{
+	u32 val;
+
+	val = inl(base);
+	if (value)
+		val |= (1UL << offset);
+	else
+		val &= ~(1UL << offset);
+	outl(val, base);
+
+	return 0;
+}
+
+static int _ich6_gpio_set_function(uint16_t base, unsigned offset, int func)
+{
+	u32 val;
+
+	if (func) {
+		val = inl(base);
+		val |= (1UL << offset);
+		outl(val, base);
+	} else {
+		val = inl(base);
+		val &= ~(1UL << offset);
+		outl(val, base);
+	}
+
+	return 0;
+}
+
+static int _ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir)
+{
+	u32 val;
+
+	if (!dir) {
+		val = inl(base);
+		val |= (1UL << offset);
+		outl(val, base);
+	} else {
+		val = inl(base);
+		val &= ~(1UL << offset);
+		outl(val, base);
+	}
+
+	return 0;
+}
+
+static int _gpio_ich6_pinctrl_cfg_pin(s32 gpiobase, s32 iobase, int pin_node)
+{
+	u32 gpio_offset[2];
+	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) {
+		/* 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);
+
+		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);
+
+		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);
+	}
+
+	/* if iobase is present, let's configure the pad */
+	if (iobase != -1) {
+		int iobase_addr;
+
+		/*
+		 * The offset for the same pin for the IOBASE and GPIOBASE are
+		 * different, so instead of maintaining a lookup table,
+		 * the device tree should provide directly the correct
+		 * value for both mapping.
+		 */
+		pad_offset =
+		    fdtdec_get_int(gd->fdt_blob, pin_node, "pad-offset", -1);
+		if (pad_offset == -1) {
+			debug("%s: Invalid register io offset %d\n",
+			      __func__, pad_offset);
+			return -EINVAL;
+		}
+
+		/* compute the absolute pad address */
+		iobase_addr = iobase + pad_offset;
+
+		/*
+		 * Do we need to set a specific function mode?
+		 * If someone put also 'mode-gpio', this option will
+		 * be just ignored by the controller
+		 */
+		val = fdtdec_get_int(gd->fdt_blob, pin_node, "mode-func", -1);
+		if (val != -1)
+			clrsetbits_le32(iobase_addr, IOPAD_MODE_MASK, val);
+
+		/* Configure the pull-up/down if needed */
+		val = fdtdec_get_int(gd->fdt_blob, pin_node, "pull-assign", -1);
+		if (val != -1)
+			clrsetbits_le32(iobase_addr,
+					IOPAD_PULL_ASSIGN_MASK,
+					val << IOPAD_PULL_ASSIGN_SHIFT);
+
+		val =
+		    fdtdec_get_int(gd->fdt_blob, pin_node, "pull-strength", -1);
+		if (val != -1)
+			clrsetbits_le32(iobase_addr,
+					IOPAD_PULL_STRENGTH_MASK,
+					val << IOPAD_PULL_STRENGTH_SHIFT);
+
+		debug("%s: pad cfg [0x%x]: %08x\n", __func__, pad_offset,
+		      readl(iobase_addr));
+	}
+
+	return 0;
+}
+
+int gpio_ich6_pinctrl_init(void)
+{
+	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;
+	}
+
+	/* This is not an error to not have a pinctrl node */
+	node =
+	    fdtdec_next_compatible(gd->fdt_blob, 0, COMPAT_INTEL_X86_PINCTRL);
+	if (node <= 0) {
+		debug("%s: no pinctrl node\n", __func__);
+		return 0;
+	}
+
+	/*
+	 * Get the IOBASE, this is not mandatory as this is not
+	 * supported by all the CPU
+	 */
+	iobase_offset = fdtdec_get_int(gd->fdt_blob, node, "io-base", -1);
+	if (iobase_offset == -1) {
+		debug("%s: io-base offset not present\n", __func__);
+	} else {
+		iobase = gpio_ich6_get_base(iobase_offset);
+		if (iobase < 0) {
+			debug("%s: invalid IOBASE address (%08x)\n", __func__,
+			      iobase);
+			return -EINVAL;
+		}
+	}
+
+	for (pin_node = fdt_first_subnode(gd->fdt_blob, node);
+	     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);
+		if (ret != 0) {
+			debug("%s: invalid configuration for the pin %d\n",
+			      __func__, pin_node);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ich6_bank_platdata *plat = dev_get_platdata(dev);
+	u16 gpiobase;
+	int offset;
+
+	gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE);
 	offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
 	if (offset == -1) {
 		debug("%s: Invalid register offset %d\n", __func__, offset);
@@ -192,30 +407,24 @@ 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);
-	u32 tmplong;
 
-	tmplong = inl(bank->io_sel);
-	tmplong |= (1UL << offset);
-	outl(bank->io_sel, tmplong);
-	return 0;
+	return _ich6_gpio_set_direction(inl(bank->io_sel), 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);
-	u32 tmplong;
 
-	gpio_set_value(offset, value);
+	ret = _ich6_gpio_set_direction(inl(bank->io_sel), offset, 1);
+	if (ret)
+		return ret;
 
-	tmplong = inl(bank->io_sel);
-	tmplong &= ~(1UL << offset);
-	outl(bank->io_sel, tmplong);
-	return 0;
+	return _ich6_gpio_set_value(bank->lvl, offset, value);
 }
 
 static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
-
 {
 	struct ich6_bank_priv *bank = dev_get_priv(dev);
 	u32 tmplong;
@@ -230,15 +439,7 @@ static int ich6_gpio_set_value(struct udevice *dev, unsigned offset,
 			       int value)
 {
 	struct ich6_bank_priv *bank = dev_get_priv(dev);
-	u32 tmplong;
-
-	tmplong = inl(bank->lvl);
-	if (value)
-		tmplong |= (1UL << offset);
-	else
-		tmplong &= ~(1UL << offset);
-	outl(bank->lvl, tmplong);
-	return 0;
+	return _ich6_gpio_set_value(bank->lvl, offset, value);
 }
 
 static int ich6_gpio_get_function(struct udevice *dev, unsigned offset)
diff --git a/include/dt-bindings/gpio/x86-gpio.h b/include/dt-bindings/gpio/x86-gpio.h
new file mode 100644
index 0000000..7f1de30
--- /dev/null
+++ b/include/dt-bindings/gpio/x86-gpio.h
@@ -0,0 +1,31 @@
+/*
+ * This header provides constants for binding intel,x86-pinctrl.
+ */
+
+#ifndef _DT_BINDINGS_GPIO_X86_GPIO_H
+#define _DT_BINDINGS_GPIO_X86_GPIO_H
+
+#include <dt-bindings/gpio/gpio.h>
+
+#define GPIO_MODE_NATIVE	0
+#define GPIO_MODE_GPIO		1
+
+#define GPIO_MODE_FUNC0	0
+#define GPIO_MODE_FUNC1	1
+#define GPIO_MODE_FUNC2	2
+#define GPIO_MODE_FUNC3	3
+#define GPIO_MODE_FUNC4	4
+#define GPIO_MODE_FUNC5	5
+#define GPIO_MODE_FUNC6	6
+
+#define PIN_INPUT	0
+#define PIN_OUTPUT	1
+
+#define PIN_INPUT_NOPULL	0
+#define PIN_INPUT_PULLUP	1
+#define PIN_INPUT_PULLDOWN	2
+
+#define PULL_STR_2K		0
+#define PULL_STR_20K	2
+
+#endif
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 6bf5f61..cea03af 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -176,6 +176,7 @@ enum fdt_compat_id {
 	COMPAT_AMS_AS3722,		/* AMS AS3722 PMIC */
 	COMPAT_INTEL_ICH_SPI,		/* Intel ICH7/9 SPI controller */
 	COMPAT_INTEL_QRK_MRC,		/* Intel Quark MRC */
+	COMPAT_INTEL_X86_PINCTRL,	/* Intel ICH7/9 pin control */
 	COMPAT_SOCIONEXT_XHCI,		/* Socionext UniPhier xHCI */
 	COMPAT_INTEL_PCH,		/* Intel PCH */
 
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index b586da2..4244310 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -75,6 +75,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(AMS_AS3722, "ams,as3722"),
 	COMPAT(INTEL_ICH_SPI, "intel,ich-spi"),
 	COMPAT(INTEL_QRK_MRC, "intel,quark-mrc"),
+	COMPAT(INTEL_X86_PINCTRL, "intel,x86-pinctrl"),
 	COMPAT(SOCIONEXT_XHCI, "socionext,uniphier-xhci"),
 	COMPAT(COMPAT_INTEL_PCH, "intel,bd82x6x"),
 };
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH v3 4/4] x86: minnowmax: initialize the pin-muxing from device tree
  2015-05-20 14:21     ` Simon Glass
@ 2015-05-26  5:30       ` gabriel huau
  2015-05-26  8:01         ` Andy Pont
  2015-06-04  9:28         ` Simon Glass
  0 siblings, 2 replies; 61+ messages in thread
From: gabriel huau @ 2015-05-26  5:30 UTC (permalink / raw)
  To: u-boot

Hi Simon,

I just submitted a new version of the patch, actually, when I tried to 
use the GPIO on the header I saw a typo in the code.

To test it, you have to define these nodes in the device tree (should be 
there by default or not?):

         soc_gpio_s5_0 at 0 {
             gpio-offset = <0x80 0>;
             pad-offset = <0x1d0>;
             mode-gpio;
             output-value = <0>;
             direction = <PIN_OUTPUT>;
         };

         soc_gpio_s5_1 at 0 {
             gpio-offset = <0x80 1>;
             pad-offset = <0x210>;
             mode-gpio;
             output-value = <0>;
             direction = <PIN_OUTPUT>;
         };

         soc_gpio_s5_2 at 0 {
             gpio-offset = <0x80 2>;
             pad-offset = <0x1e0>;
             mode-gpio;
             output-value = <0>;
             direction = <PIN_OUTPUT>;
         };

And after, you can use the GPIO commands:

=> gpio set E0
gpio: pin E0 (gpio 128) value is 1
=> gpio clear E0
gpio: pin E0 (gpio 128) value is 0
=> gpio set E2
gpio: pin E2 (gpio 130) value is 1
=> gpio clear E2
gpio: pin E2 (gpio 130) value is 0

E0 E1 and E2 correspond to the GPIO0 1 and 2.

Regards,
Gabriel

On 05/20/2015 07:21 AM, Simon Glass wrote:
> Hi Gabriel,
>
> I have two patches in patchwork:
>
> http://patchwork.ozlabs.org/patch/471146/
> http://patchwork.ozlabs.org/patch/471147/
>
> Are they the correct ones? Also do you know how to use the gpio
> command to toggle a bin on the Minnowboard MAX header? I'd like to try
> that.
>
> Regards,
> Simon
>
>
> On 12 May 2015 at 00:20, gabriel huau <contact@huau-gabriel.fr> wrote:
>> Please ignore this email/patch, I put the wrong message id ...
>>
>>
>> On 05/11/2015 11:12 PM, Gabriel Huau wrote:
>>> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
>>> Acked-by: Simon Glass <sjg@chromium.org>
>>>
>>> ---
>>>
>>> Changes in v3:
>>>       - Rebase to the origin/master
>>>
>>> Changes in v2:
>>>       - Fix ordering of include header
>>>
>>>    board/intel/minnowmax/minnowmax.c | 9 +++++++++
>>>    include/configs/minnowmax.h       | 1 +
>>>    2 files changed, 10 insertions(+)
>>>
>>> diff --git a/board/intel/minnowmax/minnowmax.c
>>> b/board/intel/minnowmax/minnowmax.c
>>> index 1f5549a..383cae0 100644
>>> --- a/board/intel/minnowmax/minnowmax.c
>>> +++ b/board/intel/minnowmax/minnowmax.c
>>> @@ -5,6 +5,7 @@
>>>     */
>>>      #include <common.h>
>>> +#include <asm/gpio.h>
>>>    #include <asm/ibmpc.h>
>>>    #include <asm/pnp_def.h>
>>>    #include <netdev.h>
>>> @@ -12,6 +13,14 @@
>>>      #define SERIAL_DEV PNP_DEV(0x2e, 4)
>>>    +int arch_early_init_r(void)
>>> +{
>>> +       /* do the pin-muxing */
>>> +       gpio_ich6_pinctrl_init();
>>> +
>>> +       return 0;
>>> +}
>>> +
>>>    int board_early_init_f(void)
>>>    {
>>>          lpc47m_enable_serial(SERIAL_DEV, UART0_BASE, UART0_IRQ);
>>> diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h
>>> index eb35a50..547765d 100644
>>> --- a/include/configs/minnowmax.h
>>> +++ b/include/configs/minnowmax.h
>>> @@ -15,6 +15,7 @@
>>>      #define CONFIG_SYS_MONITOR_LEN              (1 << 20)
>>>    #define CONFIG_BOARD_EARLY_INIT_F
>>> +#define CONFIG_ARCH_EARLY_INIT_R
>>>      #define CONFIG_X86_SERIAL
>>>    #define CONFIG_SMSC_LPC47M
>>

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH v3 4/4] x86: minnowmax: initialize the pin-muxing from device tree
  2015-05-26  5:30       ` gabriel huau
@ 2015-05-26  8:01         ` Andy Pont
  2015-05-26 14:41           ` Gabriel Huau
  2015-06-04  9:28         ` Simon Glass
  1 sibling, 1 reply; 61+ messages in thread
From: Andy Pont @ 2015-05-26  8:01 UTC (permalink / raw)
  To: u-boot

Hi Gabriel,

> 
>          soc_gpio_s5_0 at 0 {
>              gpio-offset = <0x80 0>;
>              pad-offset = <0x1d0>;
>              mode-gpio;
>              output-value = <0>;
>              direction = <PIN_OUTPUT>;
>          };
> 
>          soc_gpio_s5_1 at 0 {
>              gpio-offset = <0x80 1>;
>              pad-offset = <0x210>;
>              mode-gpio;
>              output-value = <0>;
>              direction = <PIN_OUTPUT>;
>          };
> 
>          soc_gpio_s5_2 at 0 {
>              gpio-offset = <0x80 2>;
>              pad-offset = <0x1e0>;
>              mode-gpio;
>              output-value = <0>;
>              direction = <PIN_OUTPUT>;
>          };
> 
> And after, you can use the GPIO commands:
> 
> => gpio set E0
> gpio: pin E0 (gpio 128) value is 1
> => gpio clear E0
> gpio: pin E0 (gpio 128) value is 0
> => gpio set E2
> gpio: pin E2 (gpio 130) value is 1
> => gpio clear E2
> gpio: pin E2 (gpio 130) value is 0
> 
> E0 E1 and E2 correspond to the GPIO0 1 and 2.

Is there, or can someone add, some documentation somewhere as to how to
convert between the device tree definition and the value used for "pin" in
the gpio commands as it doesn't seem intuitive or obvious to me that what
you have defined translates to E0, E1 and E2.

Thanks,

Andy.

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH v3 4/4] x86: minnowmax: initialize the pin-muxing from device tree
  2015-05-26  8:01         ` Andy Pont
@ 2015-05-26 14:41           ` Gabriel Huau
  2015-06-04  9:28             ` Simon Glass
  0 siblings, 1 reply; 61+ messages in thread
From: Gabriel Huau @ 2015-05-26 14:41 UTC (permalink / raw)
  To: u-boot

Hi Andy,

On 05/26/2015 01:01 AM, Andy Pont wrote:
> Hi Gabriel,
>
>>           soc_gpio_s5_0 at 0 {
>>               gpio-offset = <0x80 0>;
>>               pad-offset = <0x1d0>;
>>               mode-gpio;
>>               output-value = <0>;
>>               direction = <PIN_OUTPUT>;
>>           };
>>
>>           soc_gpio_s5_1 at 0 {
>>               gpio-offset = <0x80 1>;
>>               pad-offset = <0x210>;
>>               mode-gpio;
>>               output-value = <0>;
>>               direction = <PIN_OUTPUT>;
>>           };
>>
>>           soc_gpio_s5_2 at 0 {
>>               gpio-offset = <0x80 2>;
>>               pad-offset = <0x1e0>;
>>               mode-gpio;
>>               output-value = <0>;
>>               direction = <PIN_OUTPUT>;
>>           };
>>
>> And after, you can use the GPIO commands:
>>
>> => gpio set E0
>> gpio: pin E0 (gpio 128) value is 1
>> => gpio clear E0
>> gpio: pin E0 (gpio 128) value is 0
>> => gpio set E2
>> gpio: pin E2 (gpio 130) value is 1
>> => gpio clear E2
>> gpio: pin E2 (gpio 130) value is 0
>>
>> E0 E1 and E2 correspond to the GPIO0 1 and 2.
> Is there, or can someone add, some documentation somewhere as to how to
> convert between the device tree definition and the value used for "pin" in
> the gpio commands as it doesn't seem intuitive or obvious to me that what
> you have defined translates to E0, E1 and E2.
I agree, but I think the documentation should be part of another patch, 
especially as this is the case for all the x86 platform.
The naming is not specific to the minnowboard max (baytrail).

> Thanks,
>
> Andy.
>
Regards,
Gabriel

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH v3 4/4] x86: minnowmax: initialize the pin-muxing from device tree
  2015-05-26  5:30       ` gabriel huau
  2015-05-26  8:01         ` Andy Pont
@ 2015-06-04  9:28         ` Simon Glass
  1 sibling, 0 replies; 61+ messages in thread
From: Simon Glass @ 2015-06-04  9:28 UTC (permalink / raw)
  To: u-boot

Hi Gabriel,

On 25 May 2015 at 23:30, gabriel huau <contact@huau-gabriel.fr> wrote:
> Hi Simon,
>
> I just submitted a new version of the patch, actually, when I tried to use
> the GPIO on the header I saw a typo in the code.
>
> To test it, you have to define these nodes in the device tree (should be
> there by default or not?):

Yes I think so. Can you please send a patch?

>
>         soc_gpio_s5_0 at 0 {
>             gpio-offset = <0x80 0>;
>             pad-offset = <0x1d0>;
>             mode-gpio;
>             output-value = <0>;
>             direction = <PIN_OUTPUT>;
>         };
>
>         soc_gpio_s5_1 at 0 {
>             gpio-offset = <0x80 1>;
>             pad-offset = <0x210>;
>             mode-gpio;
>             output-value = <0>;
>             direction = <PIN_OUTPUT>;
>         };
>
>         soc_gpio_s5_2 at 0 {
>             gpio-offset = <0x80 2>;
>             pad-offset = <0x1e0>;
>             mode-gpio;
>             output-value = <0>;
>             direction = <PIN_OUTPUT>;
>         };
>
> And after, you can use the GPIO commands:
>
> => gpio set E0
> gpio: pin E0 (gpio 128) value is 1
> => gpio clear E0
> gpio: pin E0 (gpio 128) value is 0
> => gpio set E2
> gpio: pin E2 (gpio 130) value is 1
> => gpio clear E2
> gpio: pin E2 (gpio 130) value is 0
>
> E0 E1 and E2 correspond to the GPIO0 1 and 2.

OK thanks, that seems to work for me. I tested these with a multimeter
and can adjust the output.

Acked-by: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>

Regards,
Simon

>
> Regards,
> Gabriel
>
>
> On 05/20/2015 07:21 AM, Simon Glass wrote:
>>
>> Hi Gabriel,
>>
>> I have two patches in patchwork:
>>
>> http://patchwork.ozlabs.org/patch/471146/
>> http://patchwork.ozlabs.org/patch/471147/
>>
>> Are they the correct ones? Also do you know how to use the gpio
>> command to toggle a bin on the Minnowboard MAX header? I'd like to try
>> that.
>>
>> Regards,
>> Simon
>>
>>
>> On 12 May 2015 at 00:20, gabriel huau <contact@huau-gabriel.fr> wrote:
>>>
>>> Please ignore this email/patch, I put the wrong message id ...
>>>
>>>
>>> On 05/11/2015 11:12 PM, Gabriel Huau wrote:
>>>>
>>>> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
>>>> Acked-by: Simon Glass <sjg@chromium.org>
>>>>
>>>> ---
>>>>
>>>> Changes in v3:
>>>>       - Rebase to the origin/master
>>>>
>>>> Changes in v2:
>>>>       - Fix ordering of include header
>>>>
>>>>    board/intel/minnowmax/minnowmax.c | 9 +++++++++
>>>>    include/configs/minnowmax.h       | 1 +
>>>>    2 files changed, 10 insertions(+)
>>>>
>>>> diff --git a/board/intel/minnowmax/minnowmax.c
>>>> b/board/intel/minnowmax/minnowmax.c
>>>> index 1f5549a..383cae0 100644
>>>> --- a/board/intel/minnowmax/minnowmax.c
>>>> +++ b/board/intel/minnowmax/minnowmax.c
>>>> @@ -5,6 +5,7 @@
>>>>     */
>>>>      #include <common.h>
>>>> +#include <asm/gpio.h>
>>>>    #include <asm/ibmpc.h>
>>>>    #include <asm/pnp_def.h>
>>>>    #include <netdev.h>
>>>> @@ -12,6 +13,14 @@
>>>>      #define SERIAL_DEV PNP_DEV(0x2e, 4)
>>>>    +int arch_early_init_r(void)
>>>> +{
>>>> +       /* do the pin-muxing */
>>>> +       gpio_ich6_pinctrl_init();
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>>    int board_early_init_f(void)
>>>>    {
>>>>          lpc47m_enable_serial(SERIAL_DEV, UART0_BASE, UART0_IRQ);
>>>> diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h
>>>> index eb35a50..547765d 100644
>>>> --- a/include/configs/minnowmax.h
>>>> +++ b/include/configs/minnowmax.h
>>>> @@ -15,6 +15,7 @@
>>>>      #define CONFIG_SYS_MONITOR_LEN              (1 << 20)
>>>>    #define CONFIG_BOARD_EARLY_INIT_F
>>>> +#define CONFIG_ARCH_EARLY_INIT_R
>>>>      #define CONFIG_X86_SERIAL
>>>>    #define CONFIG_SMSC_LPC47M
>>>
>>>
>

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH v3 4/4] x86: minnowmax: initialize the pin-muxing from device tree
  2015-05-26 14:41           ` Gabriel Huau
@ 2015-06-04  9:28             ` Simon Glass
  0 siblings, 0 replies; 61+ messages in thread
From: Simon Glass @ 2015-06-04  9:28 UTC (permalink / raw)
  To: u-boot

Hi Gabriel,

On 26 May 2015 at 08:41, Gabriel Huau <contact@huau-gabriel.fr> wrote:
> Hi Andy,
>
> On 05/26/2015 01:01 AM, Andy Pont wrote:
>>
>> Hi Gabriel,
>>
>>
>>>           soc_gpio_s5_0 at 0 {
>>>               gpio-offset = <0x80 0>;
>>>               pad-offset = <0x1d0>;
>>>               mode-gpio;
>>>               output-value = <0>;
>>>               direction = <PIN_OUTPUT>;
>>>           };
>>>
>>>           soc_gpio_s5_1 at 0 {
>>>               gpio-offset = <0x80 1>;
>>>               pad-offset = <0x210>;
>>>               mode-gpio;
>>>               output-value = <0>;
>>>               direction = <PIN_OUTPUT>;
>>>           };
>>>
>>>           soc_gpio_s5_2 at 0 {
>>>               gpio-offset = <0x80 2>;
>>>               pad-offset = <0x1e0>;
>>>               mode-gpio;
>>>               output-value = <0>;
>>>               direction = <PIN_OUTPUT>;
>>>           };
>>>
>>> And after, you can use the GPIO commands:
>>>
>>> => gpio set E0
>>> gpio: pin E0 (gpio 128) value is 1
>>> => gpio clear E0
>>> gpio: pin E0 (gpio 128) value is 0
>>> => gpio set E2
>>> gpio: pin E2 (gpio 130) value is 1
>>> => gpio clear E2
>>> gpio: pin E2 (gpio 130) value is 0
>>>
>>> E0 E1 and E2 correspond to the GPIO0 1 and 2.
>>
>> Is there, or can someone add, some documentation somewhere as to how to
>> convert between the device tree definition and the value used for "pin" in
>> the gpio commands as it doesn't seem intuitive or obvious to me that what
>> you have defined translates to E0, E1 and E2.
>
> I agree, but I think the documentation should be part of another patch,
> especially as this is the case for all the x86 platform.
> The naming is not specific to the minnowboard max (baytrail).

Sounds good, please go ahead.

Regards,
Simon

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH v4 3/4] x86: gpio: add pinctrl support from the device tree
  2015-05-26  5:27   ` [U-Boot] [PATCH v4 " Gabriel Huau
@ 2015-06-04 15:17     ` Simon Glass
  0 siblings, 0 replies; 61+ messages in thread
From: Simon Glass @ 2015-06-04 15:17 UTC (permalink / raw)
  To: u-boot

On 25 May 2015 at 23:27, Gabriel Huau <contact@huau-gabriel.fr> wrote:
> Every pin can be configured now from the device tree. A dt-bindings
> has been added to describe the different property available.
>
> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
> ---
>
> Changes in v4:
>     - Rebase modification on latest update
>     - Fix typo to read the io-base
>     - Fix direction_output function to set the value
>
> Changes in v3:
>     - Fix the dt-binding copyright header
>     - Remove define for IOBASE and use a property
>     - Fix issues with signed/unsigned variable type
>     - Fix coding style
>     - Add a compatible string for the driver
>
> Changes in v2:
>     - Clean commit message
>     - Rename compatible string 'ich6' to 'x86'
>     - Fix coding style
>     - Create a dt-bindinds documentation
>     - Move x86-gpio defines to a specific header
>     - Reorder the functions to avoid the need for forward declarations
>     - Rename double underscore functions to only one
>     - Create a specific function to configure one pin
>     - Use a define to prevent build/support issues with other x86 CPU that
>     doesn't have a IOBASE.
>
>  arch/x86/dts/minnowmax.dts                         |  23 ++
>  arch/x86/include/asm/gpio.h                        |   1 +
>  .../gpio/intel,x86-pinctrl.txt                     |  31 +++
>  drivers/gpio/intel_ich6_gpio.c                     | 257 ++++++++++++++++++---
>  include/dt-bindings/gpio/x86-gpio.h                |  31 +++
>  include/fdtdec.h                                   |   1 +
>  lib/fdtdec.c                                       |   1 +
>  7 files changed, 317 insertions(+), 28 deletions(-)
>  create mode 100644 doc/device-tree-bindings/gpio/intel,x86-pinctrl.txt
>  create mode 100644 include/dt-bindings/gpio/x86-gpio.h

Applied to u-boot-x86, thanks!

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [U-Boot] [PATCH v3 4/4] x86: minnowmax: initialize the pin-muxing from device tree
  2015-05-12  6:18   ` [U-Boot] [PATCH v3 4/4] " Gabriel Huau
@ 2015-06-04 15:17     ` Simon Glass
  0 siblings, 0 replies; 61+ messages in thread
From: Simon Glass @ 2015-06-04 15:17 UTC (permalink / raw)
  To: u-boot

On 12 May 2015 at 00:18, Gabriel Huau <contact@huau-gabriel.fr> wrote:
> Signed-off-by: Gabriel Huau <contact@huau-gabriel.fr>
> Acked-by: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changes in v3:
>     - Rebase to the origin/master
>
> Changes in v2:
>     - Fix ordering of include header
>
>  board/intel/minnowmax/minnowmax.c | 9 +++++++++
>  include/configs/minnowmax.h       | 1 +
>  2 files changed, 10 insertions(+)

Applied to u-boot-x86, thanks!

^ permalink raw reply	[flat|nested] 61+ messages in thread

end of thread, other threads:[~2015-06-04 15:17 UTC | newest]

Thread overview: 61+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-23 16:16 [U-Boot] [PATCH 0/4] x86: support of pin-muxing from device tree Gabriel Huau
2015-04-23 16:16 ` [U-Boot] [PATCH 1/4] x86: baytrail: fix the GPIOBASE address Gabriel Huau
2015-04-24  1:40   ` Bin Meng
2015-04-24  3:25     ` Simon Glass
2015-04-25 20:14   ` [U-Boot] [PATCH 1/5 v2] " Gabriel Huau
2015-04-25 20:16   ` [U-Boot] [PATCH 1/4 v3] " Gabriel Huau
2015-04-26 13:52     ` Bin Meng
2015-04-28 13:53       ` Simon Glass
2015-04-28 15:39         ` Simon Glass
2015-04-23 16:16 ` [U-Boot] [PATCH 2/4] x86: minnowmax: add GPIO banks in the device tree Gabriel Huau
2015-04-24  2:03   ` Bin Meng
2015-04-24  3:26   ` Simon Glass
2015-04-24  5:05   ` [U-Boot] unassigned-patches/146: " u-boot at bugs.denx.de
2015-04-24  5:05   ` [U-Boot] unassigned-patches/147: " u-boot at bugs.denx.de
2015-04-25 20:16   ` [U-Boot] [PATCH 2/4 v2] " Gabriel Huau
2015-04-26 13:54     ` Bin Meng
2015-04-28 13:53       ` Simon Glass
2015-04-28 15:39         ` Simon Glass
2015-04-23 16:16 ` [U-Boot] [PATCH 3/4] x86: gpio: add pinctrl support from " Gabriel Huau
2015-04-24  3:14   ` Bin Meng
2015-04-24 14:32     ` Gabriel Huau
2015-04-24  3:35   ` Simon Glass
2015-04-24 14:37     ` Gabriel Huau
2015-04-24 17:55     ` [U-Boot] unassigned-patches/150: " u-boot at bugs.denx.de
2015-04-24  4:40   ` [U-Boot] unassigned-patches/144: " u-boot at bugs.denx.de
2015-04-25 20:17   ` [U-Boot] [PATCH 3/4 v2] " Gabriel Huau
2015-04-28 13:53     ` Simon Glass
2015-04-28 15:22       ` Stephen Warren
2015-05-12  3:34         ` gabriel huau
2015-05-12  3:33       ` gabriel huau
2015-05-12  6:17   ` [U-Boot] [PATCH v3 3/4] " Gabriel Huau
2015-05-26  5:27   ` [U-Boot] [PATCH v4 " Gabriel Huau
2015-06-04 15:17     ` Simon Glass
2015-04-23 16:16 ` [U-Boot] [PATCH 4/4] x86: minnowmax: initialize the pin-muxing from " Gabriel Huau
2015-04-24  3:37   ` Simon Glass
2015-04-24  4:45   ` [U-Boot] unassigned-patches/145: " u-boot at bugs.denx.de
2015-04-25 20:18   ` [U-Boot] [PATCH 4/4 v2] " Gabriel Huau
2015-04-28 13:53     ` Simon Glass
2015-05-12  6:18   ` [U-Boot] [PATCH v3 4/4] " Gabriel Huau
2015-06-04 15:17     ` Simon Glass
2015-04-23 16:45 ` [U-Boot] unassigned-patches/138: [PATCH 3/4] x86: gpio: add pinctrl support from the " u-boot at bugs.denx.de
2015-04-23 16:45 ` [U-Boot] unassigned-patches/140: [PATCH 2/4] x86: minnowmax: add GPIO banks in " u-boot at bugs.denx.de
2015-04-23 16:45 ` [U-Boot] unassigned-patches/139: [PATCH 1/4] x86: baytrail: fix the GPIOBASE address u-boot at bugs.denx.de
2015-04-23 16:55 ` [U-Boot] unassigned-patches/142: [PATCH 0/4] x86: support of pin-muxing from device tree u-boot at bugs.denx.de
2015-04-23 16:55 ` [U-Boot] unassigned-patches/143: [PATCH 4/4] x86: minnowmax: initialize the " u-boot at bugs.denx.de
2015-04-24  3:23 ` [U-Boot] [PATCH 0/4] x86: support of " Bin Meng
2015-04-24 14:40   ` Gabriel Huau
2015-04-24 17:55   ` [U-Boot] unassigned-patches/151: " u-boot at bugs.denx.de
2015-04-24  5:05 ` [U-Boot] unassigned-patches/148: " u-boot at bugs.denx.de
2015-05-12  6:10 ` [U-Boot] [PATCH v3 3/4] x86: gpio: add pinctrl support from the " Gabriel Huau
2015-05-12  6:20   ` gabriel huau
2015-05-12  6:12 ` [U-Boot] [PATCH v3 4/4] x86: minnowmax: initialize the pin-muxing from " Gabriel Huau
2015-05-12  6:20   ` gabriel huau
2015-05-20 14:21     ` Simon Glass
2015-05-26  5:30       ` gabriel huau
2015-05-26  8:01         ` Andy Pont
2015-05-26 14:41           ` Gabriel Huau
2015-06-04  9:28             ` Simon Glass
2015-06-04  9:28         ` Simon Glass
2015-05-12  6:15 ` [U-Boot] [PATCH v3 3/4] x86: gpio: add pinctrl support from the " Gabriel Huau
2015-05-12  6:21   ` gabriel huau

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.