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