13d0407baSopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
23d0407baSopenharmony_ci/*
33d0407baSopenharmony_ci * Copyright (C) 2018 Rockchip Electronics Co., Ltd.
43d0407baSopenharmony_ci */
53d0407baSopenharmony_ci
63d0407baSopenharmony_ci#ifndef ROCKCHIP_PCIE_DMA_H
73d0407baSopenharmony_ci#define ROCKCHIP_PCIE_DMA_H
83d0407baSopenharmony_ci
93d0407baSopenharmony_ci#include <linux/debugfs.h>
103d0407baSopenharmony_ci
113d0407baSopenharmony_ci#define PCIE_DMA_TABLE_NUM 24
123d0407baSopenharmony_ci
133d0407baSopenharmony_ci#define PCIE_DMA_TRX_TYPE_NUM 3
143d0407baSopenharmony_ci
153d0407baSopenharmony_ci#define PCIE_DMA_CHN0 0x0
163d0407baSopenharmony_ci
173d0407baSopenharmony_ci#define PCIE_DMA_DATA_SND_TABLE_OFFSET 0x0
183d0407baSopenharmony_ci#define PCIE_DMA_DATA_RCV_ACK_TABLE_OFFSET 0x8
193d0407baSopenharmony_ci#define PCIE_DMA_DATA_FREE_ACK_TABLE_OFFSET 0x10
203d0407baSopenharmony_ci
213d0407baSopenharmony_cienum dma_dir {
223d0407baSopenharmony_ci    DMA_FROM_BUS,
233d0407baSopenharmony_ci    DMA_TO_BUS,
243d0407baSopenharmony_ci};
253d0407baSopenharmony_ci
263d0407baSopenharmony_ci/**
273d0407baSopenharmony_ci * The Channel Control Register for read and write.
283d0407baSopenharmony_ci */
293d0407baSopenharmony_ciunion chan_ctrl_lo {
303d0407baSopenharmony_ci    struct {
313d0407baSopenharmony_ci        u32 cb : 1;    // 0
323d0407baSopenharmony_ci        u32 tcb : 1;   // 1
333d0407baSopenharmony_ci        u32 llp : 1;   // 2
343d0407baSopenharmony_ci        u32 lie : 1;   // 3
353d0407baSopenharmony_ci        u32 rie : 1;   // 4
363d0407baSopenharmony_ci        u32 cs : 2;    // 5:6
373d0407baSopenharmony_ci        u32 rsvd1 : 1; // 7
383d0407baSopenharmony_ci        u32 ccs : 1;   // 8
393d0407baSopenharmony_ci        u32 llen : 1;  // 9
403d0407baSopenharmony_ci        u32 b_64s : 1; // 10
413d0407baSopenharmony_ci        u32 b_64d : 1; // 11
423d0407baSopenharmony_ci        u32 pf : 5;    // 12:16
433d0407baSopenharmony_ci        u32 rsvd2 : 7; // 17:23
443d0407baSopenharmony_ci        u32 sn : 1;    // 24
453d0407baSopenharmony_ci        u32 ro : 1;    // 25
463d0407baSopenharmony_ci        u32 td : 1;    // 26
473d0407baSopenharmony_ci        u32 tc : 3;    // 27:29
483d0407baSopenharmony_ci        u32 at : 2;    // 30:31
493d0407baSopenharmony_ci    };
503d0407baSopenharmony_ci    u32 asdword;
513d0407baSopenharmony_ci};
523d0407baSopenharmony_ci
533d0407baSopenharmony_ci/**
543d0407baSopenharmony_ci * The Channel Control Register high part for read and write.
553d0407baSopenharmony_ci */
563d0407baSopenharmony_ciunion chan_ctrl_hi {
573d0407baSopenharmony_ci    struct {
583d0407baSopenharmony_ci        u32 vfenb : 1;  // 0
593d0407baSopenharmony_ci        u32 vfunc : 8;  // 1-8
603d0407baSopenharmony_ci        u32 rsvd0 : 23; // 9-31
613d0407baSopenharmony_ci    };
623d0407baSopenharmony_ci    u32 asdword;
633d0407baSopenharmony_ci};
643d0407baSopenharmony_ci
653d0407baSopenharmony_ci/**
663d0407baSopenharmony_ci * The Channel Weight Register.
673d0407baSopenharmony_ci */
683d0407baSopenharmony_ciunion weight {
693d0407baSopenharmony_ci    struct {
703d0407baSopenharmony_ci        u32 weight0 : 5; // 0:4
713d0407baSopenharmony_ci        u32 weight1 : 5; // 5:9
723d0407baSopenharmony_ci        u32 weight2 : 5; // 10:14
733d0407baSopenharmony_ci        u32 weight3 : 5; // 15:19
743d0407baSopenharmony_ci        u32 rsvd : 12;   // 20:31
753d0407baSopenharmony_ci    };
763d0407baSopenharmony_ci    u32 asdword;
773d0407baSopenharmony_ci};
783d0407baSopenharmony_ci
793d0407baSopenharmony_ci/**
803d0407baSopenharmony_ci * The Doorbell Register for read and write.
813d0407baSopenharmony_ci */
823d0407baSopenharmony_ciunion db {
833d0407baSopenharmony_ci    struct {
843d0407baSopenharmony_ci        u32 chnl : 3;       // 0
853d0407baSopenharmony_ci        u32 reserved0 : 28; // 3:30
863d0407baSopenharmony_ci        u32 stop : 1;       // 31
873d0407baSopenharmony_ci    };
883d0407baSopenharmony_ci    u32 asdword;
893d0407baSopenharmony_ci};
903d0407baSopenharmony_ci
913d0407baSopenharmony_ci/**
923d0407baSopenharmony_ci * The Context Registers for read and write.
933d0407baSopenharmony_ci */
943d0407baSopenharmony_cistruct ctx_regs {
953d0407baSopenharmony_ci    union chan_ctrl_lo ctrllo;
963d0407baSopenharmony_ci    union chan_ctrl_hi ctrlhi;
973d0407baSopenharmony_ci    u32 xfersize;
983d0407baSopenharmony_ci    u32 sarptrlo;
993d0407baSopenharmony_ci    u32 sarptrhi;
1003d0407baSopenharmony_ci    u32 darptrlo;
1013d0407baSopenharmony_ci    u32 darptrhi;
1023d0407baSopenharmony_ci};
1033d0407baSopenharmony_ci
1043d0407baSopenharmony_ci/**
1053d0407baSopenharmony_ci * The Enable Register for read and write.
1063d0407baSopenharmony_ci */
1073d0407baSopenharmony_ciunion enb {
1083d0407baSopenharmony_ci    struct {
1093d0407baSopenharmony_ci        u32 enb : 1;        // 0
1103d0407baSopenharmony_ci        u32 reserved0 : 31; // 1:31
1113d0407baSopenharmony_ci    };
1123d0407baSopenharmony_ci    u32 asdword;
1133d0407baSopenharmony_ci};
1143d0407baSopenharmony_ci
1153d0407baSopenharmony_ci/**
1163d0407baSopenharmony_ci * The Interrupt Status Register for read and write.
1173d0407baSopenharmony_ci */
1183d0407baSopenharmony_ciunion int_status {
1193d0407baSopenharmony_ci    struct {
1203d0407baSopenharmony_ci        u32 donesta : 8;
1213d0407baSopenharmony_ci        u32 rsvd0 : 8;
1223d0407baSopenharmony_ci        u32 abortsta : 8;
1233d0407baSopenharmony_ci        u32 rsvd1 : 8;
1243d0407baSopenharmony_ci    };
1253d0407baSopenharmony_ci    u32 asdword;
1263d0407baSopenharmony_ci};
1273d0407baSopenharmony_ci
1283d0407baSopenharmony_ci/**
1293d0407baSopenharmony_ci * The Interrupt Clear Register for read and write.
1303d0407baSopenharmony_ci */
1313d0407baSopenharmony_ciunion int_clear {
1323d0407baSopenharmony_ci    struct {
1333d0407baSopenharmony_ci        u32 doneclr : 8;
1343d0407baSopenharmony_ci        u32 rsvd0 : 8;
1353d0407baSopenharmony_ci        u32 abortclr : 8;
1363d0407baSopenharmony_ci        u32 rsvd1 : 8;
1373d0407baSopenharmony_ci    };
1383d0407baSopenharmony_ci    u32 asdword;
1393d0407baSopenharmony_ci};
1403d0407baSopenharmony_ci
1413d0407baSopenharmony_cistruct dma_table {
1423d0407baSopenharmony_ci    u32 *descs;
1433d0407baSopenharmony_ci    int chn;
1443d0407baSopenharmony_ci    phys_addr_t phys_descs;
1453d0407baSopenharmony_ci    u32 dir;
1463d0407baSopenharmony_ci    u32 type;
1473d0407baSopenharmony_ci    struct list_head tbl_node;
1483d0407baSopenharmony_ci    union enb wr_enb;
1493d0407baSopenharmony_ci    struct ctx_regs ctx_reg;
1503d0407baSopenharmony_ci    union weight wr_weilo;
1513d0407baSopenharmony_ci    union weight wr_weihi;
1523d0407baSopenharmony_ci    union db start;
1533d0407baSopenharmony_ci    phys_addr_t local;
1543d0407baSopenharmony_ci    phys_addr_t bus;
1553d0407baSopenharmony_ci    size_t buf_size;
1563d0407baSopenharmony_ci};
1573d0407baSopenharmony_ci
1583d0407baSopenharmony_cistruct dma_trx_obj {
1593d0407baSopenharmony_ci    struct device *dev;
1603d0407baSopenharmony_ci    int loop_count;
1613d0407baSopenharmony_ci    int loop_count_threshold;
1623d0407baSopenharmony_ci    void *mem_base;
1633d0407baSopenharmony_ci    phys_addr_t mem_start;
1643d0407baSopenharmony_ci    size_t mem_size;
1653d0407baSopenharmony_ci    int dma_free;
1663d0407baSopenharmony_ci    unsigned long local_write_available;
1673d0407baSopenharmony_ci    unsigned long local_read_available;
1683d0407baSopenharmony_ci    unsigned long remote_write_available;
1693d0407baSopenharmony_ci    spinlock_t tbl_list_lock; /* lock dma table */
1703d0407baSopenharmony_ci    struct list_head tbl_list;
1713d0407baSopenharmony_ci    struct work_struct dma_trx_work;
1723d0407baSopenharmony_ci    wait_queue_head_t event_queue;
1733d0407baSopenharmony_ci    struct workqueue_struct *dma_trx_wq;
1743d0407baSopenharmony_ci    struct dma_table *table[PCIE_DMA_TABLE_NUM];
1753d0407baSopenharmony_ci    struct dma_table *cur;
1763d0407baSopenharmony_ci    struct task_struct *scan_thread;
1773d0407baSopenharmony_ci    struct hrtimer scan_timer;
1783d0407baSopenharmony_ci    int busno;
1793d0407baSopenharmony_ci    void *priv;
1803d0407baSopenharmony_ci    struct completion done;
1813d0407baSopenharmony_ci    int ref_count;
1823d0407baSopenharmony_ci    struct mutex count_mutex;
1833d0407baSopenharmony_ci    unsigned long irq_num;
1843d0407baSopenharmony_ci    struct dentry *pcie_root;
1853d0407baSopenharmony_ci    struct pcie_misc_dev *pcie_dev;
1863d0407baSopenharmony_ci    void (*start_dma_func)(struct dma_trx_obj *obj);
1873d0407baSopenharmony_ci    void (*config_dma_func)(struct dma_table *table);
1883d0407baSopenharmony_ci};
1893d0407baSopenharmony_ci
1903d0407baSopenharmony_ci#ifdef CONFIG_ROCKCHIP_PCIE_DMA_OBJ
1913d0407baSopenharmony_cistruct dma_trx_obj *rk_pcie_dma_obj_probe(struct device *dev);
1923d0407baSopenharmony_civoid rk_pcie_dma_obj_remove(struct dma_trx_obj *obj);
1933d0407baSopenharmony_ci#else
1943d0407baSopenharmony_cistatic inline struct dma_trx_obj *rk_pcie_dma_obj_probe(struct device *dev)
1953d0407baSopenharmony_ci{
1963d0407baSopenharmony_ci    return NULL;
1973d0407baSopenharmony_ci}
1983d0407baSopenharmony_ci
1993d0407baSopenharmony_cistatic inline void rk_pcie_dma_obj_remove(struct dma_trx_obj *obj)
2003d0407baSopenharmony_ci{
2013d0407baSopenharmony_ci}
2023d0407baSopenharmony_ci#endif
2033d0407baSopenharmony_ci
2043d0407baSopenharmony_ci#endif /* ROCKCHIP_PCIE_DMA_H */
205