1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include "hw/hw.h"
20#include "hw/arm/arm.h"
21#include "hw/arm/omap.h"
22#include "sysemu/sysemu.h"
23#include "hw/arm/soc_dma.h"
24#include "sysemu/blockdev.h"
25#include "qemu/range.h"
26#include "hw/sysbus.h"
27
28
29uint32_t omap_badwidth_read8(void *opaque, hwaddr addr)
30{
31 uint8_t ret;
32
33 OMAP_8B_REG(addr);
34 cpu_physical_memory_read(addr, &ret, 1);
35 return ret;
36}
37
38void omap_badwidth_write8(void *opaque, hwaddr addr,
39 uint32_t value)
40{
41 uint8_t val8 = value;
42
43 OMAP_8B_REG(addr);
44 cpu_physical_memory_write(addr, &val8, 1);
45}
46
47uint32_t omap_badwidth_read16(void *opaque, hwaddr addr)
48{
49 uint16_t ret;
50
51 OMAP_16B_REG(addr);
52 cpu_physical_memory_read(addr, &ret, 2);
53 return ret;
54}
55
56void omap_badwidth_write16(void *opaque, hwaddr addr,
57 uint32_t value)
58{
59 uint16_t val16 = value;
60
61 OMAP_16B_REG(addr);
62 cpu_physical_memory_write(addr, &val16, 2);
63}
64
65uint32_t omap_badwidth_read32(void *opaque, hwaddr addr)
66{
67 uint32_t ret;
68
69 OMAP_32B_REG(addr);
70 cpu_physical_memory_read(addr, &ret, 4);
71 return ret;
72}
73
74void omap_badwidth_write32(void *opaque, hwaddr addr,
75 uint32_t value)
76{
77 OMAP_32B_REG(addr);
78 cpu_physical_memory_write(addr, &value, 4);
79}
80
81
82struct omap_mpu_timer_s {
83 MemoryRegion iomem;
84 qemu_irq irq;
85 omap_clk clk;
86 uint32_t val;
87 int64_t time;
88 QEMUTimer *timer;
89 QEMUBH *tick;
90 int64_t rate;
91 int it_ena;
92
93 int enable;
94 int ptv;
95 int ar;
96 int st;
97 uint32_t reset_val;
98};
99
100static inline uint32_t omap_timer_read(struct omap_mpu_timer_s *timer)
101{
102 uint64_t distance = qemu_get_clock_ns(vm_clock) - timer->time;
103
104 if (timer->st && timer->enable && timer->rate)
105 return timer->val - muldiv64(distance >> (timer->ptv + 1),
106 timer->rate, get_ticks_per_sec());
107 else
108 return timer->val;
109}
110
111static inline void omap_timer_sync(struct omap_mpu_timer_s *timer)
112{
113 timer->val = omap_timer_read(timer);
114 timer->time = qemu_get_clock_ns(vm_clock);
115}
116
117static inline void omap_timer_update(struct omap_mpu_timer_s *timer)
118{
119 int64_t expires;
120
121 if (timer->enable && timer->st && timer->rate) {
122 timer->val = timer->reset_val;
123 expires = muldiv64((uint64_t) timer->val << (timer->ptv + 1),
124 get_ticks_per_sec(), timer->rate);
125
126
127
128
129
130
131
132 if (expires > (get_ticks_per_sec() >> 10) || timer->ar)
133 qemu_mod_timer(timer->timer, timer->time + expires);
134 else
135 qemu_bh_schedule(timer->tick);
136 } else
137 qemu_del_timer(timer->timer);
138}
139
140static void omap_timer_fire(void *opaque)
141{
142 struct omap_mpu_timer_s *timer = opaque;
143
144 if (!timer->ar) {
145 timer->val = 0;
146 timer->st = 0;
147 }
148
149 if (timer->it_ena)
150
151 qemu_irq_pulse(timer->irq);
152}
153
154static void omap_timer_tick(void *opaque)
155{
156 struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
157
158 omap_timer_sync(timer);
159 omap_timer_fire(timer);
160 omap_timer_update(timer);
161}
162
163static void omap_timer_clk_update(void *opaque, int line, int on)
164{
165 struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
166
167 omap_timer_sync(timer);
168 timer->rate = on ? omap_clk_getrate(timer->clk) : 0;
169 omap_timer_update(timer);
170}
171
172static void omap_timer_clk_setup(struct omap_mpu_timer_s *timer)
173{
174 omap_clk_adduser(timer->clk,
175 qemu_allocate_irqs(omap_timer_clk_update, timer, 1)[0]);
176 timer->rate = omap_clk_getrate(timer->clk);
177}
178
179static uint64_t omap_mpu_timer_read(void *opaque, hwaddr addr,
180 unsigned size)
181{
182 struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
183
184 if (size != 4) {
185 return omap_badwidth_read32(opaque, addr);
186 }
187
188 switch (addr) {
189 case 0x00:
190 return (s->enable << 5) | (s->ptv << 2) | (s->ar << 1) | s->st;
191
192 case 0x04:
193 break;
194
195 case 0x08:
196 return omap_timer_read(s);
197 }
198
199 OMAP_BAD_REG(addr);
200 return 0;
201}
202
203static void omap_mpu_timer_write(void *opaque, hwaddr addr,
204 uint64_t value, unsigned size)
205{
206 struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
207
208 if (size != 4) {
209 return omap_badwidth_write32(opaque, addr, value);
210 }
211
212 switch (addr) {
213 case 0x00:
214 omap_timer_sync(s);
215 s->enable = (value >> 5) & 1;
216 s->ptv = (value >> 2) & 7;
217 s->ar = (value >> 1) & 1;
218 s->st = value & 1;
219 omap_timer_update(s);
220 return;
221
222 case 0x04:
223 s->reset_val = value;
224 return;
225
226 case 0x08:
227 OMAP_RO_REG(addr);
228 break;
229
230 default:
231 OMAP_BAD_REG(addr);
232 }
233}
234
235static const MemoryRegionOps omap_mpu_timer_ops = {
236 .read = omap_mpu_timer_read,
237 .write = omap_mpu_timer_write,
238 .endianness = DEVICE_LITTLE_ENDIAN,
239};
240
241static void omap_mpu_timer_reset(struct omap_mpu_timer_s *s)
242{
243 qemu_del_timer(s->timer);
244 s->enable = 0;
245 s->reset_val = 31337;
246 s->val = 0;
247 s->ptv = 0;
248 s->ar = 0;
249 s->st = 0;
250 s->it_ena = 1;
251}
252
253static struct omap_mpu_timer_s *omap_mpu_timer_init(MemoryRegion *system_memory,
254 hwaddr base,
255 qemu_irq irq, omap_clk clk)
256{
257 struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *)
258 g_malloc0(sizeof(struct omap_mpu_timer_s));
259
260 s->irq = irq;
261 s->clk = clk;
262 s->timer = qemu_new_timer_ns(vm_clock, omap_timer_tick, s);
263 s->tick = qemu_bh_new(omap_timer_fire, s);
264 omap_mpu_timer_reset(s);
265 omap_timer_clk_setup(s);
266
267 memory_region_init_io(&s->iomem, &omap_mpu_timer_ops, s,
268 "omap-mpu-timer", 0x100);
269
270 memory_region_add_subregion(system_memory, base, &s->iomem);
271
272 return s;
273}
274
275
276struct omap_watchdog_timer_s {
277 struct omap_mpu_timer_s timer;
278 MemoryRegion iomem;
279 uint8_t last_wr;
280 int mode;
281 int free;
282 int reset;
283};
284
285static uint64_t omap_wd_timer_read(void *opaque, hwaddr addr,
286 unsigned size)
287{
288 struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
289
290 if (size != 2) {
291 return omap_badwidth_read16(opaque, addr);
292 }
293
294 switch (addr) {
295 case 0x00:
296 return (s->timer.ptv << 9) | (s->timer.ar << 8) |
297 (s->timer.st << 7) | (s->free << 1);
298
299 case 0x04:
300 return omap_timer_read(&s->timer);
301
302 case 0x08:
303 return s->mode << 15;
304 }
305
306 OMAP_BAD_REG(addr);
307 return 0;
308}
309
310static void omap_wd_timer_write(void *opaque, hwaddr addr,
311 uint64_t value, unsigned size)
312{
313 struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
314
315 if (size != 2) {
316 return omap_badwidth_write16(opaque, addr, value);
317 }
318
319 switch (addr) {
320 case 0x00:
321 omap_timer_sync(&s->timer);
322 s->timer.ptv = (value >> 9) & 7;
323 s->timer.ar = (value >> 8) & 1;
324 s->timer.st = (value >> 7) & 1;
325 s->free = (value >> 1) & 1;
326 omap_timer_update(&s->timer);
327 break;
328
329 case 0x04:
330 s->timer.reset_val = value & 0xffff;
331 break;
332
333 case 0x08:
334 if (!s->mode && ((value >> 15) & 1))
335 omap_clk_get(s->timer.clk);
336 s->mode |= (value >> 15) & 1;
337 if (s->last_wr == 0xf5) {
338 if ((value & 0xff) == 0xa0) {
339 if (s->mode) {
340 s->mode = 0;
341 omap_clk_put(s->timer.clk);
342 }
343 } else {
344
345
346 s->reset = 1;
347 qemu_system_reset_request();
348 }
349 }
350 s->last_wr = value & 0xff;
351 break;
352
353 default:
354 OMAP_BAD_REG(addr);
355 }
356}
357
358static const MemoryRegionOps omap_wd_timer_ops = {
359 .read = omap_wd_timer_read,
360 .write = omap_wd_timer_write,
361 .endianness = DEVICE_NATIVE_ENDIAN,
362};
363
364static void omap_wd_timer_reset(struct omap_watchdog_timer_s *s)
365{
366 qemu_del_timer(s->timer.timer);
367 if (!s->mode)
368 omap_clk_get(s->timer.clk);
369 s->mode = 1;
370 s->free = 1;
371 s->reset = 0;
372 s->timer.enable = 1;
373 s->timer.it_ena = 1;
374 s->timer.reset_val = 0xffff;
375 s->timer.val = 0;
376 s->timer.st = 0;
377 s->timer.ptv = 0;
378 s->timer.ar = 0;
379 omap_timer_update(&s->timer);
380}
381
382static struct omap_watchdog_timer_s *omap_wd_timer_init(MemoryRegion *memory,
383 hwaddr base,
384 qemu_irq irq, omap_clk clk)
385{
386 struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *)
387 g_malloc0(sizeof(struct omap_watchdog_timer_s));
388
389 s->timer.irq = irq;
390 s->timer.clk = clk;
391 s->timer.timer = qemu_new_timer_ns(vm_clock, omap_timer_tick, &s->timer);
392 omap_wd_timer_reset(s);
393 omap_timer_clk_setup(&s->timer);
394
395 memory_region_init_io(&s->iomem, &omap_wd_timer_ops, s,
396 "omap-wd-timer", 0x100);
397 memory_region_add_subregion(memory, base, &s->iomem);
398
399 return s;
400}
401
402
403struct omap_32khz_timer_s {
404 struct omap_mpu_timer_s timer;
405 MemoryRegion iomem;
406};
407
408static uint64_t omap_os_timer_read(void *opaque, hwaddr addr,
409 unsigned size)
410{
411 struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
412 int offset = addr & OMAP_MPUI_REG_MASK;
413
414 if (size != 4) {
415 return omap_badwidth_read32(opaque, addr);
416 }
417
418 switch (offset) {
419 case 0x00:
420 return s->timer.reset_val;
421
422 case 0x04:
423 return omap_timer_read(&s->timer);
424
425 case 0x08:
426 return (s->timer.ar << 3) | (s->timer.it_ena << 2) | s->timer.st;
427
428 default:
429 break;
430 }
431 OMAP_BAD_REG(addr);
432 return 0;
433}
434
435static void omap_os_timer_write(void *opaque, hwaddr addr,
436 uint64_t value, unsigned size)
437{
438 struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
439 int offset = addr & OMAP_MPUI_REG_MASK;
440
441 if (size != 4) {
442 return omap_badwidth_write32(opaque, addr, value);
443 }
444
445 switch (offset) {
446 case 0x00:
447 s->timer.reset_val = value & 0x00ffffff;
448 break;
449
450 case 0x04:
451 OMAP_RO_REG(addr);
452 break;
453
454 case 0x08:
455 s->timer.ar = (value >> 3) & 1;
456 s->timer.it_ena = (value >> 2) & 1;
457 if (s->timer.st != (value & 1) || (value & 2)) {
458 omap_timer_sync(&s->timer);
459 s->timer.enable = value & 1;
460 s->timer.st = value & 1;
461 omap_timer_update(&s->timer);
462 }
463 break;
464
465 default:
466 OMAP_BAD_REG(addr);
467 }
468}
469
470static const MemoryRegionOps omap_os_timer_ops = {
471 .read = omap_os_timer_read,
472 .write = omap_os_timer_write,
473 .endianness = DEVICE_NATIVE_ENDIAN,
474};
475
476static void omap_os_timer_reset(struct omap_32khz_timer_s *s)
477{
478 qemu_del_timer(s->timer.timer);
479 s->timer.enable = 0;
480 s->timer.it_ena = 0;
481 s->timer.reset_val = 0x00ffffff;
482 s->timer.val = 0;
483 s->timer.st = 0;
484 s->timer.ptv = 0;
485 s->timer.ar = 1;
486}
487
488static struct omap_32khz_timer_s *omap_os_timer_init(MemoryRegion *memory,
489 hwaddr base,
490 qemu_irq irq, omap_clk clk)
491{
492 struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *)
493 g_malloc0(sizeof(struct omap_32khz_timer_s));
494
495 s->timer.irq = irq;
496 s->timer.clk = clk;
497 s->timer.timer = qemu_new_timer_ns(vm_clock, omap_timer_tick, &s->timer);
498 omap_os_timer_reset(s);
499 omap_timer_clk_setup(&s->timer);
500
501 memory_region_init_io(&s->iomem, &omap_os_timer_ops, s,
502 "omap-os-timer", 0x800);
503 memory_region_add_subregion(memory, base, &s->iomem);
504
505 return s;
506}
507
508
509static uint64_t omap_ulpd_pm_read(void *opaque, hwaddr addr,
510 unsigned size)
511{
512 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
513 uint16_t ret;
514
515 if (size != 2) {
516 return omap_badwidth_read16(opaque, addr);
517 }
518
519 switch (addr) {
520 case 0x14:
521 ret = s->ulpd_pm_regs[addr >> 2];
522 s->ulpd_pm_regs[addr >> 2] = 0;
523 qemu_irq_lower(qdev_get_gpio_in(s->ih[1], OMAP_INT_GAUGE_32K));
524 return ret;
525
526 case 0x18:
527 case 0x1c:
528 case 0x20:
529 case 0x28:
530 case 0x2c:
531 OMAP_BAD_REG(addr);
532
533 case 0x00:
534 case 0x04:
535 case 0x08:
536 case 0x0c:
537 case 0x10:
538 case 0x24:
539 case 0x30:
540 case 0x34:
541 case 0x38:
542 case 0x3c:
543 case 0x40:
544
545 case 0x48:
546 case 0x4c:
547 case 0x50:
548 return s->ulpd_pm_regs[addr >> 2];
549 }
550
551 OMAP_BAD_REG(addr);
552 return 0;
553}
554
555static inline void omap_ulpd_clk_update(struct omap_mpu_state_s *s,
556 uint16_t diff, uint16_t value)
557{
558 if (diff & (1 << 4))
559 omap_clk_onoff(omap_findclk(s, "usb_clk0"), (value >> 4) & 1);
560 if (diff & (1 << 5))
561 omap_clk_onoff(omap_findclk(s, "usb_w2fc_ck"), (~value >> 5) & 1);
562}
563
564static inline void omap_ulpd_req_update(struct omap_mpu_state_s *s,
565 uint16_t diff, uint16_t value)
566{
567 if (diff & (1 << 0))
568 omap_clk_canidle(omap_findclk(s, "dpll4"), (~value >> 0) & 1);
569 if (diff & (1 << 1))
570 omap_clk_canidle(omap_findclk(s, "com_mclk_out"), (~value >> 1) & 1);
571 if (diff & (1 << 2))
572 omap_clk_canidle(omap_findclk(s, "bt_mclk_out"), (~value >> 2) & 1);
573 if (diff & (1 << 3))
574 omap_clk_canidle(omap_findclk(s, "usb_clk0"), (~value >> 3) & 1);
575}
576
577static void omap_ulpd_pm_write(void *opaque, hwaddr addr,
578 uint64_t value, unsigned size)
579{
580 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
581 int64_t now, ticks;
582 int div, mult;
583 static const int bypass_div[4] = { 1, 2, 4, 4 };
584 uint16_t diff;
585
586 if (size != 2) {
587 return omap_badwidth_write16(opaque, addr, value);
588 }
589
590 switch (addr) {
591 case 0x00:
592 case 0x04:
593 case 0x08:
594 case 0x0c:
595 case 0x14:
596 case 0x40:
597 OMAP_RO_REG(addr);
598 break;
599
600 case 0x10:
601
602 if ((s->ulpd_pm_regs[addr >> 2] ^ value) & 1) {
603 now = qemu_get_clock_ns(vm_clock);
604
605 if (value & 1)
606 s->ulpd_gauge_start = now;
607 else {
608 now -= s->ulpd_gauge_start;
609
610
611 ticks = muldiv64(now, 32768, get_ticks_per_sec());
612 s->ulpd_pm_regs[0x00 >> 2] = (ticks >> 0) & 0xffff;
613 s->ulpd_pm_regs[0x04 >> 2] = (ticks >> 16) & 0xffff;
614 if (ticks >> 32)
615 s->ulpd_pm_regs[0x14 >> 2] |= 1 << 2;
616
617
618 ticks = muldiv64(now, 12000000, get_ticks_per_sec());
619 s->ulpd_pm_regs[0x08 >> 2] = (ticks >> 0) & 0xffff;
620 s->ulpd_pm_regs[0x0c >> 2] = (ticks >> 16) & 0xffff;
621 if (ticks >> 32)
622 s->ulpd_pm_regs[0x14 >> 2] |= 1 << 1;
623
624 s->ulpd_pm_regs[0x14 >> 2] |= 1 << 0;
625 qemu_irq_raise(qdev_get_gpio_in(s->ih[1], OMAP_INT_GAUGE_32K));
626 }
627 }
628 s->ulpd_pm_regs[addr >> 2] = value;
629 break;
630
631 case 0x18:
632 case 0x1c:
633 case 0x20:
634 case 0x28:
635 case 0x2c:
636 OMAP_BAD_REG(addr);
637
638 case 0x24:
639 case 0x38:
640 case 0x48:
641 case 0x50:
642 s->ulpd_pm_regs[addr >> 2] = value;
643 break;
644
645 case 0x30:
646 diff = s->ulpd_pm_regs[addr >> 2] ^ value;
647 s->ulpd_pm_regs[addr >> 2] = value & 0x3f;
648 omap_ulpd_clk_update(s, diff, value);
649 break;
650
651 case 0x34:
652 diff = s->ulpd_pm_regs[addr >> 2] ^ value;
653 s->ulpd_pm_regs[addr >> 2] = value & 0x1f;
654 omap_ulpd_req_update(s, diff, value);
655 break;
656
657 case 0x3c:
658
659
660
661
662 diff = s->ulpd_pm_regs[addr >> 2] & value;
663 s->ulpd_pm_regs[addr >> 2] = value & 0x2fff;
664 if (diff & (0x3ff << 2)) {
665 if (value & (1 << 4)) {
666 div = ((value >> 5) & 3) + 1;
667 mult = MIN((value >> 7) & 0x1f, 1);
668 } else {
669 div = bypass_div[((value >> 2) & 3)];
670 mult = 1;
671 }
672 omap_clk_setrate(omap_findclk(s, "dpll4"), div, mult);
673 }
674
675
676 s->ulpd_pm_regs[addr >> 2] =
677 (s->ulpd_pm_regs[addr >> 2] & 0xfffe) |
678 ((s->ulpd_pm_regs[addr >> 2] >> 4) & 1);
679
680
681 s->ulpd_pm_regs[addr >> 2] |= 2;
682 break;
683
684 case 0x4c:
685 diff = s->ulpd_pm_regs[addr >> 2] & value;
686 s->ulpd_pm_regs[addr >> 2] = value & 0xf;
687 if (diff & (1 << 0))
688 omap_clk_reparent(omap_findclk(s, "ck_48m"), omap_findclk(s,
689 (value & (1 << 0)) ? "apll" : "dpll4"));
690 break;
691
692 default:
693 OMAP_BAD_REG(addr);
694 }
695}
696
697static const MemoryRegionOps omap_ulpd_pm_ops = {
698 .read = omap_ulpd_pm_read,
699 .write = omap_ulpd_pm_write,
700 .endianness = DEVICE_NATIVE_ENDIAN,
701};
702
703static void omap_ulpd_pm_reset(struct omap_mpu_state_s *mpu)
704{
705 mpu->ulpd_pm_regs[0x00 >> 2] = 0x0001;
706 mpu->ulpd_pm_regs[0x04 >> 2] = 0x0000;
707 mpu->ulpd_pm_regs[0x08 >> 2] = 0x0001;
708 mpu->ulpd_pm_regs[0x0c >> 2] = 0x0000;
709 mpu->ulpd_pm_regs[0x10 >> 2] = 0x0000;
710 mpu->ulpd_pm_regs[0x18 >> 2] = 0x01;
711 mpu->ulpd_pm_regs[0x1c >> 2] = 0x01;
712 mpu->ulpd_pm_regs[0x20 >> 2] = 0x01;
713 mpu->ulpd_pm_regs[0x24 >> 2] = 0x03ff;
714 mpu->ulpd_pm_regs[0x28 >> 2] = 0x01;
715 mpu->ulpd_pm_regs[0x2c >> 2] = 0x01;
716 omap_ulpd_clk_update(mpu, mpu->ulpd_pm_regs[0x30 >> 2], 0x0000);
717 mpu->ulpd_pm_regs[0x30 >> 2] = 0x0000;
718 omap_ulpd_req_update(mpu, mpu->ulpd_pm_regs[0x34 >> 2], 0x0000);
719 mpu->ulpd_pm_regs[0x34 >> 2] = 0x0000;
720 mpu->ulpd_pm_regs[0x38 >> 2] = 0x0001;
721 mpu->ulpd_pm_regs[0x3c >> 2] = 0x2211;
722 mpu->ulpd_pm_regs[0x40 >> 2] = 0x0000;
723 mpu->ulpd_pm_regs[0x48 >> 2] = 0x960;
724 mpu->ulpd_pm_regs[0x4c >> 2] = 0x08;
725 mpu->ulpd_pm_regs[0x50 >> 2] = 0x08;
726 omap_clk_setrate(omap_findclk(mpu, "dpll4"), 1, 4);
727 omap_clk_reparent(omap_findclk(mpu, "ck_48m"), omap_findclk(mpu, "dpll4"));
728}
729
730static void omap_ulpd_pm_init(MemoryRegion *system_memory,
731 hwaddr base,
732 struct omap_mpu_state_s *mpu)
733{
734 memory_region_init_io(&mpu->ulpd_pm_iomem, &omap_ulpd_pm_ops, mpu,
735 "omap-ulpd-pm", 0x800);
736 memory_region_add_subregion(system_memory, base, &mpu->ulpd_pm_iomem);
737 omap_ulpd_pm_reset(mpu);
738}
739
740
741static uint64_t omap_pin_cfg_read(void *opaque, hwaddr addr,
742 unsigned size)
743{
744 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
745
746 if (size != 4) {
747 return omap_badwidth_read32(opaque, addr);
748 }
749
750 switch (addr) {
751 case 0x00:
752 case 0x04:
753 case 0x08:
754 return s->func_mux_ctrl[addr >> 2];
755
756 case 0x0c:
757 return s->comp_mode_ctrl[0];
758
759 case 0x10:
760 case 0x14:
761 case 0x18:
762 case 0x1c:
763 case 0x20:
764 case 0x24:
765 case 0x28:
766 case 0x2c:
767 case 0x30:
768 case 0x34:
769 case 0x38:
770 return s->func_mux_ctrl[(addr >> 2) - 1];
771
772 case 0x40:
773 case 0x44:
774 case 0x48:
775 case 0x4c:
776 return s->pull_dwn_ctrl[(addr & 0xf) >> 2];
777
778 case 0x50:
779 return s->gate_inh_ctrl[0];
780
781 case 0x60:
782 return s->voltage_ctrl[0];
783
784 case 0x70:
785 return s->test_dbg_ctrl[0];
786
787 case 0x80:
788 return s->mod_conf_ctrl[0];
789 }
790
791 OMAP_BAD_REG(addr);
792 return 0;
793}
794
795static inline void omap_pin_funcmux0_update(struct omap_mpu_state_s *s,
796 uint32_t diff, uint32_t value)
797{
798 if (s->compat1509) {
799 if (diff & (1 << 9))
800 omap_clk_onoff(omap_findclk(s, "bt_mclk_out"),
801 (~value >> 9) & 1);
802 if (diff & (1 << 7))
803 omap_clk_onoff(omap_findclk(s, "usb.clko"),
804 (value >> 7) & 1);
805 }
806}
807
808static inline void omap_pin_funcmux1_update(struct omap_mpu_state_s *s,
809 uint32_t diff, uint32_t value)
810{
811 if (s->compat1509) {
812 if (diff & (1 << 31))
813 omap_clk_onoff(omap_findclk(s, "mcbsp3.clkx"),
814 (value >> 31) & 1);
815 if (diff & (1 << 1))
816 omap_clk_onoff(omap_findclk(s, "clk32k_out"),
817 (~value >> 1) & 1);
818 }
819}
820
821static inline void omap_pin_modconf1_update(struct omap_mpu_state_s *s,
822 uint32_t diff, uint32_t value)
823{
824 if (diff & (1 << 31))
825 omap_clk_reparent(omap_findclk(s, "uart3_ck"),
826 omap_findclk(s, ((value >> 31) & 1) ?
827 "ck_48m" : "armper_ck"));
828 if (diff & (1 << 30))
829 omap_clk_reparent(omap_findclk(s, "uart2_ck"),
830 omap_findclk(s, ((value >> 30) & 1) ?
831 "ck_48m" : "armper_ck"));
832 if (diff & (1 << 29))
833 omap_clk_reparent(omap_findclk(s, "uart1_ck"),
834 omap_findclk(s, ((value >> 29) & 1) ?
835 "ck_48m" : "armper_ck"));
836 if (diff & (1 << 23))
837 omap_clk_reparent(omap_findclk(s, "mmc_ck"),
838 omap_findclk(s, ((value >> 23) & 1) ?
839 "ck_48m" : "armper_ck"));
840 if (diff & (1 << 12))
841 omap_clk_reparent(omap_findclk(s, "com_mclk_out"),
842 omap_findclk(s, ((value >> 12) & 1) ?
843 "ck_48m" : "armper_ck"));
844 if (diff & (1 << 9))
845 omap_clk_onoff(omap_findclk(s, "usb_hhc_ck"), (value >> 9) & 1);
846}
847
848static void omap_pin_cfg_write(void *opaque, hwaddr addr,
849 uint64_t value, unsigned size)
850{
851 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
852 uint32_t diff;
853
854 if (size != 4) {
855 return omap_badwidth_write32(opaque, addr, value);
856 }
857
858 switch (addr) {
859 case 0x00:
860 diff = s->func_mux_ctrl[addr >> 2] ^ value;
861 s->func_mux_ctrl[addr >> 2] = value;
862 omap_pin_funcmux0_update(s, diff, value);
863 return;
864
865 case 0x04:
866 diff = s->func_mux_ctrl[addr >> 2] ^ value;
867 s->func_mux_ctrl[addr >> 2] = value;
868 omap_pin_funcmux1_update(s, diff, value);
869 return;
870
871 case 0x08:
872 s->func_mux_ctrl[addr >> 2] = value;
873 return;
874
875 case 0x0c:
876 s->comp_mode_ctrl[0] = value;
877 s->compat1509 = (value != 0x0000eaef);
878 omap_pin_funcmux0_update(s, ~0, s->func_mux_ctrl[0]);
879 omap_pin_funcmux1_update(s, ~0, s->func_mux_ctrl[1]);
880 return;
881
882 case 0x10:
883 case 0x14:
884 case 0x18:
885 case 0x1c:
886 case 0x20:
887 case 0x24:
888 case 0x28:
889 case 0x2c:
890 case 0x30:
891 case 0x34:
892 case 0x38:
893 s->func_mux_ctrl[(addr >> 2) - 1] = value;
894 return;
895
896 case 0x40:
897 case 0x44:
898 case 0x48:
899 case 0x4c:
900 s->pull_dwn_ctrl[(addr & 0xf) >> 2] = value;
901 return;
902
903 case 0x50:
904 s->gate_inh_ctrl[0] = value;
905 return;
906
907 case 0x60:
908 s->voltage_ctrl[0] = value;
909 return;
910
911 case 0x70:
912 s->test_dbg_ctrl[0] = value;
913 return;
914
915 case 0x80:
916 diff = s->mod_conf_ctrl[0] ^ value;
917 s->mod_conf_ctrl[0] = value;
918 omap_pin_modconf1_update(s, diff, value);
919 return;
920
921 default:
922 OMAP_BAD_REG(addr);
923 }
924}
925
926static const MemoryRegionOps omap_pin_cfg_ops = {
927 .read = omap_pin_cfg_read,
928 .write = omap_pin_cfg_write,
929 .endianness = DEVICE_NATIVE_ENDIAN,
930};
931
932static void omap_pin_cfg_reset(struct omap_mpu_state_s *mpu)
933{
934
935 mpu->compat1509 = 1;
936 omap_pin_funcmux0_update(mpu, mpu->func_mux_ctrl[0], 0);
937 omap_pin_funcmux1_update(mpu, mpu->func_mux_ctrl[1], 0);
938 omap_pin_modconf1_update(mpu, mpu->mod_conf_ctrl[0], 0);
939 memset(mpu->func_mux_ctrl, 0, sizeof(mpu->func_mux_ctrl));
940 memset(mpu->comp_mode_ctrl, 0, sizeof(mpu->comp_mode_ctrl));
941 memset(mpu->pull_dwn_ctrl, 0, sizeof(mpu->pull_dwn_ctrl));
942 memset(mpu->gate_inh_ctrl, 0, sizeof(mpu->gate_inh_ctrl));
943 memset(mpu->voltage_ctrl, 0, sizeof(mpu->voltage_ctrl));
944 memset(mpu->test_dbg_ctrl, 0, sizeof(mpu->test_dbg_ctrl));
945 memset(mpu->mod_conf_ctrl, 0, sizeof(mpu->mod_conf_ctrl));
946}
947
948static void omap_pin_cfg_init(MemoryRegion *system_memory,
949 hwaddr base,
950 struct omap_mpu_state_s *mpu)
951{
952 memory_region_init_io(&mpu->pin_cfg_iomem, &omap_pin_cfg_ops, mpu,
953 "omap-pin-cfg", 0x800);
954 memory_region_add_subregion(system_memory, base, &mpu->pin_cfg_iomem);
955 omap_pin_cfg_reset(mpu);
956}
957
958
959static uint64_t omap_id_read(void *opaque, hwaddr addr,
960 unsigned size)
961{
962 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
963
964 if (size != 4) {
965 return omap_badwidth_read32(opaque, addr);
966 }
967
968 switch (addr) {
969 case 0xfffe1800:
970 return 0xc9581f0e;
971 case 0xfffe1804:
972 return 0xa8858bfa;
973
974 case 0xfffe2000:
975 return 0x00aaaafc;
976 case 0xfffe2004:
977 return 0xcafeb574;
978
979 case 0xfffed400:
980 switch (s->mpu_model) {
981 case omap310:
982 return 0x03310315;
983 case omap1510:
984 return 0x03310115;
985 default:
986 hw_error("%s: bad mpu model\n", __FUNCTION__);
987 }
988 break;
989
990 case 0xfffed404:
991 switch (s->mpu_model) {
992 case omap310:
993 return 0xfb57402f;
994 case omap1510:
995 return 0xfb47002f;
996 default:
997 hw_error("%s: bad mpu model\n", __FUNCTION__);
998 }
999 break;
1000 }
1001
1002 OMAP_BAD_REG(addr);
1003 return 0;
1004}
1005
1006static void omap_id_write(void *opaque, hwaddr addr,
1007 uint64_t value, unsigned size)
1008{
1009 if (size != 4) {
1010 return omap_badwidth_write32(opaque, addr, value);
1011 }
1012
1013 OMAP_BAD_REG(addr);
1014}
1015
1016static const MemoryRegionOps omap_id_ops = {
1017 .read = omap_id_read,
1018 .write = omap_id_write,
1019 .endianness = DEVICE_NATIVE_ENDIAN,
1020};
1021
1022static void omap_id_init(MemoryRegion *memory, struct omap_mpu_state_s *mpu)
1023{
1024 memory_region_init_io(&mpu->id_iomem, &omap_id_ops, mpu,
1025 "omap-id", 0x100000000ULL);
1026 memory_region_init_alias(&mpu->id_iomem_e18, "omap-id-e18", &mpu->id_iomem,
1027 0xfffe1800, 0x800);
1028 memory_region_add_subregion(memory, 0xfffe1800, &mpu->id_iomem_e18);
1029 memory_region_init_alias(&mpu->id_iomem_ed4, "omap-id-ed4", &mpu->id_iomem,
1030 0xfffed400, 0x100);
1031 memory_region_add_subregion(memory, 0xfffed400, &mpu->id_iomem_ed4);
1032 if (!cpu_is_omap15xx(mpu)) {
1033 memory_region_init_alias(&mpu->id_iomem_ed4, "omap-id-e20",
1034 &mpu->id_iomem, 0xfffe2000, 0x800);
1035 memory_region_add_subregion(memory, 0xfffe2000, &mpu->id_iomem_e20);
1036 }
1037}
1038
1039
1040static uint64_t omap_mpui_read(void *opaque, hwaddr addr,
1041 unsigned size)
1042{
1043 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1044
1045 if (size != 4) {
1046 return omap_badwidth_read32(opaque, addr);
1047 }
1048
1049 switch (addr) {
1050 case 0x00:
1051 return s->mpui_ctrl;
1052 case 0x04:
1053 return 0x01ffffff;
1054 case 0x08:
1055 return 0xffffffff;
1056 case 0x0c:
1057 return 0x00000800;
1058 case 0x10:
1059 return 0x00000000;
1060
1061
1062 case 0x14:
1063 case 0x18:
1064 return 0x00000000;
1065 case 0x1c:
1066 return 0x0000ffff;
1067 }
1068
1069 OMAP_BAD_REG(addr);
1070 return 0;
1071}
1072
1073static void omap_mpui_write(void *opaque, hwaddr addr,
1074 uint64_t value, unsigned size)
1075{
1076 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1077
1078 if (size != 4) {
1079 return omap_badwidth_write32(opaque, addr, value);
1080 }
1081
1082 switch (addr) {
1083 case 0x00:
1084 s->mpui_ctrl = value & 0x007fffff;
1085 break;
1086
1087 case 0x04:
1088 case 0x08:
1089 case 0x0c:
1090 case 0x10:
1091
1092 case 0x14:
1093 OMAP_RO_REG(addr);
1094 break;
1095 case 0x18:
1096 case 0x1c:
1097 break;
1098
1099 default:
1100 OMAP_BAD_REG(addr);
1101 }
1102}
1103
1104static const MemoryRegionOps omap_mpui_ops = {
1105 .read = omap_mpui_read,
1106 .write = omap_mpui_write,
1107 .endianness = DEVICE_NATIVE_ENDIAN,
1108};
1109
1110static void omap_mpui_reset(struct omap_mpu_state_s *s)
1111{
1112 s->mpui_ctrl = 0x0003ff1b;
1113}
1114
1115static void omap_mpui_init(MemoryRegion *memory, hwaddr base,
1116 struct omap_mpu_state_s *mpu)
1117{
1118 memory_region_init_io(&mpu->mpui_iomem, &omap_mpui_ops, mpu,
1119 "omap-mpui", 0x100);
1120 memory_region_add_subregion(memory, base, &mpu->mpui_iomem);
1121
1122 omap_mpui_reset(mpu);
1123}
1124
1125
1126struct omap_tipb_bridge_s {
1127 qemu_irq abort;
1128 MemoryRegion iomem;
1129
1130 int width_intr;
1131 uint16_t control;
1132 uint16_t alloc;
1133 uint16_t buffer;
1134 uint16_t enh_control;
1135};
1136
1137static uint64_t omap_tipb_bridge_read(void *opaque, hwaddr addr,
1138 unsigned size)
1139{
1140 struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
1141
1142 if (size < 2) {
1143 return omap_badwidth_read16(opaque, addr);
1144 }
1145
1146 switch (addr) {
1147 case 0x00:
1148 return s->control;
1149 case 0x04:
1150 return s->alloc;
1151 case 0x08:
1152 return s->buffer;
1153 case 0x0c:
1154 return s->enh_control;
1155 case 0x10:
1156 case 0x14:
1157 case 0x18:
1158 return 0xffff;
1159 case 0x1c:
1160 return 0x00f8;
1161 }
1162
1163 OMAP_BAD_REG(addr);
1164 return 0;
1165}
1166
1167static void omap_tipb_bridge_write(void *opaque, hwaddr addr,
1168 uint64_t value, unsigned size)
1169{
1170 struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
1171
1172 if (size < 2) {
1173 return omap_badwidth_write16(opaque, addr, value);
1174 }
1175
1176 switch (addr) {
1177 case 0x00:
1178 s->control = value & 0xffff;
1179 break;
1180
1181 case 0x04:
1182 s->alloc = value & 0x003f;
1183 break;
1184
1185 case 0x08:
1186 s->buffer = value & 0x0003;
1187 break;
1188
1189 case 0x0c:
1190 s->width_intr = !(value & 2);
1191 s->enh_control = value & 0x000f;
1192 break;
1193
1194 case 0x10:
1195 case 0x14:
1196 case 0x18:
1197 case 0x1c:
1198 OMAP_RO_REG(addr);
1199 break;
1200
1201 default:
1202 OMAP_BAD_REG(addr);
1203 }
1204}
1205
1206static const MemoryRegionOps omap_tipb_bridge_ops = {
1207 .read = omap_tipb_bridge_read,
1208 .write = omap_tipb_bridge_write,
1209 .endianness = DEVICE_NATIVE_ENDIAN,
1210};
1211
1212static void omap_tipb_bridge_reset(struct omap_tipb_bridge_s *s)
1213{
1214 s->control = 0xffff;
1215 s->alloc = 0x0009;
1216 s->buffer = 0x0000;
1217 s->enh_control = 0x000f;
1218}
1219
1220static struct omap_tipb_bridge_s *omap_tipb_bridge_init(
1221 MemoryRegion *memory, hwaddr base,
1222 qemu_irq abort_irq, omap_clk clk)
1223{
1224 struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *)
1225 g_malloc0(sizeof(struct omap_tipb_bridge_s));
1226
1227 s->abort = abort_irq;
1228 omap_tipb_bridge_reset(s);
1229
1230 memory_region_init_io(&s->iomem, &omap_tipb_bridge_ops, s,
1231 "omap-tipb-bridge", 0x100);
1232 memory_region_add_subregion(memory, base, &s->iomem);
1233
1234 return s;
1235}
1236
1237
1238static uint64_t omap_tcmi_read(void *opaque, hwaddr addr,
1239 unsigned size)
1240{
1241 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1242 uint32_t ret;
1243
1244 if (size != 4) {
1245 return omap_badwidth_read32(opaque, addr);
1246 }
1247
1248 switch (addr) {
1249 case 0x00:
1250 case 0x04:
1251 case 0x08:
1252 case 0x0c:
1253 case 0x10:
1254 case 0x14:
1255 case 0x18:
1256 case 0x1c:
1257 case 0x24:
1258 case 0x28:
1259 case 0x2c:
1260 case 0x30:
1261 case 0x3c:
1262 case 0x40:
1263 return s->tcmi_regs[addr >> 2];
1264
1265 case 0x20:
1266 ret = s->tcmi_regs[addr >> 2];
1267 s->tcmi_regs[addr >> 2] &= ~1;
1268
1269 return ret;
1270 }
1271
1272 OMAP_BAD_REG(addr);
1273 return 0;
1274}
1275
1276static void omap_tcmi_write(void *opaque, hwaddr addr,
1277 uint64_t value, unsigned size)
1278{
1279 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1280
1281 if (size != 4) {
1282 return omap_badwidth_write32(opaque, addr, value);
1283 }
1284
1285 switch (addr) {
1286 case 0x00:
1287 case 0x04:
1288 case 0x08:
1289 case 0x10:
1290 case 0x14:
1291 case 0x18:
1292 case 0x1c:
1293 case 0x20:
1294 case 0x24:
1295 case 0x28:
1296 case 0x2c:
1297 case 0x30:
1298 case 0x3c:
1299 case 0x40:
1300 s->tcmi_regs[addr >> 2] = value;
1301 break;
1302 case 0x0c:
1303 s->tcmi_regs[addr >> 2] = (value & 0xf) | (1 << 4);
1304 break;
1305
1306 default:
1307 OMAP_BAD_REG(addr);
1308 }
1309}
1310
1311static const MemoryRegionOps omap_tcmi_ops = {
1312 .read = omap_tcmi_read,
1313 .write = omap_tcmi_write,
1314 .endianness = DEVICE_NATIVE_ENDIAN,
1315};
1316
1317static void omap_tcmi_reset(struct omap_mpu_state_s *mpu)
1318{
1319 mpu->tcmi_regs[0x00 >> 2] = 0x00000000;
1320 mpu->tcmi_regs[0x04 >> 2] = 0x00000000;
1321 mpu->tcmi_regs[0x08 >> 2] = 0x00000000;
1322 mpu->tcmi_regs[0x0c >> 2] = 0x00000010;
1323 mpu->tcmi_regs[0x10 >> 2] = 0x0010fffb;
1324 mpu->tcmi_regs[0x14 >> 2] = 0x0010fffb;
1325 mpu->tcmi_regs[0x18 >> 2] = 0x0010fffb;
1326 mpu->tcmi_regs[0x1c >> 2] = 0x0010fffb;
1327 mpu->tcmi_regs[0x20 >> 2] = 0x00618800;
1328 mpu->tcmi_regs[0x24 >> 2] = 0x00000037;
1329 mpu->tcmi_regs[0x28 >> 2] = 0x00000000;
1330 mpu->tcmi_regs[0x2c >> 2] = 0x00000000;
1331 mpu->tcmi_regs[0x30 >> 2] = 0x00000000;
1332 mpu->tcmi_regs[0x3c >> 2] = 0x00000003;
1333 mpu->tcmi_regs[0x40 >> 2] = 0x00000000;
1334}
1335
1336static void omap_tcmi_init(MemoryRegion *memory, hwaddr base,
1337 struct omap_mpu_state_s *mpu)
1338{
1339 memory_region_init_io(&mpu->tcmi_iomem, &omap_tcmi_ops, mpu,
1340 "omap-tcmi", 0x100);
1341 memory_region_add_subregion(memory, base, &mpu->tcmi_iomem);
1342 omap_tcmi_reset(mpu);
1343}
1344
1345
1346struct dpll_ctl_s {
1347 MemoryRegion iomem;
1348 uint16_t mode;
1349 omap_clk dpll;
1350};
1351
1352static uint64_t omap_dpll_read(void *opaque, hwaddr addr,
1353 unsigned size)
1354{
1355 struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
1356
1357 if (size != 2) {
1358 return omap_badwidth_read16(opaque, addr);
1359 }
1360
1361 if (addr == 0x00)
1362 return s->mode;
1363
1364 OMAP_BAD_REG(addr);
1365 return 0;
1366}
1367
1368static void omap_dpll_write(void *opaque, hwaddr addr,
1369 uint64_t value, unsigned size)
1370{
1371 struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
1372 uint16_t diff;
1373 static const int bypass_div[4] = { 1, 2, 4, 4 };
1374 int div, mult;
1375
1376 if (size != 2) {
1377 return omap_badwidth_write16(opaque, addr, value);
1378 }
1379
1380 if (addr == 0x00) {
1381
1382 diff = s->mode & value;
1383 s->mode = value & 0x2fff;
1384 if (diff & (0x3ff << 2)) {
1385 if (value & (1 << 4)) {
1386 div = ((value >> 5) & 3) + 1;
1387 mult = MIN((value >> 7) & 0x1f, 1);
1388 } else {
1389 div = bypass_div[((value >> 2) & 3)];
1390 mult = 1;
1391 }
1392 omap_clk_setrate(s->dpll, div, mult);
1393 }
1394
1395
1396 s->mode = (s->mode & 0xfffe) | ((s->mode >> 4) & 1);
1397
1398
1399 s->mode |= 2;
1400 } else {
1401 OMAP_BAD_REG(addr);
1402 }
1403}
1404
1405static const MemoryRegionOps omap_dpll_ops = {
1406 .read = omap_dpll_read,
1407 .write = omap_dpll_write,
1408 .endianness = DEVICE_NATIVE_ENDIAN,
1409};
1410
1411static void omap_dpll_reset(struct dpll_ctl_s *s)
1412{
1413 s->mode = 0x2002;
1414 omap_clk_setrate(s->dpll, 1, 1);
1415}
1416
1417static struct dpll_ctl_s *omap_dpll_init(MemoryRegion *memory,
1418 hwaddr base, omap_clk clk)
1419{
1420 struct dpll_ctl_s *s = g_malloc0(sizeof(*s));
1421 memory_region_init_io(&s->iomem, &omap_dpll_ops, s, "omap-dpll", 0x100);
1422
1423 s->dpll = clk;
1424 omap_dpll_reset(s);
1425
1426 memory_region_add_subregion(memory, base, &s->iomem);
1427 return s;
1428}
1429
1430
1431static uint64_t omap_clkm_read(void *opaque, hwaddr addr,
1432 unsigned size)
1433{
1434 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1435
1436 if (size != 2) {
1437 return omap_badwidth_read16(opaque, addr);
1438 }
1439
1440 switch (addr) {
1441 case 0x00:
1442 return s->clkm.arm_ckctl;
1443
1444 case 0x04:
1445 return s->clkm.arm_idlect1;
1446
1447 case 0x08:
1448 return s->clkm.arm_idlect2;
1449
1450 case 0x0c:
1451 return s->clkm.arm_ewupct;
1452
1453 case 0x10:
1454 return s->clkm.arm_rstct1;
1455
1456 case 0x14:
1457 return s->clkm.arm_rstct2;
1458
1459 case 0x18:
1460 return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start;
1461
1462 case 0x1c:
1463 return s->clkm.arm_ckout1;
1464
1465 case 0x20:
1466 break;
1467 }
1468
1469 OMAP_BAD_REG(addr);
1470 return 0;
1471}
1472
1473static inline void omap_clkm_ckctl_update(struct omap_mpu_state_s *s,
1474 uint16_t diff, uint16_t value)
1475{
1476 omap_clk clk;
1477
1478 if (diff & (1 << 14)) {
1479 if (value & (1 << 14))
1480 ;
1481 else {
1482 clk = omap_findclk(s, "arminth_ck");
1483 omap_clk_reparent(clk, omap_findclk(s, "tc_ck"));
1484 }
1485 }
1486 if (diff & (1 << 12)) {
1487 clk = omap_findclk(s, "armtim_ck");
1488 if (value & (1 << 12))
1489 omap_clk_reparent(clk, omap_findclk(s, "clkin"));
1490 else
1491 omap_clk_reparent(clk, omap_findclk(s, "ck_gen1"));
1492 }
1493
1494 if (diff & (3 << 10)) {
1495 clk = omap_findclk(s, "dspmmu_ck");
1496 omap_clk_setrate(clk, 1 << ((value >> 10) & 3), 1);
1497 }
1498 if (diff & (3 << 8)) {
1499 clk = omap_findclk(s, "tc_ck");
1500 omap_clk_setrate(clk, 1 << ((value >> 8) & 3), 1);
1501 }
1502 if (diff & (3 << 6)) {
1503 clk = omap_findclk(s, "dsp_ck");
1504 omap_clk_setrate(clk, 1 << ((value >> 6) & 3), 1);
1505 }
1506 if (diff & (3 << 4)) {
1507 clk = omap_findclk(s, "arm_ck");
1508 omap_clk_setrate(clk, 1 << ((value >> 4) & 3), 1);
1509 }
1510 if (diff & (3 << 2)) {
1511 clk = omap_findclk(s, "lcd_ck");
1512 omap_clk_setrate(clk, 1 << ((value >> 2) & 3), 1);
1513 }
1514 if (diff & (3 << 0)) {
1515 clk = omap_findclk(s, "armper_ck");
1516 omap_clk_setrate(clk, 1 << ((value >> 0) & 3), 1);
1517 }
1518}
1519
1520static inline void omap_clkm_idlect1_update(struct omap_mpu_state_s *s,
1521 uint16_t diff, uint16_t value)
1522{
1523 omap_clk clk;
1524
1525 if (value & (1 << 11)) {
1526 cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HALT);
1527 }
1528 if (!(value & (1 << 10)))
1529 qemu_system_shutdown_request();
1530
1531#define SET_CANIDLE(clock, bit) \
1532 if (diff & (1 << bit)) { \
1533 clk = omap_findclk(s, clock); \
1534 omap_clk_canidle(clk, (value >> bit) & 1); \
1535 }
1536 SET_CANIDLE("mpuwd_ck", 0)
1537 SET_CANIDLE("armxor_ck", 1)
1538 SET_CANIDLE("mpuper_ck", 2)
1539 SET_CANIDLE("lcd_ck", 3)
1540 SET_CANIDLE("lb_ck", 4)
1541 SET_CANIDLE("hsab_ck", 5)
1542 SET_CANIDLE("tipb_ck", 6)
1543 SET_CANIDLE("dma_ck", 6)
1544 SET_CANIDLE("tc_ck", 6)
1545 SET_CANIDLE("dpll1", 7)
1546 SET_CANIDLE("dpll2", 7)
1547 SET_CANIDLE("dpll3", 7)
1548 SET_CANIDLE("mpui_ck", 8)
1549 SET_CANIDLE("armtim_ck", 9)
1550}
1551
1552static inline void omap_clkm_idlect2_update(struct omap_mpu_state_s *s,
1553 uint16_t diff, uint16_t value)
1554{
1555 omap_clk clk;
1556
1557#define SET_ONOFF(clock, bit) \
1558 if (diff & (1 << bit)) { \
1559 clk = omap_findclk(s, clock); \
1560 omap_clk_onoff(clk, (value >> bit) & 1); \
1561 }
1562 SET_ONOFF("mpuwd_ck", 0)
1563 SET_ONOFF("armxor_ck", 1)
1564 SET_ONOFF("mpuper_ck", 2)
1565 SET_ONOFF("lcd_ck", 3)
1566 SET_ONOFF("lb_ck", 4)
1567 SET_ONOFF("hsab_ck", 5)
1568 SET_ONOFF("mpui_ck", 6)
1569 SET_ONOFF("armtim_ck", 7)
1570 SET_CANIDLE("dma_ck", 8)
1571 SET_ONOFF("arm_gpio_ck", 9)
1572 SET_ONOFF("lbfree_ck", 10)
1573}
1574
1575static inline void omap_clkm_ckout1_update(struct omap_mpu_state_s *s,
1576 uint16_t diff, uint16_t value)
1577{
1578 omap_clk clk;
1579
1580 if (diff & (3 << 4)) {
1581 clk = omap_findclk(s, "tclk_out");
1582 switch ((value >> 4) & 3) {
1583 case 1:
1584 omap_clk_reparent(clk, omap_findclk(s, "ck_gen3"));
1585 omap_clk_onoff(clk, 1);
1586 break;
1587 case 2:
1588 omap_clk_reparent(clk, omap_findclk(s, "tc_ck"));
1589 omap_clk_onoff(clk, 1);
1590 break;
1591 default:
1592 omap_clk_onoff(clk, 0);
1593 }
1594 }
1595 if (diff & (3 << 2)) {
1596 clk = omap_findclk(s, "dclk_out");
1597 switch ((value >> 2) & 3) {
1598 case 0:
1599 omap_clk_reparent(clk, omap_findclk(s, "dspmmu_ck"));
1600 break;
1601 case 1:
1602 omap_clk_reparent(clk, omap_findclk(s, "ck_gen2"));
1603 break;
1604 case 2:
1605 omap_clk_reparent(clk, omap_findclk(s, "dsp_ck"));
1606 break;
1607 case 3:
1608 omap_clk_reparent(clk, omap_findclk(s, "ck_ref14"));
1609 break;
1610 }
1611 }
1612 if (diff & (3 << 0)) {
1613 clk = omap_findclk(s, "aclk_out");
1614 switch ((value >> 0) & 3) {
1615 case 1:
1616 omap_clk_reparent(clk, omap_findclk(s, "ck_gen1"));
1617 omap_clk_onoff(clk, 1);
1618 break;
1619 case 2:
1620 omap_clk_reparent(clk, omap_findclk(s, "arm_ck"));
1621 omap_clk_onoff(clk, 1);
1622 break;
1623 case 3:
1624 omap_clk_reparent(clk, omap_findclk(s, "ck_ref14"));
1625 omap_clk_onoff(clk, 1);
1626 break;
1627 default:
1628 omap_clk_onoff(clk, 0);
1629 }
1630 }
1631}
1632
1633static void omap_clkm_write(void *opaque, hwaddr addr,
1634 uint64_t value, unsigned size)
1635{
1636 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1637 uint16_t diff;
1638 omap_clk clk;
1639 static const char *clkschemename[8] = {
1640 "fully synchronous", "fully asynchronous", "synchronous scalable",
1641 "mix mode 1", "mix mode 2", "bypass mode", "mix mode 3", "mix mode 4",
1642 };
1643
1644 if (size != 2) {
1645 return omap_badwidth_write16(opaque, addr, value);
1646 }
1647
1648 switch (addr) {
1649 case 0x00:
1650 diff = s->clkm.arm_ckctl ^ value;
1651 s->clkm.arm_ckctl = value & 0x7fff;
1652 omap_clkm_ckctl_update(s, diff, value);
1653 return;
1654
1655 case 0x04:
1656 diff = s->clkm.arm_idlect1 ^ value;
1657 s->clkm.arm_idlect1 = value & 0x0fff;
1658 omap_clkm_idlect1_update(s, diff, value);
1659 return;
1660
1661 case 0x08:
1662 diff = s->clkm.arm_idlect2 ^ value;
1663 s->clkm.arm_idlect2 = value & 0x07ff;
1664 omap_clkm_idlect2_update(s, diff, value);
1665 return;
1666
1667 case 0x0c:
1668 s->clkm.arm_ewupct = value & 0x003f;
1669 return;
1670
1671 case 0x10:
1672 diff = s->clkm.arm_rstct1 ^ value;
1673 s->clkm.arm_rstct1 = value & 0x0007;
1674 if (value & 9) {
1675 qemu_system_reset_request();
1676 s->clkm.cold_start = 0xa;
1677 }
1678 if (diff & ~value & 4) {
1679 omap_mpui_reset(s);
1680 omap_tipb_bridge_reset(s->private_tipb);
1681 omap_tipb_bridge_reset(s->public_tipb);
1682 }
1683 if (diff & 2) {
1684 clk = omap_findclk(s, "dsp_ck");
1685 omap_clk_canidle(clk, (~value >> 1) & 1);
1686 }
1687 return;
1688
1689 case 0x14:
1690 s->clkm.arm_rstct2 = value & 0x0001;
1691 return;
1692
1693 case 0x18:
1694 if ((s->clkm.clocking_scheme ^ (value >> 11)) & 7) {
1695 s->clkm.clocking_scheme = (value >> 11) & 7;
1696 printf("%s: clocking scheme set to %s\n", __FUNCTION__,
1697 clkschemename[s->clkm.clocking_scheme]);
1698 }
1699 s->clkm.cold_start &= value & 0x3f;
1700 return;
1701
1702 case 0x1c:
1703 diff = s->clkm.arm_ckout1 ^ value;
1704 s->clkm.arm_ckout1 = value & 0x003f;
1705 omap_clkm_ckout1_update(s, diff, value);
1706 return;
1707
1708 case 0x20:
1709 default:
1710 OMAP_BAD_REG(addr);
1711 }
1712}
1713
1714static const MemoryRegionOps omap_clkm_ops = {
1715 .read = omap_clkm_read,
1716 .write = omap_clkm_write,
1717 .endianness = DEVICE_NATIVE_ENDIAN,
1718};
1719
1720static uint64_t omap_clkdsp_read(void *opaque, hwaddr addr,
1721 unsigned size)
1722{
1723 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1724 CPUState *cpu = CPU(s->cpu);
1725
1726 if (size != 2) {
1727 return omap_badwidth_read16(opaque, addr);
1728 }
1729
1730 switch (addr) {
1731 case 0x04:
1732 return s->clkm.dsp_idlect1;
1733
1734 case 0x08:
1735 return s->clkm.dsp_idlect2;
1736
1737 case 0x14:
1738 return s->clkm.dsp_rstct2;
1739
1740 case 0x18:
1741 cpu = CPU(s->cpu);
1742 return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start |
1743 (cpu->halted << 6);
1744 }
1745
1746 OMAP_BAD_REG(addr);
1747 return 0;
1748}
1749
1750static inline void omap_clkdsp_idlect1_update(struct omap_mpu_state_s *s,
1751 uint16_t diff, uint16_t value)
1752{
1753 omap_clk clk;
1754
1755 SET_CANIDLE("dspxor_ck", 1);
1756}
1757
1758static inline void omap_clkdsp_idlect2_update(struct omap_mpu_state_s *s,
1759 uint16_t diff, uint16_t value)
1760{
1761 omap_clk clk;
1762
1763 SET_ONOFF("dspxor_ck", 1);
1764}
1765
1766static void omap_clkdsp_write(void *opaque, hwaddr addr,
1767 uint64_t value, unsigned size)
1768{
1769 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1770 uint16_t diff;
1771
1772 if (size != 2) {
1773 return omap_badwidth_write16(opaque, addr, value);
1774 }
1775
1776 switch (addr) {
1777 case 0x04:
1778 diff = s->clkm.dsp_idlect1 ^ value;
1779 s->clkm.dsp_idlect1 = value & 0x01f7;
1780 omap_clkdsp_idlect1_update(s, diff, value);
1781 break;
1782
1783 case 0x08:
1784 s->clkm.dsp_idlect2 = value & 0x0037;
1785 diff = s->clkm.dsp_idlect1 ^ value;
1786 omap_clkdsp_idlect2_update(s, diff, value);
1787 break;
1788
1789 case 0x14:
1790 s->clkm.dsp_rstct2 = value & 0x0001;
1791 break;
1792
1793 case 0x18:
1794 s->clkm.cold_start &= value & 0x3f;
1795 break;
1796
1797 default:
1798 OMAP_BAD_REG(addr);
1799 }
1800}
1801
1802static const MemoryRegionOps omap_clkdsp_ops = {
1803 .read = omap_clkdsp_read,
1804 .write = omap_clkdsp_write,
1805 .endianness = DEVICE_NATIVE_ENDIAN,
1806};
1807
1808static void omap_clkm_reset(struct omap_mpu_state_s *s)
1809{
1810 if (s->wdt && s->wdt->reset)
1811 s->clkm.cold_start = 0x6;
1812 s->clkm.clocking_scheme = 0;
1813 omap_clkm_ckctl_update(s, ~0, 0x3000);
1814 s->clkm.arm_ckctl = 0x3000;
1815 omap_clkm_idlect1_update(s, s->clkm.arm_idlect1 ^ 0x0400, 0x0400);
1816 s->clkm.arm_idlect1 = 0x0400;
1817 omap_clkm_idlect2_update(s, s->clkm.arm_idlect2 ^ 0x0100, 0x0100);
1818 s->clkm.arm_idlect2 = 0x0100;
1819 s->clkm.arm_ewupct = 0x003f;
1820 s->clkm.arm_rstct1 = 0x0000;
1821 s->clkm.arm_rstct2 = 0x0000;
1822 s->clkm.arm_ckout1 = 0x0015;
1823 s->clkm.dpll1_mode = 0x2002;
1824 omap_clkdsp_idlect1_update(s, s->clkm.dsp_idlect1 ^ 0x0040, 0x0040);
1825 s->clkm.dsp_idlect1 = 0x0040;
1826 omap_clkdsp_idlect2_update(s, ~0, 0x0000);
1827 s->clkm.dsp_idlect2 = 0x0000;
1828 s->clkm.dsp_rstct2 = 0x0000;
1829}
1830
1831static void omap_clkm_init(MemoryRegion *memory, hwaddr mpu_base,
1832 hwaddr dsp_base, struct omap_mpu_state_s *s)
1833{
1834 memory_region_init_io(&s->clkm_iomem, &omap_clkm_ops, s,
1835 "omap-clkm", 0x100);
1836 memory_region_init_io(&s->clkdsp_iomem, &omap_clkdsp_ops, s,
1837 "omap-clkdsp", 0x1000);
1838
1839 s->clkm.arm_idlect1 = 0x03ff;
1840 s->clkm.arm_idlect2 = 0x0100;
1841 s->clkm.dsp_idlect1 = 0x0002;
1842 omap_clkm_reset(s);
1843 s->clkm.cold_start = 0x3a;
1844
1845 memory_region_add_subregion(memory, mpu_base, &s->clkm_iomem);
1846 memory_region_add_subregion(memory, dsp_base, &s->clkdsp_iomem);
1847}
1848
1849
1850struct omap_mpuio_s {
1851 qemu_irq irq;
1852 qemu_irq kbd_irq;
1853 qemu_irq *in;
1854 qemu_irq handler[16];
1855 qemu_irq wakeup;
1856 MemoryRegion iomem;
1857
1858 uint16_t inputs;
1859 uint16_t outputs;
1860 uint16_t dir;
1861 uint16_t edge;
1862 uint16_t mask;
1863 uint16_t ints;
1864
1865 uint16_t debounce;
1866 uint16_t latch;
1867 uint8_t event;
1868
1869 uint8_t buttons[5];
1870 uint8_t row_latch;
1871 uint8_t cols;
1872 int kbd_mask;
1873 int clk;
1874};
1875
1876static void omap_mpuio_set(void *opaque, int line, int level)
1877{
1878 struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
1879 uint16_t prev = s->inputs;
1880
1881 if (level)
1882 s->inputs |= 1 << line;
1883 else
1884 s->inputs &= ~(1 << line);
1885
1886 if (((1 << line) & s->dir & ~s->mask) && s->clk) {
1887 if ((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) {
1888 s->ints |= 1 << line;
1889 qemu_irq_raise(s->irq);
1890
1891 }
1892 if ((s->event & (1 << 0)) &&
1893 (s->event >> 1) == line)
1894 s->latch = s->inputs;
1895 }
1896}
1897
1898static void omap_mpuio_kbd_update(struct omap_mpuio_s *s)
1899{
1900 int i;
1901 uint8_t *row, rows = 0, cols = ~s->cols;
1902
1903 for (row = s->buttons + 4, i = 1 << 4; i; row --, i >>= 1)
1904 if (*row & cols)
1905 rows |= i;
1906
1907 qemu_set_irq(s->kbd_irq, rows && !s->kbd_mask && s->clk);
1908 s->row_latch = ~rows;
1909}
1910
1911static uint64_t omap_mpuio_read(void *opaque, hwaddr addr,
1912 unsigned size)
1913{
1914 struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
1915 int offset = addr & OMAP_MPUI_REG_MASK;
1916 uint16_t ret;
1917
1918 if (size != 2) {
1919 return omap_badwidth_read16(opaque, addr);
1920 }
1921
1922 switch (offset) {
1923 case 0x00:
1924 return s->inputs;
1925
1926 case 0x04:
1927 return s->outputs;
1928
1929 case 0x08:
1930 return s->dir;
1931
1932 case 0x10:
1933 return s->row_latch;
1934
1935 case 0x14:
1936 return s->cols;
1937
1938 case 0x18:
1939 return s->event;
1940
1941 case 0x1c:
1942 return s->edge;
1943
1944 case 0x20:
1945 return (~s->row_latch & 0x1f) && !s->kbd_mask;
1946
1947 case 0x24:
1948 ret = s->ints;
1949 s->ints &= s->mask;
1950 if (ret)
1951 qemu_irq_lower(s->irq);
1952 return ret;
1953
1954 case 0x28:
1955 return s->kbd_mask;
1956
1957 case 0x2c:
1958 return s->mask;
1959
1960 case 0x30:
1961 return s->debounce;
1962
1963 case 0x34:
1964 return s->latch;
1965 }
1966
1967 OMAP_BAD_REG(addr);
1968 return 0;
1969}
1970
1971static void omap_mpuio_write(void *opaque, hwaddr addr,
1972 uint64_t value, unsigned size)
1973{
1974 struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
1975 int offset = addr & OMAP_MPUI_REG_MASK;
1976 uint16_t diff;
1977 int ln;
1978
1979 if (size != 2) {
1980 return omap_badwidth_write16(opaque, addr, value);
1981 }
1982
1983 switch (offset) {
1984 case 0x04:
1985 diff = (s->outputs ^ value) & ~s->dir;
1986 s->outputs = value;
1987 while ((ln = ffs(diff))) {
1988 ln --;
1989 if (s->handler[ln])
1990 qemu_set_irq(s->handler[ln], (value >> ln) & 1);
1991 diff &= ~(1 << ln);
1992 }
1993 break;
1994
1995 case 0x08:
1996 diff = s->outputs & (s->dir ^ value);
1997 s->dir = value;
1998
1999 value = s->outputs & ~s->dir;
2000 while ((ln = ffs(diff))) {
2001 ln --;
2002 if (s->handler[ln])
2003 qemu_set_irq(s->handler[ln], (value >> ln) & 1);
2004 diff &= ~(1 << ln);
2005 }
2006 break;
2007
2008 case 0x14:
2009 s->cols = value;
2010 omap_mpuio_kbd_update(s);
2011 break;
2012
2013 case 0x18:
2014 s->event = value & 0x1f;
2015 break;
2016
2017 case 0x1c:
2018 s->edge = value;
2019 break;
2020
2021 case 0x28:
2022 s->kbd_mask = value & 1;
2023 omap_mpuio_kbd_update(s);
2024 break;
2025
2026 case 0x2c:
2027 s->mask = value;
2028 break;
2029
2030 case 0x30:
2031 s->debounce = value & 0x1ff;
2032 break;
2033
2034 case 0x00:
2035 case 0x10:
2036 case 0x20:
2037 case 0x24:
2038 case 0x34:
2039 OMAP_RO_REG(addr);
2040 return;
2041
2042 default:
2043 OMAP_BAD_REG(addr);
2044 return;
2045 }
2046}
2047
2048static const MemoryRegionOps omap_mpuio_ops = {
2049 .read = omap_mpuio_read,
2050 .write = omap_mpuio_write,
2051 .endianness = DEVICE_NATIVE_ENDIAN,
2052};
2053
2054static void omap_mpuio_reset(struct omap_mpuio_s *s)
2055{
2056 s->inputs = 0;
2057 s->outputs = 0;
2058 s->dir = ~0;
2059 s->event = 0;
2060 s->edge = 0;
2061 s->kbd_mask = 0;
2062 s->mask = 0;
2063 s->debounce = 0;
2064 s->latch = 0;
2065 s->ints = 0;
2066 s->row_latch = 0x1f;
2067 s->clk = 1;
2068}
2069
2070static void omap_mpuio_onoff(void *opaque, int line, int on)
2071{
2072 struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
2073
2074 s->clk = on;
2075 if (on)
2076 omap_mpuio_kbd_update(s);
2077}
2078
2079static struct omap_mpuio_s *omap_mpuio_init(MemoryRegion *memory,
2080 hwaddr base,
2081 qemu_irq kbd_int, qemu_irq gpio_int, qemu_irq wakeup,
2082 omap_clk clk)
2083{
2084 struct omap_mpuio_s *s = (struct omap_mpuio_s *)
2085 g_malloc0(sizeof(struct omap_mpuio_s));
2086
2087 s->irq = gpio_int;
2088 s->kbd_irq = kbd_int;
2089 s->wakeup = wakeup;
2090 s->in = qemu_allocate_irqs(omap_mpuio_set, s, 16);
2091 omap_mpuio_reset(s);
2092
2093 memory_region_init_io(&s->iomem, &omap_mpuio_ops, s,
2094 "omap-mpuio", 0x800);
2095 memory_region_add_subregion(memory, base, &s->iomem);
2096
2097 omap_clk_adduser(clk, qemu_allocate_irqs(omap_mpuio_onoff, s, 1)[0]);
2098
2099 return s;
2100}
2101
2102qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s)
2103{
2104 return s->in;
2105}
2106
2107void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler)
2108{
2109 if (line >= 16 || line < 0)
2110 hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
2111 s->handler[line] = handler;
2112}
2113
2114void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down)
2115{
2116 if (row >= 5 || row < 0)
2117 hw_error("%s: No key %i-%i\n", __FUNCTION__, col, row);
2118
2119 if (down)
2120 s->buttons[row] |= 1 << col;
2121 else
2122 s->buttons[row] &= ~(1 << col);
2123
2124 omap_mpuio_kbd_update(s);
2125}
2126
2127
2128struct omap_uwire_s {
2129 MemoryRegion iomem;
2130 qemu_irq txirq;
2131 qemu_irq rxirq;
2132 qemu_irq txdrq;
2133
2134 uint16_t txbuf;
2135 uint16_t rxbuf;
2136 uint16_t control;
2137 uint16_t setup[5];
2138
2139 uWireSlave *chip[4];
2140};
2141
2142static void omap_uwire_transfer_start(struct omap_uwire_s *s)
2143{
2144 int chipselect = (s->control >> 10) & 3;
2145 uWireSlave *slave = s->chip[chipselect];
2146
2147 if ((s->control >> 5) & 0x1f) {
2148 if (s->control & (1 << 12))
2149 if (slave && slave->send)
2150 slave->send(slave->opaque,
2151 s->txbuf >> (16 - ((s->control >> 5) & 0x1f)));
2152 s->control &= ~(1 << 14);
2153
2154
2155 }
2156
2157 if ((s->control >> 0) & 0x1f) {
2158 if (s->control & (1 << 12))
2159 if (slave && slave->receive)
2160 s->rxbuf = slave->receive(slave->opaque);
2161 s->control |= 1 << 15;
2162
2163
2164 }
2165}
2166
2167static uint64_t omap_uwire_read(void *opaque, hwaddr addr,
2168 unsigned size)
2169{
2170 struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
2171 int offset = addr & OMAP_MPUI_REG_MASK;
2172
2173 if (size != 2) {
2174 return omap_badwidth_read16(opaque, addr);
2175 }
2176
2177 switch (offset) {
2178 case 0x00:
2179 s->control &= ~(1 << 15);
2180 return s->rxbuf;
2181
2182 case 0x04:
2183 return s->control;
2184
2185 case 0x08:
2186 return s->setup[0];
2187 case 0x0c:
2188 return s->setup[1];
2189 case 0x10:
2190 return s->setup[2];
2191 case 0x14:
2192 return s->setup[3];
2193 case 0x18:
2194 return s->setup[4];
2195 }
2196
2197 OMAP_BAD_REG(addr);
2198 return 0;
2199}
2200
2201static void omap_uwire_write(void *opaque, hwaddr addr,
2202 uint64_t value, unsigned size)
2203{
2204 struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
2205 int offset = addr & OMAP_MPUI_REG_MASK;
2206
2207 if (size != 2) {
2208 return omap_badwidth_write16(opaque, addr, value);
2209 }
2210
2211 switch (offset) {
2212 case 0x00:
2213 s->txbuf = value;
2214 if ((s->setup[4] & (1 << 2)) &&
2215 ((s->setup[4] & (1 << 3)) ||
2216 (s->control & (1 << 12)))) {
2217 s->control |= 1 << 14;
2218 omap_uwire_transfer_start(s);
2219 }
2220 break;
2221
2222 case 0x04:
2223 s->control = value & 0x1fff;
2224 if (value & (1 << 13))
2225 omap_uwire_transfer_start(s);
2226 break;
2227
2228 case 0x08:
2229 s->setup[0] = value & 0x003f;
2230 break;
2231
2232 case 0x0c:
2233 s->setup[1] = value & 0x0fc0;
2234 break;
2235
2236 case 0x10:
2237 s->setup[2] = value & 0x0003;
2238 break;
2239
2240 case 0x14:
2241 s->setup[3] = value & 0x0001;
2242 break;
2243
2244 case 0x18:
2245 s->setup[4] = value & 0x000f;
2246 break;
2247
2248 default:
2249 OMAP_BAD_REG(addr);
2250 return;
2251 }
2252}
2253
2254static const MemoryRegionOps omap_uwire_ops = {
2255 .read = omap_uwire_read,
2256 .write = omap_uwire_write,
2257 .endianness = DEVICE_NATIVE_ENDIAN,
2258};
2259
2260static void omap_uwire_reset(struct omap_uwire_s *s)
2261{
2262 s->control = 0;
2263 s->setup[0] = 0;
2264 s->setup[1] = 0;
2265 s->setup[2] = 0;
2266 s->setup[3] = 0;
2267 s->setup[4] = 0;
2268}
2269
2270static struct omap_uwire_s *omap_uwire_init(MemoryRegion *system_memory,
2271 hwaddr base,
2272 qemu_irq txirq, qemu_irq rxirq,
2273 qemu_irq dma,
2274 omap_clk clk)
2275{
2276 struct omap_uwire_s *s = (struct omap_uwire_s *)
2277 g_malloc0(sizeof(struct omap_uwire_s));
2278
2279 s->txirq = txirq;
2280 s->rxirq = rxirq;
2281 s->txdrq = dma;
2282 omap_uwire_reset(s);
2283
2284 memory_region_init_io(&s->iomem, &omap_uwire_ops, s, "omap-uwire", 0x800);
2285 memory_region_add_subregion(system_memory, base, &s->iomem);
2286
2287 return s;
2288}
2289
2290void omap_uwire_attach(struct omap_uwire_s *s,
2291 uWireSlave *slave, int chipselect)
2292{
2293 if (chipselect < 0 || chipselect > 3) {
2294 fprintf(stderr, "%s: Bad chipselect %i\n", __FUNCTION__, chipselect);
2295 exit(-1);
2296 }
2297
2298 s->chip[chipselect] = slave;
2299}
2300
2301
2302struct omap_pwl_s {
2303 MemoryRegion iomem;
2304 uint8_t output;
2305 uint8_t level;
2306 uint8_t enable;
2307 int clk;
2308};
2309
2310static void omap_pwl_update(struct omap_pwl_s *s)
2311{
2312 int output = (s->clk && s->enable) ? s->level : 0;
2313
2314 if (output != s->output) {
2315 s->output = output;
2316 printf("%s: Backlight now at %i/256\n", __FUNCTION__, output);
2317 }
2318}
2319
2320static uint64_t omap_pwl_read(void *opaque, hwaddr addr,
2321 unsigned size)
2322{
2323 struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
2324 int offset = addr & OMAP_MPUI_REG_MASK;
2325
2326 if (size != 1) {
2327 return omap_badwidth_read8(opaque, addr);
2328 }
2329
2330 switch (offset) {
2331 case 0x00:
2332 return s->level;
2333 case 0x04:
2334 return s->enable;
2335 }
2336 OMAP_BAD_REG(addr);
2337 return 0;
2338}
2339
2340static void omap_pwl_write(void *opaque, hwaddr addr,
2341 uint64_t value, unsigned size)
2342{
2343 struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
2344 int offset = addr & OMAP_MPUI_REG_MASK;
2345
2346 if (size != 1) {
2347 return omap_badwidth_write8(opaque, addr, value);
2348 }
2349
2350 switch (offset) {
2351 case 0x00:
2352 s->level = value;
2353 omap_pwl_update(s);
2354 break;
2355 case 0x04:
2356 s->enable = value & 1;
2357 omap_pwl_update(s);
2358 break;
2359 default:
2360 OMAP_BAD_REG(addr);
2361 return;
2362 }
2363}
2364
2365static const MemoryRegionOps omap_pwl_ops = {
2366 .read = omap_pwl_read,
2367 .write = omap_pwl_write,
2368 .endianness = DEVICE_NATIVE_ENDIAN,
2369};
2370
2371static void omap_pwl_reset(struct omap_pwl_s *s)
2372{
2373 s->output = 0;
2374 s->level = 0;
2375 s->enable = 0;
2376 s->clk = 1;
2377 omap_pwl_update(s);
2378}
2379
2380static void omap_pwl_clk_update(void *opaque, int line, int on)
2381{
2382 struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
2383
2384 s->clk = on;
2385 omap_pwl_update(s);
2386}
2387
2388static struct omap_pwl_s *omap_pwl_init(MemoryRegion *system_memory,
2389 hwaddr base,
2390 omap_clk clk)
2391{
2392 struct omap_pwl_s *s = g_malloc0(sizeof(*s));
2393
2394 omap_pwl_reset(s);
2395
2396 memory_region_init_io(&s->iomem, &omap_pwl_ops, s,
2397 "omap-pwl", 0x800);
2398 memory_region_add_subregion(system_memory, base, &s->iomem);
2399
2400 omap_clk_adduser(clk, qemu_allocate_irqs(omap_pwl_clk_update, s, 1)[0]);
2401 return s;
2402}
2403
2404
2405struct omap_pwt_s {
2406 MemoryRegion iomem;
2407 uint8_t frc;
2408 uint8_t vrc;
2409 uint8_t gcr;
2410 omap_clk clk;
2411};
2412
2413static uint64_t omap_pwt_read(void *opaque, hwaddr addr,
2414 unsigned size)
2415{
2416 struct omap_pwt_s *s = (struct omap_pwt_s *) opaque;
2417 int offset = addr & OMAP_MPUI_REG_MASK;
2418
2419 if (size != 1) {
2420 return omap_badwidth_read8(opaque, addr);
2421 }
2422
2423 switch (offset) {
2424 case 0x00:
2425 return s->frc;
2426 case 0x04:
2427 return s->vrc;
2428 case 0x08:
2429 return s->gcr;
2430 }
2431 OMAP_BAD_REG(addr);
2432 return 0;
2433}
2434
2435static void omap_pwt_write(void *opaque, hwaddr addr,
2436 uint64_t value, unsigned size)
2437{
2438 struct omap_pwt_s *s = (struct omap_pwt_s *) opaque;
2439 int offset = addr & OMAP_MPUI_REG_MASK;
2440
2441 if (size != 1) {
2442 return omap_badwidth_write8(opaque, addr, value);
2443 }
2444
2445 switch (offset) {
2446 case 0x00:
2447 s->frc = value & 0x3f;
2448 break;
2449 case 0x04:
2450 if ((value ^ s->vrc) & 1) {
2451 if (value & 1)
2452 printf("%s: %iHz buzz on\n", __FUNCTION__, (int)
2453
2454 ((omap_clk_getrate(s->clk) >> 3) /
2455
2456 ((s->gcr & 2) ? 1 : 154) /
2457
2458 (2 << (value & 3)) *
2459
2460 ((value & (1 << 2)) ? 101 : 107) *
2461
2462 ((value & (1 << 3)) ? 49 : 55) *
2463
2464 ((value & (1 << 4)) ? 50 : 63) *
2465
2466 ((value & (1 << 5)) ? 80 : 127) /
2467 (107 * 55 * 63 * 127)));
2468 else
2469 printf("%s: silence!\n", __FUNCTION__);
2470 }
2471 s->vrc = value & 0x7f;
2472 break;
2473 case 0x08:
2474 s->gcr = value & 3;
2475 break;
2476 default:
2477 OMAP_BAD_REG(addr);
2478 return;
2479 }
2480}
2481
2482static const MemoryRegionOps omap_pwt_ops = {
2483 .read =omap_pwt_read,
2484 .write = omap_pwt_write,
2485 .endianness = DEVICE_NATIVE_ENDIAN,
2486};
2487
2488static void omap_pwt_reset(struct omap_pwt_s *s)
2489{
2490 s->frc = 0;
2491 s->vrc = 0;
2492 s->gcr = 0;
2493}
2494
2495static struct omap_pwt_s *omap_pwt_init(MemoryRegion *system_memory,
2496 hwaddr base,
2497 omap_clk clk)
2498{
2499 struct omap_pwt_s *s = g_malloc0(sizeof(*s));
2500 s->clk = clk;
2501 omap_pwt_reset(s);
2502
2503 memory_region_init_io(&s->iomem, &omap_pwt_ops, s,
2504 "omap-pwt", 0x800);
2505 memory_region_add_subregion(system_memory, base, &s->iomem);
2506 return s;
2507}
2508
2509
2510struct omap_rtc_s {
2511 MemoryRegion iomem;
2512 qemu_irq irq;
2513 qemu_irq alarm;
2514 QEMUTimer *clk;
2515
2516 uint8_t interrupts;
2517 uint8_t status;
2518 int16_t comp_reg;
2519 int running;
2520 int pm_am;
2521 int auto_comp;
2522 int round;
2523 struct tm alarm_tm;
2524 time_t alarm_ti;
2525
2526 struct tm current_tm;
2527 time_t ti;
2528 uint64_t tick;
2529};
2530
2531static void omap_rtc_interrupts_update(struct omap_rtc_s *s)
2532{
2533
2534 qemu_set_irq(s->alarm, (s->status >> 6) & 1);
2535}
2536
2537static void omap_rtc_alarm_update(struct omap_rtc_s *s)
2538{
2539 s->alarm_ti = mktimegm(&s->alarm_tm);
2540 if (s->alarm_ti == -1)
2541 printf("%s: conversion failed\n", __FUNCTION__);
2542}
2543
2544static uint64_t omap_rtc_read(void *opaque, hwaddr addr,
2545 unsigned size)
2546{
2547 struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
2548 int offset = addr & OMAP_MPUI_REG_MASK;
2549 uint8_t i;
2550
2551 if (size != 1) {
2552 return omap_badwidth_read8(opaque, addr);
2553 }
2554
2555 switch (offset) {
2556 case 0x00:
2557 return to_bcd(s->current_tm.tm_sec);
2558
2559 case 0x04:
2560 return to_bcd(s->current_tm.tm_min);
2561
2562 case 0x08:
2563 if (s->pm_am)
2564 return ((s->current_tm.tm_hour > 11) << 7) |
2565 to_bcd(((s->current_tm.tm_hour - 1) % 12) + 1);
2566 else
2567 return to_bcd(s->current_tm.tm_hour);
2568
2569 case 0x0c:
2570 return to_bcd(s->current_tm.tm_mday);
2571
2572 case 0x10:
2573 return to_bcd(s->current_tm.tm_mon + 1);
2574
2575 case 0x14:
2576 return to_bcd(s->current_tm.tm_year % 100);
2577
2578 case 0x18:
2579 return s->current_tm.tm_wday;
2580
2581 case 0x20:
2582 return to_bcd(s->alarm_tm.tm_sec);
2583
2584 case 0x24:
2585 return to_bcd(s->alarm_tm.tm_min);
2586
2587 case 0x28:
2588 if (s->pm_am)
2589 return ((s->alarm_tm.tm_hour > 11) << 7) |
2590 to_bcd(((s->alarm_tm.tm_hour - 1) % 12) + 1);
2591 else
2592 return to_bcd(s->alarm_tm.tm_hour);
2593
2594 case 0x2c:
2595 return to_bcd(s->alarm_tm.tm_mday);
2596
2597 case 0x30:
2598 return to_bcd(s->alarm_tm.tm_mon + 1);
2599
2600 case 0x34:
2601 return to_bcd(s->alarm_tm.tm_year % 100);
2602
2603 case 0x40:
2604 return (s->pm_am << 3) | (s->auto_comp << 2) |
2605 (s->round << 1) | s->running;
2606
2607 case 0x44:
2608 i = s->status;
2609 s->status &= ~0x3d;
2610 return i;
2611
2612 case 0x48:
2613 return s->interrupts;
2614
2615 case 0x4c:
2616 return ((uint16_t) s->comp_reg) & 0xff;
2617
2618 case 0x50:
2619 return ((uint16_t) s->comp_reg) >> 8;
2620 }
2621
2622 OMAP_BAD_REG(addr);
2623 return 0;
2624}
2625
2626static void omap_rtc_write(void *opaque, hwaddr addr,
2627 uint64_t value, unsigned size)
2628{
2629 struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
2630 int offset = addr & OMAP_MPUI_REG_MASK;
2631 struct tm new_tm;
2632 time_t ti[2];
2633
2634 if (size != 1) {
2635 return omap_badwidth_write8(opaque, addr, value);
2636 }
2637
2638 switch (offset) {
2639 case 0x00:
2640#ifdef ALMDEBUG
2641 printf("RTC SEC_REG <-- %02x\n", value);
2642#endif
2643 s->ti -= s->current_tm.tm_sec;
2644 s->ti += from_bcd(value);
2645 return;
2646
2647 case 0x04:
2648#ifdef ALMDEBUG
2649 printf("RTC MIN_REG <-- %02x\n", value);
2650#endif
2651 s->ti -= s->current_tm.tm_min * 60;
2652 s->ti += from_bcd(value) * 60;
2653 return;
2654
2655 case 0x08:
2656#ifdef ALMDEBUG
2657 printf("RTC HRS_REG <-- %02x\n", value);
2658#endif
2659 s->ti -= s->current_tm.tm_hour * 3600;
2660 if (s->pm_am) {
2661 s->ti += (from_bcd(value & 0x3f) & 12) * 3600;
2662 s->ti += ((value >> 7) & 1) * 43200;
2663 } else
2664 s->ti += from_bcd(value & 0x3f) * 3600;
2665 return;
2666
2667 case 0x0c:
2668#ifdef ALMDEBUG
2669 printf("RTC DAY_REG <-- %02x\n", value);
2670#endif
2671 s->ti -= s->current_tm.tm_mday * 86400;
2672 s->ti += from_bcd(value) * 86400;
2673 return;
2674
2675 case 0x10:
2676#ifdef ALMDEBUG
2677 printf("RTC MTH_REG <-- %02x\n", value);
2678#endif
2679 memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
2680 new_tm.tm_mon = from_bcd(value);
2681 ti[0] = mktimegm(&s->current_tm);
2682 ti[1] = mktimegm(&new_tm);
2683
2684 if (ti[0] != -1 && ti[1] != -1) {
2685 s->ti -= ti[0];
2686 s->ti += ti[1];
2687 } else {
2688
2689 s->ti -= s->current_tm.tm_mon * 2592000;
2690 s->ti += from_bcd(value) * 2592000;
2691 }
2692 return;
2693
2694 case 0x14:
2695#ifdef ALMDEBUG
2696 printf("RTC YRS_REG <-- %02x\n", value);
2697#endif
2698 memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
2699 new_tm.tm_year += from_bcd(value) - (new_tm.tm_year % 100);
2700 ti[0] = mktimegm(&s->current_tm);
2701 ti[1] = mktimegm(&new_tm);
2702
2703 if (ti[0] != -1 && ti[1] != -1) {
2704 s->ti -= ti[0];
2705 s->ti += ti[1];
2706 } else {
2707
2708 s->ti -= (s->current_tm.tm_year % 100) * 31536000;
2709 s->ti += from_bcd(value) * 31536000;
2710 }
2711 return;
2712
2713 case 0x18:
2714 return;
2715
2716 case 0x20:
2717#ifdef ALMDEBUG
2718 printf("ALM SEC_REG <-- %02x\n", value);
2719#endif
2720 s->alarm_tm.tm_sec = from_bcd(value);
2721 omap_rtc_alarm_update(s);
2722 return;
2723
2724 case 0x24:
2725#ifdef ALMDEBUG
2726 printf("ALM MIN_REG <-- %02x\n", value);
2727#endif
2728 s->alarm_tm.tm_min = from_bcd(value);
2729 omap_rtc_alarm_update(s);
2730 return;
2731
2732 case 0x28:
2733#ifdef ALMDEBUG
2734 printf("ALM HRS_REG <-- %02x\n", value);
2735#endif
2736 if (s->pm_am)
2737 s->alarm_tm.tm_hour =
2738 ((from_bcd(value & 0x3f)) % 12) +
2739 ((value >> 7) & 1) * 12;
2740 else
2741 s->alarm_tm.tm_hour = from_bcd(value);
2742 omap_rtc_alarm_update(s);
2743 return;
2744
2745 case 0x2c:
2746#ifdef ALMDEBUG
2747 printf("ALM DAY_REG <-- %02x\n", value);
2748#endif
2749 s->alarm_tm.tm_mday = from_bcd(value);
2750 omap_rtc_alarm_update(s);
2751 return;
2752
2753 case 0x30:
2754#ifdef ALMDEBUG
2755 printf("ALM MON_REG <-- %02x\n", value);
2756#endif
2757 s->alarm_tm.tm_mon = from_bcd(value);
2758 omap_rtc_alarm_update(s);
2759 return;
2760
2761 case 0x34:
2762#ifdef ALMDEBUG
2763 printf("ALM YRS_REG <-- %02x\n", value);
2764#endif
2765 s->alarm_tm.tm_year = from_bcd(value);
2766 omap_rtc_alarm_update(s);
2767 return;
2768
2769 case 0x40:
2770#ifdef ALMDEBUG
2771 printf("RTC CONTROL <-- %02x\n", value);
2772#endif
2773 s->pm_am = (value >> 3) & 1;
2774 s->auto_comp = (value >> 2) & 1;
2775 s->round = (value >> 1) & 1;
2776 s->running = value & 1;
2777 s->status &= 0xfd;
2778 s->status |= s->running << 1;
2779 return;
2780
2781 case 0x44:
2782#ifdef ALMDEBUG
2783 printf("RTC STATUSL <-- %02x\n", value);
2784#endif
2785 s->status &= ~((value & 0xc0) ^ 0x80);
2786 omap_rtc_interrupts_update(s);
2787 return;
2788
2789 case 0x48:
2790#ifdef ALMDEBUG
2791 printf("RTC INTRS <-- %02x\n", value);
2792#endif
2793 s->interrupts = value;
2794 return;
2795
2796 case 0x4c:
2797#ifdef ALMDEBUG
2798 printf("RTC COMPLSB <-- %02x\n", value);
2799#endif
2800 s->comp_reg &= 0xff00;
2801 s->comp_reg |= 0x00ff & value;
2802 return;
2803
2804 case 0x50:
2805#ifdef ALMDEBUG
2806 printf("RTC COMPMSB <-- %02x\n", value);
2807#endif
2808 s->comp_reg &= 0x00ff;
2809 s->comp_reg |= 0xff00 & (value << 8);
2810 return;
2811
2812 default:
2813 OMAP_BAD_REG(addr);
2814 return;
2815 }
2816}
2817
2818static const MemoryRegionOps omap_rtc_ops = {
2819 .read = omap_rtc_read,
2820 .write = omap_rtc_write,
2821 .endianness = DEVICE_NATIVE_ENDIAN,
2822};
2823
2824static void omap_rtc_tick(void *opaque)
2825{
2826 struct omap_rtc_s *s = opaque;
2827
2828 if (s->round) {
2829
2830 if (s->current_tm.tm_sec < 30)
2831 s->ti -= s->current_tm.tm_sec;
2832 else
2833 s->ti += 60 - s->current_tm.tm_sec;
2834
2835 s->round = 0;
2836 }
2837
2838 localtime_r(&s->ti, &s->current_tm);
2839
2840 if ((s->interrupts & 0x08) && s->ti == s->alarm_ti) {
2841 s->status |= 0x40;
2842 omap_rtc_interrupts_update(s);
2843 }
2844
2845 if (s->interrupts & 0x04)
2846 switch (s->interrupts & 3) {
2847 case 0:
2848 s->status |= 0x04;
2849 qemu_irq_pulse(s->irq);
2850 break;
2851 case 1:
2852 if (s->current_tm.tm_sec)
2853 break;
2854 s->status |= 0x08;
2855 qemu_irq_pulse(s->irq);
2856 break;
2857 case 2:
2858 if (s->current_tm.tm_sec || s->current_tm.tm_min)
2859 break;
2860 s->status |= 0x10;
2861 qemu_irq_pulse(s->irq);
2862 break;
2863 case 3:
2864 if (s->current_tm.tm_sec ||
2865 s->current_tm.tm_min || s->current_tm.tm_hour)
2866 break;
2867 s->status |= 0x20;
2868 qemu_irq_pulse(s->irq);
2869 break;
2870 }
2871
2872
2873 if (s->running)
2874 s->ti ++;
2875 s->tick += 1000;
2876
2877
2878
2879
2880
2881 if (s->auto_comp && !s->current_tm.tm_sec && !s->current_tm.tm_min)
2882 s->tick += s->comp_reg * 1000 / 32768;
2883
2884 qemu_mod_timer(s->clk, s->tick);
2885}
2886
2887static void omap_rtc_reset(struct omap_rtc_s *s)
2888{
2889 struct tm tm;
2890
2891 s->interrupts = 0;
2892 s->comp_reg = 0;
2893 s->running = 0;
2894 s->pm_am = 0;
2895 s->auto_comp = 0;
2896 s->round = 0;
2897 s->tick = qemu_get_clock_ms(rtc_clock);
2898 memset(&s->alarm_tm, 0, sizeof(s->alarm_tm));
2899 s->alarm_tm.tm_mday = 0x01;
2900 s->status = 1 << 7;
2901 qemu_get_timedate(&tm, 0);
2902 s->ti = mktimegm(&tm);
2903
2904 omap_rtc_alarm_update(s);
2905 omap_rtc_tick(s);
2906}
2907
2908static struct omap_rtc_s *omap_rtc_init(MemoryRegion *system_memory,
2909 hwaddr base,
2910 qemu_irq timerirq, qemu_irq alarmirq,
2911 omap_clk clk)
2912{
2913 struct omap_rtc_s *s = (struct omap_rtc_s *)
2914 g_malloc0(sizeof(struct omap_rtc_s));
2915
2916 s->irq = timerirq;
2917 s->alarm = alarmirq;
2918 s->clk = qemu_new_timer_ms(rtc_clock, omap_rtc_tick, s);
2919
2920 omap_rtc_reset(s);
2921
2922 memory_region_init_io(&s->iomem, &omap_rtc_ops, s,
2923 "omap-rtc", 0x800);
2924 memory_region_add_subregion(system_memory, base, &s->iomem);
2925
2926 return s;
2927}
2928
2929
2930struct omap_mcbsp_s {
2931 MemoryRegion iomem;
2932 qemu_irq txirq;
2933 qemu_irq rxirq;
2934 qemu_irq txdrq;
2935 qemu_irq rxdrq;
2936
2937 uint16_t spcr[2];
2938 uint16_t rcr[2];
2939 uint16_t xcr[2];
2940 uint16_t srgr[2];
2941 uint16_t mcr[2];
2942 uint16_t pcr;
2943 uint16_t rcer[8];
2944 uint16_t xcer[8];
2945 int tx_rate;
2946 int rx_rate;
2947 int tx_req;
2948 int rx_req;
2949
2950 I2SCodec *codec;
2951 QEMUTimer *source_timer;
2952 QEMUTimer *sink_timer;
2953};
2954
2955static void omap_mcbsp_intr_update(struct omap_mcbsp_s *s)
2956{
2957 int irq;
2958
2959 switch ((s->spcr[0] >> 4) & 3) {
2960 case 0:
2961 irq = (s->spcr[0] >> 1) & 1;
2962 break;
2963 case 3:
2964 irq = (s->spcr[0] >> 3) & 1;
2965 break;
2966 default:
2967 irq = 0;
2968 break;
2969 }
2970
2971 if (irq)
2972 qemu_irq_pulse(s->rxirq);
2973
2974 switch ((s->spcr[1] >> 4) & 3) {
2975 case 0:
2976 irq = (s->spcr[1] >> 1) & 1;
2977 break;
2978 case 3:
2979 irq = (s->spcr[1] >> 3) & 1;
2980 break;
2981 default:
2982 irq = 0;
2983 break;
2984 }
2985
2986 if (irq)
2987 qemu_irq_pulse(s->txirq);
2988}
2989
2990static void omap_mcbsp_rx_newdata(struct omap_mcbsp_s *s)
2991{
2992 if ((s->spcr[0] >> 1) & 1)
2993 s->spcr[0] |= 1 << 2;
2994 s->spcr[0] |= 1 << 1;
2995 qemu_irq_raise(s->rxdrq);
2996 omap_mcbsp_intr_update(s);
2997}
2998
2999static void omap_mcbsp_source_tick(void *opaque)
3000{
3001 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
3002 static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 };
3003
3004 if (!s->rx_rate)
3005 return;
3006 if (s->rx_req)
3007 printf("%s: Rx FIFO overrun\n", __FUNCTION__);
3008
3009 s->rx_req = s->rx_rate << bps[(s->rcr[0] >> 5) & 7];
3010
3011 omap_mcbsp_rx_newdata(s);
3012 qemu_mod_timer(s->source_timer, qemu_get_clock_ns(vm_clock) +
3013 get_ticks_per_sec());
3014}
3015
3016static void omap_mcbsp_rx_start(struct omap_mcbsp_s *s)
3017{
3018 if (!s->codec || !s->codec->rts)
3019 omap_mcbsp_source_tick(s);
3020 else if (s->codec->in.len) {
3021 s->rx_req = s->codec->in.len;
3022 omap_mcbsp_rx_newdata(s);
3023 }
3024}
3025
3026static void omap_mcbsp_rx_stop(struct omap_mcbsp_s *s)
3027{
3028 qemu_del_timer(s->source_timer);
3029}
3030
3031static void omap_mcbsp_rx_done(struct omap_mcbsp_s *s)
3032{
3033 s->spcr[0] &= ~(1 << 1);
3034 qemu_irq_lower(s->rxdrq);
3035 omap_mcbsp_intr_update(s);
3036}
3037
3038static void omap_mcbsp_tx_newdata(struct omap_mcbsp_s *s)
3039{
3040 s->spcr[1] |= 1 << 1;
3041 qemu_irq_raise(s->txdrq);
3042 omap_mcbsp_intr_update(s);
3043}
3044
3045static void omap_mcbsp_sink_tick(void *opaque)
3046{
3047 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
3048 static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 };
3049
3050 if (!s->tx_rate)
3051 return;
3052 if (s->tx_req)
3053 printf("%s: Tx FIFO underrun\n", __FUNCTION__);
3054
3055 s->tx_req = s->tx_rate << bps[(s->xcr[0] >> 5) & 7];
3056
3057 omap_mcbsp_tx_newdata(s);
3058 qemu_mod_timer(s->sink_timer, qemu_get_clock_ns(vm_clock) +
3059 get_ticks_per_sec());
3060}
3061
3062static void omap_mcbsp_tx_start(struct omap_mcbsp_s *s)
3063{
3064 if (!s->codec || !s->codec->cts)
3065 omap_mcbsp_sink_tick(s);
3066 else if (s->codec->out.size) {
3067 s->tx_req = s->codec->out.size;
3068 omap_mcbsp_tx_newdata(s);
3069 }
3070}
3071
3072static void omap_mcbsp_tx_done(struct omap_mcbsp_s *s)
3073{
3074 s->spcr[1] &= ~(1 << 1);
3075 qemu_irq_lower(s->txdrq);
3076 omap_mcbsp_intr_update(s);
3077 if (s->codec && s->codec->cts)
3078 s->codec->tx_swallow(s->codec->opaque);
3079}
3080
3081static void omap_mcbsp_tx_stop(struct omap_mcbsp_s *s)
3082{
3083 s->tx_req = 0;
3084 omap_mcbsp_tx_done(s);
3085 qemu_del_timer(s->sink_timer);
3086}
3087
3088static void omap_mcbsp_req_update(struct omap_mcbsp_s *s)
3089{
3090 int prev_rx_rate, prev_tx_rate;
3091 int rx_rate = 0, tx_rate = 0;
3092 int cpu_rate = 1500000;
3093
3094
3095 if (s->spcr[1] & (1 << 6)) {
3096 if (s->spcr[0] & (1 << 0)) {
3097 if ((s->srgr[1] & (1 << 13)) &&
3098 (s->pcr & (1 << 8))) {
3099 if (~s->pcr & (1 << 7))
3100 rx_rate = cpu_rate /
3101 ((s->srgr[0] & 0xff) + 1);
3102 } else
3103 if (s->codec)
3104 rx_rate = s->codec->rx_rate;
3105 }
3106
3107 if (s->spcr[1] & (1 << 0)) {
3108 if ((s->srgr[1] & (1 << 13)) &&
3109 (s->pcr & (1 << 9))) {
3110 if (~s->pcr & (1 << 7))
3111 tx_rate = cpu_rate /
3112 ((s->srgr[0] & 0xff) + 1);
3113 } else
3114 if (s->codec)
3115 tx_rate = s->codec->tx_rate;
3116 }
3117 }
3118 prev_tx_rate = s->tx_rate;
3119 prev_rx_rate = s->rx_rate;
3120 s->tx_rate = tx_rate;
3121 s->rx_rate = rx_rate;
3122
3123 if (s->codec)
3124 s->codec->set_rate(s->codec->opaque, rx_rate, tx_rate);
3125
3126 if (!prev_tx_rate && tx_rate)
3127 omap_mcbsp_tx_start(s);
3128 else if (s->tx_rate && !tx_rate)
3129 omap_mcbsp_tx_stop(s);
3130
3131 if (!prev_rx_rate && rx_rate)
3132 omap_mcbsp_rx_start(s);
3133 else if (prev_tx_rate && !tx_rate)
3134 omap_mcbsp_rx_stop(s);
3135}
3136
3137static uint64_t omap_mcbsp_read(void *opaque, hwaddr addr,
3138 unsigned size)
3139{
3140 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
3141 int offset = addr & OMAP_MPUI_REG_MASK;
3142 uint16_t ret;
3143
3144 if (size != 2) {
3145 return omap_badwidth_read16(opaque, addr);
3146 }
3147
3148 switch (offset) {
3149 case 0x00:
3150 if (((s->rcr[0] >> 5) & 7) < 3)
3151 return 0x0000;
3152
3153 case 0x02:
3154 if (s->rx_req < 2) {
3155 printf("%s: Rx FIFO underrun\n", __FUNCTION__);
3156 omap_mcbsp_rx_done(s);
3157 } else {
3158 s->tx_req -= 2;
3159 if (s->codec && s->codec->in.len >= 2) {
3160 ret = s->codec->in.fifo[s->codec->in.start ++] << 8;
3161 ret |= s->codec->in.fifo[s->codec->in.start ++];
3162 s->codec->in.len -= 2;
3163 } else
3164 ret = 0x0000;
3165 if (!s->tx_req)
3166 omap_mcbsp_rx_done(s);
3167 return ret;
3168 }
3169 return 0x0000;
3170
3171 case 0x04:
3172 case 0x06:
3173 return 0x0000;
3174
3175 case 0x08:
3176 return s->spcr[1];
3177 case 0x0a:
3178 return s->spcr[0];
3179 case 0x0c:
3180 return s->rcr[1];
3181 case 0x0e:
3182 return s->rcr[0];
3183 case 0x10:
3184 return s->xcr[1];
3185 case 0x12:
3186 return s->xcr[0];
3187 case 0x14:
3188 return s->srgr[1];
3189 case 0x16:
3190 return s->srgr[0];
3191 case 0x18:
3192 return s->mcr[1];
3193 case 0x1a:
3194 return s->mcr[0];
3195 case 0x1c:
3196 return s->rcer[0];
3197 case 0x1e:
3198 return s->rcer[1];
3199 case 0x20:
3200 return s->xcer[0];
3201 case 0x22:
3202 return s->xcer[1];
3203 case 0x24:
3204 return s->pcr;
3205 case 0x26:
3206 return s->rcer[2];
3207 case 0x28:
3208 return s->rcer[3];
3209 case 0x2a:
3210 return s->xcer[2];
3211 case 0x2c:
3212 return s->xcer[3];
3213 case 0x2e:
3214 return s->rcer[4];
3215 case 0x30:
3216 return s->rcer[5];
3217 case 0x32:
3218 return s->xcer[4];
3219 case 0x34:
3220 return s->xcer[5];
3221 case 0x36:
3222 return s->rcer[6];
3223 case 0x38:
3224 return s->rcer[7];
3225 case 0x3a:
3226 return s->xcer[6];
3227 case 0x3c:
3228 return s->xcer[7];
3229 }
3230
3231 OMAP_BAD_REG(addr);
3232 return 0;
3233}
3234
3235static void omap_mcbsp_writeh(void *opaque, hwaddr addr,
3236 uint32_t value)
3237{
3238 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
3239 int offset = addr & OMAP_MPUI_REG_MASK;
3240
3241 switch (offset) {
3242 case 0x00:
3243 case 0x02:
3244 OMAP_RO_REG(addr);
3245 return;
3246
3247 case 0x04:
3248 if (((s->xcr[0] >> 5) & 7) < 3)
3249 return;
3250
3251 case 0x06:
3252 if (s->tx_req > 1) {
3253 s->tx_req -= 2;
3254 if (s->codec && s->codec->cts) {
3255 s->codec->out.fifo[s->codec->out.len ++] = (value >> 8) & 0xff;
3256 s->codec->out.fifo[s->codec->out.len ++] = (value >> 0) & 0xff;
3257 }
3258 if (s->tx_req < 2)
3259 omap_mcbsp_tx_done(s);
3260 } else
3261 printf("%s: Tx FIFO overrun\n", __FUNCTION__);
3262 return;
3263
3264 case 0x08:
3265 s->spcr[1] &= 0x0002;
3266 s->spcr[1] |= 0x03f9 & value;
3267 s->spcr[1] |= 0x0004 & (value << 2);
3268 if (~value & 1)
3269 s->spcr[1] &= ~6;
3270 omap_mcbsp_req_update(s);
3271 return;
3272 case 0x0a:
3273 s->spcr[0] &= 0x0006;
3274 s->spcr[0] |= 0xf8f9 & value;
3275 if (value & (1 << 15))
3276 printf("%s: Digital Loopback mode enable attempt\n", __FUNCTION__);
3277 if (~value & 1) {
3278 s->spcr[0] &= ~6;
3279 s->rx_req = 0;
3280 omap_mcbsp_rx_done(s);
3281 }
3282 omap_mcbsp_req_update(s);
3283 return;
3284
3285 case 0x0c:
3286 s->rcr[1] = value & 0xffff;
3287 return;
3288 case 0x0e:
3289 s->rcr[0] = value & 0x7fe0;
3290 return;
3291 case 0x10:
3292 s->xcr[1] = value & 0xffff;
3293 return;
3294 case 0x12:
3295 s->xcr[0] = value & 0x7fe0;
3296 return;
3297 case 0x14:
3298 s->srgr[1] = value & 0xffff;
3299 omap_mcbsp_req_update(s);
3300 return;
3301 case 0x16:
3302 s->srgr[0] = value & 0xffff;
3303 omap_mcbsp_req_update(s);
3304 return;
3305 case 0x18:
3306 s->mcr[1] = value & 0x03e3;
3307 if (value & 3)
3308 printf("%s: Tx channel selection mode enable attempt\n",
3309 __FUNCTION__);
3310 return;
3311 case 0x1a:
3312 s->mcr[0] = value & 0x03e1;
3313 if (value & 1)
3314 printf("%s: Rx channel selection mode enable attempt\n",
3315 __FUNCTION__);
3316 return;
3317 case 0x1c:
3318 s->rcer[0] = value & 0xffff;
3319 return;
3320 case 0x1e:
3321 s->rcer[1] = value & 0xffff;
3322 return;
3323 case 0x20:
3324 s->xcer[0] = value & 0xffff;
3325 return;
3326 case 0x22:
3327 s->xcer[1] = value & 0xffff;
3328 return;
3329 case 0x24:
3330 s->pcr = value & 0x7faf;
3331 return;
3332 case 0x26:
3333 s->rcer[2] = value & 0xffff;
3334 return;
3335 case 0x28:
3336 s->rcer[3] = value & 0xffff;
3337 return;
3338 case 0x2a:
3339 s->xcer[2] = value & 0xffff;
3340 return;
3341 case 0x2c:
3342 s->xcer[3] = value & 0xffff;
3343 return;
3344 case 0x2e:
3345 s->rcer[4] = value & 0xffff;
3346 return;
3347 case 0x30:
3348 s->rcer[5] = value & 0xffff;
3349 return;
3350 case 0x32:
3351 s->xcer[4] = value & 0xffff;
3352 return;
3353 case 0x34:
3354 s->xcer[5] = value & 0xffff;
3355 return;
3356 case 0x36:
3357 s->rcer[6] = value & 0xffff;
3358 return;
3359 case 0x38:
3360 s->rcer[7] = value & 0xffff;
3361 return;
3362 case 0x3a:
3363 s->xcer[6] = value & 0xffff;
3364 return;
3365 case 0x3c:
3366 s->xcer[7] = value & 0xffff;
3367 return;
3368 }
3369
3370 OMAP_BAD_REG(addr);
3371}
3372
3373static void omap_mcbsp_writew(void *opaque, hwaddr addr,
3374 uint32_t value)
3375{
3376 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
3377 int offset = addr & OMAP_MPUI_REG_MASK;
3378
3379 if (offset == 0x04) {
3380 if (((s->xcr[0] >> 5) & 7) < 3)
3381 return;
3382 if (s->tx_req > 3) {
3383 s->tx_req -= 4;
3384 if (s->codec && s->codec->cts) {
3385 s->codec->out.fifo[s->codec->out.len ++] =
3386 (value >> 24) & 0xff;
3387 s->codec->out.fifo[s->codec->out.len ++] =
3388 (value >> 16) & 0xff;
3389 s->codec->out.fifo[s->codec->out.len ++] =
3390 (value >> 8) & 0xff;
3391 s->codec->out.fifo[s->codec->out.len ++] =
3392 (value >> 0) & 0xff;
3393 }
3394 if (s->tx_req < 4)
3395 omap_mcbsp_tx_done(s);
3396 } else
3397 printf("%s: Tx FIFO overrun\n", __FUNCTION__);
3398 return;
3399 }
3400
3401 omap_badwidth_write16(opaque, addr, value);
3402}
3403
3404static void omap_mcbsp_write(void *opaque, hwaddr addr,
3405 uint64_t value, unsigned size)
3406{
3407 switch (size) {
3408 case 2: return omap_mcbsp_writeh(opaque, addr, value);
3409 case 4: return omap_mcbsp_writew(opaque, addr, value);
3410 default: return omap_badwidth_write16(opaque, addr, value);
3411 }
3412}
3413
3414static const MemoryRegionOps omap_mcbsp_ops = {
3415 .read = omap_mcbsp_read,
3416 .write = omap_mcbsp_write,
3417 .endianness = DEVICE_NATIVE_ENDIAN,
3418};
3419
3420static void omap_mcbsp_reset(struct omap_mcbsp_s *s)
3421{
3422 memset(&s->spcr, 0, sizeof(s->spcr));
3423 memset(&s->rcr, 0, sizeof(s->rcr));
3424 memset(&s->xcr, 0, sizeof(s->xcr));
3425 s->srgr[0] = 0x0001;
3426 s->srgr[1] = 0x2000;
3427 memset(&s->mcr, 0, sizeof(s->mcr));
3428 memset(&s->pcr, 0, sizeof(s->pcr));
3429 memset(&s->rcer, 0, sizeof(s->rcer));
3430 memset(&s->xcer, 0, sizeof(s->xcer));
3431 s->tx_req = 0;
3432 s->rx_req = 0;
3433 s->tx_rate = 0;
3434 s->rx_rate = 0;
3435 qemu_del_timer(s->source_timer);
3436 qemu_del_timer(s->sink_timer);
3437}
3438
3439static struct omap_mcbsp_s *omap_mcbsp_init(MemoryRegion *system_memory,
3440 hwaddr base,
3441 qemu_irq txirq, qemu_irq rxirq,
3442 qemu_irq *dma, omap_clk clk)
3443{
3444 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *)
3445 g_malloc0(sizeof(struct omap_mcbsp_s));
3446
3447 s->txirq = txirq;
3448 s->rxirq = rxirq;
3449 s->txdrq = dma[0];
3450 s->rxdrq = dma[1];
3451 s->sink_timer = qemu_new_timer_ns(vm_clock, omap_mcbsp_sink_tick, s);
3452 s->source_timer = qemu_new_timer_ns(vm_clock, omap_mcbsp_source_tick, s);
3453 omap_mcbsp_reset(s);
3454
3455 memory_region_init_io(&s->iomem, &omap_mcbsp_ops, s, "omap-mcbsp", 0x800);
3456 memory_region_add_subregion(system_memory, base, &s->iomem);
3457
3458 return s;
3459}
3460
3461static void omap_mcbsp_i2s_swallow(void *opaque, int line, int level)
3462{
3463 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
3464
3465 if (s->rx_rate) {
3466 s->rx_req = s->codec->in.len;
3467 omap_mcbsp_rx_newdata(s);
3468 }
3469}
3470
3471static void omap_mcbsp_i2s_start(void *opaque, int line, int level)
3472{
3473 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
3474
3475 if (s->tx_rate) {
3476 s->tx_req = s->codec->out.size;
3477 omap_mcbsp_tx_newdata(s);
3478 }
3479}
3480
3481void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, I2SCodec *slave)
3482{
3483 s->codec = slave;
3484 slave->rx_swallow = qemu_allocate_irqs(omap_mcbsp_i2s_swallow, s, 1)[0];
3485 slave->tx_start = qemu_allocate_irqs(omap_mcbsp_i2s_start, s, 1)[0];
3486}
3487
3488
3489struct omap_lpg_s {
3490 MemoryRegion iomem;
3491 QEMUTimer *tm;
3492
3493 uint8_t control;
3494 uint8_t power;
3495 int64_t on;
3496 int64_t period;
3497 int clk;
3498 int cycle;
3499};
3500
3501static void omap_lpg_tick(void *opaque)
3502{
3503 struct omap_lpg_s *s = opaque;
3504
3505 if (s->cycle)
3506 qemu_mod_timer(s->tm, qemu_get_clock_ms(vm_clock) + s->period - s->on);
3507 else
3508 qemu_mod_timer(s->tm, qemu_get_clock_ms(vm_clock) + s->on);
3509
3510 s->cycle = !s->cycle;
3511 printf("%s: LED is %s\n", __FUNCTION__, s->cycle ? "on" : "off");
3512}
3513
3514static void omap_lpg_update(struct omap_lpg_s *s)
3515{
3516 int64_t on, period = 1, ticks = 1000;
3517 static const int per[8] = { 1, 2, 4, 8, 12, 16, 20, 24 };
3518
3519 if (~s->control & (1 << 6))
3520 on = 0;
3521 else if (s->control & (1 << 7))
3522 on = period;
3523 else {
3524 period = muldiv64(ticks, per[s->control & 7],
3525 256 / 32);
3526 on = (s->clk && s->power) ? muldiv64(ticks,
3527 per[(s->control >> 3) & 7], 256) : 0;
3528 }
3529
3530 qemu_del_timer(s->tm);
3531 if (on == period && s->on < s->period)
3532 printf("%s: LED is on\n", __FUNCTION__);
3533 else if (on == 0 && s->on)
3534 printf("%s: LED is off\n", __FUNCTION__);
3535 else if (on && (on != s->on || period != s->period)) {
3536 s->cycle = 0;
3537 s->on = on;
3538 s->period = period;
3539 omap_lpg_tick(s);
3540 return;
3541 }
3542
3543 s->on = on;
3544 s->period = period;
3545}
3546
3547static void omap_lpg_reset(struct omap_lpg_s *s)
3548{
3549 s->control = 0x00;
3550 s->power = 0x00;
3551 s->clk = 1;
3552 omap_lpg_update(s);
3553}
3554
3555static uint64_t omap_lpg_read(void *opaque, hwaddr addr,
3556 unsigned size)
3557{
3558 struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
3559 int offset = addr & OMAP_MPUI_REG_MASK;
3560
3561 if (size != 1) {
3562 return omap_badwidth_read8(opaque, addr);
3563 }
3564
3565 switch (offset) {
3566 case 0x00:
3567 return s->control;
3568
3569 case 0x04:
3570 return s->power;
3571 }
3572
3573 OMAP_BAD_REG(addr);
3574 return 0;
3575}
3576
3577static void omap_lpg_write(void *opaque, hwaddr addr,
3578 uint64_t value, unsigned size)
3579{
3580 struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
3581 int offset = addr & OMAP_MPUI_REG_MASK;
3582
3583 if (size != 1) {
3584 return omap_badwidth_write8(opaque, addr, value);
3585 }
3586
3587 switch (offset) {
3588 case 0x00:
3589 if (~value & (1 << 6))
3590 omap_lpg_reset(s);
3591 s->control = value & 0xff;
3592 omap_lpg_update(s);
3593 return;
3594
3595 case 0x04:
3596 s->power = value & 0x01;
3597 omap_lpg_update(s);
3598 return;
3599
3600 default:
3601 OMAP_BAD_REG(addr);
3602 return;
3603 }
3604}
3605
3606static const MemoryRegionOps omap_lpg_ops = {
3607 .read = omap_lpg_read,
3608 .write = omap_lpg_write,
3609 .endianness = DEVICE_NATIVE_ENDIAN,
3610};
3611
3612static void omap_lpg_clk_update(void *opaque, int line, int on)
3613{
3614 struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
3615
3616 s->clk = on;
3617 omap_lpg_update(s);
3618}
3619
3620static struct omap_lpg_s *omap_lpg_init(MemoryRegion *system_memory,
3621 hwaddr base, omap_clk clk)
3622{
3623 struct omap_lpg_s *s = (struct omap_lpg_s *)
3624 g_malloc0(sizeof(struct omap_lpg_s));
3625
3626 s->tm = qemu_new_timer_ms(vm_clock, omap_lpg_tick, s);
3627
3628 omap_lpg_reset(s);
3629
3630 memory_region_init_io(&s->iomem, &omap_lpg_ops, s, "omap-lpg", 0x800);
3631 memory_region_add_subregion(system_memory, base, &s->iomem);
3632
3633 omap_clk_adduser(clk, qemu_allocate_irqs(omap_lpg_clk_update, s, 1)[0]);
3634
3635 return s;
3636}
3637
3638
3639static uint64_t omap_mpui_io_read(void *opaque, hwaddr addr,
3640 unsigned size)
3641{
3642 if (size != 2) {
3643 return omap_badwidth_read16(opaque, addr);
3644 }
3645
3646 if (addr == OMAP_MPUI_BASE)
3647 return 0xfe4d;
3648
3649 OMAP_BAD_REG(addr);
3650 return 0;
3651}
3652
3653static void omap_mpui_io_write(void *opaque, hwaddr addr,
3654 uint64_t value, unsigned size)
3655{
3656
3657 omap_badwidth_write16(opaque, addr, value);
3658}
3659
3660static const MemoryRegionOps omap_mpui_io_ops = {
3661 .read = omap_mpui_io_read,
3662 .write = omap_mpui_io_write,
3663 .endianness = DEVICE_NATIVE_ENDIAN,
3664};
3665
3666static void omap_setup_mpui_io(MemoryRegion *system_memory,
3667 struct omap_mpu_state_s *mpu)
3668{
3669 memory_region_init_io(&mpu->mpui_io_iomem, &omap_mpui_io_ops, mpu,
3670 "omap-mpui-io", 0x7fff);
3671 memory_region_add_subregion(system_memory, OMAP_MPUI_BASE,
3672 &mpu->mpui_io_iomem);
3673}
3674
3675
3676static void omap1_mpu_reset(void *opaque)
3677{
3678 struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
3679
3680 omap_dma_reset(mpu->dma);
3681 omap_mpu_timer_reset(mpu->timer[0]);
3682 omap_mpu_timer_reset(mpu->timer[1]);
3683 omap_mpu_timer_reset(mpu->timer[2]);
3684 omap_wd_timer_reset(mpu->wdt);
3685 omap_os_timer_reset(mpu->os_timer);
3686 omap_lcdc_reset(mpu->lcd);
3687 omap_ulpd_pm_reset(mpu);
3688 omap_pin_cfg_reset(mpu);
3689 omap_mpui_reset(mpu);
3690 omap_tipb_bridge_reset(mpu->private_tipb);
3691 omap_tipb_bridge_reset(mpu->public_tipb);
3692 omap_dpll_reset(mpu->dpll[0]);
3693 omap_dpll_reset(mpu->dpll[1]);
3694 omap_dpll_reset(mpu->dpll[2]);
3695 omap_uart_reset(mpu->uart[0]);
3696 omap_uart_reset(mpu->uart[1]);
3697 omap_uart_reset(mpu->uart[2]);
3698 omap_mmc_reset(mpu->mmc);
3699 omap_mpuio_reset(mpu->mpuio);
3700 omap_uwire_reset(mpu->microwire);
3701 omap_pwl_reset(mpu->pwl);
3702 omap_pwt_reset(mpu->pwt);
3703 omap_rtc_reset(mpu->rtc);
3704 omap_mcbsp_reset(mpu->mcbsp1);
3705 omap_mcbsp_reset(mpu->mcbsp2);
3706 omap_mcbsp_reset(mpu->mcbsp3);
3707 omap_lpg_reset(mpu->led[0]);
3708 omap_lpg_reset(mpu->led[1]);
3709 omap_clkm_reset(mpu);
3710 cpu_reset(CPU(mpu->cpu));
3711}
3712
3713static const struct omap_map_s {
3714 hwaddr phys_dsp;
3715 hwaddr phys_mpu;
3716 uint32_t size;
3717 const char *name;
3718} omap15xx_dsp_mm[] = {
3719
3720 { 0xe1010000, 0xfffb0000, 0x800, "UART1 BT" },
3721 { 0xe1010800, 0xfffb0800, 0x800, "UART2 COM" },
3722 { 0xe1011800, 0xfffb1800, 0x800, "McBSP1 audio" },
3723 { 0xe1012000, 0xfffb2000, 0x800, "MCSI2 communication" },
3724 { 0xe1012800, 0xfffb2800, 0x800, "MCSI1 BT u-Law" },
3725 { 0xe1013000, 0xfffb3000, 0x800, "uWire" },
3726 { 0xe1013800, 0xfffb3800, 0x800, "I^2C" },
3727 { 0xe1014000, 0xfffb4000, 0x800, "USB W2FC" },
3728 { 0xe1014800, 0xfffb4800, 0x800, "RTC" },
3729 { 0xe1015000, 0xfffb5000, 0x800, "MPUIO" },
3730 { 0xe1015800, 0xfffb5800, 0x800, "PWL" },
3731 { 0xe1016000, 0xfffb6000, 0x800, "PWT" },
3732 { 0xe1017000, 0xfffb7000, 0x800, "McBSP3" },
3733 { 0xe1017800, 0xfffb7800, 0x800, "MMC" },
3734 { 0xe1019000, 0xfffb9000, 0x800, "32-kHz timer" },
3735 { 0xe1019800, 0xfffb9800, 0x800, "UART3" },
3736 { 0xe101c800, 0xfffbc800, 0x800, "TIPB switches" },
3737
3738 { 0xe101e000, 0xfffce000, 0x800, "GPIOs" },
3739
3740 { 0 }
3741};
3742
3743static void omap_setup_dsp_mapping(MemoryRegion *system_memory,
3744 const struct omap_map_s *map)
3745{
3746 MemoryRegion *io;
3747
3748 for (; map->phys_dsp; map ++) {
3749 io = g_new(MemoryRegion, 1);
3750 memory_region_init_alias(io, map->name,
3751 system_memory, map->phys_mpu, map->size);
3752 memory_region_add_subregion(system_memory, map->phys_dsp, io);
3753 }
3754}
3755
3756void omap_mpu_wakeup(void *opaque, int irq, int req)
3757{
3758 struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
3759 CPUState *cpu = CPU(mpu->cpu);
3760
3761 if (cpu->halted) {
3762 cpu_interrupt(cpu, CPU_INTERRUPT_EXITTB);
3763 }
3764}
3765
3766static const struct dma_irq_map omap1_dma_irq_map[] = {
3767 { 0, OMAP_INT_DMA_CH0_6 },
3768 { 0, OMAP_INT_DMA_CH1_7 },
3769 { 0, OMAP_INT_DMA_CH2_8 },
3770 { 0, OMAP_INT_DMA_CH3 },
3771 { 0, OMAP_INT_DMA_CH4 },
3772 { 0, OMAP_INT_DMA_CH5 },
3773 { 1, OMAP_INT_1610_DMA_CH6 },
3774 { 1, OMAP_INT_1610_DMA_CH7 },
3775 { 1, OMAP_INT_1610_DMA_CH8 },
3776 { 1, OMAP_INT_1610_DMA_CH9 },
3777 { 1, OMAP_INT_1610_DMA_CH10 },
3778 { 1, OMAP_INT_1610_DMA_CH11 },
3779 { 1, OMAP_INT_1610_DMA_CH12 },
3780 { 1, OMAP_INT_1610_DMA_CH13 },
3781 { 1, OMAP_INT_1610_DMA_CH14 },
3782 { 1, OMAP_INT_1610_DMA_CH15 }
3783};
3784
3785
3786static int omap_validate_emiff_addr(struct omap_mpu_state_s *s,
3787 hwaddr addr)
3788{
3789 return range_covers_byte(OMAP_EMIFF_BASE, s->sdram_size, addr);
3790}
3791
3792static int omap_validate_emifs_addr(struct omap_mpu_state_s *s,
3793 hwaddr addr)
3794{
3795 return range_covers_byte(OMAP_EMIFS_BASE, OMAP_EMIFF_BASE - OMAP_EMIFS_BASE,
3796 addr);
3797}
3798
3799static int omap_validate_imif_addr(struct omap_mpu_state_s *s,
3800 hwaddr addr)
3801{
3802 return range_covers_byte(OMAP_IMIF_BASE, s->sram_size, addr);
3803}
3804
3805static int omap_validate_tipb_addr(struct omap_mpu_state_s *s,
3806 hwaddr addr)
3807{
3808 return range_covers_byte(0xfffb0000, 0xffff0000 - 0xfffb0000, addr);
3809}
3810
3811static int omap_validate_local_addr(struct omap_mpu_state_s *s,
3812 hwaddr addr)
3813{
3814 return range_covers_byte(OMAP_LOCALBUS_BASE, 0x1000000, addr);
3815}
3816
3817static int omap_validate_tipb_mpui_addr(struct omap_mpu_state_s *s,
3818 hwaddr addr)
3819{
3820 return range_covers_byte(0xe1010000, 0xe1020004 - 0xe1010000, addr);
3821}
3822
3823struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
3824 unsigned long sdram_size,
3825 const char *core)
3826{
3827 int i;
3828 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
3829 g_malloc0(sizeof(struct omap_mpu_state_s));
3830 qemu_irq *cpu_irq;
3831 qemu_irq dma_irqs[6];
3832 DriveInfo *dinfo;
3833 SysBusDevice *busdev;
3834
3835 if (!core)
3836 core = "ti925t";
3837
3838
3839 s->mpu_model = omap310;
3840 s->cpu = cpu_arm_init(core);
3841 if (s->cpu == NULL) {
3842 fprintf(stderr, "Unable to find CPU definition\n");
3843 exit(1);
3844 }
3845 s->sdram_size = sdram_size;
3846 s->sram_size = OMAP15XX_SRAM_SIZE;
3847
3848 s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
3849
3850
3851 omap_clk_init(s);
3852
3853
3854 memory_region_init_ram(&s->emiff_ram, "omap1.dram", s->sdram_size);
3855 vmstate_register_ram_global(&s->emiff_ram);
3856 memory_region_add_subregion(system_memory, OMAP_EMIFF_BASE, &s->emiff_ram);
3857 memory_region_init_ram(&s->imif_ram, "omap1.sram", s->sram_size);
3858 vmstate_register_ram_global(&s->imif_ram);
3859 memory_region_add_subregion(system_memory, OMAP_IMIF_BASE, &s->imif_ram);
3860
3861 omap_clkm_init(system_memory, 0xfffece00, 0xe1008000, s);
3862
3863 cpu_irq = arm_pic_init_cpu(s->cpu);
3864 s->ih[0] = qdev_create(NULL, "omap-intc");
3865 qdev_prop_set_uint32(s->ih[0], "size", 0x100);
3866 qdev_prop_set_ptr(s->ih[0], "clk", omap_findclk(s, "arminth_ck"));
3867 qdev_init_nofail(s->ih[0]);
3868 busdev = SYS_BUS_DEVICE(s->ih[0]);
3869 sysbus_connect_irq(busdev, 0, cpu_irq[ARM_PIC_CPU_IRQ]);
3870 sysbus_connect_irq(busdev, 1, cpu_irq[ARM_PIC_CPU_FIQ]);
3871 sysbus_mmio_map(busdev, 0, 0xfffecb00);
3872 s->ih[1] = qdev_create(NULL, "omap-intc");
3873 qdev_prop_set_uint32(s->ih[1], "size", 0x800);
3874 qdev_prop_set_ptr(s->ih[1], "clk", omap_findclk(s, "arminth_ck"));
3875 qdev_init_nofail(s->ih[1]);
3876 busdev = SYS_BUS_DEVICE(s->ih[1]);
3877 sysbus_connect_irq(busdev, 0,
3878 qdev_get_gpio_in(s->ih[0], OMAP_INT_15XX_IH2_IRQ));
3879
3880 sysbus_mmio_map(busdev, 0, 0xfffe0000);
3881
3882 for (i = 0; i < 6; i++) {
3883 dma_irqs[i] = qdev_get_gpio_in(s->ih[omap1_dma_irq_map[i].ih],
3884 omap1_dma_irq_map[i].intr);
3885 }
3886 s->dma = omap_dma_init(0xfffed800, dma_irqs, system_memory,
3887 qdev_get_gpio_in(s->ih[0], OMAP_INT_DMA_LCD),
3888 s, omap_findclk(s, "dma_ck"), omap_dma_3_1);
3889
3890 s->port[emiff ].addr_valid = omap_validate_emiff_addr;
3891 s->port[emifs ].addr_valid = omap_validate_emifs_addr;
3892 s->port[imif ].addr_valid = omap_validate_imif_addr;
3893 s->port[tipb ].addr_valid = omap_validate_tipb_addr;
3894 s->port[local ].addr_valid = omap_validate_local_addr;
3895 s->port[tipb_mpui].addr_valid = omap_validate_tipb_mpui_addr;
3896
3897
3898 soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->emiff_ram),
3899 OMAP_EMIFF_BASE, s->sdram_size);
3900 soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->imif_ram),
3901 OMAP_IMIF_BASE, s->sram_size);
3902
3903 s->timer[0] = omap_mpu_timer_init(system_memory, 0xfffec500,
3904 qdev_get_gpio_in(s->ih[0], OMAP_INT_TIMER1),
3905 omap_findclk(s, "mputim_ck"));
3906 s->timer[1] = omap_mpu_timer_init(system_memory, 0xfffec600,
3907 qdev_get_gpio_in(s->ih[0], OMAP_INT_TIMER2),
3908 omap_findclk(s, "mputim_ck"));
3909 s->timer[2] = omap_mpu_timer_init(system_memory, 0xfffec700,
3910 qdev_get_gpio_in(s->ih[0], OMAP_INT_TIMER3),
3911 omap_findclk(s, "mputim_ck"));
3912
3913 s->wdt = omap_wd_timer_init(system_memory, 0xfffec800,
3914 qdev_get_gpio_in(s->ih[0], OMAP_INT_WD_TIMER),
3915 omap_findclk(s, "armwdt_ck"));
3916
3917 s->os_timer = omap_os_timer_init(system_memory, 0xfffb9000,
3918 qdev_get_gpio_in(s->ih[1], OMAP_INT_OS_TIMER),
3919 omap_findclk(s, "clk32-kHz"));
3920
3921 s->lcd = omap_lcdc_init(system_memory, 0xfffec000,
3922 qdev_get_gpio_in(s->ih[0], OMAP_INT_LCD_CTRL),
3923 omap_dma_get_lcdch(s->dma),
3924 omap_findclk(s, "lcd_ck"));
3925
3926 omap_ulpd_pm_init(system_memory, 0xfffe0800, s);
3927 omap_pin_cfg_init(system_memory, 0xfffe1000, s);
3928 omap_id_init(system_memory, s);
3929
3930 omap_mpui_init(system_memory, 0xfffec900, s);
3931
3932 s->private_tipb = omap_tipb_bridge_init(system_memory, 0xfffeca00,
3933 qdev_get_gpio_in(s->ih[0], OMAP_INT_BRIDGE_PRIV),
3934 omap_findclk(s, "tipb_ck"));
3935 s->public_tipb = omap_tipb_bridge_init(system_memory, 0xfffed300,
3936 qdev_get_gpio_in(s->ih[0], OMAP_INT_BRIDGE_PUB),
3937 omap_findclk(s, "tipb_ck"));
3938
3939 omap_tcmi_init(system_memory, 0xfffecc00, s);
3940
3941 s->uart[0] = omap_uart_init(0xfffb0000,
3942 qdev_get_gpio_in(s->ih[1], OMAP_INT_UART1),
3943 omap_findclk(s, "uart1_ck"),
3944 omap_findclk(s, "uart1_ck"),
3945 s->drq[OMAP_DMA_UART1_TX], s->drq[OMAP_DMA_UART1_RX],
3946 "uart1",
3947 serial_hds[0]);
3948 s->uart[1] = omap_uart_init(0xfffb0800,
3949 qdev_get_gpio_in(s->ih[1], OMAP_INT_UART2),
3950 omap_findclk(s, "uart2_ck"),
3951 omap_findclk(s, "uart2_ck"),
3952 s->drq[OMAP_DMA_UART2_TX], s->drq[OMAP_DMA_UART2_RX],
3953 "uart2",
3954 serial_hds[0] ? serial_hds[1] : NULL);
3955 s->uart[2] = omap_uart_init(0xfffb9800,
3956 qdev_get_gpio_in(s->ih[0], OMAP_INT_UART3),
3957 omap_findclk(s, "uart3_ck"),
3958 omap_findclk(s, "uart3_ck"),
3959 s->drq[OMAP_DMA_UART3_TX], s->drq[OMAP_DMA_UART3_RX],
3960 "uart3",
3961 serial_hds[0] && serial_hds[1] ? serial_hds[2] : NULL);
3962
3963 s->dpll[0] = omap_dpll_init(system_memory, 0xfffecf00,
3964 omap_findclk(s, "dpll1"));
3965 s->dpll[1] = omap_dpll_init(system_memory, 0xfffed000,
3966 omap_findclk(s, "dpll2"));
3967 s->dpll[2] = omap_dpll_init(system_memory, 0xfffed100,
3968 omap_findclk(s, "dpll3"));
3969
3970 dinfo = drive_get(IF_SD, 0, 0);
3971 if (!dinfo) {
3972 fprintf(stderr, "qemu: missing SecureDigital device\n");
3973 exit(1);
3974 }
3975 s->mmc = omap_mmc_init(0xfffb7800, system_memory, dinfo->bdrv,
3976 qdev_get_gpio_in(s->ih[1], OMAP_INT_OQN),
3977 &s->drq[OMAP_DMA_MMC_TX],
3978 omap_findclk(s, "mmc_ck"));
3979
3980 s->mpuio = omap_mpuio_init(system_memory, 0xfffb5000,
3981 qdev_get_gpio_in(s->ih[1], OMAP_INT_KEYBOARD),
3982 qdev_get_gpio_in(s->ih[1], OMAP_INT_MPUIO),
3983 s->wakeup, omap_findclk(s, "clk32-kHz"));
3984
3985 s->gpio = qdev_create(NULL, "omap-gpio");
3986 qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
3987 qdev_prop_set_ptr(s->gpio, "clk", omap_findclk(s, "arm_gpio_ck"));
3988 qdev_init_nofail(s->gpio);
3989 sysbus_connect_irq(SYS_BUS_DEVICE(s->gpio), 0,
3990 qdev_get_gpio_in(s->ih[0], OMAP_INT_GPIO_BANK1));
3991 sysbus_mmio_map(SYS_BUS_DEVICE(s->gpio), 0, 0xfffce000);
3992
3993 s->microwire = omap_uwire_init(system_memory, 0xfffb3000,
3994 qdev_get_gpio_in(s->ih[1], OMAP_INT_uWireTX),
3995 qdev_get_gpio_in(s->ih[1], OMAP_INT_uWireRX),
3996 s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck"));
3997
3998 s->pwl = omap_pwl_init(system_memory, 0xfffb5800,
3999 omap_findclk(s, "armxor_ck"));
4000 s->pwt = omap_pwt_init(system_memory, 0xfffb6000,
4001 omap_findclk(s, "armxor_ck"));
4002
4003 s->i2c[0] = qdev_create(NULL, "omap_i2c");
4004 qdev_prop_set_uint8(s->i2c[0], "revision", 0x11);
4005 qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "mpuper_ck"));
4006 qdev_init_nofail(s->i2c[0]);
4007 busdev = SYS_BUS_DEVICE(s->i2c[0]);
4008 sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(s->ih[1], OMAP_INT_I2C));
4009 sysbus_connect_irq(busdev, 1, s->drq[OMAP_DMA_I2C_TX]);
4010 sysbus_connect_irq(busdev, 2, s->drq[OMAP_DMA_I2C_RX]);
4011 sysbus_mmio_map(busdev, 0, 0xfffb3800);
4012
4013 s->rtc = omap_rtc_init(system_memory, 0xfffb4800,
4014 qdev_get_gpio_in(s->ih[1], OMAP_INT_RTC_TIMER),
4015 qdev_get_gpio_in(s->ih[1], OMAP_INT_RTC_ALARM),
4016 omap_findclk(s, "clk32-kHz"));
4017
4018 s->mcbsp1 = omap_mcbsp_init(system_memory, 0xfffb1800,
4019 qdev_get_gpio_in(s->ih[1], OMAP_INT_McBSP1TX),
4020 qdev_get_gpio_in(s->ih[1], OMAP_INT_McBSP1RX),
4021 &s->drq[OMAP_DMA_MCBSP1_TX], omap_findclk(s, "dspxor_ck"));
4022 s->mcbsp2 = omap_mcbsp_init(system_memory, 0xfffb1000,
4023 qdev_get_gpio_in(s->ih[0],
4024 OMAP_INT_310_McBSP2_TX),
4025 qdev_get_gpio_in(s->ih[0],
4026 OMAP_INT_310_McBSP2_RX),
4027 &s->drq[OMAP_DMA_MCBSP2_TX], omap_findclk(s, "mpuper_ck"));
4028 s->mcbsp3 = omap_mcbsp_init(system_memory, 0xfffb7000,
4029 qdev_get_gpio_in(s->ih[1], OMAP_INT_McBSP3TX),
4030 qdev_get_gpio_in(s->ih[1], OMAP_INT_McBSP3RX),
4031 &s->drq[OMAP_DMA_MCBSP3_TX], omap_findclk(s, "dspxor_ck"));
4032
4033 s->led[0] = omap_lpg_init(system_memory,
4034 0xfffbd000, omap_findclk(s, "clk32-kHz"));
4035 s->led[1] = omap_lpg_init(system_memory,
4036 0xfffbd800, omap_findclk(s, "clk32-kHz"));
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053 omap_setup_dsp_mapping(system_memory, omap15xx_dsp_mm);
4054 omap_setup_mpui_io(system_memory, s);
4055
4056 qemu_register_reset(omap1_mpu_reset, s);
4057
4058 return s;
4059}
4060