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