diff mbox

[U-Boot,v2,26/28] i8042: Handle a duplicate power-on-reset response

Message ID 1445224657-20622-27-git-send-email-sjg@chromium.org
State Superseded
Delegated to: Simon Glass
Headers show

Commit Message

Simon Glass Oct. 19, 2015, 3:17 a.m. UTC
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>
---

Changes in v2:
- Use device tree to handle this quirk

 drivers/input/i8042.c | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

Comments

Bin Meng Oct. 23, 2015, 10:19 a.m. UTC | #1
Hi Simon,

On Mon, Oct 19, 2015 at 11:17 AM, Simon Glass <sjg@chromium.org> wrote:
> 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>

Other than one typo below:

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

> ---
>
> Changes in v2:
> - Use device tree to handle this quirk
>
>  drivers/input/i8042.c | 21 +++++++++++++++++++--
>  1 file changed, 19 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/input/i8042.c b/drivers/input/i8042.c
> index e5e2926..6d358b7 100644
> --- a/drivers/input/i8042.c
> +++ b/drivers/input/i8042.c
> @@ -15,13 +15,20 @@
>  #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 {
> +       QUICK_DUP_POR   = 1 << 0,

typo: QUIRK

> +};
> +
>  /* 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;
>
> @@ -132,6 +139,10 @@ static int kbd_reset(void)
>         if (config == -1)
>                 goto err;
>
> +       /* Sometimes get a second byte */
> +       else if ((quirk & QUICK_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 +257,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;
> @@ -264,7 +276,7 @@ static int i8042_start(struct udevice *dev)
>                         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 +306,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,
> +                           "intel,duplicate-por"))
> +               priv->quirks |= QUICK_DUP_POR;
> +
>         /* Register the device. i8042_start() will be called soon */
>         input->dev = dev;
>         input->read_keys = i8042_kbd_check;
> --

Regards,
Bin
diff mbox

Patch

diff --git a/drivers/input/i8042.c b/drivers/input/i8042.c
index e5e2926..6d358b7 100644
--- a/drivers/input/i8042.c
+++ b/drivers/input/i8042.c
@@ -15,13 +15,20 @@ 
 #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 {
+	QUICK_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;
 
@@ -132,6 +139,10 @@  static int kbd_reset(void)
 	if (config == -1)
 		goto err;
 
+	/* Sometimes get a second byte */
+	else if ((quirk & QUICK_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 +257,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;
@@ -264,7 +276,7 @@  static int i8042_start(struct udevice *dev)
 			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 +306,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,
+			    "intel,duplicate-por"))
+		priv->quirks |= QUICK_DUP_POR;
+
 	/* Register the device. i8042_start() will be called soon */
 	input->dev = dev;
 	input->read_keys = i8042_kbd_check;