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
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
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"
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; \
61 #define get_bit(data, bitmask) \
62 (!!((data) & (bitmask)))
65 static inline void dwc2_update_irq(DWC2State
*s
)
70 if ((s
->gintsts
& s
->gintmsk
) && (s
->gahbcfg
& GAHBCFG_GLBL_INTR_EN
)) {
73 if (level
!= oldlevel
) {
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
)) {
85 trace_usb_dwc2_raise_global_irq(intr
);
90 static inline void dwc2_lower_global_irq(DWC2State
*s
, uint32_t intr
)
92 if (s
->gintsts
& intr
) {
94 trace_usb_dwc2_lower_global_irq(intr
);
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
;
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
);
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
);
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
;
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 */
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
);
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
)
187 trace_usb_dwc2_find_device(addr
);
189 if (!(s
->hprt0
& HPRT0_ENA
)) {
190 trace_usb_dwc2_port_disabled(0);
192 dev
= usb_find_device(&s
->uport
, addr
);
194 trace_usb_dwc2_device_found(0);
199 trace_usb_dwc2_device_not_found();
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
,
215 static const char *types
[] = {
216 "Ctrl", "Isoc", "Bulk", "Intr"
219 static const char *dirs
[] = {
223 static void dwc2_handle_packet(DWC2State
*s
, uint32_t devadr
, USBDevice
*dev
,
224 USBEndpoint
*ep
, uint32_t index
, bool send
)
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 if (len
> DWC2_MAX_XFER_SIZE
) {
242 qemu_log_mask(LOG_GUEST_ERROR
,
243 "%s: HCTSIZ transfer size too large\n", __func__
);
248 p
= &s
->packet
[chan
];
250 trace_usb_dwc2_handle_packet(chan
, dev
, &p
->packet
, epnum
, types
[eptype
],
251 dirs
[epdir
], mps
, len
, pcnt
);
254 qemu_log_mask(LOG_GUEST_ERROR
,
255 "%s: Bad HCCHAR_MPS set to zero\n", __func__
);
259 if (eptype
== USB_ENDPOINT_XFER_CONTROL
&& pid
== TSIZ_SC_MC_PID_SETUP
) {
260 pid
= USB_TOKEN_SETUP
;
262 pid
= epdir
? USB_TOKEN_IN
: USB_TOKEN_OUT
;
273 if (pid
!= USB_TOKEN_IN
) {
274 trace_usb_dwc2_memory_read(hcdma
, tlen
);
275 if (dma_memory_read(&s
->dma_as
, hcdma
, s
->usb_buf
[chan
], tlen
,
276 MEMTXATTRS_UNSPECIFIED
) != MEMTX_OK
) {
277 qemu_log_mask(LOG_GUEST_ERROR
, "%s: dma_memory_read failed\n",
282 usb_packet_init(&p
->packet
);
283 usb_packet_setup(&p
->packet
, pid
, ep
, 0, hcdma
,
284 pid
!= USB_TOKEN_IN
, true);
285 usb_packet_addbuf(&p
->packet
, s
->usb_buf
[chan
], tlen
);
286 p
->async
= DWC2_ASYNC_NONE
;
287 usb_handle_packet(dev
, &p
->packet
);
292 stsidx
= -p
->packet
.status
;
293 assert(stsidx
< sizeof(pstatus
) / sizeof(*pstatus
));
294 actual
= p
->packet
.actual_length
;
295 trace_usb_dwc2_packet_status(pstatus
[stsidx
], actual
);
298 if (p
->packet
.status
!= USB_RET_SUCCESS
&&
299 p
->packet
.status
!= USB_RET_NAK
&&
300 p
->packet
.status
!= USB_RET_STALL
&&
301 p
->packet
.status
!= USB_RET_ASYNC
) {
302 trace_usb_dwc2_packet_error(pstatus
[stsidx
]);
305 if (p
->packet
.status
== USB_RET_ASYNC
) {
306 trace_usb_dwc2_async_packet(&p
->packet
, chan
, dev
, epnum
,
308 usb_device_flush_ep_queue(dev
, ep
);
309 assert(p
->async
!= DWC2_ASYNC_INFLIGHT
);
318 p
->async
= DWC2_ASYNC_INFLIGHT
;
319 p
->needs_service
= false;
323 if (p
->packet
.status
== USB_RET_SUCCESS
) {
325 p
->packet
.status
= USB_RET_BABBLE
;
329 if (pid
== USB_TOKEN_IN
) {
330 trace_usb_dwc2_memory_write(hcdma
, actual
);
331 if (dma_memory_write(&s
->dma_as
, hcdma
, s
->usb_buf
[chan
], actual
,
332 MEMTXATTRS_UNSPECIFIED
) != MEMTX_OK
) {
333 qemu_log_mask(LOG_GUEST_ERROR
, "%s: dma_memory_write failed\n",
338 tpcnt
= actual
/ mps
;
341 if (pid
== USB_TOKEN_IN
) {
346 pcnt
-= tpcnt
< pcnt
? tpcnt
: pcnt
;
347 set_field(&hctsiz
, pcnt
, TSIZ_PKTCNT
);
348 len
-= actual
< len
? actual
: len
;
349 set_field(&hctsiz
, len
, TSIZ_XFERSIZE
);
350 s
->hreg1
[index
+ 4] = hctsiz
;
352 s
->hreg1
[index
+ 5] = hcdma
;
354 if (!pcnt
|| len
== 0 || actual
== 0) {
358 intr
|= pintr
[stsidx
];
359 if (p
->packet
.status
== USB_RET_NAK
&&
360 (eptype
== USB_ENDPOINT_XFER_CONTROL
||
361 eptype
== USB_ENDPOINT_XFER_BULK
)) {
363 * for ctrl/bulk, automatically retry on NAK,
364 * but send the interrupt anyway
366 intr
&= ~HCINTMSK_RESERVED14_31
;
367 s
->hreg1
[index
+ 2] |= intr
;
370 intr
|= HCINTMSK_CHHLTD
;
375 usb_packet_cleanup(&p
->packet
);
378 hcchar
&= ~HCCHAR_CHENA
;
379 s
->hreg1
[index
] = hcchar
;
380 if (!(intr
& HCINTMSK_CHHLTD
)) {
381 intr
|= HCINTMSK_CHHLTD
| HCINTMSK_XFERCOMPL
;
383 intr
&= ~HCINTMSK_RESERVED14_31
;
384 s
->hreg1
[index
+ 2] |= intr
;
385 p
->needs_service
= false;
386 trace_usb_dwc2_packet_done(pstatus
[stsidx
], actual
, len
, pcnt
);
387 dwc2_update_hc_irq(s
, index
);
399 p
->needs_service
= true;
400 trace_usb_dwc2_packet_next(pstatus
[stsidx
], len
, pcnt
);
402 dwc2_update_hc_irq(s
, index
);
406 /* Attach or detach a device on root hub */
408 static const char *speeds
[] = {
409 "low", "full", "high"
412 static void dwc2_attach(USBPort
*port
)
414 DWC2State
*s
= port
->opaque
;
417 trace_usb_dwc2_attach(port
);
418 assert(port
->index
== 0);
420 if (!port
->dev
|| !port
->dev
->attached
) {
424 assert(port
->dev
->speed
<= USB_SPEED_HIGH
);
425 trace_usb_dwc2_attach_speed(speeds
[port
->dev
->speed
]);
426 s
->hprt0
&= ~HPRT0_SPD_MASK
;
428 switch (port
->dev
->speed
) {
430 s
->hprt0
|= HPRT0_SPD_LOW_SPEED
<< HPRT0_SPD_SHIFT
;
433 s
->hprt0
|= HPRT0_SPD_FULL_SPEED
<< HPRT0_SPD_SHIFT
;
436 s
->hprt0
|= HPRT0_SPD_HIGH_SPEED
<< HPRT0_SPD_SHIFT
;
442 s
->usb_frame_time
= NANOSECONDS_PER_SECOND
/ 8000; /* 125000 */
443 if (NANOSECONDS_PER_SECOND
>= USB_HZ_HS
) {
444 s
->usb_bit_time
= NANOSECONDS_PER_SECOND
/ USB_HZ_HS
; /* 10.4 */
449 s
->usb_frame_time
= NANOSECONDS_PER_SECOND
/ 1000; /* 1000000 */
450 if (NANOSECONDS_PER_SECOND
>= USB_HZ_FS
) {
451 s
->usb_bit_time
= NANOSECONDS_PER_SECOND
/ USB_HZ_FS
; /* 83.3 */
457 s
->fi
= USB_FRMINTVL
- 1;
458 s
->hprt0
|= HPRT0_CONNDET
| HPRT0_CONNSTS
;
461 dwc2_raise_global_irq(s
, GINTSTS_PRTINT
);
464 static void dwc2_detach(USBPort
*port
)
466 DWC2State
*s
= port
->opaque
;
468 trace_usb_dwc2_detach(port
);
469 assert(port
->index
== 0);
473 s
->hprt0
&= ~(HPRT0_SPD_MASK
| HPRT0_SUSP
| HPRT0_ENA
| HPRT0_CONNSTS
);
474 s
->hprt0
|= HPRT0_CONNDET
| HPRT0_ENACHG
;
476 dwc2_raise_global_irq(s
, GINTSTS_PRTINT
);
479 static void dwc2_child_detach(USBPort
*port
, USBDevice
*child
)
481 trace_usb_dwc2_child_detach(port
, child
);
482 assert(port
->index
== 0);
485 static void dwc2_wakeup(USBPort
*port
)
487 DWC2State
*s
= port
->opaque
;
489 trace_usb_dwc2_wakeup(port
);
490 assert(port
->index
== 0);
492 if (s
->hprt0
& HPRT0_SUSP
) {
493 s
->hprt0
|= HPRT0_RES
;
494 dwc2_raise_global_irq(s
, GINTSTS_PRTINT
);
497 qemu_bh_schedule(s
->async_bh
);
500 static void dwc2_async_packet_complete(USBPort
*port
, USBPacket
*packet
)
502 DWC2State
*s
= port
->opaque
;
507 assert(port
->index
== 0);
508 p
= container_of(packet
, DWC2Packet
, packet
);
509 dev
= dwc2_find_device(s
, p
->devadr
);
510 ep
= usb_ep_get(dev
, p
->pid
, p
->epnum
);
511 trace_usb_dwc2_async_packet_complete(port
, packet
, p
->index
>> 3, dev
,
512 p
->epnum
, dirs
[p
->epdir
], p
->len
);
513 assert(p
->async
== DWC2_ASYNC_INFLIGHT
);
515 if (packet
->status
== USB_RET_REMOVE_FROM_QUEUE
) {
516 usb_cancel_packet(packet
);
517 usb_packet_cleanup(packet
);
521 dwc2_handle_packet(s
, p
->devadr
, dev
, ep
, p
->index
, false);
523 p
->async
= DWC2_ASYNC_FINISHED
;
524 qemu_bh_schedule(s
->async_bh
);
527 static USBPortOps dwc2_port_ops
= {
528 .attach
= dwc2_attach
,
529 .detach
= dwc2_detach
,
530 .child_detach
= dwc2_child_detach
,
531 .wakeup
= dwc2_wakeup
,
532 .complete
= dwc2_async_packet_complete
,
535 static uint32_t dwc2_get_frame_remaining(DWC2State
*s
)
540 tks
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
) - s
->sof_time
;
545 /* avoid muldiv if possible */
546 if (tks
>= s
->usb_frame_time
) {
549 if (tks
< s
->usb_bit_time
) {
554 /* tks = number of ns since SOF, divided by 83 (fs) or 10 (hs) */
555 tks
= tks
/ s
->usb_bit_time
;
556 if (tks
>= (int64_t)s
->fi
) {
560 /* remaining = frame interval minus tks */
561 fr
= (uint32_t)((int64_t)s
->fi
- tks
);
567 static void dwc2_work_bh(void *opaque
)
569 DWC2State
*s
= opaque
;
573 int64_t t_now
, expire_time
;
577 trace_usb_dwc2_work_bh();
583 t_now
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
587 p
= &s
->packet
[chan
];
588 if (p
->needs_service
) {
589 dev
= dwc2_find_device(s
, p
->devadr
);
590 ep
= usb_ep_get(dev
, p
->pid
, p
->epnum
);
591 trace_usb_dwc2_work_bh_service(s
->next_chan
, chan
, dev
, p
->epnum
);
592 dwc2_handle_packet(s
, p
->devadr
, dev
, ep
, p
->index
, true);
595 if (++chan
== DWC2_NB_CHAN
) {
600 trace_usb_dwc2_work_bh_next(chan
);
602 } while (chan
!= s
->next_chan
);
605 expire_time
= t_now
+ NANOSECONDS_PER_SECOND
/ 4000;
606 timer_mod(s
->frame_timer
, expire_time
);
611 static void dwc2_enable_chan(DWC2State
*s
, uint32_t index
)
617 uint32_t devadr
, epnum
, epdir
, eptype
, pid
, len
;
620 assert((index
>> 3) < DWC2_NB_CHAN
);
621 p
= &s
->packet
[index
>> 3];
622 hcchar
= s
->hreg1
[index
];
623 hctsiz
= s
->hreg1
[index
+ 4];
624 devadr
= get_field(hcchar
, HCCHAR_DEVADDR
);
625 epnum
= get_field(hcchar
, HCCHAR_EPNUM
);
626 epdir
= get_bit(hcchar
, HCCHAR_EPDIR
);
627 eptype
= get_field(hcchar
, HCCHAR_EPTYPE
);
628 pid
= get_field(hctsiz
, TSIZ_SC_MC_PID
);
629 len
= get_field(hctsiz
, TSIZ_XFERSIZE
);
631 dev
= dwc2_find_device(s
, devadr
);
633 trace_usb_dwc2_enable_chan(index
>> 3, dev
, &p
->packet
, epnum
);
638 if (eptype
== USB_ENDPOINT_XFER_CONTROL
&& pid
== TSIZ_SC_MC_PID_SETUP
) {
639 pid
= USB_TOKEN_SETUP
;
641 pid
= epdir
? USB_TOKEN_IN
: USB_TOKEN_OUT
;
644 ep
= usb_ep_get(dev
, pid
, epnum
);
647 * Hack: Networking doesn't like us delivering large transfers, it kind
648 * of works but the latency is horrible. So if the transfer is <= the mtu
649 * size, we take that as a hint that this might be a network transfer,
650 * and do the transfer packet-by-packet.
658 dwc2_handle_packet(s
, devadr
, dev
, ep
, index
, true);
659 qemu_bh_schedule(s
->async_bh
);
662 static const char *glbregnm
[] = {
663 "GOTGCTL ", "GOTGINT ", "GAHBCFG ", "GUSBCFG ", "GRSTCTL ",
664 "GINTSTS ", "GINTMSK ", "GRXSTSR ", "GRXSTSP ", "GRXFSIZ ",
665 "GNPTXFSIZ", "GNPTXSTS ", "GI2CCTL ", "GPVNDCTL ", "GGPIO ",
666 "GUID ", "GSNPSID ", "GHWCFG1 ", "GHWCFG2 ", "GHWCFG3 ",
667 "GHWCFG4 ", "GLPMCFG ", "GPWRDN ", "GDFIFOCFG", "GADPCTL ",
668 "GREFCLK ", "GINTMSK2 ", "GINTSTS2 "
671 static uint64_t dwc2_glbreg_read(void *ptr
, hwaddr addr
, int index
,
677 if (addr
> GINTSTS2
) {
678 qemu_log_mask(LOG_GUEST_ERROR
, "%s: Bad offset 0x%"HWADDR_PRIx
"\n",
683 val
= s
->glbreg
[index
];
687 /* clear any self-clearing bits that were set */
688 val
&= ~(GRSTCTL_TXFFLSH
| GRSTCTL_RXFFLSH
| GRSTCTL_IN_TKNQ_FLSH
|
689 GRSTCTL_FRMCNTRRST
| GRSTCTL_HSFTRST
| GRSTCTL_CSFTRST
);
690 s
->glbreg
[index
] = val
;
696 trace_usb_dwc2_glbreg_read(addr
, glbregnm
[index
], val
);
700 static void dwc2_glbreg_write(void *ptr
, hwaddr addr
, int index
, uint64_t val
,
709 if (addr
> GINTSTS2
) {
710 qemu_log_mask(LOG_GUEST_ERROR
, "%s: Bad offset 0x%"HWADDR_PRIx
"\n",
715 mmio
= &s
->glbreg
[index
];
720 /* don't allow setting of read-only bits */
721 val
&= ~(GOTGCTL_MULT_VALID_BC_MASK
| GOTGCTL_BSESVLD
|
722 GOTGCTL_ASESVLD
| GOTGCTL_DBNC_SHORT
| GOTGCTL_CONID_B
|
723 GOTGCTL_HSTNEGSCS
| GOTGCTL_SESREQSCS
);
724 /* don't allow clearing of read-only bits */
725 val
|= old
& (GOTGCTL_MULT_VALID_BC_MASK
| GOTGCTL_BSESVLD
|
726 GOTGCTL_ASESVLD
| GOTGCTL_DBNC_SHORT
| GOTGCTL_CONID_B
|
727 GOTGCTL_HSTNEGSCS
| GOTGCTL_SESREQSCS
);
730 if ((val
& GAHBCFG_GLBL_INTR_EN
) && !(old
& GAHBCFG_GLBL_INTR_EN
)) {
735 val
|= GRSTCTL_AHBIDLE
;
736 val
&= ~GRSTCTL_DMAREQ
;
737 if (!(old
& GRSTCTL_TXFFLSH
) && (val
& GRSTCTL_TXFFLSH
)) {
738 /* TODO - TX fifo flush */
739 qemu_log_mask(LOG_UNIMP
, "%s: Tx FIFO flush not implemented\n",
742 if (!(old
& GRSTCTL_RXFFLSH
) && (val
& GRSTCTL_RXFFLSH
)) {
743 /* TODO - RX fifo flush */
744 qemu_log_mask(LOG_UNIMP
, "%s: Rx FIFO flush not implemented\n",
747 if (!(old
& GRSTCTL_IN_TKNQ_FLSH
) && (val
& GRSTCTL_IN_TKNQ_FLSH
)) {
748 /* TODO - device IN token queue flush */
749 qemu_log_mask(LOG_UNIMP
, "%s: Token queue flush not implemented\n",
752 if (!(old
& GRSTCTL_FRMCNTRRST
) && (val
& GRSTCTL_FRMCNTRRST
)) {
753 /* TODO - host frame counter reset */
754 qemu_log_mask(LOG_UNIMP
,
755 "%s: Frame counter reset not implemented\n",
758 if (!(old
& GRSTCTL_HSFTRST
) && (val
& GRSTCTL_HSFTRST
)) {
759 /* TODO - host soft reset */
760 qemu_log_mask(LOG_UNIMP
, "%s: Host soft reset not implemented\n",
763 if (!(old
& GRSTCTL_CSFTRST
) && (val
& GRSTCTL_CSFTRST
)) {
764 /* TODO - core soft reset */
765 qemu_log_mask(LOG_UNIMP
, "%s: Core soft reset not implemented\n",
768 /* don't allow clearing of self-clearing bits */
769 val
|= old
& (GRSTCTL_TXFFLSH
| GRSTCTL_RXFFLSH
|
770 GRSTCTL_IN_TKNQ_FLSH
| GRSTCTL_FRMCNTRRST
|
771 GRSTCTL_HSFTRST
| GRSTCTL_CSFTRST
);
774 /* clear the write-1-to-clear bits */
777 /* don't allow clearing of read-only bits */
778 val
|= old
& (GINTSTS_PTXFEMP
| GINTSTS_HCHINT
| GINTSTS_PRTINT
|
779 GINTSTS_OEPINT
| GINTSTS_IEPINT
| GINTSTS_GOUTNAKEFF
|
780 GINTSTS_GINNAKEFF
| GINTSTS_NPTXFEMP
| GINTSTS_RXFLVL
|
781 GINTSTS_OTGINT
| GINTSTS_CURMODE_HOST
);
791 trace_usb_dwc2_glbreg_write(addr
, glbregnm
[index
], orig
, old
, val
);
799 static uint64_t dwc2_fszreg_read(void *ptr
, hwaddr addr
, int index
,
805 if (addr
!= HPTXFSIZ
) {
806 qemu_log_mask(LOG_GUEST_ERROR
, "%s: Bad offset 0x%"HWADDR_PRIx
"\n",
811 val
= s
->fszreg
[index
];
813 trace_usb_dwc2_fszreg_read(addr
, val
);
817 static void dwc2_fszreg_write(void *ptr
, hwaddr addr
, int index
, uint64_t val
,
825 if (addr
!= HPTXFSIZ
) {
826 qemu_log_mask(LOG_GUEST_ERROR
, "%s: Bad offset 0x%"HWADDR_PRIx
"\n",
831 mmio
= &s
->fszreg
[index
];
834 trace_usb_dwc2_fszreg_write(addr
, orig
, old
, val
);
838 static const char *hreg0nm
[] = {
839 "HCFG ", "HFIR ", "HFNUM ", "<rsvd> ", "HPTXSTS ",
840 "HAINT ", "HAINTMSK ", "HFLBADDR ", "<rsvd> ", "<rsvd> ",
841 "<rsvd> ", "<rsvd> ", "<rsvd> ", "<rsvd> ", "<rsvd> ",
845 static uint64_t dwc2_hreg0_read(void *ptr
, hwaddr addr
, int index
,
851 if (addr
< HCFG
|| addr
> HPRT0
) {
852 qemu_log_mask(LOG_GUEST_ERROR
, "%s: Bad offset 0x%"HWADDR_PRIx
"\n",
857 val
= s
->hreg0
[index
];
861 val
= (dwc2_get_frame_remaining(s
) << HFNUM_FRREM_SHIFT
) |
862 (s
->hfnum
<< HFNUM_FRNUM_SHIFT
);
868 trace_usb_dwc2_hreg0_read(addr
, hreg0nm
[index
], val
);
872 static void dwc2_hreg0_write(void *ptr
, hwaddr addr
, int index
, uint64_t val
,
876 USBDevice
*dev
= s
->uport
.dev
;
879 uint32_t tval
, told
, old
;
883 if (addr
< HCFG
|| addr
> HPRT0
) {
884 qemu_log_mask(LOG_GUEST_ERROR
, "%s: Bad offset 0x%"HWADDR_PRIx
"\n",
889 mmio
= &s
->hreg0
[index
];
898 qemu_log_mask(LOG_GUEST_ERROR
, "%s: write to read-only register\n",
905 /* don't allow clearing of read-only bits */
906 val
|= old
& (HPRT0_SPD_MASK
| HPRT0_LNSTS_MASK
| HPRT0_OVRCURRACT
|
908 /* don't allow clearing of self-clearing bits */
909 val
|= old
& (HPRT0_SUSP
| HPRT0_RES
);
910 /* don't allow setting of self-setting bits */
911 if (!(old
& HPRT0_ENA
) && (val
& HPRT0_ENA
)) {
914 /* clear the write-1-to-clear bits */
915 tval
= val
& (HPRT0_OVRCURRCHG
| HPRT0_ENACHG
| HPRT0_ENA
|
917 told
= old
& (HPRT0_OVRCURRCHG
| HPRT0_ENACHG
| HPRT0_ENA
|
921 tval
&= (HPRT0_OVRCURRCHG
| HPRT0_ENACHG
| HPRT0_ENA
|
923 val
&= ~(HPRT0_OVRCURRCHG
| HPRT0_ENACHG
| HPRT0_ENA
|
926 if (!(val
& HPRT0_RST
) && (old
& HPRT0_RST
)) {
927 if (dev
&& dev
->attached
) {
928 val
|= HPRT0_ENA
| HPRT0_ENACHG
;
932 if (val
& (HPRT0_OVRCURRCHG
| HPRT0_ENACHG
| HPRT0_CONNDET
)) {
943 trace_usb_dwc2_hreg0_write(addr
, hreg0nm
[index
], orig
, old
,
944 val
& ~HPRT0_CONNDET
);
945 trace_usb_dwc2_hreg0_action("call usb_port_reset");
946 usb_port_reset(&s
->uport
);
947 val
&= ~HPRT0_CONNDET
;
949 trace_usb_dwc2_hreg0_write(addr
, hreg0nm
[index
], orig
, old
, val
);
955 trace_usb_dwc2_hreg0_action("enable PRTINT");
956 dwc2_raise_global_irq(s
, GINTSTS_PRTINT
);
957 } else if (iflg
< 0) {
958 trace_usb_dwc2_hreg0_action("disable PRTINT");
959 dwc2_lower_global_irq(s
, GINTSTS_PRTINT
);
963 static const char *hreg1nm
[] = {
964 "HCCHAR ", "HCSPLT ", "HCINT ", "HCINTMSK", "HCTSIZ ", "HCDMA ",
968 static uint64_t dwc2_hreg1_read(void *ptr
, hwaddr addr
, int index
,
974 if (addr
< HCCHAR(0) || addr
> HCDMAB(DWC2_NB_CHAN
- 1)) {
975 qemu_log_mask(LOG_GUEST_ERROR
, "%s: Bad offset 0x%"HWADDR_PRIx
"\n",
980 val
= s
->hreg1
[index
];
982 trace_usb_dwc2_hreg1_read(addr
, hreg1nm
[index
& 7], addr
>> 5, val
);
986 static void dwc2_hreg1_write(void *ptr
, hwaddr addr
, int index
, uint64_t val
,
997 if (addr
< HCCHAR(0) || addr
> HCDMAB(DWC2_NB_CHAN
- 1)) {
998 qemu_log_mask(LOG_GUEST_ERROR
, "%s: Bad offset 0x%"HWADDR_PRIx
"\n",
1003 mmio
= &s
->hreg1
[index
];
1006 switch (HSOTG_REG(0x500) + (addr
& 0x1c)) {
1008 if ((val
& HCCHAR_CHDIS
) && !(old
& HCCHAR_CHDIS
)) {
1009 val
&= ~(HCCHAR_CHENA
| HCCHAR_CHDIS
);
1012 val
|= old
& HCCHAR_CHDIS
;
1013 if ((val
& HCCHAR_CHENA
) && !(old
& HCCHAR_CHENA
)) {
1014 val
&= ~HCCHAR_CHDIS
;
1017 val
|= old
& HCCHAR_CHENA
;
1022 /* clear the write-1-to-clear bits */
1025 val
&= ~HCINTMSK_RESERVED14_31
;
1029 val
&= ~HCINTMSK_RESERVED14_31
;
1033 qemu_log_mask(LOG_GUEST_ERROR
, "%s: write to read-only register\n",
1040 trace_usb_dwc2_hreg1_write(addr
, hreg1nm
[index
& 7], index
>> 3, orig
,
1045 /* set ChHltd in HCINT */
1046 s
->hreg1
[(index
& ~7) + 2] |= HCINTMSK_CHHLTD
;
1051 dwc2_enable_chan(s
, index
& ~7);
1055 dwc2_update_hc_irq(s
, index
& ~7);
1059 static const char *pcgregnm
[] = {
1060 "PCGCTL ", "PCGCCTL1 "
1063 static uint64_t dwc2_pcgreg_read(void *ptr
, hwaddr addr
, int index
,
1069 if (addr
< PCGCTL
|| addr
> PCGCCTL1
) {
1070 qemu_log_mask(LOG_GUEST_ERROR
, "%s: Bad offset 0x%"HWADDR_PRIx
"\n",
1075 val
= s
->pcgreg
[index
];
1077 trace_usb_dwc2_pcgreg_read(addr
, pcgregnm
[index
], val
);
1081 static void dwc2_pcgreg_write(void *ptr
, hwaddr addr
, int index
,
1082 uint64_t val
, unsigned size
)
1085 uint64_t orig
= val
;
1089 if (addr
< PCGCTL
|| addr
> PCGCCTL1
) {
1090 qemu_log_mask(LOG_GUEST_ERROR
, "%s: Bad offset 0x%"HWADDR_PRIx
"\n",
1095 mmio
= &s
->pcgreg
[index
];
1098 trace_usb_dwc2_pcgreg_write(addr
, pcgregnm
[index
], orig
, old
, val
);
1102 static uint64_t dwc2_hsotg_read(void *ptr
, hwaddr addr
, unsigned size
)
1107 case HSOTG_REG(0x000) ... HSOTG_REG(0x0fc):
1108 val
= dwc2_glbreg_read(ptr
, addr
, (addr
- HSOTG_REG(0x000)) >> 2, size
);
1110 case HSOTG_REG(0x100):
1111 val
= dwc2_fszreg_read(ptr
, addr
, (addr
- HSOTG_REG(0x100)) >> 2, size
);
1113 case HSOTG_REG(0x104) ... HSOTG_REG(0x3fc):
1114 /* Gadget-mode registers, just return 0 for now */
1117 case HSOTG_REG(0x400) ... HSOTG_REG(0x4fc):
1118 val
= dwc2_hreg0_read(ptr
, addr
, (addr
- HSOTG_REG(0x400)) >> 2, size
);
1120 case HSOTG_REG(0x500) ... HSOTG_REG(0x7fc):
1121 val
= dwc2_hreg1_read(ptr
, addr
, (addr
- HSOTG_REG(0x500)) >> 2, size
);
1123 case HSOTG_REG(0x800) ... HSOTG_REG(0xdfc):
1124 /* Gadget-mode registers, just return 0 for now */
1127 case HSOTG_REG(0xe00) ... HSOTG_REG(0xffc):
1128 val
= dwc2_pcgreg_read(ptr
, addr
, (addr
- HSOTG_REG(0xe00)) >> 2, size
);
1131 g_assert_not_reached();
1137 static void dwc2_hsotg_write(void *ptr
, hwaddr addr
, uint64_t val
,
1141 case HSOTG_REG(0x000) ... HSOTG_REG(0x0fc):
1142 dwc2_glbreg_write(ptr
, addr
, (addr
- HSOTG_REG(0x000)) >> 2, val
, size
);
1144 case HSOTG_REG(0x100):
1145 dwc2_fszreg_write(ptr
, addr
, (addr
- HSOTG_REG(0x100)) >> 2, val
, size
);
1147 case HSOTG_REG(0x104) ... HSOTG_REG(0x3fc):
1148 /* Gadget-mode registers, do nothing for now */
1150 case HSOTG_REG(0x400) ... HSOTG_REG(0x4fc):
1151 dwc2_hreg0_write(ptr
, addr
, (addr
- HSOTG_REG(0x400)) >> 2, val
, size
);
1153 case HSOTG_REG(0x500) ... HSOTG_REG(0x7fc):
1154 dwc2_hreg1_write(ptr
, addr
, (addr
- HSOTG_REG(0x500)) >> 2, val
, size
);
1156 case HSOTG_REG(0x800) ... HSOTG_REG(0xdfc):
1157 /* Gadget-mode registers, do nothing for now */
1159 case HSOTG_REG(0xe00) ... HSOTG_REG(0xffc):
1160 dwc2_pcgreg_write(ptr
, addr
, (addr
- HSOTG_REG(0xe00)) >> 2, val
, size
);
1163 g_assert_not_reached();
1167 static const MemoryRegionOps dwc2_mmio_hsotg_ops
= {
1168 .read
= dwc2_hsotg_read
,
1169 .write
= dwc2_hsotg_write
,
1170 .impl
.min_access_size
= 4,
1171 .impl
.max_access_size
= 4,
1172 .endianness
= DEVICE_LITTLE_ENDIAN
,
1175 static uint64_t dwc2_hreg2_read(void *ptr
, hwaddr addr
, unsigned size
)
1177 /* TODO - implement FIFOs to support slave mode */
1178 trace_usb_dwc2_hreg2_read(addr
, addr
>> 12, 0);
1179 qemu_log_mask(LOG_UNIMP
, "%s: FIFO read not implemented\n", __func__
);
1183 static void dwc2_hreg2_write(void *ptr
, hwaddr addr
, uint64_t val
,
1186 uint64_t orig
= val
;
1188 /* TODO - implement FIFOs to support slave mode */
1189 trace_usb_dwc2_hreg2_write(addr
, addr
>> 12, orig
, 0, val
);
1190 qemu_log_mask(LOG_UNIMP
, "%s: FIFO write not implemented\n", __func__
);
1193 static const MemoryRegionOps dwc2_mmio_hreg2_ops
= {
1194 .read
= dwc2_hreg2_read
,
1195 .write
= dwc2_hreg2_write
,
1196 .impl
.min_access_size
= 4,
1197 .impl
.max_access_size
= 4,
1198 .endianness
= DEVICE_LITTLE_ENDIAN
,
1201 static void dwc2_wakeup_endpoint(USBBus
*bus
, USBEndpoint
*ep
,
1202 unsigned int stream
)
1204 DWC2State
*s
= container_of(bus
, DWC2State
, bus
);
1206 trace_usb_dwc2_wakeup_endpoint(ep
, stream
);
1208 /* TODO - do something here? */
1209 qemu_bh_schedule(s
->async_bh
);
1212 static USBBusOps dwc2_bus_ops
= {
1213 .wakeup_endpoint
= dwc2_wakeup_endpoint
,
1216 static void dwc2_work_timer(void *opaque
)
1218 DWC2State
*s
= opaque
;
1220 trace_usb_dwc2_work_timer();
1221 qemu_bh_schedule(s
->async_bh
);
1224 static void dwc2_reset_enter(Object
*obj
, ResetType type
)
1226 DWC2Class
*c
= DWC2_USB_GET_CLASS(obj
);
1227 DWC2State
*s
= DWC2_USB(obj
);
1230 trace_usb_dwc2_reset_enter();
1232 if (c
->parent_phases
.enter
) {
1233 c
->parent_phases
.enter(obj
, type
);
1236 timer_del(s
->frame_timer
);
1237 qemu_bh_cancel(s
->async_bh
);
1239 if (s
->uport
.dev
&& s
->uport
.dev
->attached
) {
1240 usb_detach(&s
->uport
);
1245 s
->gotgctl
= GOTGCTL_BSESVLD
| GOTGCTL_ASESVLD
| GOTGCTL_CONID_B
;
1248 s
->gusbcfg
= 5 << GUSBCFG_USBTRDTIM_SHIFT
;
1249 s
->grstctl
= GRSTCTL_AHBIDLE
;
1250 s
->gintsts
= GINTSTS_CONIDSTSCHNG
| GINTSTS_PTXFEMP
| GINTSTS_NPTXFEMP
|
1251 GINTSTS_CURMODE_HOST
;
1256 s
->gnptxfsiz
= 1024 << FIFOSIZE_DEPTH_SHIFT
;
1257 s
->gnptxsts
= (4 << FIFOSIZE_DEPTH_SHIFT
) | 1024;
1258 s
->gi2cctl
= GI2CCTL_I2CDATSE0
| GI2CCTL_ACK
;
1262 s
->gsnpsid
= 0x4f54294a;
1264 s
->ghwcfg2
= (8 << GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT
) |
1265 (4 << GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT
) |
1266 (4 << GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT
) |
1267 GHWCFG2_DYNAMIC_FIFO
|
1268 GHWCFG2_PERIO_EP_SUPPORTED
|
1269 ((DWC2_NB_CHAN
- 1) << GHWCFG2_NUM_HOST_CHAN_SHIFT
) |
1270 (GHWCFG2_INT_DMA_ARCH
<< GHWCFG2_ARCHITECTURE_SHIFT
) |
1271 (GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST
<< GHWCFG2_OP_MODE_SHIFT
);
1272 s
->ghwcfg3
= (4096 << GHWCFG3_DFIFO_DEPTH_SHIFT
) |
1273 (4 << GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT
) |
1274 (4 << GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT
);
1277 s
->gpwrdn
= GPWRDN_PWRDNRSTN
;
1284 s
->hptxfsiz
= 500 << FIFOSIZE_DEPTH_SHIFT
;
1286 s
->hcfg
= 2 << HCFG_RESVALID_SHIFT
;
1289 s
->hptxsts
= (16 << TXSTS_QSPCAVAIL_SHIFT
) | 32768;
1294 memset(s
->hreg1
, 0, sizeof(s
->hreg1
));
1295 memset(s
->pcgreg
, 0, sizeof(s
->pcgreg
));
1298 s
->frame_number
= 0;
1299 s
->fi
= USB_FRMINTVL
- 1;
1303 for (i
= 0; i
< DWC2_NB_CHAN
; i
++) {
1304 s
->packet
[i
].needs_service
= false;
1308 static void dwc2_reset_hold(Object
*obj
)
1310 DWC2Class
*c
= DWC2_USB_GET_CLASS(obj
);
1311 DWC2State
*s
= DWC2_USB(obj
);
1313 trace_usb_dwc2_reset_hold();
1315 if (c
->parent_phases
.hold
) {
1316 c
->parent_phases
.hold(obj
);
1322 static void dwc2_reset_exit(Object
*obj
)
1324 DWC2Class
*c
= DWC2_USB_GET_CLASS(obj
);
1325 DWC2State
*s
= DWC2_USB(obj
);
1327 trace_usb_dwc2_reset_exit();
1329 if (c
->parent_phases
.exit
) {
1330 c
->parent_phases
.exit(obj
);
1333 s
->hprt0
= HPRT0_PWR
;
1334 if (s
->uport
.dev
&& s
->uport
.dev
->attached
) {
1335 usb_attach(&s
->uport
);
1336 usb_device_reset(s
->uport
.dev
);
1340 static void dwc2_realize(DeviceState
*dev
, Error
**errp
)
1342 SysBusDevice
*sbd
= SYS_BUS_DEVICE(dev
);
1343 DWC2State
*s
= DWC2_USB(dev
);
1346 obj
= object_property_get_link(OBJECT(dev
), "dma-mr", &error_abort
);
1348 s
->dma_mr
= MEMORY_REGION(obj
);
1349 address_space_init(&s
->dma_as
, s
->dma_mr
, "dwc2");
1351 usb_bus_new(&s
->bus
, sizeof(s
->bus
), &dwc2_bus_ops
, dev
);
1352 usb_register_port(&s
->bus
, &s
->uport
, s
, 0, &dwc2_port_ops
,
1353 USB_SPEED_MASK_LOW
| USB_SPEED_MASK_FULL
|
1354 (s
->usb_version
== 2 ? USB_SPEED_MASK_HIGH
: 0));
1357 s
->usb_frame_time
= NANOSECONDS_PER_SECOND
/ 1000; /* 1000000 */
1358 if (NANOSECONDS_PER_SECOND
>= USB_HZ_FS
) {
1359 s
->usb_bit_time
= NANOSECONDS_PER_SECOND
/ USB_HZ_FS
; /* 83.3 */
1361 s
->usb_bit_time
= 1;
1364 s
->fi
= USB_FRMINTVL
- 1;
1365 s
->eof_timer
= timer_new_ns(QEMU_CLOCK_VIRTUAL
, dwc2_frame_boundary
, s
);
1366 s
->frame_timer
= timer_new_ns(QEMU_CLOCK_VIRTUAL
, dwc2_work_timer
, s
);
1367 s
->async_bh
= qemu_bh_new(dwc2_work_bh
, s
);
1369 sysbus_init_irq(sbd
, &s
->irq
);
1372 static void dwc2_init(Object
*obj
)
1374 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
1375 DWC2State
*s
= DWC2_USB(obj
);
1377 memory_region_init(&s
->container
, obj
, "dwc2", DWC2_MMIO_SIZE
);
1378 sysbus_init_mmio(sbd
, &s
->container
);
1380 memory_region_init_io(&s
->hsotg
, obj
, &dwc2_mmio_hsotg_ops
, s
,
1381 "dwc2-io", 4 * KiB
);
1382 memory_region_add_subregion(&s
->container
, 0x0000, &s
->hsotg
);
1384 memory_region_init_io(&s
->fifos
, obj
, &dwc2_mmio_hreg2_ops
, s
,
1385 "dwc2-fifo", 64 * KiB
);
1386 memory_region_add_subregion(&s
->container
, 0x1000, &s
->fifos
);
1389 static const VMStateDescription vmstate_dwc2_state_packet
= {
1390 .name
= "dwc2/packet",
1392 .minimum_version_id
= 1,
1393 .fields
= (VMStateField
[]) {
1394 VMSTATE_UINT32(devadr
, DWC2Packet
),
1395 VMSTATE_UINT32(epnum
, DWC2Packet
),
1396 VMSTATE_UINT32(epdir
, DWC2Packet
),
1397 VMSTATE_UINT32(mps
, DWC2Packet
),
1398 VMSTATE_UINT32(pid
, DWC2Packet
),
1399 VMSTATE_UINT32(index
, DWC2Packet
),
1400 VMSTATE_UINT32(pcnt
, DWC2Packet
),
1401 VMSTATE_UINT32(len
, DWC2Packet
),
1402 VMSTATE_INT32(async
, DWC2Packet
),
1403 VMSTATE_BOOL(small
, DWC2Packet
),
1404 VMSTATE_BOOL(needs_service
, DWC2Packet
),
1405 VMSTATE_END_OF_LIST()
1409 const VMStateDescription vmstate_dwc2_state
= {
1412 .minimum_version_id
= 1,
1413 .fields
= (VMStateField
[]) {
1414 VMSTATE_UINT32_ARRAY(glbreg
, DWC2State
,
1415 DWC2_GLBREG_SIZE
/ sizeof(uint32_t)),
1416 VMSTATE_UINT32_ARRAY(fszreg
, DWC2State
,
1417 DWC2_FSZREG_SIZE
/ sizeof(uint32_t)),
1418 VMSTATE_UINT32_ARRAY(hreg0
, DWC2State
,
1419 DWC2_HREG0_SIZE
/ sizeof(uint32_t)),
1420 VMSTATE_UINT32_ARRAY(hreg1
, DWC2State
,
1421 DWC2_HREG1_SIZE
/ sizeof(uint32_t)),
1422 VMSTATE_UINT32_ARRAY(pcgreg
, DWC2State
,
1423 DWC2_PCGREG_SIZE
/ sizeof(uint32_t)),
1425 VMSTATE_TIMER_PTR(eof_timer
, DWC2State
),
1426 VMSTATE_TIMER_PTR(frame_timer
, DWC2State
),
1427 VMSTATE_INT64(sof_time
, DWC2State
),
1428 VMSTATE_INT64(usb_frame_time
, DWC2State
),
1429 VMSTATE_INT64(usb_bit_time
, DWC2State
),
1430 VMSTATE_UINT32(usb_version
, DWC2State
),
1431 VMSTATE_UINT16(frame_number
, DWC2State
),
1432 VMSTATE_UINT16(fi
, DWC2State
),
1433 VMSTATE_UINT16(next_chan
, DWC2State
),
1434 VMSTATE_BOOL(working
, DWC2State
),
1436 VMSTATE_STRUCT_ARRAY(packet
, DWC2State
, DWC2_NB_CHAN
, 1,
1437 vmstate_dwc2_state_packet
, DWC2Packet
),
1438 VMSTATE_UINT8_2DARRAY(usb_buf
, DWC2State
, DWC2_NB_CHAN
,
1439 DWC2_MAX_XFER_SIZE
),
1441 VMSTATE_END_OF_LIST()
1445 static Property dwc2_usb_properties
[] = {
1446 DEFINE_PROP_UINT32("usb_version", DWC2State
, usb_version
, 2),
1447 DEFINE_PROP_END_OF_LIST(),
1450 static void dwc2_class_init(ObjectClass
*klass
, void *data
)
1452 DeviceClass
*dc
= DEVICE_CLASS(klass
);
1453 DWC2Class
*c
= DWC2_USB_CLASS(klass
);
1454 ResettableClass
*rc
= RESETTABLE_CLASS(klass
);
1456 dc
->realize
= dwc2_realize
;
1457 dc
->vmsd
= &vmstate_dwc2_state
;
1458 set_bit(DEVICE_CATEGORY_USB
, dc
->categories
);
1459 device_class_set_props(dc
, dwc2_usb_properties
);
1460 resettable_class_set_parent_phases(rc
, dwc2_reset_enter
, dwc2_reset_hold
,
1461 dwc2_reset_exit
, &c
->parent_phases
);
1464 static const TypeInfo dwc2_usb_type_info
= {
1465 .name
= TYPE_DWC2_USB
,
1466 .parent
= TYPE_SYS_BUS_DEVICE
,
1467 .instance_size
= sizeof(DWC2State
),
1468 .instance_init
= dwc2_init
,
1469 .class_size
= sizeof(DWC2Class
),
1470 .class_init
= dwc2_class_init
,
1473 static void dwc2_usb_register_types(void)
1475 type_register_static(&dwc2_usb_type_info
);
1478 type_init(dwc2_usb_register_types
)