diff options
author | Tom Rini | 2023-01-27 14:48:22 -0500 |
---|---|---|
committer | Tom Rini | 2023-01-27 14:48:22 -0500 |
commit | f147aa80f52989c7455022ca1ab959e8545feccc (patch) | |
tree | 5e513d166bf3859bf649601099110312406c4c34 /include | |
parent | aa7c61f62923a1c9e9ec7f588ad37016d8c7323c (diff) | |
parent | e330c8b83e8784d23614f80ca3f12b11ceb515d8 (diff) |
Merge branch '2023-01-27-apple-soc-updates'
First, to quote the author:
This series adds support for the PCIe controller found on Apple M1 and
M2 machines and enables support for PCIe XHCI controllers. This makes
the type-A USB ports on the M1 Mac mini work. Since the use of Apples
DART IOMMU is mandatory (these PCIe DARTs don't support bypass mode),
this adds DMA mapping operations to the IOMMU uclass and implements
them for the Apple DART. It modifies the XHCI driver code to go map
DMA buffers through the IOMMU if there is one. Since the M1 Mac mini
now has two types of XHCI controllers with different number of ports
(2 for the DWC3 controllers, 8 for the Fresco Logic PCIe controller)
this uncovered an issue in with the way the hub descriptor is
implemented in the XHCI driver.
Second, Mark also fixes some Apple-specific instances of
CONFIG_IS_ENABLED that should be IS_ENABLED.
Diffstat (limited to 'include')
-rw-r--r-- | include/dm/device.h | 4 | ||||
-rw-r--r-- | include/iommu.h | 24 | ||||
-rw-r--r-- | include/usb/xhci.h | 28 |
3 files changed, 51 insertions, 5 deletions
diff --git a/include/dm/device.h b/include/dm/device.h index f3f953c9afc..e9460386ca9 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -165,6 +165,7 @@ enum { * automatically when the device is removed / unbound * @dma_offset: Offset between the physical address space (CPU's) and the * device's bus address space + * @iommu: IOMMU device associated with this device */ struct udevice { const struct driver *driver; @@ -194,6 +195,9 @@ struct udevice { #if CONFIG_IS_ENABLED(DM_DMA) ulong dma_offset; #endif +#if CONFIG_IS_ENABLED(IOMMU) + struct udevice *iommu; +#endif }; static inline int dm_udevice_size(void) diff --git a/include/iommu.h b/include/iommu.h index 6c46adf449e..cf9719c5e91 100644 --- a/include/iommu.h +++ b/include/iommu.h @@ -3,6 +3,27 @@ struct udevice; +struct iommu_ops { + /** + * map() - map DMA memory + * + * @dev: device for which to map DMA memory + * @addr: CPU address of the memory + * @size: size of the memory + * @return DMA address for the device + */ + dma_addr_t (*map)(struct udevice *dev, void *addr, size_t size); + + /** + * unmap() - unmap DMA memory + * + * @dev: device for which to unmap DMA memory + * @addr: DMA address of the memory + * @size: size of the memory + */ + void (*unmap)(struct udevice *dev, dma_addr_t addr, size_t size); +}; + #if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) && \ CONFIG_IS_ENABLED(IOMMU) int dev_iommu_enable(struct udevice *dev); @@ -13,4 +34,7 @@ static inline int dev_iommu_enable(struct udevice *dev) } #endif +dma_addr_t dev_iommu_dma_map(struct udevice *dev, void *addr, size_t size); +void dev_iommu_dma_unmap(struct udevice *dev, dma_addr_t addr, size_t size); + #endif diff --git a/include/usb/xhci.h b/include/usb/xhci.h index ea4cf3f52ba..4a4ac10229a 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; }; @@ -1214,8 +1222,10 @@ struct xhci_ctrl { struct xhci_erst_entry entry[ERST_NUM_SEGS]; struct xhci_scratchpad *scratchpad; struct xhci_virt_device *devs[MAX_HC_SLOTS]; + struct usb_hub_descriptor hub_desc; int rootdev; u16 hci_version; + int page_size; u32 quirks; #define XHCI_MTK_HOST BIT(0) }; @@ -1226,7 +1236,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 +1253,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 +1294,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_ */ |