|
|
1.1 root 1: /*
2: * National Semiconductor LM8322/8323 GPIO keyboard & PWM chips.
3: *
4: * Copyright (C) 2008 Nokia Corporation
5: * Written by Andrzej Zaborowski <[email protected]>
6: *
7: * This program is free software; you can redistribute it and/or
8: * modify it under the terms of the GNU General Public License as
9: * published by the Free Software Foundation; either version 2 or
10: * (at your option) version 3 of the License.
11: *
12: * This program is distributed in the hope that it will be useful,
13: * but WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: * GNU General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public License along
18: * with this program; if not, write to the Free Software Foundation, Inc.,
19: * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20: */
21:
22: #include "hw.h"
23: #include "i2c.h"
24: #include "qemu-timer.h"
25: #include "console.h"
26:
27: struct lm_kbd_s {
28: i2c_slave i2c;
29: int i2c_dir;
30: int i2c_cycle;
31: int reg;
32:
33: qemu_irq nirq;
34: uint16_t model;
35:
36: struct {
37: qemu_irq out[2];
38: int in[2][2];
39: } mux;
40:
41: uint8_t config;
42: uint8_t status;
43: uint8_t acttime;
44: uint8_t error;
45: uint8_t clock;
46:
47: struct {
48: uint16_t pull;
49: uint16_t mask;
50: uint16_t dir;
51: uint16_t level;
52: qemu_irq out[16];
53: } gpio;
54:
55: struct {
56: uint8_t dbnctime;
57: uint8_t size;
58: int start;
59: int len;
60: uint8_t fifo[16];
61: } kbd;
62:
63: struct {
64: uint16_t file[256];
65: uint8_t faddr;
66: uint8_t addr[3];
67: QEMUTimer *tm[3];
68: } pwm;
69: };
70:
71: #define INT_KEYPAD (1 << 0)
72: #define INT_ERROR (1 << 3)
73: #define INT_NOINIT (1 << 4)
74: #define INT_PWMEND(n) (1 << (5 + n))
75:
76: #define ERR_BADPAR (1 << 0)
77: #define ERR_CMDUNK (1 << 1)
78: #define ERR_KEYOVR (1 << 2)
79: #define ERR_FIFOOVR (1 << 6)
80:
81: static void lm_kbd_irq_update(struct lm_kbd_s *s)
82: {
83: qemu_set_irq(s->nirq, !s->status);
84: }
85:
86: static void lm_kbd_gpio_update(struct lm_kbd_s *s)
87: {
88: }
89:
90: static void lm_kbd_reset(struct lm_kbd_s *s)
91: {
92: s->config = 0x80;
93: s->status = INT_NOINIT;
94: s->acttime = 125;
95: s->kbd.dbnctime = 3;
96: s->kbd.size = 0x33;
97: s->clock = 0x08;
98:
99: lm_kbd_irq_update(s);
100: lm_kbd_gpio_update(s);
101: }
102:
103: static void lm_kbd_error(struct lm_kbd_s *s, int err)
104: {
105: s->error |= err;
106: s->status |= INT_ERROR;
107: lm_kbd_irq_update(s);
108: }
109:
110: static void lm_kbd_pwm_tick(struct lm_kbd_s *s, int line)
111: {
112: }
113:
114: static void lm_kbd_pwm_start(struct lm_kbd_s *s, int line)
115: {
116: lm_kbd_pwm_tick(s, line);
117: }
118:
119: static void lm_kbd_pwm0_tick(void *opaque)
120: {
121: lm_kbd_pwm_tick(opaque, 0);
122: }
123: static void lm_kbd_pwm1_tick(void *opaque)
124: {
125: lm_kbd_pwm_tick(opaque, 1);
126: }
127: static void lm_kbd_pwm2_tick(void *opaque)
128: {
129: lm_kbd_pwm_tick(opaque, 2);
130: }
131:
132: enum {
133: LM832x_CMD_READ_ID = 0x80, /* Read chip ID. */
134: LM832x_CMD_WRITE_CFG = 0x81, /* Set configuration item. */
135: LM832x_CMD_READ_INT = 0x82, /* Get interrupt status. */
136: LM832x_CMD_RESET = 0x83, /* Reset, same as external one */
137: LM823x_CMD_WRITE_PULL_DOWN = 0x84, /* Select GPIO pull-up/down. */
138: LM832x_CMD_WRITE_PORT_SEL = 0x85, /* Select GPIO in/out. */
139: LM832x_CMD_WRITE_PORT_STATE = 0x86, /* Set GPIO pull-up/down. */
140: LM832x_CMD_READ_PORT_SEL = 0x87, /* Get GPIO in/out. */
141: LM832x_CMD_READ_PORT_STATE = 0x88, /* Get GPIO pull-up/down. */
142: LM832x_CMD_READ_FIFO = 0x89, /* Read byte from FIFO. */
143: LM832x_CMD_RPT_READ_FIFO = 0x8a, /* Read FIFO (no increment). */
144: LM832x_CMD_SET_ACTIVE = 0x8b, /* Set active time. */
145: LM832x_CMD_READ_ERROR = 0x8c, /* Get error status. */
146: LM832x_CMD_READ_ROTATOR = 0x8e, /* Read rotator status. */
147: LM832x_CMD_SET_DEBOUNCE = 0x8f, /* Set debouncing time. */
148: LM832x_CMD_SET_KEY_SIZE = 0x90, /* Set keypad size. */
149: LM832x_CMD_READ_KEY_SIZE = 0x91, /* Get keypad size. */
150: LM832x_CMD_READ_CFG = 0x92, /* Get configuration item. */
151: LM832x_CMD_WRITE_CLOCK = 0x93, /* Set clock config. */
152: LM832x_CMD_READ_CLOCK = 0x94, /* Get clock config. */
153: LM832x_CMD_PWM_WRITE = 0x95, /* Write PWM script. */
154: LM832x_CMD_PWM_START = 0x96, /* Start PWM engine. */
155: LM832x_CMD_PWM_STOP = 0x97, /* Stop PWM engine. */
156: };
157:
158: #define LM832x_MAX_KPX 8
159: #define LM832x_MAX_KPY 12
160:
161: static uint8_t lm_kbd_read(struct lm_kbd_s *s, int reg, int byte)
162: {
163: int ret;
164:
165: switch (reg) {
166: case LM832x_CMD_READ_ID:
167: ret = 0x0400;
168: break;
169:
170: case LM832x_CMD_READ_INT:
171: ret = s->status;
172: if (!(s->status & INT_NOINIT)) {
173: s->status = 0;
174: lm_kbd_irq_update(s);
175: }
176: break;
177:
178: case LM832x_CMD_READ_PORT_SEL:
179: ret = s->gpio.dir;
180: break;
181: case LM832x_CMD_READ_PORT_STATE:
182: ret = s->gpio.mask;
183: break;
184:
185: case LM832x_CMD_READ_FIFO:
186: if (s->kbd.len <= 1)
187: return 0x00;
188:
189: /* Example response from the two commands after a INT_KEYPAD
190: * interrupt caused by the key 0x3c being pressed:
191: * RPT_READ_FIFO: 55 bc 00 4e ff 0a 50 08 00 29 d9 08 01 c9 01
192: * READ_FIFO: bc 00 00 4e ff 0a 50 08 00 29 d9 08 01 c9 01
193: * RPT_READ_FIFO: bc 00 00 4e ff 0a 50 08 00 29 d9 08 01 c9 01
194: *
195: * 55 is the code of the key release event serviced in the previous
196: * interrupt handling.
197: *
198: * TODO: find out whether the FIFO is advanced a single character
199: * before reading every byte or the whole size of the FIFO at the
200: * last LM832x_CMD_READ_FIFO. This affects LM832x_CMD_RPT_READ_FIFO
201: * output in cases where there are more than one event in the FIFO.
202: * Assume 0xbc and 0x3c events are in the FIFO:
203: * RPT_READ_FIFO: 55 bc 3c 00 4e ff 0a 50 08 00 29 d9 08 01 c9
204: * READ_FIFO: bc 3c 00 00 4e ff 0a 50 08 00 29 d9 08 01 c9
205: * Does RPT_READ_FIFO now return 0xbc and 0x3c or only 0x3c?
206: */
207: s->kbd.start ++;
208: s->kbd.start &= sizeof(s->kbd.fifo) - 1;
209: s->kbd.len --;
210:
211: return s->kbd.fifo[s->kbd.start];
212: case LM832x_CMD_RPT_READ_FIFO:
213: if (byte >= s->kbd.len)
214: return 0x00;
215:
216: return s->kbd.fifo[(s->kbd.start + byte) & (sizeof(s->kbd.fifo) - 1)];
217:
218: case LM832x_CMD_READ_ERROR:
219: return s->error;
220:
221: case LM832x_CMD_READ_ROTATOR:
222: return 0;
223:
224: case LM832x_CMD_READ_KEY_SIZE:
225: return s->kbd.size;
226:
227: case LM832x_CMD_READ_CFG:
228: return s->config & 0xf;
229:
230: case LM832x_CMD_READ_CLOCK:
231: return (s->clock & 0xfc) | 2;
232:
233: default:
234: lm_kbd_error(s, ERR_CMDUNK);
235: fprintf(stderr, "%s: unknown command %02x\n", __FUNCTION__, reg);
236: return 0x00;
237: }
238:
239: return ret >> (byte << 3);
240: }
241:
242: static void lm_kbd_write(struct lm_kbd_s *s, int reg, int byte, uint8_t value)
243: {
244: switch (reg) {
245: case LM832x_CMD_WRITE_CFG:
246: s->config = value;
247: /* This must be done whenever s->mux.in is updated (never). */
248: if ((s->config >> 1) & 1) /* MUX1EN */
249: qemu_set_irq(s->mux.out[0], s->mux.in[0][(s->config >> 0) & 1]);
250: if ((s->config >> 3) & 1) /* MUX2EN */
251: qemu_set_irq(s->mux.out[0], s->mux.in[0][(s->config >> 2) & 1]);
252: /* TODO: check that this is issued only following the chip reset
253: * and not in the middle of operation and that it is followed by
254: * the GPIO ports re-resablishing through WRITE_PORT_SEL and
255: * WRITE_PORT_STATE (using a timer perhaps) and otherwise output
256: * warnings. */
257: s->status = 0;
258: lm_kbd_irq_update(s);
259: s->kbd.len = 0;
260: s->kbd.start = 0;
261: s->reg = -1;
262: break;
263:
264: case LM832x_CMD_RESET:
265: if (value == 0xaa)
266: lm_kbd_reset(s);
267: else
268: lm_kbd_error(s, ERR_BADPAR);
269: s->reg = -1;
270: break;
271:
272: case LM823x_CMD_WRITE_PULL_DOWN:
273: if (!byte)
274: s->gpio.pull = value;
275: else {
276: s->gpio.pull |= value << 8;
277: lm_kbd_gpio_update(s);
278: s->reg = -1;
279: }
280: break;
281: case LM832x_CMD_WRITE_PORT_SEL:
282: if (!byte)
283: s->gpio.dir = value;
284: else {
285: s->gpio.dir |= value << 8;
286: lm_kbd_gpio_update(s);
287: s->reg = -1;
288: }
289: break;
290: case LM832x_CMD_WRITE_PORT_STATE:
291: if (!byte)
292: s->gpio.mask = value;
293: else {
294: s->gpio.mask |= value << 8;
295: lm_kbd_gpio_update(s);
296: s->reg = -1;
297: }
298: break;
299:
300: case LM832x_CMD_SET_ACTIVE:
301: s->acttime = value;
302: s->reg = -1;
303: break;
304:
305: case LM832x_CMD_SET_DEBOUNCE:
306: s->kbd.dbnctime = value;
307: s->reg = -1;
308: if (!value)
309: lm_kbd_error(s, ERR_BADPAR);
310: break;
311:
312: case LM832x_CMD_SET_KEY_SIZE:
313: s->kbd.size = value;
314: s->reg = -1;
315: if (
316: (value & 0xf) < 3 || (value & 0xf) > LM832x_MAX_KPY ||
317: (value >> 4) < 3 || (value >> 4) > LM832x_MAX_KPX)
318: lm_kbd_error(s, ERR_BADPAR);
319: break;
320:
321: case LM832x_CMD_WRITE_CLOCK:
322: s->clock = value;
323: s->reg = -1;
324: if ((value & 3) && (value & 3) != 3) {
325: lm_kbd_error(s, ERR_BADPAR);
326: fprintf(stderr, "%s: invalid clock setting in RCPWM\n",
327: __FUNCTION__);
328: }
329: /* TODO: Validate that the command is only issued once */
330: break;
331:
332: case LM832x_CMD_PWM_WRITE:
333: if (byte == 0) {
334: if (!(value & 3) || (value >> 2) > 59) {
335: lm_kbd_error(s, ERR_BADPAR);
336: s->reg = -1;
337: break;
338: }
339:
340: s->pwm.faddr = value;
341: s->pwm.file[s->pwm.faddr] = 0;
342: } else if (byte == 1) {
343: s->pwm.file[s->pwm.faddr] |= value << 8;
344: } else if (byte == 2) {
345: s->pwm.file[s->pwm.faddr] |= value << 0;
346: s->reg = -1;
347: }
348: break;
349: case LM832x_CMD_PWM_START:
350: s->reg = -1;
351: if (!(value & 3) || (value >> 2) > 59) {
352: lm_kbd_error(s, ERR_BADPAR);
353: break;
354: }
355:
356: s->pwm.addr[(value & 3) - 1] = value >> 2;
357: lm_kbd_pwm_start(s, (value & 3) - 1);
358: break;
359: case LM832x_CMD_PWM_STOP:
360: s->reg = -1;
361: if (!(value & 3)) {
362: lm_kbd_error(s, ERR_BADPAR);
363: break;
364: }
365:
366: qemu_del_timer(s->pwm.tm[(value & 3) - 1]);
367: break;
368:
369: case -1:
370: lm_kbd_error(s, ERR_BADPAR);
371: break;
372: default:
373: lm_kbd_error(s, ERR_CMDUNK);
374: fprintf(stderr, "%s: unknown command %02x\n", __FUNCTION__, reg);
375: break;
376: }
377: }
378:
379: static void lm_i2c_event(i2c_slave *i2c, enum i2c_event event)
380: {
381: struct lm_kbd_s *s = (struct lm_kbd_s *) i2c;
382:
383: switch (event) {
384: case I2C_START_RECV:
385: case I2C_START_SEND:
386: s->i2c_cycle = 0;
387: s->i2c_dir = (event == I2C_START_SEND);
388: break;
389:
390: default:
391: break;
392: }
393: }
394:
395: static int lm_i2c_rx(i2c_slave *i2c)
396: {
397: struct lm_kbd_s *s = (struct lm_kbd_s *) i2c;
398:
399: return lm_kbd_read(s, s->reg, s->i2c_cycle ++);
400: }
401:
402: static int lm_i2c_tx(i2c_slave *i2c, uint8_t data)
403: {
404: struct lm_kbd_s *s = (struct lm_kbd_s *) i2c;
405:
406: if (!s->i2c_cycle)
407: s->reg = data;
408: else
409: lm_kbd_write(s, s->reg, s->i2c_cycle - 1, data);
410: s->i2c_cycle ++;
411:
412: return 0;
413: }
414:
415: static void lm_kbd_save(QEMUFile *f, void *opaque)
416: {
417: struct lm_kbd_s *s = (struct lm_kbd_s *) opaque;
418: int i;
419:
420: i2c_slave_save(f, &s->i2c);
421: qemu_put_byte(f, s->i2c_dir);
422: qemu_put_byte(f, s->i2c_cycle);
423: qemu_put_byte(f, (uint8_t) s->reg);
424:
425: qemu_put_8s(f, &s->config);
426: qemu_put_8s(f, &s->status);
427: qemu_put_8s(f, &s->acttime);
428: qemu_put_8s(f, &s->error);
429: qemu_put_8s(f, &s->clock);
430:
431: qemu_put_be16s(f, &s->gpio.pull);
432: qemu_put_be16s(f, &s->gpio.mask);
433: qemu_put_be16s(f, &s->gpio.dir);
434: qemu_put_be16s(f, &s->gpio.level);
435:
436: qemu_put_byte(f, s->kbd.dbnctime);
437: qemu_put_byte(f, s->kbd.size);
438: qemu_put_byte(f, s->kbd.start);
439: qemu_put_byte(f, s->kbd.len);
440: qemu_put_buffer(f, s->kbd.fifo, sizeof(s->kbd.fifo));
441:
442: for (i = 0; i < sizeof(s->pwm.file); i ++)
443: qemu_put_be16s(f, &s->pwm.file[i]);
444: qemu_put_8s(f, &s->pwm.faddr);
445: qemu_put_buffer(f, s->pwm.addr, sizeof(s->pwm.addr));
446: qemu_put_timer(f, s->pwm.tm[0]);
447: qemu_put_timer(f, s->pwm.tm[1]);
448: qemu_put_timer(f, s->pwm.tm[2]);
449: }
450:
451: static int lm_kbd_load(QEMUFile *f, void *opaque, int version_id)
452: {
453: struct lm_kbd_s *s = (struct lm_kbd_s *) opaque;
454: int i;
455:
456: i2c_slave_load(f, &s->i2c);
457: s->i2c_dir = qemu_get_byte(f);
458: s->i2c_cycle = qemu_get_byte(f);
459: s->reg = (int8_t) qemu_get_byte(f);
460:
461: qemu_get_8s(f, &s->config);
462: qemu_get_8s(f, &s->status);
463: qemu_get_8s(f, &s->acttime);
464: qemu_get_8s(f, &s->error);
465: qemu_get_8s(f, &s->clock);
466:
467: qemu_get_be16s(f, &s->gpio.pull);
468: qemu_get_be16s(f, &s->gpio.mask);
469: qemu_get_be16s(f, &s->gpio.dir);
470: qemu_get_be16s(f, &s->gpio.level);
471:
472: s->kbd.dbnctime = qemu_get_byte(f);
473: s->kbd.size = qemu_get_byte(f);
474: s->kbd.start = qemu_get_byte(f);
475: s->kbd.len = qemu_get_byte(f);
476: qemu_get_buffer(f, s->kbd.fifo, sizeof(s->kbd.fifo));
477:
478: for (i = 0; i < sizeof(s->pwm.file); i ++)
479: qemu_get_be16s(f, &s->pwm.file[i]);
480: qemu_get_8s(f, &s->pwm.faddr);
481: qemu_get_buffer(f, s->pwm.addr, sizeof(s->pwm.addr));
482: qemu_get_timer(f, s->pwm.tm[0]);
483: qemu_get_timer(f, s->pwm.tm[1]);
484: qemu_get_timer(f, s->pwm.tm[2]);
485:
486: lm_kbd_irq_update(s);
487: lm_kbd_gpio_update(s);
488:
489: return 0;
490: }
491:
492: struct i2c_slave *lm8323_init(i2c_bus *bus, qemu_irq nirq)
493: {
494: struct lm_kbd_s *s;
495:
496: s = (struct lm_kbd_s *) i2c_slave_init(bus, 0, sizeof(struct lm_kbd_s));
497: s->model = 0x8323;
498: s->pwm.tm[0] = qemu_new_timer(vm_clock, lm_kbd_pwm0_tick, s);
499: s->pwm.tm[1] = qemu_new_timer(vm_clock, lm_kbd_pwm1_tick, s);
500: s->pwm.tm[2] = qemu_new_timer(vm_clock, lm_kbd_pwm2_tick, s);
501: s->nirq = nirq;
502:
503: s->i2c.event = lm_i2c_event;
504: s->i2c.recv = lm_i2c_rx;
505: s->i2c.send = lm_i2c_tx;
506:
507: lm_kbd_reset(s);
508:
509: qemu_register_reset((void *) lm_kbd_reset, s);
510: register_savevm("LM8323", -1, 0, lm_kbd_save, lm_kbd_load, s);
511:
512: return &s->i2c;
513: }
514:
515: void lm832x_key_event(struct i2c_slave *i2c, int key, int state)
516: {
517: struct lm_kbd_s *s = (struct lm_kbd_s *) i2c;
518:
519: if ((s->status & INT_ERROR) && (s->error & ERR_FIFOOVR))
520: return;
521:
522: if (s->kbd.len >= sizeof(s->kbd.fifo))
523: return lm_kbd_error(s, ERR_FIFOOVR);
524:
525: s->kbd.fifo[(s->kbd.start + s->kbd.len ++) & (sizeof(s->kbd.fifo) - 1)] =
526: key | (state << 7);
527:
528: /* We never set ERR_KEYOVR because we support multiple keys fine. */
529: s->status |= INT_KEYPAD;
530: lm_kbd_irq_update(s);
531: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.