ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/marvell/uboot/drivers/gpio/s5p_gpio.c b/marvell/uboot/drivers/gpio/s5p_gpio.c
new file mode 100644
index 0000000..7eeb96d
--- /dev/null
+++ b/marvell/uboot/drivers/gpio/s5p_gpio.c
@@ -0,0 +1,178 @@
+/*
+ * (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 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)
+{
+	int bank;
+	unsigned g = gpio - s5p_gpio_part_max(gpio);
+
+	bank = g / GPIO_PER_BANK;
+	bank *= sizeof(struct s5p_gpio_bank);
+	return (struct s5p_gpio_bank *) (s5p_gpio_base(gpio) + bank);
+}
+
+int s5p_gpio_get_pin(unsigned gpio)
+{
+	return gpio % GPIO_PER_BANK;
+}
+
+/* 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;
+}