GNU Linux-libre 4.19.264-gnu1
[releases.git] / drivers / staging / rtlwifi / halmac / halmac_api.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_2_platform.h"
15 #include "halmac_type.h"
16 #include "halmac_88xx/halmac_api_88xx.h"
17 #include "halmac_88xx/halmac_88xx_cfg.h"
18
19 #include "halmac_88xx/halmac_8822b/halmac_8822b_cfg.h"
20
21 static enum halmac_ret_status
22 halmac_check_platform_api(void *driver_adapter,
23                           enum halmac_interface halmac_interface,
24                           struct halmac_platform_api *halmac_platform_api)
25 {
26         void *adapter_local = NULL;
27
28         adapter_local = driver_adapter;
29
30         if (!halmac_platform_api)
31                 return HALMAC_RET_PLATFORM_API_NULL;
32
33         if (halmac_interface == HALMAC_INTERFACE_SDIO) {
34                 if (!halmac_platform_api->SDIO_CMD52_READ) {
35                         pr_err("(!halmac_platform_api->SDIO_CMD52_READ)\n");
36                         return HALMAC_RET_PLATFORM_API_NULL;
37                 }
38                 if (!halmac_platform_api->SDIO_CMD53_READ_8) {
39                         pr_err("(!halmac_platform_api->SDIO_CMD53_READ_8)\n");
40                         return HALMAC_RET_PLATFORM_API_NULL;
41                 }
42                 if (!halmac_platform_api->SDIO_CMD53_READ_16) {
43                         pr_err("(!halmac_platform_api->SDIO_CMD53_READ_16)\n");
44                         return HALMAC_RET_PLATFORM_API_NULL;
45                 }
46                 if (!halmac_platform_api->SDIO_CMD53_READ_32) {
47                         pr_err("(!halmac_platform_api->SDIO_CMD53_READ_32)\n");
48                         return HALMAC_RET_PLATFORM_API_NULL;
49                 }
50                 if (!halmac_platform_api->SDIO_CMD53_READ_N) {
51                         pr_err("(!halmac_platform_api->SDIO_CMD53_READ_N)\n");
52                         return HALMAC_RET_PLATFORM_API_NULL;
53                 }
54                 if (!halmac_platform_api->SDIO_CMD52_WRITE) {
55                         pr_err("(!halmac_platform_api->SDIO_CMD52_WRITE)\n");
56                         return HALMAC_RET_PLATFORM_API_NULL;
57                 }
58                 if (!halmac_platform_api->SDIO_CMD53_WRITE_8) {
59                         pr_err("(!halmac_platform_api->SDIO_CMD53_WRITE_8)\n");
60                         return HALMAC_RET_PLATFORM_API_NULL;
61                 }
62                 if (!halmac_platform_api->SDIO_CMD53_WRITE_16) {
63                         pr_err("(!halmac_platform_api->SDIO_CMD53_WRITE_16)\n");
64                         return HALMAC_RET_PLATFORM_API_NULL;
65                 }
66                 if (!halmac_platform_api->SDIO_CMD53_WRITE_32) {
67                         pr_err("(!halmac_platform_api->SDIO_CMD53_WRITE_32)\n");
68                         return HALMAC_RET_PLATFORM_API_NULL;
69                 }
70         }
71
72         if (halmac_interface == HALMAC_INTERFACE_USB ||
73             halmac_interface == HALMAC_INTERFACE_PCIE) {
74                 if (!halmac_platform_api->REG_READ_8) {
75                         pr_err("(!halmac_platform_api->REG_READ_8)\n");
76                         return HALMAC_RET_PLATFORM_API_NULL;
77                 }
78                 if (!halmac_platform_api->REG_READ_16) {
79                         pr_err("(!halmac_platform_api->REG_READ_16)\n");
80                         return HALMAC_RET_PLATFORM_API_NULL;
81                 }
82                 if (!halmac_platform_api->REG_READ_32) {
83                         pr_err("(!halmac_platform_api->REG_READ_32)\n");
84                         return HALMAC_RET_PLATFORM_API_NULL;
85                 }
86                 if (!halmac_platform_api->REG_WRITE_8) {
87                         pr_err("(!halmac_platform_api->REG_WRITE_8)\n");
88                         return HALMAC_RET_PLATFORM_API_NULL;
89                 }
90                 if (!halmac_platform_api->REG_WRITE_16) {
91                         pr_err("(!halmac_platform_api->REG_WRITE_16)\n");
92                         return HALMAC_RET_PLATFORM_API_NULL;
93                 }
94                 if (!halmac_platform_api->REG_WRITE_32) {
95                         pr_err("(!halmac_platform_api->REG_WRITE_32)\n");
96                         return HALMAC_RET_PLATFORM_API_NULL;
97                 }
98         }
99
100         if (!halmac_platform_api->EVENT_INDICATION) {
101                 pr_err("(!halmac_platform_api->EVENT_INDICATION)\n");
102                 return HALMAC_RET_PLATFORM_API_NULL;
103         }
104
105         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
106                         "%s ==========>\n", __func__);
107
108         return HALMAC_RET_SUCCESS;
109 }
110
111 static enum halmac_ret_status
112 halmac_convert_to_sdio_bus_offset(u32 *halmac_offset)
113 {
114         switch ((*halmac_offset) & 0xFFFF0000) {
115         case WLAN_IOREG_OFFSET:
116                 *halmac_offset = (HALMAC_SDIO_CMD_ADDR_MAC_REG << 13) |
117                                  (*halmac_offset & HALMAC_WLAN_MAC_REG_MSK);
118                 break;
119         case SDIO_LOCAL_OFFSET:
120                 *halmac_offset = (HALMAC_SDIO_CMD_ADDR_SDIO_REG << 13) |
121                                  (*halmac_offset & HALMAC_SDIO_LOCAL_MSK);
122                 break;
123         default:
124                 *halmac_offset = 0xFFFFFFFF;
125                 return HALMAC_RET_CONVERT_SDIO_OFFSET_FAIL;
126         }
127
128         return HALMAC_RET_SUCCESS;
129 }
130
131 static u8
132 platform_reg_read_8_sdio(void *driver_adapter,
133                          struct halmac_platform_api *halmac_platform_api,
134                          u32 offset)
135 {
136         u8 value8;
137         u32 halmac_offset = offset;
138         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
139
140         if ((halmac_offset & 0xFFFF0000) == 0)
141                 halmac_offset |= WLAN_IOREG_OFFSET;
142
143         status = halmac_convert_to_sdio_bus_offset(&halmac_offset);
144         if (status != HALMAC_RET_SUCCESS) {
145                 pr_err("%s error = %x\n", __func__, status);
146                 return status;
147         }
148
149         value8 = halmac_platform_api->SDIO_CMD52_READ(driver_adapter,
150                                                       halmac_offset);
151
152         return value8;
153 }
154
155 static enum halmac_ret_status
156 platform_reg_write_8_sdio(void *driver_adapter,
157                           struct halmac_platform_api *halmac_platform_api,
158                           u32 offset, u8 data)
159 {
160         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
161         u32 halmac_offset = offset;
162
163         if ((halmac_offset & 0xFFFF0000) == 0)
164                 halmac_offset |= WLAN_IOREG_OFFSET;
165
166         status = halmac_convert_to_sdio_bus_offset(&halmac_offset);
167
168         if (status != HALMAC_RET_SUCCESS) {
169                 pr_err("halmac_reg_write_8_sdio_88xx error = %x\n", status);
170                 return status;
171         }
172         halmac_platform_api->SDIO_CMD52_WRITE(driver_adapter, halmac_offset,
173                                               data);
174
175         return HALMAC_RET_SUCCESS;
176 }
177
178 static enum halmac_ret_status
179 halmac_get_chip_info(void *driver_adapter,
180                      struct halmac_platform_api *halmac_platform_api,
181                      enum halmac_interface halmac_interface,
182                      struct halmac_adapter *halmac_adapter)
183 {
184         struct halmac_api *halmac_api = (struct halmac_api *)NULL;
185         u8 chip_id, chip_version;
186         u32 polling_count;
187
188         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
189
190         /* Get Chip_id and Chip_version */
191         if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_SDIO) {
192                 platform_reg_write_8_sdio(
193                         driver_adapter, halmac_platform_api, REG_SDIO_HSUS_CTRL,
194                         platform_reg_read_8_sdio(driver_adapter,
195                                                  halmac_platform_api,
196                                                  REG_SDIO_HSUS_CTRL) &
197                                 ~(BIT(0)));
198
199                 polling_count = 10000;
200                 while (!(platform_reg_read_8_sdio(driver_adapter,
201                                                   halmac_platform_api,
202                                                   REG_SDIO_HSUS_CTRL) &
203                          0x02)) {
204                         polling_count--;
205                         if (polling_count == 0)
206                                 return HALMAC_RET_SDIO_LEAVE_SUSPEND_FAIL;
207                 }
208
209                 chip_id = platform_reg_read_8_sdio(
210                         driver_adapter, halmac_platform_api, REG_SYS_CFG2);
211                 chip_version = platform_reg_read_8_sdio(driver_adapter,
212                                                         halmac_platform_api,
213                                                         REG_SYS_CFG1 + 1) >>
214                                4;
215         } else {
216                 chip_id = halmac_platform_api->REG_READ_8(driver_adapter,
217                                                           REG_SYS_CFG2);
218                 chip_version = halmac_platform_api->REG_READ_8(
219                                        driver_adapter, REG_SYS_CFG1 + 1) >>
220                                4;
221         }
222
223         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
224                         "[TRACE]Chip id : 0x%X\n", chip_id);
225         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
226                         "[TRACE]Chip version : 0x%X\n", chip_version);
227
228         halmac_adapter->chip_version = (enum halmac_chip_ver)chip_version;
229
230         if (chip_id == HALMAC_CHIP_ID_HW_DEF_8822B)
231                 halmac_adapter->chip_id = HALMAC_CHIP_ID_8822B;
232         else if (chip_id == HALMAC_CHIP_ID_HW_DEF_8821C)
233                 halmac_adapter->chip_id = HALMAC_CHIP_ID_8821C;
234         else if (chip_id == HALMAC_CHIP_ID_HW_DEF_8814B)
235                 halmac_adapter->chip_id = HALMAC_CHIP_ID_8814B;
236         else if (chip_id == HALMAC_CHIP_ID_HW_DEF_8197F)
237                 halmac_adapter->chip_id = HALMAC_CHIP_ID_8197F;
238         else
239                 halmac_adapter->chip_id = HALMAC_CHIP_ID_UNDEFINE;
240
241         if (halmac_adapter->chip_id == HALMAC_CHIP_ID_UNDEFINE)
242                 return HALMAC_RET_CHIP_NOT_SUPPORT;
243
244         return HALMAC_RET_SUCCESS;
245 }
246
247 /**
248  * halmac_init_adapter() - init halmac_adapter
249  * @driver_adapter : the adapter of caller
250  * @halmac_platform_api : the platform APIs which is used in halmac APIs
251  * @halmac_interface : bus interface
252  * @pp_halmac_adapter : the adapter of halmac
253  * @pp_halmac_api : the function pointer of APIs, caller shall call APIs by
254  *                 function pointer
255  * Author : KaiYuan Chang / Ivan Lin
256  * Return : enum halmac_ret_status
257  * More details of status code can be found in prototype document
258  */
259 enum halmac_ret_status
260 halmac_init_adapter(void *driver_adapter,
261                     struct halmac_platform_api *halmac_platform_api,
262                     enum halmac_interface halmac_interface,
263                     struct halmac_adapter **pp_halmac_adapter,
264                     struct halmac_api **pp_halmac_api)
265 {
266         struct halmac_adapter *halmac_adapter = (struct halmac_adapter *)NULL;
267         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
268
269         union {
270                 u32 i;
271                 u8 x[4];
272         } ENDIAN_CHECK = {0x01000000};
273
274         status = halmac_check_platform_api(driver_adapter, halmac_interface,
275                                            halmac_platform_api);
276         if (status != HALMAC_RET_SUCCESS)
277                 return status;
278         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
279                         HALMAC_SVN_VER "\n");
280         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
281                         "HALMAC_MAJOR_VER = %x\n", HALMAC_MAJOR_VER);
282         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
283                         "HALMAC_PROTOTYPE_VER = %x\n", HALMAC_PROTOTYPE_VER);
284         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
285                         "HALMAC_MINOR_VER = %x\n", HALMAC_MINOR_VER);
286         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
287                         "HALMAC_PATCH_VER = %x\n", HALMAC_PATCH_VER);
288
289         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
290                         "halmac_init_adapter_88xx ==========>\n");
291
292         /* Check endian setting - Little endian : 1, Big endian : 0*/
293         if (ENDIAN_CHECK.x[0] == HALMAC_SYSTEM_ENDIAN) {
294                 pr_err("Endian setting Err!!\n");
295                 return HALMAC_RET_ENDIAN_ERR;
296         }
297
298         halmac_adapter = kzalloc(sizeof(*halmac_adapter), GFP_KERNEL);
299         if (!halmac_adapter) {
300                 /* out of memory */
301                 return HALMAC_RET_MALLOC_FAIL;
302         }
303
304         /* return halmac adapter address to caller */
305         *pp_halmac_adapter = halmac_adapter;
306
307         /* Record caller info */
308         halmac_adapter->halmac_platform_api = halmac_platform_api;
309         halmac_adapter->driver_adapter = driver_adapter;
310         halmac_interface = halmac_interface == HALMAC_INTERFACE_AXI ?
311                                    HALMAC_INTERFACE_PCIE :
312                                    halmac_interface;
313         halmac_adapter->halmac_interface = halmac_interface;
314
315         spin_lock_init(&halmac_adapter->efuse_lock);
316         spin_lock_init(&halmac_adapter->h2c_seq_lock);
317
318         /*Get Chip*/
319         if (halmac_get_chip_info(driver_adapter, halmac_platform_api,
320                                  halmac_interface,
321                                  halmac_adapter) != HALMAC_RET_SUCCESS) {
322                 pr_err("HALMAC_RET_CHIP_NOT_SUPPORT\n");
323                 return HALMAC_RET_CHIP_NOT_SUPPORT;
324         }
325
326         /* Assign function pointer to halmac API */
327         halmac_init_adapter_para_88xx(halmac_adapter);
328         status = halmac_mount_api_88xx(halmac_adapter);
329
330         /* Return halmac API function pointer */
331         *pp_halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
332
333         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
334                         "halmac_init_adapter_88xx <==========\n");
335
336         return status;
337 }
338
339 /**
340  * halmac_halt_api() - stop halmac_api action
341  * @halmac_adapter : the adapter of halmac
342  * Author : Ivan Lin
343  * Return : enum halmac_ret_status
344  * More details of status code can be found in prototype document
345  */
346 enum halmac_ret_status halmac_halt_api(struct halmac_adapter *halmac_adapter)
347 {
348         void *driver_adapter = NULL;
349         struct halmac_platform_api *halmac_platform_api =
350                 (struct halmac_platform_api *)NULL;
351
352         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
353                 return HALMAC_RET_ADAPTER_INVALID;
354
355         driver_adapter = halmac_adapter->driver_adapter;
356         halmac_platform_api = halmac_adapter->halmac_platform_api;
357
358         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
359                         "%s ==========>\n", __func__);
360         halmac_adapter->halmac_state.api_state = HALMAC_API_STATE_HALT;
361         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
362                         "%s ==========>\n", __func__);
363         return HALMAC_RET_SUCCESS;
364 }
365
366 /**
367  * halmac_deinit_adapter() - deinit halmac adapter
368  * @halmac_adapter : the adapter of halmac
369  * Author : KaiYuan Chang / Ivan Lin
370  * Return : enum halmac_ret_status
371  * More details of status code can be found in prototype document
372  */
373 enum halmac_ret_status
374 halmac_deinit_adapter(struct halmac_adapter *halmac_adapter)
375 {
376         void *driver_adapter = NULL;
377
378         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
379                 return HALMAC_RET_ADAPTER_INVALID;
380
381         driver_adapter = halmac_adapter->driver_adapter;
382
383         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
384                         "[TRACE]halmac_deinit_adapter_88xx ==========>\n");
385
386         kfree(halmac_adapter->hal_efuse_map);
387         halmac_adapter->hal_efuse_map = (u8 *)NULL;
388
389         kfree(halmac_adapter->halmac_state.psd_set.data);
390         halmac_adapter->halmac_state.psd_set.data = (u8 *)NULL;
391
392         kfree(halmac_adapter->halmac_api);
393         halmac_adapter->halmac_api = NULL;
394
395         halmac_adapter->hal_adapter_backup = NULL;
396         kfree(halmac_adapter);
397
398         return HALMAC_RET_SUCCESS;
399 }
400
401 /**
402  * halmac_get_version() - get HALMAC version
403  * @version : return version of major, prototype and minor information
404  * Author : KaiYuan Chang / Ivan Lin
405  * Return : enum halmac_ret_status
406  * More details of status code can be found in prototype document
407  */
408 enum halmac_ret_status halmac_get_version(struct halmac_ver *version)
409 {
410         version->major_ver = (u8)HALMAC_MAJOR_VER;
411         version->prototype_ver = (u8)HALMAC_PROTOTYPE_VER;
412         version->minor_ver = (u8)HALMAC_MINOR_VER;
413
414         return HALMAC_RET_SUCCESS;
415 }