linux-user: Add an api to print enumareted argument values with strace
[qemu/ar7.git] / hw / usb / hcd-dwc2.c
blob56f91f6beeeb05dc9560e47eb7b74ef57ef40f2f
1 /*
2 * dwc-hsotg (dwc2) USB host controller emulation
4 * Based on hw/usb/hcd-ehci.c and hw/usb/hcd-ohci.c
6 * Note that to use this emulation with the dwc-otg driver in the
7 * Raspbian kernel, you must pass the option "dwc_otg.fiq_fsm_enable=0"
8 * on the kernel command line.
10 * Some useful documentation used to develop this emulation can be
11 * found online (as of April 2020) at:
13 * http://www.capital-micro.com/PDF/CME-M7_Family_User_Guide_EN.pdf
14 * which has a pretty complete description of the controller starting
15 * on page 370.
17 * https://sourceforge.net/p/wive-ng/wive-ng-mt/ci/master/tree/docs/DataSheets/RT3050_5x_V2.0_081408_0902.pdf
18 * which has a description of the controller registers starting on
19 * page 130.
21 * Copyright (c) 2020 Paul Zimmerman <pauldzim@gmail.com>
23 * This program is free software; you can redistribute it and/or modify
24 * it under the terms of the GNU General Public License as published by
25 * the Free Software Foundation; either version 2 of the License, or
26 * (at your option) any later version.
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
34 #include "qemu/osdep.h"
35 #include "qemu/units.h"
36 #include "qapi/error.h"
37 #include "hw/usb/dwc2-regs.h"
38 #include "hw/usb/hcd-dwc2.h"
39 #include "migration/vmstate.h"
40 #include "trace.h"
41 #include "qemu/log.h"
42 #include "qemu/error-report.h"
43 #include "qemu/main-loop.h"
44 #include "hw/qdev-properties.h"
46 #define USB_HZ_FS 12000000
47 #define USB_HZ_HS 96000000
48 #define USB_FRMINTVL 12000
50 /* nifty macros from Arnon's EHCI version */
51 #define get_field(data, field) \
52 (((data) & field##_MASK) >> field##_SHIFT)
54 #define set_field(data, newval, field) do { \
55 uint32_t val = *(data); \
56 val &= ~field##_MASK; \
57 val |= ((newval) << field##_SHIFT) & field##_MASK; \
58 *(data) = val; \
59 } while (0)
61 #define get_bit(data, bitmask) \
62 (!!((data) & (bitmask)))
64 /* update irq line */
65 static inline void dwc2_update_irq(DWC2State *s)
67 static int oldlevel;
68 int level = 0;
70 if ((s->gintsts & s->gintmsk) && (s->gahbcfg & GAHBCFG_GLBL_INTR_EN)) {
71 level = 1;
73 if (level != oldlevel) {
74 oldlevel = level;
75 trace_usb_dwc2_update_irq(level);
76 qemu_set_irq(s->irq, level);
80 /* flag interrupt condition */
81 static inline void dwc2_raise_global_irq(DWC2State *s, uint32_t intr)
83 if (!(s->gintsts & intr)) {
84 s->gintsts |= intr;
85 trace_usb_dwc2_raise_global_irq(intr);
86 dwc2_update_irq(s);
90 static inline void dwc2_lower_global_irq(DWC2State *s, uint32_t intr)
92 if (s->gintsts & intr) {
93 s->gintsts &= ~intr;
94 trace_usb_dwc2_lower_global_irq(intr);
95 dwc2_update_irq(s);
99 static inline void dwc2_raise_host_irq(DWC2State *s, uint32_t host_intr)
101 if (!(s->haint & host_intr)) {
102 s->haint |= host_intr;
103 s->haint &= 0xffff;
104 trace_usb_dwc2_raise_host_irq(host_intr);
105 if (s->haint & s->haintmsk) {
106 dwc2_raise_global_irq(s, GINTSTS_HCHINT);
111 static inline void dwc2_lower_host_irq(DWC2State *s, uint32_t host_intr)
113 if (s->haint & host_intr) {
114 s->haint &= ~host_intr;
115 trace_usb_dwc2_lower_host_irq(host_intr);
116 if (!(s->haint & s->haintmsk)) {
117 dwc2_lower_global_irq(s, GINTSTS_HCHINT);
122 static inline void dwc2_update_hc_irq(DWC2State *s, int index)
124 uint32_t host_intr = 1 << (index >> 3);
126 if (s->hreg1[index + 2] & s->hreg1[index + 3]) {
127 dwc2_raise_host_irq(s, host_intr);
128 } else {
129 dwc2_lower_host_irq(s, host_intr);
133 /* set a timer for EOF */
134 static void dwc2_eof_timer(DWC2State *s)
136 timer_mod(s->eof_timer, s->sof_time + s->usb_frame_time);
139 /* Set a timer for EOF and generate SOF event */
140 static void dwc2_sof(DWC2State *s)
142 s->sof_time += s->usb_frame_time;
143 trace_usb_dwc2_sof(s->sof_time);
144 dwc2_eof_timer(s);
145 dwc2_raise_global_irq(s, GINTSTS_SOF);
148 /* Do frame processing on frame boundary */
149 static void dwc2_frame_boundary(void *opaque)
151 DWC2State *s = opaque;
152 int64_t now;
153 uint16_t frcnt;
155 now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
157 /* Frame boundary, so do EOF stuff here */
159 /* Increment frame number */
160 frcnt = (uint16_t)((now - s->sof_time) / s->fi);
161 s->frame_number = (s->frame_number + frcnt) & 0xffff;
162 s->hfnum = s->frame_number & HFNUM_MAX_FRNUM;
164 /* Do SOF stuff here */
165 dwc2_sof(s);
168 /* Start sending SOF tokens on the USB bus */
169 static void dwc2_bus_start(DWC2State *s)
171 trace_usb_dwc2_bus_start();
172 s->sof_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
173 dwc2_eof_timer(s);
176 /* Stop sending SOF tokens on the USB bus */
177 static void dwc2_bus_stop(DWC2State *s)
179 trace_usb_dwc2_bus_stop();
180 timer_del(s->eof_timer);
183 static USBDevice *dwc2_find_device(DWC2State *s, uint8_t addr)
185 USBDevice *dev;
187 trace_usb_dwc2_find_device(addr);
189 if (!(s->hprt0 & HPRT0_ENA)) {
190 trace_usb_dwc2_port_disabled(0);
191 } else {
192 dev = usb_find_device(&s->uport, addr);
193 if (dev != NULL) {
194 trace_usb_dwc2_device_found(0);
195 return dev;
199 trace_usb_dwc2_device_not_found();
200 return NULL;
203 static const char *pstatus[] = {
204 "USB_RET_SUCCESS", "USB_RET_NODEV", "USB_RET_NAK", "USB_RET_STALL",
205 "USB_RET_BABBLE", "USB_RET_IOERROR", "USB_RET_ASYNC",
206 "USB_RET_ADD_TO_QUEUE", "USB_RET_REMOVE_FROM_QUEUE"
209 static uint32_t pintr[] = {
210 HCINTMSK_XFERCOMPL, HCINTMSK_XACTERR, HCINTMSK_NAK, HCINTMSK_STALL,
211 HCINTMSK_BBLERR, HCINTMSK_XACTERR, HCINTMSK_XACTERR, HCINTMSK_XACTERR,
212 HCINTMSK_XACTERR
215 static const char *types[] = {
216 "Ctrl", "Isoc", "Bulk", "Intr"
219 static const char *dirs[] = {
220 "Out", "In"
223 static void dwc2_handle_packet(DWC2State *s, uint32_t devadr, USBDevice *dev,
224 USBEndpoint *ep, uint32_t index, bool send)
226 DWC2Packet *p;
227 uint32_t hcchar = s->hreg1[index];
228 uint32_t hctsiz = s->hreg1[index + 4];
229 uint32_t hcdma = s->hreg1[index + 5];
230 uint32_t chan, epnum, epdir, eptype, mps, pid, pcnt, len, tlen, intr = 0;
231 uint32_t tpcnt, stsidx, actual = 0;
232 bool do_intr = false, done = false;
234 epnum = get_field(hcchar, HCCHAR_EPNUM);
235 epdir = get_bit(hcchar, HCCHAR_EPDIR);
236 eptype = get_field(hcchar, HCCHAR_EPTYPE);
237 mps = get_field(hcchar, HCCHAR_MPS);
238 pid = get_field(hctsiz, TSIZ_SC_MC_PID);
239 pcnt = get_field(hctsiz, TSIZ_PKTCNT);
240 len = get_field(hctsiz, TSIZ_XFERSIZE);
241 assert(len <= DWC2_MAX_XFER_SIZE);
242 chan = index >> 3;
243 p = &s->packet[chan];
245 trace_usb_dwc2_handle_packet(chan, dev, &p->packet, epnum, types[eptype],
246 dirs[epdir], mps, len, pcnt);
248 if (eptype == USB_ENDPOINT_XFER_CONTROL && pid == TSIZ_SC_MC_PID_SETUP) {
249 pid = USB_TOKEN_SETUP;
250 } else {
251 pid = epdir ? USB_TOKEN_IN : USB_TOKEN_OUT;
254 if (send) {
255 tlen = len;
256 if (p->small) {
257 if (tlen > mps) {
258 tlen = mps;
262 if (pid != USB_TOKEN_IN) {
263 trace_usb_dwc2_memory_read(hcdma, tlen);
264 if (dma_memory_read(&s->dma_as, hcdma,
265 s->usb_buf[chan], tlen) != MEMTX_OK) {
266 qemu_log_mask(LOG_GUEST_ERROR, "%s: dma_memory_read failed\n",
267 __func__);
271 usb_packet_init(&p->packet);
272 usb_packet_setup(&p->packet, pid, ep, 0, hcdma,
273 pid != USB_TOKEN_IN, true);
274 usb_packet_addbuf(&p->packet, s->usb_buf[chan], tlen);
275 p->async = DWC2_ASYNC_NONE;
276 usb_handle_packet(dev, &p->packet);
277 } else {
278 tlen = p->len;
281 stsidx = -p->packet.status;
282 assert(stsidx < sizeof(pstatus) / sizeof(*pstatus));
283 actual = p->packet.actual_length;
284 trace_usb_dwc2_packet_status(pstatus[stsidx], actual);
286 babble:
287 if (p->packet.status != USB_RET_SUCCESS &&
288 p->packet.status != USB_RET_NAK &&
289 p->packet.status != USB_RET_STALL &&
290 p->packet.status != USB_RET_ASYNC) {
291 trace_usb_dwc2_packet_error(pstatus[stsidx]);
294 if (p->packet.status == USB_RET_ASYNC) {
295 trace_usb_dwc2_async_packet(&p->packet, chan, dev, epnum,
296 dirs[epdir], tlen);
297 usb_device_flush_ep_queue(dev, ep);
298 assert(p->async != DWC2_ASYNC_INFLIGHT);
299 p->devadr = devadr;
300 p->epnum = epnum;
301 p->epdir = epdir;
302 p->mps = mps;
303 p->pid = pid;
304 p->index = index;
305 p->pcnt = pcnt;
306 p->len = tlen;
307 p->async = DWC2_ASYNC_INFLIGHT;
308 p->needs_service = false;
309 return;
312 if (p->packet.status == USB_RET_SUCCESS) {
313 if (actual > tlen) {
314 p->packet.status = USB_RET_BABBLE;
315 goto babble;
318 if (pid == USB_TOKEN_IN) {
319 trace_usb_dwc2_memory_write(hcdma, actual);
320 if (dma_memory_write(&s->dma_as, hcdma, s->usb_buf[chan],
321 actual) != MEMTX_OK) {
322 qemu_log_mask(LOG_GUEST_ERROR, "%s: dma_memory_write failed\n",
323 __func__);
327 tpcnt = actual / mps;
328 if (actual % mps) {
329 tpcnt++;
330 if (pid == USB_TOKEN_IN) {
331 done = true;
335 pcnt -= tpcnt < pcnt ? tpcnt : pcnt;
336 set_field(&hctsiz, pcnt, TSIZ_PKTCNT);
337 len -= actual < len ? actual : len;
338 set_field(&hctsiz, len, TSIZ_XFERSIZE);
339 s->hreg1[index + 4] = hctsiz;
340 hcdma += actual;
341 s->hreg1[index + 5] = hcdma;
343 if (!pcnt || len == 0 || actual == 0) {
344 done = true;
346 } else {
347 intr |= pintr[stsidx];
348 if (p->packet.status == USB_RET_NAK &&
349 (eptype == USB_ENDPOINT_XFER_CONTROL ||
350 eptype == USB_ENDPOINT_XFER_BULK)) {
352 * for ctrl/bulk, automatically retry on NAK,
353 * but send the interrupt anyway
355 intr &= ~HCINTMSK_RESERVED14_31;
356 s->hreg1[index + 2] |= intr;
357 do_intr = true;
358 } else {
359 intr |= HCINTMSK_CHHLTD;
360 done = true;
364 usb_packet_cleanup(&p->packet);
366 if (done) {
367 hcchar &= ~HCCHAR_CHENA;
368 s->hreg1[index] = hcchar;
369 if (!(intr & HCINTMSK_CHHLTD)) {
370 intr |= HCINTMSK_CHHLTD | HCINTMSK_XFERCOMPL;
372 intr &= ~HCINTMSK_RESERVED14_31;
373 s->hreg1[index + 2] |= intr;
374 p->needs_service = false;
375 trace_usb_dwc2_packet_done(pstatus[stsidx], actual, len, pcnt);
376 dwc2_update_hc_irq(s, index);
377 return;
380 p->devadr = devadr;
381 p->epnum = epnum;
382 p->epdir = epdir;
383 p->mps = mps;
384 p->pid = pid;
385 p->index = index;
386 p->pcnt = pcnt;
387 p->len = len;
388 p->needs_service = true;
389 trace_usb_dwc2_packet_next(pstatus[stsidx], len, pcnt);
390 if (do_intr) {
391 dwc2_update_hc_irq(s, index);
395 /* Attach or detach a device on root hub */
397 static const char *speeds[] = {
398 "low", "full", "high"
401 static void dwc2_attach(USBPort *port)
403 DWC2State *s = port->opaque;
404 int hispd = 0;
406 trace_usb_dwc2_attach(port);
407 assert(port->index == 0);
409 if (!port->dev || !port->dev->attached) {
410 return;
413 assert(port->dev->speed <= USB_SPEED_HIGH);
414 trace_usb_dwc2_attach_speed(speeds[port->dev->speed]);
415 s->hprt0 &= ~HPRT0_SPD_MASK;
417 switch (port->dev->speed) {
418 case USB_SPEED_LOW:
419 s->hprt0 |= HPRT0_SPD_LOW_SPEED << HPRT0_SPD_SHIFT;
420 break;
421 case USB_SPEED_FULL:
422 s->hprt0 |= HPRT0_SPD_FULL_SPEED << HPRT0_SPD_SHIFT;
423 break;
424 case USB_SPEED_HIGH:
425 s->hprt0 |= HPRT0_SPD_HIGH_SPEED << HPRT0_SPD_SHIFT;
426 hispd = 1;
427 break;
430 if (hispd) {
431 s->usb_frame_time = NANOSECONDS_PER_SECOND / 8000; /* 125000 */
432 if (NANOSECONDS_PER_SECOND >= USB_HZ_HS) {
433 s->usb_bit_time = NANOSECONDS_PER_SECOND / USB_HZ_HS; /* 10.4 */
434 } else {
435 s->usb_bit_time = 1;
437 } else {
438 s->usb_frame_time = NANOSECONDS_PER_SECOND / 1000; /* 1000000 */
439 if (NANOSECONDS_PER_SECOND >= USB_HZ_FS) {
440 s->usb_bit_time = NANOSECONDS_PER_SECOND / USB_HZ_FS; /* 83.3 */
441 } else {
442 s->usb_bit_time = 1;
446 s->fi = USB_FRMINTVL - 1;
447 s->hprt0 |= HPRT0_CONNDET | HPRT0_CONNSTS;
449 dwc2_bus_start(s);
450 dwc2_raise_global_irq(s, GINTSTS_PRTINT);
453 static void dwc2_detach(USBPort *port)
455 DWC2State *s = port->opaque;
457 trace_usb_dwc2_detach(port);
458 assert(port->index == 0);
460 dwc2_bus_stop(s);
462 s->hprt0 &= ~(HPRT0_SPD_MASK | HPRT0_SUSP | HPRT0_ENA | HPRT0_CONNSTS);
463 s->hprt0 |= HPRT0_CONNDET | HPRT0_ENACHG;
465 dwc2_raise_global_irq(s, GINTSTS_PRTINT);
468 static void dwc2_child_detach(USBPort *port, USBDevice *child)
470 trace_usb_dwc2_child_detach(port, child);
471 assert(port->index == 0);
474 static void dwc2_wakeup(USBPort *port)
476 DWC2State *s = port->opaque;
478 trace_usb_dwc2_wakeup(port);
479 assert(port->index == 0);
481 if (s->hprt0 & HPRT0_SUSP) {
482 s->hprt0 |= HPRT0_RES;
483 dwc2_raise_global_irq(s, GINTSTS_PRTINT);
486 qemu_bh_schedule(s->async_bh);
489 static void dwc2_async_packet_complete(USBPort *port, USBPacket *packet)
491 DWC2State *s = port->opaque;
492 DWC2Packet *p;
493 USBDevice *dev;
494 USBEndpoint *ep;
496 assert(port->index == 0);
497 p = container_of(packet, DWC2Packet, packet);
498 dev = dwc2_find_device(s, p->devadr);
499 ep = usb_ep_get(dev, p->pid, p->epnum);
500 trace_usb_dwc2_async_packet_complete(port, packet, p->index >> 3, dev,
501 p->epnum, dirs[p->epdir], p->len);
502 assert(p->async == DWC2_ASYNC_INFLIGHT);
504 if (packet->status == USB_RET_REMOVE_FROM_QUEUE) {
505 usb_cancel_packet(packet);
506 usb_packet_cleanup(packet);
507 return;
510 dwc2_handle_packet(s, p->devadr, dev, ep, p->index, false);
512 p->async = DWC2_ASYNC_FINISHED;
513 qemu_bh_schedule(s->async_bh);
516 static USBPortOps dwc2_port_ops = {
517 .attach = dwc2_attach,
518 .detach = dwc2_detach,
519 .child_detach = dwc2_child_detach,
520 .wakeup = dwc2_wakeup,
521 .complete = dwc2_async_packet_complete,
524 static uint32_t dwc2_get_frame_remaining(DWC2State *s)
526 uint32_t fr = 0;
527 int64_t tks;
529 tks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->sof_time;
530 if (tks < 0) {
531 tks = 0;
534 /* avoid muldiv if possible */
535 if (tks >= s->usb_frame_time) {
536 goto out;
538 if (tks < s->usb_bit_time) {
539 fr = s->fi;
540 goto out;
543 /* tks = number of ns since SOF, divided by 83 (fs) or 10 (hs) */
544 tks = tks / s->usb_bit_time;
545 if (tks >= (int64_t)s->fi) {
546 goto out;
549 /* remaining = frame interval minus tks */
550 fr = (uint32_t)((int64_t)s->fi - tks);
552 out:
553 return fr;
556 static void dwc2_work_bh(void *opaque)
558 DWC2State *s = opaque;
559 DWC2Packet *p;
560 USBDevice *dev;
561 USBEndpoint *ep;
562 int64_t t_now, expire_time;
563 int chan;
564 bool found = false;
566 trace_usb_dwc2_work_bh();
567 if (s->working) {
568 return;
570 s->working = true;
572 t_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
573 chan = s->next_chan;
575 do {
576 p = &s->packet[chan];
577 if (p->needs_service) {
578 dev = dwc2_find_device(s, p->devadr);
579 ep = usb_ep_get(dev, p->pid, p->epnum);
580 trace_usb_dwc2_work_bh_service(s->next_chan, chan, dev, p->epnum);
581 dwc2_handle_packet(s, p->devadr, dev, ep, p->index, true);
582 found = true;
584 if (++chan == DWC2_NB_CHAN) {
585 chan = 0;
587 if (found) {
588 s->next_chan = chan;
589 trace_usb_dwc2_work_bh_next(chan);
591 } while (chan != s->next_chan);
593 if (found) {
594 expire_time = t_now + NANOSECONDS_PER_SECOND / 4000;
595 timer_mod(s->frame_timer, expire_time);
597 s->working = false;
600 static void dwc2_enable_chan(DWC2State *s, uint32_t index)
602 USBDevice *dev;
603 USBEndpoint *ep;
604 uint32_t hcchar;
605 uint32_t hctsiz;
606 uint32_t devadr, epnum, epdir, eptype, pid, len;
607 DWC2Packet *p;
609 assert((index >> 3) < DWC2_NB_CHAN);
610 p = &s->packet[index >> 3];
611 hcchar = s->hreg1[index];
612 hctsiz = s->hreg1[index + 4];
613 devadr = get_field(hcchar, HCCHAR_DEVADDR);
614 epnum = get_field(hcchar, HCCHAR_EPNUM);
615 epdir = get_bit(hcchar, HCCHAR_EPDIR);
616 eptype = get_field(hcchar, HCCHAR_EPTYPE);
617 pid = get_field(hctsiz, TSIZ_SC_MC_PID);
618 len = get_field(hctsiz, TSIZ_XFERSIZE);
620 dev = dwc2_find_device(s, devadr);
622 trace_usb_dwc2_enable_chan(index >> 3, dev, &p->packet, epnum);
623 if (dev == NULL) {
624 return;
627 if (eptype == USB_ENDPOINT_XFER_CONTROL && pid == TSIZ_SC_MC_PID_SETUP) {
628 pid = USB_TOKEN_SETUP;
629 } else {
630 pid = epdir ? USB_TOKEN_IN : USB_TOKEN_OUT;
633 ep = usb_ep_get(dev, pid, epnum);
636 * Hack: Networking doesn't like us delivering large transfers, it kind
637 * of works but the latency is horrible. So if the transfer is <= the mtu
638 * size, we take that as a hint that this might be a network transfer,
639 * and do the transfer packet-by-packet.
641 if (len > 1536) {
642 p->small = false;
643 } else {
644 p->small = true;
647 dwc2_handle_packet(s, devadr, dev, ep, index, true);
648 qemu_bh_schedule(s->async_bh);
651 static const char *glbregnm[] = {
652 "GOTGCTL ", "GOTGINT ", "GAHBCFG ", "GUSBCFG ", "GRSTCTL ",
653 "GINTSTS ", "GINTMSK ", "GRXSTSR ", "GRXSTSP ", "GRXFSIZ ",
654 "GNPTXFSIZ", "GNPTXSTS ", "GI2CCTL ", "GPVNDCTL ", "GGPIO ",
655 "GUID ", "GSNPSID ", "GHWCFG1 ", "GHWCFG2 ", "GHWCFG3 ",
656 "GHWCFG4 ", "GLPMCFG ", "GPWRDN ", "GDFIFOCFG", "GADPCTL ",
657 "GREFCLK ", "GINTMSK2 ", "GINTSTS2 "
660 static uint64_t dwc2_glbreg_read(void *ptr, hwaddr addr, int index,
661 unsigned size)
663 DWC2State *s = ptr;
664 uint32_t val;
666 assert(addr <= GINTSTS2);
667 val = s->glbreg[index];
669 switch (addr) {
670 case GRSTCTL:
671 /* clear any self-clearing bits that were set */
672 val &= ~(GRSTCTL_TXFFLSH | GRSTCTL_RXFFLSH | GRSTCTL_IN_TKNQ_FLSH |
673 GRSTCTL_FRMCNTRRST | GRSTCTL_HSFTRST | GRSTCTL_CSFTRST);
674 s->glbreg[index] = val;
675 break;
676 default:
677 break;
680 trace_usb_dwc2_glbreg_read(addr, glbregnm[index], val);
681 return val;
684 static void dwc2_glbreg_write(void *ptr, hwaddr addr, int index, uint64_t val,
685 unsigned size)
687 DWC2State *s = ptr;
688 uint64_t orig = val;
689 uint32_t *mmio;
690 uint32_t old;
691 int iflg = 0;
693 assert(addr <= GINTSTS2);
694 mmio = &s->glbreg[index];
695 old = *mmio;
697 switch (addr) {
698 case GOTGCTL:
699 /* don't allow setting of read-only bits */
700 val &= ~(GOTGCTL_MULT_VALID_BC_MASK | GOTGCTL_BSESVLD |
701 GOTGCTL_ASESVLD | GOTGCTL_DBNC_SHORT | GOTGCTL_CONID_B |
702 GOTGCTL_HSTNEGSCS | GOTGCTL_SESREQSCS);
703 /* don't allow clearing of read-only bits */
704 val |= old & (GOTGCTL_MULT_VALID_BC_MASK | GOTGCTL_BSESVLD |
705 GOTGCTL_ASESVLD | GOTGCTL_DBNC_SHORT | GOTGCTL_CONID_B |
706 GOTGCTL_HSTNEGSCS | GOTGCTL_SESREQSCS);
707 break;
708 case GAHBCFG:
709 if ((val & GAHBCFG_GLBL_INTR_EN) && !(old & GAHBCFG_GLBL_INTR_EN)) {
710 iflg = 1;
712 break;
713 case GRSTCTL:
714 val |= GRSTCTL_AHBIDLE;
715 val &= ~GRSTCTL_DMAREQ;
716 if (!(old & GRSTCTL_TXFFLSH) && (val & GRSTCTL_TXFFLSH)) {
717 /* TODO - TX fifo flush */
718 qemu_log_mask(LOG_UNIMP, "Tx FIFO flush not implemented\n");
720 if (!(old & GRSTCTL_RXFFLSH) && (val & GRSTCTL_RXFFLSH)) {
721 /* TODO - RX fifo flush */
722 qemu_log_mask(LOG_UNIMP, "Rx FIFO flush not implemented\n");
724 if (!(old & GRSTCTL_IN_TKNQ_FLSH) && (val & GRSTCTL_IN_TKNQ_FLSH)) {
725 /* TODO - device IN token queue flush */
726 qemu_log_mask(LOG_UNIMP, "Token queue flush not implemented\n");
728 if (!(old & GRSTCTL_FRMCNTRRST) && (val & GRSTCTL_FRMCNTRRST)) {
729 /* TODO - host frame counter reset */
730 qemu_log_mask(LOG_UNIMP, "Frame counter reset not implemented\n");
732 if (!(old & GRSTCTL_HSFTRST) && (val & GRSTCTL_HSFTRST)) {
733 /* TODO - host soft reset */
734 qemu_log_mask(LOG_UNIMP, "Host soft reset not implemented\n");
736 if (!(old & GRSTCTL_CSFTRST) && (val & GRSTCTL_CSFTRST)) {
737 /* TODO - core soft reset */
738 qemu_log_mask(LOG_UNIMP, "Core soft reset not implemented\n");
740 /* don't allow clearing of self-clearing bits */
741 val |= old & (GRSTCTL_TXFFLSH | GRSTCTL_RXFFLSH |
742 GRSTCTL_IN_TKNQ_FLSH | GRSTCTL_FRMCNTRRST |
743 GRSTCTL_HSFTRST | GRSTCTL_CSFTRST);
744 break;
745 case GINTSTS:
746 /* clear the write-1-to-clear bits */
747 val |= ~old;
748 val = ~val;
749 /* don't allow clearing of read-only bits */
750 val |= old & (GINTSTS_PTXFEMP | GINTSTS_HCHINT | GINTSTS_PRTINT |
751 GINTSTS_OEPINT | GINTSTS_IEPINT | GINTSTS_GOUTNAKEFF |
752 GINTSTS_GINNAKEFF | GINTSTS_NPTXFEMP | GINTSTS_RXFLVL |
753 GINTSTS_OTGINT | GINTSTS_CURMODE_HOST);
754 iflg = 1;
755 break;
756 case GINTMSK:
757 iflg = 1;
758 break;
759 default:
760 break;
763 trace_usb_dwc2_glbreg_write(addr, glbregnm[index], orig, old, val);
764 *mmio = val;
766 if (iflg) {
767 dwc2_update_irq(s);
771 static uint64_t dwc2_fszreg_read(void *ptr, hwaddr addr, int index,
772 unsigned size)
774 DWC2State *s = ptr;
775 uint32_t val;
777 assert(addr == HPTXFSIZ);
778 val = s->fszreg[index];
780 trace_usb_dwc2_fszreg_read(addr, val);
781 return val;
784 static void dwc2_fszreg_write(void *ptr, hwaddr addr, int index, uint64_t val,
785 unsigned size)
787 DWC2State *s = ptr;
788 uint64_t orig = val;
789 uint32_t *mmio;
790 uint32_t old;
792 assert(addr == HPTXFSIZ);
793 mmio = &s->fszreg[index];
794 old = *mmio;
796 trace_usb_dwc2_fszreg_write(addr, orig, old, val);
797 *mmio = val;
800 static const char *hreg0nm[] = {
801 "HCFG ", "HFIR ", "HFNUM ", "<rsvd> ", "HPTXSTS ",
802 "HAINT ", "HAINTMSK ", "HFLBADDR ", "<rsvd> ", "<rsvd> ",
803 "<rsvd> ", "<rsvd> ", "<rsvd> ", "<rsvd> ", "<rsvd> ",
804 "<rsvd> ", "HPRT0 "
807 static uint64_t dwc2_hreg0_read(void *ptr, hwaddr addr, int index,
808 unsigned size)
810 DWC2State *s = ptr;
811 uint32_t val;
813 assert(addr >= HCFG && addr <= HPRT0);
814 val = s->hreg0[index];
816 switch (addr) {
817 case HFNUM:
818 val = (dwc2_get_frame_remaining(s) << HFNUM_FRREM_SHIFT) |
819 (s->hfnum << HFNUM_FRNUM_SHIFT);
820 break;
821 default:
822 break;
825 trace_usb_dwc2_hreg0_read(addr, hreg0nm[index], val);
826 return val;
829 static void dwc2_hreg0_write(void *ptr, hwaddr addr, int index, uint64_t val,
830 unsigned size)
832 DWC2State *s = ptr;
833 USBDevice *dev = s->uport.dev;
834 uint64_t orig = val;
835 uint32_t *mmio;
836 uint32_t tval, told, old;
837 int prst = 0;
838 int iflg = 0;
840 assert(addr >= HCFG && addr <= HPRT0);
841 mmio = &s->hreg0[index];
842 old = *mmio;
844 switch (addr) {
845 case HFIR:
846 break;
847 case HFNUM:
848 case HPTXSTS:
849 case HAINT:
850 qemu_log_mask(LOG_GUEST_ERROR, "%s: write to read-only register\n",
851 __func__);
852 return;
853 case HAINTMSK:
854 val &= 0xffff;
855 break;
856 case HPRT0:
857 /* don't allow clearing of read-only bits */
858 val |= old & (HPRT0_SPD_MASK | HPRT0_LNSTS_MASK | HPRT0_OVRCURRACT |
859 HPRT0_CONNSTS);
860 /* don't allow clearing of self-clearing bits */
861 val |= old & (HPRT0_SUSP | HPRT0_RES);
862 /* don't allow setting of self-setting bits */
863 if (!(old & HPRT0_ENA) && (val & HPRT0_ENA)) {
864 val &= ~HPRT0_ENA;
866 /* clear the write-1-to-clear bits */
867 tval = val & (HPRT0_OVRCURRCHG | HPRT0_ENACHG | HPRT0_ENA |
868 HPRT0_CONNDET);
869 told = old & (HPRT0_OVRCURRCHG | HPRT0_ENACHG | HPRT0_ENA |
870 HPRT0_CONNDET);
871 tval |= ~told;
872 tval = ~tval;
873 tval &= (HPRT0_OVRCURRCHG | HPRT0_ENACHG | HPRT0_ENA |
874 HPRT0_CONNDET);
875 val &= ~(HPRT0_OVRCURRCHG | HPRT0_ENACHG | HPRT0_ENA |
876 HPRT0_CONNDET);
877 val |= tval;
878 if (!(val & HPRT0_RST) && (old & HPRT0_RST)) {
879 if (dev && dev->attached) {
880 val |= HPRT0_ENA | HPRT0_ENACHG;
881 prst = 1;
884 if (val & (HPRT0_OVRCURRCHG | HPRT0_ENACHG | HPRT0_CONNDET)) {
885 iflg = 1;
886 } else {
887 iflg = -1;
889 break;
890 default:
891 break;
894 if (prst) {
895 trace_usb_dwc2_hreg0_write(addr, hreg0nm[index], orig, old,
896 val & ~HPRT0_CONNDET);
897 trace_usb_dwc2_hreg0_action("call usb_port_reset");
898 usb_port_reset(&s->uport);
899 val &= ~HPRT0_CONNDET;
900 } else {
901 trace_usb_dwc2_hreg0_write(addr, hreg0nm[index], orig, old, val);
904 *mmio = val;
906 if (iflg > 0) {
907 trace_usb_dwc2_hreg0_action("enable PRTINT");
908 dwc2_raise_global_irq(s, GINTSTS_PRTINT);
909 } else if (iflg < 0) {
910 trace_usb_dwc2_hreg0_action("disable PRTINT");
911 dwc2_lower_global_irq(s, GINTSTS_PRTINT);
915 static const char *hreg1nm[] = {
916 "HCCHAR ", "HCSPLT ", "HCINT ", "HCINTMSK", "HCTSIZ ", "HCDMA ",
917 "<rsvd> ", "HCDMAB "
920 static uint64_t dwc2_hreg1_read(void *ptr, hwaddr addr, int index,
921 unsigned size)
923 DWC2State *s = ptr;
924 uint32_t val;
926 assert(addr >= HCCHAR(0) && addr <= HCDMAB(DWC2_NB_CHAN - 1));
927 val = s->hreg1[index];
929 trace_usb_dwc2_hreg1_read(addr, hreg1nm[index & 7], addr >> 5, val);
930 return val;
933 static void dwc2_hreg1_write(void *ptr, hwaddr addr, int index, uint64_t val,
934 unsigned size)
936 DWC2State *s = ptr;
937 uint64_t orig = val;
938 uint32_t *mmio;
939 uint32_t old;
940 int iflg = 0;
941 int enflg = 0;
942 int disflg = 0;
944 assert(addr >= HCCHAR(0) && addr <= HCDMAB(DWC2_NB_CHAN - 1));
945 mmio = &s->hreg1[index];
946 old = *mmio;
948 switch (HSOTG_REG(0x500) + (addr & 0x1c)) {
949 case HCCHAR(0):
950 if ((val & HCCHAR_CHDIS) && !(old & HCCHAR_CHDIS)) {
951 val &= ~(HCCHAR_CHENA | HCCHAR_CHDIS);
952 disflg = 1;
953 } else {
954 val |= old & HCCHAR_CHDIS;
955 if ((val & HCCHAR_CHENA) && !(old & HCCHAR_CHENA)) {
956 val &= ~HCCHAR_CHDIS;
957 enflg = 1;
958 } else {
959 val |= old & HCCHAR_CHENA;
962 break;
963 case HCINT(0):
964 /* clear the write-1-to-clear bits */
965 val |= ~old;
966 val = ~val;
967 val &= ~HCINTMSK_RESERVED14_31;
968 iflg = 1;
969 break;
970 case HCINTMSK(0):
971 val &= ~HCINTMSK_RESERVED14_31;
972 iflg = 1;
973 break;
974 case HCDMAB(0):
975 qemu_log_mask(LOG_GUEST_ERROR, "%s: write to read-only register\n",
976 __func__);
977 return;
978 default:
979 break;
982 trace_usb_dwc2_hreg1_write(addr, hreg1nm[index & 7], index >> 3, orig,
983 old, val);
984 *mmio = val;
986 if (disflg) {
987 /* set ChHltd in HCINT */
988 s->hreg1[(index & ~7) + 2] |= HCINTMSK_CHHLTD;
989 iflg = 1;
992 if (enflg) {
993 dwc2_enable_chan(s, index & ~7);
996 if (iflg) {
997 dwc2_update_hc_irq(s, index & ~7);
1001 static const char *pcgregnm[] = {
1002 "PCGCTL ", "PCGCCTL1 "
1005 static uint64_t dwc2_pcgreg_read(void *ptr, hwaddr addr, int index,
1006 unsigned size)
1008 DWC2State *s = ptr;
1009 uint32_t val;
1011 assert(addr >= PCGCTL && addr <= PCGCCTL1);
1012 val = s->pcgreg[index];
1014 trace_usb_dwc2_pcgreg_read(addr, pcgregnm[index], val);
1015 return val;
1018 static void dwc2_pcgreg_write(void *ptr, hwaddr addr, int index,
1019 uint64_t val, unsigned size)
1021 DWC2State *s = ptr;
1022 uint64_t orig = val;
1023 uint32_t *mmio;
1024 uint32_t old;
1026 assert(addr >= PCGCTL && addr <= PCGCCTL1);
1027 mmio = &s->pcgreg[index];
1028 old = *mmio;
1030 trace_usb_dwc2_pcgreg_write(addr, pcgregnm[index], orig, old, val);
1031 *mmio = val;
1034 static uint64_t dwc2_hsotg_read(void *ptr, hwaddr addr, unsigned size)
1036 uint64_t val;
1038 switch (addr) {
1039 case HSOTG_REG(0x000) ... HSOTG_REG(0x0fc):
1040 val = dwc2_glbreg_read(ptr, addr, (addr - HSOTG_REG(0x000)) >> 2, size);
1041 break;
1042 case HSOTG_REG(0x100):
1043 val = dwc2_fszreg_read(ptr, addr, (addr - HSOTG_REG(0x100)) >> 2, size);
1044 break;
1045 case HSOTG_REG(0x104) ... HSOTG_REG(0x3fc):
1046 /* Gadget-mode registers, just return 0 for now */
1047 val = 0;
1048 break;
1049 case HSOTG_REG(0x400) ... HSOTG_REG(0x4fc):
1050 val = dwc2_hreg0_read(ptr, addr, (addr - HSOTG_REG(0x400)) >> 2, size);
1051 break;
1052 case HSOTG_REG(0x500) ... HSOTG_REG(0x7fc):
1053 val = dwc2_hreg1_read(ptr, addr, (addr - HSOTG_REG(0x500)) >> 2, size);
1054 break;
1055 case HSOTG_REG(0x800) ... HSOTG_REG(0xdfc):
1056 /* Gadget-mode registers, just return 0 for now */
1057 val = 0;
1058 break;
1059 case HSOTG_REG(0xe00) ... HSOTG_REG(0xffc):
1060 val = dwc2_pcgreg_read(ptr, addr, (addr - HSOTG_REG(0xe00)) >> 2, size);
1061 break;
1062 default:
1063 g_assert_not_reached();
1066 return val;
1069 static void dwc2_hsotg_write(void *ptr, hwaddr addr, uint64_t val,
1070 unsigned size)
1072 switch (addr) {
1073 case HSOTG_REG(0x000) ... HSOTG_REG(0x0fc):
1074 dwc2_glbreg_write(ptr, addr, (addr - HSOTG_REG(0x000)) >> 2, val, size);
1075 break;
1076 case HSOTG_REG(0x100):
1077 dwc2_fszreg_write(ptr, addr, (addr - HSOTG_REG(0x100)) >> 2, val, size);
1078 break;
1079 case HSOTG_REG(0x104) ... HSOTG_REG(0x3fc):
1080 /* Gadget-mode registers, do nothing for now */
1081 break;
1082 case HSOTG_REG(0x400) ... HSOTG_REG(0x4fc):
1083 dwc2_hreg0_write(ptr, addr, (addr - HSOTG_REG(0x400)) >> 2, val, size);
1084 break;
1085 case HSOTG_REG(0x500) ... HSOTG_REG(0x7fc):
1086 dwc2_hreg1_write(ptr, addr, (addr - HSOTG_REG(0x500)) >> 2, val, size);
1087 break;
1088 case HSOTG_REG(0x800) ... HSOTG_REG(0xdfc):
1089 /* Gadget-mode registers, do nothing for now */
1090 break;
1091 case HSOTG_REG(0xe00) ... HSOTG_REG(0xffc):
1092 dwc2_pcgreg_write(ptr, addr, (addr - HSOTG_REG(0xe00)) >> 2, val, size);
1093 break;
1094 default:
1095 g_assert_not_reached();
1099 static const MemoryRegionOps dwc2_mmio_hsotg_ops = {
1100 .read = dwc2_hsotg_read,
1101 .write = dwc2_hsotg_write,
1102 .impl.min_access_size = 4,
1103 .impl.max_access_size = 4,
1104 .endianness = DEVICE_LITTLE_ENDIAN,
1107 static uint64_t dwc2_hreg2_read(void *ptr, hwaddr addr, unsigned size)
1109 /* TODO - implement FIFOs to support slave mode */
1110 trace_usb_dwc2_hreg2_read(addr, addr >> 12, 0);
1111 qemu_log_mask(LOG_UNIMP, "FIFO read not implemented\n");
1112 return 0;
1115 static void dwc2_hreg2_write(void *ptr, hwaddr addr, uint64_t val,
1116 unsigned size)
1118 uint64_t orig = val;
1120 /* TODO - implement FIFOs to support slave mode */
1121 trace_usb_dwc2_hreg2_write(addr, addr >> 12, orig, 0, val);
1122 qemu_log_mask(LOG_UNIMP, "FIFO write not implemented\n");
1125 static const MemoryRegionOps dwc2_mmio_hreg2_ops = {
1126 .read = dwc2_hreg2_read,
1127 .write = dwc2_hreg2_write,
1128 .impl.min_access_size = 4,
1129 .impl.max_access_size = 4,
1130 .endianness = DEVICE_LITTLE_ENDIAN,
1133 static void dwc2_wakeup_endpoint(USBBus *bus, USBEndpoint *ep,
1134 unsigned int stream)
1136 DWC2State *s = container_of(bus, DWC2State, bus);
1138 trace_usb_dwc2_wakeup_endpoint(ep, stream);
1140 /* TODO - do something here? */
1141 qemu_bh_schedule(s->async_bh);
1144 static USBBusOps dwc2_bus_ops = {
1145 .wakeup_endpoint = dwc2_wakeup_endpoint,
1148 static void dwc2_work_timer(void *opaque)
1150 DWC2State *s = opaque;
1152 trace_usb_dwc2_work_timer();
1153 qemu_bh_schedule(s->async_bh);
1156 static void dwc2_reset_enter(Object *obj, ResetType type)
1158 DWC2Class *c = DWC2_GET_CLASS(obj);
1159 DWC2State *s = DWC2_USB(obj);
1160 int i;
1162 trace_usb_dwc2_reset_enter();
1164 if (c->parent_phases.enter) {
1165 c->parent_phases.enter(obj, type);
1168 timer_del(s->frame_timer);
1169 qemu_bh_cancel(s->async_bh);
1171 if (s->uport.dev && s->uport.dev->attached) {
1172 usb_detach(&s->uport);
1175 dwc2_bus_stop(s);
1177 s->gotgctl = GOTGCTL_BSESVLD | GOTGCTL_ASESVLD | GOTGCTL_CONID_B;
1178 s->gotgint = 0;
1179 s->gahbcfg = 0;
1180 s->gusbcfg = 5 << GUSBCFG_USBTRDTIM_SHIFT;
1181 s->grstctl = GRSTCTL_AHBIDLE;
1182 s->gintsts = GINTSTS_CONIDSTSCHNG | GINTSTS_PTXFEMP | GINTSTS_NPTXFEMP |
1183 GINTSTS_CURMODE_HOST;
1184 s->gintmsk = 0;
1185 s->grxstsr = 0;
1186 s->grxstsp = 0;
1187 s->grxfsiz = 1024;
1188 s->gnptxfsiz = 1024 << FIFOSIZE_DEPTH_SHIFT;
1189 s->gnptxsts = (4 << FIFOSIZE_DEPTH_SHIFT) | 1024;
1190 s->gi2cctl = GI2CCTL_I2CDATSE0 | GI2CCTL_ACK;
1191 s->gpvndctl = 0;
1192 s->ggpio = 0;
1193 s->guid = 0;
1194 s->gsnpsid = 0x4f54294a;
1195 s->ghwcfg1 = 0;
1196 s->ghwcfg2 = (8 << GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT) |
1197 (4 << GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT) |
1198 (4 << GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT) |
1199 GHWCFG2_DYNAMIC_FIFO |
1200 GHWCFG2_PERIO_EP_SUPPORTED |
1201 ((DWC2_NB_CHAN - 1) << GHWCFG2_NUM_HOST_CHAN_SHIFT) |
1202 (GHWCFG2_INT_DMA_ARCH << GHWCFG2_ARCHITECTURE_SHIFT) |
1203 (GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST << GHWCFG2_OP_MODE_SHIFT);
1204 s->ghwcfg3 = (4096 << GHWCFG3_DFIFO_DEPTH_SHIFT) |
1205 (4 << GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT) |
1206 (4 << GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT);
1207 s->ghwcfg4 = 0;
1208 s->glpmcfg = 0;
1209 s->gpwrdn = GPWRDN_PWRDNRSTN;
1210 s->gdfifocfg = 0;
1211 s->gadpctl = 0;
1212 s->grefclk = 0;
1213 s->gintmsk2 = 0;
1214 s->gintsts2 = 0;
1216 s->hptxfsiz = 500 << FIFOSIZE_DEPTH_SHIFT;
1218 s->hcfg = 2 << HCFG_RESVALID_SHIFT;
1219 s->hfir = 60000;
1220 s->hfnum = 0x3fff;
1221 s->hptxsts = (16 << TXSTS_QSPCAVAIL_SHIFT) | 32768;
1222 s->haint = 0;
1223 s->haintmsk = 0;
1224 s->hprt0 = 0;
1226 memset(s->hreg1, 0, sizeof(s->hreg1));
1227 memset(s->pcgreg, 0, sizeof(s->pcgreg));
1229 s->sof_time = 0;
1230 s->frame_number = 0;
1231 s->fi = USB_FRMINTVL - 1;
1232 s->next_chan = 0;
1233 s->working = false;
1235 for (i = 0; i < DWC2_NB_CHAN; i++) {
1236 s->packet[i].needs_service = false;
1240 static void dwc2_reset_hold(Object *obj)
1242 DWC2Class *c = DWC2_GET_CLASS(obj);
1243 DWC2State *s = DWC2_USB(obj);
1245 trace_usb_dwc2_reset_hold();
1247 if (c->parent_phases.hold) {
1248 c->parent_phases.hold(obj);
1251 dwc2_update_irq(s);
1254 static void dwc2_reset_exit(Object *obj)
1256 DWC2Class *c = DWC2_GET_CLASS(obj);
1257 DWC2State *s = DWC2_USB(obj);
1259 trace_usb_dwc2_reset_exit();
1261 if (c->parent_phases.exit) {
1262 c->parent_phases.exit(obj);
1265 s->hprt0 = HPRT0_PWR;
1266 if (s->uport.dev && s->uport.dev->attached) {
1267 usb_attach(&s->uport);
1268 usb_device_reset(s->uport.dev);
1272 static void dwc2_realize(DeviceState *dev, Error **errp)
1274 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
1275 DWC2State *s = DWC2_USB(dev);
1276 Object *obj;
1278 obj = object_property_get_link(OBJECT(dev), "dma-mr", &error_abort);
1280 s->dma_mr = MEMORY_REGION(obj);
1281 address_space_init(&s->dma_as, s->dma_mr, "dwc2");
1283 usb_bus_new(&s->bus, sizeof(s->bus), &dwc2_bus_ops, dev);
1284 usb_register_port(&s->bus, &s->uport, s, 0, &dwc2_port_ops,
1285 USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL |
1286 (s->usb_version == 2 ? USB_SPEED_MASK_HIGH : 0));
1287 s->uport.dev = 0;
1289 s->usb_frame_time = NANOSECONDS_PER_SECOND / 1000; /* 1000000 */
1290 if (NANOSECONDS_PER_SECOND >= USB_HZ_FS) {
1291 s->usb_bit_time = NANOSECONDS_PER_SECOND / USB_HZ_FS; /* 83.3 */
1292 } else {
1293 s->usb_bit_time = 1;
1296 s->fi = USB_FRMINTVL - 1;
1297 s->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, dwc2_frame_boundary, s);
1298 s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, dwc2_work_timer, s);
1299 s->async_bh = qemu_bh_new(dwc2_work_bh, s);
1301 sysbus_init_irq(sbd, &s->irq);
1304 static void dwc2_init(Object *obj)
1306 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1307 DWC2State *s = DWC2_USB(obj);
1309 memory_region_init(&s->container, obj, "dwc2", DWC2_MMIO_SIZE);
1310 sysbus_init_mmio(sbd, &s->container);
1312 memory_region_init_io(&s->hsotg, obj, &dwc2_mmio_hsotg_ops, s,
1313 "dwc2-io", 4 * KiB);
1314 memory_region_add_subregion(&s->container, 0x0000, &s->hsotg);
1316 memory_region_init_io(&s->fifos, obj, &dwc2_mmio_hreg2_ops, s,
1317 "dwc2-fifo", 64 * KiB);
1318 memory_region_add_subregion(&s->container, 0x1000, &s->fifos);
1321 static const VMStateDescription vmstate_dwc2_state_packet = {
1322 .name = "dwc2/packet",
1323 .version_id = 1,
1324 .minimum_version_id = 1,
1325 .fields = (VMStateField[]) {
1326 VMSTATE_UINT32(devadr, DWC2Packet),
1327 VMSTATE_UINT32(epnum, DWC2Packet),
1328 VMSTATE_UINT32(epdir, DWC2Packet),
1329 VMSTATE_UINT32(mps, DWC2Packet),
1330 VMSTATE_UINT32(pid, DWC2Packet),
1331 VMSTATE_UINT32(index, DWC2Packet),
1332 VMSTATE_UINT32(pcnt, DWC2Packet),
1333 VMSTATE_UINT32(len, DWC2Packet),
1334 VMSTATE_INT32(async, DWC2Packet),
1335 VMSTATE_BOOL(small, DWC2Packet),
1336 VMSTATE_BOOL(needs_service, DWC2Packet),
1337 VMSTATE_END_OF_LIST()
1341 const VMStateDescription vmstate_dwc2_state = {
1342 .name = "dwc2",
1343 .version_id = 1,
1344 .minimum_version_id = 1,
1345 .fields = (VMStateField[]) {
1346 VMSTATE_UINT32_ARRAY(glbreg, DWC2State,
1347 DWC2_GLBREG_SIZE / sizeof(uint32_t)),
1348 VMSTATE_UINT32_ARRAY(fszreg, DWC2State,
1349 DWC2_FSZREG_SIZE / sizeof(uint32_t)),
1350 VMSTATE_UINT32_ARRAY(hreg0, DWC2State,
1351 DWC2_HREG0_SIZE / sizeof(uint32_t)),
1352 VMSTATE_UINT32_ARRAY(hreg1, DWC2State,
1353 DWC2_HREG1_SIZE / sizeof(uint32_t)),
1354 VMSTATE_UINT32_ARRAY(pcgreg, DWC2State,
1355 DWC2_PCGREG_SIZE / sizeof(uint32_t)),
1357 VMSTATE_TIMER_PTR(eof_timer, DWC2State),
1358 VMSTATE_TIMER_PTR(frame_timer, DWC2State),
1359 VMSTATE_INT64(sof_time, DWC2State),
1360 VMSTATE_INT64(usb_frame_time, DWC2State),
1361 VMSTATE_INT64(usb_bit_time, DWC2State),
1362 VMSTATE_UINT32(usb_version, DWC2State),
1363 VMSTATE_UINT16(frame_number, DWC2State),
1364 VMSTATE_UINT16(fi, DWC2State),
1365 VMSTATE_UINT16(next_chan, DWC2State),
1366 VMSTATE_BOOL(working, DWC2State),
1368 VMSTATE_STRUCT_ARRAY(packet, DWC2State, DWC2_NB_CHAN, 1,
1369 vmstate_dwc2_state_packet, DWC2Packet),
1370 VMSTATE_UINT8_2DARRAY(usb_buf, DWC2State, DWC2_NB_CHAN,
1371 DWC2_MAX_XFER_SIZE),
1373 VMSTATE_END_OF_LIST()
1377 static Property dwc2_usb_properties[] = {
1378 DEFINE_PROP_UINT32("usb_version", DWC2State, usb_version, 2),
1379 DEFINE_PROP_END_OF_LIST(),
1382 static void dwc2_class_init(ObjectClass *klass, void *data)
1384 DeviceClass *dc = DEVICE_CLASS(klass);
1385 DWC2Class *c = DWC2_CLASS(klass);
1386 ResettableClass *rc = RESETTABLE_CLASS(klass);
1388 dc->realize = dwc2_realize;
1389 dc->vmsd = &vmstate_dwc2_state;
1390 set_bit(DEVICE_CATEGORY_USB, dc->categories);
1391 device_class_set_props(dc, dwc2_usb_properties);
1392 resettable_class_set_parent_phases(rc, dwc2_reset_enter, dwc2_reset_hold,
1393 dwc2_reset_exit, &c->parent_phases);
1396 static const TypeInfo dwc2_usb_type_info = {
1397 .name = TYPE_DWC2_USB,
1398 .parent = TYPE_SYS_BUS_DEVICE,
1399 .instance_size = sizeof(DWC2State),
1400 .instance_init = dwc2_init,
1401 .class_size = sizeof(DWC2Class),
1402 .class_init = dwc2_class_init,
1405 static void dwc2_usb_register_types(void)
1407 type_register_static(&dwc2_usb_type_info);
1410 type_init(dwc2_usb_register_types)