diff options
author | Stefan Agner <stefan.agner@toradex.com> | 2015-04-23 17:19:58 +0200 |
---|---|---|
committer | Stefan Agner <stefan.agner@toradex.com> | 2015-04-23 17:19:58 +0200 |
commit | 769c0f8d9c7a98d77855aa7efd8ec21a2f125924 (patch) | |
tree | c81bfe80a1e201f9f38587278594ad638e65da1d /drivers | |
parent | f51c0c368c45a55f3eb41b1fa4206b87165f8661 (diff) | |
parent | 60f63388e38a305ae60d5502e20b9f16d1f78f83 (diff) |
Merge branch '2015.04-toradex-next-gpio' into 2015.04-toradex-next
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpio/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-uclass.c | 1 | ||||
-rw-r--r-- | drivers/gpio/vybrid_gpio.c | 122 |
3 files changed, 124 insertions, 0 deletions
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 85f71c5d4a7..62c73042b76 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -42,3 +42,4 @@ obj-$(CONFIG_TCA642X) += tca642x.o oby-$(CONFIG_SX151X) += sx151x.o obj-$(CONFIG_SUNXI_GPIO) += sunxi_gpio.o obj-$(CONFIG_LPC32XX_GPIO) += lpc32xx_gpio.o +obj-$(CONFIG_VYBRID_GPIO) += vybrid_gpio.o diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index a69bbd2002e..27778b4fccc 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -717,6 +717,7 @@ static int gpio_pre_remove(struct udevice *dev) UCLASS_DRIVER(gpio) = { .id = UCLASS_GPIO, .name = "gpio", + .flags = DM_UC_FLAG_SEQ_ALIAS, .post_probe = gpio_post_probe, .pre_remove = gpio_pre_remove, .per_device_auto_alloc_size = sizeof(struct gpio_dev_priv), diff --git a/drivers/gpio/vybrid_gpio.c b/drivers/gpio/vybrid_gpio.c new file mode 100644 index 00000000000..9fa0762b7cc --- /dev/null +++ b/drivers/gpio/vybrid_gpio.c @@ -0,0 +1,122 @@ +/* + * 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 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, +}; + +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->uclass_priv; + + uc_priv->bank_name = "GPIO"; + 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; + + plat = calloc(1, sizeof(*plat)); + if (!plat) + return -ENOMEM; + + plat->base = base_addr; + plat->chip = dev->req_seq; + dev->platdata = plat; + + return 0; +} + +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, +}; |