From 51bdb50904b1ffffc1caa8dd92f5abea78e33a0b Mon Sep 17 00:00:00 2001 From: Nicolas Saenz Julienne Date: Tue, 12 Jan 2021 13:55:22 +0100 Subject: dm: Introduce xxx_get_dma_range() Add the following functions to get a specific device's DMA ranges: - dev_get_dma_range() - ofnode_get_dma_range() - of_get_dma_range() - fdt_get_dma_range() They are specially useful in oder to be able validate a physical address space range into a bus's and to convert addresses from and to address spaces. Signed-off-by: Nicolas Saenz Julienne Reviewed-by: Simon Glass Tested-by: Peter Robinson Signed-off-by: Matthias Brugger --- include/dm/of_addr.h | 17 +++++++++++++++++ include/dm/ofnode.h | 16 ++++++++++++++++ include/dm/read.h | 21 +++++++++++++++++++++ include/fdt_support.h | 14 ++++++++++++++ 4 files changed, 68 insertions(+) (limited to 'include') diff --git a/include/dm/of_addr.h b/include/dm/of_addr.h index 3fa1ffce81a..ee21d5cf4fc 100644 --- a/include/dm/of_addr.h +++ b/include/dm/of_addr.h @@ -44,6 +44,23 @@ u64 of_translate_address(const struct device_node *no, const __be32 *in_addr); */ u64 of_translate_dma_address(const struct device_node *no, const __be32 *in_addr); + +/** + * of_get_dma_range() - get dma-ranges for a specific DT node + * + * Get DMA ranges for a specifc node, this is useful to perform bus->cpu and + * cpu->bus address translations + * + * @param blob Pointer to device tree blob + * @param node_offset Node DT offset + * @param cpu Pointer to variable storing the range's cpu address + * @param bus Pointer to variable storing the range's bus address + * @param size Pointer to variable storing the range's size + * @return translated DMA address or OF_BAD_ADDR on error + */ +int of_get_dma_range(const struct device_node *dev, phys_addr_t *cpu, + dma_addr_t *bus, u64 *size); + /** * of_get_address() - obtain an address from a node * diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index 5318d650357..2c0597c4073 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -998,6 +998,22 @@ u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr); */ u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr); +/** + * ofnode_get_dma_range() - get dma-ranges for a specific DT node + * + * Get DMA ranges for a specifc node, this is useful to perform bus->cpu and + * cpu->bus address translations + * + * @param blob Pointer to device tree blob + * @param node_offset Node DT offset + * @param cpu Pointer to variable storing the range's cpu address + * @param bus Pointer to variable storing the range's bus address + * @param size Pointer to variable storing the range's size + * @return translated DMA address or OF_BAD_ADDR on error + */ +int ofnode_get_dma_range(ofnode node, phys_addr_t *cpu, dma_addr_t *bus, + u64 *size); + /** * ofnode_device_is_compatible() - check if the node is compatible with compat * diff --git a/include/dm/read.h b/include/dm/read.h index 97575bcad04..5bf34056147 100644 --- a/include/dm/read.h +++ b/include/dm/read.h @@ -647,6 +647,21 @@ u64 dev_translate_address(const struct udevice *dev, const fdt32_t *in_addr); u64 dev_translate_dma_address(const struct udevice *dev, const fdt32_t *in_addr); +/** + * dev_get_dma_range() - Get a device's DMA constraints + * + * Provide the address bases and size of the linear mapping between the CPU and + * a device's BUS address space. + * + * @dev: device giving the context in which to translate the DMA address + * @cpu: base address for CPU's view of memory + * @bus: base address for BUS's view of memory + * @size: size of the address space + * @return 0 if ok, negative on error + */ +int dev_get_dma_range(const struct udevice *dev, phys_addr_t *cpu, + dma_addr_t *bus, u64 *size); + /** * dev_read_alias_highest_id - Get highest alias id for the given stem * @stem: Alias stem to be examined @@ -1005,6 +1020,12 @@ static inline u64 dev_translate_dma_address(const struct udevice *dev, return ofnode_translate_dma_address(dev_ofnode(dev), in_addr); } +static inline int dev_get_dma_range(const struct udevice *dev, phys_addr_t *cpu, + dma_addr_t *bus, u64 *size) +{ + return ofnode_get_dma_range(dev_ofnode(dev), cpu, bus, size); +} + static inline int dev_read_alias_highest_id(const char *stem) { if (!CONFIG_IS_ENABLED(OF_LIBFDT) || !gd->fdt_blob) diff --git a/include/fdt_support.h b/include/fdt_support.h index dbbac0fb6a3..46eb1dbbb24 100644 --- a/include/fdt_support.h +++ b/include/fdt_support.h @@ -260,6 +260,20 @@ u64 fdt_translate_address(const void *blob, int node_offset, u64 fdt_translate_dma_address(const void *blob, int node_offset, const __be32 *in_addr); +/** + * Get DMA ranges for a specifc node, this is useful to perform bus->cpu and + * cpu->bus address translations + * + * @param blob Pointer to device tree blob + * @param node_offset Node DT offset + * @param cpu Pointer to variable storing the range's cpu address + * @param bus Pointer to variable storing the range's bus address + * @param size Pointer to variable storing the range's size + * @return translated DMA address or OF_BAD_ADDR on error + */ +int fdt_get_dma_range(const void *blob, int node_offset, phys_addr_t *cpu, + dma_addr_t *bus, u64 *size); + int fdt_node_offset_by_compat_reg(void *blob, const char *compat, phys_addr_t compat_off); int fdt_alloc_phandle(void *blob); -- cgit v1.3.1 From 4abf68d57d495674e521b693191be1dcada46ecd Mon Sep 17 00:00:00 2001 From: Nicolas Saenz Julienne Date: Tue, 12 Jan 2021 13:55:24 +0100 Subject: dm: Introduce DMA constraints into the core device model Calculating the DMA offset between a bus address space and CPU's every time we call phys_to_bus() and bus_to_phys() isn't ideal performance wise, as it implies traversing the device tree from the device's node up to the root. Since this information is static and available before the device's initialization, parse it before the probe call an provide the DMA offset in 'struct udevice' for the address translation code to use it. Signed-off-by: Nicolas Saenz Julienne Reviewed-by: Simon Glass Tested-by: Peter Robinson Signed-off-by: Matthias Brugger --- drivers/core/Kconfig | 10 ++++++++++ drivers/core/device.c | 41 +++++++++++++++++++++++++++++++++++++++++ include/dm/device.h | 13 +++++++++++++ 3 files changed, 64 insertions(+) (limited to 'include') diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig index dbfe51c6e87..00554af4995 100644 --- a/drivers/core/Kconfig +++ b/drivers/core/Kconfig @@ -129,6 +129,16 @@ config TPL_DM_INLINE_OFNODE This applies to several ofnode functions (see ofnode.h) which are seldom used. Inlining them can help reduce code size. +config DM_DMA + bool "Support per-device DMA constraints" + depends on DM + default n + help + Enable this to extract per-device DMA constraints, only supported on + device-tree systems for now. This is needed in order translate + addresses on systems where different buses have different views of + the physical address space. + config REGMAP bool "Support register maps" depends on DM diff --git a/drivers/core/device.c b/drivers/core/device.c index 82a00989604..625134921d6 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -422,6 +422,43 @@ fail: return ret; } +/** + * device_get_dma_constraints() - Populate device's DMA constraints + * + * Gets a device's DMA constraints from firmware. This information is later + * used by drivers to translate physcal addresses to the device's bus address + * space. For now only device-tree is supported. + * + * @dev: Pointer to target device + * Return: 0 if OK or if no DMA constraints were found, error otherwise + */ +static int device_get_dma_constraints(struct udevice *dev) +{ + struct udevice *parent = dev->parent; + phys_addr_t cpu = 0; + dma_addr_t bus = 0; + u64 size = 0; + int ret; + + if (!CONFIG_IS_ENABLED(DM_DMA) || !parent || !dev_has_ofnode(parent)) + return 0; + + /* + * We start parsing for dma-ranges from the device's bus node. This is + * specially important on nested buses. + */ + ret = dev_get_dma_range(parent, &cpu, &bus, &size); + /* Don't return an error if no 'dma-ranges' were found */ + if (ret && ret != -ENOENT) { + dm_warn("%s: failed to get DMA range, %d\n", dev->name, ret); + return ret; + } + + dev_set_dma_offset(dev, cpu - bus); + + return 0; +} + int device_probe(struct udevice *dev) { const struct driver *drv; @@ -484,6 +521,10 @@ int device_probe(struct udevice *dev) goto fail; } + ret = device_get_dma_constraints(dev); + if (ret) + goto fail; + ret = uclass_pre_probe_device(dev); if (ret) goto fail; diff --git a/include/dm/device.h b/include/dm/device.h index 28533ce0b6d..bb9faa0ed93 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -159,6 +159,8 @@ enum { * When CONFIG_DEVRES is enabled, devm_kmalloc() and friends will * add to this list. Memory so-allocated will be freed * automatically when the device is removed / unbound + * @dma_offset: Offset between the physical address space (CPU's) and the + * device's bus address space */ struct udevice { const struct driver *driver; @@ -183,6 +185,9 @@ struct udevice { #ifdef CONFIG_DEVRES struct list_head devres_head; #endif +#if CONFIG_IS_ENABLED(DM_DMA) + ulong dma_offset; +#endif }; /* Maximum sequence number supported */ @@ -224,6 +229,14 @@ static inline ofnode dev_ofnode(const struct udevice *dev) /* Returns non-zero if the device is active (probed and not removed) */ #define device_active(dev) (dev_get_flags(dev) & DM_FLAG_ACTIVATED) +#if CONFIG_IS_ENABLED(DM_DMA) +#define dev_set_dma_offset(_dev, _offset) _dev->dma_offset = _offset +#define dev_get_dma_offset(_dev) _dev->dma_offset +#else +#define dev_set_dma_offset(_dev, _offset) +#define dev_get_dma_offset(_dev) 0 +#endif + static inline int dev_of_offset(const struct udevice *dev) { #if !CONFIG_IS_ENABLED(OF_PLATDATA) -- cgit v1.3.1 From 2a15a25c362bbeddf0c8e6fcfb142321076eb904 Mon Sep 17 00:00:00 2001 From: Nicolas Saenz Julienne Date: Tue, 12 Jan 2021 13:55:26 +0100 Subject: dm: Introduce dev_phys_to_bus()/dev_bus_to_phys() These functions, instead of relying on hard-coded platform-specific address translations, make use of the DMA constraints provided by the DM core. This allows for per-device translations. We can't yet get rid of the legacy phys_to_bus()/bus_to_phys() implementations as some of its users are not integrated into the device model. Signed-off-by: Nicolas Saenz Julienne Reviewed-by: Simon Glass Reviewed-by: Stefan Roese Tested-by: Peter Robinson Signed-off-by: Matthias Brugger --- include/phys2bus.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'include') diff --git a/include/phys2bus.h b/include/phys2bus.h index dc9b8e5a253..866b8b51a8c 100644 --- a/include/phys2bus.h +++ b/include/phys2bus.h @@ -21,4 +21,21 @@ static inline unsigned long bus_to_phys(unsigned long bus) } #endif +#if CONFIG_IS_ENABLED(DM) +#include + +static inline dma_addr_t dev_phys_to_bus(struct udevice *dev, phys_addr_t phys) +{ + return phys - dev_get_dma_offset(dev); +} + +static inline phys_addr_t dev_bus_to_phys(struct udevice *dev, dma_addr_t bus) +{ + return bus + dev_get_dma_offset(dev); +} +#else +#define dev_phys_to_bus(_, _addr) _addr +#define dev_bus_to_phys(_, _addr) _addr +#endif + #endif -- cgit v1.3.1 From 1a474559d90a4b4f7acd95050fe759fe52395867 Mon Sep 17 00:00:00 2001 From: Nicolas Saenz Julienne Date: Tue, 12 Jan 2021 13:55:28 +0100 Subject: xhci: translate virtual addresses into the bus's address space So far we've been content with passing physical addresses when configuring memory addresses into XHCI controllers, but not all platforms have buses with transparent mappings. Specifically the Raspberry Pi 4 might introduce an offset to memory accesses incoming from its PCIe port. Introduce xhci_virt_to_bus() and xhci_bus_to_virt() to cater with these limitations, and make sure we don't break non DM users. Signed-off-by: Nicolas Saenz Julienne Reviewed-by: Simon Glass Reviewed-by: Stefan Roese Tested-by: Peter Robinson [mb: fix compilation for 32 bit] Signed-off-by: Matthias Brugger fix from nicolas --- drivers/usb/host/xhci-mem.c | 45 +++++++++++++++++++++++--------------------- drivers/usb/host/xhci-ring.c | 13 ++++++++----- drivers/usb/host/xhci.c | 4 ++-- include/usb/xhci.h | 20 +++++++++++++++++++- 4 files changed, 53 insertions(+), 29 deletions(-) (limited to 'include') diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index b002d6f1664..83147d51b5c 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -110,7 +110,7 @@ static void xhci_scratchpad_free(struct xhci_ctrl *ctrl) ctrl->dcbaa->dev_context_ptrs[0] = 0; - free((void *)(uintptr_t)le64_to_cpu(ctrl->scratchpad->sp_array[0])); + free(xhci_bus_to_virt(ctrl, le64_to_cpu(ctrl->scratchpad->sp_array[0]))); free(ctrl->scratchpad->sp_array); free(ctrl->scratchpad); ctrl->scratchpad = NULL; @@ -216,8 +216,8 @@ static void *xhci_malloc(unsigned int size) * @param link_trbs flag to indicate whether to link the trbs or NOT * @return none */ -static void xhci_link_segments(struct xhci_segment *prev, - struct xhci_segment *next, bool link_trbs) +static void xhci_link_segments(struct xhci_ctrl *ctrl, struct xhci_segment *prev, + struct xhci_segment *next, bool link_trbs) { u32 val; u64 val_64 = 0; @@ -226,7 +226,7 @@ static void xhci_link_segments(struct xhci_segment *prev, return; prev->next = next; if (link_trbs) { - val_64 = virt_to_phys(next->trbs); + val_64 = xhci_virt_to_bus(ctrl, next->trbs); prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = cpu_to_le64(val_64); @@ -304,7 +304,8 @@ static struct xhci_segment *xhci_segment_alloc(void) * @param link_trbs flag to indicate whether to link the trbs or NOT * @return pointer to the newly created RING */ -struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs) +struct xhci_ring *xhci_ring_alloc(struct xhci_ctrl *ctrl, unsigned int num_segs, + bool link_trbs) { struct xhci_ring *ring; struct xhci_segment *prev; @@ -327,12 +328,12 @@ struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs) next = xhci_segment_alloc(); BUG_ON(!next); - xhci_link_segments(prev, next, link_trbs); + xhci_link_segments(ctrl, prev, next, link_trbs); prev = next; num_segs--; } - xhci_link_segments(prev, ring->first_seg, link_trbs); + xhci_link_segments(ctrl, prev, ring->first_seg, link_trbs); if (link_trbs) { /* See section 4.9.2.1 and 6.4.4.1 */ prev->trbs[TRBS_PER_SEGMENT-1].link.control |= @@ -354,6 +355,7 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl) struct xhci_hccr *hccr = ctrl->hccr; struct xhci_hcor *hcor = ctrl->hcor; struct xhci_scratchpad *scratchpad; + uint64_t val_64; int num_sp; uint32_t page_size; void *buf; @@ -371,8 +373,9 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl) scratchpad->sp_array = xhci_malloc(num_sp * sizeof(u64)); if (!scratchpad->sp_array) goto fail_sp2; - ctrl->dcbaa->dev_context_ptrs[0] = - cpu_to_le64((uintptr_t)scratchpad->sp_array); + + val_64 = xhci_virt_to_bus(ctrl, scratchpad->sp_array); + ctrl->dcbaa->dev_context_ptrs[0] = cpu_to_le64(val_64); xhci_flush_cache((uintptr_t)&ctrl->dcbaa->dev_context_ptrs[0], sizeof(ctrl->dcbaa->dev_context_ptrs[0])); @@ -393,8 +396,8 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl) xhci_flush_cache((uintptr_t)buf, num_sp * page_size); for (i = 0; i < num_sp; i++) { - uintptr_t ptr = (uintptr_t)buf + i * page_size; - scratchpad->sp_array[i] = cpu_to_le64(ptr); + val_64 = xhci_virt_to_bus(ctrl, buf + i * page_size); + scratchpad->sp_array[i] = cpu_to_le64(val_64); } xhci_flush_cache((uintptr_t)scratchpad->sp_array, @@ -484,9 +487,9 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id) } /* Allocate endpoint 0 ring */ - virt_dev->eps[0].ring = xhci_ring_alloc(1, true); + virt_dev->eps[0].ring = xhci_ring_alloc(ctrl, 1, true); - byte_64 = virt_to_phys(virt_dev->out_ctx->bytes); + byte_64 = xhci_virt_to_bus(ctrl, virt_dev->out_ctx->bytes); /* Point to output device context in dcbaa. */ ctrl->dcbaa->dev_context_ptrs[slot_id] = cpu_to_le64(byte_64); @@ -522,15 +525,15 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, return -ENOMEM; } - val_64 = virt_to_phys(ctrl->dcbaa); + val_64 = xhci_virt_to_bus(ctrl, ctrl->dcbaa); /* Set the pointer in DCBAA register */ xhci_writeq(&hcor->or_dcbaap, val_64); /* Command ring control pointer register initialization */ - ctrl->cmd_ring = xhci_ring_alloc(1, true); + ctrl->cmd_ring = xhci_ring_alloc(ctrl, 1, true); /* Set the address in the Command Ring Control register */ - trb_64 = virt_to_phys(ctrl->cmd_ring->first_seg->trbs); + trb_64 = xhci_virt_to_bus(ctrl, ctrl->cmd_ring->first_seg->trbs); val_64 = xhci_readq(&hcor->or_crcr); val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) | (trb_64 & (u64) ~CMD_RING_RSVD_BITS) | @@ -551,7 +554,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, ctrl->ir_set = &ctrl->run_regs->ir_set[0]; /* Event ring does not maintain link TRB */ - ctrl->event_ring = xhci_ring_alloc(ERST_NUM_SEGS, false); + ctrl->event_ring = xhci_ring_alloc(ctrl, ERST_NUM_SEGS, false); ctrl->erst.entries = xhci_malloc(sizeof(struct xhci_erst_entry) * ERST_NUM_SEGS); @@ -560,8 +563,8 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, for (val = 0, seg = ctrl->event_ring->first_seg; val < ERST_NUM_SEGS; val++) { - trb_64 = virt_to_phys(seg->trbs); struct xhci_erst_entry *entry = &ctrl->erst.entries[val]; + trb_64 = xhci_virt_to_bus(ctrl, seg->trbs); entry->seg_addr = cpu_to_le64(trb_64); entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT); entry->rsvd = 0; @@ -570,7 +573,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, xhci_flush_cache((uintptr_t)ctrl->erst.entries, ERST_NUM_SEGS * sizeof(struct xhci_erst_entry)); - deq = virt_to_phys(ctrl->event_ring->dequeue); + deq = xhci_virt_to_bus(ctrl, ctrl->event_ring->dequeue); /* Update HC event ring dequeue pointer */ xhci_writeq(&ctrl->ir_set->erst_dequeue, @@ -585,7 +588,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, /* this is the event ring segment table pointer */ val_64 = xhci_readq(&ctrl->ir_set->erst_base); val_64 &= ERST_PTR_MASK; - val_64 |= virt_to_phys(ctrl->erst.entries) & ~ERST_PTR_MASK; + val_64 |= xhci_virt_to_bus(ctrl, ctrl->erst.entries) & ~ERST_PTR_MASK; xhci_writeq(&ctrl->ir_set->erst_base, val_64); @@ -848,7 +851,7 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, /* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */ ep0_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(0) | ERROR_COUNT(3)); - trb_64 = virt_to_phys(virt_dev->eps[0].ring->first_seg->trbs); + trb_64 = xhci_virt_to_bus(ctrl, virt_dev->eps[0].ring->first_seg->trbs); ep0_ctx->deq = cpu_to_le64(trb_64 | virt_dev->eps[0].ring->cycle_state); /* diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index d6c47d579bc..46c137f8578 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -275,10 +275,13 @@ void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr, u32 slot_id, u32 ep_index, trb_type cmd) { u32 fields[4]; - u64 val_64 = virt_to_phys(ptr); + u64 val_64 = 0; BUG_ON(prepare_ring(ctrl, ctrl->cmd_ring, EP_STATE_RUNNING)); + if (ptr) + val_64 = xhci_virt_to_bus(ctrl, ptr); + fields[0] = lower_32_bits(val_64); fields[1] = upper_32_bits(val_64); fields[2] = 0; @@ -401,7 +404,7 @@ void xhci_acknowledge_event(struct xhci_ctrl *ctrl) /* Inform the hardware */ xhci_writeq(&ctrl->ir_set->erst_dequeue, - virt_to_phys(ctrl->event_ring->dequeue) | ERST_EHB); + xhci_virt_to_bus(ctrl, ctrl->event_ring->dequeue) | ERST_EHB); } /** @@ -579,7 +582,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, u64 addr; int ret; u32 trb_fields[4]; - u64 val_64 = virt_to_phys(buffer); + u64 val_64 = xhci_virt_to_bus(ctrl, buffer); void *last_transfer_trb_addr; int available_length; @@ -724,7 +727,7 @@ again: } if ((uintptr_t)(le64_to_cpu(event->trans_event.buffer)) != - (uintptr_t)virt_to_phys(last_transfer_trb_addr)) { + (uintptr_t)xhci_virt_to_bus(ctrl, last_transfer_trb_addr)) { available_length -= (int)EVENT_TRB_LEN(le32_to_cpu(event->trans_event.transfer_len)); xhci_acknowledge_event(ctrl); @@ -884,7 +887,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, if (length > 0) { if (req->requesttype & USB_DIR_IN) field |= TRB_DIR_IN; - buf_64 = virt_to_phys(buffer); + buf_64 = xhci_virt_to_bus(ctrl, buffer); trb_fields[0] = lower_32_bits(buf_64); trb_fields[1] = upper_32_bits(buf_64); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 7080f8fabe7..d27ac01c837 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -604,7 +604,7 @@ static int xhci_set_configuration(struct usb_device *udev) ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, in_ctx, ep_index); /* Allocate the ep rings */ - virt_dev->eps[ep_index].ring = xhci_ring_alloc(1, true); + virt_dev->eps[ep_index].ring = xhci_ring_alloc(ctrl, 1, true); if (!virt_dev->eps[ep_index].ring) return -ENOMEM; @@ -628,7 +628,7 @@ static int xhci_set_configuration(struct usb_device *udev) cpu_to_le32(MAX_BURST(max_burst) | ERROR_COUNT(err_count)); - trb_64 = virt_to_phys(virt_dev->eps[ep_index].ring->enqueue); + trb_64 = xhci_virt_to_bus(ctrl, virt_dev->eps[ep_index].ring->enqueue); ep_ctx[ep_index]->deq = cpu_to_le64(trb_64 | virt_dev->eps[ep_index].ring->cycle_state); diff --git a/include/usb/xhci.h b/include/usb/xhci.h index e1d382369a3..8d95e213b01 100644 --- a/include/usb/xhci.h +++ b/include/usb/xhci.h @@ -16,6 +16,7 @@ #ifndef HOST_XHCI_H_ #define HOST_XHCI_H_ +#include #include #include #include @@ -1221,6 +1222,12 @@ struct xhci_ctrl { #define XHCI_MTK_HOST BIT(0) }; +#if CONFIG_IS_ENABLED(DM_USB) +#define xhci_to_dev(_ctrl) _ctrl->dev +#else +#define xhci_to_dev(_ctrl) NULL +#endif + unsigned long trb_addr(struct xhci_segment *seg, union xhci_trb *trb); struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_container_ctx *ctx); @@ -1250,7 +1257,8 @@ int xhci_check_maxpacket(struct usb_device *udev); void xhci_flush_cache(uintptr_t addr, u32 type_len); void xhci_inval_cache(uintptr_t addr, u32 type_len); void xhci_cleanup(struct xhci_ctrl *ctrl); -struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs); +struct xhci_ring *xhci_ring_alloc(struct xhci_ctrl *ctrl, unsigned int num_segs, + bool link_trbs); int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id); int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, struct xhci_hcor *hcor); @@ -1278,4 +1286,14 @@ 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) +{ + return dev_phys_to_bus(xhci_to_dev(ctrl), virt_to_phys(addr)); +} + +static inline void *xhci_bus_to_virt(struct xhci_ctrl *ctrl, dma_addr_t addr) +{ + return phys_to_virt(dev_bus_to_phys(xhci_to_dev(ctrl), addr)); +} + #endif /* HOST_XHCI_H_ */ -- cgit v1.3.1 From c89c96d3222ca4f4ecfacd2cbaf560ff5d3d2a2f Mon Sep 17 00:00:00 2001 From: Nicolas Saenz Julienne Date: Tue, 12 Jan 2021 13:55:29 +0100 Subject: mmc: Introduce mmc_phys_to_bus()/mmc_bus_to_phys() This will allow us to use DM variants of phys_to_bus()/bus_to_phys() when relevant. Signed-off-by: Nicolas Saenz Julienne Reviewed-by: Simon Glass Tested-by: Peter Robinson Signed-off-by: Matthias Brugger --- drivers/mmc/sdhci.c | 10 ++++++---- include/mmc.h | 6 ++++++ 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index ed0dc173253..5f18d472bd1 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -74,6 +74,7 @@ static void sdhci_transfer_pio(struct sdhci_host *host, struct mmc_data *data) static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data, int *is_aligned, int trans_bytes) { + dma_addr_t dma_addr; unsigned char ctrl; void *buf; @@ -104,8 +105,8 @@ static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data, mmc_get_dma_dir(data)); if (host->flags & USE_SDMA) { - sdhci_writel(host, phys_to_bus((ulong)host->start_addr), - SDHCI_DMA_ADDRESS); + dma_addr = dev_phys_to_bus(mmc_to_dev(host->mmc), host->start_addr); + sdhci_writel(host, dma_addr, SDHCI_DMA_ADDRESS); } #if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA) else if (host->flags & (USE_ADMA | USE_ADMA64)) { @@ -163,8 +164,9 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data) start_addr &= ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1); start_addr += SDHCI_DEFAULT_BOUNDARY_SIZE; - sdhci_writel(host, phys_to_bus((ulong)start_addr), - SDHCI_DMA_ADDRESS); + start_addr = dev_phys_to_bus(mmc_to_dev(host->mmc), + start_addr); + sdhci_writel(host, start_addr, SDHCI_DMA_ADDRESS); } } if (timeout-- > 0) diff --git a/include/mmc.h b/include/mmc.h index 1d377e0281f..c12c7a0b5cf 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -736,6 +736,12 @@ struct mmc { u8 hs400_tuning; }; +#if CONFIG_IS_ENABLED(DM_MMC) +#define mmc_to_dev(_mmc) _mmc->dev +#else +#define mmc_to_dev(_mmc) NULL +#endif + struct mmc_hwpart_conf { struct { uint enh_start; /* in 512-byte sectors */ -- cgit v1.3.1