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