net: wireless: rockchip_wlan: add rtl8723ds support
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8723ds / hal / hal_hci / hal_sdio.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20 #define _HAL_SDIO_C_
21
22 #include <drv_types.h>
23 #include <hal_data.h>
24
25 #ifndef RTW_HALMAC
26 static void dump_sdio_f0(PADAPTER padapter)
27 {
28         char str_out[128];
29         char str_val[8];
30         char *p = NULL;
31         int index = 0, i = 0;
32         u8 val8 = 0, len = 0;
33
34         RTW_ERR("Dump SDIO function_0 register:\n");
35         for (index = 0 ; index < 0x100 ; index += 16) {
36                 p = &str_out[0];
37                 len = snprintf(str_val, sizeof(str_val),
38                                "0x%02x: ", index);
39                 strncpy(str_out, str_val, len);
40                 p += len;
41
42                 for (i = 0 ; i < 16 ; i++) {
43                         len = snprintf(str_val, sizeof(str_val), "%02x ",
44                                        rtw_sd_f0_read8(padapter, index + i));
45                         strncpy(p, str_val, len);
46                         p += len;
47                 }
48                 RTW_INFO("%s\n", str_out);
49                 _rtw_memset(&str_out, '\0', sizeof(str_out));
50         }
51 }
52
53 static void dump_sdio_local(PADAPTER padapter)
54 {
55         char str_out[128];
56         char str_val[8];
57         char *p = NULL;
58         int index = 0, i = 0;
59         u8 val8 = 0, len = 0;
60
61         RTW_ERR("Dump SDIO local register:\n");
62         for (index = 0 ; index < 0x100 ; index += 16) {
63                 p = &str_out[0];
64                 len = snprintf(str_val, sizeof(str_val),
65                                "0x%02x: ", index);
66                 strncpy(str_out, str_val, len);
67                 p += len;
68
69                 for (i = 0 ; i < 16 ; i++) {
70                         len = snprintf(str_val, sizeof(str_val), "%02x ",
71                                        rtw_read8(padapter, (0x1025 << 16) | (index + i)));
72                         strncpy(p, str_val, len);
73                         p += len;
74                 }
75                 RTW_INFO("%s\n", str_out);
76                 _rtw_memset(&str_out, '\0', sizeof(str_out));
77         }
78 }
79
80 static void dump_mac_page0(PADAPTER padapter)
81 {
82         char str_out[128];
83         char str_val[8];
84         char *p = NULL;
85         int index = 0, i = 0;
86         u8 val8 = 0, len = 0;
87
88         RTW_ERR("Dump MAC Page0 register:\n");
89         for (index = 0 ; index < 0x100 ; index += 16) {
90                 p = &str_out[0];
91                 len = snprintf(str_val, sizeof(str_val),
92                                "0x%02x: ", index);
93                 strncpy(str_out, str_val, len);
94                 p += len;
95
96                 for (i = 0 ; i < 16 ; i++) {
97                         len = snprintf(str_val, sizeof(str_val), "%02x ",
98                                        rtw_read8(padapter, index + i));
99                         strncpy(p, str_val, len);
100                         p += len;
101                 }
102                 RTW_INFO("%s\n", str_out);
103                 _rtw_memset(&str_out, '\0', sizeof(str_out));
104         }
105 }
106
107 /*
108  * Description:
109  *      Call this function to make sure power on successfully
110  *
111  * Return:
112  *      _SUCCESS        enable success
113  *      _FAIL   enable fail
114  */
115 bool sdio_power_on_check(PADAPTER padapter) {
116         u32 val_offset0, val_offset1, val_offset2, val_offset3;
117         u32 val_mix = 0;
118         u32 res = 0;
119         bool ret = _FAIL;
120         int index = 0;
121
122         val_offset0 = rtw_read8(padapter, REG_CR);
123         val_offset1 = rtw_read8(padapter, REG_CR + 1);
124         val_offset2 = rtw_read8(padapter, REG_CR + 2);
125         val_offset3 = rtw_read8(padapter, REG_CR + 3);
126
127         if (val_offset0 == 0xEA || val_offset1 == 0xEA ||
128             val_offset2 == 0xEA || val_offset3 == 0xEA) {
129                 RTW_INFO("%s: power on fail, do Power on again\n", __func__);
130                 goto _exit;
131         }
132
133         val_mix = val_offset3 << 24 | val_mix;
134         val_mix = val_offset2 << 16 | val_mix;
135         val_mix = val_offset1 << 8 | val_mix;
136         val_mix = val_offset0 | val_mix;
137
138         res = rtw_read32(padapter, REG_CR);
139
140         RTW_INFO("%s: val_mix:0x%08x, res:0x%08x\n", __func__, val_mix, res);
141
142         while (index < 100) {
143                 if (res == val_mix) {
144                         RTW_INFO("%s: 0x100 the result of cmd52 and cmd53 is the same.\n", __func__);
145                         ret = _SUCCESS;
146                         break;
147                 } else {
148                         RTW_INFO("%s: 0x100 cmd52 and cmd53 is not the same(index:%d).\n", __func__, index);
149                         res = rtw_read32(padapter, REG_CR);
150                         index++;
151                         ret = _FAIL;
152                 }
153         }
154
155         if (ret) {
156                 index = 0;
157                 while (index < 100) {
158                         rtw_write32(padapter, 0x1B8, 0x12345678);
159                         res = rtw_read32(padapter, 0x1B8);
160                         if (res == 0x12345678) {
161                                 RTW_INFO("%s: 0x1B8 test Pass.\n", __func__);
162                                 ret = _SUCCESS;
163                                 break;
164                         } else {
165                                 index++;
166                                 RTW_INFO("%s: 0x1B8 test Fail(index: %d).\n", __func__, index);
167                                 ret = _FAIL;
168                         }
169                 }
170         } else
171                 RTW_INFO("%s: fail at cmd52, cmd53.\n", __func__);
172
173 _exit:
174         if (ret == _FAIL) {
175                 dump_sdio_f0(padapter);
176                 dump_sdio_local(padapter);
177                 dump_mac_page0(padapter);
178         }
179
180         return ret;
181 }
182
183 u8 rtw_hal_sdio_max_txoqt_free_space(_adapter *padapter)
184 {
185         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
186
187         if (pHalData->SdioTxOQTMaxFreeSpace < 8)
188                 pHalData->SdioTxOQTMaxFreeSpace = 8;
189
190         return pHalData->SdioTxOQTMaxFreeSpace;
191 }
192
193 u8 rtw_hal_sdio_query_tx_freepage(_adapter *padapter, u8 PageIdx, u8 RequiredPageNum)
194 {
195         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
196
197         if ((pHalData->SdioTxFIFOFreePage[PageIdx] + pHalData->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]) >= (RequiredPageNum))
198                 return _TRUE;
199         else
200                 return _FALSE;
201 }
202
203 void rtw_hal_sdio_update_tx_freepage(_adapter *padapter, u8 PageIdx, u8 RequiredPageNum)
204 {
205         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
206         u8      DedicatedPgNum = 0;
207         u8      RequiredPublicFreePgNum = 0;
208         /* _irqL irql; */
209
210         /* _enter_critical_bh(&pHalData->SdioTxFIFOFreePageLock, &irql); */
211
212         DedicatedPgNum = pHalData->SdioTxFIFOFreePage[PageIdx];
213         if (RequiredPageNum <= DedicatedPgNum)
214                 pHalData->SdioTxFIFOFreePage[PageIdx] -= RequiredPageNum;
215         else {
216                 pHalData->SdioTxFIFOFreePage[PageIdx] = 0;
217                 RequiredPublicFreePgNum = RequiredPageNum - DedicatedPgNum;
218                 pHalData->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX] -= RequiredPublicFreePgNum;
219         }
220
221         /* _exit_critical_bh(&pHalData->SdioTxFIFOFreePageLock, &irql); */
222 }
223
224 void rtw_hal_set_sdio_tx_max_length(PADAPTER padapter, u8 numHQ, u8 numNQ, u8 numLQ, u8 numPubQ)
225 {
226         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
227         u32     page_size;
228         u32     lenHQ, lenNQ, lenLQ;
229
230         rtw_hal_get_def_var(padapter, HAL_DEF_TX_PAGE_SIZE, &page_size);
231
232         lenHQ = ((numHQ + numPubQ) >> 1) * page_size;
233         lenNQ = ((numNQ + numPubQ) >> 1) * page_size;
234         lenLQ = ((numLQ + numPubQ) >> 1) * page_size;
235
236         pHalData->sdio_tx_max_len[HI_QUEUE_IDX] = (lenHQ > MAX_XMITBUF_SZ) ? MAX_XMITBUF_SZ : lenHQ;
237         pHalData->sdio_tx_max_len[MID_QUEUE_IDX] = (lenNQ > MAX_XMITBUF_SZ) ? MAX_XMITBUF_SZ : lenNQ;
238         pHalData->sdio_tx_max_len[LOW_QUEUE_IDX] = (lenLQ > MAX_XMITBUF_SZ) ? MAX_XMITBUF_SZ : lenLQ;
239 }
240
241 u32 rtw_hal_get_sdio_tx_max_length(PADAPTER padapter, u8 queue_idx)
242 {
243         struct dvobj_priv       *pdvobjpriv = adapter_to_dvobj(padapter);
244         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
245         u32     deviceId, max_len;
246
247
248         deviceId = ffaddr2deviceId(pdvobjpriv, queue_idx);
249         switch (deviceId) {
250         case WLAN_TX_HIQ_DEVICE_ID:
251                 max_len = pHalData->sdio_tx_max_len[HI_QUEUE_IDX];
252                 break;
253
254         case WLAN_TX_MIQ_DEVICE_ID:
255                 max_len = pHalData->sdio_tx_max_len[MID_QUEUE_IDX];
256                 break;
257
258         case WLAN_TX_LOQ_DEVICE_ID:
259                 max_len = pHalData->sdio_tx_max_len[LOW_QUEUE_IDX];
260                 break;
261
262         default:
263                 max_len = pHalData->sdio_tx_max_len[MID_QUEUE_IDX];
264                 break;
265         }
266
267         return max_len;
268 }
269
270 #ifdef CONFIG_FW_C2H_REG
271 void sd_c2h_hisr_hdl(_adapter *adapter)
272 {
273         u8 c2h_evt[C2H_REG_LEN] = {0};
274         u8 id, seq, plen;
275         u8 *payload;
276
277         if (rtw_hal_c2h_evt_read(adapter, c2h_evt) != _SUCCESS)
278                 goto exit;
279
280         if (rtw_hal_c2h_reg_hdr_parse(adapter, c2h_evt, &id, &seq, &plen, &payload) != _SUCCESS)
281                 goto exit;
282                 
283         if (rtw_hal_c2h_id_handle_directly(adapter, id, seq, plen, payload)) {
284                 /* Handle directly */
285                 rtw_hal_c2h_handler(adapter, id, seq, plen, payload);
286                 goto exit;
287         }
288
289         if (rtw_c2h_reg_wk_cmd(adapter, c2h_evt) != _SUCCESS)
290                 RTW_ERR("%s rtw_c2h_reg_wk_cmd fail\n", __func__);
291
292 exit:
293         return;
294 }
295 #endif
296
297 #endif /* !RTW_HALMAC */