1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2016  Realtek Corporation.
5  *
6  * Contact Information:
7  * wlanfae <wlanfae@realtek.com>
8  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
9  * Hsinchu 300, Taiwan.
10  *
11  * Larry Finger <Larry.Finger@lwfinger.net>
12  *
13  *****************************************************************************/
14 #include "halmac_88xx_cfg.h"
15 
16 /**
17  * halmac_init_sdio_cfg_88xx() - init SDIO
18  * @halmac_adapter : the adapter of halmac
19  * Author : KaiYuan Chang/Ivan Lin
20  * Return : enum halmac_ret_status
21  * More details of status code can be found in prototype document
22  */
23 enum halmac_ret_status
halmac_init_sdio_cfg_88xx(struct halmac_adapter * halmac_adapter)24 halmac_init_sdio_cfg_88xx(struct halmac_adapter *halmac_adapter)
25 {
26 	void *driver_adapter = NULL;
27 	struct halmac_api *halmac_api;
28 
29 	if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
30 		return HALMAC_RET_ADAPTER_INVALID;
31 
32 	if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
33 		return HALMAC_RET_API_INVALID;
34 
35 	halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_INIT_SDIO_CFG);
36 
37 	driver_adapter = halmac_adapter->driver_adapter;
38 	halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
39 
40 	HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
41 			"%s ==========>\n", __func__);
42 
43 	HALMAC_REG_READ_32(halmac_adapter, REG_SDIO_FREE_TXPG);
44 	HALMAC_REG_WRITE_32(halmac_adapter, REG_SDIO_TX_CTRL, 0x00000000);
45 
46 	HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
47 			"%s <==========\n", __func__);
48 
49 	return HALMAC_RET_SUCCESS;
50 }
51 
52 /**
53  * halmac_deinit_sdio_cfg_88xx() - deinit SDIO
54  * @halmac_adapter : the adapter of halmac
55  * Author : KaiYuan Chang/Ivan Lin
56  * Return : enum halmac_ret_status
57  * More details of status code can be found in prototype document
58  */
59 enum halmac_ret_status
halmac_deinit_sdio_cfg_88xx(struct halmac_adapter * halmac_adapter)60 halmac_deinit_sdio_cfg_88xx(struct halmac_adapter *halmac_adapter)
61 {
62 	void *driver_adapter = NULL;
63 
64 	if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
65 		return HALMAC_RET_ADAPTER_INVALID;
66 
67 	if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
68 		return HALMAC_RET_API_INVALID;
69 
70 	halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DEINIT_SDIO_CFG);
71 
72 	driver_adapter = halmac_adapter->driver_adapter;
73 
74 	HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
75 			"%s ==========>\n", __func__);
76 
77 	HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
78 			"%s <==========\n", __func__);
79 
80 	return HALMAC_RET_SUCCESS;
81 }
82 
83 /**
84  * halmac_cfg_rx_aggregation_88xx_sdio() - config rx aggregation
85  * @halmac_adapter : the adapter of halmac
86  * @halmac_rx_agg_mode
87  * Author : KaiYuan Chang/Ivan Lin
88  * Return : enum halmac_ret_status
89  * More details of status code can be found in prototype document
90  */
91 enum halmac_ret_status
halmac_cfg_rx_aggregation_88xx_sdio(struct halmac_adapter * halmac_adapter,struct halmac_rxagg_cfg * phalmac_rxagg_cfg)92 halmac_cfg_rx_aggregation_88xx_sdio(struct halmac_adapter *halmac_adapter,
93 				    struct halmac_rxagg_cfg *phalmac_rxagg_cfg)
94 {
95 	u8 value8;
96 	u8 size = 0, timeout = 0, agg_enable = 0;
97 	void *driver_adapter = NULL;
98 	struct halmac_api *halmac_api;
99 
100 	if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
101 		return HALMAC_RET_ADAPTER_INVALID;
102 
103 	if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
104 		return HALMAC_RET_API_INVALID;
105 
106 	halmac_api_record_id_88xx(halmac_adapter,
107 				  HALMAC_API_CFG_RX_AGGREGATION);
108 
109 	driver_adapter = halmac_adapter->driver_adapter;
110 	halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
111 
112 	HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
113 			"%s ==========>\n", __func__);
114 
115 	agg_enable = HALMAC_REG_READ_8(halmac_adapter, REG_TXDMA_PQ_MAP);
116 
117 	switch (phalmac_rxagg_cfg->mode) {
118 	case HALMAC_RX_AGG_MODE_NONE:
119 		agg_enable &= ~(BIT_RXDMA_AGG_EN);
120 		break;
121 	case HALMAC_RX_AGG_MODE_DMA:
122 	case HALMAC_RX_AGG_MODE_USB:
123 		agg_enable |= BIT_RXDMA_AGG_EN;
124 		break;
125 	default:
126 		pr_err("halmac_cfg_rx_aggregation_88xx_usb switch case not support\n");
127 		agg_enable &= ~BIT_RXDMA_AGG_EN;
128 		break;
129 	}
130 
131 	if (!phalmac_rxagg_cfg->threshold.drv_define) {
132 		size = 0xFF;
133 		timeout = 0x01;
134 	} else {
135 		size = phalmac_rxagg_cfg->threshold.size;
136 		timeout = phalmac_rxagg_cfg->threshold.timeout;
137 	}
138 
139 	HALMAC_REG_WRITE_8(halmac_adapter, REG_TXDMA_PQ_MAP, agg_enable);
140 	HALMAC_REG_WRITE_16(halmac_adapter, REG_RXDMA_AGG_PG_TH,
141 			    (u16)(size | (timeout << BIT_SHIFT_DMA_AGG_TO)));
142 
143 	value8 = HALMAC_REG_READ_8(halmac_adapter, REG_RXDMA_MODE);
144 	if ((agg_enable & BIT_RXDMA_AGG_EN) != 0)
145 		HALMAC_REG_WRITE_8(halmac_adapter, REG_RXDMA_MODE,
146 				   value8 | BIT_DMA_MODE);
147 	else
148 		HALMAC_REG_WRITE_8(halmac_adapter, REG_RXDMA_MODE,
149 				   value8 & ~(BIT_DMA_MODE));
150 
151 	HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
152 			"%s <==========\n", __func__);
153 
154 	return HALMAC_RET_SUCCESS;
155 }
156 
157 /**
158  * halmac_reg_read_8_sdio_88xx() - read 1byte register
159  * @halmac_adapter : the adapter of halmac
160  * @halmac_offset : register offset
161  * Author : KaiYuan Chang/Ivan Lin
162  * Return : enum halmac_ret_status
163  * More details of status code can be found in prototype document
164  */
halmac_reg_read_8_sdio_88xx(struct halmac_adapter * halmac_adapter,u32 halmac_offset)165 u8 halmac_reg_read_8_sdio_88xx(struct halmac_adapter *halmac_adapter,
166 			       u32 halmac_offset)
167 {
168 	u8 value8;
169 	void *driver_adapter = NULL;
170 	struct halmac_api *halmac_api;
171 	enum halmac_ret_status status = HALMAC_RET_SUCCESS;
172 
173 	if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
174 		return HALMAC_RET_ADAPTER_INVALID;
175 
176 	if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
177 		return HALMAC_RET_API_INVALID;
178 
179 	driver_adapter = halmac_adapter->driver_adapter;
180 	halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
181 
182 	if ((halmac_offset & 0xFFFF0000) == 0)
183 		halmac_offset |= WLAN_IOREG_OFFSET;
184 
185 	status = halmac_convert_to_sdio_bus_offset_88xx(halmac_adapter,
186 							&halmac_offset);
187 
188 	if (status != HALMAC_RET_SUCCESS) {
189 		pr_err("%s error = %x\n", __func__, status);
190 		return status;
191 	}
192 
193 	value8 = PLATFORM_SDIO_CMD52_READ(driver_adapter, halmac_offset);
194 
195 	return value8;
196 }
197 
198 /**
199  * halmac_reg_write_8_sdio_88xx() - write 1byte register
200  * @halmac_adapter : the adapter of halmac
201  * @halmac_offset : register offset
202  * @halmac_data : register value
203  * Author : KaiYuan Chang/Ivan Lin
204  * Return : enum halmac_ret_status
205  * More details of status code can be found in prototype document
206  */
207 enum halmac_ret_status
halmac_reg_write_8_sdio_88xx(struct halmac_adapter * halmac_adapter,u32 halmac_offset,u8 halmac_data)208 halmac_reg_write_8_sdio_88xx(struct halmac_adapter *halmac_adapter,
209 			     u32 halmac_offset, u8 halmac_data)
210 {
211 	void *driver_adapter = NULL;
212 	struct halmac_api *halmac_api;
213 	enum halmac_ret_status status = HALMAC_RET_SUCCESS;
214 
215 	if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
216 		return HALMAC_RET_ADAPTER_INVALID;
217 
218 	if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
219 		return HALMAC_RET_API_INVALID;
220 
221 	driver_adapter = halmac_adapter->driver_adapter;
222 	halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
223 
224 	if ((halmac_offset & 0xFFFF0000) == 0)
225 		halmac_offset |= WLAN_IOREG_OFFSET;
226 
227 	status = halmac_convert_to_sdio_bus_offset_88xx(halmac_adapter,
228 							&halmac_offset);
229 
230 	if (status != HALMAC_RET_SUCCESS) {
231 		pr_err("%s error = %x\n", __func__, status);
232 		return status;
233 	}
234 
235 	PLATFORM_SDIO_CMD52_WRITE(driver_adapter, halmac_offset, halmac_data);
236 
237 	return HALMAC_RET_SUCCESS;
238 }
239 
240 /**
241  * halmac_reg_read_16_sdio_88xx() - read 2byte register
242  * @halmac_adapter : the adapter of halmac
243  * @halmac_offset : register offset
244  * Author : KaiYuan Chang/Ivan Lin
245  * Return : enum halmac_ret_status
246  * More details of status code can be found in prototype document
247  */
halmac_reg_read_16_sdio_88xx(struct halmac_adapter * halmac_adapter,u32 halmac_offset)248 u16 halmac_reg_read_16_sdio_88xx(struct halmac_adapter *halmac_adapter,
249 				 u32 halmac_offset)
250 {
251 	void *driver_adapter = NULL;
252 	struct halmac_api *halmac_api;
253 	enum halmac_ret_status status = HALMAC_RET_SUCCESS;
254 
255 	union {
256 		u16 word;
257 		u8 byte[2];
258 		__le16 le_word;
259 	} value16 = {0x0000};
260 
261 	if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
262 		return HALMAC_RET_ADAPTER_INVALID;
263 
264 	if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
265 		return HALMAC_RET_API_INVALID;
266 
267 	driver_adapter = halmac_adapter->driver_adapter;
268 	halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
269 
270 	if ((halmac_offset & 0xFFFF0000) == 0)
271 		halmac_offset |= WLAN_IOREG_OFFSET;
272 
273 	status = halmac_convert_to_sdio_bus_offset_88xx(halmac_adapter,
274 							&halmac_offset);
275 
276 	if (status != HALMAC_RET_SUCCESS) {
277 		pr_err("%s error = %x\n", __func__, status);
278 		return status;
279 	}
280 
281 	if (halmac_adapter->halmac_state.mac_power == HALMAC_MAC_POWER_OFF ||
282 	    (halmac_offset & (2 - 1)) != 0 ||
283 	    halmac_adapter->sdio_cmd53_4byte ==
284 		    HALMAC_SDIO_CMD53_4BYTE_MODE_RW ||
285 	    halmac_adapter->sdio_cmd53_4byte ==
286 		    HALMAC_SDIO_CMD53_4BYTE_MODE_R) {
287 		value16.byte[0] =
288 			PLATFORM_SDIO_CMD52_READ(driver_adapter, halmac_offset);
289 		value16.byte[1] = PLATFORM_SDIO_CMD52_READ(driver_adapter,
290 							   halmac_offset + 1);
291 		value16.word = le16_to_cpu(value16.le_word);
292 	} else {
293 #if (PLATFORM_SD_CLK > HALMAC_SD_CLK_THRESHOLD_88XX)
294 		if ((halmac_offset & 0xffffef00) == 0x00000000) {
295 			value16.byte[0] = PLATFORM_SDIO_CMD52_READ(
296 				driver_adapter, halmac_offset);
297 			value16.byte[1] = PLATFORM_SDIO_CMD52_READ(
298 				driver_adapter, halmac_offset + 1);
299 			value16.word = le16_to_cpu(value16.word);
300 		} else {
301 			value16.word = PLATFORM_SDIO_CMD53_READ_16(
302 				driver_adapter, halmac_offset);
303 		}
304 #else
305 		value16.word = PLATFORM_SDIO_CMD53_READ_16(driver_adapter,
306 							   halmac_offset);
307 #endif
308 	}
309 
310 	return value16.word;
311 }
312 
313 /**
314  * halmac_reg_write_16_sdio_88xx() - write 2byte register
315  * @halmac_adapter : the adapter of halmac
316  * @halmac_offset : register offset
317  * @halmac_data : register value
318  * Author : KaiYuan Chang/Ivan Lin
319  * Return : enum halmac_ret_status
320  * More details of status code can be found in prototype document
321  */
322 enum halmac_ret_status
halmac_reg_write_16_sdio_88xx(struct halmac_adapter * halmac_adapter,u32 halmac_offset,u16 halmac_data)323 halmac_reg_write_16_sdio_88xx(struct halmac_adapter *halmac_adapter,
324 			      u32 halmac_offset, u16 halmac_data)
325 {
326 	void *driver_adapter = NULL;
327 	struct halmac_api *halmac_api;
328 	enum halmac_ret_status status = HALMAC_RET_SUCCESS;
329 
330 	if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
331 		return HALMAC_RET_ADAPTER_INVALID;
332 
333 	if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
334 		return HALMAC_RET_API_INVALID;
335 
336 	driver_adapter = halmac_adapter->driver_adapter;
337 	halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
338 
339 	if ((halmac_offset & 0xFFFF0000) == 0)
340 		halmac_offset |= WLAN_IOREG_OFFSET;
341 
342 	status = halmac_convert_to_sdio_bus_offset_88xx(halmac_adapter,
343 							&halmac_offset);
344 
345 	if (status != HALMAC_RET_SUCCESS) {
346 		pr_err("%s error = %x\n", __func__, status);
347 		return status;
348 	}
349 
350 	if (halmac_adapter->halmac_state.mac_power == HALMAC_MAC_POWER_OFF ||
351 	    (halmac_offset & (2 - 1)) != 0 ||
352 	    halmac_adapter->sdio_cmd53_4byte ==
353 		    HALMAC_SDIO_CMD53_4BYTE_MODE_RW ||
354 	    halmac_adapter->sdio_cmd53_4byte ==
355 		    HALMAC_SDIO_CMD53_4BYTE_MODE_W) {
356 		PLATFORM_SDIO_CMD52_WRITE(driver_adapter, halmac_offset,
357 					  (u8)(halmac_data & 0xFF));
358 		PLATFORM_SDIO_CMD52_WRITE(driver_adapter, halmac_offset + 1,
359 					  (u8)((halmac_data & 0xFF00) >> 8));
360 	} else {
361 		PLATFORM_SDIO_CMD53_WRITE_16(driver_adapter, halmac_offset,
362 					     halmac_data);
363 	}
364 
365 	return HALMAC_RET_SUCCESS;
366 }
367 
368 /**
369  * halmac_reg_read_32_sdio_88xx() - read 4byte register
370  * @halmac_adapter : the adapter of halmac
371  * @halmac_offset : register offset
372  * Author : KaiYuan Chang/Ivan Lin
373  * Return : enum halmac_ret_status
374  * More details of status code can be found in prototype document
375  */
halmac_reg_read_32_sdio_88xx(struct halmac_adapter * halmac_adapter,u32 halmac_offset)376 u32 halmac_reg_read_32_sdio_88xx(struct halmac_adapter *halmac_adapter,
377 				 u32 halmac_offset)
378 {
379 	void *driver_adapter = NULL;
380 	struct halmac_api *halmac_api;
381 	enum halmac_ret_status status = HALMAC_RET_SUCCESS;
382 	u32 halmac_offset_old = 0;
383 
384 	union {
385 		u32 dword;
386 		u8 byte[4];
387 		__le32 le_dword;
388 	} value32 = {0x00000000};
389 
390 	if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
391 		return HALMAC_RET_ADAPTER_INVALID;
392 
393 	if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
394 		return HALMAC_RET_API_INVALID;
395 
396 	driver_adapter = halmac_adapter->driver_adapter;
397 	halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
398 
399 	halmac_offset_old = halmac_offset;
400 
401 	if ((halmac_offset & 0xFFFF0000) == 0)
402 		halmac_offset |= WLAN_IOREG_OFFSET;
403 
404 	status = halmac_convert_to_sdio_bus_offset_88xx(halmac_adapter,
405 							&halmac_offset);
406 	if (status != HALMAC_RET_SUCCESS) {
407 		pr_err("%s error = %x\n", __func__, status);
408 		return status;
409 	}
410 
411 	if (halmac_adapter->halmac_state.mac_power == HALMAC_MAC_POWER_OFF ||
412 	    (halmac_offset & (4 - 1)) != 0) {
413 		value32.byte[0] =
414 			PLATFORM_SDIO_CMD52_READ(driver_adapter, halmac_offset);
415 		value32.byte[1] = PLATFORM_SDIO_CMD52_READ(driver_adapter,
416 							   halmac_offset + 1);
417 		value32.byte[2] = PLATFORM_SDIO_CMD52_READ(driver_adapter,
418 							   halmac_offset + 2);
419 		value32.byte[3] = PLATFORM_SDIO_CMD52_READ(driver_adapter,
420 							   halmac_offset + 3);
421 		value32.dword = le32_to_cpu(value32.le_dword);
422 	} else {
423 #if (PLATFORM_SD_CLK > HALMAC_SD_CLK_THRESHOLD_88XX)
424 		if ((halmac_offset_old & 0xffffef00) == 0x00000000) {
425 			value32.byte[0] = PLATFORM_SDIO_CMD52_READ(
426 				driver_adapter, halmac_offset);
427 			value32.byte[1] = PLATFORM_SDIO_CMD52_READ(
428 				driver_adapter, halmac_offset + 1);
429 			value32.byte[2] = PLATFORM_SDIO_CMD52_READ(
430 				driver_adapter, halmac_offset + 2);
431 			value32.byte[3] = PLATFORM_SDIO_CMD52_READ(
432 				driver_adapter, halmac_offset + 3);
433 			value32.dword = le32_to_cpu(value32.dword);
434 		} else {
435 			value32.dword = PLATFORM_SDIO_CMD53_READ_32(
436 				driver_adapter, halmac_offset);
437 		}
438 #else
439 		value32.dword = PLATFORM_SDIO_CMD53_READ_32(driver_adapter,
440 							    halmac_offset);
441 #endif
442 	}
443 
444 	return value32.dword;
445 }
446 
447 /**
448  * halmac_reg_write_32_sdio_88xx() - write 4byte register
449  * @halmac_adapter : the adapter of halmac
450  * @halmac_offset : register offset
451  * @halmac_data : register value
452  * Author : KaiYuan Chang/Ivan Lin
453  * Return : enum halmac_ret_status
454  * More details of status code can be found in prototype document
455  */
456 enum halmac_ret_status
halmac_reg_write_32_sdio_88xx(struct halmac_adapter * halmac_adapter,u32 halmac_offset,u32 halmac_data)457 halmac_reg_write_32_sdio_88xx(struct halmac_adapter *halmac_adapter,
458 			      u32 halmac_offset, u32 halmac_data)
459 {
460 	void *driver_adapter = NULL;
461 	struct halmac_api *halmac_api;
462 	enum halmac_ret_status status = HALMAC_RET_SUCCESS;
463 
464 	if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
465 		return HALMAC_RET_ADAPTER_INVALID;
466 
467 	if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
468 		return HALMAC_RET_API_INVALID;
469 
470 	driver_adapter = halmac_adapter->driver_adapter;
471 	halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
472 
473 	if ((halmac_offset & 0xFFFF0000) == 0)
474 		halmac_offset |= WLAN_IOREG_OFFSET;
475 
476 	status = halmac_convert_to_sdio_bus_offset_88xx(halmac_adapter,
477 							&halmac_offset);
478 
479 	if (status != HALMAC_RET_SUCCESS) {
480 		pr_err("%s error = %x\n", __func__, status);
481 		return status;
482 	}
483 
484 	if (halmac_adapter->halmac_state.mac_power == HALMAC_MAC_POWER_OFF ||
485 	    (halmac_offset & (4 - 1)) != 0) {
486 		PLATFORM_SDIO_CMD52_WRITE(driver_adapter, halmac_offset,
487 					  (u8)(halmac_data & 0xFF));
488 		PLATFORM_SDIO_CMD52_WRITE(driver_adapter, halmac_offset + 1,
489 					  (u8)((halmac_data & 0xFF00) >> 8));
490 		PLATFORM_SDIO_CMD52_WRITE(driver_adapter, halmac_offset + 2,
491 					  (u8)((halmac_data & 0xFF0000) >> 16));
492 		PLATFORM_SDIO_CMD52_WRITE(
493 			driver_adapter, halmac_offset + 3,
494 			(u8)((halmac_data & 0xFF000000) >> 24));
495 	} else {
496 		PLATFORM_SDIO_CMD53_WRITE_32(driver_adapter, halmac_offset,
497 					     halmac_data);
498 	}
499 
500 	return HALMAC_RET_SUCCESS;
501 }
502 
503 /**
504  * halmac_reg_read_nbyte_sdio_88xx() - read n byte register
505  * @halmac_adapter : the adapter of halmac
506  * @halmac_offset : register offset
507  * @halmac_size : register value size
508  * @halmac_data : register value
509  * Author : Soar
510  * Return : enum halmac_ret_status
511  * More details of status code can be found in prototype document
512  */
halmac_reg_read_nbyte_sdio_88xx(struct halmac_adapter * halmac_adapter,u32 halmac_offset,u32 halmac_size,u8 * halmac_data)513 u8 halmac_reg_read_nbyte_sdio_88xx(struct halmac_adapter *halmac_adapter,
514 				   u32 halmac_offset, u32 halmac_size,
515 				   u8 *halmac_data)
516 {
517 	void *driver_adapter = NULL;
518 	struct halmac_api *halmac_api;
519 	enum halmac_ret_status status = HALMAC_RET_SUCCESS;
520 
521 	if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
522 		return HALMAC_RET_ADAPTER_INVALID;
523 
524 	if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
525 		return HALMAC_RET_API_INVALID;
526 
527 	driver_adapter = halmac_adapter->driver_adapter;
528 	halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
529 
530 	if ((halmac_offset & 0xFFFF0000) == 0) {
531 		pr_err("halmac_offset error = 0x%x\n", halmac_offset);
532 		return HALMAC_RET_FAIL;
533 	}
534 
535 	status = halmac_convert_to_sdio_bus_offset_88xx(halmac_adapter,
536 							&halmac_offset);
537 	if (status != HALMAC_RET_SUCCESS) {
538 		pr_err("%s error = %x\n", __func__, status);
539 		return status;
540 	}
541 
542 	if (halmac_adapter->halmac_state.mac_power == HALMAC_MAC_POWER_OFF) {
543 		pr_err("halmac_state error = 0x%x\n",
544 		       halmac_adapter->halmac_state.mac_power);
545 		return HALMAC_RET_FAIL;
546 	}
547 
548 	PLATFORM_SDIO_CMD53_READ_N(driver_adapter, halmac_offset, halmac_size,
549 				   halmac_data);
550 
551 	return HALMAC_RET_SUCCESS;
552 }
553 
554 /**
555  * halmac_get_sdio_tx_addr_sdio_88xx() - get CMD53 addr for the TX packet
556  * @halmac_adapter : the adapter of halmac
557  * @halmac_buf : tx packet, include txdesc
558  * @halmac_size : tx packet size
559  * @pcmd53_addr : cmd53 addr value
560  * Author : KaiYuan Chang/Ivan Lin
561  * Return : enum halmac_ret_status
562  * More details of status code can be found in prototype document
563  */
564 enum halmac_ret_status
halmac_get_sdio_tx_addr_88xx(struct halmac_adapter * halmac_adapter,u8 * halmac_buf,u32 halmac_size,u32 * pcmd53_addr)565 halmac_get_sdio_tx_addr_88xx(struct halmac_adapter *halmac_adapter,
566 			     u8 *halmac_buf, u32 halmac_size, u32 *pcmd53_addr)
567 {
568 	u32 four_byte_len;
569 	void *driver_adapter = NULL;
570 	struct halmac_api *halmac_api;
571 	enum halmac_queue_select queue_sel;
572 	enum halmac_dma_mapping dma_mapping;
573 
574 	if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
575 		return HALMAC_RET_ADAPTER_INVALID;
576 
577 	if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
578 		return HALMAC_RET_API_INVALID;
579 
580 	halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_GET_SDIO_TX_ADDR);
581 
582 	driver_adapter = halmac_adapter->driver_adapter;
583 	halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
584 
585 	HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
586 			"%s ==========>\n", __func__);
587 
588 	if (!halmac_buf) {
589 		pr_err("halmac_buf is NULL!!\n");
590 		return HALMAC_RET_DATA_BUF_NULL;
591 	}
592 
593 	if (halmac_size == 0) {
594 		pr_err("halmac_size is 0!!\n");
595 		return HALMAC_RET_DATA_SIZE_INCORRECT;
596 	}
597 
598 	queue_sel = (enum halmac_queue_select)GET_TX_DESC_QSEL(halmac_buf);
599 
600 	switch (queue_sel) {
601 	case HALMAC_QUEUE_SELECT_VO:
602 	case HALMAC_QUEUE_SELECT_VO_V2:
603 		dma_mapping =
604 			halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VO];
605 		break;
606 	case HALMAC_QUEUE_SELECT_VI:
607 	case HALMAC_QUEUE_SELECT_VI_V2:
608 		dma_mapping =
609 			halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VI];
610 		break;
611 	case HALMAC_QUEUE_SELECT_BE:
612 	case HALMAC_QUEUE_SELECT_BE_V2:
613 		dma_mapping =
614 			halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BE];
615 		break;
616 	case HALMAC_QUEUE_SELECT_BK:
617 	case HALMAC_QUEUE_SELECT_BK_V2:
618 		dma_mapping =
619 			halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BK];
620 		break;
621 	case HALMAC_QUEUE_SELECT_MGNT:
622 		dma_mapping =
623 			halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_MG];
624 		break;
625 	case HALMAC_QUEUE_SELECT_HIGH:
626 	case HALMAC_QUEUE_SELECT_BCN:
627 	case HALMAC_QUEUE_SELECT_CMD:
628 		dma_mapping =
629 			halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_HI];
630 		break;
631 	default:
632 		pr_err("Qsel is out of range\n");
633 		return HALMAC_RET_QSEL_INCORRECT;
634 	}
635 
636 	four_byte_len = (halmac_size >> 2) + ((halmac_size & (4 - 1)) ? 1 : 0);
637 
638 	switch (dma_mapping) {
639 	case HALMAC_DMA_MAPPING_HIGH:
640 		*pcmd53_addr = HALMAC_SDIO_CMD_ADDR_TXFF_HIGH;
641 		break;
642 	case HALMAC_DMA_MAPPING_NORMAL:
643 		*pcmd53_addr = HALMAC_SDIO_CMD_ADDR_TXFF_NORMAL;
644 		break;
645 	case HALMAC_DMA_MAPPING_LOW:
646 		*pcmd53_addr = HALMAC_SDIO_CMD_ADDR_TXFF_LOW;
647 		break;
648 	case HALMAC_DMA_MAPPING_EXTRA:
649 		*pcmd53_addr = HALMAC_SDIO_CMD_ADDR_TXFF_EXTRA;
650 		break;
651 	default:
652 		pr_err("DmaMapping is out of range\n");
653 		return HALMAC_RET_DMA_MAP_INCORRECT;
654 	}
655 
656 	*pcmd53_addr = (*pcmd53_addr << 13) |
657 		       (four_byte_len & HALMAC_SDIO_4BYTE_LEN_MASK);
658 
659 	HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
660 			"%s <==========\n", __func__);
661 
662 	return HALMAC_RET_SUCCESS;
663 }
664 
665 /**
666  * halmac_cfg_tx_agg_align_sdio_88xx() -config sdio bus tx agg alignment
667  * @halmac_adapter : the adapter of halmac
668  * @enable : function enable(1)/disable(0)
669  * @align_size : sdio bus tx agg alignment size (2^n, n = 3~11)
670  * Author : Soar Tu
671  * Return : enum halmac_ret_status
672  * More details of status code can be found in prototype document
673  */
674 enum halmac_ret_status
halmac_cfg_tx_agg_align_sdio_88xx(struct halmac_adapter * halmac_adapter,u8 enable,u16 align_size)675 halmac_cfg_tx_agg_align_sdio_88xx(struct halmac_adapter *halmac_adapter,
676 				  u8 enable, u16 align_size)
677 {
678 	struct halmac_api *halmac_api;
679 	void *driver_adapter = NULL;
680 	u8 i, align_size_ok = 0;
681 
682 	if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
683 		return HALMAC_RET_ADAPTER_INVALID;
684 
685 	if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
686 		return HALMAC_RET_API_INVALID;
687 
688 	halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_TX_AGG_ALIGN);
689 
690 	driver_adapter = halmac_adapter->driver_adapter;
691 	halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
692 
693 	HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
694 			"%s ==========>\n", __func__);
695 
696 	if ((align_size & 0xF000) != 0) {
697 		pr_err("Align size is out of range\n");
698 		return HALMAC_RET_FAIL;
699 	}
700 
701 	for (i = 3; i <= 11; i++) {
702 		if (align_size == 1 << i) {
703 			align_size_ok = 1;
704 			break;
705 		}
706 	}
707 	if (align_size_ok == 0) {
708 		pr_err("Align size is not 2^3 ~ 2^11\n");
709 		return HALMAC_RET_FAIL;
710 	}
711 
712 	/*Keep sdio tx agg alignment size for driver query*/
713 	halmac_adapter->hw_config_info.tx_align_size = align_size;
714 
715 	if (enable)
716 		HALMAC_REG_WRITE_16(halmac_adapter, REG_RQPN_CTRL_2,
717 				    0x8000 | align_size);
718 	else
719 		HALMAC_REG_WRITE_16(halmac_adapter, REG_RQPN_CTRL_2,
720 				    align_size);
721 
722 	HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
723 			"%s <==========\n", __func__);
724 
725 	return HALMAC_RET_SUCCESS;
726 }
727 
halmac_cfg_tx_agg_align_sdio_not_support_88xx(struct halmac_adapter * halmac_adapter,u8 enable,u16 align_size)728 enum halmac_ret_status halmac_cfg_tx_agg_align_sdio_not_support_88xx(
729 	struct halmac_adapter *halmac_adapter, u8 enable, u16 align_size)
730 {
731 	struct halmac_api *halmac_api;
732 	void *driver_adapter = NULL;
733 
734 	if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
735 		return HALMAC_RET_ADAPTER_INVALID;
736 
737 	if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
738 		return HALMAC_RET_API_INVALID;
739 
740 	halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_TX_AGG_ALIGN);
741 
742 	driver_adapter = halmac_adapter->driver_adapter;
743 	halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
744 
745 	HALMAC_RT_TRACE(
746 		driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
747 		"%s ==========>\n", __func__);
748 
749 	HALMAC_RT_TRACE(
750 		driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
751 		"%s not support\n", __func__);
752 	HALMAC_RT_TRACE(
753 		driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
754 		"%s <==========\n", __func__);
755 
756 	return HALMAC_RET_SUCCESS;
757 }
758 
759 /**
760  * halmac_tx_allowed_sdio_88xx() - check tx status
761  * @halmac_adapter : the adapter of halmac
762  * @halmac_buf : tx packet, include txdesc
763  * @halmac_size : tx packet size, include txdesc
764  * Author : Ivan Lin
765  * Return : enum halmac_ret_status
766  * More details of status code can be found in prototype document
767  */
768 enum halmac_ret_status
halmac_tx_allowed_sdio_88xx(struct halmac_adapter * halmac_adapter,u8 * halmac_buf,u32 halmac_size)769 halmac_tx_allowed_sdio_88xx(struct halmac_adapter *halmac_adapter,
770 			    u8 *halmac_buf, u32 halmac_size)
771 {
772 	u8 *curr_packet;
773 	u16 *curr_free_space;
774 	u32 i, counter;
775 	u32 tx_agg_num, packet_size = 0;
776 	u32 tx_required_page_num, total_required_page_num = 0;
777 	enum halmac_ret_status status = HALMAC_RET_SUCCESS;
778 	void *driver_adapter = NULL;
779 	enum halmac_dma_mapping dma_mapping;
780 
781 	if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
782 		return HALMAC_RET_ADAPTER_INVALID;
783 
784 	if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
785 		return HALMAC_RET_API_INVALID;
786 
787 	halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_TX_ALLOWED_SDIO);
788 
789 	driver_adapter = halmac_adapter->driver_adapter;
790 
791 	HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
792 			"%s ==========>\n", __func__);
793 
794 	tx_agg_num = GET_TX_DESC_DMA_TXAGG_NUM(halmac_buf);
795 	curr_packet = halmac_buf;
796 
797 	tx_agg_num = tx_agg_num == 0 ? 1 : tx_agg_num;
798 
799 	switch ((enum halmac_queue_select)GET_TX_DESC_QSEL(curr_packet)) {
800 	case HALMAC_QUEUE_SELECT_VO:
801 	case HALMAC_QUEUE_SELECT_VO_V2:
802 		dma_mapping =
803 			halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VO];
804 		break;
805 	case HALMAC_QUEUE_SELECT_VI:
806 	case HALMAC_QUEUE_SELECT_VI_V2:
807 		dma_mapping =
808 			halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VI];
809 		break;
810 	case HALMAC_QUEUE_SELECT_BE:
811 	case HALMAC_QUEUE_SELECT_BE_V2:
812 		dma_mapping =
813 			halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BE];
814 		break;
815 	case HALMAC_QUEUE_SELECT_BK:
816 	case HALMAC_QUEUE_SELECT_BK_V2:
817 		dma_mapping =
818 			halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BK];
819 		break;
820 	case HALMAC_QUEUE_SELECT_MGNT:
821 		dma_mapping =
822 			halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_MG];
823 		break;
824 	case HALMAC_QUEUE_SELECT_HIGH:
825 		dma_mapping =
826 			halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_HI];
827 		break;
828 	case HALMAC_QUEUE_SELECT_BCN:
829 	case HALMAC_QUEUE_SELECT_CMD:
830 		return HALMAC_RET_SUCCESS;
831 	default:
832 		pr_err("Qsel is out of range\n");
833 		return HALMAC_RET_QSEL_INCORRECT;
834 	}
835 
836 	switch (dma_mapping) {
837 	case HALMAC_DMA_MAPPING_HIGH:
838 		curr_free_space =
839 			&halmac_adapter->sdio_free_space.high_queue_number;
840 		break;
841 	case HALMAC_DMA_MAPPING_NORMAL:
842 		curr_free_space =
843 			&halmac_adapter->sdio_free_space.normal_queue_number;
844 		break;
845 	case HALMAC_DMA_MAPPING_LOW:
846 		curr_free_space =
847 			&halmac_adapter->sdio_free_space.low_queue_number;
848 		break;
849 	case HALMAC_DMA_MAPPING_EXTRA:
850 		curr_free_space =
851 			&halmac_adapter->sdio_free_space.extra_queue_number;
852 		break;
853 	default:
854 		pr_err("DmaMapping is out of range\n");
855 		return HALMAC_RET_DMA_MAP_INCORRECT;
856 	}
857 
858 	for (i = 0; i < tx_agg_num; i++) {
859 		packet_size = GET_TX_DESC_TXPKTSIZE(curr_packet) +
860 			      GET_TX_DESC_OFFSET(curr_packet) +
861 			      (GET_TX_DESC_PKT_OFFSET(curr_packet) << 3);
862 		tx_required_page_num =
863 			(packet_size >>
864 			 halmac_adapter->hw_config_info.page_size_2_power) +
865 			((packet_size &
866 			  (halmac_adapter->hw_config_info.page_size - 1)) ?
867 				 1 :
868 				 0);
869 		total_required_page_num += tx_required_page_num;
870 
871 		packet_size = HALMAC_ALIGN(packet_size, 8);
872 
873 		curr_packet += packet_size;
874 	}
875 
876 	counter = 10;
877 	do {
878 		if ((u32)(*curr_free_space +
879 			  halmac_adapter->sdio_free_space.public_queue_number) >
880 		    total_required_page_num) {
881 			if (*curr_free_space >= total_required_page_num) {
882 				*curr_free_space -=
883 					(u16)total_required_page_num;
884 			} else {
885 				halmac_adapter->sdio_free_space
886 					.public_queue_number -=
887 					(u16)(total_required_page_num -
888 					      *curr_free_space);
889 				*curr_free_space = 0;
890 			}
891 
892 			status = halmac_check_oqt_88xx(halmac_adapter,
893 						       tx_agg_num, halmac_buf);
894 
895 			if (status != HALMAC_RET_SUCCESS)
896 				return status;
897 
898 			break;
899 		}
900 
901 		halmac_update_sdio_free_page_88xx(halmac_adapter);
902 
903 		counter--;
904 		if (counter == 0)
905 			return HALMAC_RET_FREE_SPACE_NOT_ENOUGH;
906 	} while (1);
907 
908 	HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
909 			"%s <==========\n", __func__);
910 
911 	return HALMAC_RET_SUCCESS;
912 }
913 
914 /**
915  * halmac_reg_read_indirect_32_sdio_88xx() - read MAC reg by SDIO reg
916  * @halmac_adapter : the adapter of halmac
917  * @halmac_offset : register offset
918  * Author : Soar
919  * Return : enum halmac_ret_status
920  * More details of status code can be found in prototype document
921  */
halmac_reg_read_indirect_32_sdio_88xx(struct halmac_adapter * halmac_adapter,u32 halmac_offset)922 u32 halmac_reg_read_indirect_32_sdio_88xx(struct halmac_adapter *halmac_adapter,
923 					  u32 halmac_offset)
924 {
925 	u8 rtemp;
926 	u32 counter = 1000;
927 	void *driver_adapter = NULL;
928 
929 	union {
930 		u32 dword;
931 		u8 byte[4];
932 	} value32 = {0x00000000};
933 
934 	if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
935 		return HALMAC_RET_ADAPTER_INVALID;
936 
937 	if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
938 		return HALMAC_RET_API_INVALID;
939 
940 	driver_adapter = halmac_adapter->driver_adapter;
941 
942 	PLATFORM_SDIO_CMD53_WRITE_32(
943 		driver_adapter,
944 		(HALMAC_SDIO_CMD_ADDR_SDIO_REG << 13) |
945 			(REG_SDIO_INDIRECT_REG_CFG & HALMAC_SDIO_LOCAL_MSK),
946 		halmac_offset | BIT(19) | BIT(17));
947 
948 	do {
949 		rtemp = PLATFORM_SDIO_CMD52_READ(
950 			driver_adapter,
951 			(HALMAC_SDIO_CMD_ADDR_SDIO_REG << 13) |
952 				((REG_SDIO_INDIRECT_REG_CFG + 2) &
953 				 HALMAC_SDIO_LOCAL_MSK));
954 		counter--;
955 	} while ((rtemp & BIT(4)) != 0 && counter > 0);
956 
957 	value32.dword = PLATFORM_SDIO_CMD53_READ_32(
958 		driver_adapter,
959 		(HALMAC_SDIO_CMD_ADDR_SDIO_REG << 13) |
960 			(REG_SDIO_INDIRECT_REG_DATA & HALMAC_SDIO_LOCAL_MSK));
961 
962 	return value32.dword;
963 }
964