1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#if 0
27#define DEBUG
28#endif
29
30#include <common.h>
31#include <i2c.h>
32#include <command.h>
33#include <post.h>
34#include <serial.h>
35#include <malloc.h>
36
37#include <linux/types.h>
38#include <linux/string.h>
39
40DECLARE_GLOBAL_DATA_PTR;
41
42static void kbd_init (void);
43static int compare_magic (uchar *kbd_data, uchar *str);
44
45
46#define _NOT_USED_ 0xFFFFFFFF
47
48
49#define DSPIC_PON_STATUS_REG 0x80A
50#define DSPIC_PON_INV_STATUS_REG 0x80C
51#define DSPIC_PON_KEY_REG 0x810
52
53
54#define KEYBD_CMD_READ_KEYS 0x01
55#define KEYBD_CMD_READ_VERSION 0x02
56#define KEYBD_CMD_READ_STATUS 0x03
57#define KEYBD_CMD_RESET_ERRORS 0x10
58
59
60#define KEYBD_STATUS_MASK 0x3F
61#define KEYBD_STATUS_H_RESET 0x20
62#define KEYBD_STATUS_BROWNOUT 0x10
63#define KEYBD_STATUS_WD_RESET 0x08
64#define KEYBD_STATUS_OVERLOAD 0x04
65#define KEYBD_STATUS_ILLEGAL_WR 0x02
66#define KEYBD_STATUS_ILLEGAL_RD 0x01
67
68
69#define KEYBD_VERSIONLEN 2
70
71
72
73
74
75
76
77#define KEYBD_DATALEN 6
78
79
80
81static uchar kbd_addr = CONFIG_SYS_I2C_KEYBD_ADDR;
82static uchar dspic_addr = CONFIG_SYS_I2C_DSPIC_IO_ADDR;
83
84static uchar *key_match (uchar *);
85
86#define KEYBD_SET_DEBUGMODE '#'
87
88
89
90
91
92
93
94
95
96
97
98
99
100int board_postclk_init (void)
101{
102 kbd_init();
103
104 return (0);
105}
106
107static void kbd_init (void)
108{
109 uchar kbd_data[KEYBD_DATALEN];
110 uchar tmp_data[KEYBD_DATALEN];
111 uchar val, errcd;
112 int i;
113
114 i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
115
116 gd->arch.kbd_status = 0;
117
118
119 udelay(1000);
120
121
122 val = KEYBD_CMD_READ_STATUS;
123 i2c_write (kbd_addr, 0, 0, &val, 1);
124 i2c_read (kbd_addr, 0, 0, &errcd, 1);
125
126 errcd &= KEYBD_STATUS_MASK;
127
128 errcd &= ~(KEYBD_STATUS_H_RESET|KEYBD_STATUS_BROWNOUT);
129 if (errcd) {
130 gd->arch.kbd_status |= errcd << 8;
131 }
132
133 val = KEYBD_CMD_RESET_ERRORS;
134 i2c_write (kbd_addr, 0, 0, &val, 1);
135 udelay(1000);
136
137 val = KEYBD_CMD_READ_STATUS;
138 i2c_write (kbd_addr, 0, 0, &val, 1);
139 i2c_read (kbd_addr, 0, 0, &val, 1);
140
141 val &= KEYBD_STATUS_MASK;
142 if (val) {
143 gd->arch.kbd_status |= val;
144 return;
145 }
146
147
148
149
150
151
152
153
154
155
156
157
158
159 memset (tmp_data, 0xFF, KEYBD_DATALEN);
160 for (i=0; i<10; ++i) {
161 val = KEYBD_CMD_READ_KEYS;
162 i2c_write (kbd_addr, 0, 0, &val, 1);
163 i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN);
164
165 if (memcmp(kbd_data, tmp_data, KEYBD_DATALEN) == 0) {
166
167 break;
168 }
169
170 memcpy (tmp_data, kbd_data, KEYBD_DATALEN);
171 udelay (5000);
172 }
173}
174
175
176
177int _dspic_read(ushort reg, ushort *data)
178{
179 uchar buf[sizeof(*data)];
180 int rval;
181
182 if (i2c_read(dspic_addr, reg, 2, buf, 2))
183 return -1;
184
185 rval = i2c_read(dspic_addr, reg, sizeof(reg), buf, sizeof(*data));
186 *data = (buf[0] << 8) | buf[1];
187
188 return rval;
189}
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215int misc_init_r_kbd (void)
216{
217 uchar kbd_data[KEYBD_DATALEN];
218 char keybd_env[2 * KEYBD_DATALEN + 1];
219 uchar kbd_init_status = gd->arch.kbd_status >> 8;
220 uchar kbd_status = gd->arch.kbd_status;
221 uchar val;
222 ushort data, inv_data;
223 char *str;
224 int i;
225
226 if (kbd_init_status) {
227 printf ("KEYBD: Error %02X\n", kbd_init_status);
228 }
229 if (kbd_status) {
230 printf ("*** Keyboard error code %02X ***\n", kbd_status);
231 sprintf (keybd_env, "%02X", kbd_status);
232 setenv ("keybd", keybd_env);
233 return 0;
234 }
235
236
237
238
239
240
241 if ((console_assign (stdout, "serial") < 0) ||
242 (console_assign (stderr, "serial") < 0)) {
243 printf ("Can't assign serial port as output device\n");
244 }
245
246
247 val = KEYBD_CMD_READ_VERSION;
248 i2c_write (kbd_addr, 0, 0, &val, 1);
249 i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_VERSIONLEN);
250 printf ("KEYBD: Version %d.%d\n", kbd_data[0], kbd_data[1]);
251
252
253 val = KEYBD_CMD_READ_KEYS;
254 i2c_write (kbd_addr, 0, 0, &val, 1);
255 i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN);
256
257
258 _dspic_read(DSPIC_PON_STATUS_REG, &data);
259
260 if (data > 0xFF) {
261 _dspic_read(DSPIC_PON_INV_STATUS_REG, &inv_data);
262
263
264 if ((data+inv_data) == 0xFFFF) {
265
266 if (kbd_data[1] == 0) {
267
268 _dspic_read(DSPIC_PON_KEY_REG, &data);
269 str = (char *)&data;
270
271 kbd_data[1] = str[1];
272 kbd_data[2] = str[0];
273 printf("CAN received startkey: 0x%X\n", data);
274 }
275 }
276 }
277
278 for (i = 0; i < KEYBD_DATALEN; ++i) {
279 sprintf (keybd_env + i + i, "%02X", kbd_data[i]);
280 }
281
282 setenv ("keybd", keybd_env);
283
284 str = strdup ((char *)key_match (kbd_data));
285#ifdef KEYBD_SET_DEBUGMODE
286 if (kbd_data[0] == KEYBD_SET_DEBUGMODE) {
287 if ((console_assign (stdout, "lcd") < 0) ||
288 (console_assign (stderr, "lcd") < 0)) {
289 printf ("Can't assign LCD display as output device\n");
290 }
291 }
292#endif
293#ifdef CONFIG_PREBOOT
294 setenv ("preboot", str);
295#endif
296 if (str != NULL) {
297 free (str);
298 }
299 return (0);
300}
301
302#ifdef CONFIG_PREBOOT
303
304static uchar kbd_magic_prefix[] = "key_magic";
305static uchar kbd_command_prefix[] = "key_cmd";
306
307static int compare_magic (uchar *kbd_data, uchar *str)
308{
309 uchar compare[KEYBD_DATALEN-1];
310 char *nxt;
311 int i;
312
313
314 memcpy (compare, kbd_data+1, KEYBD_DATALEN-1);
315
316 for (; str != NULL; str = (*nxt) ? (uchar *)(nxt+1) : (uchar *)nxt) {
317 uchar c;
318 int k;
319
320 c = (uchar) simple_strtoul ((char *)str, (char **) (&nxt), 16);
321
322 if (str == (uchar *)nxt) {
323 break;
324 }
325
326
327
328
329
330
331 for (k = 0; k < sizeof(compare); ++k) {
332 if (compare[k] == '\0')
333 continue;
334 if (c == compare[k]) {
335 compare[k] = '\0';
336 break;
337 }
338 }
339 if (k == sizeof(compare)) {
340 return -1;
341 }
342 }
343
344
345
346
347 for (i = 0; i < sizeof(compare); ++i) {
348 if (compare[i])
349 {
350 return -1;
351 }
352 }
353
354 return 0;
355}
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384static uchar *key_match (uchar *kbd_data)
385{
386 char magic[sizeof (kbd_magic_prefix) + 1];
387 uchar *suffix;
388 char *kbd_magic_keys;
389
390
391
392
393
394
395
396
397
398 if ((kbd_magic_keys = getenv ("magic_keys")) == NULL)
399 kbd_magic_keys = "";
400
401
402
403
404 for (suffix=(uchar *)kbd_magic_keys; *suffix || suffix==(uchar *)kbd_magic_keys; ++suffix) {
405 sprintf (magic, "%s%c", kbd_magic_prefix, *suffix);
406 debug ("### Check magic \"%s\"\n", magic);
407 if (compare_magic(kbd_data, (uchar *)getenv(magic)) == 0) {
408 char cmd_name[sizeof (kbd_command_prefix) + 1];
409 char *cmd;
410
411 sprintf (cmd_name, "%s%c", kbd_command_prefix, *suffix);
412
413 cmd = getenv (cmd_name);
414 debug ("### Set PREBOOT to $(%s): \"%s\"\n",
415 cmd_name, cmd ? cmd : "<<NULL>>");
416 *kbd_data = *suffix;
417 return ((uchar *)cmd);
418 }
419 }
420 debug ("### Delete PREBOOT\n");
421 *kbd_data = '\0';
422 return (NULL);
423}
424#endif
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452int do_kbd (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
453{
454 uchar kbd_data[KEYBD_DATALEN];
455 char keybd_env[2 * KEYBD_DATALEN + 1];
456 uchar val;
457 int i;
458
459#if 0
460 i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
461#endif
462
463
464 val = KEYBD_CMD_READ_KEYS;
465 i2c_write (kbd_addr, 0, 0, &val, 1);
466 i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN);
467
468 puts ("Keys:");
469 for (i = 0; i < KEYBD_DATALEN; ++i) {
470 sprintf (keybd_env + i + i, "%02X", kbd_data[i]);
471 printf (" %02x", kbd_data[i]);
472 }
473 putc ('\n');
474 setenv ("keybd", keybd_env);
475 return 0;
476}
477
478U_BOOT_CMD(
479 kbd, 1, 1, do_kbd,
480 "read keyboard status",
481 ""
482);
483
484
485
486#ifdef CONFIG_POST
487
488
489
490
491int post_hotkeys_pressed(void)
492{
493 uchar kbd_data[KEYBD_DATALEN];
494 uchar val;
495
496
497 val = KEYBD_CMD_READ_KEYS;
498 i2c_write (kbd_addr, 0, 0, &val, 1);
499 i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN);
500
501 return (compare_magic(kbd_data, (uchar *)CONFIG_POST_KEY_MAGIC) == 0);
502}
503#endif
504