All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/2] GPIO: CREG: improve flexibility of hsdk-creg-gpio driver
@ 2018-06-08 14:58 Eugeniy Paltsev
  2018-06-08 14:58 ` [U-Boot] [PATCH 1/2] " Eugeniy Paltsev
  2018-06-08 14:58 ` [U-Boot] [PATCH 2/2] CREG GPIO: add device tree bindings Eugeniy Paltsev
  0 siblings, 2 replies; 3+ messages in thread
From: Eugeniy Paltsev @ 2018-06-08 14:58 UTC (permalink / raw)
  To: u-boot

CREG GPIO is a driver for weird soc-specific output ports, which are
controlled by some fields in memory mapped register.

Example:

31                 9        7        5           0   < bit number
|                  |        |        |           |
[     not used     | gpio-1 | gpio-0 | <-shift-> ]   < 32 bit register
                       ^        ^
                       |        |
                write 0x2 == set output to "1" (activate)
                write 0x3 == set output to "0" (deactivate)

As of tooday we only support fixed (hardcoded) bit per gpio line,
activate / deactivatei and shift values. Fix that by read them from
device tree to be able to use this driver for other boards.

Eugeniy Paltsev (2):
  GPIO: CREG: improve flexibility of hsdk-creg-gpio driver
  CREG GPIO: add device tree bindings

 MAINTAINERS                                      |   1 +
 arch/arc/dts/hsdk.dts                            |   7 +-
 doc/device-tree-bindings/gpio/snps,creg-gpio.txt |  43 ++++++++++
 drivers/gpio/hsdk-creg-gpio.c                    | 103 ++++++++++++++++++-----
 4 files changed, 131 insertions(+), 23 deletions(-)
 create mode 100644 doc/device-tree-bindings/gpio/snps,creg-gpio.txt

-- 
2.14.3

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

* [U-Boot] [PATCH 1/2] GPIO: CREG: improve flexibility of hsdk-creg-gpio driver
  2018-06-08 14:58 [U-Boot] [PATCH 0/2] GPIO: CREG: improve flexibility of hsdk-creg-gpio driver Eugeniy Paltsev
@ 2018-06-08 14:58 ` Eugeniy Paltsev
  2018-06-08 14:58 ` [U-Boot] [PATCH 2/2] CREG GPIO: add device tree bindings Eugeniy Paltsev
  1 sibling, 0 replies; 3+ messages in thread
From: Eugeniy Paltsev @ 2018-06-08 14:58 UTC (permalink / raw)
  To: u-boot

CREG GPIO is a driver for weird soc-specific output ports, which are
controlled by some fields in memory mapped register.

Example:

31                 9        7        5           0   < bit number
|                  |        |        |           |
[     not used     | gpio-1 | gpio-0 | <-shift-> ]   < 32 bit register
                       ^        ^
                       |        |
                write 0x2 == set output to "1" (activate)
                write 0x3 == set output to "0" (deactivate)

As of tooday we only support fixed (hardcoded) bit per gpio line,
activate / deactivatei and shift values. Fix that by read them from
device tree to be able to use this driver for other boards.

Remove "hsdk" prefix from compatible string as this driver can be
used with different boards like HSDK, AXS101, AXS103, etc.

Signed-off-by: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
---
 arch/arc/dts/hsdk.dts         |   7 ++-
 drivers/gpio/hsdk-creg-gpio.c | 103 +++++++++++++++++++++++++++++++++---------
 2 files changed, 87 insertions(+), 23 deletions(-)

diff --git a/arch/arc/dts/hsdk.dts b/arch/arc/dts/hsdk.dts
index 264512877e..e41e4ce84b 100644
--- a/arch/arc/dts/hsdk.dts
+++ b/arch/arc/dts/hsdk.dts
@@ -101,11 +101,16 @@
 	};
 
 	cs_gpio: gpio at f00014b0 {
-		compatible = "snps,hsdk-creg-gpio";
+		compatible = "snps,creg-gpio";
 		reg = <0xf00014b0 0x4>;
 		gpio-controller;
 		#gpio-cells = <1>;
 		gpio-bank-name = "hsdk-spi-cs";
 		gpio-count = <1>;
+		gpio-first-shift = <0>;
+		gpio-bit-per-line = <2>;
+		gpio-activate-val = <2>;
+		gpio-deactivate-val = <3>;
+		gpio-default-val = <1>;
 	};
 };
diff --git a/drivers/gpio/hsdk-creg-gpio.c b/drivers/gpio/hsdk-creg-gpio.c
index 084a2da652..800027f18e 100644
--- a/drivers/gpio/hsdk-creg-gpio.c
+++ b/drivers/gpio/hsdk-creg-gpio.c
@@ -16,25 +16,24 @@
 #include <errno.h>
 #include <linux/printk.h>
 
-#define HSDK_CREG_MAX_GPIO	8
-
-#define GPIO_ACTIVATE		0x2
-#define GPIO_DEACTIVATE		0x3
-#define GPIO_PIN_MASK		0x3
-#define BIT_PER_GPIO		2
+#define DRV_NAME	"gpio_creg"
 
 struct hsdk_creg_gpio {
-	uint32_t *regs;
+	u32	*regs;
+	u8	shift;
+	u8	activate;
+	u8	deactivate;
+	u8	bit_per_gpio;
 };
 
 static int hsdk_creg_gpio_set_value(struct udevice *dev, unsigned oft, int val)
 {
 	struct hsdk_creg_gpio *hcg = dev_get_priv(dev);
-	uint32_t reg = readl(hcg->regs);
-	uint32_t cmd = val ? GPIO_DEACTIVATE : GPIO_ACTIVATE;
+	u8 reg_shift = oft * hcg->bit_per_gpio + hcg->shift;
+	u32 reg = readl(hcg->regs);
 
-	reg &= ~(GPIO_PIN_MASK << (oft * BIT_PER_GPIO));
-	reg |=  (cmd << (oft * BIT_PER_GPIO));
+	reg &= ~(GENMASK(hcg->bit_per_gpio - 1, 0) << reg_shift);
+	reg |=  ((val ? hcg->deactivate : hcg->activate) << reg_shift);
 
 	writel(reg, hcg->regs);
 
@@ -51,7 +50,9 @@ static int hsdk_creg_gpio_direction_output(struct udevice *dev, unsigned oft,
 
 static int hsdk_creg_gpio_direction_input(struct udevice *dev, unsigned oft)
 {
-	pr_err("hsdk-creg-gpio can't be used as input!\n");
+	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	pr_err("%s can't be used as input!\n", uc_priv->bank_name);
 
 	return -ENOTSUPP;
 }
@@ -59,10 +60,11 @@ static int hsdk_creg_gpio_direction_input(struct udevice *dev, unsigned oft)
 static int hsdk_creg_gpio_get_value(struct udevice *dev, unsigned int oft)
 {
 	struct hsdk_creg_gpio *hcg = dev_get_priv(dev);
-	uint32_t val = readl(hcg->regs);
+	u32 val = readl(hcg->regs);
 
-	val = (val >> (oft * BIT_PER_GPIO)) & GPIO_PIN_MASK;
-	return (val == GPIO_DEACTIVATE) ? 1 : 0;
+	val >>= oft * hcg->bit_per_gpio + hcg->shift;
+	val &= GENMASK(hcg->bit_per_gpio - 1, 0);
+	return (val == hcg->deactivate) ? 1 : 0;
 }
 
 static const struct dm_gpio_ops hsdk_creg_gpio_ops = {
@@ -76,17 +78,74 @@ static int hsdk_creg_gpio_probe(struct udevice *dev)
 {
 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 	struct hsdk_creg_gpio *hcg = dev_get_priv(dev);
+	u32 shift, bit_per_gpio, activate, deactivate, gpio_count;
+	const u8 *defaults;
 
-	hcg->regs = (uint32_t *)devfdt_get_addr_ptr(dev);
-
-	uc_priv->gpio_count = dev_read_u32_default(dev, "gpio-count", 1);
-	if (uc_priv->gpio_count > HSDK_CREG_MAX_GPIO)
-		uc_priv->gpio_count = HSDK_CREG_MAX_GPIO;
+	hcg->regs = (u32 *)devfdt_get_addr_ptr(dev);
+	gpio_count = dev_read_u32_default(dev, "gpio-count", 1);
+	shift = dev_read_u32_default(dev, "gpio-first-shift", 0);
+	bit_per_gpio = dev_read_u32_default(dev, "gpio-bit-per-line", 1);
+	activate = dev_read_u32_default(dev, "gpio-activate-val", 1);
+	deactivate = dev_read_u32_default(dev, "gpio-deactivate-val", 0);
+	defaults = dev_read_u8_array_ptr(dev, "gpio-default-val", gpio_count);
 
 	uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name");
 	if (!uc_priv->bank_name)
 		uc_priv->bank_name = dev_read_name(dev);
 
+	if (!bit_per_gpio) {
+		pr_err("%s: 'gpio-bit-per-line' can't be 0\n",
+		       uc_priv->bank_name);
+
+		return -EINVAL;
+	}
+
+	if (!gpio_count) {
+		pr_err("%s: 'gpio-count' can't be 0\n",
+		       uc_priv->bank_name);
+
+		return -EINVAL;
+	}
+
+	if ((gpio_count * bit_per_gpio + shift) > 32) {
+		pr_err("%s: u32 io register overflow: try to use %u bits\n",
+		       uc_priv->bank_name, gpio_count * bit_per_gpio + shift);
+
+		return -EINVAL;
+	}
+
+	if (GENMASK(31, bit_per_gpio) & activate) {
+		pr_err("%s: 'gpio-activate-val' can't be more than %lu\n",
+		       uc_priv->bank_name, GENMASK(bit_per_gpio - 1, 0));
+
+		return -EINVAL;
+	}
+
+	if (GENMASK(31, bit_per_gpio) & deactivate) {
+		pr_err("%s: 'gpio-deactivate-val' can't be more than %lu\n",
+		       uc_priv->bank_name, GENMASK(bit_per_gpio - 1, 0));
+
+		return -EINVAL;
+	}
+
+	if (activate == deactivate) {
+		pr_err("%s: 'gpio-deactivate-val' and 'gpio-activate-val' can't be equal\n",
+		       uc_priv->bank_name);
+
+		return -EINVAL;
+	}
+
+	hcg->shift = (u8)shift;
+	hcg->bit_per_gpio = (u8)bit_per_gpio;
+	hcg->activate = (u8)activate;
+	hcg->deactivate = (u8)deactivate;
+	uc_priv->gpio_count = gpio_count;
+
+	/* Setup default GPIO value if we have "gpio-default-val" array */
+	if (defaults)
+		for (u8 i = 0; i < gpio_count; i++)
+			hsdk_creg_gpio_set_value(dev, i, defaults[i]);
+
 	pr_debug("%s GPIO [0x%p] controller with %d gpios probed\n",
 		 uc_priv->bank_name, hcg->regs, uc_priv->gpio_count);
 
@@ -94,12 +153,12 @@ static int hsdk_creg_gpio_probe(struct udevice *dev)
 }
 
 static const struct udevice_id hsdk_creg_gpio_ids[] = {
-	{ .compatible = "snps,hsdk-creg-gpio" },
+	{ .compatible = "snps,creg-gpio" },
 	{ }
 };
 
 U_BOOT_DRIVER(gpio_hsdk_creg) = {
-	.name	= "gpio_hsdk_creg",
+	.name	= DRV_NAME,
 	.id	= UCLASS_GPIO,
 	.ops	= &hsdk_creg_gpio_ops,
 	.probe	= hsdk_creg_gpio_probe,
-- 
2.14.3

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

* [U-Boot] [PATCH 2/2] CREG GPIO: add device tree bindings
  2018-06-08 14:58 [U-Boot] [PATCH 0/2] GPIO: CREG: improve flexibility of hsdk-creg-gpio driver Eugeniy Paltsev
  2018-06-08 14:58 ` [U-Boot] [PATCH 1/2] " Eugeniy Paltsev
@ 2018-06-08 14:58 ` Eugeniy Paltsev
  1 sibling, 0 replies; 3+ messages in thread
From: Eugeniy Paltsev @ 2018-06-08 14:58 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
---
 MAINTAINERS                                      |  1 +
 doc/device-tree-bindings/gpio/snps,creg-gpio.txt | 43 ++++++++++++++++++++++++
 2 files changed, 44 insertions(+)
 create mode 100644 doc/device-tree-bindings/gpio/snps,creg-gpio.txt

diff --git a/MAINTAINERS b/MAINTAINERS
index 642c448093..0ea730e33c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -74,6 +74,7 @@ ARC HSDK CREG GPIO
 M:	Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
 S:	Maintained
 L:	uboot-snps-arc at synopsys.com
+F:	doc/device-tree-bindings/gpio/snps,creg-gpio.txt
 F:	drivers/gpio/hsdk-creg-gpio.c
 
 ARM
diff --git a/doc/device-tree-bindings/gpio/snps,creg-gpio.txt b/doc/device-tree-bindings/gpio/snps,creg-gpio.txt
new file mode 100644
index 0000000000..46ceb65c53
--- /dev/null
+++ b/doc/device-tree-bindings/gpio/snps,creg-gpio.txt
@@ -0,0 +1,43 @@
+GPIO via CREG (control registers) driver
+
+31                 9        7        5           0   < bit number
+|                  |        |        |           |
+[     not used     | gpio-1 | gpio-0 | <-shift-> ]   < 32 bit register
+                       ^        ^
+                       |        |
+                write 0x2 == set output to "1" (activate)
+                write 0x3 == set output to "0" (deactivate)
+
+Required properties:
+- compatible : "snps,creg-gpio"
+- reg : Exactly one register range with length 0x4.
+- #gpio-cells : Should be one - the pin number.
+- gpio-controller : Marks the device node as a GPIO controller.
+- gpio-count: Number of GPIO pins.
+- gpio-bit-per-line: Number of bits per gpio line (see picture).
+- gpio-first-shift: Shift (in bits) of the first GPIO field in register
+  (see picture).
+- gpio-activate-val: Value should be set in corresponding field to set
+  output to "1" (see picture). Applied to all GPIO ports.
+- gpio-deactivate-val: Value should be set in corresponding field to set
+  output to "0" (see picture). Applied to all GPIO ports.
+
+Optional properties:
+- gpio-bank-name: name of bank (as default driver name is used is used)
+- gpio-default-val: array of default output values (must me 0 or 1)
+
+Example (see picture):
+
+gpio: gpio@f00014b0 {
+	compatible = "snps,creg-gpio";
+	reg = <0xf00014b0 0x4>;
+	gpio-controller;
+	#gpio-cells = <1>;
+	gpio-bank-name = "hsdk-spi-cs";
+	gpio-count = <2>;
+	gpio-first-shift = <5>;
+	gpio-bit-per-line = <2>;
+	gpio-activate-val = <2>;
+	gpio-deactivate-val = <3>;
+	gpio-default-val = <1 1>;
+};
-- 
2.14.3

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

end of thread, other threads:[~2018-06-08 14:58 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-08 14:58 [U-Boot] [PATCH 0/2] GPIO: CREG: improve flexibility of hsdk-creg-gpio driver Eugeniy Paltsev
2018-06-08 14:58 ` [U-Boot] [PATCH 1/2] " Eugeniy Paltsev
2018-06-08 14:58 ` [U-Boot] [PATCH 2/2] CREG GPIO: add device tree bindings Eugeniy Paltsev

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.