blob: 4c8cc866b826973ad02d7401ed6147d57455b7b5 [file] [log] [blame]
/* 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/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 const 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;
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 */