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