i8042: Handle a duplicate power-on-reset response
Sometimes we seem to get 0xaa twice which causes the config read to fail. This causes chromebook_link to fail to set up the keyboard. Add a check for this and read the config again when detected. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
parent
dcbf825714
commit
011d89d606
1 changed files with 19 additions and 2 deletions
|
@ -15,13 +15,20 @@
|
||||||
#include <keyboard.h>
|
#include <keyboard.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
/* defines */
|
/* defines */
|
||||||
#define in8(p) inb(p)
|
#define in8(p) inb(p)
|
||||||
#define out8(p, v) outb(v, p)
|
#define out8(p, v) outb(v, p)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
QUIRK_DUP_POR = 1 << 0,
|
||||||
|
};
|
||||||
|
|
||||||
/* locals */
|
/* locals */
|
||||||
struct i8042_kbd_priv {
|
struct i8042_kbd_priv {
|
||||||
bool extended; /* true if an extended keycode is expected next */
|
bool extended; /* true if an extended keycode is expected next */
|
||||||
|
int quirks; /* quirks that we support */
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned char ext_key_map[] = {
|
static unsigned char ext_key_map[] = {
|
||||||
|
@ -113,7 +120,7 @@ static int kbd_cmd_write(int cmd, int data)
|
||||||
return kbd_write(I8042_DATA_REG, data);
|
return kbd_write(I8042_DATA_REG, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kbd_reset(void)
|
static int kbd_reset(int quirk)
|
||||||
{
|
{
|
||||||
int config;
|
int config;
|
||||||
|
|
||||||
|
@ -132,6 +139,10 @@ static int kbd_reset(void)
|
||||||
if (config == -1)
|
if (config == -1)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
/* Sometimes get a second byte */
|
||||||
|
else if ((quirk & QUIRK_DUP_POR) && config == KBD_POR)
|
||||||
|
config = kbd_cmd_read(CMD_RD_CONFIG);
|
||||||
|
|
||||||
config |= CONFIG_AT_TRANS;
|
config |= CONFIG_AT_TRANS;
|
||||||
config &= ~(CONFIG_KIRQ_EN | CONFIG_MIRQ_EN);
|
config &= ~(CONFIG_KIRQ_EN | CONFIG_MIRQ_EN);
|
||||||
if (kbd_cmd_write(CMD_WR_CONFIG, config))
|
if (kbd_cmd_write(CMD_WR_CONFIG, config))
|
||||||
|
@ -246,6 +257,7 @@ static int i8042_kbd_check(struct input_config *input)
|
||||||
static int i8042_start(struct udevice *dev)
|
static int i8042_start(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct keyboard_priv *uc_priv = dev_get_uclass_priv(dev);
|
struct keyboard_priv *uc_priv = dev_get_uclass_priv(dev);
|
||||||
|
struct i8042_kbd_priv *priv = dev_get_priv(dev);
|
||||||
struct input_config *input = &uc_priv->input;
|
struct input_config *input = &uc_priv->input;
|
||||||
int keymap, try;
|
int keymap, try;
|
||||||
char *penv;
|
char *penv;
|
||||||
|
@ -264,7 +276,7 @@ static int i8042_start(struct udevice *dev)
|
||||||
keymap = KBD_GER;
|
keymap = KBD_GER;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (try = 0; kbd_reset() != 0; try++) {
|
for (try = 0; kbd_reset(priv->quirks) != 0; try++) {
|
||||||
if (try >= KBD_RESET_TRIES)
|
if (try >= KBD_RESET_TRIES)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -294,10 +306,15 @@ static int i8042_start(struct udevice *dev)
|
||||||
static int i8042_kbd_probe(struct udevice *dev)
|
static int i8042_kbd_probe(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct keyboard_priv *uc_priv = dev_get_uclass_priv(dev);
|
struct keyboard_priv *uc_priv = dev_get_uclass_priv(dev);
|
||||||
|
struct i8042_kbd_priv *priv = dev_get_priv(dev);
|
||||||
struct stdio_dev *sdev = &uc_priv->sdev;
|
struct stdio_dev *sdev = &uc_priv->sdev;
|
||||||
struct input_config *input = &uc_priv->input;
|
struct input_config *input = &uc_priv->input;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (fdtdec_get_bool(gd->fdt_blob, dev->of_offset,
|
||||||
|
"intel,duplicate-por"))
|
||||||
|
priv->quirks |= QUIRK_DUP_POR;
|
||||||
|
|
||||||
/* Register the device. i8042_start() will be called soon */
|
/* Register the device. i8042_start() will be called soon */
|
||||||
input->dev = dev;
|
input->dev = dev;
|
||||||
input->read_keys = i8042_kbd_check;
|
input->read_keys = i8042_kbd_check;
|
||||||
|
|
Loading…
Reference in a new issue