Add PowerPC power-management state check callback.
[qemu] / hw / m48t59.c
1 /*
2  * QEMU M48T59 and M48T08 NVRAM emulation for PPC PREP and Sparc platforms
3  *
4  * Copyright (c) 2003-2005, 2007 Jocelyn Mayer
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #include "vl.h"
25 #include "m48t59.h"
26
27 //#define DEBUG_NVRAM
28
29 #if defined(DEBUG_NVRAM)
30 #define NVRAM_PRINTF(fmt, args...) do { printf(fmt , ##args); } while (0)
31 #else
32 #define NVRAM_PRINTF(fmt, args...) do { } while (0)
33 #endif
34
35 /*
36  * The M48T08 and M48T59 chips are very similar. The newer '59 has
37  * alarm and a watchdog timer and related control registers. In the
38  * PPC platform there is also a nvram lock function.
39  */
40 struct m48t59_t {
41     /* Model parameters */
42     int type; // 8 = m48t08, 59 = m48t59
43     /* Hardware parameters */
44     qemu_irq IRQ;
45     int mem_index;
46     target_phys_addr_t mem_base;
47     uint32_t io_base;
48     uint16_t size;
49     /* RTC management */
50     time_t   time_offset;
51     time_t   stop_time;
52     /* Alarm & watchdog */
53     time_t   alarm;
54     struct QEMUTimer *alrm_timer;
55     struct QEMUTimer *wd_timer;
56     /* NVRAM storage */
57     uint8_t  lock;
58     uint16_t addr;
59     uint8_t *buffer;
60 };
61
62 /* Fake timer functions */
63 /* Generic helpers for BCD */
64 static inline uint8_t toBCD (uint8_t value)
65 {
66     return (((value / 10) % 10) << 4) | (value % 10);
67 }
68
69 static inline uint8_t fromBCD (uint8_t BCD)
70 {
71     return ((BCD >> 4) * 10) + (BCD & 0x0F);
72 }
73
74 /* RTC management helpers */
75 static void get_time (m48t59_t *NVRAM, struct tm *tm)
76 {
77     time_t t;
78
79     t = time(NULL) + NVRAM->time_offset;
80 #ifdef _WIN32
81     memcpy(tm,localtime(&t),sizeof(*tm));
82 #else
83     if (rtc_utc)
84         gmtime_r (&t, tm);
85     else
86         localtime_r (&t, tm) ;
87 #endif
88 }
89
90 static void set_time (m48t59_t *NVRAM, struct tm *tm)
91 {
92     time_t now, new_time;
93
94     new_time = mktime(tm);
95     now = time(NULL);
96     NVRAM->time_offset = new_time - now;
97 }
98
99 /* Alarm management */
100 static void alarm_cb (void *opaque)
101 {
102     struct tm tm, tm_now;
103     uint64_t next_time;
104     m48t59_t *NVRAM = opaque;
105
106     qemu_set_irq(NVRAM->IRQ, 1);
107     if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 &&
108         (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
109         (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
110         (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
111         /* Repeat once a month */
112         get_time(NVRAM, &tm_now);
113         memcpy(&tm, &tm_now, sizeof(struct tm));
114         tm.tm_mon++;
115         if (tm.tm_mon == 13) {
116             tm.tm_mon = 1;
117             tm.tm_year++;
118         }
119         next_time = mktime(&tm);
120     } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
121                (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
122                (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
123                (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
124         /* Repeat once a day */
125         next_time = 24 * 60 * 60 + mktime(&tm_now);
126     } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
127                (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
128                (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
129                (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
130         /* Repeat once an hour */
131         next_time = 60 * 60 + mktime(&tm_now);
132     } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
133                (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
134                (NVRAM->buffer[0x1FF3] & 0x80) != 0 &&
135                (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
136         /* Repeat once a minute */
137         next_time = 60 + mktime(&tm_now);
138     } else {
139         /* Repeat once a second */
140         next_time = 1 + mktime(&tm_now);
141     }
142     qemu_mod_timer(NVRAM->alrm_timer, next_time * 1000);
143     qemu_set_irq(NVRAM->IRQ, 0);
144 }
145
146
147 static void get_alarm (m48t59_t *NVRAM, struct tm *tm)
148 {
149 #ifdef _WIN32
150     memcpy(tm,localtime(&NVRAM->alarm),sizeof(*tm));
151 #else
152     if (rtc_utc)
153         gmtime_r (&NVRAM->alarm, tm);
154     else
155         localtime_r (&NVRAM->alarm, tm);
156 #endif
157 }
158
159 static void set_alarm (m48t59_t *NVRAM, struct tm *tm)
160 {
161     NVRAM->alarm = mktime(tm);
162     if (NVRAM->alrm_timer != NULL) {
163         qemu_del_timer(NVRAM->alrm_timer);
164         if (NVRAM->alarm - time(NULL) > 0)
165             qemu_mod_timer(NVRAM->alrm_timer, NVRAM->alarm * 1000);
166     }
167 }
168
169 /* Watchdog management */
170 static void watchdog_cb (void *opaque)
171 {
172     m48t59_t *NVRAM = opaque;
173
174     NVRAM->buffer[0x1FF0] |= 0x80;
175     if (NVRAM->buffer[0x1FF7] & 0x80) {
176         NVRAM->buffer[0x1FF7] = 0x00;
177         NVRAM->buffer[0x1FFC] &= ~0x40;
178         /* May it be a hw CPU Reset instead ? */
179         qemu_system_reset_request();
180     } else {
181         qemu_set_irq(NVRAM->IRQ, 1);
182         qemu_set_irq(NVRAM->IRQ, 0);
183     }
184 }
185
186 static void set_up_watchdog (m48t59_t *NVRAM, uint8_t value)
187 {
188     uint64_t interval; /* in 1/16 seconds */
189
190     NVRAM->buffer[0x1FF0] &= ~0x80;
191     if (NVRAM->wd_timer != NULL) {
192         qemu_del_timer(NVRAM->wd_timer);
193         if (value != 0) {
194             interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F);
195             qemu_mod_timer(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) +
196                            ((interval * 1000) >> 4));
197         }
198     }
199 }
200
201 /* Direct access to NVRAM */
202 void m48t59_write (m48t59_t *NVRAM, uint32_t addr, uint32_t val)
203 {
204     struct tm tm;
205     int tmp;
206
207     if (addr > 0x1FF8 && addr < 0x2000)
208         NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
209     if (NVRAM->type == 8 &&
210         (addr >= 0x1ff0 && addr <= 0x1ff7))
211         goto do_write;
212     switch (addr) {
213     case 0x1FF0:
214         /* flags register : read-only */
215         break;
216     case 0x1FF1:
217         /* unused */
218         break;
219     case 0x1FF2:
220         /* alarm seconds */
221         tmp = fromBCD(val & 0x7F);
222         if (tmp >= 0 && tmp <= 59) {
223             get_alarm(NVRAM, &tm);
224             tm.tm_sec = tmp;
225             NVRAM->buffer[0x1FF2] = val;
226             set_alarm(NVRAM, &tm);
227         }
228         break;
229     case 0x1FF3:
230         /* alarm minutes */
231         tmp = fromBCD(val & 0x7F);
232         if (tmp >= 0 && tmp <= 59) {
233             get_alarm(NVRAM, &tm);
234             tm.tm_min = tmp;
235             NVRAM->buffer[0x1FF3] = val;
236             set_alarm(NVRAM, &tm);
237         }
238         break;
239     case 0x1FF4:
240         /* alarm hours */
241         tmp = fromBCD(val & 0x3F);
242         if (tmp >= 0 && tmp <= 23) {
243             get_alarm(NVRAM, &tm);
244             tm.tm_hour = tmp;
245             NVRAM->buffer[0x1FF4] = val;
246             set_alarm(NVRAM, &tm);
247         }
248         break;
249     case 0x1FF5:
250         /* alarm date */
251         tmp = fromBCD(val & 0x1F);
252         if (tmp != 0) {
253             get_alarm(NVRAM, &tm);
254             tm.tm_mday = tmp;
255             NVRAM->buffer[0x1FF5] = val;
256             set_alarm(NVRAM, &tm);
257         }
258         break;
259     case 0x1FF6:
260         /* interrupts */
261         NVRAM->buffer[0x1FF6] = val;
262         break;
263     case 0x1FF7:
264         /* watchdog */
265         NVRAM->buffer[0x1FF7] = val;
266         set_up_watchdog(NVRAM, val);
267         break;
268     case 0x1FF8:
269         /* control */
270         NVRAM->buffer[0x1FF8] = (val & ~0xA0) | 0x90;
271         break;
272     case 0x1FF9:
273         /* seconds (BCD) */
274         tmp = fromBCD(val & 0x7F);
275         if (tmp >= 0 && tmp <= 59) {
276             get_time(NVRAM, &tm);
277             tm.tm_sec = tmp;
278             set_time(NVRAM, &tm);
279         }
280         if ((val & 0x80) ^ (NVRAM->buffer[0x1FF9] & 0x80)) {
281             if (val & 0x80) {
282                 NVRAM->stop_time = time(NULL);
283             } else {
284                 NVRAM->time_offset += NVRAM->stop_time - time(NULL);
285                 NVRAM->stop_time = 0;
286             }
287         }
288         NVRAM->buffer[0x1FF9] = val & 0x80;
289         break;
290     case 0x1FFA:
291         /* minutes (BCD) */
292         tmp = fromBCD(val & 0x7F);
293         if (tmp >= 0 && tmp <= 59) {
294             get_time(NVRAM, &tm);
295             tm.tm_min = tmp;
296             set_time(NVRAM, &tm);
297         }
298         break;
299     case 0x1FFB:
300         /* hours (BCD) */
301         tmp = fromBCD(val & 0x3F);
302         if (tmp >= 0 && tmp <= 23) {
303             get_time(NVRAM, &tm);
304             tm.tm_hour = tmp;
305             set_time(NVRAM, &tm);
306         }
307         break;
308     case 0x1FFC:
309         /* day of the week / century */
310         tmp = fromBCD(val & 0x07);
311         get_time(NVRAM, &tm);
312         tm.tm_wday = tmp;
313         set_time(NVRAM, &tm);
314         NVRAM->buffer[0x1FFC] = val & 0x40;
315         break;
316     case 0x1FFD:
317         /* date */
318         tmp = fromBCD(val & 0x1F);
319         if (tmp != 0) {
320             get_time(NVRAM, &tm);
321             tm.tm_mday = tmp;
322             set_time(NVRAM, &tm);
323         }
324         break;
325     case 0x1FFE:
326         /* month */
327         tmp = fromBCD(val & 0x1F);
328         if (tmp >= 1 && tmp <= 12) {
329             get_time(NVRAM, &tm);
330             tm.tm_mon = tmp - 1;
331             set_time(NVRAM, &tm);
332         }
333         break;
334     case 0x1FFF:
335         /* year */
336         tmp = fromBCD(val);
337         if (tmp >= 0 && tmp <= 99) {
338             get_time(NVRAM, &tm);
339             if (NVRAM->type == 8)
340                 tm.tm_year = fromBCD(val) + 68; // Base year is 1968
341             else
342                 tm.tm_year = fromBCD(val);
343             set_time(NVRAM, &tm);
344         }
345         break;
346     default:
347         /* Check lock registers state */
348         if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1))
349             break;
350         if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2))
351             break;
352     do_write:
353         if (addr < NVRAM->size) {
354             NVRAM->buffer[addr] = val & 0xFF;
355         }
356         break;
357     }
358 }
359
360 uint32_t m48t59_read (m48t59_t *NVRAM, uint32_t addr)
361 {
362     struct tm tm;
363     uint32_t retval = 0xFF;
364
365     if (NVRAM->type == 8 &&
366         (addr >= 0x1ff0 && addr <= 0x1ff7))
367         goto do_read;
368     switch (addr) {
369     case 0x1FF0:
370         /* flags register */
371         goto do_read;
372     case 0x1FF1:
373         /* unused */
374         retval = 0;
375         break;
376     case 0x1FF2:
377         /* alarm seconds */
378         goto do_read;
379     case 0x1FF3:
380         /* alarm minutes */
381         goto do_read;
382     case 0x1FF4:
383         /* alarm hours */
384         goto do_read;
385     case 0x1FF5:
386         /* alarm date */
387         goto do_read;
388     case 0x1FF6:
389         /* interrupts */
390         goto do_read;
391     case 0x1FF7:
392         /* A read resets the watchdog */
393         set_up_watchdog(NVRAM, NVRAM->buffer[0x1FF7]);
394         goto do_read;
395     case 0x1FF8:
396         /* control */
397         goto do_read;
398     case 0x1FF9:
399         /* seconds (BCD) */
400         get_time(NVRAM, &tm);
401         retval = (NVRAM->buffer[0x1FF9] & 0x80) | toBCD(tm.tm_sec);
402         break;
403     case 0x1FFA:
404         /* minutes (BCD) */
405         get_time(NVRAM, &tm);
406         retval = toBCD(tm.tm_min);
407         break;
408     case 0x1FFB:
409         /* hours (BCD) */
410         get_time(NVRAM, &tm);
411         retval = toBCD(tm.tm_hour);
412         break;
413     case 0x1FFC:
414         /* day of the week / century */
415         get_time(NVRAM, &tm);
416         retval = NVRAM->buffer[0x1FFC] | tm.tm_wday;
417         break;
418     case 0x1FFD:
419         /* date */
420         get_time(NVRAM, &tm);
421         retval = toBCD(tm.tm_mday);
422         break;
423     case 0x1FFE:
424         /* month */
425         get_time(NVRAM, &tm);
426         retval = toBCD(tm.tm_mon + 1);
427         break;
428     case 0x1FFF:
429         /* year */
430         get_time(NVRAM, &tm);
431         if (NVRAM->type == 8)
432             retval = toBCD(tm.tm_year - 68); // Base year is 1968
433         else
434             retval = toBCD(tm.tm_year);
435         break;
436     default:
437         /* Check lock registers state */
438         if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1))
439             break;
440         if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2))
441             break;
442     do_read:
443         if (addr < NVRAM->size) {
444             retval = NVRAM->buffer[addr];
445         }
446         break;
447     }
448     if (addr > 0x1FF9 && addr < 0x2000)
449         NVRAM_PRINTF("0x%08x <= 0x%08x\n", addr, retval);
450
451     return retval;
452 }
453
454 void m48t59_set_addr (m48t59_t *NVRAM, uint32_t addr)
455 {
456     NVRAM->addr = addr;
457 }
458
459 void m48t59_toggle_lock (m48t59_t *NVRAM, int lock)
460 {
461     NVRAM->lock ^= 1 << lock;
462 }
463
464 /* IO access to NVRAM */
465 static void NVRAM_writeb (void *opaque, uint32_t addr, uint32_t val)
466 {
467     m48t59_t *NVRAM = opaque;
468
469     addr -= NVRAM->io_base;
470     NVRAM_PRINTF("0x%08x => 0x%08x\n", addr, val);
471     switch (addr) {
472     case 0:
473         NVRAM->addr &= ~0x00FF;
474         NVRAM->addr |= val;
475         break;
476     case 1:
477         NVRAM->addr &= ~0xFF00;
478         NVRAM->addr |= val << 8;
479         break;
480     case 3:
481         m48t59_write(NVRAM, val, NVRAM->addr);
482         NVRAM->addr = 0x0000;
483         break;
484     default:
485         break;
486     }
487 }
488
489 static uint32_t NVRAM_readb (void *opaque, uint32_t addr)
490 {
491     m48t59_t *NVRAM = opaque;
492     uint32_t retval;
493
494     addr -= NVRAM->io_base;
495     switch (addr) {
496     case 3:
497         retval = m48t59_read(NVRAM, NVRAM->addr);
498         break;
499     default:
500         retval = -1;
501         break;
502     }
503     NVRAM_PRINTF("0x%08x <= 0x%08x\n", addr, retval);
504
505     return retval;
506 }
507
508 static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
509 {
510     m48t59_t *NVRAM = opaque;
511
512     addr -= NVRAM->mem_base;
513     m48t59_write(NVRAM, addr, value & 0xff);
514 }
515
516 static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
517 {
518     m48t59_t *NVRAM = opaque;
519
520     addr -= NVRAM->mem_base;
521     m48t59_write(NVRAM, addr, (value >> 8) & 0xff);
522     m48t59_write(NVRAM, addr + 1, value & 0xff);
523 }
524
525 static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
526 {
527     m48t59_t *NVRAM = opaque;
528
529     addr -= NVRAM->mem_base;
530     m48t59_write(NVRAM, addr, (value >> 24) & 0xff);
531     m48t59_write(NVRAM, addr + 1, (value >> 16) & 0xff);
532     m48t59_write(NVRAM, addr + 2, (value >> 8) & 0xff);
533     m48t59_write(NVRAM, addr + 3, value & 0xff);
534 }
535
536 static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
537 {
538     m48t59_t *NVRAM = opaque;
539     uint32_t retval;
540
541     addr -= NVRAM->mem_base;
542     retval = m48t59_read(NVRAM, addr);
543     return retval;
544 }
545
546 static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr)
547 {
548     m48t59_t *NVRAM = opaque;
549     uint32_t retval;
550
551     addr -= NVRAM->mem_base;
552     retval = m48t59_read(NVRAM, addr) << 8;
553     retval |= m48t59_read(NVRAM, addr + 1);
554     return retval;
555 }
556
557 static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
558 {
559     m48t59_t *NVRAM = opaque;
560     uint32_t retval;
561
562     addr -= NVRAM->mem_base;
563     retval = m48t59_read(NVRAM, addr) << 24;
564     retval |= m48t59_read(NVRAM, addr + 1) << 16;
565     retval |= m48t59_read(NVRAM, addr + 2) << 8;
566     retval |= m48t59_read(NVRAM, addr + 3);
567     return retval;
568 }
569
570 static CPUWriteMemoryFunc *nvram_write[] = {
571     &nvram_writeb,
572     &nvram_writew,
573     &nvram_writel,
574 };
575
576 static CPUReadMemoryFunc *nvram_read[] = {
577     &nvram_readb,
578     &nvram_readw,
579     &nvram_readl,
580 };
581
582 static void m48t59_save(QEMUFile *f, void *opaque)
583 {
584     m48t59_t *s = opaque;
585
586     qemu_put_8s(f, &s->lock);
587     qemu_put_be16s(f, &s->addr);
588     qemu_put_buffer(f, s->buffer, s->size);
589 }
590
591 static int m48t59_load(QEMUFile *f, void *opaque, int version_id)
592 {
593     m48t59_t *s = opaque;
594
595     if (version_id != 1)
596         return -EINVAL;
597
598     qemu_get_8s(f, &s->lock);
599     qemu_get_be16s(f, &s->addr);
600     qemu_get_buffer(f, s->buffer, s->size);
601
602     return 0;
603 }
604
605 static void m48t59_reset(void *opaque)
606 {
607     m48t59_t *NVRAM = opaque;
608
609     if (NVRAM->alrm_timer != NULL)
610         qemu_del_timer(NVRAM->alrm_timer);
611
612     if (NVRAM->wd_timer != NULL)
613         qemu_del_timer(NVRAM->wd_timer);
614 }
615
616 /* Initialisation routine */
617 m48t59_t *m48t59_init (qemu_irq IRQ, target_phys_addr_t mem_base,
618                        uint32_t io_base, uint16_t size,
619                        int type)
620 {
621     m48t59_t *s;
622     target_phys_addr_t save_base;
623
624     s = qemu_mallocz(sizeof(m48t59_t));
625     if (!s)
626         return NULL;
627     s->buffer = qemu_mallocz(size);
628     if (!s->buffer) {
629         qemu_free(s);
630         return NULL;
631     }
632     s->IRQ = IRQ;
633     s->size = size;
634     s->mem_base = mem_base;
635     s->io_base = io_base;
636     s->addr = 0;
637     s->type = type;
638     if (io_base != 0) {
639         register_ioport_read(io_base, 0x04, 1, NVRAM_readb, s);
640         register_ioport_write(io_base, 0x04, 1, NVRAM_writeb, s);
641     }
642     if (mem_base != 0) {
643         s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
644         cpu_register_physical_memory(mem_base, 0x4000, s->mem_index);
645     }
646     if (type == 59) {
647         s->alrm_timer = qemu_new_timer(vm_clock, &alarm_cb, s);
648         s->wd_timer = qemu_new_timer(vm_clock, &watchdog_cb, s);
649     }
650     s->lock = 0;
651
652     qemu_register_reset(m48t59_reset, s);
653     save_base = mem_base ? mem_base : io_base;
654     register_savevm("m48t59", save_base, 1, m48t59_save, m48t59_load, s);
655
656     return s;
657 }