]> git.proxmox.com Git - qemu.git/blame - hw/omap.c
Mainstone re-org, by Armin Kuster.
[qemu.git] / hw / omap.c
CommitLineData
c3d2689d
AZ
1/*
2 * TI OMAP processors emulation.
3 *
4 * Copyright (C) 2006-2007 Andrzej Zaborowski <balrog@zabor.org>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
19 * MA 02111-1307 USA
20 */
87ecb68b
PB
21#include "hw.h"
22#include "arm-misc.h"
23#include "omap.h"
24#include "sysemu.h"
25#include "qemu-timer.h"
26/* We use pc-style serial ports. */
27#include "pc.h"
c3d2689d
AZ
28
29/* Should signal the TCMI */
66450b15
AZ
30uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr)
31{
02645926
AZ
32 uint8_t ret;
33
66450b15 34 OMAP_8B_REG(addr);
b854bc19 35 cpu_physical_memory_read(addr, (void *) &ret, 1);
02645926 36 return ret;
66450b15
AZ
37}
38
39void omap_badwidth_write8(void *opaque, target_phys_addr_t addr,
40 uint32_t value)
41{
b854bc19
AZ
42 uint8_t val8 = value;
43
66450b15 44 OMAP_8B_REG(addr);
b854bc19 45 cpu_physical_memory_write(addr, (void *) &val8, 1);
66450b15
AZ
46}
47
b30bb3a2 48uint32_t omap_badwidth_read16(void *opaque, target_phys_addr_t addr)
c3d2689d 49{
b854bc19
AZ
50 uint16_t ret;
51
c3d2689d 52 OMAP_16B_REG(addr);
b854bc19
AZ
53 cpu_physical_memory_read(addr, (void *) &ret, 2);
54 return ret;
c3d2689d
AZ
55}
56
b30bb3a2 57void omap_badwidth_write16(void *opaque, target_phys_addr_t addr,
c3d2689d
AZ
58 uint32_t value)
59{
b854bc19
AZ
60 uint16_t val16 = value;
61
c3d2689d 62 OMAP_16B_REG(addr);
b854bc19 63 cpu_physical_memory_write(addr, (void *) &val16, 2);
c3d2689d
AZ
64}
65
b30bb3a2 66uint32_t omap_badwidth_read32(void *opaque, target_phys_addr_t addr)
c3d2689d 67{
b854bc19
AZ
68 uint32_t ret;
69
c3d2689d 70 OMAP_32B_REG(addr);
b854bc19
AZ
71 cpu_physical_memory_read(addr, (void *) &ret, 4);
72 return ret;
c3d2689d
AZ
73}
74
b30bb3a2 75void omap_badwidth_write32(void *opaque, target_phys_addr_t addr,
c3d2689d
AZ
76 uint32_t value)
77{
78 OMAP_32B_REG(addr);
b854bc19 79 cpu_physical_memory_write(addr, (void *) &value, 4);
c3d2689d
AZ
80}
81
c3d2689d
AZ
82/* Interrupt Handlers */
83struct omap_intr_handler_s {
84 qemu_irq *pins;
85 qemu_irq *parent_pic;
86 target_phys_addr_t base;
87
88 /* state */
89 uint32_t irqs;
90 uint32_t mask;
91 uint32_t sens_edge;
92 uint32_t fiq;
93 int priority[32];
94 uint32_t new_irq_agr;
95 uint32_t new_fiq_agr;
96 int sir_irq;
97 int sir_fiq;
98 int stats[32];
99};
100
101static void omap_inth_update(struct omap_intr_handler_s *s)
102{
cfa0b71d
AZ
103 uint32_t irq = s->irqs & ~s->mask & ~s->fiq;
104 uint32_t fiq = s->irqs & ~s->mask & s->fiq;
c3d2689d 105
cfa0b71d
AZ
106 if (s->new_irq_agr || !irq) {
107 qemu_set_irq(s->parent_pic[ARM_PIC_CPU_IRQ], irq);
108 if (irq)
109 s->new_irq_agr = 0;
110 }
c3d2689d 111
cfa0b71d
AZ
112 if (s->new_fiq_agr || !irq) {
113 qemu_set_irq(s->parent_pic[ARM_PIC_CPU_FIQ], fiq);
114 if (fiq)
115 s->new_fiq_agr = 0;
116 }
c3d2689d
AZ
117}
118
119static void omap_inth_sir_update(struct omap_intr_handler_s *s)
120{
121 int i, intr_irq, intr_fiq, p_irq, p_fiq, p, f;
122 uint32_t level = s->irqs & ~s->mask;
123
124 intr_irq = 0;
125 intr_fiq = 0;
126 p_irq = -1;
127 p_fiq = -1;
128 /* Find the interrupt line with the highest dynamic priority */
129 for (f = ffs(level), i = f - 1, level >>= f - 1; f; i += f, level >>= f) {
130 p = s->priority[i];
131 if (s->fiq & (1 << i)) {
132 if (p > p_fiq) {
133 p_fiq = p;
134 intr_fiq = i;
135 }
136 } else {
137 if (p > p_irq) {
138 p_irq = p;
139 intr_irq = i;
140 }
141 }
142
143 f = ffs(level >> 1);
144 }
145
146 s->sir_irq = intr_irq;
147 s->sir_fiq = intr_fiq;
148}
149
150#define INT_FALLING_EDGE 0
151#define INT_LOW_LEVEL 1
152
153static void omap_set_intr(void *opaque, int irq, int req)
154{
155 struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
156 uint32_t rise;
157
158 if (req) {
159 rise = ~ih->irqs & (1 << irq);
160 ih->irqs |= rise;
cfa0b71d 161 ih->stats[irq] += !!rise;
c3d2689d
AZ
162 } else {
163 rise = ih->sens_edge & ih->irqs & (1 << irq);
164 ih->irqs &= ~rise;
165 }
166
167 if (rise & ~ih->mask) {
168 omap_inth_sir_update(ih);
169
170 omap_inth_update(ih);
171 }
172}
173
174static uint32_t omap_inth_read(void *opaque, target_phys_addr_t addr)
175{
176 struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
177 int i, offset = addr - s->base;
178
179 switch (offset) {
180 case 0x00: /* ITR */
181 return s->irqs;
182
183 case 0x04: /* MIR */
184 return s->mask;
185
186 case 0x10: /* SIR_IRQ_CODE */
187 i = s->sir_irq;
188 if (((s->sens_edge >> i) & 1) == INT_FALLING_EDGE && i) {
189 s->irqs &= ~(1 << i);
190 omap_inth_sir_update(s);
191 omap_inth_update(s);
192 }
193 return i;
194
195 case 0x14: /* SIR_FIQ_CODE */
196 i = s->sir_fiq;
197 if (((s->sens_edge >> i) & 1) == INT_FALLING_EDGE && i) {
198 s->irqs &= ~(1 << i);
199 omap_inth_sir_update(s);
200 omap_inth_update(s);
201 }
202 return i;
203
204 case 0x18: /* CONTROL_REG */
205 return 0;
206
207 case 0x1c: /* ILR0 */
208 case 0x20: /* ILR1 */
209 case 0x24: /* ILR2 */
210 case 0x28: /* ILR3 */
211 case 0x2c: /* ILR4 */
212 case 0x30: /* ILR5 */
213 case 0x34: /* ILR6 */
214 case 0x38: /* ILR7 */
215 case 0x3c: /* ILR8 */
216 case 0x40: /* ILR9 */
217 case 0x44: /* ILR10 */
218 case 0x48: /* ILR11 */
219 case 0x4c: /* ILR12 */
220 case 0x50: /* ILR13 */
221 case 0x54: /* ILR14 */
222 case 0x58: /* ILR15 */
223 case 0x5c: /* ILR16 */
224 case 0x60: /* ILR17 */
225 case 0x64: /* ILR18 */
226 case 0x68: /* ILR19 */
227 case 0x6c: /* ILR20 */
228 case 0x70: /* ILR21 */
229 case 0x74: /* ILR22 */
230 case 0x78: /* ILR23 */
231 case 0x7c: /* ILR24 */
232 case 0x80: /* ILR25 */
233 case 0x84: /* ILR26 */
234 case 0x88: /* ILR27 */
235 case 0x8c: /* ILR28 */
236 case 0x90: /* ILR29 */
237 case 0x94: /* ILR30 */
238 case 0x98: /* ILR31 */
239 i = (offset - 0x1c) >> 2;
240 return (s->priority[i] << 2) |
241 (((s->sens_edge >> i) & 1) << 1) |
242 ((s->fiq >> i) & 1);
243
244 case 0x9c: /* ISR */
245 return 0x00000000;
246
247 default:
248 OMAP_BAD_REG(addr);
249 break;
250 }
251 return 0;
252}
253
254static void omap_inth_write(void *opaque, target_phys_addr_t addr,
255 uint32_t value)
256{
257 struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
258 int i, offset = addr - s->base;
259
260 switch (offset) {
261 case 0x00: /* ITR */
d8f699cb 262 s->irqs &= value | 1;
c3d2689d
AZ
263 omap_inth_sir_update(s);
264 omap_inth_update(s);
265 return;
266
267 case 0x04: /* MIR */
268 s->mask = value;
269 omap_inth_sir_update(s);
270 omap_inth_update(s);
271 return;
272
273 case 0x10: /* SIR_IRQ_CODE */
274 case 0x14: /* SIR_FIQ_CODE */
275 OMAP_RO_REG(addr);
276 break;
277
278 case 0x18: /* CONTROL_REG */
279 if (value & 2)
280 s->new_fiq_agr = ~0;
281 if (value & 1)
282 s->new_irq_agr = ~0;
283 omap_inth_update(s);
284 return;
285
286 case 0x1c: /* ILR0 */
287 case 0x20: /* ILR1 */
288 case 0x24: /* ILR2 */
289 case 0x28: /* ILR3 */
290 case 0x2c: /* ILR4 */
291 case 0x30: /* ILR5 */
292 case 0x34: /* ILR6 */
293 case 0x38: /* ILR7 */
294 case 0x3c: /* ILR8 */
295 case 0x40: /* ILR9 */
296 case 0x44: /* ILR10 */
297 case 0x48: /* ILR11 */
298 case 0x4c: /* ILR12 */
299 case 0x50: /* ILR13 */
300 case 0x54: /* ILR14 */
301 case 0x58: /* ILR15 */
302 case 0x5c: /* ILR16 */
303 case 0x60: /* ILR17 */
304 case 0x64: /* ILR18 */
305 case 0x68: /* ILR19 */
306 case 0x6c: /* ILR20 */
307 case 0x70: /* ILR21 */
308 case 0x74: /* ILR22 */
309 case 0x78: /* ILR23 */
310 case 0x7c: /* ILR24 */
311 case 0x80: /* ILR25 */
312 case 0x84: /* ILR26 */
313 case 0x88: /* ILR27 */
314 case 0x8c: /* ILR28 */
315 case 0x90: /* ILR29 */
316 case 0x94: /* ILR30 */
317 case 0x98: /* ILR31 */
318 i = (offset - 0x1c) >> 2;
319 s->priority[i] = (value >> 2) & 0x1f;
320 s->sens_edge &= ~(1 << i);
321 s->sens_edge |= ((value >> 1) & 1) << i;
322 s->fiq &= ~(1 << i);
323 s->fiq |= (value & 1) << i;
324 return;
325
326 case 0x9c: /* ISR */
327 for (i = 0; i < 32; i ++)
328 if (value & (1 << i)) {
329 omap_set_intr(s, i, 1);
330 return;
331 }
332 return;
333
334 default:
335 OMAP_BAD_REG(addr);
336 }
337}
338
339static CPUReadMemoryFunc *omap_inth_readfn[] = {
340 omap_badwidth_read32,
341 omap_badwidth_read32,
342 omap_inth_read,
343};
344
345static CPUWriteMemoryFunc *omap_inth_writefn[] = {
346 omap_inth_write,
347 omap_inth_write,
348 omap_inth_write,
349};
350
351static void omap_inth_reset(struct omap_intr_handler_s *s)
352{
353 s->irqs = 0x00000000;
354 s->mask = 0xffffffff;
355 s->sens_edge = 0x00000000;
356 s->fiq = 0x00000000;
357 memset(s->priority, 0, sizeof(s->priority));
358 s->new_irq_agr = ~0;
359 s->new_fiq_agr = ~0;
360 s->sir_irq = 0;
361 s->sir_fiq = 0;
362
363 omap_inth_update(s);
364}
365
366struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
367 unsigned long size, qemu_irq parent[2], omap_clk clk)
368{
369 int iomemtype;
370 struct omap_intr_handler_s *s = (struct omap_intr_handler_s *)
371 qemu_mallocz(sizeof(struct omap_intr_handler_s));
372
373 s->parent_pic = parent;
374 s->base = base;
375 s->pins = qemu_allocate_irqs(omap_set_intr, s, 32);
376 omap_inth_reset(s);
377
378 iomemtype = cpu_register_io_memory(0, omap_inth_readfn,
379 omap_inth_writefn, s);
380 cpu_register_physical_memory(s->base, size, iomemtype);
381
382 return s;
383}
384
385/* OMAP1 DMA module */
386typedef enum {
387 constant = 0,
388 post_incremented,
389 single_index,
390 double_index,
391} omap_dma_addressing_t;
392
393struct omap_dma_channel_s {
394 int burst[2];
395 int pack[2];
396 enum omap_dma_port port[2];
397 target_phys_addr_t addr[2];
398 omap_dma_addressing_t mode[2];
399 int data_type;
400 int end_prog;
401 int repeat;
402 int auto_init;
403 int priority;
404 int fs;
405 int sync;
406 int running;
407 int interrupts;
408 int status;
409 int signalled;
410 int post_sync;
411 int transfer;
412 uint16_t elements;
413 uint16_t frames;
414 uint16_t frame_index;
415 uint16_t element_index;
416 uint16_t cpc;
417
418 struct omap_dma_reg_set_s {
419 target_phys_addr_t src, dest;
420 int frame;
421 int element;
422 int frame_delta[2];
423 int elem_delta[2];
424 int frames;
425 int elements;
426 } active_set;
427};
428
429struct omap_dma_s {
430 qemu_irq *ih;
431 QEMUTimer *tm;
432 struct omap_mpu_state_s *mpu;
433 target_phys_addr_t base;
434 omap_clk clk;
435 int64_t delay;
1af2b62d 436 uint32_t drq;
c3d2689d
AZ
437
438 uint16_t gcr;
439 int run_count;
440
441 int chans;
442 struct omap_dma_channel_s ch[16];
443 struct omap_dma_lcd_channel_s lcd_ch;
444};
445
446static void omap_dma_interrupts_update(struct omap_dma_s *s)
447{
448 /* First three interrupts are shared between two channels each. */
449 qemu_set_irq(s->ih[OMAP_INT_DMA_CH0_6],
450 (s->ch[0].status | s->ch[6].status) & 0x3f);
451 qemu_set_irq(s->ih[OMAP_INT_DMA_CH1_7],
452 (s->ch[1].status | s->ch[7].status) & 0x3f);
453 qemu_set_irq(s->ih[OMAP_INT_DMA_CH2_8],
454 (s->ch[2].status | s->ch[8].status) & 0x3f);
455 qemu_set_irq(s->ih[OMAP_INT_DMA_CH3],
456 (s->ch[3].status) & 0x3f);
457 qemu_set_irq(s->ih[OMAP_INT_DMA_CH4],
458 (s->ch[4].status) & 0x3f);
459 qemu_set_irq(s->ih[OMAP_INT_DMA_CH5],
460 (s->ch[5].status) & 0x3f);
461}
462
463static void omap_dma_channel_load(struct omap_dma_s *s, int ch)
464{
465 struct omap_dma_reg_set_s *a = &s->ch[ch].active_set;
466 int i;
467
468 /*
469 * TODO: verify address ranges and alignment
470 * TODO: port endianness
471 */
472
473 a->src = s->ch[ch].addr[0];
474 a->dest = s->ch[ch].addr[1];
475 a->frames = s->ch[ch].frames;
476 a->elements = s->ch[ch].elements;
477 a->frame = 0;
478 a->element = 0;
479
480 if (unlikely(!s->ch[ch].elements || !s->ch[ch].frames)) {
481 printf("%s: bad DMA request\n", __FUNCTION__);
482 return;
483 }
484
485 for (i = 0; i < 2; i ++)
486 switch (s->ch[ch].mode[i]) {
487 case constant:
488 a->elem_delta[i] = 0;
489 a->frame_delta[i] = 0;
490 break;
491 case post_incremented:
492 a->elem_delta[i] = s->ch[ch].data_type;
493 a->frame_delta[i] = 0;
494 break;
495 case single_index:
496 a->elem_delta[i] = s->ch[ch].data_type +
497 s->ch[ch].element_index - 1;
498 if (s->ch[ch].element_index > 0x7fff)
499 a->elem_delta[i] -= 0x10000;
500 a->frame_delta[i] = 0;
501 break;
502 case double_index:
503 a->elem_delta[i] = s->ch[ch].data_type +
504 s->ch[ch].element_index - 1;
505 if (s->ch[ch].element_index > 0x7fff)
506 a->elem_delta[i] -= 0x10000;
507 a->frame_delta[i] = s->ch[ch].frame_index -
508 s->ch[ch].element_index;
509 if (s->ch[ch].frame_index > 0x7fff)
510 a->frame_delta[i] -= 0x10000;
511 break;
512 default:
513 break;
514 }
515}
516
517static inline void omap_dma_request_run(struct omap_dma_s *s,
518 int channel, int request)
519{
520next_channel:
521 if (request > 0)
522 for (; channel < 9; channel ++)
523 if (s->ch[channel].sync == request && s->ch[channel].running)
524 break;
525 if (channel >= 9)
526 return;
527
528 if (s->ch[channel].transfer) {
529 if (request > 0) {
530 s->ch[channel ++].post_sync = request;
531 goto next_channel;
532 }
533 s->ch[channel].status |= 0x02; /* Synchronisation drop */
534 omap_dma_interrupts_update(s);
535 return;
536 }
537
538 if (!s->ch[channel].signalled)
539 s->run_count ++;
540 s->ch[channel].signalled = 1;
541
542 if (request > 0)
543 s->ch[channel].status |= 0x40; /* External request */
544
1af2b62d 545 if (s->delay && !qemu_timer_pending(s->tm))
c3d2689d
AZ
546 qemu_mod_timer(s->tm, qemu_get_clock(vm_clock) + s->delay);
547
548 if (request > 0) {
549 channel ++;
550 goto next_channel;
551 }
552}
553
554static inline void omap_dma_request_stop(struct omap_dma_s *s, int channel)
555{
556 if (s->ch[channel].signalled)
557 s->run_count --;
558 s->ch[channel].signalled = 0;
559
560 if (!s->run_count)
561 qemu_del_timer(s->tm);
562}
563
564static void omap_dma_channel_run(struct omap_dma_s *s)
565{
566 int ch;
567 uint16_t status;
568 uint8_t value[4];
569 struct omap_dma_port_if_s *src_p, *dest_p;
570 struct omap_dma_reg_set_s *a;
571
572 for (ch = 0; ch < 9; ch ++) {
573 a = &s->ch[ch].active_set;
574
575 src_p = &s->mpu->port[s->ch[ch].port[0]];
576 dest_p = &s->mpu->port[s->ch[ch].port[1]];
577 if (s->ch[ch].signalled && (!src_p->addr_valid(s->mpu, a->src) ||
578 !dest_p->addr_valid(s->mpu, a->dest))) {
579#if 0
580 /* Bus time-out */
581 if (s->ch[ch].interrupts & 0x01)
582 s->ch[ch].status |= 0x01;
583 omap_dma_request_stop(s, ch);
584 continue;
585#endif
586 printf("%s: Bus time-out in DMA%i operation\n", __FUNCTION__, ch);
587 }
588
589 status = s->ch[ch].status;
590 while (status == s->ch[ch].status && s->ch[ch].signalled) {
591 /* Transfer a single element */
592 s->ch[ch].transfer = 1;
593 cpu_physical_memory_read(a->src, value, s->ch[ch].data_type);
594 cpu_physical_memory_write(a->dest, value, s->ch[ch].data_type);
595 s->ch[ch].transfer = 0;
596
597 a->src += a->elem_delta[0];
598 a->dest += a->elem_delta[1];
599 a->element ++;
600
601 /* Check interrupt conditions */
602 if (a->element == a->elements) {
603 a->element = 0;
604 a->src += a->frame_delta[0];
605 a->dest += a->frame_delta[1];
606 a->frame ++;
607
608 if (a->frame == a->frames) {
609 if (!s->ch[ch].repeat || !s->ch[ch].auto_init)
610 s->ch[ch].running = 0;
611
612 if (s->ch[ch].auto_init &&
613 (s->ch[ch].repeat ||
614 s->ch[ch].end_prog))
615 omap_dma_channel_load(s, ch);
616
617 if (s->ch[ch].interrupts & 0x20)
618 s->ch[ch].status |= 0x20;
619
620 if (!s->ch[ch].sync)
621 omap_dma_request_stop(s, ch);
622 }
623
624 if (s->ch[ch].interrupts & 0x08)
625 s->ch[ch].status |= 0x08;
626
1af2b62d
AZ
627 if (s->ch[ch].sync && s->ch[ch].fs &&
628 !(s->drq & (1 << s->ch[ch].sync))) {
c3d2689d
AZ
629 s->ch[ch].status &= ~0x40;
630 omap_dma_request_stop(s, ch);
631 }
632 }
633
634 if (a->element == 1 && a->frame == a->frames - 1)
635 if (s->ch[ch].interrupts & 0x10)
636 s->ch[ch].status |= 0x10;
637
638 if (a->element == (a->elements >> 1))
639 if (s->ch[ch].interrupts & 0x04)
640 s->ch[ch].status |= 0x04;
641
1af2b62d
AZ
642 if (s->ch[ch].sync && !s->ch[ch].fs &&
643 !(s->drq & (1 << s->ch[ch].sync))) {
c3d2689d
AZ
644 s->ch[ch].status &= ~0x40;
645 omap_dma_request_stop(s, ch);
646 }
647
648 /*
649 * Process requests made while the element was
650 * being transferred.
651 */
652 if (s->ch[ch].post_sync) {
653 omap_dma_request_run(s, 0, s->ch[ch].post_sync);
654 s->ch[ch].post_sync = 0;
655 }
656
657#if 0
658 break;
659#endif
660 }
661
662 s->ch[ch].cpc = a->dest & 0x0000ffff;
663 }
664
665 omap_dma_interrupts_update(s);
666 if (s->run_count && s->delay)
667 qemu_mod_timer(s->tm, qemu_get_clock(vm_clock) + s->delay);
668}
669
670static int omap_dma_ch_reg_read(struct omap_dma_s *s,
671 int ch, int reg, uint16_t *value) {
672 switch (reg) {
673 case 0x00: /* SYS_DMA_CSDP_CH0 */
674 *value = (s->ch[ch].burst[1] << 14) |
675 (s->ch[ch].pack[1] << 13) |
676 (s->ch[ch].port[1] << 9) |
677 (s->ch[ch].burst[0] << 7) |
678 (s->ch[ch].pack[0] << 6) |
679 (s->ch[ch].port[0] << 2) |
680 (s->ch[ch].data_type >> 1);
681 break;
682
683 case 0x02: /* SYS_DMA_CCR_CH0 */
684 *value = (s->ch[ch].mode[1] << 14) |
685 (s->ch[ch].mode[0] << 12) |
686 (s->ch[ch].end_prog << 11) |
687 (s->ch[ch].repeat << 9) |
688 (s->ch[ch].auto_init << 8) |
689 (s->ch[ch].running << 7) |
690 (s->ch[ch].priority << 6) |
691 (s->ch[ch].fs << 5) | s->ch[ch].sync;
692 break;
693
694 case 0x04: /* SYS_DMA_CICR_CH0 */
695 *value = s->ch[ch].interrupts;
696 break;
697
698 case 0x06: /* SYS_DMA_CSR_CH0 */
699 /* FIXME: shared CSR for channels sharing the interrupts */
700 *value = s->ch[ch].status;
701 s->ch[ch].status &= 0x40;
702 omap_dma_interrupts_update(s);
703 break;
704
705 case 0x08: /* SYS_DMA_CSSA_L_CH0 */
706 *value = s->ch[ch].addr[0] & 0x0000ffff;
707 break;
708
709 case 0x0a: /* SYS_DMA_CSSA_U_CH0 */
710 *value = s->ch[ch].addr[0] >> 16;
711 break;
712
713 case 0x0c: /* SYS_DMA_CDSA_L_CH0 */
714 *value = s->ch[ch].addr[1] & 0x0000ffff;
715 break;
716
717 case 0x0e: /* SYS_DMA_CDSA_U_CH0 */
718 *value = s->ch[ch].addr[1] >> 16;
719 break;
720
721 case 0x10: /* SYS_DMA_CEN_CH0 */
722 *value = s->ch[ch].elements;
723 break;
724
725 case 0x12: /* SYS_DMA_CFN_CH0 */
726 *value = s->ch[ch].frames;
727 break;
728
729 case 0x14: /* SYS_DMA_CFI_CH0 */
730 *value = s->ch[ch].frame_index;
731 break;
732
733 case 0x16: /* SYS_DMA_CEI_CH0 */
734 *value = s->ch[ch].element_index;
735 break;
736
737 case 0x18: /* SYS_DMA_CPC_CH0 */
738 *value = s->ch[ch].cpc;
739 break;
740
741 default:
742 return 1;
743 }
744 return 0;
745}
746
747static int omap_dma_ch_reg_write(struct omap_dma_s *s,
748 int ch, int reg, uint16_t value) {
749 switch (reg) {
750 case 0x00: /* SYS_DMA_CSDP_CH0 */
751 s->ch[ch].burst[1] = (value & 0xc000) >> 14;
752 s->ch[ch].pack[1] = (value & 0x2000) >> 13;
753 s->ch[ch].port[1] = (enum omap_dma_port) ((value & 0x1e00) >> 9);
754 s->ch[ch].burst[0] = (value & 0x0180) >> 7;
755 s->ch[ch].pack[0] = (value & 0x0040) >> 6;
756 s->ch[ch].port[0] = (enum omap_dma_port) ((value & 0x003c) >> 2);
757 s->ch[ch].data_type = (1 << (value & 3));
758 if (s->ch[ch].port[0] >= omap_dma_port_last)
759 printf("%s: invalid DMA port %i\n", __FUNCTION__,
760 s->ch[ch].port[0]);
761 if (s->ch[ch].port[1] >= omap_dma_port_last)
762 printf("%s: invalid DMA port %i\n", __FUNCTION__,
763 s->ch[ch].port[1]);
764 if ((value & 3) == 3)
765 printf("%s: bad data_type for DMA channel %i\n", __FUNCTION__, ch);
766 break;
767
768 case 0x02: /* SYS_DMA_CCR_CH0 */
769 s->ch[ch].mode[1] = (omap_dma_addressing_t) ((value & 0xc000) >> 14);
770 s->ch[ch].mode[0] = (omap_dma_addressing_t) ((value & 0x3000) >> 12);
771 s->ch[ch].end_prog = (value & 0x0800) >> 11;
772 s->ch[ch].repeat = (value & 0x0200) >> 9;
773 s->ch[ch].auto_init = (value & 0x0100) >> 8;
774 s->ch[ch].priority = (value & 0x0040) >> 6;
775 s->ch[ch].fs = (value & 0x0020) >> 5;
776 s->ch[ch].sync = value & 0x001f;
777 if (value & 0x0080) {
778 if (s->ch[ch].running) {
779 if (!s->ch[ch].signalled &&
780 s->ch[ch].auto_init && s->ch[ch].end_prog)
781 omap_dma_channel_load(s, ch);
782 } else {
783 s->ch[ch].running = 1;
784 omap_dma_channel_load(s, ch);
785 }
1af2b62d 786 if (!s->ch[ch].sync || (s->drq & (1 << s->ch[ch].sync)))
c3d2689d
AZ
787 omap_dma_request_run(s, ch, 0);
788 } else {
789 s->ch[ch].running = 0;
790 omap_dma_request_stop(s, ch);
791 }
792 break;
793
794 case 0x04: /* SYS_DMA_CICR_CH0 */
795 s->ch[ch].interrupts = value & 0x003f;
796 break;
797
798 case 0x06: /* SYS_DMA_CSR_CH0 */
799 return 1;
800
801 case 0x08: /* SYS_DMA_CSSA_L_CH0 */
802 s->ch[ch].addr[0] &= 0xffff0000;
803 s->ch[ch].addr[0] |= value;
804 break;
805
806 case 0x0a: /* SYS_DMA_CSSA_U_CH0 */
807 s->ch[ch].addr[0] &= 0x0000ffff;
b854bc19 808 s->ch[ch].addr[0] |= (uint32_t) value << 16;
c3d2689d
AZ
809 break;
810
811 case 0x0c: /* SYS_DMA_CDSA_L_CH0 */
812 s->ch[ch].addr[1] &= 0xffff0000;
813 s->ch[ch].addr[1] |= value;
814 break;
815
816 case 0x0e: /* SYS_DMA_CDSA_U_CH0 */
817 s->ch[ch].addr[1] &= 0x0000ffff;
b854bc19 818 s->ch[ch].addr[1] |= (uint32_t) value << 16;
c3d2689d
AZ
819 break;
820
821 case 0x10: /* SYS_DMA_CEN_CH0 */
822 s->ch[ch].elements = value & 0xffff;
823 break;
824
825 case 0x12: /* SYS_DMA_CFN_CH0 */
826 s->ch[ch].frames = value & 0xffff;
827 break;
828
829 case 0x14: /* SYS_DMA_CFI_CH0 */
830 s->ch[ch].frame_index = value & 0xffff;
831 break;
832
833 case 0x16: /* SYS_DMA_CEI_CH0 */
834 s->ch[ch].element_index = value & 0xffff;
835 break;
836
837 case 0x18: /* SYS_DMA_CPC_CH0 */
838 return 1;
839
840 default:
8731ac03 841 OMAP_BAD_REG((target_phys_addr_t) reg);
c3d2689d
AZ
842 }
843 return 0;
844}
845
846static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr)
847{
848 struct omap_dma_s *s = (struct omap_dma_s *) opaque;
849 int i, reg, ch, offset = addr - s->base;
850 uint16_t ret;
851
852 switch (offset) {
853 case 0x000 ... 0x2fe:
854 reg = offset & 0x3f;
855 ch = (offset >> 6) & 0x0f;
856 if (omap_dma_ch_reg_read(s, ch, reg, &ret))
857 break;
858 return ret;
859
860 case 0x300: /* SYS_DMA_LCD_CTRL */
861 i = s->lcd_ch.condition;
862 s->lcd_ch.condition = 0;
863 qemu_irq_lower(s->lcd_ch.irq);
864 return ((s->lcd_ch.src == imif) << 6) | (i << 3) |
865 (s->lcd_ch.interrupts << 1) | s->lcd_ch.dual;
866
867 case 0x302: /* SYS_DMA_LCD_TOP_F1_L */
868 return s->lcd_ch.src_f1_top & 0xffff;
869
870 case 0x304: /* SYS_DMA_LCD_TOP_F1_U */
871 return s->lcd_ch.src_f1_top >> 16;
872
873 case 0x306: /* SYS_DMA_LCD_BOT_F1_L */
874 return s->lcd_ch.src_f1_bottom & 0xffff;
875
876 case 0x308: /* SYS_DMA_LCD_BOT_F1_U */
877 return s->lcd_ch.src_f1_bottom >> 16;
878
879 case 0x30a: /* SYS_DMA_LCD_TOP_F2_L */
880 return s->lcd_ch.src_f2_top & 0xffff;
881
882 case 0x30c: /* SYS_DMA_LCD_TOP_F2_U */
883 return s->lcd_ch.src_f2_top >> 16;
884
885 case 0x30e: /* SYS_DMA_LCD_BOT_F2_L */
886 return s->lcd_ch.src_f2_bottom & 0xffff;
887
888 case 0x310: /* SYS_DMA_LCD_BOT_F2_U */
889 return s->lcd_ch.src_f2_bottom >> 16;
890
891 case 0x400: /* SYS_DMA_GCR */
892 return s->gcr;
893 }
894
895 OMAP_BAD_REG(addr);
896 return 0;
897}
898
899static void omap_dma_write(void *opaque, target_phys_addr_t addr,
900 uint32_t value)
901{
902 struct omap_dma_s *s = (struct omap_dma_s *) opaque;
903 int reg, ch, offset = addr - s->base;
904
905 switch (offset) {
906 case 0x000 ... 0x2fe:
907 reg = offset & 0x3f;
908 ch = (offset >> 6) & 0x0f;
909 if (omap_dma_ch_reg_write(s, ch, reg, value))
910 OMAP_RO_REG(addr);
911 break;
912
913 case 0x300: /* SYS_DMA_LCD_CTRL */
914 s->lcd_ch.src = (value & 0x40) ? imif : emiff;
915 s->lcd_ch.condition = 0;
916 /* Assume no bus errors and thus no BUS_ERROR irq bits. */
917 s->lcd_ch.interrupts = (value >> 1) & 1;
918 s->lcd_ch.dual = value & 1;
919 break;
920
921 case 0x302: /* SYS_DMA_LCD_TOP_F1_L */
922 s->lcd_ch.src_f1_top &= 0xffff0000;
923 s->lcd_ch.src_f1_top |= 0x0000ffff & value;
924 break;
925
926 case 0x304: /* SYS_DMA_LCD_TOP_F1_U */
927 s->lcd_ch.src_f1_top &= 0x0000ffff;
928 s->lcd_ch.src_f1_top |= value << 16;
929 break;
930
931 case 0x306: /* SYS_DMA_LCD_BOT_F1_L */
932 s->lcd_ch.src_f1_bottom &= 0xffff0000;
933 s->lcd_ch.src_f1_bottom |= 0x0000ffff & value;
934 break;
935
936 case 0x308: /* SYS_DMA_LCD_BOT_F1_U */
937 s->lcd_ch.src_f1_bottom &= 0x0000ffff;
938 s->lcd_ch.src_f1_bottom |= value << 16;
939 break;
940
941 case 0x30a: /* SYS_DMA_LCD_TOP_F2_L */
942 s->lcd_ch.src_f2_top &= 0xffff0000;
943 s->lcd_ch.src_f2_top |= 0x0000ffff & value;
944 break;
945
946 case 0x30c: /* SYS_DMA_LCD_TOP_F2_U */
947 s->lcd_ch.src_f2_top &= 0x0000ffff;
948 s->lcd_ch.src_f2_top |= value << 16;
949 break;
950
951 case 0x30e: /* SYS_DMA_LCD_BOT_F2_L */
952 s->lcd_ch.src_f2_bottom &= 0xffff0000;
953 s->lcd_ch.src_f2_bottom |= 0x0000ffff & value;
954 break;
955
956 case 0x310: /* SYS_DMA_LCD_BOT_F2_U */
957 s->lcd_ch.src_f2_bottom &= 0x0000ffff;
958 s->lcd_ch.src_f2_bottom |= value << 16;
959 break;
960
961 case 0x400: /* SYS_DMA_GCR */
962 s->gcr = value & 0x000c;
963 break;
964
965 default:
966 OMAP_BAD_REG(addr);
967 }
968}
969
970static CPUReadMemoryFunc *omap_dma_readfn[] = {
971 omap_badwidth_read16,
972 omap_dma_read,
973 omap_badwidth_read16,
974};
975
976static CPUWriteMemoryFunc *omap_dma_writefn[] = {
977 omap_badwidth_write16,
978 omap_dma_write,
979 omap_badwidth_write16,
980};
981
982static void omap_dma_request(void *opaque, int drq, int req)
983{
984 struct omap_dma_s *s = (struct omap_dma_s *) opaque;
1af2b62d
AZ
985 /* The request pins are level triggered. */
986 if (req) {
987 if (~s->drq & (1 << drq)) {
988 s->drq |= 1 << drq;
989 omap_dma_request_run(s, 0, drq);
990 }
991 } else
992 s->drq &= ~(1 << drq);
c3d2689d
AZ
993}
994
995static void omap_dma_clk_update(void *opaque, int line, int on)
996{
997 struct omap_dma_s *s = (struct omap_dma_s *) opaque;
998
999 if (on) {
73560bc8
AZ
1000 /* TODO: make a clever calculation */
1001 s->delay = ticks_per_sec >> 8;
c3d2689d
AZ
1002 if (s->run_count)
1003 qemu_mod_timer(s->tm, qemu_get_clock(vm_clock) + s->delay);
1004 } else {
1005 s->delay = 0;
1006 qemu_del_timer(s->tm);
1007 }
1008}
1009
1010static void omap_dma_reset(struct omap_dma_s *s)
1011{
1012 int i;
1013
1014 qemu_del_timer(s->tm);
1015 s->gcr = 0x0004;
1af2b62d 1016 s->drq = 0x00000000;
c3d2689d
AZ
1017 s->run_count = 0;
1018 s->lcd_ch.src = emiff;
1019 s->lcd_ch.condition = 0;
1020 s->lcd_ch.interrupts = 0;
1021 s->lcd_ch.dual = 0;
1022 memset(s->ch, 0, sizeof(s->ch));
1023 for (i = 0; i < s->chans; i ++)
1024 s->ch[i].interrupts = 0x0003;
1025}
1026
1027struct omap_dma_s *omap_dma_init(target_phys_addr_t base,
1028 qemu_irq pic[], struct omap_mpu_state_s *mpu, omap_clk clk)
1029{
1030 int iomemtype;
1031 struct omap_dma_s *s = (struct omap_dma_s *)
1032 qemu_mallocz(sizeof(struct omap_dma_s));
1033
1034 s->ih = pic;
1035 s->base = base;
1036 s->chans = 9;
1037 s->mpu = mpu;
1038 s->clk = clk;
1039 s->lcd_ch.irq = pic[OMAP_INT_DMA_LCD];
1040 s->lcd_ch.mpu = mpu;
1041 s->tm = qemu_new_timer(vm_clock, (QEMUTimerCB *) omap_dma_channel_run, s);
1042 omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]);
1043 mpu->drq = qemu_allocate_irqs(omap_dma_request, s, 32);
1044 omap_dma_reset(s);
1af2b62d 1045 omap_dma_clk_update(s, 0, 1);
c3d2689d
AZ
1046
1047 iomemtype = cpu_register_io_memory(0, omap_dma_readfn,
1048 omap_dma_writefn, s);
1049 cpu_register_physical_memory(s->base, 0x800, iomemtype);
1050
1051 return s;
1052}
1053
1054/* DMA ports */
b854bc19 1055static int omap_validate_emiff_addr(struct omap_mpu_state_s *s,
c3d2689d
AZ
1056 target_phys_addr_t addr)
1057{
1058 return addr >= OMAP_EMIFF_BASE && addr < OMAP_EMIFF_BASE + s->sdram_size;
1059}
1060
b854bc19 1061static int omap_validate_emifs_addr(struct omap_mpu_state_s *s,
c3d2689d
AZ
1062 target_phys_addr_t addr)
1063{
1064 return addr >= OMAP_EMIFS_BASE && addr < OMAP_EMIFF_BASE;
1065}
1066
b854bc19 1067static int omap_validate_imif_addr(struct omap_mpu_state_s *s,
c3d2689d
AZ
1068 target_phys_addr_t addr)
1069{
1070 return addr >= OMAP_IMIF_BASE && addr < OMAP_IMIF_BASE + s->sram_size;
1071}
1072
b854bc19 1073static int omap_validate_tipb_addr(struct omap_mpu_state_s *s,
c3d2689d
AZ
1074 target_phys_addr_t addr)
1075{
1076 return addr >= 0xfffb0000 && addr < 0xffff0000;
1077}
1078
b854bc19 1079static int omap_validate_local_addr(struct omap_mpu_state_s *s,
c3d2689d
AZ
1080 target_phys_addr_t addr)
1081{
1082 return addr >= OMAP_LOCALBUS_BASE && addr < OMAP_LOCALBUS_BASE + 0x1000000;
1083}
1084
b854bc19 1085static int omap_validate_tipb_mpui_addr(struct omap_mpu_state_s *s,
c3d2689d
AZ
1086 target_phys_addr_t addr)
1087{
1088 return addr >= 0xe1010000 && addr < 0xe1020004;
1089}
1090
1091/* MPU OS timers */
1092struct omap_mpu_timer_s {
1093 qemu_irq irq;
1094 omap_clk clk;
1095 target_phys_addr_t base;
1096 uint32_t val;
1097 int64_t time;
1098 QEMUTimer *timer;
1099 int64_t rate;
1100 int it_ena;
1101
1102 int enable;
1103 int ptv;
1104 int ar;
1105 int st;
1106 uint32_t reset_val;
1107};
1108
1109static inline uint32_t omap_timer_read(struct omap_mpu_timer_s *timer)
1110{
1111 uint64_t distance = qemu_get_clock(vm_clock) - timer->time;
1112
1113 if (timer->st && timer->enable && timer->rate)
1114 return timer->val - muldiv64(distance >> (timer->ptv + 1),
1115 timer->rate, ticks_per_sec);
1116 else
1117 return timer->val;
1118}
1119
1120static inline void omap_timer_sync(struct omap_mpu_timer_s *timer)
1121{
1122 timer->val = omap_timer_read(timer);
1123 timer->time = qemu_get_clock(vm_clock);
1124}
1125
1126static inline void omap_timer_update(struct omap_mpu_timer_s *timer)
1127{
1128 int64_t expires;
1129
1130 if (timer->enable && timer->st && timer->rate) {
1131 timer->val = timer->reset_val; /* Should skip this on clk enable */
b854bc19 1132 expires = muldiv64(timer->val << (timer->ptv + 1),
c3d2689d 1133 ticks_per_sec, timer->rate);
b854bc19
AZ
1134
1135 /* If timer expiry would be sooner than in about 1 ms and
1136 * auto-reload isn't set, then fire immediately. This is a hack
1137 * to make systems like PalmOS run in acceptable time. PalmOS
1138 * sets the interval to a very low value and polls the status bit
1139 * in a busy loop when it wants to sleep just a couple of CPU
1140 * ticks. */
1141 if (expires > (ticks_per_sec >> 10) || timer->ar)
1142 qemu_mod_timer(timer->timer, timer->time + expires);
1143 else {
1144 timer->val = 0;
1145 timer->st = 0;
1146 if (timer->it_ena)
1147 qemu_irq_raise(timer->irq);
1148 }
c3d2689d
AZ
1149 } else
1150 qemu_del_timer(timer->timer);
1151}
1152
1153static void omap_timer_tick(void *opaque)
1154{
1155 struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
1156 omap_timer_sync(timer);
1157
1158 if (!timer->ar) {
1159 timer->val = 0;
1160 timer->st = 0;
1161 }
1162
1163 if (timer->it_ena)
1164 qemu_irq_raise(timer->irq);
1165 omap_timer_update(timer);
1166}
1167
1168static void omap_timer_clk_update(void *opaque, int line, int on)
1169{
1170 struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
1171
1172 omap_timer_sync(timer);
1173 timer->rate = on ? omap_clk_getrate(timer->clk) : 0;
1174 omap_timer_update(timer);
1175}
1176
1177static void omap_timer_clk_setup(struct omap_mpu_timer_s *timer)
1178{
1179 omap_clk_adduser(timer->clk,
1180 qemu_allocate_irqs(omap_timer_clk_update, timer, 1)[0]);
1181 timer->rate = omap_clk_getrate(timer->clk);
1182}
1183
1184static uint32_t omap_mpu_timer_read(void *opaque, target_phys_addr_t addr)
1185{
1186 struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
1187 int offset = addr - s->base;
1188
1189 switch (offset) {
1190 case 0x00: /* CNTL_TIMER */
1191 return (s->enable << 5) | (s->ptv << 2) | (s->ar << 1) | s->st;
1192
1193 case 0x04: /* LOAD_TIM */
1194 break;
1195
1196 case 0x08: /* READ_TIM */
1197 return omap_timer_read(s);
1198 }
1199
1200 OMAP_BAD_REG(addr);
1201 return 0;
1202}
1203
1204static void omap_mpu_timer_write(void *opaque, target_phys_addr_t addr,
1205 uint32_t value)
1206{
1207 struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
1208 int offset = addr - s->base;
1209
1210 switch (offset) {
1211 case 0x00: /* CNTL_TIMER */
1212 omap_timer_sync(s);
1213 s->enable = (value >> 5) & 1;
1214 s->ptv = (value >> 2) & 7;
1215 s->ar = (value >> 1) & 1;
1216 s->st = value & 1;
1217 omap_timer_update(s);
1218 return;
1219
1220 case 0x04: /* LOAD_TIM */
1221 s->reset_val = value;
1222 return;
1223
1224 case 0x08: /* READ_TIM */
1225 OMAP_RO_REG(addr);
1226 break;
1227
1228 default:
1229 OMAP_BAD_REG(addr);
1230 }
1231}
1232
1233static CPUReadMemoryFunc *omap_mpu_timer_readfn[] = {
1234 omap_badwidth_read32,
1235 omap_badwidth_read32,
1236 omap_mpu_timer_read,
1237};
1238
1239static CPUWriteMemoryFunc *omap_mpu_timer_writefn[] = {
1240 omap_badwidth_write32,
1241 omap_badwidth_write32,
1242 omap_mpu_timer_write,
1243};
1244
1245static void omap_mpu_timer_reset(struct omap_mpu_timer_s *s)
1246{
1247 qemu_del_timer(s->timer);
1248 s->enable = 0;
1249 s->reset_val = 31337;
1250 s->val = 0;
1251 s->ptv = 0;
1252 s->ar = 0;
1253 s->st = 0;
1254 s->it_ena = 1;
1255}
1256
1257struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t base,
1258 qemu_irq irq, omap_clk clk)
1259{
1260 int iomemtype;
1261 struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *)
1262 qemu_mallocz(sizeof(struct omap_mpu_timer_s));
1263
1264 s->irq = irq;
1265 s->clk = clk;
1266 s->base = base;
1267 s->timer = qemu_new_timer(vm_clock, omap_timer_tick, s);
1268 omap_mpu_timer_reset(s);
1269 omap_timer_clk_setup(s);
1270
1271 iomemtype = cpu_register_io_memory(0, omap_mpu_timer_readfn,
1272 omap_mpu_timer_writefn, s);
1273 cpu_register_physical_memory(s->base, 0x100, iomemtype);
1274
1275 return s;
1276}
1277
1278/* Watchdog timer */
1279struct omap_watchdog_timer_s {
1280 struct omap_mpu_timer_s timer;
1281 uint8_t last_wr;
1282 int mode;
1283 int free;
1284 int reset;
1285};
1286
1287static uint32_t omap_wd_timer_read(void *opaque, target_phys_addr_t addr)
1288{
1289 struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
1290 int offset = addr - s->timer.base;
1291
1292 switch (offset) {
1293 case 0x00: /* CNTL_TIMER */
1294 return (s->timer.ptv << 9) | (s->timer.ar << 8) |
1295 (s->timer.st << 7) | (s->free << 1);
1296
1297 case 0x04: /* READ_TIMER */
1298 return omap_timer_read(&s->timer);
1299
1300 case 0x08: /* TIMER_MODE */
1301 return s->mode << 15;
1302 }
1303
1304 OMAP_BAD_REG(addr);
1305 return 0;
1306}
1307
1308static void omap_wd_timer_write(void *opaque, target_phys_addr_t addr,
1309 uint32_t value)
1310{
1311 struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
1312 int offset = addr - s->timer.base;
1313
1314 switch (offset) {
1315 case 0x00: /* CNTL_TIMER */
1316 omap_timer_sync(&s->timer);
1317 s->timer.ptv = (value >> 9) & 7;
1318 s->timer.ar = (value >> 8) & 1;
1319 s->timer.st = (value >> 7) & 1;
1320 s->free = (value >> 1) & 1;
1321 omap_timer_update(&s->timer);
1322 break;
1323
1324 case 0x04: /* LOAD_TIMER */
1325 s->timer.reset_val = value & 0xffff;
1326 break;
1327
1328 case 0x08: /* TIMER_MODE */
1329 if (!s->mode && ((value >> 15) & 1))
1330 omap_clk_get(s->timer.clk);
1331 s->mode |= (value >> 15) & 1;
1332 if (s->last_wr == 0xf5) {
1333 if ((value & 0xff) == 0xa0) {
d8f699cb
AZ
1334 if (s->mode) {
1335 s->mode = 0;
1336 omap_clk_put(s->timer.clk);
1337 }
c3d2689d
AZ
1338 } else {
1339 /* XXX: on T|E hardware somehow this has no effect,
1340 * on Zire 71 it works as specified. */
1341 s->reset = 1;
1342 qemu_system_reset_request();
1343 }
1344 }
1345 s->last_wr = value & 0xff;
1346 break;
1347
1348 default:
1349 OMAP_BAD_REG(addr);
1350 }
1351}
1352
1353static CPUReadMemoryFunc *omap_wd_timer_readfn[] = {
1354 omap_badwidth_read16,
1355 omap_wd_timer_read,
1356 omap_badwidth_read16,
1357};
1358
1359static CPUWriteMemoryFunc *omap_wd_timer_writefn[] = {
1360 omap_badwidth_write16,
1361 omap_wd_timer_write,
1362 omap_badwidth_write16,
1363};
1364
1365static void omap_wd_timer_reset(struct omap_watchdog_timer_s *s)
1366{
1367 qemu_del_timer(s->timer.timer);
1368 if (!s->mode)
1369 omap_clk_get(s->timer.clk);
1370 s->mode = 1;
1371 s->free = 1;
1372 s->reset = 0;
1373 s->timer.enable = 1;
1374 s->timer.it_ena = 1;
1375 s->timer.reset_val = 0xffff;
1376 s->timer.val = 0;
1377 s->timer.st = 0;
1378 s->timer.ptv = 0;
1379 s->timer.ar = 0;
1380 omap_timer_update(&s->timer);
1381}
1382
1383struct omap_watchdog_timer_s *omap_wd_timer_init(target_phys_addr_t base,
1384 qemu_irq irq, omap_clk clk)
1385{
1386 int iomemtype;
1387 struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *)
1388 qemu_mallocz(sizeof(struct omap_watchdog_timer_s));
1389
1390 s->timer.irq = irq;
1391 s->timer.clk = clk;
1392 s->timer.base = base;
1393 s->timer.timer = qemu_new_timer(vm_clock, omap_timer_tick, &s->timer);
1394 omap_wd_timer_reset(s);
1395 omap_timer_clk_setup(&s->timer);
1396
1397 iomemtype = cpu_register_io_memory(0, omap_wd_timer_readfn,
1398 omap_wd_timer_writefn, s);
1399 cpu_register_physical_memory(s->timer.base, 0x100, iomemtype);
1400
1401 return s;
1402}
1403
1404/* 32-kHz timer */
1405struct omap_32khz_timer_s {
1406 struct omap_mpu_timer_s timer;
1407};
1408
1409static uint32_t omap_os_timer_read(void *opaque, target_phys_addr_t addr)
1410{
1411 struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
cf965d24 1412 int offset = addr & OMAP_MPUI_REG_MASK;
c3d2689d
AZ
1413
1414 switch (offset) {
1415 case 0x00: /* TVR */
1416 return s->timer.reset_val;
1417
1418 case 0x04: /* TCR */
1419 return omap_timer_read(&s->timer);
1420
1421 case 0x08: /* CR */
1422 return (s->timer.ar << 3) | (s->timer.it_ena << 2) | s->timer.st;
1423
1424 default:
1425 break;
1426 }
1427 OMAP_BAD_REG(addr);
1428 return 0;
1429}
1430
1431static void omap_os_timer_write(void *opaque, target_phys_addr_t addr,
1432 uint32_t value)
1433{
1434 struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
cf965d24 1435 int offset = addr & OMAP_MPUI_REG_MASK;
c3d2689d
AZ
1436
1437 switch (offset) {
1438 case 0x00: /* TVR */
1439 s->timer.reset_val = value & 0x00ffffff;
1440 break;
1441
1442 case 0x04: /* TCR */
1443 OMAP_RO_REG(addr);
1444 break;
1445
1446 case 0x08: /* CR */
1447 s->timer.ar = (value >> 3) & 1;
1448 s->timer.it_ena = (value >> 2) & 1;
1449 if (s->timer.st != (value & 1) || (value & 2)) {
1450 omap_timer_sync(&s->timer);
1451 s->timer.enable = value & 1;
1452 s->timer.st = value & 1;
1453 omap_timer_update(&s->timer);
1454 }
1455 break;
1456
1457 default:
1458 OMAP_BAD_REG(addr);
1459 }
1460}
1461
1462static CPUReadMemoryFunc *omap_os_timer_readfn[] = {
1463 omap_badwidth_read32,
1464 omap_badwidth_read32,
1465 omap_os_timer_read,
1466};
1467
1468static CPUWriteMemoryFunc *omap_os_timer_writefn[] = {
1469 omap_badwidth_write32,
1470 omap_badwidth_write32,
1471 omap_os_timer_write,
1472};
1473
1474static void omap_os_timer_reset(struct omap_32khz_timer_s *s)
1475{
1476 qemu_del_timer(s->timer.timer);
1477 s->timer.enable = 0;
1478 s->timer.it_ena = 0;
1479 s->timer.reset_val = 0x00ffffff;
1480 s->timer.val = 0;
1481 s->timer.st = 0;
1482 s->timer.ptv = 0;
1483 s->timer.ar = 1;
1484}
1485
1486struct omap_32khz_timer_s *omap_os_timer_init(target_phys_addr_t base,
1487 qemu_irq irq, omap_clk clk)
1488{
1489 int iomemtype;
1490 struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *)
1491 qemu_mallocz(sizeof(struct omap_32khz_timer_s));
1492
1493 s->timer.irq = irq;
1494 s->timer.clk = clk;
1495 s->timer.base = base;
1496 s->timer.timer = qemu_new_timer(vm_clock, omap_timer_tick, &s->timer);
1497 omap_os_timer_reset(s);
1498 omap_timer_clk_setup(&s->timer);
1499
1500 iomemtype = cpu_register_io_memory(0, omap_os_timer_readfn,
1501 omap_os_timer_writefn, s);
1502 cpu_register_physical_memory(s->timer.base, 0x800, iomemtype);
1503
1504 return s;
1505}
1506
1507/* Ultra Low-Power Device Module */
1508static uint32_t omap_ulpd_pm_read(void *opaque, target_phys_addr_t addr)
1509{
1510 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1511 int offset = addr - s->ulpd_pm_base;
1512 uint16_t ret;
1513
1514 switch (offset) {
1515 case 0x14: /* IT_STATUS */
1516 ret = s->ulpd_pm_regs[offset >> 2];
1517 s->ulpd_pm_regs[offset >> 2] = 0;
1518 qemu_irq_lower(s->irq[1][OMAP_INT_GAUGE_32K]);
1519 return ret;
1520
1521 case 0x18: /* Reserved */
1522 case 0x1c: /* Reserved */
1523 case 0x20: /* Reserved */
1524 case 0x28: /* Reserved */
1525 case 0x2c: /* Reserved */
1526 OMAP_BAD_REG(addr);
1527 case 0x00: /* COUNTER_32_LSB */
1528 case 0x04: /* COUNTER_32_MSB */
1529 case 0x08: /* COUNTER_HIGH_FREQ_LSB */
1530 case 0x0c: /* COUNTER_HIGH_FREQ_MSB */
1531 case 0x10: /* GAUGING_CTRL */
1532 case 0x24: /* SETUP_ANALOG_CELL3_ULPD1 */
1533 case 0x30: /* CLOCK_CTRL */
1534 case 0x34: /* SOFT_REQ */
1535 case 0x38: /* COUNTER_32_FIQ */
1536 case 0x3c: /* DPLL_CTRL */
1537 case 0x40: /* STATUS_REQ */
1538 /* XXX: check clk::usecount state for every clock */
1539 case 0x48: /* LOCL_TIME */
1540 case 0x4c: /* APLL_CTRL */
1541 case 0x50: /* POWER_CTRL */
1542 return s->ulpd_pm_regs[offset >> 2];
1543 }
1544
1545 OMAP_BAD_REG(addr);
1546 return 0;
1547}
1548
1549static inline void omap_ulpd_clk_update(struct omap_mpu_state_s *s,
1550 uint16_t diff, uint16_t value)
1551{
1552 if (diff & (1 << 4)) /* USB_MCLK_EN */
1553 omap_clk_onoff(omap_findclk(s, "usb_clk0"), (value >> 4) & 1);
1554 if (diff & (1 << 5)) /* DIS_USB_PVCI_CLK */
1555 omap_clk_onoff(omap_findclk(s, "usb_w2fc_ck"), (~value >> 5) & 1);
1556}
1557
1558static inline void omap_ulpd_req_update(struct omap_mpu_state_s *s,
1559 uint16_t diff, uint16_t value)
1560{
1561 if (diff & (1 << 0)) /* SOFT_DPLL_REQ */
1562 omap_clk_canidle(omap_findclk(s, "dpll4"), (~value >> 0) & 1);
1563 if (diff & (1 << 1)) /* SOFT_COM_REQ */
1564 omap_clk_canidle(omap_findclk(s, "com_mclk_out"), (~value >> 1) & 1);
1565 if (diff & (1 << 2)) /* SOFT_SDW_REQ */
1566 omap_clk_canidle(omap_findclk(s, "bt_mclk_out"), (~value >> 2) & 1);
1567 if (diff & (1 << 3)) /* SOFT_USB_REQ */
1568 omap_clk_canidle(omap_findclk(s, "usb_clk0"), (~value >> 3) & 1);
1569}
1570
1571static void omap_ulpd_pm_write(void *opaque, target_phys_addr_t addr,
1572 uint32_t value)
1573{
1574 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1575 int offset = addr - s->ulpd_pm_base;
1576 int64_t now, ticks;
1577 int div, mult;
1578 static const int bypass_div[4] = { 1, 2, 4, 4 };
1579 uint16_t diff;
1580
1581 switch (offset) {
1582 case 0x00: /* COUNTER_32_LSB */
1583 case 0x04: /* COUNTER_32_MSB */
1584 case 0x08: /* COUNTER_HIGH_FREQ_LSB */
1585 case 0x0c: /* COUNTER_HIGH_FREQ_MSB */
1586 case 0x14: /* IT_STATUS */
1587 case 0x40: /* STATUS_REQ */
1588 OMAP_RO_REG(addr);
1589 break;
1590
1591 case 0x10: /* GAUGING_CTRL */
1592 /* Bits 0 and 1 seem to be confused in the OMAP 310 TRM */
1593 if ((s->ulpd_pm_regs[offset >> 2] ^ value) & 1) {
1594 now = qemu_get_clock(vm_clock);
1595
1596 if (value & 1)
1597 s->ulpd_gauge_start = now;
1598 else {
1599 now -= s->ulpd_gauge_start;
1600
1601 /* 32-kHz ticks */
1602 ticks = muldiv64(now, 32768, ticks_per_sec);
1603 s->ulpd_pm_regs[0x00 >> 2] = (ticks >> 0) & 0xffff;
1604 s->ulpd_pm_regs[0x04 >> 2] = (ticks >> 16) & 0xffff;
1605 if (ticks >> 32) /* OVERFLOW_32K */
1606 s->ulpd_pm_regs[0x14 >> 2] |= 1 << 2;
1607
1608 /* High frequency ticks */
1609 ticks = muldiv64(now, 12000000, ticks_per_sec);
1610 s->ulpd_pm_regs[0x08 >> 2] = (ticks >> 0) & 0xffff;
1611 s->ulpd_pm_regs[0x0c >> 2] = (ticks >> 16) & 0xffff;
1612 if (ticks >> 32) /* OVERFLOW_HI_FREQ */
1613 s->ulpd_pm_regs[0x14 >> 2] |= 1 << 1;
1614
1615 s->ulpd_pm_regs[0x14 >> 2] |= 1 << 0; /* IT_GAUGING */
1616 qemu_irq_raise(s->irq[1][OMAP_INT_GAUGE_32K]);
1617 }
1618 }
1619 s->ulpd_pm_regs[offset >> 2] = value;
1620 break;
1621
1622 case 0x18: /* Reserved */
1623 case 0x1c: /* Reserved */
1624 case 0x20: /* Reserved */
1625 case 0x28: /* Reserved */
1626 case 0x2c: /* Reserved */
1627 OMAP_BAD_REG(addr);
1628 case 0x24: /* SETUP_ANALOG_CELL3_ULPD1 */
1629 case 0x38: /* COUNTER_32_FIQ */
1630 case 0x48: /* LOCL_TIME */
1631 case 0x50: /* POWER_CTRL */
1632 s->ulpd_pm_regs[offset >> 2] = value;
1633 break;
1634
1635 case 0x30: /* CLOCK_CTRL */
1636 diff = s->ulpd_pm_regs[offset >> 2] ^ value;
1637 s->ulpd_pm_regs[offset >> 2] = value & 0x3f;
1638 omap_ulpd_clk_update(s, diff, value);
1639 break;
1640
1641 case 0x34: /* SOFT_REQ */
1642 diff = s->ulpd_pm_regs[offset >> 2] ^ value;
1643 s->ulpd_pm_regs[offset >> 2] = value & 0x1f;
1644 omap_ulpd_req_update(s, diff, value);
1645 break;
1646
1647 case 0x3c: /* DPLL_CTRL */
1648 /* XXX: OMAP310 TRM claims bit 3 is PLL_ENABLE, and bit 4 is
1649 * omitted altogether, probably a typo. */
1650 /* This register has identical semantics with DPLL(1:3) control
1651 * registers, see omap_dpll_write() */
1652 diff = s->ulpd_pm_regs[offset >> 2] & value;
1653 s->ulpd_pm_regs[offset >> 2] = value & 0x2fff;
1654 if (diff & (0x3ff << 2)) {
1655 if (value & (1 << 4)) { /* PLL_ENABLE */
1656 div = ((value >> 5) & 3) + 1; /* PLL_DIV */
1657 mult = MIN((value >> 7) & 0x1f, 1); /* PLL_MULT */
1658 } else {
1659 div = bypass_div[((value >> 2) & 3)]; /* BYPASS_DIV */
1660 mult = 1;
1661 }
1662 omap_clk_setrate(omap_findclk(s, "dpll4"), div, mult);
1663 }
1664
1665 /* Enter the desired mode. */
1666 s->ulpd_pm_regs[offset >> 2] =
1667 (s->ulpd_pm_regs[offset >> 2] & 0xfffe) |
1668 ((s->ulpd_pm_regs[offset >> 2] >> 4) & 1);
1669
1670 /* Act as if the lock is restored. */
1671 s->ulpd_pm_regs[offset >> 2] |= 2;
1672 break;
1673
1674 case 0x4c: /* APLL_CTRL */
1675 diff = s->ulpd_pm_regs[offset >> 2] & value;
1676 s->ulpd_pm_regs[offset >> 2] = value & 0xf;
1677 if (diff & (1 << 0)) /* APLL_NDPLL_SWITCH */
1678 omap_clk_reparent(omap_findclk(s, "ck_48m"), omap_findclk(s,
1679 (value & (1 << 0)) ? "apll" : "dpll4"));
1680 break;
1681
1682 default:
1683 OMAP_BAD_REG(addr);
1684 }
1685}
1686
1687static CPUReadMemoryFunc *omap_ulpd_pm_readfn[] = {
1688 omap_badwidth_read16,
1689 omap_ulpd_pm_read,
1690 omap_badwidth_read16,
1691};
1692
1693static CPUWriteMemoryFunc *omap_ulpd_pm_writefn[] = {
1694 omap_badwidth_write16,
1695 omap_ulpd_pm_write,
1696 omap_badwidth_write16,
1697};
1698
1699static void omap_ulpd_pm_reset(struct omap_mpu_state_s *mpu)
1700{
1701 mpu->ulpd_pm_regs[0x00 >> 2] = 0x0001;
1702 mpu->ulpd_pm_regs[0x04 >> 2] = 0x0000;
1703 mpu->ulpd_pm_regs[0x08 >> 2] = 0x0001;
1704 mpu->ulpd_pm_regs[0x0c >> 2] = 0x0000;
1705 mpu->ulpd_pm_regs[0x10 >> 2] = 0x0000;
1706 mpu->ulpd_pm_regs[0x18 >> 2] = 0x01;
1707 mpu->ulpd_pm_regs[0x1c >> 2] = 0x01;
1708 mpu->ulpd_pm_regs[0x20 >> 2] = 0x01;
1709 mpu->ulpd_pm_regs[0x24 >> 2] = 0x03ff;
1710 mpu->ulpd_pm_regs[0x28 >> 2] = 0x01;
1711 mpu->ulpd_pm_regs[0x2c >> 2] = 0x01;
1712 omap_ulpd_clk_update(mpu, mpu->ulpd_pm_regs[0x30 >> 2], 0x0000);
1713 mpu->ulpd_pm_regs[0x30 >> 2] = 0x0000;
1714 omap_ulpd_req_update(mpu, mpu->ulpd_pm_regs[0x34 >> 2], 0x0000);
1715 mpu->ulpd_pm_regs[0x34 >> 2] = 0x0000;
1716 mpu->ulpd_pm_regs[0x38 >> 2] = 0x0001;
1717 mpu->ulpd_pm_regs[0x3c >> 2] = 0x2211;
1718 mpu->ulpd_pm_regs[0x40 >> 2] = 0x0000; /* FIXME: dump a real STATUS_REQ */
1719 mpu->ulpd_pm_regs[0x48 >> 2] = 0x960;
1720 mpu->ulpd_pm_regs[0x4c >> 2] = 0x08;
1721 mpu->ulpd_pm_regs[0x50 >> 2] = 0x08;
1722 omap_clk_setrate(omap_findclk(mpu, "dpll4"), 1, 4);
1723 omap_clk_reparent(omap_findclk(mpu, "ck_48m"), omap_findclk(mpu, "dpll4"));
1724}
1725
1726static void omap_ulpd_pm_init(target_phys_addr_t base,
1727 struct omap_mpu_state_s *mpu)
1728{
1729 int iomemtype = cpu_register_io_memory(0, omap_ulpd_pm_readfn,
1730 omap_ulpd_pm_writefn, mpu);
1731
1732 mpu->ulpd_pm_base = base;
1733 cpu_register_physical_memory(mpu->ulpd_pm_base, 0x800, iomemtype);
1734 omap_ulpd_pm_reset(mpu);
1735}
1736
1737/* OMAP Pin Configuration */
1738static uint32_t omap_pin_cfg_read(void *opaque, target_phys_addr_t addr)
1739{
1740 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1741 int offset = addr - s->pin_cfg_base;
1742
1743 switch (offset) {
1744 case 0x00: /* FUNC_MUX_CTRL_0 */
1745 case 0x04: /* FUNC_MUX_CTRL_1 */
1746 case 0x08: /* FUNC_MUX_CTRL_2 */
1747 return s->func_mux_ctrl[offset >> 2];
1748
1749 case 0x0c: /* COMP_MODE_CTRL_0 */
1750 return s->comp_mode_ctrl[0];
1751
1752 case 0x10: /* FUNC_MUX_CTRL_3 */
1753 case 0x14: /* FUNC_MUX_CTRL_4 */
1754 case 0x18: /* FUNC_MUX_CTRL_5 */
1755 case 0x1c: /* FUNC_MUX_CTRL_6 */
1756 case 0x20: /* FUNC_MUX_CTRL_7 */
1757 case 0x24: /* FUNC_MUX_CTRL_8 */
1758 case 0x28: /* FUNC_MUX_CTRL_9 */
1759 case 0x2c: /* FUNC_MUX_CTRL_A */
1760 case 0x30: /* FUNC_MUX_CTRL_B */
1761 case 0x34: /* FUNC_MUX_CTRL_C */
1762 case 0x38: /* FUNC_MUX_CTRL_D */
1763 return s->func_mux_ctrl[(offset >> 2) - 1];
1764
1765 case 0x40: /* PULL_DWN_CTRL_0 */
1766 case 0x44: /* PULL_DWN_CTRL_1 */
1767 case 0x48: /* PULL_DWN_CTRL_2 */
1768 case 0x4c: /* PULL_DWN_CTRL_3 */
1769 return s->pull_dwn_ctrl[(offset & 0xf) >> 2];
1770
1771 case 0x50: /* GATE_INH_CTRL_0 */
1772 return s->gate_inh_ctrl[0];
1773
1774 case 0x60: /* VOLTAGE_CTRL_0 */
1775 return s->voltage_ctrl[0];
1776
1777 case 0x70: /* TEST_DBG_CTRL_0 */
1778 return s->test_dbg_ctrl[0];
1779
1780 case 0x80: /* MOD_CONF_CTRL_0 */
1781 return s->mod_conf_ctrl[0];
1782 }
1783
1784 OMAP_BAD_REG(addr);
1785 return 0;
1786}
1787
1788static inline void omap_pin_funcmux0_update(struct omap_mpu_state_s *s,
1789 uint32_t diff, uint32_t value)
1790{
1791 if (s->compat1509) {
1792 if (diff & (1 << 9)) /* BLUETOOTH */
1793 omap_clk_onoff(omap_findclk(s, "bt_mclk_out"),
1794 (~value >> 9) & 1);
1795 if (diff & (1 << 7)) /* USB.CLKO */
1796 omap_clk_onoff(omap_findclk(s, "usb.clko"),
1797 (value >> 7) & 1);
1798 }
1799}
1800
1801static inline void omap_pin_funcmux1_update(struct omap_mpu_state_s *s,
1802 uint32_t diff, uint32_t value)
1803{
1804 if (s->compat1509) {
1805 if (diff & (1 << 31)) /* MCBSP3_CLK_HIZ_DI */
1806 omap_clk_onoff(omap_findclk(s, "mcbsp3.clkx"),
1807 (value >> 31) & 1);
1808 if (diff & (1 << 1)) /* CLK32K */
1809 omap_clk_onoff(omap_findclk(s, "clk32k_out"),
1810 (~value >> 1) & 1);
1811 }
1812}
1813
1814static inline void omap_pin_modconf1_update(struct omap_mpu_state_s *s,
1815 uint32_t diff, uint32_t value)
1816{
1817 if (diff & (1 << 31)) /* CONF_MOD_UART3_CLK_MODE_R */
1818 omap_clk_reparent(omap_findclk(s, "uart3_ck"),
1819 omap_findclk(s, ((value >> 31) & 1) ?
1820 "ck_48m" : "armper_ck"));
1821 if (diff & (1 << 30)) /* CONF_MOD_UART2_CLK_MODE_R */
1822 omap_clk_reparent(omap_findclk(s, "uart2_ck"),
1823 omap_findclk(s, ((value >> 30) & 1) ?
1824 "ck_48m" : "armper_ck"));
1825 if (diff & (1 << 29)) /* CONF_MOD_UART1_CLK_MODE_R */
1826 omap_clk_reparent(omap_findclk(s, "uart1_ck"),
1827 omap_findclk(s, ((value >> 29) & 1) ?
1828 "ck_48m" : "armper_ck"));
1829 if (diff & (1 << 23)) /* CONF_MOD_MMC_SD_CLK_REQ_R */
1830 omap_clk_reparent(omap_findclk(s, "mmc_ck"),
1831 omap_findclk(s, ((value >> 23) & 1) ?
1832 "ck_48m" : "armper_ck"));
1833 if (diff & (1 << 12)) /* CONF_MOD_COM_MCLK_12_48_S */
1834 omap_clk_reparent(omap_findclk(s, "com_mclk_out"),
1835 omap_findclk(s, ((value >> 12) & 1) ?
1836 "ck_48m" : "armper_ck"));
1837 if (diff & (1 << 9)) /* CONF_MOD_USB_HOST_HHC_UHO */
1838 omap_clk_onoff(omap_findclk(s, "usb_hhc_ck"), (value >> 9) & 1);
1839}
1840
1841static void omap_pin_cfg_write(void *opaque, target_phys_addr_t addr,
1842 uint32_t value)
1843{
1844 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1845 int offset = addr - s->pin_cfg_base;
1846 uint32_t diff;
1847
1848 switch (offset) {
1849 case 0x00: /* FUNC_MUX_CTRL_0 */
1850 diff = s->func_mux_ctrl[offset >> 2] ^ value;
1851 s->func_mux_ctrl[offset >> 2] = value;
1852 omap_pin_funcmux0_update(s, diff, value);
1853 return;
1854
1855 case 0x04: /* FUNC_MUX_CTRL_1 */
1856 diff = s->func_mux_ctrl[offset >> 2] ^ value;
1857 s->func_mux_ctrl[offset >> 2] = value;
1858 omap_pin_funcmux1_update(s, diff, value);
1859 return;
1860
1861 case 0x08: /* FUNC_MUX_CTRL_2 */
1862 s->func_mux_ctrl[offset >> 2] = value;
1863 return;
1864
1865 case 0x0c: /* COMP_MODE_CTRL_0 */
1866 s->comp_mode_ctrl[0] = value;
1867 s->compat1509 = (value != 0x0000eaef);
1868 omap_pin_funcmux0_update(s, ~0, s->func_mux_ctrl[0]);
1869 omap_pin_funcmux1_update(s, ~0, s->func_mux_ctrl[1]);
1870 return;
1871
1872 case 0x10: /* FUNC_MUX_CTRL_3 */
1873 case 0x14: /* FUNC_MUX_CTRL_4 */
1874 case 0x18: /* FUNC_MUX_CTRL_5 */
1875 case 0x1c: /* FUNC_MUX_CTRL_6 */
1876 case 0x20: /* FUNC_MUX_CTRL_7 */
1877 case 0x24: /* FUNC_MUX_CTRL_8 */
1878 case 0x28: /* FUNC_MUX_CTRL_9 */
1879 case 0x2c: /* FUNC_MUX_CTRL_A */
1880 case 0x30: /* FUNC_MUX_CTRL_B */
1881 case 0x34: /* FUNC_MUX_CTRL_C */
1882 case 0x38: /* FUNC_MUX_CTRL_D */
1883 s->func_mux_ctrl[(offset >> 2) - 1] = value;
1884 return;
1885
1886 case 0x40: /* PULL_DWN_CTRL_0 */
1887 case 0x44: /* PULL_DWN_CTRL_1 */
1888 case 0x48: /* PULL_DWN_CTRL_2 */
1889 case 0x4c: /* PULL_DWN_CTRL_3 */
1890 s->pull_dwn_ctrl[(offset & 0xf) >> 2] = value;
1891 return;
1892
1893 case 0x50: /* GATE_INH_CTRL_0 */
1894 s->gate_inh_ctrl[0] = value;
1895 return;
1896
1897 case 0x60: /* VOLTAGE_CTRL_0 */
1898 s->voltage_ctrl[0] = value;
1899 return;
1900
1901 case 0x70: /* TEST_DBG_CTRL_0 */
1902 s->test_dbg_ctrl[0] = value;
1903 return;
1904
1905 case 0x80: /* MOD_CONF_CTRL_0 */
1906 diff = s->mod_conf_ctrl[0] ^ value;
1907 s->mod_conf_ctrl[0] = value;
1908 omap_pin_modconf1_update(s, diff, value);
1909 return;
1910
1911 default:
1912 OMAP_BAD_REG(addr);
1913 }
1914}
1915
1916static CPUReadMemoryFunc *omap_pin_cfg_readfn[] = {
1917 omap_badwidth_read32,
1918 omap_badwidth_read32,
1919 omap_pin_cfg_read,
1920};
1921
1922static CPUWriteMemoryFunc *omap_pin_cfg_writefn[] = {
1923 omap_badwidth_write32,
1924 omap_badwidth_write32,
1925 omap_pin_cfg_write,
1926};
1927
1928static void omap_pin_cfg_reset(struct omap_mpu_state_s *mpu)
1929{
1930 /* Start in Compatibility Mode. */
1931 mpu->compat1509 = 1;
1932 omap_pin_funcmux0_update(mpu, mpu->func_mux_ctrl[0], 0);
1933 omap_pin_funcmux1_update(mpu, mpu->func_mux_ctrl[1], 0);
1934 omap_pin_modconf1_update(mpu, mpu->mod_conf_ctrl[0], 0);
1935 memset(mpu->func_mux_ctrl, 0, sizeof(mpu->func_mux_ctrl));
1936 memset(mpu->comp_mode_ctrl, 0, sizeof(mpu->comp_mode_ctrl));
1937 memset(mpu->pull_dwn_ctrl, 0, sizeof(mpu->pull_dwn_ctrl));
1938 memset(mpu->gate_inh_ctrl, 0, sizeof(mpu->gate_inh_ctrl));
1939 memset(mpu->voltage_ctrl, 0, sizeof(mpu->voltage_ctrl));
1940 memset(mpu->test_dbg_ctrl, 0, sizeof(mpu->test_dbg_ctrl));
1941 memset(mpu->mod_conf_ctrl, 0, sizeof(mpu->mod_conf_ctrl));
1942}
1943
1944static void omap_pin_cfg_init(target_phys_addr_t base,
1945 struct omap_mpu_state_s *mpu)
1946{
1947 int iomemtype = cpu_register_io_memory(0, omap_pin_cfg_readfn,
1948 omap_pin_cfg_writefn, mpu);
1949
1950 mpu->pin_cfg_base = base;
1951 cpu_register_physical_memory(mpu->pin_cfg_base, 0x800, iomemtype);
1952 omap_pin_cfg_reset(mpu);
1953}
1954
1955/* Device Identification, Die Identification */
1956static uint32_t omap_id_read(void *opaque, target_phys_addr_t addr)
1957{
1958 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1959
1960 switch (addr) {
1961 case 0xfffe1800: /* DIE_ID_LSB */
1962 return 0xc9581f0e;
1963 case 0xfffe1804: /* DIE_ID_MSB */
1964 return 0xa8858bfa;
1965
1966 case 0xfffe2000: /* PRODUCT_ID_LSB */
1967 return 0x00aaaafc;
1968 case 0xfffe2004: /* PRODUCT_ID_MSB */
1969 return 0xcafeb574;
1970
1971 case 0xfffed400: /* JTAG_ID_LSB */
1972 switch (s->mpu_model) {
1973 case omap310:
1974 return 0x03310315;
1975 case omap1510:
1976 return 0x03310115;
1977 }
1978 break;
1979
1980 case 0xfffed404: /* JTAG_ID_MSB */
1981 switch (s->mpu_model) {
1982 case omap310:
1983 return 0xfb57402f;
1984 case omap1510:
1985 return 0xfb47002f;
1986 }
1987 break;
1988 }
1989
1990 OMAP_BAD_REG(addr);
1991 return 0;
1992}
1993
1994static void omap_id_write(void *opaque, target_phys_addr_t addr,
1995 uint32_t value)
1996{
1997 OMAP_BAD_REG(addr);
1998}
1999
2000static CPUReadMemoryFunc *omap_id_readfn[] = {
2001 omap_badwidth_read32,
2002 omap_badwidth_read32,
2003 omap_id_read,
2004};
2005
2006static CPUWriteMemoryFunc *omap_id_writefn[] = {
2007 omap_badwidth_write32,
2008 omap_badwidth_write32,
2009 omap_id_write,
2010};
2011
2012static void omap_id_init(struct omap_mpu_state_s *mpu)
2013{
2014 int iomemtype = cpu_register_io_memory(0, omap_id_readfn,
2015 omap_id_writefn, mpu);
2016 cpu_register_physical_memory(0xfffe1800, 0x800, iomemtype);
2017 cpu_register_physical_memory(0xfffed400, 0x100, iomemtype);
2018 if (!cpu_is_omap15xx(mpu))
2019 cpu_register_physical_memory(0xfffe2000, 0x800, iomemtype);
2020}
2021
2022/* MPUI Control (Dummy) */
2023static uint32_t omap_mpui_read(void *opaque, target_phys_addr_t addr)
2024{
2025 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2026 int offset = addr - s->mpui_base;
2027
2028 switch (offset) {
2029 case 0x00: /* CTRL */
2030 return s->mpui_ctrl;
2031 case 0x04: /* DEBUG_ADDR */
2032 return 0x01ffffff;
2033 case 0x08: /* DEBUG_DATA */
2034 return 0xffffffff;
2035 case 0x0c: /* DEBUG_FLAG */
2036 return 0x00000800;
2037 case 0x10: /* STATUS */
2038 return 0x00000000;
2039
2040 /* Not in OMAP310 */
2041 case 0x14: /* DSP_STATUS */
2042 case 0x18: /* DSP_BOOT_CONFIG */
2043 return 0x00000000;
2044 case 0x1c: /* DSP_MPUI_CONFIG */
2045 return 0x0000ffff;
2046 }
2047
2048 OMAP_BAD_REG(addr);
2049 return 0;
2050}
2051
2052static void omap_mpui_write(void *opaque, target_phys_addr_t addr,
2053 uint32_t value)
2054{
2055 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2056 int offset = addr - s->mpui_base;
2057
2058 switch (offset) {
2059 case 0x00: /* CTRL */
2060 s->mpui_ctrl = value & 0x007fffff;
2061 break;
2062
2063 case 0x04: /* DEBUG_ADDR */
2064 case 0x08: /* DEBUG_DATA */
2065 case 0x0c: /* DEBUG_FLAG */
2066 case 0x10: /* STATUS */
2067 /* Not in OMAP310 */
2068 case 0x14: /* DSP_STATUS */
2069 OMAP_RO_REG(addr);
2070 case 0x18: /* DSP_BOOT_CONFIG */
2071 case 0x1c: /* DSP_MPUI_CONFIG */
2072 break;
2073
2074 default:
2075 OMAP_BAD_REG(addr);
2076 }
2077}
2078
2079static CPUReadMemoryFunc *omap_mpui_readfn[] = {
2080 omap_badwidth_read32,
2081 omap_badwidth_read32,
2082 omap_mpui_read,
2083};
2084
2085static CPUWriteMemoryFunc *omap_mpui_writefn[] = {
2086 omap_badwidth_write32,
2087 omap_badwidth_write32,
2088 omap_mpui_write,
2089};
2090
2091static void omap_mpui_reset(struct omap_mpu_state_s *s)
2092{
2093 s->mpui_ctrl = 0x0003ff1b;
2094}
2095
2096static void omap_mpui_init(target_phys_addr_t base,
2097 struct omap_mpu_state_s *mpu)
2098{
2099 int iomemtype = cpu_register_io_memory(0, omap_mpui_readfn,
2100 omap_mpui_writefn, mpu);
2101
2102 mpu->mpui_base = base;
2103 cpu_register_physical_memory(mpu->mpui_base, 0x100, iomemtype);
2104
2105 omap_mpui_reset(mpu);
2106}
2107
2108/* TIPB Bridges */
2109struct omap_tipb_bridge_s {
2110 target_phys_addr_t base;
2111 qemu_irq abort;
2112
2113 int width_intr;
2114 uint16_t control;
2115 uint16_t alloc;
2116 uint16_t buffer;
2117 uint16_t enh_control;
2118};
2119
2120static uint32_t omap_tipb_bridge_read(void *opaque, target_phys_addr_t addr)
2121{
2122 struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
2123 int offset = addr - s->base;
2124
2125 switch (offset) {
2126 case 0x00: /* TIPB_CNTL */
2127 return s->control;
2128 case 0x04: /* TIPB_BUS_ALLOC */
2129 return s->alloc;
2130 case 0x08: /* MPU_TIPB_CNTL */
2131 return s->buffer;
2132 case 0x0c: /* ENHANCED_TIPB_CNTL */
2133 return s->enh_control;
2134 case 0x10: /* ADDRESS_DBG */
2135 case 0x14: /* DATA_DEBUG_LOW */
2136 case 0x18: /* DATA_DEBUG_HIGH */
2137 return 0xffff;
2138 case 0x1c: /* DEBUG_CNTR_SIG */
2139 return 0x00f8;
2140 }
2141
2142 OMAP_BAD_REG(addr);
2143 return 0;
2144}
2145
2146static void omap_tipb_bridge_write(void *opaque, target_phys_addr_t addr,
2147 uint32_t value)
2148{
2149 struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
2150 int offset = addr - s->base;
2151
2152 switch (offset) {
2153 case 0x00: /* TIPB_CNTL */
2154 s->control = value & 0xffff;
2155 break;
2156
2157 case 0x04: /* TIPB_BUS_ALLOC */
2158 s->alloc = value & 0x003f;
2159 break;
2160
2161 case 0x08: /* MPU_TIPB_CNTL */
2162 s->buffer = value & 0x0003;
2163 break;
2164
2165 case 0x0c: /* ENHANCED_TIPB_CNTL */
2166 s->width_intr = !(value & 2);
2167 s->enh_control = value & 0x000f;
2168 break;
2169
2170 case 0x10: /* ADDRESS_DBG */
2171 case 0x14: /* DATA_DEBUG_LOW */
2172 case 0x18: /* DATA_DEBUG_HIGH */
2173 case 0x1c: /* DEBUG_CNTR_SIG */
2174 OMAP_RO_REG(addr);
2175 break;
2176
2177 default:
2178 OMAP_BAD_REG(addr);
2179 }
2180}
2181
2182static CPUReadMemoryFunc *omap_tipb_bridge_readfn[] = {
2183 omap_badwidth_read16,
2184 omap_tipb_bridge_read,
2185 omap_tipb_bridge_read,
2186};
2187
2188static CPUWriteMemoryFunc *omap_tipb_bridge_writefn[] = {
2189 omap_badwidth_write16,
2190 omap_tipb_bridge_write,
2191 omap_tipb_bridge_write,
2192};
2193
2194static void omap_tipb_bridge_reset(struct omap_tipb_bridge_s *s)
2195{
2196 s->control = 0xffff;
2197 s->alloc = 0x0009;
2198 s->buffer = 0x0000;
2199 s->enh_control = 0x000f;
2200}
2201
2202struct omap_tipb_bridge_s *omap_tipb_bridge_init(target_phys_addr_t base,
2203 qemu_irq abort_irq, omap_clk clk)
2204{
2205 int iomemtype;
2206 struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *)
2207 qemu_mallocz(sizeof(struct omap_tipb_bridge_s));
2208
2209 s->abort = abort_irq;
2210 s->base = base;
2211 omap_tipb_bridge_reset(s);
2212
2213 iomemtype = cpu_register_io_memory(0, omap_tipb_bridge_readfn,
2214 omap_tipb_bridge_writefn, s);
2215 cpu_register_physical_memory(s->base, 0x100, iomemtype);
2216
2217 return s;
2218}
2219
2220/* Dummy Traffic Controller's Memory Interface */
2221static uint32_t omap_tcmi_read(void *opaque, target_phys_addr_t addr)
2222{
2223 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2224 int offset = addr - s->tcmi_base;
2225 uint32_t ret;
2226
2227 switch (offset) {
d8f699cb
AZ
2228 case 0x00: /* IMIF_PRIO */
2229 case 0x04: /* EMIFS_PRIO */
2230 case 0x08: /* EMIFF_PRIO */
2231 case 0x0c: /* EMIFS_CONFIG */
2232 case 0x10: /* EMIFS_CS0_CONFIG */
2233 case 0x14: /* EMIFS_CS1_CONFIG */
2234 case 0x18: /* EMIFS_CS2_CONFIG */
2235 case 0x1c: /* EMIFS_CS3_CONFIG */
2236 case 0x24: /* EMIFF_MRS */
2237 case 0x28: /* TIMEOUT1 */
2238 case 0x2c: /* TIMEOUT2 */
2239 case 0x30: /* TIMEOUT3 */
2240 case 0x3c: /* EMIFF_SDRAM_CONFIG_2 */
2241 case 0x40: /* EMIFS_CFG_DYN_WAIT */
c3d2689d
AZ
2242 return s->tcmi_regs[offset >> 2];
2243
d8f699cb 2244 case 0x20: /* EMIFF_SDRAM_CONFIG */
c3d2689d
AZ
2245 ret = s->tcmi_regs[offset >> 2];
2246 s->tcmi_regs[offset >> 2] &= ~1; /* XXX: Clear SLRF on SDRAM access */
2247 /* XXX: We can try using the VGA_DIRTY flag for this */
2248 return ret;
2249 }
2250
2251 OMAP_BAD_REG(addr);
2252 return 0;
2253}
2254
2255static void omap_tcmi_write(void *opaque, target_phys_addr_t addr,
2256 uint32_t value)
2257{
2258 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2259 int offset = addr - s->tcmi_base;
2260
2261 switch (offset) {
d8f699cb
AZ
2262 case 0x00: /* IMIF_PRIO */
2263 case 0x04: /* EMIFS_PRIO */
2264 case 0x08: /* EMIFF_PRIO */
2265 case 0x10: /* EMIFS_CS0_CONFIG */
2266 case 0x14: /* EMIFS_CS1_CONFIG */
2267 case 0x18: /* EMIFS_CS2_CONFIG */
2268 case 0x1c: /* EMIFS_CS3_CONFIG */
2269 case 0x20: /* EMIFF_SDRAM_CONFIG */
2270 case 0x24: /* EMIFF_MRS */
2271 case 0x28: /* TIMEOUT1 */
2272 case 0x2c: /* TIMEOUT2 */
2273 case 0x30: /* TIMEOUT3 */
2274 case 0x3c: /* EMIFF_SDRAM_CONFIG_2 */
2275 case 0x40: /* EMIFS_CFG_DYN_WAIT */
c3d2689d
AZ
2276 s->tcmi_regs[offset >> 2] = value;
2277 break;
d8f699cb 2278 case 0x0c: /* EMIFS_CONFIG */
c3d2689d
AZ
2279 s->tcmi_regs[offset >> 2] = (value & 0xf) | (1 << 4);
2280 break;
2281
2282 default:
2283 OMAP_BAD_REG(addr);
2284 }
2285}
2286
2287static CPUReadMemoryFunc *omap_tcmi_readfn[] = {
2288 omap_badwidth_read32,
2289 omap_badwidth_read32,
2290 omap_tcmi_read,
2291};
2292
2293static CPUWriteMemoryFunc *omap_tcmi_writefn[] = {
2294 omap_badwidth_write32,
2295 omap_badwidth_write32,
2296 omap_tcmi_write,
2297};
2298
2299static void omap_tcmi_reset(struct omap_mpu_state_s *mpu)
2300{
2301 mpu->tcmi_regs[0x00 >> 2] = 0x00000000;
2302 mpu->tcmi_regs[0x04 >> 2] = 0x00000000;
2303 mpu->tcmi_regs[0x08 >> 2] = 0x00000000;
2304 mpu->tcmi_regs[0x0c >> 2] = 0x00000010;
2305 mpu->tcmi_regs[0x10 >> 2] = 0x0010fffb;
2306 mpu->tcmi_regs[0x14 >> 2] = 0x0010fffb;
2307 mpu->tcmi_regs[0x18 >> 2] = 0x0010fffb;
2308 mpu->tcmi_regs[0x1c >> 2] = 0x0010fffb;
2309 mpu->tcmi_regs[0x20 >> 2] = 0x00618800;
2310 mpu->tcmi_regs[0x24 >> 2] = 0x00000037;
2311 mpu->tcmi_regs[0x28 >> 2] = 0x00000000;
2312 mpu->tcmi_regs[0x2c >> 2] = 0x00000000;
2313 mpu->tcmi_regs[0x30 >> 2] = 0x00000000;
2314 mpu->tcmi_regs[0x3c >> 2] = 0x00000003;
2315 mpu->tcmi_regs[0x40 >> 2] = 0x00000000;
2316}
2317
2318static void omap_tcmi_init(target_phys_addr_t base,
2319 struct omap_mpu_state_s *mpu)
2320{
2321 int iomemtype = cpu_register_io_memory(0, omap_tcmi_readfn,
2322 omap_tcmi_writefn, mpu);
2323
2324 mpu->tcmi_base = base;
2325 cpu_register_physical_memory(mpu->tcmi_base, 0x100, iomemtype);
2326 omap_tcmi_reset(mpu);
2327}
2328
2329/* Digital phase-locked loops control */
2330static uint32_t omap_dpll_read(void *opaque, target_phys_addr_t addr)
2331{
2332 struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
2333 int offset = addr - s->base;
2334
2335 if (offset == 0x00) /* CTL_REG */
2336 return s->mode;
2337
2338 OMAP_BAD_REG(addr);
2339 return 0;
2340}
2341
2342static void omap_dpll_write(void *opaque, target_phys_addr_t addr,
2343 uint32_t value)
2344{
2345 struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
2346 uint16_t diff;
2347 int offset = addr - s->base;
2348 static const int bypass_div[4] = { 1, 2, 4, 4 };
2349 int div, mult;
2350
2351 if (offset == 0x00) { /* CTL_REG */
2352 /* See omap_ulpd_pm_write() too */
2353 diff = s->mode & value;
2354 s->mode = value & 0x2fff;
2355 if (diff & (0x3ff << 2)) {
2356 if (value & (1 << 4)) { /* PLL_ENABLE */
2357 div = ((value >> 5) & 3) + 1; /* PLL_DIV */
2358 mult = MIN((value >> 7) & 0x1f, 1); /* PLL_MULT */
2359 } else {
2360 div = bypass_div[((value >> 2) & 3)]; /* BYPASS_DIV */
2361 mult = 1;
2362 }
2363 omap_clk_setrate(s->dpll, div, mult);
2364 }
2365
2366 /* Enter the desired mode. */
2367 s->mode = (s->mode & 0xfffe) | ((s->mode >> 4) & 1);
2368
2369 /* Act as if the lock is restored. */
2370 s->mode |= 2;
2371 } else {
2372 OMAP_BAD_REG(addr);
2373 }
2374}
2375
2376static CPUReadMemoryFunc *omap_dpll_readfn[] = {
2377 omap_badwidth_read16,
2378 omap_dpll_read,
2379 omap_badwidth_read16,
2380};
2381
2382static CPUWriteMemoryFunc *omap_dpll_writefn[] = {
2383 omap_badwidth_write16,
2384 omap_dpll_write,
2385 omap_badwidth_write16,
2386};
2387
2388static void omap_dpll_reset(struct dpll_ctl_s *s)
2389{
2390 s->mode = 0x2002;
2391 omap_clk_setrate(s->dpll, 1, 1);
2392}
2393
2394static void omap_dpll_init(struct dpll_ctl_s *s, target_phys_addr_t base,
2395 omap_clk clk)
2396{
2397 int iomemtype = cpu_register_io_memory(0, omap_dpll_readfn,
2398 omap_dpll_writefn, s);
2399
2400 s->base = base;
2401 s->dpll = clk;
2402 omap_dpll_reset(s);
2403
2404 cpu_register_physical_memory(s->base, 0x100, iomemtype);
2405}
2406
2407/* UARTs */
2408struct omap_uart_s {
2409 SerialState *serial; /* TODO */
2410};
2411
2412static void omap_uart_reset(struct omap_uart_s *s)
2413{
2414}
2415
2416struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
2417 qemu_irq irq, omap_clk clk, CharDriverState *chr)
2418{
2419 struct omap_uart_s *s = (struct omap_uart_s *)
2420 qemu_mallocz(sizeof(struct omap_uart_s));
2421 if (chr)
2422 s->serial = serial_mm_init(base, 2, irq, chr, 1);
2423 return s;
2424}
2425
2426/* MPU Clock/Reset/Power Mode Control */
2427static uint32_t omap_clkm_read(void *opaque, target_phys_addr_t addr)
2428{
2429 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2430 int offset = addr - s->clkm.mpu_base;
2431
2432 switch (offset) {
2433 case 0x00: /* ARM_CKCTL */
2434 return s->clkm.arm_ckctl;
2435
2436 case 0x04: /* ARM_IDLECT1 */
2437 return s->clkm.arm_idlect1;
2438
2439 case 0x08: /* ARM_IDLECT2 */
2440 return s->clkm.arm_idlect2;
2441
2442 case 0x0c: /* ARM_EWUPCT */
2443 return s->clkm.arm_ewupct;
2444
2445 case 0x10: /* ARM_RSTCT1 */
2446 return s->clkm.arm_rstct1;
2447
2448 case 0x14: /* ARM_RSTCT2 */
2449 return s->clkm.arm_rstct2;
2450
2451 case 0x18: /* ARM_SYSST */
d8f699cb 2452 return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start;
c3d2689d
AZ
2453
2454 case 0x1c: /* ARM_CKOUT1 */
2455 return s->clkm.arm_ckout1;
2456
2457 case 0x20: /* ARM_CKOUT2 */
2458 break;
2459 }
2460
2461 OMAP_BAD_REG(addr);
2462 return 0;
2463}
2464
2465static inline void omap_clkm_ckctl_update(struct omap_mpu_state_s *s,
2466 uint16_t diff, uint16_t value)
2467{
2468 omap_clk clk;
2469
2470 if (diff & (1 << 14)) { /* ARM_INTHCK_SEL */
2471 if (value & (1 << 14))
2472 /* Reserved */;
2473 else {
2474 clk = omap_findclk(s, "arminth_ck");
2475 omap_clk_reparent(clk, omap_findclk(s, "tc_ck"));
2476 }
2477 }
2478 if (diff & (1 << 12)) { /* ARM_TIMXO */
2479 clk = omap_findclk(s, "armtim_ck");
2480 if (value & (1 << 12))
2481 omap_clk_reparent(clk, omap_findclk(s, "clkin"));
2482 else
2483 omap_clk_reparent(clk, omap_findclk(s, "ck_gen1"));
2484 }
2485 /* XXX: en_dspck */
2486 if (diff & (3 << 10)) { /* DSPMMUDIV */
2487 clk = omap_findclk(s, "dspmmu_ck");
2488 omap_clk_setrate(clk, 1 << ((value >> 10) & 3), 1);
2489 }
2490 if (diff & (3 << 8)) { /* TCDIV */
2491 clk = omap_findclk(s, "tc_ck");
2492 omap_clk_setrate(clk, 1 << ((value >> 8) & 3), 1);
2493 }
2494 if (diff & (3 << 6)) { /* DSPDIV */
2495 clk = omap_findclk(s, "dsp_ck");
2496 omap_clk_setrate(clk, 1 << ((value >> 6) & 3), 1);
2497 }
2498 if (diff & (3 << 4)) { /* ARMDIV */
2499 clk = omap_findclk(s, "arm_ck");
2500 omap_clk_setrate(clk, 1 << ((value >> 4) & 3), 1);
2501 }
2502 if (diff & (3 << 2)) { /* LCDDIV */
2503 clk = omap_findclk(s, "lcd_ck");
2504 omap_clk_setrate(clk, 1 << ((value >> 2) & 3), 1);
2505 }
2506 if (diff & (3 << 0)) { /* PERDIV */
2507 clk = omap_findclk(s, "armper_ck");
2508 omap_clk_setrate(clk, 1 << ((value >> 0) & 3), 1);
2509 }
2510}
2511
2512static inline void omap_clkm_idlect1_update(struct omap_mpu_state_s *s,
2513 uint16_t diff, uint16_t value)
2514{
2515 omap_clk clk;
2516
2517 if (value & (1 << 11)) /* SETARM_IDLE */
2518 cpu_interrupt(s->env, CPU_INTERRUPT_HALT);
2519 if (!(value & (1 << 10))) /* WKUP_MODE */
2520 qemu_system_shutdown_request(); /* XXX: disable wakeup from IRQ */
2521
2522#define SET_CANIDLE(clock, bit) \
2523 if (diff & (1 << bit)) { \
2524 clk = omap_findclk(s, clock); \
2525 omap_clk_canidle(clk, (value >> bit) & 1); \
2526 }
2527 SET_CANIDLE("mpuwd_ck", 0) /* IDLWDT_ARM */
2528 SET_CANIDLE("armxor_ck", 1) /* IDLXORP_ARM */
2529 SET_CANIDLE("mpuper_ck", 2) /* IDLPER_ARM */
2530 SET_CANIDLE("lcd_ck", 3) /* IDLLCD_ARM */
2531 SET_CANIDLE("lb_ck", 4) /* IDLLB_ARM */
2532 SET_CANIDLE("hsab_ck", 5) /* IDLHSAB_ARM */
2533 SET_CANIDLE("tipb_ck", 6) /* IDLIF_ARM */
2534 SET_CANIDLE("dma_ck", 6) /* IDLIF_ARM */
2535 SET_CANIDLE("tc_ck", 6) /* IDLIF_ARM */
2536 SET_CANIDLE("dpll1", 7) /* IDLDPLL_ARM */
2537 SET_CANIDLE("dpll2", 7) /* IDLDPLL_ARM */
2538 SET_CANIDLE("dpll3", 7) /* IDLDPLL_ARM */
2539 SET_CANIDLE("mpui_ck", 8) /* IDLAPI_ARM */
2540 SET_CANIDLE("armtim_ck", 9) /* IDLTIM_ARM */
2541}
2542
2543static inline void omap_clkm_idlect2_update(struct omap_mpu_state_s *s,
2544 uint16_t diff, uint16_t value)
2545{
2546 omap_clk clk;
2547
2548#define SET_ONOFF(clock, bit) \
2549 if (diff & (1 << bit)) { \
2550 clk = omap_findclk(s, clock); \
2551 omap_clk_onoff(clk, (value >> bit) & 1); \
2552 }
2553 SET_ONOFF("mpuwd_ck", 0) /* EN_WDTCK */
2554 SET_ONOFF("armxor_ck", 1) /* EN_XORPCK */
2555 SET_ONOFF("mpuper_ck", 2) /* EN_PERCK */
2556 SET_ONOFF("lcd_ck", 3) /* EN_LCDCK */
2557 SET_ONOFF("lb_ck", 4) /* EN_LBCK */
2558 SET_ONOFF("hsab_ck", 5) /* EN_HSABCK */
2559 SET_ONOFF("mpui_ck", 6) /* EN_APICK */
2560 SET_ONOFF("armtim_ck", 7) /* EN_TIMCK */
2561 SET_CANIDLE("dma_ck", 8) /* DMACK_REQ */
2562 SET_ONOFF("arm_gpio_ck", 9) /* EN_GPIOCK */
2563 SET_ONOFF("lbfree_ck", 10) /* EN_LBFREECK */
2564}
2565
2566static inline void omap_clkm_ckout1_update(struct omap_mpu_state_s *s,
2567 uint16_t diff, uint16_t value)
2568{
2569 omap_clk clk;
2570
2571 if (diff & (3 << 4)) { /* TCLKOUT */
2572 clk = omap_findclk(s, "tclk_out");
2573 switch ((value >> 4) & 3) {
2574 case 1:
2575 omap_clk_reparent(clk, omap_findclk(s, "ck_gen3"));
2576 omap_clk_onoff(clk, 1);
2577 break;
2578 case 2:
2579 omap_clk_reparent(clk, omap_findclk(s, "tc_ck"));
2580 omap_clk_onoff(clk, 1);
2581 break;
2582 default:
2583 omap_clk_onoff(clk, 0);
2584 }
2585 }
2586 if (diff & (3 << 2)) { /* DCLKOUT */
2587 clk = omap_findclk(s, "dclk_out");
2588 switch ((value >> 2) & 3) {
2589 case 0:
2590 omap_clk_reparent(clk, omap_findclk(s, "dspmmu_ck"));
2591 break;
2592 case 1:
2593 omap_clk_reparent(clk, omap_findclk(s, "ck_gen2"));
2594 break;
2595 case 2:
2596 omap_clk_reparent(clk, omap_findclk(s, "dsp_ck"));
2597 break;
2598 case 3:
2599 omap_clk_reparent(clk, omap_findclk(s, "ck_ref14"));
2600 break;
2601 }
2602 }
2603 if (diff & (3 << 0)) { /* ACLKOUT */
2604 clk = omap_findclk(s, "aclk_out");
2605 switch ((value >> 0) & 3) {
2606 case 1:
2607 omap_clk_reparent(clk, omap_findclk(s, "ck_gen1"));
2608 omap_clk_onoff(clk, 1);
2609 break;
2610 case 2:
2611 omap_clk_reparent(clk, omap_findclk(s, "arm_ck"));
2612 omap_clk_onoff(clk, 1);
2613 break;
2614 case 3:
2615 omap_clk_reparent(clk, omap_findclk(s, "ck_ref14"));
2616 omap_clk_onoff(clk, 1);
2617 break;
2618 default:
2619 omap_clk_onoff(clk, 0);
2620 }
2621 }
2622}
2623
2624static void omap_clkm_write(void *opaque, target_phys_addr_t addr,
2625 uint32_t value)
2626{
2627 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2628 int offset = addr - s->clkm.mpu_base;
2629 uint16_t diff;
2630 omap_clk clk;
2631 static const char *clkschemename[8] = {
2632 "fully synchronous", "fully asynchronous", "synchronous scalable",
2633 "mix mode 1", "mix mode 2", "bypass mode", "mix mode 3", "mix mode 4",
2634 };
2635
2636 switch (offset) {
2637 case 0x00: /* ARM_CKCTL */
2638 diff = s->clkm.arm_ckctl ^ value;
2639 s->clkm.arm_ckctl = value & 0x7fff;
2640 omap_clkm_ckctl_update(s, diff, value);
2641 return;
2642
2643 case 0x04: /* ARM_IDLECT1 */
2644 diff = s->clkm.arm_idlect1 ^ value;
2645 s->clkm.arm_idlect1 = value & 0x0fff;
2646 omap_clkm_idlect1_update(s, diff, value);
2647 return;
2648
2649 case 0x08: /* ARM_IDLECT2 */
2650 diff = s->clkm.arm_idlect2 ^ value;
2651 s->clkm.arm_idlect2 = value & 0x07ff;
2652 omap_clkm_idlect2_update(s, diff, value);
2653 return;
2654
2655 case 0x0c: /* ARM_EWUPCT */
2656 diff = s->clkm.arm_ewupct ^ value;
2657 s->clkm.arm_ewupct = value & 0x003f;
2658 return;
2659
2660 case 0x10: /* ARM_RSTCT1 */
2661 diff = s->clkm.arm_rstct1 ^ value;
2662 s->clkm.arm_rstct1 = value & 0x0007;
2663 if (value & 9) {
2664 qemu_system_reset_request();
2665 s->clkm.cold_start = 0xa;
2666 }
2667 if (diff & ~value & 4) { /* DSP_RST */
2668 omap_mpui_reset(s);
2669 omap_tipb_bridge_reset(s->private_tipb);
2670 omap_tipb_bridge_reset(s->public_tipb);
2671 }
2672 if (diff & 2) { /* DSP_EN */
2673 clk = omap_findclk(s, "dsp_ck");
2674 omap_clk_canidle(clk, (~value >> 1) & 1);
2675 }
2676 return;
2677
2678 case 0x14: /* ARM_RSTCT2 */
2679 s->clkm.arm_rstct2 = value & 0x0001;
2680 return;
2681
2682 case 0x18: /* ARM_SYSST */
2683 if ((s->clkm.clocking_scheme ^ (value >> 11)) & 7) {
2684 s->clkm.clocking_scheme = (value >> 11) & 7;
2685 printf("%s: clocking scheme set to %s\n", __FUNCTION__,
2686 clkschemename[s->clkm.clocking_scheme]);
2687 }
2688 s->clkm.cold_start &= value & 0x3f;
2689 return;
2690
2691 case 0x1c: /* ARM_CKOUT1 */
2692 diff = s->clkm.arm_ckout1 ^ value;
2693 s->clkm.arm_ckout1 = value & 0x003f;
2694 omap_clkm_ckout1_update(s, diff, value);
2695 return;
2696
2697 case 0x20: /* ARM_CKOUT2 */
2698 default:
2699 OMAP_BAD_REG(addr);
2700 }
2701}
2702
2703static CPUReadMemoryFunc *omap_clkm_readfn[] = {
2704 omap_badwidth_read16,
2705 omap_clkm_read,
2706 omap_badwidth_read16,
2707};
2708
2709static CPUWriteMemoryFunc *omap_clkm_writefn[] = {
2710 omap_badwidth_write16,
2711 omap_clkm_write,
2712 omap_badwidth_write16,
2713};
2714
2715static uint32_t omap_clkdsp_read(void *opaque, target_phys_addr_t addr)
2716{
2717 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2718 int offset = addr - s->clkm.dsp_base;
2719
2720 switch (offset) {
2721 case 0x04: /* DSP_IDLECT1 */
2722 return s->clkm.dsp_idlect1;
2723
2724 case 0x08: /* DSP_IDLECT2 */
2725 return s->clkm.dsp_idlect2;
2726
2727 case 0x14: /* DSP_RSTCT2 */
2728 return s->clkm.dsp_rstct2;
2729
2730 case 0x18: /* DSP_SYSST */
d8f699cb 2731 return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start |
c3d2689d
AZ
2732 (s->env->halted << 6); /* Quite useless... */
2733 }
2734
2735 OMAP_BAD_REG(addr);
2736 return 0;
2737}
2738
2739static inline void omap_clkdsp_idlect1_update(struct omap_mpu_state_s *s,
2740 uint16_t diff, uint16_t value)
2741{
2742 omap_clk clk;
2743
2744 SET_CANIDLE("dspxor_ck", 1); /* IDLXORP_DSP */
2745}
2746
2747static inline void omap_clkdsp_idlect2_update(struct omap_mpu_state_s *s,
2748 uint16_t diff, uint16_t value)
2749{
2750 omap_clk clk;
2751
2752 SET_ONOFF("dspxor_ck", 1); /* EN_XORPCK */
2753}
2754
2755static void omap_clkdsp_write(void *opaque, target_phys_addr_t addr,
2756 uint32_t value)
2757{
2758 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2759 int offset = addr - s->clkm.dsp_base;
2760 uint16_t diff;
2761
2762 switch (offset) {
2763 case 0x04: /* DSP_IDLECT1 */
2764 diff = s->clkm.dsp_idlect1 ^ value;
2765 s->clkm.dsp_idlect1 = value & 0x01f7;
2766 omap_clkdsp_idlect1_update(s, diff, value);
2767 break;
2768
2769 case 0x08: /* DSP_IDLECT2 */
2770 s->clkm.dsp_idlect2 = value & 0x0037;
2771 diff = s->clkm.dsp_idlect1 ^ value;
2772 omap_clkdsp_idlect2_update(s, diff, value);
2773 break;
2774
2775 case 0x14: /* DSP_RSTCT2 */
2776 s->clkm.dsp_rstct2 = value & 0x0001;
2777 break;
2778
2779 case 0x18: /* DSP_SYSST */
2780 s->clkm.cold_start &= value & 0x3f;
2781 break;
2782
2783 default:
2784 OMAP_BAD_REG(addr);
2785 }
2786}
2787
2788static CPUReadMemoryFunc *omap_clkdsp_readfn[] = {
2789 omap_badwidth_read16,
2790 omap_clkdsp_read,
2791 omap_badwidth_read16,
2792};
2793
2794static CPUWriteMemoryFunc *omap_clkdsp_writefn[] = {
2795 omap_badwidth_write16,
2796 omap_clkdsp_write,
2797 omap_badwidth_write16,
2798};
2799
2800static void omap_clkm_reset(struct omap_mpu_state_s *s)
2801{
2802 if (s->wdt && s->wdt->reset)
2803 s->clkm.cold_start = 0x6;
2804 s->clkm.clocking_scheme = 0;
2805 omap_clkm_ckctl_update(s, ~0, 0x3000);
2806 s->clkm.arm_ckctl = 0x3000;
d8f699cb 2807 omap_clkm_idlect1_update(s, s->clkm.arm_idlect1 ^ 0x0400, 0x0400);
c3d2689d 2808 s->clkm.arm_idlect1 = 0x0400;
d8f699cb 2809 omap_clkm_idlect2_update(s, s->clkm.arm_idlect2 ^ 0x0100, 0x0100);
c3d2689d
AZ
2810 s->clkm.arm_idlect2 = 0x0100;
2811 s->clkm.arm_ewupct = 0x003f;
2812 s->clkm.arm_rstct1 = 0x0000;
2813 s->clkm.arm_rstct2 = 0x0000;
2814 s->clkm.arm_ckout1 = 0x0015;
2815 s->clkm.dpll1_mode = 0x2002;
2816 omap_clkdsp_idlect1_update(s, s->clkm.dsp_idlect1 ^ 0x0040, 0x0040);
2817 s->clkm.dsp_idlect1 = 0x0040;
2818 omap_clkdsp_idlect2_update(s, ~0, 0x0000);
2819 s->clkm.dsp_idlect2 = 0x0000;
2820 s->clkm.dsp_rstct2 = 0x0000;
2821}
2822
2823static void omap_clkm_init(target_phys_addr_t mpu_base,
2824 target_phys_addr_t dsp_base, struct omap_mpu_state_s *s)
2825{
2826 int iomemtype[2] = {
2827 cpu_register_io_memory(0, omap_clkm_readfn, omap_clkm_writefn, s),
2828 cpu_register_io_memory(0, omap_clkdsp_readfn, omap_clkdsp_writefn, s),
2829 };
2830
2831 s->clkm.mpu_base = mpu_base;
2832 s->clkm.dsp_base = dsp_base;
d8f699cb
AZ
2833 s->clkm.arm_idlect1 = 0x03ff;
2834 s->clkm.arm_idlect2 = 0x0100;
2835 s->clkm.dsp_idlect1 = 0x0002;
c3d2689d 2836 omap_clkm_reset(s);
d8f699cb 2837 s->clkm.cold_start = 0x3a;
c3d2689d
AZ
2838
2839 cpu_register_physical_memory(s->clkm.mpu_base, 0x100, iomemtype[0]);
2840 cpu_register_physical_memory(s->clkm.dsp_base, 0x1000, iomemtype[1]);
2841}
2842
fe71e81a
AZ
2843/* MPU I/O */
2844struct omap_mpuio_s {
2845 target_phys_addr_t base;
2846 qemu_irq irq;
2847 qemu_irq kbd_irq;
2848 qemu_irq *in;
2849 qemu_irq handler[16];
2850 qemu_irq wakeup;
2851
2852 uint16_t inputs;
2853 uint16_t outputs;
2854 uint16_t dir;
2855 uint16_t edge;
2856 uint16_t mask;
2857 uint16_t ints;
2858
2859 uint16_t debounce;
2860 uint16_t latch;
2861 uint8_t event;
2862
2863 uint8_t buttons[5];
2864 uint8_t row_latch;
2865 uint8_t cols;
2866 int kbd_mask;
2867 int clk;
2868};
2869
2870static void omap_mpuio_set(void *opaque, int line, int level)
2871{
2872 struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
2873 uint16_t prev = s->inputs;
2874
2875 if (level)
2876 s->inputs |= 1 << line;
2877 else
2878 s->inputs &= ~(1 << line);
2879
2880 if (((1 << line) & s->dir & ~s->mask) && s->clk) {
2881 if ((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) {
2882 s->ints |= 1 << line;
2883 qemu_irq_raise(s->irq);
2884 /* TODO: wakeup */
2885 }
2886 if ((s->event & (1 << 0)) && /* SET_GPIO_EVENT_MODE */
2887 (s->event >> 1) == line) /* PIN_SELECT */
2888 s->latch = s->inputs;
2889 }
2890}
2891
2892static void omap_mpuio_kbd_update(struct omap_mpuio_s *s)
2893{
2894 int i;
2895 uint8_t *row, rows = 0, cols = ~s->cols;
2896
38a34e1d 2897 for (row = s->buttons + 4, i = 1 << 4; i; row --, i >>= 1)
fe71e81a 2898 if (*row & cols)
38a34e1d 2899 rows |= i;
fe71e81a 2900
38a34e1d 2901 qemu_set_irq(s->kbd_irq, rows && ~s->kbd_mask && s->clk);
fe71e81a
AZ
2902 s->row_latch = rows ^ 0x1f;
2903}
2904
2905static uint32_t omap_mpuio_read(void *opaque, target_phys_addr_t addr)
2906{
2907 struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
cf965d24 2908 int offset = addr & OMAP_MPUI_REG_MASK;
fe71e81a
AZ
2909 uint16_t ret;
2910
2911 switch (offset) {
2912 case 0x00: /* INPUT_LATCH */
2913 return s->inputs;
2914
2915 case 0x04: /* OUTPUT_REG */
2916 return s->outputs;
2917
2918 case 0x08: /* IO_CNTL */
2919 return s->dir;
2920
2921 case 0x10: /* KBR_LATCH */
2922 return s->row_latch;
2923
2924 case 0x14: /* KBC_REG */
2925 return s->cols;
2926
2927 case 0x18: /* GPIO_EVENT_MODE_REG */
2928 return s->event;
2929
2930 case 0x1c: /* GPIO_INT_EDGE_REG */
2931 return s->edge;
2932
2933 case 0x20: /* KBD_INT */
2934 return (s->row_latch != 0x1f) && !s->kbd_mask;
2935
2936 case 0x24: /* GPIO_INT */
2937 ret = s->ints;
8e129e07
AZ
2938 s->ints &= s->mask;
2939 if (ret)
2940 qemu_irq_lower(s->irq);
fe71e81a
AZ
2941 return ret;
2942
2943 case 0x28: /* KBD_MASKIT */
2944 return s->kbd_mask;
2945
2946 case 0x2c: /* GPIO_MASKIT */
2947 return s->mask;
2948
2949 case 0x30: /* GPIO_DEBOUNCING_REG */
2950 return s->debounce;
2951
2952 case 0x34: /* GPIO_LATCH_REG */
2953 return s->latch;
2954 }
2955
2956 OMAP_BAD_REG(addr);
2957 return 0;
2958}
2959
2960static void omap_mpuio_write(void *opaque, target_phys_addr_t addr,
2961 uint32_t value)
2962{
2963 struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
cf965d24 2964 int offset = addr & OMAP_MPUI_REG_MASK;
fe71e81a
AZ
2965 uint16_t diff;
2966 int ln;
2967
2968 switch (offset) {
2969 case 0x04: /* OUTPUT_REG */
d8f699cb 2970 diff = (s->outputs ^ value) & ~s->dir;
fe71e81a 2971 s->outputs = value;
fe71e81a
AZ
2972 while ((ln = ffs(diff))) {
2973 ln --;
2974 if (s->handler[ln])
2975 qemu_set_irq(s->handler[ln], (value >> ln) & 1);
2976 diff &= ~(1 << ln);
2977 }
2978 break;
2979
2980 case 0x08: /* IO_CNTL */
2981 diff = s->outputs & (s->dir ^ value);
2982 s->dir = value;
2983
2984 value = s->outputs & ~s->dir;
2985 while ((ln = ffs(diff))) {
2986 ln --;
2987 if (s->handler[ln])
2988 qemu_set_irq(s->handler[ln], (value >> ln) & 1);
2989 diff &= ~(1 << ln);
2990 }
2991 break;
2992
2993 case 0x14: /* KBC_REG */
2994 s->cols = value;
2995 omap_mpuio_kbd_update(s);
2996 break;
2997
2998 case 0x18: /* GPIO_EVENT_MODE_REG */
2999 s->event = value & 0x1f;
3000 break;
3001
3002 case 0x1c: /* GPIO_INT_EDGE_REG */
3003 s->edge = value;
3004 break;
3005
3006 case 0x28: /* KBD_MASKIT */
3007 s->kbd_mask = value & 1;
3008 omap_mpuio_kbd_update(s);
3009 break;
3010
3011 case 0x2c: /* GPIO_MASKIT */
3012 s->mask = value;
3013 break;
3014
3015 case 0x30: /* GPIO_DEBOUNCING_REG */
3016 s->debounce = value & 0x1ff;
3017 break;
3018
3019 case 0x00: /* INPUT_LATCH */
3020 case 0x10: /* KBR_LATCH */
3021 case 0x20: /* KBD_INT */
3022 case 0x24: /* GPIO_INT */
3023 case 0x34: /* GPIO_LATCH_REG */
3024 OMAP_RO_REG(addr);
3025 return;
3026
3027 default:
3028 OMAP_BAD_REG(addr);
3029 return;
3030 }
3031}
3032
3033static CPUReadMemoryFunc *omap_mpuio_readfn[] = {
3034 omap_badwidth_read16,
3035 omap_mpuio_read,
3036 omap_badwidth_read16,
3037};
3038
3039static CPUWriteMemoryFunc *omap_mpuio_writefn[] = {
3040 omap_badwidth_write16,
3041 omap_mpuio_write,
3042 omap_badwidth_write16,
3043};
3044
9596ebb7 3045static void omap_mpuio_reset(struct omap_mpuio_s *s)
fe71e81a
AZ
3046{
3047 s->inputs = 0;
3048 s->outputs = 0;
3049 s->dir = ~0;
3050 s->event = 0;
3051 s->edge = 0;
3052 s->kbd_mask = 0;
3053 s->mask = 0;
3054 s->debounce = 0;
3055 s->latch = 0;
3056 s->ints = 0;
3057 s->row_latch = 0x1f;
38a34e1d 3058 s->clk = 1;
fe71e81a
AZ
3059}
3060
3061static void omap_mpuio_onoff(void *opaque, int line, int on)
3062{
3063 struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
3064
3065 s->clk = on;
3066 if (on)
3067 omap_mpuio_kbd_update(s);
3068}
3069
3070struct omap_mpuio_s *omap_mpuio_init(target_phys_addr_t base,
3071 qemu_irq kbd_int, qemu_irq gpio_int, qemu_irq wakeup,
3072 omap_clk clk)
3073{
3074 int iomemtype;
3075 struct omap_mpuio_s *s = (struct omap_mpuio_s *)
3076 qemu_mallocz(sizeof(struct omap_mpuio_s));
3077
3078 s->base = base;
3079 s->irq = gpio_int;
3080 s->kbd_irq = kbd_int;
3081 s->wakeup = wakeup;
3082 s->in = qemu_allocate_irqs(omap_mpuio_set, s, 16);
3083 omap_mpuio_reset(s);
3084
3085 iomemtype = cpu_register_io_memory(0, omap_mpuio_readfn,
3086 omap_mpuio_writefn, s);
3087 cpu_register_physical_memory(s->base, 0x800, iomemtype);
3088
3089 omap_clk_adduser(clk, qemu_allocate_irqs(omap_mpuio_onoff, s, 1)[0]);
3090
3091 return s;
3092}
3093
3094qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s)
3095{
3096 return s->in;
3097}
3098
3099void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler)
3100{
3101 if (line >= 16 || line < 0)
3102 cpu_abort(cpu_single_env, "%s: No GPIO line %i\n", __FUNCTION__, line);
3103 s->handler[line] = handler;
3104}
3105
3106void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down)
3107{
3108 if (row >= 5 || row < 0)
3109 cpu_abort(cpu_single_env, "%s: No key %i-%i\n",
3110 __FUNCTION__, col, row);
3111
3112 if (down)
38a34e1d 3113 s->buttons[row] |= 1 << col;
fe71e81a 3114 else
38a34e1d 3115 s->buttons[row] &= ~(1 << col);
fe71e81a
AZ
3116
3117 omap_mpuio_kbd_update(s);
3118}
3119
64330148
AZ
3120/* General-Purpose I/O */
3121struct omap_gpio_s {
3122 target_phys_addr_t base;
3123 qemu_irq irq;
3124 qemu_irq *in;
3125 qemu_irq handler[16];
3126
3127 uint16_t inputs;
3128 uint16_t outputs;
3129 uint16_t dir;
3130 uint16_t edge;
3131 uint16_t mask;
3132 uint16_t ints;
d8f699cb 3133 uint16_t pins;
64330148
AZ
3134};
3135
3136static void omap_gpio_set(void *opaque, int line, int level)
3137{
3138 struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
3139 uint16_t prev = s->inputs;
3140
3141 if (level)
3142 s->inputs |= 1 << line;
3143 else
3144 s->inputs &= ~(1 << line);
3145
3146 if (((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) &
3147 (1 << line) & s->dir & ~s->mask) {
3148 s->ints |= 1 << line;
3149 qemu_irq_raise(s->irq);
3150 }
3151}
3152
3153static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
3154{
3155 struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
cf965d24 3156 int offset = addr & OMAP_MPUI_REG_MASK;
64330148
AZ
3157
3158 switch (offset) {
3159 case 0x00: /* DATA_INPUT */
d8f699cb 3160 return s->inputs & s->pins;
64330148
AZ
3161
3162 case 0x04: /* DATA_OUTPUT */
3163 return s->outputs;
3164
3165 case 0x08: /* DIRECTION_CONTROL */
3166 return s->dir;
3167
3168 case 0x0c: /* INTERRUPT_CONTROL */
3169 return s->edge;
3170
3171 case 0x10: /* INTERRUPT_MASK */
3172 return s->mask;
3173
3174 case 0x14: /* INTERRUPT_STATUS */
3175 return s->ints;
d8f699cb
AZ
3176
3177 case 0x18: /* PIN_CONTROL (not in OMAP310) */
3178 OMAP_BAD_REG(addr);
3179 return s->pins;
64330148
AZ
3180 }
3181
3182 OMAP_BAD_REG(addr);
3183 return 0;
3184}
3185
3186static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
3187 uint32_t value)
3188{
3189 struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
cf965d24 3190 int offset = addr & OMAP_MPUI_REG_MASK;
64330148
AZ
3191 uint16_t diff;
3192 int ln;
3193
3194 switch (offset) {
3195 case 0x00: /* DATA_INPUT */
3196 OMAP_RO_REG(addr);
3197 return;
3198
3199 case 0x04: /* DATA_OUTPUT */
66450b15 3200 diff = (s->outputs ^ value) & ~s->dir;
64330148 3201 s->outputs = value;
64330148
AZ
3202 while ((ln = ffs(diff))) {
3203 ln --;
3204 if (s->handler[ln])
3205 qemu_set_irq(s->handler[ln], (value >> ln) & 1);
3206 diff &= ~(1 << ln);
3207 }
3208 break;
3209
3210 case 0x08: /* DIRECTION_CONTROL */
3211 diff = s->outputs & (s->dir ^ value);
3212 s->dir = value;
3213
3214 value = s->outputs & ~s->dir;
3215 while ((ln = ffs(diff))) {
3216 ln --;
3217 if (s->handler[ln])
3218 qemu_set_irq(s->handler[ln], (value >> ln) & 1);
3219 diff &= ~(1 << ln);
3220 }
3221 break;
3222
3223 case 0x0c: /* INTERRUPT_CONTROL */
3224 s->edge = value;
3225 break;
3226
3227 case 0x10: /* INTERRUPT_MASK */
3228 s->mask = value;
3229 break;
3230
3231 case 0x14: /* INTERRUPT_STATUS */
3232 s->ints &= ~value;
3233 if (!s->ints)
3234 qemu_irq_lower(s->irq);
3235 break;
3236
d8f699cb
AZ
3237 case 0x18: /* PIN_CONTROL (not in OMAP310 TRM) */
3238 OMAP_BAD_REG(addr);
3239 s->pins = value;
3240 break;
3241
64330148
AZ
3242 default:
3243 OMAP_BAD_REG(addr);
3244 return;
3245 }
3246}
3247
3efda49d 3248/* *Some* sources say the memory region is 32-bit. */
64330148 3249static CPUReadMemoryFunc *omap_gpio_readfn[] = {
3efda49d 3250 omap_badwidth_read16,
64330148 3251 omap_gpio_read,
3efda49d 3252 omap_badwidth_read16,
64330148
AZ
3253};
3254
3255static CPUWriteMemoryFunc *omap_gpio_writefn[] = {
3efda49d 3256 omap_badwidth_write16,
64330148 3257 omap_gpio_write,
3efda49d 3258 omap_badwidth_write16,
64330148
AZ
3259};
3260
9596ebb7 3261static void omap_gpio_reset(struct omap_gpio_s *s)
64330148
AZ
3262{
3263 s->inputs = 0;
3264 s->outputs = ~0;
3265 s->dir = ~0;
3266 s->edge = ~0;
3267 s->mask = ~0;
3268 s->ints = 0;
d8f699cb 3269 s->pins = ~0;
64330148
AZ
3270}
3271
3272struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
3273 qemu_irq irq, omap_clk clk)
3274{
3275 int iomemtype;
3276 struct omap_gpio_s *s = (struct omap_gpio_s *)
3277 qemu_mallocz(sizeof(struct omap_gpio_s));
3278
3279 s->base = base;
3280 s->irq = irq;
3281 s->in = qemu_allocate_irqs(omap_gpio_set, s, 16);
3282 omap_gpio_reset(s);
3283
3284 iomemtype = cpu_register_io_memory(0, omap_gpio_readfn,
3285 omap_gpio_writefn, s);
3286 cpu_register_physical_memory(s->base, 0x1000, iomemtype);
3287
3288 return s;
3289}
3290
3291qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s)
3292{
3293 return s->in;
3294}
3295
3296void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
3297{
3298 if (line >= 16 || line < 0)
3299 cpu_abort(cpu_single_env, "%s: No GPIO line %i\n", __FUNCTION__, line);
3300 s->handler[line] = handler;
3301}
3302
d951f6ff
AZ
3303/* MicroWire Interface */
3304struct omap_uwire_s {
3305 target_phys_addr_t base;
3306 qemu_irq txirq;
3307 qemu_irq rxirq;
3308 qemu_irq txdrq;
3309
3310 uint16_t txbuf;
3311 uint16_t rxbuf;
3312 uint16_t control;
3313 uint16_t setup[5];
3314
3315 struct uwire_slave_s *chip[4];
3316};
3317
3318static void omap_uwire_transfer_start(struct omap_uwire_s *s)
3319{
3320 int chipselect = (s->control >> 10) & 3; /* INDEX */
3321 struct uwire_slave_s *slave = s->chip[chipselect];
3322
3323 if ((s->control >> 5) & 0x1f) { /* NB_BITS_WR */
3324 if (s->control & (1 << 12)) /* CS_CMD */
3325 if (slave && slave->send)
3326 slave->send(slave->opaque,
3327 s->txbuf >> (16 - ((s->control >> 5) & 0x1f)));
3328 s->control &= ~(1 << 14); /* CSRB */
3329 /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
3330 * a DRQ. When is the level IRQ supposed to be reset? */
3331 }
3332
3333 if ((s->control >> 0) & 0x1f) { /* NB_BITS_RD */
3334 if (s->control & (1 << 12)) /* CS_CMD */
3335 if (slave && slave->receive)
3336 s->rxbuf = slave->receive(slave->opaque);
3337 s->control |= 1 << 15; /* RDRB */
3338 /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
3339 * a DRQ. When is the level IRQ supposed to be reset? */
3340 }
3341}
3342
3343static uint32_t omap_uwire_read(void *opaque, target_phys_addr_t addr)
3344{
3345 struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
cf965d24 3346 int offset = addr & OMAP_MPUI_REG_MASK;
d951f6ff
AZ
3347
3348 switch (offset) {
3349 case 0x00: /* RDR */
3350 s->control &= ~(1 << 15); /* RDRB */
3351 return s->rxbuf;
3352
3353 case 0x04: /* CSR */
3354 return s->control;
3355
3356 case 0x08: /* SR1 */
3357 return s->setup[0];
3358 case 0x0c: /* SR2 */
3359 return s->setup[1];
3360 case 0x10: /* SR3 */
3361 return s->setup[2];
3362 case 0x14: /* SR4 */
3363 return s->setup[3];
3364 case 0x18: /* SR5 */
3365 return s->setup[4];
3366 }
3367
3368 OMAP_BAD_REG(addr);
3369 return 0;
3370}
3371
3372static void omap_uwire_write(void *opaque, target_phys_addr_t addr,
3373 uint32_t value)
3374{
3375 struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
cf965d24 3376 int offset = addr & OMAP_MPUI_REG_MASK;
d951f6ff
AZ
3377
3378 switch (offset) {
3379 case 0x00: /* TDR */
3380 s->txbuf = value; /* TD */
d951f6ff
AZ
3381 if ((s->setup[4] & (1 << 2)) && /* AUTO_TX_EN */
3382 ((s->setup[4] & (1 << 3)) || /* CS_TOGGLE_TX_EN */
cf965d24
AZ
3383 (s->control & (1 << 12)))) { /* CS_CMD */
3384 s->control |= 1 << 14; /* CSRB */
d951f6ff 3385 omap_uwire_transfer_start(s);
cf965d24 3386 }
d951f6ff
AZ
3387 break;
3388
3389 case 0x04: /* CSR */
3390 s->control = value & 0x1fff;
3391 if (value & (1 << 13)) /* START */
3392 omap_uwire_transfer_start(s);
3393 break;
3394
3395 case 0x08: /* SR1 */
3396 s->setup[0] = value & 0x003f;
3397 break;
3398
3399 case 0x0c: /* SR2 */
3400 s->setup[1] = value & 0x0fc0;
3401 break;
3402
3403 case 0x10: /* SR3 */
3404 s->setup[2] = value & 0x0003;
3405 break;
3406
3407 case 0x14: /* SR4 */
3408 s->setup[3] = value & 0x0001;
3409 break;
3410
3411 case 0x18: /* SR5 */
3412 s->setup[4] = value & 0x000f;
3413 break;
3414
3415 default:
3416 OMAP_BAD_REG(addr);
3417 return;
3418 }
3419}
3420
3421static CPUReadMemoryFunc *omap_uwire_readfn[] = {
3422 omap_badwidth_read16,
3423 omap_uwire_read,
3424 omap_badwidth_read16,
3425};
3426
3427static CPUWriteMemoryFunc *omap_uwire_writefn[] = {
3428 omap_badwidth_write16,
3429 omap_uwire_write,
3430 omap_badwidth_write16,
3431};
3432
9596ebb7 3433static void omap_uwire_reset(struct omap_uwire_s *s)
d951f6ff 3434{
66450b15 3435 s->control = 0;
d951f6ff
AZ
3436 s->setup[0] = 0;
3437 s->setup[1] = 0;
3438 s->setup[2] = 0;
3439 s->setup[3] = 0;
3440 s->setup[4] = 0;
3441}
3442
3443struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
3444 qemu_irq *irq, qemu_irq dma, omap_clk clk)
3445{
3446 int iomemtype;
3447 struct omap_uwire_s *s = (struct omap_uwire_s *)
3448 qemu_mallocz(sizeof(struct omap_uwire_s));
3449
3450 s->base = base;
3451 s->txirq = irq[0];
3452 s->rxirq = irq[1];
3453 s->txdrq = dma;
3454 omap_uwire_reset(s);
3455
3456 iomemtype = cpu_register_io_memory(0, omap_uwire_readfn,
3457 omap_uwire_writefn, s);
3458 cpu_register_physical_memory(s->base, 0x800, iomemtype);
3459
3460 return s;
3461}
3462
3463void omap_uwire_attach(struct omap_uwire_s *s,
3464 struct uwire_slave_s *slave, int chipselect)
3465{
3466 if (chipselect < 0 || chipselect > 3)
3467 cpu_abort(cpu_single_env, "%s: Bad chipselect %i\n", __FUNCTION__,
3468 chipselect);
3469
3470 s->chip[chipselect] = slave;
3471}
3472
66450b15 3473/* Pseudonoise Pulse-Width Light Modulator */
9596ebb7 3474static void omap_pwl_update(struct omap_mpu_state_s *s)
66450b15
AZ
3475{
3476 int output = (s->pwl.clk && s->pwl.enable) ? s->pwl.level : 0;
3477
3478 if (output != s->pwl.output) {
3479 s->pwl.output = output;
3480 printf("%s: Backlight now at %i/256\n", __FUNCTION__, output);
3481 }
3482}
3483
3484static uint32_t omap_pwl_read(void *opaque, target_phys_addr_t addr)
3485{
3486 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
cf965d24 3487 int offset = addr & OMAP_MPUI_REG_MASK;
66450b15
AZ
3488
3489 switch (offset) {
3490 case 0x00: /* PWL_LEVEL */
3491 return s->pwl.level;
3492 case 0x04: /* PWL_CTRL */
3493 return s->pwl.enable;
3494 }
3495 OMAP_BAD_REG(addr);
3496 return 0;
3497}
3498
3499static void omap_pwl_write(void *opaque, target_phys_addr_t addr,
3500 uint32_t value)
3501{
3502 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
cf965d24 3503 int offset = addr & OMAP_MPUI_REG_MASK;
66450b15
AZ
3504
3505 switch (offset) {
3506 case 0x00: /* PWL_LEVEL */
3507 s->pwl.level = value;
3508 omap_pwl_update(s);
3509 break;
3510 case 0x04: /* PWL_CTRL */
3511 s->pwl.enable = value & 1;
3512 omap_pwl_update(s);
3513 break;
3514 default:
3515 OMAP_BAD_REG(addr);
3516 return;
3517 }
3518}
3519
3520static CPUReadMemoryFunc *omap_pwl_readfn[] = {
02645926 3521 omap_pwl_read,
66450b15
AZ
3522 omap_badwidth_read8,
3523 omap_badwidth_read8,
66450b15
AZ
3524};
3525
3526static CPUWriteMemoryFunc *omap_pwl_writefn[] = {
02645926 3527 omap_pwl_write,
66450b15
AZ
3528 omap_badwidth_write8,
3529 omap_badwidth_write8,
66450b15
AZ
3530};
3531
9596ebb7 3532static void omap_pwl_reset(struct omap_mpu_state_s *s)
66450b15
AZ
3533{
3534 s->pwl.output = 0;
3535 s->pwl.level = 0;
3536 s->pwl.enable = 0;
3537 s->pwl.clk = 1;
3538 omap_pwl_update(s);
3539}
3540
3541static void omap_pwl_clk_update(void *opaque, int line, int on)
3542{
3543 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
3544
3545 s->pwl.clk = on;
3546 omap_pwl_update(s);
3547}
3548
3549static void omap_pwl_init(target_phys_addr_t base, struct omap_mpu_state_s *s,
3550 omap_clk clk)
3551{
3552 int iomemtype;
3553
66450b15
AZ
3554 omap_pwl_reset(s);
3555
3556 iomemtype = cpu_register_io_memory(0, omap_pwl_readfn,
3557 omap_pwl_writefn, s);
b854bc19 3558 cpu_register_physical_memory(base, 0x800, iomemtype);
66450b15
AZ
3559
3560 omap_clk_adduser(clk, qemu_allocate_irqs(omap_pwl_clk_update, s, 1)[0]);
3561}
3562
f34c417b
AZ
3563/* Pulse-Width Tone module */
3564static uint32_t omap_pwt_read(void *opaque, target_phys_addr_t addr)
3565{
3566 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
cf965d24 3567 int offset = addr & OMAP_MPUI_REG_MASK;
f34c417b
AZ
3568
3569 switch (offset) {
3570 case 0x00: /* FRC */
3571 return s->pwt.frc;
3572 case 0x04: /* VCR */
3573 return s->pwt.vrc;
3574 case 0x08: /* GCR */
3575 return s->pwt.gcr;
3576 }
3577 OMAP_BAD_REG(addr);
3578 return 0;
3579}
3580
3581static void omap_pwt_write(void *opaque, target_phys_addr_t addr,
3582 uint32_t value)
3583{
3584 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
cf965d24 3585 int offset = addr & OMAP_MPUI_REG_MASK;
f34c417b
AZ
3586
3587 switch (offset) {
3588 case 0x00: /* FRC */
3589 s->pwt.frc = value & 0x3f;
3590 break;
3591 case 0x04: /* VRC */
3592 if ((value ^ s->pwt.vrc) & 1) {
3593 if (value & 1)
3594 printf("%s: %iHz buzz on\n", __FUNCTION__, (int)
3595 /* 1.5 MHz from a 12-MHz or 13-MHz PWT_CLK */
3596 ((omap_clk_getrate(s->pwt.clk) >> 3) /
3597 /* Pre-multiplexer divider */
3598 ((s->pwt.gcr & 2) ? 1 : 154) /
3599 /* Octave multiplexer */
3600 (2 << (value & 3)) *
3601 /* 101/107 divider */
3602 ((value & (1 << 2)) ? 101 : 107) *
3603 /* 49/55 divider */
3604 ((value & (1 << 3)) ? 49 : 55) *
3605 /* 50/63 divider */
3606 ((value & (1 << 4)) ? 50 : 63) *
3607 /* 80/127 divider */
3608 ((value & (1 << 5)) ? 80 : 127) /
3609 (107 * 55 * 63 * 127)));
3610 else
3611 printf("%s: silence!\n", __FUNCTION__);
3612 }
3613 s->pwt.vrc = value & 0x7f;
3614 break;
3615 case 0x08: /* GCR */
3616 s->pwt.gcr = value & 3;
3617 break;
3618 default:
3619 OMAP_BAD_REG(addr);
3620 return;
3621 }
3622}
3623
3624static CPUReadMemoryFunc *omap_pwt_readfn[] = {
02645926 3625 omap_pwt_read,
f34c417b
AZ
3626 omap_badwidth_read8,
3627 omap_badwidth_read8,
f34c417b
AZ
3628};
3629
3630static CPUWriteMemoryFunc *omap_pwt_writefn[] = {
02645926 3631 omap_pwt_write,
f34c417b
AZ
3632 omap_badwidth_write8,
3633 omap_badwidth_write8,
f34c417b
AZ
3634};
3635
9596ebb7 3636static void omap_pwt_reset(struct omap_mpu_state_s *s)
f34c417b
AZ
3637{
3638 s->pwt.frc = 0;
3639 s->pwt.vrc = 0;
3640 s->pwt.gcr = 0;
3641}
3642
3643static void omap_pwt_init(target_phys_addr_t base, struct omap_mpu_state_s *s,
3644 omap_clk clk)
3645{
3646 int iomemtype;
3647
f34c417b
AZ
3648 s->pwt.clk = clk;
3649 omap_pwt_reset(s);
3650
3651 iomemtype = cpu_register_io_memory(0, omap_pwt_readfn,
3652 omap_pwt_writefn, s);
b854bc19 3653 cpu_register_physical_memory(base, 0x800, iomemtype);
f34c417b
AZ
3654}
3655
5c1c390f
AZ
3656/* Real-time Clock module */
3657struct omap_rtc_s {
3658 target_phys_addr_t base;
3659 qemu_irq irq;
3660 qemu_irq alarm;
3661 QEMUTimer *clk;
3662
3663 uint8_t interrupts;
3664 uint8_t status;
3665 int16_t comp_reg;
3666 int running;
3667 int pm_am;
3668 int auto_comp;
3669 int round;
3670 struct tm *(*convert)(const time_t *timep, struct tm *result);
3671 struct tm alarm_tm;
3672 time_t alarm_ti;
3673
3674 struct tm current_tm;
3675 time_t ti;
3676 uint64_t tick;
3677};
3678
3679static void omap_rtc_interrupts_update(struct omap_rtc_s *s)
3680{
3681 qemu_set_irq(s->alarm, (s->status >> 6) & 1);
3682}
3683
3684static void omap_rtc_alarm_update(struct omap_rtc_s *s)
3685{
3686 s->alarm_ti = mktime(&s->alarm_tm);
3687 if (s->alarm_ti == -1)
3688 printf("%s: conversion failed\n", __FUNCTION__);
3689}
3690
3691static inline uint8_t omap_rtc_bcd(int num)
3692{
3693 return ((num / 10) << 4) | (num % 10);
3694}
3695
3696static inline int omap_rtc_bin(uint8_t num)
3697{
3698 return (num & 15) + 10 * (num >> 4);
3699}
3700
3701static uint32_t omap_rtc_read(void *opaque, target_phys_addr_t addr)
3702{
3703 struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
cf965d24 3704 int offset = addr & OMAP_MPUI_REG_MASK;
5c1c390f
AZ
3705 uint8_t i;
3706
3707 switch (offset) {
3708 case 0x00: /* SECONDS_REG */
3709 return omap_rtc_bcd(s->current_tm.tm_sec);
3710
3711 case 0x04: /* MINUTES_REG */
3712 return omap_rtc_bcd(s->current_tm.tm_min);
3713
3714 case 0x08: /* HOURS_REG */
3715 if (s->pm_am)
3716 return ((s->current_tm.tm_hour > 11) << 7) |
3717 omap_rtc_bcd(((s->current_tm.tm_hour - 1) % 12) + 1);
3718 else
3719 return omap_rtc_bcd(s->current_tm.tm_hour);
3720
3721 case 0x0c: /* DAYS_REG */
3722 return omap_rtc_bcd(s->current_tm.tm_mday);
3723
3724 case 0x10: /* MONTHS_REG */
3725 return omap_rtc_bcd(s->current_tm.tm_mon + 1);
3726
3727 case 0x14: /* YEARS_REG */
3728 return omap_rtc_bcd(s->current_tm.tm_year % 100);
3729
3730 case 0x18: /* WEEK_REG */
3731 return s->current_tm.tm_wday;
3732
3733 case 0x20: /* ALARM_SECONDS_REG */
3734 return omap_rtc_bcd(s->alarm_tm.tm_sec);
3735
3736 case 0x24: /* ALARM_MINUTES_REG */
3737 return omap_rtc_bcd(s->alarm_tm.tm_min);
3738
3739 case 0x28: /* ALARM_HOURS_REG */
3740 if (s->pm_am)
3741 return ((s->alarm_tm.tm_hour > 11) << 7) |
3742 omap_rtc_bcd(((s->alarm_tm.tm_hour - 1) % 12) + 1);
3743 else
3744 return omap_rtc_bcd(s->alarm_tm.tm_hour);
3745
3746 case 0x2c: /* ALARM_DAYS_REG */
3747 return omap_rtc_bcd(s->alarm_tm.tm_mday);
3748
3749 case 0x30: /* ALARM_MONTHS_REG */
3750 return omap_rtc_bcd(s->alarm_tm.tm_mon + 1);
3751
3752 case 0x34: /* ALARM_YEARS_REG */
3753 return omap_rtc_bcd(s->alarm_tm.tm_year % 100);
3754
3755 case 0x40: /* RTC_CTRL_REG */
3756 return (s->pm_am << 3) | (s->auto_comp << 2) |
3757 (s->round << 1) | s->running;
3758
3759 case 0x44: /* RTC_STATUS_REG */
3760 i = s->status;
3761 s->status &= ~0x3d;
3762 return i;
3763
3764 case 0x48: /* RTC_INTERRUPTS_REG */
3765 return s->interrupts;
3766
3767 case 0x4c: /* RTC_COMP_LSB_REG */
3768 return ((uint16_t) s->comp_reg) & 0xff;
3769
3770 case 0x50: /* RTC_COMP_MSB_REG */
3771 return ((uint16_t) s->comp_reg) >> 8;
3772 }
3773
3774 OMAP_BAD_REG(addr);
3775 return 0;
3776}
3777
3778static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
3779 uint32_t value)
3780{
3781 struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
cf965d24 3782 int offset = addr & OMAP_MPUI_REG_MASK;
5c1c390f
AZ
3783 struct tm new_tm;
3784 time_t ti[2];
3785
3786 switch (offset) {
3787 case 0x00: /* SECONDS_REG */
3788#if ALMDEBUG
3789 printf("RTC SEC_REG <-- %02x\n", value);
3790#endif
3791 s->ti -= s->current_tm.tm_sec;
3792 s->ti += omap_rtc_bin(value);
3793 return;
3794
3795 case 0x04: /* MINUTES_REG */
3796#if ALMDEBUG
3797 printf("RTC MIN_REG <-- %02x\n", value);
3798#endif
3799 s->ti -= s->current_tm.tm_min * 60;
3800 s->ti += omap_rtc_bin(value) * 60;
3801 return;
3802
3803 case 0x08: /* HOURS_REG */
3804#if ALMDEBUG
3805 printf("RTC HRS_REG <-- %02x\n", value);
3806#endif
3807 s->ti -= s->current_tm.tm_hour * 3600;
3808 if (s->pm_am) {
3809 s->ti += (omap_rtc_bin(value & 0x3f) & 12) * 3600;
3810 s->ti += ((value >> 7) & 1) * 43200;
3811 } else
3812 s->ti += omap_rtc_bin(value & 0x3f) * 3600;
3813 return;
3814
3815 case 0x0c: /* DAYS_REG */
3816#if ALMDEBUG
3817 printf("RTC DAY_REG <-- %02x\n", value);
3818#endif
3819 s->ti -= s->current_tm.tm_mday * 86400;
3820 s->ti += omap_rtc_bin(value) * 86400;
3821 return;
3822
3823 case 0x10: /* MONTHS_REG */
3824#if ALMDEBUG
3825 printf("RTC MTH_REG <-- %02x\n", value);
3826#endif
3827 memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
3828 new_tm.tm_mon = omap_rtc_bin(value);
3829 ti[0] = mktime(&s->current_tm);
3830 ti[1] = mktime(&new_tm);
3831
3832 if (ti[0] != -1 && ti[1] != -1) {
3833 s->ti -= ti[0];
3834 s->ti += ti[1];
3835 } else {
3836 /* A less accurate version */
3837 s->ti -= s->current_tm.tm_mon * 2592000;
3838 s->ti += omap_rtc_bin(value) * 2592000;
3839 }
3840 return;
3841
3842 case 0x14: /* YEARS_REG */
3843#if ALMDEBUG
3844 printf("RTC YRS_REG <-- %02x\n", value);
3845#endif
3846 memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
3847 new_tm.tm_year += omap_rtc_bin(value) - (new_tm.tm_year % 100);
3848 ti[0] = mktime(&s->current_tm);
3849 ti[1] = mktime(&new_tm);
3850
3851 if (ti[0] != -1 && ti[1] != -1) {
3852 s->ti -= ti[0];
3853 s->ti += ti[1];
3854 } else {
3855 /* A less accurate version */
3856 s->ti -= (s->current_tm.tm_year % 100) * 31536000;
3857 s->ti += omap_rtc_bin(value) * 31536000;
3858 }
3859 return;
3860
3861 case 0x18: /* WEEK_REG */
3862 return; /* Ignored */
3863
3864 case 0x20: /* ALARM_SECONDS_REG */
3865#if ALMDEBUG
3866 printf("ALM SEC_REG <-- %02x\n", value);
3867#endif
3868 s->alarm_tm.tm_sec = omap_rtc_bin(value);
3869 omap_rtc_alarm_update(s);
3870 return;
3871
3872 case 0x24: /* ALARM_MINUTES_REG */
3873#if ALMDEBUG
3874 printf("ALM MIN_REG <-- %02x\n", value);
3875#endif
3876 s->alarm_tm.tm_min = omap_rtc_bin(value);
3877 omap_rtc_alarm_update(s);
3878 return;
3879
3880 case 0x28: /* ALARM_HOURS_REG */
3881#if ALMDEBUG
3882 printf("ALM HRS_REG <-- %02x\n", value);
3883#endif
3884 if (s->pm_am)
3885 s->alarm_tm.tm_hour =
3886 ((omap_rtc_bin(value & 0x3f)) % 12) +
3887 ((value >> 7) & 1) * 12;
3888 else
3889 s->alarm_tm.tm_hour = omap_rtc_bin(value);
3890 omap_rtc_alarm_update(s);
3891 return;
3892
3893 case 0x2c: /* ALARM_DAYS_REG */
3894#if ALMDEBUG
3895 printf("ALM DAY_REG <-- %02x\n", value);
3896#endif
3897 s->alarm_tm.tm_mday = omap_rtc_bin(value);
3898 omap_rtc_alarm_update(s);
3899 return;
3900
3901 case 0x30: /* ALARM_MONTHS_REG */
3902#if ALMDEBUG
3903 printf("ALM MON_REG <-- %02x\n", value);
3904#endif
3905 s->alarm_tm.tm_mon = omap_rtc_bin(value);
3906 omap_rtc_alarm_update(s);
3907 return;
3908
3909 case 0x34: /* ALARM_YEARS_REG */
3910#if ALMDEBUG
3911 printf("ALM YRS_REG <-- %02x\n", value);
3912#endif
3913 s->alarm_tm.tm_year = omap_rtc_bin(value);
3914 omap_rtc_alarm_update(s);
3915 return;
3916
3917 case 0x40: /* RTC_CTRL_REG */
3918#if ALMDEBUG
3919 printf("RTC CONTROL <-- %02x\n", value);
3920#endif
3921 s->pm_am = (value >> 3) & 1;
3922 s->auto_comp = (value >> 2) & 1;
3923 s->round = (value >> 1) & 1;
3924 s->running = value & 1;
3925 s->status &= 0xfd;
3926 s->status |= s->running << 1;
3927 return;
3928
3929 case 0x44: /* RTC_STATUS_REG */
3930#if ALMDEBUG
3931 printf("RTC STATUSL <-- %02x\n", value);
3932#endif
3933 s->status &= ~((value & 0xc0) ^ 0x80);
3934 omap_rtc_interrupts_update(s);
3935 return;
3936
3937 case 0x48: /* RTC_INTERRUPTS_REG */
3938#if ALMDEBUG
3939 printf("RTC INTRS <-- %02x\n", value);
3940#endif
3941 s->interrupts = value;
3942 return;
3943
3944 case 0x4c: /* RTC_COMP_LSB_REG */
3945#if ALMDEBUG
3946 printf("RTC COMPLSB <-- %02x\n", value);
3947#endif
3948 s->comp_reg &= 0xff00;
3949 s->comp_reg |= 0x00ff & value;
3950 return;
3951
3952 case 0x50: /* RTC_COMP_MSB_REG */
3953#if ALMDEBUG
3954 printf("RTC COMPMSB <-- %02x\n", value);
3955#endif
3956 s->comp_reg &= 0x00ff;
3957 s->comp_reg |= 0xff00 & (value << 8);
3958 return;
3959
3960 default:
3961 OMAP_BAD_REG(addr);
3962 return;
3963 }
3964}
3965
3966static CPUReadMemoryFunc *omap_rtc_readfn[] = {
3967 omap_rtc_read,
3968 omap_badwidth_read8,
3969 omap_badwidth_read8,
3970};
3971
3972static CPUWriteMemoryFunc *omap_rtc_writefn[] = {
3973 omap_rtc_write,
3974 omap_badwidth_write8,
3975 omap_badwidth_write8,
3976};
3977
3978static void omap_rtc_tick(void *opaque)
3979{
3980 struct omap_rtc_s *s = opaque;
3981
3982 if (s->round) {
3983 /* Round to nearest full minute. */
3984 if (s->current_tm.tm_sec < 30)
3985 s->ti -= s->current_tm.tm_sec;
3986 else
3987 s->ti += 60 - s->current_tm.tm_sec;
3988
3989 s->round = 0;
3990 }
3991
3992 localtime_r(&s->ti, &s->current_tm);
3993
3994 if ((s->interrupts & 0x08) && s->ti == s->alarm_ti) {
3995 s->status |= 0x40;
3996 omap_rtc_interrupts_update(s);
3997 }
3998
3999 if (s->interrupts & 0x04)
4000 switch (s->interrupts & 3) {
4001 case 0:
4002 s->status |= 0x04;
4003 qemu_irq_raise(s->irq);
4004 break;
4005 case 1:
4006 if (s->current_tm.tm_sec)
4007 break;
4008 s->status |= 0x08;
4009 qemu_irq_raise(s->irq);
4010 break;
4011 case 2:
4012 if (s->current_tm.tm_sec || s->current_tm.tm_min)
4013 break;
4014 s->status |= 0x10;
4015 qemu_irq_raise(s->irq);
4016 break;
4017 case 3:
4018 if (s->current_tm.tm_sec ||
4019 s->current_tm.tm_min || s->current_tm.tm_hour)
4020 break;
4021 s->status |= 0x20;
4022 qemu_irq_raise(s->irq);
4023 break;
4024 }
4025
4026 /* Move on */
4027 if (s->running)
4028 s->ti ++;
4029 s->tick += 1000;
4030
4031 /*
4032 * Every full hour add a rough approximation of the compensation
4033 * register to the 32kHz Timer (which drives the RTC) value.
4034 */
4035 if (s->auto_comp && !s->current_tm.tm_sec && !s->current_tm.tm_min)
4036 s->tick += s->comp_reg * 1000 / 32768;
4037
4038 qemu_mod_timer(s->clk, s->tick);
4039}
4040
9596ebb7 4041static void omap_rtc_reset(struct omap_rtc_s *s)
5c1c390f
AZ
4042{
4043 s->interrupts = 0;
4044 s->comp_reg = 0;
4045 s->running = 0;
4046 s->pm_am = 0;
4047 s->auto_comp = 0;
4048 s->round = 0;
4049 s->tick = qemu_get_clock(rt_clock);
4050 memset(&s->alarm_tm, 0, sizeof(s->alarm_tm));
4051 s->alarm_tm.tm_mday = 0x01;
4052 s->status = 1 << 7;
4053 time(&s->ti);
4054 s->ti = mktime(s->convert(&s->ti, &s->current_tm));
4055
4056 omap_rtc_alarm_update(s);
4057 omap_rtc_tick(s);
4058}
4059
4060struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base,
4061 qemu_irq *irq, omap_clk clk)
4062{
4063 int iomemtype;
4064 struct omap_rtc_s *s = (struct omap_rtc_s *)
4065 qemu_mallocz(sizeof(struct omap_rtc_s));
4066
4067 s->base = base;
4068 s->irq = irq[0];
4069 s->alarm = irq[1];
4070 s->clk = qemu_new_timer(rt_clock, omap_rtc_tick, s);
4071 s->convert = rtc_utc ? gmtime_r : localtime_r;
4072
4073 omap_rtc_reset(s);
4074
4075 iomemtype = cpu_register_io_memory(0, omap_rtc_readfn,
4076 omap_rtc_writefn, s);
4077 cpu_register_physical_memory(s->base, 0x800, iomemtype);
4078
4079 return s;
4080}
4081
d8f699cb
AZ
4082/* Multi-channel Buffered Serial Port interfaces */
4083struct omap_mcbsp_s {
4084 target_phys_addr_t base;
4085 qemu_irq txirq;
4086 qemu_irq rxirq;
4087 qemu_irq txdrq;
4088 qemu_irq rxdrq;
4089
4090 uint16_t spcr[2];
4091 uint16_t rcr[2];
4092 uint16_t xcr[2];
4093 uint16_t srgr[2];
4094 uint16_t mcr[2];
4095 uint16_t pcr;
4096 uint16_t rcer[8];
4097 uint16_t xcer[8];
4098 int tx_rate;
4099 int rx_rate;
4100 int tx_req;
73560bc8 4101 int rx_req;
d8f699cb
AZ
4102
4103 struct i2s_codec_s *codec;
73560bc8
AZ
4104 QEMUTimer *source_timer;
4105 QEMUTimer *sink_timer;
d8f699cb
AZ
4106};
4107
4108static void omap_mcbsp_intr_update(struct omap_mcbsp_s *s)
4109{
4110 int irq;
4111
4112 switch ((s->spcr[0] >> 4) & 3) { /* RINTM */
4113 case 0:
4114 irq = (s->spcr[0] >> 1) & 1; /* RRDY */
4115 break;
4116 case 3:
4117 irq = (s->spcr[0] >> 3) & 1; /* RSYNCERR */
4118 break;
4119 default:
4120 irq = 0;
4121 break;
4122 }
4123
4124 qemu_set_irq(s->rxirq, irq);
4125
4126 switch ((s->spcr[1] >> 4) & 3) { /* XINTM */
4127 case 0:
4128 irq = (s->spcr[1] >> 1) & 1; /* XRDY */
4129 break;
4130 case 3:
4131 irq = (s->spcr[1] >> 3) & 1; /* XSYNCERR */
4132 break;
4133 default:
4134 irq = 0;
4135 break;
4136 }
4137
4138 qemu_set_irq(s->txirq, irq);
4139}
4140
73560bc8 4141static void omap_mcbsp_rx_newdata(struct omap_mcbsp_s *s)
d8f699cb 4142{
73560bc8
AZ
4143 if ((s->spcr[0] >> 1) & 1) /* RRDY */
4144 s->spcr[0] |= 1 << 2; /* RFULL */
4145 s->spcr[0] |= 1 << 1; /* RRDY */
4146 qemu_irq_raise(s->rxdrq);
4147 omap_mcbsp_intr_update(s);
d8f699cb
AZ
4148}
4149
73560bc8 4150static void omap_mcbsp_source_tick(void *opaque)
d8f699cb 4151{
73560bc8
AZ
4152 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
4153 static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 };
4154
4155 if (!s->rx_rate)
d8f699cb 4156 return;
73560bc8
AZ
4157 if (s->rx_req)
4158 printf("%s: Rx FIFO overrun\n", __FUNCTION__);
d8f699cb 4159
73560bc8 4160 s->rx_req = s->rx_rate << bps[(s->rcr[0] >> 5) & 7];
d8f699cb 4161
73560bc8
AZ
4162 omap_mcbsp_rx_newdata(s);
4163 qemu_mod_timer(s->source_timer, qemu_get_clock(vm_clock) + ticks_per_sec);
d8f699cb
AZ
4164}
4165
4166static void omap_mcbsp_rx_start(struct omap_mcbsp_s *s)
4167{
73560bc8
AZ
4168 if (!s->codec || !s->codec->rts)
4169 omap_mcbsp_source_tick(s);
4170 else if (s->codec->in.len) {
4171 s->rx_req = s->codec->in.len;
4172 omap_mcbsp_rx_newdata(s);
d8f699cb 4173 }
d8f699cb
AZ
4174}
4175
4176static void omap_mcbsp_rx_stop(struct omap_mcbsp_s *s)
73560bc8
AZ
4177{
4178 qemu_del_timer(s->source_timer);
4179}
4180
4181static void omap_mcbsp_rx_done(struct omap_mcbsp_s *s)
d8f699cb
AZ
4182{
4183 s->spcr[0] &= ~(1 << 1); /* RRDY */
4184 qemu_irq_lower(s->rxdrq);
4185 omap_mcbsp_intr_update(s);
4186}
4187
73560bc8
AZ
4188static void omap_mcbsp_tx_newdata(struct omap_mcbsp_s *s)
4189{
4190 s->spcr[1] |= 1 << 1; /* XRDY */
4191 qemu_irq_raise(s->txdrq);
4192 omap_mcbsp_intr_update(s);
4193}
4194
4195static void omap_mcbsp_sink_tick(void *opaque)
d8f699cb 4196{
73560bc8
AZ
4197 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
4198 static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 };
4199
4200 if (!s->tx_rate)
d8f699cb 4201 return;
73560bc8
AZ
4202 if (s->tx_req)
4203 printf("%s: Tx FIFO underrun\n", __FUNCTION__);
4204
4205 s->tx_req = s->tx_rate << bps[(s->xcr[0] >> 5) & 7];
4206
4207 omap_mcbsp_tx_newdata(s);
4208 qemu_mod_timer(s->sink_timer, qemu_get_clock(vm_clock) + ticks_per_sec);
4209}
4210
4211static void omap_mcbsp_tx_start(struct omap_mcbsp_s *s)
4212{
4213 if (!s->codec || !s->codec->cts)
4214 omap_mcbsp_sink_tick(s);
4215 else if (s->codec->out.size) {
4216 s->tx_req = s->codec->out.size;
4217 omap_mcbsp_tx_newdata(s);
4218 }
4219}
4220
4221static void omap_mcbsp_tx_done(struct omap_mcbsp_s *s)
4222{
4223 s->spcr[1] &= ~(1 << 1); /* XRDY */
4224 qemu_irq_lower(s->txdrq);
4225 omap_mcbsp_intr_update(s);
4226 if (s->codec && s->codec->cts)
4227 s->codec->tx_swallow(s->codec->opaque);
d8f699cb
AZ
4228}
4229
4230static void omap_mcbsp_tx_stop(struct omap_mcbsp_s *s)
4231{
73560bc8
AZ
4232 s->tx_req = 0;
4233 omap_mcbsp_tx_done(s);
4234 qemu_del_timer(s->sink_timer);
4235}
4236
4237static void omap_mcbsp_req_update(struct omap_mcbsp_s *s)
4238{
4239 int prev_rx_rate, prev_tx_rate;
4240 int rx_rate = 0, tx_rate = 0;
4241 int cpu_rate = 1500000; /* XXX */
4242
4243 /* TODO: check CLKSTP bit */
4244 if (s->spcr[1] & (1 << 6)) { /* GRST */
4245 if (s->spcr[0] & (1 << 0)) { /* RRST */
4246 if ((s->srgr[1] & (1 << 13)) && /* CLKSM */
4247 (s->pcr & (1 << 8))) { /* CLKRM */
4248 if (~s->pcr & (1 << 7)) /* SCLKME */
4249 rx_rate = cpu_rate /
4250 ((s->srgr[0] & 0xff) + 1); /* CLKGDV */
4251 } else
4252 if (s->codec)
4253 rx_rate = s->codec->rx_rate;
4254 }
4255
4256 if (s->spcr[1] & (1 << 0)) { /* XRST */
4257 if ((s->srgr[1] & (1 << 13)) && /* CLKSM */
4258 (s->pcr & (1 << 9))) { /* CLKXM */
4259 if (~s->pcr & (1 << 7)) /* SCLKME */
4260 tx_rate = cpu_rate /
4261 ((s->srgr[0] & 0xff) + 1); /* CLKGDV */
4262 } else
4263 if (s->codec)
4264 tx_rate = s->codec->tx_rate;
4265 }
4266 }
4267 prev_tx_rate = s->tx_rate;
4268 prev_rx_rate = s->rx_rate;
4269 s->tx_rate = tx_rate;
4270 s->rx_rate = rx_rate;
4271
4272 if (s->codec)
4273 s->codec->set_rate(s->codec->opaque, rx_rate, tx_rate);
4274
4275 if (!prev_tx_rate && tx_rate)
4276 omap_mcbsp_tx_start(s);
4277 else if (s->tx_rate && !tx_rate)
4278 omap_mcbsp_tx_stop(s);
4279
4280 if (!prev_rx_rate && rx_rate)
4281 omap_mcbsp_rx_start(s);
4282 else if (prev_tx_rate && !tx_rate)
4283 omap_mcbsp_rx_stop(s);
d8f699cb
AZ
4284}
4285
4286static uint32_t omap_mcbsp_read(void *opaque, target_phys_addr_t addr)
4287{
4288 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
4289 int offset = addr & OMAP_MPUI_REG_MASK;
4290 uint16_t ret;
4291
4292 switch (offset) {
4293 case 0x00: /* DRR2 */
4294 if (((s->rcr[0] >> 5) & 7) < 3) /* RWDLEN1 */
4295 return 0x0000;
4296 /* Fall through. */
4297 case 0x02: /* DRR1 */
73560bc8 4298 if (s->rx_req < 2) {
d8f699cb 4299 printf("%s: Rx FIFO underrun\n", __FUNCTION__);
73560bc8 4300 omap_mcbsp_rx_done(s);
d8f699cb 4301 } else {
73560bc8
AZ
4302 s->tx_req -= 2;
4303 if (s->codec && s->codec->in.len >= 2) {
4304 ret = s->codec->in.fifo[s->codec->in.start ++] << 8;
4305 ret |= s->codec->in.fifo[s->codec->in.start ++];
4306 s->codec->in.len -= 2;
4307 } else
4308 ret = 0x0000;
4309 if (!s->tx_req)
4310 omap_mcbsp_rx_done(s);
d8f699cb
AZ
4311 return ret;
4312 }
4313 return 0x0000;
4314
4315 case 0x04: /* DXR2 */
4316 case 0x06: /* DXR1 */
4317 return 0x0000;
4318
4319 case 0x08: /* SPCR2 */
4320 return s->spcr[1];
4321 case 0x0a: /* SPCR1 */
4322 return s->spcr[0];
4323 case 0x0c: /* RCR2 */
4324 return s->rcr[1];
4325 case 0x0e: /* RCR1 */
4326 return s->rcr[0];
4327 case 0x10: /* XCR2 */
4328 return s->xcr[1];
4329 case 0x12: /* XCR1 */
4330 return s->xcr[0];
4331 case 0x14: /* SRGR2 */
4332 return s->srgr[1];
4333 case 0x16: /* SRGR1 */
4334 return s->srgr[0];
4335 case 0x18: /* MCR2 */
4336 return s->mcr[1];
4337 case 0x1a: /* MCR1 */
4338 return s->mcr[0];
4339 case 0x1c: /* RCERA */
4340 return s->rcer[0];
4341 case 0x1e: /* RCERB */
4342 return s->rcer[1];
4343 case 0x20: /* XCERA */
4344 return s->xcer[0];
4345 case 0x22: /* XCERB */
4346 return s->xcer[1];
4347 case 0x24: /* PCR0 */
4348 return s->pcr;
4349 case 0x26: /* RCERC */
4350 return s->rcer[2];
4351 case 0x28: /* RCERD */
4352 return s->rcer[3];
4353 case 0x2a: /* XCERC */
4354 return s->xcer[2];
4355 case 0x2c: /* XCERD */
4356 return s->xcer[3];
4357 case 0x2e: /* RCERE */
4358 return s->rcer[4];
4359 case 0x30: /* RCERF */
4360 return s->rcer[5];
4361 case 0x32: /* XCERE */
4362 return s->xcer[4];
4363 case 0x34: /* XCERF */
4364 return s->xcer[5];
4365 case 0x36: /* RCERG */
4366 return s->rcer[6];
4367 case 0x38: /* RCERH */
4368 return s->rcer[7];
4369 case 0x3a: /* XCERG */
4370 return s->xcer[6];
4371 case 0x3c: /* XCERH */
4372 return s->xcer[7];
4373 }
4374
4375 OMAP_BAD_REG(addr);
4376 return 0;
4377}
4378
73560bc8 4379static void omap_mcbsp_writeh(void *opaque, target_phys_addr_t addr,
d8f699cb
AZ
4380 uint32_t value)
4381{
4382 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
4383 int offset = addr & OMAP_MPUI_REG_MASK;
4384
4385 switch (offset) {
4386 case 0x00: /* DRR2 */
4387 case 0x02: /* DRR1 */
4388 OMAP_RO_REG(addr);
4389 return;
4390
4391 case 0x04: /* DXR2 */
4392 if (((s->xcr[0] >> 5) & 7) < 3) /* XWDLEN1 */
4393 return;
4394 /* Fall through. */
4395 case 0x06: /* DXR1 */
73560bc8
AZ
4396 if (s->tx_req > 1) {
4397 s->tx_req -= 2;
4398 if (s->codec && s->codec->cts) {
d8f699cb
AZ
4399 s->codec->out.fifo[s->codec->out.len ++] = (value >> 8) & 0xff;
4400 s->codec->out.fifo[s->codec->out.len ++] = (value >> 0) & 0xff;
d8f699cb 4401 }
73560bc8
AZ
4402 if (s->tx_req < 2)
4403 omap_mcbsp_tx_done(s);
d8f699cb
AZ
4404 } else
4405 printf("%s: Tx FIFO overrun\n", __FUNCTION__);
4406 return;
4407
4408 case 0x08: /* SPCR2 */
4409 s->spcr[1] &= 0x0002;
4410 s->spcr[1] |= 0x03f9 & value;
4411 s->spcr[1] |= 0x0004 & (value << 2); /* XEMPTY := XRST */
73560bc8 4412 if (~value & 1) /* XRST */
d8f699cb 4413 s->spcr[1] &= ~6;
d8f699cb
AZ
4414 omap_mcbsp_req_update(s);
4415 return;
4416 case 0x0a: /* SPCR1 */
4417 s->spcr[0] &= 0x0006;
4418 s->spcr[0] |= 0xf8f9 & value;
4419 if (value & (1 << 15)) /* DLB */
4420 printf("%s: Digital Loopback mode enable attempt\n", __FUNCTION__);
4421 if (~value & 1) { /* RRST */
4422 s->spcr[0] &= ~6;
73560bc8
AZ
4423 s->rx_req = 0;
4424 omap_mcbsp_rx_done(s);
d8f699cb 4425 }
d8f699cb
AZ
4426 omap_mcbsp_req_update(s);
4427 return;
4428
4429 case 0x0c: /* RCR2 */
4430 s->rcr[1] = value & 0xffff;
4431 return;
4432 case 0x0e: /* RCR1 */
4433 s->rcr[0] = value & 0x7fe0;
4434 return;
4435 case 0x10: /* XCR2 */
4436 s->xcr[1] = value & 0xffff;
4437 return;
4438 case 0x12: /* XCR1 */
4439 s->xcr[0] = value & 0x7fe0;
4440 return;
4441 case 0x14: /* SRGR2 */
4442 s->srgr[1] = value & 0xffff;
73560bc8 4443 omap_mcbsp_req_update(s);
d8f699cb
AZ
4444 return;
4445 case 0x16: /* SRGR1 */
4446 s->srgr[0] = value & 0xffff;
73560bc8 4447 omap_mcbsp_req_update(s);
d8f699cb
AZ
4448 return;
4449 case 0x18: /* MCR2 */
4450 s->mcr[1] = value & 0x03e3;
4451 if (value & 3) /* XMCM */
4452 printf("%s: Tx channel selection mode enable attempt\n",
4453 __FUNCTION__);
4454 return;
4455 case 0x1a: /* MCR1 */
4456 s->mcr[0] = value & 0x03e1;
4457 if (value & 1) /* RMCM */
4458 printf("%s: Rx channel selection mode enable attempt\n",
4459 __FUNCTION__);
4460 return;
4461 case 0x1c: /* RCERA */
4462 s->rcer[0] = value & 0xffff;
4463 return;
4464 case 0x1e: /* RCERB */
4465 s->rcer[1] = value & 0xffff;
4466 return;
4467 case 0x20: /* XCERA */
4468 s->xcer[0] = value & 0xffff;
4469 return;
4470 case 0x22: /* XCERB */
4471 s->xcer[1] = value & 0xffff;
4472 return;
4473 case 0x24: /* PCR0 */
4474 s->pcr = value & 0x7faf;
4475 return;
4476 case 0x26: /* RCERC */
4477 s->rcer[2] = value & 0xffff;
4478 return;
4479 case 0x28: /* RCERD */
4480 s->rcer[3] = value & 0xffff;
4481 return;
4482 case 0x2a: /* XCERC */
4483 s->xcer[2] = value & 0xffff;
4484 return;
4485 case 0x2c: /* XCERD */
4486 s->xcer[3] = value & 0xffff;
4487 return;
4488 case 0x2e: /* RCERE */
4489 s->rcer[4] = value & 0xffff;
4490 return;
4491 case 0x30: /* RCERF */
4492 s->rcer[5] = value & 0xffff;
4493 return;
4494 case 0x32: /* XCERE */
4495 s->xcer[4] = value & 0xffff;
4496 return;
4497 case 0x34: /* XCERF */
4498 s->xcer[5] = value & 0xffff;
4499 return;
4500 case 0x36: /* RCERG */
4501 s->rcer[6] = value & 0xffff;
4502 return;
4503 case 0x38: /* RCERH */
4504 s->rcer[7] = value & 0xffff;
4505 return;
4506 case 0x3a: /* XCERG */
4507 s->xcer[6] = value & 0xffff;
4508 return;
4509 case 0x3c: /* XCERH */
4510 s->xcer[7] = value & 0xffff;
4511 return;
4512 }
4513
4514 OMAP_BAD_REG(addr);
4515}
4516
73560bc8
AZ
4517static void omap_mcbsp_writew(void *opaque, target_phys_addr_t addr,
4518 uint32_t value)
4519{
4520 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
4521 int offset = addr & OMAP_MPUI_REG_MASK;
4522
4523 if (offset == 0x04) { /* DXR */
4524 if (((s->xcr[0] >> 5) & 7) < 3) /* XWDLEN1 */
4525 return;
4526 if (s->tx_req > 3) {
4527 s->tx_req -= 4;
4528 if (s->codec && s->codec->cts) {
4529 s->codec->out.fifo[s->codec->out.len ++] =
4530 (value >> 24) & 0xff;
4531 s->codec->out.fifo[s->codec->out.len ++] =
4532 (value >> 16) & 0xff;
4533 s->codec->out.fifo[s->codec->out.len ++] =
4534 (value >> 8) & 0xff;
4535 s->codec->out.fifo[s->codec->out.len ++] =
4536 (value >> 0) & 0xff;
4537 }
4538 if (s->tx_req < 4)
4539 omap_mcbsp_tx_done(s);
4540 } else
4541 printf("%s: Tx FIFO overrun\n", __FUNCTION__);
4542 return;
4543 }
4544
4545 omap_badwidth_write16(opaque, addr, value);
4546}
4547
d8f699cb
AZ
4548static CPUReadMemoryFunc *omap_mcbsp_readfn[] = {
4549 omap_badwidth_read16,
4550 omap_mcbsp_read,
4551 omap_badwidth_read16,
4552};
4553
4554static CPUWriteMemoryFunc *omap_mcbsp_writefn[] = {
4555 omap_badwidth_write16,
73560bc8
AZ
4556 omap_mcbsp_writeh,
4557 omap_mcbsp_writew,
d8f699cb
AZ
4558};
4559
4560static void omap_mcbsp_reset(struct omap_mcbsp_s *s)
4561{
4562 memset(&s->spcr, 0, sizeof(s->spcr));
4563 memset(&s->rcr, 0, sizeof(s->rcr));
4564 memset(&s->xcr, 0, sizeof(s->xcr));
4565 s->srgr[0] = 0x0001;
4566 s->srgr[1] = 0x2000;
4567 memset(&s->mcr, 0, sizeof(s->mcr));
4568 memset(&s->pcr, 0, sizeof(s->pcr));
4569 memset(&s->rcer, 0, sizeof(s->rcer));
4570 memset(&s->xcer, 0, sizeof(s->xcer));
4571 s->tx_req = 0;
73560bc8 4572 s->rx_req = 0;
d8f699cb
AZ
4573 s->tx_rate = 0;
4574 s->rx_rate = 0;
73560bc8
AZ
4575 qemu_del_timer(s->source_timer);
4576 qemu_del_timer(s->sink_timer);
d8f699cb
AZ
4577}
4578
4579struct omap_mcbsp_s *omap_mcbsp_init(target_phys_addr_t base,
4580 qemu_irq *irq, qemu_irq *dma, omap_clk clk)
4581{
4582 int iomemtype;
4583 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *)
4584 qemu_mallocz(sizeof(struct omap_mcbsp_s));
4585
4586 s->base = base;
4587 s->txirq = irq[0];
4588 s->rxirq = irq[1];
4589 s->txdrq = dma[0];
4590 s->rxdrq = dma[1];
73560bc8
AZ
4591 s->sink_timer = qemu_new_timer(vm_clock, omap_mcbsp_sink_tick, s);
4592 s->source_timer = qemu_new_timer(vm_clock, omap_mcbsp_source_tick, s);
d8f699cb
AZ
4593 omap_mcbsp_reset(s);
4594
4595 iomemtype = cpu_register_io_memory(0, omap_mcbsp_readfn,
4596 omap_mcbsp_writefn, s);
4597 cpu_register_physical_memory(s->base, 0x800, iomemtype);
4598
4599 return s;
4600}
4601
9596ebb7 4602static void omap_mcbsp_i2s_swallow(void *opaque, int line, int level)
d8f699cb
AZ
4603{
4604 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
4605
73560bc8
AZ
4606 if (s->rx_rate) {
4607 s->rx_req = s->codec->in.len;
4608 omap_mcbsp_rx_newdata(s);
4609 }
d8f699cb
AZ
4610}
4611
9596ebb7 4612static void omap_mcbsp_i2s_start(void *opaque, int line, int level)
d8f699cb
AZ
4613{
4614 struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
4615
73560bc8
AZ
4616 if (s->tx_rate) {
4617 s->tx_req = s->codec->out.size;
4618 omap_mcbsp_tx_newdata(s);
4619 }
d8f699cb
AZ
4620}
4621
4622void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, struct i2s_codec_s *slave)
4623{
4624 s->codec = slave;
4625 slave->rx_swallow = qemu_allocate_irqs(omap_mcbsp_i2s_swallow, s, 1)[0];
4626 slave->tx_start = qemu_allocate_irqs(omap_mcbsp_i2s_start, s, 1)[0];
4627}
4628
f9d43072
AZ
4629/* LED Pulse Generators */
4630struct omap_lpg_s {
4631 target_phys_addr_t base;
4632 QEMUTimer *tm;
4633
4634 uint8_t control;
4635 uint8_t power;
4636 int64_t on;
4637 int64_t period;
4638 int clk;
4639 int cycle;
4640};
4641
4642static void omap_lpg_tick(void *opaque)
4643{
4644 struct omap_lpg_s *s = opaque;
4645
4646 if (s->cycle)
4647 qemu_mod_timer(s->tm, qemu_get_clock(rt_clock) + s->period - s->on);
4648 else
4649 qemu_mod_timer(s->tm, qemu_get_clock(rt_clock) + s->on);
4650
4651 s->cycle = !s->cycle;
4652 printf("%s: LED is %s\n", __FUNCTION__, s->cycle ? "on" : "off");
4653}
4654
4655static void omap_lpg_update(struct omap_lpg_s *s)
4656{
4657 int64_t on, period = 1, ticks = 1000;
4658 static const int per[8] = { 1, 2, 4, 8, 12, 16, 20, 24 };
4659
4660 if (~s->control & (1 << 6)) /* LPGRES */
4661 on = 0;
4662 else if (s->control & (1 << 7)) /* PERM_ON */
4663 on = period;
4664 else {
4665 period = muldiv64(ticks, per[s->control & 7], /* PERCTRL */
4666 256 / 32);
4667 on = (s->clk && s->power) ? muldiv64(ticks,
4668 per[(s->control >> 3) & 7], 256) : 0; /* ONCTRL */
4669 }
4670
4671 qemu_del_timer(s->tm);
4672 if (on == period && s->on < s->period)
4673 printf("%s: LED is on\n", __FUNCTION__);
4674 else if (on == 0 && s->on)
4675 printf("%s: LED is off\n", __FUNCTION__);
4676 else if (on && (on != s->on || period != s->period)) {
4677 s->cycle = 0;
4678 s->on = on;
4679 s->period = period;
4680 omap_lpg_tick(s);
4681 return;
4682 }
4683
4684 s->on = on;
4685 s->period = period;
4686}
4687
4688static void omap_lpg_reset(struct omap_lpg_s *s)
4689{
4690 s->control = 0x00;
4691 s->power = 0x00;
4692 s->clk = 1;
4693 omap_lpg_update(s);
4694}
4695
4696static uint32_t omap_lpg_read(void *opaque, target_phys_addr_t addr)
4697{
4698 struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
4699 int offset = addr & OMAP_MPUI_REG_MASK;
4700
4701 switch (offset) {
4702 case 0x00: /* LCR */
4703 return s->control;
4704
4705 case 0x04: /* PMR */
4706 return s->power;
4707 }
4708
4709 OMAP_BAD_REG(addr);
4710 return 0;
4711}
4712
4713static void omap_lpg_write(void *opaque, target_phys_addr_t addr,
4714 uint32_t value)
4715{
4716 struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
4717 int offset = addr & OMAP_MPUI_REG_MASK;
4718
4719 switch (offset) {
4720 case 0x00: /* LCR */
4721 if (~value & (1 << 6)) /* LPGRES */
4722 omap_lpg_reset(s);
4723 s->control = value & 0xff;
4724 omap_lpg_update(s);
4725 return;
4726
4727 case 0x04: /* PMR */
4728 s->power = value & 0x01;
4729 omap_lpg_update(s);
4730 return;
4731
4732 default:
4733 OMAP_BAD_REG(addr);
4734 return;
4735 }
4736}
4737
4738static CPUReadMemoryFunc *omap_lpg_readfn[] = {
4739 omap_lpg_read,
4740 omap_badwidth_read8,
4741 omap_badwidth_read8,
4742};
4743
4744static CPUWriteMemoryFunc *omap_lpg_writefn[] = {
4745 omap_lpg_write,
4746 omap_badwidth_write8,
4747 omap_badwidth_write8,
4748};
4749
4750static void omap_lpg_clk_update(void *opaque, int line, int on)
4751{
4752 struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
4753
4754 s->clk = on;
4755 omap_lpg_update(s);
4756}
4757
4758struct omap_lpg_s *omap_lpg_init(target_phys_addr_t base, omap_clk clk)
4759{
4760 int iomemtype;
4761 struct omap_lpg_s *s = (struct omap_lpg_s *)
4762 qemu_mallocz(sizeof(struct omap_lpg_s));
4763
4764 s->base = base;
4765 s->tm = qemu_new_timer(rt_clock, omap_lpg_tick, s);
4766
4767 omap_lpg_reset(s);
4768
4769 iomemtype = cpu_register_io_memory(0, omap_lpg_readfn,
4770 omap_lpg_writefn, s);
4771 cpu_register_physical_memory(s->base, 0x800, iomemtype);
4772
4773 omap_clk_adduser(clk, qemu_allocate_irqs(omap_lpg_clk_update, s, 1)[0]);
4774
4775 return s;
4776}
4777
4778/* MPUI Peripheral Bridge configuration */
4779static uint32_t omap_mpui_io_read(void *opaque, target_phys_addr_t addr)
4780{
4781 if (addr == OMAP_MPUI_BASE) /* CMR */
4782 return 0xfe4d;
4783
4784 OMAP_BAD_REG(addr);
4785 return 0;
4786}
4787
4788static CPUReadMemoryFunc *omap_mpui_io_readfn[] = {
4789 omap_badwidth_read16,
4790 omap_mpui_io_read,
4791 omap_badwidth_read16,
4792};
4793
4794static CPUWriteMemoryFunc *omap_mpui_io_writefn[] = {
4795 omap_badwidth_write16,
4796 omap_badwidth_write16,
4797 omap_badwidth_write16,
4798};
4799
4800static void omap_setup_mpui_io(struct omap_mpu_state_s *mpu)
4801{
4802 int iomemtype = cpu_register_io_memory(0, omap_mpui_io_readfn,
4803 omap_mpui_io_writefn, mpu);
4804 cpu_register_physical_memory(OMAP_MPUI_BASE, 0x7fff, iomemtype);
4805}
4806
c3d2689d
AZ
4807/* General chip reset */
4808static void omap_mpu_reset(void *opaque)
4809{
4810 struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
4811
c3d2689d
AZ
4812 omap_inth_reset(mpu->ih[0]);
4813 omap_inth_reset(mpu->ih[1]);
4814 omap_dma_reset(mpu->dma);
4815 omap_mpu_timer_reset(mpu->timer[0]);
4816 omap_mpu_timer_reset(mpu->timer[1]);
4817 omap_mpu_timer_reset(mpu->timer[2]);
4818 omap_wd_timer_reset(mpu->wdt);
4819 omap_os_timer_reset(mpu->os_timer);
4820 omap_lcdc_reset(mpu->lcd);
4821 omap_ulpd_pm_reset(mpu);
4822 omap_pin_cfg_reset(mpu);
4823 omap_mpui_reset(mpu);
4824 omap_tipb_bridge_reset(mpu->private_tipb);
4825 omap_tipb_bridge_reset(mpu->public_tipb);
4826 omap_dpll_reset(&mpu->dpll[0]);
4827 omap_dpll_reset(&mpu->dpll[1]);
4828 omap_dpll_reset(&mpu->dpll[2]);
d951f6ff
AZ
4829 omap_uart_reset(mpu->uart[0]);
4830 omap_uart_reset(mpu->uart[1]);
4831 omap_uart_reset(mpu->uart[2]);
b30bb3a2 4832 omap_mmc_reset(mpu->mmc);
fe71e81a 4833 omap_mpuio_reset(mpu->mpuio);
64330148 4834 omap_gpio_reset(mpu->gpio);
d951f6ff 4835 omap_uwire_reset(mpu->microwire);
66450b15 4836 omap_pwl_reset(mpu);
4a2c8ac2
AZ
4837 omap_pwt_reset(mpu);
4838 omap_i2c_reset(mpu->i2c);
5c1c390f 4839 omap_rtc_reset(mpu->rtc);
d8f699cb
AZ
4840 omap_mcbsp_reset(mpu->mcbsp1);
4841 omap_mcbsp_reset(mpu->mcbsp2);
4842 omap_mcbsp_reset(mpu->mcbsp3);
f9d43072
AZ
4843 omap_lpg_reset(mpu->led[0]);
4844 omap_lpg_reset(mpu->led[1]);
8ef6367e 4845 omap_clkm_reset(mpu);
c3d2689d
AZ
4846 cpu_reset(mpu->env);
4847}
4848
cf965d24
AZ
4849static const struct omap_map_s {
4850 target_phys_addr_t phys_dsp;
4851 target_phys_addr_t phys_mpu;
4852 uint32_t size;
4853 const char *name;
4854} omap15xx_dsp_mm[] = {
4855 /* Strobe 0 */
4856 { 0xe1010000, 0xfffb0000, 0x800, "UART1 BT" }, /* CS0 */
4857 { 0xe1010800, 0xfffb0800, 0x800, "UART2 COM" }, /* CS1 */
4858 { 0xe1011800, 0xfffb1800, 0x800, "McBSP1 audio" }, /* CS3 */
4859 { 0xe1012000, 0xfffb2000, 0x800, "MCSI2 communication" }, /* CS4 */
4860 { 0xe1012800, 0xfffb2800, 0x800, "MCSI1 BT u-Law" }, /* CS5 */
4861 { 0xe1013000, 0xfffb3000, 0x800, "uWire" }, /* CS6 */
4862 { 0xe1013800, 0xfffb3800, 0x800, "I^2C" }, /* CS7 */
4863 { 0xe1014000, 0xfffb4000, 0x800, "USB W2FC" }, /* CS8 */
4864 { 0xe1014800, 0xfffb4800, 0x800, "RTC" }, /* CS9 */
4865 { 0xe1015000, 0xfffb5000, 0x800, "MPUIO" }, /* CS10 */
4866 { 0xe1015800, 0xfffb5800, 0x800, "PWL" }, /* CS11 */
4867 { 0xe1016000, 0xfffb6000, 0x800, "PWT" }, /* CS12 */
4868 { 0xe1017000, 0xfffb7000, 0x800, "McBSP3" }, /* CS14 */
4869 { 0xe1017800, 0xfffb7800, 0x800, "MMC" }, /* CS15 */
4870 { 0xe1019000, 0xfffb9000, 0x800, "32-kHz timer" }, /* CS18 */
4871 { 0xe1019800, 0xfffb9800, 0x800, "UART3" }, /* CS19 */
4872 { 0xe101c800, 0xfffbc800, 0x800, "TIPB switches" }, /* CS25 */
4873 /* Strobe 1 */
4874 { 0xe101e000, 0xfffce000, 0x800, "GPIOs" }, /* CS28 */
4875
4876 { 0 }
4877};
4878
4879static void omap_setup_dsp_mapping(const struct omap_map_s *map)
4880{
4881 int io;
4882
4883 for (; map->phys_dsp; map ++) {
4884 io = cpu_get_physical_page_desc(map->phys_mpu);
4885
4886 cpu_register_physical_memory(map->phys_dsp, map->size, io);
4887 }
4888}
4889
c3d2689d
AZ
4890static void omap_mpu_wakeup(void *opaque, int irq, int req)
4891{
4892 struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
4893
fe71e81a
AZ
4894 if (mpu->env->halted)
4895 cpu_interrupt(mpu->env, CPU_INTERRUPT_EXITTB);
c3d2689d
AZ
4896}
4897
4898struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
4899 DisplayState *ds, const char *core)
4900{
4901 struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
4902 qemu_mallocz(sizeof(struct omap_mpu_state_s));
4903 ram_addr_t imif_base, emiff_base;
aaed909a
FB
4904
4905 if (!core)
4906 core = "ti925t";
c3d2689d
AZ
4907
4908 /* Core */
4909 s->mpu_model = omap310;
aaed909a
FB
4910 s->env = cpu_init(core);
4911 if (!s->env) {
4912 fprintf(stderr, "Unable to find CPU definition\n");
4913 exit(1);
4914 }
c3d2689d
AZ
4915 s->sdram_size = sdram_size;
4916 s->sram_size = OMAP15XX_SRAM_SIZE;
4917
fe71e81a
AZ
4918 s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
4919
c3d2689d
AZ
4920 /* Clocks */
4921 omap_clk_init(s);
4922
4923 /* Memory-mapped stuff */
4924 cpu_register_physical_memory(OMAP_EMIFF_BASE, s->sdram_size,
4925 (emiff_base = qemu_ram_alloc(s->sdram_size)) | IO_MEM_RAM);
4926 cpu_register_physical_memory(OMAP_IMIF_BASE, s->sram_size,
4927 (imif_base = qemu_ram_alloc(s->sram_size)) | IO_MEM_RAM);
4928
4929 omap_clkm_init(0xfffece00, 0xe1008000, s);
4930
4931 s->ih[0] = omap_inth_init(0xfffecb00, 0x100,
4932 arm_pic_init_cpu(s->env),
4933 omap_findclk(s, "arminth_ck"));
4934 s->ih[1] = omap_inth_init(0xfffe0000, 0x800,
4935 &s->ih[0]->pins[OMAP_INT_15XX_IH2_IRQ],
4936 omap_findclk(s, "arminth_ck"));
4937 s->irq[0] = s->ih[0]->pins;
4938 s->irq[1] = s->ih[1]->pins;
4939
4940 s->dma = omap_dma_init(0xfffed800, s->irq[0], s,
4941 omap_findclk(s, "dma_ck"));
4942 s->port[emiff ].addr_valid = omap_validate_emiff_addr;
4943 s->port[emifs ].addr_valid = omap_validate_emifs_addr;
4944 s->port[imif ].addr_valid = omap_validate_imif_addr;
4945 s->port[tipb ].addr_valid = omap_validate_tipb_addr;
4946 s->port[local ].addr_valid = omap_validate_local_addr;
4947 s->port[tipb_mpui].addr_valid = omap_validate_tipb_mpui_addr;
4948
4949 s->timer[0] = omap_mpu_timer_init(0xfffec500,
4950 s->irq[0][OMAP_INT_TIMER1],
4951 omap_findclk(s, "mputim_ck"));
4952 s->timer[1] = omap_mpu_timer_init(0xfffec600,
4953 s->irq[0][OMAP_INT_TIMER2],
4954 omap_findclk(s, "mputim_ck"));
4955 s->timer[2] = omap_mpu_timer_init(0xfffec700,
4956 s->irq[0][OMAP_INT_TIMER3],
4957 omap_findclk(s, "mputim_ck"));
4958
4959 s->wdt = omap_wd_timer_init(0xfffec800,
4960 s->irq[0][OMAP_INT_WD_TIMER],
4961 omap_findclk(s, "armwdt_ck"));
4962
4963 s->os_timer = omap_os_timer_init(0xfffb9000,
4964 s->irq[1][OMAP_INT_OS_TIMER],
4965 omap_findclk(s, "clk32-kHz"));
4966
4967 s->lcd = omap_lcdc_init(0xfffec000, s->irq[0][OMAP_INT_LCD_CTRL],
4968 &s->dma->lcd_ch, ds, imif_base, emiff_base,
4969 omap_findclk(s, "lcd_ck"));
4970
4971 omap_ulpd_pm_init(0xfffe0800, s);
4972 omap_pin_cfg_init(0xfffe1000, s);
4973 omap_id_init(s);
4974
4975 omap_mpui_init(0xfffec900, s);
4976
4977 s->private_tipb = omap_tipb_bridge_init(0xfffeca00,
4978 s->irq[0][OMAP_INT_BRIDGE_PRIV],
4979 omap_findclk(s, "tipb_ck"));
4980 s->public_tipb = omap_tipb_bridge_init(0xfffed300,
4981 s->irq[0][OMAP_INT_BRIDGE_PUB],
4982 omap_findclk(s, "tipb_ck"));
4983
4984 omap_tcmi_init(0xfffecc00, s);
4985
d951f6ff 4986 s->uart[0] = omap_uart_init(0xfffb0000, s->irq[1][OMAP_INT_UART1],
c3d2689d
AZ
4987 omap_findclk(s, "uart1_ck"),
4988 serial_hds[0]);
d951f6ff 4989 s->uart[1] = omap_uart_init(0xfffb0800, s->irq[1][OMAP_INT_UART2],
c3d2689d
AZ
4990 omap_findclk(s, "uart2_ck"),
4991 serial_hds[0] ? serial_hds[1] : 0);
d951f6ff 4992 s->uart[2] = omap_uart_init(0xe1019800, s->irq[0][OMAP_INT_UART3],
c3d2689d
AZ
4993 omap_findclk(s, "uart3_ck"),
4994 serial_hds[0] && serial_hds[1] ? serial_hds[2] : 0);
4995
4996 omap_dpll_init(&s->dpll[0], 0xfffecf00, omap_findclk(s, "dpll1"));
4997 omap_dpll_init(&s->dpll[1], 0xfffed000, omap_findclk(s, "dpll2"));
4998 omap_dpll_init(&s->dpll[2], 0xfffed100, omap_findclk(s, "dpll3"));
4999
87ecb68b 5000 s->mmc = omap_mmc_init(0xfffb7800, sd_bdrv, s->irq[1][OMAP_INT_OQN],
b30bb3a2
AZ
5001 &s->drq[OMAP_DMA_MMC_TX], omap_findclk(s, "mmc_ck"));
5002
fe71e81a
AZ
5003 s->mpuio = omap_mpuio_init(0xfffb5000,
5004 s->irq[1][OMAP_INT_KEYBOARD], s->irq[1][OMAP_INT_MPUIO],
5005 s->wakeup, omap_findclk(s, "clk32-kHz"));
5006
3efda49d 5007 s->gpio = omap_gpio_init(0xfffce000, s->irq[0][OMAP_INT_GPIO_BANK1],
66450b15 5008 omap_findclk(s, "arm_gpio_ck"));
64330148 5009
d951f6ff
AZ
5010 s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX],
5011 s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck"));
5012
d8f699cb
AZ
5013 omap_pwl_init(0xfffb5800, s, omap_findclk(s, "armxor_ck"));
5014 omap_pwt_init(0xfffb6000, s, omap_findclk(s, "armxor_ck"));
66450b15 5015
4a2c8ac2
AZ
5016 s->i2c = omap_i2c_init(0xfffb3800, s->irq[1][OMAP_INT_I2C],
5017 &s->drq[OMAP_DMA_I2C_RX], omap_findclk(s, "mpuper_ck"));
5018
5c1c390f
AZ
5019 s->rtc = omap_rtc_init(0xfffb4800, &s->irq[1][OMAP_INT_RTC_TIMER],
5020 omap_findclk(s, "clk32-kHz"));
02645926 5021
d8f699cb
AZ
5022 s->mcbsp1 = omap_mcbsp_init(0xfffb1800, &s->irq[1][OMAP_INT_McBSP1TX],
5023 &s->drq[OMAP_DMA_MCBSP1_TX], omap_findclk(s, "dspxor_ck"));
5024 s->mcbsp2 = omap_mcbsp_init(0xfffb1000, &s->irq[0][OMAP_INT_310_McBSP2_TX],
5025 &s->drq[OMAP_DMA_MCBSP2_TX], omap_findclk(s, "mpuper_ck"));
5026 s->mcbsp3 = omap_mcbsp_init(0xfffb7000, &s->irq[1][OMAP_INT_McBSP3TX],
5027 &s->drq[OMAP_DMA_MCBSP3_TX], omap_findclk(s, "dspxor_ck"));
5028
f9d43072
AZ
5029 s->led[0] = omap_lpg_init(0xfffbd000, omap_findclk(s, "clk32-kHz"));
5030 s->led[1] = omap_lpg_init(0xfffbd800, omap_findclk(s, "clk32-kHz"));
5031
02645926 5032 /* Register mappings not currenlty implemented:
02645926
AZ
5033 * MCSI2 Comm fffb2000 - fffb27ff (not mapped on OMAP310)
5034 * MCSI1 Bluetooth fffb2800 - fffb2fff (not mapped on OMAP310)
5035 * USB W2FC fffb4000 - fffb47ff
5036 * Camera Interface fffb6800 - fffb6fff
02645926
AZ
5037 * USB Host fffba000 - fffba7ff
5038 * FAC fffba800 - fffbafff
5039 * HDQ/1-Wire fffbc000 - fffbc7ff
b854bc19 5040 * TIPB switches fffbc800 - fffbcfff
02645926
AZ
5041 * Mailbox fffcf000 - fffcf7ff
5042 * Local bus IF fffec100 - fffec1ff
5043 * Local bus MMU fffec200 - fffec2ff
5044 * DSP MMU fffed200 - fffed2ff
5045 */
5046
cf965d24 5047 omap_setup_dsp_mapping(omap15xx_dsp_mm);
f9d43072 5048 omap_setup_mpui_io(s);
cf965d24 5049
c3d2689d 5050 qemu_register_reset(omap_mpu_reset, s);
c3d2689d
AZ
5051
5052 return s;
5053}