diff options
author | Mark Kettenis | 2023-01-21 20:27:55 +0100 |
---|---|---|
committer | Tom Rini | 2023-01-27 14:47:58 -0500 |
commit | ba1efb3d2494e8ceb0ff405642f44a955f8d8e1b (patch) | |
tree | 9785b311bfffb082a65d4ec99248e940a7a77ada /include/usb/xhci.h | |
parent | 862b4a0f32ae395dac147542c3336ae8a0c47d69 (diff) |
usb: xhci: Implement DMA mapping
An XHCI controller that sits behind an IOMMU needs to map and unmap
its memory buffers to do DMA. Implement this by inroducing new
xhci_dma_map() and xhci_dma_unmap() helper functions. The
xhci_dma_map() function replaces the existing xhci_virt_to_bus()
function in the sense that it returns the bus address in the case
of simple address translation in the absence of an IOMMU. The
xhci_bus_to_virt() function is eliminated by storing the CPU
address of the allocated scratchpad memory in struct xhci_ctrl.
Signed-off-by: Mark Kettenis <kettenis@openbsd.org>
Reviewed-by: Marek Vasut <marex@denx.de>
Diffstat (limited to 'include/usb/xhci.h')
-rw-r--r-- | include/usb/xhci.h | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/include/usb/xhci.h b/include/usb/xhci.h index ea4cf3f52ba..85c359fa1b9 100644 --- a/include/usb/xhci.h +++ b/include/usb/xhci.h @@ -16,6 +16,7 @@ #ifndef HOST_XHCI_H_ #define HOST_XHCI_H_ +#include <iommu.h> #include <phys2bus.h> #include <asm/types.h> #include <asm/cache.h> @@ -490,6 +491,7 @@ struct xhci_container_ctx { int size; u8 *bytes; + dma_addr_t dma; }; /** @@ -688,6 +690,8 @@ struct xhci_input_control_ctx { struct xhci_device_context_array { /* 64-bit device addresses; we only write 32-bit addresses */ __le64 dev_context_ptrs[MAX_HC_SLOTS]; + /* private xHCD pointers */ + dma_addr_t dma; }; /* TODO: write function to set the 64-bit device DMA address */ /* @@ -997,6 +1001,7 @@ struct xhci_segment { union xhci_trb *trbs; /* private to HCD */ struct xhci_segment *next; + dma_addr_t dma; }; struct xhci_ring { @@ -1025,11 +1030,14 @@ struct xhci_erst_entry { struct xhci_erst { struct xhci_erst_entry *entries; unsigned int num_entries; + /* xhci->event_ring keeps track of segment dma addresses */ + dma_addr_t erst_dma_addr; /* Num entries the ERST can contain */ unsigned int erst_size; }; struct xhci_scratchpad { + void *scratchpad; u64 *sp_array; }; @@ -1216,6 +1224,7 @@ struct xhci_ctrl { struct xhci_virt_device *devs[MAX_HC_SLOTS]; int rootdev; u16 hci_version; + int page_size; u32 quirks; #define XHCI_MTK_HOST BIT(0) }; @@ -1226,7 +1235,7 @@ struct xhci_ctrl { #define xhci_to_dev(_ctrl) NULL #endif -unsigned long trb_addr(struct xhci_segment *seg, union xhci_trb *trb); +dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, union xhci_trb *trb); struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_container_ctx *ctx); struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_ctrl *ctrl, @@ -1243,7 +1252,7 @@ void xhci_slot_copy(struct xhci_ctrl *ctrl, struct xhci_container_ctx *out_ctx); void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, struct usb_device *udev, int hop_portnr); -void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr, +void xhci_queue_command(struct xhci_ctrl *ctrl, dma_addr_t addr, u32 slot_id, u32 ep_index, trb_type cmd); void xhci_acknowledge_event(struct xhci_ctrl *ctrl); union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected); @@ -1284,14 +1293,22 @@ extern struct dm_usb_ops xhci_usb_ops; struct xhci_ctrl *xhci_get_ctrl(struct usb_device *udev); -static inline dma_addr_t xhci_virt_to_bus(struct xhci_ctrl *ctrl, void *addr) +static inline dma_addr_t xhci_dma_map(struct xhci_ctrl *ctrl, void *addr, + size_t size) { +#if CONFIG_IS_ENABLED(IOMMU) + return dev_iommu_dma_map(xhci_to_dev(ctrl), addr, size); +#else return dev_phys_to_bus(xhci_to_dev(ctrl), virt_to_phys(addr)); +#endif } -static inline void *xhci_bus_to_virt(struct xhci_ctrl *ctrl, dma_addr_t addr) +static inline void xhci_dma_unmap(struct xhci_ctrl *ctrl, dma_addr_t addr, + size_t size) { - return phys_to_virt(dev_bus_to_phys(xhci_to_dev(ctrl), addr)); +#if CONFIG_IS_ENABLED(IOMMU) + dev_iommu_dma_unmap(xhci_to_dev(ctrl), addr, size); +#endif } #endif /* HOST_XHCI_H_ */ |