GNU Linux-libre 4.19.286-gnu1
[releases.git] / drivers / staging / rtlwifi / halmac / halmac_88xx / halmac_api_88xx_sdio.c
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
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
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
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  */
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
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  */
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
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  */
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
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  */
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
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
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
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
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  */
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 }