Message ID | 1433164045-9987-3-git-send-email-bhuvanchandra.dv@toradex.com |
---|---|
State | Awaiting Upstream |
Delegated to: | Stefano Babic |
Headers | show |
On 01/06/2015 15:07, Bhuvanchandra DV wrote: > Add GPIO driver support to Freescale VF610 > > Signed-off-by: Bhuvanchandra DV <bhuvanchandra.dv@toradex.com> > --- > arch/arm/imx-common/iomux-v3.c | 26 +++++ > arch/arm/include/asm/arch-vf610/gpio.h | 29 +++++ > arch/arm/include/asm/arch-vf610/imx-regs.h | 5 + > arch/arm/include/asm/imx-common/iomux-v3.h | 6 + > drivers/gpio/Kconfig | 7 ++ > drivers/gpio/Makefile | 1 + > drivers/gpio/vybrid_gpio.c | 169 +++++++++++++++++++++++++++++ > 7 files changed, 243 insertions(+) > create mode 100644 arch/arm/include/asm/arch-vf610/gpio.h > create mode 100644 drivers/gpio/vybrid_gpio.c > > diff --git a/arch/arm/imx-common/iomux-v3.c b/arch/arm/imx-common/iomux-v3.c > index e88e6e2..7fb23dd 100644 > --- a/arch/arm/imx-common/iomux-v3.c > +++ b/arch/arm/imx-common/iomux-v3.c > @@ -92,3 +92,29 @@ void imx_iomux_set_gpr_register(int group, int start_bit, > reg |= (value << start_bit); > writel(reg, base + group * 4); > } > + > +#ifdef CONFIG_IOMUX_SHARE_CONF_REG > +void imx_iomux_gpio_set_direction(unsigned int gpio, > + unsigned int direction) > +{ > + u32 reg; > + /* > + * Only on Vybrid the input/output buffer enable flags > + * are part of the shared mux/conf register. > + */ > + reg = readl(base + (gpio << 2)); > + > + if (direction) > + reg |= 0x2; > + else > + reg &= ~0x2; > + > + writel(reg, base + (gpio << 2)); > +} > + > +void imx_iomux_gpio_get_function(unsigned int gpio, u32 *gpio_state) > +{ > + *gpio_state = readl(base + (gpio << 2)) & > + ((0X07 << PAD_MUX_MODE_SHIFT) | PAD_CTL_OBE_IBE_ENABLE); > +} > +#endif > diff --git a/arch/arm/include/asm/arch-vf610/gpio.h b/arch/arm/include/asm/arch-vf610/gpio.h > new file mode 100644 > index 0000000..622b8f0 > --- /dev/null > +++ b/arch/arm/include/asm/arch-vf610/gpio.h > @@ -0,0 +1,29 @@ > +/* > + * Copyright (C) 2015 > + * Bhuvanchandra DV, Toradex, Inc. > + * > + * SPDX-License-Identifier: GPL-2.0 > + */ > + > +#ifndef __ASM_ARCH_VF610_GPIO_H > +#define __ASM_ARCH_VF610_GPIO_H > + > +#define VYBRID_GPIO_COUNT 32 > +#define VF610_GPIO_DIRECTION_IN 0x0 > +#define VF610_GPIO_DIRECTION_OUT 0x1 > + > +/* GPIO registers */ > +struct vybrid_gpio_regs { > + u32 gpio_pdor; > + u32 gpio_psor; > + u32 gpio_pcor; > + u32 gpio_ptor; > + u32 gpio_pdir; > +}; > + > +struct vybrid_gpio_platdata { > + unsigned int chip; > + u32 base; > + const char *port_name; > +}; > +#endif /* __ASM_ARCH_VF610_GPIO_H */ > diff --git a/arch/arm/include/asm/arch-vf610/imx-regs.h b/arch/arm/include/asm/arch-vf610/imx-regs.h > index 2021981..7df3b1e 100644 > --- a/arch/arm/include/asm/arch-vf610/imx-regs.h > +++ b/arch/arm/include/asm/arch-vf610/imx-regs.h > @@ -81,6 +81,11 @@ > #define VREG_DIG_BASE_ADDR (AIPS0_BASE_ADDR + 0x0006D000) > #define SRC_BASE_ADDR (AIPS0_BASE_ADDR + 0x0006E000) > #define CMU_BASE_ADDR (AIPS0_BASE_ADDR + 0x0006F000) > +#define GPIO0_BASE_ADDR (AIPS0_BASE_ADDR + 0x000FF000) > +#define GPIO1_BASE_ADDR (AIPS0_BASE_ADDR + 0x000FF040) > +#define GPIO2_BASE_ADDR (AIPS0_BASE_ADDR + 0x000FF080) > +#define GPIO3_BASE_ADDR (AIPS0_BASE_ADDR + 0x000FF0C0) > +#define GPIO4_BASE_ADDR (AIPS0_BASE_ADDR + 0x000FF100) > > /* AIPS 1 */ > #define OCOTP_BASE_ADDR (AIPS1_BASE_ADDR + 0x00025000) > diff --git a/arch/arm/include/asm/imx-common/iomux-v3.h b/arch/arm/include/asm/imx-common/iomux-v3.h > index e0a49be..2581019 100644 > --- a/arch/arm/include/asm/imx-common/iomux-v3.h > +++ b/arch/arm/include/asm/imx-common/iomux-v3.h > @@ -187,6 +187,12 @@ void imx_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t const *pad_list, > */ > void imx_iomux_set_gpr_register(int group, int start_bit, > int num_bits, int value); > +#ifdef CONFIG_IOMUX_SHARE_CONF_REG > +void imx_iomux_gpio_set_direction(unsigned int gpio, > + unsigned int direction); > +void imx_iomux_gpio_get_function(unsigned int gpio, > + u32 *gpio_state); > +#endif > > /* macros for declaring and using pinmux array */ > #if defined(CONFIG_MX6QDL) > diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig > index 0840a30..0c43777 100644 > --- a/drivers/gpio/Kconfig > +++ b/drivers/gpio/Kconfig > @@ -35,3 +35,10 @@ config SANDBOX_GPIO_COUNT > are specified using the device tree. But you can also have a number > of 'anonymous' GPIOs that do not belong to any device or bank. > Select a suitable value depending on your needs. > + > +config VYBRID_GPIO > + bool "Vybrid GPIO driver" > + depends on DM > + default n > + help > + Say yes here to support Vybrid vf610 GPIOs. > diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile > index ba9efe8..5864850 100644 > --- a/drivers/gpio/Makefile > +++ b/drivers/gpio/Makefile > @@ -45,3 +45,4 @@ obj-$(CONFIG_SUNXI_GPIO) += sunxi_gpio.o > obj-$(CONFIG_LPC32XX_GPIO) += lpc32xx_gpio.o > obj-$(CONFIG_STM32_GPIO) += stm32_gpio.o > obj-$(CONFIG_ZYNQ_GPIO) += zynq_gpio.o > +obj-$(CONFIG_VYBRID_GPIO) += vybrid_gpio.o > diff --git a/drivers/gpio/vybrid_gpio.c b/drivers/gpio/vybrid_gpio.c > new file mode 100644 > index 0000000..6eaf0a9 > --- /dev/null > +++ b/drivers/gpio/vybrid_gpio.c > @@ -0,0 +1,169 @@ > +/* > + * Copyright (C) 2015 > + * Bhuvanchandra DV, Toradex, Inc. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include <common.h> > +#include <dm.h> > +#include <errno.h> > +#include <fdtdec.h> > +#include <asm/gpio.h> > +#include <asm/imx-common/iomux-v3.h> > +#include <asm/io.h> > +#include <malloc.h> > + > +DECLARE_GLOBAL_DATA_PTR; > + > +struct vybrid_gpios { > + unsigned int chip; > + struct vybrid_gpio_regs *reg; > +}; > + > +static int vybrid_gpio_direction_input(struct udevice *dev, unsigned gpio) > +{ > + const struct vybrid_gpios *gpios = dev_get_priv(dev); > + > + gpio = gpio + (gpios->chip * VYBRID_GPIO_COUNT); > + imx_iomux_gpio_set_direction(gpio, VF610_GPIO_DIRECTION_IN); > + > + return 0; > +} > + > +static int vybrid_gpio_direction_output(struct udevice *dev, unsigned gpio, > + int value) > +{ > + const struct vybrid_gpios *gpios = dev_get_priv(dev); > + > + gpio = gpio + (gpios->chip * VYBRID_GPIO_COUNT); > + gpio_set_value(gpio, value); > + imx_iomux_gpio_set_direction(gpio, VF610_GPIO_DIRECTION_OUT); > + > + return 0; > +} > + > +static int vybrid_gpio_get_value(struct udevice *dev, unsigned gpio) > +{ > + const struct vybrid_gpios *gpios = dev_get_priv(dev); > + > + return ((readl(&gpios->reg->gpio_pdir) & (1 << gpio))) ? 1 : 0; > +} > + > +static int vybrid_gpio_set_value(struct udevice *dev, unsigned gpio, > + int value) > +{ > + const struct vybrid_gpios *gpios = dev_get_priv(dev); > + if (value) > + writel((1 << gpio), &gpios->reg->gpio_psor); > + else > + writel((1 << gpio), &gpios->reg->gpio_pcor); > + > + return 0; > +} > + > +static int vybrid_gpio_get_function(struct udevice *dev, unsigned gpio) > +{ > + const struct vybrid_gpios *gpios = dev_get_priv(dev); > + u32 g_state = 0; > + > + gpio = gpio + (gpios->chip * VYBRID_GPIO_COUNT); > + > + imx_iomux_gpio_get_function(gpio, &g_state); > + > + if (((g_state & (0x07 << PAD_MUX_MODE_SHIFT)) >> PAD_MUX_MODE_SHIFT) > 0) Fixed by applying: WARNING: line over 80 characters #274: FILE: drivers/gpio/vybrid_gpio.c:74: + if (((g_state & (0x07 << PAD_MUX_MODE_SHIFT)) >> PAD_MUX_MODE_SHIFT) > 0) Applied to u-boot-imx, thanks ! Best regards, Stefano Babic
diff --git a/arch/arm/imx-common/iomux-v3.c b/arch/arm/imx-common/iomux-v3.c index e88e6e2..7fb23dd 100644 --- a/arch/arm/imx-common/iomux-v3.c +++ b/arch/arm/imx-common/iomux-v3.c @@ -92,3 +92,29 @@ void imx_iomux_set_gpr_register(int group, int start_bit, reg |= (value << start_bit); writel(reg, base + group * 4); } + +#ifdef CONFIG_IOMUX_SHARE_CONF_REG +void imx_iomux_gpio_set_direction(unsigned int gpio, + unsigned int direction) +{ + u32 reg; + /* + * Only on Vybrid the input/output buffer enable flags + * are part of the shared mux/conf register. + */ + reg = readl(base + (gpio << 2)); + + if (direction) + reg |= 0x2; + else + reg &= ~0x2; + + writel(reg, base + (gpio << 2)); +} + +void imx_iomux_gpio_get_function(unsigned int gpio, u32 *gpio_state) +{ + *gpio_state = readl(base + (gpio << 2)) & + ((0X07 << PAD_MUX_MODE_SHIFT) | PAD_CTL_OBE_IBE_ENABLE); +} +#endif diff --git a/arch/arm/include/asm/arch-vf610/gpio.h b/arch/arm/include/asm/arch-vf610/gpio.h new file mode 100644 index 0000000..622b8f0 --- /dev/null +++ b/arch/arm/include/asm/arch-vf610/gpio.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2015 + * Bhuvanchandra DV, Toradex, Inc. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef __ASM_ARCH_VF610_GPIO_H +#define __ASM_ARCH_VF610_GPIO_H + +#define VYBRID_GPIO_COUNT 32 +#define VF610_GPIO_DIRECTION_IN 0x0 +#define VF610_GPIO_DIRECTION_OUT 0x1 + +/* GPIO registers */ +struct vybrid_gpio_regs { + u32 gpio_pdor; + u32 gpio_psor; + u32 gpio_pcor; + u32 gpio_ptor; + u32 gpio_pdir; +}; + +struct vybrid_gpio_platdata { + unsigned int chip; + u32 base; + const char *port_name; +}; +#endif /* __ASM_ARCH_VF610_GPIO_H */ diff --git a/arch/arm/include/asm/arch-vf610/imx-regs.h b/arch/arm/include/asm/arch-vf610/imx-regs.h index 2021981..7df3b1e 100644 --- a/arch/arm/include/asm/arch-vf610/imx-regs.h +++ b/arch/arm/include/asm/arch-vf610/imx-regs.h @@ -81,6 +81,11 @@ #define VREG_DIG_BASE_ADDR (AIPS0_BASE_ADDR + 0x0006D000) #define SRC_BASE_ADDR (AIPS0_BASE_ADDR + 0x0006E000) #define CMU_BASE_ADDR (AIPS0_BASE_ADDR + 0x0006F000) +#define GPIO0_BASE_ADDR (AIPS0_BASE_ADDR + 0x000FF000) +#define GPIO1_BASE_ADDR (AIPS0_BASE_ADDR + 0x000FF040) +#define GPIO2_BASE_ADDR (AIPS0_BASE_ADDR + 0x000FF080) +#define GPIO3_BASE_ADDR (AIPS0_BASE_ADDR + 0x000FF0C0) +#define GPIO4_BASE_ADDR (AIPS0_BASE_ADDR + 0x000FF100) /* AIPS 1 */ #define OCOTP_BASE_ADDR (AIPS1_BASE_ADDR + 0x00025000) diff --git a/arch/arm/include/asm/imx-common/iomux-v3.h b/arch/arm/include/asm/imx-common/iomux-v3.h index e0a49be..2581019 100644 --- a/arch/arm/include/asm/imx-common/iomux-v3.h +++ b/arch/arm/include/asm/imx-common/iomux-v3.h @@ -187,6 +187,12 @@ void imx_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t const *pad_list, */ void imx_iomux_set_gpr_register(int group, int start_bit, int num_bits, int value); +#ifdef CONFIG_IOMUX_SHARE_CONF_REG +void imx_iomux_gpio_set_direction(unsigned int gpio, + unsigned int direction); +void imx_iomux_gpio_get_function(unsigned int gpio, + u32 *gpio_state); +#endif /* macros for declaring and using pinmux array */ #if defined(CONFIG_MX6QDL) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 0840a30..0c43777 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -35,3 +35,10 @@ config SANDBOX_GPIO_COUNT are specified using the device tree. But you can also have a number of 'anonymous' GPIOs that do not belong to any device or bank. Select a suitable value depending on your needs. + +config VYBRID_GPIO + bool "Vybrid GPIO driver" + depends on DM + default n + help + Say yes here to support Vybrid vf610 GPIOs. diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index ba9efe8..5864850 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -45,3 +45,4 @@ obj-$(CONFIG_SUNXI_GPIO) += sunxi_gpio.o obj-$(CONFIG_LPC32XX_GPIO) += lpc32xx_gpio.o obj-$(CONFIG_STM32_GPIO) += stm32_gpio.o obj-$(CONFIG_ZYNQ_GPIO) += zynq_gpio.o +obj-$(CONFIG_VYBRID_GPIO) += vybrid_gpio.o diff --git a/drivers/gpio/vybrid_gpio.c b/drivers/gpio/vybrid_gpio.c new file mode 100644 index 0000000..6eaf0a9 --- /dev/null +++ b/drivers/gpio/vybrid_gpio.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2015 + * Bhuvanchandra DV, Toradex, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <fdtdec.h> +#include <asm/gpio.h> +#include <asm/imx-common/iomux-v3.h> +#include <asm/io.h> +#include <malloc.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct vybrid_gpios { + unsigned int chip; + struct vybrid_gpio_regs *reg; +}; + +static int vybrid_gpio_direction_input(struct udevice *dev, unsigned gpio) +{ + const struct vybrid_gpios *gpios = dev_get_priv(dev); + + gpio = gpio + (gpios->chip * VYBRID_GPIO_COUNT); + imx_iomux_gpio_set_direction(gpio, VF610_GPIO_DIRECTION_IN); + + return 0; +} + +static int vybrid_gpio_direction_output(struct udevice *dev, unsigned gpio, + int value) +{ + const struct vybrid_gpios *gpios = dev_get_priv(dev); + + gpio = gpio + (gpios->chip * VYBRID_GPIO_COUNT); + gpio_set_value(gpio, value); + imx_iomux_gpio_set_direction(gpio, VF610_GPIO_DIRECTION_OUT); + + return 0; +} + +static int vybrid_gpio_get_value(struct udevice *dev, unsigned gpio) +{ + const struct vybrid_gpios *gpios = dev_get_priv(dev); + + return ((readl(&gpios->reg->gpio_pdir) & (1 << gpio))) ? 1 : 0; +} + +static int vybrid_gpio_set_value(struct udevice *dev, unsigned gpio, + int value) +{ + const struct vybrid_gpios *gpios = dev_get_priv(dev); + if (value) + writel((1 << gpio), &gpios->reg->gpio_psor); + else + writel((1 << gpio), &gpios->reg->gpio_pcor); + + return 0; +} + +static int vybrid_gpio_get_function(struct udevice *dev, unsigned gpio) +{ + const struct vybrid_gpios *gpios = dev_get_priv(dev); + u32 g_state = 0; + + gpio = gpio + (gpios->chip * VYBRID_GPIO_COUNT); + + imx_iomux_gpio_get_function(gpio, &g_state); + + if (((g_state & (0x07 << PAD_MUX_MODE_SHIFT)) >> PAD_MUX_MODE_SHIFT) > 0) + return GPIOF_FUNC; + if (g_state & PAD_CTL_OBE_ENABLE) + return GPIOF_OUTPUT; + if (g_state & PAD_CTL_IBE_ENABLE) + return GPIOF_INPUT; + if (!(g_state & PAD_CTL_OBE_IBE_ENABLE)) + return GPIOF_UNUSED; + + return GPIOF_UNKNOWN; +} + +static const struct dm_gpio_ops gpio_vybrid_ops = { + .direction_input = vybrid_gpio_direction_input, + .direction_output = vybrid_gpio_direction_output, + .get_value = vybrid_gpio_get_value, + .set_value = vybrid_gpio_set_value, + .get_function = vybrid_gpio_get_function, +}; + +static int vybrid_gpio_probe(struct udevice *dev) +{ + struct vybrid_gpios *gpios = dev_get_priv(dev); + struct vybrid_gpio_platdata *plat = dev_get_platdata(dev); + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + + uc_priv->bank_name = plat->port_name; + uc_priv->gpio_count = VYBRID_GPIO_COUNT; + gpios->reg = (struct vybrid_gpio_regs *)plat->base; + gpios->chip = plat->chip; + + return 0; +} + +static int vybrid_gpio_bind(struct udevice *dev) +{ + struct vybrid_gpio_platdata *plat = dev->platdata; + fdt_addr_t base_addr; + + if (plat) + return 0; + + base_addr = dev_get_addr(dev); + if (base_addr == FDT_ADDR_T_NONE) + return -ENODEV; + + /* + * TODO: + * When every board is converted to driver model and DT is + * supported, this can be done by auto-alloc feature, but + * not using calloc to alloc memory for platdata. + */ + plat = calloc(1, sizeof(*plat)); + if (!plat) + return -ENOMEM; + + plat->base = base_addr; + plat->chip = dev->req_seq; + plat->port_name = fdt_get_name(gd->fdt_blob, dev->of_offset, NULL); + dev->platdata = plat; + + return 0; +} + +#ifndef CONFIG_OF_CONTROL +static const struct vybrid_gpio_platdata vybrid_gpio[] = { + {0, GPIO0_BASE_ADDR, "GPIO0 "}, + {1, GPIO1_BASE_ADDR, "GPIO1 "}, + {2, GPIO2_BASE_ADDR, "GPIO2 "}, + {3, GPIO3_BASE_ADDR, "GPIO3 "}, + {4, GPIO4_BASE_ADDR, "GPIO4 "}, +}; + +U_BOOT_DEVICES(vybrid_gpio) = { + { "gpio_vybrid", &vybrid_gpio[0] }, + { "gpio_vybrid", &vybrid_gpio[1] }, + { "gpio_vybrid", &vybrid_gpio[2] }, + { "gpio_vybrid", &vybrid_gpio[3] }, + { "gpio_vybrid", &vybrid_gpio[4] }, +}; +#endif + +static const struct udevice_id vybrid_gpio_ids[] = { + { .compatible = "fsl,vf610-gpio" }, + { } +}; + +U_BOOT_DRIVER(gpio_vybrid) = { + .name = "gpio_vybrid", + .id = UCLASS_GPIO, + .ops = &gpio_vybrid_ops, + .probe = vybrid_gpio_probe, + .priv_auto_alloc_size = sizeof(struct vybrid_gpios), + .of_match = vybrid_gpio_ids, + .bind = vybrid_gpio_bind, +};
Add GPIO driver support to Freescale VF610 Signed-off-by: Bhuvanchandra DV <bhuvanchandra.dv@toradex.com> --- arch/arm/imx-common/iomux-v3.c | 26 +++++ arch/arm/include/asm/arch-vf610/gpio.h | 29 +++++ arch/arm/include/asm/arch-vf610/imx-regs.h | 5 + arch/arm/include/asm/imx-common/iomux-v3.h | 6 + drivers/gpio/Kconfig | 7 ++ drivers/gpio/Makefile | 1 + drivers/gpio/vybrid_gpio.c | 169 +++++++++++++++++++++++++++++ 7 files changed, 243 insertions(+) create mode 100644 arch/arm/include/asm/arch-vf610/gpio.h create mode 100644 drivers/gpio/vybrid_gpio.c