Changeset 3610


Ignore:
Timestamp:
Sep 26, 2008, 7:15:38 PM (7 years ago)
Author:
mjones
Message:

This patch fixes the dbm690t keyboard not working issue. It should also
fix the a8n_e and any other it8712f SIO keyboard issues. The it8712f
requires an archaic PS/2 mode setting to the keyboard controller before
accessing the keyboard. Beyond that, I made the keyboard controller and
keyboard init more robust and added more informative debug output.

Signed-off-by: Marc Jones <marc.jones@…>
Acked-by: Stefan Reinauer <stepan@…>

Location:
trunk/coreboot-v2/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/coreboot-v2/src/pc80/keyboard.c

    r2869 r3610  
     1/*
     2 * This file is part of the coreboot project.
     3 *
     4 * Copyright (C) 2008 Advanced Micro Devices, Inc.
     5 * Copyright (C) ???? Ollie Lo <ollielo@hotmail.com>
     6 *
     7 * This program is free software; you can redistribute it and/or modify
     8 * it under the terms of the GNU General Public License as published by
     9 * the Free Software Foundation; version 2 of the License.
     10 *
     11 * This program is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 * GNU General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU General Public License
     17 * along with this program; if not, write to the Free Software
     18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
     19 */
     20
     21
    122#include <console/console.h>
    223#include <pc80/keyboard.h>
     
    425#include <arch/io.h>
    526
    6 static int kbd_empty_input_buffer(void)
    7 {
    8         unsigned long timeout;
     27static int kbc_input_buffer_empty(void)
     28{
     29        u32 timeout;
    930        for(timeout = 1000000; timeout && (inb(0x64) & 0x02); timeout--) {
    10                 post_code(0);
     31                inb(0x80);
     32        }
     33
     34        if (!timeout) {
     35                printk_err("Unexpected Keyboard controller input buffer full\n");
    1136        }
    1237        return !!timeout;
    1338}
    1439
    15 static int kbd_empty_output_buffer(void)
    16 {
    17         unsigned long timeout;
     40
     41static int kbc_output_buffer_full(void)
     42{
     43        u32 timeout;
    1844        for(timeout = 1000000; timeout && ((inb(0x64) & 0x01) == 0); timeout--) {
    19                 post_code(0);
     45                inb(0x80);
     46        }
     47
     48        if (!timeout) {
     49                printk_err("Keyboard controller output buffer result timeout\n");
    2050        }
    2151        return !!timeout;
    2252}
    2353
    24 /* much better keyboard init courtesy ollie@sis.com.tw
    25    TODO: Typematic Setting, the keyboard is too slow for me */
     54
     55static int kbc_cleanup_buffers(void)
     56{
     57        u32 timeout;
     58        for(timeout = 1000000; timeout && (inb(0x64) & 0x03); timeout--) {
     59                inb(0x60);
     60        }
     61
     62        if (!timeout) {
     63                printk_err("Couldn't cleanup the keyboard controller buffers\n");
     64                printk_err("0x64: 0x%x, 0x60: 0x%x\n", inb(0x64), inb(0x60));
     65        }
     66        return !!timeout;
     67}
     68
     69
     70static u8 send_keyboard(u8 command)
     71{
     72        u8 regval = 0;
     73        u8 resend = 10;
     74
     75        do {
     76                if (!kbc_input_buffer_empty()) return 0;
     77                outb(command, 0x60);
     78                if (!kbc_output_buffer_full()) return 0;
     79                regval = inb(0x60);
     80                --resend;
     81        } while (regval == 0xFE && resend > 0);
     82
     83        return regval;
     84}
     85
     86
    2687static void pc_keyboard_init(struct pc_keyboard *keyboard)
    2788{
    28         unsigned char regval;
    29 
     89        u8 regval;
     90        u8 resend;
    3091        printk_debug("Keyboard init...\n");
    31         /* send cmd = 0xAA, self test 8042 */
    32         outb(0xaa, 0x64);
    33 
    34         /* empty input buffer or any other command/data will be lost */
    35         if (!kbd_empty_input_buffer()) {
    36                 printk_err("Keyboard input buffer would not empty\n");
    37                 return;
    38         }
    39 
    40         /* empty output buffer or any other command/data will be lost */
    41         if (!kbd_empty_output_buffer()) {
    42                 printk_err("Keyboard output buffer would not empty\n");
    43                 return;
    44         }
    45 
    46         /* read self-test result, 0x55 should be returned form 0x60 */
     92
     93        /* clean up any junk that might have been in the kbc */
     94        if (!kbc_cleanup_buffers()) return;
     95
     96        /* reset/self test 8042 - send cmd 0xAA,  */
     97        if (!kbc_input_buffer_empty()) return;
     98        outb(0xAA, 0x64);
     99        if (!kbc_output_buffer_full()) return;
     100
     101        /* read self-test result, 0x55 is returned in the output buffer (0x60) */
    47102        if ((regval = inb(0x60) != 0x55)) {
    48                 printk_err("Keyboard selftest failed\n");
    49                 return;
    50         }
    51 
    52         /* enable keyboard interface */
    53         outb(0x60, 0x64);
    54         kbd_empty_input_buffer();
    55 
    56         /* send cmd: enable IRQ 1 */
    57         outb(0x61, 0x60);
    58         kbd_empty_input_buffer();
    59 
    60         /* reset kerboard and self test  (keyboard side) */
    61         outb(0xff, 0x60);
    62 
    63         /* empty inut bufferm or any other command/data will be lost */
    64         kbd_empty_input_buffer();
    65 
    66         /* empty output buffer or any other command/data will be lost */
    67         kbd_empty_output_buffer();
    68 
    69         if ((regval = inb(0x60) != 0xfa))
    70                 return;
    71 
    72         kbd_empty_output_buffer();
    73         if ((regval = inb(0x60) != 0xaa))
    74                 return;
    75 }
     103                printk_err("Keyboard Controller selftest failed: 0x%x\n", regval);
     104                return;
     105        }
     106
     107        /* Enable keyboard interface - No IRQ*/
     108        resend = 10;
     109        regval = 0;
     110        do {
     111                if (!kbc_input_buffer_empty()) return;
     112                outb(0x60, 0x64);
     113                if (!kbc_input_buffer_empty()) return;
     114                outb(0x20, 0x60);       /* send cmd: enable keyboard and IRQ 1 */
     115                u8 resend = 10;
     116                if ((inb(0x64) & 0x01)) {
     117                        regval = inb(0x60);
     118                }
     119                --resend;
     120        } while (regval == 0xFE && resend > 0);
     121
     122        /* clean up any junk that might have been in the keyboard */
     123        if (!kbc_cleanup_buffers()) return;
     124
     125        /* reset keyboard and self test (keyboard side) */
     126        regval = send_keyboard(0xFF);
     127        if (regval != 0xFA) {
     128                printk_err("Keyboard selftest failed ACK: 0x%x\n", regval);
     129                return;
     130        }
     131        if (!kbc_output_buffer_full()) return;
     132        regval = inb(0x60);
     133        if (regval != 0xAA) {
     134                printk_err("Keyboard selftest failed: 0x%x\n", regval);
     135                return;
     136        }
     137
     138        /*
     139         * The following set scancode stuff is what normal BIOS do. It could be
     140         * argued that coreboot shouldn't set the scan code.....
     141         */
     142
     143        /* disable the keyboard */
     144        regval = send_keyboard(0xF5);
     145        if (regval != 0xFA) {
     146                printk_err("Keyboard disable failed ACK: 0x%x\n", regval);
     147                return;
     148        }
     149
     150        /* Set scancode command */
     151        regval = send_keyboard(0xF0);
     152        if (regval != 0xFA) {
     153                printk_err("Keyboard set scancode cmd failed ACK: 0x%x\n", regval);
     154                return;
     155        }
     156        /* Set scancode mode 2 */
     157        regval = send_keyboard(0x02);
     158        if (regval != 0xFA) {
     159                printk_err("Keyboard set scancode mode failed ACK: 0x%x\n", regval);
     160                return;
     161        }
     162
     163        /* enable the keyboard */
     164        regval = send_keyboard(0xF4);
     165        if (regval != 0xFA) {
     166                printk_err("Keyboard enable failed ACK: 0x%x\n", regval);
     167                return;
     168        }
     169
     170        /* All is well - enable keyboard interface */
     171        resend = 10;
     172        regval = 0;
     173        do {
     174                if (!kbc_input_buffer_empty()) return;
     175                outb(0x60, 0x64);
     176                if (!kbc_input_buffer_empty()) return;
     177                outb(0x61, 0x60);       /* send cmd: enable keyboard and IRQ 1 */
     178                if ((inb(0x64) & 0x01)) {
     179                        regval = inb(0x60);
     180                }
     181                --resend;
     182        } while (regval == 0xFE && resend > 0);
     183}
     184
    76185
    77186void init_pc_keyboard(unsigned port0, unsigned port1, struct pc_keyboard *kbd)
     
    81190        }
    82191}
     192
     193/*
     194 * Support PS/2 mode -  oddball SIOs(KBC) need this setup
     195 * Not well documented. Google - 0xcb keyboard controller
     196 * This is called before pc_keyboard_init().
     197 */
     198void set_kbc_ps2_mode()
     199{
     200        /* clean up any junk that might have been in the kbc */
     201        if (!kbc_cleanup_buffers()) return;
     202
     203        /* reset/self test 8042 before we can do anything */
     204        if (!kbc_input_buffer_empty()) return;
     205        outb(0xAA, 0x64);
     206        if (!kbc_output_buffer_full()) return;
     207
     208        /* read self-test result, 0x55 is returned in the output buffer (0x60) */
     209        if ((inb(0x60) != 0x55)) {
     210                printk_err("Keyboard Controller selftest failed\n");
     211                return;
     212        }
     213
     214        /* Support PS/2 mode */
     215        if (!kbc_input_buffer_empty()) return;
     216        outb(0xcb, 0x64);
     217        if (!kbc_input_buffer_empty()) return;
     218        outb(0x01, 0x60);
     219        kbc_cleanup_buffers();
     220}
  • trunk/coreboot-v2/src/superio/ite/it8712f/superio.c

    r3052 r3610  
    7777                res0 = find_resource(dev, PNP_IDX_IO0);
    7878                res1 = find_resource(dev, PNP_IDX_IO1);
     79                set_kbc_ps2_mode();
    7980                init_pc_keyboard(res0->base, res1->base, &conf->keyboard);
    8081                break;
Note: See TracChangeset for help on using the changeset viewer.