/*
|
* Copyright (C) 2018 Spreadtrum Communications Inc.
|
* This software is licensed under the terms of the GNU General Public
|
* License version 2, as published by the Free Software Foundation, and
|
* may be copied, distributed, and modified under those terms.
|
|
* This program is distributed in the hope that it will be useful,
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* GNU General Public License for more details.
|
*/
|
|
#ifndef __EDMA_ENGIN_H__
|
#define __EDMA_ENGIN_H__
|
|
#include "pcie_dbg.h"
|
#include "pcie.h"
|
|
enum ISR_TASK_MSG_ID {
|
ISR_MSG_NULL = 0,
|
ISR_MSG_TX_POP,
|
ISR_MSG_TX_COMPLETE,
|
ISR_MSG_RX_POP,
|
ISR_MSG_RX_PUSH,
|
ISR_MSG_INTx,
|
ISR_MSG_EXIT_FUNC,
|
};
|
|
enum LINK_MODE_TYPE {
|
TWO_LINK_MODE = 0,
|
ONE_LINK_MODE,
|
NON_LINK_MODE,
|
};
|
|
enum ADDR_REGION_TYPE {
|
CPU64 = 0x0,
|
AXI40 = 0x1,
|
AHB32 = 0x2,
|
};
|
|
#define CONFIG_TASKLET_SUPPORT (1)
|
#define INCR_RING_BUFF_INDX(indx, max_num) \
|
((((indx) + 1) < (max_num)) ? ((indx) + 1) : (0))
|
|
#define GET_32_OF_40(a) ((unsigned int)((unsigned long) \
|
(mpool_vir_to_phy(a)) & 0xFFFFFFFF))
|
#define GET_8_OF_40(a) (0x80)
|
#define SET_32_OF_40(a, v) do { \
|
unsigned long l = (unsigned long)(a); \
|
if (sizeof(unsigned long) == sizeof(unsigned int)) { \
|
a = (void *)((l&0x00000000)|(v)); \
|
} else { \
|
a = (void *)((l&0xFFFFFFFF00000000)|(v)); \
|
} \
|
} while (0)
|
#define SET_8_OF_40(a, v) do { \
|
unsigned long l = (unsigned long)(a); \
|
if (sizeof(unsigned long) != sizeof(unsigned int)) \
|
a = (void *)((l&0xFFFFFF00FFFFFFFF) |\
|
((unsigned long)(v) << 32));\
|
} while (0)
|
|
#define COMPARE_40_BIT(a, b) ((sizeof(unsigned int) == \
|
sizeof(unsigned long)) ? \
|
(!((unsigned long)(a) ^ (unsigned long)(b))) : \
|
(!(((unsigned long)(a) ^ (unsigned long)(b)) & 0xFFFFFFFFFF)))
|
|
struct cpdu_head {
|
struct cpdu_head *next;
|
unsigned int __next:8;
|
unsigned int len:16;
|
unsigned int offset:8;
|
unsigned int rsvd;
|
};
|
|
#ifdef __FOR_THREADX_H__
|
#define GET_32_OF_40(a) ((unsigned int)(a))
|
#define GET_8_OF_40(a) (0)
|
#define SET_32_OF_40(a, v) (a = (struct desc *)(v))
|
#define SET_8_OF_40(a, v)
|
|
#define COMPARE_40_BIT(a, b) ((sizeof(unsigned int) == \
|
sizeof(unsigned long)) ? \
|
(!((unsigned long)(a) ^ (unsigned long)(b))) : \
|
(!(((unsigned long)(a) ^ (unsigned long)(b)) & 0xFFFFFFFFFF)))
|
|
struct mbuf_t {
|
struct mbuf_t *next;
|
unsigned char *buf;
|
unsigned short len;
|
unsigned short rsvd;
|
unsigned int seq;
|
};
|
#endif
|
|
union dma_glb_pause_reg {
|
unsigned int reg;
|
struct {
|
unsigned int rf_dma_pause:1;
|
unsigned int rsvd0:1;
|
unsigned int rf_dma_pause_status:1;
|
unsigned int rsvd1:5;
|
unsigned int rf_dma_dst_outstanding_num:4;
|
unsigned int rf_dma_src_outstanding_num:4;
|
|
unsigned int edma_reg_rclk_cg_en:1;
|
unsigned int edma_glb_cfg_wclk_cg_en:1;
|
unsigned int edma_chn_cfg_wclk_cg_en:1;
|
unsigned int edma_req_cid_wclk_cg_en:1;
|
unsigned int edma_chn_int_clk_cg_en:1;
|
unsigned int edma_axi_clk_cg_en:1;
|
unsigned int rsvd2:2;
|
unsigned int rf_dma_pcie_legacy_int_en:1;
|
unsigned int rsvd3:7;
|
} bit;
|
};
|
|
union dma_glb_prot_reg {
|
unsigned int reg;
|
struct {
|
unsigned int rf_dma_pause_prot:1;
|
unsigned int rf_dma_int_raw_status_prot:1;
|
unsigned int rf_dma_int_mask_status_prot:1;
|
unsigned int rf_dma_req_status_prot:1;
|
unsigned int rf_dma_debug_status_prot:1;
|
unsigned int rf_dma_arb_sel_prot:1;
|
unsigned int rf_dma_sync_sec_normal_prot:1;
|
unsigned int rsvd:25;
|
} bit;
|
};
|
|
union dma_glb_msix_value_reg {
|
unsigned int reg;
|
struct {
|
unsigned int rf_dma_pcie_msix_value:22;
|
unsigned int rsvd:2;
|
unsigned int rf_dma_pcie_msix_reg_addr_hi:8;
|
} bit;
|
};
|
|
union dma_chn_int_reg {
|
unsigned int reg;
|
struct {
|
unsigned int rf_chn_tx_pop_int_en:1;
|
unsigned int rf_chn_tx_complete_int_en:1;
|
unsigned int rf_chn_rx_pop_int_en:1;
|
unsigned int rf_chn_rx_push_int_en:1;
|
unsigned int rf_chn_cfg_err_int_en:1;
|
unsigned int rsvd0:3;
|
unsigned int rf_chn_tx_pop_int_raw_status:1;
|
unsigned int rf_chn_tx_complete_int_raw_status:1;
|
unsigned int rf_chn_rx_pop_int_raw_status:1;
|
unsigned int rf_chn_rx_push_int_raw_status:1;
|
unsigned int rf_chn_cfg_err_int_raw_status:1;
|
unsigned int rsvd1:3;
|
unsigned int rf_chn_tx_pop_int_mask_status:1;
|
unsigned int rf_chn_tx_complete_int_mask_status:1;
|
unsigned int rf_chn_rx_pop_int_mask_status:1;
|
unsigned int rf_chn_rx_push_int_mask_status:1;
|
unsigned int rf_chn_cfg_err_int_mask_status:1;
|
unsigned int rsvd2:3;
|
unsigned int rf_chn_tx_pop_int_clr:1;
|
unsigned int rf_chn_tx_complete_int_clr:1;
|
unsigned int rf_chn_rx_pop_int_clr:1;
|
unsigned int rf_chn_rx_push_int_clr:1;
|
unsigned int rf_chn_cfg_err_int_clr:1;
|
unsigned int rsvd3:3;
|
} bit;
|
};
|
|
union dma_chn_tx_req_reg {
|
unsigned int reg;
|
struct {
|
unsigned int rf_chn_tx_req:1;
|
unsigned int rsvd:31;
|
} bit;
|
};
|
|
union dma_chn_rx_req_reg {
|
unsigned int reg;
|
struct {
|
unsigned int rf_chn_rx_req:1;
|
unsigned int rsvd:31;
|
} bit;
|
};
|
|
union dma_chn_cfg_reg {
|
unsigned int reg;
|
struct {
|
unsigned int rf_chn_en:1;
|
unsigned int rsvd0:3;
|
unsigned int rf_chn_list_mode:2;
|
unsigned int rf_chn_int_to_ap_type:1;
|
unsigned int rf_chn_dir:1;
|
unsigned int rf_chn_swt_mode:2;
|
unsigned int rf_chn_priority:2;
|
unsigned int rf_dont_wait_ddone:1;
|
unsigned int rf_chn_req_mode:1;
|
unsigned int rf_chn_int_out_sel:1;
|
unsigned int rsvd1:1;
|
unsigned int rf_chn_sem_value:8;
|
unsigned int rf_chn_err_status:3;
|
unsigned int rsvd2:5;
|
|
} bit;
|
};
|
|
union dma_dscr_trans_len_reg {
|
unsigned int reg;
|
struct {
|
unsigned int rf_chn_trsc_len:16;
|
unsigned int rf_rsvd0:8;
|
unsigned int rf_chn_done:1;
|
unsigned int rf_chn_pause:1;
|
unsigned int rf_chn_tx_intr:1;
|
unsigned int rf_chn_rx_intr:1;
|
unsigned int rf_chn_eof:1;
|
unsigned int rf_rsvd1:3;
|
} bit;
|
};
|
|
union dma_dscr_ptr_high_reg {
|
unsigned int reg;
|
struct {
|
unsigned int rf_chn_src_data_addr_high:8;
|
unsigned int rf_chn_dst_data_addr_high:8;
|
unsigned int rf_chn_tx_next_dscr_ptr_high:8;
|
unsigned int rf_chn_rx_next_dscr_ptr_high:8;
|
} bit;
|
};
|
|
union dma_dscr_req1_cid_reg {
|
unsigned int reg;
|
struct {
|
unsigned int rf_chn_req1_cid:6;
|
unsigned int rf_rsvd2:26;
|
} bit;
|
};
|
|
struct edma_glb_reg {
|
union dma_glb_pause_reg dma_pause;
|
unsigned int dma_int_raw_status;
|
unsigned int dma_int_mask_status;
|
unsigned int dma_req_status;
|
unsigned int dma_debug_status;
|
unsigned int dma_arb_sel_status;
|
unsigned int dma_chn_arprot;
|
unsigned int dma_chn_awprot;
|
unsigned int dma_chn_prot_flag;
|
union dma_glb_prot_reg dma_glb_prot;
|
unsigned int dma_req_cid_prot;
|
unsigned int dma_sync_sec_nomal;
|
unsigned int dma_pcie_msix_reg_addr_low;
|
union dma_glb_msix_value_reg dma_pcie_msix_value;
|
};
|
|
struct desc {
|
union dma_dscr_trans_len_reg chn_trans_len;
|
union dma_dscr_ptr_high_reg chn_ptr_high;
|
unsigned int rf_chn_tx_next_dscr_ptr_low;
|
unsigned int rf_chn_rx_next_dscr_ptr_low;
|
unsigned int rf_chn_data_src_addr_low;
|
unsigned int rf_chn_data_dst_addr_low;
|
|
union {
|
struct desc *p;
|
unsigned int t[2];
|
} next;
|
union {
|
void *p;
|
unsigned char *src;
|
unsigned int t[2];
|
} link;
|
union {
|
unsigned char *p;
|
unsigned char *dst;
|
unsigned int t[2];
|
} buf;
|
};
|
|
struct edma_chn_reg {
|
union dma_chn_int_reg dma_int;
|
union dma_chn_tx_req_reg dma_tx_req;
|
union dma_chn_rx_req_reg dma_rx_req;
|
union dma_chn_cfg_reg dma_cfg;
|
struct desc dma_dscr;
|
};
|
|
enum ERROR_CODE {
|
OK = 0,
|
ERROR = -1,
|
TIMEOUT = -2,
|
};
|
|
struct event_t {
|
int id;
|
int flag;
|
struct semaphore wait_sem;
|
struct timespec time;
|
struct tasklet_struct *tasklet;
|
};
|
|
struct lock_sw {
|
void *entity;
|
unsigned long flag;
|
char *name;
|
};
|
|
struct irq_lock_t {
|
spinlock_t *irq_spinlock_p;
|
unsigned long flag;
|
char *name;
|
};
|
|
struct dscr_ring {
|
int size;
|
int free;
|
struct desc *head;
|
struct desc *tail;
|
unsigned char *mem;
|
struct irq_lock_t lock;
|
};
|
|
struct edma_pending_q {
|
struct {
|
void *head;
|
void *tail;
|
int num;
|
} ring[32];
|
int wt;
|
int rd;
|
int max;
|
int status;
|
int chn;
|
struct irq_lock_t lock;
|
};
|
|
struct isr_msg_queue {
|
unsigned int seq;
|
unsigned short chn;
|
unsigned short evt;
|
union dma_chn_int_reg dma_int;
|
};
|
|
struct msg_q {
|
unsigned int seq;
|
unsigned int wt;
|
unsigned int rd;
|
unsigned int max;
|
unsigned int size;
|
unsigned char *mem;
|
struct irq_lock_t lock;
|
struct event_t event;
|
};
|
|
struct edma_info {
|
struct edma_glb_reg *dma_glb_reg;
|
struct edma_chn_reg *dma_chn_reg;
|
int (*enable)(void);
|
int (*reset)(void);
|
int ap;
|
struct {
|
int mode;
|
int wait;
|
int interval;
|
int tx_complete_verify;
|
struct event_t event;
|
struct dscr_ring dscr_ring;
|
unsigned char dir;
|
unsigned char inout;
|
unsigned char state;
|
struct edma_pending_q pending_q;
|
} chn_sw[32];
|
struct {
|
int state;
|
void *entity;
|
struct msg_q q;
|
} isr_func;
|
struct wcn_pcie_info *pcie_info;
|
};
|
|
int edma_init(struct wcn_pcie_info *pcie_info);
|
int edma_deinit(void);
|
|
int edma_chn_init(int chn, int mode, int inout, int max_trans);
|
int edma_one_link_dscr_buf_bind(struct desc *dscr, unsigned char *dst,
|
unsigned char *src, unsigned short len);
|
struct edma_info *edma_info(void);
|
int msi_irq_handle(int irq);
|
int legacy_irq_handle(int data);
|
int edma_push_link(int chn, void *head, void *tail, int num);
|
int edma_push_link_async(int chn, void *head, void *tail, int num);
|
int edma_push_link_wait_complete(int chn, void *head, void *tail,
|
int num, int timeout);
|
int mchn_hw_pop_link(int chn, void *head, void *tail, int num);
|
int mchn_hw_cb_in_irq(int chn);
|
int mchn_hw_max_pending(int chn);
|
int edma_tp_count(int chn, void *head, void *tail, int num);
|
void *mpool_malloc(int len);
|
int mpool_free(void);
|
void *pcie_alloc_memory(int len);
|
int delete_queue(struct msg_q *q);
|
#endif
|