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