xref: /aosp_15_r20/external/coreboot/src/lib/gpio.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <base3.h>
4 #include <console/console.h>
5 #include <delay.h>
6 #include <gpio.h>
7 
_check_num(const char * name,int num)8 static void _check_num(const char *name, int num)
9 {
10 	if ((num > 31) || (num < 1)) {
11 		printk(BIOS_EMERG, "%s: %d ", name, num);
12 		die("is an invalid number of GPIOs");
13 	}
14 }
15 
_gpio_base2_value(const gpio_t gpio[],int num_gpio)16 static uint32_t _gpio_base2_value(const gpio_t gpio[], int num_gpio)
17 {
18 	uint32_t result = 0;
19 	int i;
20 
21 	/* Wait until signals become stable */
22 	udelay(10);
23 
24 	for (i = 0; i < num_gpio; i++)
25 		result |= gpio_get(gpio[i]) << i;
26 
27 	return result;
28 }
29 
gpio_base2_value(const gpio_t gpio[],int num_gpio)30 uint32_t gpio_base2_value(const gpio_t gpio[], int num_gpio)
31 {
32 	int i;
33 
34 	_check_num(__func__, num_gpio);
35 	for (i = 0; i < num_gpio; i++)
36 		gpio_input(gpio[i]);
37 
38 	return _gpio_base2_value(gpio, num_gpio);
39 }
40 
gpio_pulldown_base2_value(const gpio_t gpio[],int num_gpio)41 uint32_t gpio_pulldown_base2_value(const gpio_t gpio[], int num_gpio)
42 {
43 	int i;
44 
45 	_check_num(__func__, num_gpio);
46 	for (i = 0; i < num_gpio; i++)
47 		gpio_input_pulldown(gpio[i]);
48 
49 	return _gpio_base2_value(gpio, num_gpio);
50 }
51 
gpio_pullup_base2_value(const gpio_t gpio[],int num_gpio)52 uint32_t gpio_pullup_base2_value(const gpio_t gpio[], int num_gpio)
53 {
54 	int i;
55 
56 	_check_num(__func__, num_gpio);
57 	for (i = 0; i < num_gpio; i++)
58 		gpio_input_pullup(gpio[i]);
59 
60 	return _gpio_base2_value(gpio, num_gpio);
61 }
62 
_gpio_base3_value(const gpio_t gpio[],int num_gpio,int binary_first)63 uint32_t _gpio_base3_value(const gpio_t gpio[], int num_gpio, int binary_first)
64 {
65 	/*
66 	 * GPIOs which are tied to stronger external pull up or pull down
67 	 * will stay there regardless of the internal pull up or pull
68 	 * down setting.
69 	 *
70 	 * GPIOs which are floating will go to whatever level they're
71 	 * internally pulled to.
72 	 */
73 
74 	static const char tristate_char[] = {[0] = '0', [1] = '1', [Z] = 'Z'};
75 	uint32_t result = 0;
76 	int has_z = 0;
77 	int binary_below = 0;
78 	int index;
79 	int temp;
80 	char value[32];
81 
82 	_check_num(__func__, num_gpio);
83 
84 	/* Enable internal pull up */
85 	for (index = 0; index < num_gpio; ++index)
86 		gpio_input_pullup(gpio[index]);
87 
88 	/* Wait until signals become stable */
89 	udelay(10);
90 
91 	/* Get gpio values at internal pull up */
92 	for (index = 0; index < num_gpio; ++index)
93 		value[index] = gpio_get(gpio[index]);
94 
95 	/* Enable internal pull down */
96 	for (index = 0; index < num_gpio; ++index)
97 		gpio_input_pulldown(gpio[index]);
98 
99 	/* Wait until signals become stable */
100 	udelay(10);
101 
102 	/*
103 	 * Get gpio values at internal pull down.
104 	 * Compare with gpio pull up value and then
105 	 * determine a gpio final value/state:
106 	 *  0: pull down
107 	 *  1: pull up
108 	 *  2: floating
109 	 */
110 	printk(BIOS_DEBUG, "Reading tristate GPIOs: ");
111 	for (index = num_gpio - 1; index >= 0; --index) {
112 		temp = gpio_get(gpio[index]);
113 		temp |= ((value[index] ^ temp) << 1);
114 		printk(BIOS_DEBUG, "%c ", tristate_char[temp]);
115 		result = (result * 3) + temp;
116 
117 		/* Disable pull to avoid wasting power. For HiZ we leave the
118 		   pull-down enabled, since letting them float freely back and
119 		   forth may waste power in the SoC's GPIO input logic. */
120 		if (temp != Z)
121 			gpio_input(gpio[index]);
122 
123 		/*
124 		 * For binary_first we keep track of the normal ternary result
125 		 * and whether we found any pin that was a Z. We also determine
126 		 * the amount of numbers that can be represented with only
127 		 * binary digits (no Z) whose value in the normal ternary system
128 		 * is lower than the one we are parsing. Counting from the left,
129 		 * we add 2^i for any '1' digit to account for the binary
130 		 * numbers whose values would be below it if all following
131 		 * digits we parsed would be '0'. As soon as we find a '2' digit
132 		 * we can total the remaining binary numbers below as 2^(i+1)
133 		 * because we know that all binary representations counting only
134 		 * this and following digits must have values below our number
135 		 * (since 1xxx is always smaller than 2xxx).
136 		 *
137 		 * Example: 1 0 2 1 (counting from the left / most significant)
138 		 * '1' at 3^3: Add 2^3 = 8 to account for binaries 0000-0111
139 		 * '0' at 3^2: Ignore (not all binaries 1000-1100 are below us)
140 		 * '2' at 3^1: Add 2^(1+1) = 4 to account for binaries 1000-1011
141 		 * Stop adding for lower digits (3^0), all already accounted
142 		 * now. We know that there can be no binary numbers 1020-102X.
143 		 */
144 		if (binary_first && !has_z) {
145 			switch (temp) {
146 			case 0:	/* Ignore '0' digits. */
147 				break;
148 			case 1:	/* Account for binaries 0 to 2^index - 1. */
149 				binary_below += 1 << index;
150 				break;
151 			case 2:	/* Account for binaries 0 to 2^(index+1) - 1. */
152 				binary_below += 1 << (index + 1);
153 				has_z = 1;
154 			}
155 		}
156 	}
157 
158 	if (binary_first) {
159 		if (has_z)
160 			result = result + (1 << num_gpio) - binary_below;
161 		else /* binary_below is normal binary system value if !has_z. */
162 			result = binary_below;
163 	}
164 
165 	printk(BIOS_DEBUG, "= %d (%s base3 number system)\n", result,
166 	       binary_first ? "binary_first" : "standard");
167 
168 	return result;
169 }
170 
171 /* Default handler for ACPI path is to return NULL */
gpio_acpi_path(gpio_t gpio)172 __weak const char *gpio_acpi_path(gpio_t gpio)
173 {
174 	return NULL;
175 }
176 
177 /* Default handler returns 0 because type of gpio_t is unknown */
gpio_acpi_pin(gpio_t gpio)178 __weak uint16_t gpio_acpi_pin(gpio_t gpio)
179 {
180 	return 0;
181 }
182