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