
On Tue, Sep 27, 2016 at 2:22 PM, Bin Meng bmeng.cn@gmail.com wrote:
Hi Paul,
On Tue, Sep 27, 2016 at 2:29 AM, Paul Burton paul.burton@imgtec.com wrote:
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@imgtec.com
drivers/gpio/Kconfig | 8 +++ drivers/gpio/Makefile | 1 + drivers/gpio/eg20t-gpio.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++
Please use eg20t_gpio.c as the filename, like others do.
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,
+};
Please use a struct.
+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);
nits: need a blank line.
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);
nits: need a blank line.
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";
nits: need a blank line.
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);
Other than the above comments,
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Tested on Crown Bay Tested-by: Bin Meng bmeng.cn@gmail.com