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