2 * Arm PrimeCell PL011 UART
4 * Copyright (c) 2006 CodeSourcery.
5 * Written by Paul Brook
7 * This code is licenced under the GPL.
21 uint32_t read_fifo
[16];
33 #define PL011_INT_TX 0x20
34 #define PL011_INT_RX 0x10
36 #define PL011_FLAG_TXFE 0x80
37 #define PL011_FLAG_RXFF 0x40
38 #define PL011_FLAG_TXFF 0x20
39 #define PL011_FLAG_RXFE 0x10
41 static const unsigned char pl011_id
[] =
42 { 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
44 static void pl011_update(pl011_state
*s
)
48 flags
= s
->int_level
& s
->int_enabled
;
49 qemu_set_irq(s
->irq
, flags
!= 0);
52 static uint32_t pl011_read(void *opaque
, target_phys_addr_t offset
)
54 pl011_state
*s
= (pl011_state
*)opaque
;
58 if (offset
>= 0xfe0 && offset
< 0x1000) {
59 return pl011_id
[(offset
- 0xfe0) >> 2];
61 switch (offset
>> 2) {
63 s
->flags
&= ~PL011_FLAG_RXFF
;
64 c
= s
->read_fifo
[s
->read_pos
];
65 if (s
->read_count
> 0) {
67 if (++s
->read_pos
== 16)
70 if (s
->read_count
== 0) {
71 s
->flags
|= PL011_FLAG_RXFE
;
73 if (s
->read_count
== s
->read_trigger
- 1)
74 s
->int_level
&= ~ PL011_INT_RX
;
81 case 8: /* UARTILPR */
83 case 9: /* UARTIBRD */
85 case 10: /* UARTFBRD */
87 case 11: /* UARTLCR_H */
91 case 13: /* UARTIFLS */
93 case 14: /* UARTIMSC */
94 return s
->int_enabled
;
95 case 15: /* UARTRIS */
97 case 16: /* UARTMIS */
98 return s
->int_level
& s
->int_enabled
;
99 case 18: /* UARTDMACR */
102 cpu_abort (cpu_single_env
, "pl011_read: Bad offset %x\n", offset
);
107 static void pl011_set_read_trigger(pl011_state
*s
)
110 /* The docs say the RX interrupt is triggered when the FIFO exceeds
111 the threshold. However linux only reads the FIFO in response to an
112 interrupt. Triggering the interrupt when the FIFO is non-empty seems
113 to make things work. */
115 s
->read_trigger
= (s
->ifl
>> 1) & 0x1c;
121 static void pl011_write(void *opaque
, target_phys_addr_t offset
,
124 pl011_state
*s
= (pl011_state
*)opaque
;
128 switch (offset
>> 2) {
130 /* ??? Check if transmitter is enabled. */
133 qemu_chr_write(s
->chr
, &ch
, 1);
134 s
->int_level
|= PL011_INT_TX
;
140 case 8: /* UARTUARTILPR */
143 case 9: /* UARTIBRD */
146 case 10: /* UARTFBRD */
149 case 11: /* UARTLCR_H */
151 pl011_set_read_trigger(s
);
153 case 12: /* UARTCR */
154 /* ??? Need to implement the enable and loopback bits. */
157 case 13: /* UARTIFS */
159 pl011_set_read_trigger(s
);
161 case 14: /* UARTIMSC */
162 s
->int_enabled
= value
;
165 case 17: /* UARTICR */
166 s
->int_level
&= ~value
;
169 case 18: /* UARTDMACR */
172 cpu_abort(cpu_single_env
, "PL011: DMA not implemented\n");
175 cpu_abort (cpu_single_env
, "pl011_write: Bad offset %x\n", offset
);
179 static int pl011_can_recieve(void *opaque
)
181 pl011_state
*s
= (pl011_state
*)opaque
;
184 return s
->read_count
< 16;
186 return s
->read_count
< 1;
189 static void pl011_recieve(void *opaque
, const uint8_t *buf
, int size
)
191 pl011_state
*s
= (pl011_state
*)opaque
;
194 slot
= s
->read_pos
+ s
->read_count
;
197 s
->read_fifo
[slot
] = *buf
;
199 s
->flags
&= ~PL011_FLAG_RXFE
;
200 if (s
->cr
& 0x10 || s
->read_count
== 16) {
201 s
->flags
|= PL011_FLAG_RXFF
;
203 if (s
->read_count
== s
->read_trigger
) {
204 s
->int_level
|= PL011_INT_RX
;
209 static void pl011_event(void *opaque
, int event
)
211 /* ??? Should probably implement break. */
214 static CPUReadMemoryFunc
*pl011_readfn
[] = {
220 static CPUWriteMemoryFunc
*pl011_writefn
[] = {
226 void pl011_init(uint32_t base
, qemu_irq irq
,
227 CharDriverState
*chr
)
232 s
= (pl011_state
*)qemu_mallocz(sizeof(pl011_state
));
233 iomemtype
= cpu_register_io_memory(0, pl011_readfn
,
235 cpu_register_physical_memory(base
, 0x00001000, iomemtype
);
244 qemu_chr_add_handlers(chr
, pl011_can_recieve
, pl011_recieve
,
247 /* ??? Save/restore. */