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:
parent
96722f750a
commit
1a9d1bd73a
3 changed files with 66 additions and 5 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue