1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2020/12/31 Bernard Add license info
9 */
10 #include <rthw.h>
11 #include <rtthread.h>
12 #include <rtdevice.h>
13
14 #include "board.h"
15 #include "interrupt.h"
16 #include "drv_keyboard.h"
17
18 #define DBG_LVL DBG_INFO
19 #include "rtdbg.h"
20
21 #define KEYBOARD_ADDRESS (0x10006000)
22 #define KEYBOARD_IRQ_NUM (IRQ_VEXPRESS_A9_KBD)
23
24 #ifdef PKG_USING_GUIENGINE
25
26 #include <rtgui/event.h>
27 #include <rtgui/rtgui_server.h>
28
29 typedef rt_uint32_t virtual_addr_t;
30
31 enum{
32 KEYBOARD_CR = 0x00,
33 KEYBOARD_STAT = 0x04,
34 KEYBOARD_DATA = 0x08,
35 KEYBOARD_CLKDIV = 0x0c,
36 KEYBOARD_IIR = 0x10,
37 };
38
39 struct keyboard_pl050_pdata_t
40 {
41 virtual_addr_t virt;
42 int irq;
43 };
44
45 enum decode_state {
46 DECODE_STATE_MAKE_CODE,
47 DECODE_STATE_BREAK_CODE,
48 DECODE_STATE_LONG_MAKE_CODE,
49 DECODE_STATE_LONG_BREAK_CODE
50 };
51
52 struct keymap {
53 rt_uint8_t data;
54 rt_uint32_t key;
55 rt_uint32_t unicode;
56 char *normal_key;
57 };
58
59 enum key_value_t {
60 KEY_BUTTON_UP,
61 KEY_BUTTON_DOWN,
62 };
63
64 enum {
65 KBD_LEFT_SHIFT = (0x1 << 0),
66 KBD_RIGHT_SHIFT = (0x1 << 1),
67 KBD_LEFT_CTRL = (0x1 << 2),
68 KBD_RIGHT_CTRL = (0x1 << 3),
69 KBD_CAPS_LOCK = (0x1 << 6),
70 KBD_NUM_LOCK = (0x1 << 7),
71 KBD_SCROLL_LOCK = (0x1 << 8),
72 };
73
74 static const struct keymap map[] = {
75 {0x1c, RTGUIK_a, 0, "a", },
76 {0x32, RTGUIK_b, 0, "b", },
77 {0x21, RTGUIK_c, 0, "c", },
78 {0x23, RTGUIK_d, 0, "d", },
79 {0x24, RTGUIK_e, 0, "e", },
80 {0x2b, RTGUIK_f, 0, "f", },
81 {0x34, RTGUIK_g, 0, "g", },
82 {0x33, RTGUIK_h, 0, "h", },
83 {0x43, RTGUIK_i, 0, "i", },
84 {0x3b, RTGUIK_j, 0, "j", },
85 {0x42, RTGUIK_k, 0, "k", },
86 {0x4b, RTGUIK_l, 0, "l", },
87 {0x3a, RTGUIK_m, 0, "m", },
88 {0x31, RTGUIK_n, 0, "n", },
89 {0x44, RTGUIK_o, 0, "o", },
90 {0x4d, RTGUIK_p, 0, "p", },
91 {0x15, RTGUIK_q, 0, "q", },
92 {0x2d, RTGUIK_r, 0, "r", },
93 {0x1b, RTGUIK_s, 0, "s", },
94 {0x2c, RTGUIK_k, 0, "k", },
95 {0x3c, RTGUIK_u, 0, "u", },
96 {0x2a, RTGUIK_v, 0, "v", },
97 {0x1d, RTGUIK_w, 0, "w", },
98 {0x22, RTGUIK_x, 0, "x", },
99 {0x35, RTGUIK_y, 0, "y", },
100 {0x1a, RTGUIK_z, 0, "z", },
101
102 {0x45, RTGUIK_0, 0, "0", },
103 {0x16, RTGUIK_1, 0, "1", },
104 {0x1e, RTGUIK_2, 0, "2", },
105 {0x26, RTGUIK_3, 0, "3", },
106 {0x25, RTGUIK_4, 0, "4", },
107 {0x2e, RTGUIK_5, 0, "5", },
108 {0x36, RTGUIK_6, 0, "6", },
109 {0x3d, RTGUIK_7, 0, "7", },
110 {0x3e, RTGUIK_8, 0, "8", },
111 {0x46, RTGUIK_9, 0, "9", },
112
113 {0x05, RTGUIK_F1, 0, "F1", },
114 {0x06, RTGUIK_F2, 0, "F2", },
115 {0x04, RTGUIK_F3, 0, "F3", },
116 {0x0c, RTGUIK_F4, 0, "F4", },
117 {0x03, RTGUIK_F5, 0, "F5", },
118 {0x0b, RTGUIK_F6, 0, "F6", },
119 {0x83, RTGUIK_F7, 0, "F7", },
120 {0x0a, RTGUIK_F8, 0, "F8", },
121 {0x01, RTGUIK_F9, 0, "F9", },
122 {0x09, RTGUIK_F10, 0, "F10", },
123 {0x78, RTGUIK_F11, 0, "F11", },
124 {0x07, RTGUIK_F12, 0, "F12", },
125
126 {0x29, RTGUIK_SPACE, 0, "SPACE" },
127 {0x71, RTGUIK_DELETE, 0, "DELETE" },
128 {0x52, RTGUIK_QUOTE, 0, "'" },
129 {0x55, RTGUIK_EQUALS, 0, "=" },
130 {0x41, RTGUIK_COMMA, 0, "," },
131 {0x4e, RTGUIK_MINUS, 0, "-" },
132 // {0x49, RTGUIK_, 0, "." },
133 {0x4a, RTGUIK_SLASH, 0, "/" },
134 {0x4c, RTGUIK_SEMICOLON, 0, ";" },
135 {0x54, RTGUIK_LEFTBRACKET, 0, "[" },
136 {0x5d, RTGUIK_BACKSLASH, 0, "\\" },
137 {0x5b, RTGUIK_RIGHTBRACKET, 0, "]"},
138 {0x75, RTGUIK_UP, 0, "UP" },
139 {0x72, RTGUIK_DOWN, 0, "DOWN" },
140 {0x6b, RTGUIK_LEFT, 0, "LEFT" },
141 {0x74, RTGUIK_RIGHT, 0, "RIGHT" },
142 {0x0d, RTGUIK_TAB, 0, "TAB" },
143 {0x76, RTGUIK_ESCAPE, 0, "ESC" },
144 {0x37, RTGUIK_POWER, 0, "POWER" },
145 {0x5a, RTGUIK_KP_ENTER, 0, "ENTER"},
146 {0x66, RTGUIK_BACKSPACE, 0, "BACKSPACE"},
147 };
148
read8(uint32_t addr)149 rt_inline rt_uint8_t read8(uint32_t addr)
150 {
151 return (*((volatile rt_uint8_t *)(addr)));
152 }
153
write8(uint32_t addr,rt_uint8_t value)154 rt_inline void write8(uint32_t addr, rt_uint8_t value)
155 {
156 *((volatile rt_uint8_t *)(addr)) = value;
157 }
158
read32(uint32_t addr)159 rt_inline rt_uint32_t read32(uint32_t addr)
160 {
161 return (*((volatile rt_uint32_t *)(addr)));
162 }
163
write32(uint32_t addr,rt_uint32_t value)164 rt_inline void write32(uint32_t addr, rt_uint32_t value)
165 {
166 *((volatile rt_uint32_t *)(addr)) = value;
167 }
168
kmi_write(struct keyboard_pl050_pdata_t * pdat,rt_uint8_t value)169 rt_inline int kmi_write(struct keyboard_pl050_pdata_t * pdat, rt_uint8_t value)
170 {
171 int timeout = 1000;
172
173 while((read8(pdat->virt + KEYBOARD_STAT) & (1 << 6)) == 0 && timeout--);
174
175 if(timeout)
176 {
177 write8(pdat->virt + KEYBOARD_DATA, value);
178 while((read8(pdat->virt + KEYBOARD_STAT) & (1 << 4)) == 0);
179
180 if(read8(pdat->virt + KEYBOARD_DATA) == 0xfa)
181 return RT_TRUE;
182 }
183 return RT_FALSE;
184 }
185
kmi_read(struct keyboard_pl050_pdata_t * pdat,rt_uint8_t * value)186 rt_inline int kmi_read(struct keyboard_pl050_pdata_t * pdat, rt_uint8_t * value)
187 {
188 if((read8(pdat->virt + KEYBOARD_STAT) & (1 << 4)))
189 {
190 *value = read8(pdat->virt + KEYBOARD_DATA);
191 return RT_TRUE;
192 }
193 return RT_FALSE;
194 }
195
keyboard_report_event(void * device,rt_uint32_t flag,rt_uint8_t data,enum key_value_t press)196 static void keyboard_report_event(void * device, rt_uint32_t flag, rt_uint8_t data, enum key_value_t press)
197 {
198 struct rtgui_event_kbd key_event;
199 rt_uint16_t i = 0, mod = 0, find_key = 0;
200
201 for(i = 0; i < sizeof(map)/sizeof(map[0]); i++)
202 {
203 if (map[i].data == data)
204 {
205 LOG_D("KEY info:");
206 if (flag & KBD_CAPS_LOCK)
207 {
208 LOG_D("CAPS:LOCK");
209 }
210 else
211 {
212 LOG_D("CAPS:UNLOCK");
213 }
214
215 if (flag & KBD_LEFT_SHIFT)
216 {
217 mod |= RTGUI_KMOD_LSHIFT;
218 LOG_D("SHIFT:LEFT");
219 }
220 else if (flag & KBD_RIGHT_SHIFT)
221 {
222 mod |= RTGUI_KMOD_RSHIFT;
223 LOG_D("SHIFT:RIGHT");
224 }
225 else
226 {
227 LOG_D("SHIFT:NULL");
228 }
229
230 if (flag & KBD_LEFT_CTRL)
231 {
232 mod |= RTGUI_KMOD_LCTRL;
233 LOG_D("CTRL:LEFT");
234 }
235 else if (flag & KBD_RIGHT_CTRL)
236 {
237 mod |= RTGUI_KMOD_RCTRL;
238 LOG_D("CTRL:RIGHT");
239 }
240 else
241 {
242 LOG_D("CTRL:NULL");
243 }
244
245 LOG_D("flag:0x%08x value:0x%x key:%s status:%s", \
246 flag, data, map[i].normal_key, press ==0 ? "UP" : "DOWN");
247 find_key = 1;
248 break;
249 }
250 }
251 if (find_key == 0)
252 {
253 LOG_D("flag:0x%08x value:0x%x key:%s status:%s", \
254 flag, data, "UNKNOWN", press ==0 ? "UP" : "DOWN");
255 return;
256 }
257
258 key_event.parent.sender = RT_NULL;
259 key_event.parent.type = RTGUI_EVENT_KBD;
260 key_event.type = (press == 0 ? RTGUI_KEYUP : RTGUI_KEYDOWN);
261 key_event.key = map[i].key;
262 key_event.mod = mod;
263 key_event.unicode = map[i].unicode;
264 rtgui_server_post_event(&key_event.parent, sizeof(key_event));
265 }
266
keyboard_pl050_interrupt(int irq,void * data)267 static void keyboard_pl050_interrupt(int irq, void *data)
268 {
269 struct keyboard_pl050_pdata_t * pdat = (struct keyboard_pl050_pdata_t *)data;
270 static enum decode_state ds = DECODE_STATE_MAKE_CODE;
271 static rt_uint32_t kbd_flag = KBD_NUM_LOCK;
272 rt_uint8_t status, value;
273
274 status = read8(pdat->virt + KEYBOARD_IIR);
275
276 while(status & (1 << 0))
277 {
278 value = read8(pdat->virt + KEYBOARD_DATA);
279
280 switch(ds)
281 {
282 case DECODE_STATE_MAKE_CODE:
283 /* break code */
284 if(value == 0xf0)
285 {
286 ds = DECODE_STATE_BREAK_CODE;
287 }
288 /* long make code */
289 else if(value == 0xe0)
290 {
291 ds = DECODE_STATE_LONG_MAKE_CODE;
292 }
293 else
294 {
295 ds = DECODE_STATE_MAKE_CODE;
296
297 /* left shift */
298 if(value == 0x12)
299 {
300 kbd_flag |= KBD_LEFT_SHIFT;
301 }
302 /* right shift */
303 else if(value == 0x59)
304 {
305 kbd_flag |= KBD_RIGHT_SHIFT;
306 }
307 /* left ctrl */
308 else if(value == 0x14)
309 {
310 kbd_flag |= KBD_LEFT_CTRL;
311 }
312 /* caps lock */
313 else if(value == 0x58)
314 {
315 if(kbd_flag & KBD_CAPS_LOCK)
316 kbd_flag &= ~KBD_CAPS_LOCK;
317 else
318 kbd_flag |= KBD_CAPS_LOCK;
319 }
320 /* scroll lock */
321 else if(value == 0x7e)
322 {
323 if(kbd_flag & KBD_SCROLL_LOCK)
324 kbd_flag &= ~KBD_SCROLL_LOCK;
325 else
326 kbd_flag |= KBD_SCROLL_LOCK;
327 }
328 /* num lock */
329 else if(value == 0x77)
330 {
331 if(kbd_flag & KBD_NUM_LOCK)
332 kbd_flag &= ~KBD_NUM_LOCK;
333 else
334 kbd_flag |= KBD_NUM_LOCK;
335 }
336 /* others */
337 else
338 {
339 keyboard_report_event(data, kbd_flag, value, KEY_BUTTON_DOWN);
340 }
341 }
342 break;
343
344 case DECODE_STATE_BREAK_CODE:
345 if( (value != 0xf0) && (value != 0xe0))
346 {
347 ds = DECODE_STATE_MAKE_CODE;
348
349 /* left shift */
350 if(value == 0x12)
351 {
352 kbd_flag &= ~KBD_LEFT_SHIFT;
353 }
354 /* right shift */
355 else if(value == 0x59)
356 {
357 kbd_flag &= ~KBD_RIGHT_SHIFT;
358 }
359 /* left ctrl */
360 else if(value == 0x14)
361 {
362 kbd_flag &= ~KBD_LEFT_CTRL;
363 }
364 /* others */
365 else
366 {
367 keyboard_report_event(data, kbd_flag, value, KEY_BUTTON_UP);
368 }
369 }
370 else
371 {
372 ds = DECODE_STATE_BREAK_CODE;
373 }
374 break;
375
376 case DECODE_STATE_LONG_MAKE_CODE:
377 if( value != 0xf0 && value!= 0xe0)
378 {
379 ds = DECODE_STATE_MAKE_CODE;
380
381 /* left ctrl */
382 if(value == 0x14)
383 {
384 kbd_flag |= KBD_RIGHT_CTRL;
385 }
386 /* others */
387 else
388 {
389 keyboard_report_event(data, kbd_flag, value, KEY_BUTTON_DOWN);
390 }
391 }
392 else
393 {
394 ds = DECODE_STATE_LONG_BREAK_CODE;
395 }
396 break;
397
398 case DECODE_STATE_LONG_BREAK_CODE:
399 if( (value != 0xf0) && (value != 0xe0))
400 {
401 ds = DECODE_STATE_MAKE_CODE;
402
403 /* left ctrl */
404 if(value == 0x14)
405 {
406 kbd_flag &= ~KBD_RIGHT_CTRL;
407 }
408 /* others */
409 else
410 {
411 keyboard_report_event(data, kbd_flag, value, KEY_BUTTON_UP);
412 }
413 }
414 else
415 {
416 ds = DECODE_STATE_LONG_BREAK_CODE;
417 }
418 break;
419
420 default:
421 ds = DECODE_STATE_MAKE_CODE;
422 break;
423 }
424
425 status = read8(pdat->virt + KEYBOARD_IIR);
426 }
427 }
428
rt_hw_keyboard_init(void)429 int rt_hw_keyboard_init(void)
430 {
431 rt_uint8_t value;
432 rt_uint32_t id;
433 struct keyboard_pl050_pdata_t *pdat;
434 virtual_addr_t virt;
435 int irq = KEYBOARD_IRQ_NUM;
436
437 virt = (virtual_addr_t)rt_ioremap((void*)KEYBOARD_ADDRESS, 0x1000);
438
439 id = (((read32(virt + 0xfec) & 0xff) << 24) |
440 ((read32(virt + 0xfe8) & 0xff) << 16) |
441 ((read32(virt + 0xfe4) & 0xff) << 8) |
442 ((read32(virt + 0xfe0) & 0xff) << 0));
443
444 if(((id >> 12) & 0xff) != 0x41 || (id & 0xfff) != 0x050)
445 {
446 LOG_E("read id fail id:0x%08x", id);
447 return -RT_ERROR;
448 }
449
450 pdat = rt_malloc(sizeof(struct keyboard_pl050_pdata_t));
451 if(!pdat)
452 {
453 LOG_E("malloc memory failed");
454 return -RT_ERROR;
455 }
456 rt_memset(pdat, 0, sizeof(struct keyboard_pl050_pdata_t));
457
458 pdat->virt = virt;
459 pdat->irq = irq;
460
461 write8(pdat->virt + KEYBOARD_CLKDIV, 0);
462 write8(pdat->virt + KEYBOARD_CR, (1 << 2));
463 kmi_read(pdat, &value);
464 kmi_write(pdat, 0xff);
465 kmi_read(pdat, &value);
466 kmi_write(pdat, 0xf3);
467 kmi_write(pdat, 0x2b);
468 kmi_write(pdat, 0xf0);
469 kmi_write(pdat, 0x02);
470 kmi_write(pdat, 0xfa);
471 kmi_write(pdat, 0xed);
472 kmi_write(pdat, 0x02);
473 write8(pdat->virt + KEYBOARD_CR, (1 << 2) | (1 << 4));
474
475 rt_hw_interrupt_install(irq, keyboard_pl050_interrupt, (void *)pdat, "keyboard");
476 rt_hw_interrupt_umask(irq);
477
478 return RT_EOK;
479 }
480 INIT_DEVICE_EXPORT(rt_hw_keyboard_init);
481
482 #endif
483