|
|
1.1 root 1: /*
2: * TI TWL92230C energy-management companion device for the OMAP24xx.
3: * Aka. Menelaus (N4200 MENELAUS1_V2.2)
4: *
5: * Copyright (C) 2008 Nokia Corporation
6: * Written by Andrzej Zaborowski <[email protected]>
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 or
11: * (at your option) version 3 of the License.
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 along
1.1.1.2 root 19: * with this program; if not, see <http://www.gnu.org/licenses/>.
1.1 root 20: */
21:
22: #include "hw.h"
23: #include "qemu-timer.h"
24: #include "i2c.h"
25: #include "sysemu.h"
26: #include "console.h"
27:
28: #define VERBOSE 1
29:
1.1.1.2 root 30: typedef struct {
1.1 root 31: i2c_slave i2c;
32:
33: int firstbyte;
34: uint8_t reg;
35:
36: uint8_t vcore[5];
37: uint8_t dcdc[3];
38: uint8_t ldo[8];
39: uint8_t sleep[2];
40: uint8_t osc;
41: uint8_t detect;
42: uint16_t mask;
43: uint16_t status;
44: uint8_t dir;
45: uint8_t inputs;
46: uint8_t outputs;
47: uint8_t bbsms;
48: uint8_t pull[4];
49: uint8_t mmc_ctrl[3];
50: uint8_t mmc_debounce;
51: struct {
52: uint8_t ctrl;
53: uint16_t comp;
54: QEMUTimer *hz_tm;
55: int64_t next;
56: struct tm tm;
57: struct tm new;
58: struct tm alm;
59: int sec_offset;
60: int alm_sec;
61: int next_comp;
62: } rtc;
1.1.1.3 ! root 63: uint16_t rtc_next_vmstate;
1.1.1.2 root 64: qemu_irq out[4];
1.1 root 65: qemu_irq *in;
1.1.1.3 ! root 66: uint8_t pwrbtn_state;
1.1 root 67: qemu_irq pwrbtn;
1.1.1.2 root 68: } MenelausState;
1.1 root 69:
1.1.1.2 root 70: static inline void menelaus_update(MenelausState *s)
1.1 root 71: {
1.1.1.2 root 72: qemu_set_irq(s->out[3], s->status & ~s->mask);
1.1 root 73: }
74:
1.1.1.2 root 75: static inline void menelaus_rtc_start(MenelausState *s)
1.1 root 76: {
1.1.1.3 ! root 77: s->rtc.next += qemu_get_clock(rt_clock);
1.1 root 78: qemu_mod_timer(s->rtc.hz_tm, s->rtc.next);
79: }
80:
1.1.1.2 root 81: static inline void menelaus_rtc_stop(MenelausState *s)
1.1 root 82: {
83: qemu_del_timer(s->rtc.hz_tm);
1.1.1.3 ! root 84: s->rtc.next -= qemu_get_clock(rt_clock);
1.1 root 85: if (s->rtc.next < 1)
86: s->rtc.next = 1;
87: }
88:
1.1.1.2 root 89: static void menelaus_rtc_update(MenelausState *s)
1.1 root 90: {
91: qemu_get_timedate(&s->rtc.tm, s->rtc.sec_offset);
92: }
93:
1.1.1.2 root 94: static void menelaus_alm_update(MenelausState *s)
1.1 root 95: {
96: if ((s->rtc.ctrl & 3) == 3)
97: s->rtc.alm_sec = qemu_timedate_diff(&s->rtc.alm) - s->rtc.sec_offset;
98: }
99:
100: static void menelaus_rtc_hz(void *opaque)
101: {
1.1.1.2 root 102: MenelausState *s = (MenelausState *) opaque;
1.1 root 103:
104: s->rtc.next_comp --;
105: s->rtc.alm_sec --;
106: s->rtc.next += 1000;
107: qemu_mod_timer(s->rtc.hz_tm, s->rtc.next);
108: if ((s->rtc.ctrl >> 3) & 3) { /* EVERY */
109: menelaus_rtc_update(s);
110: if (((s->rtc.ctrl >> 3) & 3) == 1 && !s->rtc.tm.tm_sec)
111: s->status |= 1 << 8; /* RTCTMR */
112: else if (((s->rtc.ctrl >> 3) & 3) == 2 && !s->rtc.tm.tm_min)
113: s->status |= 1 << 8; /* RTCTMR */
114: else if (!s->rtc.tm.tm_hour)
115: s->status |= 1 << 8; /* RTCTMR */
116: } else
117: s->status |= 1 << 8; /* RTCTMR */
118: if ((s->rtc.ctrl >> 1) & 1) { /* RTC_AL_EN */
119: if (s->rtc.alm_sec == 0)
120: s->status |= 1 << 9; /* RTCALM */
121: /* TODO: wake-up */
122: }
123: if (s->rtc.next_comp <= 0) {
124: s->rtc.next -= muldiv64((int16_t) s->rtc.comp, 1000, 0x8000);
125: s->rtc.next_comp = 3600;
126: }
127: menelaus_update(s);
128: }
129:
130: static void menelaus_reset(i2c_slave *i2c)
131: {
1.1.1.2 root 132: MenelausState *s = (MenelausState *) i2c;
1.1 root 133: s->reg = 0x00;
134:
135: s->vcore[0] = 0x0c; /* XXX: X-loader needs 0x8c? check! */
136: s->vcore[1] = 0x05;
137: s->vcore[2] = 0x02;
138: s->vcore[3] = 0x0c;
139: s->vcore[4] = 0x03;
140: s->dcdc[0] = 0x33; /* Depends on wiring */
141: s->dcdc[1] = 0x03;
142: s->dcdc[2] = 0x00;
143: s->ldo[0] = 0x95;
144: s->ldo[1] = 0x7e;
145: s->ldo[2] = 0x00;
146: s->ldo[3] = 0x00; /* Depends on wiring */
147: s->ldo[4] = 0x03; /* Depends on wiring */
148: s->ldo[5] = 0x00;
149: s->ldo[6] = 0x00;
150: s->ldo[7] = 0x00;
151: s->sleep[0] = 0x00;
152: s->sleep[1] = 0x00;
153: s->osc = 0x01;
154: s->detect = 0x09;
155: s->mask = 0x0fff;
156: s->status = 0;
157: s->dir = 0x07;
158: s->outputs = 0x00;
159: s->bbsms = 0x00;
160: s->pull[0] = 0x00;
161: s->pull[1] = 0x00;
162: s->pull[2] = 0x00;
163: s->pull[3] = 0x00;
164: s->mmc_ctrl[0] = 0x03;
165: s->mmc_ctrl[1] = 0xc0;
166: s->mmc_ctrl[2] = 0x00;
167: s->mmc_debounce = 0x05;
168:
169: if (s->rtc.ctrl & 1)
170: menelaus_rtc_stop(s);
171: s->rtc.ctrl = 0x00;
172: s->rtc.comp = 0x0000;
173: s->rtc.next = 1000;
174: s->rtc.sec_offset = 0;
175: s->rtc.next_comp = 1800;
176: s->rtc.alm_sec = 1800;
177: s->rtc.alm.tm_sec = 0x00;
178: s->rtc.alm.tm_min = 0x00;
179: s->rtc.alm.tm_hour = 0x00;
180: s->rtc.alm.tm_mday = 0x01;
181: s->rtc.alm.tm_mon = 0x00;
182: s->rtc.alm.tm_year = 2004;
183: menelaus_update(s);
184: }
185:
186: static void menelaus_gpio_set(void *opaque, int line, int level)
187: {
1.1.1.2 root 188: MenelausState *s = (MenelausState *) opaque;
1.1 root 189:
190: /* No interrupt generated */
191: s->inputs &= ~(1 << line);
192: s->inputs |= level << line;
193: }
194:
195: static void menelaus_pwrbtn_set(void *opaque, int line, int level)
196: {
1.1.1.2 root 197: MenelausState *s = (MenelausState *) opaque;
1.1 root 198:
199: if (!s->pwrbtn_state && level) {
200: s->status |= 1 << 11; /* PSHBTN */
201: menelaus_update(s);
202: }
203: s->pwrbtn_state = level;
204: }
205:
206: #define MENELAUS_REV 0x01
207: #define MENELAUS_VCORE_CTRL1 0x02
208: #define MENELAUS_VCORE_CTRL2 0x03
209: #define MENELAUS_VCORE_CTRL3 0x04
210: #define MENELAUS_VCORE_CTRL4 0x05
211: #define MENELAUS_VCORE_CTRL5 0x06
212: #define MENELAUS_DCDC_CTRL1 0x07
213: #define MENELAUS_DCDC_CTRL2 0x08
214: #define MENELAUS_DCDC_CTRL3 0x09
215: #define MENELAUS_LDO_CTRL1 0x0a
216: #define MENELAUS_LDO_CTRL2 0x0b
217: #define MENELAUS_LDO_CTRL3 0x0c
218: #define MENELAUS_LDO_CTRL4 0x0d
219: #define MENELAUS_LDO_CTRL5 0x0e
220: #define MENELAUS_LDO_CTRL6 0x0f
221: #define MENELAUS_LDO_CTRL7 0x10
222: #define MENELAUS_LDO_CTRL8 0x11
223: #define MENELAUS_SLEEP_CTRL1 0x12
224: #define MENELAUS_SLEEP_CTRL2 0x13
225: #define MENELAUS_DEVICE_OFF 0x14
226: #define MENELAUS_OSC_CTRL 0x15
227: #define MENELAUS_DETECT_CTRL 0x16
228: #define MENELAUS_INT_MASK1 0x17
229: #define MENELAUS_INT_MASK2 0x18
230: #define MENELAUS_INT_STATUS1 0x19
231: #define MENELAUS_INT_STATUS2 0x1a
232: #define MENELAUS_INT_ACK1 0x1b
233: #define MENELAUS_INT_ACK2 0x1c
234: #define MENELAUS_GPIO_CTRL 0x1d
235: #define MENELAUS_GPIO_IN 0x1e
236: #define MENELAUS_GPIO_OUT 0x1f
237: #define MENELAUS_BBSMS 0x20
238: #define MENELAUS_RTC_CTRL 0x21
239: #define MENELAUS_RTC_UPDATE 0x22
240: #define MENELAUS_RTC_SEC 0x23
241: #define MENELAUS_RTC_MIN 0x24
242: #define MENELAUS_RTC_HR 0x25
243: #define MENELAUS_RTC_DAY 0x26
244: #define MENELAUS_RTC_MON 0x27
245: #define MENELAUS_RTC_YR 0x28
246: #define MENELAUS_RTC_WKDAY 0x29
247: #define MENELAUS_RTC_AL_SEC 0x2a
248: #define MENELAUS_RTC_AL_MIN 0x2b
249: #define MENELAUS_RTC_AL_HR 0x2c
250: #define MENELAUS_RTC_AL_DAY 0x2d
251: #define MENELAUS_RTC_AL_MON 0x2e
252: #define MENELAUS_RTC_AL_YR 0x2f
253: #define MENELAUS_RTC_COMP_MSB 0x30
254: #define MENELAUS_RTC_COMP_LSB 0x31
255: #define MENELAUS_S1_PULL_EN 0x32
256: #define MENELAUS_S1_PULL_DIR 0x33
257: #define MENELAUS_S2_PULL_EN 0x34
258: #define MENELAUS_S2_PULL_DIR 0x35
259: #define MENELAUS_MCT_CTRL1 0x36
260: #define MENELAUS_MCT_CTRL2 0x37
261: #define MENELAUS_MCT_CTRL3 0x38
262: #define MENELAUS_MCT_PIN_ST 0x39
263: #define MENELAUS_DEBOUNCE1 0x3a
264:
265: static uint8_t menelaus_read(void *opaque, uint8_t addr)
266: {
1.1.1.2 root 267: MenelausState *s = (MenelausState *) opaque;
1.1 root 268: int reg = 0;
269:
270: switch (addr) {
271: case MENELAUS_REV:
272: return 0x22;
273:
274: case MENELAUS_VCORE_CTRL5: reg ++;
275: case MENELAUS_VCORE_CTRL4: reg ++;
276: case MENELAUS_VCORE_CTRL3: reg ++;
277: case MENELAUS_VCORE_CTRL2: reg ++;
278: case MENELAUS_VCORE_CTRL1:
279: return s->vcore[reg];
280:
281: case MENELAUS_DCDC_CTRL3: reg ++;
282: case MENELAUS_DCDC_CTRL2: reg ++;
283: case MENELAUS_DCDC_CTRL1:
284: return s->dcdc[reg];
285:
286: case MENELAUS_LDO_CTRL8: reg ++;
287: case MENELAUS_LDO_CTRL7: reg ++;
288: case MENELAUS_LDO_CTRL6: reg ++;
289: case MENELAUS_LDO_CTRL5: reg ++;
290: case MENELAUS_LDO_CTRL4: reg ++;
291: case MENELAUS_LDO_CTRL3: reg ++;
292: case MENELAUS_LDO_CTRL2: reg ++;
293: case MENELAUS_LDO_CTRL1:
294: return s->ldo[reg];
295:
296: case MENELAUS_SLEEP_CTRL2: reg ++;
297: case MENELAUS_SLEEP_CTRL1:
298: return s->sleep[reg];
299:
300: case MENELAUS_DEVICE_OFF:
301: return 0;
302:
303: case MENELAUS_OSC_CTRL:
304: return s->osc | (1 << 7); /* CLK32K_GOOD */
305:
306: case MENELAUS_DETECT_CTRL:
307: return s->detect;
308:
309: case MENELAUS_INT_MASK1:
310: return (s->mask >> 0) & 0xff;
311: case MENELAUS_INT_MASK2:
312: return (s->mask >> 8) & 0xff;
313:
314: case MENELAUS_INT_STATUS1:
315: return (s->status >> 0) & 0xff;
316: case MENELAUS_INT_STATUS2:
317: return (s->status >> 8) & 0xff;
318:
319: case MENELAUS_INT_ACK1:
320: case MENELAUS_INT_ACK2:
321: return 0;
322:
323: case MENELAUS_GPIO_CTRL:
324: return s->dir;
325: case MENELAUS_GPIO_IN:
326: return s->inputs | (~s->dir & s->outputs);
327: case MENELAUS_GPIO_OUT:
328: return s->outputs;
329:
330: case MENELAUS_BBSMS:
331: return s->bbsms;
332:
333: case MENELAUS_RTC_CTRL:
334: return s->rtc.ctrl;
335: case MENELAUS_RTC_UPDATE:
336: return 0x00;
337: case MENELAUS_RTC_SEC:
338: menelaus_rtc_update(s);
339: return to_bcd(s->rtc.tm.tm_sec);
340: case MENELAUS_RTC_MIN:
341: menelaus_rtc_update(s);
342: return to_bcd(s->rtc.tm.tm_min);
343: case MENELAUS_RTC_HR:
344: menelaus_rtc_update(s);
345: if ((s->rtc.ctrl >> 2) & 1) /* MODE12_n24 */
346: return to_bcd((s->rtc.tm.tm_hour % 12) + 1) |
347: (!!(s->rtc.tm.tm_hour >= 12) << 7); /* PM_nAM */
348: else
349: return to_bcd(s->rtc.tm.tm_hour);
350: case MENELAUS_RTC_DAY:
351: menelaus_rtc_update(s);
352: return to_bcd(s->rtc.tm.tm_mday);
353: case MENELAUS_RTC_MON:
354: menelaus_rtc_update(s);
355: return to_bcd(s->rtc.tm.tm_mon + 1);
356: case MENELAUS_RTC_YR:
357: menelaus_rtc_update(s);
358: return to_bcd(s->rtc.tm.tm_year - 2000);
359: case MENELAUS_RTC_WKDAY:
360: menelaus_rtc_update(s);
361: return to_bcd(s->rtc.tm.tm_wday);
362: case MENELAUS_RTC_AL_SEC:
363: return to_bcd(s->rtc.alm.tm_sec);
364: case MENELAUS_RTC_AL_MIN:
365: return to_bcd(s->rtc.alm.tm_min);
366: case MENELAUS_RTC_AL_HR:
367: if ((s->rtc.ctrl >> 2) & 1) /* MODE12_n24 */
368: return to_bcd((s->rtc.alm.tm_hour % 12) + 1) |
369: (!!(s->rtc.alm.tm_hour >= 12) << 7);/* AL_PM_nAM */
370: else
371: return to_bcd(s->rtc.alm.tm_hour);
372: case MENELAUS_RTC_AL_DAY:
373: return to_bcd(s->rtc.alm.tm_mday);
374: case MENELAUS_RTC_AL_MON:
375: return to_bcd(s->rtc.alm.tm_mon + 1);
376: case MENELAUS_RTC_AL_YR:
377: return to_bcd(s->rtc.alm.tm_year - 2000);
378: case MENELAUS_RTC_COMP_MSB:
379: return (s->rtc.comp >> 8) & 0xff;
380: case MENELAUS_RTC_COMP_LSB:
381: return (s->rtc.comp >> 0) & 0xff;
382:
383: case MENELAUS_S1_PULL_EN:
384: return s->pull[0];
385: case MENELAUS_S1_PULL_DIR:
386: return s->pull[1];
387: case MENELAUS_S2_PULL_EN:
388: return s->pull[2];
389: case MENELAUS_S2_PULL_DIR:
390: return s->pull[3];
391:
392: case MENELAUS_MCT_CTRL3: reg ++;
393: case MENELAUS_MCT_CTRL2: reg ++;
394: case MENELAUS_MCT_CTRL1:
395: return s->mmc_ctrl[reg];
396: case MENELAUS_MCT_PIN_ST:
397: /* TODO: return the real Card Detect */
398: return 0;
399: case MENELAUS_DEBOUNCE1:
400: return s->mmc_debounce;
401:
402: default:
403: #ifdef VERBOSE
404: printf("%s: unknown register %02x\n", __FUNCTION__, addr);
405: #endif
406: break;
407: }
408: return 0;
409: }
410:
411: static void menelaus_write(void *opaque, uint8_t addr, uint8_t value)
412: {
1.1.1.2 root 413: MenelausState *s = (MenelausState *) opaque;
1.1 root 414: int line;
415: int reg = 0;
416: struct tm tm;
417:
418: switch (addr) {
419: case MENELAUS_VCORE_CTRL1:
420: s->vcore[0] = (value & 0xe) | MIN(value & 0x1f, 0x12);
421: break;
422: case MENELAUS_VCORE_CTRL2:
423: s->vcore[1] = value;
424: break;
425: case MENELAUS_VCORE_CTRL3:
426: s->vcore[2] = MIN(value & 0x1f, 0x12);
427: break;
428: case MENELAUS_VCORE_CTRL4:
429: s->vcore[3] = MIN(value & 0x1f, 0x12);
430: break;
431: case MENELAUS_VCORE_CTRL5:
432: s->vcore[4] = value & 3;
433: /* XXX
434: * auto set to 3 on M_Active, nRESWARM
435: * auto set to 0 on M_WaitOn, M_Backup
436: */
437: break;
438:
439: case MENELAUS_DCDC_CTRL1:
440: s->dcdc[0] = value & 0x3f;
441: break;
442: case MENELAUS_DCDC_CTRL2:
443: s->dcdc[1] = value & 0x07;
444: /* XXX
445: * auto set to 3 on M_Active, nRESWARM
446: * auto set to 0 on M_WaitOn, M_Backup
447: */
448: break;
449: case MENELAUS_DCDC_CTRL3:
450: s->dcdc[2] = value & 0x07;
451: break;
452:
453: case MENELAUS_LDO_CTRL1:
454: s->ldo[0] = value;
455: break;
456: case MENELAUS_LDO_CTRL2:
457: s->ldo[1] = value & 0x7f;
458: /* XXX
459: * auto set to 0x7e on M_WaitOn, M_Backup
460: */
461: break;
462: case MENELAUS_LDO_CTRL3:
463: s->ldo[2] = value & 3;
464: /* XXX
465: * auto set to 3 on M_Active, nRESWARM
466: * auto set to 0 on M_WaitOn, M_Backup
467: */
468: break;
469: case MENELAUS_LDO_CTRL4:
470: s->ldo[3] = value & 3;
471: /* XXX
472: * auto set to 3 on M_Active, nRESWARM
473: * auto set to 0 on M_WaitOn, M_Backup
474: */
475: break;
476: case MENELAUS_LDO_CTRL5:
477: s->ldo[4] = value & 3;
478: /* XXX
479: * auto set to 3 on M_Active, nRESWARM
480: * auto set to 0 on M_WaitOn, M_Backup
481: */
482: break;
483: case MENELAUS_LDO_CTRL6:
484: s->ldo[5] = value & 3;
485: break;
486: case MENELAUS_LDO_CTRL7:
487: s->ldo[6] = value & 3;
488: break;
489: case MENELAUS_LDO_CTRL8:
490: s->ldo[7] = value & 3;
491: break;
492:
493: case MENELAUS_SLEEP_CTRL2: reg ++;
494: case MENELAUS_SLEEP_CTRL1:
495: s->sleep[reg] = value;
496: break;
497:
498: case MENELAUS_DEVICE_OFF:
499: if (value & 1)
500: menelaus_reset(&s->i2c);
501: break;
502:
503: case MENELAUS_OSC_CTRL:
504: s->osc = value & 7;
505: break;
506:
507: case MENELAUS_DETECT_CTRL:
508: s->detect = value & 0x7f;
509: break;
510:
511: case MENELAUS_INT_MASK1:
512: s->mask &= 0xf00;
513: s->mask |= value << 0;
514: menelaus_update(s);
515: break;
516: case MENELAUS_INT_MASK2:
517: s->mask &= 0x0ff;
518: s->mask |= value << 8;
519: menelaus_update(s);
520: break;
521:
522: case MENELAUS_INT_ACK1:
523: s->status &= ~(((uint16_t) value) << 0);
524: menelaus_update(s);
525: break;
526: case MENELAUS_INT_ACK2:
527: s->status &= ~(((uint16_t) value) << 8);
528: menelaus_update(s);
529: break;
530:
531: case MENELAUS_GPIO_CTRL:
1.1.1.2 root 532: for (line = 0; line < 3; line ++) {
533: if (((s->dir ^ value) >> line) & 1) {
534: qemu_set_irq(s->out[line],
535: ((s->outputs & ~s->dir) >> line) & 1);
536: }
537: }
1.1 root 538: s->dir = value & 0x67;
539: break;
540: case MENELAUS_GPIO_OUT:
1.1.1.2 root 541: for (line = 0; line < 3; line ++) {
542: if ((((s->outputs ^ value) & ~s->dir) >> line) & 1) {
543: qemu_set_irq(s->out[line], (s->outputs >> line) & 1);
544: }
545: }
1.1 root 546: s->outputs = value & 0x07;
547: break;
548:
549: case MENELAUS_BBSMS:
550: s->bbsms = 0x0d;
551: break;
552:
553: case MENELAUS_RTC_CTRL:
554: if ((s->rtc.ctrl ^ value) & 1) { /* RTC_EN */
555: if (value & 1)
556: menelaus_rtc_start(s);
557: else
558: menelaus_rtc_stop(s);
559: }
560: s->rtc.ctrl = value & 0x1f;
561: menelaus_alm_update(s);
562: break;
563: case MENELAUS_RTC_UPDATE:
564: menelaus_rtc_update(s);
565: memcpy(&tm, &s->rtc.tm, sizeof(tm));
566: switch (value & 0xf) {
567: case 0:
568: break;
569: case 1:
570: tm.tm_sec = s->rtc.new.tm_sec;
571: break;
572: case 2:
573: tm.tm_min = s->rtc.new.tm_min;
574: break;
575: case 3:
576: if (s->rtc.new.tm_hour > 23)
577: goto rtc_badness;
578: tm.tm_hour = s->rtc.new.tm_hour;
579: break;
580: case 4:
581: if (s->rtc.new.tm_mday < 1)
582: goto rtc_badness;
583: /* TODO check range */
584: tm.tm_mday = s->rtc.new.tm_mday;
585: break;
586: case 5:
587: if (s->rtc.new.tm_mon < 0 || s->rtc.new.tm_mon > 11)
588: goto rtc_badness;
589: tm.tm_mon = s->rtc.new.tm_mon;
590: break;
591: case 6:
592: tm.tm_year = s->rtc.new.tm_year;
593: break;
594: case 7:
595: /* TODO set .tm_mday instead */
596: tm.tm_wday = s->rtc.new.tm_wday;
597: break;
598: case 8:
599: if (s->rtc.new.tm_hour > 23)
600: goto rtc_badness;
601: if (s->rtc.new.tm_mday < 1)
602: goto rtc_badness;
603: if (s->rtc.new.tm_mon < 0 || s->rtc.new.tm_mon > 11)
604: goto rtc_badness;
605: tm.tm_sec = s->rtc.new.tm_sec;
606: tm.tm_min = s->rtc.new.tm_min;
607: tm.tm_hour = s->rtc.new.tm_hour;
608: tm.tm_mday = s->rtc.new.tm_mday;
609: tm.tm_mon = s->rtc.new.tm_mon;
610: tm.tm_year = s->rtc.new.tm_year;
611: break;
612: rtc_badness:
613: default:
614: fprintf(stderr, "%s: bad RTC_UPDATE value %02x\n",
615: __FUNCTION__, value);
616: s->status |= 1 << 10; /* RTCERR */
617: menelaus_update(s);
618: }
619: s->rtc.sec_offset = qemu_timedate_diff(&tm);
620: break;
621: case MENELAUS_RTC_SEC:
622: s->rtc.tm.tm_sec = from_bcd(value & 0x7f);
623: break;
624: case MENELAUS_RTC_MIN:
625: s->rtc.tm.tm_min = from_bcd(value & 0x7f);
626: break;
627: case MENELAUS_RTC_HR:
628: s->rtc.tm.tm_hour = (s->rtc.ctrl & (1 << 2)) ? /* MODE12_n24 */
629: MIN(from_bcd(value & 0x3f), 12) + ((value >> 7) ? 11 : -1) :
630: from_bcd(value & 0x3f);
631: break;
632: case MENELAUS_RTC_DAY:
633: s->rtc.tm.tm_mday = from_bcd(value);
634: break;
635: case MENELAUS_RTC_MON:
636: s->rtc.tm.tm_mon = MAX(1, from_bcd(value)) - 1;
637: break;
638: case MENELAUS_RTC_YR:
639: s->rtc.tm.tm_year = 2000 + from_bcd(value);
640: break;
641: case MENELAUS_RTC_WKDAY:
642: s->rtc.tm.tm_mday = from_bcd(value);
643: break;
644: case MENELAUS_RTC_AL_SEC:
645: s->rtc.alm.tm_sec = from_bcd(value & 0x7f);
646: menelaus_alm_update(s);
647: break;
648: case MENELAUS_RTC_AL_MIN:
649: s->rtc.alm.tm_min = from_bcd(value & 0x7f);
650: menelaus_alm_update(s);
651: break;
652: case MENELAUS_RTC_AL_HR:
653: s->rtc.alm.tm_hour = (s->rtc.ctrl & (1 << 2)) ? /* MODE12_n24 */
654: MIN(from_bcd(value & 0x3f), 12) + ((value >> 7) ? 11 : -1) :
655: from_bcd(value & 0x3f);
656: menelaus_alm_update(s);
657: break;
658: case MENELAUS_RTC_AL_DAY:
659: s->rtc.alm.tm_mday = from_bcd(value);
660: menelaus_alm_update(s);
661: break;
662: case MENELAUS_RTC_AL_MON:
663: s->rtc.alm.tm_mon = MAX(1, from_bcd(value)) - 1;
664: menelaus_alm_update(s);
665: break;
666: case MENELAUS_RTC_AL_YR:
667: s->rtc.alm.tm_year = 2000 + from_bcd(value);
668: menelaus_alm_update(s);
669: break;
670: case MENELAUS_RTC_COMP_MSB:
671: s->rtc.comp &= 0xff;
672: s->rtc.comp |= value << 8;
673: break;
674: case MENELAUS_RTC_COMP_LSB:
675: s->rtc.comp &= 0xff << 8;
676: s->rtc.comp |= value;
677: break;
678:
679: case MENELAUS_S1_PULL_EN:
680: s->pull[0] = value;
681: break;
682: case MENELAUS_S1_PULL_DIR:
683: s->pull[1] = value & 0x1f;
684: break;
685: case MENELAUS_S2_PULL_EN:
686: s->pull[2] = value;
687: break;
688: case MENELAUS_S2_PULL_DIR:
689: s->pull[3] = value & 0x1f;
690: break;
691:
692: case MENELAUS_MCT_CTRL1:
693: s->mmc_ctrl[0] = value & 0x7f;
694: break;
695: case MENELAUS_MCT_CTRL2:
696: s->mmc_ctrl[1] = value;
697: /* TODO update Card Detect interrupts */
698: break;
699: case MENELAUS_MCT_CTRL3:
700: s->mmc_ctrl[2] = value & 0xf;
701: break;
702: case MENELAUS_DEBOUNCE1:
703: s->mmc_debounce = value & 0x3f;
704: break;
705:
706: default:
707: #ifdef VERBOSE
708: printf("%s: unknown register %02x\n", __FUNCTION__, addr);
709: #endif
710: }
711: }
712:
713: static void menelaus_event(i2c_slave *i2c, enum i2c_event event)
714: {
1.1.1.2 root 715: MenelausState *s = (MenelausState *) i2c;
1.1 root 716:
717: if (event == I2C_START_SEND)
718: s->firstbyte = 1;
719: }
720:
721: static int menelaus_tx(i2c_slave *i2c, uint8_t data)
722: {
1.1.1.2 root 723: MenelausState *s = (MenelausState *) i2c;
1.1 root 724: /* Interpret register address byte */
725: if (s->firstbyte) {
726: s->reg = data;
727: s->firstbyte = 0;
728: } else
729: menelaus_write(s, s->reg ++, data);
730:
731: return 0;
732: }
733:
734: static int menelaus_rx(i2c_slave *i2c)
735: {
1.1.1.2 root 736: MenelausState *s = (MenelausState *) i2c;
1.1 root 737:
738: return menelaus_read(s, s->reg ++);
739: }
740:
1.1.1.3 ! root 741: /* Save restore 32 bit int as uint16_t
! 742: This is a Big hack, but it is how the old state did it.
! 743: Or we broke compatibility in the state, or we can't use struct tm
! 744: */
! 745:
! 746: static int get_int32_as_uint16(QEMUFile *f, void *pv, size_t size)
! 747: {
! 748: int *v = pv;
! 749: *v = qemu_get_be16(f);
! 750: return 0;
1.1 root 751: }
752:
1.1.1.3 ! root 753: static void put_int32_as_uint16(QEMUFile *f, void *pv, size_t size)
1.1 root 754: {
1.1.1.3 ! root 755: int *v = pv;
! 756: qemu_put_be16(f, *v);
! 757: }
1.1 root 758:
1.1.1.3 ! root 759: static const VMStateInfo vmstate_hack_int32_as_uint16 = {
! 760: .name = "int32_as_uint16",
! 761: .get = get_int32_as_uint16,
! 762: .put = put_int32_as_uint16,
! 763: };
1.1 root 764:
1.1.1.3 ! root 765: #define VMSTATE_UINT16_HACK(_f, _s) \
! 766: VMSTATE_SINGLE(_f, _s, 0, vmstate_hack_int32_as_uint16, int32_t)
1.1 root 767:
768:
1.1.1.3 ! root 769: static const VMStateDescription vmstate_menelaus_tm = {
! 770: .name = "menelaus_tm",
! 771: .version_id = 0,
! 772: .minimum_version_id = 0,
! 773: .minimum_version_id_old = 0,
! 774: .fields = (VMStateField []) {
! 775: VMSTATE_UINT16_HACK(tm_sec, struct tm),
! 776: VMSTATE_UINT16_HACK(tm_min, struct tm),
! 777: VMSTATE_UINT16_HACK(tm_hour, struct tm),
! 778: VMSTATE_UINT16_HACK(tm_mday, struct tm),
! 779: VMSTATE_UINT16_HACK(tm_min, struct tm),
! 780: VMSTATE_UINT16_HACK(tm_year, struct tm),
! 781: VMSTATE_END_OF_LIST()
! 782: }
! 783: };
! 784:
! 785: static void menelaus_pre_save(void *opaque)
1.1 root 786: {
1.1.1.3 ! root 787: MenelausState *s = opaque;
! 788: /* Should be <= 1000 */
! 789: s->rtc_next_vmstate = s->rtc.next - qemu_get_clock(rt_clock);
! 790: }
1.1 root 791:
1.1.1.3 ! root 792: static int menelaus_post_load(void *opaque, int version_id)
! 793: {
! 794: MenelausState *s = opaque;
1.1 root 795:
796: if (s->rtc.ctrl & 1) /* RTC_EN */
797: menelaus_rtc_stop(s);
1.1.1.3 ! root 798:
! 799: s->rtc.next = s->rtc_next_vmstate;
! 800:
1.1 root 801: menelaus_alm_update(s);
802: menelaus_update(s);
803: if (s->rtc.ctrl & 1) /* RTC_EN */
804: menelaus_rtc_start(s);
805: return 0;
806: }
807:
1.1.1.3 ! root 808: static const VMStateDescription vmstate_menelaus = {
! 809: .name = "menelaus",
! 810: .version_id = 0,
! 811: .minimum_version_id = 0,
! 812: .minimum_version_id_old = 0,
! 813: .pre_save = menelaus_pre_save,
! 814: .post_load = menelaus_post_load,
! 815: .fields = (VMStateField []) {
! 816: VMSTATE_INT32(firstbyte, MenelausState),
! 817: VMSTATE_UINT8(reg, MenelausState),
! 818: VMSTATE_UINT8_ARRAY(vcore, MenelausState, 5),
! 819: VMSTATE_UINT8_ARRAY(dcdc, MenelausState, 3),
! 820: VMSTATE_UINT8_ARRAY(ldo, MenelausState, 8),
! 821: VMSTATE_UINT8_ARRAY(sleep, MenelausState, 2),
! 822: VMSTATE_UINT8(osc, MenelausState),
! 823: VMSTATE_UINT8(detect, MenelausState),
! 824: VMSTATE_UINT16(mask, MenelausState),
! 825: VMSTATE_UINT16(status, MenelausState),
! 826: VMSTATE_UINT8(dir, MenelausState),
! 827: VMSTATE_UINT8(inputs, MenelausState),
! 828: VMSTATE_UINT8(outputs, MenelausState),
! 829: VMSTATE_UINT8(bbsms, MenelausState),
! 830: VMSTATE_UINT8_ARRAY(pull, MenelausState, 4),
! 831: VMSTATE_UINT8_ARRAY(mmc_ctrl, MenelausState, 3),
! 832: VMSTATE_UINT8(mmc_debounce, MenelausState),
! 833: VMSTATE_UINT8(rtc.ctrl, MenelausState),
! 834: VMSTATE_UINT16(rtc.comp, MenelausState),
! 835: VMSTATE_UINT16(rtc_next_vmstate, MenelausState),
! 836: VMSTATE_STRUCT(rtc.new, MenelausState, 0, vmstate_menelaus_tm,
! 837: struct tm),
! 838: VMSTATE_STRUCT(rtc.alm, MenelausState, 0, vmstate_menelaus_tm,
! 839: struct tm),
! 840: VMSTATE_UINT8(pwrbtn_state, MenelausState),
! 841: VMSTATE_I2C_SLAVE(i2c, MenelausState),
! 842: VMSTATE_END_OF_LIST()
! 843: }
! 844: };
! 845:
! 846: static int twl92230_init(i2c_slave *i2c)
1.1 root 847: {
1.1.1.2 root 848: MenelausState *s = FROM_I2C_SLAVE(MenelausState, i2c);
1.1 root 849:
850: s->rtc.hz_tm = qemu_new_timer(rt_clock, menelaus_rtc_hz, s);
1.1.1.2 root 851: /* Three output pins plus one interrupt pin. */
852: qdev_init_gpio_out(&i2c->qdev, s->out, 4);
853: qdev_init_gpio_in(&i2c->qdev, menelaus_gpio_set, 3);
1.1 root 854: s->pwrbtn = qemu_allocate_irqs(menelaus_pwrbtn_set, s, 1)[0];
855:
856: menelaus_reset(&s->i2c);
857:
1.1.1.3 ! root 858: return 0;
1.1 root 859: }
860:
1.1.1.2 root 861: static I2CSlaveInfo twl92230_info = {
862: .qdev.name ="twl92230",
863: .qdev.size = sizeof(MenelausState),
1.1.1.3 ! root 864: .qdev.vmsd = &vmstate_menelaus,
1.1.1.2 root 865: .init = twl92230_init,
866: .event = menelaus_event,
867: .recv = menelaus_rx,
868: .send = menelaus_tx
869: };
1.1 root 870:
1.1.1.2 root 871: static void twl92230_register_devices(void)
1.1 root 872: {
1.1.1.2 root 873: i2c_register_slave(&twl92230_info);
1.1 root 874: }
1.1.1.2 root 875:
876: device_init(twl92230_register_devices)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.