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

2016-09-28 Thread Bin Meng
On Tue, Sep 27, 2016 at 2:22 PM, Bin Meng  wrote:
> Hi Paul,
>
> On Tue, Sep 27, 2016 at 2:29 AM, Paul Burton  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 
>>
>> ---
>>
>>  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 000..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 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +
>> +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,
>> 

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

2016-09-27 Thread Simon Glass
Hi Paul,

On 27 September 2016 at 02:21, Paul Burton  wrote:
> On Monday, 26 September 2016 18:35:32 BST Simon Glass wrote:
>
>> > +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,
>
>>
>
>> How about using a struct?
>
>
>
> Hi Simon,
>
>
>
> Interesting - I was told over here[1] that using structs for register access
> was "deprecated".
>
>
>
> [1] https://www.mail-archive.com/u-boot@lists.denx.de/msg220500.html
>
>
>
> ...so I actually converted the driver away from that style before
> submitting. Yet both yourself & Bin have suggested it - shall I take it that
> it's not deprecated after all?

Well I try to use it when possible, as does Bin. It reads better and
we may as well use the features of C. It can't be used if register
offsets differ (e.g. a driver needs to deal with registers being 4
bytes apart on one machine and 8 on another). But in general I think
it is preferable to offsets.

Regards,
Simon
___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


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

2016-09-27 Thread Paul Burton
On Monday, 26 September 2016 18:35:32 BST Simon Glass wrote:
> > +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,
> 
> How about using a struct?

Hi Simon,

Interesting - I was told over here[1] that using structs for register access 
was "deprecated".

[1] https://www.mail-archive.com/u-boot@lists.denx.de/msg220500.html[1]

...so I actually converted the driver away from that style before submitting. 
Yet both 
yourself & Bin have suggested it - shall I take it that it's not deprecated 
after all?

Thanks,
Paul


[1] https://www.mail-archive.com/u-boot@lists.denx.de/msg220500.html


signature.asc
Description: This is a digitally signed message part.
___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


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

2016-09-27 Thread Bin Meng
Hi Paul,

On Tue, Sep 27, 2016 at 2:29 AM, Paul Burton  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 
>
> ---
>
>  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 000..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 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +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 = 

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

2016-09-26 Thread Simon Glass
Hi Paul,

On 26 September 2016 at 12:29, Paul Burton  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 
>
> ---
>
>  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.

Can you add a few more details? How many GPIOs? Bank organisation?
Pull-up/down support?

> +
>  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 000..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 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +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,

How about using 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);
> +   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);

clrbits_le32(ADDR, 1 << OFFSET);

> +   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);

setbits_le32()

> +
> +   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;

Can it have pins which are GPIOF_FUNC?

> +}
> +
> +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 = 

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

2016-09-26 Thread Paul Burton
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 

---

 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 000..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 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+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= _gpio_ops,