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