2 * Arm PrimeCell PL011 UART
4 * Copyright (c) 2006 CodeSourcery.
5 * Written by Paul Brook
7 * This code is licenced under the GPL.
11 #include "qemu-char.h"
22 uint32_t read_fifo
[16];
32 const unsigned char *id
;
35 #define PL011_INT_TX 0x20
36 #define PL011_INT_RX 0x10
38 #define PL011_FLAG_TXFE 0x80
39 #define PL011_FLAG_RXFF 0x40
40 #define PL011_FLAG_TXFF 0x20
41 #define PL011_FLAG_RXFE 0x10
43 static const unsigned char pl011_id_arm
[8] =
44 { 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
45 static const unsigned char pl011_id_luminary
[8] =
46 { 0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 };
48 static void pl011_update(pl011_state
*s
)
52 flags
= s
->int_level
& s
->int_enabled
;
53 qemu_set_irq(s
->irq
, flags
!= 0);
56 static uint32_t pl011_read(void *opaque
, target_phys_addr_t offset
)
58 pl011_state
*s
= (pl011_state
*)opaque
;
61 if (offset
>= 0xfe0 && offset
< 0x1000) {
62 return s
->id
[(offset
- 0xfe0) >> 2];
64 switch (offset
>> 2) {
66 s
->flags
&= ~PL011_FLAG_RXFF
;
67 c
= s
->read_fifo
[s
->read_pos
];
68 if (s
->read_count
> 0) {
70 if (++s
->read_pos
== 16)
73 if (s
->read_count
== 0) {
74 s
->flags
|= PL011_FLAG_RXFE
;
76 if (s
->read_count
== s
->read_trigger
- 1)
77 s
->int_level
&= ~ PL011_INT_RX
;
79 qemu_chr_accept_input(s
->chr
);
85 case 8: /* UARTILPR */
87 case 9: /* UARTIBRD */
89 case 10: /* UARTFBRD */
91 case 11: /* UARTLCR_H */
95 case 13: /* UARTIFLS */
97 case 14: /* UARTIMSC */
98 return s
->int_enabled
;
99 case 15: /* UARTRIS */
101 case 16: /* UARTMIS */
102 return s
->int_level
& s
->int_enabled
;
103 case 18: /* UARTDMACR */
106 hw_error("pl011_read: Bad offset %x\n", (int)offset
);
111 static void pl011_set_read_trigger(pl011_state
*s
)
114 /* The docs say the RX interrupt is triggered when the FIFO exceeds
115 the threshold. However linux only reads the FIFO in response to an
116 interrupt. Triggering the interrupt when the FIFO is non-empty seems
117 to make things work. */
119 s
->read_trigger
= (s
->ifl
>> 1) & 0x1c;
125 static void pl011_write(void *opaque
, target_phys_addr_t offset
,
128 pl011_state
*s
= (pl011_state
*)opaque
;
131 switch (offset
>> 2) {
133 /* ??? Check if transmitter is enabled. */
136 qemu_chr_write(s
->chr
, &ch
, 1);
137 s
->int_level
|= PL011_INT_TX
;
144 /* Writes to Flag register are ignored. */
146 case 8: /* UARTUARTILPR */
149 case 9: /* UARTIBRD */
152 case 10: /* UARTFBRD */
155 case 11: /* UARTLCR_H */
157 pl011_set_read_trigger(s
);
159 case 12: /* UARTCR */
160 /* ??? Need to implement the enable and loopback bits. */
163 case 13: /* UARTIFS */
165 pl011_set_read_trigger(s
);
167 case 14: /* UARTIMSC */
168 s
->int_enabled
= value
;
171 case 17: /* UARTICR */
172 s
->int_level
&= ~value
;
175 case 18: /* UARTDMACR */
178 hw_error("PL011: DMA not implemented\n");
181 hw_error("pl011_write: Bad offset %x\n", (int)offset
);
185 static int pl011_can_receive(void *opaque
)
187 pl011_state
*s
= (pl011_state
*)opaque
;
190 return s
->read_count
< 16;
192 return s
->read_count
< 1;
195 static void pl011_put_fifo(void *opaque
, uint32_t value
)
197 pl011_state
*s
= (pl011_state
*)opaque
;
200 slot
= s
->read_pos
+ s
->read_count
;
203 s
->read_fifo
[slot
] = value
;
205 s
->flags
&= ~PL011_FLAG_RXFE
;
206 if (s
->cr
& 0x10 || s
->read_count
== 16) {
207 s
->flags
|= PL011_FLAG_RXFF
;
209 if (s
->read_count
== s
->read_trigger
) {
210 s
->int_level
|= PL011_INT_RX
;
215 static void pl011_receive(void *opaque
, const uint8_t *buf
, int size
)
217 pl011_put_fifo(opaque
, *buf
);
220 static void pl011_event(void *opaque
, int event
)
222 if (event
== CHR_EVENT_BREAK
)
223 pl011_put_fifo(opaque
, 0x400);
226 static CPUReadMemoryFunc
*pl011_readfn
[] = {
232 static CPUWriteMemoryFunc
*pl011_writefn
[] = {
238 static void pl011_save(QEMUFile
*f
, void *opaque
)
240 pl011_state
*s
= (pl011_state
*)opaque
;
243 qemu_put_be32(f
, s
->readbuff
);
244 qemu_put_be32(f
, s
->flags
);
245 qemu_put_be32(f
, s
->lcr
);
246 qemu_put_be32(f
, s
->cr
);
247 qemu_put_be32(f
, s
->dmacr
);
248 qemu_put_be32(f
, s
->int_enabled
);
249 qemu_put_be32(f
, s
->int_level
);
250 for (i
= 0; i
< 16; i
++)
251 qemu_put_be32(f
, s
->read_fifo
[i
]);
252 qemu_put_be32(f
, s
->ilpr
);
253 qemu_put_be32(f
, s
->ibrd
);
254 qemu_put_be32(f
, s
->fbrd
);
255 qemu_put_be32(f
, s
->ifl
);
256 qemu_put_be32(f
, s
->read_pos
);
257 qemu_put_be32(f
, s
->read_count
);
258 qemu_put_be32(f
, s
->read_trigger
);
261 static int pl011_load(QEMUFile
*f
, void *opaque
, int version_id
)
263 pl011_state
*s
= (pl011_state
*)opaque
;
269 s
->readbuff
= qemu_get_be32(f
);
270 s
->flags
= qemu_get_be32(f
);
271 s
->lcr
= qemu_get_be32(f
);
272 s
->cr
= qemu_get_be32(f
);
273 s
->dmacr
= qemu_get_be32(f
);
274 s
->int_enabled
= qemu_get_be32(f
);
275 s
->int_level
= qemu_get_be32(f
);
276 for (i
= 0; i
< 16; i
++)
277 s
->read_fifo
[i
] = qemu_get_be32(f
);
278 s
->ilpr
= qemu_get_be32(f
);
279 s
->ibrd
= qemu_get_be32(f
);
280 s
->fbrd
= qemu_get_be32(f
);
281 s
->ifl
= qemu_get_be32(f
);
282 s
->read_pos
= qemu_get_be32(f
);
283 s
->read_count
= qemu_get_be32(f
);
284 s
->read_trigger
= qemu_get_be32(f
);
289 static void pl011_init(SysBusDevice
*dev
, const unsigned char *id
)
292 pl011_state
*s
= FROM_SYSBUS(pl011_state
, dev
);
294 iomemtype
= cpu_register_io_memory(0, pl011_readfn
,
296 sysbus_init_mmio(dev
, 0x1000,iomemtype
);
297 sysbus_init_irq(dev
, &s
->irq
);
299 s
->chr
= qdev_init_chardev(&dev
->qdev
);
306 qemu_chr_add_handlers(s
->chr
, pl011_can_receive
, pl011_receive
,
309 register_savevm("pl011_uart", -1, 1, pl011_save
, pl011_load
, s
);
312 static void pl011_init_arm(SysBusDevice
*dev
)
314 pl011_init(dev
, pl011_id_arm
);
317 static void pl011_init_luminary(SysBusDevice
*dev
)
319 pl011_init(dev
, pl011_id_luminary
);
322 static void pl011_register_devices(void)
324 sysbus_register_dev("pl011", sizeof(pl011_state
),
326 sysbus_register_dev("pl011_luminary", sizeof(pl011_state
),
327 pl011_init_luminary
);
330 device_init(pl011_register_devices
)