SPDX: Convert all of our single license tags to Linux Kernel style
[platform/kernel/u-boot.git] / drivers / input / tegra-kbc.c
index 88471d3..70429b9 100644 (file)
@@ -1,29 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  *  (C) Copyright 2011
  *  NVIDIA Corporation <www.nvidia.com>
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
  */
 
 #include <common.h>
+#include <dm.h>
 #include <fdtdec.h>
 #include <input.h>
+#include <keyboard.h>
 #include <key_matrix.h>
 #include <stdio_dev.h>
 #include <tegra-kbc.h>
@@ -33,8 +18,6 @@
 #include <asm/arch-tegra/timer.h>
 #include <linux/input.h>
 
-DECLARE_GLOBAL_DATA_PTR;
-
 enum {
        KBC_MAX_GPIO            = 24,
        KBC_MAX_KPENT           = 8,    /* size of keypress entry queue */
@@ -56,14 +39,13 @@ enum {
 };
 
 /* keyboard controller config and state */
-static struct keyb {
-       struct input_config input;      /* The input layer */
+struct tegra_kbd_priv {
+       struct input_config *input;     /* The input layer */
        struct key_matrix matrix;       /* The key matrix layer */
 
        struct kbc_tegra *kbc;          /* tegra keyboard controller */
        unsigned char inited;           /* 1 if keyboard has been inited */
        unsigned char first_scan;       /* 1 if this is our first key scan */
-       unsigned char created;          /* 1 if driver has been created */
 
        /*
         * After init we must wait a short time before polling the keyboard.
@@ -74,17 +56,17 @@ static struct keyb {
        unsigned int start_time_ms;     /* Time that we inited (in ms) */
        unsigned int last_poll_ms;      /* Time we should last polled */
        unsigned int next_repeat_ms;    /* Next time we repeat a key */
-} config;
+};
 
 /**
  * reads the keyboard fifo for current keypresses
  *
- * @param config       Keyboard config
+ * @param priv         Keyboard private data
  * @param fifo         Place to put fifo results
  * @param max_keycodes Maximum number of key codes to put in the fifo
  * @return number of items put into fifo
  */
-static int tegra_kbc_find_keys(struct keyb *config, int *fifo,
+static int tegra_kbc_find_keys(struct tegra_kbd_priv *priv, int *fifo,
                               int max_keycodes)
 {
        struct key_matrix_key keys[KBC_MAX_KPENT], *key;
@@ -94,7 +76,7 @@ static int tegra_kbc_find_keys(struct keyb *config, int *fifo,
        for (key = keys, i = 0; i < KBC_MAX_KPENT; i++, key++) {
                /* Get next word */
                if (!(i & 3))
-                       kp_ent = readl(&config->kbc->kp_ent[i / 4]);
+                       kp_ent = readl(&priv->kbc->kp_ent[i / 4]);
 
                key->valid = (kp_ent & KBC_KPENT_VALID) != 0;
                key->row = (kp_ent >> 3) & 0xf;
@@ -103,7 +85,7 @@ static int tegra_kbc_find_keys(struct keyb *config, int *fifo,
                /* Shift to get next entry */
                kp_ent >>= 8;
        }
-       return key_matrix_decode(&config->matrix, keys, KBC_MAX_KPENT, fifo,
+       return key_matrix_decode(&priv->matrix, keys, KBC_MAX_KPENT, fifo,
                                 max_keycodes);
 }
 
@@ -122,10 +104,10 @@ static int tegra_kbc_find_keys(struct keyb *config, int *fifo,
  * Note: if fifo_cnt is 0, we will tell the input layer that no keys are
  * pressed.
  *
- * @param config       Keyboard config
+ * @param priv         Keyboard private data
  * @param fifo_cnt     Number of entries in the keyboard fifo
  */
-static void process_fifo(struct keyb *config, int fifo_cnt)
+static void process_fifo(struct tegra_kbd_priv *priv, int fifo_cnt)
 {
        int fifo[KBC_MAX_KPENT];
        int cnt = 0;
@@ -133,9 +115,9 @@ static void process_fifo(struct keyb *config, int fifo_cnt)
        /* Always call input_send_keycodes() at least once */
        do {
                if (fifo_cnt)
-                       cnt = tegra_kbc_find_keys(config, fifo, KBC_MAX_KPENT);
+                       cnt = tegra_kbc_find_keys(priv, fifo, KBC_MAX_KPENT);
 
-               input_send_keycodes(&config->input, fifo, cnt);
+               input_send_keycodes(priv->input, fifo, cnt);
        } while (--fifo_cnt > 0);
 }
 
@@ -143,24 +125,24 @@ static void process_fifo(struct keyb *config, int fifo_cnt)
  * Check the keyboard controller and emit ASCII characters for any keys that
  * are pressed.
  *
- * @param config       Keyboard config
+ * @param priv         Keyboard private data
  */
-static void check_for_keys(struct keyb *config)
+static void check_for_keys(struct tegra_kbd_priv *priv)
 {
        int fifo_cnt;
 
-       if (!config->first_scan &&
-                       get_timer(config->last_poll_ms) < KBC_REPEAT_RATE_MS)
+       if (!priv->first_scan &&
+           get_timer(priv->last_poll_ms) < KBC_REPEAT_RATE_MS)
                return;
-       config->last_poll_ms = get_timer(0);
-       config->first_scan = 0;
+       priv->last_poll_ms = get_timer(0);
+       priv->first_scan = 0;
 
        /*
         * Once we get here we know the keyboard has been scanned. So if there
         * scan waiting for us, we know that nothing is held down.
         */
-       fifo_cnt = (readl(&config->kbc->interrupt) >> 4) & 0xf;
-       process_fifo(config, fifo_cnt);
+       fifo_cnt = (readl(&priv->kbc->interrupt) >> 4) & 0xf;
+       process_fifo(priv, fifo_cnt);
 }
 
 /**
@@ -169,22 +151,22 @@ static void check_for_keys(struct keyb *config)
  * Wkup mode to Continous polling mode and the repoll time. We can
  * deduct the time that's already elapsed.
  *
- * @param config       Keyboard config
+ * @param priv         Keyboard private data
  */
-static void kbd_wait_for_fifo_init(struct keyb *config)
+static void kbd_wait_for_fifo_init(struct tegra_kbd_priv *priv)
 {
-       if (!config->inited) {
+       if (!priv->inited) {
                unsigned long elapsed_time;
                long delay_ms;
 
-               elapsed_time = get_timer(config->start_time_ms);
-               delay_ms = config->init_dly_ms - elapsed_time;
+               elapsed_time = get_timer(priv->start_time_ms);
+               delay_ms = priv->init_dly_ms - elapsed_time;
                if (delay_ms > 0) {
                        udelay(delay_ms * 1000);
                        debug("%s: delay %ldms\n", __func__, delay_ms);
                }
 
-               config->inited = 1;
+               priv->inited = 1;
        }
 }
 
@@ -197,40 +179,18 @@ static void kbd_wait_for_fifo_init(struct keyb *config)
  * @param input                Input configuration
  * @return 1, to indicate that we have something to look at
  */
-int tegra_kbc_check(struct input_config *input)
+static int tegra_kbc_check(struct input_config *input)
 {
-       kbd_wait_for_fifo_init(&config);
-       check_for_keys(&config);
+       struct tegra_kbd_priv *priv = dev_get_priv(input->dev);
 
-       return 1;
-}
+       kbd_wait_for_fifo_init(priv);
+       check_for_keys(priv);
 
-/**
- * Test if keys are available to be read
- *
- * @return 0 if no keys available, 1 if keys are available
- */
-static int kbd_tstc(void)
-{
-       /* Just get input to do this for us */
-       return input_tstc(&config.input);
-}
-
-/**
- * Read a key
- *
- * TODO: U-Boot wants 0 for no key, but Ctrl-@ is a valid key...
- *
- * @return ASCII key code, or 0 if no key, or -1 if error
- */
-static int kbd_getc(void)
-{
-       /* Just get input to do this for us */
-       return input_getc(&config.input);
+       return 1;
 }
 
 /* configures keyboard GPIO registers to use the rows and columns */
-static void config_kbc_gpio(struct kbc_tegra *kbc)
+static void config_kbc_gpio(struct tegra_kbd_priv *priv, struct kbc_tegra *kbc)
 {
        int i;
 
@@ -249,10 +209,10 @@ static void config_kbc_gpio(struct kbc_tegra *kbc)
                row_cfg &= ~r_mask;
                col_cfg &= ~c_mask;
 
-               if (i < config.matrix.num_rows) {
+               if (i < priv->matrix.num_rows) {
                        row_cfg |= ((i << 1) | 1) << r_shift;
                } else {
-                       col_cfg |= (((i - config.matrix.num_rows) << 1) | 1)
+                       col_cfg |= (((i - priv->matrix.num_rows) << 1) | 1)
                                        << c_shift;
                }
 
@@ -264,9 +224,9 @@ static void config_kbc_gpio(struct kbc_tegra *kbc)
 /**
  * Start up the keyboard device
  */
-static void tegra_kbc_open(void)
+static void tegra_kbc_open(struct tegra_kbd_priv *priv)
 {
-       struct kbc_tegra *kbc = config.kbc;
+       struct kbc_tegra *kbc = priv->kbc;
        unsigned int scan_period;
        u32 val;
 
@@ -281,16 +241,32 @@ static void tegra_kbc_open(void)
         * Before reading from the keyboard we must wait for the init_dly
         * plus the rpt_delay, plus 2ms for the row scan time.
         */
-       config.init_dly_ms = scan_period * 2 + 2;
+       priv->init_dly_ms = scan_period * 2 + 2;
 
        val = KBC_DEBOUNCE_COUNT << KBC_DEBOUNCE_CNT_SHIFT;
        val |= 1 << KBC_FIFO_TH_CNT_SHIFT;      /* fifo interrupt threshold */
        val |= KBC_CONTROL_KBC_EN;              /* enable */
        writel(val, &kbc->control);
 
-       config.start_time_ms = get_timer(0);
-       config.last_poll_ms = config.next_repeat_ms = get_timer(0);
-       config.first_scan = 1;
+       priv->start_time_ms = get_timer(0);
+       priv->last_poll_ms = get_timer(0);
+       priv->next_repeat_ms = priv->last_poll_ms;
+       priv->first_scan = 1;
+}
+
+static int tegra_kbd_start(struct udevice *dev)
+{
+       struct tegra_kbd_priv *priv = dev_get_priv(dev);
+
+       /* Set up pin mux and enable the clock */
+       funcmux_select(PERIPH_ID_KBC, FUNCMUX_DEFAULT);
+       clock_enable(PERIPH_ID_KBC);
+       config_kbc_gpio(priv, priv->kbc);
+
+       tegra_kbc_open(priv);
+       debug("%s: Tegra keyboard ready\n", __func__);
+
+       return 0;
 }
 
 /**
@@ -305,88 +281,72 @@ static void tegra_kbc_open(void)
  *
  * @return 0 if ok, -ve on error
  */
-static int init_tegra_keyboard(void)
+static int tegra_kbd_probe(struct udevice *dev)
 {
-       /* check if already created */
-       if (config.created)
-               return 0;
-
-#ifdef CONFIG_OF_CONTROL
-       int     node;
-
-       node = fdtdec_next_compatible(gd->fdt_blob, 0,
-                                         COMPAT_NVIDIA_TEGRA20_KBC);
-       if (node < 0) {
-               debug("%s: cannot locate keyboard node\n", __func__);
-               return node;
-       }
-       config.kbc = (struct kbc_tegra *)fdtdec_get_addr(gd->fdt_blob,
-                      node, "reg");
-       if ((fdt_addr_t)config.kbc == FDT_ADDR_T_NONE) {
+       struct tegra_kbd_priv *priv = dev_get_priv(dev);
+       struct keyboard_priv *uc_priv = dev_get_uclass_priv(dev);
+       struct stdio_dev *sdev = &uc_priv->sdev;
+       struct input_config *input = &uc_priv->input;
+       int ret;
+
+       priv->kbc = (struct kbc_tegra *)devfdt_get_addr(dev);
+       if ((fdt_addr_t)priv->kbc == FDT_ADDR_T_NONE) {
                debug("%s: No keyboard register found\n", __func__);
-               return -1;
+               return -EINVAL;
        }
-       input_set_delays(&config.input, KBC_REPEAT_DELAY_MS,
-                       KBC_REPEAT_RATE_MS);
+       input_set_delays(input, KBC_REPEAT_DELAY_MS, KBC_REPEAT_RATE_MS);
 
        /* Decode the keyboard matrix information (16 rows, 8 columns) */
-       if (key_matrix_init(&config.matrix, 16, 8, 1)) {
-               debug("%s: Could not init key matrix\n", __func__);
-               return -1;
+       ret = key_matrix_init(&priv->matrix, 16, 8, 1);
+       if (ret) {
+               debug("%s: Could not init key matrix: %d\n", __func__, ret);
+               return ret;
        }
-       if (key_matrix_decode_fdt(&config.matrix, gd->fdt_blob, node)) {
-               debug("%s: Could not decode key matrix from fdt\n", __func__);
-               return -1;
+       ret = key_matrix_decode_fdt(dev, &priv->matrix);
+       if (ret) {
+               debug("%s: Could not decode key matrix from fdt: %d\n",
+                     __func__, ret);
+               return ret;
        }
-       if (config.matrix.fn_keycode) {
-               if (input_add_table(&config.input, KEY_FN, -1,
-                                   config.matrix.fn_keycode,
-                                   config.matrix.key_count))
-                       return -1;
+       input_add_tables(input, false);
+       if (priv->matrix.fn_keycode) {
+               ret = input_add_table(input, KEY_FN, -1,
+                                     priv->matrix.fn_keycode,
+                                     priv->matrix.key_count);
+               if (ret) {
+                       debug("%s: input_add_table() failed\n", __func__);
+                       return ret;
+               }
        }
-#else
-#error "Tegra keyboard driver requires FDT definitions"
-#endif
-
-       /* Set up pin mux and enable the clock */
-       funcmux_select(PERIPH_ID_KBC, FUNCMUX_DEFAULT);
-       clock_enable(PERIPH_ID_KBC);
-       config_kbc_gpio(config.kbc);
 
-       tegra_kbc_open();
-       config.created = 1;
-       debug("%s: Tegra keyboard ready\n", __func__);
+       /* Register the device. init_tegra_keyboard() will be called soon */
+       priv->input = input;
+       input->dev = dev;
+       input->read_keys = tegra_kbc_check;
+       strcpy(sdev->name, "tegra-kbc");
+       ret = input_stdio_register(sdev);
+       if (ret) {
+               debug("%s: input_stdio_register() failed\n", __func__);
+               return ret;
+       }
 
        return 0;
 }
 
-int drv_keyboard_init(void)
-{
-       struct stdio_dev dev;
-       char *stdinname = getenv("stdin");
-       int error;
-
-       if (input_init(&config.input, 0)) {
-               debug("%s: Cannot set up input\n", __func__);
-               return -1;
-       }
-       config.input.read_keys = tegra_kbc_check;
+static const struct keyboard_ops tegra_kbd_ops = {
+       .start  = tegra_kbd_start,
+};
 
-       memset(&dev, '\0', sizeof(dev));
-       strcpy(dev.name, "tegra-kbc");
-       dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
-       dev.getc = kbd_getc;
-       dev.tstc = kbd_tstc;
-       dev.start = init_tegra_keyboard;
+static const struct udevice_id tegra_kbd_ids[] = {
+       { .compatible = "nvidia,tegra20-kbc" },
+       { }
+};
 
-       /* Register the device. init_tegra_keyboard() will be called soon */
-       error = input_stdio_register(&dev);
-       if (error)
-               return error;
-#ifdef CONFIG_CONSOLE_MUX
-       error = iomux_doenv(stdin, stdinname);
-       if (error)
-               return error;
-#endif
-       return 0;
-}
+U_BOOT_DRIVER(tegra_kbd) = {
+       .name   = "tegra_kbd",
+       .id     = UCLASS_KEYBOARD,
+       .of_match = tegra_kbd_ids,
+       .probe = tegra_kbd_probe,
+       .ops    = &tegra_kbd_ops,
+       .priv_auto_alloc_size = sizeof(struct tegra_kbd_priv),
+};