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 "qemu-common.h"
25#include "cpu.h"
26#include "sysemu/block-backend.h"
27#include "sysemu/blockdev.h"
28#include "hw/boards.h"
29#include "hw/hw.h"
30#include "hw/arm/arm.h"
31#include "hw/arm/omap.h"
32#include "sysemu/sysemu.h"
33#include "qemu/timer.h"
34#include "chardev/char-fe.h"
35#include "hw/block/flash.h"
36#include "hw/arm/soc_dma.h"
37#include "hw/sysbus.h"
38#include "audio/audio.h"
39
40
41struct omap_eac_s {
42 qemu_irq irq;
43 MemoryRegion iomem;
44
45 uint16_t sysconfig;
46 uint8_t config[4];
47 uint8_t control;
48 uint8_t address;
49 uint16_t data;
50 uint8_t vtol;
51 uint8_t vtsl;
52 uint16_t mixer;
53 uint16_t gain[4];
54 uint8_t att;
55 uint16_t max[7];
56
57 struct {
58 qemu_irq txdrq;
59 qemu_irq rxdrq;
60 uint32_t (*txrx)(void *opaque, uint32_t, int);
61 void *opaque;
62
63#define EAC_BUF_LEN 1024
64 uint32_t rxbuf[EAC_BUF_LEN];
65 int rxoff;
66 int rxlen;
67 int rxavail;
68 uint32_t txbuf[EAC_BUF_LEN];
69 int txlen;
70 int txavail;
71
72 int enable;
73 int rate;
74
75 uint16_t config[4];
76
77
78 QEMUSoundCard card;
79 SWVoiceIn *in_voice;
80 SWVoiceOut *out_voice;
81 int hw_enable;
82 } codec;
83
84 struct {
85 uint8_t control;
86 uint16_t config;
87 } modem, bt;
88};
89
90static inline void omap_eac_interrupt_update(struct omap_eac_s *s)
91{
92 qemu_set_irq(s->irq, (s->codec.config[1] >> 14) & 1);
93}
94
95static inline void omap_eac_in_dmarequest_update(struct omap_eac_s *s)
96{
97 qemu_set_irq(s->codec.rxdrq, (s->codec.rxavail || s->codec.rxlen) &&
98 ((s->codec.config[1] >> 12) & 1));
99}
100
101static inline void omap_eac_out_dmarequest_update(struct omap_eac_s *s)
102{
103 qemu_set_irq(s->codec.txdrq, s->codec.txlen < s->codec.txavail &&
104 ((s->codec.config[1] >> 11) & 1));
105}
106
107static inline void omap_eac_in_refill(struct omap_eac_s *s)
108{
109 int left = MIN(EAC_BUF_LEN - s->codec.rxlen, s->codec.rxavail) << 2;
110 int start = ((s->codec.rxoff + s->codec.rxlen) & (EAC_BUF_LEN - 1)) << 2;
111 int leftwrap = MIN(left, (EAC_BUF_LEN << 2) - start);
112 int recv = 1;
113 uint8_t *buf = (uint8_t *) s->codec.rxbuf + start;
114
115 left -= leftwrap;
116 start = 0;
117 while (leftwrap && (recv = AUD_read(s->codec.in_voice, buf + start,
118 leftwrap)) > 0) {
119 start += recv;
120 leftwrap -= recv;
121 }
122 if (recv <= 0)
123 s->codec.rxavail = 0;
124 else
125 s->codec.rxavail -= start >> 2;
126 s->codec.rxlen += start >> 2;
127
128 if (recv > 0 && left > 0) {
129 start = 0;
130 while (left && (recv = AUD_read(s->codec.in_voice,
131 (uint8_t *) s->codec.rxbuf + start,
132 left)) > 0) {
133 start += recv;
134 left -= recv;
135 }
136 if (recv <= 0)
137 s->codec.rxavail = 0;
138 else
139 s->codec.rxavail -= start >> 2;
140 s->codec.rxlen += start >> 2;
141 }
142}
143
144static inline void omap_eac_out_empty(struct omap_eac_s *s)
145{
146 int left = s->codec.txlen << 2;
147 int start = 0;
148 int sent = 1;
149
150 while (left && (sent = AUD_write(s->codec.out_voice,
151 (uint8_t *) s->codec.txbuf + start,
152 left)) > 0) {
153 start += sent;
154 left -= sent;
155 }
156
157 if (!sent) {
158 s->codec.txavail = 0;
159 omap_eac_out_dmarequest_update(s);
160 }
161
162 if (start)
163 s->codec.txlen = 0;
164}
165
166static void omap_eac_in_cb(void *opaque, int avail_b)
167{
168 struct omap_eac_s *s = (struct omap_eac_s *) opaque;
169
170 s->codec.rxavail = avail_b >> 2;
171 omap_eac_in_refill(s);
172
173 omap_eac_in_dmarequest_update(s);
174}
175
176static void omap_eac_out_cb(void *opaque, int free_b)
177{
178 struct omap_eac_s *s = (struct omap_eac_s *) opaque;
179
180 s->codec.txavail = free_b >> 2;
181 if (s->codec.txlen)
182 omap_eac_out_empty(s);
183 else
184 omap_eac_out_dmarequest_update(s);
185}
186
187static void omap_eac_enable_update(struct omap_eac_s *s)
188{
189 s->codec.enable = !(s->codec.config[1] & 1) &&
190 (s->codec.config[1] & 2) &&
191 s->codec.hw_enable;
192}
193
194static const int omap_eac_fsint[4] = {
195 8000,
196 11025,
197 22050,
198 44100,
199};
200
201static const int omap_eac_fsint2[8] = {
202 8000,
203 11025,
204 22050,
205 44100,
206 48000,
207 0, 0, 0,
208};
209
210static const int omap_eac_fsint3[16] = {
211 8000,
212 11025,
213 16000,
214 22050,
215 24000,
216 32000,
217 44100,
218 48000,
219 0, 0, 0, 0, 0, 0, 0, 0,
220};
221
222static void omap_eac_rate_update(struct omap_eac_s *s)
223{
224 int fsint[3];
225
226 fsint[2] = (s->codec.config[3] >> 9) & 0xf;
227 fsint[1] = (s->codec.config[2] >> 0) & 0x7;
228 fsint[0] = (s->codec.config[0] >> 6) & 0x3;
229 if (fsint[2] < 0xf)
230 s->codec.rate = omap_eac_fsint3[fsint[2]];
231 else if (fsint[1] < 0x7)
232 s->codec.rate = omap_eac_fsint2[fsint[1]];
233 else
234 s->codec.rate = omap_eac_fsint[fsint[0]];
235}
236
237static void omap_eac_volume_update(struct omap_eac_s *s)
238{
239
240}
241
242static void omap_eac_format_update(struct omap_eac_s *s)
243{
244 struct audsettings fmt;
245
246
247 if (s->codec.rxlen)
248 s->codec.rxlen = 1;
249
250 if (s->codec.in_voice) {
251 AUD_set_active_in(s->codec.in_voice, 0);
252 AUD_close_in(&s->codec.card, s->codec.in_voice);
253 s->codec.in_voice = NULL;
254 }
255 if (s->codec.out_voice) {
256 omap_eac_out_empty(s);
257 AUD_set_active_out(s->codec.out_voice, 0);
258 AUD_close_out(&s->codec.card, s->codec.out_voice);
259 s->codec.out_voice = NULL;
260 s->codec.txavail = 0;
261 }
262
263 s->codec.txlen = 0;
264
265 omap_eac_enable_update(s);
266 if (!s->codec.enable)
267 return;
268
269 omap_eac_rate_update(s);
270 fmt.endianness = ((s->codec.config[0] >> 8) & 1);
271 fmt.nchannels = ((s->codec.config[0] >> 10) & 1) ? 2 : 1;
272 fmt.freq = s->codec.rate;
273
274
275
276
277 fmt.fmt = AUD_FMT_U16;
278
279 s->codec.in_voice = AUD_open_in(&s->codec.card, s->codec.in_voice,
280 "eac.codec.in", s, omap_eac_in_cb, &fmt);
281 s->codec.out_voice = AUD_open_out(&s->codec.card, s->codec.out_voice,
282 "eac.codec.out", s, omap_eac_out_cb, &fmt);
283
284 omap_eac_volume_update(s);
285
286 AUD_set_active_in(s->codec.in_voice, 1);
287 AUD_set_active_out(s->codec.out_voice, 1);
288}
289
290static void omap_eac_reset(struct omap_eac_s *s)
291{
292 s->sysconfig = 0;
293 s->config[0] = 0x0c;
294 s->config[1] = 0x09;
295 s->config[2] = 0xab;
296 s->config[3] = 0x03;
297 s->control = 0x00;
298 s->address = 0x00;
299 s->data = 0x0000;
300 s->vtol = 0x00;
301 s->vtsl = 0x00;
302 s->mixer = 0x0000;
303 s->gain[0] = 0xe7e7;
304 s->gain[1] = 0x6767;
305 s->gain[2] = 0x6767;
306 s->gain[3] = 0x6767;
307 s->att = 0xce;
308 s->max[0] = 0;
309 s->max[1] = 0;
310 s->max[2] = 0;
311 s->max[3] = 0;
312 s->max[4] = 0;
313 s->max[5] = 0;
314 s->max[6] = 0;
315
316 s->modem.control = 0x00;
317 s->modem.config = 0x0000;
318 s->bt.control = 0x00;
319 s->bt.config = 0x0000;
320 s->codec.config[0] = 0x0649;
321 s->codec.config[1] = 0x0000;
322 s->codec.config[2] = 0x0007;
323 s->codec.config[3] = 0x1ffc;
324 s->codec.rxoff = 0;
325 s->codec.rxlen = 0;
326 s->codec.txlen = 0;
327 s->codec.rxavail = 0;
328 s->codec.txavail = 0;
329
330 omap_eac_format_update(s);
331 omap_eac_interrupt_update(s);
332}
333
334static uint64_t omap_eac_read(void *opaque, hwaddr addr,
335 unsigned size)
336{
337 struct omap_eac_s *s = (struct omap_eac_s *) opaque;
338 uint32_t ret;
339
340 if (size != 2) {
341 return omap_badwidth_read16(opaque, addr);
342 }
343
344 switch (addr) {
345 case 0x000:
346 return s->config[0];
347 case 0x004:
348 return s->config[1];
349 case 0x008:
350 return s->config[2];
351 case 0x00c:
352 return s->config[3];
353
354 case 0x010:
355 return s->control | ((s->codec.rxavail + s->codec.rxlen > 0) << 7) |
356 ((s->codec.txlen < s->codec.txavail) << 5);
357
358 case 0x014:
359 return s->address;
360 case 0x018:
361 return s->data & 0xff;
362 case 0x01c:
363 return s->data >> 8;
364 case 0x020:
365 return s->vtol;
366 case 0x024:
367 return s->vtsl | (3 << 5);
368 case 0x040:
369 return s->modem.control;
370 case 0x044:
371 return s->modem.config;
372 case 0x060:
373 return s->bt.control;
374 case 0x064:
375 return s->bt.config;
376 case 0x080:
377 return s->mixer;
378 case 0x084:
379 return s->gain[0];
380 case 0x088:
381 return s->gain[1];
382 case 0x08c:
383 return s->gain[2];
384 case 0x090:
385 return s->gain[3];
386 case 0x094:
387 return s->att;
388 case 0x098:
389 return s->max[0];
390 case 0x09c:
391 return s->max[1];
392 case 0x0a0:
393 return s->max[2];
394 case 0x0a4:
395 return s->max[3];
396 case 0x0a8:
397 return s->max[4];
398 case 0x0ac:
399 return s->max[5];
400 case 0x0b0:
401 return s->max[6];
402 case 0x0b4:
403
404 return 0x0000;
405 case 0x0b8:
406 if (likely(s->codec.rxlen > 1)) {
407 ret = s->codec.rxbuf[s->codec.rxoff ++];
408 s->codec.rxlen --;
409 s->codec.rxoff &= EAC_BUF_LEN - 1;
410 return ret;
411 } else if (s->codec.rxlen) {
412 ret = s->codec.rxbuf[s->codec.rxoff ++];
413 s->codec.rxlen --;
414 s->codec.rxoff &= EAC_BUF_LEN - 1;
415 if (s->codec.rxavail)
416 omap_eac_in_refill(s);
417 omap_eac_in_dmarequest_update(s);
418 return ret;
419 }
420 return 0x0000;
421 case 0x0bc:
422 return s->codec.config[0];
423 case 0x0c0:
424 return s->codec.config[1] | ((s->codec.config[1] & 2) << 14);
425 case 0x0c4:
426 return s->codec.config[2];
427 case 0x0c8:
428 return s->codec.config[3];
429 case 0x0cc:
430 case 0x0d0:
431 case 0x0d8:
432 case 0x0e4:
433 case 0x0ec:
434 return 0x0000;
435
436 case 0x100:
437 return 0x0010;
438
439 case 0x104:
440 return s->sysconfig;
441
442 case 0x108:
443 return 1 | 0xe;
444 }
445
446 OMAP_BAD_REG(addr);
447 return 0;
448}
449
450static void omap_eac_write(void *opaque, hwaddr addr,
451 uint64_t value, unsigned size)
452{
453 struct omap_eac_s *s = (struct omap_eac_s *) opaque;
454
455 if (size != 2) {
456 omap_badwidth_write16(opaque, addr, value);
457 return;
458 }
459
460 switch (addr) {
461 case 0x098:
462 case 0x09c:
463 case 0x0a0:
464 case 0x0a4:
465 case 0x0a8:
466 case 0x0ac:
467 case 0x0b0:
468 case 0x0b8:
469 case 0x0d0:
470 case 0x0d8:
471 case 0x0e4:
472 case 0x0ec:
473 case 0x100:
474 case 0x108:
475 OMAP_RO_REG(addr);
476 return;
477
478 case 0x000:
479 s->config[0] = value & 0xff;
480 omap_eac_format_update(s);
481 break;
482 case 0x004:
483 s->config[1] = value & 0xff;
484 omap_eac_format_update(s);
485 break;
486 case 0x008:
487 s->config[2] = value & 0xff;
488 omap_eac_format_update(s);
489 break;
490 case 0x00c:
491 s->config[3] = value & 0xff;
492 omap_eac_format_update(s);
493 break;
494
495 case 0x010:
496
497 s->control = value & 0x5f;
498 omap_eac_interrupt_update(s);
499 break;
500
501 case 0x014:
502 s->address = value & 0xff;
503 break;
504 case 0x018:
505 s->data &= 0xff00;
506 s->data |= value & 0xff;
507 break;
508 case 0x01c:
509 s->data &= 0x00ff;
510 s->data |= value << 8;
511 break;
512 case 0x020:
513 s->vtol = value & 0xf8;
514 break;
515 case 0x024:
516 s->vtsl = value & 0x9f;
517 break;
518 case 0x040:
519 s->modem.control = value & 0x8f;
520 break;
521 case 0x044:
522 s->modem.config = value & 0x7fff;
523 break;
524 case 0x060:
525 s->bt.control = value & 0x8f;
526 break;
527 case 0x064:
528 s->bt.config = value & 0x7fff;
529 break;
530 case 0x080:
531 s->mixer = value & 0x0fff;
532 break;
533 case 0x084:
534 s->gain[0] = value & 0xffff;
535 break;
536 case 0x088:
537 s->gain[1] = value & 0xff7f;
538 break;
539 case 0x08c:
540 s->gain[2] = value & 0xff7f;
541 break;
542 case 0x090:
543 s->gain[3] = value & 0xff7f;
544 break;
545 case 0x094:
546 s->att = value & 0xff;
547 break;
548
549 case 0x0b4:
550 s->codec.txbuf[s->codec.txlen ++] = value;
551 if (unlikely(s->codec.txlen == EAC_BUF_LEN ||
552 s->codec.txlen == s->codec.txavail)) {
553 if (s->codec.txavail)
554 omap_eac_out_empty(s);
555
556 s->codec.txlen = 0;
557 }
558 break;
559
560 case 0x0bc:
561 s->codec.config[0] = value & 0x07ff;
562 omap_eac_format_update(s);
563 break;
564 case 0x0c0:
565 s->codec.config[1] = value & 0x780f;
566 omap_eac_format_update(s);
567 break;
568 case 0x0c4:
569 s->codec.config[2] = value & 0x003f;
570 omap_eac_format_update(s);
571 break;
572 case 0x0c8:
573 s->codec.config[3] = value & 0xffff;
574 omap_eac_format_update(s);
575 break;
576 case 0x0cc:
577 case 0x0d4:
578 case 0x0e0:
579 case 0x0e8:
580 case 0x0f0:
581 break;
582
583 case 0x104:
584 if (value & (1 << 1))
585 omap_eac_reset(s);
586 s->sysconfig = value & 0x31d;
587 break;
588
589 default:
590 OMAP_BAD_REG(addr);
591 return;
592 }
593}
594
595static const MemoryRegionOps omap_eac_ops = {
596 .read = omap_eac_read,
597 .write = omap_eac_write,
598 .endianness = DEVICE_NATIVE_ENDIAN,
599};
600
601static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
602 qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
603{
604 struct omap_eac_s *s = g_new0(struct omap_eac_s, 1);
605
606 s->irq = irq;
607 s->codec.rxdrq = *drq ++;
608 s->codec.txdrq = *drq;
609 omap_eac_reset(s);
610
611 AUD_register_card("OMAP EAC", &s->codec.card);
612
613 memory_region_init_io(&s->iomem, NULL, &omap_eac_ops, s, "omap.eac",
614 omap_l4_region_size(ta, 0));
615 omap_l4_attach(ta, 0, &s->iomem);
616
617 return s;
618}
619
620
621struct omap_sti_s {
622 qemu_irq irq;
623 MemoryRegion iomem;
624 MemoryRegion iomem_fifo;
625 CharBackend chr;
626
627 uint32_t sysconfig;
628 uint32_t systest;
629 uint32_t irqst;
630 uint32_t irqen;
631 uint32_t clkcontrol;
632 uint32_t serial_config;
633};
634
635#define STI_TRACE_CONSOLE_CHANNEL 239
636#define STI_TRACE_CONTROL_CHANNEL 253
637
638static inline void omap_sti_interrupt_update(struct omap_sti_s *s)
639{
640 qemu_set_irq(s->irq, s->irqst & s->irqen);
641}
642
643static void omap_sti_reset(struct omap_sti_s *s)
644{
645 s->sysconfig = 0;
646 s->irqst = 0;
647 s->irqen = 0;
648 s->clkcontrol = 0;
649 s->serial_config = 0;
650
651 omap_sti_interrupt_update(s);
652}
653
654static uint64_t omap_sti_read(void *opaque, hwaddr addr,
655 unsigned size)
656{
657 struct omap_sti_s *s = (struct omap_sti_s *) opaque;
658
659 if (size != 4) {
660 return omap_badwidth_read32(opaque, addr);
661 }
662
663 switch (addr) {
664 case 0x00:
665 return 0x10;
666
667 case 0x10:
668 return s->sysconfig;
669
670 case 0x14:
671 return 0x00;
672
673 case 0x18:
674 return s->irqst;
675
676 case 0x1c:
677 return s->irqen;
678
679 case 0x24:
680 case 0x28:
681
682 return 0;
683
684 case 0x2c:
685 return s->clkcontrol;
686
687 case 0x30:
688 return s->serial_config;
689 }
690
691 OMAP_BAD_REG(addr);
692 return 0;
693}
694
695static void omap_sti_write(void *opaque, hwaddr addr,
696 uint64_t value, unsigned size)
697{
698 struct omap_sti_s *s = (struct omap_sti_s *) opaque;
699
700 if (size != 4) {
701 omap_badwidth_write32(opaque, addr, value);
702 return;
703 }
704
705 switch (addr) {
706 case 0x00:
707 case 0x14:
708 OMAP_RO_REG(addr);
709 return;
710
711 case 0x10:
712 if (value & (1 << 1))
713 omap_sti_reset(s);
714 s->sysconfig = value & 0xfe;
715 break;
716
717 case 0x18:
718 s->irqst &= ~value;
719 omap_sti_interrupt_update(s);
720 break;
721
722 case 0x1c:
723 s->irqen = value & 0xffff;
724 omap_sti_interrupt_update(s);
725 break;
726
727 case 0x2c:
728 s->clkcontrol = value & 0xff;
729 break;
730
731 case 0x30:
732 s->serial_config = value & 0xff;
733 break;
734
735 case 0x24:
736 case 0x28:
737
738 return;
739
740 default:
741 OMAP_BAD_REG(addr);
742 return;
743 }
744}
745
746static const MemoryRegionOps omap_sti_ops = {
747 .read = omap_sti_read,
748 .write = omap_sti_write,
749 .endianness = DEVICE_NATIVE_ENDIAN,
750};
751
752static uint64_t omap_sti_fifo_read(void *opaque, hwaddr addr,
753 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 = (struct omap_sti_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"),
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 = (struct omap_prcm_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 = (struct omap_prcm_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 = (struct omap_sysctl_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 = (struct omap_sysctl_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,
1973 uint32_t value)
1974{
1975 struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
1976 int pad_offset, byte_offset;
1977 int prev_value;
1978
1979 switch (addr) {
1980 case 0x030 ... 0x140:
1981 pad_offset = (addr - 0x30) >> 2;
1982 byte_offset = (addr - 0x30) & (4 - 1);
1983
1984 prev_value = s->padconf[pad_offset];
1985 prev_value &= ~(0xff << (byte_offset * 8));
1986 prev_value |= ((value & 0x1f1f1f1f) << (byte_offset * 8)) & 0x1f1f1f1f;
1987 s->padconf[pad_offset] = prev_value;
1988 break;
1989
1990 default:
1991 OMAP_BAD_REG(addr);
1992 break;
1993 }
1994}
1995
1996static void omap_sysctl_write(void *opaque, hwaddr addr,
1997 uint32_t value)
1998{
1999 struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
2000
2001 switch (addr) {
2002 case 0x000:
2003 case 0x2a4:
2004 case 0x2c0:
2005 case 0x2f8:
2006 case 0x2fc:
2007 case 0x300:
2008 case 0x304:
2009 case 0x308:
2010 case 0x30c:
2011 case 0x310:
2012 case 0x314:
2013 case 0x318:
2014 case 0x31c:
2015 case 0x320:
2016 case 0x324:
2017 case 0x330:
2018 case 0x334:
2019 case 0x338:
2020 case 0x33c:
2021 case 0x340:
2022 case 0x344:
2023 case 0x348:
2024 case 0x34c:
2025 case 0x350:
2026 case 0x354:
2027 OMAP_RO_REG(addr);
2028 return;
2029
2030 case 0x010:
2031 s->sysconfig = value & 0x1e;
2032 break;
2033
2034 case 0x030 ... 0x140:
2035
2036 s->padconf[(addr - 0x30) >> 2] = value & 0x1f1f1f1f;
2037 break;
2038
2039 case 0x270:
2040 s->obs = value & 0xff;
2041 break;
2042
2043 case 0x274:
2044 s->devconfig = value & 0xffffc7ff;
2045 break;
2046
2047 case 0x28c:
2048 break;
2049
2050 case 0x290:
2051 s->msuspendmux[0] = value & 0x3fffffff;
2052 break;
2053 case 0x294:
2054 s->msuspendmux[1] = value & 0x3fffffff;
2055 break;
2056 case 0x298:
2057 s->msuspendmux[2] = value & 0x3fffffff;
2058 break;
2059 case 0x29c:
2060 s->msuspendmux[3] = value & 0x3fffffff;
2061 break;
2062 case 0x2a0:
2063 s->msuspendmux[4] = value & 0x3fffffff;
2064 break;
2065
2066 case 0x2b8:
2067 s->psaconfig = value & 0x1c;
2068 s->psaconfig |= (value & 0x20) ? 2 : 1;
2069 break;
2070 case 0x2bc:
2071 break;
2072
2073 case 0x2b0:
2074 case 0x2b4:
2075 case 0x2d0:
2076 case 0x2d4:
2077 case 0x2d8:
2078 case 0x2dc:
2079 case 0x2e0:
2080 case 0x2e4:
2081 case 0x2f0:
2082 case 0x2f4:
2083 break;
2084
2085 default:
2086 OMAP_BAD_REG(addr);
2087 return;
2088 }
2089}
2090
2091static uint64_t omap_sysctl_readfn(void *opaque, hwaddr addr,
2092 unsigned size)
2093{
2094 switch (size) {
2095 case 1:
2096 return omap_sysctl_read8(opaque, addr);
2097 case 2:
2098 return omap_badwidth_read32(opaque, addr);
2099 case 4:
2100 return omap_sysctl_read(opaque, addr);
2101 default:
2102 g_assert_not_reached();
2103 }
2104}
2105
2106static void omap_sysctl_writefn(void *opaque, hwaddr addr,
2107 uint64_t value, unsigned size)
2108{
2109 switch (size) {
2110 case 1:
2111 omap_sysctl_write8(opaque, addr, value);
2112 break;
2113 case 2:
2114 omap_badwidth_write32(opaque, addr, value);
2115 break;
2116 case 4:
2117 omap_sysctl_write(opaque, addr, value);
2118 break;
2119 default:
2120 g_assert_not_reached();
2121 }
2122}
2123
2124static const MemoryRegionOps omap_sysctl_ops = {
2125 .read = omap_sysctl_readfn,
2126 .write = omap_sysctl_writefn,
2127 .valid.min_access_size = 1,
2128 .valid.max_access_size = 4,
2129 .endianness = DEVICE_NATIVE_ENDIAN,
2130};
2131
2132static void omap_sysctl_reset(struct omap_sysctl_s *s)
2133{
2134
2135 s->sysconfig = 0;
2136 s->obs = 0;
2137 s->devconfig = 0x0c000000;
2138 s->msuspendmux[0] = 0x00000000;
2139 s->msuspendmux[1] = 0x00000000;
2140 s->msuspendmux[2] = 0x00000000;
2141 s->msuspendmux[3] = 0x00000000;
2142 s->msuspendmux[4] = 0x00000000;
2143 s->psaconfig = 1;
2144
2145 s->padconf[0x00] = 0x000f0f0f;
2146 s->padconf[0x01] = 0x00000000;
2147 s->padconf[0x02] = 0x00000000;
2148 s->padconf[0x03] = 0x00000000;
2149 s->padconf[0x04] = 0x00000000;
2150 s->padconf[0x05] = 0x00000000;
2151 s->padconf[0x06] = 0x00000000;
2152 s->padconf[0x07] = 0x00000000;
2153 s->padconf[0x08] = 0x08080800;
2154 s->padconf[0x09] = 0x08080808;
2155 s->padconf[0x0a] = 0x08080808;
2156 s->padconf[0x0b] = 0x08080808;
2157 s->padconf[0x0c] = 0x08080808;
2158 s->padconf[0x0d] = 0x08080800;
2159 s->padconf[0x0e] = 0x08080808;
2160 s->padconf[0x0f] = 0x08080808;
2161 s->padconf[0x10] = 0x18181808;
2162 s->padconf[0x11] = 0x18181818;
2163 s->padconf[0x12] = 0x18181818;
2164 s->padconf[0x13] = 0x18181818;
2165 s->padconf[0x14] = 0x18181818;
2166 s->padconf[0x15] = 0x18181818;
2167 s->padconf[0x16] = 0x18181818;
2168 s->padconf[0x17] = 0x1f001f00;
2169 s->padconf[0x18] = 0x1f1f1f1f;
2170 s->padconf[0x19] = 0x00000000;
2171 s->padconf[0x1a] = 0x1f180000;
2172 s->padconf[0x1b] = 0x00001f1f;
2173 s->padconf[0x1c] = 0x1f001f00;
2174 s->padconf[0x1d] = 0x00000000;
2175 s->padconf[0x1e] = 0x00000000;
2176 s->padconf[0x1f] = 0x08000000;
2177 s->padconf[0x20] = 0x08080808;
2178 s->padconf[0x21] = 0x08080808;
2179 s->padconf[0x22] = 0x0f080808;
2180 s->padconf[0x23] = 0x0f0f0f0f;
2181 s->padconf[0x24] = 0x000f0f0f;
2182 s->padconf[0x25] = 0x1f1f1f0f;
2183 s->padconf[0x26] = 0x080f0f1f;
2184 s->padconf[0x27] = 0x070f1808;
2185 s->padconf[0x28] = 0x0f070707;
2186 s->padconf[0x29] = 0x000f0f1f;
2187 s->padconf[0x2a] = 0x0f0f0f1f;
2188 s->padconf[0x2b] = 0x08000000;
2189 s->padconf[0x2c] = 0x0000001f;
2190 s->padconf[0x2d] = 0x0f0f1f00;
2191 s->padconf[0x2e] = 0x1f1f0f0f;
2192 s->padconf[0x2f] = 0x0f1f1f1f;
2193 s->padconf[0x30] = 0x0f0f0f0f;
2194 s->padconf[0x31] = 0x0f1f0f1f;
2195 s->padconf[0x32] = 0x0f0f0f0f;
2196 s->padconf[0x33] = 0x0f1f0f1f;
2197 s->padconf[0x34] = 0x1f1f0f0f;
2198 s->padconf[0x35] = 0x0f0f1f1f;
2199 s->padconf[0x36] = 0x0f0f1f0f;
2200 s->padconf[0x37] = 0x0f0f0f0f;
2201 s->padconf[0x38] = 0x1f18180f;
2202 s->padconf[0x39] = 0x1f1f1f1f;
2203 s->padconf[0x3a] = 0x00001f1f;
2204 s->padconf[0x3b] = 0x00000000;
2205 s->padconf[0x3c] = 0x00000000;
2206 s->padconf[0x3d] = 0x0f0f0f0f;
2207 s->padconf[0x3e] = 0x18000f0f;
2208 s->padconf[0x3f] = 0x00070000;
2209 s->padconf[0x40] = 0x00000707;
2210 s->padconf[0x41] = 0x0f1f0700;
2211 s->padconf[0x42] = 0x1f1f070f;
2212 s->padconf[0x43] = 0x0008081f;
2213 s->padconf[0x44] = 0x00000800;
2214}
2215
2216static struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
2217 omap_clk iclk, struct omap_mpu_state_s *mpu)
2218{
2219 struct omap_sysctl_s *s = g_new0(struct omap_sysctl_s, 1);
2220
2221 s->mpu = mpu;
2222 omap_sysctl_reset(s);
2223
2224 memory_region_init_io(&s->iomem, NULL, &omap_sysctl_ops, s, "omap.sysctl",
2225 omap_l4_region_size(ta, 0));
2226 omap_l4_attach(ta, 0, &s->iomem);
2227
2228 return s;
2229}
2230
2231
2232static void omap2_mpu_reset(void *opaque)
2233{
2234 struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
2235
2236 omap_dma_reset(mpu->dma);
2237 omap_prcm_reset(mpu->prcm);
2238 omap_sysctl_reset(mpu->sysc);
2239 omap_gp_timer_reset(mpu->gptimer[0]);
2240 omap_gp_timer_reset(mpu->gptimer[1]);
2241 omap_gp_timer_reset(mpu->gptimer[2]);
2242 omap_gp_timer_reset(mpu->gptimer[3]);
2243 omap_gp_timer_reset(mpu->gptimer[4]);
2244 omap_gp_timer_reset(mpu->gptimer[5]);
2245 omap_gp_timer_reset(mpu->gptimer[6]);
2246 omap_gp_timer_reset(mpu->gptimer[7]);
2247 omap_gp_timer_reset(mpu->gptimer[8]);
2248 omap_gp_timer_reset(mpu->gptimer[9]);
2249 omap_gp_timer_reset(mpu->gptimer[10]);
2250 omap_gp_timer_reset(mpu->gptimer[11]);
2251 omap_synctimer_reset(mpu->synctimer);
2252 omap_sdrc_reset(mpu->sdrc);
2253 omap_gpmc_reset(mpu->gpmc);
2254 omap_dss_reset(mpu->dss);
2255 omap_uart_reset(mpu->uart[0]);
2256 omap_uart_reset(mpu->uart[1]);
2257 omap_uart_reset(mpu->uart[2]);
2258 omap_mmc_reset(mpu->mmc);
2259 omap_mcspi_reset(mpu->mcspi[0]);
2260 omap_mcspi_reset(mpu->mcspi[1]);
2261 cpu_reset(CPU(mpu->cpu));
2262}
2263
2264static int omap2_validate_addr(struct omap_mpu_state_s *s,
2265 hwaddr addr)
2266{
2267 return 1;
2268}
2269
2270static const struct dma_irq_map omap2_dma_irq_map[] = {
2271 { 0, OMAP_INT_24XX_SDMA_IRQ0 },
2272 { 0, OMAP_INT_24XX_SDMA_IRQ1 },
2273 { 0, OMAP_INT_24XX_SDMA_IRQ2 },
2274 { 0, OMAP_INT_24XX_SDMA_IRQ3 },
2275};
2276
2277struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
2278 unsigned long sdram_size,
2279 const char *cpu_type)
2280{
2281 struct omap_mpu_state_s *s = g_new0(struct omap_mpu_state_s, 1);
2282 qemu_irq dma_irqs[4];
2283 DriveInfo *dinfo;
2284 int i;
2285 SysBusDevice *busdev;
2286 struct omap_target_agent_s *ta;
2287
2288
2289 s->mpu_model = omap2420;
2290 s->cpu = ARM_CPU(cpu_create(cpu_type));
2291 s->sdram_size = sdram_size;
2292 s->sram_size = OMAP242X_SRAM_SIZE;
2293
2294 s->wakeup = qemu_allocate_irq(omap_mpu_wakeup, s, 0);
2295
2296
2297 omap_clk_init(s);
2298
2299
2300 memory_region_allocate_system_memory(&s->sdram, NULL, "omap2.dram",
2301 s->sdram_size);
2302 memory_region_add_subregion(sysmem, OMAP2_Q2_BASE, &s->sdram);
2303 memory_region_init_ram(&s->sram, NULL, "omap2.sram", s->sram_size,
2304 &error_fatal);
2305 memory_region_add_subregion(sysmem, OMAP2_SRAM_BASE, &s->sram);
2306
2307 s->l4 = omap_l4_init(sysmem, OMAP2_L4_BASE, 54);
2308
2309
2310 s->ih[0] = qdev_create(NULL, "omap2-intc");
2311 qdev_prop_set_uint8(s->ih[0], "revision", 0x21);
2312 qdev_prop_set_ptr(s->ih[0], "fclk", omap_findclk(s, "mpu_intc_fclk"));
2313 qdev_prop_set_ptr(s->ih[0], "iclk", omap_findclk(s, "mpu_intc_iclk"));
2314 qdev_init_nofail(s->ih[0]);
2315 busdev = SYS_BUS_DEVICE(s->ih[0]);
2316 sysbus_connect_irq(busdev, 0,
2317 qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
2318 sysbus_connect_irq(busdev, 1,
2319 qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_FIQ));
2320 sysbus_mmio_map(busdev, 0, 0x480fe000);
2321 s->prcm = omap_prcm_init(omap_l4tao(s->l4, 3),
2322 qdev_get_gpio_in(s->ih[0],
2323 OMAP_INT_24XX_PRCM_MPU_IRQ),
2324 NULL, NULL, s);
2325
2326 s->sysc = omap_sysctl_init(omap_l4tao(s->l4, 1),
2327 omap_findclk(s, "omapctrl_iclk"), s);
2328
2329 for (i = 0; i < 4; i++) {
2330 dma_irqs[i] = qdev_get_gpio_in(s->ih[omap2_dma_irq_map[i].ih],
2331 omap2_dma_irq_map[i].intr);
2332 }
2333 s->dma = omap_dma4_init(0x48056000, dma_irqs, sysmem, s, 256, 32,
2334 omap_findclk(s, "sdma_iclk"),
2335 omap_findclk(s, "sdma_fclk"));
2336 s->port->addr_valid = omap2_validate_addr;
2337
2338
2339 soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sdram),
2340 OMAP2_Q2_BASE, s->sdram_size);
2341 soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sram),
2342 OMAP2_SRAM_BASE, s->sram_size);
2343
2344 s->uart[0] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 19),
2345 qdev_get_gpio_in(s->ih[0],
2346 OMAP_INT_24XX_UART1_IRQ),
2347 omap_findclk(s, "uart1_fclk"),
2348 omap_findclk(s, "uart1_iclk"),
2349 s->drq[OMAP24XX_DMA_UART1_TX],
2350 s->drq[OMAP24XX_DMA_UART1_RX],
2351 "uart1",
2352 serial_hds[0]);
2353 s->uart[1] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 20),
2354 qdev_get_gpio_in(s->ih[0],
2355 OMAP_INT_24XX_UART2_IRQ),
2356 omap_findclk(s, "uart2_fclk"),
2357 omap_findclk(s, "uart2_iclk"),
2358 s->drq[OMAP24XX_DMA_UART2_TX],
2359 s->drq[OMAP24XX_DMA_UART2_RX],
2360 "uart2",
2361 serial_hds[0] ? serial_hds[1] : NULL);
2362 s->uart[2] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 21),
2363 qdev_get_gpio_in(s->ih[0],
2364 OMAP_INT_24XX_UART3_IRQ),
2365 omap_findclk(s, "uart3_fclk"),
2366 omap_findclk(s, "uart3_iclk"),
2367 s->drq[OMAP24XX_DMA_UART3_TX],
2368 s->drq[OMAP24XX_DMA_UART3_RX],
2369 "uart3",
2370 serial_hds[0] && serial_hds[1] ? serial_hds[2] : NULL);
2371
2372 s->gptimer[0] = omap_gp_timer_init(omap_l4ta(s->l4, 7),
2373 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER1),
2374 omap_findclk(s, "wu_gpt1_clk"),
2375 omap_findclk(s, "wu_l4_iclk"));
2376 s->gptimer[1] = omap_gp_timer_init(omap_l4ta(s->l4, 8),
2377 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER2),
2378 omap_findclk(s, "core_gpt2_clk"),
2379 omap_findclk(s, "core_l4_iclk"));
2380 s->gptimer[2] = omap_gp_timer_init(omap_l4ta(s->l4, 22),
2381 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER3),
2382 omap_findclk(s, "core_gpt3_clk"),
2383 omap_findclk(s, "core_l4_iclk"));
2384 s->gptimer[3] = omap_gp_timer_init(omap_l4ta(s->l4, 23),
2385 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER4),
2386 omap_findclk(s, "core_gpt4_clk"),
2387 omap_findclk(s, "core_l4_iclk"));
2388 s->gptimer[4] = omap_gp_timer_init(omap_l4ta(s->l4, 24),
2389 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER5),
2390 omap_findclk(s, "core_gpt5_clk"),
2391 omap_findclk(s, "core_l4_iclk"));
2392 s->gptimer[5] = omap_gp_timer_init(omap_l4ta(s->l4, 25),
2393 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER6),
2394 omap_findclk(s, "core_gpt6_clk"),
2395 omap_findclk(s, "core_l4_iclk"));
2396 s->gptimer[6] = omap_gp_timer_init(omap_l4ta(s->l4, 26),
2397 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER7),
2398 omap_findclk(s, "core_gpt7_clk"),
2399 omap_findclk(s, "core_l4_iclk"));
2400 s->gptimer[7] = omap_gp_timer_init(omap_l4ta(s->l4, 27),
2401 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER8),
2402 omap_findclk(s, "core_gpt8_clk"),
2403 omap_findclk(s, "core_l4_iclk"));
2404 s->gptimer[8] = omap_gp_timer_init(omap_l4ta(s->l4, 28),
2405 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER9),
2406 omap_findclk(s, "core_gpt9_clk"),
2407 omap_findclk(s, "core_l4_iclk"));
2408 s->gptimer[9] = omap_gp_timer_init(omap_l4ta(s->l4, 29),
2409 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER10),
2410 omap_findclk(s, "core_gpt10_clk"),
2411 omap_findclk(s, "core_l4_iclk"));
2412 s->gptimer[10] = omap_gp_timer_init(omap_l4ta(s->l4, 30),
2413 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER11),
2414 omap_findclk(s, "core_gpt11_clk"),
2415 omap_findclk(s, "core_l4_iclk"));
2416 s->gptimer[11] = omap_gp_timer_init(omap_l4ta(s->l4, 31),
2417 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER12),
2418 omap_findclk(s, "core_gpt12_clk"),
2419 omap_findclk(s, "core_l4_iclk"));
2420
2421 omap_tap_init(omap_l4ta(s->l4, 2), s);
2422
2423 s->synctimer = omap_synctimer_init(omap_l4tao(s->l4, 2), s,
2424 omap_findclk(s, "clk32-kHz"),
2425 omap_findclk(s, "core_l4_iclk"));
2426
2427 s->i2c[0] = qdev_create(NULL, "omap_i2c");
2428 qdev_prop_set_uint8(s->i2c[0], "revision", 0x34);
2429 qdev_prop_set_ptr(s->i2c[0], "iclk", omap_findclk(s, "i2c1.iclk"));
2430 qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "i2c1.fclk"));
2431 qdev_init_nofail(s->i2c[0]);
2432 busdev = SYS_BUS_DEVICE(s->i2c[0]);
2433 sysbus_connect_irq(busdev, 0,
2434 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C1_IRQ));
2435 sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C1_TX]);
2436 sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C1_RX]);
2437 sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 5), 0));
2438
2439 s->i2c[1] = qdev_create(NULL, "omap_i2c");
2440 qdev_prop_set_uint8(s->i2c[1], "revision", 0x34);
2441 qdev_prop_set_ptr(s->i2c[1], "iclk", omap_findclk(s, "i2c2.iclk"));
2442 qdev_prop_set_ptr(s->i2c[1], "fclk", omap_findclk(s, "i2c2.fclk"));
2443 qdev_init_nofail(s->i2c[1]);
2444 busdev = SYS_BUS_DEVICE(s->i2c[1]);
2445 sysbus_connect_irq(busdev, 0,
2446 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C2_IRQ));
2447 sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C2_TX]);
2448 sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C2_RX]);
2449 sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 6), 0));
2450
2451 s->gpio = qdev_create(NULL, "omap2-gpio");
2452 qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
2453 qdev_prop_set_ptr(s->gpio, "iclk", omap_findclk(s, "gpio_iclk"));
2454 qdev_prop_set_ptr(s->gpio, "fclk0", omap_findclk(s, "gpio1_dbclk"));
2455 qdev_prop_set_ptr(s->gpio, "fclk1", omap_findclk(s, "gpio2_dbclk"));
2456 qdev_prop_set_ptr(s->gpio, "fclk2", omap_findclk(s, "gpio3_dbclk"));
2457 qdev_prop_set_ptr(s->gpio, "fclk3", omap_findclk(s, "gpio4_dbclk"));
2458 if (s->mpu_model == omap2430) {
2459 qdev_prop_set_ptr(s->gpio, "fclk4", omap_findclk(s, "gpio5_dbclk"));
2460 }
2461 qdev_init_nofail(s->gpio);
2462 busdev = SYS_BUS_DEVICE(s->gpio);
2463 sysbus_connect_irq(busdev, 0,
2464 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK1));
2465 sysbus_connect_irq(busdev, 3,
2466 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK2));
2467 sysbus_connect_irq(busdev, 6,
2468 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK3));
2469 sysbus_connect_irq(busdev, 9,
2470 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK4));
2471 if (s->mpu_model == omap2430) {
2472 sysbus_connect_irq(busdev, 12,
2473 qdev_get_gpio_in(s->ih[0],
2474 OMAP_INT_243X_GPIO_BANK5));
2475 }
2476 ta = omap_l4ta(s->l4, 3);
2477 sysbus_mmio_map(busdev, 0, omap_l4_region_base(ta, 1));
2478 sysbus_mmio_map(busdev, 1, omap_l4_region_base(ta, 0));
2479 sysbus_mmio_map(busdev, 2, omap_l4_region_base(ta, 2));
2480 sysbus_mmio_map(busdev, 3, omap_l4_region_base(ta, 4));
2481 sysbus_mmio_map(busdev, 4, omap_l4_region_base(ta, 5));
2482
2483 s->sdrc = omap_sdrc_init(sysmem, 0x68009000);
2484 s->gpmc = omap_gpmc_init(s, 0x6800a000,
2485 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPMC_IRQ),
2486 s->drq[OMAP24XX_DMA_GPMC]);
2487
2488 dinfo = drive_get(IF_SD, 0, 0);
2489 if (!dinfo) {
2490 error_report("missing SecureDigital device");
2491 exit(1);
2492 }
2493 s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9),
2494 blk_by_legacy_dinfo(dinfo),
2495 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MMC_IRQ),
2496 &s->drq[OMAP24XX_DMA_MMC1_TX],
2497 omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk"));
2498
2499 s->mcspi[0] = omap_mcspi_init(omap_l4ta(s->l4, 35), 4,
2500 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MCSPI1_IRQ),
2501 &s->drq[OMAP24XX_DMA_SPI1_TX0],
2502 omap_findclk(s, "spi1_fclk"),
2503 omap_findclk(s, "spi1_iclk"));
2504 s->mcspi[1] = omap_mcspi_init(omap_l4ta(s->l4, 36), 2,
2505 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MCSPI2_IRQ),
2506 &s->drq[OMAP24XX_DMA_SPI2_TX0],
2507 omap_findclk(s, "spi2_fclk"),
2508 omap_findclk(s, "spi2_iclk"));
2509
2510 s->dss = omap_dss_init(omap_l4ta(s->l4, 10), sysmem, 0x68000800,
2511
2512 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_DSS_IRQ),
2513 s->drq[OMAP24XX_DMA_DSS],
2514 omap_findclk(s, "dss_clk1"), omap_findclk(s, "dss_clk2"),
2515 omap_findclk(s, "dss_54m_clk"),
2516 omap_findclk(s, "dss_l3_iclk"),
2517 omap_findclk(s, "dss_l4_iclk"));
2518
2519 omap_sti_init(omap_l4ta(s->l4, 18), sysmem, 0x54000000,
2520 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_STI),
2521 omap_findclk(s, "emul_ck"),
2522 serial_hds[0] && serial_hds[1] && serial_hds[2] ?
2523 serial_hds[3] : NULL);
2524
2525 s->eac = omap_eac_init(omap_l4ta(s->l4, 32),
2526 qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_EAC_IRQ),
2527
2528 &s->drq[OMAP24XX_DMA_EAC_AC_RD],
2529 omap_findclk(s, "func_96m_clk"),
2530 omap_findclk(s, "core_l4_iclk"));
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
2708
2709
2710
2711
2712
2713 qemu_register_reset(omap2_mpu_reset, s);
2714
2715 return s;
2716}
2717