/* * (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 DECLARE_GLOBAL_DATA_PTR; #define DEVNAME "tegra-kbc" enum { KBC_MAX_GPIO = 24, KBC_MAX_KPENT = 8, }; #define KBC_MAX_KEY (KBC_MAX_ROW * KBC_MAX_COL) #define TEGRA2_KBC_BASE 0x7000E200 /* KBC row scan time and delay for beginning the row scan. */ #define KBC_ROW_SCAN_TIME 16 #define KBC_ROW_SCAN_DLY 5 /* uses a 32KHz clock so a cycle = 1/32Khz */ #define KBC_CYCLE_IN_USEC DIV_ROUND_UP(1000, 32) #define KBC_FIFO_TH_CNT_SHIFT(cnt) (cnt << 14) #define KBC_DEBOUNCE_CNT_SHIFT(cnt) (cnt << 4) #define KBC_CONTROL_FIFO_CNT_INT_EN (1 << 3) #define KBC_CONTROL_KBC_EN (1 << 0) #define KBC_INT_FIFO_CNT_INT_STATUS (1 << 2) #define KBC_KPENT_VALID (1 << 7) #define KBC_RPT_DLY 20 #define KBC_RPT_RATE 4 /* kbc globals */ static unsigned int kbc_repoll_time; static unsigned int kbc_init_dly; static unsigned long kbc_start_time; /* * Use a simple FIFO to convert some keys into escape sequences and to handle * testc vs getc. The FIFO length must be a power of two. Currently, four * characters is the smallest power of two that is large enough to contain all * generated escape sequences. */ #define KBC_FIFO_LENGTH (1 << 2) static int kbc_fifo[KBC_FIFO_LENGTH]; static int kbc_fifo_read; static int kbc_fifo_write; /* These are key maps for each modifier: each has KBC_KEY_COUNT entries */ u8 *kbc_plain_keycode; u8 *kbc_fn_keycode; u8 *kbc_shift_keycode; u8 *kbc_ctrl_keycode; #ifdef CONFIG_OF_CONTROL struct fdt_kbc config; /* Our keyboard config */ #if (FDT_KBC_KEY_COUNT) != (KBC_KEY_COUNT) #error definition mismatch #endif #endif static int tegra_kbc_keycode(int r, int c, int modifier) { int entry = r * KBC_MAX_COL + c; if (modifier == KEY_FN) return kbc_fn_keycode[entry]; /* Put ctrl keys ahead of shift */ else if ((modifier == KEY_LEFT_CTRL || modifier == KEY_RIGHT_CTRL) && kbc_ctrl_keycode) return kbc_ctrl_keycode[entry]; else if (modifier == KEY_SHIFT) return kbc_shift_keycode[entry]; else return kbc_plain_keycode[entry]; } /* determines if current keypress configuration can cause key ghosting */ static int is_ghost_key_config(int *rows_val, int *cols_val, int valid) { int i, j, key_in_same_col = 0, key_in_same_row = 0; /* * Matrix keyboard designs are prone to keyboard ghosting. * Ghosting occurs if there are 3 keys such that - * any 2 of the 3 keys share a row, and any 2 of them share a column. */ for (i = 0; i < valid; i++) { /* * Find 2 keys such that one key is in the same row * and the other is in the same column as the i-th key. */ for (j = i + 1; j < valid; j++) { if (cols_val[j] == cols_val[i]) key_in_same_col = 1; if (rows_val[j] == rows_val[i]) key_in_same_row = 1; } } if (key_in_same_col && key_in_same_row) return 1; else return 0; } /* reads the keyboard fifo for current keypresses. */ static int tegra_kbc_find_keys(int *fifo) { struct kbc_tegra *kbc = (struct kbc_tegra *)TEGRA2_KBC_BASE; int rows_val[KBC_MAX_KPENT], cols_val[KBC_MAX_KPENT]; u32 kp_ent_val[(KBC_MAX_KPENT + 3) / 4]; u32 *kp_ents = kp_ent_val; u32 kp_ent = 0; int i, j, k, valid = 0; int modifier = 0; for (i = 0; i < ARRAY_SIZE(kp_ent_val); i++) kp_ent_val[i] = readl(&kbc->kp_ent[i]); valid = 0; for (i = 0; i < KBC_MAX_KPENT; i++) { if (!(i&3)) kp_ent = *kp_ents++; if (kp_ent & KBC_KPENT_VALID) { cols_val[valid] = kp_ent & 0x7; rows_val[valid++] = (kp_ent >> 3) & 0xf; } kp_ent >>= 8; } for (i = 0; i < valid; i++) { k = tegra_kbc_keycode(rows_val[i], cols_val[i], 0); if (KEY_IS_MODIFIER(k)) { modifier = k; break; } } /* For a ghost key config, ignore the keypresses for this iteration. */ if ((valid >= 3) && is_ghost_key_config(rows_val, cols_val, valid)) return KBC_MAX_KPENT + 1; j = 0; for (i = 0; i < valid; i++) { k = tegra_kbc_keycode(rows_val[i], cols_val[i], modifier); /* Key modifiers (Fn and Shift) will not be part of the fifo */ if (k && (k != -1)) fifo[j++] = k; } return j; } /* processes all the keypresses in fifo and returns a single key */ static int tegra_kbc_get_single_char(u32 fifo_cnt) { int i, cnt, j; int fifo[KBC_MAX_KPENT] = {0}; static int prev_fifo[KBC_MAX_KPENT]; static int prev_cnt; static int prev_key; char key = 0; if (fifo_cnt) { do { cnt = tegra_kbc_find_keys(fifo); /* If this is a ghost key combination report no change. */ key = prev_key; if (cnt <= KBC_MAX_KPENT) { int prev_key_in_fifo = 0; /* * If multiple keys are pressed such that it * results in * 2 or more unmodified keys, we * will determine the newest key and report * that to the upper layer. */ for (i = 0; i < cnt; i++) { for (j = 0; j < prev_cnt; j++) { if (fifo[i] == prev_fifo[j]) break; } /* Found a new key. */ if (j == prev_cnt) { key = fifo[i]; break; } if (prev_key == fifo[i]) prev_key_in_fifo = 1; } /* * Keys were released and FIFO does not contain * the previous reported key. So report a null * key. */ if (i == cnt && !prev_key_in_fifo) key = 0; for (i = 0; i < cnt; i++) prev_fifo[i] = fifo[i]; prev_cnt = cnt; prev_key = key; } } while (!key && --fifo_cnt); } else { prev_cnt = 0; prev_key = 0; } udelay((fifo_cnt == 1) ? kbc_repoll_time : 1000); return key; } /* manages keyboard hardware registers on keypresses and returns a key.*/ static unsigned char tegra_kbc_get_char(void) { struct kbc_tegra *kbc = (struct kbc_tegra *)TEGRA2_KBC_BASE; u32 val, ctl; char key = 0; /* * Until all keys are released, defer further processing to * the polling loop. */ ctl = readl(&kbc->control); ctl &= ~KBC_CONTROL_FIFO_CNT_INT_EN; writel(ctl, &kbc->control); /* * Quickly bail out & reenable interrupts if the interrupt source * wasn't fifo count threshold */ val = readl(&kbc->interrupt); writel(val, &kbc->interrupt); if (val & KBC_INT_FIFO_CNT_INT_STATUS) key = tegra_kbc_get_single_char((val >> 4) & 0xf); ctl |= KBC_CONTROL_FIFO_CNT_INT_EN; writel(ctl, &kbc->control); return key; } /* handles key repeat delay and key repeat rate.*/ static int kbd_fetch_char(int test) { unsigned char key; static unsigned char prev_key; static unsigned int rpt_dly = KBC_RPT_DLY; do { key = tegra_kbc_get_char(); if (!key) { prev_key = 0; if (test) break; else continue; } /* This logic takes care of the repeat rate */ if ((key != prev_key) || !(rpt_dly--)) break; } while (1); if (key == prev_key) { rpt_dly = KBC_RPT_RATE; } else { rpt_dly = KBC_RPT_DLY; prev_key = key; } return key; } /* * Return true if there are no characters in the FIFO. */ static int kbd_fifo_empty(void) { return kbc_fifo_read == kbc_fifo_write; } /* * Return number of characters of free space in the FIFO. */ static int kbd_fifo_free_space(void) { return KBC_FIFO_LENGTH - (kbc_fifo_write - kbc_fifo_read); } /* * Insert a character into the FIFO. Calling this function when the FIFO is * full will overwrite the oldest character in the FIFO. */ static void kbd_fifo_insert(int key) { int index = kbc_fifo_write & (KBC_FIFO_LENGTH - 1); assert(kbd_fifo_free_space() > 0); kbc_fifo[index] = key; kbc_fifo_write++; } /* * Remove a character from the FIFO, it is an error to call this function when * the FIFO is empty. */ static int kbd_fifo_remove(void) { int index = kbc_fifo_read & (KBC_FIFO_LENGTH - 1); int key = kbc_fifo[index]; assert(!kbd_fifo_empty()); kbc_fifo_read++; return key; } /* * Given a keycode, convert it to the sequence of characters that U-Boot expects * to recieve from its input devices and insert the characters into the FIFO. * If the keycode is 0, ignore it. Currently this function will only ever add * at most three characters to the FIFO, so it is always safe to call when the * FIFO is empty. */ static void kbd_fifo_refill(int key) { switch (key) { /* * We need to deal with a zero keycode value here because the * testc call can call us with zero if no key is pressed. */ case 0x00: break; /* * Generate escape sequences for arrow keys. Additional escape * sequences can be added to the switch statements, but it may * be better in the future t0 use the top bit of the keycode to * indicate a key that generates an escape sequence. Then the * outer switch could turn into an "if (key & 0x80)". */ case 0x1C: case 0x1D: case 0x1E: case 0x1F: kbd_fifo_insert(0x1B); /* Escape */ kbd_fifo_insert('['); switch (key) { case 0x1C: kbd_fifo_insert('D'); break; case 0x1D: kbd_fifo_insert('C'); break; case 0x1E: kbd_fifo_insert('A'); break; case 0x1F: kbd_fifo_insert('B'); break; } break; /* * All other keycodes can be treated as characters as is and * are inserted into the FIFO directly. */ default: kbd_fifo_insert(key); break; } } static void kbd_wait_for_fifo_init(void) { unsigned long elapsed_time; long delay; static unsigned int kbc_initialized; if (kbc_initialized) return; /* * In order to detect keys pressed on boot, wait for the hardware to * complete scanning the keys. This includes time to transition from * Wkup mode to Continous polling mode and the repoll time. We can * deduct the time thats already elapsed. */ elapsed_time = timer_get_us() - kbc_start_time; delay = kbc_init_dly + kbc_repoll_time - elapsed_time; if (delay > 0) udelay(delay); kbc_initialized = 1; } static int kbd_testc(void) { kbd_wait_for_fifo_init(); if (kbd_fifo_empty()) kbd_fifo_refill(kbd_fetch_char(1)); return !kbd_fifo_empty(); } static int kbd_getc(void) { if (kbd_fifo_empty()) kbd_fifo_refill(kbd_fetch_char(0)); return kbd_fifo_remove(); } /* configures keyboard GPIO registers to use the rows and columns */ static void config_kbc(void) { struct kbc_tegra *kbc = (struct kbc_tegra *)TEGRA2_KBC_BASE; int i; for (i = 0; i < KBC_MAX_GPIO; i++) { u32 row_cfg, col_cfg; u32 r_shift = 5 * (i % 6); u32 c_shift = 4 * (i % 8); u32 r_mask = 0x1f << r_shift; u32 c_mask = 0xf << c_shift; u32 r_offs = i / 6; u32 c_offs = i / 8; row_cfg = readl(&kbc->row_cfg[r_offs]); col_cfg = readl(&kbc->col_cfg[c_offs]); row_cfg &= ~r_mask; col_cfg &= ~c_mask; if (i < KBC_MAX_ROW) row_cfg |= ((i << 1) | 1) << r_shift; else col_cfg |= (((i - KBC_MAX_ROW) << 1) | 1) << c_shift; writel(row_cfg, &kbc->row_cfg[r_offs]); writel(col_cfg, &kbc->col_cfg[c_offs]); } } static int tegra_kbc_open(void) { struct kbc_tegra *kbc = (struct kbc_tegra *)TEGRA2_KBC_BASE; unsigned int scan_time_rows, debounce_cnt, rpt_cnt; u32 val = 0; config_kbc(); /* * The time delay between two consecutive reads of the FIFO is * the sum of the repeat time and the time taken for scanning * the rows. There is an additional delay before the row scanning * starts. The repoll delay is computed in microseconds. */ rpt_cnt = 5 * DIV_ROUND_UP(1000, KBC_CYCLE_IN_USEC); debounce_cnt = 2; scan_time_rows = (KBC_ROW_SCAN_TIME + debounce_cnt) * KBC_MAX_ROW; kbc_repoll_time = KBC_ROW_SCAN_DLY + scan_time_rows + rpt_cnt; kbc_repoll_time = kbc_repoll_time * KBC_CYCLE_IN_USEC; writel(rpt_cnt, &kbc->rpt_dly); val = KBC_DEBOUNCE_CNT_SHIFT(debounce_cnt); val |= KBC_FIFO_TH_CNT_SHIFT(1); /* set fifo interrupt threshold to 1 */ val |= KBC_CONTROL_FIFO_CNT_INT_EN; /* interrupt on FIFO threshold */ val |= KBC_CONTROL_KBC_EN; /* enable */ writel(val, &kbc->control); kbc_init_dly = readl(&kbc->init_dly) * KBC_CYCLE_IN_USEC; kbc_start_time = timer_get_us(); return 0; } void config_kbc_pinmux(void) { enum pmux_pingrp pingrp[] = {PINGRP_KBCA, PINGRP_KBCB, PINGRP_KBCC, PINGRP_KBCD, PINGRP_KBCE, PINGRP_KBCF}; int i; for (i = 0; i < (sizeof(pingrp)/sizeof(pingrp[0])); i++) { pinmux_tristate_disable(pingrp[i]); pinmux_set_func(pingrp[i], PMUX_FUNC_KBC); pinmux_set_pullupdown(pingrp[i], PMUX_PULL_UP); } } int drv_keyboard_init(void) { int error; struct stdio_dev kbddev; char *stdinname; #ifdef CONFIG_OF_CONTROL int node; node = fdt_decode_next_compatible(gd->blob, 0, COMPAT_NVIDIA_TEGRA250_KBC); if (node < 0) return node; if (fdt_decode_kbc(gd->blob, node, &config)) return -1; kbc_plain_keycode = config.plain_keycode; kbc_shift_keycode = config.shift_keycode; kbc_fn_keycode = config.fn_keycode; kbc_ctrl_keycode = config.ctrl_keycode; #else kbc_plain_keycode = board_keyboard_config.plain_keycode; kbc_shift_keycode = board_keyboard_config.shift_keycode; kbc_fn_keycode = board_keyboard_config.fn_keycode; #endif config_kbc_pinmux(); /* * All of the Tegra board use the same clock configuration for now. * This can be moved to the board specific configuration if that * changes. */ clock_enable(PERIPH_ID_KBC); stdinname = getenv("stdin"); memset(&kbddev, 0, sizeof(kbddev)); strcpy(kbddev.name, DEVNAME); kbddev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; kbddev.putc = NULL; kbddev.puts = NULL; kbddev.getc = kbd_getc; kbddev.tstc = kbd_testc; kbddev.start = tegra_kbc_open; error = stdio_register(&kbddev); if (!error) { /* check if this is the standard input device */ if (strcmp(stdinname, DEVNAME) == 0) { /* reassign the console */ if (OVERWRITE_CONSOLE) return 1; error = console_assign(stdin, DEVNAME); if (!error) return 0; else return error; } return 1; } return error; }