qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

dwc-hsotg (dwc2) USB host controller emulation

Add the dwc-hsotg (dwc2) USB host controller emulation code.
Based on hw/usb/hcd-ehci.c and hw/usb/hcd-ohci.c.

Note that to use this with the dwc-otg driver in the Raspbian
kernel, you must pass the option "dwc_otg.fiq_fsm_enable=0" on
the kernel command line.

Emulation of slave mode and of descriptor-DMA mode has not been
implemented yet. These modes are seldom used.

I have used some on-line sources of information while developing
this emulation, including:

http://www.capital-micro.com/PDF/CME-M7_Family_User_Guide_EN.pdf
which has a pretty complete description of the controller starting
on page 370.

https://sourceforge.net/p/wive-ng/wive-ng-mt/ci/master/tree/docs/DataSheets/RT3050_5x_V2.0_081408_0902.pdf
which has a description of the controller registers starting on
page 130.

Thanks to Felippe Mathieu-Daude for providing a cleaner method
of implementing the memory regions for the controller registers.

Signed-off-by: Paul Zimmerman <pauldzim@gmail.com>
Message-id: 20200520235349.21215-5-pauldzim@gmail.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

authored by

Paul Zimmerman and committed by
Peter Maydell
153ef166 104a010f

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