19cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/* 29cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * DMA driver for Xilinx Video DMA Engine 39cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 49cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Copyright (C) 2010-2014 Xilinx, Inc. All rights reserved. 59cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 69cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Based on the Freescale DMA driver. 79cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 89cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Description: 99cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * The AXI Video Direct Memory Access (AXI VDMA) core is a soft Xilinx IP 109cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * core that provides high-bandwidth direct memory access between memory 119cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * and AXI4-Stream type video target peripherals. The core provides efficient 129cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * two dimensional DMA operations with independent asynchronous read (S2MM) 139cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * and write (MM2S) channel operation. It can be configured to have either 149cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * one channel or two channels. If configured as two channels, one is to 159cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * transmit to the video device (MM2S) and another is to receive from the 169cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * video device (S2MM). Initialization, status, interrupt and management 179cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * registers are accessed through an AXI4-Lite slave interface. 189cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 199cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * This program is free software: you can redistribute it and/or modify 209cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * it under the terms of the GNU General Public License as published by 219cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * the Free Software Foundation, either version 2 of the License, or 229cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * (at your option) any later version. 239cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 249cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 259cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#include <linux/amba/xilinx_dma.h> 269cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#include <linux/bitops.h> 279cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#include <linux/dmapool.h> 289cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#include <linux/init.h> 299cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#include <linux/interrupt.h> 309cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#include <linux/io.h> 319cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#include <linux/module.h> 329cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#include <linux/of_address.h> 339cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#include <linux/of_dma.h> 349cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#include <linux/of_platform.h> 359cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#include <linux/of_irq.h> 369cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#include <linux/slab.h> 379cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 389cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#include "../dmaengine.h" 399cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 409cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/* Register/Descriptor Offsets */ 419cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_MM2S_CTRL_OFFSET 0x0000 429cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_S2MM_CTRL_OFFSET 0x0030 439cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_MM2S_DESC_OFFSET 0x0050 449cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_S2MM_DESC_OFFSET 0x00a0 459cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 469cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/* Control Registers */ 479cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_REG_DMACR 0x0000 489cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMACR_DELAY_MAX 0xff 499cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMACR_DELAY_SHIFT 24 509cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMACR_FRAME_COUNT_MAX 0xff 519cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMACR_FRAME_COUNT_SHIFT 16 529cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMACR_ERR_IRQ BIT(14) 539cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMACR_DLY_CNT_IRQ BIT(13) 549cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMACR_FRM_CNT_IRQ BIT(12) 559cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMACR_MASTER_SHIFT 8 569cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMACR_FSYNCSRC_SHIFT 5 579cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMACR_FRAMECNT_EN BIT(4) 589cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMACR_GENLOCK_EN BIT(3) 599cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMACR_RESET BIT(2) 609cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMACR_CIRC_EN BIT(1) 619cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMACR_RUNSTOP BIT(0) 629cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMACR_FSYNCSRC_MASK GENMASK(6, 5) 639cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 649cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_REG_DMASR 0x0004 659cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMASR_EOL_LATE_ERR BIT(15) 669cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMASR_ERR_IRQ BIT(14) 679cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMASR_DLY_CNT_IRQ BIT(13) 689cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMASR_FRM_CNT_IRQ BIT(12) 699cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMASR_SOF_LATE_ERR BIT(11) 709cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMASR_SG_DEC_ERR BIT(10) 719cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMASR_SG_SLV_ERR BIT(9) 729cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMASR_EOF_EARLY_ERR BIT(8) 739cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMASR_SOF_EARLY_ERR BIT(7) 749cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMASR_DMA_DEC_ERR BIT(6) 759cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMASR_DMA_SLAVE_ERR BIT(5) 769cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMASR_DMA_INT_ERR BIT(4) 779cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMASR_IDLE BIT(1) 789cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMASR_HALTED BIT(0) 799cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMASR_DELAY_MASK GENMASK(31, 24) 809cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMASR_FRAME_COUNT_MASK GENMASK(23, 16) 819cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 829cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_REG_CURDESC 0x0008 839cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_REG_TAILDESC 0x0010 849cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_REG_REG_INDEX 0x0014 859cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_REG_FRMSTORE 0x0018 869cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_REG_THRESHOLD 0x001c 879cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_REG_FRMPTR_STS 0x0024 889cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_REG_PARK_PTR 0x0028 899cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_PARK_PTR_WR_REF_SHIFT 8 909cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_PARK_PTR_RD_REF_SHIFT 0 919cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_REG_VDMA_VERSION 0x002c 929cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 939cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/* Register Direct Mode Registers */ 949cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_REG_VSIZE 0x0000 959cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_REG_HSIZE 0x0004 969cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 979cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_REG_FRMDLY_STRIDE 0x0008 989cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_FRMDLY_STRIDE_FRMDLY_SHIFT 24 999cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_FRMDLY_STRIDE_STRIDE_SHIFT 0 1009cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 1019cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_REG_START_ADDRESS(n) (0x000c + 4 * (n)) 1029cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 1039cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/* HW specific definitions */ 1049cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_MAX_CHANS_PER_DEVICE 0x2 1059cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 1069cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMAXR_ALL_IRQ_MASK \ 1079cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala (XILINX_VDMA_DMASR_FRM_CNT_IRQ | \ 1089cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMASR_DLY_CNT_IRQ | \ 1099cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMASR_ERR_IRQ) 1109cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 1119cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMASR_ALL_ERR_MASK \ 1129cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala (XILINX_VDMA_DMASR_EOL_LATE_ERR | \ 1139cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMASR_SOF_LATE_ERR | \ 1149cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMASR_SG_DEC_ERR | \ 1159cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMASR_SG_SLV_ERR | \ 1169cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMASR_EOF_EARLY_ERR | \ 1179cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMASR_SOF_EARLY_ERR | \ 1189cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMASR_DMA_DEC_ERR | \ 1199cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMASR_DMA_SLAVE_ERR | \ 1209cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMASR_DMA_INT_ERR) 1219cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 1229cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/* 1239cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Recoverable errors are DMA Internal error, SOF Early, EOF Early 1249cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * and SOF Late. They are only recoverable when C_FLUSH_ON_FSYNC 1259cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * is enabled in the h/w system. 1269cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 1279cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_DMASR_ERR_RECOVER_MASK \ 1289cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala (XILINX_VDMA_DMASR_SOF_LATE_ERR | \ 1299cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMASR_EOF_EARLY_ERR | \ 1309cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMASR_SOF_EARLY_ERR | \ 1319cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMASR_DMA_INT_ERR) 1329cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 1339cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/* Axi VDMA Flush on Fsync bits */ 1349cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_FLUSH_S2MM 3 1359cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_FLUSH_MM2S 2 1369cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_FLUSH_BOTH 1 1379cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 1389cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/* Delay loop counter to prevent hardware failure */ 1399cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define XILINX_VDMA_LOOP_COUNT 1000000 1409cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 1419cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 1429cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * struct xilinx_vdma_desc_hw - Hardware Descriptor 1439cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @next_desc: Next Descriptor Pointer @0x00 1449cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @pad1: Reserved @0x04 1459cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @buf_addr: Buffer address @0x08 1469cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @pad2: Reserved @0x0C 1479cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @vsize: Vertical Size @0x10 1489cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @hsize: Horizontal Size @0x14 1499cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @stride: Number of bytes between the first 1509cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * pixels of each horizontal line @0x18 1519cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 1529cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastruct xilinx_vdma_desc_hw { 1539cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala u32 next_desc; 1549cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala u32 pad1; 1559cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala u32 buf_addr; 1569cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala u32 pad2; 1579cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala u32 vsize; 1589cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala u32 hsize; 1599cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala u32 stride; 1609cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} __aligned(64); 1619cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 1629cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 1639cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * struct xilinx_vdma_tx_segment - Descriptor segment 1649cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @hw: Hardware descriptor 1659cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @node: Node in the descriptor segments list 1669cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @phys: Physical address of segment 1679cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 1689cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastruct xilinx_vdma_tx_segment { 1699cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_desc_hw hw; 1709cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct list_head node; 1719cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dma_addr_t phys; 1729cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} __aligned(64); 1739cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 1749cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 1759cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * struct xilinx_vdma_tx_descriptor - Per Transaction structure 1769cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @async_tx: Async transaction descriptor 1779cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @segments: TX segments list 1789cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @node: Node in the channel descriptors list 1799cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 1809cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastruct xilinx_vdma_tx_descriptor { 1819cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct dma_async_tx_descriptor async_tx; 1829cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct list_head segments; 1839cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct list_head node; 1849cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala}; 1859cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 1869cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 1879cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * struct xilinx_vdma_chan - Driver specific VDMA channel structure 1889cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @xdev: Driver specific device structure 1899cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @ctrl_offset: Control registers offset 1909cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @desc_offset: TX descriptor registers offset 1919cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @lock: Descriptor operation lock 1929cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @pending_list: Descriptors waiting 1939cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @active_desc: Active descriptor 1949cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @allocated_desc: Allocated descriptor 1959cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @done_list: Complete descriptors 1969cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @common: DMA common channel 1979cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @desc_pool: Descriptors pool 1989cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @dev: The dma device 1999cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @irq: Channel IRQ 2009cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @id: Channel ID 2019cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @direction: Transfer direction 2029cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @num_frms: Number of frames 2039cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @has_sg: Support scatter transfers 2049cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @genlock: Support genlock mode 2059cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @err: Channel has errors 2069cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @tasklet: Cleanup work after irq 2079cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @config: Device configuration info 2089cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @flush_on_fsync: Flush on Frame sync 2099cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 2109cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastruct xilinx_vdma_chan { 2119cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_device *xdev; 2129cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala u32 ctrl_offset; 2139cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala u32 desc_offset; 2149cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala spinlock_t lock; 2159cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct list_head pending_list; 2169cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_tx_descriptor *active_desc; 2179cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_tx_descriptor *allocated_desc; 2189cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct list_head done_list; 2199cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct dma_chan common; 2209cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct dma_pool *desc_pool; 2219cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct device *dev; 2229cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala int irq; 2239cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala int id; 2249cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala enum dma_transfer_direction direction; 2259cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala int num_frms; 2269cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala bool has_sg; 2279cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala bool genlock; 2289cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala bool err; 2299cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct tasklet_struct tasklet; 2309cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_config config; 2319cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala bool flush_on_fsync; 2329cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala}; 2339cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 2349cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 2359cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * struct xilinx_vdma_device - VDMA device structure 2369cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @regs: I/O mapped base address 2379cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @dev: Device Structure 2389cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @common: DMA device structure 2399cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @chan: Driver specific VDMA channel 2409cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @has_sg: Specifies whether Scatter-Gather is present or not 2419cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @flush_on_fsync: Flush on frame sync 2429cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 2439cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastruct xilinx_vdma_device { 2449cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala void __iomem *regs; 2459cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct device *dev; 2469cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct dma_device common; 2479cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_chan *chan[XILINX_VDMA_MAX_CHANS_PER_DEVICE]; 2489cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala bool has_sg; 2499cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala u32 flush_on_fsync; 2509cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala}; 2519cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 2529cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/* Macros */ 2539cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define to_xilinx_chan(chan) \ 2549cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala container_of(chan, struct xilinx_vdma_chan, common) 2559cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala#define to_vdma_tx_descriptor(tx) \ 2569cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala container_of(tx, struct xilinx_vdma_tx_descriptor, async_tx) 2579cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 2589cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/* IO accessors */ 2599cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic inline u32 vdma_read(struct xilinx_vdma_chan *chan, u32 reg) 2609cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 2619cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return ioread32(chan->xdev->regs + reg); 2629cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 2639cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 2649cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic inline void vdma_write(struct xilinx_vdma_chan *chan, u32 reg, u32 value) 2659cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 2669cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala iowrite32(value, chan->xdev->regs + reg); 2679cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 2689cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 2699cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic inline void vdma_desc_write(struct xilinx_vdma_chan *chan, u32 reg, 2709cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala u32 value) 2719cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 2729cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_write(chan, chan->desc_offset + reg, value); 2739cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 2749cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 2759cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic inline u32 vdma_ctrl_read(struct xilinx_vdma_chan *chan, u32 reg) 2769cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 2779cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return vdma_read(chan, chan->ctrl_offset + reg); 2789cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 2799cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 2809cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic inline void vdma_ctrl_write(struct xilinx_vdma_chan *chan, u32 reg, 2819cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala u32 value) 2829cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 2839cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_write(chan, chan->ctrl_offset + reg, value); 2849cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 2859cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 2869cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic inline void vdma_ctrl_clr(struct xilinx_vdma_chan *chan, u32 reg, 2879cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala u32 clr) 2889cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 2899cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_ctrl_write(chan, reg, vdma_ctrl_read(chan, reg) & ~clr); 2909cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 2919cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 2929cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic inline void vdma_ctrl_set(struct xilinx_vdma_chan *chan, u32 reg, 2939cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala u32 set) 2949cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 2959cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_ctrl_write(chan, reg, vdma_ctrl_read(chan, reg) | set); 2969cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 2979cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 2989cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/* ----------------------------------------------------------------------------- 2999cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Descriptors and segments alloc and free 3009cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 3019cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 3029cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 3039cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_alloc_tx_segment - Allocate transaction segment 3049cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @chan: Driver specific VDMA channel 3059cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 3069cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Return: The allocated segment on success and NULL on failure. 3079cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 3089cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic struct xilinx_vdma_tx_segment * 3099cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalaxilinx_vdma_alloc_tx_segment(struct xilinx_vdma_chan *chan) 3109cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 3119cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_tx_segment *segment; 3129cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dma_addr_t phys; 3139cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 3149cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala segment = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &phys); 3159cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (!segment) 3169cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return NULL; 3179cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 3189cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala memset(segment, 0, sizeof(*segment)); 3199cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala segment->phys = phys; 3209cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 3219cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return segment; 3229cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 3239cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 3249cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 3259cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_free_tx_segment - Free transaction segment 3269cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @chan: Driver specific VDMA channel 3279cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @segment: VDMA transaction segment 3289cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 3299cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic void xilinx_vdma_free_tx_segment(struct xilinx_vdma_chan *chan, 3309cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_tx_segment *segment) 3319cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 3329cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dma_pool_free(chan->desc_pool, segment, segment->phys); 3339cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 3349cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 3359cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 3369cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_tx_descriptor - Allocate transaction descriptor 3379cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @chan: Driver specific VDMA channel 3389cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 3399cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Return: The allocated descriptor on success and NULL on failure. 3409cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 3419cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic struct xilinx_vdma_tx_descriptor * 3429cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalaxilinx_vdma_alloc_tx_descriptor(struct xilinx_vdma_chan *chan) 3439cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 3449cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_tx_descriptor *desc; 3459cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala unsigned long flags; 3469cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 3479cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (chan->allocated_desc) 3489cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return chan->allocated_desc; 3499cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 3509cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala desc = kzalloc(sizeof(*desc), GFP_KERNEL); 3519cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (!desc) 3529cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return NULL; 3539cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 3549cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala spin_lock_irqsave(&chan->lock, flags); 3559cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->allocated_desc = desc; 3569cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala spin_unlock_irqrestore(&chan->lock, flags); 3579cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 3589cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala INIT_LIST_HEAD(&desc->segments); 3599cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 3609cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return desc; 3619cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 3629cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 3639cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 3649cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_free_tx_descriptor - Free transaction descriptor 3659cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @chan: Driver specific VDMA channel 3669cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @desc: VDMA transaction descriptor 3679cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 3689cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic void 3699cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalaxilinx_vdma_free_tx_descriptor(struct xilinx_vdma_chan *chan, 3709cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_tx_descriptor *desc) 3719cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 3729cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_tx_segment *segment, *next; 3739cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 3749cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (!desc) 3759cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return; 3769cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 3779cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala list_for_each_entry_safe(segment, next, &desc->segments, node) { 3789cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala list_del(&segment->node); 3799cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xilinx_vdma_free_tx_segment(chan, segment); 3809cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 3819cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 3829cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala kfree(desc); 3839cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 3849cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 3859cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/* Required functions */ 3869cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 3879cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 3889cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_free_desc_list - Free descriptors list 3899cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @chan: Driver specific VDMA channel 3909cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @list: List to parse and delete the descriptor 3919cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 3929cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic void xilinx_vdma_free_desc_list(struct xilinx_vdma_chan *chan, 3939cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct list_head *list) 3949cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 3959cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_tx_descriptor *desc, *next; 3969cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 3979cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala list_for_each_entry_safe(desc, next, list, node) { 3989cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala list_del(&desc->node); 3999cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xilinx_vdma_free_tx_descriptor(chan, desc); 4009cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 4019cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 4029cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 4039cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 4049cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_free_descriptors - Free channel descriptors 4059cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @chan: Driver specific VDMA channel 4069cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 4079cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic void xilinx_vdma_free_descriptors(struct xilinx_vdma_chan *chan) 4089cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 4099cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala unsigned long flags; 4109cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 4119cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala spin_lock_irqsave(&chan->lock, flags); 4129cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 4139cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xilinx_vdma_free_desc_list(chan, &chan->pending_list); 4149cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xilinx_vdma_free_desc_list(chan, &chan->done_list); 4159cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 4169cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xilinx_vdma_free_tx_descriptor(chan, chan->active_desc); 4179cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->active_desc = NULL; 4189cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 4199cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala spin_unlock_irqrestore(&chan->lock, flags); 4209cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 4219cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 4229cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 4239cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_free_chan_resources - Free channel resources 4249cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @dchan: DMA channel 4259cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 4269cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic void xilinx_vdma_free_chan_resources(struct dma_chan *dchan) 4279cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 4289cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan); 4299cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 4309cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dev_dbg(chan->dev, "Free all channel resources.\n"); 4319cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 4329cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xilinx_vdma_free_descriptors(chan); 4339cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dma_pool_destroy(chan->desc_pool); 4349cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->desc_pool = NULL; 4359cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 4369cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 4379cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 4389cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_chan_desc_cleanup - Clean channel descriptors 4399cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @chan: Driver specific VDMA channel 4409cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 4419cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic void xilinx_vdma_chan_desc_cleanup(struct xilinx_vdma_chan *chan) 4429cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 4439cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_tx_descriptor *desc, *next; 4449cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala unsigned long flags; 4459cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 4469cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala spin_lock_irqsave(&chan->lock, flags); 4479cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 4489cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala list_for_each_entry_safe(desc, next, &chan->done_list, node) { 4499cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dma_async_tx_callback callback; 4509cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala void *callback_param; 4519cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 4529cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Remove from the list of running transactions */ 4539cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala list_del(&desc->node); 4549cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 4559cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Run the link descriptor callback function */ 4569cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala callback = desc->async_tx.callback; 4579cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala callback_param = desc->async_tx.callback_param; 4589cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (callback) { 4599cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala spin_unlock_irqrestore(&chan->lock, flags); 4609cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala callback(callback_param); 4619cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala spin_lock_irqsave(&chan->lock, flags); 4629cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 4639cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 4649cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Run any dependencies, then free the descriptor */ 4659cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dma_run_dependencies(&desc->async_tx); 4669cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xilinx_vdma_free_tx_descriptor(chan, desc); 4679cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 4689cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 4699cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala spin_unlock_irqrestore(&chan->lock, flags); 4709cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 4719cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 4729cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 4739cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_do_tasklet - Schedule completion tasklet 4749cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @data: Pointer to the Xilinx VDMA channel structure 4759cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 4769cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic void xilinx_vdma_do_tasklet(unsigned long data) 4779cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 4789cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_chan *chan = (struct xilinx_vdma_chan *)data; 4799cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 4809cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xilinx_vdma_chan_desc_cleanup(chan); 4819cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 4829cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 4839cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 4849cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_alloc_chan_resources - Allocate channel resources 4859cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @dchan: DMA channel 4869cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 4879cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Return: '0' on success and failure value on error 4889cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 4899cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic int xilinx_vdma_alloc_chan_resources(struct dma_chan *dchan) 4909cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 4919cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan); 4929cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 4939cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Has this channel already been allocated? */ 4949cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (chan->desc_pool) 4959cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return 0; 4969cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 4979cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* 4989cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * We need the descriptor to be aligned to 64bytes 4999cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * for meeting Xilinx VDMA specification requirement. 5009cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 5019cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->desc_pool = dma_pool_create("xilinx_vdma_desc_pool", 5029cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->dev, 5039cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala sizeof(struct xilinx_vdma_tx_segment), 5049cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala __alignof__(struct xilinx_vdma_tx_segment), 0); 5059cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (!chan->desc_pool) { 5069cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dev_err(chan->dev, 5079cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala "unable to allocate channel %d descriptor pool\n", 5089cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->id); 5099cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return -ENOMEM; 5109cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 5119cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 5129cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dma_cookie_init(dchan); 5139cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return 0; 5149cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 5159cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 5169cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 5179cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_tx_status - Get VDMA transaction status 5189cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @dchan: DMA channel 5199cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @cookie: Transaction identifier 5209cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @txstate: Transaction state 5219cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 5229cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Return: DMA transaction status 5239cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 5249cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic enum dma_status xilinx_vdma_tx_status(struct dma_chan *dchan, 5259cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dma_cookie_t cookie, 5269cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct dma_tx_state *txstate) 5279cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 5289cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return dma_cookie_status(dchan, cookie, txstate); 5299cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 5309cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 5319cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 5329cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_is_running - Check if VDMA channel is running 5339cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @chan: Driver specific VDMA channel 5349cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 5359cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Return: '1' if running, '0' if not. 5369cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 5379cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic bool xilinx_vdma_is_running(struct xilinx_vdma_chan *chan) 5389cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 5399cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return !(vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR) & 5409cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMASR_HALTED) && 5419cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala (vdma_ctrl_read(chan, XILINX_VDMA_REG_DMACR) & 5429cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMACR_RUNSTOP); 5439cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 5449cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 5459cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 5469cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_is_idle - Check if VDMA channel is idle 5479cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @chan: Driver specific VDMA channel 5489cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 5499cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Return: '1' if idle, '0' if not. 5509cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 5519cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic bool xilinx_vdma_is_idle(struct xilinx_vdma_chan *chan) 5529cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 5539cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR) & 5549cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMASR_IDLE; 5559cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 5569cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 5579cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 5589cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_halt - Halt VDMA channel 5599cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @chan: Driver specific VDMA channel 5609cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 5619cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic void xilinx_vdma_halt(struct xilinx_vdma_chan *chan) 5629cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 5639cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala int loop = XILINX_VDMA_LOOP_COUNT; 5649cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 5659cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_ctrl_clr(chan, XILINX_VDMA_REG_DMACR, XILINX_VDMA_DMACR_RUNSTOP); 5669cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 5679cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Wait for the hardware to halt */ 5689cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala do { 5699cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR) & 5709cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMASR_HALTED) 5719cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala break; 5729cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } while (loop--); 5739cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 5749cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (!loop) { 5759cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dev_err(chan->dev, "Cannot stop channel %p: %x\n", 5769cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan, vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR)); 5779cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->err = true; 5789cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 5799cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 5809cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return; 5819cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 5829cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 5839cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 5849cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_start - Start VDMA channel 5859cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @chan: Driver specific VDMA channel 5869cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 5879cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic void xilinx_vdma_start(struct xilinx_vdma_chan *chan) 5889cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 5899cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala int loop = XILINX_VDMA_LOOP_COUNT; 5909cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 5919cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_ctrl_set(chan, XILINX_VDMA_REG_DMACR, XILINX_VDMA_DMACR_RUNSTOP); 5929cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 5939cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Wait for the hardware to start */ 5949cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala do { 5959cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (!(vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR) & 5969cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMASR_HALTED)) 5979cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala break; 5989cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } while (loop--); 5999cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 6009cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (!loop) { 6019cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dev_err(chan->dev, "Cannot start channel %p: %x\n", 6029cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan, vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR)); 6039cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 6049cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->err = true; 6059cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 6069cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 6079cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return; 6089cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 6099cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 6109cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 6119cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_start_transfer - Starts VDMA transfer 6129cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @chan: Driver specific channel struct pointer 6139cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 6149cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic void xilinx_vdma_start_transfer(struct xilinx_vdma_chan *chan) 6159cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 6169cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_config *config = &chan->config; 6179cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_tx_descriptor *desc; 6189cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala unsigned long flags; 6199cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala u32 reg; 6209cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_tx_segment *head, *tail = NULL; 6219cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 6229cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (chan->err) 6239cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return; 6249cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 6259cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala spin_lock_irqsave(&chan->lock, flags); 6269cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 6279cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* There's already an active descriptor, bail out. */ 6289cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (chan->active_desc) 6299cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala goto out_unlock; 6309cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 6319cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (list_empty(&chan->pending_list)) 6329cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala goto out_unlock; 6339cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 6349cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala desc = list_first_entry(&chan->pending_list, 6359cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_tx_descriptor, node); 6369cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 6379cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* If it is SG mode and hardware is busy, cannot submit */ 6389cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (chan->has_sg && xilinx_vdma_is_running(chan) && 6399cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala !xilinx_vdma_is_idle(chan)) { 6409cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dev_dbg(chan->dev, "DMA controller still busy\n"); 6419cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala goto out_unlock; 6429cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 6439cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 6449cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* 6459cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * If hardware is idle, then all descriptors on the running lists are 6469cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * done, start new transfers 6479cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 6489cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (chan->has_sg) { 6499cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala head = list_first_entry(&desc->segments, 6509cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_tx_segment, node); 6519cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala tail = list_entry(desc->segments.prev, 6529cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_tx_segment, node); 6539cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 6549cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_ctrl_write(chan, XILINX_VDMA_REG_CURDESC, head->phys); 6559cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 6569cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 6579cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Configure the hardware using info in the config structure */ 6589cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala reg = vdma_ctrl_read(chan, XILINX_VDMA_REG_DMACR); 6599cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 6609cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (config->frm_cnt_en) 6619cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala reg |= XILINX_VDMA_DMACR_FRAMECNT_EN; 6629cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala else 6639cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala reg &= ~XILINX_VDMA_DMACR_FRAMECNT_EN; 6649cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 6659cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* 6669cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * With SG, start with circular mode, so that BDs can be fetched. 6679cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * In direct register mode, if not parking, enable circular mode 6689cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 6699cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (chan->has_sg || !config->park) 6709cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala reg |= XILINX_VDMA_DMACR_CIRC_EN; 6719cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 6729cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (config->park) 6739cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala reg &= ~XILINX_VDMA_DMACR_CIRC_EN; 6749cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 6759cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_ctrl_write(chan, XILINX_VDMA_REG_DMACR, reg); 6769cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 6779cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (config->park && (config->park_frm >= 0) && 6789cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala (config->park_frm < chan->num_frms)) { 6799cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (chan->direction == DMA_MEM_TO_DEV) 6809cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_write(chan, XILINX_VDMA_REG_PARK_PTR, 6819cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala config->park_frm << 6829cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_PARK_PTR_RD_REF_SHIFT); 6839cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala else 6849cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_write(chan, XILINX_VDMA_REG_PARK_PTR, 6859cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala config->park_frm << 6869cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_PARK_PTR_WR_REF_SHIFT); 6879cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 6889cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 6899cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Start the hardware */ 6909cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xilinx_vdma_start(chan); 6919cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 6929cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (chan->err) 6939cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala goto out_unlock; 6949cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 6959cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Start the transfer */ 6969cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (chan->has_sg) { 6979cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_ctrl_write(chan, XILINX_VDMA_REG_TAILDESC, tail->phys); 6989cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } else { 6999cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_tx_segment *segment, *last = NULL; 7009cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala int i = 0; 7019cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 7029cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala list_for_each_entry(segment, &desc->segments, node) { 7039cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_desc_write(chan, 7049cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_REG_START_ADDRESS(i++), 7059cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala segment->hw.buf_addr); 7069cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala last = segment; 7079cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 7089cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 7099cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (!last) 7109cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala goto out_unlock; 7119cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 7129cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* HW expects these parameters to be same for one transaction */ 7139cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_desc_write(chan, XILINX_VDMA_REG_HSIZE, last->hw.hsize); 7149cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_desc_write(chan, XILINX_VDMA_REG_FRMDLY_STRIDE, 7159cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala last->hw.stride); 7169cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_desc_write(chan, XILINX_VDMA_REG_VSIZE, last->hw.vsize); 7179cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 7189cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 7199cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala list_del(&desc->node); 7209cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->active_desc = desc; 7219cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 7229cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalaout_unlock: 7239cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala spin_unlock_irqrestore(&chan->lock, flags); 7249cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 7259cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 7269cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 7279cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_issue_pending - Issue pending transactions 7289cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @dchan: DMA channel 7299cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 7309cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic void xilinx_vdma_issue_pending(struct dma_chan *dchan) 7319cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 7329cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan); 7339cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 7349cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xilinx_vdma_start_transfer(chan); 7359cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 7369cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 7379cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 7389cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_complete_descriptor - Mark the active descriptor as complete 7399cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @chan : xilinx DMA channel 7409cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 7419cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * CONTEXT: hardirq 7429cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 7439cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic void xilinx_vdma_complete_descriptor(struct xilinx_vdma_chan *chan) 7449cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 7459cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_tx_descriptor *desc; 7469cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala unsigned long flags; 7479cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 7489cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala spin_lock_irqsave(&chan->lock, flags); 7499cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 7509cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala desc = chan->active_desc; 7519cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (!desc) { 7529cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dev_dbg(chan->dev, "no running descriptors\n"); 7539cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala goto out_unlock; 7549cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 7559cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 7569cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dma_cookie_complete(&desc->async_tx); 7579cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala list_add_tail(&desc->node, &chan->done_list); 7589cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 7599cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->active_desc = NULL; 7609cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 7619cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalaout_unlock: 7629cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala spin_unlock_irqrestore(&chan->lock, flags); 7639cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 7649cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 7659cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 7669cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_reset - Reset VDMA channel 7679cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @chan: Driver specific VDMA channel 7689cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 7699cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Return: '0' on success and failure value on error 7709cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 7719cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic int xilinx_vdma_reset(struct xilinx_vdma_chan *chan) 7729cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 7739cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala int loop = XILINX_VDMA_LOOP_COUNT; 7749cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala u32 tmp; 7759cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 7769cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_ctrl_set(chan, XILINX_VDMA_REG_DMACR, XILINX_VDMA_DMACR_RESET); 7779cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 7789cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala tmp = vdma_ctrl_read(chan, XILINX_VDMA_REG_DMACR) & 7799cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMACR_RESET; 7809cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 7819cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Wait for the hardware to finish reset */ 7829cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala do { 7839cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala tmp = vdma_ctrl_read(chan, XILINX_VDMA_REG_DMACR) & 7849cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMACR_RESET; 7859cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } while (loop-- && tmp); 7869cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 7879cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (!loop) { 7889cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dev_err(chan->dev, "reset timeout, cr %x, sr %x\n", 7899cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_ctrl_read(chan, XILINX_VDMA_REG_DMACR), 7909cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR)); 7919cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return -ETIMEDOUT; 7929cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 7939cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 7949cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->err = false; 7959cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 7969cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return 0; 7979cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 7989cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 7999cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 8009cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_chan_reset - Reset VDMA channel and enable interrupts 8019cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @chan: Driver specific VDMA channel 8029cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 8039cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Return: '0' on success and failure value on error 8049cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 8059cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic int xilinx_vdma_chan_reset(struct xilinx_vdma_chan *chan) 8069cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 8079cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala int err; 8089cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 8099cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Reset VDMA */ 8109cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala err = xilinx_vdma_reset(chan); 8119cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (err) 8129cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return err; 8139cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 8149cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Enable interrupts */ 8159cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_ctrl_set(chan, XILINX_VDMA_REG_DMACR, 8169cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMAXR_ALL_IRQ_MASK); 8179cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 8189cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return 0; 8199cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 8209cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 8219cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 8229cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_irq_handler - VDMA Interrupt handler 8239cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @irq: IRQ number 8249cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @data: Pointer to the Xilinx VDMA channel structure 8259cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 8269cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Return: IRQ_HANDLED/IRQ_NONE 8279cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 8289cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic irqreturn_t xilinx_vdma_irq_handler(int irq, void *data) 8299cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 8309cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_chan *chan = data; 8319cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala u32 status; 8329cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 8339cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Read the status and ack the interrupts. */ 8349cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala status = vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR); 8359cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (!(status & XILINX_VDMA_DMAXR_ALL_IRQ_MASK)) 8369cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return IRQ_NONE; 8379cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 8389cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_ctrl_write(chan, XILINX_VDMA_REG_DMASR, 8399cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala status & XILINX_VDMA_DMAXR_ALL_IRQ_MASK); 8409cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 8419cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (status & XILINX_VDMA_DMASR_ERR_IRQ) { 8429cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* 8439cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * An error occurred. If C_FLUSH_ON_FSYNC is enabled and the 8449cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * error is recoverable, ignore it. Otherwise flag the error. 8459cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 8469cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Only recoverable errors can be cleared in the DMASR register, 8479cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * make sure not to write to other error bits to 1. 8489cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 8499cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala u32 errors = status & XILINX_VDMA_DMASR_ALL_ERR_MASK; 8509cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_ctrl_write(chan, XILINX_VDMA_REG_DMASR, 8519cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala errors & XILINX_VDMA_DMASR_ERR_RECOVER_MASK); 8529cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 8539cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (!chan->flush_on_fsync || 8549cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala (errors & ~XILINX_VDMA_DMASR_ERR_RECOVER_MASK)) { 8559cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dev_err(chan->dev, 8569cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala "Channel %p has errors %x, cdr %x tdr %x\n", 8579cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan, errors, 8589cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_ctrl_read(chan, XILINX_VDMA_REG_CURDESC), 8599cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_ctrl_read(chan, XILINX_VDMA_REG_TAILDESC)); 8609cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->err = true; 8619cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 8629cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 8639cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 8649cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (status & XILINX_VDMA_DMASR_DLY_CNT_IRQ) { 8659cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* 8669cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Device takes too long to do the transfer when user requires 8679cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * responsiveness. 8689cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 8699cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dev_dbg(chan->dev, "Inter-packet latency too long\n"); 8709cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 8719cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 8729cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (status & XILINX_VDMA_DMASR_FRM_CNT_IRQ) { 8739cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xilinx_vdma_complete_descriptor(chan); 8749cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xilinx_vdma_start_transfer(chan); 8759cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 8769cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 8779cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala tasklet_schedule(&chan->tasklet); 8789cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return IRQ_HANDLED; 8799cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 8809cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 8819cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 8829cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_tx_submit - Submit DMA transaction 8839cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @tx: Async transaction descriptor 8849cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 8859cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Return: cookie value on success and failure value on error 8869cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 8879cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic dma_cookie_t xilinx_vdma_tx_submit(struct dma_async_tx_descriptor *tx) 8889cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 8899cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_tx_descriptor *desc = to_vdma_tx_descriptor(tx); 8909cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_chan *chan = to_xilinx_chan(tx->chan); 8919cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dma_cookie_t cookie; 8929cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala unsigned long flags; 8939cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala int err; 8949cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 8959cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (chan->err) { 8969cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* 8979cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * If reset fails, need to hard reset the system. 8989cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Channel is no longer functional 8999cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 9009cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala err = xilinx_vdma_chan_reset(chan); 9019cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (err < 0) 9029cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return err; 9039cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 9049cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 9059cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala spin_lock_irqsave(&chan->lock, flags); 9069cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 9079cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala cookie = dma_cookie_assign(tx); 9089cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 9099cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Append the transaction to the pending transactions queue. */ 9109cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala list_add_tail(&desc->node, &chan->pending_list); 9119cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 9129cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Free the allocated desc */ 9139cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->allocated_desc = NULL; 9149cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 9159cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala spin_unlock_irqrestore(&chan->lock, flags); 9169cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 9179cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return cookie; 9189cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 9199cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 9209cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 9219cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_dma_prep_interleaved - prepare a descriptor for a 9229cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * DMA_SLAVE transaction 9239cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @dchan: DMA channel 9249cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @xt: Interleaved template pointer 9259cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @flags: transfer ack flags 9269cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 9279cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Return: Async transaction descriptor on success and NULL on failure 9289cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 9299cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic struct dma_async_tx_descriptor * 9309cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalaxilinx_vdma_dma_prep_interleaved(struct dma_chan *dchan, 9319cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct dma_interleaved_template *xt, 9329cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala unsigned long flags) 9339cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 9349cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan); 9359cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_tx_descriptor *desc; 9369cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_tx_segment *segment, *prev = NULL; 9379cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_desc_hw *hw; 9389cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 9399cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (!is_slave_direction(xt->dir)) 9409cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return NULL; 9419cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 9429cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (!xt->numf || !xt->sgl[0].size) 9439cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return NULL; 9449cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 9459cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Allocate a transaction descriptor. */ 9469cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala desc = xilinx_vdma_alloc_tx_descriptor(chan); 9479cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (!desc) 9489cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return NULL; 9499cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 9509cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dma_async_tx_descriptor_init(&desc->async_tx, &chan->common); 9519cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala desc->async_tx.tx_submit = xilinx_vdma_tx_submit; 9529cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala async_tx_ack(&desc->async_tx); 9539cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 9549cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Allocate the link descriptor from DMA pool */ 9559cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala segment = xilinx_vdma_alloc_tx_segment(chan); 9569cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (!segment) 9579cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala goto error; 9589cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 9599cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Fill in the hardware descriptor */ 9609cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala hw = &segment->hw; 9619cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala hw->vsize = xt->numf; 9629cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala hw->hsize = xt->sgl[0].size; 9639cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala hw->stride = xt->sgl[0].icg << 9649cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_FRMDLY_STRIDE_STRIDE_SHIFT; 9659cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala hw->stride |= chan->config.frm_dly << 9669cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_FRMDLY_STRIDE_FRMDLY_SHIFT; 9679cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 9689cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (xt->dir != DMA_MEM_TO_DEV) 9699cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala hw->buf_addr = xt->dst_start; 9709cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala else 9719cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala hw->buf_addr = xt->src_start; 9729cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 9739cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Link the previous next descriptor to current */ 9749cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala prev = list_last_entry(&desc->segments, 9759cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_tx_segment, node); 9769cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala prev->hw.next_desc = segment->phys; 9779cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 9789cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Insert the segment into the descriptor segments list. */ 9799cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala list_add_tail(&segment->node, &desc->segments); 9809cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 9819cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala prev = segment; 9829cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 9839cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Link the last hardware descriptor with the first. */ 9849cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala segment = list_first_entry(&desc->segments, 9859cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_tx_segment, node); 9869cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala prev->hw.next_desc = segment->phys; 9879cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 9889cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return &desc->async_tx; 9899cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 9909cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalaerror: 9919cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xilinx_vdma_free_tx_descriptor(chan, desc); 9929cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return NULL; 9939cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 9949cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 9959cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 9969cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_terminate_all - Halt the channel and free descriptors 9979cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @chan: Driver specific VDMA Channel pointer 9989cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 9999cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic void xilinx_vdma_terminate_all(struct xilinx_vdma_chan *chan) 10009cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 10019cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Halt the DMA engine */ 10029cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xilinx_vdma_halt(chan); 10039cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 10049cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Remove and free all of the descriptors in the lists */ 10059cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xilinx_vdma_free_descriptors(chan); 10069cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 10079cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 10089cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 10099cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_channel_set_config - Configure VDMA channel 10109cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Run-time configuration for Axi VDMA, supports: 10119cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * . halt the channel 10129cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * . configure interrupt coalescing and inter-packet delay threshold 10139cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * . start/stop parking 10149cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * . enable genlock 10159cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 10169cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @dchan: DMA channel 10179cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @cfg: VDMA device configuration pointer 10189cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 10199cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Return: '0' on success and failure value on error 10209cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 10219cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalaint xilinx_vdma_channel_set_config(struct dma_chan *dchan, 10229cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_config *cfg) 10239cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 10249cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan); 10259cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala u32 dmacr; 10269cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 10279cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (cfg->reset) 10289cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return xilinx_vdma_chan_reset(chan); 10299cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 10309cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dmacr = vdma_ctrl_read(chan, XILINX_VDMA_REG_DMACR); 10319cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 10329cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->config.frm_dly = cfg->frm_dly; 10339cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->config.park = cfg->park; 10349cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 10359cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* genlock settings */ 10369cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->config.gen_lock = cfg->gen_lock; 10379cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->config.master = cfg->master; 10389cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 10399cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (cfg->gen_lock && chan->genlock) { 10409cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dmacr |= XILINX_VDMA_DMACR_GENLOCK_EN; 10419cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dmacr |= cfg->master << XILINX_VDMA_DMACR_MASTER_SHIFT; 10429cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 10439cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 10449cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->config.frm_cnt_en = cfg->frm_cnt_en; 10459cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (cfg->park) 10469cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->config.park_frm = cfg->park_frm; 10479cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala else 10489cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->config.park_frm = -1; 10499cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 10509cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->config.coalesc = cfg->coalesc; 10519cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->config.delay = cfg->delay; 10529cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 10539cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (cfg->coalesc <= XILINX_VDMA_DMACR_FRAME_COUNT_MAX) { 10549cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dmacr |= cfg->coalesc << XILINX_VDMA_DMACR_FRAME_COUNT_SHIFT; 10559cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->config.coalesc = cfg->coalesc; 10569cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 10579cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 10589cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (cfg->delay <= XILINX_VDMA_DMACR_DELAY_MAX) { 10599cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dmacr |= cfg->delay << XILINX_VDMA_DMACR_DELAY_SHIFT; 10609cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->config.delay = cfg->delay; 10619cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 10629cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 10639cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* FSync Source selection */ 10649cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dmacr &= ~XILINX_VDMA_DMACR_FSYNCSRC_MASK; 10659cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dmacr |= cfg->ext_fsync << XILINX_VDMA_DMACR_FSYNCSRC_SHIFT; 10669cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 10679cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_ctrl_write(chan, XILINX_VDMA_REG_DMACR, dmacr); 10689cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 10699cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return 0; 10709cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 10719cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth ThokalaEXPORT_SYMBOL(xilinx_vdma_channel_set_config); 10729cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 10739cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 10749cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_device_control - Configure DMA channel of the device 10759cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @dchan: DMA Channel pointer 10769cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @cmd: DMA control command 10779cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @arg: Channel configuration 10789cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 10799cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Return: '0' on success and failure value on error 10809cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 10819cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic int xilinx_vdma_device_control(struct dma_chan *dchan, 10829cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala enum dma_ctrl_cmd cmd, unsigned long arg) 10839cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 10849cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan); 10859cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 10869cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (cmd != DMA_TERMINATE_ALL) 10879cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return -ENXIO; 10889cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 10899cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xilinx_vdma_terminate_all(chan); 10909cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 10919cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return 0; 10929cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 10939cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 10949cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/* ----------------------------------------------------------------------------- 10959cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Probe and remove 10969cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 10979cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 10989cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 10999cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_chan_remove - Per Channel remove function 11009cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @chan: Driver specific VDMA channel 11019cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 11029cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic void xilinx_vdma_chan_remove(struct xilinx_vdma_chan *chan) 11039cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 11049cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Disable all interrupts */ 11059cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala vdma_ctrl_clr(chan, XILINX_VDMA_REG_DMACR, 11069cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala XILINX_VDMA_DMAXR_ALL_IRQ_MASK); 11079cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 11089cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (chan->irq > 0) 11099cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala free_irq(chan->irq, chan); 11109cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 11119cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala tasklet_kill(&chan->tasklet); 11129cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 11139cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala list_del(&chan->common.device_node); 11149cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 11159cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 11169cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 11179cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_chan_probe - Per Channel Probing 11189cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * It get channel features from the device tree entry and 11199cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * initialize special channel handling routines 11209cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 11219cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @xdev: Driver specific device structure 11229cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @node: Device node 11239cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 11249cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Return: '0' on success and failure value on error 11259cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 11269cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic int xilinx_vdma_chan_probe(struct xilinx_vdma_device *xdev, 11279cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct device_node *node) 11289cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 11299cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_chan *chan; 11309cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala bool has_dre = false; 11319cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala u32 value, width; 11329cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala int err; 11339cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 11349cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Allocate and initialize the channel structure */ 11359cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan = devm_kzalloc(xdev->dev, sizeof(*chan), GFP_KERNEL); 11369cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (!chan) 11379cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return -ENOMEM; 11389cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 11399cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->dev = xdev->dev; 11409cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->xdev = xdev; 11419cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->has_sg = xdev->has_sg; 11429cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 11439cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala spin_lock_init(&chan->lock); 11449cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala INIT_LIST_HEAD(&chan->pending_list); 11459cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala INIT_LIST_HEAD(&chan->done_list); 11469cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 11479cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Retrieve the channel properties from the device tree */ 11489cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala has_dre = of_property_read_bool(node, "xlnx,include-dre"); 11499cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 11509cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->genlock = of_property_read_bool(node, "xlnx,genlock-mode"); 11519cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 11529cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala err = of_property_read_u32(node, "xlnx,datawidth", &value); 11539cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (err) { 11549cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dev_err(xdev->dev, "missing xlnx,datawidth property\n"); 11559cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return err; 11569cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 11579cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala width = value >> 3; /* Convert bits to bytes */ 11589cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 11599cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* If data width is greater than 8 bytes, DRE is not in hw */ 11609cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (width > 8) 11619cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala has_dre = false; 11629cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 11639cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (!has_dre) 11649cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xdev->common.copy_align = fls(width - 1); 11659cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 11669cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (of_device_is_compatible(node, "xlnx,axi-vdma-mm2s-channel")) { 11679cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->direction = DMA_MEM_TO_DEV; 11689cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->id = 0; 11699cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 11709cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->ctrl_offset = XILINX_VDMA_MM2S_CTRL_OFFSET; 11719cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->desc_offset = XILINX_VDMA_MM2S_DESC_OFFSET; 11729cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 11739cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (xdev->flush_on_fsync == XILINX_VDMA_FLUSH_BOTH || 11749cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xdev->flush_on_fsync == XILINX_VDMA_FLUSH_MM2S) 11759cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->flush_on_fsync = true; 11769cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } else if (of_device_is_compatible(node, 11779cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala "xlnx,axi-vdma-s2mm-channel")) { 11789cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->direction = DMA_DEV_TO_MEM; 11799cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->id = 1; 11809cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 11819cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->ctrl_offset = XILINX_VDMA_S2MM_CTRL_OFFSET; 11829cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->desc_offset = XILINX_VDMA_S2MM_DESC_OFFSET; 11839cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 11849cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (xdev->flush_on_fsync == XILINX_VDMA_FLUSH_BOTH || 11859cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xdev->flush_on_fsync == XILINX_VDMA_FLUSH_S2MM) 11869cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->flush_on_fsync = true; 11879cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } else { 11889cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dev_err(xdev->dev, "Invalid channel compatible node\n"); 11899cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return -EINVAL; 11909cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 11919cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 11929cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Request the interrupt */ 11939cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->irq = irq_of_parse_and_map(node, 0); 11949cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala err = request_irq(chan->irq, xilinx_vdma_irq_handler, IRQF_SHARED, 11959cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala "xilinx-vdma-controller", chan); 11969cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (err) { 11979cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dev_err(xdev->dev, "unable to request IRQ %d\n", chan->irq); 11989cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return err; 11999cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 12009cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 12019cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Initialize the tasklet */ 12029cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala tasklet_init(&chan->tasklet, xilinx_vdma_do_tasklet, 12039cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala (unsigned long)chan); 12049cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 12059cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* 12069cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Initialize the DMA channel and add it to the DMA engine channels 12079cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * list. 12089cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 12099cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala chan->common.device = &xdev->common; 12109cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 12119cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala list_add_tail(&chan->common.device_node, &xdev->common.channels); 12129cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xdev->chan[chan->id] = chan; 12139cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 12149cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Reset the channel */ 12159cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala err = xilinx_vdma_chan_reset(chan); 12169cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (err < 0) { 12179cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dev_err(xdev->dev, "Reset channel failed\n"); 12189cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return err; 12199cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 12209cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 12219cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return 0; 12229cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 12239cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 12249cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 12259cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * of_dma_xilinx_xlate - Translation function 12269cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @dma_spec: Pointer to DMA specifier as found in the device tree 12279cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @ofdma: Pointer to DMA controller data 12289cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 12299cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Return: DMA channel pointer on success and NULL on error 12309cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 12319cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic struct dma_chan *of_dma_xilinx_xlate(struct of_phandle_args *dma_spec, 12329cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct of_dma *ofdma) 12339cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 12349cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_device *xdev = ofdma->of_dma_data; 12359cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala int chan_id = dma_spec->args[0]; 12369cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 12379cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (chan_id >= XILINX_VDMA_MAX_CHANS_PER_DEVICE) 12389cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return NULL; 12399cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 12409cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return dma_get_slave_channel(&xdev->chan[chan_id]->common); 12419cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 12429cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 12439cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 12449cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_probe - Driver probe function 12459cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @pdev: Pointer to the platform_device structure 12469cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 12479cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Return: '0' on success and failure value on error 12489cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 12499cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic int xilinx_vdma_probe(struct platform_device *pdev) 12509cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 12519cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct device_node *node = pdev->dev.of_node; 12529cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_device *xdev; 12539cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct device_node *child; 12549cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct resource *io; 12559cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala u32 num_frames; 12569cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala int i, err; 12579cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 12589cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Allocate and initialize the DMA engine structure */ 12599cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL); 12609cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (!xdev) 12619cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return -ENOMEM; 12629cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 12639cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xdev->dev = &pdev->dev; 12649cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 12659cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Request and map I/O memory */ 12669cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala io = platform_get_resource(pdev, IORESOURCE_MEM, 0); 12679cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xdev->regs = devm_ioremap_resource(&pdev->dev, io); 12689cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (IS_ERR(xdev->regs)) 12699cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return PTR_ERR(xdev->regs); 12709cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 12719cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Retrieve the DMA engine properties from the device tree */ 12729cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xdev->has_sg = of_property_read_bool(node, "xlnx,include-sg"); 12739cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 12749cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala err = of_property_read_u32(node, "xlnx,num-fstores", &num_frames); 12759cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (err < 0) { 12769cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dev_err(xdev->dev, "missing xlnx,num-fstores property\n"); 12779cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return err; 12789cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 12799cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 12809cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala err = of_property_read_u32(node, "xlnx,flush-fsync", 12819cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala &xdev->flush_on_fsync); 12829cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (err < 0) 12839cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dev_warn(xdev->dev, "missing xlnx,flush-fsync property\n"); 12849cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 12859cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Initialize the DMA engine */ 12869cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xdev->common.dev = &pdev->dev; 12879cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 12889cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala INIT_LIST_HEAD(&xdev->common.channels); 12899cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dma_cap_set(DMA_SLAVE, xdev->common.cap_mask); 12909cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dma_cap_set(DMA_PRIVATE, xdev->common.cap_mask); 12919cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 12929cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xdev->common.device_alloc_chan_resources = 12939cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xilinx_vdma_alloc_chan_resources; 12949cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xdev->common.device_free_chan_resources = 12959cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xilinx_vdma_free_chan_resources; 12969cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xdev->common.device_prep_interleaved_dma = 12979cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xilinx_vdma_dma_prep_interleaved; 12989cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xdev->common.device_control = xilinx_vdma_device_control; 12999cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xdev->common.device_tx_status = xilinx_vdma_tx_status; 13009cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xdev->common.device_issue_pending = xilinx_vdma_issue_pending; 13019cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 13029cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala platform_set_drvdata(pdev, xdev); 13039cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 13049cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Initialize the channels */ 13059cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala for_each_child_of_node(node, child) { 13069cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala err = xilinx_vdma_chan_probe(xdev, child); 13079cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (err < 0) 13089cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala goto error; 13099cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 13109cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 13119cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala for (i = 0; i < XILINX_VDMA_MAX_CHANS_PER_DEVICE; i++) 13129cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (xdev->chan[i]) 13139cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xdev->chan[i]->num_frms = num_frames; 13149cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 13159cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala /* Register the DMA engine with the core */ 13169cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dma_async_device_register(&xdev->common); 13179cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 13189cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala err = of_dma_controller_register(node, of_dma_xilinx_xlate, 13199cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xdev); 13209cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (err < 0) { 13219cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dev_err(&pdev->dev, "Unable to register DMA to DT\n"); 13229cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dma_async_device_unregister(&xdev->common); 13239cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala goto error; 13249cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala } 13259cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 13269cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dev_info(&pdev->dev, "Xilinx AXI VDMA Engine Driver Probed!!\n"); 13279cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 13289cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return 0; 13299cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 13309cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalaerror: 13319cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala for (i = 0; i < XILINX_VDMA_MAX_CHANS_PER_DEVICE; i++) 13329cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (xdev->chan[i]) 13339cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xilinx_vdma_chan_remove(xdev->chan[i]); 13349cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 13359cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return err; 13369cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 13379cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 13389cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala/** 13399cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * xilinx_vdma_remove - Driver remove function 13409cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * @pdev: Pointer to the platform_device structure 13419cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * 13429cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala * Return: Always '0' 13439cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala */ 13449cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic int xilinx_vdma_remove(struct platform_device *pdev) 13459cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala{ 13469cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala struct xilinx_vdma_device *xdev = platform_get_drvdata(pdev); 13479cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala int i; 13489cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 13499cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala of_dma_controller_free(pdev->dev.of_node); 13509cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 13519cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala dma_async_device_unregister(&xdev->common); 13529cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 13539cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala for (i = 0; i < XILINX_VDMA_MAX_CHANS_PER_DEVICE; i++) 13549cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala if (xdev->chan[i]) 13559cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala xilinx_vdma_chan_remove(xdev->chan[i]); 13569cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 13579cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala return 0; 13589cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala} 13599cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 13609cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic const struct of_device_id xilinx_vdma_of_ids[] = { 13619cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala { .compatible = "xlnx,axi-vdma-1.00.a",}, 13629cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala {} 13639cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala}; 13649cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 13659cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalastatic struct platform_driver xilinx_vdma_driver = { 13669cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala .driver = { 13679cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala .name = "xilinx-vdma", 13689cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala .of_match_table = xilinx_vdma_of_ids, 13699cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala }, 13709cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala .probe = xilinx_vdma_probe, 13719cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala .remove = xilinx_vdma_remove, 13729cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala}; 13739cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 13749cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokalamodule_platform_driver(xilinx_vdma_driver); 13759cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth Thokala 13769cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth ThokalaMODULE_AUTHOR("Xilinx, Inc."); 13779cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth ThokalaMODULE_DESCRIPTION("Xilinx VDMA driver"); 13789cd4360de6090a6daf7fbe024e34953f2ae60ef2Srikanth ThokalaMODULE_LICENSE("GPL v2"); 1379