summaryrefslogtreecommitdiffstats
path: root/qemu/roms/u-boot/drivers/gpio
diff options
context:
space:
mode:
authorYang Zhang <yang.z.zhang@intel.com>2015-08-28 09:58:54 +0800
committerYang Zhang <yang.z.zhang@intel.com>2015-09-01 12:44:00 +0800
commite44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch)
tree66b09f592c55df2878107a468a91d21506104d3f /qemu/roms/u-boot/drivers/gpio
parent9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (diff)
Add qemu 2.4.0
Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5 Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Diffstat (limited to 'qemu/roms/u-boot/drivers/gpio')
-rw-r--r--qemu/roms/u-boot/drivers/gpio/Makefile36
-rw-r--r--qemu/roms/u-boot/drivers/gpio/adi_gpio2.c423
-rw-r--r--qemu/roms/u-boot/drivers/gpio/altera_pio.c286
-rw-r--r--qemu/roms/u-boot/drivers/gpio/at91_gpio.c396
-rw-r--r--qemu/roms/u-boot/drivers/gpio/bcm2835_gpio.c78
-rw-r--r--qemu/roms/u-boot/drivers/gpio/da8xx_gpio.c396
-rw-r--r--qemu/roms/u-boot/drivers/gpio/db8500_gpio.c221
-rw-r--r--qemu/roms/u-boot/drivers/gpio/gpio-uclass.c266
-rw-r--r--qemu/roms/u-boot/drivers/gpio/intel_ich6_gpio.c274
-rw-r--r--qemu/roms/u-boot/drivers/gpio/kona_gpio.c141
-rw-r--r--qemu/roms/u-boot/drivers/gpio/kw_gpio.c150
-rw-r--r--qemu/roms/u-boot/drivers/gpio/mpc83xx_gpio.c183
-rw-r--r--qemu/roms/u-boot/drivers/gpio/mvgpio.c97
-rw-r--r--qemu/roms/u-boot/drivers/gpio/mvgpio.h58
-rw-r--r--qemu/roms/u-boot/drivers/gpio/mvmfp.c66
-rw-r--r--qemu/roms/u-boot/drivers/gpio/mxc_gpio.c136
-rw-r--r--qemu/roms/u-boot/drivers/gpio/mxs_gpio.c116
-rw-r--r--qemu/roms/u-boot/drivers/gpio/omap_gpio.c222
-rw-r--r--qemu/roms/u-boot/drivers/gpio/pca953x.c312
-rw-r--r--qemu/roms/u-boot/drivers/gpio/pca9698.c127
-rw-r--r--qemu/roms/u-boot/drivers/gpio/s3c2440_gpio.c79
-rw-r--r--qemu/roms/u-boot/drivers/gpio/s5p_gpio.c181
-rw-r--r--qemu/roms/u-boot/drivers/gpio/sandbox.c254
-rw-r--r--qemu/roms/u-boot/drivers/gpio/sh_pfc.c629
-rw-r--r--qemu/roms/u-boot/drivers/gpio/spear_gpio.c86
-rw-r--r--qemu/roms/u-boot/drivers/gpio/sx151x.c242
-rw-r--r--qemu/roms/u-boot/drivers/gpio/tca642x.c333
-rw-r--r--qemu/roms/u-boot/drivers/gpio/tegra_gpio.c246
-rw-r--r--qemu/roms/u-boot/drivers/gpio/xilinx_gpio.c348
29 files changed, 6382 insertions, 0 deletions
diff --git a/qemu/roms/u-boot/drivers/gpio/Makefile b/qemu/roms/u-boot/drivers/gpio/Makefile
new file mode 100644
index 000000000..4e001e12b
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/Makefile
@@ -0,0 +1,36 @@
+#
+# Copyright 2000-2008
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-$(CONFIG_DM_GPIO) += gpio-uclass.o
+
+obj-$(CONFIG_AT91_GPIO) += at91_gpio.o
+obj-$(CONFIG_INTEL_ICH6_GPIO) += intel_ich6_gpio.o
+obj-$(CONFIG_KIRKWOOD_GPIO) += kw_gpio.o
+obj-$(CONFIG_KONA_GPIO) += kona_gpio.o
+obj-$(CONFIG_MARVELL_GPIO) += mvgpio.o
+obj-$(CONFIG_MARVELL_MFP) += mvmfp.o
+obj-$(CONFIG_MXC_GPIO) += mxc_gpio.o
+obj-$(CONFIG_MXS_GPIO) += mxs_gpio.o
+obj-$(CONFIG_PCA953X) += pca953x.o
+obj-$(CONFIG_PCA9698) += pca9698.o
+obj-$(CONFIG_S5P) += s5p_gpio.o
+obj-$(CONFIG_SANDBOX_GPIO) += sandbox.o
+obj-$(CONFIG_SPEAR_GPIO) += spear_gpio.o
+obj-$(CONFIG_TEGRA_GPIO) += tegra_gpio.o
+obj-$(CONFIG_DA8XX_GPIO) += da8xx_gpio.o
+obj-$(CONFIG_DM644X_GPIO) += da8xx_gpio.o
+obj-$(CONFIG_ALTERA_PIO) += altera_pio.o
+obj-$(CONFIG_MPC83XX_GPIO) += mpc83xx_gpio.o
+obj-$(CONFIG_SH_GPIO_PFC) += sh_pfc.o
+obj-$(CONFIG_OMAP_GPIO) += omap_gpio.o
+obj-$(CONFIG_DB8500_GPIO) += db8500_gpio.o
+obj-$(CONFIG_BCM2835_GPIO) += bcm2835_gpio.o
+obj-$(CONFIG_S3C2440_GPIO) += s3c2440_gpio.o
+obj-$(CONFIG_XILINX_GPIO) += xilinx_gpio.o
+obj-$(CONFIG_ADI_GPIO2) += adi_gpio2.o
+obj-$(CONFIG_TCA642X) += tca642x.o
+oby-$(CONFIG_SX151X) += sx151x.o
diff --git a/qemu/roms/u-boot/drivers/gpio/adi_gpio2.c b/qemu/roms/u-boot/drivers/gpio/adi_gpio2.c
new file mode 100644
index 000000000..88cd65b87
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/adi_gpio2.c
@@ -0,0 +1,423 @@
+/*
+ * ADI GPIO2 Abstraction Layer
+ * Support BF54x, BF60x and future processors.
+ *
+ * Copyright 2008-2013 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/gpio.h>
+
+#define RESOURCE_LABEL_SIZE 16
+
+static struct str_ident {
+ char name[RESOURCE_LABEL_SIZE];
+} str_ident[MAX_RESOURCES];
+
+static void gpio_error(unsigned gpio)
+{
+ printf("adi_gpio2: GPIO %d wasn't requested!\n", gpio);
+}
+
+static void set_label(unsigned short ident, const char *label)
+{
+ if (label) {
+ strncpy(str_ident[ident].name, label,
+ RESOURCE_LABEL_SIZE);
+ str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0;
+ }
+}
+
+static char *get_label(unsigned short ident)
+{
+ return *str_ident[ident].name ? str_ident[ident].name : "UNKNOWN";
+}
+
+static int cmp_label(unsigned short ident, const char *label)
+{
+ if (label == NULL)
+ printf("adi_gpio2: please provide none-null label\n");
+
+ if (label)
+ return strcmp(str_ident[ident].name, label);
+ else
+ return -EINVAL;
+}
+
+#define map_entry(m, i) reserved_##m##_map[gpio_bank(i)]
+#define is_reserved(m, i, e) (map_entry(m, i) & gpio_bit(i))
+#define reserve(m, i) (map_entry(m, i) |= gpio_bit(i))
+#define unreserve(m, i) (map_entry(m, i) &= ~gpio_bit(i))
+#define DECLARE_RESERVED_MAP(m, c) unsigned short reserved_##m##_map[c]
+
+static DECLARE_RESERVED_MAP(gpio, GPIO_BANK_NUM);
+static DECLARE_RESERVED_MAP(peri, gpio_bank(MAX_RESOURCES));
+
+inline int check_gpio(unsigned gpio)
+{
+#if defined(CONFIG_BF54x)
+ if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15 ||
+ gpio == GPIO_PH14 || gpio == GPIO_PH15 ||
+ gpio == GPIO_PJ14 || gpio == GPIO_PJ15)
+ return -EINVAL;
+#endif
+ if (gpio >= MAX_GPIOS)
+ return -EINVAL;
+ return 0;
+}
+
+static void port_setup(unsigned gpio, unsigned short usage)
+{
+#if defined(CONFIG_BF54x)
+ if (usage == GPIO_USAGE)
+ gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
+ else
+ gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio);
+#else
+ if (usage == GPIO_USAGE)
+ gpio_array[gpio_bank(gpio)]->port_fer_clear = gpio_bit(gpio);
+ else
+ gpio_array[gpio_bank(gpio)]->port_fer_set = gpio_bit(gpio);
+#endif
+}
+
+inline void portmux_setup(unsigned short per)
+{
+ u32 pmux;
+ u16 ident = P_IDENT(per);
+ u16 function = P_FUNCT2MUX(per);
+
+ pmux = gpio_array[gpio_bank(ident)]->port_mux;
+
+ pmux &= ~(0x3 << (2 * gpio_sub_n(ident)));
+ pmux |= (function & 0x3) << (2 * gpio_sub_n(ident));
+
+ gpio_array[gpio_bank(ident)]->port_mux = pmux;
+}
+
+inline u16 get_portmux(unsigned short per)
+{
+ u32 pmux;
+ u16 ident = P_IDENT(per);
+
+ pmux = gpio_array[gpio_bank(ident)]->port_mux;
+
+ return pmux >> (2 * gpio_sub_n(ident)) & 0x3;
+}
+
+unsigned short get_gpio_dir(unsigned gpio)
+{
+ return 0x01 &
+ (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio));
+}
+
+/***********************************************************
+*
+* FUNCTIONS: Peripheral Resource Allocation
+* and PortMux Setup
+*
+* INPUTS/OUTPUTS:
+* per Peripheral Identifier
+* label String
+*
+* DESCRIPTION: Peripheral Resource Allocation and Setup API
+**************************************************************/
+
+int peripheral_request(unsigned short per, const char *label)
+{
+ unsigned short ident = P_IDENT(per);
+
+ /*
+ * Don't cares are pins with only one dedicated function
+ */
+
+ if (per & P_DONTCARE)
+ return 0;
+
+ if (!(per & P_DEFINED))
+ return -ENODEV;
+
+ BUG_ON(ident >= MAX_RESOURCES);
+
+ /* If a pin can be muxed as either GPIO or peripheral, make
+ * sure it is not already a GPIO pin when we request it.
+ */
+ if (unlikely(!check_gpio(ident) && is_reserved(gpio, ident, 1))) {
+ printf("%s: Peripheral %d is already reserved as GPIO by %s!\n",
+ __func__, ident, get_label(ident));
+ return -EBUSY;
+ }
+
+ if (unlikely(is_reserved(peri, ident, 1))) {
+ /*
+ * Pin functions like AMC address strobes my
+ * be requested and used by several drivers
+ */
+
+ if (!((per & P_MAYSHARE) &&
+ get_portmux(per) == P_FUNCT2MUX(per))) {
+ /*
+ * Allow that the identical pin function can
+ * be requested from the same driver twice
+ */
+
+ if (cmp_label(ident, label) == 0)
+ goto anyway;
+
+ printf("%s: Peripheral %d function %d is already "
+ "reserved by %s!\n", __func__, ident,
+ P_FUNCT2MUX(per), get_label(ident));
+ return -EBUSY;
+ }
+ }
+
+ anyway:
+ reserve(peri, ident);
+
+ portmux_setup(per);
+ port_setup(ident, PERIPHERAL_USAGE);
+
+ set_label(ident, label);
+
+ return 0;
+}
+
+int peripheral_request_list(const unsigned short per[], const char *label)
+{
+ u16 cnt;
+ int ret;
+
+ for (cnt = 0; per[cnt] != 0; cnt++) {
+ ret = peripheral_request(per[cnt], label);
+
+ if (ret < 0) {
+ for (; cnt > 0; cnt--)
+ peripheral_free(per[cnt - 1]);
+
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+void peripheral_free(unsigned short per)
+{
+ unsigned short ident = P_IDENT(per);
+
+ if (per & P_DONTCARE)
+ return;
+
+ if (!(per & P_DEFINED))
+ return;
+
+ if (unlikely(!is_reserved(peri, ident, 0)))
+ return;
+
+ if (!(per & P_MAYSHARE))
+ port_setup(ident, GPIO_USAGE);
+
+ unreserve(peri, ident);
+
+ set_label(ident, "free");
+}
+
+void peripheral_free_list(const unsigned short per[])
+{
+ u16 cnt;
+ for (cnt = 0; per[cnt] != 0; cnt++)
+ peripheral_free(per[cnt]);
+}
+
+/***********************************************************
+*
+* FUNCTIONS: GPIO Driver
+*
+* INPUTS/OUTPUTS:
+* gpio PIO Number between 0 and MAX_GPIOS
+* label String
+*
+* DESCRIPTION: GPIO Driver API
+**************************************************************/
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ if (check_gpio(gpio) < 0)
+ return -EINVAL;
+
+ /*
+ * Allow that the identical GPIO can
+ * be requested from the same driver twice
+ * Do nothing and return -
+ */
+
+ if (cmp_label(gpio, label) == 0)
+ return 0;
+
+ if (unlikely(is_reserved(gpio, gpio, 1))) {
+ printf("adi_gpio2: GPIO %d is already reserved by %s!\n",
+ gpio, get_label(gpio));
+ return -EBUSY;
+ }
+ if (unlikely(is_reserved(peri, gpio, 1))) {
+ printf("adi_gpio2: GPIO %d is already reserved as Peripheral "
+ "by %s!\n", gpio, get_label(gpio));
+ return -EBUSY;
+ }
+
+ reserve(gpio, gpio);
+ set_label(gpio, label);
+
+ port_setup(gpio, GPIO_USAGE);
+
+ return 0;
+}
+
+int gpio_free(unsigned gpio)
+{
+ if (check_gpio(gpio) < 0)
+ return -1;
+
+ if (unlikely(!is_reserved(gpio, gpio, 0))) {
+ gpio_error(gpio);
+ return -1;
+ }
+
+ unreserve(gpio, gpio);
+
+ set_label(gpio, "free");
+
+ return 0;
+}
+
+#ifdef ADI_SPECIAL_GPIO_BANKS
+static DECLARE_RESERVED_MAP(special_gpio, gpio_bank(MAX_RESOURCES));
+
+int special_gpio_request(unsigned gpio, const char *label)
+{
+ /*
+ * Allow that the identical GPIO can
+ * be requested from the same driver twice
+ * Do nothing and return -
+ */
+
+ if (cmp_label(gpio, label) == 0)
+ return 0;
+
+ if (unlikely(is_reserved(special_gpio, gpio, 1))) {
+ printf("adi_gpio2: GPIO %d is already reserved by %s!\n",
+ gpio, get_label(gpio));
+ return -EBUSY;
+ }
+ if (unlikely(is_reserved(peri, gpio, 1))) {
+ printf("adi_gpio2: GPIO %d is already reserved as Peripheral "
+ "by %s!\n", gpio, get_label(gpio));
+
+ return -EBUSY;
+ }
+
+ reserve(special_gpio, gpio);
+ reserve(peri, gpio);
+
+ set_label(gpio, label);
+ port_setup(gpio, GPIO_USAGE);
+
+ return 0;
+}
+
+void special_gpio_free(unsigned gpio)
+{
+ if (unlikely(!is_reserved(special_gpio, gpio, 0))) {
+ gpio_error(gpio);
+ return;
+ }
+
+ unreserve(special_gpio, gpio);
+ unreserve(peri, gpio);
+ set_label(gpio, "free");
+}
+#endif
+
+static inline void __gpio_direction_input(unsigned gpio)
+{
+ gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio);
+#if defined(CONFIG_BF54x)
+ gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
+#else
+ gpio_array[gpio_bank(gpio)]->inen_set = gpio_bit(gpio);
+#endif
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+ unsigned long flags;
+
+ if (!is_reserved(gpio, gpio, 0)) {
+ gpio_error(gpio);
+ return -EINVAL;
+ }
+
+ local_irq_save(flags);
+ __gpio_direction_input(gpio);
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+int gpio_set_value(unsigned gpio, int arg)
+{
+ if (arg)
+ gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
+ else
+ gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio);
+
+ return 0;
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ unsigned long flags;
+
+ if (!is_reserved(gpio, gpio, 0)) {
+ gpio_error(gpio);
+ return -EINVAL;
+ }
+
+ local_irq_save(flags);
+
+#if defined(CONFIG_BF54x)
+ gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
+#else
+ gpio_array[gpio_bank(gpio)]->inen_clear = gpio_bit(gpio);
+#endif
+ gpio_set_value(gpio, value);
+ gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio);
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+int gpio_get_value(unsigned gpio)
+{
+ return 1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio));
+}
+
+void gpio_labels(void)
+{
+ int c, gpio;
+
+ for (c = 0; c < MAX_RESOURCES; c++) {
+ gpio = is_reserved(gpio, c, 1);
+ if (!check_gpio(c) && gpio)
+ printf("GPIO_%d:\t%s\tGPIO %s\n", c, get_label(c),
+ get_gpio_dir(c) ? "OUTPUT" : "INPUT");
+ else if (is_reserved(peri, c, 1))
+ printf("GPIO_%d:\t%s\tPeripheral\n", c, get_label(c));
+ else
+ continue;
+ }
+}
diff --git a/qemu/roms/u-boot/drivers/gpio/altera_pio.c b/qemu/roms/u-boot/drivers/gpio/altera_pio.c
new file mode 100644
index 000000000..3ca590700
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/altera_pio.c
@@ -0,0 +1,286 @@
+/*
+ * Driver for Altera's PIO ip core
+ *
+ * Copyright (C) 2011 Missing Link Electronics
+ * Joachim Foerster <joachim@missinglinkelectronics.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * To use this driver, in your board's config. header:
+ * #define CONFIG_ALTERA_PIO
+ * #define CONFIG_SYS_ALTERA_PIO_NUM <number-of-pio-cores>
+ * #define CONFIG_SYS_ALTERA_PIO_GPIO_NUM <total-number-of-gpios>
+ * And in your board's early setup routine:
+ * altera_pio_init(<baseaddr>, <width>, 'i'|'o'|'t',
+ * <reset-value>, <neg-mask>, "label");
+ * - 'i'|'o'|'t': PIO is input-only/output-only/tri-state
+ * - <reset-value>: for correct initial status display, output-only
+ * - <neg-mask> is meant to be used to in cases of active-low
+ * GPIOs, such as LEDs and buttons (on/pressed == 0). Each bit
+ * which is 1 in <neg-mask> inverts the corresponding GPIO's value
+ * before set/after get. So: gpio_set_value(gpio, 1) => LED on .
+ *
+ * Do NOT define CONFIG_SYS_GPIO_BASE !
+ *
+ * Optionally, in your board's config. header:
+ * - To force a GPIO numbering scheme like in Linux ...
+ * #define CONFIG_GPIO_DOWNTO_NUMBERING
+ * ... starting with 255 (default)
+ * #define CONFIG_GPIO_DOWNTO_MAX 255
+ */
+#include <common.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+
+#ifdef CONFIG_GPIO_DOWNTO_NUMBERING
+#ifndef CONFIG_GPIO_DOWNTO_MAX
+#define CONFIG_GPIO_DOWNTO_MAX 255
+#endif
+#endif
+
+#define ALTERA_PIO_DATA 0x0
+#define ALTERA_PIO_DIR 0x4
+
+#define GPIO_LABEL_SIZE 9
+
+
+static struct altera_pio {
+ u32 base;
+ u8 width;
+ char iot;
+ u32 negmask;
+ u32 sh_data;
+ u32 sh_dir;
+ int gidx;
+ char label[GPIO_LABEL_SIZE];
+} pios[CONFIG_SYS_ALTERA_PIO_NUM];
+
+static int pio_num;
+
+static struct altera_pio_gpio {
+ unsigned num;
+ struct altera_pio *pio;
+ char reqlabel[GPIO_LABEL_SIZE];
+} gpios[CONFIG_SYS_ALTERA_PIO_GPIO_NUM];
+
+static int pio_gpio_num;
+
+
+static int altera_pio_gidx(unsigned gpio)
+{
+ int i;
+
+ for (i = 0; i < pio_gpio_num; ++i) {
+ if (gpio == gpios[i].num)
+ break;
+ }
+ if (i >= pio_gpio_num)
+ return -1;
+ return i;
+}
+
+static struct altera_pio *altera_pio_get_and_mask(unsigned gpio, u32 *mask)
+{
+ int gidx = altera_pio_gidx(gpio);
+ if (gidx < 0)
+ return NULL;
+ if (mask)
+ *mask = 1 << (gidx - gpios[gidx].pio->gidx);
+ return gpios[gidx].pio;
+}
+
+#define altera_pio_use_gidx(_gidx, _reqlabel) \
+ { strncpy(gpios[_gidx].reqlabel, _reqlabel, GPIO_LABEL_SIZE); }
+#define altera_pio_unuse_gidx(_gidx) { gpios[_gidx].reqlabel[0] = '\0'; }
+#define altera_pio_is_gidx_used(_gidx) (gpios[_gidx].reqlabel[0] != '\0')
+
+static int altera_pio_gpio_init(struct altera_pio *pio, u8 width)
+{
+ u8 gidx = pio_gpio_num;
+ int i;
+
+ if (!width)
+ return -1;
+ if ((pio_gpio_num + width) > CONFIG_SYS_ALTERA_PIO_GPIO_NUM)
+ return -1;
+
+ for (i = 0; i < width; ++i) {
+#ifdef CONFIG_GPIO_DOWNTO_NUMBERING
+ gpios[pio_gpio_num + i].num = \
+ CONFIG_GPIO_DOWNTO_MAX + 1 - gidx - width + i;
+#else
+ gpios[pio_gpio_num + i].num = pio_gpio_num + i;
+#endif
+ gpios[pio_gpio_num + i].pio = pio;
+ altera_pio_unuse_gidx(pio_gpio_num + i);
+ }
+ pio_gpio_num += width;
+ return gidx;
+}
+
+int altera_pio_init(u32 base, u8 width, char iot, u32 rstval, u32 negmask,
+ const char *label)
+{
+ if (pio_num >= CONFIG_SYS_ALTERA_PIO_NUM)
+ return -1;
+
+ pios[pio_num].base = base;
+ pios[pio_num].width = width;
+ pios[pio_num].iot = iot;
+ switch (iot) {
+ case 'i':
+ /* input only */
+ pios[pio_num].sh_dir = 0;
+ pios[pio_num].sh_data = readl(base + ALTERA_PIO_DATA);
+ break;
+ case 'o':
+ /* output only */
+ pios[pio_num].sh_dir = 0xffffffff & ((1 << width) - 1);
+ pios[pio_num].sh_data = rstval;
+ break;
+ case 't':
+ /* bidir, tri-state */
+ pios[pio_num].sh_dir = readl(base + ALTERA_PIO_DIR);
+ pios[pio_num].sh_data = readl(base + ALTERA_PIO_DATA);
+ break;
+ default:
+ return -1;
+ }
+ pios[pio_num].negmask = negmask & ((1 << width) - 1);
+ pios[pio_num].gidx = altera_pio_gpio_init(&pios[pio_num], width);
+ if (pios[pio_num].gidx < 0)
+ return -1;
+ strncpy(pios[pio_num].label, label, GPIO_LABEL_SIZE);
+ return pio_num++;
+}
+
+void altera_pio_info(void)
+{
+ int i;
+ int j;
+ int gidx;
+ u32 mask;
+
+ for (i = 0; i < pio_num; ++i) {
+ printf("Altera PIO % 2d, @0x%08x, "
+ "width: %u, label: %s\n",
+ i, pios[i].base, pios[i].width, pios[i].label);
+ gidx = pios[i].gidx;
+ for (j = gidx; j < (gidx + pios[i].width); ++j) {
+ mask = 1 << (j - gidx);
+ printf("\tGPIO % 4d: %s %s [%c] %s\n",
+ gpios[j].num,
+ gpios[j].pio->sh_dir & mask ? "out" : " in",
+ gpio_get_value(gpios[j].num) ? "set" : "clr",
+ altera_pio_is_gidx_used(j) ? 'x' : ' ',
+ gpios[j].reqlabel);
+ }
+ }
+}
+
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ int gidx = altera_pio_gidx(gpio);
+ if (gidx < 0)
+ return gidx;
+ if (altera_pio_is_gidx_used(gidx))
+ return -1;
+
+ altera_pio_use_gidx(gidx, label);
+ return 0;
+}
+
+int gpio_free(unsigned gpio)
+{
+ int gidx = altera_pio_gidx(gpio);
+ if (gidx < 0)
+ return gidx;
+ if (!altera_pio_is_gidx_used(gidx))
+ return -1;
+
+ altera_pio_unuse_gidx(gidx);
+ return 0;
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+ u32 mask;
+ struct altera_pio *pio;
+
+ pio = altera_pio_get_and_mask(gpio, &mask);
+ if (!pio)
+ return -1;
+ if (pio->iot == 'o')
+ return -1;
+
+ writel(pio->sh_dir &= ~mask, pio->base + ALTERA_PIO_DIR);
+ return 0;
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ u32 mask;
+ struct altera_pio *pio;
+
+ pio = altera_pio_get_and_mask(gpio, &mask);
+ if (!pio)
+ return -1;
+ if (pio->iot == 'i')
+ return -1;
+
+ value = (pio->negmask & mask) ? !value : value;
+ if (value)
+ pio->sh_data |= mask;
+ else
+ pio->sh_data &= ~mask;
+ writel(pio->sh_data, pio->base + ALTERA_PIO_DATA);
+ writel(pio->sh_dir |= mask, pio->base + ALTERA_PIO_DIR);
+ return 0;
+}
+
+int gpio_get_value(unsigned gpio)
+{
+ u32 mask;
+ struct altera_pio *pio;
+ u32 val;
+
+ pio = altera_pio_get_and_mask(gpio, &mask);
+ if (!pio)
+ return -1;
+
+ if ((pio->sh_dir & mask) || (pio->iot == 'o'))
+ val = pio->sh_data & mask;
+ else
+ val = readl(pio->base + ALTERA_PIO_DATA) & mask;
+ return (pio->negmask & mask) ? !val : val;
+}
+
+void gpio_set_value(unsigned gpio, int value)
+{
+ u32 mask;
+ struct altera_pio *pio;
+
+ pio = altera_pio_get_and_mask(gpio, &mask);
+ if (!pio)
+ return;
+ if (pio->iot == 'i')
+ return;
+
+ value = (pio->negmask & mask) ? !value : value;
+ if (value)
+ pio->sh_data |= mask;
+ else
+ pio->sh_data &= ~mask;
+ writel(pio->sh_data, pio->base + ALTERA_PIO_DATA);
+ return;
+}
+
+int gpio_is_valid(int number)
+{
+ int gidx = altera_pio_gidx(number);
+
+ if (gidx < 0)
+ return 1;
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/gpio/at91_gpio.c b/qemu/roms/u-boot/drivers/gpio/at91_gpio.c
new file mode 100644
index 000000000..0b7007187
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/at91_gpio.c
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) 2013 Bo Shen <voice.shen@atmel.com>
+ *
+ * Copyright (C) 2009 Jens Scharsig (js_at_ng@scharsoft.de)
+ *
+ * Copyright (C) 2005 HP Labs
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <linux/sizes.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_pio.h>
+#include <asm/arch/gpio.h>
+
+static struct at91_port *at91_pio_get_port(unsigned port)
+{
+ switch (port) {
+ case AT91_PIO_PORTA:
+ return (struct at91_port *)ATMEL_BASE_PIOA;
+ case AT91_PIO_PORTB:
+ return (struct at91_port *)ATMEL_BASE_PIOB;
+ case AT91_PIO_PORTC:
+ return (struct at91_port *)ATMEL_BASE_PIOC;
+#if (ATMEL_PIO_PORTS > 3)
+ case AT91_PIO_PORTD:
+ return (struct at91_port *)ATMEL_BASE_PIOD;
+#if (ATMEL_PIO_PORTS > 4)
+ case AT91_PIO_PORTE:
+ return (struct at91_port *)ATMEL_BASE_PIOE;
+#endif
+#endif
+ default:
+ return NULL;
+ }
+}
+
+int at91_set_pio_pullup(unsigned port, unsigned pin, int use_pullup)
+{
+ struct at91_port *at91_port = at91_pio_get_port(port);
+ u32 mask;
+
+ if (at91_port && (pin < 32)) {
+ mask = 1 << pin;
+ if (use_pullup)
+ writel(1 << pin, &at91_port->puer);
+ else
+ writel(1 << pin, &at91_port->pudr);
+ writel(mask, &at91_port->per);
+ }
+
+ return 0;
+}
+
+/*
+ * mux the pin to the "GPIO" peripheral role.
+ */
+int at91_set_pio_periph(unsigned port, unsigned pin, int use_pullup)
+{
+ struct at91_port *at91_port = at91_pio_get_port(port);
+ u32 mask;
+
+ if (at91_port && (pin < 32)) {
+ mask = 1 << pin;
+ writel(mask, &at91_port->idr);
+ at91_set_pio_pullup(port, pin, use_pullup);
+ writel(mask, &at91_port->per);
+ }
+
+ return 0;
+}
+
+/*
+ * mux the pin to the "A" internal peripheral role.
+ */
+int at91_set_a_periph(unsigned port, unsigned pin, int use_pullup)
+{
+ struct at91_port *at91_port = at91_pio_get_port(port);
+ u32 mask;
+
+ if (at91_port && (pin < 32)) {
+ mask = 1 << pin;
+ writel(mask, &at91_port->idr);
+ at91_set_pio_pullup(port, pin, use_pullup);
+#if defined(CPU_HAS_PIO3)
+ writel(readl(&at91_port->abcdsr1) & ~mask,
+ &at91_port->abcdsr1);
+ writel(readl(&at91_port->abcdsr2) & ~mask,
+ &at91_port->abcdsr2);
+#else
+ writel(mask, &at91_port->asr);
+#endif
+ writel(mask, &at91_port->pdr);
+ }
+
+ return 0;
+}
+
+/*
+ * mux the pin to the "B" internal peripheral role.
+ */
+int at91_set_b_periph(unsigned port, unsigned pin, int use_pullup)
+{
+ struct at91_port *at91_port = at91_pio_get_port(port);
+ u32 mask;
+
+ if (at91_port && (pin < 32)) {
+ mask = 1 << pin;
+ writel(mask, &at91_port->idr);
+ at91_set_pio_pullup(port, pin, use_pullup);
+#if defined(CPU_HAS_PIO3)
+ writel(readl(&at91_port->abcdsr1) | mask,
+ &at91_port->abcdsr1);
+ writel(readl(&at91_port->abcdsr2) & ~mask,
+ &at91_port->abcdsr2);
+#else
+ writel(mask, &at91_port->bsr);
+#endif
+ writel(mask, &at91_port->pdr);
+ }
+
+ return 0;
+}
+
+#if defined(CPU_HAS_PIO3)
+/*
+ * mux the pin to the "C" internal peripheral role.
+ */
+int at91_set_c_periph(unsigned port, unsigned pin, int use_pullup)
+{
+ struct at91_port *at91_port = at91_pio_get_port(port);
+ u32 mask;
+
+ if (at91_port && (pin < 32)) {
+ mask = 1 << pin;
+ writel(mask, &at91_port->idr);
+ at91_set_pio_pullup(port, pin, use_pullup);
+ writel(readl(&at91_port->abcdsr1) & ~mask,
+ &at91_port->abcdsr1);
+ writel(readl(&at91_port->abcdsr2) | mask,
+ &at91_port->abcdsr2);
+ writel(mask, &at91_port->pdr);
+ }
+
+ return 0;
+}
+
+/*
+ * mux the pin to the "D" internal peripheral role.
+ */
+int at91_set_d_periph(unsigned port, unsigned pin, int use_pullup)
+{
+ struct at91_port *at91_port = at91_pio_get_port(port);
+ u32 mask;
+
+ if (at91_port && (pin < 32)) {
+ mask = 1 << pin;
+ writel(mask, &at91_port->idr);
+ at91_set_pio_pullup(port, pin, use_pullup);
+ writel(readl(&at91_port->abcdsr1) | mask,
+ &at91_port->abcdsr1);
+ writel(readl(&at91_port->abcdsr2) | mask,
+ &at91_port->abcdsr2);
+ writel(mask, &at91_port->pdr);
+ }
+
+ return 0;
+}
+#endif
+
+/*
+ * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and
+ * configure it for an input.
+ */
+int at91_set_pio_input(unsigned port, u32 pin, int use_pullup)
+{
+ struct at91_port *at91_port = at91_pio_get_port(port);
+ u32 mask;
+
+ if (at91_port && (pin < 32)) {
+ mask = 1 << pin;
+ writel(mask, &at91_port->idr);
+ at91_set_pio_pullup(port, pin, use_pullup);
+ writel(mask, &at91_port->odr);
+ writel(mask, &at91_port->per);
+ }
+
+ return 0;
+}
+
+/*
+ * mux the pin to the gpio controller (instead of "A" or "B" peripheral),
+ * and configure it for an output.
+ */
+int at91_set_pio_output(unsigned port, u32 pin, int value)
+{
+ struct at91_port *at91_port = at91_pio_get_port(port);
+ u32 mask;
+
+ if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
+ mask = 1 << pin;
+ writel(mask, &at91_port->idr);
+ writel(mask, &at91_port->pudr);
+ if (value)
+ writel(mask, &at91_port->sodr);
+ else
+ writel(mask, &at91_port->codr);
+ writel(mask, &at91_port->oer);
+ writel(mask, &at91_port->per);
+ }
+
+ return 0;
+}
+
+/*
+ * enable/disable the glitch filter. mostly used with IRQ handling.
+ */
+int at91_set_pio_deglitch(unsigned port, unsigned pin, int is_on)
+{
+ struct at91_port *at91_port = at91_pio_get_port(port);
+ u32 mask;
+
+ if (at91_port && (pin < 32)) {
+ mask = 1 << pin;
+ if (is_on) {
+#if defined(CPU_HAS_PIO3)
+ writel(mask, &at91_port->ifscdr);
+#endif
+ writel(mask, &at91_port->ifer);
+ } else {
+ writel(mask, &at91_port->ifdr);
+ }
+ }
+
+ return 0;
+}
+
+#if defined(CPU_HAS_PIO3)
+/*
+ * enable/disable the debounce filter.
+ */
+int at91_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div)
+{
+ struct at91_port *at91_port = at91_pio_get_port(port);
+ u32 mask;
+
+ if (at91_port && (pin < 32)) {
+ mask = 1 << pin;
+ if (is_on) {
+ writel(mask, &at91_port->ifscer);
+ writel(div & PIO_SCDR_DIV, &at91_port->scdr);
+ writel(mask, &at91_port->ifer);
+ } else {
+ writel(mask, &at91_port->ifdr);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * enable/disable the pull-down.
+ * If pull-up already enabled while calling the function, we disable it.
+ */
+int at91_set_pio_pulldown(unsigned port, unsigned pin, int is_on)
+{
+ struct at91_port *at91_port = at91_pio_get_port(port);
+ u32 mask;
+
+ if (at91_port && (pin < 32)) {
+ mask = 1 << pin;
+ writel(mask, &at91_port->pudr);
+ if (is_on)
+ writel(mask, &at91_port->ppder);
+ else
+ writel(mask, &at91_port->ppddr);
+ }
+
+ return 0;
+}
+
+/*
+ * disable Schmitt trigger
+ */
+int at91_set_pio_disable_schmitt_trig(unsigned port, unsigned pin)
+{
+ struct at91_port *at91_port = at91_pio_get_port(port);
+ u32 mask;
+
+ if (at91_port && (pin < 32)) {
+ mask = 1 << pin;
+ writel(readl(&at91_port->schmitt) | mask,
+ &at91_port->schmitt);
+ }
+
+ return 0;
+}
+#endif
+
+/*
+ * enable/disable the multi-driver. This is only valid for output and
+ * allows the output pin to run as an open collector output.
+ */
+int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on)
+{
+ struct at91_port *at91_port = at91_pio_get_port(port);
+ u32 mask;
+
+ if (at91_port && (pin < 32)) {
+ mask = 1 << pin;
+ if (is_on)
+ writel(mask, &at91_port->mder);
+ else
+ writel(mask, &at91_port->mddr);
+ }
+
+ return 0;
+}
+
+/*
+ * assuming the pin is muxed as a gpio output, set its value.
+ */
+int at91_set_pio_value(unsigned port, unsigned pin, int value)
+{
+ struct at91_port *at91_port = at91_pio_get_port(port);
+ u32 mask;
+
+ if (at91_port && (pin < 32)) {
+ mask = 1 << pin;
+ if (value)
+ writel(mask, &at91_port->sodr);
+ else
+ writel(mask, &at91_port->codr);
+ }
+
+ return 0;
+}
+
+/*
+ * read the pin's value (works even if it's not muxed as a gpio).
+ */
+int at91_get_pio_value(unsigned port, unsigned pin)
+{
+ struct at91_port *at91_port = at91_pio_get_port(port);
+ u32 pdsr = 0, mask;
+
+ if (at91_port && (pin < 32)) {
+ mask = 1 << pin;
+ pdsr = readl(&at91_port->pdsr) & mask;
+ }
+
+ return pdsr != 0;
+}
+
+/* Common GPIO API */
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ return 0;
+}
+
+int gpio_free(unsigned gpio)
+{
+ return 0;
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+ at91_set_pio_input(at91_gpio_to_port(gpio),
+ at91_gpio_to_pin(gpio), 0);
+ return 0;
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ at91_set_pio_output(at91_gpio_to_port(gpio),
+ at91_gpio_to_pin(gpio), value);
+ return 0;
+}
+
+int gpio_get_value(unsigned gpio)
+{
+ return at91_get_pio_value(at91_gpio_to_port(gpio),
+ at91_gpio_to_pin(gpio));
+}
+
+int gpio_set_value(unsigned gpio, int value)
+{
+ at91_set_pio_value(at91_gpio_to_port(gpio),
+ at91_gpio_to_pin(gpio), value);
+
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/gpio/bcm2835_gpio.c b/qemu/roms/u-boot/drivers/gpio/bcm2835_gpio.c
new file mode 100644
index 000000000..97b513711
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/bcm2835_gpio.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2012 Vikram Narayananan
+ * <vikram186@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+
+inline int gpio_is_valid(unsigned gpio)
+{
+ return (gpio < BCM2835_GPIO_COUNT);
+}
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ return !gpio_is_valid(gpio);
+}
+
+int gpio_free(unsigned gpio)
+{
+ return 0;
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+ struct bcm2835_gpio_regs *reg =
+ (struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE;
+ unsigned val;
+
+ val = readl(&reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
+ val &= ~(BCM2835_GPIO_FSEL_MASK << BCM2835_GPIO_FSEL_SHIFT(gpio));
+ val |= (BCM2835_GPIO_INPUT << BCM2835_GPIO_FSEL_SHIFT(gpio));
+ writel(val, &reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
+
+ return 0;
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ struct bcm2835_gpio_regs *reg =
+ (struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE;
+ unsigned val;
+
+ gpio_set_value(gpio, value);
+
+ val = readl(&reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
+ val &= ~(BCM2835_GPIO_FSEL_MASK << BCM2835_GPIO_FSEL_SHIFT(gpio));
+ val |= (BCM2835_GPIO_OUTPUT << BCM2835_GPIO_FSEL_SHIFT(gpio));
+ writel(val, &reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
+
+ return 0;
+}
+
+int gpio_get_value(unsigned gpio)
+{
+ struct bcm2835_gpio_regs *reg =
+ (struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE;
+ unsigned val;
+
+ val = readl(&reg->gplev[BCM2835_GPIO_COMMON_BANK(gpio)]);
+
+ return (val >> BCM2835_GPIO_COMMON_SHIFT(gpio)) & 0x1;
+}
+
+int gpio_set_value(unsigned gpio, int value)
+{
+ struct bcm2835_gpio_regs *reg =
+ (struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE;
+ u32 *output_reg = value ? reg->gpset : reg->gpclr;
+
+ writel(1 << BCM2835_GPIO_COMMON_SHIFT(gpio),
+ &output_reg[BCM2835_GPIO_COMMON_BANK(gpio)]);
+
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/gpio/da8xx_gpio.c b/qemu/roms/u-boot/drivers/gpio/da8xx_gpio.c
new file mode 100644
index 000000000..fa3a3946f
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/da8xx_gpio.c
@@ -0,0 +1,396 @@
+/*
+ * GPIO driver for TI DaVinci DA8xx SOCs.
+ *
+ * (C) Copyright 2011 Guralp Systems Ltd.
+ * Laurence Withers <lwithers@guralp.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/davinci_misc.h>
+
+static struct gpio_registry {
+ int is_registered;
+ char name[GPIO_NAME_SIZE];
+} gpio_registry[MAX_NUM_GPIOS];
+
+#if defined(CONFIG_SOC_DA8XX)
+#define pinmux(x) (&davinci_syscfg_regs->pinmux[x])
+
+#if defined(CONFIG_SOC_DA8XX) && !defined(CONFIG_SOC_DA850)
+static const struct pinmux_config gpio_pinmux[] = {
+ { pinmux(13), 8, 6 }, /* GP0[0] */
+ { pinmux(13), 8, 7 },
+ { pinmux(14), 8, 0 },
+ { pinmux(14), 8, 1 },
+ { pinmux(14), 8, 2 },
+ { pinmux(14), 8, 3 },
+ { pinmux(14), 8, 4 },
+ { pinmux(14), 8, 5 },
+ { pinmux(14), 8, 6 },
+ { pinmux(14), 8, 7 },
+ { pinmux(15), 8, 0 },
+ { pinmux(15), 8, 1 },
+ { pinmux(15), 8, 2 },
+ { pinmux(15), 8, 3 },
+ { pinmux(15), 8, 4 },
+ { pinmux(15), 8, 5 },
+ { pinmux(15), 8, 6 }, /* GP1[0] */
+ { pinmux(15), 8, 7 },
+ { pinmux(16), 8, 0 },
+ { pinmux(16), 8, 1 },
+ { pinmux(16), 8, 2 },
+ { pinmux(16), 8, 3 },
+ { pinmux(16), 8, 4 },
+ { pinmux(16), 8, 5 },
+ { pinmux(16), 8, 6 },
+ { pinmux(16), 8, 7 },
+ { pinmux(17), 8, 0 },
+ { pinmux(17), 8, 1 },
+ { pinmux(17), 8, 2 },
+ { pinmux(17), 8, 3 },
+ { pinmux(17), 8, 4 },
+ { pinmux(17), 8, 5 },
+ { pinmux(17), 8, 6 }, /* GP2[0] */
+ { pinmux(17), 8, 7 },
+ { pinmux(18), 8, 0 },
+ { pinmux(18), 8, 1 },
+ { pinmux(18), 8, 2 },
+ { pinmux(18), 8, 3 },
+ { pinmux(18), 8, 4 },
+ { pinmux(18), 8, 5 },
+ { pinmux(18), 8, 6 },
+ { pinmux(18), 8, 7 },
+ { pinmux(19), 8, 0 },
+ { pinmux(9), 8, 2 },
+ { pinmux(9), 8, 3 },
+ { pinmux(9), 8, 4 },
+ { pinmux(9), 8, 5 },
+ { pinmux(9), 8, 6 },
+ { pinmux(10), 8, 1 }, /* GP3[0] */
+ { pinmux(10), 8, 2 },
+ { pinmux(10), 8, 3 },
+ { pinmux(10), 8, 4 },
+ { pinmux(10), 8, 5 },
+ { pinmux(10), 8, 6 },
+ { pinmux(10), 8, 7 },
+ { pinmux(11), 8, 0 },
+ { pinmux(11), 8, 1 },
+ { pinmux(11), 8, 2 },
+ { pinmux(11), 8, 3 },
+ { pinmux(11), 8, 4 },
+ { pinmux(9), 8, 7 },
+ { pinmux(2), 8, 6 },
+ { pinmux(11), 8, 5 },
+ { pinmux(11), 8, 6 },
+ { pinmux(12), 8, 4 }, /* GP4[0] */
+ { pinmux(12), 8, 5 },
+ { pinmux(12), 8, 6 },
+ { pinmux(12), 8, 7 },
+ { pinmux(13), 8, 0 },
+ { pinmux(13), 8, 1 },
+ { pinmux(13), 8, 2 },
+ { pinmux(13), 8, 3 },
+ { pinmux(13), 8, 4 },
+ { pinmux(13), 8, 5 },
+ { pinmux(11), 8, 7 },
+ { pinmux(12), 8, 0 },
+ { pinmux(12), 8, 1 },
+ { pinmux(12), 8, 2 },
+ { pinmux(12), 8, 3 },
+ { pinmux(9), 8, 1 },
+ { pinmux(7), 8, 3 }, /* GP5[0] */
+ { pinmux(7), 8, 4 },
+ { pinmux(7), 8, 5 },
+ { pinmux(7), 8, 6 },
+ { pinmux(7), 8, 7 },
+ { pinmux(8), 8, 0 },
+ { pinmux(8), 8, 1 },
+ { pinmux(8), 8, 2 },
+ { pinmux(8), 8, 3 },
+ { pinmux(8), 8, 4 },
+ { pinmux(8), 8, 5 },
+ { pinmux(8), 8, 6 },
+ { pinmux(8), 8, 7 },
+ { pinmux(9), 8, 0 },
+ { pinmux(7), 8, 1 },
+ { pinmux(7), 8, 2 },
+ { pinmux(5), 8, 1 }, /* GP6[0] */
+ { pinmux(5), 8, 2 },
+ { pinmux(5), 8, 3 },
+ { pinmux(5), 8, 4 },
+ { pinmux(5), 8, 5 },
+ { pinmux(5), 8, 6 },
+ { pinmux(5), 8, 7 },
+ { pinmux(6), 8, 0 },
+ { pinmux(6), 8, 1 },
+ { pinmux(6), 8, 2 },
+ { pinmux(6), 8, 3 },
+ { pinmux(6), 8, 4 },
+ { pinmux(6), 8, 5 },
+ { pinmux(6), 8, 6 },
+ { pinmux(6), 8, 7 },
+ { pinmux(7), 8, 0 },
+ { pinmux(1), 8, 0 }, /* GP7[0] */
+ { pinmux(1), 8, 1 },
+ { pinmux(1), 8, 2 },
+ { pinmux(1), 8, 3 },
+ { pinmux(1), 8, 4 },
+ { pinmux(1), 8, 5 },
+ { pinmux(1), 8, 6 },
+ { pinmux(1), 8, 7 },
+ { pinmux(2), 8, 0 },
+ { pinmux(2), 8, 1 },
+ { pinmux(2), 8, 2 },
+ { pinmux(2), 8, 3 },
+ { pinmux(2), 8, 4 },
+ { pinmux(2), 8, 5 },
+ { pinmux(0), 1, 0 },
+ { pinmux(0), 1, 1 },
+};
+#else /* CONFIG_SOC_DA8XX && CONFIG_SOC_DA850 */
+static const struct pinmux_config gpio_pinmux[] = {
+ { pinmux(1), 8, 7 }, /* GP0[0] */
+ { pinmux(1), 8, 6 },
+ { pinmux(1), 8, 5 },
+ { pinmux(1), 8, 4 },
+ { pinmux(1), 8, 3 },
+ { pinmux(1), 8, 2 },
+ { pinmux(1), 8, 1 },
+ { pinmux(1), 8, 0 },
+ { pinmux(0), 8, 7 },
+ { pinmux(0), 8, 6 },
+ { pinmux(0), 8, 5 },
+ { pinmux(0), 8, 4 },
+ { pinmux(0), 8, 3 },
+ { pinmux(0), 8, 2 },
+ { pinmux(0), 8, 1 },
+ { pinmux(0), 8, 0 },
+ { pinmux(4), 8, 7 }, /* GP1[0] */
+ { pinmux(4), 8, 6 },
+ { pinmux(4), 8, 5 },
+ { pinmux(4), 8, 4 },
+ { pinmux(4), 8, 3 },
+ { pinmux(4), 8, 2 },
+ { pinmux(4), 4, 1 },
+ { pinmux(4), 4, 0 },
+ { pinmux(3), 4, 0 },
+ { pinmux(2), 4, 6 },
+ { pinmux(2), 4, 5 },
+ { pinmux(2), 4, 4 },
+ { pinmux(2), 4, 3 },
+ { pinmux(2), 4, 2 },
+ { pinmux(2), 4, 1 },
+ { pinmux(2), 8, 0 },
+ { pinmux(6), 8, 7 }, /* GP2[0] */
+ { pinmux(6), 8, 6 },
+ { pinmux(6), 8, 5 },
+ { pinmux(6), 8, 4 },
+ { pinmux(6), 8, 3 },
+ { pinmux(6), 8, 2 },
+ { pinmux(6), 8, 1 },
+ { pinmux(6), 8, 0 },
+ { pinmux(5), 8, 7 },
+ { pinmux(5), 8, 6 },
+ { pinmux(5), 8, 5 },
+ { pinmux(5), 8, 4 },
+ { pinmux(5), 8, 3 },
+ { pinmux(5), 8, 2 },
+ { pinmux(5), 8, 1 },
+ { pinmux(5), 8, 0 },
+ { pinmux(8), 8, 7 }, /* GP3[0] */
+ { pinmux(8), 8, 6 },
+ { pinmux(8), 8, 5 },
+ { pinmux(8), 8, 4 },
+ { pinmux(8), 8, 3 },
+ { pinmux(8), 8, 2 },
+ { pinmux(8), 8, 1 },
+ { pinmux(8), 8, 0 },
+ { pinmux(7), 8, 7 },
+ { pinmux(7), 8, 6 },
+ { pinmux(7), 8, 5 },
+ { pinmux(7), 8, 4 },
+ { pinmux(7), 8, 3 },
+ { pinmux(7), 8, 2 },
+ { pinmux(7), 8, 1 },
+ { pinmux(7), 8, 0 },
+ { pinmux(10), 8, 7 }, /* GP4[0] */
+ { pinmux(10), 8, 6 },
+ { pinmux(10), 8, 5 },
+ { pinmux(10), 8, 4 },
+ { pinmux(10), 8, 3 },
+ { pinmux(10), 8, 2 },
+ { pinmux(10), 8, 1 },
+ { pinmux(10), 8, 0 },
+ { pinmux(9), 8, 7 },
+ { pinmux(9), 8, 6 },
+ { pinmux(9), 8, 5 },
+ { pinmux(9), 8, 4 },
+ { pinmux(9), 8, 3 },
+ { pinmux(9), 8, 2 },
+ { pinmux(9), 8, 1 },
+ { pinmux(9), 8, 0 },
+ { pinmux(12), 8, 7 }, /* GP5[0] */
+ { pinmux(12), 8, 6 },
+ { pinmux(12), 8, 5 },
+ { pinmux(12), 8, 4 },
+ { pinmux(12), 8, 3 },
+ { pinmux(12), 8, 2 },
+ { pinmux(12), 8, 1 },
+ { pinmux(12), 8, 0 },
+ { pinmux(11), 8, 7 },
+ { pinmux(11), 8, 6 },
+ { pinmux(11), 8, 5 },
+ { pinmux(11), 8, 4 },
+ { pinmux(11), 8, 3 },
+ { pinmux(11), 8, 2 },
+ { pinmux(11), 8, 1 },
+ { pinmux(11), 8, 0 },
+ { pinmux(19), 8, 6 }, /* GP6[0] */
+ { pinmux(19), 8, 5 },
+ { pinmux(19), 8, 4 },
+ { pinmux(19), 8, 3 },
+ { pinmux(19), 8, 2 },
+ { pinmux(16), 8, 1 },
+ { pinmux(14), 8, 1 },
+ { pinmux(14), 8, 0 },
+ { pinmux(13), 8, 7 },
+ { pinmux(13), 8, 6 },
+ { pinmux(13), 8, 5 },
+ { pinmux(13), 8, 4 },
+ { pinmux(13), 8, 3 },
+ { pinmux(13), 8, 2 },
+ { pinmux(13), 8, 1 },
+ { pinmux(13), 8, 0 },
+ { pinmux(18), 8, 1 }, /* GP7[0] */
+ { pinmux(18), 8, 0 },
+ { pinmux(17), 8, 7 },
+ { pinmux(17), 8, 6 },
+ { pinmux(17), 8, 5 },
+ { pinmux(17), 8, 4 },
+ { pinmux(17), 8, 3 },
+ { pinmux(17), 8, 2 },
+ { pinmux(17), 8, 1 },
+ { pinmux(17), 8, 0 },
+ { pinmux(16), 8, 7 },
+ { pinmux(16), 8, 6 },
+ { pinmux(16), 8, 5 },
+ { pinmux(16), 8, 4 },
+ { pinmux(16), 8, 3 },
+ { pinmux(16), 8, 2 },
+ { pinmux(19), 8, 0 }, /* GP8[0] */
+ { pinmux(3), 4, 7 },
+ { pinmux(3), 4, 6 },
+ { pinmux(3), 4, 5 },
+ { pinmux(3), 4, 4 },
+ { pinmux(3), 4, 3 },
+ { pinmux(3), 4, 2 },
+ { pinmux(2), 4, 7 },
+ { pinmux(19), 8, 1 },
+ { pinmux(19), 8, 0 },
+ { pinmux(18), 8, 7 },
+ { pinmux(18), 8, 6 },
+ { pinmux(18), 8, 5 },
+ { pinmux(18), 8, 4 },
+ { pinmux(18), 8, 3 },
+ { pinmux(18), 8, 2 },
+};
+#endif /* CONFIG_SOC_DA8XX && !CONFIG_SOC_DA850 */
+#else /* !CONFIG_SOC_DA8XX */
+#define davinci_configure_pin_mux(a, b)
+#endif /* CONFIG_SOC_DA8XX */
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ if (gpio >= MAX_NUM_GPIOS)
+ return -1;
+
+ if (gpio_registry[gpio].is_registered)
+ return -1;
+
+ gpio_registry[gpio].is_registered = 1;
+ strncpy(gpio_registry[gpio].name, label, GPIO_NAME_SIZE);
+ gpio_registry[gpio].name[GPIO_NAME_SIZE - 1] = 0;
+
+ davinci_configure_pin_mux(&gpio_pinmux[gpio], 1);
+
+ return 0;
+}
+
+int gpio_free(unsigned gpio)
+{
+ if (gpio >= MAX_NUM_GPIOS)
+ return -1;
+
+ if (!gpio_registry[gpio].is_registered)
+ return -1;
+
+ gpio_registry[gpio].is_registered = 0;
+ gpio_registry[gpio].name[0] = '\0';
+ /* Do not configure as input or change pin mux here */
+ return 0;
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+ struct davinci_gpio *bank;
+
+ bank = GPIO_BANK(gpio);
+ setbits_le32(&bank->dir, 1U << GPIO_BIT(gpio));
+ return 0;
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ struct davinci_gpio *bank;
+
+ bank = GPIO_BANK(gpio);
+ clrbits_le32(&bank->dir, 1U << GPIO_BIT(gpio));
+ gpio_set_value(gpio, value);
+ return 0;
+}
+
+int gpio_get_value(unsigned gpio)
+{
+ struct davinci_gpio *bank;
+ unsigned int ip;
+
+ bank = GPIO_BANK(gpio);
+ ip = in_le32(&bank->in_data) & (1U << GPIO_BIT(gpio));
+ return ip ? 1 : 0;
+}
+
+int gpio_set_value(unsigned gpio, int value)
+{
+ struct davinci_gpio *bank;
+
+ bank = GPIO_BANK(gpio);
+
+ if (value)
+ bank->set_data = 1U << GPIO_BIT(gpio);
+ else
+ bank->clr_data = 1U << GPIO_BIT(gpio);
+
+ return 0;
+}
+
+void gpio_info(void)
+{
+ unsigned gpio, dir, val;
+ struct davinci_gpio *bank;
+
+ for (gpio = 0; gpio < MAX_NUM_GPIOS; ++gpio) {
+ bank = GPIO_BANK(gpio);
+ dir = in_le32(&bank->dir) & (1U << GPIO_BIT(gpio));
+ val = gpio_get_value(gpio);
+
+ printf("% 4d: %s: %d [%c] %s\n",
+ gpio, dir ? " in" : "out", val,
+ gpio_registry[gpio].is_registered ? 'x' : ' ',
+ gpio_registry[gpio].name);
+ }
+}
diff --git a/qemu/roms/u-boot/drivers/gpio/db8500_gpio.c b/qemu/roms/u-boot/drivers/gpio/db8500_gpio.c
new file mode 100644
index 000000000..d5cb383e8
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/db8500_gpio.c
@@ -0,0 +1,221 @@
+/*
+ * Code ported from Nomadik GPIO driver in ST-Ericsson Linux kernel code.
+ * The purpose is that GPIO config found in kernel should work by simply
+ * copy-paste it to U-boot.
+ *
+ * Original Linux authors:
+ * Copyright (C) 2008,2009 STMicroelectronics
+ * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
+ * Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com>
+ *
+ * Ported to U-boot by:
+ * Copyright (C) 2010 Joakim Axelsson <joakim.axelsson AT stericsson.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+#include <asm/arch/db8500_gpio.h>
+#include <asm/arch/db8500_pincfg.h>
+#include <linux/compiler.h>
+
+#define IO_ADDR(x) (void *) (x)
+
+/*
+ * The GPIO module in the db8500 Systems-on-Chip is an
+ * AMBA device, managing 32 pins and alternate functions. The logic block
+ * is currently only used in the db8500.
+ */
+
+#define GPIO_TOTAL_PINS 268
+#define GPIO_PINS_PER_BLOCK 32
+#define GPIO_BLOCKS_COUNT (GPIO_TOTAL_PINS/GPIO_PINS_PER_BLOCK + 1)
+#define GPIO_BLOCK(pin) (((pin + GPIO_PINS_PER_BLOCK) >> 5) - 1)
+#define GPIO_PIN_WITHIN_BLOCK(pin) ((pin)%(GPIO_PINS_PER_BLOCK))
+
+/* Register in the logic block */
+#define DB8500_GPIO_DAT 0x00
+#define DB8500_GPIO_DATS 0x04
+#define DB8500_GPIO_DATC 0x08
+#define DB8500_GPIO_PDIS 0x0c
+#define DB8500_GPIO_DIR 0x10
+#define DB8500_GPIO_DIRS 0x14
+#define DB8500_GPIO_DIRC 0x18
+#define DB8500_GPIO_SLPC 0x1c
+#define DB8500_GPIO_AFSLA 0x20
+#define DB8500_GPIO_AFSLB 0x24
+
+#define DB8500_GPIO_RIMSC 0x40
+#define DB8500_GPIO_FIMSC 0x44
+#define DB8500_GPIO_IS 0x48
+#define DB8500_GPIO_IC 0x4c
+#define DB8500_GPIO_RWIMSC 0x50
+#define DB8500_GPIO_FWIMSC 0x54
+#define DB8500_GPIO_WKS 0x58
+
+static void __iomem *get_gpio_addr(unsigned gpio)
+{
+ /* Our list of GPIO chips */
+ static void __iomem *gpio_addrs[GPIO_BLOCKS_COUNT] = {
+ IO_ADDR(CFG_GPIO_0_BASE),
+ IO_ADDR(CFG_GPIO_1_BASE),
+ IO_ADDR(CFG_GPIO_2_BASE),
+ IO_ADDR(CFG_GPIO_3_BASE),
+ IO_ADDR(CFG_GPIO_4_BASE),
+ IO_ADDR(CFG_GPIO_5_BASE),
+ IO_ADDR(CFG_GPIO_6_BASE),
+ IO_ADDR(CFG_GPIO_7_BASE),
+ IO_ADDR(CFG_GPIO_8_BASE)
+ };
+
+ return gpio_addrs[GPIO_BLOCK(gpio)];
+}
+
+static unsigned get_gpio_offset(unsigned gpio)
+{
+ return GPIO_PIN_WITHIN_BLOCK(gpio);
+}
+
+/* Can only be called from config_pin. Don't configure alt-mode directly */
+static void gpio_set_mode(unsigned gpio, enum db8500_gpio_alt mode)
+{
+ void __iomem *addr = get_gpio_addr(gpio);
+ unsigned offset = get_gpio_offset(gpio);
+ u32 bit = 1 << offset;
+ u32 afunc, bfunc;
+
+ afunc = readl(addr + DB8500_GPIO_AFSLA) & ~bit;
+ bfunc = readl(addr + DB8500_GPIO_AFSLB) & ~bit;
+ if (mode & DB8500_GPIO_ALT_A)
+ afunc |= bit;
+ if (mode & DB8500_GPIO_ALT_B)
+ bfunc |= bit;
+ writel(afunc, addr + DB8500_GPIO_AFSLA);
+ writel(bfunc, addr + DB8500_GPIO_AFSLB);
+}
+
+/**
+ * db8500_gpio_set_pull() - enable/disable pull up/down on a gpio
+ * @gpio: pin number
+ * @pull: one of DB8500_GPIO_PULL_DOWN, DB8500_GPIO_PULL_UP,
+ * and DB8500_GPIO_PULL_NONE
+ *
+ * Enables/disables pull up/down on a specified pin. This only takes effect if
+ * the pin is configured as an input (either explicitly or by the alternate
+ * function).
+ *
+ * NOTE: If enabling the pull up/down, the caller must ensure that the GPIO is
+ * configured as an input. Otherwise, due to the way the controller registers
+ * work, this function will change the value output on the pin.
+ */
+void db8500_gpio_set_pull(unsigned gpio, enum db8500_gpio_pull pull)
+{
+ void __iomem *addr = get_gpio_addr(gpio);
+ unsigned offset = get_gpio_offset(gpio);
+ u32 bit = 1 << offset;
+ u32 pdis;
+
+ pdis = readl(addr + DB8500_GPIO_PDIS);
+ if (pull == DB8500_GPIO_PULL_NONE)
+ pdis |= bit;
+ else
+ pdis &= ~bit;
+ writel(pdis, addr + DB8500_GPIO_PDIS);
+
+ if (pull == DB8500_GPIO_PULL_UP)
+ writel(bit, addr + DB8500_GPIO_DATS);
+ else if (pull == DB8500_GPIO_PULL_DOWN)
+ writel(bit, addr + DB8500_GPIO_DATC);
+}
+
+void db8500_gpio_make_input(unsigned gpio)
+{
+ void __iomem *addr = get_gpio_addr(gpio);
+ unsigned offset = get_gpio_offset(gpio);
+
+ writel(1 << offset, addr + DB8500_GPIO_DIRC);
+}
+
+int db8500_gpio_get_input(unsigned gpio)
+{
+ void __iomem *addr = get_gpio_addr(gpio);
+ unsigned offset = get_gpio_offset(gpio);
+ u32 bit = 1 << offset;
+
+ printf("db8500_gpio_get_input gpio=%u addr=%p offset=%u bit=%#x\n",
+ gpio, addr, offset, bit);
+
+ return (readl(addr + DB8500_GPIO_DAT) & bit) != 0;
+}
+
+void db8500_gpio_make_output(unsigned gpio, int val)
+{
+ void __iomem *addr = get_gpio_addr(gpio);
+ unsigned offset = get_gpio_offset(gpio);
+
+ writel(1 << offset, addr + DB8500_GPIO_DIRS);
+ db8500_gpio_set_output(gpio, val);
+}
+
+void db8500_gpio_set_output(unsigned gpio, int val)
+{
+ void __iomem *addr = get_gpio_addr(gpio);
+ unsigned offset = get_gpio_offset(gpio);
+
+ if (val)
+ writel(1 << offset, addr + DB8500_GPIO_DATS);
+ else
+ writel(1 << offset, addr + DB8500_GPIO_DATC);
+}
+
+/**
+ * config_pin - configure a pin's mux attributes
+ * @cfg: pin confguration
+ *
+ * Configures a pin's mode (alternate function or GPIO), its pull up status,
+ * and its sleep mode based on the specified configuration. The @cfg is
+ * usually one of the SoC specific macros defined in mach/<soc>-pins.h. These
+ * are constructed using, and can be further enhanced with, the macros in
+ * plat/pincfg.h.
+ *
+ * If a pin's mode is set to GPIO, it is configured as an input to avoid
+ * side-effects. The gpio can be manipulated later using standard GPIO API
+ * calls.
+ */
+static void config_pin(unsigned long cfg)
+{
+ int pin = PIN_NUM(cfg);
+ int pull = PIN_PULL(cfg);
+ int af = PIN_ALT(cfg);
+ int output = PIN_DIR(cfg);
+ int val = PIN_VAL(cfg);
+
+ if (output)
+ db8500_gpio_make_output(pin, val);
+ else {
+ db8500_gpio_make_input(pin);
+ db8500_gpio_set_pull(pin, pull);
+ }
+
+ gpio_set_mode(pin, af);
+}
+
+/**
+ * db8500_config_pins - configure several pins at once
+ * @cfgs: array of pin configurations
+ * @num: number of elments in the array
+ *
+ * Configures several pins using config_pin(). Refer to that function for
+ * further information.
+ */
+void db8500_gpio_config_pins(unsigned long *cfgs, size_t num)
+{
+ size_t i;
+
+ for (i = 0; i < num; i++)
+ config_pin(cfgs[i]);
+}
diff --git a/qemu/roms/u-boot/drivers/gpio/gpio-uclass.c b/qemu/roms/u-boot/drivers/gpio/gpio-uclass.c
new file mode 100644
index 000000000..56bfd1146
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/gpio-uclass.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2013 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/gpio.h>
+
+/**
+ * gpio_to_device() - Convert global GPIO number to device, number
+ * gpio: The numeric representation of the GPIO
+ *
+ * Convert the GPIO number to an entry in the list of GPIOs
+ * or GPIO blocks registered with the GPIO controller. Returns
+ * entry on success, NULL on error.
+ */
+static int gpio_to_device(unsigned int gpio, struct device **devp,
+ unsigned int *offset)
+{
+ struct gpio_dev_priv *uc_priv;
+ struct device *dev;
+ int ret;
+
+ for (ret = uclass_first_device(UCLASS_GPIO, &dev);
+ dev;
+ ret = uclass_next_device(&dev)) {
+ uc_priv = dev->uclass_priv;
+ if (gpio >= uc_priv->gpio_base &&
+ gpio < uc_priv->gpio_base + uc_priv->gpio_count) {
+ *devp = dev;
+ *offset = gpio - uc_priv->gpio_base;
+ return 0;
+ }
+ }
+
+ /* No such GPIO */
+ return ret ? ret : -EINVAL;
+}
+
+int gpio_lookup_name(const char *name, struct device **devp,
+ unsigned int *offsetp, unsigned int *gpiop)
+{
+ struct gpio_dev_priv *uc_priv;
+ struct device *dev;
+ int ret;
+
+ if (devp)
+ *devp = NULL;
+ for (ret = uclass_first_device(UCLASS_GPIO, &dev);
+ dev;
+ ret = uclass_next_device(&dev)) {
+ ulong offset;
+ int len;
+
+ uc_priv = dev->uclass_priv;
+ len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0;
+
+ if (!strncmp(name, uc_priv->bank_name, len)) {
+ if (strict_strtoul(name + len, 10, &offset))
+ continue;
+ if (devp)
+ *devp = dev;
+ if (offsetp)
+ *offsetp = offset;
+ if (gpiop)
+ *gpiop = uc_priv->gpio_base + offset;
+ return 0;
+ }
+ }
+
+ return ret ? ret : -EINVAL;
+}
+
+/**
+ * gpio_request() - [COMPAT] Request GPIO
+ * gpio: GPIO number
+ * label: Name for the requested GPIO
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns 0 on success, negative value on error.
+ */
+int gpio_request(unsigned gpio, const char *label)
+{
+ unsigned int offset;
+ struct device *dev;
+ int ret;
+
+ ret = gpio_to_device(gpio, &dev, &offset);
+ if (ret)
+ return ret;
+
+ if (!gpio_get_ops(dev)->request)
+ return 0;
+
+ return gpio_get_ops(dev)->request(dev, offset, label);
+}
+
+/**
+ * gpio_free() - [COMPAT] Relinquish GPIO
+ * gpio: GPIO number
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns 0 on success, negative value on error.
+ */
+int gpio_free(unsigned gpio)
+{
+ unsigned int offset;
+ struct device *dev;
+ int ret;
+
+ ret = gpio_to_device(gpio, &dev, &offset);
+ if (ret)
+ return ret;
+
+ if (!gpio_get_ops(dev)->free)
+ return 0;
+ return gpio_get_ops(dev)->free(dev, offset);
+}
+
+/**
+ * gpio_direction_input() - [COMPAT] Set GPIO direction to input
+ * gpio: GPIO number
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns 0 on success, negative value on error.
+ */
+int gpio_direction_input(unsigned gpio)
+{
+ unsigned int offset;
+ struct device *dev;
+ int ret;
+
+ ret = gpio_to_device(gpio, &dev, &offset);
+ if (ret)
+ return ret;
+
+ return gpio_get_ops(dev)->direction_input(dev, offset);
+}
+
+/**
+ * gpio_direction_output() - [COMPAT] Set GPIO direction to output and set value
+ * gpio: GPIO number
+ * value: Logical value to be set on the GPIO pin
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns 0 on success, negative value on error.
+ */
+int gpio_direction_output(unsigned gpio, int value)
+{
+ unsigned int offset;
+ struct device *dev;
+ int ret;
+
+ ret = gpio_to_device(gpio, &dev, &offset);
+ if (ret)
+ return ret;
+
+ return gpio_get_ops(dev)->direction_output(dev, offset, value);
+}
+
+/**
+ * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value
+ * gpio: GPIO number
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns the value of the GPIO pin, or negative value
+ * on error.
+ */
+int gpio_get_value(unsigned gpio)
+{
+ unsigned int offset;
+ struct device *dev;
+ int ret;
+
+ ret = gpio_to_device(gpio, &dev, &offset);
+ if (ret)
+ return ret;
+
+ return gpio_get_ops(dev)->get_value(dev, offset);
+}
+
+/**
+ * gpio_set_value() - [COMPAT] Configure logical value on GPIO pin
+ * gpio: GPIO number
+ * value: Logical value to be set on the GPIO pin.
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns 0 on success, negative value on error.
+ */
+int gpio_set_value(unsigned gpio, int value)
+{
+ unsigned int offset;
+ struct device *dev;
+ int ret;
+
+ ret = gpio_to_device(gpio, &dev, &offset);
+ if (ret)
+ return ret;
+
+ return gpio_get_ops(dev)->set_value(dev, offset, value);
+}
+
+const char *gpio_get_bank_info(struct device *dev, int *bit_count)
+{
+ struct gpio_dev_priv *priv;
+
+ /* Must be called on an active device */
+ priv = dev->uclass_priv;
+ assert(priv);
+
+ *bit_count = priv->gpio_count;
+ return priv->bank_name;
+}
+
+/* We need to renumber the GPIOs when any driver is probed/removed */
+static int gpio_renumber(void)
+{
+ struct gpio_dev_priv *uc_priv;
+ struct device *dev;
+ struct uclass *uc;
+ unsigned base;
+ int ret;
+
+ ret = uclass_get(UCLASS_GPIO, &uc);
+ if (ret)
+ return ret;
+
+ /* Ensure that we have a base for each bank */
+ base = 0;
+ uclass_foreach_dev(dev, uc) {
+ if (device_active(dev)) {
+ uc_priv = dev->uclass_priv;
+ uc_priv->gpio_base = base;
+ base += uc_priv->gpio_count;
+ }
+ }
+
+ return 0;
+}
+
+static int gpio_post_probe(struct device *dev)
+{
+ return gpio_renumber();
+}
+
+static int gpio_pre_remove(struct device *dev)
+{
+ return gpio_renumber();
+}
+
+UCLASS_DRIVER(gpio) = {
+ .id = UCLASS_GPIO,
+ .name = "gpio",
+ .post_probe = gpio_post_probe,
+ .pre_remove = gpio_pre_remove,
+ .per_device_auto_alloc_size = sizeof(struct gpio_dev_priv),
+};
diff --git a/qemu/roms/u-boot/drivers/gpio/intel_ich6_gpio.c b/qemu/roms/u-boot/drivers/gpio/intel_ich6_gpio.c
new file mode 100644
index 000000000..7d9fac723
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/intel_ich6_gpio.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2012 The Chromium OS Authors.
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*
+ * This is a GPIO driver for Intel ICH6 and later. The x86 GPIOs are accessed
+ * through the PCI bus. Each PCI device has 256 bytes of configuration space,
+ * consisting of a standard header and a device-specific set of registers. PCI
+ * bus 0, device 31, function 0 gives us access to the chipset GPIOs (among
+ * other things). Within the PCI configuration space, the GPIOBASE register
+ * tells us where in the device's I/O region we can find more registers to
+ * actually access the GPIOs.
+ *
+ * PCI bus/device/function 0:1f:0 => PCI config registers
+ * PCI config register "GPIOBASE"
+ * PCI I/O space + [GPIOBASE] => start of GPIO registers
+ * GPIO registers => gpio pin function, direction, value
+ *
+ *
+ * Danger Will Robinson! Bank 0 (GPIOs 0-31) seems to be fairly stable. Most
+ * ICH versions have more, but the decoding the matrix that describes them is
+ * absurdly complex and constantly changing. We'll provide Bank 1 and Bank 2,
+ * but they will ONLY work for certain unspecified chipsets because the offset
+ * from GPIOBASE changes randomly. Even then, many GPIOs are unimplemented or
+ * reserved or subject to arcane restrictions.
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+
+/* Where in config space is the register that points to the GPIO registers? */
+#define PCI_CFG_GPIOBASE 0x48
+
+#define NUM_BANKS 3
+
+/* Within the I/O space, where are the registers to control the GPIOs? */
+static struct {
+ u8 use_sel;
+ u8 io_sel;
+ u8 lvl;
+} gpio_bank[NUM_BANKS] = {
+ { 0x00, 0x04, 0x0c }, /* Bank 0 */
+ { 0x30, 0x34, 0x38 }, /* Bank 1 */
+ { 0x40, 0x44, 0x48 } /* Bank 2 */
+};
+
+static pci_dev_t dev; /* handle for 0:1f:0 */
+static u32 gpiobase; /* offset into I/O space */
+static int found_it_once; /* valid GPIO device? */
+static u32 lock[NUM_BANKS]; /* "lock" for access to pins */
+
+static int bad_arg(int num, int *bank, int *bitnum)
+{
+ int i = num / 32;
+ int j = num % 32;
+
+ if (num < 0 || i > NUM_BANKS) {
+ debug("%s: bogus gpio num: %d\n", __func__, num);
+ return -1;
+ }
+ *bank = i;
+ *bitnum = j;
+ return 0;
+}
+
+static int mark_gpio(int bank, int bitnum)
+{
+ if (lock[bank] & (1UL << bitnum)) {
+ debug("%s: %d.%d already marked\n", __func__, bank, bitnum);
+ return -1;
+ }
+ lock[bank] |= (1 << bitnum);
+ return 0;
+}
+
+static void clear_gpio(int bank, int bitnum)
+{
+ lock[bank] &= ~(1 << bitnum);
+}
+
+static int notmine(int num, int *bank, int *bitnum)
+{
+ if (bad_arg(num, bank, bitnum))
+ return -1;
+ return !(lock[*bank] & (1UL << *bitnum));
+}
+
+static int gpio_init(void)
+{
+ u8 tmpbyte;
+ u16 tmpword;
+ u32 tmplong;
+
+ /* Have we already done this? */
+ if (found_it_once)
+ return 0;
+
+ /* Where should it be? */
+ dev = PCI_BDF(0, 0x1f, 0);
+
+ /* Is the device present? */
+ pci_read_config_word(dev, PCI_VENDOR_ID, &tmpword);
+ if (tmpword != PCI_VENDOR_ID_INTEL) {
+ debug("%s: wrong VendorID\n", __func__);
+ return -1;
+ }
+
+ pci_read_config_word(dev, PCI_DEVICE_ID, &tmpword);
+ debug("Found %04x:%04x\n", PCI_VENDOR_ID_INTEL, tmpword);
+ /*
+ * We'd like to validate the Device ID too, but pretty much any
+ * value is either a) correct with slight differences, or b)
+ * correct but undocumented. We'll have to check a bunch of other
+ * things instead...
+ */
+
+ /* I/O should already be enabled (it's a RO bit). */
+ pci_read_config_word(dev, PCI_COMMAND, &tmpword);
+ if (!(tmpword & PCI_COMMAND_IO)) {
+ debug("%s: device IO not enabled\n", __func__);
+ return -1;
+ }
+
+ /* Header Type must be normal (bits 6-0 only; see spec.) */
+ pci_read_config_byte(dev, PCI_HEADER_TYPE, &tmpbyte);
+ if ((tmpbyte & 0x7f) != PCI_HEADER_TYPE_NORMAL) {
+ debug("%s: invalid Header type\n", __func__);
+ return -1;
+ }
+
+ /* Base Class must be a bridge device */
+ pci_read_config_byte(dev, PCI_CLASS_CODE, &tmpbyte);
+ if (tmpbyte != PCI_CLASS_CODE_BRIDGE) {
+ debug("%s: invalid class\n", __func__);
+ return -1;
+ }
+ /* Sub Class must be ISA */
+ pci_read_config_byte(dev, PCI_CLASS_SUB_CODE, &tmpbyte);
+ if (tmpbyte != PCI_CLASS_SUB_CODE_BRIDGE_ISA) {
+ debug("%s: invalid subclass\n", __func__);
+ return -1;
+ }
+
+ /* Programming Interface must be 0x00 (no others exist) */
+ pci_read_config_byte(dev, PCI_CLASS_PROG, &tmpbyte);
+ if (tmpbyte != 0x00) {
+ debug("%s: invalid interface type\n", __func__);
+ return -1;
+ }
+
+ /*
+ * GPIOBASE moved to its current offset with ICH6, but prior to
+ * that it was unused (or undocumented). Check that it looks
+ * okay: not all ones or zeros, and mapped to I/O space (bit 0).
+ */
+ pci_read_config_dword(dev, PCI_CFG_GPIOBASE, &tmplong);
+ if (tmplong == 0x00000000 || tmplong == 0xffffffff ||
+ !(tmplong & 0x00000001)) {
+ debug("%s: unexpected GPIOBASE value\n", __func__);
+ return -1;
+ }
+
+ /*
+ * Okay, I guess we're looking at the right device. The actual
+ * GPIO registers are in the PCI device's I/O space, starting
+ * at the offset that we just read. Bit 0 indicates that it's
+ * an I/O address, not a memory address, so mask that off.
+ */
+ gpiobase = tmplong & 0xfffffffe;
+
+ /* Finally. These are the droids we're looking for. */
+ found_it_once = 1;
+ return 0;
+}
+
+int gpio_request(unsigned num, const char *label /* UNUSED */)
+{
+ u32 tmplong;
+ int i = 0, j = 0;
+
+ /* Is the hardware ready? */
+ if (gpio_init())
+ return -1;
+
+ if (bad_arg(num, &i, &j))
+ return -1;
+
+ /*
+ * Make sure that the GPIO pin we want isn't already in use for some
+ * built-in hardware function. We have to check this for every
+ * requested pin.
+ */
+ tmplong = inl(gpiobase + gpio_bank[i].use_sel);
+ if (!(tmplong & (1UL << j))) {
+ debug("%s: gpio %d is reserved for internal use\n", __func__,
+ num);
+ return -1;
+ }
+
+ return mark_gpio(i, j);
+}
+
+int gpio_free(unsigned num)
+{
+ int i = 0, j = 0;
+
+ if (notmine(num, &i, &j))
+ return -1;
+
+ clear_gpio(i, j);
+ return 0;
+}
+
+int gpio_direction_input(unsigned num)
+{
+ u32 tmplong;
+ int i = 0, j = 0;
+
+ if (notmine(num, &i, &j))
+ return -1;
+
+ tmplong = inl(gpiobase + gpio_bank[i].io_sel);
+ tmplong |= (1UL << j);
+ outl(gpiobase + gpio_bank[i].io_sel, tmplong);
+ return 0;
+}
+
+int gpio_direction_output(unsigned num, int value)
+{
+ u32 tmplong;
+ int i = 0, j = 0;
+
+ if (notmine(num, &i, &j))
+ return -1;
+
+ tmplong = inl(gpiobase + gpio_bank[i].io_sel);
+ tmplong &= ~(1UL << j);
+ outl(gpiobase + gpio_bank[i].io_sel, tmplong);
+ return 0;
+}
+
+int gpio_get_value(unsigned num)
+{
+ u32 tmplong;
+ int i = 0, j = 0;
+ int r;
+
+ if (notmine(num, &i, &j))
+ return -1;
+
+ tmplong = inl(gpiobase + gpio_bank[i].lvl);
+ r = (tmplong & (1UL << j)) ? 1 : 0;
+ return r;
+}
+
+int gpio_set_value(unsigned num, int value)
+{
+ u32 tmplong;
+ int i = 0, j = 0;
+
+ if (notmine(num, &i, &j))
+ return -1;
+
+ tmplong = inl(gpiobase + gpio_bank[i].lvl);
+ if (value)
+ tmplong |= (1UL << j);
+ else
+ tmplong &= ~(1UL << j);
+ outl(gpiobase + gpio_bank[i].lvl, tmplong);
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/gpio/kona_gpio.c b/qemu/roms/u-boot/drivers/gpio/kona_gpio.c
new file mode 100644
index 000000000..65117438c
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/kona_gpio.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2013 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/sysmap.h>
+
+#define GPIO_BASE (void *)GPIO2_BASE_ADDR
+
+#define GPIO_PASSWD 0x00a5a501
+#define GPIO_PER_BANK 32
+#define GPIO_MAX_BANK_NUM 8
+
+#define GPIO_BANK(gpio) ((gpio) >> 5)
+#define GPIO_BITMASK(gpio) \
+ (1UL << ((gpio) & (GPIO_PER_BANK - 1)))
+
+#define GPIO_OUT_STATUS(bank) (0x00000000 + ((bank) << 2))
+#define GPIO_IN_STATUS(bank) (0x00000020 + ((bank) << 2))
+#define GPIO_OUT_SET(bank) (0x00000040 + ((bank) << 2))
+#define GPIO_OUT_CLEAR(bank) (0x00000060 + ((bank) << 2))
+#define GPIO_INT_STATUS(bank) (0x00000080 + ((bank) << 2))
+#define GPIO_INT_MASK(bank) (0x000000a0 + ((bank) << 2))
+#define GPIO_INT_MSKCLR(bank) (0x000000c0 + ((bank) << 2))
+#define GPIO_CONTROL(bank) (0x00000100 + ((bank) << 2))
+#define GPIO_PWD_STATUS(bank) (0x00000500 + ((bank) << 2))
+
+#define GPIO_GPPWR_OFFSET 0x00000520
+
+#define GPIO_GPCTR0_DBR_SHIFT 5
+#define GPIO_GPCTR0_DBR_MASK 0x000001e0
+
+#define GPIO_GPCTR0_ITR_SHIFT 3
+#define GPIO_GPCTR0_ITR_MASK 0x00000018
+#define GPIO_GPCTR0_ITR_CMD_RISING_EDGE 0x00000001
+#define GPIO_GPCTR0_ITR_CMD_FALLING_EDGE 0x00000002
+#define GPIO_GPCTR0_ITR_CMD_BOTH_EDGE 0x00000003
+
+#define GPIO_GPCTR0_IOTR_MASK 0x00000001
+#define GPIO_GPCTR0_IOTR_CMD_0UTPUT 0x00000000
+#define GPIO_GPCTR0_IOTR_CMD_INPUT 0x00000001
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ unsigned int value, off;
+
+ writel(GPIO_PASSWD, GPIO_BASE + GPIO_GPPWR_OFFSET);
+ off = GPIO_PWD_STATUS(GPIO_BANK(gpio));
+ value = readl(GPIO_BASE + off) & ~GPIO_BITMASK(gpio);
+ writel(value, GPIO_BASE + off);
+
+ return 0;
+}
+
+int gpio_free(unsigned gpio)
+{
+ unsigned int value, off;
+
+ writel(GPIO_PASSWD, GPIO_BASE + GPIO_GPPWR_OFFSET);
+ off = GPIO_PWD_STATUS(GPIO_BANK(gpio));
+ value = readl(GPIO_BASE + off) | GPIO_BITMASK(gpio);
+ writel(value, GPIO_BASE + off);
+
+ return 0;
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+ u32 val;
+
+ val = readl(GPIO_BASE + GPIO_CONTROL(gpio));
+ val &= ~GPIO_GPCTR0_IOTR_MASK;
+ val |= GPIO_GPCTR0_IOTR_CMD_INPUT;
+ writel(val, GPIO_BASE + GPIO_CONTROL(gpio));
+
+ return 0;
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ int bank_id = GPIO_BANK(gpio);
+ int bitmask = GPIO_BITMASK(gpio);
+ u32 val, off;
+
+ val = readl(GPIO_BASE + GPIO_CONTROL(gpio));
+ val &= ~GPIO_GPCTR0_IOTR_MASK;
+ val |= GPIO_GPCTR0_IOTR_CMD_0UTPUT;
+ writel(val, GPIO_BASE + GPIO_CONTROL(gpio));
+ off = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id);
+
+ val = readl(GPIO_BASE + off);
+ val |= bitmask;
+ writel(val, GPIO_BASE + off);
+
+ return 0;
+}
+
+int gpio_get_value(unsigned gpio)
+{
+ int bank_id = GPIO_BANK(gpio);
+ int bitmask = GPIO_BITMASK(gpio);
+ u32 val, off;
+
+ /* determine the GPIO pin direction */
+ val = readl(GPIO_BASE + GPIO_CONTROL(gpio));
+ val &= GPIO_GPCTR0_IOTR_MASK;
+
+ /* read the GPIO bank status */
+ off = (GPIO_GPCTR0_IOTR_CMD_INPUT == val) ?
+ GPIO_IN_STATUS(bank_id) : GPIO_OUT_STATUS(bank_id);
+ val = readl(GPIO_BASE + off);
+
+ /* return the specified bit status */
+ return !!(val & bitmask);
+}
+
+void gpio_set_value(unsigned gpio, int value)
+{
+ int bank_id = GPIO_BANK(gpio);
+ int bitmask = GPIO_BITMASK(gpio);
+ u32 val, off;
+
+ /* determine the GPIO pin direction */
+ val = readl(GPIO_BASE + GPIO_CONTROL(gpio));
+ val &= GPIO_GPCTR0_IOTR_MASK;
+
+ /* this function only applies to output pin */
+ if (GPIO_GPCTR0_IOTR_CMD_INPUT == val) {
+ printf("%s: Cannot set an input pin %d\n", __func__, gpio);
+ return;
+ }
+
+ off = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id);
+
+ val = readl(GPIO_BASE + off);
+ val |= bitmask;
+ writel(val, GPIO_BASE + off);
+}
diff --git a/qemu/roms/u-boot/drivers/gpio/kw_gpio.c b/qemu/roms/u-boot/drivers/gpio/kw_gpio.c
new file mode 100644
index 000000000..0af75a84e
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/kw_gpio.c
@@ -0,0 +1,150 @@
+/*
+ * arch/arm/plat-orion/gpio.c
+ *
+ * Marvell Orion SoC GPIO handling.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*
+ * Based on (mostly copied from) plat-orion based Linux 2.6 kernel driver.
+ * Removed orion_gpiochip struct and kernel level irq handling.
+ *
+ * Dieter Kiermaier dk-arm-linux@gmx.de
+ */
+
+#include <common.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/arch/kirkwood.h>
+#include <asm/arch/gpio.h>
+
+static unsigned long gpio_valid_input[BITS_TO_LONGS(GPIO_MAX)];
+static unsigned long gpio_valid_output[BITS_TO_LONGS(GPIO_MAX)];
+
+void __set_direction(unsigned pin, int input)
+{
+ u32 u;
+
+ u = readl(GPIO_IO_CONF(pin));
+ if (input)
+ u |= 1 << (pin & 31);
+ else
+ u &= ~(1 << (pin & 31));
+ writel(u, GPIO_IO_CONF(pin));
+
+ u = readl(GPIO_IO_CONF(pin));
+}
+
+void __set_level(unsigned pin, int high)
+{
+ u32 u;
+
+ u = readl(GPIO_OUT(pin));
+ if (high)
+ u |= 1 << (pin & 31);
+ else
+ u &= ~(1 << (pin & 31));
+ writel(u, GPIO_OUT(pin));
+}
+
+void __set_blinking(unsigned pin, int blink)
+{
+ u32 u;
+
+ u = readl(GPIO_BLINK_EN(pin));
+ if (blink)
+ u |= 1 << (pin & 31);
+ else
+ u &= ~(1 << (pin & 31));
+ writel(u, GPIO_BLINK_EN(pin));
+}
+
+int kw_gpio_is_valid(unsigned pin, int mode)
+{
+ if (pin < GPIO_MAX) {
+ if ((mode & GPIO_INPUT_OK) && !test_bit(pin, gpio_valid_input))
+ goto err_out;
+
+ if ((mode & GPIO_OUTPUT_OK) && !test_bit(pin, gpio_valid_output))
+ goto err_out;
+ return 0;
+ }
+
+err_out:
+ printf("%s: invalid GPIO %d\n", __func__, pin);
+ return 1;
+}
+
+void kw_gpio_set_valid(unsigned pin, int mode)
+{
+ if (mode == 1)
+ mode = GPIO_INPUT_OK | GPIO_OUTPUT_OK;
+ if (mode & GPIO_INPUT_OK)
+ __set_bit(pin, gpio_valid_input);
+ else
+ __clear_bit(pin, gpio_valid_input);
+ if (mode & GPIO_OUTPUT_OK)
+ __set_bit(pin, gpio_valid_output);
+ else
+ __clear_bit(pin, gpio_valid_output);
+}
+/*
+ * GENERIC_GPIO primitives.
+ */
+int kw_gpio_direction_input(unsigned pin)
+{
+ if (kw_gpio_is_valid(pin, GPIO_INPUT_OK) != 0)
+ return 1;
+
+ /* Configure GPIO direction. */
+ __set_direction(pin, 1);
+
+ return 0;
+}
+
+int kw_gpio_direction_output(unsigned pin, int value)
+{
+ if (kw_gpio_is_valid(pin, GPIO_OUTPUT_OK) != 0)
+ {
+ printf("%s: invalid GPIO %d\n", __func__, pin);
+ return 1;
+ }
+
+ __set_blinking(pin, 0);
+
+ /* Configure GPIO output value. */
+ __set_level(pin, value);
+
+ /* Configure GPIO direction. */
+ __set_direction(pin, 0);
+
+ return 0;
+}
+
+int kw_gpio_get_value(unsigned pin)
+{
+ int val;
+
+ if (readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31)))
+ val = readl(GPIO_DATA_IN(pin)) ^ readl(GPIO_IN_POL(pin));
+ else
+ val = readl(GPIO_OUT(pin));
+
+ return (val >> (pin & 31)) & 1;
+}
+
+void kw_gpio_set_value(unsigned pin, int value)
+{
+ /* Configure GPIO output value. */
+ __set_level(pin, value);
+}
+
+void kw_gpio_set_blink(unsigned pin, int blink)
+{
+ /* Set output value to zero. */
+ __set_level(pin, 0);
+
+ /* Set blinking. */
+ __set_blinking(pin, blink);
+}
diff --git a/qemu/roms/u-boot/drivers/gpio/mpc83xx_gpio.c b/qemu/roms/u-boot/drivers/gpio/mpc83xx_gpio.c
new file mode 100644
index 000000000..92b6e0cb7
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/mpc83xx_gpio.c
@@ -0,0 +1,183 @@
+/*
+ * Freescale MPC83xx GPIO handling.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <mpc83xx.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+
+#ifndef CONFIG_MPC83XX_GPIO_0_INIT_DIRECTION
+#define CONFIG_MPC83XX_GPIO_0_INIT_DIRECTION 0
+#endif
+#ifndef CONFIG_MPC83XX_GPIO_1_INIT_DIRECTION
+#define CONFIG_MPC83XX_GPIO_1_INIT_DIRECTION 0
+#endif
+#ifndef CONFIG_MPC83XX_GPIO_0_INIT_OPEN_DRAIN
+#define CONFIG_MPC83XX_GPIO_0_INIT_OPEN_DRAIN 0
+#endif
+#ifndef CONFIG_MPC83XX_GPIO_1_INIT_OPEN_DRAIN
+#define CONFIG_MPC83XX_GPIO_1_INIT_OPEN_DRAIN 0
+#endif
+#ifndef CONFIG_MPC83XX_GPIO_0_INIT_VALUE
+#define CONFIG_MPC83XX_GPIO_0_INIT_VALUE 0
+#endif
+#ifndef CONFIG_MPC83XX_GPIO_1_INIT_VALUE
+#define CONFIG_MPC83XX_GPIO_1_INIT_VALUE 0
+#endif
+
+static unsigned int gpio_output_value[MPC83XX_GPIO_CTRLRS];
+
+/*
+ * Generic_GPIO primitives.
+ */
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ if (gpio >= MAX_NUM_GPIOS)
+ return -1;
+
+ return 0;
+}
+
+int gpio_free(unsigned gpio)
+{
+ /* Do not set to input */
+ return 0;
+}
+
+/* set GPIO pin 'gpio' as an input */
+int gpio_direction_input(unsigned gpio)
+{
+ immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ unsigned int ctrlr;
+ unsigned int line;
+ unsigned int line_mask;
+
+ /* 32-bits per controller */
+ ctrlr = gpio >> 5;
+ line = gpio & (0x1F);
+
+ /* Big endian */
+ line_mask = 1 << (31 - line);
+
+ clrbits_be32(&im->gpio[ctrlr].dir, line_mask);
+
+ return 0;
+}
+
+/* set GPIO pin 'gpio' as an output, with polarity 'value' */
+int gpio_direction_output(unsigned gpio, int value)
+{
+ immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ unsigned int ctrlr;
+ unsigned int line;
+ unsigned int line_mask;
+
+ if (value != 0 && value != 1) {
+ printf("Error: Value parameter must be 0 or 1.\n");
+ return -1;
+ }
+
+ gpio_set_value(gpio, value);
+
+ /* 32-bits per controller */
+ ctrlr = gpio >> 5;
+ line = gpio & (0x1F);
+
+ /* Big endian */
+ line_mask = 1 << (31 - line);
+
+ /* Make the line output */
+ setbits_be32(&im->gpio[ctrlr].dir, line_mask);
+
+ return 0;
+}
+
+/* read GPIO IN value of pin 'gpio' */
+int gpio_get_value(unsigned gpio)
+{
+ immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ unsigned int ctrlr;
+ unsigned int line;
+ unsigned int line_mask;
+
+ /* 32-bits per controller */
+ ctrlr = gpio >> 5;
+ line = gpio & (0x1F);
+
+ /* Big endian */
+ line_mask = 1 << (31 - line);
+
+ /* Read the value and mask off the bit */
+ return (in_be32(&im->gpio[ctrlr].dat) & line_mask) != 0;
+}
+
+/* write GPIO OUT value to pin 'gpio' */
+int gpio_set_value(unsigned gpio, int value)
+{
+ immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ unsigned int ctrlr;
+ unsigned int line;
+ unsigned int line_mask;
+
+ if (value != 0 && value != 1) {
+ printf("Error: Value parameter must be 0 or 1.\n");
+ return -1;
+ }
+
+ /* 32-bits per controller */
+ ctrlr = gpio >> 5;
+ line = gpio & (0x1F);
+
+ /* Big endian */
+ line_mask = 1 << (31 - line);
+
+ /* Update the local output buffer soft copy */
+ gpio_output_value[ctrlr] =
+ (gpio_output_value[ctrlr] & ~line_mask) | \
+ (value ? line_mask : 0);
+
+ /* Write the output */
+ out_be32(&im->gpio[ctrlr].dat, gpio_output_value[ctrlr]);
+
+ return 0;
+}
+
+/* Configure GPIO registers early */
+void mpc83xx_gpio_init_f(void)
+{
+ immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+
+#if MPC83XX_GPIO_CTRLRS >= 1
+ out_be32(&im->gpio[0].dir, CONFIG_MPC83XX_GPIO_0_INIT_DIRECTION);
+ out_be32(&im->gpio[0].odr, CONFIG_MPC83XX_GPIO_0_INIT_OPEN_DRAIN);
+ out_be32(&im->gpio[0].dat, CONFIG_MPC83XX_GPIO_0_INIT_VALUE);
+ out_be32(&im->gpio[0].ier, 0xFFFFFFFF); /* Clear all events */
+ out_be32(&im->gpio[0].imr, 0);
+ out_be32(&im->gpio[0].icr, 0);
+#endif
+
+#if MPC83XX_GPIO_CTRLRS >= 2
+ out_be32(&im->gpio[1].dir, CONFIG_MPC83XX_GPIO_1_INIT_DIRECTION);
+ out_be32(&im->gpio[1].odr, CONFIG_MPC83XX_GPIO_1_INIT_OPEN_DRAIN);
+ out_be32(&im->gpio[1].dat, CONFIG_MPC83XX_GPIO_1_INIT_VALUE);
+ out_be32(&im->gpio[1].ier, 0xFFFFFFFF); /* Clear all events */
+ out_be32(&im->gpio[1].imr, 0);
+ out_be32(&im->gpio[1].icr, 0);
+#endif
+}
+
+/* Initialize GPIO soft-copies */
+void mpc83xx_gpio_init_r(void)
+{
+#if MPC83XX_GPIO_CTRLRS >= 1
+ gpio_output_value[0] = CONFIG_MPC83XX_GPIO_0_INIT_VALUE;
+#endif
+
+#if MPC83XX_GPIO_CTRLRS >= 2
+ gpio_output_value[1] = CONFIG_MPC83XX_GPIO_1_INIT_VALUE;
+#endif
+}
diff --git a/qemu/roms/u-boot/drivers/gpio/mvgpio.c b/qemu/roms/u-boot/drivers/gpio/mvgpio.c
new file mode 100644
index 000000000..888aa07c4
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/mvgpio.c
@@ -0,0 +1,97 @@
+/*
+ * (C) Copyright 2011
+ * eInfochips Ltd. <www.einfochips.com>
+ * Written-by: Ajay Bhargav <ajay.bhargav@einfochips.com>
+ *
+ * (C) Copyright 2010
+ * Marvell Semiconductor <www.marvell.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include "mvgpio.h"
+#include <asm/gpio.h>
+
+#ifndef MV_MAX_GPIO
+#define MV_MAX_GPIO 128
+#endif
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ if (gpio >= MV_MAX_GPIO) {
+ printf("%s: Invalid GPIO requested %d\n", __func__, gpio);
+ return -1;
+ }
+ return 0;
+}
+
+int gpio_free(unsigned gpio)
+{
+ return 0;
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+ struct gpio_reg *gpio_reg_bank;
+
+ if (gpio >= MV_MAX_GPIO) {
+ printf("%s: Invalid GPIO %d\n", __func__, gpio);
+ return -1;
+ }
+
+ gpio_reg_bank = get_gpio_base(GPIO_TO_REG(gpio));
+ writel(GPIO_TO_BIT(gpio), &gpio_reg_bank->gcdr);
+ return 0;
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ struct gpio_reg *gpio_reg_bank;
+
+ if (gpio >= MV_MAX_GPIO) {
+ printf("%s: Invalid GPIO %d\n", __func__, gpio);
+ return -1;
+ }
+
+ gpio_reg_bank = get_gpio_base(GPIO_TO_REG(gpio));
+ writel(GPIO_TO_BIT(gpio), &gpio_reg_bank->gsdr);
+ gpio_set_value(gpio, value);
+ return 0;
+}
+
+int gpio_get_value(unsigned gpio)
+{
+ struct gpio_reg *gpio_reg_bank;
+ u32 gpio_val;
+
+ if (gpio >= MV_MAX_GPIO) {
+ printf("%s: Invalid GPIO %d\n", __func__, gpio);
+ return -1;
+ }
+
+ gpio_reg_bank = get_gpio_base(GPIO_TO_REG(gpio));
+ gpio_val = readl(&gpio_reg_bank->gplr);
+
+ return GPIO_VAL(gpio, gpio_val);
+}
+
+int gpio_set_value(unsigned gpio, int value)
+{
+ struct gpio_reg *gpio_reg_bank;
+
+ if (gpio >= MV_MAX_GPIO) {
+ printf("%s: Invalid GPIO %d\n", __func__, gpio);
+ return -1;
+ }
+
+ gpio_reg_bank = get_gpio_base(GPIO_TO_REG(gpio));
+ if (value)
+ writel(GPIO_TO_BIT(gpio), &gpio_reg_bank->gpsr);
+ else
+ writel(GPIO_TO_BIT(gpio), &gpio_reg_bank->gpcr);
+
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/gpio/mvgpio.h b/qemu/roms/u-boot/drivers/gpio/mvgpio.h
new file mode 100644
index 000000000..a3f17a0c3
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/mvgpio.h
@@ -0,0 +1,58 @@
+/*
+ * (C) Copyright 2011
+ * eInfochips Ltd. <www.einfochips.com>
+ * Written-by: Ajay Bhargav <ajay.bhargav@einfochips.com>
+ *
+ * (C) Copyright 2010
+ * Marvell Semiconductor <www.marvell.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __MVGPIO_H__
+#define __MVGPIO_H__
+
+#include <common.h>
+
+#ifdef CONFIG_SHEEVA_88SV331xV5
+/*
+ * GPIO Register map for SHEEVA 88SV331xV5
+ */
+struct gpio_reg {
+ u32 gplr; /* Pin Level Register - 0x0000 */
+ u32 pad0[2];
+ u32 gpdr; /* Pin Direction Register - 0x000C */
+ u32 pad1[2];
+ u32 gpsr; /* Pin Output Set Register - 0x0018 */
+ u32 pad2[2];
+ u32 gpcr; /* Pin Output Clear Register - 0x0024 */
+ u32 pad3[2];
+ u32 grer; /* Rising-Edge Detect Enable Register - 0x0030 */
+ u32 pad4[2];
+ u32 gfer; /* Falling-Edge Detect Enable Register - 0x003C */
+ u32 pad5[2];
+ u32 gedr; /* Edge Detect Status Register - 0x0048 */
+ u32 pad6[2];
+ u32 gsdr; /* Bitwise Set of GPIO Direction Register - 0x0054 */
+ u32 pad7[2];
+ u32 gcdr; /* Bitwise Clear of GPIO Direction Register - 0x0060 */
+ u32 pad8[2];
+ u32 gsrer; /* Bitwise Set of Rising-Edge Detect Enable
+ Register - 0x006C */
+ u32 pad9[2];
+ u32 gcrer; /* Bitwise Clear of Rising-Edge Detect Enable
+ Register - 0x0078 */
+ u32 pad10[2];
+ u32 gsfer; /* Bitwise Set of Falling-Edge Detect Enable
+ Register - 0x0084 */
+ u32 pad11[2];
+ u32 gcfer; /* Bitwise Clear of Falling-Edge Detect Enable
+ Register - 0x0090 */
+ u32 pad12[2];
+ u32 apmask; /* Bitwise Mask of Edge Detect Register - 0x009C */
+};
+#else
+#error "CPU core subversion not defined"
+#endif
+
+#endif /* __MVGPIO_H__ */
diff --git a/qemu/roms/u-boot/drivers/gpio/mvmfp.c b/qemu/roms/u-boot/drivers/gpio/mvmfp.c
new file mode 100644
index 000000000..97bbe996f
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/mvmfp.c
@@ -0,0 +1,66 @@
+/*
+ * (C) Copyright 2010
+ * Marvell Semiconductor <www.marvell.com>
+ * Written-by: Prafulla Wadaskar <prafulla@marvell.com>,
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <mvmfp.h>
+#include <asm/arch/mfp.h>
+
+/*
+ * mfp_config
+ *
+ * On most of Marvell SoCs (ex. ARMADA100) there is Multi-Funtion-Pin
+ * configuration registers to configure each GPIO/Function pin on the
+ * SoC.
+ *
+ * This function reads the array of values for
+ * MFPR_X registers and programms them into respective
+ * Multi-Function Pin registers.
+ * It supports - Alternate Function Selection programming.
+ *
+ * Whereas,
+ * The Configureation value is constructed using MFP()
+ * array consists of 32bit values as defined in MFP(xx,xx..) macro
+ */
+void mfp_config(u32 *mfp_cfgs)
+{
+ u32 *p_mfpr = NULL;
+ u32 cfg_val, val;
+
+ do {
+ cfg_val = *mfp_cfgs++;
+ /* exit if End of configuration table detected */
+ if (cfg_val == MFP_EOC)
+ break;
+
+ p_mfpr = (u32 *)(MV_MFPR_BASE
+ + MFP_REG_GET_OFFSET(cfg_val));
+
+ /* Write a mfg register as per configuration */
+ val = 0;
+ if (cfg_val & MFP_AF_FLAG)
+ /* Abstract and program Afternate-Func Selection */
+ val |= cfg_val & MFP_AF_MASK;
+ if (cfg_val & MFP_EDGE_FLAG)
+ /* Abstract and program Edge configuration */
+ val |= cfg_val & MFP_LPM_EDGE_MASK;
+ if (cfg_val & MFP_DRIVE_FLAG)
+ /* Abstract and program Drive configuration */
+ val |= cfg_val & MFP_DRIVE_MASK;
+ if (cfg_val & MFP_PULL_FLAG)
+ /* Abstract and program Pullup/down configuration */
+ val |= cfg_val & MFP_PULL_MASK;
+
+ writel(val, p_mfpr);
+ } while (1);
+ /*
+ * perform a read-back of any MFPR register to make sure the
+ * previous writings are finished
+ */
+ readl(p_mfpr);
+}
diff --git a/qemu/roms/u-boot/drivers/gpio/mxc_gpio.c b/qemu/roms/u-boot/drivers/gpio/mxc_gpio.c
new file mode 100644
index 000000000..6a572d545
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/mxc_gpio.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2009
+ * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
+ *
+ * Copyright (C) 2011
+ * Stefano Babic, DENX Software Engineering, <sbabic@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#include <common.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <errno.h>
+
+enum mxc_gpio_direction {
+ MXC_GPIO_DIRECTION_IN,
+ MXC_GPIO_DIRECTION_OUT,
+};
+
+#define GPIO_TO_PORT(n) (n / 32)
+
+/* GPIO port description */
+static unsigned long gpio_ports[] = {
+ [0] = GPIO1_BASE_ADDR,
+ [1] = GPIO2_BASE_ADDR,
+ [2] = GPIO3_BASE_ADDR,
+#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
+ defined(CONFIG_MX53) || defined(CONFIG_MX6)
+ [3] = GPIO4_BASE_ADDR,
+#endif
+#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
+ [4] = GPIO5_BASE_ADDR,
+ [5] = GPIO6_BASE_ADDR,
+#endif
+#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
+ [6] = GPIO7_BASE_ADDR,
+#endif
+};
+
+static int mxc_gpio_direction(unsigned int gpio,
+ enum mxc_gpio_direction direction)
+{
+ unsigned int port = GPIO_TO_PORT(gpio);
+ struct gpio_regs *regs;
+ u32 l;
+
+ if (port >= ARRAY_SIZE(gpio_ports))
+ return -1;
+
+ gpio &= 0x1f;
+
+ regs = (struct gpio_regs *)gpio_ports[port];
+
+ l = readl(&regs->gpio_dir);
+
+ switch (direction) {
+ case MXC_GPIO_DIRECTION_OUT:
+ l |= 1 << gpio;
+ break;
+ case MXC_GPIO_DIRECTION_IN:
+ l &= ~(1 << gpio);
+ }
+ writel(l, &regs->gpio_dir);
+
+ return 0;
+}
+
+int gpio_set_value(unsigned gpio, int value)
+{
+ unsigned int port = GPIO_TO_PORT(gpio);
+ struct gpio_regs *regs;
+ u32 l;
+
+ if (port >= ARRAY_SIZE(gpio_ports))
+ return -1;
+
+ gpio &= 0x1f;
+
+ regs = (struct gpio_regs *)gpio_ports[port];
+
+ l = readl(&regs->gpio_dr);
+ if (value)
+ l |= 1 << gpio;
+ else
+ l &= ~(1 << gpio);
+ writel(l, &regs->gpio_dr);
+
+ return 0;
+}
+
+int gpio_get_value(unsigned gpio)
+{
+ unsigned int port = GPIO_TO_PORT(gpio);
+ struct gpio_regs *regs;
+ u32 val;
+
+ if (port >= ARRAY_SIZE(gpio_ports))
+ return -1;
+
+ gpio &= 0x1f;
+
+ regs = (struct gpio_regs *)gpio_ports[port];
+
+ val = (readl(&regs->gpio_psr) >> gpio) & 0x01;
+
+ return val;
+}
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ unsigned int port = GPIO_TO_PORT(gpio);
+ if (port >= ARRAY_SIZE(gpio_ports))
+ return -1;
+ return 0;
+}
+
+int gpio_free(unsigned gpio)
+{
+ return 0;
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+ return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_IN);
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ int ret = gpio_set_value(gpio, value);
+
+ if (ret < 0)
+ return ret;
+
+ return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_OUT);
+}
diff --git a/qemu/roms/u-boot/drivers/gpio/mxs_gpio.c b/qemu/roms/u-boot/drivers/gpio/mxs_gpio.c
new file mode 100644
index 000000000..da0199b16
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/mxs_gpio.c
@@ -0,0 +1,116 @@
+/*
+ * Freescale i.MX28 GPIO control code
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <netdev.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/imx-regs.h>
+
+#if defined(CONFIG_MX23)
+#define PINCTRL_BANKS 3
+#define PINCTRL_DOUT(n) (0x0500 + ((n) * 0x10))
+#define PINCTRL_DIN(n) (0x0600 + ((n) * 0x10))
+#define PINCTRL_DOE(n) (0x0700 + ((n) * 0x10))
+#define PINCTRL_PIN2IRQ(n) (0x0800 + ((n) * 0x10))
+#define PINCTRL_IRQEN(n) (0x0900 + ((n) * 0x10))
+#define PINCTRL_IRQSTAT(n) (0x0c00 + ((n) * 0x10))
+#elif defined(CONFIG_MX28)
+#define PINCTRL_BANKS 5
+#define PINCTRL_DOUT(n) (0x0700 + ((n) * 0x10))
+#define PINCTRL_DIN(n) (0x0900 + ((n) * 0x10))
+#define PINCTRL_DOE(n) (0x0b00 + ((n) * 0x10))
+#define PINCTRL_PIN2IRQ(n) (0x1000 + ((n) * 0x10))
+#define PINCTRL_IRQEN(n) (0x1100 + ((n) * 0x10))
+#define PINCTRL_IRQSTAT(n) (0x1400 + ((n) * 0x10))
+#else
+#error "Please select CONFIG_MX23 or CONFIG_MX28"
+#endif
+
+#define GPIO_INT_FALL_EDGE 0x0
+#define GPIO_INT_LOW_LEV 0x1
+#define GPIO_INT_RISE_EDGE 0x2
+#define GPIO_INT_HIGH_LEV 0x3
+#define GPIO_INT_LEV_MASK (1 << 0)
+#define GPIO_INT_POL_MASK (1 << 1)
+
+void mxs_gpio_init(void)
+{
+ int i;
+
+ for (i = 0; i < PINCTRL_BANKS; i++) {
+ writel(0, MXS_PINCTRL_BASE + PINCTRL_PIN2IRQ(i));
+ writel(0, MXS_PINCTRL_BASE + PINCTRL_IRQEN(i));
+ /* Use SCT address here to clear the IRQSTAT bits */
+ writel(0xffffffff, MXS_PINCTRL_BASE + PINCTRL_IRQSTAT(i) + 8);
+ }
+}
+
+int gpio_get_value(unsigned gpio)
+{
+ uint32_t bank = PAD_BANK(gpio);
+ uint32_t offset = PINCTRL_DIN(bank);
+ struct mxs_register_32 *reg =
+ (struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset);
+
+ return (readl(&reg->reg) >> PAD_PIN(gpio)) & 1;
+}
+
+void gpio_set_value(unsigned gpio, int value)
+{
+ uint32_t bank = PAD_BANK(gpio);
+ uint32_t offset = PINCTRL_DOUT(bank);
+ struct mxs_register_32 *reg =
+ (struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset);
+
+ if (value)
+ writel(1 << PAD_PIN(gpio), &reg->reg_set);
+ else
+ writel(1 << PAD_PIN(gpio), &reg->reg_clr);
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+ uint32_t bank = PAD_BANK(gpio);
+ uint32_t offset = PINCTRL_DOE(bank);
+ struct mxs_register_32 *reg =
+ (struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset);
+
+ writel(1 << PAD_PIN(gpio), &reg->reg_clr);
+
+ return 0;
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ uint32_t bank = PAD_BANK(gpio);
+ uint32_t offset = PINCTRL_DOE(bank);
+ struct mxs_register_32 *reg =
+ (struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset);
+
+ gpio_set_value(gpio, value);
+
+ writel(1 << PAD_PIN(gpio), &reg->reg_set);
+
+ return 0;
+}
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ if (PAD_BANK(gpio) >= PINCTRL_BANKS)
+ return -1;
+
+ return 0;
+}
+
+int gpio_free(unsigned gpio)
+{
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/gpio/omap_gpio.c b/qemu/roms/u-boot/drivers/gpio/omap_gpio.c
new file mode 100644
index 000000000..13dcf7987
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/omap_gpio.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2009 Wind River Systems, Inc.
+ * Tom Rix <Tom.Rix@windriver.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ * This work is derived from the linux 2.6.27 kernel source
+ * To fetch, use the kernel repository
+ * git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
+ * Use the v2.6.27 tag.
+ *
+ * Below is the original's header including its copyright
+ *
+ * linux/arch/arm/plat-omap/gpio.c
+ *
+ * Support functions for OMAP GPIO
+ *
+ * Copyright (C) 2003-2005 Nokia Corporation
+ * Written by Juha Yrjölä <juha.yrjola@nokia.com>
+ */
+#include <common.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+
+#define OMAP_GPIO_DIR_OUT 0
+#define OMAP_GPIO_DIR_IN 1
+
+static inline const struct gpio_bank *get_gpio_bank(int gpio)
+{
+ return &omap_gpio_bank[gpio >> 5];
+}
+
+static inline int get_gpio_index(int gpio)
+{
+ return gpio & 0x1f;
+}
+
+int gpio_is_valid(int gpio)
+{
+ return (gpio >= 0) && (gpio < OMAP_MAX_GPIO);
+}
+
+static int check_gpio(int gpio)
+{
+ if (!gpio_is_valid(gpio)) {
+ printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
+ return -1;
+ }
+ return 0;
+}
+
+static void _set_gpio_direction(const struct gpio_bank *bank, int gpio,
+ int is_input)
+{
+ void *reg = bank->base;
+ u32 l;
+
+ switch (bank->method) {
+ case METHOD_GPIO_24XX:
+ reg += OMAP_GPIO_OE;
+ break;
+ default:
+ return;
+ }
+ l = __raw_readl(reg);
+ if (is_input)
+ l |= 1 << gpio;
+ else
+ l &= ~(1 << gpio);
+ __raw_writel(l, reg);
+}
+
+/**
+ * Get the direction of the GPIO by reading the GPIO_OE register
+ * corresponding to the specified bank.
+ */
+static int _get_gpio_direction(const struct gpio_bank *bank, int gpio)
+{
+ void *reg = bank->base;
+ u32 v;
+
+ switch (bank->method) {
+ case METHOD_GPIO_24XX:
+ reg += OMAP_GPIO_OE;
+ break;
+ default:
+ return -1;
+ }
+
+ v = __raw_readl(reg);
+
+ if (v & (1 << gpio))
+ return OMAP_GPIO_DIR_IN;
+ else
+ return OMAP_GPIO_DIR_OUT;
+}
+
+static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio,
+ int enable)
+{
+ void *reg = bank->base;
+ u32 l = 0;
+
+ switch (bank->method) {
+ case METHOD_GPIO_24XX:
+ if (enable)
+ reg += OMAP_GPIO_SETDATAOUT;
+ else
+ reg += OMAP_GPIO_CLEARDATAOUT;
+ l = 1 << gpio;
+ break;
+ default:
+ printf("omap3-gpio unknown bank method %s %d\n",
+ __FILE__, __LINE__);
+ return;
+ }
+ __raw_writel(l, reg);
+}
+
+/**
+ * Set value of the specified gpio
+ */
+int gpio_set_value(unsigned gpio, int value)
+{
+ const struct gpio_bank *bank;
+
+ if (check_gpio(gpio) < 0)
+ return -1;
+ bank = get_gpio_bank(gpio);
+ _set_gpio_dataout(bank, get_gpio_index(gpio), value);
+
+ return 0;
+}
+
+/**
+ * Get value of the specified gpio
+ */
+int gpio_get_value(unsigned gpio)
+{
+ const struct gpio_bank *bank;
+ void *reg;
+ int input;
+
+ if (check_gpio(gpio) < 0)
+ return -1;
+ bank = get_gpio_bank(gpio);
+ reg = bank->base;
+ switch (bank->method) {
+ case METHOD_GPIO_24XX:
+ input = _get_gpio_direction(bank, get_gpio_index(gpio));
+ switch (input) {
+ case OMAP_GPIO_DIR_IN:
+ reg += OMAP_GPIO_DATAIN;
+ break;
+ case OMAP_GPIO_DIR_OUT:
+ reg += OMAP_GPIO_DATAOUT;
+ break;
+ default:
+ return -1;
+ }
+ break;
+ default:
+ return -1;
+ }
+ return (__raw_readl(reg)
+ & (1 << get_gpio_index(gpio))) != 0;
+}
+
+/**
+ * Set gpio direction as input
+ */
+int gpio_direction_input(unsigned gpio)
+{
+ const struct gpio_bank *bank;
+
+ if (check_gpio(gpio) < 0)
+ return -1;
+
+ bank = get_gpio_bank(gpio);
+ _set_gpio_direction(bank, get_gpio_index(gpio), 1);
+
+ return 0;
+}
+
+/**
+ * Set gpio direction as output
+ */
+int gpio_direction_output(unsigned gpio, int value)
+{
+ const struct gpio_bank *bank;
+
+ if (check_gpio(gpio) < 0)
+ return -1;
+
+ bank = get_gpio_bank(gpio);
+ _set_gpio_dataout(bank, get_gpio_index(gpio), value);
+ _set_gpio_direction(bank, get_gpio_index(gpio), 0);
+
+ return 0;
+}
+
+/**
+ * Request a gpio before using it.
+ *
+ * NOTE: Argument 'label' is unused.
+ */
+int gpio_request(unsigned gpio, const char *label)
+{
+ if (check_gpio(gpio) < 0)
+ return -1;
+
+ return 0;
+}
+
+/**
+ * Reset and free the gpio after using it.
+ */
+int gpio_free(unsigned gpio)
+{
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/gpio/pca953x.c b/qemu/roms/u-boot/drivers/gpio/pca953x.c
new file mode 100644
index 000000000..7371cd4a8
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/pca953x.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2008 Extreme Engineering Solutions, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * Driver for NXP's 4, 8 and 16 bit I2C gpio expanders (eg pca9537, pca9557,
+ * pca9539, etc)
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <pca953x.h>
+
+/* Default to an address that hopefully won't corrupt other i2c devices */
+#ifndef CONFIG_SYS_I2C_PCA953X_ADDR
+#define CONFIG_SYS_I2C_PCA953X_ADDR (~0)
+#endif
+
+enum {
+ PCA953X_CMD_INFO,
+ PCA953X_CMD_DEVICE,
+ PCA953X_CMD_OUTPUT,
+ PCA953X_CMD_INPUT,
+ PCA953X_CMD_INVERT,
+};
+
+#ifdef CONFIG_SYS_I2C_PCA953X_WIDTH
+struct pca953x_chip_ngpio {
+ uint8_t chip;
+ uint8_t ngpio;
+};
+
+static struct pca953x_chip_ngpio pca953x_chip_ngpios[] =
+ CONFIG_SYS_I2C_PCA953X_WIDTH;
+
+/*
+ * Determine the number of GPIO pins supported. If we don't know we assume
+ * 8 pins.
+ */
+static int pca953x_ngpio(uint8_t chip)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pca953x_chip_ngpios); i++)
+ if (pca953x_chip_ngpios[i].chip == chip)
+ return pca953x_chip_ngpios[i].ngpio;
+
+ return 8;
+}
+#else
+static int pca953x_ngpio(uint8_t chip)
+{
+ return 8;
+}
+#endif
+
+/*
+ * Modify masked bits in register
+ */
+static int pca953x_reg_write(uint8_t chip, uint addr, uint mask, uint data)
+{
+ uint8_t valb;
+ uint16_t valw;
+
+ if (pca953x_ngpio(chip) <= 8) {
+ if (i2c_read(chip, addr, 1, &valb, 1))
+ return -1;
+
+ valb &= ~mask;
+ valb |= data;
+
+ return i2c_write(chip, addr, 1, &valb, 1);
+ } else {
+ if (i2c_read(chip, addr << 1, 1, (u8*)&valw, 2))
+ return -1;
+
+ valw &= ~mask;
+ valw |= data;
+
+ return i2c_write(chip, addr << 1, 1, (u8*)&valw, 2);
+ }
+}
+
+static int pca953x_reg_read(uint8_t chip, uint addr, uint *data)
+{
+ uint8_t valb;
+ uint16_t valw;
+
+ if (pca953x_ngpio(chip) <= 8) {
+ if (i2c_read(chip, addr, 1, &valb, 1))
+ return -1;
+ *data = (int)valb;
+ } else {
+ if (i2c_read(chip, addr << 1, 1, (u8*)&valw, 2))
+ return -1;
+ *data = (int)valw;
+ }
+ return 0;
+}
+
+/*
+ * Set output value of IO pins in 'mask' to corresponding value in 'data'
+ * 0 = low, 1 = high
+ */
+int pca953x_set_val(uint8_t chip, uint mask, uint data)
+{
+ return pca953x_reg_write(chip, PCA953X_OUT, mask, data);
+}
+
+/*
+ * Set read polarity of IO pins in 'mask' to corresponding value in 'data'
+ * 0 = read pin value, 1 = read inverted pin value
+ */
+int pca953x_set_pol(uint8_t chip, uint mask, uint data)
+{
+ return pca953x_reg_write(chip, PCA953X_POL, mask, data);
+}
+
+/*
+ * Set direction of IO pins in 'mask' to corresponding value in 'data'
+ * 0 = output, 1 = input
+ */
+int pca953x_set_dir(uint8_t chip, uint mask, uint data)
+{
+ return pca953x_reg_write(chip, PCA953X_CONF, mask, data);
+}
+
+/*
+ * Read current logic level of all IO pins
+ */
+int pca953x_get_val(uint8_t chip)
+{
+ uint val;
+
+ if (pca953x_reg_read(chip, PCA953X_IN, &val) < 0)
+ return -1;
+
+ return (int)val;
+}
+
+#ifdef CONFIG_CMD_PCA953X
+#ifdef CONFIG_CMD_PCA953X_INFO
+/*
+ * Display pca953x information
+ */
+static int pca953x_info(uint8_t chip)
+{
+ int i;
+ uint data;
+ int nr_gpio = pca953x_ngpio(chip);
+ int msb = nr_gpio - 1;
+
+ printf("pca953x@ 0x%x (%d pins):\n\n", chip, nr_gpio);
+ printf("gpio pins: ");
+ for (i = msb; i >= 0; i--)
+ printf("%x", i);
+ printf("\n");
+ for (i = 11 + nr_gpio; i > 0; i--)
+ printf("-");
+ printf("\n");
+
+ if (pca953x_reg_read(chip, PCA953X_CONF, &data) < 0)
+ return -1;
+ printf("conf: ");
+ for (i = msb; i >= 0; i--)
+ printf("%c", data & (1 << i) ? 'i' : 'o');
+ printf("\n");
+
+ if (pca953x_reg_read(chip, PCA953X_POL, &data) < 0)
+ return -1;
+ printf("invert: ");
+ for (i = msb; i >= 0; i--)
+ printf("%c", data & (1 << i) ? '1' : '0');
+ printf("\n");
+
+ if (pca953x_reg_read(chip, PCA953X_IN, &data) < 0)
+ return -1;
+ printf("input: ");
+ for (i = msb; i >= 0; i--)
+ printf("%c", data & (1 << i) ? '1' : '0');
+ printf("\n");
+
+ if (pca953x_reg_read(chip, PCA953X_OUT, &data) < 0)
+ return -1;
+ printf("output: ");
+ for (i = msb; i >= 0; i--)
+ printf("%c", data & (1 << i) ? '1' : '0');
+ printf("\n");
+
+ return 0;
+}
+#endif /* CONFIG_CMD_PCA953X_INFO */
+
+cmd_tbl_t cmd_pca953x[] = {
+ U_BOOT_CMD_MKENT(device, 3, 0, (void *)PCA953X_CMD_DEVICE, "", ""),
+ U_BOOT_CMD_MKENT(output, 4, 0, (void *)PCA953X_CMD_OUTPUT, "", ""),
+ U_BOOT_CMD_MKENT(input, 3, 0, (void *)PCA953X_CMD_INPUT, "", ""),
+ U_BOOT_CMD_MKENT(invert, 4, 0, (void *)PCA953X_CMD_INVERT, "", ""),
+#ifdef CONFIG_CMD_PCA953X_INFO
+ U_BOOT_CMD_MKENT(info, 2, 0, (void *)PCA953X_CMD_INFO, "", ""),
+#endif
+};
+
+int do_pca953x(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ static uint8_t chip = CONFIG_SYS_I2C_PCA953X_ADDR;
+ int ret = CMD_RET_USAGE, val;
+ ulong ul_arg2 = 0;
+ ulong ul_arg3 = 0;
+ cmd_tbl_t *c;
+
+ c = find_cmd_tbl(argv[1], cmd_pca953x, ARRAY_SIZE(cmd_pca953x));
+
+ /* All commands but "device" require 'maxargs' arguments */
+ if (!c || !((argc == (c->maxargs)) ||
+ (((int)c->cmd == PCA953X_CMD_DEVICE) &&
+ (argc == (c->maxargs - 1))))) {
+ return CMD_RET_USAGE;
+ }
+
+ /* arg2 used as chip number or pin number */
+ if (argc > 2)
+ ul_arg2 = simple_strtoul(argv[2], NULL, 16);
+
+ /* arg3 used as pin or invert value */
+ if (argc > 3)
+ ul_arg3 = simple_strtoul(argv[3], NULL, 16) & 0x1;
+
+ switch ((int)c->cmd) {
+#ifdef CONFIG_CMD_PCA953X_INFO
+ case PCA953X_CMD_INFO:
+ ret = pca953x_info(chip);
+ if (ret)
+ ret = CMD_RET_FAILURE;
+ break;
+#endif
+
+ case PCA953X_CMD_DEVICE:
+ if (argc == 3)
+ chip = (uint8_t)ul_arg2;
+ printf("Current device address: 0x%x\n", chip);
+ ret = CMD_RET_SUCCESS;
+ break;
+
+ case PCA953X_CMD_INPUT:
+ ret = pca953x_set_dir(chip, (1 << ul_arg2),
+ PCA953X_DIR_IN << ul_arg2);
+ val = (pca953x_get_val(chip) & (1 << ul_arg2)) != 0;
+
+ if (ret)
+ ret = CMD_RET_FAILURE;
+ else
+ printf("chip 0x%02x, pin 0x%lx = %d\n", chip, ul_arg2,
+ val);
+ break;
+
+ case PCA953X_CMD_OUTPUT:
+ ret = pca953x_set_dir(chip, (1 << ul_arg2),
+ (PCA953X_DIR_OUT << ul_arg2));
+ if (!ret)
+ ret = pca953x_set_val(chip, (1 << ul_arg2),
+ (ul_arg3 << ul_arg2));
+ if (ret)
+ ret = CMD_RET_FAILURE;
+ break;
+
+ case PCA953X_CMD_INVERT:
+ ret = pca953x_set_pol(chip, (1 << ul_arg2),
+ (ul_arg3 << ul_arg2));
+ if (ret)
+ ret = CMD_RET_FAILURE;
+ break;
+ }
+
+ if (ret == CMD_RET_FAILURE)
+ eprintf("Error talking to chip at 0x%x\n", chip);
+
+ return ret;
+}
+
+U_BOOT_CMD(
+ pca953x, 5, 1, do_pca953x,
+ "pca953x gpio access",
+ "device [dev]\n"
+ " - show or set current device address\n"
+#ifdef CONFIG_CMD_PCA953X_INFO
+ "pca953x info\n"
+ " - display info for current chip\n"
+#endif
+ "pca953x output pin 0|1\n"
+ " - set pin as output and drive low or high\n"
+ "pca953x invert pin 0|1\n"
+ " - disable/enable polarity inversion for reads\n"
+ "pca953x input pin\n"
+ " - set pin as input and read value"
+);
+
+#endif /* CONFIG_CMD_PCA953X */
diff --git a/qemu/roms/u-boot/drivers/gpio/pca9698.c b/qemu/roms/u-boot/drivers/gpio/pca9698.c
new file mode 100644
index 000000000..3152bf6df
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/pca9698.c
@@ -0,0 +1,127 @@
+/*
+ * (C) Copyright 2011
+ * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*
+ * Driver for NXP's pca9698 40 bit I2C gpio expander
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <asm/errno.h>
+#include <pca9698.h>
+
+/*
+ * The pca9698 registers
+ */
+
+#define PCA9698_REG_INPUT 0x00
+#define PCA9698_REG_OUTPUT 0x08
+#define PCA9698_REG_POLARITY 0x10
+#define PCA9698_REG_CONFIG 0x18
+
+#define PCA9698_BUFFER_SIZE 5
+#define PCA9698_GPIO_COUNT 40
+
+static int pca9698_read40(u8 addr, u8 offset, u8 *buffer)
+{
+ u8 command = offset | 0x80; /* autoincrement */
+
+ return i2c_read(addr, command, 1, buffer, PCA9698_BUFFER_SIZE);
+}
+
+static int pca9698_write40(u8 addr, u8 offset, u8 *buffer)
+{
+ u8 command = offset | 0x80; /* autoincrement */
+
+ return i2c_write(addr, command, 1, buffer, PCA9698_BUFFER_SIZE);
+}
+
+static void pca9698_set_bit(unsigned gpio, u8 *buffer, unsigned value)
+{
+ unsigned byte = gpio / 8;
+ unsigned bit = gpio % 8;
+
+ if (value)
+ buffer[byte] |= (1 << bit);
+ else
+ buffer[byte] &= ~(1 << bit);
+}
+
+int pca9698_request(unsigned gpio, const char *label)
+{
+ if (gpio >= PCA9698_GPIO_COUNT)
+ return -EINVAL;
+
+ return 0;
+}
+
+void pca9698_free(unsigned gpio)
+{
+}
+
+int pca9698_direction_input(u8 addr, unsigned gpio)
+{
+ u8 data[PCA9698_BUFFER_SIZE];
+ int res;
+
+ res = pca9698_read40(addr, PCA9698_REG_CONFIG, data);
+ if (res)
+ return res;
+
+ pca9698_set_bit(gpio, data, 1);
+
+ return pca9698_write40(addr, PCA9698_REG_CONFIG, data);
+}
+
+int pca9698_direction_output(u8 addr, unsigned gpio, int value)
+{
+ u8 data[PCA9698_BUFFER_SIZE];
+ int res;
+
+ res = pca9698_set_value(addr, gpio, value);
+ if (res)
+ return res;
+
+ res = pca9698_read40(addr, PCA9698_REG_CONFIG, data);
+ if (res)
+ return res;
+
+ pca9698_set_bit(gpio, data, 0);
+
+ return pca9698_write40(addr, PCA9698_REG_CONFIG, data);
+}
+
+int pca9698_get_value(u8 addr, unsigned gpio)
+{
+ unsigned config_byte = gpio / 8;
+ unsigned config_bit = gpio % 8;
+ unsigned value;
+ u8 data[PCA9698_BUFFER_SIZE];
+ int res;
+
+ res = pca9698_read40(addr, PCA9698_REG_INPUT, data);
+ if (res)
+ return -1;
+
+ value = data[config_byte] & (1 << config_bit);
+
+ return !!value;
+}
+
+int pca9698_set_value(u8 addr, unsigned gpio, int value)
+{
+ u8 data[PCA9698_BUFFER_SIZE];
+ int res;
+
+ res = pca9698_read40(addr, PCA9698_REG_OUTPUT, data);
+ if (res)
+ return res;
+
+ pca9698_set_bit(gpio, data, value);
+
+ return pca9698_write40(addr, PCA9698_REG_OUTPUT, data);
+}
diff --git a/qemu/roms/u-boot/drivers/gpio/s3c2440_gpio.c b/qemu/roms/u-boot/drivers/gpio/s3c2440_gpio.c
new file mode 100644
index 000000000..e1e2d3f80
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/s3c2440_gpio.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2012
+ * Gabriel Huau <contact@huau-gabriel.fr>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#include <common.h>
+#include <asm/arch/s3c2440.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+
+#define GPIO_INPUT 0x0
+#define GPIO_OUTPUT 0x1
+
+/* 0x4 means that we want DAT and not CON register */
+#define GPIO_PORT(x) ((((x) >> 5) & 0x3) + 0x4)
+#define GPIO_BIT(x) ((x) & 0x3f)
+
+/*
+ * It's how we calculate the full port address
+ * We have to get the number of the port + 1 (Port A is at 0x56000001 ...)
+ * We move it at the second digit, and finally we add 0x4 because we want
+ * to modify GPIO DAT and not CON
+ */
+#define GPIO_FULLPORT(x) (S3C24X0_GPIO_BASE | ((GPIO_PORT(gpio) + 1) << 1))
+
+int gpio_set_value(unsigned gpio, int value)
+{
+ unsigned l = readl(GPIO_FULLPORT(gpio));
+ unsigned bit;
+ unsigned port = GPIO_FULLPORT(gpio);
+
+ /*
+ * All GPIO Port have a configuration on
+ * 2 bits excepted the first GPIO (A) which
+ * have only 1 bit of configuration.
+ */
+ if (!GPIO_PORT(gpio))
+ bit = (0x1 << GPIO_BIT(gpio));
+ else
+ bit = (0x3 << GPIO_BIT(gpio));
+
+ if (value)
+ l |= bit;
+ else
+ l &= ~bit;
+
+ return writel(l, port);
+}
+
+int gpio_get_value(unsigned gpio)
+{
+ unsigned l = readl(GPIO_FULLPORT(gpio));
+
+ if (GPIO_PORT(gpio) == 0) /* PORT A */
+ return (l >> GPIO_BIT(gpio)) & 0x1;
+ return (l >> GPIO_BIT(gpio)) & 0x3;
+}
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ return 0;
+}
+
+int gpio_free(unsigned gpio)
+{
+ return 0;
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+ return writel(GPIO_INPUT << GPIO_BIT(gpio), GPIO_FULLPORT(gpio));
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ writel(GPIO_OUTPUT << GPIO_BIT(gpio), GPIO_FULLPORT(gpio));
+ return gpio_set_value(gpio, value);
+}
diff --git a/qemu/roms/u-boot/drivers/gpio/s5p_gpio.c b/qemu/roms/u-boot/drivers/gpio/s5p_gpio.c
new file mode 100644
index 000000000..11a0472c6
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/s5p_gpio.c
@@ -0,0 +1,181 @@
+/*
+ * (C) Copyright 2009 Samsung Electronics
+ * Minkyu Kang <mk7.kang@samsung.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+
+#define S5P_GPIO_GET_BANK(x) ((x >> S5P_GPIO_BANK_SHIFT) \
+ & S5P_GPIO_BANK_MASK)
+
+#define S5P_GPIO_GET_PIN(x) (x & S5P_GPIO_PIN_MASK)
+
+#define CON_MASK(x) (0xf << ((x) << 2))
+#define CON_SFR(x, v) ((v) << ((x) << 2))
+
+#define DAT_MASK(x) (0x1 << (x))
+#define DAT_SET(x) (0x1 << (x))
+
+#define PULL_MASK(x) (0x3 << ((x) << 1))
+#define PULL_MODE(x, v) ((v) << ((x) << 1))
+
+#define DRV_MASK(x) (0x3 << ((x) << 1))
+#define DRV_SET(x, m) ((m) << ((x) << 1))
+#define RATE_MASK(x) (0x1 << (x + 16))
+#define RATE_SET(x) (0x1 << (x + 16))
+
+void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg)
+{
+ unsigned int value;
+
+ value = readl(&bank->con);
+ value &= ~CON_MASK(gpio);
+ value |= CON_SFR(gpio, cfg);
+ writel(value, &bank->con);
+}
+
+void s5p_gpio_direction_output(struct s5p_gpio_bank *bank, int gpio, int en)
+{
+ s5p_gpio_cfg_pin(bank, gpio, GPIO_OUTPUT);
+ s5p_gpio_set_value(bank, gpio, en);
+}
+
+void s5p_gpio_direction_input(struct s5p_gpio_bank *bank, int gpio)
+{
+ s5p_gpio_cfg_pin(bank, gpio, GPIO_INPUT);
+}
+
+void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en)
+{
+ unsigned int value;
+
+ value = readl(&bank->dat);
+ value &= ~DAT_MASK(gpio);
+ if (en)
+ value |= DAT_SET(gpio);
+ writel(value, &bank->dat);
+}
+
+unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio)
+{
+ unsigned int value;
+
+ value = readl(&bank->dat);
+ return !!(value & DAT_MASK(gpio));
+}
+
+void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode)
+{
+ unsigned int value;
+
+ value = readl(&bank->pull);
+ value &= ~PULL_MASK(gpio);
+
+ switch (mode) {
+ case GPIO_PULL_DOWN:
+ case GPIO_PULL_UP:
+ value |= PULL_MODE(gpio, mode);
+ break;
+ default:
+ break;
+ }
+
+ writel(value, &bank->pull);
+}
+
+void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode)
+{
+ unsigned int value;
+
+ value = readl(&bank->drv);
+ value &= ~DRV_MASK(gpio);
+
+ switch (mode) {
+ case GPIO_DRV_1X:
+ case GPIO_DRV_2X:
+ case GPIO_DRV_3X:
+ case GPIO_DRV_4X:
+ value |= DRV_SET(gpio, mode);
+ break;
+ default:
+ return;
+ }
+
+ writel(value, &bank->drv);
+}
+
+void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode)
+{
+ unsigned int value;
+
+ value = readl(&bank->drv);
+ value &= ~RATE_MASK(gpio);
+
+ switch (mode) {
+ case GPIO_DRV_FAST:
+ case GPIO_DRV_SLOW:
+ value |= RATE_SET(gpio);
+ break;
+ default:
+ return;
+ }
+
+ writel(value, &bank->drv);
+}
+
+struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned gpio)
+{
+ unsigned bank = S5P_GPIO_GET_BANK(gpio);
+ unsigned base = s5p_gpio_base(gpio);
+
+ return (struct s5p_gpio_bank *)(base + bank);
+}
+
+int s5p_gpio_get_pin(unsigned gpio)
+{
+ return S5P_GPIO_GET_PIN(gpio);
+}
+
+/* Common GPIO API */
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ return 0;
+}
+
+int gpio_free(unsigned gpio)
+{
+ return 0;
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+ s5p_gpio_direction_input(s5p_gpio_get_bank(gpio),
+ s5p_gpio_get_pin(gpio));
+ return 0;
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ s5p_gpio_direction_output(s5p_gpio_get_bank(gpio),
+ s5p_gpio_get_pin(gpio), value);
+ return 0;
+}
+
+int gpio_get_value(unsigned gpio)
+{
+ return (int) s5p_gpio_get_value(s5p_gpio_get_bank(gpio),
+ s5p_gpio_get_pin(gpio));
+}
+
+int gpio_set_value(unsigned gpio, int value)
+{
+ s5p_gpio_set_value(s5p_gpio_get_bank(gpio),
+ s5p_gpio_get_pin(gpio), value);
+
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/gpio/sandbox.c b/qemu/roms/u-boot/drivers/gpio/sandbox.c
new file mode 100644
index 000000000..22b6a5f79
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/sandbox.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <asm/gpio.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Flags for each GPIO */
+#define GPIOF_OUTPUT (1 << 0) /* Currently set as an output */
+#define GPIOF_HIGH (1 << 1) /* Currently set high */
+#define GPIOF_RESERVED (1 << 2) /* Is in use / requested */
+
+struct gpio_state {
+ const char *label; /* label given by requester */
+ u8 flags; /* flags (GPIOF_...) */
+};
+
+/* Access routines for GPIO state */
+static u8 *get_gpio_flags(struct device *dev, unsigned offset)
+{
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+ struct gpio_state *state = dev_get_priv(dev);
+
+ if (offset >= uc_priv->gpio_count) {
+ static u8 invalid_flags;
+ printf("sandbox_gpio: error: invalid gpio %u\n", offset);
+ return &invalid_flags;
+ }
+
+ return &state[offset].flags;
+}
+
+static int get_gpio_flag(struct device *dev, unsigned offset, int flag)
+{
+ return (*get_gpio_flags(dev, offset) & flag) != 0;
+}
+
+static int set_gpio_flag(struct device *dev, unsigned offset, int flag,
+ int value)
+{
+ u8 *gpio = get_gpio_flags(dev, offset);
+
+ if (value)
+ *gpio |= flag;
+ else
+ *gpio &= ~flag;
+
+ return 0;
+}
+
+static int check_reserved(struct device *dev, unsigned offset,
+ const char *func)
+{
+ if (!get_gpio_flag(dev, offset, GPIOF_RESERVED)) {
+ printf("sandbox_gpio: %s: error: offset %u not reserved\n",
+ func, offset);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Back-channel sandbox-internal-only access to GPIO state
+ */
+
+int sandbox_gpio_get_value(struct device *dev, unsigned offset)
+{
+ if (get_gpio_flag(dev, offset, GPIOF_OUTPUT))
+ debug("sandbox_gpio: get_value on output gpio %u\n", offset);
+ return get_gpio_flag(dev, offset, GPIOF_HIGH);
+}
+
+int sandbox_gpio_set_value(struct device *dev, unsigned offset, int value)
+{
+ return set_gpio_flag(dev, offset, GPIOF_HIGH, value);
+}
+
+int sandbox_gpio_get_direction(struct device *dev, unsigned offset)
+{
+ return get_gpio_flag(dev, offset, GPIOF_OUTPUT);
+}
+
+int sandbox_gpio_set_direction(struct device *dev, unsigned offset, int output)
+{
+ return set_gpio_flag(dev, offset, GPIOF_OUTPUT, output);
+}
+
+/*
+ * These functions implement the public interface within U-Boot
+ */
+
+/* set GPIO port 'offset' as an input */
+static int sb_gpio_direction_input(struct device *dev, unsigned offset)
+{
+ debug("%s: offset:%u\n", __func__, offset);
+
+ if (check_reserved(dev, offset, __func__))
+ return -1;
+
+ return sandbox_gpio_set_direction(dev, offset, 0);
+}
+
+/* set GPIO port 'offset' as an output, with polarity 'value' */
+static int sb_gpio_direction_output(struct device *dev, unsigned offset,
+ int value)
+{
+ debug("%s: offset:%u, value = %d\n", __func__, offset, value);
+
+ if (check_reserved(dev, offset, __func__))
+ return -1;
+
+ return sandbox_gpio_set_direction(dev, offset, 1) |
+ sandbox_gpio_set_value(dev, offset, value);
+}
+
+/* read GPIO IN value of port 'offset' */
+static int sb_gpio_get_value(struct device *dev, unsigned offset)
+{
+ debug("%s: offset:%u\n", __func__, offset);
+
+ if (check_reserved(dev, offset, __func__))
+ return -1;
+
+ return sandbox_gpio_get_value(dev, offset);
+}
+
+/* write GPIO OUT value to port 'offset' */
+static int sb_gpio_set_value(struct device *dev, unsigned offset, int value)
+{
+ debug("%s: offset:%u, value = %d\n", __func__, offset, value);
+
+ if (check_reserved(dev, offset, __func__))
+ return -1;
+
+ if (!sandbox_gpio_get_direction(dev, offset)) {
+ printf("sandbox_gpio: error: set_value on input gpio %u\n",
+ offset);
+ return -1;
+ }
+
+ return sandbox_gpio_set_value(dev, offset, value);
+}
+
+static int sb_gpio_request(struct device *dev, unsigned offset,
+ const char *label)
+{
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+ struct gpio_state *state = dev_get_priv(dev);
+
+ debug("%s: offset:%u, label:%s\n", __func__, offset, label);
+
+ if (offset >= uc_priv->gpio_count) {
+ printf("sandbox_gpio: error: invalid gpio %u\n", offset);
+ return -1;
+ }
+
+ if (get_gpio_flag(dev, offset, GPIOF_RESERVED)) {
+ printf("sandbox_gpio: error: gpio %u already reserved\n",
+ offset);
+ return -1;
+ }
+
+ state[offset].label = label;
+ return set_gpio_flag(dev, offset, GPIOF_RESERVED, 1);
+}
+
+static int sb_gpio_free(struct device *dev, unsigned offset)
+{
+ struct gpio_state *state = dev_get_priv(dev);
+
+ debug("%s: offset:%u\n", __func__, offset);
+
+ if (check_reserved(dev, offset, __func__))
+ return -1;
+
+ state[offset].label = NULL;
+ return set_gpio_flag(dev, offset, GPIOF_RESERVED, 0);
+}
+
+static int sb_gpio_get_state(struct device *dev, unsigned int offset,
+ char *buf, int bufsize)
+{
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+ struct gpio_state *state = dev_get_priv(dev);
+ const char *label;
+
+ label = state[offset].label;
+ snprintf(buf, bufsize, "%s%d: %s: %d [%c]%s%s",
+ uc_priv->bank_name ? uc_priv->bank_name : "", offset,
+ sandbox_gpio_get_direction(dev, offset) ? "out" : " in",
+ sandbox_gpio_get_value(dev, offset),
+ get_gpio_flag(dev, offset, GPIOF_RESERVED) ? 'x' : ' ',
+ label ? " " : "",
+ label ? label : "");
+
+ return 0;
+}
+
+static const struct dm_gpio_ops gpio_sandbox_ops = {
+ .request = sb_gpio_request,
+ .free = sb_gpio_free,
+ .direction_input = sb_gpio_direction_input,
+ .direction_output = sb_gpio_direction_output,
+ .get_value = sb_gpio_get_value,
+ .set_value = sb_gpio_set_value,
+ .get_state = sb_gpio_get_state,
+};
+
+static int sandbox_gpio_ofdata_to_platdata(struct device *dev)
+{
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+
+ uc_priv->gpio_count = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+ "num-gpios", 0);
+ uc_priv->bank_name = fdt_getprop(gd->fdt_blob, dev->of_offset,
+ "gpio-bank-name", NULL);
+
+ return 0;
+}
+
+static int gpio_sandbox_probe(struct device *dev)
+{
+ struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+
+ if (dev->of_offset == -1) {
+ /* Tell the uclass how many GPIOs we have */
+ uc_priv->gpio_count = CONFIG_SANDBOX_GPIO_COUNT;
+ }
+
+ dev->priv = calloc(sizeof(struct gpio_state), uc_priv->gpio_count);
+
+ return 0;
+}
+
+static const struct device_id sandbox_gpio_ids[] = {
+ { .compatible = "sandbox,gpio" },
+ { }
+};
+
+U_BOOT_DRIVER(gpio_sandbox) = {
+ .name = "gpio_sandbox",
+ .id = UCLASS_GPIO,
+ .of_match = sandbox_gpio_ids,
+ .ofdata_to_platdata = sandbox_gpio_ofdata_to_platdata,
+ .probe = gpio_sandbox_probe,
+ .ops = &gpio_sandbox_ops,
+};
diff --git a/qemu/roms/u-boot/drivers/gpio/sh_pfc.c b/qemu/roms/u-boot/drivers/gpio/sh_pfc.c
new file mode 100644
index 000000000..7a5af20a2
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/sh_pfc.c
@@ -0,0 +1,629 @@
+/*
+ * Pinmuxed GPIO support for SuperH.
+ * Copy from linux kernel driver/sh/pfc.c
+ *
+ * Copyright (C) 2008 Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <common.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <sh_pfc.h>
+
+static struct pinmux_info *gpioc;
+
+#define pfc_phys_to_virt(p, a) ((void *)a)
+
+static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
+{
+ if (enum_id < r->begin)
+ return 0;
+
+ if (enum_id > r->end)
+ return 0;
+
+ return 1;
+}
+
+static unsigned long gpio_read_raw_reg(void *mapped_reg,
+ unsigned long reg_width)
+{
+ switch (reg_width) {
+
+ case 8:
+ return readb(mapped_reg);
+ case 16:
+ return readw(mapped_reg);
+ case 32:
+ return readl(mapped_reg);
+ }
+
+ BUG();
+ return 0;
+}
+
+static void gpio_write_raw_reg(void *mapped_reg,
+ unsigned long reg_width,
+ unsigned long data)
+{
+ switch (reg_width) {
+ case 8:
+ writeb(data, mapped_reg);
+ return;
+ case 16:
+ writew(data, mapped_reg);
+ return;
+ case 32:
+ writel(data, mapped_reg);
+ return;
+ }
+
+ BUG();
+}
+
+static int gpio_read_bit(struct pinmux_data_reg *dr,
+ unsigned long in_pos)
+{
+ unsigned long pos;
+
+ pos = dr->reg_width - (in_pos + 1);
+
+ debug("read_bit: addr = %lx, pos = %ld, "
+ "r_width = %ld\n", dr->reg, pos, dr->reg_width);
+
+ return (gpio_read_raw_reg(dr->mapped_reg, dr->reg_width) >> pos) & 1;
+}
+
+static void gpio_write_bit(struct pinmux_data_reg *dr,
+ unsigned long in_pos, unsigned long value)
+{
+ unsigned long pos;
+
+ pos = dr->reg_width - (in_pos + 1);
+
+ debug("write_bit addr = %lx, value = %d, pos = %ld, "
+ "r_width = %ld\n",
+ dr->reg, !!value, pos, dr->reg_width);
+
+ if (value)
+ __set_bit(pos, &dr->reg_shadow);
+ else
+ __clear_bit(pos, &dr->reg_shadow);
+
+ gpio_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow);
+}
+
+static void config_reg_helper(struct pinmux_info *gpioc,
+ struct pinmux_cfg_reg *crp,
+ unsigned long in_pos,
+#if 0
+ void __iomem **mapped_regp,
+#else
+ void **mapped_regp,
+#endif
+ unsigned long *maskp,
+ unsigned long *posp)
+{
+ int k;
+
+ *mapped_regp = pfc_phys_to_virt(gpioc, crp->reg);
+
+ if (crp->field_width) {
+ *maskp = (1 << crp->field_width) - 1;
+ *posp = crp->reg_width - ((in_pos + 1) * crp->field_width);
+ } else {
+ *maskp = (1 << crp->var_field_width[in_pos]) - 1;
+ *posp = crp->reg_width;
+ for (k = 0; k <= in_pos; k++)
+ *posp -= crp->var_field_width[k];
+ }
+}
+
+static int read_config_reg(struct pinmux_info *gpioc,
+ struct pinmux_cfg_reg *crp,
+ unsigned long field)
+{
+ void *mapped_reg;
+
+ unsigned long mask, pos;
+
+ config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos);
+
+ debug("read_reg: addr = %lx, field = %ld, "
+ "r_width = %ld, f_width = %ld\n",
+ crp->reg, field, crp->reg_width, crp->field_width);
+
+ return (gpio_read_raw_reg(mapped_reg, crp->reg_width) >> pos) & mask;
+}
+
+static void write_config_reg(struct pinmux_info *gpioc,
+ struct pinmux_cfg_reg *crp,
+ unsigned long field, unsigned long value)
+{
+ void *mapped_reg;
+ unsigned long mask, pos, data;
+
+ config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos);
+
+ debug("write_reg addr = %lx, value = %ld, field = %ld, "
+ "r_width = %ld, f_width = %ld\n",
+ crp->reg, value, field, crp->reg_width, crp->field_width);
+
+ mask = ~(mask << pos);
+ value = value << pos;
+
+ data = gpio_read_raw_reg(mapped_reg, crp->reg_width);
+ data &= mask;
+ data |= value;
+
+ if (gpioc->unlock_reg)
+ gpio_write_raw_reg(pfc_phys_to_virt(gpioc, gpioc->unlock_reg),
+ 32, ~data);
+
+ gpio_write_raw_reg(mapped_reg, crp->reg_width, data);
+}
+
+static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio)
+{
+ struct pinmux_gpio *gpiop = &gpioc->gpios[gpio];
+ struct pinmux_data_reg *data_reg;
+ int k, n;
+
+ if (!enum_in_range(gpiop->enum_id, &gpioc->data))
+ return -1;
+
+ k = 0;
+ while (1) {
+ data_reg = gpioc->data_regs + k;
+
+ if (!data_reg->reg_width)
+ break;
+
+ data_reg->mapped_reg = pfc_phys_to_virt(gpioc, data_reg->reg);
+
+ for (n = 0; n < data_reg->reg_width; n++) {
+ if (data_reg->enum_ids[n] == gpiop->enum_id) {
+ gpiop->flags &= ~PINMUX_FLAG_DREG;
+ gpiop->flags |= (k << PINMUX_FLAG_DREG_SHIFT);
+ gpiop->flags &= ~PINMUX_FLAG_DBIT;
+ gpiop->flags |= (n << PINMUX_FLAG_DBIT_SHIFT);
+ return 0;
+ }
+ }
+ k++;
+ }
+
+ BUG();
+
+ return -1;
+}
+
+static void setup_data_regs(struct pinmux_info *gpioc)
+{
+ struct pinmux_data_reg *drp;
+ int k;
+
+ for (k = gpioc->first_gpio; k <= gpioc->last_gpio; k++)
+ setup_data_reg(gpioc, k);
+
+ k = 0;
+ while (1) {
+ drp = gpioc->data_regs + k;
+
+ if (!drp->reg_width)
+ break;
+
+ drp->reg_shadow = gpio_read_raw_reg(drp->mapped_reg,
+ drp->reg_width);
+ k++;
+ }
+}
+
+static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio,
+ struct pinmux_data_reg **drp, int *bitp)
+{
+ struct pinmux_gpio *gpiop = &gpioc->gpios[gpio];
+ int k, n;
+
+ if (!enum_in_range(gpiop->enum_id, &gpioc->data))
+ return -1;
+
+ k = (gpiop->flags & PINMUX_FLAG_DREG) >> PINMUX_FLAG_DREG_SHIFT;
+ n = (gpiop->flags & PINMUX_FLAG_DBIT) >> PINMUX_FLAG_DBIT_SHIFT;
+ *drp = gpioc->data_regs + k;
+ *bitp = n;
+ return 0;
+}
+
+static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
+ struct pinmux_cfg_reg **crp,
+ int *fieldp, int *valuep,
+ unsigned long **cntp)
+{
+ struct pinmux_cfg_reg *config_reg;
+ unsigned long r_width, f_width, curr_width, ncomb;
+ int k, m, n, pos, bit_pos;
+
+ k = 0;
+ while (1) {
+ config_reg = gpioc->cfg_regs + k;
+
+ r_width = config_reg->reg_width;
+ f_width = config_reg->field_width;
+
+ if (!r_width)
+ break;
+
+ pos = 0;
+ m = 0;
+ for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width) {
+ if (f_width)
+ curr_width = f_width;
+ else
+ curr_width = config_reg->var_field_width[m];
+
+ ncomb = 1 << curr_width;
+ for (n = 0; n < ncomb; n++) {
+ if (config_reg->enum_ids[pos + n] == enum_id) {
+ *crp = config_reg;
+ *fieldp = m;
+ *valuep = n;
+ *cntp = &config_reg->cnt[m];
+ return 0;
+ }
+ }
+ pos += ncomb;
+ m++;
+ }
+ k++;
+ }
+
+ return -1;
+}
+
+static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio,
+ int pos, pinmux_enum_t *enum_idp)
+{
+ pinmux_enum_t enum_id = gpioc->gpios[gpio].enum_id;
+ pinmux_enum_t *data = gpioc->gpio_data;
+ int k;
+
+ if (!enum_in_range(enum_id, &gpioc->data)) {
+ if (!enum_in_range(enum_id, &gpioc->mark)) {
+ debug("non data/mark enum_id for gpio %d\n", gpio);
+ return -1;
+ }
+ }
+
+ if (pos) {
+ *enum_idp = data[pos + 1];
+ return pos + 1;
+ }
+
+ for (k = 0; k < gpioc->gpio_data_size; k++) {
+ if (data[k] == enum_id) {
+ *enum_idp = data[k + 1];
+ return k + 1;
+ }
+ }
+
+ debug("cannot locate data/mark enum_id for gpio %d\n", gpio);
+ return -1;
+}
+
+enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE };
+
+static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
+ int pinmux_type, int cfg_mode)
+{
+ struct pinmux_cfg_reg *cr = NULL;
+ pinmux_enum_t enum_id;
+ struct pinmux_range *range;
+ int in_range, pos, field, value;
+ unsigned long *cntp;
+
+ switch (pinmux_type) {
+
+ case PINMUX_TYPE_FUNCTION:
+ range = NULL;
+ break;
+
+ case PINMUX_TYPE_OUTPUT:
+ range = &gpioc->output;
+ break;
+
+ case PINMUX_TYPE_INPUT:
+ range = &gpioc->input;
+ break;
+
+ case PINMUX_TYPE_INPUT_PULLUP:
+ range = &gpioc->input_pu;
+ break;
+
+ case PINMUX_TYPE_INPUT_PULLDOWN:
+ range = &gpioc->input_pd;
+ break;
+
+ default:
+ goto out_err;
+ }
+
+ pos = 0;
+ enum_id = 0;
+ field = 0;
+ value = 0;
+ while (1) {
+ pos = get_gpio_enum_id(gpioc, gpio, pos, &enum_id);
+ if (pos <= 0)
+ goto out_err;
+
+ if (!enum_id)
+ break;
+
+ /* first check if this is a function enum */
+ in_range = enum_in_range(enum_id, &gpioc->function);
+ if (!in_range) {
+ /* not a function enum */
+ if (range) {
+ /*
+ * other range exists, so this pin is
+ * a regular GPIO pin that now is being
+ * bound to a specific direction.
+ *
+ * for this case we only allow function enums
+ * and the enums that match the other range.
+ */
+ in_range = enum_in_range(enum_id, range);
+
+ /*
+ * special case pass through for fixed
+ * input-only or output-only pins without
+ * function enum register association.
+ */
+ if (in_range && enum_id == range->force)
+ continue;
+ } else {
+ /*
+ * no other range exists, so this pin
+ * must then be of the function type.
+ *
+ * allow function type pins to select
+ * any combination of function/in/out
+ * in their MARK lists.
+ */
+ in_range = 1;
+ }
+ }
+
+ if (!in_range)
+ continue;
+
+ if (get_config_reg(gpioc, enum_id, &cr,
+ &field, &value, &cntp) != 0)
+ goto out_err;
+
+ switch (cfg_mode) {
+ case GPIO_CFG_DRYRUN:
+ if (!*cntp ||
+ (read_config_reg(gpioc, cr, field) != value))
+ continue;
+ break;
+
+ case GPIO_CFG_REQ:
+ write_config_reg(gpioc, cr, field, value);
+ *cntp = *cntp + 1;
+ break;
+
+ case GPIO_CFG_FREE:
+ *cntp = *cntp - 1;
+ break;
+ }
+ }
+
+ return 0;
+ out_err:
+ return -1;
+}
+
+#if 0
+static DEFINE_SPINLOCK(gpio_lock);
+static struct pinmux_info *chip_to_pinmux(struct gpio_chip *chip)
+{
+ return container_of(chip, struct pinmux_info, chip);
+}
+#endif
+
+static int sh_gpio_request(unsigned offset)
+{
+ struct pinmux_data_reg *dummy;
+ int i, ret, pinmux_type;
+
+ ret = -1;
+
+ if (!gpioc)
+ goto err_out;
+
+ if ((gpioc->gpios[offset].flags & PINMUX_FLAG_TYPE) != PINMUX_TYPE_NONE)
+ goto err_out;
+
+ /* setup pin function here if no data is associated with pin */
+
+ if (get_data_reg(gpioc, offset, &dummy, &i) != 0)
+ pinmux_type = PINMUX_TYPE_FUNCTION;
+ else
+ pinmux_type = PINMUX_TYPE_GPIO;
+
+ if (pinmux_type == PINMUX_TYPE_FUNCTION) {
+ if (pinmux_config_gpio(gpioc, offset,
+ pinmux_type,
+ GPIO_CFG_DRYRUN) != 0)
+ goto err_out;
+
+ if (pinmux_config_gpio(gpioc, offset,
+ pinmux_type,
+ GPIO_CFG_REQ) != 0)
+ BUG();
+ }
+
+ gpioc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE;
+ gpioc->gpios[offset].flags |= pinmux_type;
+
+ ret = 0;
+err_out:
+ return ret;
+}
+
+static void sh_gpio_free(unsigned offset)
+{
+ int pinmux_type;
+
+ if (!gpioc)
+ return;
+
+ pinmux_type = gpioc->gpios[offset].flags & PINMUX_FLAG_TYPE;
+ pinmux_config_gpio(gpioc, offset, pinmux_type, GPIO_CFG_FREE);
+ gpioc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE;
+ gpioc->gpios[offset].flags |= PINMUX_TYPE_NONE;
+}
+
+static int pinmux_direction(struct pinmux_info *gpioc,
+ unsigned gpio, int new_pinmux_type)
+{
+ int pinmux_type;
+ int ret = -1;
+
+ if (!gpioc)
+ goto err_out;
+
+ pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE;
+
+ switch (pinmux_type) {
+ case PINMUX_TYPE_GPIO:
+ break;
+ case PINMUX_TYPE_OUTPUT:
+ case PINMUX_TYPE_INPUT:
+ case PINMUX_TYPE_INPUT_PULLUP:
+ case PINMUX_TYPE_INPUT_PULLDOWN:
+ pinmux_config_gpio(gpioc, gpio, pinmux_type, GPIO_CFG_FREE);
+ break;
+ default:
+ goto err_out;
+ }
+
+ if (pinmux_config_gpio(gpioc, gpio,
+ new_pinmux_type,
+ GPIO_CFG_DRYRUN) != 0)
+ goto err_out;
+
+ if (pinmux_config_gpio(gpioc, gpio,
+ new_pinmux_type,
+ GPIO_CFG_REQ) != 0)
+ BUG();
+
+ gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE;
+ gpioc->gpios[gpio].flags |= new_pinmux_type;
+
+ ret = 0;
+ err_out:
+ return ret;
+}
+
+static int sh_gpio_direction_input(unsigned offset)
+{
+ return pinmux_direction(gpioc, offset, PINMUX_TYPE_INPUT);
+}
+
+static void sh_gpio_set_value(struct pinmux_info *gpioc,
+ unsigned gpio, int value)
+{
+ struct pinmux_data_reg *dr = NULL;
+ int bit = 0;
+
+ if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
+ BUG();
+ else
+ gpio_write_bit(dr, bit, value);
+}
+
+static int sh_gpio_direction_output(unsigned offset, int value)
+{
+ sh_gpio_set_value(gpioc, offset, value);
+ return pinmux_direction(gpioc, offset, PINMUX_TYPE_OUTPUT);
+}
+
+static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio)
+{
+ struct pinmux_data_reg *dr = NULL;
+ int bit = 0;
+
+ if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
+ return -1;
+
+ return gpio_read_bit(dr, bit);
+}
+
+static int sh_gpio_get(unsigned offset)
+{
+ return sh_gpio_get_value(gpioc, offset);
+}
+
+static void sh_gpio_set(unsigned offset, int value)
+{
+ sh_gpio_set_value(gpioc, offset, value);
+}
+
+int register_pinmux(struct pinmux_info *pip)
+{
+ if (pip != NULL) {
+ gpioc = pip;
+ debug("%s deregistering\n", pip->name);
+ setup_data_regs(gpioc);
+ }
+ return 0;
+}
+
+int unregister_pinmux(struct pinmux_info *pip)
+{
+ debug("%s deregistering\n", pip->name);
+ if (gpioc != pip)
+ return -1;
+
+ gpioc = NULL;
+ return 0;
+}
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ sh_gpio_request(gpio);
+ return 0;
+}
+
+int gpio_free(unsigned gpio)
+{
+ sh_gpio_free(gpio);
+ return 0;
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+ return sh_gpio_direction_input(gpio);
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ return sh_gpio_direction_output(gpio, value);
+}
+
+void gpio_set_value(unsigned gpio, int value)
+{
+ sh_gpio_set(gpio, value);
+}
+
+int gpio_get_value(unsigned gpio)
+{
+ return sh_gpio_get(gpio);
+}
diff --git a/qemu/roms/u-boot/drivers/gpio/spear_gpio.c b/qemu/roms/u-boot/drivers/gpio/spear_gpio.c
new file mode 100644
index 000000000..367b67016
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/spear_gpio.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*
+ * Driver for SPEAr600 GPIO controller
+ */
+
+#include <common.h>
+#include <asm/arch/hardware.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <errno.h>
+
+static int gpio_direction(unsigned gpio,
+ enum gpio_direction direction)
+{
+ struct gpio_regs *regs = (struct gpio_regs *)CONFIG_GPIO_BASE;
+ u32 val;
+
+ val = readl(&regs->gpiodir);
+
+ if (direction == GPIO_DIRECTION_OUT)
+ val |= 1 << gpio;
+ else
+ val &= ~(1 << gpio);
+
+ writel(val, &regs->gpiodir);
+
+ return 0;
+}
+
+int gpio_set_value(unsigned gpio, int value)
+{
+ struct gpio_regs *regs = (struct gpio_regs *)CONFIG_GPIO_BASE;
+
+ writel(1 << gpio, &regs->gpiodata[DATA_REG_ADDR(gpio)]);
+
+ return 0;
+}
+
+int gpio_get_value(unsigned gpio)
+{
+ struct gpio_regs *regs = (struct gpio_regs *)CONFIG_GPIO_BASE;
+ u32 val;
+
+ val = readl(&regs->gpiodata[DATA_REG_ADDR(gpio)]);
+
+ return !!val;
+}
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ if (gpio >= SPEAR_GPIO_COUNT)
+ return -EINVAL;
+
+ return 0;
+}
+
+int gpio_free(unsigned gpio)
+{
+ return 0;
+}
+
+void gpio_toggle_value(unsigned gpio)
+{
+ gpio_set_value(gpio, !gpio_get_value(gpio));
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+ return gpio_direction(gpio, GPIO_DIRECTION_IN);
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ int ret = gpio_direction(gpio, GPIO_DIRECTION_OUT);
+
+ if (ret < 0)
+ return ret;
+
+ gpio_set_value(gpio, value);
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/gpio/sx151x.c b/qemu/roms/u-boot/drivers/gpio/sx151x.c
new file mode 100644
index 000000000..167cf40c7
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/sx151x.c
@@ -0,0 +1,242 @@
+/*
+ * (C) Copyright 2013
+ * Viktar Palstsiuk, Promwad, viktar.palstsiuk@promwad.com
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*
+ * Driver for Semtech SX151x SPI GPIO Expanders
+ */
+
+#include <common.h>
+#include <spi.h>
+#include <sx151x.h>
+
+#ifndef CONFIG_SX151X_SPI_BUS
+#define CONFIG_SX151X_SPI_BUS 0
+#endif
+
+/*
+ * The SX151x registers
+ */
+
+#ifdef CONFIG_SX151X_GPIO_COUNT_8
+/* 8bit: SX1511 */
+#define SX151X_REG_DIR 0x07
+#define SX151X_REG_DATA 0x08
+#else
+/* 16bit: SX1512 */
+#define SX151X_REG_DIR 0x0F
+#define SX151X_REG_DATA 0x11
+#endif
+#define SX151X_REG_RESET 0x7D
+
+static int sx151x_spi_write(int chip, unsigned char reg, unsigned char val)
+{
+ struct spi_slave *slave;
+ unsigned char buf[2];
+ int ret;
+
+ slave = spi_setup_slave(CONFIG_SX151X_SPI_BUS, chip, 1000000,
+ SPI_MODE_0);
+ if (!slave)
+ return 0;
+
+ spi_claim_bus(slave);
+
+ buf[0] = reg;
+ buf[1] = val;
+
+ ret = spi_xfer(slave, 16, buf, NULL, SPI_XFER_BEGIN | SPI_XFER_END);
+ if (ret < 0)
+ printf("spi%d.%d write fail: can't write %02x to %02x: %d\n",
+ CONFIG_SX151X_SPI_BUS, chip, val, reg, ret);
+ else
+ printf("spi%d.%d write 0x%02x to register 0x%02x\n",
+ CONFIG_SX151X_SPI_BUS, chip, val, reg);
+ spi_release_bus(slave);
+ spi_free_slave(slave);
+
+ return ret;
+}
+
+static int sx151x_spi_read(int chip, unsigned char reg)
+{
+ struct spi_slave *slave;
+ int ret;
+
+ slave = spi_setup_slave(CONFIG_SX151X_SPI_BUS, chip, 1000000,
+ SPI_MODE_0);
+ if (!slave)
+ return 0;
+
+ spi_claim_bus(slave);
+
+ ret = spi_w8r8(slave, reg | 0x80);
+ if (ret < 0)
+ printf("spi%d.%d read fail: can't read %02x: %d\n",
+ CONFIG_SX151X_SPI_BUS, chip, reg, ret);
+ else
+ printf("spi%d.%d read register 0x%02x: 0x%02x\n",
+ CONFIG_SX151X_SPI_BUS, chip, reg, ret);
+
+ spi_release_bus(slave);
+ spi_free_slave(slave);
+
+ return ret;
+}
+
+static inline void sx151x_find_cfg(int gpio, unsigned char *reg, unsigned char *mask)
+{
+ *reg -= gpio / 8;
+ *mask = 1 << (gpio % 8);
+}
+
+static int sx151x_write_cfg(int chip, unsigned char gpio, unsigned char reg, int val)
+{
+ unsigned char mask;
+ unsigned char data;
+ int ret;
+
+ sx151x_find_cfg(gpio, &reg, &mask);
+ ret = sx151x_spi_read(chip, reg);
+ if (ret < 0)
+ return ret;
+ else
+ data = ret;
+ data &= ~mask;
+ data |= (val << (gpio % 8)) & mask;
+ return sx151x_spi_write(chip, reg, data);
+}
+
+int sx151x_get_value(int chip, int gpio)
+{
+ unsigned char reg = SX151X_REG_DATA;
+ unsigned char mask;
+ int ret;
+
+ sx151x_find_cfg(gpio, &reg, &mask);
+ ret = sx151x_spi_read(chip, reg);
+ if (ret >= 0)
+ ret = (ret & mask) != 0 ? 1 : 0;
+
+ return ret;
+}
+
+int sx151x_set_value(int chip, int gpio, int val)
+{
+ return sx151x_write_cfg(chip, gpio, SX151X_REG_DATA, (val ? 1 : 0));
+}
+
+int sx151x_direction_input(int chip, int gpio)
+{
+ return sx151x_write_cfg(chip, gpio, SX151X_REG_DIR, 1);
+}
+
+int sx151x_direction_output(int chip, int gpio)
+{
+ return sx151x_write_cfg(chip, gpio, SX151X_REG_DIR, 0);
+}
+
+int sx151x_reset(int chip)
+{
+ int err;
+
+ err = sx151x_spi_write(chip, SX151X_REG_RESET, 0x12);
+ if (err < 0)
+ return err;
+
+ err = sx151x_spi_write(chip, SX151X_REG_RESET, 0x34);
+ return err;
+}
+
+#ifdef CONFIG_CMD_SX151X
+
+int do_sx151x(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int ret = CMD_RET_USAGE, chip = 0, gpio = 0, val = 0;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ /* arg2 used as chip number */
+ chip = simple_strtoul(argv[2], NULL, 10);
+
+ if (strcmp(argv[1], "reset") == 0) {
+ ret = sx151x_reset(chip);
+ if (!ret) {
+ printf("Device at spi%d.%d was reset\n",
+ CONFIG_SX151X_SPI_BUS, chip);
+ }
+ return ret;
+ }
+
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ /* arg3 used as gpio number */
+ gpio = simple_strtoul(argv[3], NULL, 10);
+
+ if (strcmp(argv[1], "get") == 0) {
+ ret = sx151x_get_value(chip, gpio);
+ if (ret < 0)
+ printf("Failed to get value at spi%d.%d gpio %d\n",
+ CONFIG_SX151X_SPI_BUS, chip, gpio);
+ else {
+ printf("Value at spi%d.%d gpio %d is %d\n",
+ CONFIG_SX151X_SPI_BUS, chip, gpio, ret);
+ ret = 0;
+ }
+ return ret;
+ }
+
+ if (argc < 5)
+ return CMD_RET_USAGE;
+
+ /* arg4 used as value or direction */
+ val = simple_strtoul(argv[4], NULL, 10);
+
+ if (strcmp(argv[1], "set") == 0) {
+ ret = sx151x_set_value(chip, gpio, val);
+ if (ret < 0)
+ printf("Failed to set value at spi%d.%d gpio %d\n",
+ CONFIG_SX151X_SPI_BUS, chip, gpio);
+ else
+ printf("New value at spi%d.%d gpio %d is %d\n",
+ CONFIG_SX151X_SPI_BUS, chip, gpio, val);
+ return ret;
+ } else if (strcmp(argv[1], "dir") == 0) {
+ if (val == 0)
+ ret = sx151x_direction_output(chip, gpio);
+ else
+ ret = sx151x_direction_input(chip, gpio);
+
+ if (ret < 0)
+ printf("Failed to set direction of spi%d.%d gpio %d\n",
+ CONFIG_SX151X_SPI_BUS, chip, gpio);
+ else
+ printf("New direction of spi%d.%d gpio %d is %d\n",
+ CONFIG_SX151X_SPI_BUS, chip, gpio, val);
+ return ret;
+ }
+
+ printf("Please see usage\n");
+
+ return ret;
+}
+
+U_BOOT_CMD(
+ sx151x, 5, 1, do_sx151x,
+ "sx151x gpio access",
+ "dir chip gpio 0|1\n"
+ " - set gpio direction (0 for output, 1 for input)\n"
+ "sx151x get chip gpio\n"
+ " - get gpio value\n"
+ "sx151x set chip gpio 0|1\n"
+ " - set gpio value\n"
+ "sx151x reset chip\n"
+ " - reset chip"
+);
+
+#endif /* CONFIG_CMD_SX151X */
diff --git a/qemu/roms/u-boot/drivers/gpio/tca642x.c b/qemu/roms/u-boot/drivers/gpio/tca642x.c
new file mode 100644
index 000000000..6386835d5
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/tca642x.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright 2013 Texas Instruments, Inc.
+ * Author: Dan Murphy <dmurphy@ti.com>
+ *
+ * Derived work from the pca953x.c driver
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <tca642x.h>
+
+/* tca642x register address definitions */
+struct tca642x_bank_info tca642x_regs[] = {
+ { .input_reg = 0x00,
+ .output_reg = 0x04,
+ .polarity_reg = 0x08,
+ .configuration_reg = 0x0c },
+ { .input_reg = 0x01,
+ .output_reg = 0x05,
+ .polarity_reg = 0x09,
+ .configuration_reg = 0x0d },
+ { .input_reg = 0x02,
+ .output_reg = 0x06,
+ .polarity_reg = 0x0a,
+ .configuration_reg = 0x0e },
+};
+
+/*
+ * Modify masked bits in register
+ */
+static int tca642x_reg_write(uchar chip, uint8_t addr,
+ uint8_t reg_bit, uint8_t data)
+{
+ uint8_t valw;
+ int org_bus_num;
+ int ret;
+
+ org_bus_num = i2c_get_bus_num();
+ i2c_set_bus_num(CONFIG_SYS_I2C_TCA642X_BUS_NUM);
+
+ if (i2c_read(chip, addr, 1, (uint8_t *)&valw, 1)) {
+ printf("Could not read before writing\n");
+ ret = -1;
+ goto error;
+ }
+ valw &= ~reg_bit;
+ valw |= data;
+
+ ret = i2c_write(chip, addr, 1, (u8 *)&valw, 1);
+
+error:
+ i2c_set_bus_num(org_bus_num);
+ return ret;
+}
+
+static int tca642x_reg_read(uchar chip, uint8_t addr, uint8_t *data)
+{
+ uint8_t valw;
+ int org_bus_num;
+ int ret = 0;
+
+ org_bus_num = i2c_get_bus_num();
+ i2c_set_bus_num(CONFIG_SYS_I2C_TCA642X_BUS_NUM);
+ if (i2c_read(chip, addr, 1, (u8 *)&valw, 1)) {
+ ret = -1;
+ goto error;
+ }
+
+ *data = valw;
+
+error:
+ i2c_set_bus_num(org_bus_num);
+ return ret;
+}
+
+/*
+ * Set output value of IO pins in 'reg_bit' to corresponding value in 'data'
+ * 0 = low, 1 = high
+ */
+int tca642x_set_val(uchar chip, uint8_t gpio_bank,
+ uint8_t reg_bit, uint8_t data)
+{
+ uint8_t out_reg = tca642x_regs[gpio_bank].output_reg;
+
+ return tca642x_reg_write(chip, out_reg, reg_bit, data);
+}
+
+/*
+ * Set read polarity of IO pins in 'reg_bit' to corresponding value in 'data'
+ * 0 = read pin value, 1 = read inverted pin value
+ */
+int tca642x_set_pol(uchar chip, uint8_t gpio_bank,
+ uint8_t reg_bit, uint8_t data)
+{
+ uint8_t pol_reg = tca642x_regs[gpio_bank].polarity_reg;
+
+ return tca642x_reg_write(chip, pol_reg, reg_bit, data);
+}
+
+/*
+ * Set direction of IO pins in 'reg_bit' to corresponding value in 'data'
+ * 0 = output, 1 = input
+ */
+int tca642x_set_dir(uchar chip, uint8_t gpio_bank,
+ uint8_t reg_bit, uint8_t data)
+{
+ uint8_t config_reg = tca642x_regs[gpio_bank].configuration_reg;
+
+ return tca642x_reg_write(chip, config_reg, reg_bit, data);
+}
+
+/*
+ * Read current logic level of all IO pins
+ */
+int tca642x_get_val(uchar chip, uint8_t gpio_bank)
+{
+ uint8_t val;
+ uint8_t in_reg = tca642x_regs[gpio_bank].input_reg;
+
+ if (tca642x_reg_read(chip, in_reg, &val) < 0)
+ return -1;
+
+ return (int)val;
+}
+
+/*
+ * Set the inital register states for the tca642x gpio expander
+ */
+int tca642x_set_inital_state(uchar chip, struct tca642x_bank_info init_data[])
+{
+ int i, ret;
+ uint8_t config_reg;
+ uint8_t polarity_reg;
+ uint8_t output_reg;
+
+ for (i = 0; i < 3; i++) {
+ config_reg = tca642x_regs[i].configuration_reg;
+ ret = tca642x_reg_write(chip, config_reg, 0xff,
+ init_data[i].configuration_reg);
+ polarity_reg = tca642x_regs[i].polarity_reg;
+ ret = tca642x_reg_write(chip, polarity_reg, 0xff,
+ init_data[i].polarity_reg);
+ output_reg = tca642x_regs[i].output_reg;
+ ret = tca642x_reg_write(chip, output_reg, 0xff,
+ init_data[i].output_reg);
+ }
+
+ return ret;
+}
+
+#ifdef CONFIG_CMD_TCA642X
+/*
+ * Display tca642x information
+ */
+static int tca642x_info(uchar chip)
+{
+ int i, j;
+ uint8_t data;
+
+ printf("tca642x@ 0x%x (%d pins):\n", chip, 24);
+ for (i = 0; i < 3; i++) {
+ printf("Bank %i\n", i);
+ if (tca642x_reg_read(chip,
+ tca642x_regs[i].configuration_reg,
+ &data) < 0)
+ return -1;
+ printf("\tConfiguration: ");
+ for (j = 7; j >= 0; j--)
+ printf("%c", data & (1 << j) ? 'i' : 'o');
+ printf("\n");
+
+ if (tca642x_reg_read(chip,
+ tca642x_regs[i].polarity_reg, &data) < 0)
+ return -1;
+ printf("\tPolarity: ");
+ for (j = 7; j >= 0; j--)
+ printf("%c", data & (1 << j) ? '1' : '0');
+ printf("\n");
+
+ if (tca642x_reg_read(chip,
+ tca642x_regs[i].input_reg, &data) < 0)
+ return -1;
+ printf("\tInput value: ");
+ for (j = 7; j >= 0; j--)
+ printf("%c", data & (1 << j) ? '1' : '0');
+ printf("\n");
+
+ if (tca642x_reg_read(chip,
+ tca642x_regs[i].output_reg, &data) < 0)
+ return -1;
+ printf("\tOutput value: ");
+ for (j = 7; j >= 0; j--)
+ printf("%c", data & (1 << j) ? '1' : '0');
+ printf("\n");
+ }
+
+ return 0;
+}
+
+cmd_tbl_t cmd_tca642x[] = {
+ U_BOOT_CMD_MKENT(device, 3, 0, (void *)TCA642X_CMD_DEVICE, "", ""),
+ U_BOOT_CMD_MKENT(output, 4, 0, (void *)TCA642X_CMD_OUTPUT, "", ""),
+ U_BOOT_CMD_MKENT(input, 3, 0, (void *)TCA642X_CMD_INPUT, "", ""),
+ U_BOOT_CMD_MKENT(invert, 4, 0, (void *)TCA642X_CMD_INVERT, "", ""),
+ U_BOOT_CMD_MKENT(info, 2, 0, (void *)TCA642X_CMD_INFO, "", ""),
+};
+
+int do_tca642x(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ static uchar chip = CONFIG_SYS_I2C_TCA642X_ADDR;
+ int ret = CMD_RET_USAGE, val;
+ uint8_t gpio_bank = 0;
+ uint8_t bank_shift;
+ ulong ul_arg2 = 0;
+ ulong ul_arg3 = 0;
+ cmd_tbl_t *c;
+
+ c = find_cmd_tbl(argv[1], cmd_tca642x, ARRAY_SIZE(cmd_tca642x));
+
+ /* All commands but "device" require 'maxargs' arguments */
+ if (!c ||
+ !((argc == (c->maxargs)) ||
+ (((int)c->cmd == TCA642X_CMD_DEVICE) &&
+ (argc == (c->maxargs - 1))))) {
+ return CMD_RET_USAGE;
+ }
+
+ /* arg2 used as chip number or pin number */
+ if (argc > 2)
+ ul_arg2 = simple_strtoul(argv[2], NULL, 10);
+
+ /* arg3 used as pin or invert value */
+ if (argc > 3) {
+ ul_arg3 = simple_strtoul(argv[3], NULL, 10) & 0x1;
+ if (ul_arg2 <= 7) {
+ gpio_bank = 0;
+ } else if ((ul_arg2 >= 10) && (ul_arg2 <= 17)) {
+ gpio_bank = 1;
+ } else if ((ul_arg2 >= 20) && (ul_arg2 <= 27)) {
+ gpio_bank = 2;
+ } else {
+ printf("Requested pin is not available\n");
+ ret = CMD_RET_FAILURE;
+ goto error;
+ }
+ }
+
+ switch ((int)c->cmd) {
+ case TCA642X_CMD_INFO:
+ ret = tca642x_info(chip);
+ if (ret)
+ ret = CMD_RET_FAILURE;
+ break;
+
+ case TCA642X_CMD_DEVICE:
+ if (argc == 3)
+ chip = (uint8_t)ul_arg2;
+ printf("Current device address: 0x%x\n", chip);
+ ret = CMD_RET_SUCCESS;
+ break;
+
+ case TCA642X_CMD_INPUT:
+ bank_shift = ul_arg2 - (gpio_bank * 10);
+ ret = tca642x_set_dir(chip, gpio_bank, (1 << bank_shift),
+ TCA642X_DIR_IN << bank_shift);
+ val = (tca642x_get_val(chip, gpio_bank) &
+ (1 << bank_shift)) != 0;
+
+ if (ret)
+ ret = CMD_RET_FAILURE;
+ else
+ printf("chip 0x%02x, pin 0x%lx = %d\n", chip,
+ ul_arg2, val);
+ break;
+
+ case TCA642X_CMD_OUTPUT:
+ bank_shift = ul_arg2 - (gpio_bank * 10);
+ ret = tca642x_set_dir(chip, gpio_bank, (1 << bank_shift),
+ (TCA642X_DIR_OUT << bank_shift));
+ if (!ret)
+ ret = tca642x_set_val(chip,
+ gpio_bank, (1 << bank_shift),
+ (ul_arg3 << bank_shift));
+ if (ret)
+ ret = CMD_RET_FAILURE;
+ break;
+
+ case TCA642X_CMD_INVERT:
+ bank_shift = ul_arg2 - (gpio_bank * 10);
+ ret = tca642x_set_pol(chip, gpio_bank, (1 << bank_shift),
+ (ul_arg3 << bank_shift));
+ if (ret)
+ ret = CMD_RET_FAILURE;
+ break;
+ }
+error:
+ if (ret == CMD_RET_FAILURE)
+ eprintf("Error talking to chip at 0x%x\n", chip);
+
+ return ret;
+}
+
+U_BOOT_CMD(
+ tca642x, 5, 1, do_tca642x,
+ "tca642x gpio access",
+ "device [dev]\n"
+ " - show or set current device address\n"
+ "tca642x info\n"
+ " - display info for current chip\n"
+ "tca642x output pin 0|1\n"
+ " - set pin as output and drive low or high\n"
+ "tca642x invert pin 0|1\n"
+ " - disable/enable polarity inversion for reads\n"
+ "tca642x input pin\n"
+ " - set pin as input and read value"
+);
+
+#endif /* CONFIG_CMD_TCA642X */
diff --git a/qemu/roms/u-boot/drivers/gpio/tegra_gpio.c b/qemu/roms/u-boot/drivers/gpio/tegra_gpio.c
new file mode 100644
index 000000000..82b30d5ab
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/tegra_gpio.c
@@ -0,0 +1,246 @@
+/*
+ * NVIDIA Tegra20 GPIO handling.
+ * (C) Copyright 2010-2012
+ * NVIDIA Corporation <www.nvidia.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*
+ * Based on (mostly copied from) kw_gpio.c based Linux 2.6 kernel driver.
+ * Tom Warren (twarren@nvidia.com)
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <asm/arch/tegra.h>
+#include <asm/gpio.h>
+
+enum {
+ TEGRA_CMD_INFO,
+ TEGRA_CMD_PORT,
+ TEGRA_CMD_OUTPUT,
+ TEGRA_CMD_INPUT,
+};
+
+static struct gpio_names {
+ char name[GPIO_NAME_SIZE];
+} gpio_names[MAX_NUM_GPIOS];
+
+static char *get_name(int i)
+{
+ return *gpio_names[i].name ? gpio_names[i].name : "UNKNOWN";
+}
+
+/* Return config of pin 'gpio' as GPIO (1) or SFPIO (0) */
+static int get_config(unsigned gpio)
+{
+ struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
+ struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
+ u32 u;
+ int type;
+
+ u = readl(&bank->gpio_config[GPIO_PORT(gpio)]);
+ type = (u >> GPIO_BIT(gpio)) & 1;
+
+ debug("get_config: port = %d, bit = %d is %s\n",
+ GPIO_FULLPORT(gpio), GPIO_BIT(gpio), type ? "GPIO" : "SFPIO");
+
+ return type;
+}
+
+/* Config pin 'gpio' as GPIO or SFPIO, based on 'type' */
+static void set_config(unsigned gpio, int type)
+{
+ struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
+ struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
+ u32 u;
+
+ debug("set_config: port = %d, bit = %d, %s\n",
+ GPIO_FULLPORT(gpio), GPIO_BIT(gpio), type ? "GPIO" : "SFPIO");
+
+ u = readl(&bank->gpio_config[GPIO_PORT(gpio)]);
+ if (type) /* GPIO */
+ u |= 1 << GPIO_BIT(gpio);
+ else
+ u &= ~(1 << GPIO_BIT(gpio));
+ writel(u, &bank->gpio_config[GPIO_PORT(gpio)]);
+}
+
+/* Return GPIO pin 'gpio' direction - 0 = input or 1 = output */
+static int get_direction(unsigned gpio)
+{
+ struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
+ struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
+ u32 u;
+ int dir;
+
+ u = readl(&bank->gpio_dir_out[GPIO_PORT(gpio)]);
+ dir = (u >> GPIO_BIT(gpio)) & 1;
+
+ debug("get_direction: port = %d, bit = %d, %s\n",
+ GPIO_FULLPORT(gpio), GPIO_BIT(gpio), dir ? "OUT" : "IN");
+
+ return dir;
+}
+
+/* Config GPIO pin 'gpio' as input or output (OE) as per 'output' */
+static void set_direction(unsigned gpio, int output)
+{
+ struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
+ struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
+ u32 u;
+
+ debug("set_direction: port = %d, bit = %d, %s\n",
+ GPIO_FULLPORT(gpio), GPIO_BIT(gpio), output ? "OUT" : "IN");
+
+ u = readl(&bank->gpio_dir_out[GPIO_PORT(gpio)]);
+ if (output)
+ u |= 1 << GPIO_BIT(gpio);
+ else
+ u &= ~(1 << GPIO_BIT(gpio));
+ writel(u, &bank->gpio_dir_out[GPIO_PORT(gpio)]);
+}
+
+/* set GPIO pin 'gpio' output bit as 0 or 1 as per 'high' */
+static void set_level(unsigned gpio, int high)
+{
+ struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
+ struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
+ u32 u;
+
+ debug("set_level: port = %d, bit %d == %d\n",
+ GPIO_FULLPORT(gpio), GPIO_BIT(gpio), high);
+
+ u = readl(&bank->gpio_out[GPIO_PORT(gpio)]);
+ if (high)
+ u |= 1 << GPIO_BIT(gpio);
+ else
+ u &= ~(1 << GPIO_BIT(gpio));
+ writel(u, &bank->gpio_out[GPIO_PORT(gpio)]);
+}
+
+/*
+ * Generic_GPIO primitives.
+ */
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ if (gpio >= MAX_NUM_GPIOS)
+ return -1;
+
+ if (label != NULL) {
+ strncpy(gpio_names[gpio].name, label, GPIO_NAME_SIZE);
+ gpio_names[gpio].name[GPIO_NAME_SIZE - 1] = '\0';
+ }
+
+ /* Configure as a GPIO */
+ set_config(gpio, 1);
+
+ return 0;
+}
+
+int gpio_free(unsigned gpio)
+{
+ if (gpio >= MAX_NUM_GPIOS)
+ return -1;
+
+ gpio_names[gpio].name[0] = '\0';
+ /* Do not configure as input or change pin mux here */
+ return 0;
+}
+
+/* read GPIO OUT value of pin 'gpio' */
+static int gpio_get_output_value(unsigned gpio)
+{
+ struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
+ struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
+ int val;
+
+ debug("gpio_get_output_value: pin = %d (port %d:bit %d)\n",
+ gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
+
+ val = readl(&bank->gpio_out[GPIO_PORT(gpio)]);
+
+ return (val >> GPIO_BIT(gpio)) & 1;
+}
+
+/* set GPIO pin 'gpio' as an input */
+int gpio_direction_input(unsigned gpio)
+{
+ debug("gpio_direction_input: pin = %d (port %d:bit %d)\n",
+ gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
+
+ /* Configure GPIO direction as input. */
+ set_direction(gpio, 0);
+
+ return 0;
+}
+
+/* set GPIO pin 'gpio' as an output, with polarity 'value' */
+int gpio_direction_output(unsigned gpio, int value)
+{
+ debug("gpio_direction_output: pin = %d (port %d:bit %d) = %s\n",
+ gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio),
+ value ? "HIGH" : "LOW");
+
+ /* Configure GPIO output value. */
+ set_level(gpio, value);
+
+ /* Configure GPIO direction as output. */
+ set_direction(gpio, 1);
+
+ return 0;
+}
+
+/* read GPIO IN value of pin 'gpio' */
+int gpio_get_value(unsigned gpio)
+{
+ struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
+ struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
+ int val;
+
+ debug("gpio_get_value: pin = %d (port %d:bit %d)\n",
+ gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
+
+ val = readl(&bank->gpio_in[GPIO_PORT(gpio)]);
+
+ return (val >> GPIO_BIT(gpio)) & 1;
+}
+
+/* write GPIO OUT value to pin 'gpio' */
+int gpio_set_value(unsigned gpio, int value)
+{
+ debug("gpio_set_value: pin = %d (port %d:bit %d), value = %d\n",
+ gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio), value);
+
+ /* Configure GPIO output value. */
+ set_level(gpio, value);
+
+ return 0;
+}
+
+/*
+ * Display Tegra GPIO information
+ */
+void gpio_info(void)
+{
+ unsigned c;
+ int type;
+
+ for (c = 0; c < MAX_NUM_GPIOS; c++) {
+ type = get_config(c); /* GPIO, not SFPIO */
+ if (type) {
+ printf("GPIO_%d:\t%s is an %s, ", c,
+ get_name(c),
+ get_direction(c) ? "OUTPUT" : "INPUT");
+ if (get_direction(c))
+ printf("value = %d", gpio_get_output_value(c));
+ else
+ printf("value = %d", gpio_get_value(c));
+ printf("\n");
+ } else
+ continue;
+ }
+}
diff --git a/qemu/roms/u-boot/drivers/gpio/xilinx_gpio.c b/qemu/roms/u-boot/drivers/gpio/xilinx_gpio.c
new file mode 100644
index 000000000..949fd96fe
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/gpio/xilinx_gpio.c
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2013 Xilinx, Michal Simek
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <malloc.h>
+#include <linux/list.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+
+static LIST_HEAD(gpio_list);
+
+enum gpio_direction {
+ GPIO_DIRECTION_OUT = 0,
+ GPIO_DIRECTION_IN = 1,
+};
+
+/* Gpio simple map */
+struct gpio_regs {
+ u32 gpiodata;
+ u32 gpiodir;
+};
+
+#define GPIO_NAME_SIZE 10
+
+struct gpio_names {
+ char name[GPIO_NAME_SIZE];
+};
+
+/* Initialized, rxbd_current, rx_first_buf must be 0 after init */
+struct xilinx_gpio_priv {
+ struct gpio_regs *regs;
+ u32 gpio_min;
+ u32 gpio_max;
+ u32 gpiodata_store;
+ char name[GPIO_NAME_SIZE];
+ struct list_head list;
+ struct gpio_names *gpio_name;
+};
+
+/* Store number of allocated gpio pins */
+static u32 xilinx_gpio_max;
+
+/* Get associated gpio controller */
+static struct xilinx_gpio_priv *gpio_get_controller(unsigned gpio)
+{
+ struct list_head *entry;
+ struct xilinx_gpio_priv *priv = NULL;
+
+ list_for_each(entry, &gpio_list) {
+ priv = list_entry(entry, struct xilinx_gpio_priv, list);
+ if (gpio >= priv->gpio_min && gpio <= priv->gpio_max) {
+ debug("%s: reg: %x, min-max: %d-%d\n", __func__,
+ (u32)priv->regs, priv->gpio_min, priv->gpio_max);
+ return priv;
+ }
+ }
+ puts("!!!Can't get gpio controller!!!\n");
+ return NULL;
+}
+
+/* Get gpio pin name if used/setup */
+static char *get_name(unsigned gpio)
+{
+ u32 gpio_priv;
+ struct xilinx_gpio_priv *priv;
+
+ debug("%s\n", __func__);
+
+ priv = gpio_get_controller(gpio);
+ if (priv) {
+ gpio_priv = gpio - priv->gpio_min;
+
+ return *priv->gpio_name[gpio_priv].name ?
+ priv->gpio_name[gpio_priv].name : "UNKNOWN";
+ }
+ return "UNKNOWN";
+}
+
+/* Get output value */
+static int gpio_get_output_value(unsigned gpio)
+{
+ u32 val, gpio_priv;
+ struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
+
+ if (priv) {
+ gpio_priv = gpio - priv->gpio_min;
+ val = !!(priv->gpiodata_store & (1 << gpio_priv));
+ debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__,
+ (u32)priv->regs, gpio_priv, val);
+
+ return val;
+ }
+ return -1;
+}
+
+/* Get input value */
+static int gpio_get_input_value(unsigned gpio)
+{
+ u32 val, gpio_priv;
+ struct gpio_regs *regs;
+ struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
+
+ if (priv) {
+ regs = priv->regs;
+ gpio_priv = gpio - priv->gpio_min;
+ val = readl(&regs->gpiodata);
+ val = !!(val & (1 << gpio_priv));
+ debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__,
+ (u32)priv->regs, gpio_priv, val);
+
+ return val;
+ }
+ return -1;
+}
+
+/* Set gpio direction */
+static int gpio_set_direction(unsigned gpio, enum gpio_direction direction)
+{
+ u32 val, gpio_priv;
+ struct gpio_regs *regs;
+ struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
+
+ if (priv) {
+ regs = priv->regs;
+ val = readl(&regs->gpiodir);
+
+ gpio_priv = gpio - priv->gpio_min;
+ if (direction == GPIO_DIRECTION_OUT)
+ val &= ~(1 << gpio_priv);
+ else
+ val |= 1 << gpio_priv;
+
+ writel(val, &regs->gpiodir);
+ debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__,
+ (u32)priv->regs, gpio_priv, val);
+
+ return 0;
+ }
+
+ return -1;
+}
+
+/* Get gpio direction */
+static int gpio_get_direction(unsigned gpio)
+{
+ u32 val, gpio_priv;
+ struct gpio_regs *regs;
+ struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
+
+ if (priv) {
+ regs = priv->regs;
+ gpio_priv = gpio - priv->gpio_min;
+ val = readl(&regs->gpiodir);
+ val = !!(val & (1 << gpio_priv));
+ debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__,
+ (u32)priv->regs, gpio_priv, val);
+
+ return val;
+ }
+
+ return -1;
+}
+
+/*
+ * Get input value
+ * for example gpio setup to output only can't get input value
+ * which is breaking gpio toggle command
+ */
+int gpio_get_value(unsigned gpio)
+{
+ u32 val;
+
+ if (gpio_get_direction(gpio) == GPIO_DIRECTION_OUT)
+ val = gpio_get_output_value(gpio);
+ else
+ val = gpio_get_input_value(gpio);
+
+ return val;
+}
+
+/* Set output value */
+static int gpio_set_output_value(unsigned gpio, int value)
+{
+ u32 val, gpio_priv;
+ struct gpio_regs *regs;
+ struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
+
+ if (priv) {
+ regs = priv->regs;
+ gpio_priv = gpio - priv->gpio_min;
+ val = priv->gpiodata_store;
+ if (value)
+ val |= 1 << gpio_priv;
+ else
+ val &= ~(1 << gpio_priv);
+
+ writel(val, &regs->gpiodata);
+ debug("%s: reg: %x, gpio_no: %d, output_val: %d\n", __func__,
+ (u32)priv->regs, gpio_priv, val);
+ priv->gpiodata_store = val;
+
+ return 0;
+ }
+
+ return -1;
+}
+
+int gpio_set_value(unsigned gpio, int value)
+{
+ if (gpio_get_direction(gpio) == GPIO_DIRECTION_OUT)
+ return gpio_set_output_value(gpio, value);
+
+ return -1;
+}
+
+/* Set GPIO as input */
+int gpio_direction_input(unsigned gpio)
+{
+ debug("%s\n", __func__);
+ return gpio_set_direction(gpio, GPIO_DIRECTION_IN);
+}
+
+/* Setup GPIO as output and set output value */
+int gpio_direction_output(unsigned gpio, int value)
+{
+ int ret = gpio_set_direction(gpio, GPIO_DIRECTION_OUT);
+
+ debug("%s\n", __func__);
+
+ if (ret < 0)
+ return ret;
+
+ return gpio_set_output_value(gpio, value);
+}
+
+/* Show gpio status */
+void gpio_info(void)
+{
+ unsigned gpio;
+
+ struct list_head *entry;
+ struct xilinx_gpio_priv *priv = NULL;
+
+ list_for_each(entry, &gpio_list) {
+ priv = list_entry(entry, struct xilinx_gpio_priv, list);
+ printf("\n%s: %s/%x (%d-%d)\n", __func__, priv->name,
+ (u32)priv->regs, priv->gpio_min, priv->gpio_max);
+
+ for (gpio = priv->gpio_min; gpio <= priv->gpio_max; gpio++) {
+ printf("GPIO_%d:\t%s is an ", gpio, get_name(gpio));
+ if (gpio_get_direction(gpio) == GPIO_DIRECTION_OUT)
+ printf("OUTPUT value = %d\n",
+ gpio_get_output_value(gpio));
+ else
+ printf("INPUT value = %d\n",
+ gpio_get_input_value(gpio));
+ }
+ }
+}
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ u32 gpio_priv;
+ struct xilinx_gpio_priv *priv;
+
+ if (gpio >= xilinx_gpio_max)
+ return -EINVAL;
+
+ priv = gpio_get_controller(gpio);
+ if (priv) {
+ gpio_priv = gpio - priv->gpio_min;
+
+ if (label != NULL) {
+ strncpy(priv->gpio_name[gpio_priv].name, label,
+ GPIO_NAME_SIZE);
+ priv->gpio_name[gpio_priv].name[GPIO_NAME_SIZE - 1] =
+ '\0';
+ }
+ return 0;
+ }
+
+ return -1;
+}
+
+int gpio_free(unsigned gpio)
+{
+ u32 gpio_priv;
+ struct xilinx_gpio_priv *priv;
+
+ if (gpio >= xilinx_gpio_max)
+ return -EINVAL;
+
+ priv = gpio_get_controller(gpio);
+ if (priv) {
+ gpio_priv = gpio - priv->gpio_min;
+ priv->gpio_name[gpio_priv].name[0] = '\0';
+
+ /* Do nothing here */
+ return 0;
+ }
+
+ return -1;
+}
+
+int gpio_alloc(u32 baseaddr, const char *name, u32 gpio_no)
+{
+ struct xilinx_gpio_priv *priv;
+
+ priv = calloc(1, sizeof(struct xilinx_gpio_priv));
+
+ /* Setup gpio name */
+ if (name != NULL) {
+ strncpy(priv->name, name, GPIO_NAME_SIZE);
+ priv->name[GPIO_NAME_SIZE - 1] = '\0';
+ }
+ priv->regs = (struct gpio_regs *)baseaddr;
+
+ priv->gpio_min = xilinx_gpio_max;
+ xilinx_gpio_max = priv->gpio_min + gpio_no;
+ priv->gpio_max = xilinx_gpio_max - 1;
+
+ priv->gpio_name = calloc(gpio_no, sizeof(struct gpio_names));
+
+ INIT_LIST_HEAD(&priv->list);
+ list_add_tail(&priv->list, &gpio_list);
+
+ printf("%s: Add %s (%d-%d)\n", __func__, name,
+ priv->gpio_min, priv->gpio_max);
+
+ /* Return the first gpio allocated for this device */
+ return priv->gpio_min;
+}
+
+/* Dual channel gpio is one IP with two independent channels */
+int gpio_alloc_dual(u32 baseaddr, const char *name, u32 gpio_no0, u32 gpio_no1)
+{
+ int ret;
+
+ ret = gpio_alloc(baseaddr, name, gpio_no0);
+ gpio_alloc(baseaddr + 8, strcat((char *)name, "_1"), gpio_no1);
+
+ /* Return the first gpio allocated for this device */
+ return ret;
+}