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