From 7df95299b94a63ec67a6389fc02dc25019a80ee8 Mon Sep 17 00:00:00 2001 From: Matt Sickler Date: Mon, 22 Apr 2019 22:05:58 +0000 Subject: staging: kpc2000: Add DMA driver Add Daktronics DMA driver. I've added the SPDX license identifiers, Kconfig entry, and cleaned up as many of the warnings as I could. The AIO support code will be removed in a future patch. Signed-off-by: Matt Sickler Signed-off-by: Greg Kroah-Hartman --- drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.h | 220 +++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.h (limited to 'drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.h') diff --git a/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.h b/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.h new file mode 100644 index 000000000000..ef913b7496e6 --- /dev/null +++ b/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.h @@ -0,0 +1,220 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#ifndef KPC_DMA_DRIVER_H +#define KPC_DMA_DRIVER_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../kpc.h" + + +struct kp2000_device; +struct kpc_dma_device { + struct list_head list; + struct platform_device *pldev; + u32 __iomem *eng_regs; + struct device *kpc_dma_dev; + struct kobject kobj; + char name[16]; + + int dir; // DMA_FROM_DEVICE || DMA_TO_DEVICE + struct mutex sem; + unsigned int irq; + struct work_struct irq_work; + + atomic_t open_count; + + size_t accumulated_bytes; + u32 accumulated_flags; + + // Descriptor "Pool" housekeeping + u32 desc_pool_cnt; + struct dma_pool *desc_pool; + struct kpc_dma_descriptor *desc_pool_first; + struct kpc_dma_descriptor *desc_pool_last; + + struct kpc_dma_descriptor *desc_next; + struct kpc_dma_descriptor *desc_completed; +}; + +struct dev_private_data { + struct kpc_dma_device *ldev; + u64 card_addr; + u64 user_ctl; + u64 user_ctl_last; + u64 user_sts; +}; + +struct kpc_dma_device * kpc_dma_lookup_device(int minor); + +extern struct file_operations kpc_dma_fops; + +#define ENG_CAP_PRESENT 0x00000001 +#define ENG_CAP_DIRECTION 0x00000002 +#define ENG_CAP_TYPE_MASK 0x000000F0 +#define ENG_CAP_NUMBER_MASK 0x0000FF00 +#define ENG_CAP_CARD_ADDR_SIZE_MASK 0x007F0000 +#define ENG_CAP_DESC_MAX_BYTE_CNT_MASK 0x3F000000 +#define ENG_CAP_PERF_SCALE_MASK 0xC0000000 + +#define ENG_CTL_IRQ_ENABLE BIT(0) +#define ENG_CTL_IRQ_ACTIVE BIT(1) +#define ENG_CTL_DESC_COMPLETE BIT(2) +#define ENG_CTL_DESC_ALIGN_ERR BIT(3) +#define ENG_CTL_DESC_FETCH_ERR BIT(4) +#define ENG_CTL_SW_ABORT_ERR BIT(5) +#define ENG_CTL_DESC_CHAIN_END BIT(7) +#define ENG_CTL_DMA_ENABLE BIT(8) +#define ENG_CTL_DMA_RUNNING BIT(10) +#define ENG_CTL_DMA_WAITING BIT(11) +#define ENG_CTL_DMA_WAITING_PERSIST BIT(12) +#define ENG_CTL_DMA_RESET_REQUEST BIT(14) +#define ENG_CTL_DMA_RESET BIT(15) +#define ENG_CTL_DESC_FETCH_ERR_CLASS_MASK 0x700000 + +struct aio_cb_data { + struct dev_private_data *priv; + struct kpc_dma_device *ldev; + struct completion *cpl; + unsigned char flags; + struct kiocb *kcb; + size_t len; + + unsigned int page_count; + struct page **user_pages; + struct sg_table sgt; + int mapped_entry_count; +}; + +#define ACD_FLAG_DONE 0 +#define ACD_FLAG_ABORT 1 +#define ACD_FLAG_ENG_ACCUM_ERROR 4 +#define ACD_FLAG_ENG_ACCUM_SHORT 5 + +struct kpc_dma_descriptor { + struct { + volatile u32 DescByteCount :20; + volatile u32 DescStatusErrorFlags :4; + volatile u32 DescStatusFlags :8; + }; + volatile u32 DescUserControlLS; + volatile u32 DescUserControlMS; + volatile u32 DescCardAddrLS; + struct { + volatile u32 DescBufferByteCount :20; + volatile u32 DescCardAddrMS :4; + volatile u32 DescControlFlags :8; + }; + volatile u32 DescSystemAddrLS; + volatile u32 DescSystemAddrMS; + volatile u32 DescNextDescPtr; + + dma_addr_t MyDMAAddr; + struct kpc_dma_descriptor *Next; + + struct aio_cb_data *acd; +} __attribute__((packed)); +// DescControlFlags: +#define DMA_DESC_CTL_SOP BIT(7) +#define DMA_DESC_CTL_EOP BIT(6) +#define DMA_DESC_CTL_AFIFO BIT(2) +#define DMA_DESC_CTL_IRQONERR BIT(1) +#define DMA_DESC_CTL_IRQONDONE BIT(0) +// DescStatusFlags: +#define DMA_DESC_STS_SOP BIT(7) +#define DMA_DESC_STS_EOP BIT(6) +#define DMA_DESC_STS_ERROR BIT(4) +#define DMA_DESC_STS_USMSZ BIT(3) +#define DMA_DESC_STS_USLSZ BIT(2) +#define DMA_DESC_STS_SHORT BIT(1) +#define DMA_DESC_STS_COMPLETE BIT(0) +// DescStatusErrorFlags: +#define DMA_DESC_ESTS_ECRC BIT(2) +#define DMA_DESC_ESTS_POISON BIT(1) +#define DMA_DESC_ESTS_UNSUCCESSFUL BIT(0) + +#define DMA_DESC_ALIGNMENT 0x20 + +static inline +u32 GetEngineCapabilities(struct kpc_dma_device *eng) +{ + return readl(eng->eng_regs + 0); +} + +static inline +void WriteEngineControl(struct kpc_dma_device *eng, u32 value) +{ + writel(value, eng->eng_regs + 1); +} +static inline +u32 GetEngineControl(struct kpc_dma_device *eng) +{ + return readl(eng->eng_regs + 1); +} +static inline +void SetClearEngineControl(struct kpc_dma_device *eng, u32 set_bits, u32 clear_bits) +{ + u32 val = GetEngineControl(eng); + val |= set_bits; + val &= ~clear_bits; + WriteEngineControl(eng, val); +} + +static inline +void SetEngineNextPtr(struct kpc_dma_device *eng, struct kpc_dma_descriptor * desc) +{ + writel(desc->MyDMAAddr, eng->eng_regs + 2); +} +static inline +void SetEngineSWPtr(struct kpc_dma_device *eng, struct kpc_dma_descriptor * desc) +{ + writel(desc->MyDMAAddr, eng->eng_regs + 3); +} +static inline +void ClearEngineCompletePtr(struct kpc_dma_device *eng) +{ + writel(0, eng->eng_regs + 4); +} +static inline +u32 GetEngineCompletePtr(struct kpc_dma_device *eng) +{ + return readl(eng->eng_regs + 4); +} + +static inline +void lock_engine(struct kpc_dma_device *eng) +{ + BUG_ON(eng == NULL); + mutex_lock(&eng->sem); +} + +static inline +void unlock_engine(struct kpc_dma_device *eng) +{ + BUG_ON(eng == NULL); + mutex_unlock(&eng->sem); +} + + +/// Shared Functions +void start_dma_engine(struct kpc_dma_device *eng); +int setup_dma_engine(struct kpc_dma_device *eng, u32 desc_cnt); +void stop_dma_engine(struct kpc_dma_device *eng); +void destroy_dma_engine(struct kpc_dma_device *eng); +void clear_desc(struct kpc_dma_descriptor *desc); +int count_descriptors_available(struct kpc_dma_device *eng); +void transfer_complete_cb(struct aio_cb_data *acd, size_t xfr_count, u32 flags); + +#endif /* KPC_DMA_DRIVER_H */ + -- cgit v1.2.3-59-g8ed1b