exynos/s5p: Add helper function for reading a single MVL3 GPIO

This adds a helper function to read only a single GPIO which uses
3-state logic. Examples of this typically include board straps which
are used to provide mainboard-specific information at the hardware-
level, such as board revision or configuration options.

This is part of a larger clean-up effort for Snow. We may want to
genericise this for other CPUs in the future.

Change-Id: Ic44f5e589cda89b419a07eca246847e9ce7dcd8d
Signed-off-by: David Hendricks <dhendrix@chromium.org>
Reviewed-on: http://review.coreboot.org/2266
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
This commit is contained in:
David Hendricks 2013-02-02 17:02:36 -08:00 committed by Ronald G. Minnich
parent d58ba2add4
commit ad7f98cb01
2 changed files with 54 additions and 25 deletions

View File

@ -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_ */

View File

@ -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;