* [PATCH v6 1/7] usb/hcd-xhci: Make dma read/writes hooks pci free
2020-09-16 11:41 [PATCH v6 0/7] Make hcd-xhci independent of pci hooks Sai Pavan Boddu
@ 2020-09-16 11:41 ` Sai Pavan Boddu
2020-09-16 11:41 ` [PATCH v6 2/7] usb/hcd-xhci: Move qemu-xhci device to hcd-xhci-pci.c Sai Pavan Boddu
` (6 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Sai Pavan Boddu @ 2020-09-16 11:41 UTC (permalink / raw)
To: Peter Maydell, Markus Armbruster,
'Marc-André Lureau', Paolo Bonzini, Gerd Hoffmann,
Edgar Iglesias, Francisco Eduardo Iglesias
Cc: Eduardo Habkost, Vikram Garhwal, qemu-devel, Paul Zimmerman,
Sai Pavan Boddu, Alistair Francis, Ying Fang,
'Philippe Mathieu-Daudé'
This patch starts making the hcd-xhci.c pci free, as part of this
restructuring dma read/writes are handled without passing pci object.
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
hw/usb/hcd-xhci.c | 24 +++++++++++-------------
hw/usb/hcd-xhci.h | 1 +
2 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 46a2186..254cf1e 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -495,7 +495,7 @@ static inline void xhci_dma_read_u32s(XHCIState *xhci, dma_addr_t addr,
assert((len % sizeof(uint32_t)) == 0);
- pci_dma_read(PCI_DEVICE(xhci), addr, buf, len);
+ dma_memory_read(xhci->as, addr, buf, len);
for (i = 0; i < (len / sizeof(uint32_t)); i++) {
buf[i] = le32_to_cpu(buf[i]);
@@ -515,7 +515,7 @@ static inline void xhci_dma_write_u32s(XHCIState *xhci, dma_addr_t addr,
for (i = 0; i < n; i++) {
tmp[i] = cpu_to_le32(buf[i]);
}
- pci_dma_write(PCI_DEVICE(xhci), addr, tmp, len);
+ dma_memory_write(xhci->as, addr, tmp, len);
}
static XHCIPort *xhci_lookup_port(XHCIState *xhci, struct USBPort *uport)
@@ -644,7 +644,6 @@ static void xhci_die(XHCIState *xhci)
static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v)
{
- PCIDevice *pci_dev = PCI_DEVICE(xhci);
XHCIInterrupter *intr = &xhci->intr[v];
XHCITRB ev_trb;
dma_addr_t addr;
@@ -663,7 +662,7 @@ static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v)
ev_trb.status, ev_trb.control);
addr = intr->er_start + TRB_SIZE*intr->er_ep_idx;
- pci_dma_write(pci_dev, addr, &ev_trb, TRB_SIZE);
+ dma_memory_write(xhci->as, addr, &ev_trb, TRB_SIZE);
intr->er_ep_idx++;
if (intr->er_ep_idx >= intr->er_size) {
@@ -720,12 +719,11 @@ static void xhci_ring_init(XHCIState *xhci, XHCIRing *ring,
static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb,
dma_addr_t *addr)
{
- PCIDevice *pci_dev = PCI_DEVICE(xhci);
uint32_t link_cnt = 0;
while (1) {
TRBType type;
- pci_dma_read(pci_dev, ring->dequeue, trb, TRB_SIZE);
+ dma_memory_read(xhci->as, ring->dequeue, trb, TRB_SIZE);
trb->addr = ring->dequeue;
trb->ccs = ring->ccs;
le64_to_cpus(&trb->parameter);
@@ -762,7 +760,6 @@ static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb,
static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring)
{
- PCIDevice *pci_dev = PCI_DEVICE(xhci);
XHCITRB trb;
int length = 0;
dma_addr_t dequeue = ring->dequeue;
@@ -773,7 +770,7 @@ static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring)
while (1) {
TRBType type;
- pci_dma_read(pci_dev, dequeue, &trb, TRB_SIZE);
+ dma_memory_read(xhci->as, dequeue, &trb, TRB_SIZE);
le64_to_cpus(&trb.parameter);
le32_to_cpus(&trb.status);
le32_to_cpus(&trb.control);
@@ -828,7 +825,7 @@ static void xhci_er_reset(XHCIState *xhci, int v)
xhci_die(xhci);
return;
}
- pci_dma_read(PCI_DEVICE(xhci), erstba, &seg, sizeof(seg));
+ dma_memory_read(xhci->as, erstba, &seg, sizeof(seg));
le32_to_cpus(&seg.addr_low);
le32_to_cpus(&seg.addr_high);
le32_to_cpus(&seg.size);
@@ -1440,7 +1437,7 @@ static int xhci_xfer_create_sgl(XHCITransfer *xfer, int in_xfer)
int i;
xfer->int_req = false;
- pci_dma_sglist_init(&xfer->sgl, PCI_DEVICE(xhci), xfer->trb_count);
+ qemu_sglist_init(&xfer->sgl, DEVICE(xhci), xfer->trb_count, xhci->as);
for (i = 0; i < xfer->trb_count; i++) {
XHCITRB *trb = &xfer->trbs[i];
dma_addr_t addr;
@@ -2104,7 +2101,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
assert(slotid >= 1 && slotid <= xhci->numslots);
dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high);
- poctx = ldq_le_pci_dma(PCI_DEVICE(xhci), dcbaap + 8 * slotid);
+ poctx = ldq_le_dma(xhci->as, dcbaap + 8 * slotid);
ictx = xhci_mask64(pictx);
octx = xhci_mask64(poctx);
@@ -2442,7 +2439,7 @@ static TRBCCode xhci_get_port_bandwidth(XHCIState *xhci, uint64_t pctx)
/* TODO: actually implement real values here */
bw_ctx[0] = 0;
memset(&bw_ctx[1], 80, xhci->numports); /* 80% */
- pci_dma_write(PCI_DEVICE(xhci), ctx, bw_ctx, sizeof(bw_ctx));
+ dma_memory_write(xhci->as, ctx, bw_ctx, sizeof(bw_ctx));
return CC_SUCCESS;
}
@@ -3434,6 +3431,7 @@ static void usb_xhci_realize(struct PCIDevice *dev, Error **errp)
}
usb_xhci_init(xhci);
+ xhci->as = pci_get_address_space(dev);
xhci->mfwrap_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, xhci_mfwrap_timer, xhci);
memory_region_init(&xhci->mem, OBJECT(xhci), "xhci", LEN_REGS);
@@ -3534,7 +3532,7 @@ static int usb_xhci_post_load(void *opaque, int version_id)
continue;
}
slot->ctx =
- xhci_mask64(ldq_le_pci_dma(pci_dev, dcbaap + 8 * slotid));
+ xhci_mask64(ldq_le_dma(xhci->as, dcbaap + 8 * slotid));
xhci_dma_read_u32s(xhci, slot->ctx, slot_ctx, sizeof(slot_ctx));
slot->uport = xhci_lookup_uport(xhci, slot_ctx);
if (!slot->uport) {
diff --git a/hw/usb/hcd-xhci.h b/hw/usb/hcd-xhci.h
index 2110c03..2570937 100644
--- a/hw/usb/hcd-xhci.h
+++ b/hw/usb/hcd-xhci.h
@@ -190,6 +190,7 @@ struct XHCIState {
USBBus bus;
MemoryRegion mem;
+ AddressSpace *as;
MemoryRegion mem_cap;
MemoryRegion mem_oper;
MemoryRegion mem_runtime;
--
2.7.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v6 2/7] usb/hcd-xhci: Move qemu-xhci device to hcd-xhci-pci.c
2020-09-16 11:41 [PATCH v6 0/7] Make hcd-xhci independent of pci hooks Sai Pavan Boddu
2020-09-16 11:41 ` [PATCH v6 1/7] usb/hcd-xhci: Make dma read/writes hooks pci free Sai Pavan Boddu
@ 2020-09-16 11:41 ` Sai Pavan Boddu
2020-09-16 11:41 ` [PATCH v6 3/7] usb/hcd-xhci: Split pci wrapper for xhci base model Sai Pavan Boddu
` (5 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Sai Pavan Boddu @ 2020-09-16 11:41 UTC (permalink / raw)
To: Peter Maydell, Markus Armbruster,
'Marc-André Lureau', Paolo Bonzini, Gerd Hoffmann,
Edgar Iglesias, Francisco Eduardo Iglesias
Cc: Eduardo Habkost, Vikram Garhwal, qemu-devel, Paul Zimmerman,
Sai Pavan Boddu, Alistair Francis, Ying Fang,
'Philippe Mathieu-Daudé'
Move pci specific devices to new file. This set the environment to move all
pci specific hooks in hcd-xhci.c to hcd-xhci-pci.c.
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
---
hw/usb/Kconfig | 6 +++++
hw/usb/hcd-xhci-pci.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++
hw/usb/hcd-xhci.c | 33 ++------------------------
hw/usb/hcd-xhci.h | 4 ++++
hw/usb/meson.build | 1 +
5 files changed, 79 insertions(+), 31 deletions(-)
create mode 100644 hw/usb/hcd-xhci-pci.c
diff --git a/hw/usb/Kconfig b/hw/usb/Kconfig
index 3fc8fbe..bab582f 100644
--- a/hw/usb/Kconfig
+++ b/hw/usb/Kconfig
@@ -36,6 +36,12 @@ config USB_XHCI
depends on PCI
select USB
+config USB_XHCI_PCI
+ bool
+ default y if PCI_DEVICES
+ depends on PCI
+ select USB_XHCI
+
config USB_XHCI_NEC
bool
default y if PCI_DEVICES
diff --git a/hw/usb/hcd-xhci-pci.c b/hw/usb/hcd-xhci-pci.c
new file mode 100644
index 0000000..1562757
--- /dev/null
+++ b/hw/usb/hcd-xhci-pci.c
@@ -0,0 +1,66 @@
+/*
+ * USB xHCI controller with PCI bus emulation
+ *
+ * SPDX-FileCopyrightText: 2011 Securiforest
+ * SPDX-FileContributor: Hector Martin <hector@marcansoft.com>
+ * SPDX-sourceInfo: Based on usb-ohci.c, emulates Renesas NEC USB 3.0
+ * SPDX-FileCopyrightText: 2020 Xilinx
+ * SPDX-FileContributor: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
+ * SPDX-sourceInfo: Moved the pci specific content for hcd-xhci.c to
+ * hcd-xhci-pci.c
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "qemu/osdep.h"
+#include "hw/pci/pci.h"
+#include "hw/qdev-properties.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/msix.h"
+#include "hcd-xhci.h"
+#include "trace.h"
+#include "qapi/error.h"
+
+static void qemu_xhci_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->vendor_id = PCI_VENDOR_ID_REDHAT;
+ k->device_id = PCI_DEVICE_ID_REDHAT_XHCI;
+ k->revision = 0x01;
+}
+
+static void qemu_xhci_instance_init(Object *obj)
+{
+ XHCIState *xhci = XHCI(obj);
+
+ xhci->msi = ON_OFF_AUTO_OFF;
+ xhci->msix = ON_OFF_AUTO_AUTO;
+ xhci->numintrs = MAXINTRS;
+ xhci->numslots = MAXSLOTS;
+ xhci_set_flag(xhci, XHCI_FLAG_SS_FIRST);
+}
+
+static const TypeInfo qemu_xhci_info = {
+ .name = TYPE_QEMU_XHCI,
+ .parent = TYPE_XHCI,
+ .class_init = qemu_xhci_class_init,
+ .instance_init = qemu_xhci_instance_init,
+};
+
+static void xhci_register_types(void)
+{
+ type_register_static(&qemu_xhci_info);
+}
+
+type_init(xhci_register_types)
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 254cf1e..f927567 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -23,7 +23,6 @@
#include "qemu/timer.h"
#include "qemu/module.h"
#include "qemu/queue.h"
-#include "hw/usb.h"
#include "migration/vmstate.h"
#include "hw/pci/pci.h"
#include "hw/qdev-properties.h"
@@ -429,12 +428,12 @@ static const char *ep_state_name(uint32_t state)
ARRAY_SIZE(ep_state_names));
}
-static bool xhci_get_flag(XHCIState *xhci, enum xhci_flags bit)
+bool xhci_get_flag(XHCIState *xhci, enum xhci_flags bit)
{
return xhci->flags & (1 << bit);
}
-static void xhci_set_flag(XHCIState *xhci, enum xhci_flags bit)
+void xhci_set_flag(XHCIState *xhci, enum xhci_flags bit)
{
xhci->flags |= (1 << bit);
}
@@ -3730,37 +3729,9 @@ static const TypeInfo xhci_info = {
},
};
-static void qemu_xhci_class_init(ObjectClass *klass, void *data)
-{
- PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
- k->vendor_id = PCI_VENDOR_ID_REDHAT;
- k->device_id = PCI_DEVICE_ID_REDHAT_XHCI;
- k->revision = 0x01;
-}
-
-static void qemu_xhci_instance_init(Object *obj)
-{
- XHCIState *xhci = XHCI(obj);
-
- xhci->msi = ON_OFF_AUTO_OFF;
- xhci->msix = ON_OFF_AUTO_AUTO;
- xhci->numintrs = MAXINTRS;
- xhci->numslots = MAXSLOTS;
- xhci_set_flag(xhci, XHCI_FLAG_SS_FIRST);
-}
-
-static const TypeInfo qemu_xhci_info = {
- .name = TYPE_QEMU_XHCI,
- .parent = TYPE_XHCI,
- .class_init = qemu_xhci_class_init,
- .instance_init = qemu_xhci_instance_init,
-};
-
static void xhci_register_types(void)
{
type_register_static(&xhci_info);
- type_register_static(&qemu_xhci_info);
}
type_init(xhci_register_types)
diff --git a/hw/usb/hcd-xhci.h b/hw/usb/hcd-xhci.h
index 2570937..dab3424 100644
--- a/hw/usb/hcd-xhci.h
+++ b/hw/usb/hcd-xhci.h
@@ -23,6 +23,8 @@
#define HW_USB_HCD_XHCI_H
#include "qom/object.h"
+#include "hw/usb.h"
+
#define TYPE_XHCI "base-xhci"
#define TYPE_NEC_XHCI "nec-usb-xhci"
#define TYPE_QEMU_XHCI "qemu-xhci"
@@ -231,4 +233,6 @@ struct XHCIState {
bool nec_quirks;
};
+bool xhci_get_flag(XHCIState *xhci, enum xhci_flags bit);
+void xhci_set_flag(XHCIState *xhci, enum xhci_flags bit);
#endif
diff --git a/hw/usb/meson.build b/hw/usb/meson.build
index b7c7ff2..90dc54f 100644
--- a/hw/usb/meson.build
+++ b/hw/usb/meson.build
@@ -21,6 +21,7 @@ softmmu_ss.add(when: 'CONFIG_USB_EHCI', if_true: files('hcd-ehci.c'))
softmmu_ss.add(when: 'CONFIG_USB_EHCI_PCI', if_true: files('hcd-ehci-pci.c'))
softmmu_ss.add(when: 'CONFIG_USB_EHCI_SYSBUS', if_true: files('hcd-ehci.c', 'hcd-ehci-sysbus.c'))
softmmu_ss.add(when: 'CONFIG_USB_XHCI', if_true: files('hcd-xhci.c'))
+softmmu_ss.add(when: 'CONFIG_USB_XHCI_PCI', if_true: files('hcd-xhci-pci.c'))
softmmu_ss.add(when: 'CONFIG_USB_XHCI_NEC', if_true: files('hcd-xhci-nec.c'))
softmmu_ss.add(when: 'CONFIG_USB_MUSB', if_true: files('hcd-musb.c'))
softmmu_ss.add(when: 'CONFIG_USB_DWC2', if_true: files('hcd-dwc2.c'))
--
2.7.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v6 3/7] usb/hcd-xhci: Split pci wrapper for xhci base model
2020-09-16 11:41 [PATCH v6 0/7] Make hcd-xhci independent of pci hooks Sai Pavan Boddu
2020-09-16 11:41 ` [PATCH v6 1/7] usb/hcd-xhci: Make dma read/writes hooks pci free Sai Pavan Boddu
2020-09-16 11:41 ` [PATCH v6 2/7] usb/hcd-xhci: Move qemu-xhci device to hcd-xhci-pci.c Sai Pavan Boddu
@ 2020-09-16 11:41 ` Sai Pavan Boddu
2020-09-16 11:41 ` [PATCH v6 4/7] usb: hcd-xhci-sysbus: Attach xhci to sysbus device Sai Pavan Boddu
` (4 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Sai Pavan Boddu @ 2020-09-16 11:41 UTC (permalink / raw)
To: Peter Maydell, Markus Armbruster,
'Marc-André Lureau', Paolo Bonzini, Gerd Hoffmann,
Edgar Iglesias, Francisco Eduardo Iglesias
Cc: Eduardo Habkost, Vikram Garhwal, qemu-devel, Paul Zimmerman,
Sai Pavan Boddu, Alistair Francis, Ying Fang,
'Philippe Mathieu-Daudé'
This patch sets the base to use xhci as sysbus model, for which pci
specific hooks are moved to hcd-xhci-pci.c. As a part of this requirment
msi/msix interrupts handling is moved under XHCIPCIState. Made required
changes for qemu-xhci-nec.
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
fixup
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
---
hw/usb/hcd-xhci-nec.c | 18 ++---
hw/usb/hcd-xhci-pci.c | 188 +++++++++++++++++++++++++++++++++++++++++++--
hw/usb/hcd-xhci-pci.h | 45 +++++++++++
hw/usb/hcd-xhci.c | 205 ++++++++++----------------------------------------
hw/usb/hcd-xhci.h | 16 ++--
5 files changed, 285 insertions(+), 187 deletions(-)
create mode 100644 hw/usb/hcd-xhci-pci.h
diff --git a/hw/usb/hcd-xhci-nec.c b/hw/usb/hcd-xhci-nec.c
index e6a5a22..2efa6fa 100644
--- a/hw/usb/hcd-xhci-nec.c
+++ b/hw/usb/hcd-xhci-nec.c
@@ -25,17 +25,17 @@
#include "hw/pci/pci.h"
#include "hw/qdev-properties.h"
-#include "hcd-xhci.h"
+#include "hcd-xhci-pci.h"
static Property nec_xhci_properties[] = {
- DEFINE_PROP_ON_OFF_AUTO("msi", XHCIState, msi, ON_OFF_AUTO_AUTO),
- DEFINE_PROP_ON_OFF_AUTO("msix", XHCIState, msix, ON_OFF_AUTO_AUTO),
- DEFINE_PROP_BIT("superspeed-ports-first",
- XHCIState, flags, XHCI_FLAG_SS_FIRST, true),
- DEFINE_PROP_BIT("force-pcie-endcap", XHCIState, flags,
+ DEFINE_PROP_ON_OFF_AUTO("msi", XHCIPciState, msi, ON_OFF_AUTO_AUTO),
+ DEFINE_PROP_ON_OFF_AUTO("msix", XHCIPciState, msix, ON_OFF_AUTO_AUTO),
+ DEFINE_PROP_BIT("superspeed-ports-first", XHCIPciState,
+ xhci.flags, XHCI_FLAG_SS_FIRST, true),
+ DEFINE_PROP_BIT("force-pcie-endcap", XHCIPciState, xhci.flags,
XHCI_FLAG_FORCE_PCIE_ENDCAP, false),
- DEFINE_PROP_UINT32("intrs", XHCIState, numintrs, MAXINTRS),
- DEFINE_PROP_UINT32("slots", XHCIState, numslots, MAXSLOTS),
+ DEFINE_PROP_UINT32("intrs", XHCIPciState, xhci.numintrs, MAXINTRS),
+ DEFINE_PROP_UINT32("slots", XHCIPciState, xhci.numslots, MAXSLOTS),
DEFINE_PROP_END_OF_LIST(),
};
@@ -52,7 +52,7 @@ static void nec_xhci_class_init(ObjectClass *klass, void *data)
static const TypeInfo nec_xhci_info = {
.name = TYPE_NEC_XHCI,
- .parent = TYPE_XHCI,
+ .parent = TYPE_XHCI_PCI,
.class_init = nec_xhci_class_init,
};
diff --git a/hw/usb/hcd-xhci-pci.c b/hw/usb/hcd-xhci-pci.c
index 1562757..15d288c 100644
--- a/hw/usb/hcd-xhci-pci.c
+++ b/hw/usb/hcd-xhci-pci.c
@@ -25,12 +25,188 @@
#include "qemu/osdep.h"
#include "hw/pci/pci.h"
#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
#include "hw/pci/msi.h"
#include "hw/pci/msix.h"
-#include "hcd-xhci.h"
+#include "hcd-xhci-pci.h"
#include "trace.h"
#include "qapi/error.h"
+#define OFF_MSIX_TABLE 0x3000
+#define OFF_MSIX_PBA 0x3800
+
+static void xhci_pci_intr_update(XHCIState *xhci, int n, bool enable)
+{
+ XHCIPciState *s = container_of(xhci, XHCIPciState, xhci);
+ PCIDevice *pci_dev = PCI_DEVICE(s);
+
+ if (!msix_enabled(pci_dev)) {
+ return;
+ }
+ if (enable == !!s->msix_used[n]) {
+ return;
+ }
+ if (enable) {
+ trace_usb_xhci_irq_msix_use(n);
+ msix_vector_use(pci_dev, n);
+ s->msix_used[n] = 1;
+ } else {
+ trace_usb_xhci_irq_msix_unuse(n);
+ msix_vector_unuse(pci_dev, n);
+ s->msix_used[n] = 0;
+ }
+}
+
+static void xhci_pci_intr_raise(XHCIState *xhci, int n, bool level)
+{
+ XHCIPciState *s = container_of(xhci, XHCIPciState, xhci);
+ PCIDevice *pci_dev = PCI_DEVICE(s);
+
+ if (n == 0 &&
+ !(msix_enabled(pci_dev) ||
+ msi_enabled(pci_dev))) {
+ pci_set_irq(pci_dev, level);
+ }
+ if (msix_enabled(pci_dev)) {
+ msix_notify(pci_dev, n);
+ return;
+ }
+
+ if (msi_enabled(pci_dev)) {
+ msi_notify(pci_dev, n);
+ return;
+ }
+}
+
+static void xhci_pci_reset(DeviceState *dev)
+{
+ XHCIPciState *s = XHCI_PCI(dev);
+
+ device_legacy_reset(DEVICE(&s->xhci));
+}
+
+static void usb_xhci_pci_realize(struct PCIDevice *dev, Error **errp)
+{
+ int ret;
+ Error *err = NULL;
+ XHCIPciState *s = XHCI_PCI(dev);
+
+ dev->config[PCI_CLASS_PROG] = 0x30; /* xHCI */
+ dev->config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin 1 */
+ dev->config[PCI_CACHE_LINE_SIZE] = 0x10;
+ dev->config[0x60] = 0x30; /* release number */
+
+ object_property_set_link(OBJECT(&s->xhci), "host", OBJECT(s), NULL);
+ s->xhci.intr_update = xhci_pci_intr_update;
+ s->xhci.intr_raise = xhci_pci_intr_raise;
+ object_property_set_bool(OBJECT(&s->xhci), "realized", true, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ if (strcmp(object_get_typename(OBJECT(dev)), TYPE_NEC_XHCI) == 0) {
+ s->xhci.nec_quirks = true;
+ }
+
+ if (s->msi != ON_OFF_AUTO_OFF) {
+ ret = msi_init(dev, 0x70, s->xhci.numintrs, true, false, &err);
+ /*
+ * Any error other than -ENOTSUP(board's MSI support is broken)
+ * is a programming error
+ */
+ assert(!ret || ret == -ENOTSUP);
+ if (ret && s->msi == ON_OFF_AUTO_ON) {
+ /* Can't satisfy user's explicit msi=on request, fail */
+ error_append_hint(&err, "You have to use msi=auto (default) or "
+ "msi=off with this machine type.\n");
+ error_propagate(errp, err);
+ return;
+ }
+ assert(!err || s->msi == ON_OFF_AUTO_AUTO);
+ /* With msi=auto, we fall back to MSI off silently */
+ error_free(err);
+ }
+ pci_register_bar(dev, 0,
+ PCI_BASE_ADDRESS_SPACE_MEMORY |
+ PCI_BASE_ADDRESS_MEM_TYPE_64,
+ &s->xhci.mem);
+
+ if (pci_bus_is_express(pci_get_bus(dev)) ||
+ xhci_get_flag(&s->xhci, XHCI_FLAG_FORCE_PCIE_ENDCAP)) {
+ ret = pcie_endpoint_cap_init(dev, 0xa0);
+ assert(ret > 0);
+ }
+
+ if (s->msix != ON_OFF_AUTO_OFF) {
+ /* TODO check for errors, and should fail when msix=on */
+ msix_init(dev, s->xhci.numintrs,
+ &s->xhci.mem, 0, OFF_MSIX_TABLE,
+ &s->xhci.mem, 0, OFF_MSIX_PBA,
+ 0x90, NULL);
+ }
+ s->xhci.as = pci_get_address_space(dev);
+}
+
+static void usb_xhci_pci_exit(PCIDevice *dev)
+{
+ XHCIPciState *s = XHCI_PCI(dev);
+ /* destroy msix memory region */
+ if (dev->msix_table && dev->msix_pba
+ && dev->msix_entry_used) {
+ msix_uninit(dev, &s->xhci.mem, &s->xhci.mem);
+ }
+}
+
+static const VMStateDescription vmstate_xhci_pci = {
+ .name = "xhci-pci",
+ .version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_PCI_DEVICE(parent_obj, XHCIPciState),
+ VMSTATE_MSIX(parent_obj, XHCIPciState),
+ VMSTATE_UINT8_ARRAY(msix_used, XHCIPciState, MAXINTRS),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void xhci_instance_init(Object *obj)
+{
+ XHCIPciState *s = XHCI_PCI(obj);
+ /*
+ * QEMU_PCI_CAP_EXPRESS initialization does not depend on QEMU command
+ * line, therefore, no need to wait to realize like other devices
+ */
+ PCI_DEVICE(obj)->cap_present |= QEMU_PCI_CAP_EXPRESS;
+ object_initialize_child(obj, "xhci-core", &s->xhci, TYPE_XHCI);
+ qdev_alias_all_properties(DEVICE(&s->xhci), obj);
+}
+
+static void xhci_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = xhci_pci_reset;
+ dc->vmsd = &vmstate_xhci_pci;
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
+ k->realize = usb_xhci_pci_realize;
+ k->exit = usb_xhci_pci_exit;
+ k->class_id = PCI_CLASS_SERIAL_USB;
+}
+
+static const TypeInfo xhci_pci_info = {
+ .name = TYPE_XHCI_PCI,
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(XHCIPciState),
+ .class_init = xhci_class_init,
+ .instance_init = xhci_instance_init,
+ .abstract = true,
+ .interfaces = (InterfaceInfo[]) {
+ { INTERFACE_PCIE_DEVICE },
+ { INTERFACE_CONVENTIONAL_PCI_DEVICE },
+ { }
+ },
+};
+
static void qemu_xhci_class_init(ObjectClass *klass, void *data)
{
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
@@ -42,10 +218,11 @@ static void qemu_xhci_class_init(ObjectClass *klass, void *data)
static void qemu_xhci_instance_init(Object *obj)
{
- XHCIState *xhci = XHCI(obj);
+ XHCIPciState *s = XHCI_PCI(obj);
+ XHCIState *xhci = &s->xhci;
- xhci->msi = ON_OFF_AUTO_OFF;
- xhci->msix = ON_OFF_AUTO_AUTO;
+ s->msi = ON_OFF_AUTO_OFF;
+ s->msix = ON_OFF_AUTO_AUTO;
xhci->numintrs = MAXINTRS;
xhci->numslots = MAXSLOTS;
xhci_set_flag(xhci, XHCI_FLAG_SS_FIRST);
@@ -53,13 +230,14 @@ static void qemu_xhci_instance_init(Object *obj)
static const TypeInfo qemu_xhci_info = {
.name = TYPE_QEMU_XHCI,
- .parent = TYPE_XHCI,
+ .parent = TYPE_XHCI_PCI,
.class_init = qemu_xhci_class_init,
.instance_init = qemu_xhci_instance_init,
};
static void xhci_register_types(void)
{
+ type_register_static(&xhci_pci_info);
type_register_static(&qemu_xhci_info);
}
diff --git a/hw/usb/hcd-xhci-pci.h b/hw/usb/hcd-xhci-pci.h
new file mode 100644
index 0000000..e7c005e
--- /dev/null
+++ b/hw/usb/hcd-xhci-pci.h
@@ -0,0 +1,45 @@
+/*
+ * USB xHCI controller emulation
+ *
+ * Copyright (c) 2011 Securiforest
+ * Date: 2011-05-11 ; Author: Hector Martin <hector@marcansoft.com>
+ * Based on usb-ohci.c, emulates Renesas NEC USB 3.0
+ * Date: 2020-01-1; Author: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
+ * PCI hooks are moved from XHCIState to XHCIPciState
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_USB_HCD_XHCI_PCI_H
+#define HW_USB_HCD_XHCI_PCI_H
+
+#include "hw/usb.h"
+#include "hcd-xhci.h"
+
+#define TYPE_XHCI_PCI "pci-xhci"
+#define XHCI_PCI(obj) \
+ OBJECT_CHECK(XHCIPciState, (obj), TYPE_XHCI_PCI)
+
+
+typedef struct XHCIPciState {
+ /*< private >*/
+ PCIDevice parent_obj;
+ /*< public >*/
+ XHCIState xhci;
+ OnOffAuto msi;
+ OnOffAuto msix;
+ uint8_t msix_used[MAXINTRS];
+} XHCIPciState;
+
+#endif
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index f927567..6a03edd 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -24,10 +24,7 @@
#include "qemu/module.h"
#include "qemu/queue.h"
#include "migration/vmstate.h"
-#include "hw/pci/pci.h"
#include "hw/qdev-properties.h"
-#include "hw/pci/msi.h"
-#include "hw/pci/msix.h"
#include "trace.h"
#include "qapi/error.h"
@@ -56,8 +53,6 @@
#define OFF_OPER LEN_CAP
#define OFF_RUNTIME 0x1000
#define OFF_DOORBELL 0x2000
-#define OFF_MSIX_TABLE 0x3000
-#define OFF_MSIX_PBA 0x3800
/* must be power of 2 */
#define LEN_REGS 0x4000
@@ -547,54 +542,28 @@ static XHCIPort *xhci_lookup_port(XHCIState *xhci, struct USBPort *uport)
return &xhci->ports[index];
}
-static void xhci_intx_update(XHCIState *xhci)
+static void xhci_intr_update(XHCIState *xhci, int v)
{
- PCIDevice *pci_dev = PCI_DEVICE(xhci);
int level = 0;
- if (msix_enabled(pci_dev) ||
- msi_enabled(pci_dev)) {
- return;
- }
-
- if (xhci->intr[0].iman & IMAN_IP &&
- xhci->intr[0].iman & IMAN_IE &&
- xhci->usbcmd & USBCMD_INTE) {
- level = 1;
- }
-
- trace_usb_xhci_irq_intx(level);
- pci_set_irq(pci_dev, level);
-}
-
-static void xhci_msix_update(XHCIState *xhci, int v)
-{
- PCIDevice *pci_dev = PCI_DEVICE(xhci);
- bool enabled;
-
- if (!msix_enabled(pci_dev)) {
- return;
- }
-
- enabled = xhci->intr[v].iman & IMAN_IE;
- if (enabled == xhci->intr[v].msix_used) {
- return;
+ if (v == 0) {
+ if (xhci->intr[0].iman & IMAN_IP &&
+ xhci->intr[0].iman & IMAN_IE &&
+ xhci->usbcmd & USBCMD_INTE) {
+ level = 1;
+ }
+ if (xhci->intr_raise) {
+ xhci->intr_raise(xhci, 0, level);
+ }
}
-
- if (enabled) {
- trace_usb_xhci_irq_msix_use(v);
- msix_vector_use(pci_dev, v);
- xhci->intr[v].msix_used = true;
- } else {
- trace_usb_xhci_irq_msix_unuse(v);
- msix_vector_unuse(pci_dev, v);
- xhci->intr[v].msix_used = false;
+ if (xhci->intr_update) {
+ xhci->intr_update(xhci, v,
+ xhci->intr[v].iman & IMAN_IE);
}
}
static void xhci_intr_raise(XHCIState *xhci, int v)
{
- PCIDevice *pci_dev = PCI_DEVICE(xhci);
bool pending = (xhci->intr[v].erdp_low & ERDP_EHB);
xhci->intr[v].erdp_low |= ERDP_EHB;
@@ -611,22 +580,8 @@ static void xhci_intr_raise(XHCIState *xhci, int v)
if (!(xhci->usbcmd & USBCMD_INTE)) {
return;
}
-
- if (msix_enabled(pci_dev)) {
- trace_usb_xhci_irq_msix(v);
- msix_notify(pci_dev, v);
- return;
- }
-
- if (msi_enabled(pci_dev)) {
- trace_usb_xhci_irq_msi(v);
- msi_notify(pci_dev, v);
- return;
- }
-
- if (v == 0) {
- trace_usb_xhci_irq_intx(1);
- pci_irq_assert(pci_dev);
+ if (xhci->intr_raise) {
+ xhci->intr_raise(xhci, v, true);
}
}
@@ -2717,7 +2672,6 @@ static void xhci_reset(DeviceState *dev)
xhci->intr[i].erstba_high = 0;
xhci->intr[i].erdp_low = 0;
xhci->intr[i].erdp_high = 0;
- xhci->intr[i].msix_used = 0;
xhci->intr[i].er_ep_idx = 0;
xhci->intr[i].er_pcs = 1;
@@ -2939,8 +2893,7 @@ static uint64_t xhci_oper_read(void *ptr, hwaddr reg, unsigned size)
static void xhci_oper_write(void *ptr, hwaddr reg,
uint64_t val, unsigned size)
{
- XHCIState *xhci = ptr;
- DeviceState *d = DEVICE(ptr);
+ XHCIState *xhci = XHCI(ptr);
trace_usb_xhci_oper_write(reg, val);
@@ -2962,15 +2915,15 @@ static void xhci_oper_write(void *ptr, hwaddr reg,
xhci->usbcmd = val & 0xc0f;
xhci_mfwrap_update(xhci);
if (val & USBCMD_HCRST) {
- xhci_reset(d);
+ xhci_reset(DEVICE(xhci));
}
- xhci_intx_update(xhci);
+ xhci_intr_update(xhci, 0);
break;
case 0x04: /* USBSTS */
/* these bits are write-1-to-clear */
xhci->usbsts &= ~(val & (USBSTS_HSE|USBSTS_EINT|USBSTS_PCD|USBSTS_SRE));
- xhci_intx_update(xhci);
+ xhci_intr_update(xhci, 0);
break;
case 0x14: /* DNCTRL */
@@ -3073,10 +3026,7 @@ static void xhci_runtime_write(void *ptr, hwaddr reg,
}
intr->iman &= ~IMAN_IE;
intr->iman |= val & IMAN_IE;
- if (v == 0) {
- xhci_intx_update(xhci);
- }
- xhci_msix_update(xhci, v);
+ xhci_intr_update(xhci, v);
break;
case 0x04: /* IMOD */
intr->imod = val;
@@ -3321,7 +3271,6 @@ static USBBusOps xhci_bus_ops = {
static void usb_xhci_init(XHCIState *xhci)
{
- DeviceState *dev = DEVICE(xhci);
XHCIPort *port;
unsigned int i, usbports, speedmask;
@@ -3336,7 +3285,7 @@ static void usb_xhci_init(XHCIState *xhci)
usbports = MAX(xhci->numports_2, xhci->numports_3);
xhci->numports = xhci->numports_2 + xhci->numports_3;
- usb_bus_new(&xhci->bus, sizeof(xhci->bus), &xhci_bus_ops, dev);
+ usb_bus_new(&xhci->bus, sizeof(xhci->bus), &xhci_bus_ops, xhci->hostOpaque);
for (i = 0; i < usbports; i++) {
speedmask = 0;
@@ -3376,21 +3325,12 @@ static void usb_xhci_init(XHCIState *xhci)
}
}
-static void usb_xhci_realize(struct PCIDevice *dev, Error **errp)
+static void usb_xhci_realize(DeviceState *dev, Error **errp)
{
- int i, ret;
- Error *err = NULL;
+ int i;
XHCIState *xhci = XHCI(dev);
- dev->config[PCI_CLASS_PROG] = 0x30; /* xHCI */
- dev->config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin 1 */
- dev->config[PCI_CACHE_LINE_SIZE] = 0x10;
- dev->config[0x60] = 0x30; /* release number */
-
- if (strcmp(object_get_typename(OBJECT(dev)), TYPE_NEC_XHCI) == 0) {
- xhci->nec_quirks = true;
- }
if (xhci->numintrs > MAXINTRS) {
xhci->numintrs = MAXINTRS;
}
@@ -3412,36 +3352,18 @@ static void usb_xhci_realize(struct PCIDevice *dev, Error **errp)
xhci->max_pstreams_mask = 0;
}
- if (xhci->msi != ON_OFF_AUTO_OFF) {
- ret = msi_init(dev, 0x70, xhci->numintrs, true, false, &err);
- /* Any error other than -ENOTSUP(board's MSI support is broken)
- * is a programming error */
- assert(!ret || ret == -ENOTSUP);
- if (ret && xhci->msi == ON_OFF_AUTO_ON) {
- /* Can't satisfy user's explicit msi=on request, fail */
- error_append_hint(&err, "You have to use msi=auto (default) or "
- "msi=off with this machine type.\n");
- error_propagate(errp, err);
- return;
- }
- assert(!err || xhci->msi == ON_OFF_AUTO_AUTO);
- /* With msi=auto, we fall back to MSI off silently */
- error_free(err);
- }
-
usb_xhci_init(xhci);
- xhci->as = pci_get_address_space(dev);
xhci->mfwrap_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, xhci_mfwrap_timer, xhci);
- memory_region_init(&xhci->mem, OBJECT(xhci), "xhci", LEN_REGS);
- memory_region_init_io(&xhci->mem_cap, OBJECT(xhci), &xhci_cap_ops, xhci,
+ memory_region_init(&xhci->mem, OBJECT(dev), "xhci", LEN_REGS);
+ memory_region_init_io(&xhci->mem_cap, OBJECT(dev), &xhci_cap_ops, xhci,
"capabilities", LEN_CAP);
- memory_region_init_io(&xhci->mem_oper, OBJECT(xhci), &xhci_oper_ops, xhci,
+ memory_region_init_io(&xhci->mem_oper, OBJECT(dev), &xhci_oper_ops, xhci,
"operational", 0x400);
- memory_region_init_io(&xhci->mem_runtime, OBJECT(xhci), &xhci_runtime_ops, xhci,
- "runtime", LEN_RUNTIME);
- memory_region_init_io(&xhci->mem_doorbell, OBJECT(xhci), &xhci_doorbell_ops, xhci,
- "doorbell", LEN_DOORBELL);
+ memory_region_init_io(&xhci->mem_runtime, OBJECT(dev), &xhci_runtime_ops,
+ xhci, "runtime", LEN_RUNTIME);
+ memory_region_init_io(&xhci->mem_doorbell, OBJECT(dev), &xhci_doorbell_ops,
+ xhci, "doorbell", LEN_DOORBELL);
memory_region_add_subregion(&xhci->mem, 0, &xhci->mem_cap);
memory_region_add_subregion(&xhci->mem, OFF_OPER, &xhci->mem_oper);
@@ -3452,31 +3374,13 @@ static void usb_xhci_realize(struct PCIDevice *dev, Error **errp)
XHCIPort *port = &xhci->ports[i];
uint32_t offset = OFF_OPER + 0x400 + 0x10 * i;
port->xhci = xhci;
- memory_region_init_io(&port->mem, OBJECT(xhci), &xhci_port_ops, port,
+ memory_region_init_io(&port->mem, OBJECT(dev), &xhci_port_ops, port,
port->name, 0x10);
memory_region_add_subregion(&xhci->mem, offset, &port->mem);
}
-
- pci_register_bar(dev, 0,
- PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64,
- &xhci->mem);
-
- if (pci_bus_is_express(pci_get_bus(dev)) ||
- xhci_get_flag(xhci, XHCI_FLAG_FORCE_PCIE_ENDCAP)) {
- ret = pcie_endpoint_cap_init(dev, 0xa0);
- assert(ret > 0);
- }
-
- if (xhci->msix != ON_OFF_AUTO_OFF) {
- /* TODO check for errors, and should fail when msix=on */
- msix_init(dev, xhci->numintrs,
- &xhci->mem, 0, OFF_MSIX_TABLE,
- &xhci->mem, 0, OFF_MSIX_PBA,
- 0x90, NULL);
- }
}
-static void usb_xhci_exit(PCIDevice *dev)
+static void usb_xhci_unrealize(DeviceState *dev)
{
int i;
XHCIState *xhci = XHCI(dev);
@@ -3503,19 +3407,12 @@ static void usb_xhci_exit(PCIDevice *dev)
memory_region_del_subregion(&xhci->mem, &port->mem);
}
- /* destroy msix memory region */
- if (dev->msix_table && dev->msix_pba
- && dev->msix_entry_used) {
- msix_uninit(dev, &xhci->mem, &xhci->mem);
- }
-
usb_bus_release(&xhci->bus);
}
static int usb_xhci_post_load(void *opaque, int version_id)
{
XHCIState *xhci = opaque;
- PCIDevice *pci_dev = PCI_DEVICE(xhci);
XHCISlot *slot;
XHCIEPContext *epctx;
dma_addr_t dcbaap, pctx;
@@ -3561,11 +3458,7 @@ static int usb_xhci_post_load(void *opaque, int version_id)
}
for (intr = 0; intr < xhci->numintrs; intr++) {
- if (xhci->intr[intr].msix_used) {
- msix_vector_use(pci_dev, intr);
- } else {
- msix_vector_unuse(pci_dev, intr);
- }
+ xhci_intr_update(xhci, intr);
}
return 0;
@@ -3634,7 +3527,6 @@ static const VMStateDescription vmstate_xhci_intr = {
VMSTATE_UINT32(erdp_high, XHCIInterrupter),
/* state */
- VMSTATE_BOOL(msix_used, XHCIInterrupter),
VMSTATE_BOOL(er_pcs, XHCIInterrupter),
VMSTATE_UINT64(er_start, XHCIInterrupter),
VMSTATE_UINT32(er_size, XHCIInterrupter),
@@ -3657,9 +3549,6 @@ static const VMStateDescription vmstate_xhci = {
.version_id = 1,
.post_load = usb_xhci_post_load,
.fields = (VMStateField[]) {
- VMSTATE_PCI_DEVICE(parent_obj, XHCIState),
- VMSTATE_MSIX(parent_obj, XHCIState),
-
VMSTATE_STRUCT_VARRAY_UINT32(ports, XHCIState, numports, 1,
vmstate_xhci_port, XHCIPort),
VMSTATE_STRUCT_VARRAY_UINT32(slots, XHCIState, numslots, 1,
@@ -3691,42 +3580,28 @@ static Property xhci_properties[] = {
XHCI_FLAG_ENABLE_STREAMS, true),
DEFINE_PROP_UINT32("p2", XHCIState, numports_2, 4),
DEFINE_PROP_UINT32("p3", XHCIState, numports_3, 4),
+ DEFINE_PROP_LINK("host", XHCIState, hostOpaque, TYPE_DEVICE,
+ DeviceState *),
DEFINE_PROP_END_OF_LIST(),
};
-static void xhci_instance_init(Object *obj)
-{
- /* QEMU_PCI_CAP_EXPRESS initialization does not depend on QEMU command
- * line, therefore, no need to wait to realize like other devices */
- PCI_DEVICE(obj)->cap_present |= QEMU_PCI_CAP_EXPRESS;
-}
-
static void xhci_class_init(ObjectClass *klass, void *data)
{
- PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->realize = usb_xhci_realize;
+ dc->unrealize = usb_xhci_unrealize;
+ dc->reset = xhci_reset;
dc->vmsd = &vmstate_xhci;
device_class_set_props(dc, xhci_properties);
- dc->reset = xhci_reset;
- set_bit(DEVICE_CATEGORY_USB, dc->categories);
- k->realize = usb_xhci_realize;
- k->exit = usb_xhci_exit;
- k->class_id = PCI_CLASS_SERIAL_USB;
+ dc->user_creatable = false;
}
static const TypeInfo xhci_info = {
.name = TYPE_XHCI,
- .parent = TYPE_PCI_DEVICE,
+ .parent = TYPE_DEVICE,
.instance_size = sizeof(XHCIState),
.class_init = xhci_class_init,
- .instance_init = xhci_instance_init,
- .abstract = true,
- .interfaces = (InterfaceInfo[]) {
- { INTERFACE_PCIE_DEVICE },
- { INTERFACE_CONVENTIONAL_PCI_DEVICE },
- { }
- },
};
static void xhci_register_types(void)
diff --git a/hw/usb/hcd-xhci.h b/hw/usb/hcd-xhci.h
index dab3424..525291b 100644
--- a/hw/usb/hcd-xhci.h
+++ b/hw/usb/hcd-xhci.h
@@ -24,6 +24,7 @@
#include "qom/object.h"
#include "hw/usb.h"
+#include "sysemu/dma.h"
#define TYPE_XHCI "base-xhci"
#define TYPE_NEC_XHCI "nec-usb-xhci"
@@ -171,7 +172,7 @@ typedef struct XHCIInterrupter {
uint32_t erdp_low;
uint32_t erdp_high;
- bool msix_used, er_pcs;
+ bool er_pcs;
dma_addr_t er_start;
uint32_t er_size;
@@ -185,10 +186,8 @@ typedef struct XHCIInterrupter {
} XHCIInterrupter;
-struct XHCIState {
- /*< private >*/
- PCIDevice parent_obj;
- /*< public >*/
+typedef struct XHCIState {
+ DeviceState parent;
USBBus bus;
MemoryRegion mem;
@@ -205,8 +204,9 @@ struct XHCIState {
uint32_t numslots;
uint32_t flags;
uint32_t max_pstreams_mask;
- OnOffAuto msi;
- OnOffAuto msix;
+ void (*intr_update)(XHCIState *s, int n, bool enable);
+ void (*intr_raise)(XHCIState *s, int n, bool level);
+ DeviceState *hostOpaque;
/* Operational Registers */
uint32_t usbcmd;
@@ -231,7 +231,7 @@ struct XHCIState {
XHCIRing cmd_ring;
bool nec_quirks;
-};
+} XHCIState;
bool xhci_get_flag(XHCIState *xhci, enum xhci_flags bit);
void xhci_set_flag(XHCIState *xhci, enum xhci_flags bit);
--
2.7.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v6 4/7] usb: hcd-xhci-sysbus: Attach xhci to sysbus device
2020-09-16 11:41 [PATCH v6 0/7] Make hcd-xhci independent of pci hooks Sai Pavan Boddu
` (2 preceding siblings ...)
2020-09-16 11:41 ` [PATCH v6 3/7] usb/hcd-xhci: Split pci wrapper for xhci base model Sai Pavan Boddu
@ 2020-09-16 11:41 ` Sai Pavan Boddu
2020-09-16 11:41 ` [PATCH v6 5/7] misc: Add versal-usb2-ctrl-regs module Sai Pavan Boddu
` (3 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Sai Pavan Boddu @ 2020-09-16 11:41 UTC (permalink / raw)
To: Peter Maydell, Markus Armbruster,
'Marc-André Lureau', Paolo Bonzini, Gerd Hoffmann,
Edgar Iglesias, Francisco Eduardo Iglesias
Cc: Eduardo Habkost, Vikram Garhwal, qemu-devel, Paul Zimmerman,
Sai Pavan Boddu, Alistair Francis, Ying Fang,
'Philippe Mathieu-Daudé'
Use XHCI as sysbus device, add memory region property to get the
address space instance for dma read/write.
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
---
hw/usb/Kconfig | 5 +++
hw/usb/hcd-xhci-sysbus.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++
hw/usb/hcd-xhci-sysbus.h | 32 ++++++++++++++++
hw/usb/hcd-xhci.h | 1 +
hw/usb/meson.build | 1 +
5 files changed, 138 insertions(+)
create mode 100644 hw/usb/hcd-xhci-sysbus.c
create mode 100644 hw/usb/hcd-xhci-sysbus.h
diff --git a/hw/usb/Kconfig b/hw/usb/Kconfig
index bab582f..4dd2ba9 100644
--- a/hw/usb/Kconfig
+++ b/hw/usb/Kconfig
@@ -48,6 +48,11 @@ config USB_XHCI_NEC
depends on PCI
select USB_XHCI
+config USB_XHCI_SYSBUS
+ bool
+ default y if USB_XHCI
+ select USB
+
config USB_MUSB
bool
select USB
diff --git a/hw/usb/hcd-xhci-sysbus.c b/hw/usb/hcd-xhci-sysbus.c
new file mode 100644
index 0000000..d5b4656
--- /dev/null
+++ b/hw/usb/hcd-xhci-sysbus.c
@@ -0,0 +1,99 @@
+/*
+ * USB xHCI controller for system-bus interface
+ * Based on hcd-echi-sysbus.c
+
+ * SPDX-FileCopyrightText: 2020 Xilinx
+ * SPDX-FileContributor: Author: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "qemu/osdep.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+#include "qapi/error.h"
+#include "hcd-xhci-sysbus.h"
+#include "hw/irq.h"
+
+static void xhci_sysbus_intr_raise(XHCIState *xhci, int n, bool level)
+{
+ XHCISysbusState *s = container_of(xhci, XHCISysbusState, xhci);
+
+ qemu_set_irq(s->irq[n], level);
+}
+
+void xhci_sysbus_reset(DeviceState *dev)
+{
+ XHCISysbusState *s = XHCI_SYSBUS(dev);
+
+ device_legacy_reset(DEVICE(&s->xhci));
+}
+
+static void xhci_sysbus_realize(DeviceState *dev, Error **errp)
+{
+ XHCISysbusState *s = XHCI_SYSBUS(dev);
+ Error *err = NULL;
+
+ object_property_set_link(OBJECT(&s->xhci), "host", OBJECT(s), NULL);
+ object_property_set_bool(OBJECT(&s->xhci), "realized", true, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ s->irq = g_new0(qemu_irq, s->xhci.numintrs);
+ qdev_init_gpio_out_named(dev, s->irq, SYSBUS_DEVICE_GPIO_IRQ,
+ s->xhci.numintrs);
+ if (s->xhci.dma_mr) {
+ s->xhci.as = g_malloc0(sizeof(AddressSpace));
+ address_space_init(s->xhci.as, s->xhci.dma_mr, NULL);
+ } else {
+ s->xhci.as = &address_space_memory;
+ }
+
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->xhci.mem);
+}
+
+static void xhci_sysbus_instance_init(Object *obj)
+{
+ XHCISysbusState *s = XHCI_SYSBUS(obj);
+
+ object_initialize_child(obj, "xhci-core", &s->xhci, TYPE_XHCI);
+ qdev_alias_all_properties(DEVICE(&s->xhci), obj);
+
+ object_property_add_link(obj, "dma", TYPE_MEMORY_REGION,
+ (Object **)&s->xhci.dma_mr,
+ qdev_prop_allow_set_link_before_realize,
+ OBJ_PROP_LINK_STRONG);
+ s->xhci.intr_update = NULL;
+ s->xhci.intr_raise = xhci_sysbus_intr_raise;
+}
+
+static Property xhci_sysbus_props[] = {
+ DEFINE_PROP_UINT32("intrs", XHCISysbusState, xhci.numintrs, MAXINTRS),
+ DEFINE_PROP_UINT32("slots", XHCISysbusState, xhci.numslots, MAXSLOTS),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void xhci_sysbus_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = xhci_sysbus_reset;
+ dc->realize = xhci_sysbus_realize;
+ device_class_set_props(dc, xhci_sysbus_props);
+}
+
+static const TypeInfo xhci_sysbus_info = {
+ .name = TYPE_XHCI_SYSBUS,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(XHCISysbusState),
+ .class_init = xhci_sysbus_class_init,
+ .instance_init = xhci_sysbus_instance_init
+};
+
+static void xhci_sysbus_register_types(void)
+{
+ type_register_static(&xhci_sysbus_info);
+}
+
+type_init(xhci_sysbus_register_types);
diff --git a/hw/usb/hcd-xhci-sysbus.h b/hw/usb/hcd-xhci-sysbus.h
new file mode 100644
index 0000000..a308753
--- /dev/null
+++ b/hw/usb/hcd-xhci-sysbus.h
@@ -0,0 +1,32 @@
+/*
+ * USB xHCI controller for system-bus interface
+ *
+ * SPDX-FileCopyrightText: 2020 Xilinx
+ * SPDX-FileContributor: Author: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
+ * SPDX-sourceInfo: Based on hcd-echi-sysbus
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_USB_HCD_XHCI_SYSBUS_H
+#define HW_USB_HCD_XHCI_SYSBUS_H
+
+#include "hw/usb.h"
+#include "hcd-xhci.h"
+#include "hw/sysbus.h"
+
+#define TYPE_XHCI_SYSBUS "sysbus-xhci"
+#define XHCI_SYSBUS(obj) \
+ OBJECT_CHECK(XHCISysbusState, (obj), TYPE_XHCI_SYSBUS)
+
+
+typedef struct XHCISysbusState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+ XHCIState xhci;
+ qemu_irq *irq;
+} XHCISysbusState;
+
+void xhci_sysbus_reset(DeviceState *dev);
+#endif
diff --git a/hw/usb/hcd-xhci.h b/hw/usb/hcd-xhci.h
index 525291b..4108a65 100644
--- a/hw/usb/hcd-xhci.h
+++ b/hw/usb/hcd-xhci.h
@@ -191,6 +191,7 @@ typedef struct XHCIState {
USBBus bus;
MemoryRegion mem;
+ MemoryRegion *dma_mr;
AddressSpace *as;
MemoryRegion mem_cap;
MemoryRegion mem_oper;
diff --git a/hw/usb/meson.build b/hw/usb/meson.build
index 90dc54f..934e4fa 100644
--- a/hw/usb/meson.build
+++ b/hw/usb/meson.build
@@ -22,6 +22,7 @@ softmmu_ss.add(when: 'CONFIG_USB_EHCI_PCI', if_true: files('hcd-ehci-pci.c'))
softmmu_ss.add(when: 'CONFIG_USB_EHCI_SYSBUS', if_true: files('hcd-ehci.c', 'hcd-ehci-sysbus.c'))
softmmu_ss.add(when: 'CONFIG_USB_XHCI', if_true: files('hcd-xhci.c'))
softmmu_ss.add(when: 'CONFIG_USB_XHCI_PCI', if_true: files('hcd-xhci-pci.c'))
+softmmu_ss.add(when: 'CONFIG_USB_XHCI_SYSBUS', if_true: files('hcd-xhci-sysbus.c'))
softmmu_ss.add(when: 'CONFIG_USB_XHCI_NEC', if_true: files('hcd-xhci-nec.c'))
softmmu_ss.add(when: 'CONFIG_USB_MUSB', if_true: files('hcd-musb.c'))
softmmu_ss.add(when: 'CONFIG_USB_DWC2', if_true: files('hcd-dwc2.c'))
--
2.7.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v6 5/7] misc: Add versal-usb2-ctrl-regs module
2020-09-16 11:41 [PATCH v6 0/7] Make hcd-xhci independent of pci hooks Sai Pavan Boddu
` (3 preceding siblings ...)
2020-09-16 11:41 ` [PATCH v6 4/7] usb: hcd-xhci-sysbus: Attach xhci to sysbus device Sai Pavan Boddu
@ 2020-09-16 11:41 ` Sai Pavan Boddu
2020-09-16 12:02 ` Gerd Hoffmann
2020-09-16 11:41 ` [PATCH v6 5/7] misc: Add versal-usb2-regs module Sai Pavan Boddu
` (2 subsequent siblings)
7 siblings, 1 reply; 14+ messages in thread
From: Sai Pavan Boddu @ 2020-09-16 11:41 UTC (permalink / raw)
To: Peter Maydell, Markus Armbruster,
'Marc-André Lureau', Paolo Bonzini, Gerd Hoffmann,
Edgar Iglesias, Francisco Eduardo Iglesias
Cc: Eduardo Habkost, Vikram Garhwal, qemu-devel, Paul Zimmerman,
Sai Pavan Boddu, Alistair Francis, Ying Fang,
'Philippe Mathieu-Daudé'
This module emulates control registers of versal usb2 controller, this is added
just to make guest happy. In general this module would control the phy-reset
signal from usb controller, data coherency of the transactions, signals
the host system errors received from controller.
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
---
hw/misc/meson.build | 1 +
hw/misc/xlnx-versal-usb2-ctrl-regs.c | 222 +++++++++++++++++++++++++++
include/hw/misc/xlnx-versal-usb2-ctrl-regs.h | 45 ++++++
3 files changed, 268 insertions(+)
create mode 100644 hw/misc/xlnx-versal-usb2-ctrl-regs.c
create mode 100644 include/hw/misc/xlnx-versal-usb2-ctrl-regs.h
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 793d45b..b336dd1 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -109,3 +109,4 @@ specific_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_cmgcr.c', 'mips_cp
specific_ss.add(when: 'CONFIG_MIPS_ITU', if_true: files('mips_itu.c'))
specific_ss.add(when: 'CONFIG_SBSA_REF', if_true: files('sbsa_ec.c'))
+specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-usb2-ctrl-regs.c'))
diff --git a/hw/misc/xlnx-versal-usb2-ctrl-regs.c b/hw/misc/xlnx-versal-usb2-ctrl-regs.c
new file mode 100644
index 0000000..94fd7cf
--- /dev/null
+++ b/hw/misc/xlnx-versal-usb2-ctrl-regs.c
@@ -0,0 +1,222 @@
+/*
+ * QEMU model of the VersalUsb2CtrlRegs Register control/Status block for
+ * USB2.0 controller
+ *
+ * This module should control phy_reset, permanent device plugs, frame length
+ * time adjust & setting of coherency paths. None of which are emulated in
+ * present model.
+ *
+ * Copyright (c) 2020 Xilinx Inc. Vikram Garhwal <fnu.vikram@xilinx.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "hw/register.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qom/object.h"
+#include "migration/vmstate.h"
+#include "hw/misc/xlnx-versal-usb2-ctrl-regs.h"
+
+#ifndef XILINX_VERSAL_USB2_CTRL_REGS_ERR_DEBUG
+#define XILINX_VERSAL_USB2_CTRL_REGS_ERR_DEBUG 0
+#endif
+
+REG32(BUS_FILTER, 0x30)
+ FIELD(BUS_FILTER, BYPASS, 0, 4)
+REG32(PORT, 0x34)
+ FIELD(PORT, HOST_SMI_BAR_WR, 4, 1)
+ FIELD(PORT, HOST_SMI_PCI_CMD_REG_WR, 3, 1)
+ FIELD(PORT, HOST_MSI_ENABLE, 2, 1)
+ FIELD(PORT, PWR_CTRL_PRSNT, 1, 1)
+ FIELD(PORT, HUB_PERM_ATTACH, 0, 1)
+REG32(JITTER_ADJUST, 0x38)
+ FIELD(JITTER_ADJUST, FLADJ, 0, 6)
+REG32(BIGENDIAN, 0x40)
+ FIELD(BIGENDIAN, ENDIAN_GS, 0, 1)
+REG32(COHERENCY, 0x44)
+ FIELD(COHERENCY, USB_COHERENCY, 0, 1)
+REG32(XHC_BME, 0x48)
+ FIELD(XHC_BME, XHC_BME, 0, 1)
+REG32(REG_CTRL, 0x60)
+ FIELD(REG_CTRL, SLVERR_ENABLE, 0, 1)
+REG32(IR_STATUS, 0x64)
+ FIELD(IR_STATUS, HOST_SYS_ERR, 1, 1)
+ FIELD(IR_STATUS, ADDR_DEC_ERR, 0, 1)
+REG32(IR_MASK, 0x68)
+ FIELD(IR_MASK, HOST_SYS_ERR, 1, 1)
+ FIELD(IR_MASK, ADDR_DEC_ERR, 0, 1)
+REG32(IR_ENABLE, 0x6c)
+ FIELD(IR_ENABLE, HOST_SYS_ERR, 1, 1)
+ FIELD(IR_ENABLE, ADDR_DEC_ERR, 0, 1)
+REG32(IR_DISABLE, 0x70)
+ FIELD(IR_DISABLE, HOST_SYS_ERR, 1, 1)
+ FIELD(IR_DISABLE, ADDR_DEC_ERR, 0, 1)
+REG32(USB3, 0x78)
+
+static void ir_update_irq(VersalUsb2CtrlRegs *s)
+{
+ bool pending = s->regs[R_IR_STATUS] & ~s->regs[R_IR_MASK];
+ qemu_set_irq(s->irq_ir, pending);
+}
+
+static void ir_status_postw(RegisterInfo *reg, uint64_t val64)
+{
+ VersalUsb2CtrlRegs *s = XILINX_VERSAL_USB2_CTRL_REGS(reg->opaque);
+ /*
+ * TODO: This should also clear USBSTS.HSE field in USB XHCI register.
+ * May be combine both the modules.
+ */
+ ir_update_irq(s);
+}
+
+static uint64_t ir_enable_prew(RegisterInfo *reg, uint64_t val64)
+{
+ VersalUsb2CtrlRegs *s = XILINX_VERSAL_USB2_CTRL_REGS(reg->opaque);
+ uint32_t val = val64;
+
+ s->regs[R_IR_MASK] &= ~val;
+ ir_update_irq(s);
+ return 0;
+}
+
+static uint64_t ir_disable_prew(RegisterInfo *reg, uint64_t val64)
+{
+ VersalUsb2CtrlRegs *s = XILINX_VERSAL_USB2_CTRL_REGS(reg->opaque);
+ uint32_t val = val64;
+
+ s->regs[R_IR_MASK] |= val;
+ ir_update_irq(s);
+ return 0;
+}
+
+static const RegisterAccessInfo usb2_regs_regs_info[] = {
+ { .name = "BUS_FILTER", .addr = A_BUS_FILTER,
+ .rsvd = 0xfffffff0,
+ },{ .name = "PORT", .addr = A_PORT,
+ .rsvd = 0xffffffe0,
+ },{ .name = "JITTER_ADJUST", .addr = A_JITTER_ADJUST,
+ .reset = 0x20,
+ .rsvd = 0xffffffc0,
+ },{ .name = "BIGENDIAN", .addr = A_BIGENDIAN,
+ .rsvd = 0xfffffffe,
+ },{ .name = "COHERENCY", .addr = A_COHERENCY,
+ .rsvd = 0xfffffffe,
+ },{ .name = "XHC_BME", .addr = A_XHC_BME,
+ .reset = 0x1,
+ .rsvd = 0xfffffffe,
+ },{ .name = "REG_CTRL", .addr = A_REG_CTRL,
+ .rsvd = 0xfffffffe,
+ },{ .name = "IR_STATUS", .addr = A_IR_STATUS,
+ .rsvd = 0xfffffffc,
+ .w1c = 0x3,
+ .post_write = ir_status_postw,
+ },{ .name = "IR_MASK", .addr = A_IR_MASK,
+ .reset = 0x3,
+ .rsvd = 0xfffffffc,
+ .ro = 0x3,
+ },{ .name = "IR_ENABLE", .addr = A_IR_ENABLE,
+ .rsvd = 0xfffffffc,
+ .pre_write = ir_enable_prew,
+ },{ .name = "IR_DISABLE", .addr = A_IR_DISABLE,
+ .rsvd = 0xfffffffc,
+ .pre_write = ir_disable_prew,
+ },{ .name = "USB3", .addr = A_USB3,
+ }
+};
+
+static void usb2_regs_reset(DeviceState *dev)
+{
+ VersalUsb2CtrlRegs *s = XILINX_VERSAL_USB2_CTRL_REGS(dev);
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
+ register_reset(&s->regs_info[i]);
+ }
+
+ ir_update_irq(s);
+}
+
+static const MemoryRegionOps usb2_regs_ops = {
+ .read = register_read_memory,
+ .write = register_write_memory,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
+
+static void usb2_regs_init(Object *obj)
+{
+ VersalUsb2CtrlRegs *s = XILINX_VERSAL_USB2_CTRL_REGS(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ RegisterInfoArray *reg_array;
+
+ memory_region_init(&s->iomem, obj, TYPE_XILINX_VERSAL_USB2_CTRL_REGS,
+ USB2_REGS_R_MAX * 4);
+ reg_array =
+ register_init_block32(DEVICE(obj), usb2_regs_regs_info,
+ ARRAY_SIZE(usb2_regs_regs_info),
+ s->regs_info, s->regs,
+ &usb2_regs_ops,
+ XILINX_VERSAL_USB2_CTRL_REGS_ERR_DEBUG,
+ USB2_REGS_R_MAX * 4);
+ memory_region_add_subregion(&s->iomem,
+ 0x0,
+ ®_array->mem);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq_ir);
+}
+
+static const VMStateDescription vmstate_usb2_regs = {
+ .name = TYPE_XILINX_VERSAL_USB2_CTRL_REGS,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(regs, VersalUsb2CtrlRegs, USB2_REGS_R_MAX),
+ VMSTATE_END_OF_LIST(),
+ }
+};
+
+static void usb2_regs_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = usb2_regs_reset;
+ dc->vmsd = &vmstate_usb2_regs;
+}
+
+static const TypeInfo usb2_regs_info = {
+ .name = TYPE_XILINX_VERSAL_USB2_CTRL_REGS,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(VersalUsb2CtrlRegs),
+ .class_init = usb2_regs_class_init,
+ .instance_init = usb2_regs_init,
+};
+
+static void usb2_regs_register_types(void)
+{
+ type_register_static(&usb2_regs_info);
+}
+
+type_init(usb2_regs_register_types)
diff --git a/include/hw/misc/xlnx-versal-usb2-ctrl-regs.h b/include/hw/misc/xlnx-versal-usb2-ctrl-regs.h
new file mode 100644
index 0000000..975a717
--- /dev/null
+++ b/include/hw/misc/xlnx-versal-usb2-ctrl-regs.h
@@ -0,0 +1,45 @@
+/*
+ * QEMU model of the VersalUsb2CtrlRegs Register control/Status block for
+ * USB2.0 controller
+ *
+ * Copyright (c) 2020 Xilinx Inc. Vikram Garhwal <fnu.vikram@xilinx.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef _XLNX_USB2_REGS_H_
+#define _XLNX_USB2_REGS_H_
+
+#define TYPE_XILINX_VERSAL_USB2_CTRL_REGS "xlnx.versal-usb2-ctrl-regs"
+
+#define XILINX_VERSAL_USB2_CTRL_REGS(obj) \
+ OBJECT_CHECK(VersalUsb2CtrlRegs, (obj), TYPE_XILINX_VERSAL_USB2_CTRL_REGS)
+
+#define USB2_REGS_R_MAX ((0x78 / 4) + 1)
+
+typedef struct VersalUsb2CtrlRegs {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+ qemu_irq irq_ir;
+
+ uint32_t regs[USB2_REGS_R_MAX];
+ RegisterInfo regs_info[USB2_REGS_R_MAX];
+} VersalUsb2CtrlRegs;
+
+#endif
--
2.7.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v6 5/7] misc: Add versal-usb2-ctrl-regs module
2020-09-16 11:41 ` [PATCH v6 5/7] misc: Add versal-usb2-ctrl-regs module Sai Pavan Boddu
@ 2020-09-16 12:02 ` Gerd Hoffmann
2020-09-16 14:17 ` Sai Pavan Boddu
0 siblings, 1 reply; 14+ messages in thread
From: Gerd Hoffmann @ 2020-09-16 12:02 UTC (permalink / raw)
To: Sai Pavan Boddu
Cc: Francisco Eduardo Iglesias, Peter Maydell, Eduardo Habkost,
Vikram Garhwal, Markus Armbruster, qemu-devel, Sai Pavan Boddu,
Edgar Iglesias, Alistair Francis,
'Marc-André Lureau', Ying Fang, Paolo Bonzini,
Paul Zimmerman, 'Philippe Mathieu-Daudé'
On Wed, Sep 16, 2020 at 05:11:06PM +0530, Sai Pavan Boddu wrote:
> This module emulates control registers of versal usb2 controller, this is added
> just to make guest happy. In general this module would control the phy-reset
> signal from usb controller, data coherency of the transactions, signals
> the host system errors received from controller.
>
> Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
> Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
Huh? Patch 5/7 is twice in this series ...
take care,
Gerd
^ permalink raw reply [flat|nested] 14+ messages in thread
* RE: [PATCH v6 5/7] misc: Add versal-usb2-ctrl-regs module
2020-09-16 12:02 ` Gerd Hoffmann
@ 2020-09-16 14:17 ` Sai Pavan Boddu
0 siblings, 0 replies; 14+ messages in thread
From: Sai Pavan Boddu @ 2020-09-16 14:17 UTC (permalink / raw)
To: Gerd Hoffmann
Cc: Francisco Eduardo Iglesias, Peter Maydell, Eduardo Habkost,
Vikram Garhwal, Markus Armbruster, qemu-devel@nongnu.org,
Edgar Iglesias, Alistair Francis,
'Marc-André Lureau', Ying Fang, Paolo Bonzini,
Paul Zimmerman, 'Philippe Mathieu-Daudé'
Hi Gerd,
> -----Original Message-----
> From: Gerd Hoffmann <kraxel@redhat.com>
> Sent: Wednesday, September 16, 2020 5:32 PM
> To: Sai Pavan Boddu <saipava@xilinx.com>
> Cc: Peter Maydell <peter.maydell@linaro.org>; Markus Armbruster
> <armbru@redhat.com>; 'Marc-André Lureau'
> <marcandre.lureau@redhat.com>; Paolo Bonzini <pbonzini@redhat.com>;
> Edgar Iglesias <edgari@xilinx.com>; Francisco Eduardo Iglesias
> <figlesia@xilinx.com>; qemu-devel@nongnu.org; Alistair Francis
> <alistair.francis@wdc.com>; Eduardo Habkost <ehabkost@redhat.com>;
> Ying Fang <fangying1@huawei.com>; 'Philippe Mathieu-Daudé'
> <philmd@redhat.com>; Vikram Garhwal <fnuv@xilinx.com>; Paul
> Zimmerman <pauldzim@gmail.com>; Sai Pavan Boddu
> <saipava@xilinx.com>
> Subject: Re: [PATCH v6 5/7] misc: Add versal-usb2-ctrl-regs module
>
> On Wed, Sep 16, 2020 at 05:11:06PM +0530, Sai Pavan Boddu wrote:
> > This module emulates control registers of versal usb2 controller, this
> > is added just to make guest happy. In general this module would
> > control the phy-reset signal from usb controller, data coherency of
> > the transactions, signals the host system errors received from controller.
> >
> > Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
> > Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
>
> Huh? Patch 5/7 is twice in this series ...
[Sai Pavan Boddu] Sorry, that was a mistake. Sending out V7.
Regards,
Sai Pavan
>
> take care,
> Gerd
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v6 5/7] misc: Add versal-usb2-regs module
2020-09-16 11:41 [PATCH v6 0/7] Make hcd-xhci independent of pci hooks Sai Pavan Boddu
` (4 preceding siblings ...)
2020-09-16 11:41 ` [PATCH v6 5/7] misc: Add versal-usb2-ctrl-regs module Sai Pavan Boddu
@ 2020-09-16 11:41 ` Sai Pavan Boddu
2020-09-16 12:35 ` Sai Pavan Boddu
2020-09-16 11:41 ` [PATCH v6 6/7] usb: Add DWC3 model Sai Pavan Boddu
2020-09-16 11:41 ` [PATCH v6 7/7] Versal: Connect DWC3 controller with virt-versal Sai Pavan Boddu
7 siblings, 1 reply; 14+ messages in thread
From: Sai Pavan Boddu @ 2020-09-16 11:41 UTC (permalink / raw)
To: Peter Maydell, Markus Armbruster,
'Marc-André Lureau', Paolo Bonzini, Gerd Hoffmann,
Edgar Iglesias, Francisco Eduardo Iglesias
Cc: Eduardo Habkost, Vikram Garhwal, qemu-devel, Paul Zimmerman,
Sai Pavan Boddu, Alistair Francis, Ying Fang,
'Philippe Mathieu-Daudé'
This module emulates control registers of versal usb2 controller, this is added
just to make guest happy. In general this module would control the phy-reset
signal from usb controller, data coherency of the transactions, signals
the host system errors received from controller.
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
---
hw/misc/meson.build | 1 +
hw/misc/xlnx-versal-usb2-ctrl-regs.c | 221 +++++++++++++++++++++++++++
include/hw/misc/xlnx-versal-usb2-ctrl-regs.h | 46 ++++++
3 files changed, 268 insertions(+)
create mode 100644 hw/misc/xlnx-versal-usb2-ctrl-regs.c
create mode 100644 include/hw/misc/xlnx-versal-usb2-ctrl-regs.h
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 793d45b..b336dd1 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -109,3 +109,4 @@ specific_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_cmgcr.c', 'mips_cp
specific_ss.add(when: 'CONFIG_MIPS_ITU', if_true: files('mips_itu.c'))
specific_ss.add(when: 'CONFIG_SBSA_REF', if_true: files('sbsa_ec.c'))
+specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-usb2-ctrl-regs.c'))
diff --git a/hw/misc/xlnx-versal-usb2-ctrl-regs.c b/hw/misc/xlnx-versal-usb2-ctrl-regs.c
new file mode 100644
index 0000000..6ddd38b
--- /dev/null
+++ b/hw/misc/xlnx-versal-usb2-ctrl-regs.c
@@ -0,0 +1,221 @@
+/*
+ * QEMU model of the XlnxUsb2Regs Register control block/Status for USB2.0 IP
+ *
+ * This module should control phy_reset, permanent device plugs, frame length
+ * time adjust & setting of coherency paths. None of which are emulated in
+ * present model.
+ *
+ * Copyright (c) 2020 Xilinx Inc. Vikram Garhwal <fnu.vikram@xilinx.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "hw/register.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qom/object.h"
+#include "migration/vmstate.h"
+#include "hw/misc/xlnx-versal-usb2-ctrl-regs.h"
+
+#ifndef XILINX_USB2_REGS_ERR_DEBUG
+#define XILINX_USB2_REGS_ERR_DEBUG 0
+#endif
+
+REG32(BUS_FILTER, 0x30)
+ FIELD(BUS_FILTER, BYPASS, 0, 4)
+REG32(PORT, 0x34)
+ FIELD(PORT, HOST_SMI_BAR_WR, 4, 1)
+ FIELD(PORT, HOST_SMI_PCI_CMD_REG_WR, 3, 1)
+ FIELD(PORT, HOST_MSI_ENABLE, 2, 1)
+ FIELD(PORT, PWR_CTRL_PRSNT, 1, 1)
+ FIELD(PORT, HUB_PERM_ATTACH, 0, 1)
+REG32(JITTER_ADJUST, 0x38)
+ FIELD(JITTER_ADJUST, FLADJ, 0, 6)
+REG32(BIGENDIAN, 0x40)
+ FIELD(BIGENDIAN, ENDIAN_GS, 0, 1)
+REG32(COHERENCY, 0x44)
+ FIELD(COHERENCY, USB_COHERENCY, 0, 1)
+REG32(XHC_BME, 0x48)
+ FIELD(XHC_BME, XHC_BME, 0, 1)
+REG32(REG_CTRL, 0x60)
+ FIELD(REG_CTRL, SLVERR_ENABLE, 0, 1)
+REG32(IR_STATUS, 0x64)
+ FIELD(IR_STATUS, HOST_SYS_ERR, 1, 1)
+ FIELD(IR_STATUS, ADDR_DEC_ERR, 0, 1)
+REG32(IR_MASK, 0x68)
+ FIELD(IR_MASK, HOST_SYS_ERR, 1, 1)
+ FIELD(IR_MASK, ADDR_DEC_ERR, 0, 1)
+REG32(IR_ENABLE, 0x6c)
+ FIELD(IR_ENABLE, HOST_SYS_ERR, 1, 1)
+ FIELD(IR_ENABLE, ADDR_DEC_ERR, 0, 1)
+REG32(IR_DISABLE, 0x70)
+ FIELD(IR_DISABLE, HOST_SYS_ERR, 1, 1)
+ FIELD(IR_DISABLE, ADDR_DEC_ERR, 0, 1)
+REG32(USB3, 0x78)
+
+static void ir_update_irq(XlnxUsb2Regs *s)
+{
+ bool pending = s->regs[R_IR_STATUS] & ~s->regs[R_IR_MASK];
+ qemu_set_irq(s->irq_ir, pending);
+}
+
+static void ir_status_postw(RegisterInfo *reg, uint64_t val64)
+{
+ XlnxUsb2Regs *s = XILINX_USB2_REGS(reg->opaque);
+ /*
+ * TODO: This should also clear USBSTS.HSE field in USB XHCI register.
+ * May be combine both the modules.
+ */
+ ir_update_irq(s);
+}
+
+static uint64_t ir_enable_prew(RegisterInfo *reg, uint64_t val64)
+{
+ XlnxUsb2Regs *s = XILINX_USB2_REGS(reg->opaque);
+ uint32_t val = val64;
+
+ s->regs[R_IR_MASK] &= ~val;
+ ir_update_irq(s);
+ return 0;
+}
+
+static uint64_t ir_disable_prew(RegisterInfo *reg, uint64_t val64)
+{
+ XlnxUsb2Regs *s = XILINX_USB2_REGS(reg->opaque);
+ uint32_t val = val64;
+
+ s->regs[R_IR_MASK] |= val;
+ ir_update_irq(s);
+ return 0;
+}
+
+static const RegisterAccessInfo usb2_regs_regs_info[] = {
+ { .name = "BUS_FILTER", .addr = A_BUS_FILTER,
+ .rsvd = 0xfffffff0,
+ },{ .name = "PORT", .addr = A_PORT,
+ .rsvd = 0xffffffe0,
+ },{ .name = "JITTER_ADJUST", .addr = A_JITTER_ADJUST,
+ .reset = 0x20,
+ .rsvd = 0xffffffc0,
+ },{ .name = "BIGENDIAN", .addr = A_BIGENDIAN,
+ .rsvd = 0xfffffffe,
+ },{ .name = "COHERENCY", .addr = A_COHERENCY,
+ .rsvd = 0xfffffffe,
+ },{ .name = "XHC_BME", .addr = A_XHC_BME,
+ .reset = 0x1,
+ .rsvd = 0xfffffffe,
+ },{ .name = "REG_CTRL", .addr = A_REG_CTRL,
+ .rsvd = 0xfffffffe,
+ },{ .name = "IR_STATUS", .addr = A_IR_STATUS,
+ .rsvd = 0xfffffffc,
+ .w1c = 0x3,
+ .post_write = ir_status_postw,
+ },{ .name = "IR_MASK", .addr = A_IR_MASK,
+ .reset = 0x3,
+ .rsvd = 0xfffffffc,
+ .ro = 0x3,
+ },{ .name = "IR_ENABLE", .addr = A_IR_ENABLE,
+ .rsvd = 0xfffffffc,
+ .pre_write = ir_enable_prew,
+ },{ .name = "IR_DISABLE", .addr = A_IR_DISABLE,
+ .rsvd = 0xfffffffc,
+ .pre_write = ir_disable_prew,
+ },{ .name = "USB3", .addr = A_USB3,
+ }
+};
+
+static void usb2_regs_reset(DeviceState *dev)
+{
+ XlnxUsb2Regs *s = XILINX_USB2_REGS(dev);
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
+ register_reset(&s->regs_info[i]);
+ }
+
+ ir_update_irq(s);
+}
+
+static const MemoryRegionOps usb2_regs_ops = {
+ .read = register_read_memory,
+ .write = register_write_memory,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
+
+static void usb2_regs_init(Object *obj)
+{
+ XlnxUsb2Regs *s = XILINX_USB2_REGS(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ RegisterInfoArray *reg_array;
+
+ memory_region_init(&s->iomem, obj, TYPE_XILINX_USB2_REGS,
+ USB2_REGS_R_MAX * 4);
+ reg_array =
+ register_init_block32(DEVICE(obj), usb2_regs_regs_info,
+ ARRAY_SIZE(usb2_regs_regs_info),
+ s->regs_info, s->regs,
+ &usb2_regs_ops,
+ XILINX_USB2_REGS_ERR_DEBUG,
+ USB2_REGS_R_MAX * 4);
+ memory_region_add_subregion(&s->iomem,
+ 0x0,
+ ®_array->mem);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq_ir);
+}
+
+static const VMStateDescription vmstate_usb2_regs = {
+ .name = TYPE_XILINX_USB2_REGS,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(regs, XlnxUsb2Regs, USB2_REGS_R_MAX),
+ VMSTATE_END_OF_LIST(),
+ }
+};
+
+static void usb2_regs_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = usb2_regs_reset;
+ dc->vmsd = &vmstate_usb2_regs;
+}
+
+static const TypeInfo usb2_regs_info = {
+ .name = TYPE_XILINX_USB2_REGS,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(XlnxUsb2Regs),
+ .class_init = usb2_regs_class_init,
+ .instance_init = usb2_regs_init,
+};
+
+static void usb2_regs_register_types(void)
+{
+ type_register_static(&usb2_regs_info);
+}
+
+type_init(usb2_regs_register_types)
diff --git a/include/hw/misc/xlnx-versal-usb2-ctrl-regs.h b/include/hw/misc/xlnx-versal-usb2-ctrl-regs.h
new file mode 100644
index 0000000..1d75f63
--- /dev/null
+++ b/include/hw/misc/xlnx-versal-usb2-ctrl-regs.h
@@ -0,0 +1,46 @@
+/*
+ * QEMU model of the XlnxUsb2Regs Register control block/Status for USB2.0 IP
+ *
+ * Copyright (c) 2020 Xilinx Inc.
+ *
+ * Autogenerated by xregqemu.py 2020-04-08.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef _XLNX_USB2_REGS_H_
+#define _XLNX_USB2_REGS_H_
+
+#define TYPE_XILINX_USB2_REGS "xlnx.versal-usb2-ctrl-regs"
+
+#define XILINX_USB2_REGS(obj) \
+ OBJECT_CHECK(XlnxUsb2Regs, (obj), TYPE_XILINX_USB2_REGS)
+
+#define USB2_REGS_R_MAX ((0x78 / 4) + 1)
+
+typedef struct XlnxUsb2Regs {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+ qemu_irq irq_ir;
+
+ uint32_t regs[USB2_REGS_R_MAX];
+ RegisterInfo regs_info[USB2_REGS_R_MAX];
+} XlnxUsb2Regs;
+
+#endif
--
2.7.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* RE: [PATCH v6 5/7] misc: Add versal-usb2-regs module
2020-09-16 11:41 ` [PATCH v6 5/7] misc: Add versal-usb2-regs module Sai Pavan Boddu
@ 2020-09-16 12:35 ` Sai Pavan Boddu
0 siblings, 0 replies; 14+ messages in thread
From: Sai Pavan Boddu @ 2020-09-16 12:35 UTC (permalink / raw)
To: Sai Pavan Boddu, Peter Maydell, Markus Armbruster,
'Marc-André Lureau', Paolo Bonzini, Gerd Hoffmann,
Edgar Iglesias, Francisco Eduardo Iglesias
Cc: Eduardo Habkost, Vikram Garhwal, qemu-devel@nongnu.org,
Paul Zimmerman, Alistair Francis, Ying Fang,
'Philippe Mathieu-Daudé'
Hi Gerd,
Please ignore this
Regards,
Sai Pavan
> -----Original Message-----
> From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
> Sent: Wednesday, September 16, 2020 5:11 PM
> To: Peter Maydell <peter.maydell@linaro.org>; Markus Armbruster
> <armbru@redhat.com>; 'Marc-André Lureau'
> <marcandre.lureau@redhat.com>; Paolo Bonzini <pbonzini@redhat.com>;
> Gerd Hoffmann <kraxel@redhat.com>; Edgar Iglesias <edgari@xilinx.com>;
> Francisco Eduardo Iglesias <figlesia@xilinx.com>
> Cc: qemu-devel@nongnu.org; Alistair Francis <alistair.francis@wdc.com>;
> Eduardo Habkost <ehabkost@redhat.com>; Ying Fang
> <fangying1@huawei.com>; 'Philippe Mathieu-Daudé'
> <philmd@redhat.com>; Vikram Garhwal <fnuv@xilinx.com>; Paul
> Zimmerman <pauldzim@gmail.com>; Sai Pavan Boddu
> <saipava@xilinx.com>
> Subject: [PATCH v6 5/7] misc: Add versal-usb2-regs module
>
> This module emulates control registers of versal usb2 controller, this is
> added just to make guest happy. In general this module would control the
> phy-reset signal from usb controller, data coherency of the transactions,
> signals the host system errors received from controller.
>
> Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
> Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
> ---
> hw/misc/meson.build | 1 +
> hw/misc/xlnx-versal-usb2-ctrl-regs.c | 221
> +++++++++++++++++++++++++++
> include/hw/misc/xlnx-versal-usb2-ctrl-regs.h | 46 ++++++
> 3 files changed, 268 insertions(+)
> create mode 100644 hw/misc/xlnx-versal-usb2-ctrl-regs.c
> create mode 100644 include/hw/misc/xlnx-versal-usb2-ctrl-regs.h
>
> diff --git a/hw/misc/meson.build b/hw/misc/meson.build index
> 793d45b..b336dd1 100644
> --- a/hw/misc/meson.build
> +++ b/hw/misc/meson.build
> @@ -109,3 +109,4 @@ specific_ss.add(when: 'CONFIG_MIPS_CPS', if_true:
> files('mips_cmgcr.c', 'mips_cp
> specific_ss.add(when: 'CONFIG_MIPS_ITU', if_true: files('mips_itu.c'))
>
> specific_ss.add(when: 'CONFIG_SBSA_REF', if_true: files('sbsa_ec.c'))
> +specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true:
> +files('xlnx-versal-usb2-ctrl-regs.c'))
> diff --git a/hw/misc/xlnx-versal-usb2-ctrl-regs.c b/hw/misc/xlnx-versal-usb2-
> ctrl-regs.c
> new file mode 100644
> index 0000000..6ddd38b
> --- /dev/null
> +++ b/hw/misc/xlnx-versal-usb2-ctrl-regs.c
> @@ -0,0 +1,221 @@
> +/*
> + * QEMU model of the XlnxUsb2Regs Register control block/Status for
> +USB2.0 IP
> + *
> + * This module should control phy_reset, permanent device plugs, frame
> +length
> + * time adjust & setting of coherency paths. None of which are emulated
> +in
> + * present model.
> + *
> + * Copyright (c) 2020 Xilinx Inc. Vikram Garhwal
> +<fnu.vikram@xilinx.com>
> + *
> + * Permission is hereby granted, free of charge, to any person
> +obtaining a copy
> + * of this software and associated documentation files (the
> +"Software"), to deal
> + * in the Software without restriction, including without limitation
> +the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or
> +sell
> + * copies of the Software, and to permit persons to whom the Software
> +is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be
> +included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
> KIND,
> +EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> +MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
> EVENT
> +SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
> DAMAGES OR
> +OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> +ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> +DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/sysbus.h"
> +#include "hw/irq.h"
> +#include "hw/register.h"
> +#include "qemu/bitops.h"
> +#include "qemu/log.h"
> +#include "qom/object.h"
> +#include "migration/vmstate.h"
> +#include "hw/misc/xlnx-versal-usb2-ctrl-regs.h"
> +
> +#ifndef XILINX_USB2_REGS_ERR_DEBUG
> +#define XILINX_USB2_REGS_ERR_DEBUG 0
> +#endif
> +
> +REG32(BUS_FILTER, 0x30)
> + FIELD(BUS_FILTER, BYPASS, 0, 4)
> +REG32(PORT, 0x34)
> + FIELD(PORT, HOST_SMI_BAR_WR, 4, 1)
> + FIELD(PORT, HOST_SMI_PCI_CMD_REG_WR, 3, 1)
> + FIELD(PORT, HOST_MSI_ENABLE, 2, 1)
> + FIELD(PORT, PWR_CTRL_PRSNT, 1, 1)
> + FIELD(PORT, HUB_PERM_ATTACH, 0, 1)
> +REG32(JITTER_ADJUST, 0x38)
> + FIELD(JITTER_ADJUST, FLADJ, 0, 6)
> +REG32(BIGENDIAN, 0x40)
> + FIELD(BIGENDIAN, ENDIAN_GS, 0, 1)
> +REG32(COHERENCY, 0x44)
> + FIELD(COHERENCY, USB_COHERENCY, 0, 1) REG32(XHC_BME, 0x48)
> + FIELD(XHC_BME, XHC_BME, 0, 1)
> +REG32(REG_CTRL, 0x60)
> + FIELD(REG_CTRL, SLVERR_ENABLE, 0, 1) REG32(IR_STATUS, 0x64)
> + FIELD(IR_STATUS, HOST_SYS_ERR, 1, 1)
> + FIELD(IR_STATUS, ADDR_DEC_ERR, 0, 1) REG32(IR_MASK, 0x68)
> + FIELD(IR_MASK, HOST_SYS_ERR, 1, 1)
> + FIELD(IR_MASK, ADDR_DEC_ERR, 0, 1)
> +REG32(IR_ENABLE, 0x6c)
> + FIELD(IR_ENABLE, HOST_SYS_ERR, 1, 1)
> + FIELD(IR_ENABLE, ADDR_DEC_ERR, 0, 1) REG32(IR_DISABLE, 0x70)
> + FIELD(IR_DISABLE, HOST_SYS_ERR, 1, 1)
> + FIELD(IR_DISABLE, ADDR_DEC_ERR, 0, 1) REG32(USB3, 0x78)
> +
> +static void ir_update_irq(XlnxUsb2Regs *s) {
> + bool pending = s->regs[R_IR_STATUS] & ~s->regs[R_IR_MASK];
> + qemu_set_irq(s->irq_ir, pending);
> +}
> +
> +static void ir_status_postw(RegisterInfo *reg, uint64_t val64) {
> + XlnxUsb2Regs *s = XILINX_USB2_REGS(reg->opaque);
> + /*
> + * TODO: This should also clear USBSTS.HSE field in USB XHCI register.
> + * May be combine both the modules.
> + */
> + ir_update_irq(s);
> +}
> +
> +static uint64_t ir_enable_prew(RegisterInfo *reg, uint64_t val64) {
> + XlnxUsb2Regs *s = XILINX_USB2_REGS(reg->opaque);
> + uint32_t val = val64;
> +
> + s->regs[R_IR_MASK] &= ~val;
> + ir_update_irq(s);
> + return 0;
> +}
> +
> +static uint64_t ir_disable_prew(RegisterInfo *reg, uint64_t val64) {
> + XlnxUsb2Regs *s = XILINX_USB2_REGS(reg->opaque);
> + uint32_t val = val64;
> +
> + s->regs[R_IR_MASK] |= val;
> + ir_update_irq(s);
> + return 0;
> +}
> +
> +static const RegisterAccessInfo usb2_regs_regs_info[] = {
> + { .name = "BUS_FILTER", .addr = A_BUS_FILTER,
> + .rsvd = 0xfffffff0,
> + },{ .name = "PORT", .addr = A_PORT,
> + .rsvd = 0xffffffe0,
> + },{ .name = "JITTER_ADJUST", .addr = A_JITTER_ADJUST,
> + .reset = 0x20,
> + .rsvd = 0xffffffc0,
> + },{ .name = "BIGENDIAN", .addr = A_BIGENDIAN,
> + .rsvd = 0xfffffffe,
> + },{ .name = "COHERENCY", .addr = A_COHERENCY,
> + .rsvd = 0xfffffffe,
> + },{ .name = "XHC_BME", .addr = A_XHC_BME,
> + .reset = 0x1,
> + .rsvd = 0xfffffffe,
> + },{ .name = "REG_CTRL", .addr = A_REG_CTRL,
> + .rsvd = 0xfffffffe,
> + },{ .name = "IR_STATUS", .addr = A_IR_STATUS,
> + .rsvd = 0xfffffffc,
> + .w1c = 0x3,
> + .post_write = ir_status_postw,
> + },{ .name = "IR_MASK", .addr = A_IR_MASK,
> + .reset = 0x3,
> + .rsvd = 0xfffffffc,
> + .ro = 0x3,
> + },{ .name = "IR_ENABLE", .addr = A_IR_ENABLE,
> + .rsvd = 0xfffffffc,
> + .pre_write = ir_enable_prew,
> + },{ .name = "IR_DISABLE", .addr = A_IR_DISABLE,
> + .rsvd = 0xfffffffc,
> + .pre_write = ir_disable_prew,
> + },{ .name = "USB3", .addr = A_USB3,
> + }
> +};
> +
> +static void usb2_regs_reset(DeviceState *dev) {
> + XlnxUsb2Regs *s = XILINX_USB2_REGS(dev);
> + unsigned int i;
> +
> + for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
> + register_reset(&s->regs_info[i]);
> + }
> +
> + ir_update_irq(s);
> +}
> +
> +static const MemoryRegionOps usb2_regs_ops = {
> + .read = register_read_memory,
> + .write = register_write_memory,
> + .endianness = DEVICE_LITTLE_ENDIAN,
> + .valid = {
> + .min_access_size = 4,
> + .max_access_size = 4,
> + },
> +};
> +
> +static void usb2_regs_init(Object *obj) {
> + XlnxUsb2Regs *s = XILINX_USB2_REGS(obj);
> + SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
> + RegisterInfoArray *reg_array;
> +
> + memory_region_init(&s->iomem, obj, TYPE_XILINX_USB2_REGS,
> + USB2_REGS_R_MAX * 4);
> + reg_array =
> + register_init_block32(DEVICE(obj), usb2_regs_regs_info,
> + ARRAY_SIZE(usb2_regs_regs_info),
> + s->regs_info, s->regs,
> + &usb2_regs_ops,
> + XILINX_USB2_REGS_ERR_DEBUG,
> + USB2_REGS_R_MAX * 4);
> + memory_region_add_subregion(&s->iomem,
> + 0x0,
> + ®_array->mem);
> + sysbus_init_mmio(sbd, &s->iomem);
> + sysbus_init_irq(sbd, &s->irq_ir);
> +}
> +
> +static const VMStateDescription vmstate_usb2_regs = {
> + .name = TYPE_XILINX_USB2_REGS,
> + .version_id = 1,
> + .minimum_version_id = 1,
> + .fields = (VMStateField[]) {
> + VMSTATE_UINT32_ARRAY(regs, XlnxUsb2Regs, USB2_REGS_R_MAX),
> + VMSTATE_END_OF_LIST(),
> + }
> +};
> +
> +static void usb2_regs_class_init(ObjectClass *klass, void *data) {
> + DeviceClass *dc = DEVICE_CLASS(klass);
> +
> + dc->reset = usb2_regs_reset;
> + dc->vmsd = &vmstate_usb2_regs;
> +}
> +
> +static const TypeInfo usb2_regs_info = {
> + .name = TYPE_XILINX_USB2_REGS,
> + .parent = TYPE_SYS_BUS_DEVICE,
> + .instance_size = sizeof(XlnxUsb2Regs),
> + .class_init = usb2_regs_class_init,
> + .instance_init = usb2_regs_init,
> +};
> +
> +static void usb2_regs_register_types(void) {
> + type_register_static(&usb2_regs_info);
> +}
> +
> +type_init(usb2_regs_register_types)
> diff --git a/include/hw/misc/xlnx-versal-usb2-ctrl-regs.h
> b/include/hw/misc/xlnx-versal-usb2-ctrl-regs.h
> new file mode 100644
> index 0000000..1d75f63
> --- /dev/null
> +++ b/include/hw/misc/xlnx-versal-usb2-ctrl-regs.h
> @@ -0,0 +1,46 @@
> +/*
> + * QEMU model of the XlnxUsb2Regs Register control block/Status for
> +USB2.0 IP
> + *
> + * Copyright (c) 2020 Xilinx Inc.
> + *
> + * Autogenerated by xregqemu.py 2020-04-08.
> + *
> + * Permission is hereby granted, free of charge, to any person
> +obtaining a copy
> + * of this software and associated documentation files (the
> +"Software"), to deal
> + * in the Software without restriction, including without limitation
> +the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or
> +sell
> + * copies of the Software, and to permit persons to whom the Software
> +is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be
> +included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
> KIND,
> +EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> +MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
> EVENT
> +SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
> DAMAGES OR
> +OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> +ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> +DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#ifndef _XLNX_USB2_REGS_H_
> +#define _XLNX_USB2_REGS_H_
> +
> +#define TYPE_XILINX_USB2_REGS "xlnx.versal-usb2-ctrl-regs"
> +
> +#define XILINX_USB2_REGS(obj) \
> + OBJECT_CHECK(XlnxUsb2Regs, (obj), TYPE_XILINX_USB2_REGS)
> +
> +#define USB2_REGS_R_MAX ((0x78 / 4) + 1)
> +
> +typedef struct XlnxUsb2Regs {
> + SysBusDevice parent_obj;
> + MemoryRegion iomem;
> + qemu_irq irq_ir;
> +
> + uint32_t regs[USB2_REGS_R_MAX];
> + RegisterInfo regs_info[USB2_REGS_R_MAX]; } XlnxUsb2Regs;
> +
> +#endif
> --
> 2.7.4
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v6 6/7] usb: Add DWC3 model
2020-09-16 11:41 [PATCH v6 0/7] Make hcd-xhci independent of pci hooks Sai Pavan Boddu
` (5 preceding siblings ...)
2020-09-16 11:41 ` [PATCH v6 5/7] misc: Add versal-usb2-regs module Sai Pavan Boddu
@ 2020-09-16 11:41 ` Sai Pavan Boddu
2020-09-16 11:41 ` [PATCH v6 7/7] Versal: Connect DWC3 controller with virt-versal Sai Pavan Boddu
7 siblings, 0 replies; 14+ messages in thread
From: Sai Pavan Boddu @ 2020-09-16 11:41 UTC (permalink / raw)
To: Peter Maydell, Markus Armbruster,
'Marc-André Lureau', Paolo Bonzini, Gerd Hoffmann,
Edgar Iglesias, Francisco Eduardo Iglesias
Cc: Eduardo Habkost, Vikram Garhwal, qemu-devel, Paul Zimmerman,
Sai Pavan Boddu, Alistair Francis, Ying Fang,
'Philippe Mathieu-Daudé'
From: Vikram Garhwal <fnu.vikram@xilinx.com>
This patch adds skeleton model of dwc3 usb controller attached to
xhci-sysbus device. It defines global register space of DWC3 controller,
global registers control the AXI/AHB interfaces properties, external FIFO
support and event count support. All of which are unimplemented at
present,we are only supporting core reset and read of ID register.
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
---
hw/usb/Kconfig | 6 +
hw/usb/hcd-dwc3.c | 717 ++++++++++++++++++++++++++++++++++++++++++++++
hw/usb/meson.build | 1 +
include/hw/usb/hcd-dwc3.h | 55 ++++
4 files changed, 779 insertions(+)
create mode 100644 hw/usb/hcd-dwc3.c
create mode 100644 include/hw/usb/hcd-dwc3.h
diff --git a/hw/usb/Kconfig b/hw/usb/Kconfig
index 4dd2ba9..f5762f0 100644
--- a/hw/usb/Kconfig
+++ b/hw/usb/Kconfig
@@ -116,3 +116,9 @@ config IMX_USBPHY
bool
default y
depends on USB
+
+config USB_DWC3
+ bool
+ default y if USB_XHCI_SYSBUS
+ select USB
+ select REGISTER
diff --git a/hw/usb/hcd-dwc3.c b/hw/usb/hcd-dwc3.c
new file mode 100644
index 0000000..de8be7a
--- /dev/null
+++ b/hw/usb/hcd-dwc3.c
@@ -0,0 +1,717 @@
+/*
+ * QEMU model of the USB DWC3 host controller emulation.
+ *
+ * This model defines global register space of DWC3 controller. Global
+ * registers control the AXI/AHB interfaces properties, external FIFO support
+ * and event count support. All of which are unimplemented at present. We are
+ * only supporting core reset and read of ID register.
+ *
+ * Copyright (c) 2020 Xilinx Inc. Vikram Garhwal<fnu.vikram@xilinx.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qom/object.h"
+#include "migration/vmstate.h"
+#include "hw/qdev-properties.h"
+#include "hw/usb/hcd-dwc3.h"
+#include "qapi/error.h"
+
+#ifndef USB_DWC3_ERR_DEBUG
+#define USB_DWC3_ERR_DEBUG 0
+#endif
+
+#define HOST_MODE 1
+#define FIFO_LEN 0x1000
+
+REG32(GSBUSCFG0, 0x00)
+ FIELD(GSBUSCFG0, DATRDREQINFO, 28, 4)
+ FIELD(GSBUSCFG0, DESRDREQINFO, 24, 4)
+ FIELD(GSBUSCFG0, DATWRREQINFO, 20, 4)
+ FIELD(GSBUSCFG0, DESWRREQINFO, 16, 4)
+ FIELD(GSBUSCFG0, RESERVED_15_12, 12, 4)
+ FIELD(GSBUSCFG0, DATBIGEND, 11, 1)
+ FIELD(GSBUSCFG0, DESBIGEND, 10, 1)
+ FIELD(GSBUSCFG0, RESERVED_9_8, 8, 2)
+ FIELD(GSBUSCFG0, INCR256BRSTENA, 7, 1)
+ FIELD(GSBUSCFG0, INCR128BRSTENA, 6, 1)
+ FIELD(GSBUSCFG0, INCR64BRSTENA, 5, 1)
+ FIELD(GSBUSCFG0, INCR32BRSTENA, 4, 1)
+ FIELD(GSBUSCFG0, INCR16BRSTENA, 3, 1)
+ FIELD(GSBUSCFG0, INCR8BRSTENA, 2, 1)
+ FIELD(GSBUSCFG0, INCR4BRSTENA, 1, 1)
+ FIELD(GSBUSCFG0, INCRBRSTENA, 0, 1)
+REG32(GSBUSCFG1, 0x04)
+ FIELD(GSBUSCFG1, RESERVED_31_13, 13, 19)
+ FIELD(GSBUSCFG1, EN1KPAGE, 12, 1)
+ FIELD(GSBUSCFG1, PIPETRANSLIMIT, 8, 4)
+ FIELD(GSBUSCFG1, RESERVED_7_0, 0, 8)
+REG32(GTXTHRCFG, 0x08)
+ FIELD(GTXTHRCFG, RESERVED_31, 31, 1)
+ FIELD(GTXTHRCFG, RESERVED_30, 30, 1)
+ FIELD(GTXTHRCFG, USBTXPKTCNTSEL, 29, 1)
+ FIELD(GTXTHRCFG, RESERVED_28, 28, 1)
+ FIELD(GTXTHRCFG, USBTXPKTCNT, 24, 4)
+ FIELD(GTXTHRCFG, USBMAXTXBURSTSIZE, 16, 8)
+ FIELD(GTXTHRCFG, RESERVED_15, 15, 1)
+ FIELD(GTXTHRCFG, RESERVED_14, 14, 1)
+ FIELD(GTXTHRCFG, RESERVED_13_11, 11, 3)
+ FIELD(GTXTHRCFG, RESERVED_10_0, 0, 11)
+REG32(GRXTHRCFG, 0x0c)
+ FIELD(GRXTHRCFG, RESERVED_31_30, 30, 2)
+ FIELD(GRXTHRCFG, USBRXPKTCNTSEL, 29, 1)
+ FIELD(GRXTHRCFG, RESERVED_28, 28, 1)
+ FIELD(GRXTHRCFG, USBRXPKTCNT, 24, 4)
+ FIELD(GRXTHRCFG, USBMAXRXBURSTSIZE, 19, 5)
+ FIELD(GRXTHRCFG, RESERVED_18_16, 16, 3)
+ FIELD(GRXTHRCFG, RESERVED_15, 15, 1)
+ FIELD(GRXTHRCFG, RESERVED_14_13, 13, 2)
+ FIELD(GRXTHRCFG, RESVISOCOUTSPC, 0, 13)
+REG32(GCTL, 0x10)
+ FIELD(GCTL, PWRDNSCALE, 19, 13)
+ FIELD(GCTL, MASTERFILTBYPASS, 18, 1)
+ FIELD(GCTL, BYPSSETADDR, 17, 1)
+ FIELD(GCTL, U2RSTECN, 16, 1)
+ FIELD(GCTL, FRMSCLDWN, 14, 2)
+ FIELD(GCTL, PRTCAPDIR, 12, 2)
+ FIELD(GCTL, CORESOFTRESET, 11, 1)
+ FIELD(GCTL, U1U2TIMERSCALE, 9, 1)
+ FIELD(GCTL, DEBUGATTACH, 8, 1)
+ FIELD(GCTL, RAMCLKSEL, 6, 2)
+ FIELD(GCTL, SCALEDOWN, 4, 2)
+ FIELD(GCTL, DISSCRAMBLE, 3, 1)
+ FIELD(GCTL, U2EXIT_LFPS, 2, 1)
+ FIELD(GCTL, GBLHIBERNATIONEN, 1, 1)
+ FIELD(GCTL, DSBLCLKGTNG, 0, 1)
+REG32(GPMSTS, 0x14)
+REG32(GSTS, 0x18)
+ FIELD(GSTS, CBELT, 20, 12)
+ FIELD(GSTS, RESERVED_19_12, 12, 8)
+ FIELD(GSTS, SSIC_IP, 11, 1)
+ FIELD(GSTS, OTG_IP, 10, 1)
+ FIELD(GSTS, BC_IP, 9, 1)
+ FIELD(GSTS, ADP_IP, 8, 1)
+ FIELD(GSTS, HOST_IP, 7, 1)
+ FIELD(GSTS, DEVICE_IP, 6, 1)
+ FIELD(GSTS, CSRTIMEOUT, 5, 1)
+ FIELD(GSTS, BUSERRADDRVLD, 4, 1)
+ FIELD(GSTS, RESERVED_3_2, 2, 2)
+ FIELD(GSTS, CURMOD, 0, 2)
+REG32(GUCTL1, 0x1c)
+ FIELD(GUCTL1, RESUME_OPMODE_HS_HOST, 10, 1)
+REG32(GSNPSID, 0x20)
+REG32(GGPIO, 0x24)
+ FIELD(GGPIO, GPO, 16, 16)
+ FIELD(GGPIO, GPI, 0, 16)
+REG32(GUID, 0x28)
+REG32(GUCTL, 0x2c)
+ FIELD(GUCTL, REFCLKPER, 22, 10)
+ FIELD(GUCTL, NOEXTRDL, 21, 1)
+ FIELD(GUCTL, RESERVED_20_18, 18, 3)
+ FIELD(GUCTL, SPRSCTRLTRANSEN, 17, 1)
+ FIELD(GUCTL, RESBWHSEPS, 16, 1)
+ FIELD(GUCTL, RESERVED_15, 15, 1)
+ FIELD(GUCTL, USBHSTINAUTORETRYEN, 14, 1)
+ FIELD(GUCTL, ENOVERLAPCHK, 13, 1)
+ FIELD(GUCTL, EXTCAPSUPPTEN, 12, 1)
+ FIELD(GUCTL, INSRTEXTRFSBODI, 11, 1)
+ FIELD(GUCTL, DTCT, 9, 2)
+ FIELD(GUCTL, DTFT, 0, 9)
+REG32(GBUSERRADDRLO, 0x30)
+REG32(GBUSERRADDRHI, 0x34)
+REG32(GHWPARAMS0, 0x40)
+ FIELD(GHWPARAMS0, GHWPARAMS0_31_24, 24, 8)
+ FIELD(GHWPARAMS0, GHWPARAMS0_23_16, 16, 8)
+ FIELD(GHWPARAMS0, GHWPARAMS0_15_8, 8, 8)
+ FIELD(GHWPARAMS0, GHWPARAMS0_7_6, 6, 2)
+ FIELD(GHWPARAMS0, GHWPARAMS0_5_3, 3, 3)
+ FIELD(GHWPARAMS0, GHWPARAMS0_2_0, 0, 3)
+REG32(GHWPARAMS1, 0x44)
+ FIELD(GHWPARAMS1, GHWPARAMS1_31, 31, 1)
+ FIELD(GHWPARAMS1, GHWPARAMS1_30, 30, 1)
+ FIELD(GHWPARAMS1, GHWPARAMS1_29, 29, 1)
+ FIELD(GHWPARAMS1, GHWPARAMS1_28, 28, 1)
+ FIELD(GHWPARAMS1, GHWPARAMS1_27, 27, 1)
+ FIELD(GHWPARAMS1, GHWPARAMS1_26, 26, 1)
+ FIELD(GHWPARAMS1, GHWPARAMS1_25_24, 24, 2)
+ FIELD(GHWPARAMS1, GHWPARAMS1_23, 23, 1)
+ FIELD(GHWPARAMS1, GHWPARAMS1_22_21, 21, 2)
+ FIELD(GHWPARAMS1, GHWPARAMS1_20_15, 15, 6)
+ FIELD(GHWPARAMS1, GHWPARAMS1_14_12, 12, 3)
+ FIELD(GHWPARAMS1, GHWPARAMS1_11_9, 9, 3)
+ FIELD(GHWPARAMS1, GHWPARAMS1_8_6, 6, 3)
+ FIELD(GHWPARAMS1, GHWPARAMS1_5_3, 3, 3)
+ FIELD(GHWPARAMS1, GHWPARAMS1_2_0, 0, 3)
+REG32(GHWPARAMS2, 0x48)
+REG32(GHWPARAMS3, 0x4c)
+ FIELD(GHWPARAMS3, GHWPARAMS3_31, 31, 1)
+ FIELD(GHWPARAMS3, GHWPARAMS3_30_23, 23, 8)
+ FIELD(GHWPARAMS3, GHWPARAMS3_22_18, 18, 5)
+ FIELD(GHWPARAMS3, GHWPARAMS3_17_12, 12, 6)
+ FIELD(GHWPARAMS3, GHWPARAMS3_11, 11, 1)
+ FIELD(GHWPARAMS3, GHWPARAMS3_10, 10, 1)
+ FIELD(GHWPARAMS3, GHWPARAMS3_9_8, 8, 2)
+ FIELD(GHWPARAMS3, GHWPARAMS3_7_6, 6, 2)
+ FIELD(GHWPARAMS3, GHWPARAMS3_5_4, 4, 2)
+ FIELD(GHWPARAMS3, GHWPARAMS3_3_2, 2, 2)
+ FIELD(GHWPARAMS3, GHWPARAMS3_1_0, 0, 2)
+REG32(GHWPARAMS4, 0x50)
+ FIELD(GHWPARAMS4, GHWPARAMS4_31_28, 28, 4)
+ FIELD(GHWPARAMS4, GHWPARAMS4_27_24, 24, 4)
+ FIELD(GHWPARAMS4, GHWPARAMS4_23, 23, 1)
+ FIELD(GHWPARAMS4, GHWPARAMS4_22, 22, 1)
+ FIELD(GHWPARAMS4, GHWPARAMS4_21, 21, 1)
+ FIELD(GHWPARAMS4, GHWPARAMS4_20_17, 17, 4)
+ FIELD(GHWPARAMS4, GHWPARAMS4_16_13, 13, 4)
+ FIELD(GHWPARAMS4, GHWPARAMS4_12, 12, 1)
+ FIELD(GHWPARAMS4, GHWPARAMS4_11, 11, 1)
+ FIELD(GHWPARAMS4, GHWPARAMS4_10_9, 9, 2)
+ FIELD(GHWPARAMS4, GHWPARAMS4_8_7, 7, 2)
+ FIELD(GHWPARAMS4, GHWPARAMS4_6, 6, 1)
+ FIELD(GHWPARAMS4, GHWPARAMS4_5_0, 0, 6)
+REG32(GHWPARAMS5, 0x54)
+ FIELD(GHWPARAMS5, GHWPARAMS5_31_28, 28, 4)
+ FIELD(GHWPARAMS5, GHWPARAMS5_27_22, 22, 6)
+ FIELD(GHWPARAMS5, GHWPARAMS5_21_16, 16, 6)
+ FIELD(GHWPARAMS5, GHWPARAMS5_15_10, 10, 6)
+ FIELD(GHWPARAMS5, GHWPARAMS5_9_4, 4, 6)
+ FIELD(GHWPARAMS5, GHWPARAMS5_3_0, 0, 4)
+REG32(GHWPARAMS6, 0x58)
+ FIELD(GHWPARAMS6, GHWPARAMS6_31_16, 16, 16)
+ FIELD(GHWPARAMS6, BUSFLTRSSUPPORT, 15, 1)
+ FIELD(GHWPARAMS6, BCSUPPORT, 14, 1)
+ FIELD(GHWPARAMS6, OTG_SS_SUPPORT, 13, 1)
+ FIELD(GHWPARAMS6, ADPSUPPORT, 12, 1)
+ FIELD(GHWPARAMS6, HNPSUPPORT, 11, 1)
+ FIELD(GHWPARAMS6, SRPSUPPORT, 10, 1)
+ FIELD(GHWPARAMS6, GHWPARAMS6_9_8, 8, 2)
+ FIELD(GHWPARAMS6, GHWPARAMS6_7, 7, 1)
+ FIELD(GHWPARAMS6, GHWPARAMS6_6, 6, 1)
+ FIELD(GHWPARAMS6, GHWPARAMS6_5_0, 0, 6)
+REG32(GHWPARAMS7, 0x5c)
+ FIELD(GHWPARAMS7, GHWPARAMS7_31_16, 16, 16)
+ FIELD(GHWPARAMS7, GHWPARAMS7_15_0, 0, 16)
+REG32(GDBGFIFOSPACE, 0x60)
+ FIELD(GDBGFIFOSPACE, SPACE_AVAILABLE, 16, 16)
+ FIELD(GDBGFIFOSPACE, RESERVED_15_9, 9, 7)
+ FIELD(GDBGFIFOSPACE, FIFO_QUEUE_SELECT, 0, 9)
+REG32(GUCTL2, 0x9c)
+ FIELD(GUCTL2, RESERVED_31_26, 26, 6)
+ FIELD(GUCTL2, EN_HP_PM_TIMER, 19, 7)
+ FIELD(GUCTL2, NOLOWPWRDUR, 15, 4)
+ FIELD(GUCTL2, RST_ACTBITLATER, 14, 1)
+ FIELD(GUCTL2, RESERVED_13, 13, 1)
+ FIELD(GUCTL2, DISABLECFC, 11, 1)
+REG32(GUSB2PHYCFG, 0x100)
+ FIELD(GUSB2PHYCFG, U2_FREECLK_EXISTS, 30, 1)
+ FIELD(GUSB2PHYCFG, ULPI_LPM_WITH_OPMODE_CHK, 29, 1)
+ FIELD(GUSB2PHYCFG, RESERVED_25, 25, 1)
+ FIELD(GUSB2PHYCFG, LSTRD, 22, 3)
+ FIELD(GUSB2PHYCFG, LSIPD, 19, 3)
+ FIELD(GUSB2PHYCFG, ULPIEXTVBUSINDIACTOR, 18, 1)
+ FIELD(GUSB2PHYCFG, ULPIEXTVBUSDRV, 17, 1)
+ FIELD(GUSB2PHYCFG, RESERVED_16, 16, 1)
+ FIELD(GUSB2PHYCFG, ULPIAUTORES, 15, 1)
+ FIELD(GUSB2PHYCFG, RESERVED_14, 14, 1)
+ FIELD(GUSB2PHYCFG, USBTRDTIM, 10, 4)
+ FIELD(GUSB2PHYCFG, XCVRDLY, 9, 1)
+ FIELD(GUSB2PHYCFG, ENBLSLPM, 8, 1)
+ FIELD(GUSB2PHYCFG, PHYSEL, 7, 1)
+ FIELD(GUSB2PHYCFG, SUSPENDUSB20, 6, 1)
+ FIELD(GUSB2PHYCFG, FSINTF, 5, 1)
+ FIELD(GUSB2PHYCFG, ULPI_UTMI_SEL, 4, 1)
+ FIELD(GUSB2PHYCFG, PHYIF, 3, 1)
+ FIELD(GUSB2PHYCFG, TOUTCAL, 0, 3)
+REG32(GUSB2I2CCTL, 0x140)
+REG32(GUSB2PHYACC_ULPI, 0x180)
+ FIELD(GUSB2PHYACC_ULPI, RESERVED_31_27, 27, 5)
+ FIELD(GUSB2PHYACC_ULPI, DISUIPIDRVR, 26, 1)
+ FIELD(GUSB2PHYACC_ULPI, NEWREGREQ, 25, 1)
+ FIELD(GUSB2PHYACC_ULPI, VSTSDONE, 24, 1)
+ FIELD(GUSB2PHYACC_ULPI, VSTSBSY, 23, 1)
+ FIELD(GUSB2PHYACC_ULPI, REGWR, 22, 1)
+ FIELD(GUSB2PHYACC_ULPI, REGADDR, 16, 6)
+ FIELD(GUSB2PHYACC_ULPI, EXTREGADDR, 8, 8)
+ FIELD(GUSB2PHYACC_ULPI, REGDATA, 0, 8)
+REG32(GTXFIFOSIZ0, 0x200)
+ FIELD(GTXFIFOSIZ0, TXFSTADDR_N, 16, 16)
+ FIELD(GTXFIFOSIZ0, TXFDEP_N, 0, 16)
+REG32(GTXFIFOSIZ1, 0x204)
+ FIELD(GTXFIFOSIZ1, TXFSTADDR_N, 16, 16)
+ FIELD(GTXFIFOSIZ1, TXFDEP_N, 0, 16)
+REG32(GTXFIFOSIZ2, 0x208)
+ FIELD(GTXFIFOSIZ2, TXFSTADDR_N, 16, 16)
+ FIELD(GTXFIFOSIZ2, TXFDEP_N, 0, 16)
+REG32(GTXFIFOSIZ3, 0x20c)
+ FIELD(GTXFIFOSIZ3, TXFSTADDR_N, 16, 16)
+ FIELD(GTXFIFOSIZ3, TXFDEP_N, 0, 16)
+REG32(GTXFIFOSIZ4, 0x210)
+ FIELD(GTXFIFOSIZ4, TXFSTADDR_N, 16, 16)
+ FIELD(GTXFIFOSIZ4, TXFDEP_N, 0, 16)
+REG32(GTXFIFOSIZ5, 0x214)
+ FIELD(GTXFIFOSIZ5, TXFSTADDR_N, 16, 16)
+ FIELD(GTXFIFOSIZ5, TXFDEP_N, 0, 16)
+REG32(GRXFIFOSIZ0, 0x280)
+ FIELD(GRXFIFOSIZ0, RXFSTADDR_N, 16, 16)
+ FIELD(GRXFIFOSIZ0, RXFDEP_N, 0, 16)
+REG32(GRXFIFOSIZ1, 0x284)
+ FIELD(GRXFIFOSIZ1, RXFSTADDR_N, 16, 16)
+ FIELD(GRXFIFOSIZ1, RXFDEP_N, 0, 16)
+REG32(GRXFIFOSIZ2, 0x288)
+ FIELD(GRXFIFOSIZ2, RXFSTADDR_N, 16, 16)
+ FIELD(GRXFIFOSIZ2, RXFDEP_N, 0, 16)
+REG32(GEVNTADRLO_0, 0x300)
+REG32(GEVNTADRHI_0, 0x304)
+REG32(GEVNTSIZ_0, 0x308)
+ FIELD(GEVNTSIZ_0, EVNTINTRPTMASK, 31, 1)
+ FIELD(GEVNTSIZ_0, RESERVED_30_16, 16, 15)
+ FIELD(GEVNTSIZ_0, EVENTSIZ, 0, 16)
+REG32(GEVNTCOUNT_0, 0x30c)
+ FIELD(GEVNTCOUNT_0, EVNT_HANDLER_BUSY, 31, 1)
+ FIELD(GEVNTCOUNT_0, RESERVED_30_16, 16, 15)
+ FIELD(GEVNTCOUNT_0, EVNTCOUNT, 0, 16)
+REG32(GEVNTADRLO_1, 0x310)
+REG32(GEVNTADRHI_1, 0x314)
+REG32(GEVNTSIZ_1, 0x318)
+ FIELD(GEVNTSIZ_1, EVNTINTRPTMASK, 31, 1)
+ FIELD(GEVNTSIZ_1, RESERVED_30_16, 16, 15)
+ FIELD(GEVNTSIZ_1, EVENTSIZ, 0, 16)
+REG32(GEVNTCOUNT_1, 0x31c)
+ FIELD(GEVNTCOUNT_1, EVNT_HANDLER_BUSY, 31, 1)
+ FIELD(GEVNTCOUNT_1, RESERVED_30_16, 16, 15)
+ FIELD(GEVNTCOUNT_1, EVNTCOUNT, 0, 16)
+REG32(GEVNTADRLO_2, 0x320)
+REG32(GEVNTADRHI_2, 0x324)
+REG32(GEVNTSIZ_2, 0x328)
+ FIELD(GEVNTSIZ_2, EVNTINTRPTMASK, 31, 1)
+ FIELD(GEVNTSIZ_2, RESERVED_30_16, 16, 15)
+ FIELD(GEVNTSIZ_2, EVENTSIZ, 0, 16)
+REG32(GEVNTCOUNT_2, 0x32c)
+ FIELD(GEVNTCOUNT_2, EVNT_HANDLER_BUSY, 31, 1)
+ FIELD(GEVNTCOUNT_2, RESERVED_30_16, 16, 15)
+ FIELD(GEVNTCOUNT_2, EVNTCOUNT, 0, 16)
+REG32(GEVNTADRLO_3, 0x330)
+REG32(GEVNTADRHI_3, 0x334)
+REG32(GEVNTSIZ_3, 0x338)
+ FIELD(GEVNTSIZ_3, EVNTINTRPTMASK, 31, 1)
+ FIELD(GEVNTSIZ_3, RESERVED_30_16, 16, 15)
+ FIELD(GEVNTSIZ_3, EVENTSIZ, 0, 16)
+REG32(GEVNTCOUNT_3, 0x33c)
+ FIELD(GEVNTCOUNT_3, EVNT_HANDLER_BUSY, 31, 1)
+ FIELD(GEVNTCOUNT_3, RESERVED_30_16, 16, 15)
+ FIELD(GEVNTCOUNT_3, EVNTCOUNT, 0, 16)
+REG32(GHWPARAMS8, 0x500)
+REG32(GTXFIFOPRIDEV, 0x510)
+ FIELD(GTXFIFOPRIDEV, RESERVED_31_N, 6, 26)
+ FIELD(GTXFIFOPRIDEV, GTXFIFOPRIDEV, 0, 6)
+REG32(GTXFIFOPRIHST, 0x518)
+ FIELD(GTXFIFOPRIHST, RESERVED_31_16, 3, 29)
+ FIELD(GTXFIFOPRIHST, GTXFIFOPRIHST, 0, 3)
+REG32(GRXFIFOPRIHST, 0x51c)
+ FIELD(GRXFIFOPRIHST, RESERVED_31_16, 3, 29)
+ FIELD(GRXFIFOPRIHST, GRXFIFOPRIHST, 0, 3)
+REG32(GDMAHLRATIO, 0x524)
+ FIELD(GDMAHLRATIO, RESERVED_31_13, 13, 19)
+ FIELD(GDMAHLRATIO, HSTRXFIFO, 8, 5)
+ FIELD(GDMAHLRATIO, RESERVED_7_5, 5, 3)
+ FIELD(GDMAHLRATIO, HSTTXFIFO, 0, 5)
+REG32(GFLADJ, 0x530)
+ FIELD(GFLADJ, GFLADJ_REFCLK_240MHZDECR_PLS1, 31, 1)
+ FIELD(GFLADJ, GFLADJ_REFCLK_240MHZ_DECR, 24, 7)
+ FIELD(GFLADJ, GFLADJ_REFCLK_LPM_SEL, 23, 1)
+ FIELD(GFLADJ, RESERVED_22, 22, 1)
+ FIELD(GFLADJ, GFLADJ_REFCLK_FLADJ, 8, 14)
+ FIELD(GFLADJ, GFLADJ_30MHZ_SDBND_SEL, 7, 1)
+ FIELD(GFLADJ, GFLADJ_30MHZ, 0, 6)
+
+static void reset_csr(USBDWC3 * s)
+{
+ int i = 0;
+ /*
+ * We reset all CSR regs except GCTL, GUCTL, GSTS, GSNPSID, GGPIO, GUID,
+ * GUSB2PHYCFGn registers and GUSB3PIPECTLn registers. We will skip PHY
+ * register as we don't implement them.
+ */
+ for (i = 0; i < R_GCTL; i++) {
+ register_reset(&s->regs_info[i]);
+ }
+
+ for (i = R_GCTL; i < R_GBUSERRADDRLO; i++) {
+ if (i == R_GUCTL1 || i == R_GPMSTS) {
+ register_reset(&s->regs_info[i]);
+ } else {
+ continue;
+ }
+ }
+
+ for (i = R_GBUSERRADDRLO; i < USB_DWC3_R_MAX; i++) {
+ register_reset(&s->regs_info[i]);
+ }
+
+ xhci_sysbus_reset(DEVICE(&s->sysbus_xhci));
+}
+
+static void usb_dwc3_gctl_postw(RegisterInfo *reg, uint64_t val64)
+{
+ USBDWC3 *s = USB_DWC3(reg->opaque);
+
+ if (ARRAY_FIELD_EX32(s->regs, GCTL, CORESOFTRESET)) {
+ reset_csr(s);
+ }
+}
+
+static void usb_dwc3_guid_postw(RegisterInfo *reg, uint64_t val64)
+{
+ USBDWC3 *s = USB_DWC3(reg->opaque);
+
+ s->regs[R_GUID] = s->cfg.dwc_usb3_user;
+}
+
+static void usb_dwc3_unimpl_postw(RegisterInfo *reg, uint64_t val64)
+{
+ qemu_log_mask(LOG_UNIMP, "%s not supported\n", reg->access->name);
+}
+
+static uint64_t usb_dwc3_unimpl_postr(RegisterInfo *reg, uint64_t val64)
+{
+ qemu_log_mask(LOG_UNIMP, "%s not supported\n", reg->access->name);
+ return val64;
+}
+
+static const RegisterAccessInfo usb_dwc3_regs_info[] = {
+ { .name = "GSBUSCFG0", .addr = A_GSBUSCFG0,
+ .ro = 0xf300,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GSBUSCFG1", .addr = A_GSBUSCFG1,
+ .reset = 0x300,
+ .ro = 0xffffe0ff,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GTXTHRCFG", .addr = A_GTXTHRCFG,
+ .ro = 0xd000ffff,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GRXTHRCFG", .addr = A_GRXTHRCFG,
+ .ro = 0xd007e000,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GCTL", .addr = A_GCTL,
+ .reset = 0x30c13004, .post_write = usb_dwc3_gctl_postw,
+ },{ .name = "GPMSTS", .addr = A_GPMSTS,
+ .ro = 0xfffffff,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GSTS", .addr = A_GSTS,
+ .reset = 0x7e800000,
+ .ro = 0xffffffcf,
+ .w1c = 0x30,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GUCTL1", .addr = A_GUCTL1,
+ .reset = 0x198a,
+ .ro = 0x7800,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GSNPSID", .addr = A_GSNPSID,
+ .reset = 0x5533330a,
+ .ro = 0xffffffff,
+ },{ .name = "GGPIO", .addr = A_GGPIO,
+ .ro = 0xffff,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GUID", .addr = A_GUID,
+ .reset = 0x12345678, .post_write = usb_dwc3_guid_postw,
+ },{ .name = "GUCTL", .addr = A_GUCTL,
+ .reset = 0x0c808010,
+ .ro = 0x1c8000,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GBUSERRADDRLO", .addr = A_GBUSERRADDRLO,
+ .ro = 0xffffffff,
+ .post_read = usb_dwc3_unimpl_postr,
+ },{ .name = "GBUSERRADDRHI", .addr = A_GBUSERRADDRHI,
+ .ro = 0xffffffff,
+ .post_read = usb_dwc3_unimpl_postr,
+ },{ .name = "GHWPARAMS0", .addr = A_GHWPARAMS0,
+ .ro = 0xffffffff,
+ },{ .name = "GHWPARAMS1", .addr = A_GHWPARAMS1,
+ .ro = 0xffffffff,
+ },{ .name = "GHWPARAMS2", .addr = A_GHWPARAMS2,
+ .ro = 0xffffffff,
+ },{ .name = "GHWPARAMS3", .addr = A_GHWPARAMS3,
+ .ro = 0xffffffff,
+ },{ .name = "GHWPARAMS4", .addr = A_GHWPARAMS4,
+ .ro = 0xffffffff,
+ },{ .name = "GHWPARAMS5", .addr = A_GHWPARAMS5,
+ .ro = 0xffffffff,
+ },{ .name = "GHWPARAMS6", .addr = A_GHWPARAMS6,
+ .ro = 0xffffffff,
+ },{ .name = "GHWPARAMS7", .addr = A_GHWPARAMS7,
+ .ro = 0xffffffff,
+ },{ .name = "GDBGFIFOSPACE", .addr = A_GDBGFIFOSPACE,
+ .reset = 0xa0000,
+ .ro = 0xfffffe00,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GUCTL2", .addr = A_GUCTL2,
+ .reset = 0x40d,
+ .ro = 0x2000,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GUSB2PHYCFG", .addr = A_GUSB2PHYCFG,
+ .reset = 0x40102410,
+ .ro = 0x1e014030,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GUSB2I2CCTL", .addr = A_GUSB2I2CCTL,
+ .ro = 0xffffffff,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GUSB2PHYACC_ULPI", .addr = A_GUSB2PHYACC_ULPI,
+ .ro = 0xfd000000,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GTXFIFOSIZ0", .addr = A_GTXFIFOSIZ0,
+ .reset = 0x2c7000a,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GTXFIFOSIZ1", .addr = A_GTXFIFOSIZ1,
+ .reset = 0x2d10103,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GTXFIFOSIZ2", .addr = A_GTXFIFOSIZ2,
+ .reset = 0x3d40103,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GTXFIFOSIZ3", .addr = A_GTXFIFOSIZ3,
+ .reset = 0x4d70083,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GTXFIFOSIZ4", .addr = A_GTXFIFOSIZ4,
+ .reset = 0x55a0083,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GTXFIFOSIZ5", .addr = A_GTXFIFOSIZ5,
+ .reset = 0x5dd0083,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GRXFIFOSIZ0", .addr = A_GRXFIFOSIZ0,
+ .reset = 0x1c20105,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GRXFIFOSIZ1", .addr = A_GRXFIFOSIZ1,
+ .reset = 0x2c70000,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GRXFIFOSIZ2", .addr = A_GRXFIFOSIZ2,
+ .reset = 0x2c70000,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GEVNTADRLO_0", .addr = A_GEVNTADRLO_0,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GEVNTADRHI_0", .addr = A_GEVNTADRHI_0,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GEVNTSIZ_0", .addr = A_GEVNTSIZ_0,
+ .ro = 0x7fff0000,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GEVNTCOUNT_0", .addr = A_GEVNTCOUNT_0,
+ .ro = 0x7fff0000,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GEVNTADRLO_1", .addr = A_GEVNTADRLO_1,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GEVNTADRHI_1", .addr = A_GEVNTADRHI_1,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GEVNTSIZ_1", .addr = A_GEVNTSIZ_1,
+ .ro = 0x7fff0000,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GEVNTCOUNT_1", .addr = A_GEVNTCOUNT_1,
+ .ro = 0x7fff0000,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GEVNTADRLO_2", .addr = A_GEVNTADRLO_2,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GEVNTADRHI_2", .addr = A_GEVNTADRHI_2,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GEVNTSIZ_2", .addr = A_GEVNTSIZ_2,
+ .ro = 0x7fff0000,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GEVNTCOUNT_2", .addr = A_GEVNTCOUNT_2,
+ .ro = 0x7fff0000,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GEVNTADRLO_3", .addr = A_GEVNTADRLO_3,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GEVNTADRHI_3", .addr = A_GEVNTADRHI_3,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GEVNTSIZ_3", .addr = A_GEVNTSIZ_3,
+ .ro = 0x7fff0000,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GEVNTCOUNT_3", .addr = A_GEVNTCOUNT_3,
+ .ro = 0x7fff0000,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GHWPARAMS8", .addr = A_GHWPARAMS8,
+ .ro = 0xffffffff,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GTXFIFOPRIDEV", .addr = A_GTXFIFOPRIDEV,
+ .ro = 0xffffffc0,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GTXFIFOPRIHST", .addr = A_GTXFIFOPRIHST,
+ .ro = 0xfffffff8,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GRXFIFOPRIHST", .addr = A_GRXFIFOPRIHST,
+ .ro = 0xfffffff8,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GDMAHLRATIO", .addr = A_GDMAHLRATIO,
+ .ro = 0xffffe0e0,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ },{ .name = "GFLADJ", .addr = A_GFLADJ,
+ .reset = 0xc83f020,
+ .rsvd = 0x40,
+ .ro = 0x400040,
+ .post_read = usb_dwc3_unimpl_postr,
+ .post_write = usb_dwc3_unimpl_postw,
+ }
+};
+
+static void usb_dwc3_reset(DeviceState *dev)
+{
+ USBDWC3 *s = USB_DWC3(dev);
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
+ register_reset(&s->regs_info[i]);
+ }
+
+ /*
+ * Device Configuration
+ */
+ s->regs[R_GHWPARAMS0] = 0x40204048 | s->cfg.mode;
+ s->regs[R_GHWPARAMS1] = 0x222493b;
+ s->regs[R_GHWPARAMS2] = 0x12345678;
+ s->regs[R_GHWPARAMS3] = 0x618c088;
+ s->regs[R_GHWPARAMS4] = 0x47822004;
+ s->regs[R_GHWPARAMS5] = 0x4202088;
+ s->regs[R_GHWPARAMS6] = 0x7850c20;
+ s->regs[R_GHWPARAMS7] = 0x0;
+ s->regs[R_GHWPARAMS8] = 0x478;
+
+ xhci_sysbus_reset(DEVICE(&s->sysbus_xhci));
+}
+
+static const MemoryRegionOps usb_dwc3_ops = {
+ .read = register_read_memory,
+ .write = register_write_memory,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
+
+static void usb_dwc3_realize(DeviceState *dev, Error **errp)
+{
+ USBDWC3 *s = USB_DWC3(dev);
+ Error *err = NULL;
+
+ sysbus_realize(SYS_BUS_DEVICE(&s->sysbus_xhci), &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+}
+
+static void usb_dwc3_init(Object *obj)
+{
+ USBDWC3 *s = USB_DWC3(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ RegisterInfoArray *reg_array;
+
+ memory_region_init(&s->iomem, obj, TYPE_USB_DWC3, USB_DWC3_R_MAX * 4);
+ reg_array =
+ register_init_block32(DEVICE(obj), usb_dwc3_regs_info,
+ ARRAY_SIZE(usb_dwc3_regs_info),
+ s->regs_info, s->regs,
+ &usb_dwc3_ops,
+ USB_DWC3_ERR_DEBUG,
+ USB_DWC3_R_MAX * 4);
+ memory_region_add_subregion(&s->iomem,
+ 0x0,
+ ®_array->mem);
+ sysbus_init_mmio(sbd, &s->iomem);
+ object_initialize_child(obj, "dwc3-xhci", &s->sysbus_xhci,
+ TYPE_XHCI_SYSBUS);
+ qdev_alias_all_properties(DEVICE(&s->sysbus_xhci), obj);
+
+ s->cfg.mode = HOST_MODE;
+}
+
+static Property usb_dwc3_properties[] = {
+ DEFINE_PROP_UINT32("DWC_USB3_USERID", USBDWC3, cfg.dwc_usb3_user,
+ 0x12345678),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void usb_dwc3_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = usb_dwc3_reset;
+ dc->realize = usb_dwc3_realize;
+ device_class_set_props(dc, usb_dwc3_properties);
+}
+
+static const TypeInfo usb_dwc3_info = {
+ .name = TYPE_USB_DWC3,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(USBDWC3),
+ .class_init = usb_dwc3_class_init,
+ .instance_init = usb_dwc3_init,
+};
+
+static void usb_dwc3_register_types(void)
+{
+ type_register_static(&usb_dwc3_info);
+}
+
+type_init(usb_dwc3_register_types)
diff --git a/hw/usb/meson.build b/hw/usb/meson.build
index 934e4fa..962fbc0 100644
--- a/hw/usb/meson.build
+++ b/hw/usb/meson.build
@@ -26,6 +26,7 @@ softmmu_ss.add(when: 'CONFIG_USB_XHCI_SYSBUS', if_true: files('hcd-xhci-sysbus.c
softmmu_ss.add(when: 'CONFIG_USB_XHCI_NEC', if_true: files('hcd-xhci-nec.c'))
softmmu_ss.add(when: 'CONFIG_USB_MUSB', if_true: files('hcd-musb.c'))
softmmu_ss.add(when: 'CONFIG_USB_DWC2', if_true: files('hcd-dwc2.c'))
+softmmu_ss.add(when: 'CONFIG_USB_DWC3', if_true: files('hcd-dwc3.c'))
softmmu_ss.add(when: 'CONFIG_TUSB6010', if_true: files('tusb6010.c'))
softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('chipidea.c'))
diff --git a/include/hw/usb/hcd-dwc3.h b/include/hw/usb/hcd-dwc3.h
new file mode 100644
index 0000000..586968d
--- /dev/null
+++ b/include/hw/usb/hcd-dwc3.h
@@ -0,0 +1,55 @@
+/*
+ * QEMU model of the USB DWC3 host controller emulation.
+ *
+ * Copyright (c) 2020 Xilinx Inc.
+ *
+ * Written by Vikram Garhwal<fnu.vikram@xilinx.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef HCD_DWC3_H
+#define HCD_DWC3_H
+
+#include "hw/usb/hcd-xhci.h"
+#include "hw/usb/hcd-xhci-sysbus.h"
+
+#define TYPE_USB_DWC3 "usb_dwc3"
+
+#define USB_DWC3(obj) \
+ OBJECT_CHECK(USBDWC3, (obj), TYPE_USB_DWC3)
+
+#define USB_DWC3_R_MAX ((0x530 / 4) + 1)
+
+typedef struct USBDWC3 {
+ SysBusDevice parent_obj;
+ MemoryRegion iomem;
+ MemoryRegion fifos;
+ XHCISysbusState sysbus_xhci;
+
+ uint32_t regs[USB_DWC3_R_MAX];
+ RegisterInfo regs_info[USB_DWC3_R_MAX];
+
+ struct {
+ uint8_t mode;
+ uint32_t dwc_usb3_user;
+ } cfg;
+
+} USBDWC3;
+
+#endif
--
2.7.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v6 7/7] Versal: Connect DWC3 controller with virt-versal
2020-09-16 11:41 [PATCH v6 0/7] Make hcd-xhci independent of pci hooks Sai Pavan Boddu
` (6 preceding siblings ...)
2020-09-16 11:41 ` [PATCH v6 6/7] usb: Add DWC3 model Sai Pavan Boddu
@ 2020-09-16 11:41 ` Sai Pavan Boddu
2020-09-16 12:30 ` Edgar E. Iglesias
7 siblings, 1 reply; 14+ messages in thread
From: Sai Pavan Boddu @ 2020-09-16 11:41 UTC (permalink / raw)
To: Peter Maydell, Markus Armbruster,
'Marc-André Lureau', Paolo Bonzini, Gerd Hoffmann,
Edgar Iglesias, Francisco Eduardo Iglesias
Cc: Eduardo Habkost, Vikram Garhwal, qemu-devel, Paul Zimmerman,
Sai Pavan Boddu, Alistair Francis, Ying Fang,
'Philippe Mathieu-Daudé'
From: Vikram Garhwal <fnu.vikram@xilinx.com>
Connect dwc3 controller and usb2-reg module to xlnx-versal SOC, its placed
in iou of lpd domain and configure it as dual port host controller. Add the
respective guest dts nodes for "xlnx-versal-virt" machine.
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
---
hw/arm/xlnx-versal-virt.c | 55 ++++++++++++++++++++++++++++++++++++++++++++
hw/arm/xlnx-versal.c | 34 +++++++++++++++++++++++++++
include/hw/arm/xlnx-versal.h | 12 ++++++++++
3 files changed, 101 insertions(+)
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 1f9409e..2b4564b 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -41,6 +41,8 @@ struct VersalVirt {
uint32_t ethernet_phy[2];
uint32_t clk_125Mhz;
uint32_t clk_25Mhz;
+ uint32_t usb;
+ uint32_t dwc;
} phandle;
struct arm_boot_info binfo;
@@ -68,6 +70,8 @@ static void fdt_create(VersalVirt *s)
s->phandle.clk_25Mhz = qemu_fdt_alloc_phandle(s->fdt);
s->phandle.clk_125Mhz = qemu_fdt_alloc_phandle(s->fdt);
+ s->phandle.usb = qemu_fdt_alloc_phandle(s->fdt);
+ s->phandle.dwc = qemu_fdt_alloc_phandle(s->fdt);
/* Create /chosen node for load_dtb. */
qemu_fdt_add_subnode(s->fdt, "/chosen");
@@ -150,6 +154,56 @@ static void fdt_add_timer_nodes(VersalVirt *s)
compat, sizeof(compat));
}
+static void fdt_add_usb_xhci_nodes(VersalVirt *s)
+{
+ const char clocknames[] = "bus_clk\0ref_clk";
+ char *name = g_strdup_printf("/usb@%" PRIx32, MM_USB2_CTRL_REGS);
+ const char compat[] = "xlnx,versal-dwc3";
+ qemu_fdt_add_subnode(s->fdt, name);
+ qemu_fdt_setprop(s->fdt, name, "compatible",
+ compat, sizeof(compat));
+ qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
+ 2, MM_USB2_CTRL_REGS,
+ 2, MM_USB2_CTRL_REGS_SIZE);
+ qemu_fdt_setprop(s->fdt, name, "clock-names",
+ clocknames, sizeof(clocknames));
+ qemu_fdt_setprop_cells(s->fdt, name, "clocks",
+ s->phandle.clk_25Mhz, s->phandle.clk_125Mhz);
+ qemu_fdt_setprop(s->fdt, name, "ranges", NULL, 0);
+ qemu_fdt_setprop_cell(s->fdt, name, "#address-cells", 2);
+ qemu_fdt_setprop_cell(s->fdt, name, "#size-cells", 2);
+ qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.usb);
+ g_free(name);
+
+ {
+ const char irq_name[] = "dwc_usb3";
+ const char compat[] = "snps,dwc3";
+ name = g_strdup_printf("/usb@%" PRIx32 "/dwc3@%" PRIx32,
+ MM_USB2_CTRL_REGS, MM_USB_XHCI_0);
+ qemu_fdt_add_subnode(s->fdt, name);
+ qemu_fdt_setprop(s->fdt, name, "compatible",
+ compat, sizeof(compat));
+ qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
+ 2, MM_USB_XHCI_0, 2, MM_USB_XHCI_0_SIZE);
+ qemu_fdt_setprop(s->fdt, name, "interrupt-names",
+ irq_name, sizeof(irq_name));
+ qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
+ GIC_FDT_IRQ_TYPE_SPI, VERSAL_USB0_IRQ_0,
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+ qemu_fdt_setprop_cell(s->fdt, name,
+ "snps,quirk-frame-length-adjustment", 0x20);
+ qemu_fdt_setprop_cells(s->fdt, name, "#stream-id-cells", 1);
+ qemu_fdt_setprop_string(s->fdt, name, "dr_mode", "host");
+ qemu_fdt_setprop_string(s->fdt, name, "phy-names", "usb3-phy");
+ qemu_fdt_setprop(s->fdt, name, "snps,dis_u2_susphy_quirk", NULL, 0);
+ qemu_fdt_setprop(s->fdt, name, "snps,dis_u3_susphy_quirk", NULL, 0);
+ qemu_fdt_setprop(s->fdt, name, "snps,refclk_fladj", NULL, 0);
+ qemu_fdt_setprop(s->fdt, name, "snps,mask_phy_reset", NULL, 0);
+ qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.dwc);
+ qemu_fdt_setprop_string(s->fdt, name, "maximum-speed", "high-speed");
+ g_free(name);
+ }
+}
static void fdt_add_uart_nodes(VersalVirt *s)
{
uint64_t addrs[] = { MM_UART1, MM_UART0 };
@@ -517,6 +571,7 @@ static void versal_virt_init(MachineState *machine)
fdt_add_gic_nodes(s);
fdt_add_timer_nodes(s);
fdt_add_zdma_nodes(s);
+ fdt_add_usb_xhci_nodes(s);
fdt_add_sd_nodes(s);
fdt_add_rtc_node(s);
fdt_add_cpu_nodes(s, psci_conduit);
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 12ba6c4..88f7dc8 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -145,6 +145,39 @@ static void versal_create_uarts(Versal *s, qemu_irq *pic)
}
}
+static void versal_create_usbs(Versal *s, qemu_irq *pic)
+{
+ DeviceState *dev, *xhci_dev;
+ MemoryRegion *mr;
+
+ object_initialize_child(OBJECT(s), "dwc3-0", &s->lpd.iou.dwc3,
+ TYPE_USB_DWC3);
+ dev = DEVICE(&s->lpd.iou.dwc3);
+ xhci_dev = DEVICE(&s->lpd.iou.dwc3.sysbus_xhci);
+
+ object_property_set_link(OBJECT(xhci_dev), "dma", OBJECT(&s->mr_ps),
+ &error_abort);
+ qdev_prop_set_uint32(xhci_dev, "intrs", 1);
+ qdev_prop_set_uint32(xhci_dev, "slots", 2);
+
+ sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
+
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
+ memory_region_add_subregion(&s->mr_ps, MM_USB_XHCI_0_DWC3_GLOBAL, mr);
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(xhci_dev), 0);
+ memory_region_add_subregion(&s->mr_ps, MM_USB_XHCI_0, mr);
+
+ sysbus_connect_irq(SYS_BUS_DEVICE(xhci_dev), 0, pic[VERSAL_USB0_IRQ_0]);
+
+ object_initialize_child(OBJECT(s), "usb2reg-0", &s->lpd.iou.Usb2Regs,
+ TYPE_XILINX_VERSAL_USB2_CTRL_REGS);
+ dev = DEVICE(&s->lpd.iou.Usb2Regs);
+ sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
+
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
+ memory_region_add_subregion(&s->mr_ps, MM_USB2_CTRL_REGS, mr);
+}
+
static void versal_create_gems(Versal *s, qemu_irq *pic)
{
int i;
@@ -333,6 +366,7 @@ static void versal_realize(DeviceState *dev, Error **errp)
versal_create_apu_cpus(s);
versal_create_apu_gic(s, pic);
versal_create_uarts(s, pic);
+ versal_create_usbs(s, pic);
versal_create_gems(s, pic);
versal_create_admas(s, pic);
versal_create_sds(s, pic);
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index eaa9023..a428933 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -21,6 +21,8 @@
#include "hw/net/cadence_gem.h"
#include "hw/rtc/xlnx-zynqmp-rtc.h"
#include "qom/object.h"
+#include "hw/usb/hcd-dwc3.h"
+#include "hw/misc/xlnx-versal-usb2-ctrl-regs.h"
#define TYPE_XLNX_VERSAL "xlnx-versal"
typedef struct Versal Versal;
@@ -61,6 +63,8 @@ struct Versal {
PL011State uart[XLNX_VERSAL_NR_UARTS];
CadenceGEMState gem[XLNX_VERSAL_NR_GEMS];
XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS];
+ USBDWC3 dwc3;
+ VersalUsb2CtrlRegs Usb2Regs;
} iou;
} lpd;
@@ -90,6 +94,7 @@ struct Versal {
#define VERSAL_UART0_IRQ_0 18
#define VERSAL_UART1_IRQ_0 19
+#define VERSAL_USB0_IRQ_0 22
#define VERSAL_GEM0_IRQ_0 56
#define VERSAL_GEM0_WAKE_IRQ_0 57
#define VERSAL_GEM1_IRQ_0 58
@@ -127,6 +132,13 @@ struct Versal {
#define MM_OCM 0xfffc0000U
#define MM_OCM_SIZE 0x40000
+#define MM_USB2_CTRL_REGS 0xFF9D0000
+#define MM_USB2_CTRL_REGS_SIZE 0x10000
+
+#define MM_USB_XHCI_0 0xFE200000
+#define MM_USB_XHCI_0_SIZE 0x10000
+#define MM_USB_XHCI_0_DWC3_GLOBAL (MM_USB_XHCI_0 + 0xC100)
+
#define MM_TOP_DDR 0x0
#define MM_TOP_DDR_SIZE 0x80000000U
#define MM_TOP_DDR_2 0x800000000ULL
--
2.7.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v6 7/7] Versal: Connect DWC3 controller with virt-versal
2020-09-16 11:41 ` [PATCH v6 7/7] Versal: Connect DWC3 controller with virt-versal Sai Pavan Boddu
@ 2020-09-16 12:30 ` Edgar E. Iglesias
2020-09-16 14:15 ` Sai Pavan Boddu
0 siblings, 1 reply; 14+ messages in thread
From: Edgar E. Iglesias @ 2020-09-16 12:30 UTC (permalink / raw)
To: Sai Pavan Boddu
Cc: Francisco Eduardo Iglesias, Peter Maydell, Eduardo Habkost,
Vikram Garhwal, Markus Armbruster, qemu-devel, Sai Pavan Boddu,
Edgar Iglesias, Alistair Francis, Gerd Hoffmann,
'Marc-André Lureau', Ying Fang, Paolo Bonzini,
Paul Zimmerman, 'Philippe Mathieu-Daudé'
On Wed, Sep 16, 2020 at 05:11:09PM +0530, Sai Pavan Boddu wrote:
> From: Vikram Garhwal <fnu.vikram@xilinx.com>
>
> Connect dwc3 controller and usb2-reg module to xlnx-versal SOC, its placed
> in iou of lpd domain and configure it as dual port host controller. Add the
> respective guest dts nodes for "xlnx-versal-virt" machine.
>
> Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
> Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
> ---
> hw/arm/xlnx-versal-virt.c | 55 ++++++++++++++++++++++++++++++++++++++++++++
> hw/arm/xlnx-versal.c | 34 +++++++++++++++++++++++++++
> include/hw/arm/xlnx-versal.h | 12 ++++++++++
> 3 files changed, 101 insertions(+)
>
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index 1f9409e..2b4564b 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -41,6 +41,8 @@ struct VersalVirt {
> uint32_t ethernet_phy[2];
> uint32_t clk_125Mhz;
> uint32_t clk_25Mhz;
> + uint32_t usb;
> + uint32_t dwc;
> } phandle;
> struct arm_boot_info binfo;
>
> @@ -68,6 +70,8 @@ static void fdt_create(VersalVirt *s)
> s->phandle.clk_25Mhz = qemu_fdt_alloc_phandle(s->fdt);
> s->phandle.clk_125Mhz = qemu_fdt_alloc_phandle(s->fdt);
>
> + s->phandle.usb = qemu_fdt_alloc_phandle(s->fdt);
> + s->phandle.dwc = qemu_fdt_alloc_phandle(s->fdt);
> /* Create /chosen node for load_dtb. */
> qemu_fdt_add_subnode(s->fdt, "/chosen");
>
> @@ -150,6 +154,56 @@ static void fdt_add_timer_nodes(VersalVirt *s)
> compat, sizeof(compat));
> }
>
> +static void fdt_add_usb_xhci_nodes(VersalVirt *s)
> +{
> + const char clocknames[] = "bus_clk\0ref_clk";
> + char *name = g_strdup_printf("/usb@%" PRIx32, MM_USB2_CTRL_REGS);
> + const char compat[] = "xlnx,versal-dwc3";
Need a blank line here.
> + qemu_fdt_add_subnode(s->fdt, name);
> + qemu_fdt_setprop(s->fdt, name, "compatible",
> + compat, sizeof(compat));
> + qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
> + 2, MM_USB2_CTRL_REGS,
> + 2, MM_USB2_CTRL_REGS_SIZE);
> + qemu_fdt_setprop(s->fdt, name, "clock-names",
> + clocknames, sizeof(clocknames));
> + qemu_fdt_setprop_cells(s->fdt, name, "clocks",
> + s->phandle.clk_25Mhz, s->phandle.clk_125Mhz);
> + qemu_fdt_setprop(s->fdt, name, "ranges", NULL, 0);
> + qemu_fdt_setprop_cell(s->fdt, name, "#address-cells", 2);
> + qemu_fdt_setprop_cell(s->fdt, name, "#size-cells", 2);
> + qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.usb);
> + g_free(name);
> +
> + {
> + const char irq_name[] = "dwc_usb3";
> + const char compat[] = "snps,dwc3";
Here too.
> + name = g_strdup_printf("/usb@%" PRIx32 "/dwc3@%" PRIx32,
> + MM_USB2_CTRL_REGS, MM_USB_XHCI_0);
> + qemu_fdt_add_subnode(s->fdt, name);
> + qemu_fdt_setprop(s->fdt, name, "compatible",
> + compat, sizeof(compat));
> + qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
> + 2, MM_USB_XHCI_0, 2, MM_USB_XHCI_0_SIZE);
> + qemu_fdt_setprop(s->fdt, name, "interrupt-names",
> + irq_name, sizeof(irq_name));
> + qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
> + GIC_FDT_IRQ_TYPE_SPI, VERSAL_USB0_IRQ_0,
> + GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> + qemu_fdt_setprop_cell(s->fdt, name,
> + "snps,quirk-frame-length-adjustment", 0x20);
> + qemu_fdt_setprop_cells(s->fdt, name, "#stream-id-cells", 1);
> + qemu_fdt_setprop_string(s->fdt, name, "dr_mode", "host");
> + qemu_fdt_setprop_string(s->fdt, name, "phy-names", "usb3-phy");
> + qemu_fdt_setprop(s->fdt, name, "snps,dis_u2_susphy_quirk", NULL, 0);
> + qemu_fdt_setprop(s->fdt, name, "snps,dis_u3_susphy_quirk", NULL, 0);
> + qemu_fdt_setprop(s->fdt, name, "snps,refclk_fladj", NULL, 0);
> + qemu_fdt_setprop(s->fdt, name, "snps,mask_phy_reset", NULL, 0);
> + qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.dwc);
> + qemu_fdt_setprop_string(s->fdt, name, "maximum-speed", "high-speed");
> + g_free(name);
> + }
> +}
> static void fdt_add_uart_nodes(VersalVirt *s)
> {
> uint64_t addrs[] = { MM_UART1, MM_UART0 };
> @@ -517,6 +571,7 @@ static void versal_virt_init(MachineState *machine)
> fdt_add_gic_nodes(s);
> fdt_add_timer_nodes(s);
> fdt_add_zdma_nodes(s);
> + fdt_add_usb_xhci_nodes(s);
> fdt_add_sd_nodes(s);
> fdt_add_rtc_node(s);
> fdt_add_cpu_nodes(s, psci_conduit);
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index 12ba6c4..88f7dc8 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -145,6 +145,39 @@ static void versal_create_uarts(Versal *s, qemu_irq *pic)
> }
> }
>
> +static void versal_create_usbs(Versal *s, qemu_irq *pic)
> +{
> + DeviceState *dev, *xhci_dev;
> + MemoryRegion *mr;
> +
> + object_initialize_child(OBJECT(s), "dwc3-0", &s->lpd.iou.dwc3,
> + TYPE_USB_DWC3);
> + dev = DEVICE(&s->lpd.iou.dwc3);
> + xhci_dev = DEVICE(&s->lpd.iou.dwc3.sysbus_xhci);
> +
> + object_property_set_link(OBJECT(xhci_dev), "dma", OBJECT(&s->mr_ps),
> + &error_abort);
> + qdev_prop_set_uint32(xhci_dev, "intrs", 1);
> + qdev_prop_set_uint32(xhci_dev, "slots", 2);
> +
> + sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
> +
> + mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
> + memory_region_add_subregion(&s->mr_ps, MM_USB_XHCI_0_DWC3_GLOBAL, mr);
> + mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(xhci_dev), 0);
> + memory_region_add_subregion(&s->mr_ps, MM_USB_XHCI_0, mr);
> +
> + sysbus_connect_irq(SYS_BUS_DEVICE(xhci_dev), 0, pic[VERSAL_USB0_IRQ_0]);
> +
> + object_initialize_child(OBJECT(s), "usb2reg-0", &s->lpd.iou.Usb2Regs,
> + TYPE_XILINX_VERSAL_USB2_CTRL_REGS);
> + dev = DEVICE(&s->lpd.iou.Usb2Regs);
> + sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
> +
> + mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
> + memory_region_add_subregion(&s->mr_ps, MM_USB2_CTRL_REGS, mr);
> +}
> +
> static void versal_create_gems(Versal *s, qemu_irq *pic)
> {
> int i;
> @@ -333,6 +366,7 @@ static void versal_realize(DeviceState *dev, Error **errp)
> versal_create_apu_cpus(s);
> versal_create_apu_gic(s, pic);
> versal_create_uarts(s, pic);
> + versal_create_usbs(s, pic);
> versal_create_gems(s, pic);
> versal_create_admas(s, pic);
> versal_create_sds(s, pic);
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index eaa9023..a428933 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -21,6 +21,8 @@
> #include "hw/net/cadence_gem.h"
> #include "hw/rtc/xlnx-zynqmp-rtc.h"
> #include "qom/object.h"
> +#include "hw/usb/hcd-dwc3.h"
> +#include "hw/misc/xlnx-versal-usb2-ctrl-regs.h"
>
> #define TYPE_XLNX_VERSAL "xlnx-versal"
> typedef struct Versal Versal;
> @@ -61,6 +63,8 @@ struct Versal {
> PL011State uart[XLNX_VERSAL_NR_UARTS];
> CadenceGEMState gem[XLNX_VERSAL_NR_GEMS];
> XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS];
> + USBDWC3 dwc3;
> + VersalUsb2CtrlRegs Usb2Regs;
Can you please add a sub-struct for the usb stuff?
e.g:
struct {
USBDWC3 dwc3;
VersalUsb2CtrlRegs regs;
} usb;
> } iou;
> } lpd;
>
> @@ -90,6 +94,7 @@ struct Versal {
>
> #define VERSAL_UART0_IRQ_0 18
> #define VERSAL_UART1_IRQ_0 19
> +#define VERSAL_USB0_IRQ_0 22
> #define VERSAL_GEM0_IRQ_0 56
> #define VERSAL_GEM0_WAKE_IRQ_0 57
> #define VERSAL_GEM1_IRQ_0 58
> @@ -127,6 +132,13 @@ struct Versal {
> #define MM_OCM 0xfffc0000U
> #define MM_OCM_SIZE 0x40000
>
> +#define MM_USB2_CTRL_REGS 0xFF9D0000
> +#define MM_USB2_CTRL_REGS_SIZE 0x10000
> +
> +#define MM_USB_XHCI_0 0xFE200000
> +#define MM_USB_XHCI_0_SIZE 0x10000
> +#define MM_USB_XHCI_0_DWC3_GLOBAL (MM_USB_XHCI_0 + 0xC100)
> +
> #define MM_TOP_DDR 0x0
> #define MM_TOP_DDR_SIZE 0x80000000U
> #define MM_TOP_DDR_2 0x800000000ULL
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* RE: [PATCH v6 7/7] Versal: Connect DWC3 controller with virt-versal
2020-09-16 12:30 ` Edgar E. Iglesias
@ 2020-09-16 14:15 ` Sai Pavan Boddu
0 siblings, 0 replies; 14+ messages in thread
From: Sai Pavan Boddu @ 2020-09-16 14:15 UTC (permalink / raw)
To: Edgar Iglesias
Cc: Francisco Eduardo Iglesias, Peter Maydell, Eduardo Habkost,
Vikram Garhwal, Markus Armbruster, qemu-devel@nongnu.org,
Edgar Iglesias, Alistair Francis, Gerd Hoffmann,
'Marc-André Lureau', Ying Fang, Paolo Bonzini,
Paul Zimmerman, 'Philippe Mathieu-Daudé'
Hi Edgar,
Thanks for suggestions, I will send V7 with those changes.
Regards,
Sai Pavan
> -----Original Message-----
> From: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
> Sent: Wednesday, September 16, 2020 6:01 PM
> To: Sai Pavan Boddu <saipava@xilinx.com>
> Cc: Peter Maydell <peter.maydell@linaro.org>; Markus Armbruster
> <armbru@redhat.com>; 'Marc-André Lureau'
> <marcandre.lureau@redhat.com>; Paolo Bonzini <pbonzini@redhat.com>;
> Gerd Hoffmann <kraxel@redhat.com>; Edgar Iglesias <edgari@xilinx.com>;
> Francisco Eduardo Iglesias <figlesia@xilinx.com>; qemu-devel@nongnu.org;
> Alistair Francis <alistair.francis@wdc.com>; Eduardo Habkost
> <ehabkost@redhat.com>; Ying Fang <fangying1@huawei.com>; 'Philippe
> Mathieu-Daudé' <philmd@redhat.com>; Vikram Garhwal
> <fnuv@xilinx.com>; Paul Zimmerman <pauldzim@gmail.com>; Sai Pavan
> Boddu <saipava@xilinx.com>
> Subject: Re: [PATCH v6 7/7] Versal: Connect DWC3 controller with virt-versal
>
> On Wed, Sep 16, 2020 at 05:11:09PM +0530, Sai Pavan Boddu wrote:
> > From: Vikram Garhwal <fnu.vikram@xilinx.com>
> >
> > Connect dwc3 controller and usb2-reg module to xlnx-versal SOC, its
> > placed in iou of lpd domain and configure it as dual port host
> > controller. Add the respective guest dts nodes for "xlnx-versal-virt"
> machine.
> >
> > Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
> > Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
> > ---
> > hw/arm/xlnx-versal-virt.c | 55
> ++++++++++++++++++++++++++++++++++++++++++++
> > hw/arm/xlnx-versal.c | 34 +++++++++++++++++++++++++++
> > include/hw/arm/xlnx-versal.h | 12 ++++++++++
> > 3 files changed, 101 insertions(+)
> >
> > diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> > index 1f9409e..2b4564b 100644
> > --- a/hw/arm/xlnx-versal-virt.c
> > +++ b/hw/arm/xlnx-versal-virt.c
> > @@ -41,6 +41,8 @@ struct VersalVirt {
> > uint32_t ethernet_phy[2];
> > uint32_t clk_125Mhz;
> > uint32_t clk_25Mhz;
> > + uint32_t usb;
> > + uint32_t dwc;
> > } phandle;
> > struct arm_boot_info binfo;
> >
> > @@ -68,6 +70,8 @@ static void fdt_create(VersalVirt *s)
> > s->phandle.clk_25Mhz = qemu_fdt_alloc_phandle(s->fdt);
> > s->phandle.clk_125Mhz = qemu_fdt_alloc_phandle(s->fdt);
> >
> > + s->phandle.usb = qemu_fdt_alloc_phandle(s->fdt);
> > + s->phandle.dwc = qemu_fdt_alloc_phandle(s->fdt);
> > /* Create /chosen node for load_dtb. */
> > qemu_fdt_add_subnode(s->fdt, "/chosen");
> >
> > @@ -150,6 +154,56 @@ static void fdt_add_timer_nodes(VersalVirt *s)
> > compat, sizeof(compat)); }
> >
> > +static void fdt_add_usb_xhci_nodes(VersalVirt *s) {
> > + const char clocknames[] = "bus_clk\0ref_clk";
> > + char *name = g_strdup_printf("/usb@%" PRIx32,
> MM_USB2_CTRL_REGS);
> > + const char compat[] = "xlnx,versal-dwc3";
>
> Need a blank line here.
>
> > + qemu_fdt_add_subnode(s->fdt, name);
> > + qemu_fdt_setprop(s->fdt, name, "compatible",
> > + compat, sizeof(compat));
> > + qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
> > + 2, MM_USB2_CTRL_REGS,
> > + 2, MM_USB2_CTRL_REGS_SIZE);
> > + qemu_fdt_setprop(s->fdt, name, "clock-names",
> > + clocknames, sizeof(clocknames));
> > + qemu_fdt_setprop_cells(s->fdt, name, "clocks",
> > + s->phandle.clk_25Mhz, s->phandle.clk_125Mhz);
> > + qemu_fdt_setprop(s->fdt, name, "ranges", NULL, 0);
> > + qemu_fdt_setprop_cell(s->fdt, name, "#address-cells", 2);
> > + qemu_fdt_setprop_cell(s->fdt, name, "#size-cells", 2);
> > + qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.usb);
> > + g_free(name);
> > +
> > + {
> > + const char irq_name[] = "dwc_usb3";
> > + const char compat[] = "snps,dwc3";
>
> Here too.
>
>
> > + name = g_strdup_printf("/usb@%" PRIx32 "/dwc3@%" PRIx32,
> > + MM_USB2_CTRL_REGS, MM_USB_XHCI_0);
> > + qemu_fdt_add_subnode(s->fdt, name);
> > + qemu_fdt_setprop(s->fdt, name, "compatible",
> > + compat, sizeof(compat));
> > + qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
> > + 2, MM_USB_XHCI_0, 2, MM_USB_XHCI_0_SIZE);
> > + qemu_fdt_setprop(s->fdt, name, "interrupt-names",
> > + irq_name, sizeof(irq_name));
> > + qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
> > + GIC_FDT_IRQ_TYPE_SPI, VERSAL_USB0_IRQ_0,
> > + GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> > + qemu_fdt_setprop_cell(s->fdt, name,
> > + "snps,quirk-frame-length-adjustment", 0x20);
> > + qemu_fdt_setprop_cells(s->fdt, name, "#stream-id-cells", 1);
> > + qemu_fdt_setprop_string(s->fdt, name, "dr_mode", "host");
> > + qemu_fdt_setprop_string(s->fdt, name, "phy-names", "usb3-phy");
> > + qemu_fdt_setprop(s->fdt, name, "snps,dis_u2_susphy_quirk", NULL,
> 0);
> > + qemu_fdt_setprop(s->fdt, name, "snps,dis_u3_susphy_quirk", NULL,
> 0);
> > + qemu_fdt_setprop(s->fdt, name, "snps,refclk_fladj", NULL, 0);
> > + qemu_fdt_setprop(s->fdt, name, "snps,mask_phy_reset", NULL, 0);
> > + qemu_fdt_setprop_cell(s->fdt, name, "phandle", s->phandle.dwc);
> > + qemu_fdt_setprop_string(s->fdt, name, "maximum-speed", "high-
> speed");
> > + g_free(name);
> > + }
> > +}
> > static void fdt_add_uart_nodes(VersalVirt *s) {
> > uint64_t addrs[] = { MM_UART1, MM_UART0 }; @@ -517,6 +571,7 @@
> > static void versal_virt_init(MachineState *machine)
> > fdt_add_gic_nodes(s);
> > fdt_add_timer_nodes(s);
> > fdt_add_zdma_nodes(s);
> > + fdt_add_usb_xhci_nodes(s);
> > fdt_add_sd_nodes(s);
> > fdt_add_rtc_node(s);
> > fdt_add_cpu_nodes(s, psci_conduit); diff --git
> > a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index 12ba6c4..88f7dc8
> > 100644
> > --- a/hw/arm/xlnx-versal.c
> > +++ b/hw/arm/xlnx-versal.c
> > @@ -145,6 +145,39 @@ static void versal_create_uarts(Versal *s,
> qemu_irq *pic)
> > }
> > }
> >
> > +static void versal_create_usbs(Versal *s, qemu_irq *pic) {
> > + DeviceState *dev, *xhci_dev;
> > + MemoryRegion *mr;
> > +
> > + object_initialize_child(OBJECT(s), "dwc3-0", &s->lpd.iou.dwc3,
> > + TYPE_USB_DWC3);
> > + dev = DEVICE(&s->lpd.iou.dwc3);
> > + xhci_dev = DEVICE(&s->lpd.iou.dwc3.sysbus_xhci);
> > +
> > + object_property_set_link(OBJECT(xhci_dev), "dma", OBJECT(&s-
> >mr_ps),
> > + &error_abort);
> > + qdev_prop_set_uint32(xhci_dev, "intrs", 1);
> > + qdev_prop_set_uint32(xhci_dev, "slots", 2);
> > +
> > + sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
> > +
> > + mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
> > + memory_region_add_subregion(&s->mr_ps,
> MM_USB_XHCI_0_DWC3_GLOBAL, mr);
> > + mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(xhci_dev), 0);
> > + memory_region_add_subregion(&s->mr_ps, MM_USB_XHCI_0, mr);
> > +
> > + sysbus_connect_irq(SYS_BUS_DEVICE(xhci_dev), 0,
> > + pic[VERSAL_USB0_IRQ_0]);
> > +
> > + object_initialize_child(OBJECT(s), "usb2reg-0", &s->lpd.iou.Usb2Regs,
> > + TYPE_XILINX_VERSAL_USB2_CTRL_REGS);
> > + dev = DEVICE(&s->lpd.iou.Usb2Regs);
> > + sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
> > +
> > + mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
> > + memory_region_add_subregion(&s->mr_ps, MM_USB2_CTRL_REGS,
> mr); }
> > +
> > static void versal_create_gems(Versal *s, qemu_irq *pic) {
> > int i;
> > @@ -333,6 +366,7 @@ static void versal_realize(DeviceState *dev, Error
> **errp)
> > versal_create_apu_cpus(s);
> > versal_create_apu_gic(s, pic);
> > versal_create_uarts(s, pic);
> > + versal_create_usbs(s, pic);
> > versal_create_gems(s, pic);
> > versal_create_admas(s, pic);
> > versal_create_sds(s, pic);
> > diff --git a/include/hw/arm/xlnx-versal.h
> > b/include/hw/arm/xlnx-versal.h index eaa9023..a428933 100644
> > --- a/include/hw/arm/xlnx-versal.h
> > +++ b/include/hw/arm/xlnx-versal.h
> > @@ -21,6 +21,8 @@
> > #include "hw/net/cadence_gem.h"
> > #include "hw/rtc/xlnx-zynqmp-rtc.h"
> > #include "qom/object.h"
> > +#include "hw/usb/hcd-dwc3.h"
> > +#include "hw/misc/xlnx-versal-usb2-ctrl-regs.h"
> >
> > #define TYPE_XLNX_VERSAL "xlnx-versal"
> > typedef struct Versal Versal;
> > @@ -61,6 +63,8 @@ struct Versal {
> > PL011State uart[XLNX_VERSAL_NR_UARTS];
> > CadenceGEMState gem[XLNX_VERSAL_NR_GEMS];
> > XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS];
> > + USBDWC3 dwc3;
> > + VersalUsb2CtrlRegs Usb2Regs;
>
> Can you please add a sub-struct for the usb stuff?
> e.g:
> struct {
> USBDWC3 dwc3;
> VersalUsb2CtrlRegs regs;
> } usb;
>
> > } iou;
> > } lpd;
> >
> > @@ -90,6 +94,7 @@ struct Versal {
> >
> > #define VERSAL_UART0_IRQ_0 18
> > #define VERSAL_UART1_IRQ_0 19
> > +#define VERSAL_USB0_IRQ_0 22
> > #define VERSAL_GEM0_IRQ_0 56
> > #define VERSAL_GEM0_WAKE_IRQ_0 57
> > #define VERSAL_GEM1_IRQ_0 58
> > @@ -127,6 +132,13 @@ struct Versal {
> > #define MM_OCM 0xfffc0000U
> > #define MM_OCM_SIZE 0x40000
> >
> > +#define MM_USB2_CTRL_REGS 0xFF9D0000
> > +#define MM_USB2_CTRL_REGS_SIZE 0x10000
> > +
> > +#define MM_USB_XHCI_0 0xFE200000
> > +#define MM_USB_XHCI_0_SIZE 0x10000
> > +#define MM_USB_XHCI_0_DWC3_GLOBAL (MM_USB_XHCI_0 + 0xC100)
> > +
> > #define MM_TOP_DDR 0x0
> > #define MM_TOP_DDR_SIZE 0x80000000U
> > #define MM_TOP_DDR_2 0x800000000ULL
> > --
> > 2.7.4
> >
^ permalink raw reply [flat|nested] 14+ messages in thread