[U-Boot] [PATCH 15/23] gpio: eg20t: Add driver for Intel EG20T GPIO controllers

Paul Burton paul.burton at imgtec.com
Mon Sep 26 20:29:09 CEST 2016


Add a driver for the GPIO controller found in the Intel EG20T Platform
Controller Hub. This is used on the MIPS Boston development board to
provide GPIOs including ethernet PHY reset.

Signed-off-by: Paul Burton <paul.burton at imgtec.com>

---

 drivers/gpio/Kconfig      |   8 +++
 drivers/gpio/Makefile     |   1 +
 drivers/gpio/eg20t-gpio.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 142 insertions(+)
 create mode 100644 drivers/gpio/eg20t-gpio.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 8d9ab52..4a6a22f 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -221,4 +221,12 @@ config MPC85XX_GPIO
 
 	  The driver has been tested on MPC85XX, but it is likely that other
 	  PowerQUICC III devices will work as well.
+
+config EG20T_GPIO
+	bool "Intel EG20T GPIO driver"
+	depends on DM_GPIO && DM_PCI
+	help
+	  Enable this to support the GPIO controller found in the Intel EG20T
+	  Platform Controller Hub.
+
 endmenu
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 8939226..a94aeb1 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -58,3 +58,4 @@ obj-$(CONFIG_MVEBU_GPIO)	+= mvebu_gpio.o
 obj-$(CONFIG_MSM_GPIO)		+= msm_gpio.o
 obj-$(CONFIG_$(SPL_)PCF8575_GPIO)	+= pcf8575_gpio.o
 obj-$(CONFIG_PM8916_GPIO)	+= pm8916_gpio.o
+obj-$(CONFIG_EG20T_GPIO)	+= eg20t-gpio.o
diff --git a/drivers/gpio/eg20t-gpio.c b/drivers/gpio/eg20t-gpio.c
new file mode 100644
index 0000000..05db771
--- /dev/null
+++ b/drivers/gpio/eg20t-gpio.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2016 Imagination Technologies
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <pci.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+
+enum {
+	REG_IEN		= 0x00,
+	REG_ISTATUS	= 0x04,
+	REG_IDISP	= 0x08,
+	REG_ICLR	= 0x0c,
+	REG_IMASK	= 0x10,
+	REG_IMASKCLR	= 0x14,
+	REG_PO		= 0x18,
+	REG_PI		= 0x1c,
+	REG_PM		= 0x20,
+};
+
+struct eg20t_gpio_priv {
+	void *base;
+};
+
+static int eg20t_gpio_get_value(struct udevice *dev, unsigned int offset)
+{
+	struct eg20t_gpio_priv *priv = dev_get_priv(dev);
+	uint32_t pm, pval;
+
+	pm = readl(priv->base + REG_PM);
+	if ((pm >> offset) & 0x1)
+		pval = readl(priv->base + REG_PO);
+	else
+		pval = readl(priv->base + REG_PI);
+
+	return (pval >> offset) & 0x1;
+}
+
+static int eg20t_gpio_set_value(struct udevice *dev, unsigned int offset,
+				int value)
+{
+	struct eg20t_gpio_priv *priv = dev_get_priv(dev);
+	uint32_t po;
+
+	po = readl(priv->base + REG_PO);
+	if (value)
+		po |= 1 << offset;
+	else
+		po &= ~(1 << offset);
+	writel(po, priv->base + REG_PO);
+	return 0;
+}
+
+static int eg20t_gpio_direction_input(struct udevice *dev, unsigned int offset)
+{
+	struct eg20t_gpio_priv *priv = dev_get_priv(dev);
+	uint32_t pm;
+
+	pm = readl(priv->base + REG_PM);
+	pm &= ~(1 << offset);
+	writel(pm, priv->base + REG_PM);
+	return 0;
+}
+
+static int eg20t_gpio_direction_output(struct udevice *dev, unsigned int offset,
+				       int value)
+{
+	struct eg20t_gpio_priv *priv = dev_get_priv(dev);
+	uint32_t pm;
+
+	pm = readl(priv->base + REG_PM);
+	pm |= 1 << offset;
+	writel(pm, priv->base + REG_PM);
+
+	return eg20t_gpio_set_value(dev, offset, value);
+}
+
+static int eg20t_gpio_get_function(struct udevice *dev, unsigned int offset)
+{
+	struct eg20t_gpio_priv *priv = dev_get_priv(dev);
+	uint32_t pm;
+
+	pm = readl(priv->base + REG_PM);
+
+	if ((pm >> offset) & 0x1)
+		return GPIOF_OUTPUT;
+
+	return GPIOF_INPUT;
+}
+
+static const struct dm_gpio_ops eg20t_gpio_ops = {
+	.direction_input	= eg20t_gpio_direction_input,
+	.direction_output	= eg20t_gpio_direction_output,
+	.get_value		= eg20t_gpio_get_value,
+	.set_value		= eg20t_gpio_set_value,
+	.get_function		= eg20t_gpio_get_function,
+};
+
+static int eg20t_gpio_probe(struct udevice *dev)
+{
+	struct eg20t_gpio_priv *priv = dev_get_priv(dev);
+	struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+
+	priv->base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_1, PCI_REGION_MEM);
+	if (!priv->base) {
+		debug("failed to map GPIO registers\n");
+		return -EINVAL;
+	}
+
+	uc_priv->gpio_count = 12;
+	uc_priv->bank_name = "eg20t";
+	return 0;
+}
+
+U_BOOT_DRIVER(eg20t_gpio) = {
+	.name	= "eg20t-gpio",
+	.id	= UCLASS_GPIO,
+	.probe	= eg20t_gpio_probe,
+	.priv_auto_alloc_size = sizeof(struct eg20t_gpio_priv),
+	.ops	= &eg20t_gpio_ops,
+};
+
+static struct pci_device_id eg20t_gpio_supported[] = {
+	{ PCI_VENDOR_ID_INTEL, 0x8803 },
+	{ },
+};
+
+U_BOOT_PCI_DEVICE(eg20t_gpio, eg20t_gpio_supported);
-- 
2.10.0



More information about the U-Boot mailing list