summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cpu/samsung/exynos5250/gpio.h9
-rw-r--r--src/cpu/samsung/s5p-common/s5p_gpio.c70
2 files changed, 54 insertions, 25 deletions
diff --git a/src/cpu/samsung/exynos5250/gpio.h b/src/cpu/samsung/exynos5250/gpio.h
index 7606262062..12143849f5 100644
--- a/src/cpu/samsung/exynos5250/gpio.h
+++ b/src/cpu/samsung/exynos5250/gpio.h
@@ -477,6 +477,15 @@ void gpio_set_rate(int gpio, int mode);
*/
int gpio_decode_number(unsigned gpio_list[], int count);
+/*
+ * similar to gpio_decode_number, but reads only a single GPIO
+ *
+ * @param gpio GPIO to read
+ * @return -1 if the value cannot be determined. Otherwise returns
+ * the corresponding MVL3 enum value.
+ */
+int gpio_read_mvl3(unsigned gpio);
+
void gpio_info(void);
#endif /* EXYNOS5250_GPIO_H_ */
diff --git a/src/cpu/samsung/s5p-common/s5p_gpio.c b/src/cpu/samsung/s5p-common/s5p_gpio.c
index 50c451974c..f09d0a4ee5 100644
--- a/src/cpu/samsung/s5p-common/s5p_gpio.c
+++ b/src/cpu/samsung/s5p-common/s5p_gpio.c
@@ -21,6 +21,7 @@
/* FIXME(dhendrix): fix this up so it doesn't require a bunch of #ifdefs... */
#include <common.h>
//#include <arch/io.h>
+#include <gpio.h>
#include <arch/gpio.h>
#include <console/console.h>
#include <cpu/samsung/s5p-common/gpio.h>
@@ -414,42 +415,61 @@ int gpio_set_value(unsigned gpio, int value)
*/
#define GPIO_DELAY_US 5
-/* FIXME(dhendrix): this should probably go to a more generic location */
+int gpio_read_mvl3(unsigned gpio)
+{
+ int high, low;
+ enum mvl3 value;
+
+ if (gpio >= GPIO_MAX_PORT)
+ return -1;
+
+ gpio_direction_input(gpio);
+ gpio_set_pull(gpio, EXYNOS_GPIO_PULL_UP);
+ udelay(GPIO_DELAY_US);
+ high = gpio_get_value(gpio);
+ gpio_set_pull(gpio, EXYNOS_GPIO_PULL_DOWN);
+ udelay(GPIO_DELAY_US);
+ low = gpio_get_value(gpio);
+
+ if (high && low) /* external pullup */
+ value = LOGIC_1;
+ else if (!high && !low) /* external pulldown */
+ value = LOGIC_0;
+ else /* floating */
+ value = LOGIC_Z;
+
+ /*
+ * Check if line is externally pulled high and
+ * configure the internal pullup to match. For
+ * floating and pulldowns, the GPIO is already
+ * configured with an internal pulldown from the
+ * above test.
+ */
+ if (value == LOGIC_1)
+ gpio_set_pull(gpio, EXYNOS_GPIO_PULL_UP);
+
+ return value;
+}
+
int gpio_decode_number(unsigned gpio_list[], int count)
{
int result = 0;
int multiplier = 1;
- int value, high, low;
- int gpio, i;
+ int gpio, i, value;
+ enum mvl3 mvl3;
for (i = 0; i < count; i++) {
gpio = gpio_list[i];
- if (gpio >= GPIO_MAX_PORT)
- return -1;
- gpio_direction_input(gpio);
- gpio_set_pull(gpio, EXYNOS_GPIO_PULL_UP);
- udelay(GPIO_DELAY_US);
- high = gpio_get_value(gpio);
- gpio_set_pull(gpio, EXYNOS_GPIO_PULL_DOWN);
- udelay(GPIO_DELAY_US);
- low = gpio_get_value(gpio);
- if (high && low) /* external pullup */
+ mvl3 = gpio_read_mvl3(gpio);
+ if (mvl3 == LOGIC_1)
value = 2;
- else if (!high && !low) /* external pulldown */
+ else if (mvl3 == LOGIC_0)
value = 1;
- else /* floating */
+ else if (mvl3 == LOGIC_Z)
value = 0;
-
- /*
- * Check if line is externally pulled high and
- * configure the internal pullup to match. For
- * floating and pulldowns, the GPIO is already
- * configured with an internal pulldown from the
- * above test.
- */
- if (value == 2)
- gpio_set_pull(gpio, EXYNOS_GPIO_PULL_UP);
+ else
+ return -1;
result += value * multiplier;
multiplier *= 3;