13d829045SPawel Laszczak // SPDX-License-Identifier: GPL-2.0 23d829045SPawel Laszczak /* 33d829045SPawel Laszczak * Cadence CDNSP DRD Driver. 43d829045SPawel Laszczak * 53d829045SPawel Laszczak * Copyright (C) 2020 Cadence. 63d829045SPawel Laszczak * 73d829045SPawel Laszczak * Author: Pawel Laszczak <pawell@cadence.com> 83d829045SPawel Laszczak * 93d829045SPawel Laszczak * Code based on Linux XHCI driver. 103d829045SPawel Laszczak * Origin: Copyright (C) 2008 Intel Corp. 113d829045SPawel Laszczak */ 123d829045SPawel Laszczak 133d829045SPawel Laszczak #include <linux/dma-mapping.h> 143d829045SPawel Laszczak #include <linux/dmapool.h> 153d829045SPawel Laszczak #include <linux/slab.h> 163d829045SPawel Laszczak #include <linux/usb.h> 173d829045SPawel Laszczak 183d829045SPawel Laszczak #include "cdnsp-gadget.h" 19118b2a32SPawel Laszczak #include "cdnsp-trace.h" 203d829045SPawel Laszczak 213d829045SPawel Laszczak static void cdnsp_free_stream_info(struct cdnsp_device *pdev, 223d829045SPawel Laszczak struct cdnsp_ep *pep); 233d829045SPawel Laszczak /* 243d829045SPawel Laszczak * Allocates a generic ring segment from the ring pool, sets the dma address, 253d829045SPawel Laszczak * initializes the segment to zero, and sets the private next pointer to NULL. 263d829045SPawel Laszczak * 273d829045SPawel Laszczak * "All components of all Command and Transfer TRBs shall be initialized to '0'" 283d829045SPawel Laszczak */ 293d829045SPawel Laszczak static struct cdnsp_segment *cdnsp_segment_alloc(struct cdnsp_device *pdev, 303d829045SPawel Laszczak unsigned int cycle_state, 313d829045SPawel Laszczak unsigned int max_packet, 323d829045SPawel Laszczak gfp_t flags) 333d829045SPawel Laszczak { 343d829045SPawel Laszczak struct cdnsp_segment *seg; 353d829045SPawel Laszczak dma_addr_t dma; 363d829045SPawel Laszczak int i; 373d829045SPawel Laszczak 383d829045SPawel Laszczak seg = kzalloc(sizeof(*seg), flags); 393d829045SPawel Laszczak if (!seg) 403d829045SPawel Laszczak return NULL; 413d829045SPawel Laszczak 423d829045SPawel Laszczak seg->trbs = dma_pool_zalloc(pdev->segment_pool, flags, &dma); 433d829045SPawel Laszczak if (!seg->trbs) { 443d829045SPawel Laszczak kfree(seg); 453d829045SPawel Laszczak return NULL; 463d829045SPawel Laszczak } 473d829045SPawel Laszczak 483d829045SPawel Laszczak if (max_packet) { 493d829045SPawel Laszczak seg->bounce_buf = kzalloc(max_packet, flags | GFP_DMA); 503d829045SPawel Laszczak if (!seg->bounce_buf) 513d829045SPawel Laszczak goto free_dma; 523d829045SPawel Laszczak } 533d829045SPawel Laszczak 543d829045SPawel Laszczak /* If the cycle state is 0, set the cycle bit to 1 for all the TRBs. */ 553d829045SPawel Laszczak if (cycle_state == 0) { 563d829045SPawel Laszczak for (i = 0; i < TRBS_PER_SEGMENT; i++) 573d829045SPawel Laszczak seg->trbs[i].link.control |= cpu_to_le32(TRB_CYCLE); 583d829045SPawel Laszczak } 593d829045SPawel Laszczak seg->dma = dma; 603d829045SPawel Laszczak seg->next = NULL; 613d829045SPawel Laszczak 623d829045SPawel Laszczak return seg; 633d829045SPawel Laszczak 643d829045SPawel Laszczak free_dma: 653d829045SPawel Laszczak dma_pool_free(pdev->segment_pool, seg->trbs, dma); 663d829045SPawel Laszczak kfree(seg); 673d829045SPawel Laszczak 683d829045SPawel Laszczak return NULL; 693d829045SPawel Laszczak } 703d829045SPawel Laszczak 713d829045SPawel Laszczak static void cdnsp_segment_free(struct cdnsp_device *pdev, 723d829045SPawel Laszczak struct cdnsp_segment *seg) 733d829045SPawel Laszczak { 743d829045SPawel Laszczak if (seg->trbs) 753d829045SPawel Laszczak dma_pool_free(pdev->segment_pool, seg->trbs, seg->dma); 763d829045SPawel Laszczak 773d829045SPawel Laszczak kfree(seg->bounce_buf); 783d829045SPawel Laszczak kfree(seg); 793d829045SPawel Laszczak } 803d829045SPawel Laszczak 813d829045SPawel Laszczak static void cdnsp_free_segments_for_ring(struct cdnsp_device *pdev, 823d829045SPawel Laszczak struct cdnsp_segment *first) 833d829045SPawel Laszczak { 843d829045SPawel Laszczak struct cdnsp_segment *seg; 853d829045SPawel Laszczak 863d829045SPawel Laszczak seg = first->next; 873d829045SPawel Laszczak 883d829045SPawel Laszczak while (seg != first) { 893d829045SPawel Laszczak struct cdnsp_segment *next = seg->next; 903d829045SPawel Laszczak 913d829045SPawel Laszczak cdnsp_segment_free(pdev, seg); 923d829045SPawel Laszczak seg = next; 933d829045SPawel Laszczak } 943d829045SPawel Laszczak 953d829045SPawel Laszczak cdnsp_segment_free(pdev, first); 963d829045SPawel Laszczak } 973d829045SPawel Laszczak 983d829045SPawel Laszczak /* 993d829045SPawel Laszczak * Make the prev segment point to the next segment. 1003d829045SPawel Laszczak * 1013d829045SPawel Laszczak * Change the last TRB in the prev segment to be a Link TRB which points to the 1023d829045SPawel Laszczak * DMA address of the next segment. The caller needs to set any Link TRB 1033d829045SPawel Laszczak * related flags, such as End TRB, Toggle Cycle, and no snoop. 1043d829045SPawel Laszczak */ 1053d829045SPawel Laszczak static void cdnsp_link_segments(struct cdnsp_device *pdev, 1063d829045SPawel Laszczak struct cdnsp_segment *prev, 1073d829045SPawel Laszczak struct cdnsp_segment *next, 1083d829045SPawel Laszczak enum cdnsp_ring_type type) 1093d829045SPawel Laszczak { 1103d829045SPawel Laszczak struct cdnsp_link_trb *link; 1113d829045SPawel Laszczak u32 val; 1123d829045SPawel Laszczak 1133d829045SPawel Laszczak if (!prev || !next) 1143d829045SPawel Laszczak return; 1153d829045SPawel Laszczak 1163d829045SPawel Laszczak prev->next = next; 1173d829045SPawel Laszczak if (type != TYPE_EVENT) { 1183d829045SPawel Laszczak link = &prev->trbs[TRBS_PER_SEGMENT - 1].link; 1193d829045SPawel Laszczak link->segment_ptr = cpu_to_le64(next->dma); 1203d829045SPawel Laszczak 1213d829045SPawel Laszczak /* 1223d829045SPawel Laszczak * Set the last TRB in the segment to have a TRB type ID 1233d829045SPawel Laszczak * of Link TRB 1243d829045SPawel Laszczak */ 1253d829045SPawel Laszczak val = le32_to_cpu(link->control); 1263d829045SPawel Laszczak val &= ~TRB_TYPE_BITMASK; 1273d829045SPawel Laszczak val |= TRB_TYPE(TRB_LINK); 1283d829045SPawel Laszczak link->control = cpu_to_le32(val); 1293d829045SPawel Laszczak } 1303d829045SPawel Laszczak } 1313d829045SPawel Laszczak 1323d829045SPawel Laszczak /* 1333d829045SPawel Laszczak * Link the ring to the new segments. 1343d829045SPawel Laszczak * Set Toggle Cycle for the new ring if needed. 1353d829045SPawel Laszczak */ 1363d829045SPawel Laszczak static void cdnsp_link_rings(struct cdnsp_device *pdev, 1373d829045SPawel Laszczak struct cdnsp_ring *ring, 1383d829045SPawel Laszczak struct cdnsp_segment *first, 1393d829045SPawel Laszczak struct cdnsp_segment *last, 1403d829045SPawel Laszczak unsigned int num_segs) 1413d829045SPawel Laszczak { 1423d829045SPawel Laszczak struct cdnsp_segment *next; 1433d829045SPawel Laszczak 1443d829045SPawel Laszczak if (!ring || !first || !last) 1453d829045SPawel Laszczak return; 1463d829045SPawel Laszczak 1473d829045SPawel Laszczak next = ring->enq_seg->next; 1483d829045SPawel Laszczak cdnsp_link_segments(pdev, ring->enq_seg, first, ring->type); 1493d829045SPawel Laszczak cdnsp_link_segments(pdev, last, next, ring->type); 1503d829045SPawel Laszczak ring->num_segs += num_segs; 1513d829045SPawel Laszczak ring->num_trbs_free += (TRBS_PER_SEGMENT - 1) * num_segs; 1523d829045SPawel Laszczak 1533d829045SPawel Laszczak if (ring->type != TYPE_EVENT && ring->enq_seg == ring->last_seg) { 1543d829045SPawel Laszczak ring->last_seg->trbs[TRBS_PER_SEGMENT - 1].link.control &= 1553d829045SPawel Laszczak ~cpu_to_le32(LINK_TOGGLE); 1563d829045SPawel Laszczak last->trbs[TRBS_PER_SEGMENT - 1].link.control |= 1573d829045SPawel Laszczak cpu_to_le32(LINK_TOGGLE); 1583d829045SPawel Laszczak ring->last_seg = last; 1593d829045SPawel Laszczak } 1603d829045SPawel Laszczak } 1613d829045SPawel Laszczak 1623d829045SPawel Laszczak /* 1633d829045SPawel Laszczak * We need a radix tree for mapping physical addresses of TRBs to which stream 1643d829045SPawel Laszczak * ID they belong to. We need to do this because the device controller won't 1653d829045SPawel Laszczak * tell us which stream ring the TRB came from. We could store the stream ID 1663d829045SPawel Laszczak * in an event data TRB, but that doesn't help us for the cancellation case, 1673d829045SPawel Laszczak * since the endpoint may stop before it reaches that event data TRB. 1683d829045SPawel Laszczak * 1693d829045SPawel Laszczak * The radix tree maps the upper portion of the TRB DMA address to a ring 1703d829045SPawel Laszczak * segment that has the same upper portion of DMA addresses. For example, 1713d829045SPawel Laszczak * say I have segments of size 1KB, that are always 1KB aligned. A segment may 1723d829045SPawel Laszczak * start at 0x10c91000 and end at 0x10c913f0. If I use the upper 10 bits, the 1733d829045SPawel Laszczak * key to the stream ID is 0x43244. I can use the DMA address of the TRB to 1743d829045SPawel Laszczak * pass the radix tree a key to get the right stream ID: 1753d829045SPawel Laszczak * 1763d829045SPawel Laszczak * 0x10c90fff >> 10 = 0x43243 1773d829045SPawel Laszczak * 0x10c912c0 >> 10 = 0x43244 1783d829045SPawel Laszczak * 0x10c91400 >> 10 = 0x43245 1793d829045SPawel Laszczak * 1803d829045SPawel Laszczak * Obviously, only those TRBs with DMA addresses that are within the segment 1813d829045SPawel Laszczak * will make the radix tree return the stream ID for that ring. 1823d829045SPawel Laszczak * 1833d829045SPawel Laszczak * Caveats for the radix tree: 1843d829045SPawel Laszczak * 1853d829045SPawel Laszczak * The radix tree uses an unsigned long as a key pair. On 32-bit systems, an 1863d829045SPawel Laszczak * unsigned long will be 32-bits; on a 64-bit system an unsigned long will be 1873d829045SPawel Laszczak * 64-bits. Since we only request 32-bit DMA addresses, we can use that as the 1883d829045SPawel Laszczak * key on 32-bit or 64-bit systems (it would also be fine if we asked for 64-bit 1893d829045SPawel Laszczak * PCI DMA addresses on a 64-bit system). There might be a problem on 32-bit 1903d829045SPawel Laszczak * extended systems (where the DMA address can be bigger than 32-bits), 1913d829045SPawel Laszczak * if we allow the PCI dma mask to be bigger than 32-bits. So don't do that. 1923d829045SPawel Laszczak */ 1933d829045SPawel Laszczak static int cdnsp_insert_segment_mapping(struct radix_tree_root *trb_address_map, 1943d829045SPawel Laszczak struct cdnsp_ring *ring, 1953d829045SPawel Laszczak struct cdnsp_segment *seg, 1963d829045SPawel Laszczak gfp_t mem_flags) 1973d829045SPawel Laszczak { 1983d829045SPawel Laszczak unsigned long key; 1993d829045SPawel Laszczak int ret; 2003d829045SPawel Laszczak 2013d829045SPawel Laszczak key = (unsigned long)(seg->dma >> TRB_SEGMENT_SHIFT); 2023d829045SPawel Laszczak 2033d829045SPawel Laszczak /* Skip any segments that were already added. */ 2043d829045SPawel Laszczak if (radix_tree_lookup(trb_address_map, key)) 2053d829045SPawel Laszczak return 0; 2063d829045SPawel Laszczak 2073d829045SPawel Laszczak ret = radix_tree_maybe_preload(mem_flags); 2083d829045SPawel Laszczak if (ret) 2093d829045SPawel Laszczak return ret; 2103d829045SPawel Laszczak 2113d829045SPawel Laszczak ret = radix_tree_insert(trb_address_map, key, ring); 2123d829045SPawel Laszczak radix_tree_preload_end(); 2133d829045SPawel Laszczak 2143d829045SPawel Laszczak return ret; 2153d829045SPawel Laszczak } 2163d829045SPawel Laszczak 2173d829045SPawel Laszczak static void cdnsp_remove_segment_mapping(struct radix_tree_root *trb_address_map, 2183d829045SPawel Laszczak struct cdnsp_segment *seg) 2193d829045SPawel Laszczak { 2203d829045SPawel Laszczak unsigned long key; 2213d829045SPawel Laszczak 2223d829045SPawel Laszczak key = (unsigned long)(seg->dma >> TRB_SEGMENT_SHIFT); 2233d829045SPawel Laszczak if (radix_tree_lookup(trb_address_map, key)) 2243d829045SPawel Laszczak radix_tree_delete(trb_address_map, key); 2253d829045SPawel Laszczak } 2263d829045SPawel Laszczak 2273d829045SPawel Laszczak static int cdnsp_update_stream_segment_mapping(struct radix_tree_root *trb_address_map, 2283d829045SPawel Laszczak struct cdnsp_ring *ring, 2293d829045SPawel Laszczak struct cdnsp_segment *first_seg, 2303d829045SPawel Laszczak struct cdnsp_segment *last_seg, 2313d829045SPawel Laszczak gfp_t mem_flags) 2323d829045SPawel Laszczak { 2333d829045SPawel Laszczak struct cdnsp_segment *failed_seg; 2343d829045SPawel Laszczak struct cdnsp_segment *seg; 2353d829045SPawel Laszczak int ret; 2363d829045SPawel Laszczak 2373d829045SPawel Laszczak seg = first_seg; 2383d829045SPawel Laszczak do { 2393d829045SPawel Laszczak ret = cdnsp_insert_segment_mapping(trb_address_map, ring, seg, 2403d829045SPawel Laszczak mem_flags); 2413d829045SPawel Laszczak if (ret) 2423d829045SPawel Laszczak goto remove_streams; 2433d829045SPawel Laszczak if (seg == last_seg) 2443d829045SPawel Laszczak return 0; 2453d829045SPawel Laszczak seg = seg->next; 2463d829045SPawel Laszczak } while (seg != first_seg); 2473d829045SPawel Laszczak 2483d829045SPawel Laszczak return 0; 2493d829045SPawel Laszczak 2503d829045SPawel Laszczak remove_streams: 2513d829045SPawel Laszczak failed_seg = seg; 2523d829045SPawel Laszczak seg = first_seg; 2533d829045SPawel Laszczak do { 2543d829045SPawel Laszczak cdnsp_remove_segment_mapping(trb_address_map, seg); 2553d829045SPawel Laszczak if (seg == failed_seg) 2563d829045SPawel Laszczak return ret; 2573d829045SPawel Laszczak seg = seg->next; 2583d829045SPawel Laszczak } while (seg != first_seg); 2593d829045SPawel Laszczak 2603d829045SPawel Laszczak return ret; 2613d829045SPawel Laszczak } 2623d829045SPawel Laszczak 2633d829045SPawel Laszczak static void cdnsp_remove_stream_mapping(struct cdnsp_ring *ring) 2643d829045SPawel Laszczak { 2653d829045SPawel Laszczak struct cdnsp_segment *seg; 2663d829045SPawel Laszczak 2673d829045SPawel Laszczak seg = ring->first_seg; 2683d829045SPawel Laszczak do { 2693d829045SPawel Laszczak cdnsp_remove_segment_mapping(ring->trb_address_map, seg); 2703d829045SPawel Laszczak seg = seg->next; 2713d829045SPawel Laszczak } while (seg != ring->first_seg); 2723d829045SPawel Laszczak } 2733d829045SPawel Laszczak 2743d829045SPawel Laszczak static int cdnsp_update_stream_mapping(struct cdnsp_ring *ring) 2753d829045SPawel Laszczak { 2763d829045SPawel Laszczak return cdnsp_update_stream_segment_mapping(ring->trb_address_map, ring, 2773d829045SPawel Laszczak ring->first_seg, ring->last_seg, GFP_ATOMIC); 2783d829045SPawel Laszczak } 2793d829045SPawel Laszczak 2803d829045SPawel Laszczak static void cdnsp_ring_free(struct cdnsp_device *pdev, struct cdnsp_ring *ring) 2813d829045SPawel Laszczak { 2823d829045SPawel Laszczak if (!ring) 2833d829045SPawel Laszczak return; 2843d829045SPawel Laszczak 285118b2a32SPawel Laszczak trace_cdnsp_ring_free(ring); 286118b2a32SPawel Laszczak 2873d829045SPawel Laszczak if (ring->first_seg) { 2883d829045SPawel Laszczak if (ring->type == TYPE_STREAM) 2893d829045SPawel Laszczak cdnsp_remove_stream_mapping(ring); 2903d829045SPawel Laszczak 2913d829045SPawel Laszczak cdnsp_free_segments_for_ring(pdev, ring->first_seg); 2923d829045SPawel Laszczak } 2933d829045SPawel Laszczak 2943d829045SPawel Laszczak kfree(ring); 2953d829045SPawel Laszczak } 2963d829045SPawel Laszczak 2973d829045SPawel Laszczak void cdnsp_initialize_ring_info(struct cdnsp_ring *ring) 2983d829045SPawel Laszczak { 2993d829045SPawel Laszczak ring->enqueue = ring->first_seg->trbs; 3003d829045SPawel Laszczak ring->enq_seg = ring->first_seg; 3013d829045SPawel Laszczak ring->dequeue = ring->enqueue; 3023d829045SPawel Laszczak ring->deq_seg = ring->first_seg; 3033d829045SPawel Laszczak 3043d829045SPawel Laszczak /* 3053d829045SPawel Laszczak * The ring is initialized to 0. The producer must write 1 to the cycle 3063d829045SPawel Laszczak * bit to handover ownership of the TRB, so PCS = 1. The consumer must 3073d829045SPawel Laszczak * compare CCS to the cycle bit to check ownership, so CCS = 1. 3083d829045SPawel Laszczak * 3093d829045SPawel Laszczak * New rings are initialized with cycle state equal to 1; if we are 3103d829045SPawel Laszczak * handling ring expansion, set the cycle state equal to the old ring. 3113d829045SPawel Laszczak */ 3123d829045SPawel Laszczak ring->cycle_state = 1; 3133d829045SPawel Laszczak 3143d829045SPawel Laszczak /* 3153d829045SPawel Laszczak * Each segment has a link TRB, and leave an extra TRB for SW 3163d829045SPawel Laszczak * accounting purpose 3173d829045SPawel Laszczak */ 3183d829045SPawel Laszczak ring->num_trbs_free = ring->num_segs * (TRBS_PER_SEGMENT - 1) - 1; 3193d829045SPawel Laszczak } 3203d829045SPawel Laszczak 3213d829045SPawel Laszczak /* Allocate segments and link them for a ring. */ 3223d829045SPawel Laszczak static int cdnsp_alloc_segments_for_ring(struct cdnsp_device *pdev, 3233d829045SPawel Laszczak struct cdnsp_segment **first, 3243d829045SPawel Laszczak struct cdnsp_segment **last, 3253d829045SPawel Laszczak unsigned int num_segs, 3263d829045SPawel Laszczak unsigned int cycle_state, 3273d829045SPawel Laszczak enum cdnsp_ring_type type, 3283d829045SPawel Laszczak unsigned int max_packet, 3293d829045SPawel Laszczak gfp_t flags) 3303d829045SPawel Laszczak { 3313d829045SPawel Laszczak struct cdnsp_segment *prev; 3323d829045SPawel Laszczak 3333d829045SPawel Laszczak /* Allocate first segment. */ 3343d829045SPawel Laszczak prev = cdnsp_segment_alloc(pdev, cycle_state, max_packet, flags); 3353d829045SPawel Laszczak if (!prev) 3363d829045SPawel Laszczak return -ENOMEM; 3373d829045SPawel Laszczak 3383d829045SPawel Laszczak num_segs--; 3393d829045SPawel Laszczak *first = prev; 3403d829045SPawel Laszczak 3413d829045SPawel Laszczak /* Allocate all other segments. */ 3423d829045SPawel Laszczak while (num_segs > 0) { 3433d829045SPawel Laszczak struct cdnsp_segment *next; 3443d829045SPawel Laszczak 3453d829045SPawel Laszczak next = cdnsp_segment_alloc(pdev, cycle_state, 3463d829045SPawel Laszczak max_packet, flags); 3473d829045SPawel Laszczak if (!next) { 3483d829045SPawel Laszczak cdnsp_free_segments_for_ring(pdev, *first); 3493d829045SPawel Laszczak return -ENOMEM; 3503d829045SPawel Laszczak } 3513d829045SPawel Laszczak 3523d829045SPawel Laszczak cdnsp_link_segments(pdev, prev, next, type); 3533d829045SPawel Laszczak 3543d829045SPawel Laszczak prev = next; 3553d829045SPawel Laszczak num_segs--; 3563d829045SPawel Laszczak } 3573d829045SPawel Laszczak 3583d829045SPawel Laszczak cdnsp_link_segments(pdev, prev, *first, type); 3593d829045SPawel Laszczak *last = prev; 3603d829045SPawel Laszczak 3613d829045SPawel Laszczak return 0; 3623d829045SPawel Laszczak } 3633d829045SPawel Laszczak 3643d829045SPawel Laszczak /* 3653d829045SPawel Laszczak * Create a new ring with zero or more segments. 3663d829045SPawel Laszczak * 3673d829045SPawel Laszczak * Link each segment together into a ring. 3683d829045SPawel Laszczak * Set the end flag and the cycle toggle bit on the last segment. 3693d829045SPawel Laszczak */ 3703d829045SPawel Laszczak static struct cdnsp_ring *cdnsp_ring_alloc(struct cdnsp_device *pdev, 3713d829045SPawel Laszczak unsigned int num_segs, 3723d829045SPawel Laszczak enum cdnsp_ring_type type, 3733d829045SPawel Laszczak unsigned int max_packet, 3743d829045SPawel Laszczak gfp_t flags) 3753d829045SPawel Laszczak { 3763d829045SPawel Laszczak struct cdnsp_ring *ring; 3773d829045SPawel Laszczak int ret; 3783d829045SPawel Laszczak 3793d829045SPawel Laszczak ring = kzalloc(sizeof *(ring), flags); 3803d829045SPawel Laszczak if (!ring) 3813d829045SPawel Laszczak return NULL; 3823d829045SPawel Laszczak 3833d829045SPawel Laszczak ring->num_segs = num_segs; 3843d829045SPawel Laszczak ring->bounce_buf_len = max_packet; 3853d829045SPawel Laszczak INIT_LIST_HEAD(&ring->td_list); 3863d829045SPawel Laszczak ring->type = type; 3873d829045SPawel Laszczak 3883d829045SPawel Laszczak if (num_segs == 0) 3893d829045SPawel Laszczak return ring; 3903d829045SPawel Laszczak 3913d829045SPawel Laszczak ret = cdnsp_alloc_segments_for_ring(pdev, &ring->first_seg, 3923d829045SPawel Laszczak &ring->last_seg, num_segs, 3933d829045SPawel Laszczak 1, type, max_packet, flags); 3943d829045SPawel Laszczak if (ret) 3953d829045SPawel Laszczak goto fail; 3963d829045SPawel Laszczak 3973d829045SPawel Laszczak /* Only event ring does not use link TRB. */ 3983d829045SPawel Laszczak if (type != TYPE_EVENT) 3993d829045SPawel Laszczak ring->last_seg->trbs[TRBS_PER_SEGMENT - 1].link.control |= 4003d829045SPawel Laszczak cpu_to_le32(LINK_TOGGLE); 4013d829045SPawel Laszczak 4023d829045SPawel Laszczak cdnsp_initialize_ring_info(ring); 403118b2a32SPawel Laszczak trace_cdnsp_ring_alloc(ring); 4043d829045SPawel Laszczak return ring; 4053d829045SPawel Laszczak fail: 4063d829045SPawel Laszczak kfree(ring); 4073d829045SPawel Laszczak return NULL; 4083d829045SPawel Laszczak } 4093d829045SPawel Laszczak 4103d829045SPawel Laszczak void cdnsp_free_endpoint_rings(struct cdnsp_device *pdev, struct cdnsp_ep *pep) 4113d829045SPawel Laszczak { 4123d829045SPawel Laszczak cdnsp_ring_free(pdev, pep->ring); 4133d829045SPawel Laszczak pep->ring = NULL; 4143d829045SPawel Laszczak cdnsp_free_stream_info(pdev, pep); 4153d829045SPawel Laszczak } 4163d829045SPawel Laszczak 4173d829045SPawel Laszczak /* 4183d829045SPawel Laszczak * Expand an existing ring. 4193d829045SPawel Laszczak * Allocate a new ring which has same segment numbers and link the two rings. 4203d829045SPawel Laszczak */ 4213d829045SPawel Laszczak int cdnsp_ring_expansion(struct cdnsp_device *pdev, 4223d829045SPawel Laszczak struct cdnsp_ring *ring, 4233d829045SPawel Laszczak unsigned int num_trbs, 4243d829045SPawel Laszczak gfp_t flags) 4253d829045SPawel Laszczak { 4263d829045SPawel Laszczak unsigned int num_segs_needed; 4273d829045SPawel Laszczak struct cdnsp_segment *first; 4283d829045SPawel Laszczak struct cdnsp_segment *last; 4293d829045SPawel Laszczak unsigned int num_segs; 4303d829045SPawel Laszczak int ret; 4313d829045SPawel Laszczak 4323d829045SPawel Laszczak num_segs_needed = (num_trbs + (TRBS_PER_SEGMENT - 1) - 1) / 4333d829045SPawel Laszczak (TRBS_PER_SEGMENT - 1); 4343d829045SPawel Laszczak 4353d829045SPawel Laszczak /* Allocate number of segments we needed, or double the ring size. */ 4363d829045SPawel Laszczak num_segs = max(ring->num_segs, num_segs_needed); 4373d829045SPawel Laszczak 4383d829045SPawel Laszczak ret = cdnsp_alloc_segments_for_ring(pdev, &first, &last, num_segs, 4393d829045SPawel Laszczak ring->cycle_state, ring->type, 4403d829045SPawel Laszczak ring->bounce_buf_len, flags); 4413d829045SPawel Laszczak if (ret) 4423d829045SPawel Laszczak return -ENOMEM; 4433d829045SPawel Laszczak 4443d829045SPawel Laszczak if (ring->type == TYPE_STREAM) 4453d829045SPawel Laszczak ret = cdnsp_update_stream_segment_mapping(ring->trb_address_map, 4463d829045SPawel Laszczak ring, first, 4473d829045SPawel Laszczak last, flags); 4483d829045SPawel Laszczak 4493d829045SPawel Laszczak if (ret) { 4503d829045SPawel Laszczak cdnsp_free_segments_for_ring(pdev, first); 4513d829045SPawel Laszczak 4523d829045SPawel Laszczak return ret; 4533d829045SPawel Laszczak } 4543d829045SPawel Laszczak 4553d829045SPawel Laszczak cdnsp_link_rings(pdev, ring, first, last, num_segs); 456118b2a32SPawel Laszczak trace_cdnsp_ring_expansion(ring); 4573d829045SPawel Laszczak 4583d829045SPawel Laszczak return 0; 4593d829045SPawel Laszczak } 4603d829045SPawel Laszczak 4613d829045SPawel Laszczak static int cdnsp_init_device_ctx(struct cdnsp_device *pdev) 4623d829045SPawel Laszczak { 4633d829045SPawel Laszczak int size = HCC_64BYTE_CONTEXT(pdev->hcc_params) ? 2048 : 1024; 4643d829045SPawel Laszczak 4653d829045SPawel Laszczak pdev->out_ctx.type = CDNSP_CTX_TYPE_DEVICE; 4663d829045SPawel Laszczak pdev->out_ctx.size = size; 4673d829045SPawel Laszczak pdev->out_ctx.ctx_size = CTX_SIZE(pdev->hcc_params); 4683d829045SPawel Laszczak pdev->out_ctx.bytes = dma_pool_zalloc(pdev->device_pool, GFP_ATOMIC, 4693d829045SPawel Laszczak &pdev->out_ctx.dma); 4703d829045SPawel Laszczak 4713d829045SPawel Laszczak if (!pdev->out_ctx.bytes) 4723d829045SPawel Laszczak return -ENOMEM; 4733d829045SPawel Laszczak 4743d829045SPawel Laszczak pdev->in_ctx.type = CDNSP_CTX_TYPE_INPUT; 4753d829045SPawel Laszczak pdev->in_ctx.ctx_size = pdev->out_ctx.ctx_size; 4763d829045SPawel Laszczak pdev->in_ctx.size = size + pdev->out_ctx.ctx_size; 4773d829045SPawel Laszczak pdev->in_ctx.bytes = dma_pool_zalloc(pdev->device_pool, GFP_ATOMIC, 4783d829045SPawel Laszczak &pdev->in_ctx.dma); 4793d829045SPawel Laszczak 4803d829045SPawel Laszczak if (!pdev->in_ctx.bytes) { 4813d829045SPawel Laszczak dma_pool_free(pdev->device_pool, pdev->out_ctx.bytes, 4823d829045SPawel Laszczak pdev->out_ctx.dma); 4833d829045SPawel Laszczak return -ENOMEM; 4843d829045SPawel Laszczak } 4853d829045SPawel Laszczak 4863d829045SPawel Laszczak return 0; 4873d829045SPawel Laszczak } 4883d829045SPawel Laszczak 4893d829045SPawel Laszczak struct cdnsp_input_control_ctx 4903d829045SPawel Laszczak *cdnsp_get_input_control_ctx(struct cdnsp_container_ctx *ctx) 4913d829045SPawel Laszczak { 4923d829045SPawel Laszczak if (ctx->type != CDNSP_CTX_TYPE_INPUT) 4933d829045SPawel Laszczak return NULL; 4943d829045SPawel Laszczak 4953d829045SPawel Laszczak return (struct cdnsp_input_control_ctx *)ctx->bytes; 4963d829045SPawel Laszczak } 4973d829045SPawel Laszczak 4983d829045SPawel Laszczak struct cdnsp_slot_ctx *cdnsp_get_slot_ctx(struct cdnsp_container_ctx *ctx) 4993d829045SPawel Laszczak { 5003d829045SPawel Laszczak if (ctx->type == CDNSP_CTX_TYPE_DEVICE) 5013d829045SPawel Laszczak return (struct cdnsp_slot_ctx *)ctx->bytes; 5023d829045SPawel Laszczak 5033d829045SPawel Laszczak return (struct cdnsp_slot_ctx *)(ctx->bytes + ctx->ctx_size); 5043d829045SPawel Laszczak } 5053d829045SPawel Laszczak 5063d829045SPawel Laszczak struct cdnsp_ep_ctx *cdnsp_get_ep_ctx(struct cdnsp_container_ctx *ctx, 5073d829045SPawel Laszczak unsigned int ep_index) 5083d829045SPawel Laszczak { 5093d829045SPawel Laszczak /* Increment ep index by offset of start of ep ctx array. */ 5103d829045SPawel Laszczak ep_index++; 5113d829045SPawel Laszczak if (ctx->type == CDNSP_CTX_TYPE_INPUT) 5123d829045SPawel Laszczak ep_index++; 5133d829045SPawel Laszczak 5143d829045SPawel Laszczak return (struct cdnsp_ep_ctx *)(ctx->bytes + (ep_index * ctx->ctx_size)); 5153d829045SPawel Laszczak } 5163d829045SPawel Laszczak 5173d829045SPawel Laszczak static void cdnsp_free_stream_ctx(struct cdnsp_device *pdev, 5183d829045SPawel Laszczak struct cdnsp_ep *pep) 5193d829045SPawel Laszczak { 5203d829045SPawel Laszczak dma_pool_free(pdev->device_pool, pep->stream_info.stream_ctx_array, 5213d829045SPawel Laszczak pep->stream_info.ctx_array_dma); 5223d829045SPawel Laszczak } 5233d829045SPawel Laszczak 5243d829045SPawel Laszczak /* The stream context array must be a power of 2. */ 5253d829045SPawel Laszczak static struct cdnsp_stream_ctx 5263d829045SPawel Laszczak *cdnsp_alloc_stream_ctx(struct cdnsp_device *pdev, struct cdnsp_ep *pep) 5273d829045SPawel Laszczak { 5283d829045SPawel Laszczak size_t size = sizeof(struct cdnsp_stream_ctx) * 5293d829045SPawel Laszczak pep->stream_info.num_stream_ctxs; 5303d829045SPawel Laszczak 5313d829045SPawel Laszczak if (size > CDNSP_CTX_SIZE) 5323d829045SPawel Laszczak return NULL; 5333d829045SPawel Laszczak 5343d829045SPawel Laszczak /** 5353d829045SPawel Laszczak * Driver uses intentionally the device_pool to allocated stream 5363d829045SPawel Laszczak * context array. Device Pool has 2048 bytes of size what gives us 5373d829045SPawel Laszczak * 128 entries. 5383d829045SPawel Laszczak */ 5393d829045SPawel Laszczak return dma_pool_zalloc(pdev->device_pool, GFP_DMA32 | GFP_ATOMIC, 5403d829045SPawel Laszczak &pep->stream_info.ctx_array_dma); 5413d829045SPawel Laszczak } 5423d829045SPawel Laszczak 5433d829045SPawel Laszczak struct cdnsp_ring *cdnsp_dma_to_transfer_ring(struct cdnsp_ep *pep, u64 address) 5443d829045SPawel Laszczak { 5453d829045SPawel Laszczak if (pep->ep_state & EP_HAS_STREAMS) 5463d829045SPawel Laszczak return radix_tree_lookup(&pep->stream_info.trb_address_map, 5473d829045SPawel Laszczak address >> TRB_SEGMENT_SHIFT); 5483d829045SPawel Laszczak 5493d829045SPawel Laszczak return pep->ring; 5503d829045SPawel Laszczak } 5513d829045SPawel Laszczak 5523d829045SPawel Laszczak /* 5533d829045SPawel Laszczak * Change an endpoint's internal structure so it supports stream IDs. 5543d829045SPawel Laszczak * The number of requested streams includes stream 0, which cannot be used by 5553d829045SPawel Laszczak * driver. 5563d829045SPawel Laszczak * 5573d829045SPawel Laszczak * The number of stream contexts in the stream context array may be bigger than 5583d829045SPawel Laszczak * the number of streams the driver wants to use. This is because the number of 5593d829045SPawel Laszczak * stream context array entries must be a power of two. 5603d829045SPawel Laszczak */ 5613d829045SPawel Laszczak int cdnsp_alloc_stream_info(struct cdnsp_device *pdev, 5623d829045SPawel Laszczak struct cdnsp_ep *pep, 5633d829045SPawel Laszczak unsigned int num_stream_ctxs, 5643d829045SPawel Laszczak unsigned int num_streams) 5653d829045SPawel Laszczak { 5663d829045SPawel Laszczak struct cdnsp_stream_info *stream_info; 5673d829045SPawel Laszczak struct cdnsp_ring *cur_ring; 5683d829045SPawel Laszczak u32 cur_stream; 5693d829045SPawel Laszczak u64 addr; 5703d829045SPawel Laszczak int ret; 5713d829045SPawel Laszczak int mps; 5723d829045SPawel Laszczak 5733d829045SPawel Laszczak stream_info = &pep->stream_info; 5743d829045SPawel Laszczak stream_info->num_streams = num_streams; 5753d829045SPawel Laszczak stream_info->num_stream_ctxs = num_stream_ctxs; 5763d829045SPawel Laszczak 5773d829045SPawel Laszczak /* Initialize the array of virtual pointers to stream rings. */ 5783d829045SPawel Laszczak stream_info->stream_rings = kcalloc(num_streams, 5793d829045SPawel Laszczak sizeof(struct cdnsp_ring *), 5803d829045SPawel Laszczak GFP_ATOMIC); 5813d829045SPawel Laszczak if (!stream_info->stream_rings) 5823d829045SPawel Laszczak return -ENOMEM; 5833d829045SPawel Laszczak 5843d829045SPawel Laszczak /* Initialize the array of DMA addresses for stream rings for the HW. */ 5853d829045SPawel Laszczak stream_info->stream_ctx_array = cdnsp_alloc_stream_ctx(pdev, pep); 5863d829045SPawel Laszczak if (!stream_info->stream_ctx_array) 5873d829045SPawel Laszczak goto cleanup_stream_rings; 5883d829045SPawel Laszczak 5893d829045SPawel Laszczak memset(stream_info->stream_ctx_array, 0, 5903d829045SPawel Laszczak sizeof(struct cdnsp_stream_ctx) * num_stream_ctxs); 5913d829045SPawel Laszczak INIT_RADIX_TREE(&stream_info->trb_address_map, GFP_ATOMIC); 5923d829045SPawel Laszczak mps = usb_endpoint_maxp(pep->endpoint.desc); 5933d829045SPawel Laszczak 5943d829045SPawel Laszczak /* 5953d829045SPawel Laszczak * Allocate rings for all the streams that the driver will use, 5963d829045SPawel Laszczak * and add their segment DMA addresses to the radix tree. 5973d829045SPawel Laszczak * Stream 0 is reserved. 5983d829045SPawel Laszczak */ 5993d829045SPawel Laszczak for (cur_stream = 1; cur_stream < num_streams; cur_stream++) { 6003d829045SPawel Laszczak cur_ring = cdnsp_ring_alloc(pdev, 2, TYPE_STREAM, mps, 6013d829045SPawel Laszczak GFP_ATOMIC); 6023d829045SPawel Laszczak stream_info->stream_rings[cur_stream] = cur_ring; 6033d829045SPawel Laszczak 6043d829045SPawel Laszczak if (!cur_ring) 6053d829045SPawel Laszczak goto cleanup_rings; 6063d829045SPawel Laszczak 6073d829045SPawel Laszczak cur_ring->stream_id = cur_stream; 6083d829045SPawel Laszczak cur_ring->trb_address_map = &stream_info->trb_address_map; 6093d829045SPawel Laszczak 6103d829045SPawel Laszczak /* Set deq ptr, cycle bit, and stream context type. */ 6113d829045SPawel Laszczak addr = cur_ring->first_seg->dma | SCT_FOR_CTX(SCT_PRI_TR) | 6123d829045SPawel Laszczak cur_ring->cycle_state; 6133d829045SPawel Laszczak 6143d829045SPawel Laszczak stream_info->stream_ctx_array[cur_stream].stream_ring = 6153d829045SPawel Laszczak cpu_to_le64(addr); 6163d829045SPawel Laszczak 617118b2a32SPawel Laszczak trace_cdnsp_set_stream_ring(cur_ring); 618118b2a32SPawel Laszczak 6193d829045SPawel Laszczak ret = cdnsp_update_stream_mapping(cur_ring); 6203d829045SPawel Laszczak if (ret) 6213d829045SPawel Laszczak goto cleanup_rings; 6223d829045SPawel Laszczak } 6233d829045SPawel Laszczak 6243d829045SPawel Laszczak return 0; 6253d829045SPawel Laszczak 6263d829045SPawel Laszczak cleanup_rings: 6273d829045SPawel Laszczak for (cur_stream = 1; cur_stream < num_streams; cur_stream++) { 6283d829045SPawel Laszczak cur_ring = stream_info->stream_rings[cur_stream]; 6293d829045SPawel Laszczak if (cur_ring) { 6303d829045SPawel Laszczak cdnsp_ring_free(pdev, cur_ring); 6313d829045SPawel Laszczak stream_info->stream_rings[cur_stream] = NULL; 6323d829045SPawel Laszczak } 6333d829045SPawel Laszczak } 6343d829045SPawel Laszczak 6353d829045SPawel Laszczak cleanup_stream_rings: 6363d829045SPawel Laszczak kfree(pep->stream_info.stream_rings); 6373d829045SPawel Laszczak 6383d829045SPawel Laszczak return -ENOMEM; 6393d829045SPawel Laszczak } 6403d829045SPawel Laszczak 6413d829045SPawel Laszczak /* Frees all stream contexts associated with the endpoint. */ 6423d829045SPawel Laszczak static void cdnsp_free_stream_info(struct cdnsp_device *pdev, 6433d829045SPawel Laszczak struct cdnsp_ep *pep) 6443d829045SPawel Laszczak { 6453d829045SPawel Laszczak struct cdnsp_stream_info *stream_info = &pep->stream_info; 6463d829045SPawel Laszczak struct cdnsp_ring *cur_ring; 6473d829045SPawel Laszczak int cur_stream; 6483d829045SPawel Laszczak 6493d829045SPawel Laszczak if (!(pep->ep_state & EP_HAS_STREAMS)) 6503d829045SPawel Laszczak return; 6513d829045SPawel Laszczak 6523d829045SPawel Laszczak for (cur_stream = 1; cur_stream < stream_info->num_streams; 6533d829045SPawel Laszczak cur_stream++) { 6543d829045SPawel Laszczak cur_ring = stream_info->stream_rings[cur_stream]; 6553d829045SPawel Laszczak if (cur_ring) { 6563d829045SPawel Laszczak cdnsp_ring_free(pdev, cur_ring); 6573d829045SPawel Laszczak stream_info->stream_rings[cur_stream] = NULL; 6583d829045SPawel Laszczak } 6593d829045SPawel Laszczak } 6603d829045SPawel Laszczak 6613d829045SPawel Laszczak if (stream_info->stream_ctx_array) 6623d829045SPawel Laszczak cdnsp_free_stream_ctx(pdev, pep); 6633d829045SPawel Laszczak 6643d829045SPawel Laszczak kfree(stream_info->stream_rings); 6653d829045SPawel Laszczak pep->ep_state &= ~EP_HAS_STREAMS; 6663d829045SPawel Laszczak } 6673d829045SPawel Laszczak 6683d829045SPawel Laszczak /* All the cdnsp_tds in the ring's TD list should be freed at this point.*/ 6693d829045SPawel Laszczak static void cdnsp_free_priv_device(struct cdnsp_device *pdev) 6703d829045SPawel Laszczak { 6713d829045SPawel Laszczak pdev->dcbaa->dev_context_ptrs[1] = 0; 6723d829045SPawel Laszczak 6733d829045SPawel Laszczak cdnsp_free_endpoint_rings(pdev, &pdev->eps[0]); 6743d829045SPawel Laszczak 6753d829045SPawel Laszczak if (pdev->in_ctx.bytes) 6763d829045SPawel Laszczak dma_pool_free(pdev->device_pool, pdev->in_ctx.bytes, 6773d829045SPawel Laszczak pdev->in_ctx.dma); 6783d829045SPawel Laszczak 6793d829045SPawel Laszczak if (pdev->out_ctx.bytes) 6803d829045SPawel Laszczak dma_pool_free(pdev->device_pool, pdev->out_ctx.bytes, 6813d829045SPawel Laszczak pdev->out_ctx.dma); 6823d829045SPawel Laszczak 6833d829045SPawel Laszczak pdev->in_ctx.bytes = NULL; 6843d829045SPawel Laszczak pdev->out_ctx.bytes = NULL; 6853d829045SPawel Laszczak } 6863d829045SPawel Laszczak 687dc68ba6cSPawel Laszczak static int cdnsp_alloc_priv_device(struct cdnsp_device *pdev) 6883d829045SPawel Laszczak { 6899ecc3eb0SColin Ian King int ret; 6903d829045SPawel Laszczak 6913d829045SPawel Laszczak ret = cdnsp_init_device_ctx(pdev); 6923d829045SPawel Laszczak if (ret) 6933d829045SPawel Laszczak return ret; 6943d829045SPawel Laszczak 6953d829045SPawel Laszczak /* Allocate endpoint 0 ring. */ 696dc68ba6cSPawel Laszczak pdev->eps[0].ring = cdnsp_ring_alloc(pdev, 2, TYPE_CTRL, 0, GFP_ATOMIC); 6973d829045SPawel Laszczak if (!pdev->eps[0].ring) 6983d829045SPawel Laszczak goto fail; 6993d829045SPawel Laszczak 7003d829045SPawel Laszczak /* Point to output device context in dcbaa. */ 7013d829045SPawel Laszczak pdev->dcbaa->dev_context_ptrs[1] = cpu_to_le64(pdev->out_ctx.dma); 7023d829045SPawel Laszczak pdev->cmd.in_ctx = &pdev->in_ctx; 7033d829045SPawel Laszczak 704118b2a32SPawel Laszczak trace_cdnsp_alloc_priv_device(pdev); 7053d829045SPawel Laszczak return 0; 7063d829045SPawel Laszczak fail: 7073d829045SPawel Laszczak dma_pool_free(pdev->device_pool, pdev->out_ctx.bytes, 7083d829045SPawel Laszczak pdev->out_ctx.dma); 7093d829045SPawel Laszczak dma_pool_free(pdev->device_pool, pdev->in_ctx.bytes, 7103d829045SPawel Laszczak pdev->in_ctx.dma); 7113d829045SPawel Laszczak 7123d829045SPawel Laszczak return ret; 7133d829045SPawel Laszczak } 7143d829045SPawel Laszczak 7153d829045SPawel Laszczak void cdnsp_copy_ep0_dequeue_into_input_ctx(struct cdnsp_device *pdev) 7163d829045SPawel Laszczak { 7173d829045SPawel Laszczak struct cdnsp_ep_ctx *ep0_ctx = pdev->eps[0].in_ctx; 7183d829045SPawel Laszczak struct cdnsp_ring *ep_ring = pdev->eps[0].ring; 7193d829045SPawel Laszczak dma_addr_t dma; 7203d829045SPawel Laszczak 7213d829045SPawel Laszczak dma = cdnsp_trb_virt_to_dma(ep_ring->enq_seg, ep_ring->enqueue); 7223d829045SPawel Laszczak ep0_ctx->deq = cpu_to_le64(dma | ep_ring->cycle_state); 7233d829045SPawel Laszczak } 7243d829045SPawel Laszczak 7253d829045SPawel Laszczak /* Setup an controller private device for a Set Address command. */ 7263d829045SPawel Laszczak int cdnsp_setup_addressable_priv_dev(struct cdnsp_device *pdev) 7273d829045SPawel Laszczak { 7283d829045SPawel Laszczak struct cdnsp_slot_ctx *slot_ctx; 7293d829045SPawel Laszczak struct cdnsp_ep_ctx *ep0_ctx; 7303d829045SPawel Laszczak u32 max_packets, port; 7313d829045SPawel Laszczak 7323d829045SPawel Laszczak ep0_ctx = cdnsp_get_ep_ctx(&pdev->in_ctx, 0); 7333d829045SPawel Laszczak slot_ctx = cdnsp_get_slot_ctx(&pdev->in_ctx); 7343d829045SPawel Laszczak 7353d829045SPawel Laszczak /* Only the control endpoint is valid - one endpoint context. */ 7363d829045SPawel Laszczak slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1)); 7373d829045SPawel Laszczak 7383d829045SPawel Laszczak switch (pdev->gadget.speed) { 7393d829045SPawel Laszczak case USB_SPEED_SUPER_PLUS: 7403d829045SPawel Laszczak slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SSP); 7413d829045SPawel Laszczak max_packets = MAX_PACKET(512); 7423d829045SPawel Laszczak break; 7433d829045SPawel Laszczak case USB_SPEED_SUPER: 7443d829045SPawel Laszczak slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SS); 7453d829045SPawel Laszczak max_packets = MAX_PACKET(512); 7463d829045SPawel Laszczak break; 7473d829045SPawel Laszczak case USB_SPEED_HIGH: 7483d829045SPawel Laszczak slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_HS); 7493d829045SPawel Laszczak max_packets = MAX_PACKET(64); 7503d829045SPawel Laszczak break; 7513d829045SPawel Laszczak case USB_SPEED_FULL: 7523d829045SPawel Laszczak slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_FS); 7533d829045SPawel Laszczak max_packets = MAX_PACKET(64); 7543d829045SPawel Laszczak break; 7553d829045SPawel Laszczak default: 7563d829045SPawel Laszczak /* Speed was not set , this shouldn't happen. */ 7573d829045SPawel Laszczak return -EINVAL; 7583d829045SPawel Laszczak } 7593d829045SPawel Laszczak 7603d829045SPawel Laszczak port = DEV_PORT(pdev->active_port->port_num); 7613d829045SPawel Laszczak slot_ctx->dev_port |= cpu_to_le32(port); 76216e36101SPawel Laszczak slot_ctx->dev_state = cpu_to_le32((pdev->device_address & 76316e36101SPawel Laszczak DEV_ADDR_MASK)); 76416e36101SPawel Laszczak ep0_ctx->tx_info = cpu_to_le32(EP_AVG_TRB_LENGTH(0x8)); 7653d829045SPawel Laszczak ep0_ctx->ep_info2 = cpu_to_le32(EP_TYPE(CTRL_EP)); 7663d829045SPawel Laszczak ep0_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(0) | ERROR_COUNT(3) | 7673d829045SPawel Laszczak max_packets); 7683d829045SPawel Laszczak 7693d829045SPawel Laszczak ep0_ctx->deq = cpu_to_le64(pdev->eps[0].ring->first_seg->dma | 7703d829045SPawel Laszczak pdev->eps[0].ring->cycle_state); 7713d829045SPawel Laszczak 772118b2a32SPawel Laszczak trace_cdnsp_setup_addressable_priv_device(pdev); 773118b2a32SPawel Laszczak 7743d829045SPawel Laszczak return 0; 7753d829045SPawel Laszczak } 7763d829045SPawel Laszczak 7773d829045SPawel Laszczak /* 7783d829045SPawel Laszczak * Convert interval expressed as 2^(bInterval - 1) == interval into 7793d829045SPawel Laszczak * straight exponent value 2^n == interval. 7803d829045SPawel Laszczak */ 7813d829045SPawel Laszczak static unsigned int cdnsp_parse_exponent_interval(struct usb_gadget *g, 7823d829045SPawel Laszczak struct cdnsp_ep *pep) 7833d829045SPawel Laszczak { 7843d829045SPawel Laszczak unsigned int interval; 7853d829045SPawel Laszczak 7863d829045SPawel Laszczak interval = clamp_val(pep->endpoint.desc->bInterval, 1, 16) - 1; 7873d829045SPawel Laszczak if (interval != pep->endpoint.desc->bInterval - 1) 7883d829045SPawel Laszczak dev_warn(&g->dev, "ep %s - rounding interval to %d %sframes\n", 7893d829045SPawel Laszczak pep->name, 1 << interval, 7903d829045SPawel Laszczak g->speed == USB_SPEED_FULL ? "" : "micro"); 7913d829045SPawel Laszczak 7923d829045SPawel Laszczak /* 7933d829045SPawel Laszczak * Full speed isoc endpoints specify interval in frames, 7943d829045SPawel Laszczak * not microframes. We are using microframes everywhere, 7953d829045SPawel Laszczak * so adjust accordingly. 7963d829045SPawel Laszczak */ 7973d829045SPawel Laszczak if (g->speed == USB_SPEED_FULL) 7983d829045SPawel Laszczak interval += 3; /* 1 frame = 2^3 uframes */ 7993d829045SPawel Laszczak 8003d829045SPawel Laszczak /* Controller handles only up to 512ms (2^12). */ 8013d829045SPawel Laszczak if (interval > 12) 8023d829045SPawel Laszczak interval = 12; 8033d829045SPawel Laszczak 8043d829045SPawel Laszczak return interval; 8053d829045SPawel Laszczak } 8063d829045SPawel Laszczak 8073d829045SPawel Laszczak /* 8083d829045SPawel Laszczak * Convert bInterval expressed in microframes (in 1-255 range) to exponent of 8093d829045SPawel Laszczak * microframes, rounded down to nearest power of 2. 8103d829045SPawel Laszczak */ 8113d829045SPawel Laszczak static unsigned int cdnsp_microframes_to_exponent(struct usb_gadget *g, 8123d829045SPawel Laszczak struct cdnsp_ep *pep, 8133d829045SPawel Laszczak unsigned int desc_interval, 8143d829045SPawel Laszczak unsigned int min_exponent, 8153d829045SPawel Laszczak unsigned int max_exponent) 8163d829045SPawel Laszczak { 8173d829045SPawel Laszczak unsigned int interval; 8183d829045SPawel Laszczak 8193d829045SPawel Laszczak interval = fls(desc_interval) - 1; 8203d829045SPawel Laszczak return clamp_val(interval, min_exponent, max_exponent); 8213d829045SPawel Laszczak } 8223d829045SPawel Laszczak 8233d829045SPawel Laszczak /* 8243d829045SPawel Laszczak * Return the polling interval. 8253d829045SPawel Laszczak * 8263d829045SPawel Laszczak * The polling interval is expressed in "microframes". If controllers's Interval 8273d829045SPawel Laszczak * field is set to N, it will service the endpoint every 2^(Interval)*125us. 8283d829045SPawel Laszczak */ 8293d829045SPawel Laszczak static unsigned int cdnsp_get_endpoint_interval(struct usb_gadget *g, 8303d829045SPawel Laszczak struct cdnsp_ep *pep) 8313d829045SPawel Laszczak { 8323d829045SPawel Laszczak unsigned int interval = 0; 8333d829045SPawel Laszczak 8343d829045SPawel Laszczak switch (g->speed) { 8353d829045SPawel Laszczak case USB_SPEED_HIGH: 8363d829045SPawel Laszczak case USB_SPEED_SUPER_PLUS: 8373d829045SPawel Laszczak case USB_SPEED_SUPER: 8383d829045SPawel Laszczak if (usb_endpoint_xfer_int(pep->endpoint.desc) || 8393d829045SPawel Laszczak usb_endpoint_xfer_isoc(pep->endpoint.desc)) 8403d829045SPawel Laszczak interval = cdnsp_parse_exponent_interval(g, pep); 8413d829045SPawel Laszczak break; 8423d829045SPawel Laszczak case USB_SPEED_FULL: 8433d829045SPawel Laszczak if (usb_endpoint_xfer_isoc(pep->endpoint.desc)) { 8443d829045SPawel Laszczak interval = cdnsp_parse_exponent_interval(g, pep); 8453d829045SPawel Laszczak } else if (usb_endpoint_xfer_int(pep->endpoint.desc)) { 8463d829045SPawel Laszczak interval = pep->endpoint.desc->bInterval << 3; 8473d829045SPawel Laszczak interval = cdnsp_microframes_to_exponent(g, pep, 8483d829045SPawel Laszczak interval, 8493d829045SPawel Laszczak 3, 10); 8503d829045SPawel Laszczak } 8513d829045SPawel Laszczak 8523d829045SPawel Laszczak break; 8533d829045SPawel Laszczak default: 8543d829045SPawel Laszczak WARN_ON(1); 8553d829045SPawel Laszczak } 8563d829045SPawel Laszczak 8573d829045SPawel Laszczak return interval; 8583d829045SPawel Laszczak } 8593d829045SPawel Laszczak 8603d829045SPawel Laszczak /* 8613d829045SPawel Laszczak * The "Mult" field in the endpoint context is only set for SuperSpeed isoc eps. 8623d829045SPawel Laszczak * High speed endpoint descriptors can define "the number of additional 8633d829045SPawel Laszczak * transaction opportunities per microframe", but that goes in the Max Burst 8643d829045SPawel Laszczak * endpoint context field. 8653d829045SPawel Laszczak */ 8663d829045SPawel Laszczak static u32 cdnsp_get_endpoint_mult(struct usb_gadget *g, struct cdnsp_ep *pep) 8673d829045SPawel Laszczak { 8683d829045SPawel Laszczak if (g->speed < USB_SPEED_SUPER || 8693d829045SPawel Laszczak !usb_endpoint_xfer_isoc(pep->endpoint.desc)) 8703d829045SPawel Laszczak return 0; 8713d829045SPawel Laszczak 8723d829045SPawel Laszczak return pep->endpoint.comp_desc->bmAttributes; 8733d829045SPawel Laszczak } 8743d829045SPawel Laszczak 8753d829045SPawel Laszczak static u32 cdnsp_get_endpoint_max_burst(struct usb_gadget *g, 8763d829045SPawel Laszczak struct cdnsp_ep *pep) 8773d829045SPawel Laszczak { 8783d829045SPawel Laszczak /* Super speed and Plus have max burst in ep companion desc */ 8793d829045SPawel Laszczak if (g->speed >= USB_SPEED_SUPER) 8803d829045SPawel Laszczak return pep->endpoint.comp_desc->bMaxBurst; 8813d829045SPawel Laszczak 8823d829045SPawel Laszczak if (g->speed == USB_SPEED_HIGH && 8833d829045SPawel Laszczak (usb_endpoint_xfer_isoc(pep->endpoint.desc) || 8843d829045SPawel Laszczak usb_endpoint_xfer_int(pep->endpoint.desc))) 885*e9ab75f2SChunfeng Yun return usb_endpoint_maxp_mult(pep->endpoint.desc) - 1; 8863d829045SPawel Laszczak 8873d829045SPawel Laszczak return 0; 8883d829045SPawel Laszczak } 8893d829045SPawel Laszczak 8903d829045SPawel Laszczak static u32 cdnsp_get_endpoint_type(const struct usb_endpoint_descriptor *desc) 8913d829045SPawel Laszczak { 8923d829045SPawel Laszczak int in; 8933d829045SPawel Laszczak 8943d829045SPawel Laszczak in = usb_endpoint_dir_in(desc); 8953d829045SPawel Laszczak 8963d829045SPawel Laszczak switch (usb_endpoint_type(desc)) { 8973d829045SPawel Laszczak case USB_ENDPOINT_XFER_CONTROL: 8983d829045SPawel Laszczak return CTRL_EP; 8993d829045SPawel Laszczak case USB_ENDPOINT_XFER_BULK: 9003d829045SPawel Laszczak return in ? BULK_IN_EP : BULK_OUT_EP; 9013d829045SPawel Laszczak case USB_ENDPOINT_XFER_ISOC: 9023d829045SPawel Laszczak return in ? ISOC_IN_EP : ISOC_OUT_EP; 9033d829045SPawel Laszczak case USB_ENDPOINT_XFER_INT: 9043d829045SPawel Laszczak return in ? INT_IN_EP : INT_OUT_EP; 9053d829045SPawel Laszczak } 9063d829045SPawel Laszczak 9073d829045SPawel Laszczak return 0; 9083d829045SPawel Laszczak } 9093d829045SPawel Laszczak 9103d829045SPawel Laszczak /* 9113d829045SPawel Laszczak * Return the maximum endpoint service interval time (ESIT) payload. 9123d829045SPawel Laszczak * Basically, this is the maxpacket size, multiplied by the burst size 9133d829045SPawel Laszczak * and mult size. 9143d829045SPawel Laszczak */ 9153d829045SPawel Laszczak static u32 cdnsp_get_max_esit_payload(struct usb_gadget *g, 9163d829045SPawel Laszczak struct cdnsp_ep *pep) 9173d829045SPawel Laszczak { 9183d829045SPawel Laszczak int max_packet; 9193d829045SPawel Laszczak int max_burst; 9203d829045SPawel Laszczak 9213d829045SPawel Laszczak /* Only applies for interrupt or isochronous endpoints*/ 9223d829045SPawel Laszczak if (usb_endpoint_xfer_control(pep->endpoint.desc) || 9233d829045SPawel Laszczak usb_endpoint_xfer_bulk(pep->endpoint.desc)) 9243d829045SPawel Laszczak return 0; 9253d829045SPawel Laszczak 9263d829045SPawel Laszczak /* SuperSpeedPlus Isoc ep sending over 48k per EIST. */ 9273d829045SPawel Laszczak if (g->speed >= USB_SPEED_SUPER_PLUS && 9283d829045SPawel Laszczak USB_SS_SSP_ISOC_COMP(pep->endpoint.desc->bmAttributes)) 92916e36101SPawel Laszczak return le16_to_cpu(pep->endpoint.comp_desc->wBytesPerInterval); 9303d829045SPawel Laszczak /* SuperSpeed or SuperSpeedPlus Isoc ep with less than 48k per esit */ 9313d829045SPawel Laszczak else if (g->speed >= USB_SPEED_SUPER) 9323d829045SPawel Laszczak return le16_to_cpu(pep->endpoint.comp_desc->wBytesPerInterval); 9333d829045SPawel Laszczak 9343d829045SPawel Laszczak max_packet = usb_endpoint_maxp(pep->endpoint.desc); 9353d829045SPawel Laszczak max_burst = usb_endpoint_maxp_mult(pep->endpoint.desc); 9363d829045SPawel Laszczak 9373d829045SPawel Laszczak /* A 0 in max burst means 1 transfer per ESIT */ 9383d829045SPawel Laszczak return max_packet * max_burst; 9393d829045SPawel Laszczak } 9403d829045SPawel Laszczak 9413d829045SPawel Laszczak int cdnsp_endpoint_init(struct cdnsp_device *pdev, 9423d829045SPawel Laszczak struct cdnsp_ep *pep, 9433d829045SPawel Laszczak gfp_t mem_flags) 9443d829045SPawel Laszczak { 9453d829045SPawel Laszczak enum cdnsp_ring_type ring_type; 9463d829045SPawel Laszczak struct cdnsp_ep_ctx *ep_ctx; 9473d829045SPawel Laszczak unsigned int err_count = 0; 9483d829045SPawel Laszczak unsigned int avg_trb_len; 9493d829045SPawel Laszczak unsigned int max_packet; 9503d829045SPawel Laszczak unsigned int max_burst; 9513d829045SPawel Laszczak unsigned int interval; 9523d829045SPawel Laszczak u32 max_esit_payload; 9533d829045SPawel Laszczak unsigned int mult; 9543d829045SPawel Laszczak u32 endpoint_type; 9553d829045SPawel Laszczak int ret; 9563d829045SPawel Laszczak 9573d829045SPawel Laszczak ep_ctx = pep->in_ctx; 9583d829045SPawel Laszczak 9593d829045SPawel Laszczak endpoint_type = cdnsp_get_endpoint_type(pep->endpoint.desc); 9603d829045SPawel Laszczak if (!endpoint_type) 9613d829045SPawel Laszczak return -EINVAL; 9623d829045SPawel Laszczak 9633d829045SPawel Laszczak ring_type = usb_endpoint_type(pep->endpoint.desc); 9643d829045SPawel Laszczak 9653d829045SPawel Laszczak /* 9663d829045SPawel Laszczak * Get values to fill the endpoint context, mostly from ep descriptor. 9673d829045SPawel Laszczak * The average TRB buffer length for bulk endpoints is unclear as we 9683d829045SPawel Laszczak * have no clue on scatter gather list entry size. For Isoc and Int, 9693d829045SPawel Laszczak * set it to max available. 9703d829045SPawel Laszczak */ 9713d829045SPawel Laszczak max_esit_payload = cdnsp_get_max_esit_payload(&pdev->gadget, pep); 9723d829045SPawel Laszczak interval = cdnsp_get_endpoint_interval(&pdev->gadget, pep); 9733d829045SPawel Laszczak mult = cdnsp_get_endpoint_mult(&pdev->gadget, pep); 9743d829045SPawel Laszczak max_packet = usb_endpoint_maxp(pep->endpoint.desc); 9753d829045SPawel Laszczak max_burst = cdnsp_get_endpoint_max_burst(&pdev->gadget, pep); 9763d829045SPawel Laszczak avg_trb_len = max_esit_payload; 9773d829045SPawel Laszczak 9783d829045SPawel Laszczak /* Allow 3 retries for everything but isoc, set CErr = 3. */ 9793d829045SPawel Laszczak if (!usb_endpoint_xfer_isoc(pep->endpoint.desc)) 9803d829045SPawel Laszczak err_count = 3; 9813d829045SPawel Laszczak if (usb_endpoint_xfer_bulk(pep->endpoint.desc) && 9823d829045SPawel Laszczak pdev->gadget.speed == USB_SPEED_HIGH) 9833d829045SPawel Laszczak max_packet = 512; 9843d829045SPawel Laszczak /* Controller spec indicates that ctrl ep avg TRB Length should be 8. */ 9853d829045SPawel Laszczak if (usb_endpoint_xfer_control(pep->endpoint.desc)) 9863d829045SPawel Laszczak avg_trb_len = 8; 9873d829045SPawel Laszczak 9883d829045SPawel Laszczak /* Set up the endpoint ring. */ 9893d829045SPawel Laszczak pep->ring = cdnsp_ring_alloc(pdev, 2, ring_type, max_packet, mem_flags); 9903d829045SPawel Laszczak pep->skip = false; 9913d829045SPawel Laszczak 9923d829045SPawel Laszczak /* Fill the endpoint context */ 9933d829045SPawel Laszczak ep_ctx->ep_info = cpu_to_le32(EP_MAX_ESIT_PAYLOAD_HI(max_esit_payload) | 9943d829045SPawel Laszczak EP_INTERVAL(interval) | EP_MULT(mult)); 9953d829045SPawel Laszczak ep_ctx->ep_info2 = cpu_to_le32(EP_TYPE(endpoint_type) | 9963d829045SPawel Laszczak MAX_PACKET(max_packet) | MAX_BURST(max_burst) | 9973d829045SPawel Laszczak ERROR_COUNT(err_count)); 9983d829045SPawel Laszczak ep_ctx->deq = cpu_to_le64(pep->ring->first_seg->dma | 9993d829045SPawel Laszczak pep->ring->cycle_state); 10003d829045SPawel Laszczak 10013d829045SPawel Laszczak ep_ctx->tx_info = cpu_to_le32(EP_MAX_ESIT_PAYLOAD_LO(max_esit_payload) | 10023d829045SPawel Laszczak EP_AVG_TRB_LENGTH(avg_trb_len)); 10033d829045SPawel Laszczak 10043d829045SPawel Laszczak if (usb_endpoint_xfer_bulk(pep->endpoint.desc) && 10053d829045SPawel Laszczak pdev->gadget.speed > USB_SPEED_HIGH) { 10063d829045SPawel Laszczak ret = cdnsp_alloc_streams(pdev, pep); 10073d829045SPawel Laszczak if (ret < 0) 10083d829045SPawel Laszczak return ret; 10093d829045SPawel Laszczak } 10103d829045SPawel Laszczak 10113d829045SPawel Laszczak return 0; 10123d829045SPawel Laszczak } 10133d829045SPawel Laszczak 10143d829045SPawel Laszczak void cdnsp_endpoint_zero(struct cdnsp_device *pdev, struct cdnsp_ep *pep) 10153d829045SPawel Laszczak { 10163d829045SPawel Laszczak pep->in_ctx->ep_info = 0; 10173d829045SPawel Laszczak pep->in_ctx->ep_info2 = 0; 10183d829045SPawel Laszczak pep->in_ctx->deq = 0; 10193d829045SPawel Laszczak pep->in_ctx->tx_info = 0; 10203d829045SPawel Laszczak } 10213d829045SPawel Laszczak 10223d829045SPawel Laszczak static int cdnsp_alloc_erst(struct cdnsp_device *pdev, 10233d829045SPawel Laszczak struct cdnsp_ring *evt_ring, 1024dc68ba6cSPawel Laszczak struct cdnsp_erst *erst) 10253d829045SPawel Laszczak { 10263d829045SPawel Laszczak struct cdnsp_erst_entry *entry; 10273d829045SPawel Laszczak struct cdnsp_segment *seg; 10283d829045SPawel Laszczak unsigned int val; 10293d829045SPawel Laszczak size_t size; 10303d829045SPawel Laszczak 10313d829045SPawel Laszczak size = sizeof(struct cdnsp_erst_entry) * evt_ring->num_segs; 10323d829045SPawel Laszczak erst->entries = dma_alloc_coherent(pdev->dev, size, 1033dc68ba6cSPawel Laszczak &erst->erst_dma_addr, GFP_KERNEL); 10343d829045SPawel Laszczak if (!erst->entries) 10353d829045SPawel Laszczak return -ENOMEM; 10363d829045SPawel Laszczak 10373d829045SPawel Laszczak erst->num_entries = evt_ring->num_segs; 10383d829045SPawel Laszczak 10393d829045SPawel Laszczak seg = evt_ring->first_seg; 10403d829045SPawel Laszczak for (val = 0; val < evt_ring->num_segs; val++) { 10413d829045SPawel Laszczak entry = &erst->entries[val]; 10423d829045SPawel Laszczak entry->seg_addr = cpu_to_le64(seg->dma); 10433d829045SPawel Laszczak entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT); 10443d829045SPawel Laszczak entry->rsvd = 0; 10453d829045SPawel Laszczak seg = seg->next; 10463d829045SPawel Laszczak } 10473d829045SPawel Laszczak 10483d829045SPawel Laszczak return 0; 10493d829045SPawel Laszczak } 10503d829045SPawel Laszczak 10513d829045SPawel Laszczak static void cdnsp_free_erst(struct cdnsp_device *pdev, struct cdnsp_erst *erst) 10523d829045SPawel Laszczak { 10533d829045SPawel Laszczak size_t size = sizeof(struct cdnsp_erst_entry) * (erst->num_entries); 10543d829045SPawel Laszczak struct device *dev = pdev->dev; 10553d829045SPawel Laszczak 10563d829045SPawel Laszczak if (erst->entries) 10573d829045SPawel Laszczak dma_free_coherent(dev, size, erst->entries, 10583d829045SPawel Laszczak erst->erst_dma_addr); 10593d829045SPawel Laszczak 10603d829045SPawel Laszczak erst->entries = NULL; 10613d829045SPawel Laszczak } 10623d829045SPawel Laszczak 10633d829045SPawel Laszczak void cdnsp_mem_cleanup(struct cdnsp_device *pdev) 10643d829045SPawel Laszczak { 10653d829045SPawel Laszczak struct device *dev = pdev->dev; 10663d829045SPawel Laszczak 10673d829045SPawel Laszczak cdnsp_free_priv_device(pdev); 10683d829045SPawel Laszczak cdnsp_free_erst(pdev, &pdev->erst); 10693d829045SPawel Laszczak 10703d829045SPawel Laszczak if (pdev->event_ring) 10713d829045SPawel Laszczak cdnsp_ring_free(pdev, pdev->event_ring); 10723d829045SPawel Laszczak 10733d829045SPawel Laszczak pdev->event_ring = NULL; 10743d829045SPawel Laszczak 10753d829045SPawel Laszczak if (pdev->cmd_ring) 10763d829045SPawel Laszczak cdnsp_ring_free(pdev, pdev->cmd_ring); 10773d829045SPawel Laszczak 10783d829045SPawel Laszczak pdev->cmd_ring = NULL; 10793d829045SPawel Laszczak 10803d829045SPawel Laszczak dma_pool_destroy(pdev->segment_pool); 10813d829045SPawel Laszczak pdev->segment_pool = NULL; 10823d829045SPawel Laszczak dma_pool_destroy(pdev->device_pool); 10833d829045SPawel Laszczak pdev->device_pool = NULL; 10843d829045SPawel Laszczak 10853d829045SPawel Laszczak dma_free_coherent(dev, sizeof(*pdev->dcbaa), 10863d829045SPawel Laszczak pdev->dcbaa, pdev->dcbaa->dma); 10873d829045SPawel Laszczak 10883d829045SPawel Laszczak pdev->dcbaa = NULL; 10893d829045SPawel Laszczak 10903d829045SPawel Laszczak pdev->usb2_port.exist = 0; 10913d829045SPawel Laszczak pdev->usb3_port.exist = 0; 10923d829045SPawel Laszczak pdev->usb2_port.port_num = 0; 10933d829045SPawel Laszczak pdev->usb3_port.port_num = 0; 10943d829045SPawel Laszczak pdev->active_port = NULL; 10953d829045SPawel Laszczak } 10963d829045SPawel Laszczak 10973d829045SPawel Laszczak static void cdnsp_set_event_deq(struct cdnsp_device *pdev) 10983d829045SPawel Laszczak { 10993d829045SPawel Laszczak dma_addr_t deq; 11003d829045SPawel Laszczak u64 temp; 11013d829045SPawel Laszczak 11023d829045SPawel Laszczak deq = cdnsp_trb_virt_to_dma(pdev->event_ring->deq_seg, 11033d829045SPawel Laszczak pdev->event_ring->dequeue); 11043d829045SPawel Laszczak 11053d829045SPawel Laszczak /* Update controller event ring dequeue pointer */ 11063d829045SPawel Laszczak temp = cdnsp_read_64(&pdev->ir_set->erst_dequeue); 11073d829045SPawel Laszczak temp &= ERST_PTR_MASK; 11083d829045SPawel Laszczak 11093d829045SPawel Laszczak /* 11103d829045SPawel Laszczak * Don't clear the EHB bit (which is RW1C) because 11113d829045SPawel Laszczak * there might be more events to service. 11123d829045SPawel Laszczak */ 11133d829045SPawel Laszczak temp &= ~ERST_EHB; 11143d829045SPawel Laszczak 11153d829045SPawel Laszczak cdnsp_write_64(((u64)deq & (u64)~ERST_PTR_MASK) | temp, 11163d829045SPawel Laszczak &pdev->ir_set->erst_dequeue); 11173d829045SPawel Laszczak } 11183d829045SPawel Laszczak 11193d829045SPawel Laszczak static void cdnsp_add_in_port(struct cdnsp_device *pdev, 11203d829045SPawel Laszczak struct cdnsp_port *port, 11213d829045SPawel Laszczak __le32 __iomem *addr) 11223d829045SPawel Laszczak { 1123118b2a32SPawel Laszczak u32 temp, port_offset, port_count; 11243d829045SPawel Laszczak 11253d829045SPawel Laszczak temp = readl(addr); 11263d829045SPawel Laszczak port->maj_rev = CDNSP_EXT_PORT_MAJOR(temp); 11273d829045SPawel Laszczak port->min_rev = CDNSP_EXT_PORT_MINOR(temp); 11283d829045SPawel Laszczak 11293d829045SPawel Laszczak /* Port offset and count in the third dword.*/ 11303d829045SPawel Laszczak temp = readl(addr + 2); 11313d829045SPawel Laszczak port_offset = CDNSP_EXT_PORT_OFF(temp); 1132118b2a32SPawel Laszczak port_count = CDNSP_EXT_PORT_COUNT(temp); 1133118b2a32SPawel Laszczak 1134118b2a32SPawel Laszczak trace_cdnsp_port_info(addr, port_offset, port_count, port->maj_rev); 11353d829045SPawel Laszczak 11363d829045SPawel Laszczak port->port_num = port_offset; 11373d829045SPawel Laszczak port->exist = 1; 11383d829045SPawel Laszczak } 11393d829045SPawel Laszczak 11403d829045SPawel Laszczak /* 11413d829045SPawel Laszczak * Scan the Extended Capabilities for the "Supported Protocol Capabilities" that 11423d829045SPawel Laszczak * specify what speeds each port is supposed to be. 11433d829045SPawel Laszczak */ 1144dc68ba6cSPawel Laszczak static int cdnsp_setup_port_arrays(struct cdnsp_device *pdev) 11453d829045SPawel Laszczak { 11463d829045SPawel Laszczak void __iomem *base; 11473d829045SPawel Laszczak u32 offset; 11483d829045SPawel Laszczak int i; 11493d829045SPawel Laszczak 11503d829045SPawel Laszczak base = &pdev->cap_regs->hc_capbase; 11513d829045SPawel Laszczak offset = cdnsp_find_next_ext_cap(base, 0, 11523d829045SPawel Laszczak EXT_CAP_CFG_DEV_20PORT_CAP_ID); 11533d829045SPawel Laszczak pdev->port20_regs = base + offset; 11543d829045SPawel Laszczak 11553d829045SPawel Laszczak offset = cdnsp_find_next_ext_cap(base, 0, D_XEC_CFG_3XPORT_CAP); 11563d829045SPawel Laszczak pdev->port3x_regs = base + offset; 11573d829045SPawel Laszczak 11583d829045SPawel Laszczak offset = 0; 11593d829045SPawel Laszczak base = &pdev->cap_regs->hc_capbase; 11603d829045SPawel Laszczak 11613d829045SPawel Laszczak /* Driver expects max 2 extended protocol capability. */ 11623d829045SPawel Laszczak for (i = 0; i < 2; i++) { 11633d829045SPawel Laszczak u32 temp; 11643d829045SPawel Laszczak 11653d829045SPawel Laszczak offset = cdnsp_find_next_ext_cap(base, offset, 11663d829045SPawel Laszczak EXT_CAPS_PROTOCOL); 11673d829045SPawel Laszczak temp = readl(base + offset); 11683d829045SPawel Laszczak 11693d829045SPawel Laszczak if (CDNSP_EXT_PORT_MAJOR(temp) == 0x03 && 11703d829045SPawel Laszczak !pdev->usb3_port.port_num) 11713d829045SPawel Laszczak cdnsp_add_in_port(pdev, &pdev->usb3_port, 11723d829045SPawel Laszczak base + offset); 11733d829045SPawel Laszczak 11743d829045SPawel Laszczak if (CDNSP_EXT_PORT_MAJOR(temp) == 0x02 && 11753d829045SPawel Laszczak !pdev->usb2_port.port_num) 11763d829045SPawel Laszczak cdnsp_add_in_port(pdev, &pdev->usb2_port, 11773d829045SPawel Laszczak base + offset); 11783d829045SPawel Laszczak } 11793d829045SPawel Laszczak 11803d829045SPawel Laszczak if (!pdev->usb2_port.exist || !pdev->usb3_port.exist) { 11813d829045SPawel Laszczak dev_err(pdev->dev, "Error: Only one port detected\n"); 11823d829045SPawel Laszczak return -ENODEV; 11833d829045SPawel Laszczak } 11843d829045SPawel Laszczak 1185118b2a32SPawel Laszczak trace_cdnsp_init("Found USB 2.0 ports and USB 3.0 ports."); 1186118b2a32SPawel Laszczak 118716e36101SPawel Laszczak pdev->usb2_port.regs = (struct cdnsp_port_regs __iomem *) 11883d829045SPawel Laszczak (&pdev->op_regs->port_reg_base + NUM_PORT_REGS * 11893d829045SPawel Laszczak (pdev->usb2_port.port_num - 1)); 11903d829045SPawel Laszczak 119116e36101SPawel Laszczak pdev->usb3_port.regs = (struct cdnsp_port_regs __iomem *) 11923d829045SPawel Laszczak (&pdev->op_regs->port_reg_base + NUM_PORT_REGS * 11933d829045SPawel Laszczak (pdev->usb3_port.port_num - 1)); 11943d829045SPawel Laszczak 11953d829045SPawel Laszczak return 0; 11963d829045SPawel Laszczak } 11973d829045SPawel Laszczak 11983d829045SPawel Laszczak /* 11993d829045SPawel Laszczak * Initialize memory for CDNSP (one-time init). 12003d829045SPawel Laszczak * 12013d829045SPawel Laszczak * Program the PAGESIZE register, initialize the device context array, create 12023d829045SPawel Laszczak * device contexts, set up a command ring segment, create event 12033d829045SPawel Laszczak * ring (one for now). 12043d829045SPawel Laszczak */ 1205dc68ba6cSPawel Laszczak int cdnsp_mem_init(struct cdnsp_device *pdev) 12063d829045SPawel Laszczak { 12073d829045SPawel Laszczak struct device *dev = pdev->dev; 12083d829045SPawel Laszczak int ret = -ENOMEM; 12093d829045SPawel Laszczak unsigned int val; 12103d829045SPawel Laszczak dma_addr_t dma; 12113d829045SPawel Laszczak u32 page_size; 12123d829045SPawel Laszczak u64 val_64; 12133d829045SPawel Laszczak 12143d829045SPawel Laszczak /* 12153d829045SPawel Laszczak * Use 4K pages, since that's common and the minimum the 12163d829045SPawel Laszczak * controller supports 12173d829045SPawel Laszczak */ 12183d829045SPawel Laszczak page_size = 1 << 12; 12193d829045SPawel Laszczak 12203d829045SPawel Laszczak val = readl(&pdev->op_regs->config_reg); 12213d829045SPawel Laszczak val |= ((val & ~MAX_DEVS) | CDNSP_DEV_MAX_SLOTS) | CONFIG_U3E; 12223d829045SPawel Laszczak writel(val, &pdev->op_regs->config_reg); 12233d829045SPawel Laszczak 12243d829045SPawel Laszczak /* 12253d829045SPawel Laszczak * Doorbell array must be physically contiguous 12263d829045SPawel Laszczak * and 64-byte (cache line) aligned. 12273d829045SPawel Laszczak */ 12283d829045SPawel Laszczak pdev->dcbaa = dma_alloc_coherent(dev, sizeof(*pdev->dcbaa), 12293d829045SPawel Laszczak &dma, GFP_KERNEL); 12303d829045SPawel Laszczak if (!pdev->dcbaa) 1231e2d60f8cSPawel Laszczak return -ENOMEM; 12323d829045SPawel Laszczak 12333d829045SPawel Laszczak pdev->dcbaa->dma = dma; 12343d829045SPawel Laszczak 12353d829045SPawel Laszczak cdnsp_write_64(dma, &pdev->op_regs->dcbaa_ptr); 12363d829045SPawel Laszczak 12373d829045SPawel Laszczak /* 12383d829045SPawel Laszczak * Initialize the ring segment pool. The ring must be a contiguous 12393d829045SPawel Laszczak * structure comprised of TRBs. The TRBs must be 16 byte aligned, 12403d829045SPawel Laszczak * however, the command ring segment needs 64-byte aligned segments 12413d829045SPawel Laszczak * and our use of dma addresses in the trb_address_map radix tree needs 12423d829045SPawel Laszczak * TRB_SEGMENT_SIZE alignment, so driver pick the greater alignment 12433d829045SPawel Laszczak * need. 12443d829045SPawel Laszczak */ 12453d829045SPawel Laszczak pdev->segment_pool = dma_pool_create("CDNSP ring segments", dev, 12463d829045SPawel Laszczak TRB_SEGMENT_SIZE, TRB_SEGMENT_SIZE, 12473d829045SPawel Laszczak page_size); 1248e2d60f8cSPawel Laszczak if (!pdev->segment_pool) 1249e2d60f8cSPawel Laszczak goto release_dcbaa; 12503d829045SPawel Laszczak 12513d829045SPawel Laszczak pdev->device_pool = dma_pool_create("CDNSP input/output contexts", dev, 12523d829045SPawel Laszczak CDNSP_CTX_SIZE, 64, page_size); 1253e2d60f8cSPawel Laszczak if (!pdev->device_pool) 1254e2d60f8cSPawel Laszczak goto destroy_segment_pool; 12553d829045SPawel Laszczak 12563d829045SPawel Laszczak 12573d829045SPawel Laszczak /* Set up the command ring to have one segments for now. */ 1258dc68ba6cSPawel Laszczak pdev->cmd_ring = cdnsp_ring_alloc(pdev, 1, TYPE_COMMAND, 0, GFP_KERNEL); 12593d829045SPawel Laszczak if (!pdev->cmd_ring) 1260e2d60f8cSPawel Laszczak goto destroy_device_pool; 12613d829045SPawel Laszczak 12623d829045SPawel Laszczak /* Set the address in the Command Ring Control register */ 12633d829045SPawel Laszczak val_64 = cdnsp_read_64(&pdev->op_regs->cmd_ring); 12643d829045SPawel Laszczak val_64 = (val_64 & (u64)CMD_RING_RSVD_BITS) | 12653d829045SPawel Laszczak (pdev->cmd_ring->first_seg->dma & (u64)~CMD_RING_RSVD_BITS) | 12663d829045SPawel Laszczak pdev->cmd_ring->cycle_state; 12673d829045SPawel Laszczak cdnsp_write_64(val_64, &pdev->op_regs->cmd_ring); 12683d829045SPawel Laszczak 12693d829045SPawel Laszczak val = readl(&pdev->cap_regs->db_off); 12703d829045SPawel Laszczak val &= DBOFF_MASK; 12713d829045SPawel Laszczak pdev->dba = (void __iomem *)pdev->cap_regs + val; 12723d829045SPawel Laszczak 12733d829045SPawel Laszczak /* Set ir_set to interrupt register set 0 */ 12743d829045SPawel Laszczak pdev->ir_set = &pdev->run_regs->ir_set[0]; 12753d829045SPawel Laszczak 12763d829045SPawel Laszczak /* 12773d829045SPawel Laszczak * Event ring setup: Allocate a normal ring, but also setup 12783d829045SPawel Laszczak * the event ring segment table (ERST). 12793d829045SPawel Laszczak */ 12803d829045SPawel Laszczak pdev->event_ring = cdnsp_ring_alloc(pdev, ERST_NUM_SEGS, TYPE_EVENT, 1281dc68ba6cSPawel Laszczak 0, GFP_KERNEL); 12823d829045SPawel Laszczak if (!pdev->event_ring) 1283e2d60f8cSPawel Laszczak goto free_cmd_ring; 12843d829045SPawel Laszczak 1285dc68ba6cSPawel Laszczak ret = cdnsp_alloc_erst(pdev, pdev->event_ring, &pdev->erst); 12863d829045SPawel Laszczak if (ret) 1287e2d60f8cSPawel Laszczak goto free_event_ring; 12883d829045SPawel Laszczak 12893d829045SPawel Laszczak /* Set ERST count with the number of entries in the segment table. */ 12903d829045SPawel Laszczak val = readl(&pdev->ir_set->erst_size); 12913d829045SPawel Laszczak val &= ERST_SIZE_MASK; 12923d829045SPawel Laszczak val |= ERST_NUM_SEGS; 12933d829045SPawel Laszczak writel(val, &pdev->ir_set->erst_size); 12943d829045SPawel Laszczak 12953d829045SPawel Laszczak /* Set the segment table base address. */ 12963d829045SPawel Laszczak val_64 = cdnsp_read_64(&pdev->ir_set->erst_base); 12973d829045SPawel Laszczak val_64 &= ERST_PTR_MASK; 12983d829045SPawel Laszczak val_64 |= (pdev->erst.erst_dma_addr & (u64)~ERST_PTR_MASK); 12993d829045SPawel Laszczak cdnsp_write_64(val_64, &pdev->ir_set->erst_base); 13003d829045SPawel Laszczak 13013d829045SPawel Laszczak /* Set the event ring dequeue address. */ 13023d829045SPawel Laszczak cdnsp_set_event_deq(pdev); 13033d829045SPawel Laszczak 1304dc68ba6cSPawel Laszczak ret = cdnsp_setup_port_arrays(pdev); 13053d829045SPawel Laszczak if (ret) 1306e2d60f8cSPawel Laszczak goto free_erst; 13073d829045SPawel Laszczak 1308dc68ba6cSPawel Laszczak ret = cdnsp_alloc_priv_device(pdev); 13093d829045SPawel Laszczak if (ret) { 13103d829045SPawel Laszczak dev_err(pdev->dev, 13113d829045SPawel Laszczak "Could not allocate cdnsp_device data structures\n"); 1312e2d60f8cSPawel Laszczak goto free_erst; 13133d829045SPawel Laszczak } 13143d829045SPawel Laszczak 13153d829045SPawel Laszczak return 0; 13163d829045SPawel Laszczak 1317e2d60f8cSPawel Laszczak free_erst: 1318e2d60f8cSPawel Laszczak cdnsp_free_erst(pdev, &pdev->erst); 1319e2d60f8cSPawel Laszczak free_event_ring: 1320e2d60f8cSPawel Laszczak cdnsp_ring_free(pdev, pdev->event_ring); 1321e2d60f8cSPawel Laszczak free_cmd_ring: 1322e2d60f8cSPawel Laszczak cdnsp_ring_free(pdev, pdev->cmd_ring); 1323e2d60f8cSPawel Laszczak destroy_device_pool: 1324e2d60f8cSPawel Laszczak dma_pool_destroy(pdev->device_pool); 1325e2d60f8cSPawel Laszczak destroy_segment_pool: 1326e2d60f8cSPawel Laszczak dma_pool_destroy(pdev->segment_pool); 1327e2d60f8cSPawel Laszczak release_dcbaa: 1328e2d60f8cSPawel Laszczak dma_free_coherent(dev, sizeof(*pdev->dcbaa), pdev->dcbaa, 1329e2d60f8cSPawel Laszczak pdev->dcbaa->dma); 1330e2d60f8cSPawel Laszczak 13313d829045SPawel Laszczak cdnsp_reset(pdev); 13323d829045SPawel Laszczak 13333d829045SPawel Laszczak return ret; 13343d829045SPawel Laszczak } 1335