1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "qemu/osdep.h"
22#include "qapi/error.h"
23#include "qemu-common.h"
24#include "cpu.h"
25#include "sysemu/block-backend.h"
26#include "sysemu/blockdev.h"
27#include "hw/boards.h"
28#include "hw/hw.h"
29#include "hw/arm/arm.h"
30#include "hw/arm/omap.h"
31#include "sysemu/sysemu.h"
32#include "qemu/timer.h"
33#include "sysemu/char.h"
34#include "hw/block/flash.h"
35#include "hw/arm/soc_dma.h"
36#include "hw/sysbus.h"
37#include "audio/audio.h"
38
39
40struct omap_eac_s {
41 qemu_irq irq;
42 MemoryRegion iomem;
43
44 uint16_t sysconfig;
45 uint8_t config[4];
46 uint8_t control;
47 uint8_t address;
48 uint16_t data;
49 uint8_t vtol;
50 uint8_t vtsl;
51 uint16_t mixer;
52 uint16_t gain[4];
53 uint8_t att;
54 uint16_t max[7];
55
56 struct {
57 qemu_irq txdrq;
58 qemu_irq rxdrq;
59 uint32_t (*txrx)(void *opaque, uint32_t, int);
60 void *opaque;
61
62#define EAC_BUF_LEN 1024
63 uint32_t rxbuf[EAC_BUF_LEN];
64 int rxoff;
65 int rxlen;
66 int rxavail;
67 uint32_t txbuf[EAC_BUF_LEN];
68 int txlen;
69 int txavail;
70
71 int enable;
72 int rate;
73
74 uint16_t config[4];
75
76
77 QEMUSoundCard card;
78 SWVoiceIn *in_voice;
79 SWVoiceOut *out_voice;
80 int hw_enable;
81 } codec;
82
83 struct {
84 uint8_t control;
85 uint16_t config;
86 } modem, bt;
87};
88
89static inline void omap_eac_interrupt_update(struct omap_eac_s *s)
90{
91 qemu_set_irq(s->irq, (s->codec.config[1] >> 14) & 1);
92}
93
94static inline void omap_eac_in_dmarequest_update(struct omap_eac_s *s)
95{
96 qemu_set_irq(s->codec.rxdrq, (s->codec.rxavail || s->codec.rxlen) &&
97 ((s->codec.config[1] >> 12) & 1));
98}
99
100static inline void omap_eac_out_dmarequest_update(struct omap_eac_s *s)
101{
102 qemu_set_irq(s->codec.txdrq, s->codec.txlen < s->codec.txavail &&
103 ((s->codec.config[1] >> 11) & 1));
104}
105
106static inline void omap_eac_in_refill(struct omap_eac_s *s)
107{
108 int left = MIN(EAC_BUF_LEN - s->codec.rxlen, s->codec.rxavail) << 2;
109 int start = ((s->codec.rxoff + s->codec.rxlen) & (EAC_BUF_LEN - 1)) << 2;
110 int leftwrap = MIN(left, (EAC_BUF_LEN << 2) - start);
111 int recv = 1;
112 uint8_t *buf = (uint8_t *) s->codec.rxbuf + start;
113
114 left -= leftwrap;
115 start = 0;
116 while (leftwrap && (recv = AUD_read(s->codec.in_voice, buf + start,
117 leftwrap)) > 0) {
118 start += recv;
119 leftwrap -= recv;
120 }
121 if (recv <= 0)
122 s->codec.rxavail = 0;
123 else
124 s->codec.rxavail -= start >> 2;
125 s->codec.rxlen += start >> 2;
126
127 if (recv > 0 && left > 0) {
128 start = 0;
129 while (left && (recv = AUD_read(s->codec.in_voice,
130 (uint8_t *) s->codec.rxbuf + start,
131 left)) > 0) {
132 start += recv;
133 left -= recv;
134 }
135 if (recv <= 0)
136 s->codec.rxavail = 0;
137 else
138 s->codec.rxavail -= start >> 2;
139 s->codec.rxlen += start >> 2;
140 }
141}
142
143static inline void omap_eac_out_empty(struct omap_eac_s *s)
144{
145 int left = s->codec.txlen << 2;
146 int start = 0;
147 int sent = 1;
148
149 while (left && (sent = AUD_write(s->codec.out_voice,
150 (uint8_t *) s->codec.txbuf + start,
151 left)) > 0) {
152 start += sent;
153 left -= sent;
154 }
155
156 if (!sent) {
157 s->codec.txavail = 0;
158 omap_eac_out_dmarequest_update(s);
159 }
160
161 if (start)
162 s->codec.txlen = 0;
163}
164
165static void omap_eac_in_cb(void *opaque, int avail_b)
166{
167 struct omap_eac_s *s = (struct omap_eac_s *) opaque;
168
169 s->codec.rxavail = avail_b >> 2;
170 omap_eac_in_refill(s);
171
172 omap_eac_in_dmarequest_update(s);
173}
174
175static void omap_eac_out_cb(void *opaque, int free_b)
176{
177 struct omap_eac_s *s = (struct omap_eac_s *) opaque;
178
179 s->codec.txavail = free_b >> 2;
180 if (s->codec.txlen)
181 omap_eac_out_empty(s);
182 else
183 omap_eac_out_dmarequest_update(s);
184}
185
186static void omap_eac_enable_update(struct omap_eac_s *s)
187{
188 s->codec.enable = !(s->codec.config[1] & 1) &&
189 (s->codec.config[1] & 2) &&
190 s->codec.hw_enable;
191}
192
193static const int omap_eac_fsint[4] = {
194 8000,
195 11025,
196 22050,
197 44100,
198};
199
200static const int omap_eac_fsint2[8] = {
201 8000,
202 11025,
203 22050,
204 44100,
205 48000,
206 0, 0, 0,
207};
208
209static const int omap_eac_fsint3[16] = {
210 8000,
211 11025,
212 16000,
213 22050,
214 24000,
215 32000,
216 44100,
217 48000,
218 0, 0, 0, 0, 0, 0, 0, 0,
219};
220
221static void omap_eac_rate_update(struct omap_eac_s *s)
222{
223 int fsint[3];
224
225 fsint[2] = (s->codec.config[3] >> 9) & 0xf;
226 fsint[1] = (s->codec.config[2] >> 0) & 0x7;
227 fsint[0] = (s->codec.config[0] >> 6) & 0x3;
228 if (fsint[2] < 0xf)
229 s->codec.rate = omap_eac_fsint3[fsint[2]];
230 else if (fsint[1] < 0x7)
231 s->codec.rate = omap_eac_fsint2[fsint[1]];
232 else
233 s->codec.rate = omap_eac_fsint[fsint[0]];
234}
235
236static void omap_eac_volume_update(struct omap_eac_s *s)
237{
238
239}
240
241static void omap_eac_format_update(struct omap_eac_s *s)
242{
243 struct audsettings fmt;
244
245
246 if (s->codec.rxlen)
247 s->codec.rxlen = 1;
248
249 if (s->codec.in_voice) {
250 AUD_set_active_in(s->codec.in_voice, 0);
251 AUD_close_in(&s->codec.card, s->codec.in_voice);
252 s->codec.in_voice = NULL;
253 }
254 if (s->codec.out_voice) {
255 omap_eac_out_empty(s);
256 AUD_set_active_out(s->codec.out_voice, 0);
257 AUD_close_out(&s->codec.card, s->codec.out_voice);
258 s->codec.out_voice = NULL;
259 s->codec.txavail = 0;
260 }
261
262 s->codec.txlen = 0;
263
264 omap_eac_enable_update(s);
265 if (!s->codec.enable)
266 return;
267
268 omap_eac_rate_update(s);
269 fmt.endianness = ((s->codec.config[0] >> 8) & 1);
270 fmt.nchannels = ((s->codec.config[0] >> 10) & 1) ? 2 : 1;
271 fmt.freq = s->codec.rate;
272
273
274
275
276 fmt.fmt = AUD_FMT_U16;
277
278 s->codec.in_voice = AUD_open_in(&s->codec.card, s->codec.in_voice,
279 "eac.codec.in", s, omap_eac_in_cb, &fmt);
280 s->codec.out_voice = AUD_open_out(&s->codec.card, s->codec.out_voice,
281 "eac.codec.out", s, omap_eac_out_cb, &fmt);
282
283 omap_eac_volume_update(s);
284
285 AUD_set_active_in(s->codec.in_voice, 1);
286 AUD_set_active_out(s->codec.out_voice, 1);
287}
288
289static void omap_eac_reset(struct omap_eac_s *s)
290{
291 s->sysconfig = 0;
292 s->config[0] = 0x0c;
293 s->config[1] = 0x09;
294 s->config[2] = 0xab;
295 s->config[3] = 0x03;
296 s->control = 0x00;
297 s->address = 0x00;
298 s->data = 0x0000;
299 s->vtol = 0x00;
300 s->vtsl = 0x00;
301 s->mixer = 0x0000;
302 s->gain[0] = 0xe7e7;
303 s->gain[1] = 0x6767;
304 s->gain[2] = 0x6767;
305 s->gain[3] = 0x6767;
306 s->att = 0xce;
307 s->max[0] = 0;
308 s->max[1] = 0;
309 s->max[2] = 0;
310 s->max[3] = 0;
311 s->max[4] = 0;
312 s->max[5] = 0;
313 s->max[6] = 0;
314
315 s->modem.control = 0x00;
316 s->modem.config = 0x0000;
317 s->bt.control = 0x00;
318 s->bt.config = 0x0000;
319 s->codec.config[0] = 0x0649;
320 s->codec.config[1] = 0x0000;
321 s->codec.config[2] = 0x0007;
322 s->codec.config[3] = 0x1ffc;
323 s->codec.rxoff = 0;
324 s->codec.rxlen = 0;
325 s->codec.txlen = 0;
326 s->codec.rxavail = 0;
327 s->codec.txavail = 0;
328
329 omap_eac_format_update(s);
330 omap_eac_interrupt_update(s);
331}
332
333static uint64_t omap_eac_read(void *opaque, hwaddr addr,
334 unsigned size)
335{
336 struct omap_eac_s *s = (struct omap_eac_s *) opaque;
337 uint32_t ret;
338
339 if (size != 2) {
340 return omap_badwidth_read16(opaque, addr);
341 }
342
343 switch (addr) {
344 case 0x000:
345 return s->config[0];
346 case 0x004:
347 return s->config[1];
348 case 0x008:
349 return s->config[2];
350 case 0x00c:
351 return s->config[3];
352
353 case 0x010:
354 return s->control | ((s->codec.rxavail + s->codec.rxlen > 0) << 7) |
355 ((s->codec.txlen < s->codec.txavail) << 5);
356
357 case 0x014:
358 return s->address;
359 case 0x018:
360 return s->data & 0xff;
361 case 0x01c:
362 return s->data >> 8;
363 case 0x020:
364 return s->vtol;
365 case 0x024:
366 return s->vtsl | (3 << 5);
367 case 0x040:
368 return s->modem.control;
369 case 0x044:
370 return s->modem.config;
371 case 0x060:
372 return s->bt.control;
373 case 0x064:
374 return s->bt.config;
375 case 0x080:
376 return s->mixer;
377 case 0x084:
378 return s->gain[0];
379 case 0x088:
380 return s->gain[1];
381 case 0x08c:
382 return s->gain[2];
383 case 0x090:
384 return s->gain[3];
385 case 0x094:
386 return s->att;
387 case 0x098:
388 return s->max[0];
389 case 0x09c:
390 return s->max[1];
391 case 0x0a0:
392 return s->max[2];
393 case 0x0a4:
394 return s->max[3];
395 case 0x0a8:
396 return s->max[4];
397 case 0x0ac:
398 return s->max[5];
399 case 0x0b0:
400 return s->max[6];
401 case 0x0b4:
402
403 return 0x0000;
404 case 0x0b8:
405 if (likely(s->codec.rxlen > 1)) {
406 ret = s->codec.rxbuf[s->codec.rxoff ++];
407 s->codec.rxlen --;
408 s->codec.rxoff &= EAC_BUF_LEN - 1;
409 return ret;
410 } else if (s->codec.rxlen) {
411 ret = s->codec.rxbuf[s->codec.rxoff ++];
412 s->codec.rxlen --;
413 s->codec.rxoff &= EAC_BUF_LEN - 1;
414 if (s->codec.rxavail)
415 omap_eac_in_refill(s);
416 omap_eac_in_dmarequest_update(s);
417 return ret;
418 }
419 return 0x0000;
420 case 0x0bc:
421 return s->codec.config[0];
422 case 0x0c0:
423 return s->codec.config[1] | ((s->codec.config[1] & 2) << 14);
424 case 0x0c4:
425 return s->codec.config[2];
426 case 0x0c8:
427 return s->codec.config[3];
428 case 0x0cc:
429 case 0x0d0:
430 case 0x0d8:
431 case 0x0e4:
432 case 0x0ec:
433 return 0x0000;
434
435 case 0x100:
436 return 0x0010;
437
438 case 0x104:
439 return s->sysconfig;
440
441 case 0x108:
442 return 1 | 0xe;
443 }
444
445 OMAP_BAD_REG(addr);
446 return 0;
447}
448
449static void omap_eac_write(void *opaque, hwaddr addr,
450 uint64_t value, unsigned size)
451{
452 struct omap_eac_s *s = (struct omap_eac_s *) opaque;
453
454 if (size != 2) {
455 omap_badwidth_write16(opaque, addr, value);
456 return;
457 }
458
459 switch (addr) {
460 case 0x098:
461 case 0x09c:
462 case 0x0a0:
463 case 0x0a4:
464 case 0x0a8:
465 case 0x0ac:
466 case 0x0b0:
467 case 0x0b8:
468 case 0x0d0:
469 case 0x0d8:
470 case 0x0e4:
471 case 0x0ec:
472 case 0x100:
473 case 0x108:
474 OMAP_RO_REG(addr);
475 return;
476
477 case 0x000:
478 s->config[0] = value & 0xff;
479 omap_eac_format_update(s);
480 break;
481 case 0x004:
482 s->config[1] = value & 0xff;
483 omap_eac_format_update(s);
484 break;
485 case 0x008:
486 s->config[2] = value & 0xff;
487 omap_eac_format_update(s);
488 break;
489 case 0x00c:
490 s->config[3] = value & 0xff;
491 omap_eac_format_update(s);
492 break;
493
494 case 0x010:
495
496 s->control = value & 0x5f;
497 omap_eac_interrupt_update(s);
498 break;
499
500 case 0x014:
501 s->address = value & 0xff;
502 break;
503 case 0x018:
504 s->data &= 0xff00;
505 s->data |= value & 0xff;
506 break;
507 case 0x01c:
508 s->data &= 0x00ff;
509 s->data |= value << 8;
510 break;
511 case 0x020:
512 s->vtol = value & 0xf8;
513 break;
514 case 0x024:
515 s->vtsl = value & 0x9f;
516 break;
517 case 0x040:
518 s->modem.control = value & 0x8f;
519 break;
520 case 0x044:
521 s->modem.config = value & 0x7fff;
522 break;
523 case 0x060:
524 s->bt.control = value & 0x8f;
525 break;
526 case 0x064:
527 s->bt.config = value & 0x7fff;
528 break;
529 case 0x080:
530 s->mixer = value & 0x0fff;
531 break;
532 case 0x084:
533 s->gain[0] = value & 0xffff;
534 break;
535 case 0x088:
536 s->gain[1] = value & 0xff7f;
537 break;
538 case 0x08c:
539 s->gain[2] = value & 0xff7f;
540 break;
541 case 0x090:
542 s->gain[3] = value & 0xff7f;
543 break;
544 case 0x094:
545 s->att = value & 0xff;
546 break;
547
548 case 0x0b4:
549 s->codec.txbuf[s->codec.txlen ++] = value;
550 if (unlikely(s->codec.txlen == EAC_BUF_LEN ||
551 s->codec.txlen == s->codec.txavail)) {
552 if (s->codec.txavail)
553 omap_eac_out_empty(s);
554
555 s->codec.txlen = 0;
556 }
557 break;
558
559 case 0x0bc:
560 s->codec.config[0] = value & 0x07ff;
561 omap_eac_format_update(s);
562 break;
563 case 0x0c0:
564 s->codec.config[1] = value & 0x780f;
565 omap_eac_format_update(s);
566 break;
567 case 0x0c4:
568 s->codec.config[2] = value & 0x003f;
569 omap_eac_format_update(s);
570 break;
571 case 0x0c8:
572 s->codec.config[3] = value & 0xffff;
573 omap_eac_format_update(s);
574 break;
575 case 0x0cc:
576 case 0x0d4:
577 case 0x0e0:
578 case 0x0e8:
579 case 0x0f0:
580 break;
581
582 case 0x104:
583 if (value & (1 << 1))
584 omap_eac_reset(s);
585 s->sysconfig = value & 0x31d;
586 break;
587
588 default:
589 OMAP_BAD_REG(addr);
590 return;
591 }
592}
593
594static const MemoryRegionOps omap_eac_ops = {
595 .read = omap_eac_read,
596 .write = omap_eac_write,
597 .endianness = DEVICE_NATIVE_ENDIAN,
598};
599
600static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
601 qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
602{
603 struct omap_eac_s *s = g_new0(struct omap_eac_s, 1);
604
605 s->irq = irq;
606 s->codec.rxdrq = *drq ++;
607 s->codec.txdrq = *drq;
608 omap_eac_reset(s);
609
610 AUD_register_card("OMAP EAC", &s->codec.card);
611
612 memory_region_init_io(&s->iomem, NULL, &omap_eac_ops, s, "omap.eac",
613 omap_l4_region_size(ta, 0));
614 omap_l4_attach(ta, 0, &s->iomem);
615
616 return s;
617}
618
619
620struct omap_sti_s {
621 qemu_irq irq;
622 MemoryRegion iomem;
623 MemoryRegion iomem_fifo;
624 CharDriverState *chr;
625
626 uint32_t sysconfig;
627 uint32_t systest;
628 uint32_t irqst;
629 uint32_t irqen;
630 uint32_t clkcontrol;
631 uint32_t serial_config;
632};
633
634#define STI_TRACE_CONSOLE_CHANNEL 239
635#define STI_TRACE_CONTROL_CHANNEL 253
636
637static inline void omap_sti_interrupt_update(struct omap_sti_s *s)
638{
639 qemu_set_irq(s->irq, s->irqst & s->irqen);
640}
641
642static void omap_sti_reset(struct omap_sti_s *s)
643{
644 s->sysconfig = 0;
645 s->irqst = 0;
646 s->irqen = 0;
647 s->clkcontrol = 0;
648 s->serial_config = 0;
649
650 omap_sti_interrupt_update(s);
651}
652
653static uint64_t omap_sti_read(void *opaque, hwaddr addr,
654 unsigned size)
655{
656 struct omap_sti_s *s = (struct omap_sti_s *) opaque;
657
658 if (size != 4) {
659 return omap_badwidth_read32(opaque, addr);
660 }
661
662 switch (addr) {
663 case 0x00:
664 return 0x10;
665
666 case 0x10:
667 return s->sysconfig;
668
669 case 0x14:
670 return 0x00;
671
672 case 0x18:
673 return s->irqst;
674
675 case 0x1c:
676 return s->irqen;
677
678 case 0x24:
679 case 0x28:
680
681 return 0;
682
683 case 0x2c:
684 return s->clkcontrol;
685
686 case 0x30:
687 return s->serial_config;
688 }
689
690 OMAP_BAD_REG(addr);
691 return 0;
692}
693
694static void omap_sti_write(void *opaque, hwaddr addr,
695 uint64_t value, unsigned size)
696{
697 struct omap_sti_s *s = (struct omap_sti_s *) opaque;
698
699 if (size != 4) {
700 omap_badwidth_write32(opaque, addr, value);
701 return;
702 }
703
704 switch (addr) {
705 case 0x00:
706 case 0x14:
707 OMAP_RO_REG(addr);
708 return;
709
710 case 0x10:
711 if (value & (1 << 1))
712 omap_sti_reset(s);
713 s->sysconfig = value & 0xfe;
714 break;
715
716 case 0x18:
717 s->irqst &= ~value;
718 omap_sti_interrupt_update(s);
719 break;
720
721 case 0x1c:
722 s->irqen = value & 0xffff;
723 omap_sti_interrupt_update(s);
724 break;
725
726 case 0x2c:
727 s->clkcontrol = value & 0xff;
728 break;
729
730 case 0x30:
731 s->serial_config = value & 0xff;
732 break;
733
734 case 0x24:
735 case 0x28:
736
737 return;
738
739 default:
740 OMAP_BAD_REG(addr);
741 return;
742 }
743}
744
745static const MemoryRegionOps omap_sti_ops = {
746 .read = omap_sti_read,
747 .write = omap_sti_write,
748 .endianness = DEVICE_NATIVE_ENDIAN,
749};
750
751static uint64_t omap_sti_fifo_read(void *opaque, hwaddr addr,
752 unsigned size)
753{
754 OMAP_BAD_REG(addr);
755 return 0;
756}
757
758static void omap_sti_fifo_write(void *opaque, hwaddr addr,
759 uint64_t value, unsigned size)
760{
761 struct omap_sti_s *s = (struct omap_sti_s *) opaque;
762 int ch = addr >> 6;
763 uint8_t byte = value;
764
765 if (size != 1) {
766 omap_badwidth_write8(opaque, addr, size);
767 return;
768 }
769
770 if (ch == STI_TRACE_CONTROL_CHANNEL) {
771
772 qemu_chr_fe_write(s->chr, (const uint8_t *) "\r", 1);
773 } else if (ch == STI_TRACE_CONSOLE_CHANNEL || 1) {
774 if (value == 0xc0 || value == 0xc3) {
775
776 } else if (value == 0x00)
777 qemu_chr_fe_write(s->chr, (const uint8_t *) "\n", 1);
778 else
779 qemu_chr_fe_write(s->chr, &byte, 1);
780 }
781}
782
783static const MemoryRegionOps omap_sti_fifo_ops = {
784 .read = omap_sti_fifo_read,
785 .write = omap_sti_fifo_write,
786 .endianness = DEVICE_NATIVE_ENDIAN,
787};
788
789static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta,
790 MemoryRegion *sysmem,
791 hwaddr channel_base, qemu_irq irq, omap_clk clk,
792 CharDriverState *chr)
793{
794 struct omap_sti_s *s = g_new0(struct omap_sti_s, 1);
795
796 s->irq = irq;
797 omap_sti_reset(s);
798
799 s->chr = chr ?: qemu_chr_new("null", "null", NULL);
800
801 memory_region_init_io(&s->iomem, NULL, &omap_sti_ops, s, "omap.sti",
802 omap_l4_region_size(ta, 0));
803 omap_l4_attach(ta, 0, &s->iomem);
804
805 memory_region_init_io(&s->iomem_fifo, NULL, &omap_sti_fifo_ops, s,
806 "omap.sti.fifo", 0x10000);
807 memory_region_add_subregion(sysmem, channel_base, &s->iomem_fifo);
808
809 return s;
810}
811
812
813#define L4TA(n) (n)
814#define L4TAO(n) ((n) + 39)
815
816static const struct omap_l4_region_s omap_l4_region[125] = {
817 [ 1] = { 0x40800, 0x800, 32 },
818 [ 2] = { 0x41000, 0x1000, 32 },
819 [ 0] = { 0x40000, 0x800, 32 },
820 [ 3] = { 0x00000, 0x1000, 32 | 16 | 8 },
821 [ 4] = { 0x01000, 0x1000, 32 | 16 | 8 },
822 [ 5] = { 0x04000, 0x1000, 32 | 16 },
823 [ 6] = { 0x05000, 0x1000, 32 | 16 | 8 },
824 [ 7] = { 0x08000, 0x800, 32 },
825 [ 8] = { 0x08800, 0x800, 32 },
826 [ 9] = { 0x09000, 0x1000, 32 | 16 | 8 },
827 [ 10] = { 0x12000, 0x1000, 32 | 16 | 8 },
828 [ 11] = { 0x13000, 0x1000, 32 | 16 | 8 },
829 [ 12] = { 0x14000, 0x1000, 32 },
830 [ 13] = { 0x15000, 0x1000, 32 | 16 | 8 },
831 [ 14] = { 0x18000, 0x1000, 32 | 16 | 8 },
832 [ 16] = { 0x1a000, 0x1000, 32 | 16 | 8 },
833 [ 18] = { 0x1c000, 0x1000, 32 | 16 | 8 },
834 [ 19] = { 0x1e000, 0x1000, 32 | 16 | 8 },
835 [ 15] = { 0x19000, 0x1000, 32 | 16 | 8 },
836 [ 17] = { 0x1b000, 0x1000, 32 | 16 | 8 },
837 [ 20] = { 0x20000, 0x1000, 32 | 16 | 8 },
838 [ 22] = { 0x22000, 0x1000, 32 | 16 | 8 },
839 [ 21] = { 0x21000, 0x1000, 32 | 16 | 8 },
840 [ 23] = { 0x23000, 0x1000, 32 | 16 | 8 },
841 [ 24] = { 0x28000, 0x1000, 32 | 16 | 8 },
842 [ 25] = { 0x29000, 0x1000, 32 | 16 | 8 },
843 [ 26] = { 0x48000, 0x2000, 32 | 16 | 8 },
844 [ 27] = { 0x4a000, 0x1000, 32 | 16 | 8 },
845 [ 28] = { 0x50000, 0x400, 32 | 16 | 8 },
846 [ 29] = { 0x50400, 0x400, 32 | 16 | 8 },
847 [ 30] = { 0x50800, 0x400, 32 | 16 | 8 },
848 [ 31] = { 0x50c00, 0x400, 32 | 16 | 8 },
849 [ 32] = { 0x51000, 0x1000, 32 | 16 | 8 },
850 [ 33] = { 0x52000, 0x400, 32 | 16 | 8 },
851 [ 34] = { 0x52400, 0x400, 32 | 16 | 8 },
852 [ 35] = { 0x52800, 0x400, 32 | 16 | 8 },
853 [ 36] = { 0x52c00, 0x400, 32 | 16 | 8 },
854 [ 37] = { 0x53000, 0x1000, 32 | 16 | 8 },
855 [ 38] = { 0x56000, 0x1000, 32 | 16 | 8 },
856 [ 39] = { 0x57000, 0x1000, 32 | 16 | 8 },
857 [ 40] = { 0x58000, 0x1000, 32 | 16 | 8 },
858 [ 41] = { 0x59000, 0x1000, 32 | 16 | 8 },
859 [ 42] = { 0x5a000, 0x1000, 32 | 16 | 8 },
860 [ 43] = { 0x5b000, 0x1000, 32 | 16 | 8 },
861 [ 44] = { 0x5c000, 0x1000, 32 | 16 | 8 },
862 [ 45] = { 0x5e000, 0x1000, 32 | 16 | 8 },
863 [ 46] = { 0x5f000, 0x1000, 32 | 16 | 8 },
864 [ 47] = { 0x60000, 0x1000, 32 | 16 | 8 },
865 [ 48] = { 0x61000, 0x1000, 32 | 16 | 8 },
866 [ 49] = { 0x62000, 0x1000, 32 | 16 | 8 },
867 [ 50] = { 0x63000, 0x1000, 32 | 16 | 8 },
868 [ 51] = { 0x64000, 0x1000, 32 | 16 | 8 },
869 [ 52] = { 0x65000, 0x1000, 32 | 16 | 8 },
870 [ 53] = { 0x66000, 0x300, 32 | 16 | 8 },
871 [ 54] = { 0x67000, 0x1000, 32 | 16 | 8 },
872 [ 55] = { 0x68000, 0x1000, 32 | 16 | 8 },
873 [ 56] = { 0x69000, 0x1000, 32 | 16 | 8 },
874 [ 57] = { 0x6a000, 0x1000, 16 | 8 },
875 [ 58] = { 0x6b000, 0x1000, 32 | 16 | 8 },
876 [ 59] = { 0x6c000, 0x1000, 16 | 8 },
877 [ 60] = { 0x6d000, 0x1000, 32 | 16 | 8 },
878 [ 61] = { 0x6e000, 0x1000, 16 | 8 },
879 [ 62] = { 0x6f000, 0x1000, 32 | 16 | 8 },
880 [ 63] = { 0x70000, 0x1000, 16 },
881 [ 64] = { 0x71000, 0x1000, 32 | 16 | 8 },
882 [ 65] = { 0x72000, 0x1000, 16 },
883 [ 66] = { 0x73000, 0x1000, 32 | 16 | 8 },
884 [ 67] = { 0x74000, 0x1000, 16 },
885 [ 68] = { 0x75000, 0x1000, 32 | 16 | 8 },
886 [ 69] = { 0x76000, 0x1000, 16 },
887 [ 70] = { 0x77000, 0x1000, 32 | 16 | 8 },
888 [ 71] = { 0x24000, 0x1000, 32 | 16 | 8 },
889 [ 72] = { 0x25000, 0x1000, 32 | 16 | 8 },
890 [ 73] = { 0x26000, 0x1000, 32 | 16 | 8 },
891 [ 74] = { 0x27000, 0x1000, 32 | 16 | 8 },
892 [ 75] = { 0x2a000, 0x1000, 32 | 16 | 8 },
893 [ 76] = { 0x2b000, 0x1000, 32 | 16 | 8 },
894 [ 77] = { 0x78000, 0x1000, 32 | 16 | 8 },
895 [ 78] = { 0x79000, 0x1000, 32 | 16 | 8 },
896 [ 79] = { 0x7a000, 0x1000, 32 | 16 | 8 },
897 [ 80] = { 0x7b000, 0x1000, 32 | 16 | 8 },
898 [ 81] = { 0x7c000, 0x1000, 32 | 16 | 8 },
899 [ 82] = { 0x7d000, 0x1000, 32 | 16 | 8 },
900 [ 83] = { 0x7e000, 0x1000, 32 | 16 | 8 },
901 [ 84] = { 0x7f000, 0x1000, 32 | 16 | 8 },
902 [ 85] = { 0x80000, 0x1000, 32 | 16 | 8 },
903 [ 86] = { 0x81000, 0x1000, 32 | 16 | 8 },
904 [ 87] = { 0x82000, 0x1000, 32 | 16 | 8 },
905 [ 88] = { 0x83000, 0x1000, 32 | 16 | 8 },
906 [ 89] = { 0x84000, 0x1000, 32 | 16 | 8 },
907 [ 90] = { 0x85000, 0x1000, 32 | 16 | 8 },
908 [ 91] = { 0x86000, 0x1000, 32 | 16 | 8 },
909 [ 92] = { 0x87000, 0x1000, 32 | 16 | 8 },
910 [ 93] = { 0x88000, 0x1000, 32 | 16 | 8 },
911 [ 94] = { 0x89000, 0x1000, 32 | 16 | 8 },
912 [ 95] = { 0x8a000, 0x1000, 32 | 16 | 8 },
913 [ 96] = { 0x8b000, 0x1000, 32 | 16 | 8 },
914 [ 97] = { 0x90000, 0x1000, 16 },
915 [ 98] = { 0x91000, 0x1000, 32 | 16 | 8 },
916 [ 99] = { 0x92000, 0x1000, 16 },
917 [100] = { 0x93000, 0x1000, 32 | 16 | 8 },
918 [101] = { 0x94000, 0x1000, 32 | 16 | 8 },
919 [102] = { 0x95000, 0x1000, 32 | 16 | 8 },
920 [103] = { 0x98000, 0x1000, 32 | 16 | 8 },
921 [104] = { 0x99000, 0x1000, 32 | 16 | 8 },
922 [105] = { 0x9a000, 0x1000, 32 | 16 | 8 },
923 [106] = { 0x9b000, 0x1000, 32 | 16 | 8 },
924 [107] = { 0x9c000, 0x1000, 16 | 8 },
925 [108] = { 0x9d000, 0x1000, 32 | 16 | 8 },
926 [109] = { 0x9e000, 0x1000, 32 | 16 | 8 },
927 [110] = { 0x9f000, 0x1000, 32 | 16 | 8 },
928 [111] = { 0xa0000, 0x1000, 32 },
929 [112] = { 0xa1000, 0x1000, 32 | 16 | 8 },
930 [113] = { 0xa2000, 0x1000, 32 },
931 [114] = { 0xa3000, 0x1000, 32 | 16 | 8 },
932 [115] = { 0xa4000, 0x1000, 32 },
933 [116] = { 0xa5000, 0x1000, 32 | 16 | 8 },
934 [117] = { 0xa6000, 0x1000, 32 },
935 [118] = { 0xa7000, 0x1000, 32 | 16 | 8 },
936 [119] = { 0xa8000, 0x2000, 32 },
937 [120] = { 0xaa000, 0x1000, 32 | 16 | 8 },
938 [121] = { 0xb0000, 0x1000, 32 },
939 [122] = { 0xb1000, 0x1000, 32 | 16 | 8 },
940 [123] = { 0xb2000, 0x1000, 32 },
941 [124] = { 0xb3000, 0x1000, 32 | 16 | 8 },
942};
943
944static const struct omap_l4_agent_info_s omap_l4_agent_info[54] = {
945 { 0, 0, 3, 2 },
946 { L4TAO(1), 3, 2, 1 },
947 { L4TAO(2), 5, 2, 1 },
948 { L4TAO(3), 7, 3, 2 },
949 { L4TA(1), 10, 2, 1 },
950 { L4TA(2), 12, 2, 1 },
951 { L4TA(3), 14, 6, 3 },
952 { L4TA(4), 20, 4, 3 },
953 { L4TA(7), 24, 2, 1 },
954 { L4TA(9), 26, 2, 1 },
955 { L4TA(10), 28, 5, 4 },
956 { L4TA(11), 33, 5, 4 },
957 { L4TA(12), 38, 2, 1 },
958 { L4TA(13), 40, 5, 4 },
959 { L4TAO(4), 45, 2, 1 },
960 { L4TA(14), 47, 2, 1 },
961 { L4TA(15), 49, 2, 1 },
962 { L4TA(16), 51, 2, 1 },
963 { L4TA(17), 53, 2, 1 },
964 { L4TA(18), 55, 2, 1 },
965 { L4TA(19), 57, 2, 1 },
966 { L4TA(20), 59, 2, 1 },
967 { L4TA(21), 61, 2, 1 },
968 { L4TAO(5), 63, 2, 1 },
969 { L4TAO(6), 65, 2, 1 },
970 { L4TAO(7), 67, 2, 1 },
971 { L4TAO(8), 69, 2, 1 },
972 { L4TA(5), 71, 2, 1 },
973 { L4TA(6), 73, 2, 1 },
974 { L4TA(8), 75, 2, 1 },
975 { L4TA(22), 77, 2, 1 },
976 { L4TA(23), 79, 2, 1 },
977 { L4TA(24), 81, 2, 1 },
978 { L4TA(25), 83, 2, 1 },
979 { L4TA(26), 85, 2, 1 },
980 { L4TA(27), 87, 2, 1 },
981 { L4TA(28), 89, 2, 1 },
982 { L4TA(29), 91, 2, 1 },
983 { L4TA(30), 93, 2, 1 },
984 { L4TA(31), 95, 2, 1 },
985 { L4TA(32), 97, 2, 1 },
986 { L4TA(33), 99, 2, 1 },
987 { L4TA(34), 101, 2, 1 },
988 { L4TA(35), 103, 2, 1 },
989 { L4TA(36), 105, 2, 1 },
990 { L4TAO(9), 107, 2, 1 },
991 { L4TAO(10), 109, 2, 1 },
992 { L4TAO(11), 111, 2, 1 },
993 { L4TAO(12), 113, 2, 1 },
994 { L4TAO(13), 115, 2, 1 },
995 { L4TA(37), 117, 2, 1 },
996 { L4TA(38), 119, 2, 1 },
997 { -1, 121, 2, 1 },
998 { L4TA(39), 123, 2, 1 },
999};
1000
1001#define omap_l4ta(bus, cs) \
1002 omap_l4ta_get(bus, omap_l4_region, omap_l4_agent_info, L4TA(cs))
1003#define omap_l4tao(bus, cs) \
1004 omap_l4ta_get(bus, omap_l4_region, omap_l4_agent_info, L4TAO(cs))
1005
1006
1007struct omap_prcm_s {
1008 qemu_irq irq[3];
1009 struct omap_mpu_state_s *mpu;
1010 MemoryRegion iomem0;
1011 MemoryRegion iomem1;
1012
1013 uint32_t irqst[3];
1014 uint32_t irqen[3];
1015
1016 uint32_t sysconfig;
1017 uint32_t voltctrl;
1018 uint32_t scratch[20];
1019
1020 uint32_t clksrc[1];
1021 uint32_t clkout[1];
1022 uint32_t clkemul[1];
1023 uint32_t clkpol[1];
1024 uint32_t clksel[8];
1025 uint32_t clken[12];
1026 uint32_t clkctrl[4];
1027 uint32_t clkidle[7];
1028 uint32_t setuptime[2];
1029
1030 uint32_t wkup[3];
1031 uint32_t wken[3];
1032 uint32_t wkst[3];
1033 uint32_t rst[4];
1034 uint32_t rstctrl[1];
1035 uint32_t power[4];
1036 uint32_t rsttime_wkup;
1037
1038 uint32_t ev;
1039 uint32_t evtime[2];
1040
1041 int dpll_lock, apll_lock[2];
1042};
1043
1044static void omap_prcm_int_update(struct omap_prcm_s *s, int dom)
1045{
1046 qemu_set_irq(s->irq[dom], s->irqst[dom] & s->irqen[dom]);
1047
1048}
1049
1050static uint64_t omap_prcm_read(void *opaque, hwaddr addr,
1051 unsigned size)
1052{
1053 struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
1054 uint32_t ret;
1055
1056 if (size != 4) {
1057 return omap_badwidth_read32(opaque, addr);
1058 }
1059
1060 switch (addr) {
1061 case 0x000:
1062 return 0x10;
1063
1064 case 0x010:
1065 return s->sysconfig;
1066
1067 case 0x018:
1068 return s->irqst[0];
1069
1070 case 0x01c:
1071 return s->irqen[0];
1072
1073 case 0x050:
1074 return s->voltctrl;
1075 case 0x054:
1076 return s->voltctrl & 3;
1077
1078 case 0x060:
1079 return s->clksrc[0];
1080 case 0x070:
1081 return s->clkout[0];
1082 case 0x078:
1083 return s->clkemul[0];
1084 case 0x080:
1085 case 0x084:
1086 return 0;
1087
1088 case 0x090:
1089 return s->setuptime[0];
1090
1091 case 0x094:
1092 return s->setuptime[1];
1093
1094 case 0x098:
1095 return s->clkpol[0];
1096
1097 case 0x0b0:
1098 case 0x0b4:
1099 case 0x0b8:
1100 case 0x0bc:
1101 case 0x0c0:
1102 case 0x0c4:
1103 case 0x0c8:
1104 case 0x0cc:
1105 case 0x0d0:
1106 case 0x0d4:
1107 case 0x0d8:
1108 case 0x0dc:
1109 case 0x0e0:
1110 case 0x0e4:
1111 case 0x0e8:
1112 case 0x0ec:
1113 case 0x0f0:
1114 case 0x0f4:
1115 case 0x0f8:
1116 case 0x0fc:
1117 return s->scratch[(addr - 0xb0) >> 2];
1118
1119 case 0x140:
1120 return s->clksel[0];
1121 case 0x148:
1122 return s->clkctrl[0];
1123
1124 case 0x158:
1125 return s->rst[0];
1126 case 0x1c8:
1127 return s->wkup[0];
1128 case 0x1d4:
1129 return s->ev;
1130 case 0x1d8:
1131 return s->evtime[0];
1132 case 0x1dc:
1133 return s->evtime[1];
1134 case 0x1e0:
1135 return s->power[0];
1136 case 0x1e4:
1137 return 0;
1138
1139 case 0x200:
1140 return s->clken[0];
1141 case 0x204:
1142 return s->clken[1];
1143 case 0x210:
1144 return s->clken[2];
1145 case 0x214:
1146 return s->clken[3];
1147 case 0x21c:
1148 return s->clken[4];
1149
1150 case 0x220:
1151
1152 return 0x7ffffff9;
1153 case 0x224:
1154
1155 return 0x00000007;
1156 case 0x22c:
1157
1158 return 0x0000001f;
1159
1160 case 0x230:
1161 return s->clkidle[0];
1162 case 0x234:
1163 return s->clkidle[1];
1164 case 0x238:
1165 return s->clkidle[2];
1166 case 0x23c:
1167 return s->clkidle[3];
1168
1169 case 0x240:
1170 return s->clksel[1];
1171 case 0x244:
1172 return s->clksel[2];
1173
1174 case 0x248:
1175 return s->clkctrl[1];
1176
1177 case 0x2a0:
1178 return s->wken[0];
1179 case 0x2a4:
1180 return s->wken[1];
1181
1182 case 0x2b0:
1183 return s->wkst[0];
1184 case 0x2b4:
1185 return s->wkst[1];
1186 case 0x2c8:
1187 return 0x1e;
1188
1189 case 0x2e0:
1190 return s->power[1];
1191 case 0x2e4:
1192 return 0x000030 | (s->power[1] & 0xfc00);
1193
1194 case 0x300:
1195 return s->clken[5];
1196 case 0x310:
1197 return s->clken[6];
1198 case 0x320:
1199
1200 return 0x00000001;
1201 case 0x340:
1202 return s->clksel[3];
1203 case 0x348:
1204 return s->clkctrl[2];
1205 case 0x350:
1206 return s->rstctrl[0];
1207 case 0x358:
1208 return s->rst[1];
1209 case 0x3c8:
1210 return s->wkup[1];
1211
1212 case 0x3e0:
1213 return s->power[2];
1214 case 0x3e4:
1215 return s->power[2] & 3;
1216
1217 case 0x400:
1218 return s->clken[7];
1219 case 0x410:
1220 return s->clken[8];
1221 case 0x420:
1222
1223 return 0x0000003f;
1224 case 0x430:
1225 return s->clkidle[4];
1226 case 0x440:
1227 return s->clksel[4];
1228 case 0x450:
1229 return 0;
1230 case 0x454:
1231 return s->rsttime_wkup;
1232 case 0x458:
1233 return s->rst[2];
1234 case 0x4a0:
1235 return s->wken[2];
1236 case 0x4b0:
1237 return s->wkst[2];
1238
1239 case 0x500:
1240 return s->clken[9];
1241 case 0x520:
1242 ret = 0x0000070 | (s->apll_lock[0] << 9) | (s->apll_lock[1] << 8);
1243 if (!(s->clksel[6] & 3))
1244
1245 ret |= 3 << 0;
1246 else if (!s->dpll_lock)
1247
1248 ret |= 1 << 0;
1249 else
1250
1251 ret |= 2 << 0;
1252 return ret;
1253 case 0x530:
1254 return s->clkidle[5];
1255 case 0x540:
1256 return s->clksel[5];
1257 case 0x544:
1258 return s->clksel[6];
1259
1260 case 0x800:
1261 return s->clken[10];
1262 case 0x810:
1263 return s->clken[11];
1264 case 0x820:
1265
1266 return 0x00000103;
1267 case 0x830:
1268 return s->clkidle[6];
1269 case 0x840:
1270 return s->clksel[7];
1271 case 0x848:
1272 return s->clkctrl[3];
1273 case 0x850:
1274 return 0;
1275 case 0x858:
1276 return s->rst[3];
1277 case 0x8c8:
1278 return s->wkup[2];
1279 case 0x8e0:
1280 return s->power[3];
1281 case 0x8e4:
1282 return 0x008030 | (s->power[3] & 0x3003);
1283
1284 case 0x8f0:
1285 return s->irqst[1];
1286 case 0x8f4:
1287 return s->irqen[1];
1288
1289 case 0x8f8:
1290 return s->irqst[2];
1291 case 0x8fc:
1292 return s->irqen[2];
1293 }
1294
1295 OMAP_BAD_REG(addr);
1296 return 0;
1297}
1298
1299static void omap_prcm_apll_update(struct omap_prcm_s *s)
1300{
1301 int mode[2];
1302
1303 mode[0] = (s->clken[9] >> 6) & 3;
1304 s->apll_lock[0] = (mode[0] == 3);
1305 mode[1] = (s->clken[9] >> 2) & 3;
1306 s->apll_lock[1] = (mode[1] == 3);
1307
1308
1309 if (mode[0] == 1 || mode[0] == 2 || mode[1] == 1 || mode[1] == 2)
1310 fprintf(stderr, "%s: bad EN_54M_PLL or bad EN_96M_PLL\n",
1311 __FUNCTION__);
1312}
1313
1314static void omap_prcm_dpll_update(struct omap_prcm_s *s)
1315{
1316 omap_clk dpll = omap_findclk(s->mpu, "dpll");
1317 omap_clk dpll_x2 = omap_findclk(s->mpu, "dpll");
1318 omap_clk core = omap_findclk(s->mpu, "core_clk");
1319 int mode = (s->clken[9] >> 0) & 3;
1320 int mult, div;
1321
1322 mult = (s->clksel[5] >> 12) & 0x3ff;
1323 div = (s->clksel[5] >> 8) & 0xf;
1324 if (mult == 0 || mult == 1)
1325 mode = 1;
1326
1327 s->dpll_lock = 0;
1328 switch (mode) {
1329 case 0:
1330 fprintf(stderr, "%s: bad EN_DPLL\n", __FUNCTION__);
1331 break;
1332 case 1:
1333 case 2:
1334 omap_clk_setrate(dpll, 1, 1);
1335 omap_clk_setrate(dpll_x2, 1, 1);
1336 break;
1337 case 3:
1338 s->dpll_lock = 1;
1339
1340 omap_clk_setrate(dpll, div + 1, mult);
1341 omap_clk_setrate(dpll_x2, div + 1, mult * 2);
1342 break;
1343 }
1344
1345 switch ((s->clksel[6] >> 0) & 3) {
1346 case 0:
1347 omap_clk_reparent(core, omap_findclk(s->mpu, "clk32-kHz"));
1348 break;
1349 case 1:
1350 omap_clk_reparent(core, dpll);
1351 break;
1352 case 2:
1353
1354 omap_clk_reparent(core, dpll_x2);
1355 break;
1356 case 3:
1357 fprintf(stderr, "%s: bad CORE_CLK_SRC\n", __FUNCTION__);
1358 break;
1359 }
1360}
1361
1362static void omap_prcm_write(void *opaque, hwaddr addr,
1363 uint64_t value, unsigned size)
1364{
1365 struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
1366
1367 if (size != 4) {
1368 omap_badwidth_write32(opaque, addr, value);
1369 return;
1370 }
1371
1372 switch (addr) {
1373 case 0x000:
1374 case 0x054:
1375 case 0x084:
1376 case 0x1e4:
1377 case 0x220:
1378 case 0x224:
1379 case 0x22c:
1380 case 0x2c8:
1381 case 0x2e4:
1382 case 0x320:
1383 case 0x3e4:
1384 case 0x420:
1385 case 0x520:
1386 case 0x820:
1387 case 0x8e4:
1388 OMAP_RO_REG(addr);
1389 return;
1390
1391 case 0x010:
1392 s->sysconfig = value & 1;
1393 break;
1394
1395 case 0x018:
1396 s->irqst[0] &= ~value;
1397 omap_prcm_int_update(s, 0);
1398 break;
1399 case 0x01c:
1400 s->irqen[0] = value & 0x3f;
1401 omap_prcm_int_update(s, 0);
1402 break;
1403
1404 case 0x050:
1405 s->voltctrl = value & 0xf1c3;
1406 break;
1407
1408 case 0x060:
1409 s->clksrc[0] = value & 0xdb;
1410
1411 break;
1412
1413 case 0x070:
1414 s->clkout[0] = value & 0xbbbb;
1415
1416 break;
1417
1418 case 0x078:
1419 s->clkemul[0] = value & 1;
1420
1421 break;
1422
1423 case 0x080:
1424 break;
1425
1426 case 0x090:
1427 s->setuptime[0] = value & 0xffff;
1428 break;
1429 case 0x094:
1430 s->setuptime[1] = value & 0xffff;
1431 break;
1432
1433 case 0x098:
1434 s->clkpol[0] = value & 0x701;
1435 break;
1436
1437 case 0x0b0:
1438 case 0x0b4:
1439 case 0x0b8:
1440 case 0x0bc:
1441 case 0x0c0:
1442 case 0x0c4:
1443 case 0x0c8:
1444 case 0x0cc:
1445 case 0x0d0:
1446 case 0x0d4:
1447 case 0x0d8:
1448 case 0x0dc:
1449 case 0x0e0:
1450 case 0x0e4:
1451 case 0x0e8:
1452 case 0x0ec:
1453 case 0x0f0:
1454 case 0x0f4:
1455 case 0x0f8:
1456 case 0x0fc:
1457 s->scratch[(addr - 0xb0) >> 2] = value;
1458 break;
1459
1460 case 0x140:
1461 s->clksel[0] = value & 0x1f;
1462
1463 break;
1464 case 0x148:
1465 s->clkctrl[0] = value & 0x1f;
1466 break;
1467
1468 case 0x158:
1469 s->rst[0] &= ~value;
1470 break;
1471 case 0x1c8:
1472 s->wkup[0] = value & 0x15;
1473 break;
1474
1475 case 0x1d4:
1476 s->ev = value & 0x1f;
1477 break;
1478 case 0x1d8:
1479 s->evtime[0] = value;
1480 break;
1481 case 0x1dc:
1482 s->evtime[1] = value;
1483 break;
1484
1485 case 0x1e0:
1486 s->power[0] = value & 0xc0f;
1487 break;
1488
1489 case 0x200:
1490 s->clken[0] = value & 0xbfffffff;
1491
1492
1493 break;
1494 case 0x204:
1495 s->clken[1] = value & 0x00000007;
1496
1497 break;
1498 case 0x210:
1499 s->clken[2] = value & 0xfffffff9;
1500
1501
1502 break;
1503 case 0x214:
1504 s->clken[3] = value & 0x00000007;
1505
1506 break;
1507 case 0x21c:
1508 s->clken[4] = value & 0x0000001f;
1509
1510 break;
1511
1512 case 0x230:
1513 s->clkidle[0] = value & 0xfffffff9;
1514
1515 break;
1516 case 0x234:
1517 s->clkidle[1] = value & 0x00000007;
1518
1519 break;
1520 case 0x238:
1521 s->clkidle[2] = value & 0x00000007;
1522
1523 break;
1524 case 0x23c:
1525 s->clkidle[3] = value & 0x0000001f;
1526
1527 break;
1528
1529 case 0x240:
1530 s->clksel[1] = value & 0x0fffbf7f;
1531
1532 break;
1533
1534 case 0x244:
1535 s->clksel[2] = value & 0x00fffffc;
1536
1537 break;
1538
1539 case 0x248:
1540 s->clkctrl[1] = value & 0x7;
1541 break;
1542
1543 case 0x2a0:
1544 s->wken[0] = value & 0x04667ff8;
1545 break;
1546 case 0x2a4:
1547 s->wken[1] = value & 0x00000005;
1548 break;
1549
1550 case 0x2b0:
1551 s->wkst[0] &= ~value;
1552 break;
1553 case 0x2b4:
1554 s->wkst[1] &= ~value;
1555 break;
1556
1557 case 0x2e0:
1558 s->power[1] = (value & 0x00fc3f) | (1 << 2);
1559 break;
1560
1561 case 0x300:
1562 s->clken[5] = value & 6;
1563
1564 break;
1565 case 0x310:
1566 s->clken[6] = value & 1;
1567
1568 break;
1569 case 0x340:
1570 s->clksel[3] = value & 7;
1571
1572 break;
1573 case 0x348:
1574 s->clkctrl[2] = value & 1;
1575 break;
1576 case 0x350:
1577 s->rstctrl[0] = value & 1;
1578
1579 break;
1580 case 0x358:
1581 s->rst[1] &= ~value;
1582 break;
1583 case 0x3c8:
1584 s->wkup[1] = value & 0x13;
1585 break;
1586 case 0x3e0:
1587 s->power[2] = (value & 0x00c0f) | (3 << 2);
1588 break;
1589
1590 case 0x400:
1591 s->clken[7] = value & 0xd;
1592
1593 break;
1594 case 0x410:
1595 s->clken[8] = value & 0x3f;
1596
1597 break;
1598 case 0x430:
1599 s->clkidle[4] = value & 0x0000003f;
1600
1601 break;
1602 case 0x440:
1603 s->clksel[4] = value & 3;
1604
1605 break;
1606 case 0x450:
1607
1608 if (value & 2)
1609 qemu_system_reset_request();
1610 break;
1611 case 0x454:
1612 s->rsttime_wkup = value & 0x1fff;
1613 break;
1614 case 0x458:
1615 s->rst[2] &= ~value;
1616 break;
1617 case 0x4a0:
1618 s->wken[2] = value & 0x00000005;
1619 break;
1620 case 0x4b0:
1621 s->wkst[2] &= ~value;
1622 break;
1623
1624 case 0x500:
1625 if (value & 0xffffff30)
1626 fprintf(stderr, "%s: write 0s in CM_CLKEN_PLL for "
1627 "future compatibility\n", __FUNCTION__);
1628 if ((s->clken[9] ^ value) & 0xcc) {
1629 s->clken[9] &= ~0xcc;
1630 s->clken[9] |= value & 0xcc;
1631 omap_prcm_apll_update(s);
1632 }
1633 if ((s->clken[9] ^ value) & 3) {
1634 s->clken[9] &= ~3;
1635 s->clken[9] |= value & 3;
1636 omap_prcm_dpll_update(s);
1637 }
1638 break;
1639 case 0x530:
1640 s->clkidle[5] = value & 0x000000cf;
1641
1642 break;
1643 case 0x540:
1644 if (value & 0xfc4000d7)
1645 fprintf(stderr, "%s: write 0s in CM_CLKSEL1_PLL for "
1646 "future compatibility\n", __FUNCTION__);
1647 if ((s->clksel[5] ^ value) & 0x003fff00) {
1648 s->clksel[5] = value & 0x03bfff28;
1649 omap_prcm_dpll_update(s);
1650 }
1651
1652
1653 s->clksel[5] = value & 0x03bfff28;
1654 break;
1655 case 0x544:
1656 if (value & ~3)
1657 fprintf(stderr, "%s: write 0s in CM_CLKSEL2_PLL[31:2] for "
1658 "future compatibility\n", __FUNCTION__);
1659 if (s->clksel[6] != (value & 3)) {
1660 s->clksel[6] = value & 3;
1661 omap_prcm_dpll_update(s);
1662 }
1663 break;
1664
1665 case 0x800:
1666 s->clken[10] = value & 0x501;
1667
1668 break;
1669 case 0x810:
1670 s->clken[11] = value & 0x2;
1671
1672 break;
1673 case 0x830:
1674 s->clkidle[6] = value & 0x2;
1675
1676 break;
1677 case 0x840:
1678 s->clksel[7] = value & 0x3fff;
1679
1680 break;
1681 case 0x848:
1682 s->clkctrl[3] = value & 0x101;
1683 break;
1684 case 0x850:
1685
1686 break;
1687 case 0x858:
1688 s->rst[3] &= ~value;
1689 break;
1690 case 0x8c8:
1691 s->wkup[2] = value & 0x13;
1692 break;
1693 case 0x8e0:
1694 s->power[3] = (value & 0x03017) | (3 << 2);
1695 break;
1696
1697 case 0x8f0:
1698 s->irqst[1] &= ~value;
1699 omap_prcm_int_update(s, 1);
1700 break;
1701 case 0x8f4:
1702 s->irqen[1] = value & 0x7;
1703 omap_prcm_int_update(s, 1);
1704 break;
1705
1706 case 0x8f8:
1707 s->irqst[2] &= ~value;
1708 omap_prcm_int_update(s, 2);
1709 break;
1710 case 0x8fc:
1711 s->irqen[2] = value & 0x7;
1712 omap_prcm_int_update(s, 2);
1713 break;
1714
1715 default:
1716 OMAP_BAD_REG(addr);
1717 return;
1718 }
1719}
1720
1721static const MemoryRegionOps omap_prcm_ops = {
1722 .read = omap_prcm_read,
1723 .write = omap_prcm_write,
1724 .endianness = DEVICE_NATIVE_ENDIAN,
1725};
1726
1727static void omap_prcm_reset(struct omap_prcm_s *s)
1728{
1729 s->sysconfig = 0;
1730 s->irqst[0] = 0;
1731 s->irqst[1] = 0;
1732 s->irqst[2] = 0;
1733 s->irqen[0] = 0;
1734 s->irqen[1] = 0;
1735 s->irqen[2] = 0;
1736 s->voltctrl = 0x1040;
1737 s->ev = 0x14;
1738 s->evtime[0] = 0;
1739 s->evtime[1] = 0;
1740 s->clkctrl[0] = 0;
1741 s->clkctrl[1] = 0;
1742 s->clkctrl[2] = 0;
1743 s->clkctrl[3] = 0;
1744 s->clken[1] = 7;
1745 s->clken[3] = 7;
1746 s->clken[4] = 0;
1747 s->clken[5] = 0;
1748 s->clken[6] = 0;
1749 s->clken[7] = 0xc;
1750 s->clken[8] = 0x3e;
1751 s->clken[9] = 0x0d;
1752 s->clken[10] = 0;
1753 s->clken[11] = 0;
1754 s->clkidle[0] = 0;
1755 s->clkidle[2] = 7;
1756 s->clkidle[3] = 0;
1757 s->clkidle[4] = 0;
1758 s->clkidle[5] = 0x0c;
1759 s->clkidle[6] = 0;
1760 s->clksel[0] = 0x01;
1761 s->clksel[1] = 0x02100121;
1762 s->clksel[2] = 0x00000000;
1763 s->clksel[3] = 0x01;
1764 s->clksel[4] = 0;
1765 s->clksel[7] = 0x0121;
1766 s->wkup[0] = 0x15;
1767 s->wkup[1] = 0x13;
1768 s->wkup[2] = 0x13;
1769 s->wken[0] = 0x04667ff8;
1770 s->wken[1] = 0x00000005;
1771 s->wken[2] = 5;
1772 s->wkst[0] = 0;
1773 s->wkst[1] = 0;
1774 s->wkst[2] = 0;
1775 s->power[0] = 0x00c;
1776 s->power[1] = 4;
1777 s->power[2] = 0x0000c;
1778 s->power[3] = 0x14;
1779 s->rstctrl[0] = 1;
1780 s->rst[3] = 1;
1781 omap_prcm_apll_update(s);
1782 omap_prcm_dpll_update(s);
1783}
1784
1785static void omap_prcm_coldreset(struct omap_prcm_s *s)
1786{
1787 s->setuptime[0] = 0;
1788 s->setuptime[1] = 0;
1789 memset(&s->scratch, 0, sizeof(s->scratch));
1790 s->rst[0] = 0x01;
1791 s->rst[1] = 0x00;
1792 s->rst[2] = 0x01;
1793 s->clken[0] = 0;
1794 s->clken[2] = 0;
1795 s->clkidle[1] = 0;
1796 s->clksel[5] = 0;
1797 s->clksel[6] = 2;
1798 s->clksrc[0] = 0x43;
1799 s->clkout[0] = 0x0303;
1800 s->clkemul[0] = 0;
1801 s->clkpol[0] = 0x100;
1802 s->rsttime_wkup = 0x1002;
1803
1804 omap_prcm_reset(s);
1805}
1806
1807static struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
1808 qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int,
1809 struct omap_mpu_state_s *mpu)
1810{
1811 struct omap_prcm_s *s = g_new0(struct omap_prcm_s, 1);
1812
1813 s->irq[0] = mpu_int;
1814 s->irq[1] = dsp_int;
1815 s->irq[2] = iva_int;
1816 s->mpu = mpu;
1817 omap_prcm_coldreset(s);
1818
1819 memory_region_init_io(&s->iomem0, NULL, &omap_prcm_ops, s, "omap.pcrm0",
1820 omap_l4_region_size(ta, 0));
1821 memory_region_init_io(&s->iomem1, NULL, &omap_prcm_ops, s, "omap.pcrm1",
1822 omap_l4_region_size(ta, 1));
1823 omap_l4_attach(ta, 0, &s->iomem0);
1824 omap_l4_attach(ta, 1, &s->iomem1);
1825
1826 return s;
1827}
1828
1829
1830struct omap_sysctl_s {
1831 struct omap_mpu_state_s *mpu;
1832 MemoryRegion iomem;
1833
1834 uint32_t sysconfig;
1835 uint32_t devconfig;
1836 uint32_t psaconfig;
1837 uint32_t padconf[0x45];
1838 uint8_t obs;
1839 uint32_t msuspendmux[5];
1840};
1841
1842static uint32_t omap_sysctl_read8(void *opaque, hwaddr addr)
1843{
1844
1845 struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
1846 int pad_offset, byte_offset;
1847 int value;
1848
1849 switch (addr) {
1850 case 0x030 ... 0x140:
1851 pad_offset = (addr - 0x30) >> 2;
1852 byte_offset = (addr - 0x30) & (4 - 1);
1853
1854 value = s->padconf[pad_offset];
1855 value = (value >> (byte_offset * 8)) & 0xff;
1856
1857 return value;
1858
1859 default:
1860 break;
1861 }
1862
1863 OMAP_BAD_REG(addr);
1864 return 0;
1865}
1866
1867static uint32_t omap_sysctl_read(void *opaque, hwaddr addr)
1868{
1869 struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
1870
1871 switch (addr) {
1872 case 0x000:
1873 return 0x20;
1874
1875 case 0x010:
1876 return s->sysconfig;
1877
1878 case 0x030 ... 0x140:
1879 return s->padconf[(addr - 0x30) >> 2];
1880
1881 case 0x270:
1882 return s->obs;
1883
1884 case 0x274:
1885 return s->devconfig;
1886
1887 case 0x28c:
1888 return 0;
1889
1890 case 0x290:
1891 return s->msuspendmux[0];
1892 case 0x294:
1893 return s->msuspendmux[1];
1894 case 0x298:
1895 return s->msuspendmux[2];
1896 case 0x29c:
1897 return s->msuspendmux[3];
1898 case 0x2a0:
1899 return s->msuspendmux[4];
1900 case 0x2a4:
1901 return 0;
1902
1903 case 0x2b8:
1904 return s->psaconfig;
1905 case 0x2bc:
1906 case 0x2c0:
1907 return 0;
1908
1909 case 0x2b0:
1910 return 0x800000f1;
1911 case 0x2d0:
1912 return 0x80000015;
1913 case 0x2d4:
1914 return 0x8000007f;
1915 case 0x2b4:
1916 case 0x2f0:
1917 case 0x2f4:
1918
1919
1920 return 0;
1921
1922 case 0x2d8:
1923 return 0xff;
1924 case 0x2dc:
1925 case 0x2e0:
1926 case 0x2e4:
1927
1928 return 0;
1929
1930 case 0x2f8:
1931
1932 return 0x0300;
1933 case 0x2fc:
1934
1935 case 0x300:
1936 case 0x304:
1937 case 0x308:
1938 case 0x30c:
1939 return 0xdecafbad;
1940
1941 case 0x310:
1942 case 0x314:
1943 case 0x318:
1944 case 0x31c:
1945 case 0x320:
1946 case 0x324:
1947 case 0x330:
1948 case 0x334:
1949 case 0x338:
1950 case 0x33c:
1951 case 0x340:
1952 case 0x344:
1953 case 0x348:
1954 case 0x34c:
1955 case 0x350:
1956 case 0x354:
1957
1958
1959
1960 return 0;
1961 }
1962
1963 OMAP_BAD_REG(addr);
1964 return 0;
1965}
1966
1967static void omap_sysctl_write8(void *opaque, hwaddr addr,
1968 uint32_t value)
1969{
1970 struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
1971 int pad_offset, byte_offset;
1972 int prev_value;
1973
1974 switch (addr) {
1975 case 0x030 ... 0x140:
1976 pad_offset = (addr - 0x30) >> 2;
1977 byte_offset = (addr - 0x30) & (4 - 1);
1978
1979 prev_value = s->padconf[pad_offset];
1980 prev_value &= ~(0xff << (byte_offset * 8));
1981 prev_value |= ((value & 0x1f1f1f1f) << (byte_offset * 8)) & 0x1f1f1f1f;
1982 s->padconf[pad_offset] = prev_value;
1983 break;
1984
1985 default:
1986 OMAP_BAD_REG(addr);
1987 break;
1988 }
1989}
1990
1991static void omap_sysctl_write(void *opaque, hwaddr addr,
1992 uint32_t value)
1993{
1994 struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
1995
1996 switch (addr) {
1997 case 0x000:
1998 case 0x2a4:
1999 case 0x2c0:
2000 case 0x2f8:
2001 case 0x2fc:
2002 case 0x300:
2003 case 0x304:
2004 case 0x308:
2005 case 0x30c:
2006 case 0x310:
2007 case 0x314:
2008 case 0x318:
2009 case 0x31c:
2010 case 0x320:
2011 case 0x324:
2012 case 0x330:
2013 case 0x334:
2014 case 0x338:
2015 case 0x33c:
2016 case 0x340:
2017 case 0x344:
2018 case 0x348:
2019 case 0x34c:
2020 case 0x350:
2021 case 0x354:
2022 OMAP_RO_REG(addr);
2023 return;
2024
2025 case 0x010:
2026 s->sysconfig = value & 0x1e;
2027 break;
2028
2029 case 0x030 ... 0x140:
2030
2031 s->padconf[(addr - 0x30) >> 2] = value & 0x1f1f1f1f;
2032 break;
2033
2034 case 0x270:
2035 s->obs = value & 0xff;
2036 break;
2037
2038 case 0x274:
2039 s->devconfig = value & 0xffffc7ff;
2040 break;
2041
2042 case 0x28c:
2043 break;
2044
2045 case 0x290:
2046 s->msuspendmux[0] = value & 0x3fffffff;
2047 break;
2048 case 0x294:
2049 s->msuspendmux[1] = value & 0x3fffffff;
2050 break;
2051 case 0x298:
2052 s->msuspendmux[2] = value & 0x3fffffff;
2053 break;
2054 case 0x29c:
2055 s->msuspendmux[3] = value & 0x3fffffff;
2056 break;
2057 case 0x2a0:
2058 s->msuspendmux[4] = value & 0x3fffffff;
2059 break;
2060
2061 case 0x2b8:
2062 s->psaconfig = value & 0x1c;
2063 s->psaconfig |= (value & 0x20) ? 2 : 1;
2064 break;
2065 case 0x2bc:
2066 break;
2067
2068 case 0x2b0:
2069 case 0x2b4:
2070 case 0x2d0:
2071 case 0x2d4:
2072 case 0x2d8:
2073 case 0x2dc:
2074 case 0x2e0:
2075 case 0x2e4:
2076 case 0x2f0:
2077 case 0x2f4:
2078 break;
2079
2080 default:
2081 OMAP_BAD_REG(addr);
2082 return;
2083 }
2084}
2085
2086static const MemoryRegionOps omap_sysctl_ops = {
2087 .old_mmio = {
2088 .read = {
2089 omap_sysctl_read8,
2090 omap_badwidth_read32,
2091 omap_sysctl_read,
2092 },
2093 .write = {
2094 omap_sysctl_write8,
2095 omap_badwidth_write32,
2096 omap_sysctl_write,
2097 },
2098 },
2099 .endianness = DEVICE_NATIVE_ENDIAN,
2100};
2101
2102static void omap_sysctl_reset(struct omap_sysctl_s *s)
2103{
2104
2105 s->sysconfig = 0;
2106 s->obs = 0;
2107 s->devconfig = 0x0c000000;
2108 s->msuspendmux[0] = 0x00000000;
2109 s->msuspendmux[1] = 0x00000000;
2110 s->msuspendmux[2] = 0x00000000;
2111 s->msuspendmux[3] = 0x00000000;
2112 s->msuspendmux[4] = 0x00000000;
2113 s->psaconfig = 1;
2114
2115 s->padconf[0x00] = 0x000f0f0f;
2116 s->padconf[0x01] = 0x00000000;
2117 s->padconf[0x02] = 0x00000000;
2118 s->padconf[0x03] = 0x00000000;
2119 s->padconf[0x04] = 0x00000000;
2120 s->padconf[0x05] = 0x00000000;
2121 s->padconf[0x06] = 0x00000000;
2122 s->padconf[0x07] = 0x00000000;
2123 s->padconf[0x08] = 0x08080800;
2124 s->padconf[0x09] = 0x08080808;
2125 s->padconf[0x0a] = 0x08080808;
2126 s->padconf[0x0b] = 0x08080808;
2127 s->padconf[0x0c] = 0x08080808;
2128 s->padconf[0x0d] = 0x08080800;
2129 s->padconf[0x0e] = 0x08080808;
2130 s->padconf[0x0f] = 0x08080808;
2131 s->padconf[0x10] = 0x18181808;
2132 s->padconf[0x11] = 0x18181818;
2133 s->padconf[0x12] = 0x18181818;
2134 s->padconf[0x13] = 0x18181818;
2135 s->padconf[0x14] = 0x18181818;
2136 s->padconf[0x15] = 0x18181818;
2137 s->padconf[0x16] = 0x18181818;
2138 s->padconf[0x17] = 0x1f001f00;
2139 s->padconf[0x18] = 0x1f1f1f1f;
2140 s->padconf[0x19] = 0x00000000;
2141 s->padconf[0x1a] = 0x1f180000;
2142 s->padconf[0x1b] = 0x00001f1f;
2143 s->padconf[0x1c] = 0x1f001f00;
2144 s->padconf[0x1d] = 0x00000000;
2145 s->padconf[0x1e] = 0x00000000;
2146 s->padconf[0x1f] = 0x08000000;
2147 s->padconf[0x20] = 0x08080808;
2148 s->padconf[0x21] = 0x08080808;
2149 s->padconf[0x22] = 0x0f080808;
2150 s->padconf[0x23] = 0x0f0f0f0f;
2151 s->padconf[0x24] = 0x000f0f0f;
2152 s->padconf[0x25] = 0x1f1f1f0f;
2153 s->padconf[0x26] = 0x080f0f1f;
2154 s->padconf[0x27] = 0x070f1808;
2155 s->padconf[0x28] = 0x0f070707;
2156 s->padconf[0x29] = 0x000f0f1f;
2157 s->padconf[0x2a] = 0x0f0f0f1f;
2158 s->padconf[0x2b] = 0x08000000;
2159 s->padconf[0x2c] = 0x0000001f;
2160 s->padconf[0x2d] = 0x0f0f1f00;
2161 s->padconf[0x2e] = 0x1f1f0f0f;
2162 s->padconf[0x2f] = 0x0f1f1f1f;
2163 s->padconf[0x30] = 0x0f0f0f0f;
2164 s->padconf[0x31] = 0x0f1f0f1f;
2165 s->padconf[0x32] = 0x0f0f0f0f;
2166 s->padconf[0x33] = 0x0f1f0f1f;
2167 s->padconf[0x34] = 0x1f1f0f0f;
2168 s->padconf[0x35] = 0x0f0f1f1f;
2169 s->padconf[0x36] = 0x0f0f1f0f;
2170 s->padconf[0x37] = 0x0f0f0f0f;
2171 s->padconf[0x38] = 0x1f18180f;
2172 s->padconf[0x39] = 0x1f1f1f1f;
2173 s->padconf[0x3a] = 0x00001f1f;
2174 s->padconf[0x3b] = 0x00000000;
2175 s->padconf[0x3c] = 0x00000000;
2176 s->padconf[0x3d] = 0x0f0f0f0f;
2177 s->padconf[0x3e] = 0x18000f0f;
2178 s->padconf[0x3f] = 0x00070000;
2179 s->padconf[0x40] = 0x00000707;
2180 s->padconf[0x41] = 0x0f1f0700;
2181 s->padconf[0x42] = 0x1f1f070f;
2182 s->padconf[0x43] = 0x0008081f;
2183 s->padconf[0x44] = 0x00000800;
2184}
2185
2186static struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
2187 omap_clk iclk, struct omap_mpu_state_s *mpu)
2188{
2189 struct omap_sysctl_s *s = g_new0(struct omap_sysctl_s, 1);
2190
2191 s->mpu = mpu;
2192 omap_sysctl_reset(s);
2193
2194 memory_region_init_io(&s->iomem, NULL, &omap_sysctl_ops, s, "omap.sysctl",
2195 omap_l4_region_size(ta, 0));
2196 omap_l4_attach(ta, 0, &s->iomem);
2197
2198 return s;
2199}
2200
2201
2202static void omap2_mpu_reset(void *opaque)
2203{
2204 struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
2205
2206 omap_dma_reset(mpu->dma);
2207 omap_prcm_reset(mpu->prcm);
2208 omap_sysctl_reset(mpu->sysc);
2209 omap_gp_timer_reset(mpu->gptimer[0]);
2210 omap_gp_timer_reset(mpu->gptimer[1]);
2211 omap_gp_timer_reset(mpu->gptimer[2]);
2212 omap_gp_timer_reset(mpu->gptimer[3]);
2213 omap_gp_timer_reset(mpu->gptimer[4]);
2214 omap_gp_timer_reset(mpu->gptimer[5]);
2215 omap_gp_timer_reset(mpu->gptimer[6]);
2216 omap_gp_timer_reset(mpu->gptimer[7]);
2217 omap_gp_timer_reset(mpu->gptimer[8]);
2218 omap_gp_timer_reset(mpu->gptimer[9]);
2219 omap_gp_timer_reset(mpu->gptimer[10]);
2220 omap_gp_timer_reset(mpu->gptimer[11]);
2221 omap_synctimer_reset(mpu->synctimer);
2222 omap_sdrc_reset(mpu->sdrc);
2223 omap_gpmc_reset(mpu->gpmc);
2224 omap_dss_reset(mpu->dss);
2225 omap_uart_reset(mpu->uart[0]);
2226 omap_uart_reset(mpu->uart[1]);
2227 omap_uart_reset(mpu->uart[2]);
2228 omap_mmc_reset(mpu->mmc);
2229 omap_mcspi_reset(mpu->mcspi[0]);
2230 omap_mcspi_reset(mpu->mcspi[1]);
2231 cpu_reset(CPU(mpu->cpu));
2232}
2233
2234static int omap2_validate_addr(struct omap_mpu_state_s *s,
2235 hwaddr addr)
2236{
2237 return 1;
2238}
2239
2240static const struct dma_irq_map omap2_dma_irq_map[] = {
2241 { 0, OMAP_INT_24XX_SDMA_IRQ0 },
2242 { 0, OMAP_INT_24XX_SDMA_IRQ1 },
2243 { 0, OMAP_INT_24XX_SDMA_IRQ2 },
2244 { 0, OMAP_INT_24XX_SDMA_IRQ3 },
2245};
2246
2247struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
2248 unsigned long sdram_size,
2249 const char *core)
2250{
2251 struct omap_mpu_state_s *s = g_new0(struct omap_mpu_state_s, 1);
2252 qemu_irq dma_irqs[4];
2253 DriveInfo *dinfo;
2254 int i;
2255 SysBusDevice *busdev;
2256 struct omap_target_agent_s *ta;
2257
2258
2259 s->mpu_model = omap2420;
2260 s->cpu = cpu_arm_init(core ?: "arm1136-r2");
2261 if (s->cpu == NULL) {
2262 fprintf(stderr, "Unable to find CPU definition\n");
2263 exit(1);
2264 }
2265 s->sdram_size = sdram_size;
2266 s->sram_size = OMAP242X_SRAM_SIZE;
2267
2268 s->wakeup = qemu_allocate_irq(omap_mpu_wakeup, s, 0);
2269
2270
2271 omap_clk_init(s);
2272
2273
2274 memory_region_allocate_system_memory(&s->sdram, NULL, "omap2.dram",
2275 s->sdram_size);
2276 memory_region_add_subregion(sysmem, OMAP2_Q2_BASE, &s->sdram);
2277 memory_region_init_ram(&s->sram, NULL, "omap2.sram", s->sram_size,
2278 &error_fatal);
2279 vmstate_register_ram_global(&s->sram);
2280 memory_region_add_subregion(sysmem, OMAP2_SRAM_BASE, &s->sram);
2281
2282 s->l4 = omap_l4_init(sysmem, OMAP2_L4_BASE, 54);
2283
2284
2285 s->ih[0] = qdev_create(NULL, "omap2-intc");
2286 qdev_prop_set_uint8(s->ih[0], "revision", 0x21);
2287 qdev_prop_set_ptr(s->ih[0], "fclk", omap_findclk(s, "mpu_intc_fclk"));
2288 qdev_prop_set_ptr(s->ih[0], "iclk", omap_findclk(s, "mpu_intc_iclk"));
2289 qdev_init_nofail(s->ih[0]);
2290 busdev = SYS_BUS_DEVICE(s->ih[0]);
2291 sysbus_connect_irq(busdev, 0,
2292 qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
2293 sysbus_connect_irq(busdev, 1,
2294 qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_FIQ));
2295 sysbus_mmio_map(busdev, 0, 0x480fe000);
2296 s->prcm = omap_prcm_init(omap_l4tao(s->l4, 3),
2297 qdev_get_gpio_in(s->ih[0],
2298 OMAP_INT_24XX_PRCM_MPU_IRQ),
2299 NULL, NULL, s);
2300
2301 s->sysc = omap_sysctl_init(omap_l4tao(s->l4, 1),
2302 omap_findclk(s, "omapctrl_iclk"), s);
2303
2304 for (i = 0; i < 4; i++) {
2305 dma_irqs[i] = qdev_get_gpio_in(s->ih[omap2_dma_irq_map[i].ih],
2306 omap2_dma_irq_map[i].intr);
2307 }
2308 s->dma = omap_dma4_init(0x48056000, dma_irqs, sysmem, s, 256, 32,
2309 omap_findclk(s, "sdma_iclk"),
2310 omap_findclk(s, "sdma_fclk"));
2311 s->port->addr_valid = omap2_validate_addr;
2312
2313
2314 soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sdram),
2315 OMAP2_Q2_BASE, s->sdram_size);
2316 soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sram),
2317 OMAP2_SRAM_BASE, s->sram_size);
2318
2319 s->uart[0] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 19),
2320 qdev_get_gpio_in(s->ih[0],
2321 OMAP_INT_24XX_UART1_IRQ),
2322 omap_findclk(s, "uart1_fclk"),
2323 omap_findclk(s, "uart1_iclk"),
2324 s->drq[OMAP24XX_DMA_UART1_TX],
2325 s->drq[OMAP24XX_DMA_UART1_RX],
2326 "uart1",
2327 serial_hds[0]);
2328 s->uart[1] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 20),
2329 qdev_get_gpio_in(s->ih[0],
2330 OMAP_INT_24XX_UART2_IRQ),
2331 omap_findclk(s, "uart2_fclk"),
2332 omap_findclk(s, "uart2_iclk"),
2333 s->drq[OMAP24XX_DMA_UART2_TX],
2334 s->drq[OMAP24XX_DMA_UART2_RX],
2335 "uart2",
2336 serial_hds[0] ? serial_hds[1] : NULL);
2337 s->uart[2] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 21),
2338 qdev_get_gpio_in(s->ih[0],
2339 OMAP_INT_24XX_UART3_IRQ),
2340 omap_findclk(s, "uart3_fclk"),
2341 omap_findclk(s, "uart3_iclk"),
2342 s->drq[OMAP24XX_DMA_UART3_TX],
2343 s->drq[OMAP24XX_DMA_UART3_RX],
2344 "uart3",
2345 serial_hds[0] && serial_hds[1] ? serial_hds[2] : NULL);
2346
2347 s->gptimer[0] = omap_gp_timer_init(omap_l4ta(s->l4, 7),
2348 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER1),
2349 omap_findclk(s, "wu_gpt1_clk"),
2350 omap_findclk(s, "wu_l4_iclk"));
2351 s->gptimer[1] = omap_gp_timer_init(omap_l4ta(s->l4, 8),
2352 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER2),
2353 omap_findclk(s, "core_gpt2_clk"),
2354 omap_findclk(s, "core_l4_iclk"));
2355 s->gptimer[2] = omap_gp_timer_init(omap_l4ta(s->l4, 22),
2356 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER3),
2357 omap_findclk(s, "core_gpt3_clk"),
2358 omap_findclk(s, "core_l4_iclk"));
2359 s->gptimer[3] = omap_gp_timer_init(omap_l4ta(s->l4, 23),
2360 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER4),
2361 omap_findclk(s, "core_gpt4_clk"),
2362 omap_findclk(s, "core_l4_iclk"));
2363 s->gptimer[4] = omap_gp_timer_init(omap_l4ta(s->l4, 24),
2364 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER5),
2365 omap_findclk(s, "core_gpt5_clk"),
2366 omap_findclk(s, "core_l4_iclk"));
2367 s->gptimer[5] = omap_gp_timer_init(omap_l4ta(s->l4, 25),
2368 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER6),
2369 omap_findclk(s, "core_gpt6_clk"),
2370 omap_findclk(s, "core_l4_iclk"));
2371 s->gptimer[6] = omap_gp_timer_init(omap_l4ta(s->l4, 26),
2372 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER7),
2373 omap_findclk(s, "core_gpt7_clk"),
2374 omap_findclk(s, "core_l4_iclk"));
2375 s->gptimer[7] = omap_gp_timer_init(omap_l4ta(s->l4, 27),
2376 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER8),
2377 omap_findclk(s, "core_gpt8_clk"),
2378 omap_findclk(s, "core_l4_iclk"));
2379 s->gptimer[8] = omap_gp_timer_init(omap_l4ta(s->l4, 28),
2380 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER9),
2381 omap_findclk(s, "core_gpt9_clk"),
2382 omap_findclk(s, "core_l4_iclk"));
2383 s->gptimer[9] = omap_gp_timer_init(omap_l4ta(s->l4, 29),
2384 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER10),
2385 omap_findclk(s, "core_gpt10_clk"),
2386 omap_findclk(s, "core_l4_iclk"));
2387 s->gptimer[10] = omap_gp_timer_init(omap_l4ta(s->l4, 30),
2388 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER11),
2389 omap_findclk(s, "core_gpt11_clk"),
2390 omap_findclk(s, "core_l4_iclk"));
2391 s->gptimer[11] = omap_gp_timer_init(omap_l4ta(s->l4, 31),
2392 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER12),
2393 omap_findclk(s, "core_gpt12_clk"),
2394 omap_findclk(s, "core_l4_iclk"));
2395
2396 omap_tap_init(omap_l4ta(s->l4, 2), s);
2397
2398 s->synctimer = omap_synctimer_init(omap_l4tao(s->l4, 2), s,
2399 omap_findclk(s, "clk32-kHz"),
2400 omap_findclk(s, "core_l4_iclk"));
2401
2402 s->i2c[0] = qdev_create(NULL, "omap_i2c");
2403 qdev_prop_set_uint8(s->i2c[0], "revision", 0x34);
2404 qdev_prop_set_ptr(s->i2c[0], "iclk", omap_findclk(s, "i2c1.iclk"));
2405 qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "i2c1.fclk"));
2406 qdev_init_nofail(s->i2c[0]);
2407 busdev = SYS_BUS_DEVICE(s->i2c[0]);
2408 sysbus_connect_irq(busdev, 0,
2409 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C1_IRQ));
2410 sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C1_TX]);
2411 sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C1_RX]);
2412 sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 5), 0));
2413
2414 s->i2c[1] = qdev_create(NULL, "omap_i2c");
2415 qdev_prop_set_uint8(s->i2c[1], "revision", 0x34);
2416 qdev_prop_set_ptr(s->i2c[1], "iclk", omap_findclk(s, "i2c2.iclk"));
2417 qdev_prop_set_ptr(s->i2c[1], "fclk", omap_findclk(s, "i2c2.fclk"));
2418 qdev_init_nofail(s->i2c[1]);
2419 busdev = SYS_BUS_DEVICE(s->i2c[1]);
2420 sysbus_connect_irq(busdev, 0,
2421 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C2_IRQ));
2422 sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C2_TX]);
2423 sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C2_RX]);
2424 sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 6), 0));
2425
2426 s->gpio = qdev_create(NULL, "omap2-gpio");
2427 qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
2428 qdev_prop_set_ptr(s->gpio, "iclk", omap_findclk(s, "gpio_iclk"));
2429 qdev_prop_set_ptr(s->gpio, "fclk0", omap_findclk(s, "gpio1_dbclk"));
2430 qdev_prop_set_ptr(s->gpio, "fclk1", omap_findclk(s, "gpio2_dbclk"));
2431 qdev_prop_set_ptr(s->gpio, "fclk2", omap_findclk(s, "gpio3_dbclk"));
2432 qdev_prop_set_ptr(s->gpio, "fclk3", omap_findclk(s, "gpio4_dbclk"));
2433 if (s->mpu_model == omap2430) {
2434 qdev_prop_set_ptr(s->gpio, "fclk4", omap_findclk(s, "gpio5_dbclk"));
2435 }
2436 qdev_init_nofail(s->gpio);
2437 busdev = SYS_BUS_DEVICE(s->gpio);
2438 sysbus_connect_irq(busdev, 0,
2439 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK1));
2440 sysbus_connect_irq(busdev, 3,
2441 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK2));
2442 sysbus_connect_irq(busdev, 6,
2443 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK3));
2444 sysbus_connect_irq(busdev, 9,
2445 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK4));
2446 if (s->mpu_model == omap2430) {
2447 sysbus_connect_irq(busdev, 12,
2448 qdev_get_gpio_in(s->ih[0],
2449 OMAP_INT_243X_GPIO_BANK5));
2450 }
2451 ta = omap_l4ta(s->l4, 3);
2452 sysbus_mmio_map(busdev, 0, omap_l4_region_base(ta, 1));
2453 sysbus_mmio_map(busdev, 1, omap_l4_region_base(ta, 0));
2454 sysbus_mmio_map(busdev, 2, omap_l4_region_base(ta, 2));
2455 sysbus_mmio_map(busdev, 3, omap_l4_region_base(ta, 4));
2456 sysbus_mmio_map(busdev, 4, omap_l4_region_base(ta, 5));
2457
2458 s->sdrc = omap_sdrc_init(sysmem, 0x68009000);
2459 s->gpmc = omap_gpmc_init(s, 0x6800a000,
2460 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPMC_IRQ),
2461 s->drq[OMAP24XX_DMA_GPMC]);
2462
2463 dinfo = drive_get(IF_SD, 0, 0);
2464 if (!dinfo) {
2465 fprintf(stderr, "qemu: missing SecureDigital device\n");
2466 exit(1);
2467 }
2468 s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9),
2469 blk_by_legacy_dinfo(dinfo),
2470 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MMC_IRQ),
2471 &s->drq[OMAP24XX_DMA_MMC1_TX],
2472 omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk"));
2473
2474 s->mcspi[0] = omap_mcspi_init(omap_l4ta(s->l4, 35), 4,
2475 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MCSPI1_IRQ),
2476 &s->drq[OMAP24XX_DMA_SPI1_TX0],
2477 omap_findclk(s, "spi1_fclk"),
2478 omap_findclk(s, "spi1_iclk"));
2479 s->mcspi[1] = omap_mcspi_init(omap_l4ta(s->l4, 36), 2,
2480 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MCSPI2_IRQ),
2481 &s->drq[OMAP24XX_DMA_SPI2_TX0],
2482 omap_findclk(s, "spi2_fclk"),
2483 omap_findclk(s, "spi2_iclk"));
2484
2485 s->dss = omap_dss_init(omap_l4ta(s->l4, 10), sysmem, 0x68000800,
2486
2487 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_DSS_IRQ),
2488 s->drq[OMAP24XX_DMA_DSS],
2489 omap_findclk(s, "dss_clk1"), omap_findclk(s, "dss_clk2"),
2490 omap_findclk(s, "dss_54m_clk"),
2491 omap_findclk(s, "dss_l3_iclk"),
2492 omap_findclk(s, "dss_l4_iclk"));
2493
2494 omap_sti_init(omap_l4ta(s->l4, 18), sysmem, 0x54000000,
2495 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_STI),
2496 omap_findclk(s, "emul_ck"),
2497 serial_hds[0] && serial_hds[1] && serial_hds[2] ?
2498 serial_hds[3] : NULL);
2499
2500 s->eac = omap_eac_init(omap_l4ta(s->l4, 32),
2501 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_EAC_IRQ),
2502
2503 &s->drq[OMAP24XX_DMA_EAC_AC_RD],
2504 omap_findclk(s, "func_96m_clk"),
2505 omap_findclk(s, "core_l4_iclk"));
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688 qemu_register_reset(omap2_mpu_reset, s);
2689
2690 return s;
2691}
2692