Merge tag 'v9.0.0-rc3'
[qemu/ar7.git] / hw / usb / bcm2835_usb.c
blob32f096dca3bda1fe167e669f53e386c2222a4e77
1 /*
2 * Raspberry Pi emulation (c) 2012-2013 Gregory Estrade
3 * This code is licensed under the GNU GPLv2 and later.
4 */
6 /* This is wrong at so many levels, but well, I'm releasing it anyway */
8 #include "qemu/osdep.h"
9 #include "qemu/log.h"
10 #include "hw/irq.h" /* qemu_set_irq */
11 #include "hw/usb/bcm2835_usb.h"
12 #include "migration/vmstate.h" /* VMStateDescription */
13 #include "qapi/error.h"
14 #include "sysemu/dma.h"
16 #include "bcm2835_usb_regs.h"
18 /* You may have to change these parameters to get an almost-usable mouse
19 * support.
20 * The problem is that frame scheduling is all done by software, so a LOT of
21 * interrupts are generated, which doesn't help... */
22 #define SOF_INCR 1
23 #define SOF_DELAY 5000
25 static void bcm2835_usb_update_irq(BCM2835UsbState *s)
27 int n;
29 s->haint = 0;
30 for (n = 0; n < BCM2835_USB_HCHANS; n++) {
31 if (s->hchan[n].hcint & s->hchan[n].hcintmsk) {
32 s->haint |= (1 << n);
35 s->gintsts &= ~gintsts_hcintr;
36 if (s->haint & s->haintmsk) {
37 s->gintsts |= gintsts_hcintr;
40 if ((s->hprt0 & hprt0_prtconndet)
41 || (s->hprt0 & hprt0_prtenchng)) {
42 s->gintsts |= gintsts_portintr;
43 } else {
44 s->gintsts &= ~gintsts_portintr;
47 s->gintsts |= gintsts_nptxfempty | gintsts_ptxfempty;
49 if (!(s->gahbcfg & gahbcfg_glblintrmsk)) {
50 qemu_set_irq(s->irq, 0);
51 } else {
52 if (s->gintsts & s->gintmsk) {
53 qemu_set_irq(s->irq, 1);
54 } else {
55 qemu_set_irq(s->irq, 0);
61 static void bcm2835_usb_sof_tick(void *opaque)
63 BCM2835UsbState *s = (BCM2835UsbState *)opaque;
64 int64_t now;
66 uint32_t num = (s->hfnum & 0x3fff) + SOF_INCR;
67 s->hfnum = (num & 0x3fff) | (0x3210 << 16);
68 s->gintsts |= gintsts_sofintr;
70 bcm2835_usb_update_irq(s);
72 now = qemu_clock_get_us(QEMU_CLOCK_VIRTUAL);
73 timer_mod(s->sof_timer, now + SOF_DELAY);
76 static void channel_enable(BCM2835UsbHcState *c)
78 USBEndpoint *ep;
79 USBDevice *dev;
81 uint32_t epnum = (c->hcchar >> hcchar_epnum_shift) & hcchar_epnum_mask;
82 uint32_t devaddr = (c->hcchar >> hcchar_devaddr_shift)
83 & hcchar_devaddr_mask;
84 uint32_t xfersize = (c->hctsiz >> hctsiz_xfersize_shift)
85 & hctsiz_xfersize_mask;
86 uint32_t pid = (c->hctsiz >> hctsiz_pid_shift) & hctsiz_pid_mask;
87 uint32_t dma_addr = c->hcdma; /* ??? */
88 int actual_length;
89 int qpid;
91 if (!c->parent->reset_done) {
92 return;
95 if (c->hcchar & hcchar_epdir) {
96 /* IN */
97 qpid = USB_TOKEN_IN;
98 } else {
99 /* OUT/SETUP */
100 if (pid == DWC_HCTSIZ_SETUP) {
101 qpid = USB_TOKEN_SETUP;
102 } else {
103 qpid = USB_TOKEN_OUT;
107 dev = usb_find_device(&c->parent->port, devaddr);
108 assert(dev != NULL);
110 ep = usb_ep_get(dev, qpid, epnum);
111 usb_packet_setup(&c->packet, qpid, ep, 0, devaddr, 0, 0);
113 if (xfersize > 0) {
114 dma_memory_read(&c->parent->dma_as, dma_addr, c->buffer, xfersize);
116 usb_packet_addbuf(&c->packet, c->buffer, xfersize);
118 usb_handle_packet(dev, &c->packet);
120 if (c->packet.status == USB_RET_SUCCESS) {
121 if (qpid == USB_TOKEN_IN) {
122 actual_length = c->packet.actual_length;
124 xfersize -= actual_length;
125 c->hctsiz &= ~(hctsiz_xfersize_mask << hctsiz_xfersize_shift);
126 c->hctsiz |= xfersize << hctsiz_xfersize_shift;
128 dma_memory_write(&c->parent->dma_as, dma_addr, c->buffer,
129 actual_length);
132 c->hcint |= hcint_xfercomp | hcint_chhltd;
133 bcm2835_usb_update_irq(c->parent);
134 } else if (c->packet.status == USB_RET_NAK) {
135 c->hcint |= hcint_chhltd | hcint_nak;
136 bcm2835_usb_update_irq(c->parent);
137 } else {
138 /* assert(0); */
139 c->hcint |= hcint_chhltd | hcint_stall;
140 bcm2835_usb_update_irq(c->parent);
145 static uint32_t bcm2835_usb_hchan_read(BCM2835UsbState *s, int ch,
146 int offset)
148 BCM2835UsbHcState *c = &s->hchan[ch];
149 uint32_t res;
151 switch (offset) {
152 case 0x0:
153 res = c->hcchar;
154 break;
155 case 0x4:
156 res = c->hcsplt;
157 break;
158 case 0x8:
159 res = c->hcint;
160 break;
161 case 0xc:
162 res = c->hcintmsk;
163 break;
164 case 0x10:
165 res = c->hctsiz;
166 break;
167 case 0x14:
168 res = c->hcdma;
169 break;
170 case 0x1c:
171 res = c->hcdmab;
172 break;
173 default:
174 res = 0;
175 break;
177 return res;
179 static void bcm2835_usb_hchan_write(BCM2835UsbState *s, int ch,
180 int offset, uint32_t value, int *pset_irq)
182 BCM2835UsbHcState *c = &s->hchan[ch];
184 switch (offset) {
185 case 0x0:
186 c->hcchar = value;
187 if (value & hcchar_chdis) {
188 c->hcchar &= ~(hcchar_chdis | hcchar_chen);
189 /* TODO irq */
191 if (value & hcchar_chen) {
192 channel_enable(c);
194 break;
195 case 0x4:
196 c->hcsplt = value;
197 break;
198 case 0x8:
199 /* Looks like a standard interrupt register */
200 c->hcint &= ~value;
201 *pset_irq = 1;
202 break;
203 case 0xc:
204 c->hcintmsk = value;
205 break;
206 case 0x10:
207 c->hctsiz = value;
208 break;
209 case 0x14:
210 c->hcdma = value;
211 break;
212 case 0x1c:
213 c->hcdmab = value;
214 break;
215 default:
216 break;
220 static uint64_t bcm2835_usb_read(void *opaque, hwaddr offset,
221 unsigned size)
223 BCM2835UsbState *s = (BCM2835UsbState *)opaque;
224 uint32_t res = 0;
225 int i;
227 assert(size == 4);
229 switch (offset) {
230 case 0x0:
231 res = s->gotgctl;
232 break;
233 case 0x4:
234 res = s->gotgint;
235 break;
236 case 0x8:
237 res = s->gahbcfg;
238 break;
239 case 0xc:
240 res = s->gusbcfg;
241 break;
242 case 0x10:
243 res = s->grstctl;
244 break;
245 case 0x14:
246 res = s->gintsts;
247 /* Enforce Host mode */
248 res |= gintsts_curmode;
249 break;
250 case 0x18:
251 res = s->gintmsk;
252 break;
253 case 0x24:
254 res = s->grxfsiz;
255 break;
256 case 0x28:
257 res = s->gnptxfsiz;
258 break;
259 case 0x2c:
260 res = s->gnptxsts;
261 break;
262 case 0x3c:
263 res = s->guid;
264 break;
265 case 0x40:
266 res = 0x4f54280a;
267 break;
268 case 0x44:
269 res = 0;
270 break;
271 case 0x48:
272 res = 0x228ddd50;
273 break;
274 case 0x4c:
275 res = 0x0ff000e8;
276 break;
277 case 0x50:
278 res = 0x1ff00020;
279 break;
280 case 0x5c:
281 res = s->gdfifocfg;
282 break;
283 case 0x100:
284 res = s->hptxfsiz;
285 break;
286 case 0x400:
287 res = s->hcfg;
288 break;
289 case 0x408:
290 res = s->hfnum;
291 break;
292 case 0x410:
293 res = s->hptxsts;
294 break;
295 case 0x414:
296 res = s->haint;
297 break;
298 case 0x418:
299 res = s->haintmsk;
300 break;
301 case 0x440:
302 res = s->hprt0;
303 res &= ~hprt0_prtconnsts;
304 if (s->attached) {
305 res |= hprt0_prtconnsts;
307 break;
308 case 0x800:
309 res = s->dcfg;
310 break;
312 case 0xe00:
313 case 0x54:
314 case 0x58:
315 res = 0;
316 break;
318 default:
319 if ((offset >= 0x104) && (offset < 0x104 + (15 << 2))) {
320 res = s->dtxfsiz[(offset - 0x104) >> 2];
321 } else if ((offset >= 0x500) && (offset < 0x500 + 0x20*BCM2835_USB_HCHANS)) {
322 i = (offset - 0x500) >> 5;
323 res = bcm2835_usb_hchan_read(s, i, offset & 0x1f);
324 } else {
325 qemu_log_mask(LOG_GUEST_ERROR,
326 "bcm2835_usb_read: Bad offset %x\n", (int)offset);
327 res = 0;
329 break;
331 return res;
334 static void bcm2835_usb_write(void *opaque, hwaddr offset,
335 uint64_t value, unsigned size)
337 BCM2835UsbState *s = (BCM2835UsbState *)opaque;
339 int i;
340 int set_irq = 0;
342 assert(size == 4);
344 switch (offset) {
345 case 0x0:
346 s->gotgctl = value;
347 break;
348 case 0x4:
349 /* Looks like a standard interrupt register */
350 s->gotgint &= ~value;
351 break;
352 case 0x8:
353 s->gahbcfg = value;
354 set_irq = 1;
355 break;
356 case 0xc:
357 s->gusbcfg = value;
358 break;
359 case 0x10:
360 s->grstctl &= ~0x7c0;
361 s->grstctl |= value & 0x7c0;
362 break;
363 case 0x14:
364 s->gintsts &= ~value;
365 /* Enforce Host mode */
366 s->gintsts |= gintsts_curmode;
367 set_irq = 1;
368 break;
369 case 0x18:
370 s->gintmsk = value;
371 break;
372 case 0x24:
373 s->grxfsiz = value;
374 break;
375 case 0x28:
376 s->gnptxfsiz = value;
377 break;
378 case 0x3c:
379 s->guid = value;
380 break;
381 case 0x5c:
382 s->gdfifocfg = value;
383 break;
384 case 0x100:
385 s->hptxfsiz = value;
386 break;
387 case 0x400:
388 s->hcfg = value;
389 break;
390 case 0x408:
391 /* Probably RO */
392 break;
393 case 0x410:
394 /* Probably RO */
395 break;
396 case 0x414:
397 /* Probably RO */
398 break;
399 case 0x418:
400 s->haintmsk = value & ((1 << BCM2835_USB_HCHANS) - 1);
401 set_irq = 1;
402 break;
403 case 0x440:
404 if (!(s->hprt0 & hprt0_prtpwr) && (value & hprt0_prtpwr)) {
405 /* Trigger the port status change interrupt on power on */
406 if (s->attached) {
407 s->hprt0 |= hprt0_prtconndet;
408 set_irq = 1;
409 /* Reset the device (that's probably not the right place) */
410 usb_device_reset(s->port.dev);
411 s->reset_done = 1;
412 timer_mod(s->sof_timer, 0);
415 s->hprt0 &= ~hprt0_prtpwr;
416 s->hprt0 |= value & hprt0_prtpwr;
418 if ((s->hprt0 & hprt0_prtres) ^ (value & hprt0_prtres)) {
419 s->hprt0 |= hprt0_prtenchng;
420 set_irq = 1;
422 s->hprt0 &= ~(hprt0_prtena | hprt0_prtres);
423 if (value & hprt0_prtres) {
424 s->hprt0 |= hprt0_prtres;
425 } else {
426 s->hprt0 |= hprt0_prtena;
429 /* Interrupt clears */
430 if (value & hprt0_prtconndet) {
431 s->hprt0 &= ~hprt0_prtconndet;
432 set_irq = 1;
434 if (value & hprt0_prtenchng) {
435 s->hprt0 &= ~hprt0_prtenchng;
436 set_irq = 1;
439 break;
441 case 0xe00:
442 case 0x54:
443 case 0x58:
444 break;
446 default:
447 if ((offset >= 0x104) && (offset < 0x104 + (15 << 2))) {
448 s->dtxfsiz[(offset - 0x104) >> 2] = value;
449 } else if ((offset >= 0x500) && (offset < 0x500 + 0x20*BCM2835_USB_HCHANS)) {
450 i = (offset - 0x500) >> 5;
451 bcm2835_usb_hchan_write(s, i, offset & 0x1f, value, &set_irq);
452 } else {
453 qemu_log_mask(LOG_GUEST_ERROR,
454 "bcm2835_usb_write: Bad offset %x\n", (int)offset);
456 break;
459 if (set_irq) {
460 bcm2835_usb_update_irq(s);
464 static void bcm2835_usb_attach(USBPort *port1)
466 BCM2835UsbState *s = port1->opaque;
467 s->attached = 1;
469 static void bcm2835_usb_detach(USBPort *port1)
472 static void bcm2835_usb_child_detach(USBPort *port1, USBDevice *child)
475 static void bcm2835_usb_wakeup(USBPort *port1)
478 static void bcm2835_usb_async_complete(USBPort *port, USBPacket *packet)
483 static const MemoryRegionOps bcm2835_usb_ops = {
484 .read = bcm2835_usb_read,
485 .write = bcm2835_usb_write,
486 .endianness = DEVICE_NATIVE_ENDIAN,
489 static const VMStateDescription vmstate_bcm2835_usb = {
490 .name = TYPE_BCM2835_USB,
491 .version_id = 1,
492 .minimum_version_id = 1,
493 .minimum_version_id_old = 1,
494 .fields = (VMStateField[]) {
495 VMSTATE_END_OF_LIST()
499 static USBPortOps bcm2835_usb_port_ops = {
500 .attach = bcm2835_usb_attach,
501 .detach = bcm2835_usb_detach,
502 .child_detach = bcm2835_usb_child_detach,
503 .wakeup = bcm2835_usb_wakeup,
504 .complete = bcm2835_usb_async_complete,
507 static USBBusOps bcm2835_usb_bus_ops = {
510 static void bcm2835_usb_init(Object *obj)
512 BCM2835UsbState *s = BCM2835_USB(obj);
514 memory_region_init_io(&s->iomem, obj, &bcm2835_usb_ops, s,
515 TYPE_BCM2835_USB, 0x20000);
516 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
517 sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
520 static void bcm2835_usb_realize(DeviceState *dev, Error **errp)
522 int n;
523 BCM2835UsbState *s = BCM2835_USB(dev);
524 Error *err = NULL;
525 Object *obj;
527 obj = object_property_get_link(OBJECT(dev), "dma_mr", &err);
528 if (err || obj == NULL) {
529 error_setg(errp, "bcm2835_usb: required dma_mr property not found");
530 return;
533 s->dma_mr = MEMORY_REGION(obj);
534 address_space_init(&s->dma_as, s->dma_mr, NULL);
536 s->gusbcfg = 0x20402700;
537 s->hptxfsiz = 0x02002000;
538 s->hcfg = 0x00000001;
539 s->dcfg = 0x00000000;
540 s->grxfsiz = 0x00001000;
541 s->gnptxfsiz = 0x01001000;
542 for (n = 0; n < 15; n++) {
543 s->dtxfsiz[n] = 0x02002000;
545 s->gahbcfg = 0x0000000e;
546 s->grstctl = 0x80000000;
547 s->gotgctl = 0x001c0000;
548 s->gotgint = 0;
549 s->gintsts = 0;
550 s->gintmsk = 0;
551 s->gdfifocfg = 0x00000000;
552 s->hprt0 = DWC_HPRT0_PRTSPD_FULL_SPEED << hprt0_prtspd_shift;
553 s->gnptxsts = 0x080100;
554 s->hfnum = 0;
555 s->hptxsts = 0x080200;
556 s->guid = 0x2708A000;
558 for (n = 0; n < BCM2835_USB_HCHANS; n++) {
559 s->hchan[n].parent = s;
560 s->hchan[n].index = n;
562 s->hchan[n].hcchar = 0;
563 s->hchan[n].hcsplt = 0;
564 s->hchan[n].hcint = 0;
565 s->hchan[n].hcintmsk = 0;
566 s->hchan[n].hctsiz = 0;
567 s->hchan[n].hcdma = 0;
568 s->hchan[n].hcdmab = 0;
570 usb_packet_init(&s->hchan[n].packet);
573 s->attached = 0;
574 s->reset_done = 0;
576 s->sof_timer = timer_new_us(QEMU_CLOCK_VIRTUAL, bcm2835_usb_sof_tick, s);
578 usb_bus_new(&s->bus, sizeof(s->bus), &bcm2835_usb_bus_ops, DEVICE(s));
579 usb_register_port(&s->bus, &s->port, s, 0, &bcm2835_usb_port_ops,
580 USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
583 static void bcm2835_usb_class_init(ObjectClass *klass, void *data)
585 DeviceClass *dc = DEVICE_CLASS(klass);
587 dc->realize = bcm2835_usb_realize;
588 dc->vmsd = &vmstate_bcm2835_usb;
591 static TypeInfo bcm2835_usb_info = {
592 .name = TYPE_BCM2835_USB,
593 .parent = TYPE_SYS_BUS_DEVICE,
594 .instance_size = sizeof(BCM2835UsbState),
595 .class_init = bcm2835_usb_class_init,
596 .instance_init = bcm2835_usb_init,
599 static void bcm2835_usb_register_types(void)
601 type_register_static(&bcm2835_usb_info);
604 type_init(bcm2835_usb_register_types)