X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=drivers%2Finput%2Ftegra-kbc.c;h=70429b94a49c6c866afb2b0b3997301dbe250ccb;hb=83d290c56fab2d38cd1ab4c4cc7099559c1d5046;hp=88471d3edf253e432458a44fb0c8d5ed29317d47;hpb=7528cf5f016b5b8b8b12b373f6f31a10bf89233d;p=platform%2Fkernel%2Fu-boot.git diff --git a/drivers/input/tegra-kbc.c b/drivers/input/tegra-kbc.c index 88471d3..70429b9 100644 --- a/drivers/input/tegra-kbc.c +++ b/drivers/input/tegra-kbc.c @@ -1,29 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * (C) Copyright 2011 * NVIDIA Corporation - * - * 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 +#include #include #include +#include #include #include #include @@ -33,8 +18,6 @@ #include #include -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), +};