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