Message ID | 20200520104020.9013-3-hui.song_1@nxp.com |
---|---|
State | Accepted |
Commit | d5d6b548d950385cb66e1fa97ad5f6790bbca3ad |
Headers | show |
Series | [1/3] armv8: gpio: add gpio feature | expand |
>-----Original Message----- >From: U-Boot <u-boot-bounces@lists.denx.de> On Behalf Of Hui Song >Sent: Wednesday, May 20, 2020 4:10 PM >To: Jagdish Gediya <jagdish.gediya@nxp.com>; Priyanka Jain ><priyanka.jain@nxp.com>; hs@denx.de; jagan@amarulasolutions.com; >aford173@gmail.com; Alison Wang <alison.wang@nxp.com>; >jh80.chung@samsung.com; Pramod Kumar <pramod.kumar_1@nxp.com>; >Rajesh Bhagat <rajesh.bhagat@nxp.com>; Ruchika Gupta ><ruchika.gupta@nxp.com>; olteanv@gmail.com >Cc: Xiaobo Xie <xiaobo.xie@nxp.com>; Jiafei Pan <jiafei.pan@nxp.com>; u- >boot@lists.denx.de; Z.q. Hou <zhiqiang.hou@nxp.com>; Hui Song ><hui.song_1@nxp.com> >Subject: [PATCH 3/3] gpio: mpc8xxx: support fsl-layerscape platform. No '.' in subject > >From: "hui.song" <hui.song_1@nxp.com> > >Make the MPC8XXX gpio driver to support the fsl-layerscape. > >Signed-off-by: hui.song <hui.song_1@nxp.com> >--- > drivers/gpio/mpc8xxx_gpio.c | 108 +++++++++++++++++++++++++++++------- > 1 file changed, 87 insertions(+), 21 deletions(-) > >diff --git a/drivers/gpio/mpc8xxx_gpio.c b/drivers/gpio/mpc8xxx_gpio.c index >1dfd22522c..41bd2f8374 100644 >--- a/drivers/gpio/mpc8xxx_gpio.c >+++ b/drivers/gpio/mpc8xxx_gpio.c >@@ -6,12 +6,15 @@ > * based on arch/powerpc/include/asm/mpc85xx_gpio.h, which is > * > * Copyright 2010 eXMeritus, A Boeing Company >+ * Copyright 2020 NXP > */ > > #include <common.h> > #include <dm.h> > #include <mapmem.h> > #include <asm/gpio.h> >+#include <asm/io.h> >+#include <dm/of_access.h> > > struct ccsr_gpio { > u32 gpdir; >@@ -20,6 +23,7 @@ struct ccsr_gpio { > u32 gpier; > u32 gpimr; > u32 gpicr; >+ u32 gpibe; > }; > > struct mpc8xxx_gpio_data { >@@ -35,6 +39,7 @@ struct mpc8xxx_gpio_data { > */ > u32 dat_shadow; > ulong type; >+ bool little_endian; > }; > > enum { >@@ -47,33 +52,56 @@ inline u32 gpio_mask(uint gpio) > return (1U << (31 - (gpio))); > } > >-static inline u32 mpc8xxx_gpio_get_val(struct ccsr_gpio *base, u32 mask) >+static inline u32 mpc8xxx_gpio_get_val(struct udevice *dev, u32 mask) > { >- return in_be32(&base->gpdat) & mask; >+ struct mpc8xxx_gpio_data *data = dev_get_priv(dev); >+ >+ if (data->little_endian) >+ return in_le32(&data->base->gpdat) & mask; >+ else >+ return in_be32(&data->base->gpdat) & mask; > } > >-static inline u32 mpc8xxx_gpio_get_dir(struct ccsr_gpio *base, u32 mask) >+static inline u32 mpc8xxx_gpio_get_dir(struct udevice *dev, u32 mask) > { >- return in_be32(&base->gpdir) & mask; >+ struct mpc8xxx_gpio_data *data = dev_get_priv(dev); >+ >+ if (data->little_endian) >+ return in_le32(&data->base->gpdir) & mask; >+ else >+ return in_be32(&data->base->gpdir) & mask; > } > >-static inline int mpc8xxx_gpio_open_drain_val(struct ccsr_gpio *base, u32 >mask) >+static inline int mpc8xxx_gpio_open_drain_val(struct udevice *dev, u32 >+mask) > { >- return in_be32(&base->gpodr) & mask; >+ struct mpc8xxx_gpio_data *data = dev_get_priv(dev); >+ >+ if (data->little_endian) >+ return in_le32(&data->base->gpodr) & mask; >+ else >+ return in_be32(&data->base->gpodr) & mask; > } > >-static inline void mpc8xxx_gpio_open_drain_on(struct ccsr_gpio *base, u32 >+static inline void mpc8xxx_gpio_open_drain_on(struct udevice *dev, u32 > gpios) > { >+ struct mpc8xxx_gpio_data *data = dev_get_priv(dev); > /* GPODR register 1 -> open drain on */ >- setbits_be32(&base->gpodr, gpios); >+ if (data->little_endian) >+ setbits_le32(&data->base->gpodr, gpios); >+ else >+ setbits_be32(&data->base->gpodr, gpios); > } > >-static inline void mpc8xxx_gpio_open_drain_off(struct ccsr_gpio *base, >+static inline void mpc8xxx_gpio_open_drain_off(struct udevice *dev, > u32 gpios) > { >+ struct mpc8xxx_gpio_data *data = dev_get_priv(dev); > /* GPODR register 0 -> open drain off (actively driven) */ >- clrbits_be32(&base->gpodr, gpios); >+ if (data->little_endian) >+ clrbits_le32(&data->base->gpodr, gpios); >+ else >+ clrbits_be32(&data->base->gpodr, gpios); > } > > static int mpc8xxx_gpio_direction_input(struct udevice *dev, uint gpio) @@ - >82,7 +110,10 @@ static int mpc8xxx_gpio_direction_input(struct udevice >*dev, uint gpio) > u32 mask = gpio_mask(gpio); > > /* GPDIR register 0 -> input */ >- clrbits_be32(&data->base->gpdir, mask); >+ if (data->little_endian) >+ clrbits_le32(&data->base->gpdir, mask); >+ else >+ clrbits_be32(&data->base->gpdir, mask); > > return 0; > } >@@ -100,10 +131,20 @@ static int mpc8xxx_gpio_set_value(struct udevice >*dev, uint gpio, int value) > data->dat_shadow &= ~mask; > } > >- gpdir = in_be32(&base->gpdir); >+ if (data->little_endian) >+ gpdir = in_le32(&base->gpdir); >+ else >+ gpdir = in_be32(&base->gpdir); >+ > gpdir |= gpio_mask(gpio); >- out_be32(&base->gpdat, gpdir & data->dat_shadow); >- out_be32(&base->gpdir, gpdir); >+ >+ if (data->little_endian) { >+ out_le32(&base->gpdat, gpdir & data->dat_shadow); >+ out_le32(&base->gpdir, gpdir); >+ } else { >+ out_be32(&base->gpdat, gpdir & data->dat_shadow); >+ out_be32(&base->gpdir, gpdir); >+ } > > return 0; > } >@@ -124,21 +165,20 @@ static int mpc8xxx_gpio_get_value(struct udevice >*dev, uint gpio) { > struct mpc8xxx_gpio_data *data = dev_get_priv(dev); > >- if (!!mpc8xxx_gpio_get_dir(data->base, gpio_mask(gpio))) { >+ if (!!mpc8xxx_gpio_get_dir(dev, gpio_mask(gpio))) { > /* Output -> use shadowed value */ > return !!(data->dat_shadow & gpio_mask(gpio)); > } > > /* Input -> read value from GPDAT register */ >- return !!mpc8xxx_gpio_get_val(data->base, gpio_mask(gpio)); >+ return !!mpc8xxx_gpio_get_val(dev, gpio_mask(gpio)); > } > > static int mpc8xxx_gpio_get_function(struct udevice *dev, uint gpio) { >- struct mpc8xxx_gpio_data *data = dev_get_priv(dev); > int dir; > >- dir = !!mpc8xxx_gpio_get_dir(data->base, gpio_mask(gpio)); >+ dir = !!mpc8xxx_gpio_get_dir(dev, gpio_mask(gpio)); > return dir ? GPIOF_OUTPUT : GPIOF_INPUT; } > >@@ -146,14 +186,33 @@ static int mpc8xxx_gpio_get_function(struct udevice >*dev, uint gpio) static int mpc8xxx_gpio_ofdata_to_platdata(struct udevice >*dev) { > struct mpc8xxx_gpio_plat *plat = dev_get_platdata(dev); >+ struct mpc8xxx_gpio_data *data = dev_get_priv(dev); > fdt_addr_t addr; >- u32 reg[2]; >+ u32 i; >+ u32 reg[4]; >+ >+ if (ofnode_read_bool(dev->node, "little-endian")) >+ data->little_endian = true; >+ >+ if (data->little_endian) >+ dev_read_u32_array(dev, "reg", reg, 4); >+ else >+ dev_read_u32_array(dev, "reg", reg, 2); >+ >+ if (data->little_endian) { >+ for (i = 0; i < 2; i++) >+ reg[i] = be32_to_cpu(reg[i]); >+ } > >- dev_read_u32_array(dev, "reg", reg, 2); > addr = dev_translate_address(dev, reg); > > plat->addr = addr; >- plat->size = reg[1]; >+ >+ if (data->little_endian) >+ plat->size = reg[3]; >+ else >+ plat->size = reg[1]; >+ > plat->ngpios = dev_read_u32_default(dev, "ngpios", 32); > > return 0; >@@ -198,6 +257,13 @@ static int mpc8xxx_gpio_probe(struct udevice *dev) > if (!str) > return -ENOMEM; > >+ if (ofnode_device_is_compatible(dev->node, "fsl,qoriq-gpio")) { >+ unsigned long gpibe = data->addr + sizeof(struct ccsr_gpio) >+ - sizeof(u32); >+ >+ out_be32(gpibe, 0xffffffff); >+ } >+ > uc_priv->bank_name = str; > uc_priv->gpio_count = data->gpio_count; > >-- >2.17.1 Please fix below build error: powerpc: + gazerbeam +drivers/gpio/mpc8xxx_gpio.c: In function 'mpc8xxx_gpio_probe': +drivers/gpio/mpc8xxx_gpio.c:264:12: error: passing argument 1 of 'out_be32' makes pointer from integer without a cast [-Werror=int-conversion] + 264 | out_be32(gpibe, 0xffffffff); + | ^~~~~ + | | + | long unsigned int +In file included from arch/powerpc/include/asm/fsl_lbc.h:467, + from include/mpc83xx.h:10, + from arch/powerpc/include/asm/ppc.h:27, + from arch/powerpc/include/asm/u-boot.h:23, + from include/common.h:25, + from drivers/gpio/mpc8xxx_gpio.c:12: +arch/powerpc/include/asm/io.h:244:56: note: expected 'volatile unsigned int *' but argument is of type 'long unsigned int' + 244 | static inline void out_be32(volatile unsigned __iomem *addr, u32 val) + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~ +cc1: all warnings being treated as errors +make[2]: *** [drivers/gpio/mpc8xxx_gpio.o] Error 1 +make[1]: *** [drivers/gpio] Error 2 +make: *** [sub-make] Error 2 Regards Priyanka
diff --git a/drivers/gpio/mpc8xxx_gpio.c b/drivers/gpio/mpc8xxx_gpio.c index 1dfd22522c..41bd2f8374 100644 --- a/drivers/gpio/mpc8xxx_gpio.c +++ b/drivers/gpio/mpc8xxx_gpio.c @@ -6,12 +6,15 @@ * based on arch/powerpc/include/asm/mpc85xx_gpio.h, which is * * Copyright 2010 eXMeritus, A Boeing Company + * Copyright 2020 NXP */ #include <common.h> #include <dm.h> #include <mapmem.h> #include <asm/gpio.h> +#include <asm/io.h> +#include <dm/of_access.h> struct ccsr_gpio { u32 gpdir; @@ -20,6 +23,7 @@ struct ccsr_gpio { u32 gpier; u32 gpimr; u32 gpicr; + u32 gpibe; }; struct mpc8xxx_gpio_data { @@ -35,6 +39,7 @@ struct mpc8xxx_gpio_data { */ u32 dat_shadow; ulong type; + bool little_endian; }; enum { @@ -47,33 +52,56 @@ inline u32 gpio_mask(uint gpio) return (1U << (31 - (gpio))); } -static inline u32 mpc8xxx_gpio_get_val(struct ccsr_gpio *base, u32 mask) +static inline u32 mpc8xxx_gpio_get_val(struct udevice *dev, u32 mask) { - return in_be32(&base->gpdat) & mask; + struct mpc8xxx_gpio_data *data = dev_get_priv(dev); + + if (data->little_endian) + return in_le32(&data->base->gpdat) & mask; + else + return in_be32(&data->base->gpdat) & mask; } -static inline u32 mpc8xxx_gpio_get_dir(struct ccsr_gpio *base, u32 mask) +static inline u32 mpc8xxx_gpio_get_dir(struct udevice *dev, u32 mask) { - return in_be32(&base->gpdir) & mask; + struct mpc8xxx_gpio_data *data = dev_get_priv(dev); + + if (data->little_endian) + return in_le32(&data->base->gpdir) & mask; + else + return in_be32(&data->base->gpdir) & mask; } -static inline int mpc8xxx_gpio_open_drain_val(struct ccsr_gpio *base, u32 mask) +static inline int mpc8xxx_gpio_open_drain_val(struct udevice *dev, u32 mask) { - return in_be32(&base->gpodr) & mask; + struct mpc8xxx_gpio_data *data = dev_get_priv(dev); + + if (data->little_endian) + return in_le32(&data->base->gpodr) & mask; + else + return in_be32(&data->base->gpodr) & mask; } -static inline void mpc8xxx_gpio_open_drain_on(struct ccsr_gpio *base, u32 +static inline void mpc8xxx_gpio_open_drain_on(struct udevice *dev, u32 gpios) { + struct mpc8xxx_gpio_data *data = dev_get_priv(dev); /* GPODR register 1 -> open drain on */ - setbits_be32(&base->gpodr, gpios); + if (data->little_endian) + setbits_le32(&data->base->gpodr, gpios); + else + setbits_be32(&data->base->gpodr, gpios); } -static inline void mpc8xxx_gpio_open_drain_off(struct ccsr_gpio *base, +static inline void mpc8xxx_gpio_open_drain_off(struct udevice *dev, u32 gpios) { + struct mpc8xxx_gpio_data *data = dev_get_priv(dev); /* GPODR register 0 -> open drain off (actively driven) */ - clrbits_be32(&base->gpodr, gpios); + if (data->little_endian) + clrbits_le32(&data->base->gpodr, gpios); + else + clrbits_be32(&data->base->gpodr, gpios); } static int mpc8xxx_gpio_direction_input(struct udevice *dev, uint gpio) @@ -82,7 +110,10 @@ static int mpc8xxx_gpio_direction_input(struct udevice *dev, uint gpio) u32 mask = gpio_mask(gpio); /* GPDIR register 0 -> input */ - clrbits_be32(&data->base->gpdir, mask); + if (data->little_endian) + clrbits_le32(&data->base->gpdir, mask); + else + clrbits_be32(&data->base->gpdir, mask); return 0; } @@ -100,10 +131,20 @@ static int mpc8xxx_gpio_set_value(struct udevice *dev, uint gpio, int value) data->dat_shadow &= ~mask; } - gpdir = in_be32(&base->gpdir); + if (data->little_endian) + gpdir = in_le32(&base->gpdir); + else + gpdir = in_be32(&base->gpdir); + gpdir |= gpio_mask(gpio); - out_be32(&base->gpdat, gpdir & data->dat_shadow); - out_be32(&base->gpdir, gpdir); + + if (data->little_endian) { + out_le32(&base->gpdat, gpdir & data->dat_shadow); + out_le32(&base->gpdir, gpdir); + } else { + out_be32(&base->gpdat, gpdir & data->dat_shadow); + out_be32(&base->gpdir, gpdir); + } return 0; } @@ -124,21 +165,20 @@ static int mpc8xxx_gpio_get_value(struct udevice *dev, uint gpio) { struct mpc8xxx_gpio_data *data = dev_get_priv(dev); - if (!!mpc8xxx_gpio_get_dir(data->base, gpio_mask(gpio))) { + if (!!mpc8xxx_gpio_get_dir(dev, gpio_mask(gpio))) { /* Output -> use shadowed value */ return !!(data->dat_shadow & gpio_mask(gpio)); } /* Input -> read value from GPDAT register */ - return !!mpc8xxx_gpio_get_val(data->base, gpio_mask(gpio)); + return !!mpc8xxx_gpio_get_val(dev, gpio_mask(gpio)); } static int mpc8xxx_gpio_get_function(struct udevice *dev, uint gpio) { - struct mpc8xxx_gpio_data *data = dev_get_priv(dev); int dir; - dir = !!mpc8xxx_gpio_get_dir(data->base, gpio_mask(gpio)); + dir = !!mpc8xxx_gpio_get_dir(dev, gpio_mask(gpio)); return dir ? GPIOF_OUTPUT : GPIOF_INPUT; } @@ -146,14 +186,33 @@ static int mpc8xxx_gpio_get_function(struct udevice *dev, uint gpio) static int mpc8xxx_gpio_ofdata_to_platdata(struct udevice *dev) { struct mpc8xxx_gpio_plat *plat = dev_get_platdata(dev); + struct mpc8xxx_gpio_data *data = dev_get_priv(dev); fdt_addr_t addr; - u32 reg[2]; + u32 i; + u32 reg[4]; + + if (ofnode_read_bool(dev->node, "little-endian")) + data->little_endian = true; + + if (data->little_endian) + dev_read_u32_array(dev, "reg", reg, 4); + else + dev_read_u32_array(dev, "reg", reg, 2); + + if (data->little_endian) { + for (i = 0; i < 2; i++) + reg[i] = be32_to_cpu(reg[i]); + } - dev_read_u32_array(dev, "reg", reg, 2); addr = dev_translate_address(dev, reg); plat->addr = addr; - plat->size = reg[1]; + + if (data->little_endian) + plat->size = reg[3]; + else + plat->size = reg[1]; + plat->ngpios = dev_read_u32_default(dev, "ngpios", 32); return 0; @@ -198,6 +257,13 @@ static int mpc8xxx_gpio_probe(struct udevice *dev) if (!str) return -ENOMEM; + if (ofnode_device_is_compatible(dev->node, "fsl,qoriq-gpio")) { + unsigned long gpibe = data->addr + sizeof(struct ccsr_gpio) + - sizeof(u32); + + out_be32(gpibe, 0xffffffff); + } + uc_priv->bank_name = str; uc_priv->gpio_count = data->gpio_count;