2 * Motorola ColdFire MCF5206 SoC embedded peripheral emulation.
4 * Copyright (c) 2007 CodeSourcery.
6 * This code is licenced under the GPL
10 /* General purpose timer module. */
31 static void m5206_timer_update(m5206_timer_state
*s
)
33 if ((s
->tmr
& TMR_ORI
) != 0 && (s
->ter
& TER_REF
))
34 qemu_irq_raise(s
->irq
);
36 qemu_irq_lower(s
->irq
);
39 static void m5206_timer_reset(m5206_timer_state
*s
)
45 static void m5206_timer_recalibrate(m5206_timer_state
*s
)
50 ptimer_stop(s
->timer
);
52 if ((s
->tmr
& TMR_RST
) == 0)
55 prescale
= (s
->tmr
>> 8) + 1;
56 mode
= (s
->tmr
>> 1) & 3;
60 if (mode
== 3 || mode
== 0)
61 cpu_abort(cpu_single_env
,
62 "m5206_timer: mode %d not implemented\n", mode
);
63 if ((s
->tmr
& TMR_FRR
) == 0)
64 cpu_abort(cpu_single_env
,
65 "m5206_timer: free running mode not implemented\n");
67 /* Assume 66MHz system clock. */
68 ptimer_set_freq(s
->timer
, 66000000 / prescale
);
70 ptimer_set_limit(s
->timer
, s
->trr
, 0);
72 ptimer_run(s
->timer
, 0);
75 static void m5206_timer_trigger(void *opaque
)
77 m5206_timer_state
*s
= (m5206_timer_state
*)opaque
;
79 m5206_timer_update(s
);
82 static uint32_t m5206_timer_read(m5206_timer_state
*s
, uint32_t addr
)
92 return s
->trr
- ptimer_get_count(s
->timer
);
100 static void m5206_timer_write(m5206_timer_state
*s
, uint32_t addr
, uint32_t val
)
104 if ((s
->tmr
& TMR_RST
) != 0 && (val
& TMR_RST
) == 0) {
105 m5206_timer_reset(s
);
108 m5206_timer_recalibrate(s
);
112 m5206_timer_recalibrate(s
);
118 ptimer_set_count(s
->timer
, val
);
126 m5206_timer_update(s
);
129 static m5206_timer_state
*m5206_timer_init(qemu_irq irq
)
131 m5206_timer_state
*s
;
134 s
= (m5206_timer_state
*)qemu_mallocz(sizeof(m5206_timer_state
));
135 bh
= qemu_bh_new(m5206_timer_trigger
, s
);
136 s
->timer
= ptimer_init(bh
);
138 m5206_timer_reset(s
);
158 CharDriverState
*chr
;
161 /* UART Status Register bits. */
162 #define M5206_UART_RxRDY 0x01
163 #define M5206_UART_FFULL 0x02
164 #define M5206_UART_TxRDY 0x04
165 #define M5206_UART_TxEMP 0x08
166 #define M5206_UART_OE 0x10
167 #define M5206_UART_PE 0x20
168 #define M5206_UART_FE 0x40
169 #define M5206_UART_RB 0x80
171 /* Interrupt flags. */
172 #define M5206_UART_TxINT 0x01
173 #define M5206_UART_RxINT 0x02
174 #define M5206_UART_DBINT 0x04
175 #define M5206_UART_COSINT 0x80
178 #define M5206_UART_BC0 0x01
179 #define M5206_UART_BC1 0x02
180 #define M5206_UART_PT 0x04
181 #define M5206_UART_PM0 0x08
182 #define M5206_UART_PM1 0x10
183 #define M5206_UART_ERR 0x20
184 #define M5206_UART_RxIRQ 0x40
185 #define M5206_UART_RxRTS 0x80
187 static void m5206_uart_update(m5206_uart_state
*s
)
189 s
->isr
&= ~(M5206_UART_TxINT
| M5206_UART_RxINT
);
190 if (s
->sr
& M5206_UART_TxRDY
)
191 s
->isr
|= M5206_UART_TxINT
;
192 if ((s
->sr
& ((s
->mr
[0] & M5206_UART_RxIRQ
)
193 ? M5206_UART_FFULL
: M5206_UART_RxRDY
)) != 0)
194 s
->isr
|= M5206_UART_RxINT
;
196 qemu_set_irq(s
->irq
, (s
->isr
& s
->imr
) != 0);
199 static uint32_t m5206_uart_read(m5206_uart_state
*s
, uint32_t addr
)
203 return s
->mr
[s
->current_mr
];
211 if (s
->fifo_len
== 0)
216 for (i
= 0; i
< s
->fifo_len
; i
++)
217 s
->fifo
[i
] = s
->fifo
[i
+ 1];
218 s
->sr
&= ~M5206_UART_FFULL
;
219 if (s
->fifo_len
== 0)
220 s
->sr
&= ~M5206_UART_RxRDY
;
221 m5206_uart_update(s
);
225 /* TODO: Implement IPCR. */
238 /* Update TxRDY flag and set data if present and enabled. */
239 static void m5206_uart_do_tx(m5206_uart_state
*s
)
241 if (s
->tx_enabled
&& (s
->sr
& M5206_UART_TxEMP
) == 0) {
243 qemu_chr_write(s
->chr
, (unsigned char *)&s
->tb
, 1);
244 s
->sr
|= M5206_UART_TxEMP
;
247 s
->sr
|= M5206_UART_TxRDY
;
249 s
->sr
&= ~M5206_UART_TxRDY
;
253 static void m5206_do_command(m5206_uart_state
*s
, uint8_t cmd
)
256 switch ((cmd
>> 4) & 3) {
259 case 1: /* Reset mode register pointer. */
262 case 2: /* Reset receiver. */
265 s
->sr
&= ~(M5206_UART_RxRDY
| M5206_UART_FFULL
);
267 case 3: /* Reset transmitter. */
269 s
->sr
|= M5206_UART_TxEMP
;
270 s
->sr
&= ~M5206_UART_TxRDY
;
272 case 4: /* Reset error status. */
274 case 5: /* Reset break-change interrupt. */
275 s
->isr
&= ~M5206_UART_DBINT
;
277 case 6: /* Start break. */
278 case 7: /* Stop break. */
282 /* Transmitter command. */
283 switch ((cmd
>> 2) & 3) {
286 case 1: /* Enable. */
290 case 2: /* Disable. */
294 case 3: /* Reserved. */
295 fprintf(stderr
, "m5206_uart: Bad TX command\n");
299 /* Receiver command. */
303 case 1: /* Enable. */
309 case 3: /* Reserved. */
310 fprintf(stderr
, "m5206_uart: Bad RX command\n");
315 static void m5206_uart_write(m5206_uart_state
*s
, uint32_t addr
, uint32_t val
)
319 s
->mr
[s
->current_mr
] = val
;
323 /* CSR is ignored. */
325 case 0x08: /* Command Register. */
326 m5206_do_command(s
, val
);
328 case 0x0c: /* Transmit Buffer. */
329 s
->sr
&= ~M5206_UART_TxEMP
;
334 /* ACR is ignored. */
342 m5206_uart_update(s
);
345 static void m5206_uart_reset(m5206_uart_state
*s
)
350 s
->sr
= M5206_UART_TxEMP
;
357 static void m5206_uart_push_byte(m5206_uart_state
*s
, uint8_t data
)
359 /* Break events overwrite the last byte if the fifo is full. */
360 if (s
->fifo_len
== 4)
363 s
->fifo
[s
->fifo_len
] = data
;
365 s
->sr
|= M5206_UART_RxRDY
;
366 if (s
->fifo_len
== 4)
367 s
->sr
|= M5206_UART_FFULL
;
369 m5206_uart_update(s
);
372 static void m5206_uart_event(void *opaque
, int event
)
374 m5206_uart_state
*s
= (m5206_uart_state
*)opaque
;
377 case CHR_EVENT_BREAK
:
378 s
->isr
|= M5206_UART_DBINT
;
379 m5206_uart_push_byte(s
, 0);
386 static int m5206_uart_can_receive(void *opaque
)
388 m5206_uart_state
*s
= (m5206_uart_state
*)opaque
;
390 return s
->rx_enabled
&& (s
->sr
& M5206_UART_FFULL
) == 0;
393 static void m5206_uart_receive(void *opaque
, const uint8_t *buf
, int size
)
395 m5206_uart_state
*s
= (m5206_uart_state
*)opaque
;
397 m5206_uart_push_byte(s
, buf
[0]);
400 static m5206_uart_state
*m5206_uart_init(qemu_irq irq
, CharDriverState
*chr
)
404 s
= qemu_mallocz(sizeof(m5206_uart_state
));
408 qemu_chr_add_handlers(chr
, m5206_uart_can_receive
, m5206_uart_receive
,
409 m5206_uart_event
, s
);
415 /* System Integration Module. */
419 m5206_timer_state
*timer
[2];
420 m5206_uart_state
*uart
[2];
423 uint16_t imr
; /* 1 == interrupt is masked. */
428 /* Include the UART vector registers here. */
432 /* Interrupt controller. */
434 static int m5206_find_pending_irq(m5206_mbar_state
*s
)
443 active
= s
->ipr
& ~s
->imr
;
447 for (i
= 1; i
< 14; i
++) {
448 if (active
& (1 << i
)) {
449 if ((s
->icr
[i
] & 0x1f) > level
) {
450 level
= s
->icr
[i
] & 0x1f;
462 static void m5206_mbar_update(m5206_mbar_state
*s
)
468 irq
= m5206_find_pending_irq(s
);
472 level
= (tmp
>> 2) & 7;
488 /* Unknown vector. */
489 fprintf(stderr
, "Unhandled vector for IRQ %d\n", irq
);
498 m68k_set_irq_level(s
->env
, level
, vector
);
501 static void m5206_mbar_set_irq(void *opaque
, int irq
, int level
)
503 m5206_mbar_state
*s
= (m5206_mbar_state
*)opaque
;
507 s
->ipr
&= ~(1 << irq
);
509 m5206_mbar_update(s
);
512 /* System Integration Module. */
514 static void m5206_mbar_reset(m5206_mbar_state
*s
)
536 static uint32_t m5206_mbar_read(m5206_mbar_state
*s
, uint32_t offset
)
538 if (offset
>= 0x100 && offset
< 0x120) {
539 return m5206_timer_read(s
->timer
[0], offset
- 0x100);
540 } else if (offset
>= 0x120 && offset
< 0x140) {
541 return m5206_timer_read(s
->timer
[1], offset
- 0x120);
542 } else if (offset
>= 0x140 && offset
< 0x160) {
543 return m5206_uart_read(s
->uart
[0], offset
- 0x140);
544 } else if (offset
>= 0x180 && offset
< 0x1a0) {
545 return m5206_uart_read(s
->uart
[1], offset
- 0x180);
548 case 0x03: return s
->scr
;
549 case 0x14 ... 0x20: return s
->icr
[offset
- 0x13];
550 case 0x36: return s
->imr
;
551 case 0x3a: return s
->ipr
;
552 case 0x40: return s
->rsr
;
554 case 0x42: return s
->swivr
;
556 /* DRAM mask register. */
557 /* FIXME: currently hardcoded to 128Mb. */
560 while (mask
> ram_size
)
562 return mask
& 0x0ffe0000;
564 case 0x5c: return 1; /* DRAM bank 1 empty. */
565 case 0xcb: return s
->par
;
566 case 0x170: return s
->uivr
[0];
567 case 0x1b0: return s
->uivr
[1];
569 cpu_abort(cpu_single_env
, "Bad MBAR read offset 0x%x", (int)offset
);
573 static void m5206_mbar_write(m5206_mbar_state
*s
, uint32_t offset
,
576 if (offset
>= 0x100 && offset
< 0x120) {
577 m5206_timer_write(s
->timer
[0], offset
- 0x100, value
);
579 } else if (offset
>= 0x120 && offset
< 0x140) {
580 m5206_timer_write(s
->timer
[1], offset
- 0x120, value
);
582 } else if (offset
>= 0x140 && offset
< 0x160) {
583 m5206_uart_write(s
->uart
[0], offset
- 0x140, value
);
585 } else if (offset
>= 0x180 && offset
< 0x1a0) {
586 m5206_uart_write(s
->uart
[1], offset
- 0x180, value
);
594 s
->icr
[offset
- 0x13] = value
;
595 m5206_mbar_update(s
);
599 m5206_mbar_update(s
);
605 /* TODO: implement watchdog. */
616 case 0x178: case 0x17c: case 0x1c8: case 0x1bc:
617 /* Not implemented: UART Output port bits. */
623 cpu_abort(cpu_single_env
, "Bad MBAR write offset 0x%x", (int)offset
);
628 /* Internal peripherals use a variety of register widths.
629 This lookup table allows a single routine to handle all of them. */
630 static const int m5206_mbar_width
[] =
632 /* 000-040 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
633 /* 040-080 */ 1, 2, 2, 2, 4, 1, 2, 4, 1, 2, 4, 2, 2, 4, 2, 2,
634 /* 080-0c0 */ 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4,
635 /* 0c0-100 */ 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
636 /* 100-140 */ 2, 2, 2, 2, 1, 0, 0, 0, 2, 2, 2, 2, 1, 0, 0, 0,
637 /* 140-180 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
638 /* 180-1c0 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
639 /* 1c0-200 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
642 static uint32_t m5206_mbar_readw(void *opaque
, target_phys_addr_t offset
);
643 static uint32_t m5206_mbar_readl(void *opaque
, target_phys_addr_t offset
);
645 static uint32_t m5206_mbar_readb(void *opaque
, target_phys_addr_t offset
)
647 m5206_mbar_state
*s
= (m5206_mbar_state
*)opaque
;
649 if (offset
> 0x200) {
650 cpu_abort(cpu_single_env
, "Bad MBAR read offset 0x%x", (int)offset
);
652 if (m5206_mbar_width
[offset
>> 2] > 1) {
654 val
= m5206_mbar_readw(opaque
, offset
& ~1);
655 if ((offset
& 1) == 0) {
660 return m5206_mbar_read(s
, offset
);
663 static uint32_t m5206_mbar_readw(void *opaque
, target_phys_addr_t offset
)
665 m5206_mbar_state
*s
= (m5206_mbar_state
*)opaque
;
668 if (offset
> 0x200) {
669 cpu_abort(cpu_single_env
, "Bad MBAR read offset 0x%x", (int)offset
);
671 width
= m5206_mbar_width
[offset
>> 2];
674 val
= m5206_mbar_readl(opaque
, offset
& ~3);
675 if ((offset
& 3) == 0)
678 } else if (width
< 2) {
680 val
= m5206_mbar_readb(opaque
, offset
) << 8;
681 val
|= m5206_mbar_readb(opaque
, offset
+ 1);
684 return m5206_mbar_read(s
, offset
);
687 static uint32_t m5206_mbar_readl(void *opaque
, target_phys_addr_t offset
)
689 m5206_mbar_state
*s
= (m5206_mbar_state
*)opaque
;
692 if (offset
> 0x200) {
693 cpu_abort(cpu_single_env
, "Bad MBAR read offset 0x%x", (int)offset
);
695 width
= m5206_mbar_width
[offset
>> 2];
698 val
= m5206_mbar_readw(opaque
, offset
) << 16;
699 val
|= m5206_mbar_readw(opaque
, offset
+ 2);
702 return m5206_mbar_read(s
, offset
);
705 static void m5206_mbar_writew(void *opaque
, target_phys_addr_t offset
,
707 static void m5206_mbar_writel(void *opaque
, target_phys_addr_t offset
,
710 static void m5206_mbar_writeb(void *opaque
, target_phys_addr_t offset
,
713 m5206_mbar_state
*s
= (m5206_mbar_state
*)opaque
;
716 if (offset
> 0x200) {
717 cpu_abort(cpu_single_env
, "Bad MBAR write offset 0x%x", (int)offset
);
719 width
= m5206_mbar_width
[offset
>> 2];
722 tmp
= m5206_mbar_readw(opaque
, offset
& ~1);
724 tmp
= (tmp
& 0xff00) | value
;
726 tmp
= (tmp
& 0x00ff) | (value
<< 8);
728 m5206_mbar_writew(opaque
, offset
& ~1, tmp
);
731 m5206_mbar_write(s
, offset
, value
);
734 static void m5206_mbar_writew(void *opaque
, target_phys_addr_t offset
,
737 m5206_mbar_state
*s
= (m5206_mbar_state
*)opaque
;
740 if (offset
> 0x200) {
741 cpu_abort(cpu_single_env
, "Bad MBAR write offset 0x%x", (int)offset
);
743 width
= m5206_mbar_width
[offset
>> 2];
746 tmp
= m5206_mbar_readl(opaque
, offset
& ~3);
748 tmp
= (tmp
& 0xffff0000) | value
;
750 tmp
= (tmp
& 0x0000ffff) | (value
<< 16);
752 m5206_mbar_writel(opaque
, offset
& ~3, tmp
);
754 } else if (width
< 2) {
755 m5206_mbar_writeb(opaque
, offset
, value
>> 8);
756 m5206_mbar_writeb(opaque
, offset
+ 1, value
& 0xff);
759 m5206_mbar_write(s
, offset
, value
);
762 static void m5206_mbar_writel(void *opaque
, target_phys_addr_t offset
,
765 m5206_mbar_state
*s
= (m5206_mbar_state
*)opaque
;
768 if (offset
> 0x200) {
769 cpu_abort(cpu_single_env
, "Bad MBAR write offset 0x%x", (int)offset
);
771 width
= m5206_mbar_width
[offset
>> 2];
773 m5206_mbar_writew(opaque
, offset
, value
>> 16);
774 m5206_mbar_writew(opaque
, offset
+ 2, value
& 0xffff);
777 m5206_mbar_write(s
, offset
, value
);
780 static CPUReadMemoryFunc
*m5206_mbar_readfn
[] = {
786 static CPUWriteMemoryFunc
*m5206_mbar_writefn
[] = {
792 qemu_irq
*mcf5206_init(uint32_t base
, CPUState
*env
)
798 s
= (m5206_mbar_state
*)qemu_mallocz(sizeof(m5206_mbar_state
));
799 iomemtype
= cpu_register_io_memory(0, m5206_mbar_readfn
,
800 m5206_mbar_writefn
, s
);
801 cpu_register_physical_memory(base
, 0x00000fff, iomemtype
);
803 pic
= qemu_allocate_irqs(m5206_mbar_set_irq
, s
, 14);
804 s
->timer
[0] = m5206_timer_init(pic
[9]);
805 s
->timer
[1] = m5206_timer_init(pic
[10]);
806 s
->uart
[0] = m5206_uart_init(pic
[12], serial_hds
[0]);
807 s
->uart
[1] = m5206_uart_init(pic
[13], serial_hds
[1]);