summaryrefslogtreecommitdiffstats
path: root/src/lib/gpio.c
diff options
context:
space:
mode:
authorJulius Werner <jwerner@chromium.org>2016-03-16 17:11:55 -0700
committerJulius Werner <jwerner@chromium.org>2016-03-22 21:18:30 +0100
commit2b239485358ec063a4803f248c88378076810e24 (patch)
treeddb88cf8b776ccd3a9d91bef93529ed18f465bfb /src/lib/gpio.c
parent4a1c69aa34cec4a959bc3318d68c287ed4eafbb0 (diff)
downloadcoreboot-2b239485358ec063a4803f248c88378076810e24.tar.gz
coreboot-2b239485358ec063a4803f248c88378076810e24.tar.bz2
coreboot-2b239485358ec063a4803f248c88378076810e24.zip
gpio: Add support for binary_first base3 number system
This patch adds support for an alternative ternary number system in which group of GPIOs can be interpreted. In this system, the digit combinations that would form a binary number (i.e. that contain no 'Z' state) are used to represent the lower values in the way they're used in the normal binary system, and all the combinations that do contain a 'Z' are used to represent values above those. We can use this for boards that originally get strapped with binary board IDs but eventually require more revisions than that representation allows. We can switch their code to binary_first base3 and all old revisions with already produced boards will still get read as the correct numbers. Credit for the algorithm idea goes to Haran Talmon. BRANCH=None BUG=None TEST=Stubbed out the actual GPIO reading and simulated all combinations of 4 ternary digits for both number systems. Change-Id: Ib5127656455f97f890ce2999ba5ac5f58a20cf93 Signed-off-by: Julius Werner <jwerner@chromium.org> Reviewed-on: https://review.coreboot.org/14116 Tested-by: build bot (Jenkins) Reviewed-by: David Hendricks <dhendrix@chromium.org> Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'src/lib/gpio.c')
-rw-r--r--src/lib/gpio.c49
1 files changed, 47 insertions, 2 deletions
diff --git a/src/lib/gpio.c b/src/lib/gpio.c
index 5147cfebaceb..2e345956f8e1 100644
--- a/src/lib/gpio.c
+++ b/src/lib/gpio.c
@@ -35,7 +35,7 @@ int gpio_base2_value(gpio_t gpio[], int num_gpio)
return result;
}
-int gpio_base3_value(gpio_t gpio[], int num_gpio)
+int _gpio_base3_value(gpio_t gpio[], int num_gpio, int binary_first)
{
/*
* GPIOs which are tied to stronger external pull up or pull down
@@ -50,6 +50,8 @@ int gpio_base3_value(gpio_t gpio[], int num_gpio)
int temp;
int index;
int result = 0;
+ int has_z = 0;
+ int binary_below = 0;
char value[32];
assert(num_gpio <= 32);
@@ -85,8 +87,51 @@ int gpio_base3_value(gpio_t gpio[], int num_gpio)
temp |= ((value[index] ^ temp) << 1);
printk(BIOS_DEBUG, "%c ", tristate_char[temp]);
result = (result * 3) + temp;
+
+ /*
+ * For binary_first we keep track of the normal ternary result
+ * and whether we found any pin that was a Z. We also determine
+ * the amount of numbers that can be represented with only
+ * binary digits (no Z) whose value in the normal ternary system
+ * is lower than the one we are parsing. Counting from the left,
+ * we add 2^i for any '1' digit to account for the binary
+ * numbers whose values would be below it if all following
+ * digits we parsed would be '0'. As soon as we find a '2' digit
+ * we can total the remaining binary numbers below as 2^(i+1)
+ * because we know that all binary representations counting only
+ * this and following digits must have values below our number
+ * (since 1xxx is always smaller than 2xxx).
+ *
+ * Example: 1 0 2 1 (counting from the left / most significant)
+ * '1' at 3^3: Add 2^3 = 8 to account for binaries 0000-0111
+ * '0' at 3^2: Ignore (not all binaries 1000-1100 are below us)
+ * '2' at 3^1: Add 2^(1+1) = 4 to account for binaries 1000-1011
+ * Stop adding for lower digits (3^0), all already accounted
+ * now. We know that there can be no binary numbers 1020-102X.
+ */
+ if (binary_first && !has_z) {
+ switch(temp) {
+ case 0: /* Ignore '0' digits. */
+ break;
+ case 1: /* Account for binaries 0 to 2^index - 1. */
+ binary_below += 1 << index;
+ break;
+ case 2: /* Account for binaries 0 to 2^(index+1) - 1. */
+ binary_below += 1 << (index + 1);
+ has_z = 1;
+ }
+ }
+ }
+
+ if (binary_first) {
+ if (has_z)
+ result = result + (1 << num_gpio) - binary_below;
+ else /* binary_below is normal binary system value if !has_z. */
+ result = binary_below;
}
- printk(BIOS_DEBUG, "= %d\n", result);
+
+ printk(BIOS_DEBUG, "= %d (%s base3 number system)\n", result,
+ binary_first ? "binary_first" : "standard");
/* Disable pull up / pull down to conserve power */
for (index = 0; index < num_gpio; ++index)