2 * ColdFire UART emulation.
4 * Copyright (c) 2007 CodeSourcery.
6 * This code is licensed under the GPL
10 #include "qemu-char.h"
29 /* UART Status Register bits. */
30 #define MCF_UART_RxRDY 0x01
31 #define MCF_UART_FFULL 0x02
32 #define MCF_UART_TxRDY 0x04
33 #define MCF_UART_TxEMP 0x08
34 #define MCF_UART_OE 0x10
35 #define MCF_UART_PE 0x20
36 #define MCF_UART_FE 0x40
37 #define MCF_UART_RB 0x80
39 /* Interrupt flags. */
40 #define MCF_UART_TxINT 0x01
41 #define MCF_UART_RxINT 0x02
42 #define MCF_UART_DBINT 0x04
43 #define MCF_UART_COSINT 0x80
46 #define MCF_UART_BC0 0x01
47 #define MCF_UART_BC1 0x02
48 #define MCF_UART_PT 0x04
49 #define MCF_UART_PM0 0x08
50 #define MCF_UART_PM1 0x10
51 #define MCF_UART_ERR 0x20
52 #define MCF_UART_RxIRQ 0x40
53 #define MCF_UART_RxRTS 0x80
55 static void mcf_uart_update_handlers(mcf_uart_state
*s
);
57 static void mcf_uart_update(mcf_uart_state
*s
)
59 s
->isr
&= ~(MCF_UART_TxINT
| MCF_UART_RxINT
);
60 if (s
->sr
& MCF_UART_TxRDY
)
61 s
->isr
|= MCF_UART_TxINT
;
62 if ((s
->sr
& ((s
->mr
[0] & MCF_UART_RxIRQ
)
63 ? MCF_UART_FFULL
: MCF_UART_RxRDY
)) != 0)
64 s
->isr
|= MCF_UART_RxINT
;
66 qemu_set_irq(s
->irq
, (s
->isr
& s
->imr
) != 0);
69 uint32_t mcf_uart_read(void *opaque
, target_phys_addr_t addr
)
71 mcf_uart_state
*s
= (mcf_uart_state
*)opaque
;
72 switch (addr
& 0x3f) {
74 return s
->mr
[s
->current_mr
];
87 for (i
= 0; i
< s
->fifo_len
; i
++)
88 s
->fifo
[i
] = s
->fifo
[i
+ 1];
89 s
->sr
&= ~MCF_UART_FFULL
;
91 s
->sr
&= ~MCF_UART_RxRDY
;
93 mcf_uart_update_handlers(s
);
97 /* TODO: Implement IPCR. */
110 /* Update TxRDY flag and set data if present and enabled. */
111 static void mcf_uart_do_tx(mcf_uart_state
*s
)
113 if (s
->tx_enabled
&& (s
->sr
& MCF_UART_TxEMP
) == 0) {
115 qemu_chr_fe_write(s
->chr
, (unsigned char *)&s
->tb
, 1);
116 s
->sr
|= MCF_UART_TxEMP
;
119 s
->sr
|= MCF_UART_TxRDY
;
121 s
->sr
&= ~MCF_UART_TxRDY
;
123 mcf_uart_update_handlers(s
);
126 static void mcf_do_command(mcf_uart_state
*s
, uint8_t cmd
)
129 switch ((cmd
>> 4) & 3) {
132 case 1: /* Reset mode register pointer. */
135 case 2: /* Reset receiver. */
138 s
->sr
&= ~(MCF_UART_RxRDY
| MCF_UART_FFULL
);
139 mcf_uart_update_handlers(s
);
141 case 3: /* Reset transmitter. */
143 s
->sr
|= MCF_UART_TxEMP
;
144 s
->sr
&= ~MCF_UART_TxRDY
;
145 mcf_uart_update_handlers(s
);
147 case 4: /* Reset error status. */
149 case 5: /* Reset break-change interrupt. */
150 s
->isr
&= ~MCF_UART_DBINT
;
152 case 6: /* Start break. */
153 case 7: /* Stop break. */
157 /* Transmitter command. */
158 switch ((cmd
>> 2) & 3) {
161 case 1: /* Enable. */
165 case 2: /* Disable. */
169 case 3: /* Reserved. */
170 fprintf(stderr
, "mcf_uart: Bad TX command\n");
174 /* Receiver command. */
178 case 1: /* Enable. */
180 mcf_uart_update_handlers(s
);
184 mcf_uart_update_handlers(s
);
186 case 3: /* Reserved. */
187 fprintf(stderr
, "mcf_uart: Bad RX command\n");
192 void mcf_uart_write(void *opaque
, target_phys_addr_t addr
, uint32_t val
)
194 mcf_uart_state
*s
= (mcf_uart_state
*)opaque
;
195 switch (addr
& 0x3f) {
197 s
->mr
[s
->current_mr
] = val
;
201 /* CSR is ignored. */
203 case 0x08: /* Command Register. */
204 mcf_do_command(s
, val
);
206 case 0x0c: /* Transmit Buffer. */
207 s
->sr
&= ~MCF_UART_TxEMP
;
210 mcf_uart_update_handlers(s
);
213 /* ACR is ignored. */
224 static void mcf_uart_reset(mcf_uart_state
*s
)
229 s
->sr
= MCF_UART_TxEMP
;
234 mcf_uart_update_handlers(s
);
237 static void mcf_uart_push_byte(mcf_uart_state
*s
, uint8_t data
)
239 /* Break events overwrite the last byte if the fifo is full. */
240 if (s
->fifo_len
== 4)
243 s
->fifo
[s
->fifo_len
] = data
;
245 s
->sr
|= MCF_UART_RxRDY
;
246 if (s
->fifo_len
== 4)
247 s
->sr
|= MCF_UART_FFULL
;
249 mcf_uart_update_handlers(s
);
253 static int mcf_uart_event(void *opaque
, int event
, void *data
)
255 mcf_uart_state
*s
= (mcf_uart_state
*)opaque
;
258 case CHR_EVENT_BREAK
:
259 s
->isr
|= MCF_UART_DBINT
;
260 mcf_uart_push_byte(s
, 0);
268 static int mcf_uart_can_receive(mcf_uart_state
*s
)
270 return s
->rx_enabled
&& (s
->sr
& MCF_UART_FFULL
) == 0;
273 static void mcf_uart_receive(mcf_uart_state
*s
, const uint8_t *buf
, int size
)
275 mcf_uart_push_byte(s
, buf
[0]);
278 static void mcf_uart_receive_handler(void *opaque
)
280 mcf_uart_state
*s
= opaque
;
284 size
= mcf_uart_can_receive(s
);
285 size
= MIN(size
, sizeof(buf
));
286 size
= qemu_chr_fe_read(s
->chr
, buf
, size
);
288 mcf_uart_receive(s
, buf
, size
);
291 static void mcf_uart_update_handlers(mcf_uart_state
*s
)
293 if (mcf_uart_can_receive(s
) > 0) {
294 qemu_chr_fe_set_handlers(s
->chr
, mcf_uart_receive_handler
,
295 NULL
, mcf_uart_event
, s
);
297 qemu_chr_fe_set_handlers(s
->chr
, NULL
, NULL
, mcf_uart_event
, s
);
301 void *mcf_uart_init(qemu_irq irq
, CharDriverState
*chr
)
305 s
= qemu_mallocz(sizeof(mcf_uart_state
));
309 qemu_chr_fe_open(chr
);
316 static CPUReadMemoryFunc
* const mcf_uart_readfn
[] = {
322 static CPUWriteMemoryFunc
* const mcf_uart_writefn
[] = {
328 void mcf_uart_mm_init(target_phys_addr_t base
, qemu_irq irq
,
329 CharDriverState
*chr
)
334 s
= mcf_uart_init(irq
, chr
);
335 iomemtype
= cpu_register_io_memory(mcf_uart_readfn
,
337 DEVICE_NATIVE_ENDIAN
);
338 cpu_register_physical_memory(base
, 0x40, iomemtype
);