summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/wcn36xx/dxe.h
blob: c012e807753b763112a1be05b046b71f2d51087f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
/*
 * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef _DXE_H_
#define _DXE_H_

#include "wcn36xx.h"

/*
TX_LOW	= DMA0
TX_HIGH	= DMA4
RX_LOW	= DMA1
RX_HIGH	= DMA3
H2H_TEST_RX_TX = DMA2
*/

/* DXE registers */
#define WCN36XX_DXE_MEM_REG			0

#define WCN36XX_CCU_DXE_INT_SELECT_RIVA		0x310
#define WCN36XX_CCU_DXE_INT_SELECT_PRONTO	0x10dc

/* TODO This must calculated properly but not hardcoded */
#define WCN36XX_DXE_CTRL_TX_L			0x328a44
#define WCN36XX_DXE_CTRL_TX_H			0x32ce44
#define WCN36XX_DXE_CTRL_RX_L			0x12ad2f
#define WCN36XX_DXE_CTRL_RX_H			0x12d12f
#define WCN36XX_DXE_CTRL_TX_H_BD		0x30ce45
#define WCN36XX_DXE_CTRL_TX_H_SKB		0x32ce4d
#define WCN36XX_DXE_CTRL_TX_L_BD		0x308a45
#define WCN36XX_DXE_CTRL_TX_L_SKB		0x328a4d

/* TODO This must calculated properly but not hardcoded */
#define WCN36XX_DXE_WQ_TX_L			0x17
#define WCN36XX_DXE_WQ_TX_H			0x17
#define WCN36XX_DXE_WQ_RX_L			0xB
#define WCN36XX_DXE_WQ_RX_H			0x4

/* DXE descriptor control filed */
#define WCN36XX_DXE_CTRL_VALID_MASK (0x00000001)

/* TODO This must calculated properly but not hardcoded */
/* DXE default control register values */
#define WCN36XX_DXE_CH_DEFAULT_CTL_RX_L		0x847EAD2F
#define WCN36XX_DXE_CH_DEFAULT_CTL_RX_H		0x84FED12F
#define WCN36XX_DXE_CH_DEFAULT_CTL_TX_H		0x853ECF4D
#define WCN36XX_DXE_CH_DEFAULT_CTL_TX_L		0x843e8b4d

/* Common DXE registers */
#define WCN36XX_DXE_MEM_CSR			(WCN36XX_DXE_MEM_REG + 0x00)
#define WCN36XX_DXE_REG_CSR_RESET		(WCN36XX_DXE_MEM_REG + 0x00)
#define WCN36XX_DXE_ENCH_ADDR			(WCN36XX_DXE_MEM_REG + 0x04)
#define WCN36XX_DXE_REG_CH_EN			(WCN36XX_DXE_MEM_REG + 0x08)
#define WCN36XX_DXE_REG_CH_DONE			(WCN36XX_DXE_MEM_REG + 0x0C)
#define WCN36XX_DXE_REG_CH_ERR			(WCN36XX_DXE_MEM_REG + 0x10)
#define WCN36XX_DXE_INT_MASK_REG		(WCN36XX_DXE_MEM_REG + 0x18)
#define WCN36XX_DXE_INT_SRC_RAW_REG		(WCN36XX_DXE_MEM_REG + 0x20)
	/* #define WCN36XX_DXE_INT_CH6_MASK	0x00000040 */
	/* #define WCN36XX_DXE_INT_CH5_MASK	0x00000020 */
	#define WCN36XX_DXE_INT_CH4_MASK	0x00000010
	#define WCN36XX_DXE_INT_CH3_MASK	0x00000008
	/* #define WCN36XX_DXE_INT_CH2_MASK	0x00000004 */
	#define WCN36XX_DXE_INT_CH1_MASK	0x00000002
	#define WCN36XX_DXE_INT_CH0_MASK	0x00000001
#define WCN36XX_DXE_0_INT_CLR			(WCN36XX_DXE_MEM_REG + 0x30)
#define WCN36XX_DXE_0_INT_ED_CLR		(WCN36XX_DXE_MEM_REG + 0x34)
#define WCN36XX_DXE_0_INT_DONE_CLR		(WCN36XX_DXE_MEM_REG + 0x38)
#define WCN36XX_DXE_0_INT_ERR_CLR		(WCN36XX_DXE_MEM_REG + 0x3C)

#define WCN36XX_DXE_0_CH0_STATUS		(WCN36XX_DXE_MEM_REG + 0x404)
#define WCN36XX_DXE_0_CH1_STATUS		(WCN36XX_DXE_MEM_REG + 0x444)
#define WCN36XX_DXE_0_CH2_STATUS		(WCN36XX_DXE_MEM_REG + 0x484)
#define WCN36XX_DXE_0_CH3_STATUS		(WCN36XX_DXE_MEM_REG + 0x4C4)
#define WCN36XX_DXE_0_CH4_STATUS		(WCN36XX_DXE_MEM_REG + 0x504)

#define WCN36XX_DXE_REG_RESET			0x5c89

/* Temporary BMU Workqueue 4 */
#define WCN36XX_DXE_BMU_WQ_RX_LOW		0xB
#define WCN36XX_DXE_BMU_WQ_RX_HIGH		0x4
/* DMA channel offset */
#define WCN36XX_DXE_TX_LOW_OFFSET		0x400
#define WCN36XX_DXE_TX_HIGH_OFFSET		0x500
#define WCN36XX_DXE_RX_LOW_OFFSET		0x440
#define WCN36XX_DXE_RX_HIGH_OFFSET		0x4C0

/* Address of the next DXE descriptor */
#define WCN36XX_DXE_CH_NEXT_DESC_ADDR		0x001C
#define WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_L	(WCN36XX_DXE_MEM_REG + \
						 WCN36XX_DXE_TX_LOW_OFFSET + \
						 WCN36XX_DXE_CH_NEXT_DESC_ADDR)
#define WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_H	(WCN36XX_DXE_MEM_REG + \
						 WCN36XX_DXE_TX_HIGH_OFFSET + \
						 WCN36XX_DXE_CH_NEXT_DESC_ADDR)
#define WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_L	(WCN36XX_DXE_MEM_REG + \
						 WCN36XX_DXE_RX_LOW_OFFSET + \
						 WCN36XX_DXE_CH_NEXT_DESC_ADDR)
#define WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_H	(WCN36XX_DXE_MEM_REG + \
						 WCN36XX_DXE_RX_HIGH_OFFSET + \
						 WCN36XX_DXE_CH_NEXT_DESC_ADDR)

/* DXE Descriptor source address */
#define WCN36XX_DXE_CH_SRC_ADDR			0x000C
#define WCN36XX_DXE_CH_SRC_ADDR_RX_L		(WCN36XX_DXE_MEM_REG + \
						 WCN36XX_DXE_RX_LOW_OFFSET + \
						 WCN36XX_DXE_CH_SRC_ADDR)
#define WCN36XX_DXE_CH_SRC_ADDR_RX_H		(WCN36XX_DXE_MEM_REG + \
						 WCN36XX_DXE_RX_HIGH_OFFSET + \
						 WCN36XX_DXE_CH_SRC_ADDR)

/* DXE Descriptor address destination address */
#define WCN36XX_DXE_CH_DEST_ADDR		0x0014
#define WCN36XX_DXE_CH_DEST_ADDR_TX_L		(WCN36XX_DXE_MEM_REG + \
						 WCN36XX_DXE_TX_LOW_OFFSET + \
						 WCN36XX_DXE_CH_DEST_ADDR)
#define WCN36XX_DXE_CH_DEST_ADDR_TX_H		(WCN36XX_DXE_MEM_REG + \
						 WCN36XX_DXE_TX_HIGH_OFFSET + \
						 WCN36XX_DXE_CH_DEST_ADDR)
#define WCN36XX_DXE_CH_DEST_ADDR_RX_L		(WCN36XX_DXE_MEM_REG + \
						 WCN36XX_DXE_RX_LOW_OFFSET + \
						 WCN36XX_DXE_CH_DEST_ADDR)
#define WCN36XX_DXE_CH_DEST_ADDR_RX_H		(WCN36XX_DXE_MEM_REG + \
						 WCN36XX_DXE_RX_HIGH_OFFSET + \
						 WCN36XX_DXE_CH_DEST_ADDR)

/* Interrupt status */
#define WCN36XX_DXE_CH_STATUS_REG_ADDR		0x0004
#define WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_L	(WCN36XX_DXE_MEM_REG + \
						 WCN36XX_DXE_TX_LOW_OFFSET + \
						 WCN36XX_DXE_CH_STATUS_REG_ADDR)
#define WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_H	(WCN36XX_DXE_MEM_REG + \
						 WCN36XX_DXE_TX_HIGH_OFFSET + \
						 WCN36XX_DXE_CH_STATUS_REG_ADDR)
#define WCN36XX_DXE_CH_STATUS_REG_ADDR_RX_L	(WCN36XX_DXE_MEM_REG + \
						 WCN36XX_DXE_RX_LOW_OFFSET + \
						 WCN36XX_DXE_CH_STATUS_REG_ADDR)
#define WCN36XX_DXE_CH_STATUS_REG_ADDR_RX_H	(WCN36XX_DXE_MEM_REG + \
						 WCN36XX_DXE_RX_HIGH_OFFSET + \
						 WCN36XX_DXE_CH_STATUS_REG_ADDR)


/* DXE default control register */
#define WCN36XX_DXE_REG_CTL_RX_L		(WCN36XX_DXE_MEM_REG + \
						 WCN36XX_DXE_RX_LOW_OFFSET)
#define WCN36XX_DXE_REG_CTL_RX_H		(WCN36XX_DXE_MEM_REG + \
						 WCN36XX_DXE_RX_HIGH_OFFSET)
#define WCN36XX_DXE_REG_CTL_TX_H		(WCN36XX_DXE_MEM_REG + \
						 WCN36XX_DXE_TX_HIGH_OFFSET)
#define WCN36XX_DXE_REG_CTL_TX_L		(WCN36XX_DXE_MEM_REG + \
						 WCN36XX_DXE_TX_LOW_OFFSET)

#define WCN36XX_SMSM_WLAN_TX_ENABLE		0x00000400
#define WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY	0x00000200


/* Interrupt control channel mask */
#define WCN36XX_INT_MASK_CHAN_TX_L		0x00000001
#define WCN36XX_INT_MASK_CHAN_RX_L		0x00000002
#define WCN36XX_INT_MASK_CHAN_RX_H		0x00000008
#define WCN36XX_INT_MASK_CHAN_TX_H		0x00000010

#define WCN36XX_BD_CHUNK_SIZE			128

#define WCN36XX_PKT_SIZE			0xF20
enum wcn36xx_dxe_ch_type {
	WCN36XX_DXE_CH_TX_L,
	WCN36XX_DXE_CH_TX_H,
	WCN36XX_DXE_CH_RX_L,
	WCN36XX_DXE_CH_RX_H
};

/* amount of descriptors per channel */
enum wcn36xx_dxe_ch_desc_num {
	WCN36XX_DXE_CH_DESC_NUMB_TX_L		= 128,
	WCN36XX_DXE_CH_DESC_NUMB_TX_H		= 10,
	WCN36XX_DXE_CH_DESC_NUMB_RX_L		= 512,
	WCN36XX_DXE_CH_DESC_NUMB_RX_H		= 40
};

/**
 * struct wcn36xx_dxe_desc - describes descriptor of one DXE buffer
 *
 * @ctrl: is a union that consists of following bits:
 * union {
 *	u32	valid		:1; //0 = DMA stop, 1 = DMA continue with this
 *				    //descriptor
 *	u32	transfer_type	:2; //0 = Host to Host space
 *	u32	eop		:1; //End of Packet
 *	u32	bd_handling	:1; //if transferType = Host to BMU, then 0
 *				    // means first 128 bytes contain BD, and 1
 *				    // means create new empty BD
 *	u32	siq		:1; // SIQ
 *	u32	diq		:1; // DIQ
 *	u32	pdu_rel		:1; //0 = don't release BD and PDUs when done,
 *				    // 1 = release them
 *	u32	bthld_sel	:4; //BMU Threshold Select
 *	u32	prio		:3; //Specifies the priority level to use for
 *				    // the transfer
 *	u32	stop_channel	:1; //1 = DMA stops processing further, channel
 *				    //requires re-enabling after this
 *	u32	intr		:1; //Interrupt on Descriptor Done
 *	u32	rsvd		:1; //reserved
 *	u32	size		:14;//14 bits used - ignored for BMU transfers,
 *				    //only used for host to host transfers?
 * } ctrl;
 */
struct wcn36xx_dxe_desc {
	u32	ctrl;
	u32	fr_len;

	u32	src_addr_l;
	u32	dst_addr_l;
	u32	phy_next_l;
	u32	src_addr_h;
	u32	dst_addr_h;
	u32	phy_next_h;
} __packed;

/* DXE Control block */
struct wcn36xx_dxe_ctl {
	struct wcn36xx_dxe_ctl	*next;
	struct wcn36xx_dxe_desc	*desc;
	unsigned int		desc_phy_addr;
	int			ctl_blk_order;
	struct sk_buff		*skb;
	spinlock_t              skb_lock;
	void			*bd_cpu_addr;
	dma_addr_t		bd_phy_addr;
};

struct wcn36xx_dxe_ch {
	spinlock_t			lock;	/* protects head/tail ptrs */
	enum wcn36xx_dxe_ch_type	ch_type;
	void				*cpu_addr;
	dma_addr_t			dma_addr;
	enum wcn36xx_dxe_ch_desc_num	desc_num;
	/* DXE control block ring */
	struct wcn36xx_dxe_ctl		*head_blk_ctl;
	struct wcn36xx_dxe_ctl		*tail_blk_ctl;

	/* DXE channel specific configs */
	u32				dxe_wq;
	u32				ctrl_bd;
	u32				ctrl_skb;
	u32				reg_ctrl;
	u32				def_ctrl;
};

/* Memory Pool for BD headers */
struct wcn36xx_dxe_mem_pool {
	int		chunk_size;
	void		*virt_addr;
	dma_addr_t	phy_addr;
};

struct wcn36xx_vif;
int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn);
void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn);
void wcn36xx_dxe_rx_frame(struct wcn36xx *wcn);
int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn);
void wcn36xx_dxe_free_ctl_blks(struct wcn36xx *wcn);
int wcn36xx_dxe_init(struct wcn36xx *wcn);
void wcn36xx_dxe_deinit(struct wcn36xx *wcn);
int wcn36xx_dxe_init_channels(struct wcn36xx *wcn);
int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
			 struct wcn36xx_vif *vif_priv,
			 struct sk_buff *skb,
			 bool is_low);
void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status);
void *wcn36xx_dxe_get_next_bd(struct wcn36xx *wcn, bool is_low);
#endif	/* _DXE_H_ */