aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.h
diff options
context:
space:
mode:
authorMatt Sickler <Matt.Sickler@daktronics.com>2019-04-22 22:05:58 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-04-25 12:07:33 +0200
commit7df95299b94a63ec67a6389fc02dc25019a80ee8 (patch)
tree921d3bd124d6a07ecc8457748fd5e8f5be63b612 /drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.h
parentStaging: vc04_services: Cleanup in ctrl_set_bitrate() (diff)
downloadlinux-dev-7df95299b94a63ec67a6389fc02dc25019a80ee8.tar.xz
linux-dev-7df95299b94a63ec67a6389fc02dc25019a80ee8.zip
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 <matt.sickler@daktronics.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to '')
-rw-r--r--drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.h220
1 files changed, 220 insertions, 0 deletions
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 <linux/platform_device.h>
+#include <linux/cdev.h>
+#include <linux/kfifo.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/miscdevice.h>
+#include <linux/rwsem.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/aio.h>
+#include <linux/bitops.h>
+#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 */
+