OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * (C) Copyright 2010 |
| 3 * NVIDIA Corporation <www.nvidia.com> |
| 4 * |
| 5 * See file CREDITS for list of people who contributed to this |
| 6 * project. |
| 7 * |
| 8 * This program is free software; you can redistribute it and/or |
| 9 * modify it under the terms of the GNU General Public License as |
| 10 * published by the Free Software Foundation; either version 2 of |
| 11 * the License, or (at your option) any later version. |
| 12 * |
| 13 * This program is distributed in the hope that it will be useful, |
| 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 * GNU General Public License for more details. |
| 17 * |
| 18 * You should have received a copy of the GNU General Public License |
| 19 * along with this program; if not, write to the Free Software |
| 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
| 21 * MA 02111-1307 USA |
| 22 */ |
| 23 |
| 24 #include <common.h> |
| 25 #include <malloc.h> |
| 26 #include <stdio_dev.h> |
| 27 |
| 28 #define DEVNAME "tegra-kbc" |
| 29 |
| 30 #define KBC_MAX_GPIO 24 |
| 31 #define KBC_MAX_KPENT 8 |
| 32 #define KBC_MAX_ROW 16 |
| 33 #define KBC_MAX_COL 8 |
| 34 |
| 35 #define KBC_MAX_KEY (KBC_MAX_ROW*KBC_MAX_COL) |
| 36 |
| 37 #define TEGRA_KBC_BASE 0x7000E200 |
| 38 |
| 39 #define KBC_CONTROL_0 0 |
| 40 #define KBC_INT_0 4 |
| 41 #define KBC_ROW_CFG0_0 8 |
| 42 #define KBC_COL_CFG0_0 0x18 |
| 43 #define KBC_RPT_DLY_0 0x2c |
| 44 #define KBC_KP_ENT0_0 0x30 |
| 45 #define KBC_KP_ENT1_0 0x34 |
| 46 #define KBC_ROW0_MASK_0 0x38 |
| 47 |
| 48 #define KBC_RPT_DLY 20 |
| 49 #define KBC_RPT_RATE 4 |
| 50 |
| 51 #define readl(addr) (*(volatile unsigned int *)(addr)) |
| 52 #define writel(b, addr) ((*(volatile unsigned int *) (addr)) = (b)) |
| 53 #define kbc_readl(addr) readl(TEGRA_KBC_BASE + addr) |
| 54 #define kbc_writel(b, addr) writel(b, TEGRA_KBC_BASE + addr) |
| 55 |
| 56 /* Define function and shift keys to untypable ASCII values */ |
| 57 #define KEY_FN 222 |
| 58 #define KEY_SHIFT 223 |
| 59 |
| 60 #ifdef CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE |
| 61 extern int overwrite_console(void); |
| 62 #define OVERWRITE_CONSOLE overwrite_console() |
| 63 #else |
| 64 #define OVERWRITE_CONSOLE 0 |
| 65 #endif /* CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE */ |
| 66 |
| 67 extern void config_kbc_pinmux(void); |
| 68 extern void config_kbc_clock(void); |
| 69 |
| 70 enum bool {false = 0, true = 1}; |
| 71 |
| 72 struct tegra_kbc { |
| 73 void *mmio; |
| 74 unsigned int repoll_time; |
| 75 unsigned int debounce_cnt; |
| 76 unsigned int rpt_cnt; |
| 77 int *plain_keycode; |
| 78 int *fn_keycode; |
| 79 int *shift_keycode; |
| 80 }; |
| 81 |
| 82 struct tegra_kbc *kbc; |
| 83 |
| 84 static int plain_kbd_keycode[] = { |
| 85 0, 0, 'w', 's', 'a', 'z', 0, KEY_FN, |
| 86 0, 0, 0, 0, 0, 0, 0, 0, |
| 87 0, 0, 0, 0, 0, 0, 0, 0, |
| 88 '5', '4', 'r', 'e', 'f', 'd', 'x', 0, |
| 89 '7', '6', 't', 'h', 'g', 'v', 'c', ' ', |
| 90 '9', '8', 'u', 'y', 'j', 'n', 'b', '\\', |
| 91 '-', '0', 'o', 'i', 'l', 'k', ',', 'm', |
| 92 0, '=', ']', '\r', 0, 0, 0, 0, |
| 93 0, 0, 0, 0, KEY_SHIFT, KEY_SHIFT, 0, 0, |
| 94 0, 0, 0, 0, 0, 0, 0, 0, |
| 95 0, 0, 0, 0, 0, 0, 0, 0, |
| 96 '[', 'p', '\'', ';', '/', '.', 0, 0, |
| 97 0, 0, 0x08, '3', '2', 0, 0, 0, |
| 98 0, 0x7F, 0, 0, 0, 0, 0, 0, |
| 99 0, 0, 0, 'q', 0, 0, '1', 0, |
| 100 0x1B, '`', 0, 0x9, 0, 0, 0, 0 |
| 101 }; |
| 102 |
| 103 static int shift_kbd_keycode[] = { |
| 104 0, 0, 'W', 'S', 'A', 'Z', 0, 0, |
| 105 0, 0, 0, 0, 0, 0, 0, 0, |
| 106 0, 0, 0, 0, 0, 0, 0, 0, |
| 107 '%', '$', 'R', 'E', 'F', 'D', 'X', 0, |
| 108 '&', '^', 'T', 'H', 'G', 'V', 'C', ' ', |
| 109 '(', '*', 'U', 'Y', 'J', 'N', 'B', '|', |
| 110 '_', ')', 'O', 'I', 'L', 'K', ',', 'M', |
| 111 0, '+', '}', '\r', 0, 0, 0, 0, |
| 112 0, 0, 0, 0, 0, 0, 0, 0, |
| 113 0, 0, 0, 0, 0, 0, 0, 0, |
| 114 0, 0, 0, 0, 0, 0, 0, 0, |
| 115 '{', 'P', '"', ':', '?', '>', 0, 0, |
| 116 0, 0, 0x08, '#', '@', 0, 0, 0, |
| 117 0, 0x7F, 0, 0, 0, 0, 0, 0, |
| 118 0, 0, 0, 'Q', 0, 0, '!', 0, |
| 119 0x1B, '~', 0, 0x9, 0, 0, 0, 0 |
| 120 }; |
| 121 |
| 122 static int fn_kbd_keycode[] = { |
| 123 0, 0, 0, 0, 0, 0, 0, 0, |
| 124 0, 0, 0, 0, 0, 0, 0, 0, |
| 125 0, 0, 0, 0, 0, 0, 0, 0, |
| 126 0, 0, 0, 0, 0, 0, 0, 0, |
| 127 '7', 0, 0, 0, 0, 0, 0, 0, |
| 128 '9', '8', '4', 0, '1', 0, 0, 0, |
| 129 0, '/', '6', '5', '3', '2', 0, '0', |
| 130 0, 0, 0, 0, 0, 0, 0, 0, |
| 131 0, 0, 0, 0, 0, 0, 0, 0, |
| 132 0, 0, 0, 0, 0, 0, 0, 0, |
| 133 0, 0, 0, 0, 0, 0, 0, 0, |
| 134 0, '\'', 0, '-', '+', '.', 0, 0, |
| 135 0, 0, 0, 0, 0, 0, 0, 0, |
| 136 0, 0, 0, 0, 0, 0, 0, 0, |
| 137 0, 0, 0, 0, 0, 0, 0, 0, |
| 138 0, 0, 0, 0, '?', 0, 0, 0 |
| 139 }; |
| 140 |
| 141 void msleep(int a) |
| 142 { |
| 143 int i; |
| 144 |
| 145 for (i = 0; i < a; i++) |
| 146 udelay(1000); |
| 147 } |
| 148 |
| 149 static int tegra_kbc_keycode(struct tegra_kbc *kbc, int r, int c, int spl_key) |
| 150 { |
| 151 if (spl_key == KEY_FN) |
| 152 return kbc->fn_keycode[(r * KBC_MAX_COL) + c]; |
| 153 else if (spl_key == KEY_SHIFT) |
| 154 return kbc->shift_keycode[(r * KBC_MAX_COL) + c]; |
| 155 else |
| 156 return kbc->plain_keycode[(r * KBC_MAX_COL) + c]; |
| 157 } |
| 158 |
| 159 static int tegra_kbc_find_keys(int *fifo) |
| 160 { |
| 161 int rows_val[KBC_MAX_KPENT], cols_val[KBC_MAX_KPENT]; |
| 162 u32 kp_ent_val[(KBC_MAX_KPENT + 3) / 4]; |
| 163 u32 *kp_ents = kp_ent_val; |
| 164 u32 kp_ent = 0; |
| 165 int i, j, valid = 0; |
| 166 int spl = 0; |
| 167 |
| 168 for (i = 0; i < ARRAY_SIZE(kp_ent_val); i++) |
| 169 kp_ent_val[i] = kbc_readl(KBC_KP_ENT0_0 + (i*4)); |
| 170 |
| 171 valid = 0; |
| 172 for (i = 0; i < KBC_MAX_KPENT; i++) { |
| 173 if (!(i&3)) |
| 174 kp_ent = *kp_ents++; |
| 175 |
| 176 if (kp_ent & 0x80) { |
| 177 cols_val[valid] = kp_ent & 0x7; |
| 178 rows_val[valid++] = (kp_ent >> 3) & 0xf; |
| 179 } |
| 180 kp_ent >>= 8; |
| 181 } |
| 182 |
| 183 for (i = 0; i < valid; i++) { |
| 184 int k = tegra_kbc_keycode(kbc, rows_val[i], cols_val[i], 0); |
| 185 if ((k == KEY_FN) || (k == KEY_SHIFT)) { |
| 186 spl = k; |
| 187 break; |
| 188 } |
| 189 } |
| 190 |
| 191 j = 0; |
| 192 for (i = 0; i < valid; i++) { |
| 193 int k = tegra_kbc_keycode(kbc, rows_val[i], cols_val[i], spl); |
| 194 if (k != -1) |
| 195 fifo[j++] = k; |
| 196 } |
| 197 |
| 198 return j; |
| 199 } |
| 200 |
| 201 static unsigned char tegra_kbc_get_char(void) |
| 202 { |
| 203 u32 val, ctl; |
| 204 int fifo[KBC_MAX_KPENT], i, cnt; |
| 205 char c = 0; |
| 206 |
| 207 for (i = 0; i < KBC_MAX_KPENT; i++) |
| 208 fifo[i] = 0; |
| 209 |
| 210 /* until all keys are released, defer further processing to |
| 211 * the polling loop in tegra_kbc_key_repeat */ |
| 212 ctl = kbc_readl(KBC_CONTROL_0); |
| 213 ctl &= ~(1<<3); |
| 214 kbc_writel(ctl, KBC_CONTROL_0); |
| 215 |
| 216 /* quickly bail out & reenable interrupts if the interrupt source |
| 217 * wasn't fifo count threshold */ |
| 218 val = kbc_readl(KBC_INT_0); |
| 219 kbc_writel(val, KBC_INT_0); |
| 220 |
| 221 if (!(val & (1<<2))) { |
| 222 ctl |= 1<<3; |
| 223 kbc_writel(ctl, KBC_CONTROL_0); |
| 224 return 0; |
| 225 } |
| 226 |
| 227 val = (val >> 4) & 0xf; |
| 228 if (val) { |
| 229 cnt = tegra_kbc_find_keys(fifo); |
| 230 |
| 231 /* |
| 232 * Get to the firxt non-zero key value in the key fifo. |
| 233 * The FN and Shift keys will appear as zero values. |
| 234 * The U-boot upper layers can accept only one key. |
| 235 */ |
| 236 for (i = 0; i < cnt; i++) { |
| 237 if (fifo[i]) { |
| 238 c = fifo[i]; |
| 239 break; |
| 240 } |
| 241 } |
| 242 } |
| 243 |
| 244 msleep((val == 1) ? kbc->repoll_time : 1); |
| 245 |
| 246 ctl |= (1<<3); |
| 247 kbc_writel(ctl, KBC_CONTROL_0); |
| 248 |
| 249 return c; |
| 250 } |
| 251 |
| 252 static int kbd_fetch_char(int loop) |
| 253 { |
| 254 unsigned char c; |
| 255 static unsigned char prev_c; |
| 256 static unsigned int rpt_dly = KBC_RPT_DLY; |
| 257 |
| 258 do { |
| 259 c = tegra_kbc_get_char(); |
| 260 if (!c) { |
| 261 prev_c = 0; |
| 262 continue; |
| 263 } |
| 264 |
| 265 /* This logic takes care of the repeat rate */ |
| 266 if ((c != prev_c) || !(rpt_dly--)) |
| 267 break; |
| 268 } while (loop); |
| 269 |
| 270 if (c == prev_c) { |
| 271 /* kbc_testc should return 0 to indicate repeat charachters */ |
| 272 if (!loop) |
| 273 c = 0; |
| 274 else |
| 275 rpt_dly = KBC_RPT_RATE; |
| 276 } else { |
| 277 rpt_dly = KBC_RPT_DLY; |
| 278 prev_c = c; |
| 279 } |
| 280 |
| 281 return c; |
| 282 } |
| 283 |
| 284 static int kbd_testc(void) |
| 285 { |
| 286 unsigned char c = kbd_fetch_char(false); |
| 287 |
| 288 return (c != 0); |
| 289 } |
| 290 |
| 291 static int kbd_getc(void) |
| 292 { |
| 293 unsigned char c = kbd_fetch_char(true); |
| 294 |
| 295 return c; |
| 296 } |
| 297 |
| 298 static void config_kbc(void) |
| 299 { |
| 300 int i; |
| 301 |
| 302 for (i = 0; i < KBC_MAX_GPIO; i++) { |
| 303 u32 row_cfg, col_cfg; |
| 304 u32 r_shift = 5 * (i%6); |
| 305 u32 c_shift = 4 * (i%8); |
| 306 u32 r_mask = 0x1f << r_shift; |
| 307 u32 c_mask = 0xf << c_shift; |
| 308 u32 r_offs = (i / 6) * 4 + KBC_ROW_CFG0_0; |
| 309 u32 c_offs = (i / 8) * 4 + KBC_COL_CFG0_0; |
| 310 |
| 311 row_cfg = kbc_readl(r_offs); |
| 312 col_cfg = kbc_readl(c_offs); |
| 313 |
| 314 row_cfg &= ~r_mask; |
| 315 col_cfg &= ~c_mask; |
| 316 |
| 317 if (i < KBC_MAX_ROW) |
| 318 row_cfg |= ((i << 1) | 1) << r_shift; |
| 319 else |
| 320 col_cfg |= (((i - KBC_MAX_ROW) << 1) | 1) << c_shift; |
| 321 |
| 322 kbc_writel(row_cfg, r_offs); |
| 323 kbc_writel(col_cfg, c_offs); |
| 324 } |
| 325 } |
| 326 |
| 327 static int tegra_kbc_open(void) |
| 328 { |
| 329 u32 val = 0; |
| 330 |
| 331 config_kbc(); |
| 332 |
| 333 kbc_writel(kbc->rpt_cnt, KBC_RPT_DLY_0); |
| 334 |
| 335 val = kbc->debounce_cnt << 4; |
| 336 val |= 1<<14; /* fifo interrupt threshold = 1 entry */ |
| 337 val |= 1<<3; /* interrupt on FIFO threshold reached */ |
| 338 val |= 1; /* enable */ |
| 339 kbc_writel(val, KBC_CONTROL_0); |
| 340 |
| 341 /* |
| 342 * atomically clear out any remaining entries in the key FIFO |
| 343 * and enable keyboard interrupts. |
| 344 */ |
| 345 while (1) { |
| 346 val = kbc_readl(KBC_INT_0); |
| 347 val >>= 4; |
| 348 if (val) { |
| 349 val = kbc_readl(KBC_KP_ENT0_0); |
| 350 val = kbc_readl(KBC_KP_ENT1_0); |
| 351 } else { |
| 352 break; |
| 353 } |
| 354 } |
| 355 kbc_writel(0x7, KBC_INT_0); |
| 356 |
| 357 return 0; |
| 358 } |
| 359 |
| 360 int tegra_kbc_init(void) |
| 361 { |
| 362 int error; |
| 363 struct stdio_dev kbddev; |
| 364 char *stdinname; |
| 365 |
| 366 config_kbc_pinmux(); |
| 367 config_kbc_clock(); |
| 368 |
| 369 kbc = malloc(sizeof(*kbc)); |
| 370 if (!kbc) |
| 371 return -1; |
| 372 |
| 373 kbc->debounce_cnt = 2; |
| 374 kbc->rpt_cnt = 5 * 32; |
| 375 kbc->debounce_cnt = min(kbc->debounce_cnt, 0x3fful); |
| 376 kbc->repoll_time = 5 + (16 + kbc->debounce_cnt) * 0x10 + kbc->rpt_cnt; |
| 377 kbc->repoll_time = (kbc->repoll_time + 31) / 32; |
| 378 |
| 379 kbc->plain_keycode = plain_kbd_keycode; |
| 380 kbc->fn_keycode = fn_kbd_keycode; |
| 381 kbc->shift_keycode = shift_kbd_keycode; |
| 382 |
| 383 stdinname = getenv("stdin"); |
| 384 memset(&kbddev, 0, sizeof(kbddev)); |
| 385 strcpy(kbddev.name, DEVNAME); |
| 386 kbddev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; |
| 387 kbddev.putc = NULL; |
| 388 kbddev.puts = NULL; |
| 389 kbddev.getc = kbd_getc; |
| 390 kbddev.tstc = kbd_testc; |
| 391 kbddev.start = tegra_kbc_open; |
| 392 |
| 393 error = stdio_register(&kbddev); |
| 394 if (!error) { |
| 395 /* check if this is the standard input device*/ |
| 396 if (strcmp(stdinname, DEVNAME) == 0) { |
| 397 /* reassign the console */ |
| 398 if (OVERWRITE_CONSOLE) |
| 399 return 1; |
| 400 |
| 401 error = console_assign(stdin, DEVNAME); |
| 402 if (!error) |
| 403 return 0; |
| 404 else |
| 405 return error; |
| 406 } |
| 407 return 1; |
| 408 } |
| 409 |
| 410 return error; |
| 411 } |
| 412 |
OLD | NEW |