| /* 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); |
| mutex_lock(&eng->sem); |
| } |
| |
| static inline |
| void unlock_engine(struct kpc_dma_device *eng) |
| { |
| BUG_ON(!eng); |
| 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 */ |
| |