diff --git a/src/include/base3.h b/src/include/base3.h new file mode 100644 index 0000000000..e92cc8bae7 --- /dev/null +++ b/src/include/base3.h @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SRC_INCLUDE_BASE3_H__ +#define __SRC_INCLUDE_BASE3_H__ + +/* We translate a floating pin (Z) as the ternary digit 2. */ +#define Z 2 + +/* + * This provides a variadic macro BASE3() that can be used to translate a set of + * pin states into its base-3 integer representation, even in the context of a + * static initializer. You can call it with any number of up to 6 arguments, + * e.g. BASE3(1, Z) -> 5 or BASE3(0, Z, 1, 0) -> 21. Just don't look too closely + * at how the sausage is made. (Pay extra attention to typos when expanding it!) + */ +#define _BASE3_IMPL_1(arg0, arg1, arg2, arg3, arg4, arg5) arg0 +#define _BASE3_IMPL_2(arg0, arg1, arg2, arg3, arg4, arg5) \ + (arg1 + (3 * _BASE3_IMPL_1(arg0, arg1, arg2, arg3, arg4, arg5))) +#define _BASE3_IMPL_3(arg0, arg1, arg2, arg3, arg4, arg5) \ + (arg2 + (3 * _BASE3_IMPL_2(arg0, arg1, arg2, arg3, arg4, arg5))) +#define _BASE3_IMPL_4(arg0, arg1, arg2, arg3, arg4, arg5) \ + (arg3 + (3 * _BASE3_IMPL_3(arg0, arg1, arg2, arg3, arg4, arg5))) +#define _BASE3_IMPL_5(arg0, arg1, arg2, arg3, arg4, arg5) \ + (arg4 + (3 * _BASE3_IMPL_4(arg0, arg1, arg2, arg3, arg4, arg5))) +#define _BASE3_IMPL_6(arg0, arg1, arg2, arg3, arg4, arg5) \ + (arg5 + (3 * _BASE3_IMPL_5(arg0, arg1, arg2, arg3, arg4, arg5))) +#define _BASE3_IMPL(arg0, arg1, arg2, arg3, arg4, arg5, NARGS, ...) \ + _BASE3_IMPL##NARGS(arg0, arg1, arg2, arg3, arg4, arg5) +#define BASE3(...) _BASE3_IMPL(__VA_ARGS__, _6, _5, _4, _3, _2, _1) + +#endif /* __SRC_INCLUDE_BASE3_H__ */ diff --git a/src/include/gpio.h b/src/include/gpio.h index af06697050..b2a341dabc 100644 --- a/src/include/gpio.h +++ b/src/include/gpio.h @@ -36,17 +36,13 @@ void gpio_output(gpio_t gpio, int value); /* * Read the value presented by the set of GPIOs, when each pin is interpreted - * as a number in 0..2 range depending on the external pullup situation. + * as a base-3 digit (LOW = 0, HIGH = 1, Z/floating = 2). + * Example: X1 = Z, X2 = 1 -> gpio_get_tristates({GPIO(X1), GPIO(X2)}) = 5 + * BASE3() from can generate numbers to compare the result to. * - * Depending on the third parameter, the return value is either a set of two - * bit fields, each representing one GPIO value, or a number where each GPIO is - * included multiplied by 3^gpio_num, resulting in a true tertiary value. - * - * gpio[]: pin positions to read. little-endian (less significant value first). + * gpio[]: pin positions to read. gpio[0] is less significant than gpio[1]. * num_gpio: number of pins to read. - * tertiary: 1: pins are interpreted as a quad coded tertiary. - * 0: pins are interpreted as a set of two bit fields. */ -int gpio_get_tristates(gpio_t gpio[], int num_gpio, int tertiary); +int gpio_get_tristates(gpio_t gpio[], int num_gpio); #endif /* __SRC_INCLUDE_GPIO_H__ */ diff --git a/src/lib/tristate_gpios.c b/src/lib/tristate_gpios.c index 5ee5580ae8..0967a8f4be 100644 --- a/src/lib/tristate_gpios.c +++ b/src/lib/tristate_gpios.c @@ -17,10 +17,12 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include #include #include -int gpio_get_tristates(gpio_t gpio[], int num_gpio, int tertiary) +int gpio_get_tristates(gpio_t gpio[], int num_gpio) { /* * GPIOs which are tied to stronger external pull up or pull down @@ -31,6 +33,7 @@ int gpio_get_tristates(gpio_t gpio[], int num_gpio, int tertiary) * internally pulled to. */ + static const char tristate_char[] = {[0] = '0', [1] = '1', [Z] = 'Z'}; int temp; int index; int id = 0; @@ -62,14 +65,14 @@ int gpio_get_tristates(gpio_t gpio[], int num_gpio, int tertiary) * 1: pull up * 2: floating */ + printk(BIOS_DEBUG, "Reading tristate GPIOs: "); for (index = num_gpio - 1; index >= 0; --index) { - if (tertiary) - id *= 3; - else - id <<= 2; temp = gpio_get(gpio[index]); - id += ((value[index] ^ temp) << 1) | temp; + temp |= ((value[index] ^ temp) << 1); + printk(BIOS_DEBUG, "%c ", tristate_char[temp]); + id = (id * 3) + temp; } + printk(BIOS_DEBUG, "= %d\n", id); /* Disable pull up / pull down to conserve power */ for (index = 0; index < num_gpio; ++index) diff --git a/src/mainboard/google/nyan_big/boardid.c b/src/mainboard/google/nyan_big/boardid.c index 00f646d392..b420f5aca0 100644 --- a/src/mainboard/google/nyan_big/boardid.c +++ b/src/mainboard/google/nyan_big/boardid.c @@ -25,13 +25,13 @@ uint8_t board_id(void) { static int id = -1; + gpio_t gpio[] = {[3] = GPIO(X4), [2] = GPIO(X1), /* X4 is MSB */ + [1] = GPIO(T1), [0] = GPIO(Q3),}; /* Q3 is LSB */ if (id < 0) { - gpio_t gpio[] = {GPIO(Q3), GPIO(T1), GPIO(X1), GPIO(X4)}; + id = gpio_get_tristates(gpio, ARRAY_SIZE(gpio)); - id = gpio_get_tristates(gpio, ARRAY_SIZE(gpio), 0); - - printk(BIOS_SPEW, "Board TRISTATE ID: %#x.\n", id); + printk(BIOS_SPEW, "Board TRISTATE ID: %d.\n", id); } return id; diff --git a/src/mainboard/google/nyan_blaze/boardid.c b/src/mainboard/google/nyan_blaze/boardid.c index 00f646d392..b420f5aca0 100644 --- a/src/mainboard/google/nyan_blaze/boardid.c +++ b/src/mainboard/google/nyan_blaze/boardid.c @@ -25,13 +25,13 @@ uint8_t board_id(void) { static int id = -1; + gpio_t gpio[] = {[3] = GPIO(X4), [2] = GPIO(X1), /* X4 is MSB */ + [1] = GPIO(T1), [0] = GPIO(Q3),}; /* Q3 is LSB */ if (id < 0) { - gpio_t gpio[] = {GPIO(Q3), GPIO(T1), GPIO(X1), GPIO(X4)}; + id = gpio_get_tristates(gpio, ARRAY_SIZE(gpio)); - id = gpio_get_tristates(gpio, ARRAY_SIZE(gpio), 0); - - printk(BIOS_SPEW, "Board TRISTATE ID: %#x.\n", id); + printk(BIOS_SPEW, "Board TRISTATE ID: %d.\n", id); } return id; diff --git a/src/mainboard/google/rush_ryu/boardid.c b/src/mainboard/google/rush_ryu/boardid.c index ba3a4be9e9..5b4c1cd73f 100644 --- a/src/mainboard/google/rush_ryu/boardid.c +++ b/src/mainboard/google/rush_ryu/boardid.c @@ -17,35 +17,13 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include #include #include "gpio.h" -/* - * +------------------+---------+ - * | BD_ID_STRAP[1:0] | PHASE | - * +------------------+---------+ - * | 00 | PROTO0 | - * +------------------+---------+ - * | 01 | PROTO1 | - * +------------------+---------+ - * | 0Z | EVT | - * +------------------+---------+ - * | 10 | DVT | - * +------------------+---------+ - * | 11 | PVT | - * +------------------+---------+ - * | 1Z | MP | - * +------------------+---------+ - * | Z0 | | - * +------------------+---------+ - * | Z1 | | - * +------------------+---------+ - * | ZZ | | - * +------------------+---------+ - */ struct id_to_str { const char *str; int tri_state_value; @@ -53,15 +31,15 @@ struct id_to_str { }; static const struct id_to_str bdid_map[] = { - { "PROTO 0", 0x00, BOARD_ID_PROTO_0 }, - { "PROTO 1", 0x01, BOARD_ID_PROTO_1 }, - { "EVT", 0x02, BOARD_ID_EVT }, - { "DVT", 0x04, BOARD_ID_DVT }, - { "PVT", 0x05, BOARD_ID_PVT }, - { "MP", 0x06, BOARD_ID_MP }, - { "Z0", 0x08, -1 }, - { "Z1", 0x09, -1 }, - { "ZZ", 0x0a, -1 }, + { "PROTO 0", BASE3(0, 0), BOARD_ID_PROTO_0 }, + { "PROTO 1", BASE3(0, 1), BOARD_ID_PROTO_1 }, + { "EVT", BASE3(0, Z), BOARD_ID_EVT }, + { "DVT", BASE3(1, 0), BOARD_ID_DVT }, + { "PVT", BASE3(1, 1), BOARD_ID_PVT }, + { "MP", BASE3(1, Z), BOARD_ID_MP }, + { "Z0", BASE3(Z, 0), -1 }, + { "Z1", BASE3(Z, 1), -1 }, + { "ZZ", BASE3(Z, Z), -1 }, }; uint8_t board_id(void) @@ -72,9 +50,9 @@ uint8_t board_id(void) const char *idstr = "Unknown"; int i; int tristate_id; - gpio_t gpio[] = { BD_ID0, BD_ID1 }; + gpio_t gpio[] = {[1] = BD_ID1, [0] = BD_ID0}; /* ID0 is LSB */ - tristate_id = gpio_get_tristates(gpio, ARRAY_SIZE(gpio), 0); + tristate_id = gpio_get_tristates(gpio, ARRAY_SIZE(gpio)); for (i = 0; i < ARRAY_SIZE(bdid_map); i++) { if (tristate_id != bdid_map[i].tri_state_value) diff --git a/src/mainboard/google/storm/boardid.c b/src/mainboard/google/storm/boardid.c index 878598bf92..c32567e273 100644 --- a/src/mainboard/google/storm/boardid.c +++ b/src/mainboard/google/storm/boardid.c @@ -42,10 +42,10 @@ static int board_id_value = -1; static uint8_t get_board_id(void) { uint8_t bid; - gpio_t hw_rev_gpios[] = {29, 30, 68}; + gpio_t hw_rev_gpios[] = {[2] = 68, [1] = 30, [0] = 29}; /* 29 is LSB */ int offset = 19; - bid = gpio_get_tristates(hw_rev_gpios, ARRAY_SIZE(hw_rev_gpios), 1); + bid = gpio_get_tristates(hw_rev_gpios, ARRAY_SIZE(hw_rev_gpios)); bid = (bid + offset) % 27; printk(BIOS_INFO, "Board ID %d\n", bid); diff --git a/src/mainboard/google/veyron_pinky/boardid.c b/src/mainboard/google/veyron_pinky/boardid.c index d8f4a3d7f7..8d3e183ed1 100644 --- a/src/mainboard/google/veyron_pinky/boardid.c +++ b/src/mainboard/google/veyron_pinky/boardid.c @@ -25,12 +25,8 @@ uint8_t board_id(void) { static int id = -1; - static const gpio_t pins[] = { - { .port = 2, .bank = GPIO_A, .idx = 0 }, - { .port = 2, .bank = GPIO_A, .idx = 1 }, - { .port = 2, .bank = GPIO_A, .idx = 2 }, - { .port = 2, .bank = GPIO_A, .idx = 7 }, - }; + static const gpio_t pins[] = {[3] = GPIO(2, A, 7), [2] = GPIO(2, A, 2), + [1] = GPIO(2, A, 1), [0] = GPIO(2, A, 0)}; /* GPIO2_A0 is LSB */ if (id < 0) { int i; @@ -40,7 +36,7 @@ uint8_t board_id(void) gpio_input(pins[i]); id |= gpio_get(pins[i]) << i; } - printk(BIOS_SPEW, "Board ID: %#x.\n", id); + printk(BIOS_SPEW, "Board ID: %d.\n", id); } return id;