summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Agner <stefan.agner@toradex.com>2015-04-23 17:19:58 +0200
committerStefan Agner <stefan.agner@toradex.com>2015-04-23 17:19:58 +0200
commit769c0f8d9c7a98d77855aa7efd8ec21a2f125924 (patch)
treec81bfe80a1e201f9f38587278594ad638e65da1d
parentf51c0c368c45a55f3eb41b1fa4206b87165f8661 (diff)
parent60f63388e38a305ae60d5502e20b9f16d1f78f83 (diff)
Merge branch '2015.04-toradex-next-gpio' into 2015.04-toradex-next
-rw-r--r--arch/arm/imx-common/iomux-v3.c19
-rw-r--r--arch/arm/include/asm/arch-vf610/gpio.h28
-rw-r--r--arch/arm/include/asm/arch-vf610/imx-regs.h5
-rw-r--r--arch/arm/include/asm/arch-vf610/iomux-vf610.h13
-rw-r--r--arch/arm/include/asm/imx-common/iomux-v3.h2
-rw-r--r--board/toradex/colibri_vf/colibri_vf.c44
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-uclass.c1
-rw-r--r--drivers/gpio/vybrid_gpio.c122
-rw-r--r--include/configs/colibri_vf.h8
10 files changed, 243 insertions, 0 deletions
diff --git a/arch/arm/imx-common/iomux-v3.c b/arch/arm/imx-common/iomux-v3.c
index e88e6e2a98..22c536e0c3 100644
--- a/arch/arm/imx-common/iomux-v3.c
+++ b/arch/arm/imx-common/iomux-v3.c
@@ -92,3 +92,22 @@ 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)));
+}
+#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 0000000000..57d50c3b01
--- /dev/null
+++ b/arch/arm/include/asm/arch-vf610/gpio.h
@@ -0,0 +1,28 @@
+/*
+ * 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;
+};
+#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 512bc1fdb5..5ca3abba58 100644
--- a/arch/arm/include/asm/arch-vf610/imx-regs.h
+++ b/arch/arm/include/asm/arch-vf610/imx-regs.h
@@ -82,6 +82,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/arch-vf610/iomux-vf610.h b/arch/arm/include/asm/arch-vf610/iomux-vf610.h
index 6d0f817f12..d9257ae599 100644
--- a/arch/arm/include/asm/arch-vf610/iomux-vf610.h
+++ b/arch/arm/include/asm/arch-vf610/iomux-vf610.h
@@ -35,13 +35,26 @@
#define VF610_DCU_PAD_CTRL (PAD_CTL_SPEED_MED | PAD_CTL_SRE | \
PAD_CTL_DSE_37ohm | PAD_CTL_OBE_ENABLE)
+#define VF610_GPIO_PAD_CTRL (PAD_CTL_SPEED_MED | PAD_CTL_DSE_50ohm | \
+ PAD_CTL_PUS_47K_UP | PAD_CTL_IBE_ENABLE)
+
enum {
VF610_PAD_PTA6__RMII0_CLKIN = IOMUX_PAD(0x0000, 0x0000, 2, __NA_, 0, VF610_ENET_PAD_CTRL),
VF610_PAD_PTA6__RMII0_CLKOUT = IOMUX_PAD(0x0000, 0x0000, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+ VF610_PAD_PTA17__GPIO_7 = IOMUX_PAD(0x001c, 0x001c, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+ VF610_PAD_PTA20__GPIO_10 = IOMUX_PAD(0x0028, 0x0028, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+ VF610_PAD_PTA21__GPIO_11 = IOMUX_PAD(0x002c, 0x002c, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+ VF610_PAD_PTA30__GPIO_20 = IOMUX_PAD(0x0050, 0x0050, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+ VF610_PAD_PTA31__GPIO_21 = IOMUX_PAD(0x0054, 0x0054, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+ VF610_PAD_PTB0__GPIO_22 = IOMUX_PAD(0x0058, 0x0058, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+ VF610_PAD_PTB1__GPIO_23 = IOMUX_PAD(0x005C, 0x005C, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
VF610_PAD_PTB4__UART1_TX = IOMUX_PAD(0x0068, 0x0068, 2, 0x0380, 0, VF610_UART_PAD_CTRL),
VF610_PAD_PTB5__UART1_RX = IOMUX_PAD(0x006c, 0x006c, 2, 0x037c, 0, VF610_UART_PAD_CTRL),
+ VF610_PAD_PTB8__GPIO_30 = IOMUX_PAD(0x0078, 0x0078, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+ VF610_PAD_PTB9__GPIO_31 = IOMUX_PAD(0x007C, 0x007C, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
VF610_PAD_PTB10__UART0_TX = IOMUX_PAD(0x0080, 0x0080, 1, __NA_, 0, VF610_UART_PAD_CTRL),
VF610_PAD_PTB11__UART0_RX = IOMUX_PAD(0x0084, 0x0084, 1, __NA_, 0, VF610_UART_PAD_CTRL),
+ VF610_PAD_PTC0__GPIO_45 = IOMUX_PAD(0x00b4, 0x00b4, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
VF610_PAD_PTC1__RMII0_MDIO = IOMUX_PAD(0x00b8, 0x00b8, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
VF610_PAD_PTC0__RMII0_MDC = IOMUX_PAD(0x00b4, 0x00b4, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
VF610_PAD_PTC2__RMII0_CRS_DV = IOMUX_PAD(0x00bc, 0x00bc, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
diff --git a/arch/arm/include/asm/imx-common/iomux-v3.h b/arch/arm/include/asm/imx-common/iomux-v3.h
index 5f161bb5f1..a817b0cc03 100644
--- a/arch/arm/include/asm/imx-common/iomux-v3.h
+++ b/arch/arm/include/asm/imx-common/iomux-v3.h
@@ -190,6 +190,8 @@ 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);
+void imx_iomux_gpio_set_direction(unsigned int gpio,
+ unsigned int direction);
/* macros for declaring and using pinmux array */
#if defined(CONFIG_MX6QDL)
diff --git a/board/toradex/colibri_vf/colibri_vf.c b/board/toradex/colibri_vf/colibri_vf.c
index 0b1269ad3d..42de260661 100644
--- a/board/toradex/colibri_vf/colibri_vf.c
+++ b/board/toradex/colibri_vf/colibri_vf.c
@@ -8,6 +8,7 @@
*/
#include <common.h>
+#include <dm.h>
#include <asm/io.h>
#include <asm/arch/imx-regs.h>
#include <asm/arch/iomux-vf610.h>
@@ -22,6 +23,7 @@
#include <netdev.h>
#include <i2c.h>
#include <g_dnl.h>
+#include <asm/gpio.h>
#include "../common/configblock.h"
@@ -193,6 +195,26 @@ static void setup_tcon(void)
}
#endif
+#ifdef CONFIG_VYBRID_GPIO
+static void setup_iomux_gpio(void)
+{
+ static const iomux_v3_cfg_t gpio_pads[] = {
+ VF610_PAD_PTA17__GPIO_7,
+ VF610_PAD_PTA20__GPIO_10,
+ VF610_PAD_PTA21__GPIO_11,
+ VF610_PAD_PTA30__GPIO_20,
+ VF610_PAD_PTA31__GPIO_21,
+ VF610_PAD_PTB0__GPIO_22,
+ VF610_PAD_PTB1__GPIO_23,
+ VF610_PAD_PTB8__GPIO_30,
+ VF610_PAD_PTB9__GPIO_31,
+ VF610_PAD_PTC0__GPIO_45,
+ };
+
+ imx_iomux_v3_setup_multiple_pads(gpio_pads, ARRAY_SIZE(gpio_pads));
+}
+#endif
+
#ifdef CONFIG_FSL_ESDHC
struct fsl_esdhc_cfg esdhc_cfg[1] = {
{ESDHC1_BASE_ADDR},
@@ -365,6 +387,10 @@ int board_early_init_f(void)
setup_iomux_fsl_dcu();
#endif
+#ifdef CONFIG_VYBRID_GPIO
+ setup_iomux_gpio();
+#endif
+
return 0;
}
@@ -375,6 +401,24 @@ static const struct boot_mode board_boot_modes[] = {
};
#endif
+#ifndef CONFIG_OF_CONTROL
+static const struct vybrid_gpio_platdata vybrid_gpio[] = {
+ {0, GPIO0_BASE_ADDR},
+ {1, GPIO1_BASE_ADDR},
+ {2, GPIO2_BASE_ADDR},
+ {3, GPIO3_BASE_ADDR},
+ {4, GPIO4_BASE_ADDR},
+};
+
+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
+
#ifdef CONFIG_BOARD_LATE_INIT
int board_late_init(void)
{
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 85f71c5d4a..62c73042b7 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 a69bbd2002..27778b4fcc 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 0000000000..9fa0762b7c
--- /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,
+};
diff --git a/include/configs/colibri_vf.h b/include/configs/colibri_vf.h
index aef2014f52..5a01c7f2f9 100644
--- a/include/configs/colibri_vf.h
+++ b/include/configs/colibri_vf.h
@@ -80,6 +80,14 @@
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_NAND_BASE NFC_BASE_ADDR
+/* Enable driver model */
+#define CONFIG_DM
+
+/* GPIO support */
+#define CONFIG_DM_GPIO
+#define CONFIG_CMD_GPIO
+#define CONFIG_VYBRID_GPIO
+
/* Dynamic MTD partition support */
#define CONFIG_CMD_MTDPARTS /* Enable 'mtdparts' command line support */
#define CONFIG_MTD_PARTITIONS