]> git.sur5r.net Git - u-boot/blobdiff - drivers/input/i8042.c
Merge git://www.denx.de/git/u-boot-imx
[u-boot] / drivers / input / i8042.c
index e5e2926670d7c1d7deeff4cf83d26c6b2dd3ce37..18476e97d1886d8569e1343a1d9129c73835b4ce 100644 (file)
 #include <keyboard.h>
 #include <asm/io.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /* defines */
 #define in8(p)         inb(p)
 #define out8(p, v)     outb(v, p)
 
+enum {
+       QUIRK_DUP_POR   = 1 << 0,
+};
+
 /* locals */
 struct i8042_kbd_priv {
        bool extended;  /* true if an extended keycode is expected next */
+       int quirks;     /* quirks that we support */
 };
 
 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);
 }
 
-static int kbd_reset(void)
+static int kbd_reset(int quirk)
 {
        int config;
 
@@ -127,11 +134,19 @@ static int kbd_reset(void)
            kbd_read(I8042_DATA_REG) != KBD_POR)
                goto err;
 
+       if (kbd_write(I8042_DATA_REG, CMD_DRAIN_OUTPUT) ||
+           kbd_read(I8042_DATA_REG) != KBD_ACK)
+               goto err;
+
        /* set AT translation and disable irq */
        config = kbd_cmd_read(CMD_RD_CONFIG);
        if (config == -1)
                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_KIRQ_EN | CONFIG_MIRQ_EN);
        if (kbd_cmd_write(CMD_WR_CONFIG, config))
@@ -246,6 +261,7 @@ static int i8042_kbd_check(struct input_config *input)
 static int i8042_start(struct udevice *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;
        int keymap, try;
        char *penv;
@@ -258,13 +274,13 @@ static int i8042_start(struct udevice *dev)
 
        /* Init keyboard device (default US layout) */
        keymap = KBD_US;
-       penv = getenv("keymap");
+       penv = env_get("keymap");
        if (penv != NULL) {
                if (strncmp(penv, "de", 3) == 0)
                        keymap = KBD_GER;
        }
 
-       for (try = 0; kbd_reset() != 0; try++) {
+       for (try = 0; kbd_reset(priv->quirks) != 0; try++) {
                if (try >= KBD_RESET_TRIES)
                        return -1;
        }
@@ -294,10 +310,15 @@ static int i8042_start(struct udevice *dev)
 static int i8042_kbd_probe(struct udevice *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 input_config *input = &uc_priv->input;
        int ret;
 
+       if (fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
+                           "intel,duplicate-por"))
+               priv->quirks |= QUIRK_DUP_POR;
+
        /* Register the device. i8042_start() will be called soon */
        input->dev = dev;
        input->read_keys = i8042_kbd_check;