162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Cadence CDNSP DRD Driver.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2020 Cadence.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Author: Pawel Laszczak <pawell@cadence.com>
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Code based on Linux XHCI driver.
1062306a36Sopenharmony_ci * Origin: Copyright (C) 2008 Intel Corp.
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/dma-mapping.h>
1462306a36Sopenharmony_ci#include <linux/dmapool.h>
1562306a36Sopenharmony_ci#include <linux/slab.h>
1662306a36Sopenharmony_ci#include <linux/usb.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#include "cdnsp-gadget.h"
1962306a36Sopenharmony_ci#include "cdnsp-trace.h"
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_cistatic void cdnsp_free_stream_info(struct cdnsp_device *pdev,
2262306a36Sopenharmony_ci				   struct cdnsp_ep *pep);
2362306a36Sopenharmony_ci/*
2462306a36Sopenharmony_ci * Allocates a generic ring segment from the ring pool, sets the dma address,
2562306a36Sopenharmony_ci * initializes the segment to zero, and sets the private next pointer to NULL.
2662306a36Sopenharmony_ci *
2762306a36Sopenharmony_ci * "All components of all Command and Transfer TRBs shall be initialized to '0'"
2862306a36Sopenharmony_ci */
2962306a36Sopenharmony_cistatic struct cdnsp_segment *cdnsp_segment_alloc(struct cdnsp_device *pdev,
3062306a36Sopenharmony_ci						 unsigned int cycle_state,
3162306a36Sopenharmony_ci						 unsigned int max_packet,
3262306a36Sopenharmony_ci						 gfp_t flags)
3362306a36Sopenharmony_ci{
3462306a36Sopenharmony_ci	struct cdnsp_segment *seg;
3562306a36Sopenharmony_ci	dma_addr_t dma;
3662306a36Sopenharmony_ci	int i;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	seg = kzalloc(sizeof(*seg), flags);
3962306a36Sopenharmony_ci	if (!seg)
4062306a36Sopenharmony_ci		return NULL;
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	seg->trbs = dma_pool_zalloc(pdev->segment_pool, flags, &dma);
4362306a36Sopenharmony_ci	if (!seg->trbs) {
4462306a36Sopenharmony_ci		kfree(seg);
4562306a36Sopenharmony_ci		return NULL;
4662306a36Sopenharmony_ci	}
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	if (max_packet) {
4962306a36Sopenharmony_ci		seg->bounce_buf = kzalloc(max_packet, flags | GFP_DMA);
5062306a36Sopenharmony_ci		if (!seg->bounce_buf)
5162306a36Sopenharmony_ci			goto free_dma;
5262306a36Sopenharmony_ci	}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	/* If the cycle state is 0, set the cycle bit to 1 for all the TRBs. */
5562306a36Sopenharmony_ci	if (cycle_state == 0) {
5662306a36Sopenharmony_ci		for (i = 0; i < TRBS_PER_SEGMENT; i++)
5762306a36Sopenharmony_ci			seg->trbs[i].link.control |= cpu_to_le32(TRB_CYCLE);
5862306a36Sopenharmony_ci	}
5962306a36Sopenharmony_ci	seg->dma = dma;
6062306a36Sopenharmony_ci	seg->next = NULL;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	return seg;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cifree_dma:
6562306a36Sopenharmony_ci	dma_pool_free(pdev->segment_pool, seg->trbs, dma);
6662306a36Sopenharmony_ci	kfree(seg);
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	return NULL;
6962306a36Sopenharmony_ci}
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_cistatic void cdnsp_segment_free(struct cdnsp_device *pdev,
7262306a36Sopenharmony_ci			       struct cdnsp_segment *seg)
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci	if (seg->trbs)
7562306a36Sopenharmony_ci		dma_pool_free(pdev->segment_pool, seg->trbs, seg->dma);
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	kfree(seg->bounce_buf);
7862306a36Sopenharmony_ci	kfree(seg);
7962306a36Sopenharmony_ci}
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_cistatic void cdnsp_free_segments_for_ring(struct cdnsp_device *pdev,
8262306a36Sopenharmony_ci					 struct cdnsp_segment *first)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	struct cdnsp_segment *seg;
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	seg = first->next;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	while (seg != first) {
8962306a36Sopenharmony_ci		struct cdnsp_segment *next = seg->next;
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci		cdnsp_segment_free(pdev, seg);
9262306a36Sopenharmony_ci		seg = next;
9362306a36Sopenharmony_ci	}
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	cdnsp_segment_free(pdev, first);
9662306a36Sopenharmony_ci}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci/*
9962306a36Sopenharmony_ci * Make the prev segment point to the next segment.
10062306a36Sopenharmony_ci *
10162306a36Sopenharmony_ci * Change the last TRB in the prev segment to be a Link TRB which points to the
10262306a36Sopenharmony_ci * DMA address of the next segment. The caller needs to set any Link TRB
10362306a36Sopenharmony_ci * related flags, such as End TRB, Toggle Cycle, and no snoop.
10462306a36Sopenharmony_ci */
10562306a36Sopenharmony_cistatic void cdnsp_link_segments(struct cdnsp_device *pdev,
10662306a36Sopenharmony_ci				struct cdnsp_segment *prev,
10762306a36Sopenharmony_ci				struct cdnsp_segment *next,
10862306a36Sopenharmony_ci				enum cdnsp_ring_type type)
10962306a36Sopenharmony_ci{
11062306a36Sopenharmony_ci	struct cdnsp_link_trb *link;
11162306a36Sopenharmony_ci	u32 val;
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	if (!prev || !next)
11462306a36Sopenharmony_ci		return;
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	prev->next = next;
11762306a36Sopenharmony_ci	if (type != TYPE_EVENT) {
11862306a36Sopenharmony_ci		link = &prev->trbs[TRBS_PER_SEGMENT - 1].link;
11962306a36Sopenharmony_ci		link->segment_ptr = cpu_to_le64(next->dma);
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci		/*
12262306a36Sopenharmony_ci		 * Set the last TRB in the segment to have a TRB type ID
12362306a36Sopenharmony_ci		 * of Link TRB
12462306a36Sopenharmony_ci		 */
12562306a36Sopenharmony_ci		val = le32_to_cpu(link->control);
12662306a36Sopenharmony_ci		val &= ~TRB_TYPE_BITMASK;
12762306a36Sopenharmony_ci		val |= TRB_TYPE(TRB_LINK);
12862306a36Sopenharmony_ci		link->control = cpu_to_le32(val);
12962306a36Sopenharmony_ci	}
13062306a36Sopenharmony_ci}
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci/*
13362306a36Sopenharmony_ci * Link the ring to the new segments.
13462306a36Sopenharmony_ci * Set Toggle Cycle for the new ring if needed.
13562306a36Sopenharmony_ci */
13662306a36Sopenharmony_cistatic void cdnsp_link_rings(struct cdnsp_device *pdev,
13762306a36Sopenharmony_ci			     struct cdnsp_ring *ring,
13862306a36Sopenharmony_ci			     struct cdnsp_segment *first,
13962306a36Sopenharmony_ci			     struct cdnsp_segment *last,
14062306a36Sopenharmony_ci			     unsigned int num_segs)
14162306a36Sopenharmony_ci{
14262306a36Sopenharmony_ci	struct cdnsp_segment *next;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	if (!ring || !first || !last)
14562306a36Sopenharmony_ci		return;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	next = ring->enq_seg->next;
14862306a36Sopenharmony_ci	cdnsp_link_segments(pdev, ring->enq_seg, first, ring->type);
14962306a36Sopenharmony_ci	cdnsp_link_segments(pdev, last, next, ring->type);
15062306a36Sopenharmony_ci	ring->num_segs += num_segs;
15162306a36Sopenharmony_ci	ring->num_trbs_free += (TRBS_PER_SEGMENT - 1) * num_segs;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	if (ring->type != TYPE_EVENT && ring->enq_seg == ring->last_seg) {
15462306a36Sopenharmony_ci		ring->last_seg->trbs[TRBS_PER_SEGMENT - 1].link.control &=
15562306a36Sopenharmony_ci			~cpu_to_le32(LINK_TOGGLE);
15662306a36Sopenharmony_ci		last->trbs[TRBS_PER_SEGMENT - 1].link.control |=
15762306a36Sopenharmony_ci			cpu_to_le32(LINK_TOGGLE);
15862306a36Sopenharmony_ci		ring->last_seg = last;
15962306a36Sopenharmony_ci	}
16062306a36Sopenharmony_ci}
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci/*
16362306a36Sopenharmony_ci * We need a radix tree for mapping physical addresses of TRBs to which stream
16462306a36Sopenharmony_ci * ID they belong to. We need to do this because the device controller won't
16562306a36Sopenharmony_ci * tell us which stream ring the TRB came from. We could store the stream ID
16662306a36Sopenharmony_ci * in an event data TRB, but that doesn't help us for the cancellation case,
16762306a36Sopenharmony_ci * since the endpoint may stop before it reaches that event data TRB.
16862306a36Sopenharmony_ci *
16962306a36Sopenharmony_ci * The radix tree maps the upper portion of the TRB DMA address to a ring
17062306a36Sopenharmony_ci * segment that has the same upper portion of DMA addresses. For example,
17162306a36Sopenharmony_ci * say I have segments of size 1KB, that are always 1KB aligned. A segment may
17262306a36Sopenharmony_ci * start at 0x10c91000 and end at 0x10c913f0. If I use the upper 10 bits, the
17362306a36Sopenharmony_ci * key to the stream ID is 0x43244. I can use the DMA address of the TRB to
17462306a36Sopenharmony_ci * pass the radix tree a key to get the right stream ID:
17562306a36Sopenharmony_ci *
17662306a36Sopenharmony_ci *	0x10c90fff >> 10 = 0x43243
17762306a36Sopenharmony_ci *	0x10c912c0 >> 10 = 0x43244
17862306a36Sopenharmony_ci *	0x10c91400 >> 10 = 0x43245
17962306a36Sopenharmony_ci *
18062306a36Sopenharmony_ci * Obviously, only those TRBs with DMA addresses that are within the segment
18162306a36Sopenharmony_ci * will make the radix tree return the stream ID for that ring.
18262306a36Sopenharmony_ci *
18362306a36Sopenharmony_ci * Caveats for the radix tree:
18462306a36Sopenharmony_ci *
18562306a36Sopenharmony_ci * The radix tree uses an unsigned long as a key pair. On 32-bit systems, an
18662306a36Sopenharmony_ci * unsigned long will be 32-bits; on a 64-bit system an unsigned long will be
18762306a36Sopenharmony_ci * 64-bits. Since we only request 32-bit DMA addresses, we can use that as the
18862306a36Sopenharmony_ci * key on 32-bit or 64-bit systems (it would also be fine if we asked for 64-bit
18962306a36Sopenharmony_ci * PCI DMA addresses on a 64-bit system). There might be a problem on 32-bit
19062306a36Sopenharmony_ci * extended systems (where the DMA address can be bigger than 32-bits),
19162306a36Sopenharmony_ci * if we allow the PCI dma mask to be bigger than 32-bits. So don't do that.
19262306a36Sopenharmony_ci */
19362306a36Sopenharmony_cistatic int cdnsp_insert_segment_mapping(struct radix_tree_root *trb_address_map,
19462306a36Sopenharmony_ci					struct cdnsp_ring *ring,
19562306a36Sopenharmony_ci					struct cdnsp_segment *seg,
19662306a36Sopenharmony_ci					gfp_t mem_flags)
19762306a36Sopenharmony_ci{
19862306a36Sopenharmony_ci	unsigned long key;
19962306a36Sopenharmony_ci	int ret;
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	key = (unsigned long)(seg->dma >> TRB_SEGMENT_SHIFT);
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	/* Skip any segments that were already added. */
20462306a36Sopenharmony_ci	if (radix_tree_lookup(trb_address_map, key))
20562306a36Sopenharmony_ci		return 0;
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	ret = radix_tree_maybe_preload(mem_flags);
20862306a36Sopenharmony_ci	if (ret)
20962306a36Sopenharmony_ci		return ret;
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	ret = radix_tree_insert(trb_address_map, key, ring);
21262306a36Sopenharmony_ci	radix_tree_preload_end();
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	return ret;
21562306a36Sopenharmony_ci}
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_cistatic void cdnsp_remove_segment_mapping(struct radix_tree_root *trb_address_map,
21862306a36Sopenharmony_ci					 struct cdnsp_segment *seg)
21962306a36Sopenharmony_ci{
22062306a36Sopenharmony_ci	unsigned long key;
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	key = (unsigned long)(seg->dma >> TRB_SEGMENT_SHIFT);
22362306a36Sopenharmony_ci	if (radix_tree_lookup(trb_address_map, key))
22462306a36Sopenharmony_ci		radix_tree_delete(trb_address_map, key);
22562306a36Sopenharmony_ci}
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_cistatic int cdnsp_update_stream_segment_mapping(struct radix_tree_root *trb_address_map,
22862306a36Sopenharmony_ci					       struct cdnsp_ring *ring,
22962306a36Sopenharmony_ci					       struct cdnsp_segment *first_seg,
23062306a36Sopenharmony_ci					       struct cdnsp_segment *last_seg,
23162306a36Sopenharmony_ci					       gfp_t mem_flags)
23262306a36Sopenharmony_ci{
23362306a36Sopenharmony_ci	struct cdnsp_segment *failed_seg;
23462306a36Sopenharmony_ci	struct cdnsp_segment *seg;
23562306a36Sopenharmony_ci	int ret;
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	seg = first_seg;
23862306a36Sopenharmony_ci	do {
23962306a36Sopenharmony_ci		ret = cdnsp_insert_segment_mapping(trb_address_map, ring, seg,
24062306a36Sopenharmony_ci						   mem_flags);
24162306a36Sopenharmony_ci		if (ret)
24262306a36Sopenharmony_ci			goto remove_streams;
24362306a36Sopenharmony_ci		if (seg == last_seg)
24462306a36Sopenharmony_ci			return 0;
24562306a36Sopenharmony_ci		seg = seg->next;
24662306a36Sopenharmony_ci	} while (seg != first_seg);
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	return 0;
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ciremove_streams:
25162306a36Sopenharmony_ci	failed_seg = seg;
25262306a36Sopenharmony_ci	seg = first_seg;
25362306a36Sopenharmony_ci	do {
25462306a36Sopenharmony_ci		cdnsp_remove_segment_mapping(trb_address_map, seg);
25562306a36Sopenharmony_ci		if (seg == failed_seg)
25662306a36Sopenharmony_ci			return ret;
25762306a36Sopenharmony_ci		seg = seg->next;
25862306a36Sopenharmony_ci	} while (seg != first_seg);
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	return ret;
26162306a36Sopenharmony_ci}
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_cistatic void cdnsp_remove_stream_mapping(struct cdnsp_ring *ring)
26462306a36Sopenharmony_ci{
26562306a36Sopenharmony_ci	struct cdnsp_segment *seg;
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	seg = ring->first_seg;
26862306a36Sopenharmony_ci	do {
26962306a36Sopenharmony_ci		cdnsp_remove_segment_mapping(ring->trb_address_map, seg);
27062306a36Sopenharmony_ci		seg = seg->next;
27162306a36Sopenharmony_ci	} while (seg != ring->first_seg);
27262306a36Sopenharmony_ci}
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_cistatic int cdnsp_update_stream_mapping(struct cdnsp_ring *ring)
27562306a36Sopenharmony_ci{
27662306a36Sopenharmony_ci	return cdnsp_update_stream_segment_mapping(ring->trb_address_map, ring,
27762306a36Sopenharmony_ci			ring->first_seg, ring->last_seg, GFP_ATOMIC);
27862306a36Sopenharmony_ci}
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_cistatic void cdnsp_ring_free(struct cdnsp_device *pdev, struct cdnsp_ring *ring)
28162306a36Sopenharmony_ci{
28262306a36Sopenharmony_ci	if (!ring)
28362306a36Sopenharmony_ci		return;
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	trace_cdnsp_ring_free(ring);
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	if (ring->first_seg) {
28862306a36Sopenharmony_ci		if (ring->type == TYPE_STREAM)
28962306a36Sopenharmony_ci			cdnsp_remove_stream_mapping(ring);
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci		cdnsp_free_segments_for_ring(pdev, ring->first_seg);
29262306a36Sopenharmony_ci	}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	kfree(ring);
29562306a36Sopenharmony_ci}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_civoid cdnsp_initialize_ring_info(struct cdnsp_ring *ring)
29862306a36Sopenharmony_ci{
29962306a36Sopenharmony_ci	ring->enqueue = ring->first_seg->trbs;
30062306a36Sopenharmony_ci	ring->enq_seg = ring->first_seg;
30162306a36Sopenharmony_ci	ring->dequeue = ring->enqueue;
30262306a36Sopenharmony_ci	ring->deq_seg = ring->first_seg;
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	/*
30562306a36Sopenharmony_ci	 * The ring is initialized to 0. The producer must write 1 to the cycle
30662306a36Sopenharmony_ci	 * bit to handover ownership of the TRB, so PCS = 1. The consumer must
30762306a36Sopenharmony_ci	 * compare CCS to the cycle bit to check ownership, so CCS = 1.
30862306a36Sopenharmony_ci	 *
30962306a36Sopenharmony_ci	 * New rings are initialized with cycle state equal to 1; if we are
31062306a36Sopenharmony_ci	 * handling ring expansion, set the cycle state equal to the old ring.
31162306a36Sopenharmony_ci	 */
31262306a36Sopenharmony_ci	ring->cycle_state = 1;
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	/*
31562306a36Sopenharmony_ci	 * Each segment has a link TRB, and leave an extra TRB for SW
31662306a36Sopenharmony_ci	 * accounting purpose
31762306a36Sopenharmony_ci	 */
31862306a36Sopenharmony_ci	ring->num_trbs_free = ring->num_segs * (TRBS_PER_SEGMENT - 1) - 1;
31962306a36Sopenharmony_ci}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci/* Allocate segments and link them for a ring. */
32262306a36Sopenharmony_cistatic int cdnsp_alloc_segments_for_ring(struct cdnsp_device *pdev,
32362306a36Sopenharmony_ci					 struct cdnsp_segment **first,
32462306a36Sopenharmony_ci					 struct cdnsp_segment **last,
32562306a36Sopenharmony_ci					 unsigned int num_segs,
32662306a36Sopenharmony_ci					 unsigned int cycle_state,
32762306a36Sopenharmony_ci					 enum cdnsp_ring_type type,
32862306a36Sopenharmony_ci					 unsigned int max_packet,
32962306a36Sopenharmony_ci					 gfp_t flags)
33062306a36Sopenharmony_ci{
33162306a36Sopenharmony_ci	struct cdnsp_segment *prev;
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	/* Allocate first segment. */
33462306a36Sopenharmony_ci	prev = cdnsp_segment_alloc(pdev, cycle_state, max_packet, flags);
33562306a36Sopenharmony_ci	if (!prev)
33662306a36Sopenharmony_ci		return -ENOMEM;
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	num_segs--;
33962306a36Sopenharmony_ci	*first = prev;
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	/* Allocate all other segments. */
34262306a36Sopenharmony_ci	while (num_segs > 0) {
34362306a36Sopenharmony_ci		struct cdnsp_segment	*next;
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci		next = cdnsp_segment_alloc(pdev, cycle_state,
34662306a36Sopenharmony_ci					   max_packet, flags);
34762306a36Sopenharmony_ci		if (!next) {
34862306a36Sopenharmony_ci			cdnsp_free_segments_for_ring(pdev, *first);
34962306a36Sopenharmony_ci			return -ENOMEM;
35062306a36Sopenharmony_ci		}
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci		cdnsp_link_segments(pdev, prev, next, type);
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci		prev = next;
35562306a36Sopenharmony_ci		num_segs--;
35662306a36Sopenharmony_ci	}
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	cdnsp_link_segments(pdev, prev, *first, type);
35962306a36Sopenharmony_ci	*last = prev;
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	return 0;
36262306a36Sopenharmony_ci}
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci/*
36562306a36Sopenharmony_ci * Create a new ring with zero or more segments.
36662306a36Sopenharmony_ci *
36762306a36Sopenharmony_ci * Link each segment together into a ring.
36862306a36Sopenharmony_ci * Set the end flag and the cycle toggle bit on the last segment.
36962306a36Sopenharmony_ci */
37062306a36Sopenharmony_cistatic struct cdnsp_ring *cdnsp_ring_alloc(struct cdnsp_device *pdev,
37162306a36Sopenharmony_ci					   unsigned int num_segs,
37262306a36Sopenharmony_ci					   enum cdnsp_ring_type type,
37362306a36Sopenharmony_ci					   unsigned int max_packet,
37462306a36Sopenharmony_ci					   gfp_t flags)
37562306a36Sopenharmony_ci{
37662306a36Sopenharmony_ci	struct cdnsp_ring *ring;
37762306a36Sopenharmony_ci	int ret;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	ring = kzalloc(sizeof *(ring), flags);
38062306a36Sopenharmony_ci	if (!ring)
38162306a36Sopenharmony_ci		return NULL;
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	ring->num_segs = num_segs;
38462306a36Sopenharmony_ci	ring->bounce_buf_len = max_packet;
38562306a36Sopenharmony_ci	INIT_LIST_HEAD(&ring->td_list);
38662306a36Sopenharmony_ci	ring->type = type;
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	if (num_segs == 0)
38962306a36Sopenharmony_ci		return ring;
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	ret = cdnsp_alloc_segments_for_ring(pdev, &ring->first_seg,
39262306a36Sopenharmony_ci					    &ring->last_seg, num_segs,
39362306a36Sopenharmony_ci					    1, type, max_packet, flags);
39462306a36Sopenharmony_ci	if (ret)
39562306a36Sopenharmony_ci		goto fail;
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	/* Only event ring does not use link TRB. */
39862306a36Sopenharmony_ci	if (type != TYPE_EVENT)
39962306a36Sopenharmony_ci		ring->last_seg->trbs[TRBS_PER_SEGMENT - 1].link.control |=
40062306a36Sopenharmony_ci			cpu_to_le32(LINK_TOGGLE);
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	cdnsp_initialize_ring_info(ring);
40362306a36Sopenharmony_ci	trace_cdnsp_ring_alloc(ring);
40462306a36Sopenharmony_ci	return ring;
40562306a36Sopenharmony_cifail:
40662306a36Sopenharmony_ci	kfree(ring);
40762306a36Sopenharmony_ci	return NULL;
40862306a36Sopenharmony_ci}
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_civoid cdnsp_free_endpoint_rings(struct cdnsp_device *pdev, struct cdnsp_ep *pep)
41162306a36Sopenharmony_ci{
41262306a36Sopenharmony_ci	cdnsp_ring_free(pdev, pep->ring);
41362306a36Sopenharmony_ci	pep->ring = NULL;
41462306a36Sopenharmony_ci	cdnsp_free_stream_info(pdev, pep);
41562306a36Sopenharmony_ci}
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci/*
41862306a36Sopenharmony_ci * Expand an existing ring.
41962306a36Sopenharmony_ci * Allocate a new ring which has same segment numbers and link the two rings.
42062306a36Sopenharmony_ci */
42162306a36Sopenharmony_ciint cdnsp_ring_expansion(struct cdnsp_device *pdev,
42262306a36Sopenharmony_ci			 struct cdnsp_ring *ring,
42362306a36Sopenharmony_ci			 unsigned int num_trbs,
42462306a36Sopenharmony_ci			 gfp_t flags)
42562306a36Sopenharmony_ci{
42662306a36Sopenharmony_ci	unsigned int num_segs_needed;
42762306a36Sopenharmony_ci	struct cdnsp_segment *first;
42862306a36Sopenharmony_ci	struct cdnsp_segment *last;
42962306a36Sopenharmony_ci	unsigned int num_segs;
43062306a36Sopenharmony_ci	int ret;
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	num_segs_needed = (num_trbs + (TRBS_PER_SEGMENT - 1) - 1) /
43362306a36Sopenharmony_ci			(TRBS_PER_SEGMENT - 1);
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	/* Allocate number of segments we needed, or double the ring size. */
43662306a36Sopenharmony_ci	num_segs = max(ring->num_segs, num_segs_needed);
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci	ret = cdnsp_alloc_segments_for_ring(pdev, &first, &last, num_segs,
43962306a36Sopenharmony_ci					    ring->cycle_state, ring->type,
44062306a36Sopenharmony_ci					    ring->bounce_buf_len, flags);
44162306a36Sopenharmony_ci	if (ret)
44262306a36Sopenharmony_ci		return -ENOMEM;
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	if (ring->type == TYPE_STREAM)
44562306a36Sopenharmony_ci		ret = cdnsp_update_stream_segment_mapping(ring->trb_address_map,
44662306a36Sopenharmony_ci							  ring, first,
44762306a36Sopenharmony_ci							  last, flags);
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ci	if (ret) {
45062306a36Sopenharmony_ci		cdnsp_free_segments_for_ring(pdev, first);
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci		return ret;
45362306a36Sopenharmony_ci	}
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci	cdnsp_link_rings(pdev, ring, first, last, num_segs);
45662306a36Sopenharmony_ci	trace_cdnsp_ring_expansion(ring);
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	return 0;
45962306a36Sopenharmony_ci}
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_cistatic int cdnsp_init_device_ctx(struct cdnsp_device *pdev)
46262306a36Sopenharmony_ci{
46362306a36Sopenharmony_ci	int size = HCC_64BYTE_CONTEXT(pdev->hcc_params) ? 2048 : 1024;
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci	pdev->out_ctx.type = CDNSP_CTX_TYPE_DEVICE;
46662306a36Sopenharmony_ci	pdev->out_ctx.size = size;
46762306a36Sopenharmony_ci	pdev->out_ctx.ctx_size = CTX_SIZE(pdev->hcc_params);
46862306a36Sopenharmony_ci	pdev->out_ctx.bytes = dma_pool_zalloc(pdev->device_pool, GFP_ATOMIC,
46962306a36Sopenharmony_ci					      &pdev->out_ctx.dma);
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci	if (!pdev->out_ctx.bytes)
47262306a36Sopenharmony_ci		return -ENOMEM;
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	pdev->in_ctx.type = CDNSP_CTX_TYPE_INPUT;
47562306a36Sopenharmony_ci	pdev->in_ctx.ctx_size = pdev->out_ctx.ctx_size;
47662306a36Sopenharmony_ci	pdev->in_ctx.size = size + pdev->out_ctx.ctx_size;
47762306a36Sopenharmony_ci	pdev->in_ctx.bytes = dma_pool_zalloc(pdev->device_pool, GFP_ATOMIC,
47862306a36Sopenharmony_ci					     &pdev->in_ctx.dma);
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci	if (!pdev->in_ctx.bytes) {
48162306a36Sopenharmony_ci		dma_pool_free(pdev->device_pool, pdev->out_ctx.bytes,
48262306a36Sopenharmony_ci			      pdev->out_ctx.dma);
48362306a36Sopenharmony_ci		return -ENOMEM;
48462306a36Sopenharmony_ci	}
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci	return 0;
48762306a36Sopenharmony_ci}
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_cistruct cdnsp_input_control_ctx
49062306a36Sopenharmony_ci	*cdnsp_get_input_control_ctx(struct cdnsp_container_ctx *ctx)
49162306a36Sopenharmony_ci{
49262306a36Sopenharmony_ci	if (ctx->type != CDNSP_CTX_TYPE_INPUT)
49362306a36Sopenharmony_ci		return NULL;
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci	return (struct cdnsp_input_control_ctx *)ctx->bytes;
49662306a36Sopenharmony_ci}
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_cistruct cdnsp_slot_ctx *cdnsp_get_slot_ctx(struct cdnsp_container_ctx *ctx)
49962306a36Sopenharmony_ci{
50062306a36Sopenharmony_ci	if (ctx->type == CDNSP_CTX_TYPE_DEVICE)
50162306a36Sopenharmony_ci		return (struct cdnsp_slot_ctx *)ctx->bytes;
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci	return (struct cdnsp_slot_ctx *)(ctx->bytes + ctx->ctx_size);
50462306a36Sopenharmony_ci}
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_cistruct cdnsp_ep_ctx *cdnsp_get_ep_ctx(struct cdnsp_container_ctx *ctx,
50762306a36Sopenharmony_ci				      unsigned int ep_index)
50862306a36Sopenharmony_ci{
50962306a36Sopenharmony_ci	/* Increment ep index by offset of start of ep ctx array. */
51062306a36Sopenharmony_ci	ep_index++;
51162306a36Sopenharmony_ci	if (ctx->type == CDNSP_CTX_TYPE_INPUT)
51262306a36Sopenharmony_ci		ep_index++;
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	return (struct cdnsp_ep_ctx *)(ctx->bytes + (ep_index * ctx->ctx_size));
51562306a36Sopenharmony_ci}
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_cistatic void cdnsp_free_stream_ctx(struct cdnsp_device *pdev,
51862306a36Sopenharmony_ci				  struct cdnsp_ep *pep)
51962306a36Sopenharmony_ci{
52062306a36Sopenharmony_ci	dma_pool_free(pdev->device_pool, pep->stream_info.stream_ctx_array,
52162306a36Sopenharmony_ci		      pep->stream_info.ctx_array_dma);
52262306a36Sopenharmony_ci}
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci/* The stream context array must be a power of 2. */
52562306a36Sopenharmony_cistatic struct cdnsp_stream_ctx
52662306a36Sopenharmony_ci	*cdnsp_alloc_stream_ctx(struct cdnsp_device *pdev, struct cdnsp_ep *pep)
52762306a36Sopenharmony_ci{
52862306a36Sopenharmony_ci	size_t size = sizeof(struct cdnsp_stream_ctx) *
52962306a36Sopenharmony_ci		      pep->stream_info.num_stream_ctxs;
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci	if (size > CDNSP_CTX_SIZE)
53262306a36Sopenharmony_ci		return NULL;
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	/**
53562306a36Sopenharmony_ci	 * Driver uses intentionally the device_pool to allocated stream
53662306a36Sopenharmony_ci	 * context array. Device Pool has 2048 bytes of size what gives us
53762306a36Sopenharmony_ci	 * 128 entries.
53862306a36Sopenharmony_ci	 */
53962306a36Sopenharmony_ci	return dma_pool_zalloc(pdev->device_pool, GFP_DMA32 | GFP_ATOMIC,
54062306a36Sopenharmony_ci			       &pep->stream_info.ctx_array_dma);
54162306a36Sopenharmony_ci}
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_cistruct cdnsp_ring *cdnsp_dma_to_transfer_ring(struct cdnsp_ep *pep, u64 address)
54462306a36Sopenharmony_ci{
54562306a36Sopenharmony_ci	if (pep->ep_state & EP_HAS_STREAMS)
54662306a36Sopenharmony_ci		return radix_tree_lookup(&pep->stream_info.trb_address_map,
54762306a36Sopenharmony_ci					 address >> TRB_SEGMENT_SHIFT);
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci	return pep->ring;
55062306a36Sopenharmony_ci}
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci/*
55362306a36Sopenharmony_ci * Change an endpoint's internal structure so it supports stream IDs.
55462306a36Sopenharmony_ci * The number of requested streams includes stream 0, which cannot be used by
55562306a36Sopenharmony_ci * driver.
55662306a36Sopenharmony_ci *
55762306a36Sopenharmony_ci * The number of stream contexts in the stream context array may be bigger than
55862306a36Sopenharmony_ci * the number of streams the driver wants to use. This is because the number of
55962306a36Sopenharmony_ci * stream context array entries must be a power of two.
56062306a36Sopenharmony_ci */
56162306a36Sopenharmony_ciint cdnsp_alloc_stream_info(struct cdnsp_device *pdev,
56262306a36Sopenharmony_ci			    struct cdnsp_ep *pep,
56362306a36Sopenharmony_ci			    unsigned int num_stream_ctxs,
56462306a36Sopenharmony_ci			    unsigned int num_streams)
56562306a36Sopenharmony_ci{
56662306a36Sopenharmony_ci	struct cdnsp_stream_info *stream_info;
56762306a36Sopenharmony_ci	struct cdnsp_ring *cur_ring;
56862306a36Sopenharmony_ci	u32 cur_stream;
56962306a36Sopenharmony_ci	u64 addr;
57062306a36Sopenharmony_ci	int ret;
57162306a36Sopenharmony_ci	int mps;
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci	stream_info = &pep->stream_info;
57462306a36Sopenharmony_ci	stream_info->num_streams = num_streams;
57562306a36Sopenharmony_ci	stream_info->num_stream_ctxs = num_stream_ctxs;
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci	/* Initialize the array of virtual pointers to stream rings. */
57862306a36Sopenharmony_ci	stream_info->stream_rings = kcalloc(num_streams,
57962306a36Sopenharmony_ci					    sizeof(struct cdnsp_ring *),
58062306a36Sopenharmony_ci					    GFP_ATOMIC);
58162306a36Sopenharmony_ci	if (!stream_info->stream_rings)
58262306a36Sopenharmony_ci		return -ENOMEM;
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	/* Initialize the array of DMA addresses for stream rings for the HW. */
58562306a36Sopenharmony_ci	stream_info->stream_ctx_array = cdnsp_alloc_stream_ctx(pdev, pep);
58662306a36Sopenharmony_ci	if (!stream_info->stream_ctx_array)
58762306a36Sopenharmony_ci		goto cleanup_stream_rings;
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	memset(stream_info->stream_ctx_array, 0,
59062306a36Sopenharmony_ci	       sizeof(struct cdnsp_stream_ctx) * num_stream_ctxs);
59162306a36Sopenharmony_ci	INIT_RADIX_TREE(&stream_info->trb_address_map, GFP_ATOMIC);
59262306a36Sopenharmony_ci	mps = usb_endpoint_maxp(pep->endpoint.desc);
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	/*
59562306a36Sopenharmony_ci	 * Allocate rings for all the streams that the driver will use,
59662306a36Sopenharmony_ci	 * and add their segment DMA addresses to the radix tree.
59762306a36Sopenharmony_ci	 * Stream 0 is reserved.
59862306a36Sopenharmony_ci	 */
59962306a36Sopenharmony_ci	for (cur_stream = 1; cur_stream < num_streams; cur_stream++) {
60062306a36Sopenharmony_ci		cur_ring = cdnsp_ring_alloc(pdev, 2, TYPE_STREAM, mps,
60162306a36Sopenharmony_ci					    GFP_ATOMIC);
60262306a36Sopenharmony_ci		stream_info->stream_rings[cur_stream] = cur_ring;
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci		if (!cur_ring)
60562306a36Sopenharmony_ci			goto cleanup_rings;
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci		cur_ring->stream_id = cur_stream;
60862306a36Sopenharmony_ci		cur_ring->trb_address_map = &stream_info->trb_address_map;
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci		/* Set deq ptr, cycle bit, and stream context type. */
61162306a36Sopenharmony_ci		addr = cur_ring->first_seg->dma | SCT_FOR_CTX(SCT_PRI_TR) |
61262306a36Sopenharmony_ci		       cur_ring->cycle_state;
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci		stream_info->stream_ctx_array[cur_stream].stream_ring =
61562306a36Sopenharmony_ci			cpu_to_le64(addr);
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci		trace_cdnsp_set_stream_ring(cur_ring);
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci		ret = cdnsp_update_stream_mapping(cur_ring);
62062306a36Sopenharmony_ci		if (ret)
62162306a36Sopenharmony_ci			goto cleanup_rings;
62262306a36Sopenharmony_ci	}
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_ci	return 0;
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_cicleanup_rings:
62762306a36Sopenharmony_ci	for (cur_stream = 1; cur_stream < num_streams; cur_stream++) {
62862306a36Sopenharmony_ci		cur_ring = stream_info->stream_rings[cur_stream];
62962306a36Sopenharmony_ci		if (cur_ring) {
63062306a36Sopenharmony_ci			cdnsp_ring_free(pdev, cur_ring);
63162306a36Sopenharmony_ci			stream_info->stream_rings[cur_stream] = NULL;
63262306a36Sopenharmony_ci		}
63362306a36Sopenharmony_ci	}
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_cicleanup_stream_rings:
63662306a36Sopenharmony_ci	kfree(pep->stream_info.stream_rings);
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ci	return -ENOMEM;
63962306a36Sopenharmony_ci}
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci/* Frees all stream contexts associated with the endpoint. */
64262306a36Sopenharmony_cistatic void cdnsp_free_stream_info(struct cdnsp_device *pdev,
64362306a36Sopenharmony_ci				   struct cdnsp_ep *pep)
64462306a36Sopenharmony_ci{
64562306a36Sopenharmony_ci	struct cdnsp_stream_info *stream_info = &pep->stream_info;
64662306a36Sopenharmony_ci	struct cdnsp_ring *cur_ring;
64762306a36Sopenharmony_ci	int cur_stream;
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ci	if (!(pep->ep_state & EP_HAS_STREAMS))
65062306a36Sopenharmony_ci		return;
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	for (cur_stream = 1; cur_stream < stream_info->num_streams;
65362306a36Sopenharmony_ci	     cur_stream++) {
65462306a36Sopenharmony_ci		cur_ring = stream_info->stream_rings[cur_stream];
65562306a36Sopenharmony_ci		if (cur_ring) {
65662306a36Sopenharmony_ci			cdnsp_ring_free(pdev, cur_ring);
65762306a36Sopenharmony_ci			stream_info->stream_rings[cur_stream] = NULL;
65862306a36Sopenharmony_ci		}
65962306a36Sopenharmony_ci	}
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	if (stream_info->stream_ctx_array)
66262306a36Sopenharmony_ci		cdnsp_free_stream_ctx(pdev, pep);
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci	kfree(stream_info->stream_rings);
66562306a36Sopenharmony_ci	pep->ep_state &= ~EP_HAS_STREAMS;
66662306a36Sopenharmony_ci}
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci/* All the cdnsp_tds in the ring's TD list should be freed at this point.*/
66962306a36Sopenharmony_cistatic void cdnsp_free_priv_device(struct cdnsp_device *pdev)
67062306a36Sopenharmony_ci{
67162306a36Sopenharmony_ci	pdev->dcbaa->dev_context_ptrs[1] = 0;
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci	cdnsp_free_endpoint_rings(pdev, &pdev->eps[0]);
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci	if (pdev->in_ctx.bytes)
67662306a36Sopenharmony_ci		dma_pool_free(pdev->device_pool, pdev->in_ctx.bytes,
67762306a36Sopenharmony_ci			      pdev->in_ctx.dma);
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci	if (pdev->out_ctx.bytes)
68062306a36Sopenharmony_ci		dma_pool_free(pdev->device_pool, pdev->out_ctx.bytes,
68162306a36Sopenharmony_ci			      pdev->out_ctx.dma);
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci	pdev->in_ctx.bytes = NULL;
68462306a36Sopenharmony_ci	pdev->out_ctx.bytes = NULL;
68562306a36Sopenharmony_ci}
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_cistatic int cdnsp_alloc_priv_device(struct cdnsp_device *pdev)
68862306a36Sopenharmony_ci{
68962306a36Sopenharmony_ci	int ret;
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	ret = cdnsp_init_device_ctx(pdev);
69262306a36Sopenharmony_ci	if (ret)
69362306a36Sopenharmony_ci		return ret;
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	/* Allocate endpoint 0 ring. */
69662306a36Sopenharmony_ci	pdev->eps[0].ring = cdnsp_ring_alloc(pdev, 2, TYPE_CTRL, 0, GFP_ATOMIC);
69762306a36Sopenharmony_ci	if (!pdev->eps[0].ring)
69862306a36Sopenharmony_ci		goto fail;
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci	/* Point to output device context in dcbaa. */
70162306a36Sopenharmony_ci	pdev->dcbaa->dev_context_ptrs[1] = cpu_to_le64(pdev->out_ctx.dma);
70262306a36Sopenharmony_ci	pdev->cmd.in_ctx = &pdev->in_ctx;
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_ci	trace_cdnsp_alloc_priv_device(pdev);
70562306a36Sopenharmony_ci	return 0;
70662306a36Sopenharmony_cifail:
70762306a36Sopenharmony_ci	dma_pool_free(pdev->device_pool, pdev->out_ctx.bytes,
70862306a36Sopenharmony_ci		      pdev->out_ctx.dma);
70962306a36Sopenharmony_ci	dma_pool_free(pdev->device_pool, pdev->in_ctx.bytes,
71062306a36Sopenharmony_ci		      pdev->in_ctx.dma);
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci	return ret;
71362306a36Sopenharmony_ci}
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_civoid cdnsp_copy_ep0_dequeue_into_input_ctx(struct cdnsp_device *pdev)
71662306a36Sopenharmony_ci{
71762306a36Sopenharmony_ci	struct cdnsp_ep_ctx *ep0_ctx = pdev->eps[0].in_ctx;
71862306a36Sopenharmony_ci	struct cdnsp_ring *ep_ring = pdev->eps[0].ring;
71962306a36Sopenharmony_ci	dma_addr_t dma;
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_ci	dma = cdnsp_trb_virt_to_dma(ep_ring->enq_seg, ep_ring->enqueue);
72262306a36Sopenharmony_ci	ep0_ctx->deq = cpu_to_le64(dma | ep_ring->cycle_state);
72362306a36Sopenharmony_ci}
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_ci/* Setup an controller private device for a Set Address command. */
72662306a36Sopenharmony_ciint cdnsp_setup_addressable_priv_dev(struct cdnsp_device *pdev)
72762306a36Sopenharmony_ci{
72862306a36Sopenharmony_ci	struct cdnsp_slot_ctx *slot_ctx;
72962306a36Sopenharmony_ci	struct cdnsp_ep_ctx *ep0_ctx;
73062306a36Sopenharmony_ci	u32 max_packets, port;
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	ep0_ctx = cdnsp_get_ep_ctx(&pdev->in_ctx, 0);
73362306a36Sopenharmony_ci	slot_ctx = cdnsp_get_slot_ctx(&pdev->in_ctx);
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci	/* Only the control endpoint is valid - one endpoint context. */
73662306a36Sopenharmony_ci	slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1));
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci	switch (pdev->gadget.speed) {
73962306a36Sopenharmony_ci	case USB_SPEED_SUPER_PLUS:
74062306a36Sopenharmony_ci		slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SSP);
74162306a36Sopenharmony_ci		max_packets = MAX_PACKET(512);
74262306a36Sopenharmony_ci		break;
74362306a36Sopenharmony_ci	case USB_SPEED_SUPER:
74462306a36Sopenharmony_ci		slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SS);
74562306a36Sopenharmony_ci		max_packets = MAX_PACKET(512);
74662306a36Sopenharmony_ci		break;
74762306a36Sopenharmony_ci	case USB_SPEED_HIGH:
74862306a36Sopenharmony_ci		slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_HS);
74962306a36Sopenharmony_ci		max_packets = MAX_PACKET(64);
75062306a36Sopenharmony_ci		break;
75162306a36Sopenharmony_ci	case USB_SPEED_FULL:
75262306a36Sopenharmony_ci		slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_FS);
75362306a36Sopenharmony_ci		max_packets = MAX_PACKET(64);
75462306a36Sopenharmony_ci		break;
75562306a36Sopenharmony_ci	default:
75662306a36Sopenharmony_ci		/* Speed was not set , this shouldn't happen. */
75762306a36Sopenharmony_ci		return -EINVAL;
75862306a36Sopenharmony_ci	}
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ci	port = DEV_PORT(pdev->active_port->port_num);
76162306a36Sopenharmony_ci	slot_ctx->dev_port |= cpu_to_le32(port);
76262306a36Sopenharmony_ci	slot_ctx->dev_state = cpu_to_le32((pdev->device_address &
76362306a36Sopenharmony_ci					   DEV_ADDR_MASK));
76462306a36Sopenharmony_ci	ep0_ctx->tx_info = cpu_to_le32(EP_AVG_TRB_LENGTH(0x8));
76562306a36Sopenharmony_ci	ep0_ctx->ep_info2 = cpu_to_le32(EP_TYPE(CTRL_EP));
76662306a36Sopenharmony_ci	ep0_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(0) | ERROR_COUNT(3) |
76762306a36Sopenharmony_ci					 max_packets);
76862306a36Sopenharmony_ci
76962306a36Sopenharmony_ci	ep0_ctx->deq = cpu_to_le64(pdev->eps[0].ring->first_seg->dma |
77062306a36Sopenharmony_ci				   pdev->eps[0].ring->cycle_state);
77162306a36Sopenharmony_ci
77262306a36Sopenharmony_ci	trace_cdnsp_setup_addressable_priv_device(pdev);
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci	return 0;
77562306a36Sopenharmony_ci}
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci/*
77862306a36Sopenharmony_ci * Convert interval expressed as 2^(bInterval - 1) == interval into
77962306a36Sopenharmony_ci * straight exponent value 2^n == interval.
78062306a36Sopenharmony_ci */
78162306a36Sopenharmony_cistatic unsigned int cdnsp_parse_exponent_interval(struct usb_gadget *g,
78262306a36Sopenharmony_ci						  struct cdnsp_ep *pep)
78362306a36Sopenharmony_ci{
78462306a36Sopenharmony_ci	unsigned int interval;
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci	interval = clamp_val(pep->endpoint.desc->bInterval, 1, 16) - 1;
78762306a36Sopenharmony_ci	if (interval != pep->endpoint.desc->bInterval - 1)
78862306a36Sopenharmony_ci		dev_warn(&g->dev, "ep %s - rounding interval to %d %sframes\n",
78962306a36Sopenharmony_ci			 pep->name, 1 << interval,
79062306a36Sopenharmony_ci			 g->speed == USB_SPEED_FULL ? "" : "micro");
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci	/*
79362306a36Sopenharmony_ci	 * Full speed isoc endpoints specify interval in frames,
79462306a36Sopenharmony_ci	 * not microframes. We are using microframes everywhere,
79562306a36Sopenharmony_ci	 * so adjust accordingly.
79662306a36Sopenharmony_ci	 */
79762306a36Sopenharmony_ci	if (g->speed == USB_SPEED_FULL)
79862306a36Sopenharmony_ci		interval += 3;	/* 1 frame = 2^3 uframes */
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci	/* Controller handles only up to 512ms (2^12). */
80162306a36Sopenharmony_ci	if (interval > 12)
80262306a36Sopenharmony_ci		interval = 12;
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci	return interval;
80562306a36Sopenharmony_ci}
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ci/*
80862306a36Sopenharmony_ci * Convert bInterval expressed in microframes (in 1-255 range) to exponent of
80962306a36Sopenharmony_ci * microframes, rounded down to nearest power of 2.
81062306a36Sopenharmony_ci */
81162306a36Sopenharmony_cistatic unsigned int cdnsp_microframes_to_exponent(struct usb_gadget *g,
81262306a36Sopenharmony_ci						  struct cdnsp_ep *pep,
81362306a36Sopenharmony_ci						  unsigned int desc_interval,
81462306a36Sopenharmony_ci						  unsigned int min_exponent,
81562306a36Sopenharmony_ci						  unsigned int max_exponent)
81662306a36Sopenharmony_ci{
81762306a36Sopenharmony_ci	unsigned int interval;
81862306a36Sopenharmony_ci
81962306a36Sopenharmony_ci	interval = fls(desc_interval) - 1;
82062306a36Sopenharmony_ci	return clamp_val(interval, min_exponent, max_exponent);
82162306a36Sopenharmony_ci}
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_ci/*
82462306a36Sopenharmony_ci * Return the polling interval.
82562306a36Sopenharmony_ci *
82662306a36Sopenharmony_ci * The polling interval is expressed in "microframes". If controllers's Interval
82762306a36Sopenharmony_ci * field is set to N, it will service the endpoint every 2^(Interval)*125us.
82862306a36Sopenharmony_ci */
82962306a36Sopenharmony_cistatic unsigned int cdnsp_get_endpoint_interval(struct usb_gadget *g,
83062306a36Sopenharmony_ci						struct cdnsp_ep *pep)
83162306a36Sopenharmony_ci{
83262306a36Sopenharmony_ci	unsigned int interval = 0;
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci	switch (g->speed) {
83562306a36Sopenharmony_ci	case USB_SPEED_HIGH:
83662306a36Sopenharmony_ci	case USB_SPEED_SUPER_PLUS:
83762306a36Sopenharmony_ci	case USB_SPEED_SUPER:
83862306a36Sopenharmony_ci		if (usb_endpoint_xfer_int(pep->endpoint.desc) ||
83962306a36Sopenharmony_ci		    usb_endpoint_xfer_isoc(pep->endpoint.desc))
84062306a36Sopenharmony_ci			interval = cdnsp_parse_exponent_interval(g, pep);
84162306a36Sopenharmony_ci		break;
84262306a36Sopenharmony_ci	case USB_SPEED_FULL:
84362306a36Sopenharmony_ci		if (usb_endpoint_xfer_isoc(pep->endpoint.desc)) {
84462306a36Sopenharmony_ci			interval = cdnsp_parse_exponent_interval(g, pep);
84562306a36Sopenharmony_ci		} else if (usb_endpoint_xfer_int(pep->endpoint.desc)) {
84662306a36Sopenharmony_ci			interval = pep->endpoint.desc->bInterval << 3;
84762306a36Sopenharmony_ci			interval = cdnsp_microframes_to_exponent(g, pep,
84862306a36Sopenharmony_ci								 interval,
84962306a36Sopenharmony_ci								 3, 10);
85062306a36Sopenharmony_ci		}
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_ci		break;
85362306a36Sopenharmony_ci	default:
85462306a36Sopenharmony_ci		WARN_ON(1);
85562306a36Sopenharmony_ci	}
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ci	return interval;
85862306a36Sopenharmony_ci}
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci/*
86162306a36Sopenharmony_ci * The "Mult" field in the endpoint context is only set for SuperSpeed isoc eps.
86262306a36Sopenharmony_ci * High speed endpoint descriptors can define "the number of additional
86362306a36Sopenharmony_ci * transaction opportunities per microframe", but that goes in the Max Burst
86462306a36Sopenharmony_ci * endpoint context field.
86562306a36Sopenharmony_ci */
86662306a36Sopenharmony_cistatic u32 cdnsp_get_endpoint_mult(struct usb_gadget *g, struct cdnsp_ep *pep)
86762306a36Sopenharmony_ci{
86862306a36Sopenharmony_ci	if (g->speed < USB_SPEED_SUPER ||
86962306a36Sopenharmony_ci	    !usb_endpoint_xfer_isoc(pep->endpoint.desc))
87062306a36Sopenharmony_ci		return 0;
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci	return pep->endpoint.comp_desc->bmAttributes;
87362306a36Sopenharmony_ci}
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_cistatic u32 cdnsp_get_endpoint_max_burst(struct usb_gadget *g,
87662306a36Sopenharmony_ci					struct cdnsp_ep *pep)
87762306a36Sopenharmony_ci{
87862306a36Sopenharmony_ci	/* Super speed and Plus have max burst in ep companion desc */
87962306a36Sopenharmony_ci	if (g->speed >= USB_SPEED_SUPER)
88062306a36Sopenharmony_ci		return pep->endpoint.comp_desc->bMaxBurst;
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci	if (g->speed == USB_SPEED_HIGH &&
88362306a36Sopenharmony_ci	    (usb_endpoint_xfer_isoc(pep->endpoint.desc) ||
88462306a36Sopenharmony_ci	     usb_endpoint_xfer_int(pep->endpoint.desc)))
88562306a36Sopenharmony_ci		return usb_endpoint_maxp_mult(pep->endpoint.desc) - 1;
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ci	return 0;
88862306a36Sopenharmony_ci}
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_cistatic u32 cdnsp_get_endpoint_type(const struct usb_endpoint_descriptor *desc)
89162306a36Sopenharmony_ci{
89262306a36Sopenharmony_ci	int in;
89362306a36Sopenharmony_ci
89462306a36Sopenharmony_ci	in = usb_endpoint_dir_in(desc);
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_ci	switch (usb_endpoint_type(desc)) {
89762306a36Sopenharmony_ci	case USB_ENDPOINT_XFER_CONTROL:
89862306a36Sopenharmony_ci		return CTRL_EP;
89962306a36Sopenharmony_ci	case USB_ENDPOINT_XFER_BULK:
90062306a36Sopenharmony_ci		return in ? BULK_IN_EP : BULK_OUT_EP;
90162306a36Sopenharmony_ci	case USB_ENDPOINT_XFER_ISOC:
90262306a36Sopenharmony_ci		return in ? ISOC_IN_EP : ISOC_OUT_EP;
90362306a36Sopenharmony_ci	case USB_ENDPOINT_XFER_INT:
90462306a36Sopenharmony_ci		return in ? INT_IN_EP : INT_OUT_EP;
90562306a36Sopenharmony_ci	}
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_ci	return 0;
90862306a36Sopenharmony_ci}
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci/*
91162306a36Sopenharmony_ci * Return the maximum endpoint service interval time (ESIT) payload.
91262306a36Sopenharmony_ci * Basically, this is the maxpacket size, multiplied by the burst size
91362306a36Sopenharmony_ci * and mult size.
91462306a36Sopenharmony_ci */
91562306a36Sopenharmony_cistatic u32 cdnsp_get_max_esit_payload(struct usb_gadget *g,
91662306a36Sopenharmony_ci				      struct cdnsp_ep *pep)
91762306a36Sopenharmony_ci{
91862306a36Sopenharmony_ci	int max_packet;
91962306a36Sopenharmony_ci	int max_burst;
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci	/* Only applies for interrupt or isochronous endpoints*/
92262306a36Sopenharmony_ci	if (usb_endpoint_xfer_control(pep->endpoint.desc) ||
92362306a36Sopenharmony_ci	    usb_endpoint_xfer_bulk(pep->endpoint.desc))
92462306a36Sopenharmony_ci		return 0;
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_ci	/* SuperSpeedPlus Isoc ep sending over 48k per EIST. */
92762306a36Sopenharmony_ci	if (g->speed >= USB_SPEED_SUPER_PLUS &&
92862306a36Sopenharmony_ci	    USB_SS_SSP_ISOC_COMP(pep->endpoint.desc->bmAttributes))
92962306a36Sopenharmony_ci		return le16_to_cpu(pep->endpoint.comp_desc->wBytesPerInterval);
93062306a36Sopenharmony_ci	/* SuperSpeed or SuperSpeedPlus Isoc ep with less than 48k per esit */
93162306a36Sopenharmony_ci	else if (g->speed >= USB_SPEED_SUPER)
93262306a36Sopenharmony_ci		return le16_to_cpu(pep->endpoint.comp_desc->wBytesPerInterval);
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_ci	max_packet = usb_endpoint_maxp(pep->endpoint.desc);
93562306a36Sopenharmony_ci	max_burst = usb_endpoint_maxp_mult(pep->endpoint.desc);
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_ci	/* A 0 in max burst means 1 transfer per ESIT */
93862306a36Sopenharmony_ci	return max_packet * max_burst;
93962306a36Sopenharmony_ci}
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_ciint cdnsp_endpoint_init(struct cdnsp_device *pdev,
94262306a36Sopenharmony_ci			struct cdnsp_ep *pep,
94362306a36Sopenharmony_ci			gfp_t mem_flags)
94462306a36Sopenharmony_ci{
94562306a36Sopenharmony_ci	enum cdnsp_ring_type ring_type;
94662306a36Sopenharmony_ci	struct cdnsp_ep_ctx *ep_ctx;
94762306a36Sopenharmony_ci	unsigned int err_count = 0;
94862306a36Sopenharmony_ci	unsigned int avg_trb_len;
94962306a36Sopenharmony_ci	unsigned int max_packet;
95062306a36Sopenharmony_ci	unsigned int max_burst;
95162306a36Sopenharmony_ci	unsigned int interval;
95262306a36Sopenharmony_ci	u32 max_esit_payload;
95362306a36Sopenharmony_ci	unsigned int mult;
95462306a36Sopenharmony_ci	u32 endpoint_type;
95562306a36Sopenharmony_ci	int ret;
95662306a36Sopenharmony_ci
95762306a36Sopenharmony_ci	ep_ctx = pep->in_ctx;
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_ci	endpoint_type = cdnsp_get_endpoint_type(pep->endpoint.desc);
96062306a36Sopenharmony_ci	if (!endpoint_type)
96162306a36Sopenharmony_ci		return -EINVAL;
96262306a36Sopenharmony_ci
96362306a36Sopenharmony_ci	ring_type = usb_endpoint_type(pep->endpoint.desc);
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	/*
96662306a36Sopenharmony_ci	 * Get values to fill the endpoint context, mostly from ep descriptor.
96762306a36Sopenharmony_ci	 * The average TRB buffer length for bulk endpoints is unclear as we
96862306a36Sopenharmony_ci	 * have no clue on scatter gather list entry size. For Isoc and Int,
96962306a36Sopenharmony_ci	 * set it to max available.
97062306a36Sopenharmony_ci	 */
97162306a36Sopenharmony_ci	max_esit_payload = cdnsp_get_max_esit_payload(&pdev->gadget, pep);
97262306a36Sopenharmony_ci	interval = cdnsp_get_endpoint_interval(&pdev->gadget, pep);
97362306a36Sopenharmony_ci	mult = cdnsp_get_endpoint_mult(&pdev->gadget, pep);
97462306a36Sopenharmony_ci	max_packet = usb_endpoint_maxp(pep->endpoint.desc);
97562306a36Sopenharmony_ci	max_burst = cdnsp_get_endpoint_max_burst(&pdev->gadget, pep);
97662306a36Sopenharmony_ci	avg_trb_len = max_esit_payload;
97762306a36Sopenharmony_ci
97862306a36Sopenharmony_ci	/* Allow 3 retries for everything but isoc, set CErr = 3. */
97962306a36Sopenharmony_ci	if (!usb_endpoint_xfer_isoc(pep->endpoint.desc))
98062306a36Sopenharmony_ci		err_count = 3;
98162306a36Sopenharmony_ci	if (usb_endpoint_xfer_bulk(pep->endpoint.desc) &&
98262306a36Sopenharmony_ci	    pdev->gadget.speed == USB_SPEED_HIGH)
98362306a36Sopenharmony_ci		max_packet = 512;
98462306a36Sopenharmony_ci	/* Controller spec indicates that ctrl ep avg TRB Length should be 8. */
98562306a36Sopenharmony_ci	if (usb_endpoint_xfer_control(pep->endpoint.desc))
98662306a36Sopenharmony_ci		avg_trb_len = 8;
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci	/* Set up the endpoint ring. */
98962306a36Sopenharmony_ci	pep->ring = cdnsp_ring_alloc(pdev, 2, ring_type, max_packet, mem_flags);
99062306a36Sopenharmony_ci	if (!pep->ring)
99162306a36Sopenharmony_ci		return -ENOMEM;
99262306a36Sopenharmony_ci
99362306a36Sopenharmony_ci	pep->skip = false;
99462306a36Sopenharmony_ci
99562306a36Sopenharmony_ci	/* Fill the endpoint context */
99662306a36Sopenharmony_ci	ep_ctx->ep_info = cpu_to_le32(EP_MAX_ESIT_PAYLOAD_HI(max_esit_payload) |
99762306a36Sopenharmony_ci				EP_INTERVAL(interval) | EP_MULT(mult));
99862306a36Sopenharmony_ci	ep_ctx->ep_info2 = cpu_to_le32(EP_TYPE(endpoint_type) |
99962306a36Sopenharmony_ci				MAX_PACKET(max_packet) | MAX_BURST(max_burst) |
100062306a36Sopenharmony_ci				ERROR_COUNT(err_count));
100162306a36Sopenharmony_ci	ep_ctx->deq = cpu_to_le64(pep->ring->first_seg->dma |
100262306a36Sopenharmony_ci				  pep->ring->cycle_state);
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci	ep_ctx->tx_info = cpu_to_le32(EP_MAX_ESIT_PAYLOAD_LO(max_esit_payload) |
100562306a36Sopenharmony_ci				EP_AVG_TRB_LENGTH(avg_trb_len));
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	if (usb_endpoint_xfer_bulk(pep->endpoint.desc) &&
100862306a36Sopenharmony_ci	    pdev->gadget.speed > USB_SPEED_HIGH) {
100962306a36Sopenharmony_ci		ret = cdnsp_alloc_streams(pdev, pep);
101062306a36Sopenharmony_ci		if (ret < 0)
101162306a36Sopenharmony_ci			return ret;
101262306a36Sopenharmony_ci	}
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_ci	return 0;
101562306a36Sopenharmony_ci}
101662306a36Sopenharmony_ci
101762306a36Sopenharmony_civoid cdnsp_endpoint_zero(struct cdnsp_device *pdev, struct cdnsp_ep *pep)
101862306a36Sopenharmony_ci{
101962306a36Sopenharmony_ci	pep->in_ctx->ep_info = 0;
102062306a36Sopenharmony_ci	pep->in_ctx->ep_info2 = 0;
102162306a36Sopenharmony_ci	pep->in_ctx->deq = 0;
102262306a36Sopenharmony_ci	pep->in_ctx->tx_info = 0;
102362306a36Sopenharmony_ci}
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_cistatic int cdnsp_alloc_erst(struct cdnsp_device *pdev,
102662306a36Sopenharmony_ci			    struct cdnsp_ring *evt_ring,
102762306a36Sopenharmony_ci			    struct cdnsp_erst *erst)
102862306a36Sopenharmony_ci{
102962306a36Sopenharmony_ci	struct cdnsp_erst_entry *entry;
103062306a36Sopenharmony_ci	struct cdnsp_segment *seg;
103162306a36Sopenharmony_ci	unsigned int val;
103262306a36Sopenharmony_ci	size_t size;
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_ci	size = sizeof(struct cdnsp_erst_entry) * evt_ring->num_segs;
103562306a36Sopenharmony_ci	erst->entries = dma_alloc_coherent(pdev->dev, size,
103662306a36Sopenharmony_ci					   &erst->erst_dma_addr, GFP_KERNEL);
103762306a36Sopenharmony_ci	if (!erst->entries)
103862306a36Sopenharmony_ci		return -ENOMEM;
103962306a36Sopenharmony_ci
104062306a36Sopenharmony_ci	erst->num_entries = evt_ring->num_segs;
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci	seg = evt_ring->first_seg;
104362306a36Sopenharmony_ci	for (val = 0; val < evt_ring->num_segs; val++) {
104462306a36Sopenharmony_ci		entry = &erst->entries[val];
104562306a36Sopenharmony_ci		entry->seg_addr = cpu_to_le64(seg->dma);
104662306a36Sopenharmony_ci		entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT);
104762306a36Sopenharmony_ci		entry->rsvd = 0;
104862306a36Sopenharmony_ci		seg = seg->next;
104962306a36Sopenharmony_ci	}
105062306a36Sopenharmony_ci
105162306a36Sopenharmony_ci	return 0;
105262306a36Sopenharmony_ci}
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_cistatic void cdnsp_free_erst(struct cdnsp_device *pdev, struct cdnsp_erst *erst)
105562306a36Sopenharmony_ci{
105662306a36Sopenharmony_ci	size_t size = sizeof(struct cdnsp_erst_entry) * (erst->num_entries);
105762306a36Sopenharmony_ci	struct device *dev = pdev->dev;
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci	if (erst->entries)
106062306a36Sopenharmony_ci		dma_free_coherent(dev, size, erst->entries,
106162306a36Sopenharmony_ci				  erst->erst_dma_addr);
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_ci	erst->entries = NULL;
106462306a36Sopenharmony_ci}
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_civoid cdnsp_mem_cleanup(struct cdnsp_device *pdev)
106762306a36Sopenharmony_ci{
106862306a36Sopenharmony_ci	struct device *dev = pdev->dev;
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ci	cdnsp_free_priv_device(pdev);
107162306a36Sopenharmony_ci	cdnsp_free_erst(pdev, &pdev->erst);
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_ci	if (pdev->event_ring)
107462306a36Sopenharmony_ci		cdnsp_ring_free(pdev, pdev->event_ring);
107562306a36Sopenharmony_ci
107662306a36Sopenharmony_ci	pdev->event_ring = NULL;
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	if (pdev->cmd_ring)
107962306a36Sopenharmony_ci		cdnsp_ring_free(pdev, pdev->cmd_ring);
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_ci	pdev->cmd_ring = NULL;
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	dma_pool_destroy(pdev->segment_pool);
108462306a36Sopenharmony_ci	pdev->segment_pool = NULL;
108562306a36Sopenharmony_ci	dma_pool_destroy(pdev->device_pool);
108662306a36Sopenharmony_ci	pdev->device_pool = NULL;
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci	dma_free_coherent(dev, sizeof(*pdev->dcbaa),
108962306a36Sopenharmony_ci			  pdev->dcbaa, pdev->dcbaa->dma);
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_ci	pdev->dcbaa = NULL;
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci	pdev->usb2_port.exist = 0;
109462306a36Sopenharmony_ci	pdev->usb3_port.exist = 0;
109562306a36Sopenharmony_ci	pdev->usb2_port.port_num = 0;
109662306a36Sopenharmony_ci	pdev->usb3_port.port_num = 0;
109762306a36Sopenharmony_ci	pdev->active_port = NULL;
109862306a36Sopenharmony_ci}
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_cistatic void cdnsp_set_event_deq(struct cdnsp_device *pdev)
110162306a36Sopenharmony_ci{
110262306a36Sopenharmony_ci	dma_addr_t deq;
110362306a36Sopenharmony_ci	u64 temp;
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ci	deq = cdnsp_trb_virt_to_dma(pdev->event_ring->deq_seg,
110662306a36Sopenharmony_ci				    pdev->event_ring->dequeue);
110762306a36Sopenharmony_ci
110862306a36Sopenharmony_ci	/* Update controller event ring dequeue pointer */
110962306a36Sopenharmony_ci	temp = cdnsp_read_64(&pdev->ir_set->erst_dequeue);
111062306a36Sopenharmony_ci	temp &= ERST_PTR_MASK;
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_ci	/*
111362306a36Sopenharmony_ci	 * Don't clear the EHB bit (which is RW1C) because
111462306a36Sopenharmony_ci	 * there might be more events to service.
111562306a36Sopenharmony_ci	 */
111662306a36Sopenharmony_ci	temp &= ~ERST_EHB;
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_ci	cdnsp_write_64(((u64)deq & (u64)~ERST_PTR_MASK) | temp,
111962306a36Sopenharmony_ci		       &pdev->ir_set->erst_dequeue);
112062306a36Sopenharmony_ci}
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_cistatic void cdnsp_add_in_port(struct cdnsp_device *pdev,
112362306a36Sopenharmony_ci			      struct cdnsp_port *port,
112462306a36Sopenharmony_ci			      __le32 __iomem *addr)
112562306a36Sopenharmony_ci{
112662306a36Sopenharmony_ci	u32 temp, port_offset, port_count;
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	temp = readl(addr);
112962306a36Sopenharmony_ci	port->maj_rev = CDNSP_EXT_PORT_MAJOR(temp);
113062306a36Sopenharmony_ci	port->min_rev = CDNSP_EXT_PORT_MINOR(temp);
113162306a36Sopenharmony_ci
113262306a36Sopenharmony_ci	/* Port offset and count in the third dword.*/
113362306a36Sopenharmony_ci	temp = readl(addr + 2);
113462306a36Sopenharmony_ci	port_offset = CDNSP_EXT_PORT_OFF(temp);
113562306a36Sopenharmony_ci	port_count = CDNSP_EXT_PORT_COUNT(temp);
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci	trace_cdnsp_port_info(addr, port_offset, port_count, port->maj_rev);
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_ci	port->port_num = port_offset;
114062306a36Sopenharmony_ci	port->exist = 1;
114162306a36Sopenharmony_ci}
114262306a36Sopenharmony_ci
114362306a36Sopenharmony_ci/*
114462306a36Sopenharmony_ci * Scan the Extended Capabilities for the "Supported Protocol Capabilities" that
114562306a36Sopenharmony_ci * specify what speeds each port is supposed to be.
114662306a36Sopenharmony_ci */
114762306a36Sopenharmony_cistatic int cdnsp_setup_port_arrays(struct cdnsp_device *pdev)
114862306a36Sopenharmony_ci{
114962306a36Sopenharmony_ci	void __iomem *base;
115062306a36Sopenharmony_ci	u32 offset;
115162306a36Sopenharmony_ci	int i;
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci	base = &pdev->cap_regs->hc_capbase;
115462306a36Sopenharmony_ci	offset = cdnsp_find_next_ext_cap(base, 0,
115562306a36Sopenharmony_ci					 EXT_CAP_CFG_DEV_20PORT_CAP_ID);
115662306a36Sopenharmony_ci	pdev->port20_regs = base + offset;
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci	offset = cdnsp_find_next_ext_cap(base, 0, D_XEC_CFG_3XPORT_CAP);
115962306a36Sopenharmony_ci	pdev->port3x_regs =  base + offset;
116062306a36Sopenharmony_ci
116162306a36Sopenharmony_ci	offset = 0;
116262306a36Sopenharmony_ci	base = &pdev->cap_regs->hc_capbase;
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_ci	/* Driver expects max 2 extended protocol capability. */
116562306a36Sopenharmony_ci	for (i = 0; i < 2; i++) {
116662306a36Sopenharmony_ci		u32 temp;
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci		offset = cdnsp_find_next_ext_cap(base, offset,
116962306a36Sopenharmony_ci						 EXT_CAPS_PROTOCOL);
117062306a36Sopenharmony_ci		temp = readl(base + offset);
117162306a36Sopenharmony_ci
117262306a36Sopenharmony_ci		if (CDNSP_EXT_PORT_MAJOR(temp) == 0x03 &&
117362306a36Sopenharmony_ci		    !pdev->usb3_port.port_num)
117462306a36Sopenharmony_ci			cdnsp_add_in_port(pdev, &pdev->usb3_port,
117562306a36Sopenharmony_ci					  base + offset);
117662306a36Sopenharmony_ci
117762306a36Sopenharmony_ci		if (CDNSP_EXT_PORT_MAJOR(temp) == 0x02 &&
117862306a36Sopenharmony_ci		    !pdev->usb2_port.port_num)
117962306a36Sopenharmony_ci			cdnsp_add_in_port(pdev, &pdev->usb2_port,
118062306a36Sopenharmony_ci					  base + offset);
118162306a36Sopenharmony_ci	}
118262306a36Sopenharmony_ci
118362306a36Sopenharmony_ci	if (!pdev->usb2_port.exist || !pdev->usb3_port.exist) {
118462306a36Sopenharmony_ci		dev_err(pdev->dev, "Error: Only one port detected\n");
118562306a36Sopenharmony_ci		return -ENODEV;
118662306a36Sopenharmony_ci	}
118762306a36Sopenharmony_ci
118862306a36Sopenharmony_ci	trace_cdnsp_init("Found USB 2.0 ports and  USB 3.0 ports.");
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci	pdev->usb2_port.regs = (struct cdnsp_port_regs __iomem *)
119162306a36Sopenharmony_ci			       (&pdev->op_regs->port_reg_base + NUM_PORT_REGS *
119262306a36Sopenharmony_ci				(pdev->usb2_port.port_num - 1));
119362306a36Sopenharmony_ci
119462306a36Sopenharmony_ci	pdev->usb3_port.regs = (struct cdnsp_port_regs __iomem *)
119562306a36Sopenharmony_ci			       (&pdev->op_regs->port_reg_base + NUM_PORT_REGS *
119662306a36Sopenharmony_ci				(pdev->usb3_port.port_num - 1));
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci	return 0;
119962306a36Sopenharmony_ci}
120062306a36Sopenharmony_ci
120162306a36Sopenharmony_ci/*
120262306a36Sopenharmony_ci * Initialize memory for CDNSP (one-time init).
120362306a36Sopenharmony_ci *
120462306a36Sopenharmony_ci * Program the PAGESIZE register, initialize the device context array, create
120562306a36Sopenharmony_ci * device contexts, set up a command ring segment, create event
120662306a36Sopenharmony_ci * ring (one for now).
120762306a36Sopenharmony_ci */
120862306a36Sopenharmony_ciint cdnsp_mem_init(struct cdnsp_device *pdev)
120962306a36Sopenharmony_ci{
121062306a36Sopenharmony_ci	struct device *dev = pdev->dev;
121162306a36Sopenharmony_ci	int ret = -ENOMEM;
121262306a36Sopenharmony_ci	unsigned int val;
121362306a36Sopenharmony_ci	dma_addr_t dma;
121462306a36Sopenharmony_ci	u32 page_size;
121562306a36Sopenharmony_ci	u64 val_64;
121662306a36Sopenharmony_ci
121762306a36Sopenharmony_ci	/*
121862306a36Sopenharmony_ci	 * Use 4K pages, since that's common and the minimum the
121962306a36Sopenharmony_ci	 * controller supports
122062306a36Sopenharmony_ci	 */
122162306a36Sopenharmony_ci	page_size = 1 << 12;
122262306a36Sopenharmony_ci
122362306a36Sopenharmony_ci	val = readl(&pdev->op_regs->config_reg);
122462306a36Sopenharmony_ci	val |= ((val & ~MAX_DEVS) | CDNSP_DEV_MAX_SLOTS) | CONFIG_U3E;
122562306a36Sopenharmony_ci	writel(val, &pdev->op_regs->config_reg);
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci	/*
122862306a36Sopenharmony_ci	 * Doorbell array must be physically contiguous
122962306a36Sopenharmony_ci	 * and 64-byte (cache line) aligned.
123062306a36Sopenharmony_ci	 */
123162306a36Sopenharmony_ci	pdev->dcbaa = dma_alloc_coherent(dev, sizeof(*pdev->dcbaa),
123262306a36Sopenharmony_ci					 &dma, GFP_KERNEL);
123362306a36Sopenharmony_ci	if (!pdev->dcbaa)
123462306a36Sopenharmony_ci		return -ENOMEM;
123562306a36Sopenharmony_ci
123662306a36Sopenharmony_ci	pdev->dcbaa->dma = dma;
123762306a36Sopenharmony_ci
123862306a36Sopenharmony_ci	cdnsp_write_64(dma, &pdev->op_regs->dcbaa_ptr);
123962306a36Sopenharmony_ci
124062306a36Sopenharmony_ci	/*
124162306a36Sopenharmony_ci	 * Initialize the ring segment pool.  The ring must be a contiguous
124262306a36Sopenharmony_ci	 * structure comprised of TRBs. The TRBs must be 16 byte aligned,
124362306a36Sopenharmony_ci	 * however, the command ring segment needs 64-byte aligned segments
124462306a36Sopenharmony_ci	 * and our use of dma addresses in the trb_address_map radix tree needs
124562306a36Sopenharmony_ci	 * TRB_SEGMENT_SIZE alignment, so driver pick the greater alignment
124662306a36Sopenharmony_ci	 * need.
124762306a36Sopenharmony_ci	 */
124862306a36Sopenharmony_ci	pdev->segment_pool = dma_pool_create("CDNSP ring segments", dev,
124962306a36Sopenharmony_ci					     TRB_SEGMENT_SIZE, TRB_SEGMENT_SIZE,
125062306a36Sopenharmony_ci					     page_size);
125162306a36Sopenharmony_ci	if (!pdev->segment_pool)
125262306a36Sopenharmony_ci		goto release_dcbaa;
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_ci	pdev->device_pool = dma_pool_create("CDNSP input/output contexts", dev,
125562306a36Sopenharmony_ci					    CDNSP_CTX_SIZE, 64, page_size);
125662306a36Sopenharmony_ci	if (!pdev->device_pool)
125762306a36Sopenharmony_ci		goto destroy_segment_pool;
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_ci
126062306a36Sopenharmony_ci	/* Set up the command ring to have one segments for now. */
126162306a36Sopenharmony_ci	pdev->cmd_ring = cdnsp_ring_alloc(pdev, 1, TYPE_COMMAND, 0, GFP_KERNEL);
126262306a36Sopenharmony_ci	if (!pdev->cmd_ring)
126362306a36Sopenharmony_ci		goto destroy_device_pool;
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_ci	/* Set the address in the Command Ring Control register */
126662306a36Sopenharmony_ci	val_64 = cdnsp_read_64(&pdev->op_regs->cmd_ring);
126762306a36Sopenharmony_ci	val_64 = (val_64 & (u64)CMD_RING_RSVD_BITS) |
126862306a36Sopenharmony_ci		 (pdev->cmd_ring->first_seg->dma & (u64)~CMD_RING_RSVD_BITS) |
126962306a36Sopenharmony_ci		 pdev->cmd_ring->cycle_state;
127062306a36Sopenharmony_ci	cdnsp_write_64(val_64, &pdev->op_regs->cmd_ring);
127162306a36Sopenharmony_ci
127262306a36Sopenharmony_ci	val = readl(&pdev->cap_regs->db_off);
127362306a36Sopenharmony_ci	val &= DBOFF_MASK;
127462306a36Sopenharmony_ci	pdev->dba = (void __iomem *)pdev->cap_regs + val;
127562306a36Sopenharmony_ci
127662306a36Sopenharmony_ci	/* Set ir_set to interrupt register set 0 */
127762306a36Sopenharmony_ci	pdev->ir_set = &pdev->run_regs->ir_set[0];
127862306a36Sopenharmony_ci
127962306a36Sopenharmony_ci	/*
128062306a36Sopenharmony_ci	 * Event ring setup: Allocate a normal ring, but also setup
128162306a36Sopenharmony_ci	 * the event ring segment table (ERST).
128262306a36Sopenharmony_ci	 */
128362306a36Sopenharmony_ci	pdev->event_ring = cdnsp_ring_alloc(pdev, ERST_NUM_SEGS, TYPE_EVENT,
128462306a36Sopenharmony_ci					    0, GFP_KERNEL);
128562306a36Sopenharmony_ci	if (!pdev->event_ring)
128662306a36Sopenharmony_ci		goto free_cmd_ring;
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ci	ret = cdnsp_alloc_erst(pdev, pdev->event_ring, &pdev->erst);
128962306a36Sopenharmony_ci	if (ret)
129062306a36Sopenharmony_ci		goto free_event_ring;
129162306a36Sopenharmony_ci
129262306a36Sopenharmony_ci	/* Set ERST count with the number of entries in the segment table. */
129362306a36Sopenharmony_ci	val = readl(&pdev->ir_set->erst_size);
129462306a36Sopenharmony_ci	val &= ERST_SIZE_MASK;
129562306a36Sopenharmony_ci	val |= ERST_NUM_SEGS;
129662306a36Sopenharmony_ci	writel(val, &pdev->ir_set->erst_size);
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_ci	/* Set the segment table base address. */
129962306a36Sopenharmony_ci	val_64 = cdnsp_read_64(&pdev->ir_set->erst_base);
130062306a36Sopenharmony_ci	val_64 &= ERST_PTR_MASK;
130162306a36Sopenharmony_ci	val_64 |= (pdev->erst.erst_dma_addr & (u64)~ERST_PTR_MASK);
130262306a36Sopenharmony_ci	cdnsp_write_64(val_64, &pdev->ir_set->erst_base);
130362306a36Sopenharmony_ci
130462306a36Sopenharmony_ci	/* Set the event ring dequeue address. */
130562306a36Sopenharmony_ci	cdnsp_set_event_deq(pdev);
130662306a36Sopenharmony_ci
130762306a36Sopenharmony_ci	ret = cdnsp_setup_port_arrays(pdev);
130862306a36Sopenharmony_ci	if (ret)
130962306a36Sopenharmony_ci		goto free_erst;
131062306a36Sopenharmony_ci
131162306a36Sopenharmony_ci	ret = cdnsp_alloc_priv_device(pdev);
131262306a36Sopenharmony_ci	if (ret) {
131362306a36Sopenharmony_ci		dev_err(pdev->dev,
131462306a36Sopenharmony_ci			"Could not allocate cdnsp_device data structures\n");
131562306a36Sopenharmony_ci		goto free_erst;
131662306a36Sopenharmony_ci	}
131762306a36Sopenharmony_ci
131862306a36Sopenharmony_ci	return 0;
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_cifree_erst:
132162306a36Sopenharmony_ci	cdnsp_free_erst(pdev, &pdev->erst);
132262306a36Sopenharmony_cifree_event_ring:
132362306a36Sopenharmony_ci	cdnsp_ring_free(pdev, pdev->event_ring);
132462306a36Sopenharmony_cifree_cmd_ring:
132562306a36Sopenharmony_ci	cdnsp_ring_free(pdev, pdev->cmd_ring);
132662306a36Sopenharmony_cidestroy_device_pool:
132762306a36Sopenharmony_ci	dma_pool_destroy(pdev->device_pool);
132862306a36Sopenharmony_cidestroy_segment_pool:
132962306a36Sopenharmony_ci	dma_pool_destroy(pdev->segment_pool);
133062306a36Sopenharmony_cirelease_dcbaa:
133162306a36Sopenharmony_ci	dma_free_coherent(dev, sizeof(*pdev->dcbaa), pdev->dcbaa,
133262306a36Sopenharmony_ci			  pdev->dcbaa->dma);
133362306a36Sopenharmony_ci
133462306a36Sopenharmony_ci	cdnsp_reset(pdev);
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_ci	return ret;
133762306a36Sopenharmony_ci}
1338