Fix the size of the property fields.
[qemu/navara.git] / hw / at91_dbgu.c
blobb244b239043a5769e8e64ec45170fe2ba01b14b8
1 /*
2 * AT91 Debug Unit
4 * Copyright (c) 2009 Filip Navara
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
25 /* TODO: Channel mode, ICE pins, FIFO?, overrun, retransmission */
27 #include "sysbus.h"
28 #include "qemu-char.h"
29 #include "at91.h"
31 /* #define DEBUG_DBGU */
33 #define DBGU_SIZE 0x200
35 #define DBGU_CR 0x00 /* Control Register */
36 #define DBGU_MR 0x04 /* Mode Register */
37 #define DBGU_IER 0x08 /* Interrupt Enable Register */
38 #define DBGU_IDR 0x0c /* Interrupt Disable Register */
39 #define DBGU_IMR 0x10 /* Interrupt Mask Register */
40 #define DBGU_SR 0x14 /* Channel Status Register */
41 #define DBGU_RHR 0x18 /* Receiver Holding Register */
42 #define DBGU_THR 0x1c /* Transmitter Holding Register */
43 #define DBGU_BRGR 0x20 /* Baud Rate Generator Register */
44 #define DBGU_CIDR 0x40 /* Chip ID Register */
45 #define DBGU_EXID 0x44 /* Chip ID Extension Register */
46 #define DBGU_FNR 0x48 /* Force NTRST Register */
48 #define SR_RXRDY 0x01 /* Reciever Ready */
49 #define SR_TXRDY 0x02 /* Transmitter Ready */
50 #define SR_ENDRX 0x08 /* End of Receive Transfer */
51 #define SR_ENDTX 0x10 /* End of Transmit */
52 #define SR_OVRE 0x20 /* Overrun */
53 #define SR_FRAME 0x40 /* Framing Error */
54 #define SR_PARE 0x80 /* Parity Error */
55 #define SR_TXEMPTY 0x200 /* Transmitter Empty */
56 #define SR_TXBUFE 0x800 /* Transmission Buffer Empty */
57 #define SR_RXBUFF 0x1000 /* Receiver Buffer Full */
58 #define SR_COMM_TX 0x40000000
59 #define SR_COMM_RX 0x80000000
61 #define CR_RXEN 0x10
62 #define CR_RXDIS 0x20
63 #define CR_TXEN 0x40
64 #define CR_TXDIS 0x80
65 #define CR_RSTSTA 0x100
67 #define DEFAULT_CHIPID 0x275b0940
69 typedef struct DBGUState {
70 SysBusDevice busdev;
71 CharDriverState *chr;
72 qemu_irq irq;
73 uint32_t chipid;
74 uint32_t chipid_ext;
76 uint8_t rx_enabled;
77 uint8_t tx_enabled;
78 uint32_t mr;
79 uint32_t imr;
80 uint32_t sr;
81 uint8_t rhr;
82 uint8_t thr;
83 uint16_t brgr;
84 uint32_t fnr;
85 } DBGUState;
87 static void at91_dbgu_update_irq(DBGUState *s)
89 qemu_set_irq(s->irq, !!(s->sr & s->imr));
92 static void at91_dbgu_update_parameters(DBGUState *s)
94 QEMUSerialSetParams ssp;
96 if (s->brgr == 0)
97 return;
98 if (s->brgr == 1)
99 ssp.speed = at91_master_clock_frequency / s->brgr;
100 else
101 ssp.speed = at91_master_clock_frequency / (16 * s->brgr);
102 ssp.parity = 'O';
103 ssp.data_bits = 8;
104 ssp.stop_bits = 1;
105 qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
108 static void at91_dbgu_receive(void *opaque, const uint8_t *buf, int size)
110 DBGUState *s = opaque;
112 s->sr |= SR_RXRDY | SR_RXBUFF;
113 s->rhr = (buf[0] & 0xff);
114 at91_dbgu_update_irq(s);
117 static int at91_dbgu_can_receive(void *opaque)
119 DBGUState *s = opaque;
121 if (s->rx_enabled && !(s->sr & SR_RXRDY))
122 return 1;
123 return 0;
126 static void at91_dbgu_event(void *opaque, int event)
130 static uint32_t at91_dbgu_mem_read(void *opaque, target_phys_addr_t offset)
132 DBGUState *s = opaque;
133 uint32_t value;
135 offset &= DBGU_SIZE - 1;
136 switch (offset) {
137 case DBGU_MR:
138 return s->mr;
139 case DBGU_IMR:
140 return s->imr;
141 case DBGU_SR:
142 return s->sr;
143 case DBGU_RHR:
144 value = s->rhr;
145 s->sr &= ~(SR_RXRDY | SR_RXBUFF);
146 at91_dbgu_update_irq(s);
147 return value;
148 case DBGU_BRGR:
149 return s->brgr;
150 case DBGU_CIDR:
151 return s->chipid;
152 case DBGU_EXID:
153 return s->chipid_ext;
154 case DBGU_FNR:
155 return s->fnr;
156 default:
157 return 0;
161 static void at91_dbgu_mem_write(void *opaque, target_phys_addr_t offset,
162 uint32_t value)
164 DBGUState *s = opaque;
165 unsigned char ch = value;
167 offset &= DBGU_SIZE - 1;
168 switch (offset) {
169 case DBGU_CR:
170 if (value & CR_RXDIS) {
171 s->rx_enabled = 0;
172 } else if (value & CR_RXEN) {
173 s->rx_enabled = 1;
175 if (value & CR_TXDIS) {
176 s->tx_enabled = 0;
177 } else if (value & CR_TXEN) {
178 s->tx_enabled = 1;
180 if (value & CR_RSTSTA) {
181 s->sr &= ~(SR_PARE | SR_FRAME | SR_OVRE);
183 break;
184 case DBGU_MR:
185 s->mr = value;
186 break;
187 case DBGU_IER:
188 s->imr |= value;
189 break;
190 case DBGU_IDR:
191 s->imr &= ~value;
192 break;
193 case DBGU_THR:
194 if (s->tx_enabled)
196 /* TODO: shift register, error checking */
197 s->thr = value;
198 qemu_chr_write(s->chr, &ch, 1);
199 s->sr |= SR_TXRDY | SR_TXBUFE | SR_TXEMPTY;
201 break;
202 case DBGU_BRGR:
203 s->brgr = value;
204 at91_dbgu_update_parameters(s);
205 break;
206 case DBGU_FNR:
207 s->fnr = value;
208 break;
209 default:
210 return;
213 at91_dbgu_update_irq(s);
216 #ifdef DEBUG_DBGU
217 static uint32_t at91_dbgu_mem_read_dbg(void *opaque, target_phys_addr_t offset)
219 uint32_t value = at91_dbgu_mem_read(opaque, offset);
220 printf("%s offset=%x val=%x\n", __func__, offset, value);
221 return value;
224 static void at91_dbgu_mem_write_dbg(void *opaque, target_phys_addr_t offset,
225 uint32_t value)
227 printf("%s offset=%x val=%x\n", __func__, offset, value);
228 at91_dbgu_mem_write(opaque, offset, value);
231 #define at91_dbgu_mem_read at91_dbgu_mem_read_dbg
232 #define at91_dbgu_mem_write at91_dbgu_mem_write_dbg
233 #endif
235 static CPUReadMemoryFunc *at91_dbgu_readfn[] = {
236 at91_dbgu_mem_read,
237 at91_dbgu_mem_read,
238 at91_dbgu_mem_read,
241 static CPUWriteMemoryFunc *at91_dbgu_writefn[] = {
242 at91_dbgu_mem_write,
243 at91_dbgu_mem_write,
244 at91_dbgu_mem_write,
247 static void at91_dbgu_save(QEMUFile *f, void *opaque)
249 DBGUState *s = opaque;
251 qemu_put_byte(f, s->rx_enabled);
252 qemu_put_byte(f, s->tx_enabled);
253 qemu_put_be32(f, s->mr);
254 qemu_put_be32(f, s->imr);
255 qemu_put_be32(f, s->sr);
256 qemu_put_byte(f, s->rhr);
257 qemu_put_byte(f, s->thr);
258 qemu_put_be16(f, s->brgr);
259 qemu_put_be32(f, s->fnr);
262 static int at91_dbgu_load(QEMUFile *f, void *opaque, int version_id)
264 DBGUState *s = opaque;
266 if (version_id != 1)
267 return -EINVAL;
269 s->rx_enabled = qemu_get_byte(f);
270 s->tx_enabled = qemu_get_byte(f);
271 s->mr = qemu_get_be32(f);
272 s->imr = qemu_get_be32(f);
273 s->sr = qemu_get_be32(f);
274 s->rhr = qemu_get_byte(f);
275 s->thr = qemu_get_byte(f);
276 s->brgr = qemu_get_be16(f);
277 s->fnr = qemu_get_be32(f);
279 return 0;
282 static void at91_dbgu_reset(void *opaque)
284 DBGUState *s = opaque;
286 s->rx_enabled = 0;
287 s->tx_enabled = 0;
288 s->mr = 0;
289 s->imr = 0;
290 /* Transmitter begins ready and idle */
291 s->sr = SR_TXRDY | SR_TXBUFE | SR_TXEMPTY;
292 s->rhr = 0;
293 s->thr = 0;
294 s->brgr = 0;
295 s->fnr = 0;
298 static void at91_dbgu_init(SysBusDevice *dev)
300 DBGUState *s = FROM_SYSBUS(typeof (*s), dev);
301 int ser_regs;
303 sysbus_init_irq(dev, &s->irq);
304 ser_regs = cpu_register_io_memory(at91_dbgu_readfn, at91_dbgu_writefn, s);
305 sysbus_init_mmio(dev, DBGU_SIZE, ser_regs);
306 s->chr = qdev_init_chardev(&dev->qdev);
307 if (s->chr) {
308 qemu_chr_add_handlers(s->chr, at91_dbgu_can_receive,
309 at91_dbgu_receive, at91_dbgu_event, s);
312 at91_dbgu_reset(s);
313 qemu_register_reset(at91_dbgu_reset, s);
315 register_savevm("at91_dbgu", -1, 1, at91_dbgu_save, at91_dbgu_load, s);
318 static SysBusDeviceInfo at91_dbgu_info = {
319 .init = at91_dbgu_init,
320 .qdev.name = "at91,dbgu",
321 .qdev.size = sizeof(DBGUState),
322 .qdev.props = (Property[]) {
324 .name = "chipid",
325 .info = &qdev_prop_uint32,
326 .offset = offsetof(DBGUState, chipid),
327 .defval = (uint32_t[]) { DEFAULT_CHIPID },
330 .name = "chipid-ext",
331 .info = &qdev_prop_uint32,
332 .offset = offsetof(DBGUState, chipid_ext)
334 {/* end of list */}
338 static void at91_dbgu_register(void)
340 sysbus_register_withprop(&at91_dbgu_info);
343 device_init(at91_dbgu_register)