18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2005-2006 by Texas Instruments 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This file implements a DMA interface using TI's CPPI DMA. 68c2ecf20Sopenharmony_ci * For now it's DaVinci-only, but CPPI isn't specific to DaVinci or USB. 78c2ecf20Sopenharmony_ci * The TUSB6020, using VLYNQ, has CPPI that looks much like DaVinci. 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/module.h> 118c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 128c2ecf20Sopenharmony_ci#include <linux/slab.h> 138c2ecf20Sopenharmony_ci#include <linux/usb.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include "musb_core.h" 168c2ecf20Sopenharmony_ci#include "musb_debug.h" 178c2ecf20Sopenharmony_ci#include "cppi_dma.h" 188c2ecf20Sopenharmony_ci#include "davinci.h" 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci/* CPPI DMA status 7-mar-2006: 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * - See musb_{host,gadget}.c for more info 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * - Correct RX DMA generally forces the engine into irq-per-packet mode, 268c2ecf20Sopenharmony_ci * which can easily saturate the CPU under non-mass-storage loads. 278c2ecf20Sopenharmony_ci * 288c2ecf20Sopenharmony_ci * NOTES 24-aug-2006 (2.6.18-rc4): 298c2ecf20Sopenharmony_ci * 308c2ecf20Sopenharmony_ci * - peripheral RXDMA wedged in a test with packets of length 512/512/1. 318c2ecf20Sopenharmony_ci * evidently after the 1 byte packet was received and acked, the queue 328c2ecf20Sopenharmony_ci * of BDs got garbaged so it wouldn't empty the fifo. (rxcsr 0x2003, 338c2ecf20Sopenharmony_ci * and RX DMA0: 4 left, 80000000 8feff880, 8feff860 8feff860; 8f321401 348c2ecf20Sopenharmony_ci * 004001ff 00000001 .. 8feff860) Host was just getting NAKed on tx 358c2ecf20Sopenharmony_ci * of its next (512 byte) packet. IRQ issues? 368c2ecf20Sopenharmony_ci * 378c2ecf20Sopenharmony_ci * REVISIT: the "transfer DMA" glue between CPPI and USB fifos will 388c2ecf20Sopenharmony_ci * evidently also directly update the RX and TX CSRs ... so audit all 398c2ecf20Sopenharmony_ci * host and peripheral side DMA code to avoid CSR access after DMA has 408c2ecf20Sopenharmony_ci * been started. 418c2ecf20Sopenharmony_ci */ 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* REVISIT now we can avoid preallocating these descriptors; or 448c2ecf20Sopenharmony_ci * more simply, switch to a global freelist not per-channel ones. 458c2ecf20Sopenharmony_ci * Note: at full speed, 64 descriptors == 4K bulk data. 468c2ecf20Sopenharmony_ci */ 478c2ecf20Sopenharmony_ci#define NUM_TXCHAN_BD 64 488c2ecf20Sopenharmony_ci#define NUM_RXCHAN_BD 64 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic inline void cpu_drain_writebuffer(void) 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci wmb(); 538c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_ARM926T 548c2ecf20Sopenharmony_ci /* REVISIT this "should not be needed", 558c2ecf20Sopenharmony_ci * but lack of it sure seemed to hurt ... 568c2ecf20Sopenharmony_ci */ 578c2ecf20Sopenharmony_ci asm("mcr p15, 0, r0, c7, c10, 4 @ drain write buffer\n"); 588c2ecf20Sopenharmony_ci#endif 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic inline struct cppi_descriptor *cppi_bd_alloc(struct cppi_channel *c) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci struct cppi_descriptor *bd = c->freelist; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci if (bd) 668c2ecf20Sopenharmony_ci c->freelist = bd->next; 678c2ecf20Sopenharmony_ci return bd; 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistatic inline void 718c2ecf20Sopenharmony_cicppi_bd_free(struct cppi_channel *c, struct cppi_descriptor *bd) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci if (!bd) 748c2ecf20Sopenharmony_ci return; 758c2ecf20Sopenharmony_ci bd->next = c->freelist; 768c2ecf20Sopenharmony_ci c->freelist = bd; 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci/* 808c2ecf20Sopenharmony_ci * Start DMA controller 818c2ecf20Sopenharmony_ci * 828c2ecf20Sopenharmony_ci * Initialize the DMA controller as necessary. 838c2ecf20Sopenharmony_ci */ 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci/* zero out entire rx state RAM entry for the channel */ 868c2ecf20Sopenharmony_cistatic void cppi_reset_rx(struct cppi_rx_stateram __iomem *rx) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci musb_writel(&rx->rx_skipbytes, 0, 0); 898c2ecf20Sopenharmony_ci musb_writel(&rx->rx_head, 0, 0); 908c2ecf20Sopenharmony_ci musb_writel(&rx->rx_sop, 0, 0); 918c2ecf20Sopenharmony_ci musb_writel(&rx->rx_current, 0, 0); 928c2ecf20Sopenharmony_ci musb_writel(&rx->rx_buf_current, 0, 0); 938c2ecf20Sopenharmony_ci musb_writel(&rx->rx_len_len, 0, 0); 948c2ecf20Sopenharmony_ci musb_writel(&rx->rx_cnt_cnt, 0, 0); 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci/* zero out entire tx state RAM entry for the channel */ 988c2ecf20Sopenharmony_cistatic void cppi_reset_tx(struct cppi_tx_stateram __iomem *tx, u32 ptr) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci musb_writel(&tx->tx_head, 0, 0); 1018c2ecf20Sopenharmony_ci musb_writel(&tx->tx_buf, 0, 0); 1028c2ecf20Sopenharmony_ci musb_writel(&tx->tx_current, 0, 0); 1038c2ecf20Sopenharmony_ci musb_writel(&tx->tx_buf_current, 0, 0); 1048c2ecf20Sopenharmony_ci musb_writel(&tx->tx_info, 0, 0); 1058c2ecf20Sopenharmony_ci musb_writel(&tx->tx_rem_len, 0, 0); 1068c2ecf20Sopenharmony_ci /* musb_writel(&tx->tx_dummy, 0, 0); */ 1078c2ecf20Sopenharmony_ci musb_writel(&tx->tx_complete, 0, ptr); 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic void cppi_pool_init(struct cppi *cppi, struct cppi_channel *c) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci int j; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci /* initialize channel fields */ 1158c2ecf20Sopenharmony_ci c->head = NULL; 1168c2ecf20Sopenharmony_ci c->tail = NULL; 1178c2ecf20Sopenharmony_ci c->last_processed = NULL; 1188c2ecf20Sopenharmony_ci c->channel.status = MUSB_DMA_STATUS_UNKNOWN; 1198c2ecf20Sopenharmony_ci c->controller = cppi; 1208c2ecf20Sopenharmony_ci c->is_rndis = 0; 1218c2ecf20Sopenharmony_ci c->freelist = NULL; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci /* build the BD Free list for the channel */ 1248c2ecf20Sopenharmony_ci for (j = 0; j < NUM_TXCHAN_BD + 1; j++) { 1258c2ecf20Sopenharmony_ci struct cppi_descriptor *bd; 1268c2ecf20Sopenharmony_ci dma_addr_t dma; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci bd = dma_pool_alloc(cppi->pool, GFP_KERNEL, &dma); 1298c2ecf20Sopenharmony_ci bd->dma = dma; 1308c2ecf20Sopenharmony_ci cppi_bd_free(c, bd); 1318c2ecf20Sopenharmony_ci } 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cistatic int cppi_channel_abort(struct dma_channel *); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic void cppi_pool_free(struct cppi_channel *c) 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci struct cppi *cppi = c->controller; 1398c2ecf20Sopenharmony_ci struct cppi_descriptor *bd; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci (void) cppi_channel_abort(&c->channel); 1428c2ecf20Sopenharmony_ci c->channel.status = MUSB_DMA_STATUS_UNKNOWN; 1438c2ecf20Sopenharmony_ci c->controller = NULL; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci /* free all its bds */ 1468c2ecf20Sopenharmony_ci bd = c->last_processed; 1478c2ecf20Sopenharmony_ci do { 1488c2ecf20Sopenharmony_ci if (bd) 1498c2ecf20Sopenharmony_ci dma_pool_free(cppi->pool, bd, bd->dma); 1508c2ecf20Sopenharmony_ci bd = cppi_bd_alloc(c); 1518c2ecf20Sopenharmony_ci } while (bd); 1528c2ecf20Sopenharmony_ci c->last_processed = NULL; 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_cistatic void cppi_controller_start(struct cppi *controller) 1568c2ecf20Sopenharmony_ci{ 1578c2ecf20Sopenharmony_ci void __iomem *tibase; 1588c2ecf20Sopenharmony_ci int i; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci /* do whatever is necessary to start controller */ 1618c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(controller->tx); i++) { 1628c2ecf20Sopenharmony_ci controller->tx[i].transmit = true; 1638c2ecf20Sopenharmony_ci controller->tx[i].index = i; 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(controller->rx); i++) { 1668c2ecf20Sopenharmony_ci controller->rx[i].transmit = false; 1678c2ecf20Sopenharmony_ci controller->rx[i].index = i; 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci /* setup BD list on a per channel basis */ 1718c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(controller->tx); i++) 1728c2ecf20Sopenharmony_ci cppi_pool_init(controller, controller->tx + i); 1738c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(controller->rx); i++) 1748c2ecf20Sopenharmony_ci cppi_pool_init(controller, controller->rx + i); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci tibase = controller->tibase; 1778c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&controller->tx_complete); 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci /* initialise tx/rx channel head pointers to zero */ 1808c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(controller->tx); i++) { 1818c2ecf20Sopenharmony_ci struct cppi_channel *tx_ch = controller->tx + i; 1828c2ecf20Sopenharmony_ci struct cppi_tx_stateram __iomem *tx; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&tx_ch->tx_complete); 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci tx = tibase + DAVINCI_TXCPPI_STATERAM_OFFSET(i); 1878c2ecf20Sopenharmony_ci tx_ch->state_ram = tx; 1888c2ecf20Sopenharmony_ci cppi_reset_tx(tx, 0); 1898c2ecf20Sopenharmony_ci } 1908c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(controller->rx); i++) { 1918c2ecf20Sopenharmony_ci struct cppi_channel *rx_ch = controller->rx + i; 1928c2ecf20Sopenharmony_ci struct cppi_rx_stateram __iomem *rx; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&rx_ch->tx_complete); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci rx = tibase + DAVINCI_RXCPPI_STATERAM_OFFSET(i); 1978c2ecf20Sopenharmony_ci rx_ch->state_ram = rx; 1988c2ecf20Sopenharmony_ci cppi_reset_rx(rx); 1998c2ecf20Sopenharmony_ci } 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci /* enable individual cppi channels */ 2028c2ecf20Sopenharmony_ci musb_writel(tibase, DAVINCI_TXCPPI_INTENAB_REG, 2038c2ecf20Sopenharmony_ci DAVINCI_DMA_ALL_CHANNELS_ENABLE); 2048c2ecf20Sopenharmony_ci musb_writel(tibase, DAVINCI_RXCPPI_INTENAB_REG, 2058c2ecf20Sopenharmony_ci DAVINCI_DMA_ALL_CHANNELS_ENABLE); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci /* enable tx/rx CPPI control */ 2088c2ecf20Sopenharmony_ci musb_writel(tibase, DAVINCI_TXCPPI_CTRL_REG, DAVINCI_DMA_CTRL_ENABLE); 2098c2ecf20Sopenharmony_ci musb_writel(tibase, DAVINCI_RXCPPI_CTRL_REG, DAVINCI_DMA_CTRL_ENABLE); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci /* disable RNDIS mode, also host rx RNDIS autorequest */ 2128c2ecf20Sopenharmony_ci musb_writel(tibase, DAVINCI_RNDIS_REG, 0); 2138c2ecf20Sopenharmony_ci musb_writel(tibase, DAVINCI_AUTOREQ_REG, 0); 2148c2ecf20Sopenharmony_ci} 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci/* 2178c2ecf20Sopenharmony_ci * Stop DMA controller 2188c2ecf20Sopenharmony_ci * 2198c2ecf20Sopenharmony_ci * De-Init the DMA controller as necessary. 2208c2ecf20Sopenharmony_ci */ 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_cistatic void cppi_controller_stop(struct cppi *controller) 2238c2ecf20Sopenharmony_ci{ 2248c2ecf20Sopenharmony_ci void __iomem *tibase; 2258c2ecf20Sopenharmony_ci int i; 2268c2ecf20Sopenharmony_ci struct musb *musb; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci musb = controller->controller.musb; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci tibase = controller->tibase; 2318c2ecf20Sopenharmony_ci /* DISABLE INDIVIDUAL CHANNEL Interrupts */ 2328c2ecf20Sopenharmony_ci musb_writel(tibase, DAVINCI_TXCPPI_INTCLR_REG, 2338c2ecf20Sopenharmony_ci DAVINCI_DMA_ALL_CHANNELS_ENABLE); 2348c2ecf20Sopenharmony_ci musb_writel(tibase, DAVINCI_RXCPPI_INTCLR_REG, 2358c2ecf20Sopenharmony_ci DAVINCI_DMA_ALL_CHANNELS_ENABLE); 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci musb_dbg(musb, "Tearing down RX and TX Channels"); 2388c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(controller->tx); i++) { 2398c2ecf20Sopenharmony_ci /* FIXME restructure of txdma to use bds like rxdma */ 2408c2ecf20Sopenharmony_ci controller->tx[i].last_processed = NULL; 2418c2ecf20Sopenharmony_ci cppi_pool_free(controller->tx + i); 2428c2ecf20Sopenharmony_ci } 2438c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(controller->rx); i++) 2448c2ecf20Sopenharmony_ci cppi_pool_free(controller->rx + i); 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci /* in Tx Case proper teardown is supported. We resort to disabling 2478c2ecf20Sopenharmony_ci * Tx/Rx CPPI after cleanup of Tx channels. Before TX teardown is 2488c2ecf20Sopenharmony_ci * complete TX CPPI cannot be disabled. 2498c2ecf20Sopenharmony_ci */ 2508c2ecf20Sopenharmony_ci /*disable tx/rx cppi */ 2518c2ecf20Sopenharmony_ci musb_writel(tibase, DAVINCI_TXCPPI_CTRL_REG, DAVINCI_DMA_CTRL_DISABLE); 2528c2ecf20Sopenharmony_ci musb_writel(tibase, DAVINCI_RXCPPI_CTRL_REG, DAVINCI_DMA_CTRL_DISABLE); 2538c2ecf20Sopenharmony_ci} 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci/* While dma channel is allocated, we only want the core irqs active 2568c2ecf20Sopenharmony_ci * for fault reports, otherwise we'd get irqs that we don't care about. 2578c2ecf20Sopenharmony_ci * Except for TX irqs, where dma done != fifo empty and reusable ... 2588c2ecf20Sopenharmony_ci * 2598c2ecf20Sopenharmony_ci * NOTE: docs don't say either way, but irq masking **enables** irqs. 2608c2ecf20Sopenharmony_ci * 2618c2ecf20Sopenharmony_ci * REVISIT same issue applies to pure PIO usage too, and non-cppi dma... 2628c2ecf20Sopenharmony_ci */ 2638c2ecf20Sopenharmony_cistatic inline void core_rxirq_disable(void __iomem *tibase, unsigned epnum) 2648c2ecf20Sopenharmony_ci{ 2658c2ecf20Sopenharmony_ci musb_writel(tibase, DAVINCI_USB_INT_MASK_CLR_REG, 1 << (epnum + 8)); 2668c2ecf20Sopenharmony_ci} 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_cistatic inline void core_rxirq_enable(void __iomem *tibase, unsigned epnum) 2698c2ecf20Sopenharmony_ci{ 2708c2ecf20Sopenharmony_ci musb_writel(tibase, DAVINCI_USB_INT_MASK_SET_REG, 1 << (epnum + 8)); 2718c2ecf20Sopenharmony_ci} 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci/* 2758c2ecf20Sopenharmony_ci * Allocate a CPPI Channel for DMA. With CPPI, channels are bound to 2768c2ecf20Sopenharmony_ci * each transfer direction of a non-control endpoint, so allocating 2778c2ecf20Sopenharmony_ci * (and deallocating) is mostly a way to notice bad housekeeping on 2788c2ecf20Sopenharmony_ci * the software side. We assume the irqs are always active. 2798c2ecf20Sopenharmony_ci */ 2808c2ecf20Sopenharmony_cistatic struct dma_channel * 2818c2ecf20Sopenharmony_cicppi_channel_allocate(struct dma_controller *c, 2828c2ecf20Sopenharmony_ci struct musb_hw_ep *ep, u8 transmit) 2838c2ecf20Sopenharmony_ci{ 2848c2ecf20Sopenharmony_ci struct cppi *controller; 2858c2ecf20Sopenharmony_ci u8 index; 2868c2ecf20Sopenharmony_ci struct cppi_channel *cppi_ch; 2878c2ecf20Sopenharmony_ci void __iomem *tibase; 2888c2ecf20Sopenharmony_ci struct musb *musb; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci controller = container_of(c, struct cppi, controller); 2918c2ecf20Sopenharmony_ci tibase = controller->tibase; 2928c2ecf20Sopenharmony_ci musb = c->musb; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci /* ep0 doesn't use DMA; remember cppi indices are 0..N-1 */ 2958c2ecf20Sopenharmony_ci index = ep->epnum - 1; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci /* return the corresponding CPPI Channel Handle, and 2988c2ecf20Sopenharmony_ci * probably disable the non-CPPI irq until we need it. 2998c2ecf20Sopenharmony_ci */ 3008c2ecf20Sopenharmony_ci if (transmit) { 3018c2ecf20Sopenharmony_ci if (index >= ARRAY_SIZE(controller->tx)) { 3028c2ecf20Sopenharmony_ci musb_dbg(musb, "no %cX%d CPPI channel", 'T', index); 3038c2ecf20Sopenharmony_ci return NULL; 3048c2ecf20Sopenharmony_ci } 3058c2ecf20Sopenharmony_ci cppi_ch = controller->tx + index; 3068c2ecf20Sopenharmony_ci } else { 3078c2ecf20Sopenharmony_ci if (index >= ARRAY_SIZE(controller->rx)) { 3088c2ecf20Sopenharmony_ci musb_dbg(musb, "no %cX%d CPPI channel", 'R', index); 3098c2ecf20Sopenharmony_ci return NULL; 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci cppi_ch = controller->rx + index; 3128c2ecf20Sopenharmony_ci core_rxirq_disable(tibase, ep->epnum); 3138c2ecf20Sopenharmony_ci } 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci /* REVISIT make this an error later once the same driver code works 3168c2ecf20Sopenharmony_ci * with the other DMA engine too 3178c2ecf20Sopenharmony_ci */ 3188c2ecf20Sopenharmony_ci if (cppi_ch->hw_ep) 3198c2ecf20Sopenharmony_ci musb_dbg(musb, "re-allocating DMA%d %cX channel %p", 3208c2ecf20Sopenharmony_ci index, transmit ? 'T' : 'R', cppi_ch); 3218c2ecf20Sopenharmony_ci cppi_ch->hw_ep = ep; 3228c2ecf20Sopenharmony_ci cppi_ch->channel.status = MUSB_DMA_STATUS_FREE; 3238c2ecf20Sopenharmony_ci cppi_ch->channel.max_len = 0x7fffffff; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci musb_dbg(musb, "Allocate CPPI%d %cX", index, transmit ? 'T' : 'R'); 3268c2ecf20Sopenharmony_ci return &cppi_ch->channel; 3278c2ecf20Sopenharmony_ci} 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci/* Release a CPPI Channel. */ 3308c2ecf20Sopenharmony_cistatic void cppi_channel_release(struct dma_channel *channel) 3318c2ecf20Sopenharmony_ci{ 3328c2ecf20Sopenharmony_ci struct cppi_channel *c; 3338c2ecf20Sopenharmony_ci void __iomem *tibase; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci /* REVISIT: for paranoia, check state and abort if needed... */ 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci c = container_of(channel, struct cppi_channel, channel); 3388c2ecf20Sopenharmony_ci tibase = c->controller->tibase; 3398c2ecf20Sopenharmony_ci if (!c->hw_ep) 3408c2ecf20Sopenharmony_ci musb_dbg(c->controller->controller.musb, 3418c2ecf20Sopenharmony_ci "releasing idle DMA channel %p", c); 3428c2ecf20Sopenharmony_ci else if (!c->transmit) 3438c2ecf20Sopenharmony_ci core_rxirq_enable(tibase, c->index + 1); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci /* for now, leave its cppi IRQ enabled (we won't trigger it) */ 3468c2ecf20Sopenharmony_ci c->hw_ep = NULL; 3478c2ecf20Sopenharmony_ci channel->status = MUSB_DMA_STATUS_UNKNOWN; 3488c2ecf20Sopenharmony_ci} 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci/* Context: controller irqlocked */ 3518c2ecf20Sopenharmony_cistatic void 3528c2ecf20Sopenharmony_cicppi_dump_rx(int level, struct cppi_channel *c, const char *tag) 3538c2ecf20Sopenharmony_ci{ 3548c2ecf20Sopenharmony_ci void __iomem *base = c->controller->mregs; 3558c2ecf20Sopenharmony_ci struct cppi_rx_stateram __iomem *rx = c->state_ram; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci musb_ep_select(base, c->index + 1); 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci musb_dbg(c->controller->controller.musb, 3608c2ecf20Sopenharmony_ci "RX DMA%d%s: %d left, csr %04x, " 3618c2ecf20Sopenharmony_ci "%08x H%08x S%08x C%08x, " 3628c2ecf20Sopenharmony_ci "B%08x L%08x %08x .. %08x", 3638c2ecf20Sopenharmony_ci c->index, tag, 3648c2ecf20Sopenharmony_ci musb_readl(c->controller->tibase, 3658c2ecf20Sopenharmony_ci DAVINCI_RXCPPI_BUFCNT0_REG + 4 * c->index), 3668c2ecf20Sopenharmony_ci musb_readw(c->hw_ep->regs, MUSB_RXCSR), 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci musb_readl(&rx->rx_skipbytes, 0), 3698c2ecf20Sopenharmony_ci musb_readl(&rx->rx_head, 0), 3708c2ecf20Sopenharmony_ci musb_readl(&rx->rx_sop, 0), 3718c2ecf20Sopenharmony_ci musb_readl(&rx->rx_current, 0), 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci musb_readl(&rx->rx_buf_current, 0), 3748c2ecf20Sopenharmony_ci musb_readl(&rx->rx_len_len, 0), 3758c2ecf20Sopenharmony_ci musb_readl(&rx->rx_cnt_cnt, 0), 3768c2ecf20Sopenharmony_ci musb_readl(&rx->rx_complete, 0) 3778c2ecf20Sopenharmony_ci ); 3788c2ecf20Sopenharmony_ci} 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci/* Context: controller irqlocked */ 3818c2ecf20Sopenharmony_cistatic void 3828c2ecf20Sopenharmony_cicppi_dump_tx(int level, struct cppi_channel *c, const char *tag) 3838c2ecf20Sopenharmony_ci{ 3848c2ecf20Sopenharmony_ci void __iomem *base = c->controller->mregs; 3858c2ecf20Sopenharmony_ci struct cppi_tx_stateram __iomem *tx = c->state_ram; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci musb_ep_select(base, c->index + 1); 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci musb_dbg(c->controller->controller.musb, 3908c2ecf20Sopenharmony_ci "TX DMA%d%s: csr %04x, " 3918c2ecf20Sopenharmony_ci "H%08x S%08x C%08x %08x, " 3928c2ecf20Sopenharmony_ci "F%08x L%08x .. %08x", 3938c2ecf20Sopenharmony_ci c->index, tag, 3948c2ecf20Sopenharmony_ci musb_readw(c->hw_ep->regs, MUSB_TXCSR), 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci musb_readl(&tx->tx_head, 0), 3978c2ecf20Sopenharmony_ci musb_readl(&tx->tx_buf, 0), 3988c2ecf20Sopenharmony_ci musb_readl(&tx->tx_current, 0), 3998c2ecf20Sopenharmony_ci musb_readl(&tx->tx_buf_current, 0), 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci musb_readl(&tx->tx_info, 0), 4028c2ecf20Sopenharmony_ci musb_readl(&tx->tx_rem_len, 0), 4038c2ecf20Sopenharmony_ci /* dummy/unused word 6 */ 4048c2ecf20Sopenharmony_ci musb_readl(&tx->tx_complete, 0) 4058c2ecf20Sopenharmony_ci ); 4068c2ecf20Sopenharmony_ci} 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci/* Context: controller irqlocked */ 4098c2ecf20Sopenharmony_cistatic inline void 4108c2ecf20Sopenharmony_cicppi_rndis_update(struct cppi_channel *c, int is_rx, 4118c2ecf20Sopenharmony_ci void __iomem *tibase, int is_rndis) 4128c2ecf20Sopenharmony_ci{ 4138c2ecf20Sopenharmony_ci /* we may need to change the rndis flag for this cppi channel */ 4148c2ecf20Sopenharmony_ci if (c->is_rndis != is_rndis) { 4158c2ecf20Sopenharmony_ci u32 value = musb_readl(tibase, DAVINCI_RNDIS_REG); 4168c2ecf20Sopenharmony_ci u32 temp = 1 << (c->index); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci if (is_rx) 4198c2ecf20Sopenharmony_ci temp <<= 16; 4208c2ecf20Sopenharmony_ci if (is_rndis) 4218c2ecf20Sopenharmony_ci value |= temp; 4228c2ecf20Sopenharmony_ci else 4238c2ecf20Sopenharmony_ci value &= ~temp; 4248c2ecf20Sopenharmony_ci musb_writel(tibase, DAVINCI_RNDIS_REG, value); 4258c2ecf20Sopenharmony_ci c->is_rndis = is_rndis; 4268c2ecf20Sopenharmony_ci } 4278c2ecf20Sopenharmony_ci} 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_cistatic void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd) 4308c2ecf20Sopenharmony_ci{ 4318c2ecf20Sopenharmony_ci pr_debug("RXBD/%s %08x: " 4328c2ecf20Sopenharmony_ci "nxt %08x buf %08x off.blen %08x opt.plen %08x\n", 4338c2ecf20Sopenharmony_ci tag, bd->dma, 4348c2ecf20Sopenharmony_ci bd->hw_next, bd->hw_bufp, bd->hw_off_len, 4358c2ecf20Sopenharmony_ci bd->hw_options); 4368c2ecf20Sopenharmony_ci} 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_cistatic void cppi_dump_rxq(int level, const char *tag, struct cppi_channel *rx) 4398c2ecf20Sopenharmony_ci{ 4408c2ecf20Sopenharmony_ci struct cppi_descriptor *bd; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci cppi_dump_rx(level, rx, tag); 4438c2ecf20Sopenharmony_ci if (rx->last_processed) 4448c2ecf20Sopenharmony_ci cppi_dump_rxbd("last", rx->last_processed); 4458c2ecf20Sopenharmony_ci for (bd = rx->head; bd; bd = bd->next) 4468c2ecf20Sopenharmony_ci cppi_dump_rxbd("active", bd); 4478c2ecf20Sopenharmony_ci} 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci/* NOTE: DaVinci autoreq is ignored except for host side "RNDIS" mode RX; 4518c2ecf20Sopenharmony_ci * so we won't ever use it (see "CPPI RX Woes" below). 4528c2ecf20Sopenharmony_ci */ 4538c2ecf20Sopenharmony_cistatic inline int cppi_autoreq_update(struct cppi_channel *rx, 4548c2ecf20Sopenharmony_ci void __iomem *tibase, int onepacket, unsigned n_bds) 4558c2ecf20Sopenharmony_ci{ 4568c2ecf20Sopenharmony_ci u32 val; 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci#ifdef RNDIS_RX_IS_USABLE 4598c2ecf20Sopenharmony_ci u32 tmp; 4608c2ecf20Sopenharmony_ci /* assert(is_host_active(musb)) */ 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci /* start from "AutoReq never" */ 4638c2ecf20Sopenharmony_ci tmp = musb_readl(tibase, DAVINCI_AUTOREQ_REG); 4648c2ecf20Sopenharmony_ci val = tmp & ~((0x3) << (rx->index * 2)); 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci /* HCD arranged reqpkt for packet #1. we arrange int 4678c2ecf20Sopenharmony_ci * for all but the last one, maybe in two segments. 4688c2ecf20Sopenharmony_ci */ 4698c2ecf20Sopenharmony_ci if (!onepacket) { 4708c2ecf20Sopenharmony_ci#if 0 4718c2ecf20Sopenharmony_ci /* use two segments, autoreq "all" then the last "never" */ 4728c2ecf20Sopenharmony_ci val |= ((0x3) << (rx->index * 2)); 4738c2ecf20Sopenharmony_ci n_bds--; 4748c2ecf20Sopenharmony_ci#else 4758c2ecf20Sopenharmony_ci /* one segment, autoreq "all-but-last" */ 4768c2ecf20Sopenharmony_ci val |= ((0x1) << (rx->index * 2)); 4778c2ecf20Sopenharmony_ci#endif 4788c2ecf20Sopenharmony_ci } 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci if (val != tmp) { 4818c2ecf20Sopenharmony_ci int n = 100; 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci /* make sure that autoreq is updated before continuing */ 4848c2ecf20Sopenharmony_ci musb_writel(tibase, DAVINCI_AUTOREQ_REG, val); 4858c2ecf20Sopenharmony_ci do { 4868c2ecf20Sopenharmony_ci tmp = musb_readl(tibase, DAVINCI_AUTOREQ_REG); 4878c2ecf20Sopenharmony_ci if (tmp == val) 4888c2ecf20Sopenharmony_ci break; 4898c2ecf20Sopenharmony_ci cpu_relax(); 4908c2ecf20Sopenharmony_ci } while (n-- > 0); 4918c2ecf20Sopenharmony_ci } 4928c2ecf20Sopenharmony_ci#endif 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci /* REQPKT is turned off after each segment */ 4958c2ecf20Sopenharmony_ci if (n_bds && rx->channel.actual_len) { 4968c2ecf20Sopenharmony_ci void __iomem *regs = rx->hw_ep->regs; 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci val = musb_readw(regs, MUSB_RXCSR); 4998c2ecf20Sopenharmony_ci if (!(val & MUSB_RXCSR_H_REQPKT)) { 5008c2ecf20Sopenharmony_ci val |= MUSB_RXCSR_H_REQPKT | MUSB_RXCSR_H_WZC_BITS; 5018c2ecf20Sopenharmony_ci musb_writew(regs, MUSB_RXCSR, val); 5028c2ecf20Sopenharmony_ci /* flush writebuffer */ 5038c2ecf20Sopenharmony_ci val = musb_readw(regs, MUSB_RXCSR); 5048c2ecf20Sopenharmony_ci } 5058c2ecf20Sopenharmony_ci } 5068c2ecf20Sopenharmony_ci return n_bds; 5078c2ecf20Sopenharmony_ci} 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci/* Buffer enqueuing Logic: 5118c2ecf20Sopenharmony_ci * 5128c2ecf20Sopenharmony_ci * - RX builds new queues each time, to help handle routine "early 5138c2ecf20Sopenharmony_ci * termination" cases (faults, including errors and short reads) 5148c2ecf20Sopenharmony_ci * more correctly. 5158c2ecf20Sopenharmony_ci * 5168c2ecf20Sopenharmony_ci * - for now, TX reuses the same queue of BDs every time 5178c2ecf20Sopenharmony_ci * 5188c2ecf20Sopenharmony_ci * REVISIT long term, we want a normal dynamic model. 5198c2ecf20Sopenharmony_ci * ... the goal will be to append to the 5208c2ecf20Sopenharmony_ci * existing queue, processing completed "dma buffers" (segments) on the fly. 5218c2ecf20Sopenharmony_ci * 5228c2ecf20Sopenharmony_ci * Otherwise we force an IRQ latency between requests, which slows us a lot 5238c2ecf20Sopenharmony_ci * (especially in "transparent" dma). Unfortunately that model seems to be 5248c2ecf20Sopenharmony_ci * inherent in the DMA model from the Mentor code, except in the rare case 5258c2ecf20Sopenharmony_ci * of transfers big enough (~128+ KB) that we could append "middle" segments 5268c2ecf20Sopenharmony_ci * in the TX paths. (RX can't do this, see below.) 5278c2ecf20Sopenharmony_ci * 5288c2ecf20Sopenharmony_ci * That's true even in the CPPI- friendly iso case, where most urbs have 5298c2ecf20Sopenharmony_ci * several small segments provided in a group and where the "packet at a time" 5308c2ecf20Sopenharmony_ci * "transparent" DMA model is always correct, even on the RX side. 5318c2ecf20Sopenharmony_ci */ 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci/* 5348c2ecf20Sopenharmony_ci * CPPI TX: 5358c2ecf20Sopenharmony_ci * ======== 5368c2ecf20Sopenharmony_ci * TX is a lot more reasonable than RX; it doesn't need to run in 5378c2ecf20Sopenharmony_ci * irq-per-packet mode very often. RNDIS mode seems to behave too 5388c2ecf20Sopenharmony_ci * (except how it handles the exactly-N-packets case). Building a 5398c2ecf20Sopenharmony_ci * txdma queue with multiple requests (urb or usb_request) looks 5408c2ecf20Sopenharmony_ci * like it would work ... but fault handling would need much testing. 5418c2ecf20Sopenharmony_ci * 5428c2ecf20Sopenharmony_ci * The main issue with TX mode RNDIS relates to transfer lengths that 5438c2ecf20Sopenharmony_ci * are an exact multiple of the packet length. It appears that there's 5448c2ecf20Sopenharmony_ci * a hiccup in that case (maybe the DMA completes before the ZLP gets 5458c2ecf20Sopenharmony_ci * written?) boiling down to not being able to rely on CPPI writing any 5468c2ecf20Sopenharmony_ci * terminating zero length packet before the next transfer is written. 5478c2ecf20Sopenharmony_ci * So that's punted to PIO; better yet, gadget drivers can avoid it. 5488c2ecf20Sopenharmony_ci * 5498c2ecf20Sopenharmony_ci * Plus, there's allegedly an undocumented constraint that rndis transfer 5508c2ecf20Sopenharmony_ci * length be a multiple of 64 bytes ... but the chip doesn't act that 5518c2ecf20Sopenharmony_ci * way, and we really don't _want_ that behavior anyway. 5528c2ecf20Sopenharmony_ci * 5538c2ecf20Sopenharmony_ci * On TX, "transparent" mode works ... although experiments have shown 5548c2ecf20Sopenharmony_ci * problems trying to use the SOP/EOP bits in different USB packets. 5558c2ecf20Sopenharmony_ci * 5568c2ecf20Sopenharmony_ci * REVISIT try to handle terminating zero length packets using CPPI 5578c2ecf20Sopenharmony_ci * instead of doing it by PIO after an IRQ. (Meanwhile, make Ethernet 5588c2ecf20Sopenharmony_ci * links avoid that issue by forcing them to avoid zlps.) 5598c2ecf20Sopenharmony_ci */ 5608c2ecf20Sopenharmony_cistatic void 5618c2ecf20Sopenharmony_cicppi_next_tx_segment(struct musb *musb, struct cppi_channel *tx) 5628c2ecf20Sopenharmony_ci{ 5638c2ecf20Sopenharmony_ci unsigned maxpacket = tx->maxpacket; 5648c2ecf20Sopenharmony_ci dma_addr_t addr = tx->buf_dma + tx->offset; 5658c2ecf20Sopenharmony_ci size_t length = tx->buf_len - tx->offset; 5668c2ecf20Sopenharmony_ci struct cppi_descriptor *bd; 5678c2ecf20Sopenharmony_ci unsigned n_bds; 5688c2ecf20Sopenharmony_ci unsigned i; 5698c2ecf20Sopenharmony_ci struct cppi_tx_stateram __iomem *tx_ram = tx->state_ram; 5708c2ecf20Sopenharmony_ci int rndis; 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci /* TX can use the CPPI "rndis" mode, where we can probably fit this 5738c2ecf20Sopenharmony_ci * transfer in one BD and one IRQ. The only time we would NOT want 5748c2ecf20Sopenharmony_ci * to use it is when hardware constraints prevent it, or if we'd 5758c2ecf20Sopenharmony_ci * trigger the "send a ZLP?" confusion. 5768c2ecf20Sopenharmony_ci */ 5778c2ecf20Sopenharmony_ci rndis = (maxpacket & 0x3f) == 0 5788c2ecf20Sopenharmony_ci && length > maxpacket 5798c2ecf20Sopenharmony_ci && length < 0xffff 5808c2ecf20Sopenharmony_ci && (length % maxpacket) != 0; 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci if (rndis) { 5838c2ecf20Sopenharmony_ci maxpacket = length; 5848c2ecf20Sopenharmony_ci n_bds = 1; 5858c2ecf20Sopenharmony_ci } else { 5868c2ecf20Sopenharmony_ci if (length) 5878c2ecf20Sopenharmony_ci n_bds = DIV_ROUND_UP(length, maxpacket); 5888c2ecf20Sopenharmony_ci else 5898c2ecf20Sopenharmony_ci n_bds = 1; 5908c2ecf20Sopenharmony_ci n_bds = min(n_bds, (unsigned) NUM_TXCHAN_BD); 5918c2ecf20Sopenharmony_ci length = min(n_bds * maxpacket, length); 5928c2ecf20Sopenharmony_ci } 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci musb_dbg(musb, "TX DMA%d, pktSz %d %s bds %d dma 0x%llx len %u", 5958c2ecf20Sopenharmony_ci tx->index, 5968c2ecf20Sopenharmony_ci maxpacket, 5978c2ecf20Sopenharmony_ci rndis ? "rndis" : "transparent", 5988c2ecf20Sopenharmony_ci n_bds, 5998c2ecf20Sopenharmony_ci (unsigned long long)addr, length); 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci cppi_rndis_update(tx, 0, musb->ctrl_base, rndis); 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci /* assuming here that channel_program is called during 6048c2ecf20Sopenharmony_ci * transfer initiation ... current code maintains state 6058c2ecf20Sopenharmony_ci * for one outstanding request only (no queues, not even 6068c2ecf20Sopenharmony_ci * the implicit ones of an iso urb). 6078c2ecf20Sopenharmony_ci */ 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci bd = tx->freelist; 6108c2ecf20Sopenharmony_ci tx->head = bd; 6118c2ecf20Sopenharmony_ci tx->last_processed = NULL; 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci /* FIXME use BD pool like RX side does, and just queue 6148c2ecf20Sopenharmony_ci * the minimum number for this request. 6158c2ecf20Sopenharmony_ci */ 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci /* Prepare queue of BDs first, then hand it to hardware. 6188c2ecf20Sopenharmony_ci * All BDs except maybe the last should be of full packet 6198c2ecf20Sopenharmony_ci * size; for RNDIS there _is_ only that last packet. 6208c2ecf20Sopenharmony_ci */ 6218c2ecf20Sopenharmony_ci for (i = 0; i < n_bds; ) { 6228c2ecf20Sopenharmony_ci if (++i < n_bds && bd->next) 6238c2ecf20Sopenharmony_ci bd->hw_next = bd->next->dma; 6248c2ecf20Sopenharmony_ci else 6258c2ecf20Sopenharmony_ci bd->hw_next = 0; 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci bd->hw_bufp = tx->buf_dma + tx->offset; 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci /* FIXME set EOP only on the last packet, 6308c2ecf20Sopenharmony_ci * SOP only on the first ... avoid IRQs 6318c2ecf20Sopenharmony_ci */ 6328c2ecf20Sopenharmony_ci if ((tx->offset + maxpacket) <= tx->buf_len) { 6338c2ecf20Sopenharmony_ci tx->offset += maxpacket; 6348c2ecf20Sopenharmony_ci bd->hw_off_len = maxpacket; 6358c2ecf20Sopenharmony_ci bd->hw_options = CPPI_SOP_SET | CPPI_EOP_SET 6368c2ecf20Sopenharmony_ci | CPPI_OWN_SET | maxpacket; 6378c2ecf20Sopenharmony_ci } else { 6388c2ecf20Sopenharmony_ci /* only this one may be a partial USB Packet */ 6398c2ecf20Sopenharmony_ci u32 partial_len; 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci partial_len = tx->buf_len - tx->offset; 6428c2ecf20Sopenharmony_ci tx->offset = tx->buf_len; 6438c2ecf20Sopenharmony_ci bd->hw_off_len = partial_len; 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci bd->hw_options = CPPI_SOP_SET | CPPI_EOP_SET 6468c2ecf20Sopenharmony_ci | CPPI_OWN_SET | partial_len; 6478c2ecf20Sopenharmony_ci if (partial_len == 0) 6488c2ecf20Sopenharmony_ci bd->hw_options |= CPPI_ZERO_SET; 6498c2ecf20Sopenharmony_ci } 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci musb_dbg(musb, "TXBD %p: nxt %08x buf %08x len %04x opt %08x", 6528c2ecf20Sopenharmony_ci bd, bd->hw_next, bd->hw_bufp, 6538c2ecf20Sopenharmony_ci bd->hw_off_len, bd->hw_options); 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci /* update the last BD enqueued to the list */ 6568c2ecf20Sopenharmony_ci tx->tail = bd; 6578c2ecf20Sopenharmony_ci bd = bd->next; 6588c2ecf20Sopenharmony_ci } 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci /* BDs live in DMA-coherent memory, but writes might be pending */ 6618c2ecf20Sopenharmony_ci cpu_drain_writebuffer(); 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci /* Write to the HeadPtr in state RAM to trigger */ 6648c2ecf20Sopenharmony_ci musb_writel(&tx_ram->tx_head, 0, (u32)tx->freelist->dma); 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci cppi_dump_tx(5, tx, "/S"); 6678c2ecf20Sopenharmony_ci} 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci/* 6708c2ecf20Sopenharmony_ci * CPPI RX Woes: 6718c2ecf20Sopenharmony_ci * ============= 6728c2ecf20Sopenharmony_ci * Consider a 1KB bulk RX buffer in two scenarios: (a) it's fed two 300 byte 6738c2ecf20Sopenharmony_ci * packets back-to-back, and (b) it's fed two 512 byte packets back-to-back. 6748c2ecf20Sopenharmony_ci * (Full speed transfers have similar scenarios.) 6758c2ecf20Sopenharmony_ci * 6768c2ecf20Sopenharmony_ci * The correct behavior for Linux is that (a) fills the buffer with 300 bytes, 6778c2ecf20Sopenharmony_ci * and the next packet goes into a buffer that's queued later; while (b) fills 6788c2ecf20Sopenharmony_ci * the buffer with 1024 bytes. How to do that with CPPI? 6798c2ecf20Sopenharmony_ci * 6808c2ecf20Sopenharmony_ci * - RX queues in "rndis" mode -- one single BD -- handle (a) correctly, but 6818c2ecf20Sopenharmony_ci * (b) loses **BADLY** because nothing (!) happens when that second packet 6828c2ecf20Sopenharmony_ci * fills the buffer, much less when a third one arrives. (Which makes this 6838c2ecf20Sopenharmony_ci * not a "true" RNDIS mode. In the RNDIS protocol short-packet termination 6848c2ecf20Sopenharmony_ci * is optional, and it's fine if peripherals -- not hosts! -- pad messages 6858c2ecf20Sopenharmony_ci * out to end-of-buffer. Standard PCI host controller DMA descriptors 6868c2ecf20Sopenharmony_ci * implement that mode by default ... which is no accident.) 6878c2ecf20Sopenharmony_ci * 6888c2ecf20Sopenharmony_ci * - RX queues in "transparent" mode -- two BDs with 512 bytes each -- have 6898c2ecf20Sopenharmony_ci * converse problems: (b) is handled right, but (a) loses badly. CPPI RX 6908c2ecf20Sopenharmony_ci * ignores SOP/EOP markings and processes both of those BDs; so both packets 6918c2ecf20Sopenharmony_ci * are loaded into the buffer (with a 212 byte gap between them), and the next 6928c2ecf20Sopenharmony_ci * buffer queued will NOT get its 300 bytes of data. (It seems like SOP/EOP 6938c2ecf20Sopenharmony_ci * are intended as outputs for RX queues, not inputs...) 6948c2ecf20Sopenharmony_ci * 6958c2ecf20Sopenharmony_ci * - A variant of "transparent" mode -- one BD at a time -- is the only way to 6968c2ecf20Sopenharmony_ci * reliably make both cases work, with software handling both cases correctly 6978c2ecf20Sopenharmony_ci * and at the significant penalty of needing an IRQ per packet. (The lack of 6988c2ecf20Sopenharmony_ci * I/O overlap can be slightly ameliorated by enabling double buffering.) 6998c2ecf20Sopenharmony_ci * 7008c2ecf20Sopenharmony_ci * So how to get rid of IRQ-per-packet? The transparent multi-BD case could 7018c2ecf20Sopenharmony_ci * be used in special cases like mass storage, which sets URB_SHORT_NOT_OK 7028c2ecf20Sopenharmony_ci * (or maybe its peripheral side counterpart) to flag (a) scenarios as errors 7038c2ecf20Sopenharmony_ci * with guaranteed driver level fault recovery and scrubbing out what's left 7048c2ecf20Sopenharmony_ci * of that garbaged datastream. 7058c2ecf20Sopenharmony_ci * 7068c2ecf20Sopenharmony_ci * But there seems to be no way to identify the cases where CPPI RNDIS mode 7078c2ecf20Sopenharmony_ci * is appropriate -- which do NOT include RNDIS host drivers, but do include 7088c2ecf20Sopenharmony_ci * the CDC Ethernet driver! -- and the documentation is incomplete/wrong. 7098c2ecf20Sopenharmony_ci * So we can't _ever_ use RX RNDIS mode ... except by using a heuristic 7108c2ecf20Sopenharmony_ci * that applies best on the peripheral side (and which could fail rudely). 7118c2ecf20Sopenharmony_ci * 7128c2ecf20Sopenharmony_ci * Leaving only "transparent" mode; we avoid multi-bd modes in almost all 7138c2ecf20Sopenharmony_ci * cases other than mass storage class. Otherwise we're correct but slow, 7148c2ecf20Sopenharmony_ci * since CPPI penalizes our need for a "true RNDIS" default mode. 7158c2ecf20Sopenharmony_ci */ 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci/* Heuristic, intended to kick in for ethernet/rndis peripheral ONLY 7198c2ecf20Sopenharmony_ci * 7208c2ecf20Sopenharmony_ci * IFF 7218c2ecf20Sopenharmony_ci * (a) peripheral mode ... since rndis peripherals could pad their 7228c2ecf20Sopenharmony_ci * writes to hosts, causing i/o failure; or we'd have to cope with 7238c2ecf20Sopenharmony_ci * a largely unknowable variety of host side protocol variants 7248c2ecf20Sopenharmony_ci * (b) and short reads are NOT errors ... since full reads would 7258c2ecf20Sopenharmony_ci * cause those same i/o failures 7268c2ecf20Sopenharmony_ci * (c) and read length is 7278c2ecf20Sopenharmony_ci * - less than 64KB (max per cppi descriptor) 7288c2ecf20Sopenharmony_ci * - not a multiple of 4096 (g_zero default, full reads typical) 7298c2ecf20Sopenharmony_ci * - N (>1) packets long, ditto (full reads not EXPECTED) 7308c2ecf20Sopenharmony_ci * THEN 7318c2ecf20Sopenharmony_ci * try rx rndis mode 7328c2ecf20Sopenharmony_ci * 7338c2ecf20Sopenharmony_ci * Cost of heuristic failing: RXDMA wedges at the end of transfers that 7348c2ecf20Sopenharmony_ci * fill out the whole buffer. Buggy host side usb network drivers could 7358c2ecf20Sopenharmony_ci * trigger that, but "in the field" such bugs seem to be all but unknown. 7368c2ecf20Sopenharmony_ci * 7378c2ecf20Sopenharmony_ci * So this module parameter lets the heuristic be disabled. When using 7388c2ecf20Sopenharmony_ci * gadgetfs, the heuristic will probably need to be disabled. 7398c2ecf20Sopenharmony_ci */ 7408c2ecf20Sopenharmony_cistatic bool cppi_rx_rndis = 1; 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_cimodule_param(cppi_rx_rndis, bool, 0); 7438c2ecf20Sopenharmony_ciMODULE_PARM_DESC(cppi_rx_rndis, "enable/disable RX RNDIS heuristic"); 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci/** 7478c2ecf20Sopenharmony_ci * cppi_next_rx_segment - dma read for the next chunk of a buffer 7488c2ecf20Sopenharmony_ci * @musb: the controller 7498c2ecf20Sopenharmony_ci * @rx: dma channel 7508c2ecf20Sopenharmony_ci * @onepacket: true unless caller treats short reads as errors, and 7518c2ecf20Sopenharmony_ci * performs fault recovery above usbcore. 7528c2ecf20Sopenharmony_ci * Context: controller irqlocked 7538c2ecf20Sopenharmony_ci * 7548c2ecf20Sopenharmony_ci * See above notes about why we can't use multi-BD RX queues except in 7558c2ecf20Sopenharmony_ci * rare cases (mass storage class), and can never use the hardware "rndis" 7568c2ecf20Sopenharmony_ci * mode (since it's not a "true" RNDIS mode) with complete safety.. 7578c2ecf20Sopenharmony_ci * 7588c2ecf20Sopenharmony_ci * It's ESSENTIAL that callers specify "onepacket" mode unless they kick in 7598c2ecf20Sopenharmony_ci * code to recover from corrupted datastreams after each short transfer. 7608c2ecf20Sopenharmony_ci */ 7618c2ecf20Sopenharmony_cistatic void 7628c2ecf20Sopenharmony_cicppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket) 7638c2ecf20Sopenharmony_ci{ 7648c2ecf20Sopenharmony_ci unsigned maxpacket = rx->maxpacket; 7658c2ecf20Sopenharmony_ci dma_addr_t addr = rx->buf_dma + rx->offset; 7668c2ecf20Sopenharmony_ci size_t length = rx->buf_len - rx->offset; 7678c2ecf20Sopenharmony_ci struct cppi_descriptor *bd, *tail; 7688c2ecf20Sopenharmony_ci unsigned n_bds; 7698c2ecf20Sopenharmony_ci unsigned i; 7708c2ecf20Sopenharmony_ci void __iomem *tibase = musb->ctrl_base; 7718c2ecf20Sopenharmony_ci int is_rndis = 0; 7728c2ecf20Sopenharmony_ci struct cppi_rx_stateram __iomem *rx_ram = rx->state_ram; 7738c2ecf20Sopenharmony_ci struct cppi_descriptor *d; 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci if (onepacket) { 7768c2ecf20Sopenharmony_ci /* almost every USB driver, host or peripheral side */ 7778c2ecf20Sopenharmony_ci n_bds = 1; 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci /* maybe apply the heuristic above */ 7808c2ecf20Sopenharmony_ci if (cppi_rx_rndis 7818c2ecf20Sopenharmony_ci && is_peripheral_active(musb) 7828c2ecf20Sopenharmony_ci && length > maxpacket 7838c2ecf20Sopenharmony_ci && (length & ~0xffff) == 0 7848c2ecf20Sopenharmony_ci && (length & 0x0fff) != 0 7858c2ecf20Sopenharmony_ci && (length & (maxpacket - 1)) == 0) { 7868c2ecf20Sopenharmony_ci maxpacket = length; 7878c2ecf20Sopenharmony_ci is_rndis = 1; 7888c2ecf20Sopenharmony_ci } 7898c2ecf20Sopenharmony_ci } else { 7908c2ecf20Sopenharmony_ci /* virtually nothing except mass storage class */ 7918c2ecf20Sopenharmony_ci if (length > 0xffff) { 7928c2ecf20Sopenharmony_ci n_bds = 0xffff / maxpacket; 7938c2ecf20Sopenharmony_ci length = n_bds * maxpacket; 7948c2ecf20Sopenharmony_ci } else { 7958c2ecf20Sopenharmony_ci n_bds = DIV_ROUND_UP(length, maxpacket); 7968c2ecf20Sopenharmony_ci } 7978c2ecf20Sopenharmony_ci if (n_bds == 1) 7988c2ecf20Sopenharmony_ci onepacket = 1; 7998c2ecf20Sopenharmony_ci else 8008c2ecf20Sopenharmony_ci n_bds = min(n_bds, (unsigned) NUM_RXCHAN_BD); 8018c2ecf20Sopenharmony_ci } 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci /* In host mode, autorequest logic can generate some IN tokens; it's 8048c2ecf20Sopenharmony_ci * tricky since we can't leave REQPKT set in RXCSR after the transfer 8058c2ecf20Sopenharmony_ci * finishes. So: multipacket transfers involve two or more segments. 8068c2ecf20Sopenharmony_ci * And always at least two IRQs ... RNDIS mode is not an option. 8078c2ecf20Sopenharmony_ci */ 8088c2ecf20Sopenharmony_ci if (is_host_active(musb)) 8098c2ecf20Sopenharmony_ci n_bds = cppi_autoreq_update(rx, tibase, onepacket, n_bds); 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci cppi_rndis_update(rx, 1, musb->ctrl_base, is_rndis); 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci length = min(n_bds * maxpacket, length); 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci musb_dbg(musb, "RX DMA%d seg, maxp %d %s bds %d (cnt %d) " 8168c2ecf20Sopenharmony_ci "dma 0x%llx len %u %u/%u", 8178c2ecf20Sopenharmony_ci rx->index, maxpacket, 8188c2ecf20Sopenharmony_ci onepacket 8198c2ecf20Sopenharmony_ci ? (is_rndis ? "rndis" : "onepacket") 8208c2ecf20Sopenharmony_ci : "multipacket", 8218c2ecf20Sopenharmony_ci n_bds, 8228c2ecf20Sopenharmony_ci musb_readl(tibase, 8238c2ecf20Sopenharmony_ci DAVINCI_RXCPPI_BUFCNT0_REG + (rx->index * 4)) 8248c2ecf20Sopenharmony_ci & 0xffff, 8258c2ecf20Sopenharmony_ci (unsigned long long)addr, length, 8268c2ecf20Sopenharmony_ci rx->channel.actual_len, rx->buf_len); 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci /* only queue one segment at a time, since the hardware prevents 8298c2ecf20Sopenharmony_ci * correct queue shutdown after unexpected short packets 8308c2ecf20Sopenharmony_ci */ 8318c2ecf20Sopenharmony_ci bd = cppi_bd_alloc(rx); 8328c2ecf20Sopenharmony_ci rx->head = bd; 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci /* Build BDs for all packets in this segment */ 8358c2ecf20Sopenharmony_ci for (i = 0, tail = NULL; bd && i < n_bds; i++, tail = bd) { 8368c2ecf20Sopenharmony_ci u32 bd_len; 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci if (i) { 8398c2ecf20Sopenharmony_ci bd = cppi_bd_alloc(rx); 8408c2ecf20Sopenharmony_ci if (!bd) 8418c2ecf20Sopenharmony_ci break; 8428c2ecf20Sopenharmony_ci tail->next = bd; 8438c2ecf20Sopenharmony_ci tail->hw_next = bd->dma; 8448c2ecf20Sopenharmony_ci } 8458c2ecf20Sopenharmony_ci bd->hw_next = 0; 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci /* all but the last packet will be maxpacket size */ 8488c2ecf20Sopenharmony_ci if (maxpacket < length) 8498c2ecf20Sopenharmony_ci bd_len = maxpacket; 8508c2ecf20Sopenharmony_ci else 8518c2ecf20Sopenharmony_ci bd_len = length; 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci bd->hw_bufp = addr; 8548c2ecf20Sopenharmony_ci addr += bd_len; 8558c2ecf20Sopenharmony_ci rx->offset += bd_len; 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci bd->hw_off_len = (0 /*offset*/ << 16) + bd_len; 8588c2ecf20Sopenharmony_ci bd->buflen = bd_len; 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci bd->hw_options = CPPI_OWN_SET | (i == 0 ? length : 0); 8618c2ecf20Sopenharmony_ci length -= bd_len; 8628c2ecf20Sopenharmony_ci } 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci /* we always expect at least one reusable BD! */ 8658c2ecf20Sopenharmony_ci if (!tail) { 8668c2ecf20Sopenharmony_ci WARNING("rx dma%d -- no BDs? need %d\n", rx->index, n_bds); 8678c2ecf20Sopenharmony_ci return; 8688c2ecf20Sopenharmony_ci } else if (i < n_bds) 8698c2ecf20Sopenharmony_ci WARNING("rx dma%d -- only %d of %d BDs\n", rx->index, i, n_bds); 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci tail->next = NULL; 8728c2ecf20Sopenharmony_ci tail->hw_next = 0; 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci bd = rx->head; 8758c2ecf20Sopenharmony_ci rx->tail = tail; 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci /* short reads and other faults should terminate this entire 8788c2ecf20Sopenharmony_ci * dma segment. we want one "dma packet" per dma segment, not 8798c2ecf20Sopenharmony_ci * one per USB packet, terminating the whole queue at once... 8808c2ecf20Sopenharmony_ci * NOTE that current hardware seems to ignore SOP and EOP. 8818c2ecf20Sopenharmony_ci */ 8828c2ecf20Sopenharmony_ci bd->hw_options |= CPPI_SOP_SET; 8838c2ecf20Sopenharmony_ci tail->hw_options |= CPPI_EOP_SET; 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci for (d = rx->head; d; d = d->next) 8868c2ecf20Sopenharmony_ci cppi_dump_rxbd("S", d); 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci /* in case the preceding transfer left some state... */ 8898c2ecf20Sopenharmony_ci tail = rx->last_processed; 8908c2ecf20Sopenharmony_ci if (tail) { 8918c2ecf20Sopenharmony_ci tail->next = bd; 8928c2ecf20Sopenharmony_ci tail->hw_next = bd->dma; 8938c2ecf20Sopenharmony_ci } 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci core_rxirq_enable(tibase, rx->index + 1); 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci /* BDs live in DMA-coherent memory, but writes might be pending */ 8988c2ecf20Sopenharmony_ci cpu_drain_writebuffer(); 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci /* REVISIT specs say to write this AFTER the BUFCNT register 9018c2ecf20Sopenharmony_ci * below ... but that loses badly. 9028c2ecf20Sopenharmony_ci */ 9038c2ecf20Sopenharmony_ci musb_writel(&rx_ram->rx_head, 0, bd->dma); 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci /* bufferCount must be at least 3, and zeroes on completion 9068c2ecf20Sopenharmony_ci * unless it underflows below zero, or stops at two, or keeps 9078c2ecf20Sopenharmony_ci * growing ... grr. 9088c2ecf20Sopenharmony_ci */ 9098c2ecf20Sopenharmony_ci i = musb_readl(tibase, 9108c2ecf20Sopenharmony_ci DAVINCI_RXCPPI_BUFCNT0_REG + (rx->index * 4)) 9118c2ecf20Sopenharmony_ci & 0xffff; 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci if (!i) 9148c2ecf20Sopenharmony_ci musb_writel(tibase, 9158c2ecf20Sopenharmony_ci DAVINCI_RXCPPI_BUFCNT0_REG + (rx->index * 4), 9168c2ecf20Sopenharmony_ci n_bds + 2); 9178c2ecf20Sopenharmony_ci else if (n_bds > (i - 3)) 9188c2ecf20Sopenharmony_ci musb_writel(tibase, 9198c2ecf20Sopenharmony_ci DAVINCI_RXCPPI_BUFCNT0_REG + (rx->index * 4), 9208c2ecf20Sopenharmony_ci n_bds - (i - 3)); 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_ci i = musb_readl(tibase, 9238c2ecf20Sopenharmony_ci DAVINCI_RXCPPI_BUFCNT0_REG + (rx->index * 4)) 9248c2ecf20Sopenharmony_ci & 0xffff; 9258c2ecf20Sopenharmony_ci if (i < (2 + n_bds)) { 9268c2ecf20Sopenharmony_ci musb_dbg(musb, "bufcnt%d underrun - %d (for %d)", 9278c2ecf20Sopenharmony_ci rx->index, i, n_bds); 9288c2ecf20Sopenharmony_ci musb_writel(tibase, 9298c2ecf20Sopenharmony_ci DAVINCI_RXCPPI_BUFCNT0_REG + (rx->index * 4), 9308c2ecf20Sopenharmony_ci n_bds + 2); 9318c2ecf20Sopenharmony_ci } 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci cppi_dump_rx(4, rx, "/S"); 9348c2ecf20Sopenharmony_ci} 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci/** 9378c2ecf20Sopenharmony_ci * cppi_channel_program - program channel for data transfer 9388c2ecf20Sopenharmony_ci * @ch: the channel 9398c2ecf20Sopenharmony_ci * @maxpacket: max packet size 9408c2ecf20Sopenharmony_ci * @mode: For RX, 1 unless the usb protocol driver promised to treat 9418c2ecf20Sopenharmony_ci * all short reads as errors and kick in high level fault recovery. 9428c2ecf20Sopenharmony_ci * For TX, ignored because of RNDIS mode races/glitches. 9438c2ecf20Sopenharmony_ci * @dma_addr: dma address of buffer 9448c2ecf20Sopenharmony_ci * @len: length of buffer 9458c2ecf20Sopenharmony_ci * Context: controller irqlocked 9468c2ecf20Sopenharmony_ci */ 9478c2ecf20Sopenharmony_cistatic int cppi_channel_program(struct dma_channel *ch, 9488c2ecf20Sopenharmony_ci u16 maxpacket, u8 mode, 9498c2ecf20Sopenharmony_ci dma_addr_t dma_addr, u32 len) 9508c2ecf20Sopenharmony_ci{ 9518c2ecf20Sopenharmony_ci struct cppi_channel *cppi_ch; 9528c2ecf20Sopenharmony_ci struct cppi *controller; 9538c2ecf20Sopenharmony_ci struct musb *musb; 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci cppi_ch = container_of(ch, struct cppi_channel, channel); 9568c2ecf20Sopenharmony_ci controller = cppi_ch->controller; 9578c2ecf20Sopenharmony_ci musb = controller->controller.musb; 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci switch (ch->status) { 9608c2ecf20Sopenharmony_ci case MUSB_DMA_STATUS_BUS_ABORT: 9618c2ecf20Sopenharmony_ci case MUSB_DMA_STATUS_CORE_ABORT: 9628c2ecf20Sopenharmony_ci /* fault irq handler should have handled cleanup */ 9638c2ecf20Sopenharmony_ci WARNING("%cX DMA%d not cleaned up after abort!\n", 9648c2ecf20Sopenharmony_ci cppi_ch->transmit ? 'T' : 'R', 9658c2ecf20Sopenharmony_ci cppi_ch->index); 9668c2ecf20Sopenharmony_ci /* WARN_ON(1); */ 9678c2ecf20Sopenharmony_ci break; 9688c2ecf20Sopenharmony_ci case MUSB_DMA_STATUS_BUSY: 9698c2ecf20Sopenharmony_ci WARNING("program active channel? %cX DMA%d\n", 9708c2ecf20Sopenharmony_ci cppi_ch->transmit ? 'T' : 'R', 9718c2ecf20Sopenharmony_ci cppi_ch->index); 9728c2ecf20Sopenharmony_ci /* WARN_ON(1); */ 9738c2ecf20Sopenharmony_ci break; 9748c2ecf20Sopenharmony_ci case MUSB_DMA_STATUS_UNKNOWN: 9758c2ecf20Sopenharmony_ci musb_dbg(musb, "%cX DMA%d not allocated!", 9768c2ecf20Sopenharmony_ci cppi_ch->transmit ? 'T' : 'R', 9778c2ecf20Sopenharmony_ci cppi_ch->index); 9788c2ecf20Sopenharmony_ci fallthrough; 9798c2ecf20Sopenharmony_ci case MUSB_DMA_STATUS_FREE: 9808c2ecf20Sopenharmony_ci break; 9818c2ecf20Sopenharmony_ci } 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci ch->status = MUSB_DMA_STATUS_BUSY; 9848c2ecf20Sopenharmony_ci 9858c2ecf20Sopenharmony_ci /* set transfer parameters, then queue up its first segment */ 9868c2ecf20Sopenharmony_ci cppi_ch->buf_dma = dma_addr; 9878c2ecf20Sopenharmony_ci cppi_ch->offset = 0; 9888c2ecf20Sopenharmony_ci cppi_ch->maxpacket = maxpacket; 9898c2ecf20Sopenharmony_ci cppi_ch->buf_len = len; 9908c2ecf20Sopenharmony_ci cppi_ch->channel.actual_len = 0; 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci /* TX channel? or RX? */ 9938c2ecf20Sopenharmony_ci if (cppi_ch->transmit) 9948c2ecf20Sopenharmony_ci cppi_next_tx_segment(musb, cppi_ch); 9958c2ecf20Sopenharmony_ci else 9968c2ecf20Sopenharmony_ci cppi_next_rx_segment(musb, cppi_ch, mode); 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci return true; 9998c2ecf20Sopenharmony_ci} 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_cistatic bool cppi_rx_scan(struct cppi *cppi, unsigned ch) 10028c2ecf20Sopenharmony_ci{ 10038c2ecf20Sopenharmony_ci struct cppi_channel *rx = &cppi->rx[ch]; 10048c2ecf20Sopenharmony_ci struct cppi_rx_stateram __iomem *state = rx->state_ram; 10058c2ecf20Sopenharmony_ci struct cppi_descriptor *bd; 10068c2ecf20Sopenharmony_ci struct cppi_descriptor *last = rx->last_processed; 10078c2ecf20Sopenharmony_ci bool completed = false; 10088c2ecf20Sopenharmony_ci bool acked = false; 10098c2ecf20Sopenharmony_ci int i; 10108c2ecf20Sopenharmony_ci dma_addr_t safe2ack; 10118c2ecf20Sopenharmony_ci void __iomem *regs = rx->hw_ep->regs; 10128c2ecf20Sopenharmony_ci struct musb *musb = cppi->controller.musb; 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci cppi_dump_rx(6, rx, "/K"); 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci bd = last ? last->next : rx->head; 10178c2ecf20Sopenharmony_ci if (!bd) 10188c2ecf20Sopenharmony_ci return false; 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci /* run through all completed BDs */ 10218c2ecf20Sopenharmony_ci for (i = 0, safe2ack = musb_readl(&state->rx_complete, 0); 10228c2ecf20Sopenharmony_ci (safe2ack || completed) && bd && i < NUM_RXCHAN_BD; 10238c2ecf20Sopenharmony_ci i++, bd = bd->next) { 10248c2ecf20Sopenharmony_ci u16 len; 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci /* catch latest BD writes from CPPI */ 10278c2ecf20Sopenharmony_ci rmb(); 10288c2ecf20Sopenharmony_ci if (!completed && (bd->hw_options & CPPI_OWN_SET)) 10298c2ecf20Sopenharmony_ci break; 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci musb_dbg(musb, "C/RXBD %llx: nxt %08x buf %08x " 10328c2ecf20Sopenharmony_ci "off.len %08x opt.len %08x (%d)", 10338c2ecf20Sopenharmony_ci (unsigned long long)bd->dma, bd->hw_next, bd->hw_bufp, 10348c2ecf20Sopenharmony_ci bd->hw_off_len, bd->hw_options, 10358c2ecf20Sopenharmony_ci rx->channel.actual_len); 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_ci /* actual packet received length */ 10388c2ecf20Sopenharmony_ci if ((bd->hw_options & CPPI_SOP_SET) && !completed) 10398c2ecf20Sopenharmony_ci len = bd->hw_off_len & CPPI_RECV_PKTLEN_MASK; 10408c2ecf20Sopenharmony_ci else 10418c2ecf20Sopenharmony_ci len = 0; 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci if (bd->hw_options & CPPI_EOQ_MASK) 10448c2ecf20Sopenharmony_ci completed = true; 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci if (!completed && len < bd->buflen) { 10478c2ecf20Sopenharmony_ci /* NOTE: when we get a short packet, RXCSR_H_REQPKT 10488c2ecf20Sopenharmony_ci * must have been cleared, and no more DMA packets may 10498c2ecf20Sopenharmony_ci * active be in the queue... TI docs didn't say, but 10508c2ecf20Sopenharmony_ci * CPPI ignores those BDs even though OWN is still set. 10518c2ecf20Sopenharmony_ci */ 10528c2ecf20Sopenharmony_ci completed = true; 10538c2ecf20Sopenharmony_ci musb_dbg(musb, "rx short %d/%d (%d)", 10548c2ecf20Sopenharmony_ci len, bd->buflen, 10558c2ecf20Sopenharmony_ci rx->channel.actual_len); 10568c2ecf20Sopenharmony_ci } 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci /* If we got here, we expect to ack at least one BD; meanwhile 10598c2ecf20Sopenharmony_ci * CPPI may completing other BDs while we scan this list... 10608c2ecf20Sopenharmony_ci * 10618c2ecf20Sopenharmony_ci * RACE: we can notice OWN cleared before CPPI raises the 10628c2ecf20Sopenharmony_ci * matching irq by writing that BD as the completion pointer. 10638c2ecf20Sopenharmony_ci * In such cases, stop scanning and wait for the irq, avoiding 10648c2ecf20Sopenharmony_ci * lost acks and states where BD ownership is unclear. 10658c2ecf20Sopenharmony_ci */ 10668c2ecf20Sopenharmony_ci if (bd->dma == safe2ack) { 10678c2ecf20Sopenharmony_ci musb_writel(&state->rx_complete, 0, safe2ack); 10688c2ecf20Sopenharmony_ci safe2ack = musb_readl(&state->rx_complete, 0); 10698c2ecf20Sopenharmony_ci acked = true; 10708c2ecf20Sopenharmony_ci if (bd->dma == safe2ack) 10718c2ecf20Sopenharmony_ci safe2ack = 0; 10728c2ecf20Sopenharmony_ci } 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci rx->channel.actual_len += len; 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci cppi_bd_free(rx, last); 10778c2ecf20Sopenharmony_ci last = bd; 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci /* stop scanning on end-of-segment */ 10808c2ecf20Sopenharmony_ci if (bd->hw_next == 0) 10818c2ecf20Sopenharmony_ci completed = true; 10828c2ecf20Sopenharmony_ci } 10838c2ecf20Sopenharmony_ci rx->last_processed = last; 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci /* dma abort, lost ack, or ... */ 10868c2ecf20Sopenharmony_ci if (!acked && last) { 10878c2ecf20Sopenharmony_ci int csr; 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci if (safe2ack == 0 || safe2ack == rx->last_processed->dma) 10908c2ecf20Sopenharmony_ci musb_writel(&state->rx_complete, 0, safe2ack); 10918c2ecf20Sopenharmony_ci if (safe2ack == 0) { 10928c2ecf20Sopenharmony_ci cppi_bd_free(rx, last); 10938c2ecf20Sopenharmony_ci rx->last_processed = NULL; 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci /* if we land here on the host side, H_REQPKT will 10968c2ecf20Sopenharmony_ci * be clear and we need to restart the queue... 10978c2ecf20Sopenharmony_ci */ 10988c2ecf20Sopenharmony_ci WARN_ON(rx->head); 10998c2ecf20Sopenharmony_ci } 11008c2ecf20Sopenharmony_ci musb_ep_select(cppi->mregs, rx->index + 1); 11018c2ecf20Sopenharmony_ci csr = musb_readw(regs, MUSB_RXCSR); 11028c2ecf20Sopenharmony_ci if (csr & MUSB_RXCSR_DMAENAB) { 11038c2ecf20Sopenharmony_ci musb_dbg(musb, "list%d %p/%p, last %llx%s, csr %04x", 11048c2ecf20Sopenharmony_ci rx->index, 11058c2ecf20Sopenharmony_ci rx->head, rx->tail, 11068c2ecf20Sopenharmony_ci rx->last_processed 11078c2ecf20Sopenharmony_ci ? (unsigned long long) 11088c2ecf20Sopenharmony_ci rx->last_processed->dma 11098c2ecf20Sopenharmony_ci : 0, 11108c2ecf20Sopenharmony_ci completed ? ", completed" : "", 11118c2ecf20Sopenharmony_ci csr); 11128c2ecf20Sopenharmony_ci cppi_dump_rxq(4, "/what?", rx); 11138c2ecf20Sopenharmony_ci } 11148c2ecf20Sopenharmony_ci } 11158c2ecf20Sopenharmony_ci if (!completed) { 11168c2ecf20Sopenharmony_ci int csr; 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci rx->head = bd; 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci /* REVISIT seems like "autoreq all but EOP" doesn't... 11218c2ecf20Sopenharmony_ci * setting it here "should" be racey, but seems to work 11228c2ecf20Sopenharmony_ci */ 11238c2ecf20Sopenharmony_ci csr = musb_readw(rx->hw_ep->regs, MUSB_RXCSR); 11248c2ecf20Sopenharmony_ci if (is_host_active(cppi->controller.musb) 11258c2ecf20Sopenharmony_ci && bd 11268c2ecf20Sopenharmony_ci && !(csr & MUSB_RXCSR_H_REQPKT)) { 11278c2ecf20Sopenharmony_ci csr |= MUSB_RXCSR_H_REQPKT; 11288c2ecf20Sopenharmony_ci musb_writew(regs, MUSB_RXCSR, 11298c2ecf20Sopenharmony_ci MUSB_RXCSR_H_WZC_BITS | csr); 11308c2ecf20Sopenharmony_ci csr = musb_readw(rx->hw_ep->regs, MUSB_RXCSR); 11318c2ecf20Sopenharmony_ci } 11328c2ecf20Sopenharmony_ci } else { 11338c2ecf20Sopenharmony_ci rx->head = NULL; 11348c2ecf20Sopenharmony_ci rx->tail = NULL; 11358c2ecf20Sopenharmony_ci } 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_ci cppi_dump_rx(6, rx, completed ? "/completed" : "/cleaned"); 11388c2ecf20Sopenharmony_ci return completed; 11398c2ecf20Sopenharmony_ci} 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_ciirqreturn_t cppi_interrupt(int irq, void *dev_id) 11428c2ecf20Sopenharmony_ci{ 11438c2ecf20Sopenharmony_ci struct musb *musb = dev_id; 11448c2ecf20Sopenharmony_ci struct cppi *cppi; 11458c2ecf20Sopenharmony_ci void __iomem *tibase; 11468c2ecf20Sopenharmony_ci struct musb_hw_ep *hw_ep = NULL; 11478c2ecf20Sopenharmony_ci u32 rx, tx; 11488c2ecf20Sopenharmony_ci int i, index; 11498c2ecf20Sopenharmony_ci unsigned long flags; 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_ci cppi = container_of(musb->dma_controller, struct cppi, controller); 11528c2ecf20Sopenharmony_ci if (cppi->irq) 11538c2ecf20Sopenharmony_ci spin_lock_irqsave(&musb->lock, flags); 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_ci tibase = musb->ctrl_base; 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci tx = musb_readl(tibase, DAVINCI_TXCPPI_MASKED_REG); 11588c2ecf20Sopenharmony_ci rx = musb_readl(tibase, DAVINCI_RXCPPI_MASKED_REG); 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci if (!tx && !rx) { 11618c2ecf20Sopenharmony_ci if (cppi->irq) 11628c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&musb->lock, flags); 11638c2ecf20Sopenharmony_ci return IRQ_NONE; 11648c2ecf20Sopenharmony_ci } 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci musb_dbg(musb, "CPPI IRQ Tx%x Rx%x", tx, rx); 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_ci /* process TX channels */ 11698c2ecf20Sopenharmony_ci for (index = 0; tx; tx = tx >> 1, index++) { 11708c2ecf20Sopenharmony_ci struct cppi_channel *tx_ch; 11718c2ecf20Sopenharmony_ci struct cppi_tx_stateram __iomem *tx_ram; 11728c2ecf20Sopenharmony_ci bool completed = false; 11738c2ecf20Sopenharmony_ci struct cppi_descriptor *bd; 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci if (!(tx & 1)) 11768c2ecf20Sopenharmony_ci continue; 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_ci tx_ch = cppi->tx + index; 11798c2ecf20Sopenharmony_ci tx_ram = tx_ch->state_ram; 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci /* FIXME need a cppi_tx_scan() routine, which 11828c2ecf20Sopenharmony_ci * can also be called from abort code 11838c2ecf20Sopenharmony_ci */ 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_ci cppi_dump_tx(5, tx_ch, "/E"); 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci bd = tx_ch->head; 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ci /* 11908c2ecf20Sopenharmony_ci * If Head is null then this could mean that a abort interrupt 11918c2ecf20Sopenharmony_ci * that needs to be acknowledged. 11928c2ecf20Sopenharmony_ci */ 11938c2ecf20Sopenharmony_ci if (NULL == bd) { 11948c2ecf20Sopenharmony_ci musb_dbg(musb, "null BD"); 11958c2ecf20Sopenharmony_ci musb_writel(&tx_ram->tx_complete, 0, 0); 11968c2ecf20Sopenharmony_ci continue; 11978c2ecf20Sopenharmony_ci } 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci /* run through all completed BDs */ 12008c2ecf20Sopenharmony_ci for (i = 0; !completed && bd && i < NUM_TXCHAN_BD; 12018c2ecf20Sopenharmony_ci i++, bd = bd->next) { 12028c2ecf20Sopenharmony_ci u16 len; 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_ci /* catch latest BD writes from CPPI */ 12058c2ecf20Sopenharmony_ci rmb(); 12068c2ecf20Sopenharmony_ci if (bd->hw_options & CPPI_OWN_SET) 12078c2ecf20Sopenharmony_ci break; 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci musb_dbg(musb, "C/TXBD %p n %x b %x off %x opt %x", 12108c2ecf20Sopenharmony_ci bd, bd->hw_next, bd->hw_bufp, 12118c2ecf20Sopenharmony_ci bd->hw_off_len, bd->hw_options); 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci len = bd->hw_off_len & CPPI_BUFFER_LEN_MASK; 12148c2ecf20Sopenharmony_ci tx_ch->channel.actual_len += len; 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci tx_ch->last_processed = bd; 12178c2ecf20Sopenharmony_ci 12188c2ecf20Sopenharmony_ci /* write completion register to acknowledge 12198c2ecf20Sopenharmony_ci * processing of completed BDs, and possibly 12208c2ecf20Sopenharmony_ci * release the IRQ; EOQ might not be set ... 12218c2ecf20Sopenharmony_ci * 12228c2ecf20Sopenharmony_ci * REVISIT use the same ack strategy as rx 12238c2ecf20Sopenharmony_ci * 12248c2ecf20Sopenharmony_ci * REVISIT have observed bit 18 set; huh?? 12258c2ecf20Sopenharmony_ci */ 12268c2ecf20Sopenharmony_ci /* if ((bd->hw_options & CPPI_EOQ_MASK)) */ 12278c2ecf20Sopenharmony_ci musb_writel(&tx_ram->tx_complete, 0, bd->dma); 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_ci /* stop scanning on end-of-segment */ 12308c2ecf20Sopenharmony_ci if (bd->hw_next == 0) 12318c2ecf20Sopenharmony_ci completed = true; 12328c2ecf20Sopenharmony_ci } 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci /* on end of segment, maybe go to next one */ 12358c2ecf20Sopenharmony_ci if (completed) { 12368c2ecf20Sopenharmony_ci /* cppi_dump_tx(4, tx_ch, "/complete"); */ 12378c2ecf20Sopenharmony_ci 12388c2ecf20Sopenharmony_ci /* transfer more, or report completion */ 12398c2ecf20Sopenharmony_ci if (tx_ch->offset >= tx_ch->buf_len) { 12408c2ecf20Sopenharmony_ci tx_ch->head = NULL; 12418c2ecf20Sopenharmony_ci tx_ch->tail = NULL; 12428c2ecf20Sopenharmony_ci tx_ch->channel.status = MUSB_DMA_STATUS_FREE; 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci hw_ep = tx_ch->hw_ep; 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ci musb_dma_completion(musb, index + 1, 1); 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci } else { 12498c2ecf20Sopenharmony_ci /* Bigger transfer than we could fit in 12508c2ecf20Sopenharmony_ci * that first batch of descriptors... 12518c2ecf20Sopenharmony_ci */ 12528c2ecf20Sopenharmony_ci cppi_next_tx_segment(musb, tx_ch); 12538c2ecf20Sopenharmony_ci } 12548c2ecf20Sopenharmony_ci } else 12558c2ecf20Sopenharmony_ci tx_ch->head = bd; 12568c2ecf20Sopenharmony_ci } 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ci /* Start processing the RX block */ 12598c2ecf20Sopenharmony_ci for (index = 0; rx; rx = rx >> 1, index++) { 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_ci if (rx & 1) { 12628c2ecf20Sopenharmony_ci struct cppi_channel *rx_ch; 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_ci rx_ch = cppi->rx + index; 12658c2ecf20Sopenharmony_ci 12668c2ecf20Sopenharmony_ci /* let incomplete dma segments finish */ 12678c2ecf20Sopenharmony_ci if (!cppi_rx_scan(cppi, index)) 12688c2ecf20Sopenharmony_ci continue; 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_ci /* start another dma segment if needed */ 12718c2ecf20Sopenharmony_ci if (rx_ch->channel.actual_len != rx_ch->buf_len 12728c2ecf20Sopenharmony_ci && rx_ch->channel.actual_len 12738c2ecf20Sopenharmony_ci == rx_ch->offset) { 12748c2ecf20Sopenharmony_ci cppi_next_rx_segment(musb, rx_ch, 1); 12758c2ecf20Sopenharmony_ci continue; 12768c2ecf20Sopenharmony_ci } 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ci /* all segments completed! */ 12798c2ecf20Sopenharmony_ci rx_ch->channel.status = MUSB_DMA_STATUS_FREE; 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci hw_ep = rx_ch->hw_ep; 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci core_rxirq_disable(tibase, index + 1); 12848c2ecf20Sopenharmony_ci musb_dma_completion(musb, index + 1, 0); 12858c2ecf20Sopenharmony_ci } 12868c2ecf20Sopenharmony_ci } 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_ci /* write to CPPI EOI register to re-enable interrupts */ 12898c2ecf20Sopenharmony_ci musb_writel(tibase, DAVINCI_CPPI_EOI_REG, 0); 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_ci if (cppi->irq) 12928c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&musb->lock, flags); 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_ci return IRQ_HANDLED; 12958c2ecf20Sopenharmony_ci} 12968c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(cppi_interrupt); 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_ci/* Instantiate a software object representing a DMA controller. */ 12998c2ecf20Sopenharmony_cistruct dma_controller * 13008c2ecf20Sopenharmony_cicppi_dma_controller_create(struct musb *musb, void __iomem *mregs) 13018c2ecf20Sopenharmony_ci{ 13028c2ecf20Sopenharmony_ci struct cppi *controller; 13038c2ecf20Sopenharmony_ci struct device *dev = musb->controller; 13048c2ecf20Sopenharmony_ci struct platform_device *pdev = to_platform_device(dev); 13058c2ecf20Sopenharmony_ci int irq = platform_get_irq_byname(pdev, "dma"); 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci controller = kzalloc(sizeof *controller, GFP_KERNEL); 13088c2ecf20Sopenharmony_ci if (!controller) 13098c2ecf20Sopenharmony_ci return NULL; 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci controller->mregs = mregs; 13128c2ecf20Sopenharmony_ci controller->tibase = mregs - DAVINCI_BASE_OFFSET; 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci controller->controller.musb = musb; 13158c2ecf20Sopenharmony_ci controller->controller.channel_alloc = cppi_channel_allocate; 13168c2ecf20Sopenharmony_ci controller->controller.channel_release = cppi_channel_release; 13178c2ecf20Sopenharmony_ci controller->controller.channel_program = cppi_channel_program; 13188c2ecf20Sopenharmony_ci controller->controller.channel_abort = cppi_channel_abort; 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci /* NOTE: allocating from on-chip SRAM would give the least 13218c2ecf20Sopenharmony_ci * contention for memory access, if that ever matters here. 13228c2ecf20Sopenharmony_ci */ 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci /* setup BufferPool */ 13258c2ecf20Sopenharmony_ci controller->pool = dma_pool_create("cppi", 13268c2ecf20Sopenharmony_ci controller->controller.musb->controller, 13278c2ecf20Sopenharmony_ci sizeof(struct cppi_descriptor), 13288c2ecf20Sopenharmony_ci CPPI_DESCRIPTOR_ALIGN, 0); 13298c2ecf20Sopenharmony_ci if (!controller->pool) { 13308c2ecf20Sopenharmony_ci kfree(controller); 13318c2ecf20Sopenharmony_ci return NULL; 13328c2ecf20Sopenharmony_ci } 13338c2ecf20Sopenharmony_ci 13348c2ecf20Sopenharmony_ci if (irq > 0) { 13358c2ecf20Sopenharmony_ci if (request_irq(irq, cppi_interrupt, 0, "cppi-dma", musb)) { 13368c2ecf20Sopenharmony_ci dev_err(dev, "request_irq %d failed!\n", irq); 13378c2ecf20Sopenharmony_ci musb_dma_controller_destroy(&controller->controller); 13388c2ecf20Sopenharmony_ci return NULL; 13398c2ecf20Sopenharmony_ci } 13408c2ecf20Sopenharmony_ci controller->irq = irq; 13418c2ecf20Sopenharmony_ci } 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_ci cppi_controller_start(controller); 13448c2ecf20Sopenharmony_ci return &controller->controller; 13458c2ecf20Sopenharmony_ci} 13468c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(cppi_dma_controller_create); 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_ci/* 13498c2ecf20Sopenharmony_ci * Destroy a previously-instantiated DMA controller. 13508c2ecf20Sopenharmony_ci */ 13518c2ecf20Sopenharmony_civoid cppi_dma_controller_destroy(struct dma_controller *c) 13528c2ecf20Sopenharmony_ci{ 13538c2ecf20Sopenharmony_ci struct cppi *cppi; 13548c2ecf20Sopenharmony_ci 13558c2ecf20Sopenharmony_ci cppi = container_of(c, struct cppi, controller); 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_ci cppi_controller_stop(cppi); 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci if (cppi->irq) 13608c2ecf20Sopenharmony_ci free_irq(cppi->irq, cppi->controller.musb); 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ci /* assert: caller stopped the controller first */ 13638c2ecf20Sopenharmony_ci dma_pool_destroy(cppi->pool); 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_ci kfree(cppi); 13668c2ecf20Sopenharmony_ci} 13678c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(cppi_dma_controller_destroy); 13688c2ecf20Sopenharmony_ci 13698c2ecf20Sopenharmony_ci/* 13708c2ecf20Sopenharmony_ci * Context: controller irqlocked, endpoint selected 13718c2ecf20Sopenharmony_ci */ 13728c2ecf20Sopenharmony_cistatic int cppi_channel_abort(struct dma_channel *channel) 13738c2ecf20Sopenharmony_ci{ 13748c2ecf20Sopenharmony_ci struct cppi_channel *cppi_ch; 13758c2ecf20Sopenharmony_ci struct cppi *controller; 13768c2ecf20Sopenharmony_ci void __iomem *mbase; 13778c2ecf20Sopenharmony_ci void __iomem *tibase; 13788c2ecf20Sopenharmony_ci void __iomem *regs; 13798c2ecf20Sopenharmony_ci u32 value; 13808c2ecf20Sopenharmony_ci struct cppi_descriptor *queue; 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_ci cppi_ch = container_of(channel, struct cppi_channel, channel); 13838c2ecf20Sopenharmony_ci 13848c2ecf20Sopenharmony_ci controller = cppi_ch->controller; 13858c2ecf20Sopenharmony_ci 13868c2ecf20Sopenharmony_ci switch (channel->status) { 13878c2ecf20Sopenharmony_ci case MUSB_DMA_STATUS_BUS_ABORT: 13888c2ecf20Sopenharmony_ci case MUSB_DMA_STATUS_CORE_ABORT: 13898c2ecf20Sopenharmony_ci /* from RX or TX fault irq handler */ 13908c2ecf20Sopenharmony_ci case MUSB_DMA_STATUS_BUSY: 13918c2ecf20Sopenharmony_ci /* the hardware needs shutting down */ 13928c2ecf20Sopenharmony_ci regs = cppi_ch->hw_ep->regs; 13938c2ecf20Sopenharmony_ci break; 13948c2ecf20Sopenharmony_ci case MUSB_DMA_STATUS_UNKNOWN: 13958c2ecf20Sopenharmony_ci case MUSB_DMA_STATUS_FREE: 13968c2ecf20Sopenharmony_ci return 0; 13978c2ecf20Sopenharmony_ci default: 13988c2ecf20Sopenharmony_ci return -EINVAL; 13998c2ecf20Sopenharmony_ci } 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_ci if (!cppi_ch->transmit && cppi_ch->head) 14028c2ecf20Sopenharmony_ci cppi_dump_rxq(3, "/abort", cppi_ch); 14038c2ecf20Sopenharmony_ci 14048c2ecf20Sopenharmony_ci mbase = controller->mregs; 14058c2ecf20Sopenharmony_ci tibase = controller->tibase; 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ci queue = cppi_ch->head; 14088c2ecf20Sopenharmony_ci cppi_ch->head = NULL; 14098c2ecf20Sopenharmony_ci cppi_ch->tail = NULL; 14108c2ecf20Sopenharmony_ci 14118c2ecf20Sopenharmony_ci /* REVISIT should rely on caller having done this, 14128c2ecf20Sopenharmony_ci * and caller should rely on us not changing it. 14138c2ecf20Sopenharmony_ci * peripheral code is safe ... check host too. 14148c2ecf20Sopenharmony_ci */ 14158c2ecf20Sopenharmony_ci musb_ep_select(mbase, cppi_ch->index + 1); 14168c2ecf20Sopenharmony_ci 14178c2ecf20Sopenharmony_ci if (cppi_ch->transmit) { 14188c2ecf20Sopenharmony_ci struct cppi_tx_stateram __iomem *tx_ram; 14198c2ecf20Sopenharmony_ci /* REVISIT put timeouts on these controller handshakes */ 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_ci cppi_dump_tx(6, cppi_ch, " (teardown)"); 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci /* teardown DMA engine then usb core */ 14248c2ecf20Sopenharmony_ci do { 14258c2ecf20Sopenharmony_ci value = musb_readl(tibase, DAVINCI_TXCPPI_TEAR_REG); 14268c2ecf20Sopenharmony_ci } while (!(value & CPPI_TEAR_READY)); 14278c2ecf20Sopenharmony_ci musb_writel(tibase, DAVINCI_TXCPPI_TEAR_REG, cppi_ch->index); 14288c2ecf20Sopenharmony_ci 14298c2ecf20Sopenharmony_ci tx_ram = cppi_ch->state_ram; 14308c2ecf20Sopenharmony_ci do { 14318c2ecf20Sopenharmony_ci value = musb_readl(&tx_ram->tx_complete, 0); 14328c2ecf20Sopenharmony_ci } while (0xFFFFFFFC != value); 14338c2ecf20Sopenharmony_ci 14348c2ecf20Sopenharmony_ci /* FIXME clean up the transfer state ... here? 14358c2ecf20Sopenharmony_ci * the completion routine should get called with 14368c2ecf20Sopenharmony_ci * an appropriate status code. 14378c2ecf20Sopenharmony_ci */ 14388c2ecf20Sopenharmony_ci 14398c2ecf20Sopenharmony_ci value = musb_readw(regs, MUSB_TXCSR); 14408c2ecf20Sopenharmony_ci value &= ~MUSB_TXCSR_DMAENAB; 14418c2ecf20Sopenharmony_ci value |= MUSB_TXCSR_FLUSHFIFO; 14428c2ecf20Sopenharmony_ci musb_writew(regs, MUSB_TXCSR, value); 14438c2ecf20Sopenharmony_ci musb_writew(regs, MUSB_TXCSR, value); 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_ci /* 14468c2ecf20Sopenharmony_ci * 1. Write to completion Ptr value 0x1(bit 0 set) 14478c2ecf20Sopenharmony_ci * (write back mode) 14488c2ecf20Sopenharmony_ci * 2. Wait for abort interrupt and then put the channel in 14498c2ecf20Sopenharmony_ci * compare mode by writing 1 to the tx_complete register. 14508c2ecf20Sopenharmony_ci */ 14518c2ecf20Sopenharmony_ci cppi_reset_tx(tx_ram, 1); 14528c2ecf20Sopenharmony_ci cppi_ch->head = NULL; 14538c2ecf20Sopenharmony_ci musb_writel(&tx_ram->tx_complete, 0, 1); 14548c2ecf20Sopenharmony_ci cppi_dump_tx(5, cppi_ch, " (done teardown)"); 14558c2ecf20Sopenharmony_ci 14568c2ecf20Sopenharmony_ci /* REVISIT tx side _should_ clean up the same way 14578c2ecf20Sopenharmony_ci * as the RX side ... this does no cleanup at all! 14588c2ecf20Sopenharmony_ci */ 14598c2ecf20Sopenharmony_ci 14608c2ecf20Sopenharmony_ci } else /* RX */ { 14618c2ecf20Sopenharmony_ci u16 csr; 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_ci /* NOTE: docs don't guarantee any of this works ... we 14648c2ecf20Sopenharmony_ci * expect that if the usb core stops telling the cppi core 14658c2ecf20Sopenharmony_ci * to pull more data from it, then it'll be safe to flush 14668c2ecf20Sopenharmony_ci * current RX DMA state iff any pending fifo transfer is done. 14678c2ecf20Sopenharmony_ci */ 14688c2ecf20Sopenharmony_ci 14698c2ecf20Sopenharmony_ci core_rxirq_disable(tibase, cppi_ch->index + 1); 14708c2ecf20Sopenharmony_ci 14718c2ecf20Sopenharmony_ci /* for host, ensure ReqPkt is never set again */ 14728c2ecf20Sopenharmony_ci if (is_host_active(cppi_ch->controller->controller.musb)) { 14738c2ecf20Sopenharmony_ci value = musb_readl(tibase, DAVINCI_AUTOREQ_REG); 14748c2ecf20Sopenharmony_ci value &= ~((0x3) << (cppi_ch->index * 2)); 14758c2ecf20Sopenharmony_ci musb_writel(tibase, DAVINCI_AUTOREQ_REG, value); 14768c2ecf20Sopenharmony_ci } 14778c2ecf20Sopenharmony_ci 14788c2ecf20Sopenharmony_ci csr = musb_readw(regs, MUSB_RXCSR); 14798c2ecf20Sopenharmony_ci 14808c2ecf20Sopenharmony_ci /* for host, clear (just) ReqPkt at end of current packet(s) */ 14818c2ecf20Sopenharmony_ci if (is_host_active(cppi_ch->controller->controller.musb)) { 14828c2ecf20Sopenharmony_ci csr |= MUSB_RXCSR_H_WZC_BITS; 14838c2ecf20Sopenharmony_ci csr &= ~MUSB_RXCSR_H_REQPKT; 14848c2ecf20Sopenharmony_ci } else 14858c2ecf20Sopenharmony_ci csr |= MUSB_RXCSR_P_WZC_BITS; 14868c2ecf20Sopenharmony_ci 14878c2ecf20Sopenharmony_ci /* clear dma enable */ 14888c2ecf20Sopenharmony_ci csr &= ~(MUSB_RXCSR_DMAENAB); 14898c2ecf20Sopenharmony_ci musb_writew(regs, MUSB_RXCSR, csr); 14908c2ecf20Sopenharmony_ci csr = musb_readw(regs, MUSB_RXCSR); 14918c2ecf20Sopenharmony_ci 14928c2ecf20Sopenharmony_ci /* Quiesce: wait for current dma to finish (if not cleanup). 14938c2ecf20Sopenharmony_ci * We can't use bit zero of stateram->rx_sop, since that 14948c2ecf20Sopenharmony_ci * refers to an entire "DMA packet" not just emptying the 14958c2ecf20Sopenharmony_ci * current fifo. Most segments need multiple usb packets. 14968c2ecf20Sopenharmony_ci */ 14978c2ecf20Sopenharmony_ci if (channel->status == MUSB_DMA_STATUS_BUSY) 14988c2ecf20Sopenharmony_ci udelay(50); 14998c2ecf20Sopenharmony_ci 15008c2ecf20Sopenharmony_ci /* scan the current list, reporting any data that was 15018c2ecf20Sopenharmony_ci * transferred and acking any IRQ 15028c2ecf20Sopenharmony_ci */ 15038c2ecf20Sopenharmony_ci cppi_rx_scan(controller, cppi_ch->index); 15048c2ecf20Sopenharmony_ci 15058c2ecf20Sopenharmony_ci /* clobber the existing state once it's idle 15068c2ecf20Sopenharmony_ci * 15078c2ecf20Sopenharmony_ci * NOTE: arguably, we should also wait for all the other 15088c2ecf20Sopenharmony_ci * RX channels to quiesce (how??) and then temporarily 15098c2ecf20Sopenharmony_ci * disable RXCPPI_CTRL_REG ... but it seems that we can 15108c2ecf20Sopenharmony_ci * rely on the controller restarting from state ram, with 15118c2ecf20Sopenharmony_ci * only RXCPPI_BUFCNT state being bogus. BUFCNT will 15128c2ecf20Sopenharmony_ci * correct itself after the next DMA transfer though. 15138c2ecf20Sopenharmony_ci * 15148c2ecf20Sopenharmony_ci * REVISIT does using rndis mode change that? 15158c2ecf20Sopenharmony_ci */ 15168c2ecf20Sopenharmony_ci cppi_reset_rx(cppi_ch->state_ram); 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_ci /* next DMA request _should_ load cppi head ptr */ 15198c2ecf20Sopenharmony_ci 15208c2ecf20Sopenharmony_ci /* ... we don't "free" that list, only mutate it in place. */ 15218c2ecf20Sopenharmony_ci cppi_dump_rx(5, cppi_ch, " (done abort)"); 15228c2ecf20Sopenharmony_ci 15238c2ecf20Sopenharmony_ci /* clean up previously pending bds */ 15248c2ecf20Sopenharmony_ci cppi_bd_free(cppi_ch, cppi_ch->last_processed); 15258c2ecf20Sopenharmony_ci cppi_ch->last_processed = NULL; 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_ci while (queue) { 15288c2ecf20Sopenharmony_ci struct cppi_descriptor *tmp = queue->next; 15298c2ecf20Sopenharmony_ci 15308c2ecf20Sopenharmony_ci cppi_bd_free(cppi_ch, queue); 15318c2ecf20Sopenharmony_ci queue = tmp; 15328c2ecf20Sopenharmony_ci } 15338c2ecf20Sopenharmony_ci } 15348c2ecf20Sopenharmony_ci 15358c2ecf20Sopenharmony_ci channel->status = MUSB_DMA_STATUS_FREE; 15368c2ecf20Sopenharmony_ci cppi_ch->buf_dma = 0; 15378c2ecf20Sopenharmony_ci cppi_ch->offset = 0; 15388c2ecf20Sopenharmony_ci cppi_ch->buf_len = 0; 15398c2ecf20Sopenharmony_ci cppi_ch->maxpacket = 0; 15408c2ecf20Sopenharmony_ci return 0; 15418c2ecf20Sopenharmony_ci} 15428c2ecf20Sopenharmony_ci 15438c2ecf20Sopenharmony_ci/* TBD Queries: 15448c2ecf20Sopenharmony_ci * 15458c2ecf20Sopenharmony_ci * Power Management ... probably turn off cppi during suspend, restart; 15468c2ecf20Sopenharmony_ci * check state ram? Clocking is presumably shared with usb core. 15478c2ecf20Sopenharmony_ci */ 1548