[U-Boot] [PATCH] i.MX6: mx6qsabrelite: Add keypress support

Marek Vasut
2012-03-03T02:18:24Z

> This patch adds support for the GPIO keyboard used on MX6Q SabreLite.
>
> This is generally used for invoking Android "recovery mode" in
> response to a long press of volume key down during boot.
>
> This can be tested by a boot script like so:
> if keypress voldown && sleep 1 && keypress voldown ; then
> echo "do recovery thing" ;
> fi
>
> Key values can be seen by issuing keypress with no arguments:
>
> MX6QSABRELITE U-Boot > keypress
> keys: !menu !back !search !home !volup !voldown
> ---
> board/freescale/mx6qsabrelite/mx6qsabrelite.c | 76
> +++++++++++++++++++++++++ 1 files changed, 76 insertions(+), 0
> deletions(-)
>
> diff --git a/board/freescale/mx6qsabrelite/mx6qsabrelite.c
> b/board/freescale/mx6qsabrelite/mx6qsabrelite.c index e0ba6a4..0d45615
> 100644
> --- a/board/freescale/mx6qsabrelite/mx6qsabrelite.c
> +++ b/board/freescale/mx6qsabrelite/mx6qsabrelite.c
> @@ -50,6 +50,10 @@ DECLARE_GLOBAL_DATA_PTR;
> PAD_CTL_PUS_100K_DOWN | PAD_CTL_SPEED_MED | \
> PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
>
> +#define BUTTON_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \
> + PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
> + PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
> +
> int dram_init(void)
> {
> gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
> @@ -122,6 +126,15 @@ iomux_v3_cfg_t enet_pads2[] = {
> MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
> };
>
> +static iomux_v3_cfg_t const button_pads[] = {
> + MX6Q_PAD_NANDF_D1__GPIO_2_1 | MUX_PAD_CTRL(BUTTON_PAD_CTRL), /* J14
-
> Menu Button */ + MX6Q_PAD_NANDF_D2__GPIO_2_2 |
> MUX_PAD_CTRL(BUTTON_PAD_CTRL), /* J14 - Back Button */
> + MX6Q_PAD_NANDF_D3__GPIO_2_3 | MUX_PAD_CTRL(BUTTON_PAD_CTRL), /* J14
-
> Search Button */ + MX6Q_PAD_NANDF_D4__GPIO_2_4 |
> MUX_PAD_CTRL(BUTTON_PAD_CTRL), /* J14 - Home Button */
> + MX6Q_PAD_GPIO_19__GPIO_4_5 | MUX_PAD_CTRL(BUTTON_PAD_CTRL), /* J14
-
> Volume Down */ + MX6Q_PAD_GPIO_18__GPIO_7_13 |
> MUX_PAD_CTRL(BUTTON_PAD_CTRL), /* J14 - Volume Up */ +};
> +
> static void setup_iomux_enet(void)
> {
> gpio_direction_output(87, 0); /* GPIO 3-23 */
> @@ -323,10 +336,18 @@ int setup_sata(void)
> }
> #endif
>
> +static void setup_buttons(void)
> +{
> + imx_iomux_v3_setup_multiple_pads(button_pads,
> + ARRAY_SIZE(button_pads));
> +}
> +
> int board_early_init_f(void)
> {
> setup_iomux_uart();
>
> + setup_buttons();
> +
> #ifdef CONFIG_CMD_SATA
> setup_sata();
> #endif
> @@ -350,3 +371,58 @@ int checkboard(void)
>
> return 0;
> }
> +
> +struct button_key {
> + char const *name;
> + unsigned gpnum;
> +};
> +
> +static struct button_key const buttons[] = {
> + {"menu", GPIO_NUMBER(2, 1)},
> + {"back", GPIO_NUMBER(2, 2)},
> + {"search", GPIO_NUMBER(2, 3)},
> + {"home", GPIO_NUMBER(2, 4)},
> + {"voldown", GPIO_NUMBER(4, 5)},
> + {"volup", GPIO_NUMBER(7, 13)},
> +};
> +
> +static int keypress(cmd_tbl_t *cmdtp, int flag, int argc, char * const
> argv[]) +{
> + if (1 < argc) {
> + int arg;
> + int pressed = 1 ;
> + for (arg=1; arg<argc; arg++) {
> + char const *keyname=argv[arg];
> + int i;
> + for (i=0; pressed && (i < ARRAY_SIZE(buttons)); i++) {
> + if (0 == strcmp(buttons[i].name,keyname)) {
> + pressed = pressed && (0 ==
gpio_get_value(buttons[i].gpnum));
> + break;
> + }
> + }
> + if (ARRAY_SIZE(buttons) == i) {
> + printf ("unrecognized key %s\n", keyname);
> + pressed = 0;
> + break;
> + }
> + }
> + return (0 == pressed);
> + } else {
> + int i;
> + printf ("keys: ");
> + for (i=0; i<ARRAY_SIZE(buttons); i++) {
> + if (0 != gpio_get_value(buttons[i].gpnum))
> + printf("!");
> + printf("%s\t",buttons[i].name);
> + }
> + printf("\n");
> + return 0 ;
> + }
> +}
> +
> +U_BOOT_CMD(
> + keypress, CONFIG_SYS_MAXARGS, 1, keypress,
> + "Display or test keypresses",
> + " keypress - show key(s) pressed\n"
> + " keypress name - test key name (return 0 if pressed)\n"
> +);

Why not make it an STDIN device as any other keyboard?

M