xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/rtl8723b/sdio/sdio_ops.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2017 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  *****************************************************************************/
15 #define _SDIO_OPS_C_
16 
17 #include <rtl8723b_hal.h>
18 
19 /* #define SDIO_DEBUG_IO 1 */
20 
21 
22 /*
23  * Description:
24  *	The following mapping is for SDIO host local register space.
25  *
26  * Creadted by Roger, 2011.01.31.
27  *   */
HalSdioGetCmdAddr8723BSdio(IN PADAPTER padapter,IN u8 DeviceID,IN u32 Addr,OUT u32 * pCmdAddr)28 static void HalSdioGetCmdAddr8723BSdio(
29 	IN	PADAPTER			padapter,
30 	IN	u8				DeviceID,
31 	IN	u32				Addr,
32 	OUT	u32				*pCmdAddr
33 )
34 {
35 	switch (DeviceID) {
36 	case SDIO_LOCAL_DEVICE_ID:
37 		*pCmdAddr = ((SDIO_LOCAL_DEVICE_ID << 13) | (Addr & SDIO_LOCAL_MSK));
38 		break;
39 
40 	case WLAN_IOREG_DEVICE_ID:
41 		*pCmdAddr = ((WLAN_IOREG_DEVICE_ID << 13) | (Addr & WLAN_IOREG_MSK));
42 		break;
43 
44 	case WLAN_TX_HIQ_DEVICE_ID:
45 		*pCmdAddr = ((WLAN_TX_HIQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK));
46 		break;
47 
48 	case WLAN_TX_MIQ_DEVICE_ID:
49 		*pCmdAddr = ((WLAN_TX_MIQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK));
50 		break;
51 
52 	case WLAN_TX_LOQ_DEVICE_ID:
53 		*pCmdAddr = ((WLAN_TX_LOQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK));
54 		break;
55 
56 	case WLAN_RX0FF_DEVICE_ID:
57 		*pCmdAddr = ((WLAN_RX0FF_DEVICE_ID << 13) | (Addr & WLAN_RX0FF_MSK));
58 		break;
59 
60 	default:
61 		break;
62 	}
63 }
64 
get_deviceid(u32 addr)65 static u8 get_deviceid(u32 addr)
66 {
67 	u8 devideId;
68 	u16 pseudoId;
69 
70 
71 	pseudoId = (u16)(addr >> 16);
72 	switch (pseudoId) {
73 	case 0x1025:
74 		devideId = SDIO_LOCAL_DEVICE_ID;
75 		break;
76 
77 	case 0x1026:
78 		devideId = WLAN_IOREG_DEVICE_ID;
79 		break;
80 
81 	/*		case 0x1027:
82 	 *			devideId = SDIO_FIRMWARE_FIFO;
83 	 *			break; */
84 
85 	case 0x1031:
86 		devideId = WLAN_TX_HIQ_DEVICE_ID;
87 		break;
88 
89 	case 0x1032:
90 		devideId = WLAN_TX_MIQ_DEVICE_ID;
91 		break;
92 
93 	case 0x1033:
94 		devideId = WLAN_TX_LOQ_DEVICE_ID;
95 		break;
96 
97 	case 0x1034:
98 		devideId = WLAN_RX0FF_DEVICE_ID;
99 		break;
100 
101 	default:
102 		/*			devideId = (u8)((addr >> 13) & 0xF); */
103 		devideId = WLAN_IOREG_DEVICE_ID;
104 		break;
105 	}
106 
107 	return devideId;
108 }
109 
110 /*
111  * Ref:
112  *	HalSdioGetCmdAddr8723BSdio()
113  */
_cvrt2ftaddr(const u32 addr,u8 * pdeviceId,u16 * poffset)114 static u32 _cvrt2ftaddr(const u32 addr, u8 *pdeviceId, u16 *poffset)
115 {
116 	u8 deviceId;
117 	u16 offset;
118 	u32 ftaddr;
119 
120 
121 	deviceId = get_deviceid(addr);
122 	offset = 0;
123 
124 	switch (deviceId) {
125 	case SDIO_LOCAL_DEVICE_ID:
126 		offset = addr & SDIO_LOCAL_MSK;
127 		break;
128 
129 	case WLAN_TX_HIQ_DEVICE_ID:
130 	case WLAN_TX_MIQ_DEVICE_ID:
131 	case WLAN_TX_LOQ_DEVICE_ID:
132 		offset = addr & WLAN_FIFO_MSK;
133 		break;
134 
135 	case WLAN_RX0FF_DEVICE_ID:
136 		offset = addr & WLAN_RX0FF_MSK;
137 		break;
138 
139 	case WLAN_IOREG_DEVICE_ID:
140 	default:
141 		deviceId = WLAN_IOREG_DEVICE_ID;
142 		offset = addr & WLAN_IOREG_MSK;
143 		break;
144 	}
145 	ftaddr = (deviceId << 13) | offset;
146 
147 	if (pdeviceId)
148 		*pdeviceId = deviceId;
149 	if (poffset)
150 		*poffset = offset;
151 
152 	return ftaddr;
153 }
154 
sdio_read8(struct intf_hdl * pintfhdl,u32 addr)155 u8 sdio_read8(struct intf_hdl *pintfhdl, u32 addr)
156 {
157 	u32 ftaddr;
158 	u8 val;
159 
160 	ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
161 	val = sd_read8(pintfhdl, ftaddr, NULL);
162 
163 
164 	return val;
165 }
166 
sdio_read16(struct intf_hdl * pintfhdl,u32 addr)167 u16 sdio_read16(struct intf_hdl *pintfhdl, u32 addr)
168 {
169 	u32 ftaddr;
170 	u16 val;
171 
172 	ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
173 	val = 0;
174 	sd_cmd52_read(pintfhdl, ftaddr, 2, (u8 *)&val);
175 	val = le16_to_cpu(val);
176 
177 
178 	return val;
179 }
180 
sdio_read32(struct intf_hdl * pintfhdl,u32 addr)181 u32 sdio_read32(struct intf_hdl *pintfhdl, u32 addr)
182 {
183 	PADAPTER padapter;
184 	u8 bMacPwrCtrlOn;
185 	u8 deviceId;
186 	u16 offset;
187 	u32 ftaddr;
188 	u8 shift;
189 	u32 val;
190 	s32 err;
191 
192 
193 	padapter = pintfhdl->padapter;
194 	ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
195 
196 	bMacPwrCtrlOn = _FALSE;
197 	rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
198 	if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100))
199 	    || (_FALSE == bMacPwrCtrlOn)
200 #ifdef CONFIG_LPS_LCLK
201 	    || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
202 #endif
203 	   ) {
204 		val = 0;
205 		err = sd_cmd52_read(pintfhdl, ftaddr, 4, (u8 *)&val);
206 #ifdef SDIO_DEBUG_IO
207 		if (!err) {
208 #endif
209 			val = le32_to_cpu(val);
210 			return val;
211 #ifdef SDIO_DEBUG_IO
212 		}
213 
214 		RTW_ERR("%s: Mac Power off, Read FAIL(%d)! addr=0x%x\n", __func__, err, addr);
215 		return SDIO_ERR_VAL32;
216 #endif
217 	}
218 
219 	/* 4 bytes alignment */
220 	shift = ftaddr & 0x3;
221 	if (shift == 0)
222 		val = sd_read32(pintfhdl, ftaddr, NULL);
223 	else {
224 		u8 *ptmpbuf;
225 
226 		ptmpbuf = (u8 *)rtw_malloc(8);
227 		if (NULL == ptmpbuf) {
228 			RTW_ERR("%s: Allocate memory FAIL!(size=8) addr=0x%x\n", __func__, addr);
229 			return SDIO_ERR_VAL32;
230 		}
231 
232 		ftaddr &= ~(u16)0x3;
233 		err = sd_read(pintfhdl, ftaddr, 8, ptmpbuf);
234 		if (err)
235 			return SDIO_ERR_VAL32;
236 		_rtw_memcpy(&val, ptmpbuf + shift, 4);
237 		val = le32_to_cpu(val);
238 
239 		rtw_mfree(ptmpbuf, 8);
240 	}
241 
242 
243 	return val;
244 }
245 
sdio_readN(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * pbuf)246 s32 sdio_readN(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pbuf)
247 {
248 	PADAPTER padapter;
249 	u8 bMacPwrCtrlOn;
250 	u8 deviceId;
251 	u16 offset;
252 	u32 ftaddr;
253 	u8 shift;
254 	s32 err;
255 
256 
257 	padapter = pintfhdl->padapter;
258 	err = 0;
259 
260 	ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
261 
262 	bMacPwrCtrlOn = _FALSE;
263 	rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
264 	if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100))
265 	    || (_FALSE == bMacPwrCtrlOn)
266 #ifdef CONFIG_LPS_LCLK
267 	    || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
268 #endif
269 	   ) {
270 		err = sd_cmd52_read(pintfhdl, ftaddr, cnt, pbuf);
271 		return err;
272 	}
273 
274 	/* 4 bytes alignment */
275 	shift = ftaddr & 0x3;
276 	if (shift == 0)
277 		err = sd_read(pintfhdl, ftaddr, cnt, pbuf);
278 	else {
279 		u8 *ptmpbuf;
280 		u32 n;
281 
282 		ftaddr &= ~(u16)0x3;
283 		n = cnt + shift;
284 		ptmpbuf = rtw_malloc(n);
285 		if (NULL == ptmpbuf)
286 			return -1;
287 		err = sd_read(pintfhdl, ftaddr, n, ptmpbuf);
288 		if (!err)
289 			_rtw_memcpy(pbuf, ptmpbuf + shift, cnt);
290 		rtw_mfree(ptmpbuf, n);
291 	}
292 
293 
294 	return err;
295 }
296 
sdio_write8(struct intf_hdl * pintfhdl,u32 addr,u8 val)297 s32 sdio_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
298 {
299 	u32 ftaddr;
300 	s32 err;
301 
302 	ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
303 	err = 0;
304 	sd_write8(pintfhdl, ftaddr, val, &err);
305 
306 
307 	return err;
308 }
309 
sdio_write16(struct intf_hdl * pintfhdl,u32 addr,u16 val)310 s32 sdio_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
311 {
312 	u32 ftaddr;
313 	u8 shift;
314 	s32 err;
315 
316 	ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
317 	val = cpu_to_le16(val);
318 	err = sd_cmd52_write(pintfhdl, ftaddr, 2, (u8 *)&val);
319 
320 
321 	return err;
322 }
323 
sdio_write32(struct intf_hdl * pintfhdl,u32 addr,u32 val)324 s32 sdio_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
325 {
326 	PADAPTER padapter;
327 	u8 bMacPwrCtrlOn;
328 	u8 deviceId;
329 	u16 offset;
330 	u32 ftaddr;
331 	u8 shift;
332 	s32 err;
333 
334 
335 	padapter = pintfhdl->padapter;
336 	err = 0;
337 
338 	ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
339 
340 	bMacPwrCtrlOn = _FALSE;
341 	rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
342 	if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100))
343 	    || (_FALSE == bMacPwrCtrlOn)
344 #ifdef CONFIG_LPS_LCLK
345 	    || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
346 #endif
347 	   ) {
348 		val = cpu_to_le32(val);
349 		err = sd_cmd52_write(pintfhdl, ftaddr, 4, (u8 *)&val);
350 		return err;
351 	}
352 
353 	/* 4 bytes alignment */
354 	shift = ftaddr & 0x3;
355 #if 1
356 	if (shift == 0)
357 		sd_write32(pintfhdl, ftaddr, val, &err);
358 	else {
359 		val = cpu_to_le32(val);
360 		err = sd_cmd52_write(pintfhdl, ftaddr, 4, (u8 *)&val);
361 	}
362 #else
363 	if (shift == 0)
364 		sd_write32(pintfhdl, ftaddr, val, &err);
365 	else {
366 		u8 *ptmpbuf;
367 
368 		ptmpbuf = (u8 *)rtw_malloc(8);
369 		if (NULL == ptmpbuf)
370 			return -1;
371 
372 		ftaddr &= ~(u16)0x3;
373 		err = sd_read(pintfhdl, ftaddr, 8, ptmpbuf);
374 		if (err) {
375 			rtw_mfree(ptmpbuf, 8);
376 			return err;
377 		}
378 		val = cpu_to_le32(val);
379 		_rtw_memcpy(ptmpbuf + shift, &val, 4);
380 		err = sd_write(pintfhdl, ftaddr, 8, ptmpbuf);
381 
382 		rtw_mfree(ptmpbuf, 8);
383 	}
384 #endif
385 
386 
387 	return err;
388 }
389 
sdio_writeN(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * pbuf)390 s32 sdio_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pbuf)
391 {
392 	PADAPTER padapter;
393 	u8 bMacPwrCtrlOn;
394 	u8 deviceId;
395 	u16 offset;
396 	u32 ftaddr;
397 	u8 shift;
398 	s32 err;
399 
400 
401 	padapter = pintfhdl->padapter;
402 	err = 0;
403 
404 	ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
405 
406 	bMacPwrCtrlOn = _FALSE;
407 	rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
408 	if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100))
409 	    || (_FALSE == bMacPwrCtrlOn)
410 #ifdef CONFIG_LPS_LCLK
411 	    || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
412 #endif
413 	   ) {
414 		err = sd_cmd52_write(pintfhdl, ftaddr, cnt, pbuf);
415 		return err;
416 	}
417 
418 	shift = ftaddr & 0x3;
419 	if (shift == 0)
420 		err = sd_write(pintfhdl, ftaddr, cnt, pbuf);
421 	else {
422 		u8 *ptmpbuf;
423 		u32 n;
424 
425 		ftaddr &= ~(u16)0x3;
426 		n = cnt + shift;
427 		ptmpbuf = rtw_malloc(n);
428 		if (NULL == ptmpbuf)
429 			return -1;
430 		err = sd_read(pintfhdl, ftaddr, 4, ptmpbuf);
431 		if (err) {
432 			rtw_mfree(ptmpbuf, n);
433 			return err;
434 		}
435 		_rtw_memcpy(ptmpbuf + shift, pbuf, cnt);
436 		err = sd_write(pintfhdl, ftaddr, n, ptmpbuf);
437 		rtw_mfree(ptmpbuf, n);
438 	}
439 
440 
441 	return err;
442 }
443 
sdio_f0_read8(struct intf_hdl * pintfhdl,u32 addr)444 u8 sdio_f0_read8(struct intf_hdl *pintfhdl, u32 addr)
445 {
446 	u32 ftaddr;
447 	u8 val;
448 
449 	val = sd_f0_read8(pintfhdl, addr, NULL);
450 
451 
452 	return val;
453 }
454 
sdio_read_mem(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * rmem)455 void sdio_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
456 {
457 	s32 err;
458 
459 
460 	err = sdio_readN(pintfhdl, addr, cnt, rmem);
461 
462 }
463 
sdio_write_mem(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * wmem)464 void sdio_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
465 {
466 
467 	sdio_writeN(pintfhdl, addr, cnt, wmem);
468 
469 }
470 
471 /*
472  * Description:
473  *	Read from RX FIFO
474  *	Round read size to block size,
475  *	and make sure data transfer will be done in one command.
476  *
477  * Parameters:
478  *	pintfhdl	a pointer of intf_hdl
479  *	addr		port ID
480  *	cnt			size to read
481  *	rmem		address to put data
482  *
483  * Return:
484  *	_SUCCESS(1)		Success
485  *	_FAIL(0)		Fail
486  */
sdio_read_port(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * mem)487 static u32 sdio_read_port(
488 	struct intf_hdl *pintfhdl,
489 	u32 addr,
490 	u32 cnt,
491 	u8 *mem)
492 {
493 	PADAPTER padapter;
494 	PSDIO_DATA psdio;
495 	PHAL_DATA_TYPE phal;
496 	u32 oldcnt;
497 #ifdef SDIO_DYNAMIC_ALLOC_MEM
498 	u8 *oldmem;
499 #endif
500 	s32 err;
501 
502 
503 	padapter = pintfhdl->padapter;
504 	psdio = &adapter_to_dvobj(padapter)->intf_data;
505 	phal = GET_HAL_DATA(padapter);
506 
507 	HalSdioGetCmdAddr8723BSdio(padapter, addr, phal->SdioRxFIFOCnt++, &addr);
508 
509 	oldcnt = cnt;
510 	if (cnt > psdio->block_transfer_len)
511 		cnt = _RND(cnt, psdio->block_transfer_len);
512 	/*	cnt = sdio_align_size(cnt); */
513 
514 	if (oldcnt != cnt) {
515 #ifdef SDIO_DYNAMIC_ALLOC_MEM
516 		oldmem = mem;
517 		mem = rtw_malloc(cnt);
518 		if (mem == NULL) {
519 			RTW_WARN("%s: allocate memory %d bytes fail!\n", __func__, cnt);
520 			mem = oldmem;
521 			oldmem == NULL;
522 		}
523 #else
524 		/* in this case, caller should gurante the buffer is big enough */
525 		/* to receive data after alignment */
526 #endif
527 	}
528 
529 	err = _sd_read(pintfhdl, addr, cnt, mem);
530 
531 #ifdef SDIO_DYNAMIC_ALLOC_MEM
532 	if ((oldcnt != cnt) && (oldmem)) {
533 		_rtw_memcpy(oldmem, mem, oldcnt);
534 		rtw_mfree(mem, cnt);
535 	}
536 #endif
537 
538 	if (err)
539 		return _FAIL;
540 	return _SUCCESS;
541 }
542 
543 /*
544  * Description:
545  *	Write to TX FIFO
546  *	Align write size block size,
547  *	and make sure data could be written in one command.
548  *
549  * Parameters:
550  *	pintfhdl	a pointer of intf_hdl
551  *	addr		port ID
552  *	cnt			size to write
553  *	wmem		data pointer to write
554  *
555  * Return:
556  *	_SUCCESS(1)		Success
557  *	_FAIL(0)		Fail
558  */
sdio_write_port(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * mem)559 static u32 sdio_write_port(
560 	struct intf_hdl *pintfhdl,
561 	u32 addr,
562 	u32 cnt,
563 	u8 *mem)
564 {
565 	PADAPTER padapter;
566 	PSDIO_DATA psdio;
567 	s32 err;
568 	struct xmit_buf *xmitbuf = (struct xmit_buf *)mem;
569 
570 	padapter = pintfhdl->padapter;
571 	psdio = &adapter_to_dvobj(padapter)->intf_data;
572 
573 	if (!rtw_is_hw_init_completed(padapter)) {
574 		RTW_INFO("%s [addr=0x%x cnt=%d] padapter->hw_init_completed == _FALSE\n", __func__, addr, cnt);
575 		return _FAIL;
576 	}
577 
578 	cnt = _RND4(cnt);
579 	HalSdioGetCmdAddr8723BSdio(padapter, addr, cnt >> 2, &addr);
580 
581 	if (cnt > psdio->block_transfer_len)
582 		cnt = _RND(cnt, psdio->block_transfer_len);
583 	/*	cnt = sdio_align_size(cnt); */
584 
585 	err = sd_write(pintfhdl, addr, cnt, xmitbuf->pdata);
586 
587 	rtw_sctx_done_err(&xmitbuf->sctx,
588 		  err ? RTW_SCTX_DONE_WRITE_PORT_ERR : RTW_SCTX_DONE_SUCCESS);
589 
590 	if (err)
591 		return _FAIL;
592 	return _SUCCESS;
593 }
594 
sdio_set_intf_ops(_adapter * padapter,struct _io_ops * pops)595 void sdio_set_intf_ops(_adapter *padapter, struct _io_ops *pops)
596 {
597 
598 	pops->_read8 = &sdio_read8;
599 	pops->_read16 = &sdio_read16;
600 	pops->_read32 = &sdio_read32;
601 	pops->_read_mem = &sdio_read_mem;
602 	pops->_read_port = &sdio_read_port;
603 
604 	pops->_write8 = &sdio_write8;
605 	pops->_write16 = &sdio_write16;
606 	pops->_write32 = &sdio_write32;
607 	pops->_writeN = &sdio_writeN;
608 	pops->_write_mem = &sdio_write_mem;
609 	pops->_write_port = &sdio_write_port;
610 
611 	pops->_sd_f0_read8 = sdio_f0_read8;
612 
613 }
614 
615 /*
616  * Todo: align address to 4 bytes.
617  */
_sdio_local_read(PADAPTER padapter,u32 addr,u32 cnt,u8 * pbuf)618 s32 _sdio_local_read(
619 	PADAPTER	padapter,
620 	u32			addr,
621 	u32			cnt,
622 	u8			*pbuf)
623 {
624 	struct intf_hdl *pintfhdl;
625 	u8 bMacPwrCtrlOn;
626 	s32 err;
627 	u8 *ptmpbuf;
628 	u32 n;
629 
630 
631 	pintfhdl = &padapter->iopriv.intf;
632 
633 	HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
634 
635 	bMacPwrCtrlOn = _FALSE;
636 	rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
637 	if (_FALSE == bMacPwrCtrlOn) {
638 		err = _sd_cmd52_read(pintfhdl, addr, cnt, pbuf);
639 		return err;
640 	}
641 
642 	n = RND4(cnt);
643 	ptmpbuf = (u8 *)rtw_malloc(n);
644 	if (!ptmpbuf)
645 		return -1;
646 
647 	err = _sd_read(pintfhdl, addr, n, ptmpbuf);
648 	if (!err)
649 		_rtw_memcpy(pbuf, ptmpbuf, cnt);
650 
651 	if (ptmpbuf)
652 		rtw_mfree(ptmpbuf, n);
653 
654 	return err;
655 }
656 
657 /*
658  * Todo: align address to 4 bytes.
659  */
sdio_local_read(PADAPTER padapter,u32 addr,u32 cnt,u8 * pbuf)660 s32 sdio_local_read(
661 	PADAPTER	padapter,
662 	u32			addr,
663 	u32			cnt,
664 	u8			*pbuf)
665 {
666 	struct intf_hdl *pintfhdl;
667 	u8 bMacPwrCtrlOn;
668 	s32 err;
669 	u8 *ptmpbuf;
670 	u32 n;
671 
672 	pintfhdl = &padapter->iopriv.intf;
673 
674 	HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
675 
676 	bMacPwrCtrlOn = _FALSE;
677 	rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
678 	if ((_FALSE == bMacPwrCtrlOn)
679 #ifdef CONFIG_LPS_LCLK
680 	    || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
681 #endif
682 	   ) {
683 		err = sd_cmd52_read(pintfhdl, addr, cnt, pbuf);
684 		return err;
685 	}
686 
687 	n = RND4(cnt);
688 	ptmpbuf = (u8 *)rtw_malloc(n);
689 	if (!ptmpbuf)
690 		return -1;
691 
692 	err = sd_read(pintfhdl, addr, n, ptmpbuf);
693 	if (!err)
694 		_rtw_memcpy(pbuf, ptmpbuf, cnt);
695 
696 	if (ptmpbuf)
697 		rtw_mfree(ptmpbuf, n);
698 
699 	return err;
700 }
701 
702 /*
703  * Todo: align address to 4 bytes.
704  */
_sdio_local_write(PADAPTER padapter,u32 addr,u32 cnt,u8 * pbuf)705 s32 _sdio_local_write(
706 	PADAPTER	padapter,
707 	u32			addr,
708 	u32			cnt,
709 	u8			*pbuf)
710 {
711 	struct intf_hdl *pintfhdl;
712 	u8 bMacPwrCtrlOn;
713 	s32 err;
714 	u8 *ptmpbuf;
715 
716 	if (addr & 0x3)
717 		RTW_INFO("%s, address must be 4 bytes alignment\n", __FUNCTION__);
718 
719 	if (cnt  & 0x3)
720 		RTW_INFO("%s, size must be the multiple of 4\n", __FUNCTION__);
721 
722 	pintfhdl = &padapter->iopriv.intf;
723 
724 	HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
725 
726 	bMacPwrCtrlOn = _FALSE;
727 	rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
728 	if ((_FALSE == bMacPwrCtrlOn)
729 #ifdef CONFIG_LPS_LCLK
730 	    || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
731 #endif
732 	   ) {
733 		err = _sd_cmd52_write(pintfhdl, addr, cnt, pbuf);
734 		return err;
735 	}
736 
737 	ptmpbuf = (u8 *)rtw_malloc(cnt);
738 	if (!ptmpbuf)
739 		return -1;
740 
741 	_rtw_memcpy(ptmpbuf, pbuf, cnt);
742 
743 	err = _sd_write(pintfhdl, addr, cnt, ptmpbuf);
744 
745 	if (ptmpbuf)
746 		rtw_mfree(ptmpbuf, cnt);
747 
748 	return err;
749 }
750 
751 /*
752  * Todo: align address to 4 bytes.
753  */
sdio_local_write(PADAPTER padapter,u32 addr,u32 cnt,u8 * pbuf)754 s32 sdio_local_write(
755 	PADAPTER	padapter,
756 	u32		addr,
757 	u32		cnt,
758 	u8		*pbuf)
759 {
760 	struct intf_hdl *pintfhdl;
761 	u8 bMacPwrCtrlOn;
762 	s32 err;
763 	u8 *ptmpbuf;
764 
765 	if (addr & 0x3)
766 		RTW_INFO("%s, address must be 4 bytes alignment\n", __FUNCTION__);
767 
768 	if (cnt  & 0x3)
769 		RTW_INFO("%s, size must be the multiple of 4\n", __FUNCTION__);
770 
771 	pintfhdl = &padapter->iopriv.intf;
772 
773 	HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
774 
775 	bMacPwrCtrlOn = _FALSE;
776 	rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
777 	if ((_FALSE == bMacPwrCtrlOn)
778 #ifdef CONFIG_LPS_LCLK
779 	    || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
780 #endif
781 	   ) {
782 		err = sd_cmd52_write(pintfhdl, addr, cnt, pbuf);
783 		return err;
784 	}
785 
786 	ptmpbuf = (u8 *)rtw_malloc(cnt);
787 	if (!ptmpbuf)
788 		return -1;
789 
790 	_rtw_memcpy(ptmpbuf, pbuf, cnt);
791 
792 	err = sd_write(pintfhdl, addr, cnt, ptmpbuf);
793 
794 	if (ptmpbuf)
795 		rtw_mfree(ptmpbuf, cnt);
796 
797 	return err;
798 }
799 
SdioLocalCmd52Read1Byte(PADAPTER padapter,u32 addr)800 u8 SdioLocalCmd52Read1Byte(PADAPTER padapter, u32 addr)
801 {
802 	u8 val = 0;
803 	struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
804 
805 	HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
806 	sd_cmd52_read(pintfhdl, addr, 1, &val);
807 
808 	return val;
809 }
810 
SdioLocalCmd52Read2Byte(PADAPTER padapter,u32 addr)811 u16 SdioLocalCmd52Read2Byte(PADAPTER padapter, u32 addr)
812 {
813 	u16 val = 0;
814 	struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
815 
816 	HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
817 	sd_cmd52_read(pintfhdl, addr, 2, (u8 *)&val);
818 
819 	val = le16_to_cpu(val);
820 
821 	return val;
822 }
823 
SdioLocalCmd52Read4Byte(PADAPTER padapter,u32 addr)824 u32 SdioLocalCmd52Read4Byte(PADAPTER padapter, u32 addr)
825 {
826 	u32 val = 0;
827 	struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
828 
829 	HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
830 	sd_cmd52_read(pintfhdl, addr, 4, (u8 *)&val);
831 
832 	val = le32_to_cpu(val);
833 
834 	return val;
835 }
836 
SdioLocalCmd53Read4Byte(PADAPTER padapter,u32 addr)837 u32 SdioLocalCmd53Read4Byte(PADAPTER padapter, u32 addr)
838 {
839 
840 	u8 bMacPwrCtrlOn;
841 	u32 val = 0;
842 	struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
843 
844 	HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
845 	bMacPwrCtrlOn = _FALSE;
846 	rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
847 	if ((_FALSE == bMacPwrCtrlOn)
848 #ifdef CONFIG_LPS_LCLK
849 	    || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
850 #endif
851 	   ) {
852 		sd_cmd52_read(pintfhdl, addr, 4, (u8 *)&val);
853 		val = le32_to_cpu(val);
854 	} else
855 		val = sd_read32(pintfhdl, addr, NULL);
856 
857 	return val;
858 }
859 
SdioLocalCmd52Write1Byte(PADAPTER padapter,u32 addr,u8 v)860 void SdioLocalCmd52Write1Byte(PADAPTER padapter, u32 addr, u8 v)
861 {
862 	struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
863 
864 	HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
865 	sd_cmd52_write(pintfhdl, addr, 1, &v);
866 }
867 
SdioLocalCmd52Write2Byte(PADAPTER padapter,u32 addr,u16 v)868 void SdioLocalCmd52Write2Byte(PADAPTER padapter, u32 addr, u16 v)
869 {
870 	struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
871 
872 	HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
873 	v = cpu_to_le16(v);
874 	sd_cmd52_write(pintfhdl, addr, 2, (u8 *)&v);
875 }
876 
SdioLocalCmd52Write4Byte(PADAPTER padapter,u32 addr,u32 v)877 void SdioLocalCmd52Write4Byte(PADAPTER padapter, u32 addr, u32 v)
878 {
879 	struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
880 	HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
881 	v = cpu_to_le32(v);
882 	sd_cmd52_write(pintfhdl, addr, 4, (u8 *)&v);
883 }
884 
885 #if 0
886 void
887 DumpLoggedInterruptHistory8723Sdio(
888 	PADAPTER		padapter
889 )
890 {
891 	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
892 	u4Byte				DebugLevel = DBG_LOUD;
893 
894 	if (DBG_Var.DbgPrintIsr == 0)
895 		return;
896 
897 	DBG_ChkDrvResource(padapter);
898 
899 
900 
901 }
902 
903 void
904 LogInterruptHistory8723Sdio(
905 	PADAPTER			padapter,
906 	PRT_ISR_CONTENT	pIsrContent
907 )
908 {
909 	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
910 
911 	if ((pHalData->IntrMask[0] & SDIO_HIMR_RX_REQUEST_MSK) &&
912 	    (pIsrContent->IntArray[0] & SDIO_HISR_RX_REQUEST))
913 		pHalData->InterruptLog.nISR_RX_REQUEST++;
914 	if ((pHalData->IntrMask[0] & SDIO_HIMR_AVAL_MSK) &&
915 	    (pIsrContent->IntArray[0] & SDIO_HISR_AVAL))
916 		pHalData->InterruptLog.nISR_AVAL++;
917 	if ((pHalData->IntrMask[0] & SDIO_HIMR_TXERR_MSK) &&
918 	    (pIsrContent->IntArray[0] & SDIO_HISR_TXERR))
919 		pHalData->InterruptLog.nISR_TXERR++;
920 	if ((pHalData->IntrMask[0] & SDIO_HIMR_RXERR_MSK) &&
921 	    (pIsrContent->IntArray[0] & SDIO_HISR_RXERR))
922 		pHalData->InterruptLog.nISR_RXERR++;
923 	if ((pHalData->IntrMask[0] & SDIO_HIMR_TXFOVW_MSK) &&
924 	    (pIsrContent->IntArray[0] & SDIO_HISR_TXFOVW))
925 		pHalData->InterruptLog.nISR_TXFOVW++;
926 	if ((pHalData->IntrMask[0] & SDIO_HIMR_RXFOVW_MSK) &&
927 	    (pIsrContent->IntArray[0] & SDIO_HISR_RXFOVW))
928 		pHalData->InterruptLog.nISR_RXFOVW++;
929 	if ((pHalData->IntrMask[0] & SDIO_HIMR_TXBCNOK_MSK) &&
930 	    (pIsrContent->IntArray[0] & SDIO_HISR_TXBCNOK))
931 		pHalData->InterruptLog.nISR_TXBCNOK++;
932 	if ((pHalData->IntrMask[0] & SDIO_HIMR_TXBCNERR_MSK) &&
933 	    (pIsrContent->IntArray[0] & SDIO_HISR_TXBCNERR))
934 		pHalData->InterruptLog.nISR_TXBCNERR++;
935 	if ((pHalData->IntrMask[0] & SDIO_HIMR_BCNERLY_INT_MSK) &&
936 	    (pIsrContent->IntArray[0] & SDIO_HISR_BCNERLY_INT))
937 		pHalData->InterruptLog.nISR_BCNERLY_INT++;
938 	if ((pHalData->IntrMask[0] & SDIO_HIMR_C2HCMD_MSK) &&
939 	    (pIsrContent->IntArray[0] & SDIO_HISR_C2HCMD))
940 		pHalData->InterruptLog.nISR_C2HCMD++;
941 	if ((pHalData->IntrMask[0] & SDIO_HIMR_CPWM1_MSK) &&
942 	    (pIsrContent->IntArray[0] & SDIO_HISR_CPWM1))
943 		pHalData->InterruptLog.nISR_CPWM1++;
944 	if ((pHalData->IntrMask[0] & SDIO_HIMR_CPWM2_MSK) &&
945 	    (pIsrContent->IntArray[0] & SDIO_HISR_CPWM2))
946 		pHalData->InterruptLog.nISR_CPWM2++;
947 	if ((pHalData->IntrMask[0] & SDIO_HIMR_HSISR_IND_MSK) &&
948 	    (pIsrContent->IntArray[0] & SDIO_HISR_HSISR_IND))
949 		pHalData->InterruptLog.nISR_HSISR_IND++;
950 	if ((pHalData->IntrMask[0] & SDIO_HIMR_GTINT3_IND_MSK) &&
951 	    (pIsrContent->IntArray[0] & SDIO_HISR_GTINT3_IND))
952 		pHalData->InterruptLog.nISR_GTINT3_IND++;
953 	if ((pHalData->IntrMask[0] & SDIO_HIMR_GTINT4_IND_MSK) &&
954 	    (pIsrContent->IntArray[0] & SDIO_HISR_GTINT4_IND))
955 		pHalData->InterruptLog.nISR_GTINT4_IND++;
956 	if ((pHalData->IntrMask[0] & SDIO_HIMR_PSTIMEOUT_MSK) &&
957 	    (pIsrContent->IntArray[0] & SDIO_HISR_PSTIMEOUT))
958 		pHalData->InterruptLog.nISR_PSTIMEOUT++;
959 	if ((pHalData->IntrMask[0] & SDIO_HIMR_OCPINT_MSK) &&
960 	    (pIsrContent->IntArray[0] & SDIO_HISR_OCPINT))
961 		pHalData->InterruptLog.nISR_OCPINT++;
962 	if ((pHalData->IntrMask[0] & SDIO_HIMR_ATIMEND_MSK) &&
963 	    (pIsrContent->IntArray[0] & SDIO_HISR_ATIMEND))
964 		pHalData->InterruptLog.nISR_ATIMEND++;
965 	if ((pHalData->IntrMask[0] & SDIO_HIMR_ATIMEND_E_MSK) &&
966 	    (pIsrContent->IntArray[0] & SDIO_HISR_ATIMEND_E))
967 		pHalData->InterruptLog.nISR_ATIMEND_E++;
968 	if ((pHalData->IntrMask[0] & SDIO_HIMR_CTWEND_MSK) &&
969 	    (pIsrContent->IntArray[0] & SDIO_HISR_CTWEND))
970 		pHalData->InterruptLog.nISR_CTWEND++;
971 
972 }
973 
974 void
975 DumpHardwareProfile8723Sdio(
976 	IN	PADAPTER		padapter
977 )
978 {
979 	DumpLoggedInterruptHistory8723Sdio(padapter);
980 }
981 #endif
982 
ReadInterrupt8723BSdio(PADAPTER padapter,u32 * phisr)983 static s32 ReadInterrupt8723BSdio(PADAPTER padapter, u32 *phisr)
984 {
985 	u32 hisr, himr;
986 	u8 val8, hisr_len;
987 
988 
989 	if (phisr == NULL)
990 		return _FALSE;
991 
992 	himr = GET_HAL_DATA(padapter)->sdio_himr;
993 
994 	/* decide how many bytes need to be read */
995 	hisr_len = 0;
996 	while (himr) {
997 		hisr_len++;
998 		himr >>= 8;
999 	}
1000 
1001 	hisr = 0;
1002 	while (hisr_len != 0) {
1003 		hisr_len--;
1004 		val8 = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_HISR + hisr_len);
1005 		hisr |= (val8 << (8 * hisr_len));
1006 	}
1007 
1008 	*phisr = hisr;
1009 
1010 	return _TRUE;
1011 }
1012 
1013 /*
1014  *	Description:
1015  *		Initialize SDIO Host Interrupt Mask configuration variables for future use.
1016  *
1017  *	Assumption:
1018  *		Using SDIO Local register ONLY for configuration.
1019  *
1020  *	Created by Roger, 2011.02.11.
1021  *   */
InitInterrupt8723BSdio(PADAPTER padapter)1022 void InitInterrupt8723BSdio(PADAPTER padapter)
1023 {
1024 	PHAL_DATA_TYPE pHalData;
1025 
1026 
1027 	pHalData = GET_HAL_DATA(padapter);
1028 	pHalData->sdio_himr = (u32)(\
1029 				    SDIO_HIMR_RX_REQUEST_MSK			|
1030 #ifdef CONFIG_SDIO_TX_ENABLE_AVAL_INT
1031 				    SDIO_HIMR_AVAL_MSK					|
1032 #endif
1033 				    /*								SDIO_HIMR_TXERR_MSK				|
1034 				     *								SDIO_HIMR_RXERR_MSK				|
1035 				     *								SDIO_HIMR_TXFOVW_MSK				|
1036 				     *								SDIO_HIMR_RXFOVW_MSK				|
1037 				     *								SDIO_HIMR_TXBCNOK_MSK				|
1038 				     *								SDIO_HIMR_TXBCNERR_MSK			|
1039 				     *								SDIO_HIMR_BCNERLY_INT_MSK			|
1040 				     *								SDIO_HIMR_C2HCMD_MSK				| */
1041 #if defined(CONFIG_LPS_LCLK) && !defined(CONFIG_DETECT_CPWM_BY_POLLING)
1042 				    SDIO_HIMR_CPWM1_MSK				|
1043 #endif /* CONFIG_LPS_LCLK && !CONFIG_DETECT_CPWM_BY_POLLING */
1044 #ifdef CONFIG_WOWLAN
1045 				    SDIO_HIMR_CPWM2_MSK				|
1046 #endif
1047 
1048 				    /*								SDIO_HIMR_HSISR_IND_MSK			|
1049 				     *								SDIO_HIMR_GTINT3_IND_MSK			|
1050 				     *								SDIO_HIMR_GTINT4_IND_MSK			|
1051 				     *								SDIO_HIMR_PSTIMEOUT_MSK			|
1052 				     *								SDIO_HIMR_OCPINT_MSK				|
1053 				     *								SDIO_HIMR_ATIMEND_MSK				|
1054 				     *								SDIO_HIMR_ATIMEND_E_MSK			|
1055 				     *								SDIO_HIMR_CTWEND_MSK				| */
1056 				    0);
1057 }
1058 
1059 /*
1060  *	Description:
1061  *		Initialize System Host Interrupt Mask configuration variables for future use.
1062  *
1063  *	Created by Roger, 2011.08.03.
1064  *   */
InitSysInterrupt8723BSdio(PADAPTER padapter)1065 void InitSysInterrupt8723BSdio(PADAPTER padapter)
1066 {
1067 	PHAL_DATA_TYPE pHalData;
1068 
1069 
1070 	pHalData = GET_HAL_DATA(padapter);
1071 
1072 	pHalData->SysIntrMask = (\
1073 				 /*							HSIMR_GPIO12_0_INT_EN			|
1074 				  *							HSIMR_SPS_OCP_INT_EN			|
1075 				  *							HSIMR_RON_INT_EN				|
1076 				  *							HSIMR_PDNINT_EN				|
1077 				  *							HSIMR_GPIO9_INT_EN				| */
1078 				 0);
1079 }
1080 
1081 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
1082 /*
1083  *	Description:
1084  *		Clear corresponding SDIO Host ISR interrupt service.
1085  *
1086  *	Assumption:
1087  *		Using SDIO Local register ONLY for configuration.
1088  *
1089  *	Created by Roger, 2011.02.11.
1090  *   */
ClearInterrupt8723BSdio(PADAPTER padapter)1091 void ClearInterrupt8723BSdio(PADAPTER padapter)
1092 {
1093 	PHAL_DATA_TYPE pHalData;
1094 	u8 *clear;
1095 
1096 
1097 	if (rtw_is_surprise_removed(padapter))
1098 		return;
1099 
1100 	pHalData = GET_HAL_DATA(padapter);
1101 	clear = rtw_zmalloc(4);
1102 
1103 	/* Clear corresponding HISR Content if needed */
1104 	*(u32 *)clear = cpu_to_le32(pHalData->sdio_hisr & MASK_SDIO_HISR_CLEAR);
1105 	if (*(u32 *)clear) {
1106 		/* Perform write one clear operation */
1107 		sdio_local_write(padapter, SDIO_REG_HISR, 4, clear);
1108 	}
1109 
1110 	rtw_mfree(clear, 4);
1111 }
1112 #endif
1113 
1114 /*
1115  *	Description:
1116  *		Clear corresponding system Host ISR interrupt service.
1117  *
1118  *
1119  *	Created by Roger, 2011.02.11.
1120  *   */
ClearSysInterrupt8723BSdio(PADAPTER padapter)1121 void ClearSysInterrupt8723BSdio(PADAPTER padapter)
1122 {
1123 	PHAL_DATA_TYPE pHalData;
1124 	u32 clear;
1125 
1126 
1127 	if (rtw_is_surprise_removed(padapter))
1128 		return;
1129 
1130 	pHalData = GET_HAL_DATA(padapter);
1131 
1132 	/* Clear corresponding HISR Content if needed */
1133 	clear = pHalData->SysIntrStatus & MASK_HSISR_CLEAR;
1134 	if (clear) {
1135 		/* Perform write one clear operation */
1136 		rtw_write32(padapter, REG_HSISR, clear);
1137 	}
1138 }
1139 
1140 /*
1141  *	Description:
1142  *		Enalbe SDIO Host Interrupt Mask configuration on SDIO local domain.
1143  *
1144  *	Assumption:
1145  *		1. Using SDIO Local register ONLY for configuration.
1146  *		2. PASSIVE LEVEL
1147  *
1148  *	Created by Roger, 2011.02.11.
1149  *   */
EnableInterrupt8723BSdio(PADAPTER padapter)1150 void EnableInterrupt8723BSdio(PADAPTER padapter)
1151 {
1152 	PHAL_DATA_TYPE pHalData;
1153 	u32 himr;
1154 
1155 	pHalData = GET_HAL_DATA(padapter);
1156 
1157 	himr = cpu_to_le32(pHalData->sdio_himr);
1158 	sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
1159 
1160 
1161 	/* Update current system IMR settings */
1162 	himr = rtw_read32(padapter, REG_HSIMR);
1163 	rtw_write32(padapter, REG_HSIMR, himr | pHalData->SysIntrMask);
1164 
1165 
1166 	/*  */
1167 	/* <Roger_Notes> There are some C2H CMDs have been sent before system interrupt is enabled, e.g., C2H, CPWM. */
1168 	/* So we need to clear all C2H events that FW has notified, otherwise FW won't schedule any commands anymore. */
1169 	/* 2011.10.19. */
1170 	/*  */
1171 	rtw_write8(padapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
1172 }
1173 
1174 /*
1175  *	Description:
1176  *		Disable SDIO Host IMR configuration to mask unnecessary interrupt service.
1177  *
1178  *	Assumption:
1179  *		Using SDIO Local register ONLY for configuration.
1180  *
1181  *	Created by Roger, 2011.02.11.
1182  *   */
DisableInterrupt8723BSdio(PADAPTER padapter)1183 void DisableInterrupt8723BSdio(PADAPTER padapter)
1184 {
1185 	u32 himr;
1186 
1187 	himr = cpu_to_le32(SDIO_HIMR_DISABLED);
1188 	sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
1189 
1190 }
1191 
1192 /*
1193  *	Description:
1194  *		Using 0x100 to check the power status of FW.
1195  *
1196  *	Assumption:
1197  *		Using SDIO Local register ONLY for configuration.
1198  *
1199  *	Created by Isaac, 2013.09.10.
1200  *   */
CheckIPSStatus(PADAPTER padapter)1201 u8 CheckIPSStatus(PADAPTER padapter)
1202 {
1203 	RTW_INFO("%s(): Read 0x100=0x%02x 0x86=0x%02x\n", __func__,
1204 		 rtw_read8(padapter, 0x100), rtw_read8(padapter, 0x86));
1205 
1206 	if (rtw_read8(padapter, 0x100) == 0xEA)
1207 		return _TRUE;
1208 	else
1209 		return _FALSE;
1210 }
1211 
1212 #ifdef CONFIG_WOWLAN
DisableInterruptButCpwm28723BSdio(PADAPTER padapter)1213 void DisableInterruptButCpwm28723BSdio(PADAPTER padapter)
1214 {
1215 	u32 himr, tmp;
1216 
1217 	sdio_local_read(padapter, SDIO_REG_HIMR, 4, (u8 *)&tmp);
1218 	RTW_INFO("DisableInterruptButCpwm28723BSdio(): Read SDIO_REG_HIMR: 0x%08x\n", tmp);
1219 
1220 	himr = cpu_to_le32(SDIO_HIMR_DISABLED) | SDIO_HIMR_CPWM2_MSK;
1221 	sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
1222 
1223 	sdio_local_read(padapter, SDIO_REG_HIMR, 4, (u8 *)&tmp);
1224 	RTW_INFO("DisableInterruptButCpwm28723BSdio(): Read again SDIO_REG_HIMR: 0x%08x\n", tmp);
1225 }
1226 #endif /* CONFIG_WOWLAN
1227  *
1228  *	Description:
1229  *		Update SDIO Host Interrupt Mask configuration on SDIO local domain.
1230  *
1231  *	Assumption:
1232  *		1. Using SDIO Local register ONLY for configuration.
1233  *		2. PASSIVE LEVEL
1234  *
1235  *	Created by Roger, 2011.02.11.
1236  *   */
UpdateInterruptMask8723BSdio(PADAPTER padapter,u32 AddMSR,u32 RemoveMSR)1237 void UpdateInterruptMask8723BSdio(PADAPTER padapter, u32 AddMSR, u32 RemoveMSR)
1238 {
1239 	HAL_DATA_TYPE *pHalData;
1240 
1241 	pHalData = GET_HAL_DATA(padapter);
1242 
1243 	if (AddMSR)
1244 		pHalData->sdio_himr |= AddMSR;
1245 
1246 	if (RemoveMSR)
1247 		pHalData->sdio_himr &= (~RemoveMSR);
1248 
1249 	DisableInterrupt8723BSdio(padapter);
1250 	EnableInterrupt8723BSdio(padapter);
1251 }
1252 
1253 #ifdef CONFIG_MAC_LOOPBACK_DRIVER
sd_recv_loopback(PADAPTER padapter,u32 size)1254 static void sd_recv_loopback(PADAPTER padapter, u32 size)
1255 {
1256 	PLOOPBACKDATA ploopback;
1257 	u32 readsize, allocsize;
1258 	u8 *preadbuf;
1259 
1260 
1261 	readsize = size;
1262 	RTW_INFO("%s: read size=%d\n", __func__, readsize);
1263 	allocsize = _RND(readsize, adapter_to_dvobj(padapter)->intf_data.block_transfer_len);
1264 
1265 	ploopback = padapter->ploopback;
1266 	if (ploopback) {
1267 		ploopback->rxsize = readsize;
1268 		preadbuf = ploopback->rxbuf;
1269 	} else {
1270 		preadbuf = rtw_malloc(allocsize);
1271 		if (preadbuf == NULL) {
1272 			RTW_INFO("%s: malloc fail size=%d\n", __func__, allocsize);
1273 			return;
1274 		}
1275 	}
1276 
1277 	/*	rtw_read_port(padapter, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf); */
1278 	sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
1279 
1280 	if (ploopback)
1281 		_rtw_up_sema(&ploopback->sema);
1282 	else {
1283 		u32 i;
1284 
1285 		RTW_INFO("%s: drop pkt\n", __func__);
1286 		for (i = 0; i < readsize; i += 4) {
1287 			RTW_INFO("%08X", *(u32 *)(preadbuf + i));
1288 			if ((i + 4) & 0x1F)
1289 				printk(" ");
1290 			else
1291 				printk("\n");
1292 		}
1293 		printk("\n");
1294 		rtw_mfree(preadbuf, allocsize);
1295 	}
1296 }
1297 #endif /* CONFIG_MAC_LOOPBACK_DRIVER */
1298 
1299 #ifdef CONFIG_SDIO_RX_COPY
sd_recv_rxfifo(PADAPTER padapter,u32 size)1300 static struct recv_buf *sd_recv_rxfifo(PADAPTER padapter, u32 size)
1301 {
1302 	u32 readsize, ret;
1303 	u8 *preadbuf;
1304 	struct recv_priv *precvpriv;
1305 	struct recv_buf	*precvbuf;
1306 
1307 
1308 #if 0
1309 	readsize = size;
1310 #else
1311 	/* Patch for some SDIO Host 4 bytes issue */
1312 	/* ex. RK3188 */
1313 	readsize = RND4(size);
1314 #endif
1315 
1316 	/* 3 1. alloc recvbuf */
1317 	precvpriv = &padapter->recvpriv;
1318 	precvbuf = rtw_dequeue_recvbuf(&precvpriv->free_recv_buf_queue);
1319 	if (precvbuf == NULL) {
1320 		RTW_ERR("%s: alloc recvbuf FAIL!\n", __FUNCTION__);
1321 		return NULL;
1322 	}
1323 
1324 	/* 3 2. alloc skb */
1325 	if (precvbuf->pskb == NULL) {
1326 		SIZE_PTR tmpaddr = 0;
1327 		SIZE_PTR alignment = 0;
1328 
1329 		precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
1330 		if (precvbuf->pskb == NULL) {
1331 			RTW_INFO("%s: alloc_skb fail! read=%d\n", __FUNCTION__, readsize);
1332 			rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
1333 			return NULL;
1334 		}
1335 
1336 		precvbuf->pskb->dev = padapter->pnetdev;
1337 
1338 		tmpaddr = (SIZE_PTR)precvbuf->pskb->data;
1339 		alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
1340 		skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
1341 	}
1342 
1343 	/* 3 3. read data from rxfifo */
1344 	preadbuf = precvbuf->pskb->data;
1345 	/*	rtw_read_port(padapter, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf); */
1346 	ret = sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
1347 	if (ret == _FAIL) {
1348 		rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
1349 		return NULL;
1350 	}
1351 
1352 	/* 3 4. init recvbuf */
1353 	precvbuf->len = size;
1354 	precvbuf->phead = precvbuf->pskb->head;
1355 	precvbuf->pdata = precvbuf->pskb->data;
1356 	skb_set_tail_pointer(precvbuf->pskb, size);
1357 	precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
1358 	precvbuf->pend = skb_end_pointer(precvbuf->pskb);
1359 
1360 	return precvbuf;
1361 }
1362 #else /* !CONFIG_SDIO_RX_COPY */
sd_recv_rxfifo(PADAPTER padapter,u32 size)1363 static struct recv_buf *sd_recv_rxfifo(PADAPTER padapter, u32 size)
1364 {
1365 	u32 sdioblksize, readsize, allocsize, ret;
1366 	u8 *preadbuf;
1367 	_pkt *ppkt;
1368 	struct recv_priv *precvpriv;
1369 	struct recv_buf	*precvbuf;
1370 
1371 
1372 	sdioblksize = adapter_to_dvobj(padapter)->intf_data.block_transfer_len;
1373 #if 0
1374 	readsize = size;
1375 #else
1376 	/* Patch for some SDIO Host 4 bytes issue */
1377 	/* ex. RK3188 */
1378 	readsize = RND4(size);
1379 #endif
1380 
1381 	/* 3 1. alloc skb */
1382 	/* align to block size */
1383 	if (readsize > sdioblksize)
1384 		allocsize = _RND(readsize, sdioblksize);
1385 	else
1386 		allocsize = readsize;
1387 
1388 	ppkt = rtw_skb_alloc(allocsize);
1389 
1390 	if (ppkt == NULL) {
1391 		return NULL;
1392 	}
1393 
1394 	/* 3 2. read data from rxfifo */
1395 	preadbuf = skb_put(ppkt, size);
1396 	/*	rtw_read_port(padapter, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf); */
1397 	ret = sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
1398 	if (ret == _FAIL) {
1399 		rtw_skb_free(ppkt);
1400 		return NULL;
1401 	}
1402 
1403 	/* 3 3. alloc recvbuf */
1404 	precvpriv = &padapter->recvpriv;
1405 	precvbuf = rtw_dequeue_recvbuf(&precvpriv->free_recv_buf_queue);
1406 	if (precvbuf == NULL) {
1407 		rtw_skb_free(ppkt);
1408 		RTW_ERR("%s: alloc recvbuf FAIL!\n", __FUNCTION__);
1409 		return NULL;
1410 	}
1411 
1412 	/* 3 4. init recvbuf */
1413 	precvbuf->pskb = ppkt;
1414 
1415 	precvbuf->len = ppkt->len;
1416 
1417 	precvbuf->phead = ppkt->head;
1418 	precvbuf->pdata = ppkt->data;
1419 	precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
1420 	precvbuf->pend = skb_end_pointer(precvbuf->pskb);
1421 
1422 	return precvbuf;
1423 }
1424 #endif /* !CONFIG_SDIO_RX_COPY */
1425 
sd_rxhandler(PADAPTER padapter,struct recv_buf * precvbuf)1426 static void sd_rxhandler(PADAPTER padapter, struct recv_buf *precvbuf)
1427 {
1428 	struct recv_priv *precvpriv;
1429 	_queue *ppending_queue;
1430 
1431 
1432 	precvpriv = &padapter->recvpriv;
1433 	ppending_queue = &precvpriv->recv_buf_pending_queue;
1434 
1435 	/* 3 1. enqueue recvbuf */
1436 	rtw_enqueue_recvbuf(precvbuf, ppending_queue);
1437 
1438 	/* 3 2. schedule tasklet */
1439 #ifdef PLATFORM_LINUX
1440 	tasklet_schedule(&precvpriv->recv_tasklet);
1441 #endif
1442 }
1443 
sd_int_dpc(PADAPTER padapter)1444 void sd_int_dpc(PADAPTER padapter)
1445 {
1446 	PHAL_DATA_TYPE phal;
1447 	struct dvobj_priv *dvobj;
1448 	struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
1449 	struct pwrctrl_priv *pwrctl;
1450 
1451 
1452 	phal = GET_HAL_DATA(padapter);
1453 	dvobj = adapter_to_dvobj(padapter);
1454 	pwrctl = dvobj_to_pwrctl(dvobj);
1455 
1456 #ifdef CONFIG_SDIO_TX_ENABLE_AVAL_INT
1457 	if (phal->sdio_hisr & SDIO_HISR_AVAL) {
1458 		/* _irqL irql; */
1459 		u8	freepage[4];
1460 
1461 		_sdio_local_read(padapter, SDIO_REG_FREE_TXPG, 4, freepage);
1462 		/* _enter_critical_bh(&phal->SdioTxFIFOFreePageLock, &irql); */
1463 		/* _rtw_memcpy(phal->SdioTxFIFOFreePage, freepage, 4); */
1464 		/* _exit_critical_bh(&phal->SdioTxFIFOFreePageLock, &irql); */
1465 		/* RTW_INFO("SDIO_HISR_AVAL, Tx Free Page = 0x%x%x%x%x\n", */
1466 		/*	freepage[0], */
1467 		/*	freepage[1], */
1468 		/*	freepage[2], */
1469 		/*	freepage[3]); */
1470 		_rtw_up_sema(&(padapter->xmitpriv.xmit_sema));
1471 	}
1472 #endif
1473 	if (phal->sdio_hisr & SDIO_HISR_CPWM1) {
1474 		struct reportpwrstate_parm report;
1475 
1476 #ifdef CONFIG_LPS_RPWM_TIMER
1477 		_cancel_timer_ex(&(pwrctl->pwr_rpwm_timer));
1478 #endif /* CONFIG_LPS_RPWM_TIMER */
1479 
1480 		report.state = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_HCPWM1_8723B);
1481 
1482 #ifdef CONFIG_LPS_LCLK
1483 		/* cpwm_int_hdl(padapter, &report); */
1484 		_set_workitem(&(pwrctl->cpwm_event));
1485 #endif
1486 	}
1487 
1488 	if (phal->sdio_hisr & SDIO_HISR_TXERR) {
1489 		u8 *status;
1490 		u32 addr;
1491 
1492 		status = rtw_malloc(4);
1493 		if (status) {
1494 			addr = REG_TXDMA_STATUS;
1495 			HalSdioGetCmdAddr8723BSdio(padapter, WLAN_IOREG_DEVICE_ID, addr, &addr);
1496 			_sd_read(pintfhdl, addr, 4, status);
1497 			_sd_write(pintfhdl, addr, 4, status);
1498 			RTW_INFO("%s: SDIO_HISR_TXERR (0x%08x)\n", __func__, le32_to_cpu(*(u32 *)status));
1499 			rtw_mfree(status, 4);
1500 		} else
1501 			RTW_INFO("%s: SDIO_HISR_TXERR, but can't allocate memory to read status!\n", __func__);
1502 	}
1503 
1504 	if (phal->sdio_hisr & SDIO_HISR_TXBCNOK)
1505 		RTW_INFO("%s: SDIO_HISR_TXBCNOK\n", __func__);
1506 
1507 	if (phal->sdio_hisr & SDIO_HISR_TXBCNERR)
1508 		RTW_INFO("%s: SDIO_HISR_TXBCNERR\n", __func__);
1509 
1510 #ifdef CONFIG_FW_C2H_REG
1511 	if (phal->sdio_hisr & SDIO_HISR_C2HCMD) {
1512 		RTW_INFO("%s: C2H Command\n", __func__);
1513 		sd_c2h_hisr_hdl(padapter);
1514 	}
1515 #endif
1516 
1517 	if (phal->sdio_hisr & SDIO_HISR_RXFOVW)
1518 		RTW_INFO("%s: Rx Overflow\n", __func__);
1519 	if (phal->sdio_hisr & SDIO_HISR_RXERR)
1520 		RTW_INFO("%s: Rx Error\n", __func__);
1521 
1522 	if (phal->sdio_hisr & SDIO_HISR_RX_REQUEST) {
1523 		struct recv_buf *precvbuf;
1524 		int alloc_fail_time = 0;
1525 		u32 hisr;
1526 
1527 		/*		RTW_INFO("%s: RX Request, size=%d\n", __func__, phal->SdioRxFIFOSize); */
1528 		phal->sdio_hisr ^= SDIO_HISR_RX_REQUEST;
1529 		do {
1530 			phal->SdioRxFIFOSize = SdioLocalCmd52Read2Byte(padapter, SDIO_REG_RX0_REQ_LEN);
1531 			if (phal->SdioRxFIFOSize != 0) {
1532 #ifdef CONFIG_MAC_LOOPBACK_DRIVER
1533 				sd_recv_loopback(padapter, phal->SdioRxFIFOSize);
1534 #else
1535 				precvbuf = sd_recv_rxfifo(padapter, phal->SdioRxFIFOSize);
1536 				if (precvbuf)
1537 					sd_rxhandler(padapter, precvbuf);
1538 				else {
1539 					alloc_fail_time++;
1540 					RTW_INFO("%s: recv fail!(time=%d)\n", __func__, alloc_fail_time);
1541 					if (alloc_fail_time >= 10)
1542 						break;
1543 				}
1544 				phal->SdioRxFIFOSize = 0;
1545 #endif
1546 			} else
1547 				break;
1548 
1549 			hisr = 0;
1550 			ReadInterrupt8723BSdio(padapter, &hisr);
1551 			hisr &= SDIO_HISR_RX_REQUEST;
1552 			if (!hisr)
1553 				break;
1554 		} while (1);
1555 
1556 		if (alloc_fail_time == 10)
1557 			RTW_INFO("%s: exit because recv failed more than 10 times!\n", __func__);
1558 	}
1559 }
1560 
sd_int_hdl(PADAPTER padapter)1561 void sd_int_hdl(PADAPTER padapter)
1562 {
1563 	PHAL_DATA_TYPE phal;
1564 
1565 
1566 	if (RTW_CANNOT_RUN(padapter))
1567 		return;
1568 
1569 	phal = GET_HAL_DATA(padapter);
1570 
1571 	phal->sdio_hisr = 0;
1572 	ReadInterrupt8723BSdio(padapter, &phal->sdio_hisr);
1573 
1574 	if (phal->sdio_hisr & phal->sdio_himr) {
1575 		u32 v32;
1576 
1577 		phal->sdio_hisr &= phal->sdio_himr;
1578 
1579 		/* clear HISR */
1580 		v32 = phal->sdio_hisr & MASK_SDIO_HISR_CLEAR;
1581 		if (v32)
1582 			SdioLocalCmd52Write4Byte(padapter, SDIO_REG_HISR, v32);
1583 
1584 		sd_int_dpc(padapter);
1585 	}
1586 }
1587 
1588 /*
1589  *	Description:
1590  *		Query SDIO Local register to query current the number of Free TxPacketBuffer page.
1591  *
1592  *	Assumption:
1593  *		1. Running at PASSIVE_LEVEL
1594  *		2. RT_TX_SPINLOCK is NOT acquired.
1595  *
1596  *	Created by Roger, 2011.01.28.
1597  *   */
HalQueryTxBufferStatus8723BSdio(PADAPTER padapter)1598 u8 HalQueryTxBufferStatus8723BSdio(PADAPTER padapter)
1599 {
1600 	PHAL_DATA_TYPE phal;
1601 	u32 NumOfFreePage;
1602 	/* _irqL irql; */
1603 
1604 
1605 	phal = GET_HAL_DATA(padapter);
1606 
1607 	NumOfFreePage = SdioLocalCmd53Read4Byte(padapter, SDIO_REG_FREE_TXPG);
1608 
1609 	/* _enter_critical_bh(&phal->SdioTxFIFOFreePageLock, &irql); */
1610 	_rtw_memcpy(phal->SdioTxFIFOFreePage, &NumOfFreePage, 4);
1611 	/* _exit_critical_bh(&phal->SdioTxFIFOFreePageLock, &irql); */
1612 
1613 	return _TRUE;
1614 }
1615 
1616 /*
1617  *	Description:
1618  *		Query SDIO Local register to get the current number of TX OQT Free Space.
1619  *   */
HalQueryTxOQTBufferStatus8723BSdio(PADAPTER padapter)1620 u8 HalQueryTxOQTBufferStatus8723BSdio(PADAPTER padapter)
1621 {
1622 	HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
1623 	pHalData->SdioTxOQTFreeSpace = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_OQT_FREE_PG);
1624 	return _TRUE;
1625 }
1626 
1627 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
RecvOnePkt(PADAPTER padapter)1628 u8 RecvOnePkt(PADAPTER padapter)
1629 {
1630 	struct recv_buf *precvbuf;
1631 	struct dvobj_priv *psddev;
1632 	PSDIO_DATA psdio_data;
1633 	struct sdio_func *func;
1634 	u32 tmp = 0;
1635 	u16 len = 0;
1636 	u8 res = _FALSE;
1637 
1638 	if (padapter == NULL) {
1639 		RTW_ERR("%s: padapter is NULL!\n", __func__);
1640 		return _FALSE;
1641 	}
1642 
1643 	psddev = adapter_to_dvobj(padapter);
1644 	psdio_data = &psddev->intf_data;
1645 	func = psdio_data->func;
1646 
1647 	/* If RX_DMA is not idle, receive one pkt from DMA */
1648 	res = sdio_local_read(padapter,
1649 			  SDIO_REG_RX0_REQ_LEN, 4, (u8 *)&tmp);
1650 	len = le16_to_cpu(tmp);
1651 	RTW_INFO("+%s: size: %d+\n", __func__, len);
1652 
1653 	if (len) {
1654 		sdio_claim_host(func);
1655 		precvbuf = sd_recv_rxfifo(padapter, len);
1656 
1657 		if (precvbuf) {
1658 			/* printk("Completed Recv One Pkt.\n"); */
1659 			sd_rxhandler(padapter, precvbuf);
1660 			res = _TRUE;
1661 		} else
1662 			res = _FALSE;
1663 		sdio_release_host(func);
1664 	}
1665 	RTW_INFO("-%s-\n", __func__);
1666 	return res;
1667 }
1668 #endif /* CONFIG_WOWLAN */
1669 
1670