diff --git a/src/Kconfig b/src/Kconfig index 26141fe3a2..25184eb887 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -1122,6 +1122,13 @@ config DEBUG_COVERAGE If enabled, the code coverage hooks in coreboot will output some information about the coverage data that is dumped. +config TERTIARY_BOARD_ID + bool "Interpret board ID GPIOs as tertiary inputs" + default n + help + Consider each GPIO as being in one of three states: pulled down (0), + pulled up (1), or not connected (2) + endmenu # These probably belong somewhere else, but they are needed somewhere. @@ -1184,4 +1191,4 @@ config MAX_REBOOT_CNT help Internal option that sets the maximum number of bootblock executions allowed with the normal image enabled before assuming the normal image is defective - and switching to the fallback image. \ No newline at end of file + and switching to the fallback image. diff --git a/src/include/gpiolib.h b/src/include/gpiolib.h new file mode 100644 index 0000000000..daec3b66bd --- /dev/null +++ b/src/include/gpiolib.h @@ -0,0 +1,47 @@ +/* + * 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_GPIOLIB_H__ +#define __SRC_INCLUDE_GPIOLIB_H__ + +/* A generic type, use accessor macros to actually access the hardware. */ +typedef unsigned gpio_t; + +/* + * 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. + * + * 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. + * + */ +int gpio_board_id(gpio_t gpio[], int num_gpio, int tertiary); + +/* + * The following functions are not provided by the common library, but must be + * implemented by the appropriate SOC/board instead. + */ +int gpio_get_in_value(gpio_t gpio); +void gpio_set_out_value(gpio_t gpio, int value); +void gpio_input_pulldown(gpio_t gpio); +void gpio_input_pullup(gpio_t gpio); +void gpio_input(gpio_t gpio); + +#endif diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index d1e3a92b21..1e70e2e01a 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -57,6 +57,7 @@ ifeq ($(CONFIG_COMPILER_GCC),y) romstage-$(CONFIG_ARCH_ROMSTAGE_X86_32) += gcc.c ramstage-$(CONFIG_ARCH_RAMSTAGE_X86_32) += gcc.c endif +romstage-$(CONFIG_TERTIARY_BOARD_ID) += tristate_gpios.c ramstage-y += hardwaremain.c ramstage-y += selfboot.c diff --git a/src/lib/tristate_gpios.c b/src/lib/tristate_gpios.c new file mode 100644 index 0000000000..b1ebbc0f71 --- /dev/null +++ b/src/lib/tristate_gpios.c @@ -0,0 +1,79 @@ +/* + * 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 + */ + +#include +#include + +int gpio_board_id(gpio_t gpio[], int num_gpio, int tertiary) +{ + /* + * 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; + int id = 0; + char value[num_gpio]; + + /* 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) { + if (tertiary) + id *= 3; + else + id <<= 2; + temp = gpio_get_in_value(gpio[index]); + id += ((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 id; +} diff --git a/src/mainboard/google/nyan_big/boardid.c b/src/mainboard/google/nyan_big/boardid.c index c7bd2e6a1d..c79af45812 100644 --- a/src/mainboard/google/nyan_big/boardid.c +++ b/src/mainboard/google/nyan_big/boardid.c @@ -29,15 +29,9 @@ uint8_t board_id(void) if (id < 0) { 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); + id = gpio_board_id(gpio, ARRAY_SIZE(gpio), 0); - /* 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); } diff --git a/src/mainboard/google/nyan_blaze/boardid.c b/src/mainboard/google/nyan_blaze/boardid.c index c7bd2e6a1d..c79af45812 100644 --- a/src/mainboard/google/nyan_blaze/boardid.c +++ b/src/mainboard/google/nyan_blaze/boardid.c @@ -29,15 +29,9 @@ uint8_t board_id(void) if (id < 0) { 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); + id = gpio_board_id(gpio, ARRAY_SIZE(gpio), 0); - /* 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); } diff --git a/src/soc/nvidia/tegra/gpio.c b/src/soc/nvidia/tegra/gpio.c index b10cded12d..17b90aa1d9 100644 --- a/src/soc/nvidia/tegra/gpio.c +++ b/src/soc/nvidia/tegra/gpio.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "gpio.h" #include "pinmux.h" @@ -175,58 +176,6 @@ 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; @@ -279,3 +228,18 @@ void gpio_set_int_clear(gpio_t gpio) offsetof(struct gpio_bank, int_clear), 1 << bit, 1 << bit); } + +void gpio_input_pulldown(gpio_t gpio) +{ + __gpio_input(gpio, PINMUX_PULL_DOWN); +} + +void gpio_input_pullup(gpio_t gpio) +{ + __gpio_input(gpio, PINMUX_PULL_UP); +} + +void gpio_input(gpio_t gpio) +{ + __gpio_input(gpio, PINMUX_PULL_NONE); +} diff --git a/src/soc/nvidia/tegra/gpio.h b/src/soc/nvidia/tegra/gpio.h index 5f6833af79..43f898958e 100644 --- a/src/soc/nvidia/tegra/gpio.h +++ b/src/soc/nvidia/tegra/gpio.h @@ -21,12 +21,10 @@ #define __SOC_NVIDIA_TEGRA_GPIO_H__ #include +#include #include "pinmux.h" -/* Wrapper type for GPIOs. Always use GPIO() macro to generate. */ -typedef u32 gpio_t; - #define GPIO_PINMUX_SHIFT 16 #define GPIO(name) ((gpio_t)(GPIO_##name##_INDEX | \ (PINMUX_GPIO_##name << GPIO_PINMUX_SHIFT))) @@ -46,21 +44,6 @@ static inline void gpio_output_open_drain(gpio_t gpio, int value) __gpio_output(gpio, value, PINMUX_OPEN_DRAIN); } -static inline void gpio_input(gpio_t gpio) -{ - __gpio_input(gpio, PINMUX_PULL_NONE); -} - -static inline void gpio_input_pulldown(gpio_t gpio) -{ - __gpio_input(gpio, PINMUX_PULL_DOWN); -} - -static inline void gpio_input_pullup(gpio_t gpio) -{ - __gpio_input(gpio, PINMUX_PULL_UP); -} - /* Functions to modify specific GPIO control values. */ enum gpio_mode { @@ -77,12 +60,8 @@ int gpio_get_lock(gpio_t gpio); void gpio_set_out_enable(gpio_t gpio, int enable); int gpio_get_out_enable(gpio_t gpio); -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); void gpio_set_int_enable(gpio_t gpio, int enable); diff --git a/src/soc/qualcomm/ipq806x/include/gpio.h b/src/soc/qualcomm/ipq806x/include/gpio.h index c1cefd4a8b..1f35aa7061 100644 --- a/src/soc/qualcomm/ipq806x/include/gpio.h +++ b/src/soc/qualcomm/ipq806x/include/gpio.h @@ -33,7 +33,7 @@ #ifndef __SOC_QUALCOMM_IPQ806X_GPIO_H_ #define __SOC_QUALCOMM_IPQ806X_GPIO_H_ -typedef unsigned int gpio_t; +#include #define GPIO_FUNC_ENABLE 1 #define GPIO_FUNC_DISABLE 0