116b195c8SJean-Christophe PLAGNIOL-VILLARD /* 216b195c8SJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2002 ELTEC Elektronik AG 316b195c8SJean-Christophe PLAGNIOL-VILLARD * Frank Gottschling <fgottschling@eltec.de> 416b195c8SJean-Christophe PLAGNIOL-VILLARD * 51a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 616b195c8SJean-Christophe PLAGNIOL-VILLARD */ 716b195c8SJean-Christophe PLAGNIOL-VILLARD 816b195c8SJean-Christophe PLAGNIOL-VILLARD /* i8042.c - Intel 8042 keyboard driver routines */ 916b195c8SJean-Christophe PLAGNIOL-VILLARD 1016b195c8SJean-Christophe PLAGNIOL-VILLARD /* includes */ 1116b195c8SJean-Christophe PLAGNIOL-VILLARD 1216b195c8SJean-Christophe PLAGNIOL-VILLARD #include <common.h> 13835dd000SBin Meng #include <asm/io.h> 1416b195c8SJean-Christophe PLAGNIOL-VILLARD #include <i8042.h> 1516b195c8SJean-Christophe PLAGNIOL-VILLARD 1616b195c8SJean-Christophe PLAGNIOL-VILLARD /* defines */ 17835dd000SBin Meng #define in8(p) inb(p) 18835dd000SBin Meng #define out8(p, v) outb(v, p) 1916b195c8SJean-Christophe PLAGNIOL-VILLARD 2016b195c8SJean-Christophe PLAGNIOL-VILLARD /* locals */ 2116b195c8SJean-Christophe PLAGNIOL-VILLARD 2216b195c8SJean-Christophe PLAGNIOL-VILLARD static int kbd_input = -1; /* no input yet */ 2316b195c8SJean-Christophe PLAGNIOL-VILLARD static int kbd_mapping = KBD_US; /* default US keyboard */ 2416b195c8SJean-Christophe PLAGNIOL-VILLARD static int kbd_flags = NORMAL; /* after reset */ 25dd4a5b22SGabe Black static int kbd_state; /* unshift code */ 2616b195c8SJean-Christophe PLAGNIOL-VILLARD 27dd4a5b22SGabe Black static unsigned char kbd_fct_map[144] = { 28dd4a5b22SGabe Black /* kbd_fct_map table for scan code */ 29835dd000SBin Meng 0, AS, AS, AS, AS, AS, AS, AS, /* scan 00-07 */ 30835dd000SBin Meng AS, AS, AS, AS, AS, AS, AS, AS, /* scan 08-0F */ 3116b195c8SJean-Christophe PLAGNIOL-VILLARD AS, AS, AS, AS, AS, AS, AS, AS, /* scan 10-17 */ 3216b195c8SJean-Christophe PLAGNIOL-VILLARD AS, AS, AS, AS, AS, CN, AS, AS, /* scan 18-1F */ 3316b195c8SJean-Christophe PLAGNIOL-VILLARD AS, AS, AS, AS, AS, AS, AS, AS, /* scan 20-27 */ 3416b195c8SJean-Christophe PLAGNIOL-VILLARD AS, AS, SH, AS, AS, AS, AS, AS, /* scan 28-2F */ 3516b195c8SJean-Christophe PLAGNIOL-VILLARD AS, AS, AS, AS, AS, AS, SH, AS, /* scan 30-37 */ 3616b195c8SJean-Christophe PLAGNIOL-VILLARD AS, AS, CP, 0, 0, 0, 0, 0, /* scan 38-3F */ 3716b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, NM, ST, ES, /* scan 40-47 */ 3816b195c8SJean-Christophe PLAGNIOL-VILLARD ES, ES, ES, ES, ES, ES, ES, ES, /* scan 48-4F */ 3916b195c8SJean-Christophe PLAGNIOL-VILLARD ES, ES, ES, ES, 0, 0, AS, 0, /* scan 50-57 */ 4016b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */ 4116b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */ 4216b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */ 4316b195c8SJean-Christophe PLAGNIOL-VILLARD AS, 0, 0, AS, 0, 0, AS, 0, /* scan 70-77 */ 4416b195c8SJean-Christophe PLAGNIOL-VILLARD 0, AS, 0, 0, 0, AS, 0, 0, /* scan 78-7F */ 4516b195c8SJean-Christophe PLAGNIOL-VILLARD AS, CN, AS, AS, AK, ST, EX, EX, /* enhanced */ 4616b195c8SJean-Christophe PLAGNIOL-VILLARD AS, EX, EX, AS, EX, AS, EX, EX /* enhanced */ 4716b195c8SJean-Christophe PLAGNIOL-VILLARD }; 4816b195c8SJean-Christophe PLAGNIOL-VILLARD 49dd4a5b22SGabe Black static unsigned char kbd_key_map[2][5][144] = { 5016b195c8SJean-Christophe PLAGNIOL-VILLARD { /* US keyboard */ 5116b195c8SJean-Christophe PLAGNIOL-VILLARD { /* unshift code */ 52835dd000SBin Meng 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 00-07 */ 53835dd000SBin Meng '7', '8', '9', '0', '-', '=', 0x08, '\t', /* scan 08-0F */ 5416b195c8SJean-Christophe PLAGNIOL-VILLARD 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* scan 10-17 */ 5516b195c8SJean-Christophe PLAGNIOL-VILLARD 'o', 'p', '[', ']', '\r', CN, 'a', 's', /* scan 18-1F */ 5616b195c8SJean-Christophe PLAGNIOL-VILLARD 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* scan 20-27 */ 5716b195c8SJean-Christophe PLAGNIOL-VILLARD '\'', '`', SH, '\\', 'z', 'x', 'c', 'v', /* scan 28-2F */ 5816b195c8SJean-Christophe PLAGNIOL-VILLARD 'b', 'n', 'm', ',', '.', '/', SH, '*', /* scan 30-37 */ 5916b195c8SJean-Christophe PLAGNIOL-VILLARD ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */ 6016b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */ 6116b195c8SJean-Christophe PLAGNIOL-VILLARD '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */ 6216b195c8SJean-Christophe PLAGNIOL-VILLARD '2', '3', '0', '.', 0, 0, 0, 0, /* scan 50-57 */ 6316b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */ 6416b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */ 6516b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */ 6616b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */ 6716b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */ 6816b195c8SJean-Christophe PLAGNIOL-VILLARD '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */ 6916b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ 7016b195c8SJean-Christophe PLAGNIOL-VILLARD }, 7116b195c8SJean-Christophe PLAGNIOL-VILLARD { /* shift code */ 72835dd000SBin Meng 0, 0x1b, '!', '@', '#', '$', '%', '^', /* scan 00-07 */ 73835dd000SBin Meng '&', '*', '(', ')', '_', '+', 0x08, '\t', /* scan 08-0F */ 7416b195c8SJean-Christophe PLAGNIOL-VILLARD 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* scan 10-17 */ 7516b195c8SJean-Christophe PLAGNIOL-VILLARD 'O', 'P', '{', '}', '\r', CN, 'A', 'S', /* scan 18-1F */ 7616b195c8SJean-Christophe PLAGNIOL-VILLARD 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* scan 20-27 */ 7716b195c8SJean-Christophe PLAGNIOL-VILLARD '"', '~', SH, '|', 'Z', 'X', 'C', 'V', /* scan 28-2F */ 7816b195c8SJean-Christophe PLAGNIOL-VILLARD 'B', 'N', 'M', '<', '>', '?', SH, '*', /* scan 30-37 */ 7916b195c8SJean-Christophe PLAGNIOL-VILLARD ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */ 8016b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */ 8116b195c8SJean-Christophe PLAGNIOL-VILLARD '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */ 8216b195c8SJean-Christophe PLAGNIOL-VILLARD '2', '3', '0', '.', 0, 0, 0, 0, /* scan 50-57 */ 8316b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */ 8416b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */ 8516b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */ 8616b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */ 8716b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */ 8816b195c8SJean-Christophe PLAGNIOL-VILLARD '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */ 8916b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ 9016b195c8SJean-Christophe PLAGNIOL-VILLARD }, 9116b195c8SJean-Christophe PLAGNIOL-VILLARD { /* control code */ 92835dd000SBin Meng 0xff, 0x1b, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, /* scan 00-07 */ 93835dd000SBin Meng 0x1e, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, '\t', /* scan 08-0F */ 9416b195c8SJean-Christophe PLAGNIOL-VILLARD 0x11, 0x17, 0x05, 0x12, 0x14, 0x19, 0x15, 0x09, /* scan 10-17 */ 9516b195c8SJean-Christophe PLAGNIOL-VILLARD 0x0f, 0x10, 0x1b, 0x1d, '\r', CN, 0x01, 0x13, /* scan 18-1F */ 9616b195c8SJean-Christophe PLAGNIOL-VILLARD 0x04, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0c, 0xff, /* scan 20-27 */ 9716b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0x1c, SH, 0xff, 0x1a, 0x18, 0x03, 0x16, /* scan 28-2F */ 9816b195c8SJean-Christophe PLAGNIOL-VILLARD 0x02, 0x0e, 0x0d, 0xff, 0xff, 0xff, SH, 0xff, /* scan 30-37 */ 9916b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, CP, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38-3F */ 10016b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, NM, ST, 0xff, /* scan 40-47 */ 10116b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48-4F */ 10216b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 50-57 */ 10316b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58-5F */ 10416b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60-67 */ 10516b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68-6F */ 10616b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70-77 */ 10716b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78-7F */ 10816b195c8SJean-Christophe PLAGNIOL-VILLARD '\r', CN, '/', '*', ' ', ST, 0xff, 0xff, /* extended */ 10916b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */ 11016b195c8SJean-Christophe PLAGNIOL-VILLARD }, 11116b195c8SJean-Christophe PLAGNIOL-VILLARD { /* non numeric code */ 112835dd000SBin Meng 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 00-07 */ 113835dd000SBin Meng '7', '8', '9', '0', '-', '=', 0x08, '\t', /* scan 08-0F */ 11416b195c8SJean-Christophe PLAGNIOL-VILLARD 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* scan 10-17 */ 11516b195c8SJean-Christophe PLAGNIOL-VILLARD 'o', 'p', '[', ']', '\r', CN, 'a', 's', /* scan 18-1F */ 11616b195c8SJean-Christophe PLAGNIOL-VILLARD 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* scan 20-27 */ 11716b195c8SJean-Christophe PLAGNIOL-VILLARD '\'', '`', SH, '\\', 'z', 'x', 'c', 'v', /* scan 28-2F */ 11816b195c8SJean-Christophe PLAGNIOL-VILLARD 'b', 'n', 'm', ',', '.', '/', SH, '*', /* scan 30-37 */ 11916b195c8SJean-Christophe PLAGNIOL-VILLARD ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */ 12016b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, NM, ST, 'w', /* scan 40-47 */ 12116b195c8SJean-Christophe PLAGNIOL-VILLARD 'x', 'y', 'l', 't', 'u', 'v', 'm', 'q', /* scan 48-4F */ 12216b195c8SJean-Christophe PLAGNIOL-VILLARD 'r', 's', 'p', 'n', 0, 0, 0, 0, /* scan 50-57 */ 12316b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */ 12416b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */ 12516b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */ 12616b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */ 12716b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */ 12816b195c8SJean-Christophe PLAGNIOL-VILLARD '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */ 12916b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ 13016b195c8SJean-Christophe PLAGNIOL-VILLARD }, 13116b195c8SJean-Christophe PLAGNIOL-VILLARD { /* right alt mode - not used in US keyboard */ 132835dd000SBin Meng 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 00-07 */ 133835dd000SBin Meng 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 08-0F */ 13416b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 10-17 */ 13516b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 18-1F */ 13616b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 20-27 */ 13716b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 28-2F */ 13816b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 30-37 */ 13916b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38-3F */ 14016b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 40-47 */ 14116b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48-4F */ 14216b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 50-57 */ 14316b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58-5F */ 14416b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60-67 */ 14516b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68-6F */ 14616b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70-77 */ 14716b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78-7F */ 14816b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* extended */ 14916b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */ 15016b195c8SJean-Christophe PLAGNIOL-VILLARD } 15116b195c8SJean-Christophe PLAGNIOL-VILLARD }, 152835dd000SBin Meng { /* German keyboard */ 15316b195c8SJean-Christophe PLAGNIOL-VILLARD { /* unshift code */ 154835dd000SBin Meng 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 00-07 */ 155835dd000SBin Meng '7', '8', '9', '0', 0xe1, '\'', 0x08, '\t', /* scan 08-0F */ 15616b195c8SJean-Christophe PLAGNIOL-VILLARD 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', /* scan 10-17 */ 15716b195c8SJean-Christophe PLAGNIOL-VILLARD 'o', 'p', 0x81, '+', '\r', CN, 'a', 's', /* scan 18-1F */ 15816b195c8SJean-Christophe PLAGNIOL-VILLARD 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0x94, /* scan 20-27 */ 15916b195c8SJean-Christophe PLAGNIOL-VILLARD 0x84, '^', SH, '#', 'y', 'x', 'c', 'v', /* scan 28-2F */ 16016b195c8SJean-Christophe PLAGNIOL-VILLARD 'b', 'n', 'm', ',', '.', '-', SH, '*', /* scan 30-37 */ 16116b195c8SJean-Christophe PLAGNIOL-VILLARD ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */ 16216b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */ 16316b195c8SJean-Christophe PLAGNIOL-VILLARD '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */ 16416b195c8SJean-Christophe PLAGNIOL-VILLARD '2', '3', '0', ',', 0, 0, '<', 0, /* scan 50-57 */ 16516b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */ 16616b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */ 16716b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */ 16816b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */ 16916b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */ 17016b195c8SJean-Christophe PLAGNIOL-VILLARD '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */ 17116b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ 17216b195c8SJean-Christophe PLAGNIOL-VILLARD }, 17316b195c8SJean-Christophe PLAGNIOL-VILLARD { /* shift code */ 174835dd000SBin Meng 0, 0x1b, '!', '"', 0x15, '$', '%', '&', /* scan 00-07 */ 175835dd000SBin Meng '/', '(', ')', '=', '?', '`', 0x08, '\t', /* scan 08-0F */ 17616b195c8SJean-Christophe PLAGNIOL-VILLARD 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I', /* scan 10-17 */ 17716b195c8SJean-Christophe PLAGNIOL-VILLARD 'O', 'P', 0x9a, '*', '\r', CN, 'A', 'S', /* scan 18-1F */ 17816b195c8SJean-Christophe PLAGNIOL-VILLARD 'D', 'F', 'G', 'H', 'J', 'K', 'L', 0x99, /* scan 20-27 */ 17916b195c8SJean-Christophe PLAGNIOL-VILLARD 0x8e, 0xf8, SH, '\'', 'Y', 'X', 'C', 'V', /* scan 28-2F */ 18016b195c8SJean-Christophe PLAGNIOL-VILLARD 'B', 'N', 'M', ';', ':', '_', SH, '*', /* scan 30-37 */ 18116b195c8SJean-Christophe PLAGNIOL-VILLARD ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */ 18216b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */ 18316b195c8SJean-Christophe PLAGNIOL-VILLARD '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */ 18416b195c8SJean-Christophe PLAGNIOL-VILLARD '2', '3', '0', ',', 0, 0, '>', 0, /* scan 50-57 */ 18516b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */ 18616b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */ 18716b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */ 18816b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */ 18916b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */ 19016b195c8SJean-Christophe PLAGNIOL-VILLARD '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */ 19116b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ 19216b195c8SJean-Christophe PLAGNIOL-VILLARD }, 19316b195c8SJean-Christophe PLAGNIOL-VILLARD { /* control code */ 194835dd000SBin Meng 0xff, 0x1b, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, /* scan 00-07 */ 195835dd000SBin Meng 0x1e, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, '\t', /* scan 08-0F */ 19616b195c8SJean-Christophe PLAGNIOL-VILLARD 0x11, 0x17, 0x05, 0x12, 0x14, 0x19, 0x15, 0x09, /* scan 10-17 */ 19716b195c8SJean-Christophe PLAGNIOL-VILLARD 0x0f, 0x10, 0x1b, 0x1d, '\r', CN, 0x01, 0x13, /* scan 18-1F */ 19816b195c8SJean-Christophe PLAGNIOL-VILLARD 0x04, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0c, 0xff, /* scan 20-27 */ 19916b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0x1c, SH, 0xff, 0x1a, 0x18, 0x03, 0x16, /* scan 28-2F */ 20016b195c8SJean-Christophe PLAGNIOL-VILLARD 0x02, 0x0e, 0x0d, 0xff, 0xff, 0xff, SH, 0xff, /* scan 30-37 */ 20116b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, CP, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38-3F */ 20216b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, NM, ST, 0xff, /* scan 40-47 */ 20316b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48-4F */ 20416b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 50-57 */ 20516b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58-5F */ 20616b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60-67 */ 20716b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68-6F */ 20816b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70-77 */ 20916b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78-7F */ 21016b195c8SJean-Christophe PLAGNIOL-VILLARD '\r', CN, '/', '*', ' ', ST, 0xff, 0xff, /* extended */ 21116b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */ 21216b195c8SJean-Christophe PLAGNIOL-VILLARD }, 21316b195c8SJean-Christophe PLAGNIOL-VILLARD { /* non numeric code */ 214835dd000SBin Meng 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 00-07 */ 215835dd000SBin Meng '7', '8', '9', '0', 0xe1, '\'', 0x08, '\t', /* scan 08-0F */ 21616b195c8SJean-Christophe PLAGNIOL-VILLARD 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', /* scan 10-17 */ 21716b195c8SJean-Christophe PLAGNIOL-VILLARD 'o', 'p', 0x81, '+', '\r', CN, 'a', 's', /* scan 18-1F */ 21816b195c8SJean-Christophe PLAGNIOL-VILLARD 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0x94, /* scan 20-27 */ 21916b195c8SJean-Christophe PLAGNIOL-VILLARD 0x84, '^', SH, 0, 'y', 'x', 'c', 'v', /* scan 28-2F */ 22016b195c8SJean-Christophe PLAGNIOL-VILLARD 'b', 'n', 'm', ',', '.', '-', SH, '*', /* scan 30-37 */ 22116b195c8SJean-Christophe PLAGNIOL-VILLARD ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */ 22216b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, NM, ST, 'w', /* scan 40-47 */ 22316b195c8SJean-Christophe PLAGNIOL-VILLARD 'x', 'y', 'l', 't', 'u', 'v', 'm', 'q', /* scan 48-4F */ 22416b195c8SJean-Christophe PLAGNIOL-VILLARD 'r', 's', 'p', 'n', 0, 0, '<', 0, /* scan 50-57 */ 22516b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */ 22616b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */ 22716b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */ 22816b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */ 22916b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */ 23016b195c8SJean-Christophe PLAGNIOL-VILLARD '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */ 23116b195c8SJean-Christophe PLAGNIOL-VILLARD 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ 23216b195c8SJean-Christophe PLAGNIOL-VILLARD }, 233835dd000SBin Meng { /* right alt mode - is used in German keyboard */ 234835dd000SBin Meng 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 00-07 */ 235835dd000SBin Meng '{', '[', ']', '}', '\\', 0xff, 0xff, 0xff, /* scan 08-0F */ 23616b195c8SJean-Christophe PLAGNIOL-VILLARD '@', 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 10-17 */ 23716b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, '~', 0xff, 0xff, 0xff, 0xff, /* scan 18-1F */ 23816b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 20-27 */ 23916b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 28-2F */ 24016b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 30-37 */ 24116b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38-3F */ 24216b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 40-47 */ 24316b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48-4F */ 24416b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, '|', 0xff, /* scan 50-57 */ 24516b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58-5F */ 24616b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60-67 */ 24716b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68-6F */ 24816b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70-77 */ 24916b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78-7F */ 25016b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* extended */ 25116b195c8SJean-Christophe PLAGNIOL-VILLARD 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */ 25216b195c8SJean-Christophe PLAGNIOL-VILLARD } 25316b195c8SJean-Christophe PLAGNIOL-VILLARD } 25416b195c8SJean-Christophe PLAGNIOL-VILLARD }; 25516b195c8SJean-Christophe PLAGNIOL-VILLARD 256dd4a5b22SGabe Black static unsigned char ext_key_map[] = { 25716b195c8SJean-Christophe PLAGNIOL-VILLARD 0x1c, /* keypad enter */ 25816b195c8SJean-Christophe PLAGNIOL-VILLARD 0x1d, /* right control */ 25916b195c8SJean-Christophe PLAGNIOL-VILLARD 0x35, /* keypad slash */ 26016b195c8SJean-Christophe PLAGNIOL-VILLARD 0x37, /* print screen */ 26116b195c8SJean-Christophe PLAGNIOL-VILLARD 0x38, /* right alt */ 26216b195c8SJean-Christophe PLAGNIOL-VILLARD 0x46, /* break */ 26316b195c8SJean-Christophe PLAGNIOL-VILLARD 0x47, /* editpad home */ 26416b195c8SJean-Christophe PLAGNIOL-VILLARD 0x48, /* editpad up */ 26516b195c8SJean-Christophe PLAGNIOL-VILLARD 0x49, /* editpad pgup */ 26616b195c8SJean-Christophe PLAGNIOL-VILLARD 0x4b, /* editpad left */ 26716b195c8SJean-Christophe PLAGNIOL-VILLARD 0x4d, /* editpad right */ 26816b195c8SJean-Christophe PLAGNIOL-VILLARD 0x4f, /* editpad end */ 26916b195c8SJean-Christophe PLAGNIOL-VILLARD 0x50, /* editpad dn */ 27016b195c8SJean-Christophe PLAGNIOL-VILLARD 0x51, /* editpad pgdn */ 27116b195c8SJean-Christophe PLAGNIOL-VILLARD 0x52, /* editpad ins */ 27216b195c8SJean-Christophe PLAGNIOL-VILLARD 0x53, /* editpad del */ 27316b195c8SJean-Christophe PLAGNIOL-VILLARD 0x00 /* map end */ 27416b195c8SJean-Christophe PLAGNIOL-VILLARD }; 27516b195c8SJean-Christophe PLAGNIOL-VILLARD 2763928d66aSBin Meng static int kbd_input_empty(void) 2773928d66aSBin Meng { 278835dd000SBin Meng int kbd_timeout = KBD_TIMEOUT * 1000; 2793928d66aSBin Meng 280835dd000SBin Meng while ((in8(I8042_STS_REG) & STATUS_IBF) && kbd_timeout--) 2813928d66aSBin Meng udelay(1); 2823928d66aSBin Meng 283835dd000SBin Meng return kbd_timeout != -1; 2843928d66aSBin Meng } 2853928d66aSBin Meng 286835dd000SBin Meng static int kbd_output_full(void) 2873928d66aSBin Meng { 288835dd000SBin Meng int kbd_timeout = KBD_TIMEOUT * 1000; 2893928d66aSBin Meng 290835dd000SBin Meng while (((in8(I8042_STS_REG) & STATUS_OBF) == 0) && kbd_timeout--) 2913928d66aSBin Meng udelay(1); 2923928d66aSBin Meng 293835dd000SBin Meng return kbd_timeout != -1; 2943928d66aSBin Meng } 2953928d66aSBin Meng 2963928d66aSBin Meng static void kbd_led_set(void) 2973928d66aSBin Meng { 2983928d66aSBin Meng kbd_input_empty(); 299835dd000SBin Meng out8(I8042_DATA_REG, CMD_SET_KBD_LED); 3003928d66aSBin Meng kbd_input_empty(); 301835dd000SBin Meng out8(I8042_DATA_REG, (kbd_flags & 0x7)); 3023928d66aSBin Meng } 3033928d66aSBin Meng 3043928d66aSBin Meng static void kbd_normal(unsigned char scan_code) 3053928d66aSBin Meng { 3063928d66aSBin Meng unsigned char chr; 3073928d66aSBin Meng 3083928d66aSBin Meng if ((kbd_flags & BRK) == NORMAL) { 3093928d66aSBin Meng chr = kbd_key_map[kbd_mapping][kbd_state][scan_code]; 3103928d66aSBin Meng if ((chr == 0xff) || (chr == 0x00)) 3113928d66aSBin Meng return; 3123928d66aSBin Meng 3133928d66aSBin Meng /* if caps lock convert upper to lower */ 3143928d66aSBin Meng if (((kbd_flags & CAPS) == CAPS) && 3153928d66aSBin Meng (chr >= 'a' && chr <= 'z')) { 3163928d66aSBin Meng chr -= 'a' - 'A'; 3173928d66aSBin Meng } 3183928d66aSBin Meng kbd_input = chr; 3193928d66aSBin Meng } 3203928d66aSBin Meng } 3213928d66aSBin Meng 3223928d66aSBin Meng static void kbd_shift(unsigned char scan_code) 3233928d66aSBin Meng { 3243928d66aSBin Meng if ((kbd_flags & BRK) == BRK) { 3253928d66aSBin Meng kbd_state = AS; 3263928d66aSBin Meng kbd_flags &= (~SHIFT); 3273928d66aSBin Meng } else { 3283928d66aSBin Meng kbd_state = SH; 3293928d66aSBin Meng kbd_flags |= SHIFT; 3303928d66aSBin Meng } 3313928d66aSBin Meng } 3323928d66aSBin Meng 3333928d66aSBin Meng static void kbd_ctrl(unsigned char scan_code) 3343928d66aSBin Meng { 3353928d66aSBin Meng if ((kbd_flags & BRK) == BRK) { 3363928d66aSBin Meng kbd_state = AS; 3373928d66aSBin Meng kbd_flags &= (~CTRL); 3383928d66aSBin Meng } else { 3393928d66aSBin Meng kbd_state = CN; 3403928d66aSBin Meng kbd_flags |= CTRL; 3413928d66aSBin Meng } 3423928d66aSBin Meng } 3433928d66aSBin Meng 3443928d66aSBin Meng static void kbd_num(unsigned char scan_code) 3453928d66aSBin Meng { 3463928d66aSBin Meng if ((kbd_flags & BRK) == NORMAL) { 3473928d66aSBin Meng kbd_flags ^= NUM; 3483928d66aSBin Meng kbd_state = (kbd_flags & NUM) ? AS : NM; 349835dd000SBin Meng kbd_led_set(); 3503928d66aSBin Meng } 3513928d66aSBin Meng } 3523928d66aSBin Meng 3533928d66aSBin Meng static void kbd_alt(unsigned char scan_code) 3543928d66aSBin Meng { 3553928d66aSBin Meng if ((kbd_flags & BRK) == BRK) { 3563928d66aSBin Meng kbd_state = AS; 3573928d66aSBin Meng kbd_flags &= (~ALT); 3583928d66aSBin Meng } else { 3593928d66aSBin Meng kbd_state = AK; 3603928d66aSBin Meng kbd_flags &= ALT; 3613928d66aSBin Meng } 3623928d66aSBin Meng } 3633928d66aSBin Meng 3643928d66aSBin Meng static void kbd_caps(unsigned char scan_code) 3653928d66aSBin Meng { 3663928d66aSBin Meng if ((kbd_flags & BRK) == NORMAL) { 3673928d66aSBin Meng kbd_flags ^= CAPS; 368835dd000SBin Meng kbd_led_set(); 3693928d66aSBin Meng } 3703928d66aSBin Meng } 3713928d66aSBin Meng 3723928d66aSBin Meng static void kbd_scroll(unsigned char scan_code) 3733928d66aSBin Meng { 3743928d66aSBin Meng if ((kbd_flags & BRK) == NORMAL) { 3753928d66aSBin Meng kbd_flags ^= STP; 376835dd000SBin Meng kbd_led_set(); 3773928d66aSBin Meng if (kbd_flags & STP) 3783928d66aSBin Meng kbd_input = 0x13; 3793928d66aSBin Meng else 3803928d66aSBin Meng kbd_input = 0x11; 3813928d66aSBin Meng } 3823928d66aSBin Meng } 3833928d66aSBin Meng 3843928d66aSBin Meng static void kbd_conv_char(unsigned char scan_code) 3853928d66aSBin Meng { 3863928d66aSBin Meng if (scan_code == 0xe0) { 3873928d66aSBin Meng kbd_flags |= EXT; 3883928d66aSBin Meng return; 3893928d66aSBin Meng } 3903928d66aSBin Meng 3913928d66aSBin Meng /* if high bit of scan_code, set break flag */ 3923928d66aSBin Meng if (scan_code & 0x80) 3933928d66aSBin Meng kbd_flags |= BRK; 3943928d66aSBin Meng else 3953928d66aSBin Meng kbd_flags &= ~BRK; 3963928d66aSBin Meng 3973928d66aSBin Meng if ((scan_code == 0xe1) || (kbd_flags & E1)) { 3983928d66aSBin Meng if (scan_code == 0xe1) { 3993928d66aSBin Meng kbd_flags ^= BRK; /* reset the break flag */ 4003928d66aSBin Meng kbd_flags ^= E1; /* bitwise EXOR with E1 flag */ 4013928d66aSBin Meng } 4023928d66aSBin Meng return; 4033928d66aSBin Meng } 4043928d66aSBin Meng 4053928d66aSBin Meng scan_code &= 0x7f; 4063928d66aSBin Meng 4073928d66aSBin Meng if (kbd_flags & EXT) { 4083928d66aSBin Meng int i; 4093928d66aSBin Meng 4103928d66aSBin Meng kbd_flags ^= EXT; 4113928d66aSBin Meng for (i = 0; ext_key_map[i]; i++) { 4123928d66aSBin Meng if (ext_key_map[i] == scan_code) { 4133928d66aSBin Meng scan_code = 0x80 + i; 4143928d66aSBin Meng break; 4153928d66aSBin Meng } 4163928d66aSBin Meng } 4173928d66aSBin Meng /* not found ? */ 4183928d66aSBin Meng if (!ext_key_map[i]) 4193928d66aSBin Meng return; 4203928d66aSBin Meng } 4213928d66aSBin Meng 4223928d66aSBin Meng switch (kbd_fct_map[scan_code]) { 4233928d66aSBin Meng case AS: 4243928d66aSBin Meng kbd_normal(scan_code); 4253928d66aSBin Meng break; 4263928d66aSBin Meng case SH: 4273928d66aSBin Meng kbd_shift(scan_code); 4283928d66aSBin Meng break; 4293928d66aSBin Meng case CN: 4303928d66aSBin Meng kbd_ctrl(scan_code); 4313928d66aSBin Meng break; 4323928d66aSBin Meng case NM: 4333928d66aSBin Meng kbd_num(scan_code); 4343928d66aSBin Meng break; 4353928d66aSBin Meng case AK: 4363928d66aSBin Meng kbd_alt(scan_code); 4373928d66aSBin Meng break; 4383928d66aSBin Meng case CP: 4393928d66aSBin Meng kbd_caps(scan_code); 4403928d66aSBin Meng break; 4413928d66aSBin Meng case ST: 4423928d66aSBin Meng kbd_scroll(scan_code); 4433928d66aSBin Meng break; 4443928d66aSBin Meng } 445835dd000SBin Meng 4463928d66aSBin Meng return; 4473928d66aSBin Meng } 4483928d66aSBin Meng 44931d38ee6SSimon Glass static int kbd_write(int reg, int value) 45031d38ee6SSimon Glass { 45131d38ee6SSimon Glass if (!kbd_input_empty()) 45231d38ee6SSimon Glass return -1; 45331d38ee6SSimon Glass out8(reg, value); 45431d38ee6SSimon Glass 45531d38ee6SSimon Glass return 0; 45631d38ee6SSimon Glass } 45731d38ee6SSimon Glass 45831d38ee6SSimon Glass static int kbd_read(int reg) 45931d38ee6SSimon Glass { 46031d38ee6SSimon Glass if (!kbd_output_full()) 46131d38ee6SSimon Glass return -1; 46231d38ee6SSimon Glass 46331d38ee6SSimon Glass return in8(reg); 46431d38ee6SSimon Glass } 46531d38ee6SSimon Glass 46631d38ee6SSimon Glass static int kbd_cmd_read(int cmd) 46731d38ee6SSimon Glass { 46831d38ee6SSimon Glass if (kbd_write(I8042_CMD_REG, cmd)) 46931d38ee6SSimon Glass return -1; 47031d38ee6SSimon Glass 47131d38ee6SSimon Glass return kbd_read(I8042_DATA_REG); 47231d38ee6SSimon Glass } 47331d38ee6SSimon Glass 47431d38ee6SSimon Glass static int kbd_cmd_write(int cmd, int data) 47531d38ee6SSimon Glass { 47631d38ee6SSimon Glass if (kbd_write(I8042_CMD_REG, cmd)) 47731d38ee6SSimon Glass return -1; 47831d38ee6SSimon Glass 47931d38ee6SSimon Glass return kbd_write(I8042_DATA_REG, data); 48031d38ee6SSimon Glass } 48131d38ee6SSimon Glass 4823928d66aSBin Meng static int kbd_reset(void) 4833928d66aSBin Meng { 48431d38ee6SSimon Glass int config; 4857d96166bSBin Meng 4867d96166bSBin Meng /* controller self test */ 48731d38ee6SSimon Glass if (kbd_cmd_read(CMD_SELF_TEST) != KBC_TEST_OK) 4884f087bacSSimon Glass goto err; 4893928d66aSBin Meng 4907d96166bSBin Meng /* keyboard reset */ 49131d38ee6SSimon Glass if (kbd_write(I8042_DATA_REG, CMD_RESET_KBD) || 49231d38ee6SSimon Glass kbd_read(I8042_DATA_REG) != KBD_ACK || 49331d38ee6SSimon Glass kbd_read(I8042_DATA_REG) != KBD_POR) 4944f087bacSSimon Glass goto err; 4953928d66aSBin Meng 4967d96166bSBin Meng /* set AT translation and disable irq */ 49731d38ee6SSimon Glass config = kbd_cmd_read(CMD_RD_CONFIG); 49831d38ee6SSimon Glass if (config == -1) 4994f087bacSSimon Glass goto err; 50031d38ee6SSimon Glass 5017d96166bSBin Meng config |= CONFIG_AT_TRANS; 5027d96166bSBin Meng config &= ~(CONFIG_KIRQ_EN | CONFIG_MIRQ_EN); 50331d38ee6SSimon Glass if (kbd_cmd_write(CMD_WR_CONFIG, config)) 5044f087bacSSimon Glass goto err; 5053928d66aSBin Meng 5067d96166bSBin Meng /* enable keyboard */ 50731d38ee6SSimon Glass if (kbd_write(I8042_CMD_REG, CMD_KBD_EN) || 50831d38ee6SSimon Glass !kbd_input_empty()) 5094f087bacSSimon Glass goto err; 5103928d66aSBin Meng 5113928d66aSBin Meng return 0; 5124f087bacSSimon Glass err: 5134f087bacSSimon Glass debug("%s: Keyboard failure\n", __func__); 5144f087bacSSimon Glass return -1; 5153928d66aSBin Meng } 5163928d66aSBin Meng 51722e0f5a9SGabe Black static int kbd_controller_present(void) 51822e0f5a9SGabe Black { 519835dd000SBin Meng return in8(I8042_STS_REG) != 0xff; 52022e0f5a9SGabe Black } 52122e0f5a9SGabe Black 52248edb304SGabe Black /* 52348edb304SGabe Black * Implement a weak default function for boards that optionally 52448edb304SGabe Black * need to skip the i8042 initialization. 52548edb304SGabe Black */ 52648edb304SGabe Black int __weak board_i8042_skip(void) 52748edb304SGabe Black { 52848edb304SGabe Black /* As default, don't skip */ 52948edb304SGabe Black return 0; 53048edb304SGabe Black } 53148edb304SGabe Black 53245fe668fSLouis Yung-Chieh Lo void i8042_flush(void) 53345fe668fSLouis Yung-Chieh Lo { 53445fe668fSLouis Yung-Chieh Lo int timeout; 53545fe668fSLouis Yung-Chieh Lo 53645fe668fSLouis Yung-Chieh Lo /* 537835dd000SBin Meng * The delay is to give the keyboard controller some time 538835dd000SBin Meng * to fill the next byte. 53945fe668fSLouis Yung-Chieh Lo */ 54045fe668fSLouis Yung-Chieh Lo while (1) { 54145fe668fSLouis Yung-Chieh Lo timeout = 100; /* wait for no longer than 100us */ 542835dd000SBin Meng while (timeout > 0 && !(in8(I8042_STS_REG) & STATUS_OBF)) { 54345fe668fSLouis Yung-Chieh Lo udelay(1); 54445fe668fSLouis Yung-Chieh Lo timeout--; 54545fe668fSLouis Yung-Chieh Lo } 54645fe668fSLouis Yung-Chieh Lo 547835dd000SBin Meng /* Try to pull next byte if not timeout */ 548835dd000SBin Meng if (in8(I8042_STS_REG) & STATUS_OBF) 54945fe668fSLouis Yung-Chieh Lo in8(I8042_DATA_REG); 55045fe668fSLouis Yung-Chieh Lo else 55145fe668fSLouis Yung-Chieh Lo break; 55245fe668fSLouis Yung-Chieh Lo } 55345fe668fSLouis Yung-Chieh Lo } 55445fe668fSLouis Yung-Chieh Lo 55545fe668fSLouis Yung-Chieh Lo int i8042_disable(void) 55645fe668fSLouis Yung-Chieh Lo { 55745fe668fSLouis Yung-Chieh Lo if (kbd_input_empty() == 0) 55845fe668fSLouis Yung-Chieh Lo return -1; 55945fe668fSLouis Yung-Chieh Lo 56045fe668fSLouis Yung-Chieh Lo /* Disable keyboard */ 561835dd000SBin Meng out8(I8042_CMD_REG, CMD_KBD_DIS); 56245fe668fSLouis Yung-Chieh Lo 56345fe668fSLouis Yung-Chieh Lo if (kbd_input_empty() == 0) 56445fe668fSLouis Yung-Chieh Lo return -1; 56545fe668fSLouis Yung-Chieh Lo 56645fe668fSLouis Yung-Chieh Lo return 0; 56745fe668fSLouis Yung-Chieh Lo } 56845fe668fSLouis Yung-Chieh Lo 569835dd000SBin Meng /* i8042_kbd_init - reset keyboard and init state flags */ 57016b195c8SJean-Christophe PLAGNIOL-VILLARD int i8042_kbd_init(void) 57116b195c8SJean-Christophe PLAGNIOL-VILLARD { 57216b195c8SJean-Christophe PLAGNIOL-VILLARD int keymap, try; 57316b195c8SJean-Christophe PLAGNIOL-VILLARD char *penv; 57416b195c8SJean-Christophe PLAGNIOL-VILLARD 575835dd000SBin Meng if (!kbd_controller_present() || board_i8042_skip()) { 576835dd000SBin Meng debug("i8042 keyboard controller is not present\n"); 57722e0f5a9SGabe Black return -1; 578835dd000SBin Meng } 57922e0f5a9SGabe Black 58016b195c8SJean-Christophe PLAGNIOL-VILLARD /* Init keyboard device (default US layout) */ 58116b195c8SJean-Christophe PLAGNIOL-VILLARD keymap = KBD_US; 582dd4a5b22SGabe Black penv = getenv("keymap"); 583dd4a5b22SGabe Black if (penv != NULL) { 58416b195c8SJean-Christophe PLAGNIOL-VILLARD if (strncmp(penv, "de", 3) == 0) 58516b195c8SJean-Christophe PLAGNIOL-VILLARD keymap = KBD_GER; 58616b195c8SJean-Christophe PLAGNIOL-VILLARD } 58716b195c8SJean-Christophe PLAGNIOL-VILLARD 588*c5d257f9SSimon Glass for (try = 0; kbd_reset() != 0; try++) { 589*c5d257f9SSimon Glass if (try >= KBD_RESET_TRIES) 590*c5d257f9SSimon Glass return -1; 591*c5d257f9SSimon Glass } 592*c5d257f9SSimon Glass 59316b195c8SJean-Christophe PLAGNIOL-VILLARD kbd_mapping = keymap; 59416b195c8SJean-Christophe PLAGNIOL-VILLARD kbd_flags = NORMAL; 59516b195c8SJean-Christophe PLAGNIOL-VILLARD kbd_state = 0; 59616b195c8SJean-Christophe PLAGNIOL-VILLARD kbd_led_set(); 597835dd000SBin Meng 59816b195c8SJean-Christophe PLAGNIOL-VILLARD return 0; 59916b195c8SJean-Christophe PLAGNIOL-VILLARD } 60016b195c8SJean-Christophe PLAGNIOL-VILLARD 601835dd000SBin Meng /* 60216b195c8SJean-Christophe PLAGNIOL-VILLARD * i8042_tstc - test if keyboard input is available 603835dd000SBin Meng * 60416b195c8SJean-Christophe PLAGNIOL-VILLARD * option: cursor blinking if called in a loop 60516b195c8SJean-Christophe PLAGNIOL-VILLARD */ 606709ea543SSimon Glass int i8042_tstc(struct stdio_dev *dev) 60716b195c8SJean-Christophe PLAGNIOL-VILLARD { 60816b195c8SJean-Christophe PLAGNIOL-VILLARD unsigned char scan_code = 0; 60916b195c8SJean-Christophe PLAGNIOL-VILLARD 610835dd000SBin Meng if ((in8(I8042_STS_REG) & STATUS_OBF) == 0) { 61116b195c8SJean-Christophe PLAGNIOL-VILLARD return 0; 612dd4a5b22SGabe Black } else { 61316b195c8SJean-Christophe PLAGNIOL-VILLARD scan_code = in8(I8042_DATA_REG); 61416b195c8SJean-Christophe PLAGNIOL-VILLARD if (scan_code == 0xfa) 61516b195c8SJean-Christophe PLAGNIOL-VILLARD return 0; 61616b195c8SJean-Christophe PLAGNIOL-VILLARD 61716b195c8SJean-Christophe PLAGNIOL-VILLARD kbd_conv_char(scan_code); 61816b195c8SJean-Christophe PLAGNIOL-VILLARD 61916b195c8SJean-Christophe PLAGNIOL-VILLARD if (kbd_input != -1) 62016b195c8SJean-Christophe PLAGNIOL-VILLARD return 1; 62116b195c8SJean-Christophe PLAGNIOL-VILLARD } 622835dd000SBin Meng 62316b195c8SJean-Christophe PLAGNIOL-VILLARD return 0; 62416b195c8SJean-Christophe PLAGNIOL-VILLARD } 62516b195c8SJean-Christophe PLAGNIOL-VILLARD 626835dd000SBin Meng /* 62716b195c8SJean-Christophe PLAGNIOL-VILLARD * i8042_getc - wait till keyboard input is available 628835dd000SBin Meng * 62916b195c8SJean-Christophe PLAGNIOL-VILLARD * option: turn on/off cursor while waiting 63016b195c8SJean-Christophe PLAGNIOL-VILLARD */ 631709ea543SSimon Glass int i8042_getc(struct stdio_dev *dev) 63216b195c8SJean-Christophe PLAGNIOL-VILLARD { 63316b195c8SJean-Christophe PLAGNIOL-VILLARD int ret_chr; 63416b195c8SJean-Christophe PLAGNIOL-VILLARD unsigned char scan_code; 63516b195c8SJean-Christophe PLAGNIOL-VILLARD 636dd4a5b22SGabe Black while (kbd_input == -1) { 637835dd000SBin Meng while ((in8(I8042_STS_REG) & STATUS_OBF) == 0) { 63816b195c8SJean-Christophe PLAGNIOL-VILLARD } 63916b195c8SJean-Christophe PLAGNIOL-VILLARD scan_code = in8(I8042_DATA_REG); 64016b195c8SJean-Christophe PLAGNIOL-VILLARD if (scan_code != 0xfa) 64116b195c8SJean-Christophe PLAGNIOL-VILLARD kbd_conv_char(scan_code); 64216b195c8SJean-Christophe PLAGNIOL-VILLARD } 64316b195c8SJean-Christophe PLAGNIOL-VILLARD ret_chr = kbd_input; 64416b195c8SJean-Christophe PLAGNIOL-VILLARD kbd_input = -1; 645835dd000SBin Meng 64616b195c8SJean-Christophe PLAGNIOL-VILLARD return ret_chr; 64716b195c8SJean-Christophe PLAGNIOL-VILLARD } 648