xref: /aosp_15_r20/external/coreboot/src/drivers/pc80/pc/keyboard.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
4 #include <pc80/keyboard.h>
5 #include <device/device.h>
6 #include <arch/io.h>
7 #include <delay.h>
8 #include <types.h>
9 #include <acpi/acpi.h>
10 
11 #define KBD_DATA	0x60
12 #define KBD_COMMAND	0x64
13 #define KBD_STATUS	0x64
14 #define KBD_IBF	(1 << 1)	// 1: input buffer full (data ready for ec)
15 #define KBD_OBF	(1 << 0)	// 1: output buffer full (data ready for host)
16 
17 // Keyboard Controller Commands
18 #define KBC_CMD_READ_COMMAND	0x20	// Read command byte
19 #define KBC_CMD_WRITE_COMMAND	0x60	// Write command byte
20 #define KBC_CMD_AUX_ENABLE	0xA8	// Auxiliary Interface enable
21 #define KBC_CMD_AUX_TEST	0xA9	// Auxiliary Interface test
22 #define KBC_CMD_SELF_TEST	0xAA	// Controller self-test
23 #define KBC_CMD_KBD_TEST	0xAB	// Keyboard Interface test
24 
25 /* The Keyboard controller command byte
26  *  BIT	| Description
27  *  ----+-------------------------------------------------------
28  *   7  | reserved, must be zero
29  *   6  | XT Translation, (1 = on, 0 = off)
30  *   5  | Disable Mouse Port (1 = disable, 0 = enable)
31  *   4  | Disable Keyboard Port (1 = disable, 0 = enable)
32  *   3  | reserved, must be zero
33  *   2  | System Flag (1 = self-test passed. DO NOT SET TO ZERO)
34  *   1  | Mouse Port Interrupts (1 = enable, 0 = disable)
35  *   0  | Keyboard Port Interrupts (1 = enable, 0 = disable)
36  */
37 
38 // Keyboard Controller Replies
39 #define KBC_REPLY_SELFTEST_OK	0x55	// controller self-test succeeded
40 
41 //
42 // Keyboard Replies
43 //
44 #define KBD_REPLY_POR		0xAA	// Power on reset
45 #define KBD_REPLY_ACK		0xFA	// Command ACK
46 #define KBD_REPLY_RESEND	0xFE	// Command NACK, send command again
47 
48 /* Wait 400ms for keyboard controller answers */
49 #define KBC_TIMEOUT_IN_MS 400
50 
kbc_input_buffer_empty(void)51 static int kbc_input_buffer_empty(void)
52 {
53 	u32 timeout;
54 
55 	for (timeout = KBC_TIMEOUT_IN_MS;
56 	     timeout && (inb(KBD_STATUS) & KBD_IBF); timeout--)
57 		mdelay(1);
58 
59 	if (!timeout)
60 		printk(BIOS_WARNING,
61 		       "Unexpected Keyboard controller input buffer full\n");
62 	return !!timeout;
63 }
64 
kbc_output_buffer_full(void)65 static int kbc_output_buffer_full(void)
66 {
67 	u32 timeout;
68 
69 	for (timeout = KBC_TIMEOUT_IN_MS;
70 	     timeout && ((inb(KBD_STATUS) & KBD_OBF) == 0); timeout--)
71 		mdelay(1);
72 
73 	if (!timeout)
74 		printk(BIOS_INFO,
75 		       "Keyboard controller output buffer result timeout\n");
76 	return !!timeout;
77 }
78 
kbc_cleanup_buffers(void)79 static int kbc_cleanup_buffers(void)
80 {
81 	u32 timeout;
82 
83 	for (timeout = KBC_TIMEOUT_IN_MS;
84 	     timeout && (inb(KBD_STATUS) & (KBD_OBF | KBD_IBF)); timeout--) {
85 		mdelay(1);
86 		inb(KBD_DATA);
87 	}
88 
89 	if (!timeout) {
90 		printk(BIOS_ERR,
91 		       "Couldn't cleanup the keyboard controller buffers\n");
92 		printk(BIOS_ERR, "Status (0x%x): 0x%x, Buffer (0x%x): 0x%x\n",
93 		       KBD_STATUS, inb(KBD_STATUS), KBD_DATA, inb(KBD_DATA));
94 	}
95 
96 	return !!timeout;
97 }
98 
kbc_self_test(uint8_t probe_aux,uint8_t * aux_probe_result)99 static enum cb_err kbc_self_test(uint8_t probe_aux, uint8_t *aux_probe_result)
100 {
101 	uint8_t self_test;
102 	uint8_t byte;
103 
104 	/* Set initial aux probe output value */
105 	if (aux_probe_result)
106 		*aux_probe_result = 0;
107 
108 	/* Clean up any junk that might have been in the KBC.
109 	 * Both input and output buffers must be empty.
110 	 */
111 	if (!kbc_cleanup_buffers())
112 		return CB_KBD_CONTROLLER_FAILURE;
113 
114 	/* reset/self test 8042 - send cmd 0xAA */
115 	outb(KBC_CMD_SELF_TEST, KBD_COMMAND);
116 
117 	if (!kbc_output_buffer_full()) {
118 		/* There probably is no keyboard controller. */
119 		printk(BIOS_ERR, "Could not reset keyboard controller.\n");
120 		return CB_KBD_CONTROLLER_FAILURE;
121 	}
122 
123 	/* read self-test result, 0x55 is returned in the output buffer */
124 	self_test = inb(KBD_DATA);
125 
126 	if (self_test != 0x55) {
127 		printk(BIOS_ERR, "Keyboard Controller self-test failed: 0x%x\n",
128 		       self_test);
129 		return CB_KBD_CONTROLLER_FAILURE;
130 	}
131 
132 	/* ensure the buffers are empty */
133 	kbc_cleanup_buffers();
134 
135 	/* keyboard interface test */
136 	outb(KBC_CMD_KBD_TEST, KBD_COMMAND);
137 
138 	if (!kbc_output_buffer_full()) {
139 		printk(BIOS_ERR, "Keyboard Interface test timed out.\n");
140 		return CB_KBD_CONTROLLER_FAILURE;
141 	}
142 
143 	/* read test result, 0x00 should be returned in case of no failures */
144 	self_test = inb(KBD_DATA);
145 
146 	if (self_test != 0x00) {
147 		printk(BIOS_ERR, "Keyboard Interface test failed: 0x%x\n",
148 		       self_test);
149 		return CB_KBD_INTERFACE_FAILURE;
150 	}
151 
152 	if (probe_aux) {
153 		/* aux interface detect */
154 		outb(KBC_CMD_AUX_ENABLE, KBD_COMMAND);
155 		if (!kbc_input_buffer_empty()) {
156 			printk(BIOS_ERR, "Timeout waiting for controller during aux enable.\n");
157 			return CB_KBD_CONTROLLER_FAILURE;
158 		}
159 		outb(KBC_CMD_READ_COMMAND, KBD_COMMAND);
160 		if (!kbc_output_buffer_full()) {
161 			printk(BIOS_ERR, "Timeout waiting for controller during aux probe.\n");
162 			return CB_KBD_CONTROLLER_FAILURE;
163 		}
164 
165 		byte = inb(KBD_DATA);
166 		if (!(byte & (0x1 << 5))) {
167 			printk(BIOS_DEBUG, "PS/2 auxiliary channel detected...\n");
168 
169 			/* auxiliary interface test */
170 			outb(KBC_CMD_AUX_TEST, KBD_COMMAND);
171 
172 			if (!kbc_output_buffer_full()) {
173 				printk(BIOS_ERR, "Auxiliary channel probe timed out.\n");
174 				goto aux_failure;
175 			}
176 
177 			/* read test result, 0x00 should be returned in case of no failures */
178 			self_test = inb(KBD_DATA);
179 
180 			if (self_test != 0x00) {
181 				printk(BIOS_ERR, "No device detected on auxiliary channel: 0x%x\n",
182 				self_test);
183 				goto aux_failure;
184 			}
185 
186 			printk(BIOS_DEBUG, "PS/2 device detected on auxiliary channel\n");
187 			if (aux_probe_result)
188 				*aux_probe_result = 1;
189 		}
190 	}
191 
192 aux_failure:
193 
194 	return CB_SUCCESS;
195 }
196 
send_keyboard(u8 command)197 static u8 send_keyboard(u8 command)
198 {
199 	u8 regval = 0;
200 	u8 resend = 10;
201 
202 	do {
203 		if (!kbc_input_buffer_empty())
204 			return 0;
205 		outb(command, KBD_DATA);
206 		/* the reset command takes much longer then normal commands and
207 		 * even worse, some keyboards do send the ACK _after_ doing the
208 		 * reset */
209 		if (command == 0xFF) {
210 			u8 retries;
211 
212 			for (retries = 9; retries && !kbc_output_buffer_full();
213 			     retries--)
214 				;
215 		}
216 		if (!kbc_output_buffer_full()) {
217 			printk(BIOS_ERR,
218 			       "Could not send keyboard command %02x\n",
219 			       command);
220 			return 0;
221 		}
222 		regval = inb(KBD_DATA);
223 		--resend;
224 	} while (regval == KBD_REPLY_RESEND && resend > 0);
225 
226 	return regval;
227 }
228 
pc_keyboard_init(uint8_t probe_aux)229 uint8_t pc_keyboard_init(uint8_t probe_aux)
230 {
231 	u8 retries;
232 	u8 regval;
233 	enum cb_err err;
234 	uint8_t aux_dev_detected;
235 
236 	if (!CONFIG(DRIVERS_PS2_KEYBOARD))
237 		return 0;
238 
239 	if (acpi_is_wakeup_s3())
240 		return 0;
241 
242 	printk(BIOS_DEBUG, "Keyboard init...\n");
243 
244 	/* Run a keyboard controller self-test */
245 	err = kbc_self_test(probe_aux, &aux_dev_detected);
246 	/* Ignore interface failure as it's non-fatal.  */
247 	if (err != CB_SUCCESS && err != CB_KBD_INTERFACE_FAILURE)
248 		return 0;
249 
250 	/* Enable keyboard interface - No IRQ */
251 	if (!kbc_input_buffer_empty())
252 		return 0;
253 	outb(0x60, KBD_COMMAND);
254 	if (!kbc_input_buffer_empty())
255 		return 0;
256 	outb(0x20, KBD_DATA);	/* send cmd: enable keyboard */
257 	if (!kbc_input_buffer_empty()) {
258 		printk(BIOS_INFO, "Timeout while enabling keyboard\n");
259 		return 0;
260 	}
261 
262 	/* clean up any junk that might have been in the keyboard */
263 	if (!kbc_cleanup_buffers())
264 		return 0;
265 
266 	/* reset keyboard and self test (keyboard side) */
267 	regval = send_keyboard(0xFF);
268 	if (regval == KBD_REPLY_RESEND) {
269 		/* keeps sending RESENDs, probably no keyboard. */
270 		printk(BIOS_INFO, "No PS/2 keyboard detected.\n");
271 		return 0;
272 	}
273 
274 	if (regval != KBD_REPLY_ACK) {
275 		printk(BIOS_ERR, "Keyboard reset failed ACK: 0x%x\n", regval);
276 		return 0;
277 	}
278 
279 	/* the reset command takes some time, so wait a little longer */
280 	for (retries = 9; retries && !kbc_output_buffer_full(); retries--)
281 		;
282 
283 	if (!kbc_output_buffer_full()) {
284 		printk(BIOS_ERR, "Timeout waiting for keyboard after reset.\n");
285 		return 0;
286 	}
287 
288 	regval = inb(KBD_DATA);
289 	if (regval != 0xAA) {
290 		printk(BIOS_ERR, "Keyboard reset selftest failed: 0x%x\n",
291 		       regval);
292 		return 0;
293 	}
294 
295 	/*
296 	 * The following set scancode stuff is what normal BIOS do. It could be
297 	 * argued that coreboot shouldn't set the scan code.....
298 	 */
299 
300 	/* disable the keyboard */
301 	regval = send_keyboard(0xF5);
302 	if (regval != KBD_REPLY_ACK) {
303 		printk(BIOS_ERR, "Keyboard disable failed ACK: 0x%x\n", regval);
304 		return 0;
305 	}
306 
307 	/* Set scancode command */
308 	regval = send_keyboard(0xF0);
309 	if (regval != KBD_REPLY_ACK) {
310 		printk(BIOS_ERR, "Keyboard set scancode cmd failed ACK: 0x%x\n",
311 		       regval);
312 		return 0;
313 	}
314 	/* Set scancode mode 2 */
315 	regval = send_keyboard(0x02);
316 	if (regval != KBD_REPLY_ACK) {
317 		printk(BIOS_ERR,
318 		       "Keyboard set scancode mode failed ACK: 0x%x\n", regval);
319 		return 0;
320 	}
321 
322 	/* All is well - enable keyboard interface */
323 	if (!kbc_input_buffer_empty())
324 		return 0;
325 	outb(0x60, KBD_COMMAND);
326 	if (!kbc_input_buffer_empty())
327 		return 0;
328 	outb(0x65, KBD_DATA);	/* send cmd: enable keyboard and IRQ 1 */
329 	if (!kbc_input_buffer_empty()) {
330 		printk(BIOS_ERR, "Timeout during keyboard enable\n");
331 		return 0;
332 	}
333 
334 	/* enable the keyboard */
335 	regval = send_keyboard(0xF4);
336 	if (regval != KBD_REPLY_ACK) {
337 		printk(BIOS_ERR, "Keyboard enable failed ACK: 0x%x\n", regval);
338 		return 0;
339 	}
340 
341 	printk(BIOS_DEBUG, "PS/2 keyboard initialized on primary channel\n");
342 
343 	return aux_dev_detected;
344 }
345 
346 /*
347  * Support PS/2 mode -  oddball SIOs(KBC) need this setup
348  * Not well documented. Google - 0xcb keyboard controller
349  * This is called before pc_keyboard_init().
350  */
set_kbc_ps2_mode(void)351 void set_kbc_ps2_mode(void)
352 {
353 	enum cb_err err;
354 
355 	/* Run a keyboard controller self-test */
356 	err = kbc_self_test(0, NULL);
357 	/* Ignore interface failure as it's non-fatal.  */
358 	if (err != CB_SUCCESS && err != CB_KBD_INTERFACE_FAILURE)
359 		return;
360 
361 	/* Support PS/2 mode */
362 	if (!kbc_input_buffer_empty())
363 		return;
364 	outb(0xcb, KBD_COMMAND);
365 
366 	if (!kbc_input_buffer_empty())
367 		return;
368 	outb(0x01, KBD_DATA);
369 
370 	kbc_cleanup_buffers();
371 }
372