tegra124: support tri-state Board Id

Since Nyan Big board id pins may layout in tri-state, we need code
to support this change.

We use every two-bit to encode a gpio state as below:
 b00: LOW
 b01: HIGH
 b10: TRI-STATE

BUG=none
TEST=emerge-nyan chromeos-coreboot-nyan
     coreboot log shows "Board TRISTATE ID: 0x41" for gpios 1001

Change-Id: I05d63f0bdafd533ef9d9e0da668837ecd2f4c8c0
Signed-off-by: Jimmy Zhang <jimmzhang@nvidia.com>
Reviewed-on: https://chromium-review.googlesource.com/183855
Reviewed-by: Gabe Black <gabeblack@chromium.org>
Commit-Queue: Doug Anderson <dianders@chromium.org>
This commit is contained in:
Jimmy Zhang 2014-01-24 18:04:36 -08:00 committed by chrome-internal-fetch
commit 1a9d1bd73a
3 changed files with 66 additions and 5 deletions

View file

@ -19,6 +19,7 @@
#include <console/console.h>
#include <soc/nvidia/tegra124/gpio.h>
#include <stdlib.h>
#include "boardid.h"
@ -27,11 +28,17 @@ uint8_t board_id(void)
static int id = -1;
if (id < 0) {
id = gpio_get_in_value(GPIO(Q3)) << 0 |
gpio_get_in_value(GPIO(T1)) << 1 |
gpio_get_in_value(GPIO(X1)) << 2 |
gpio_get_in_value(GPIO(X4)) << 3;
printk(BIOS_SPEW, "Board ID: %#x.\n", id);
gpio_t gpio[] = {GPIO(Q3), GPIO(T1), GPIO(X1), GPIO(X4)};
int value[ARRAY_SIZE(gpio)];
gpio_get_in_tristate_values(gpio, ARRAY_SIZE(gpio), value);
/* A gpio state is encoded in every two-bit */
id = value[0] << 0 |
value[1] << 2 |
value[2] << 4 |
value[3] << 6;
printk(BIOS_SPEW, "Board TRISTATE ID: %#x.\n", id);
}
return id;

View file

@ -22,6 +22,7 @@
#include <soc/addressmap.h>
#include <stddef.h>
#include <stdint.h>
#include <delay.h>
#include "gpio.h"
#include "pinmux.h"
@ -174,6 +175,58 @@ int gpio_get_in_value(gpio_t gpio)
return (port & (1 << bit)) != 0;
}
int gpio_get_in_tristate_values(gpio_t gpio[], int num_gpio, int value[])
{
/*
* GPIOs which are tied to stronger external pull up or pull down
* will stay there regardless of the internal pull up or pull
* down setting.
*
* GPIOs which are floating will go to whatever level they're
* internally pulled to.
*/
int temp;
int index;
/* Enable internal pull up */
for (index = 0; index < num_gpio; ++index)
gpio_input_pullup(gpio[index]);
/* Wait until signals become stable */
udelay(10);
/* Get gpio values at internal pull up */
for (index = 0; index < num_gpio; ++index)
value[index] = gpio_get_in_value(gpio[index]);
/* Enable internal pull down */
for (index = 0; index < num_gpio; ++index)
gpio_input_pulldown(gpio[index]);
/* Wait until signals become stable */
udelay(10);
/*
* Get gpio values at internal pull down.
* Compare with gpio pull up value and then
* determine a gpio final value/state:
* 0: pull down
* 1: pull up
* 2: floating
*/
for (index = 0; index < num_gpio; ++index) {
temp = gpio_get_in_value(gpio[index]);
value[index] = ((value[index] ^ temp) << 1) | temp;
}
/* Disable pull up / pull down to conserve power */
for (index = 0; index < num_gpio; ++index)
gpio_input(gpio[index]);
return 0;
}
int gpio_get_int_status(gpio_t gpio)
{
int bit = gpio % GPIO_GPIOS_PER_PORT;

View file

@ -81,6 +81,7 @@ void gpio_set_out_value(gpio_t gpio, int value);
int gpio_get_out_value(gpio_t gpio);
int gpio_get_in_value(gpio_t gpio);
int gpio_get_in_tristate_values(gpio_t gpio[], int num_gpio, int value[]);
int gpio_get_int_status(gpio_t gpio);