xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/rtl8723cs/hal/rtl8703b/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 <rtl8703b_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  *   */
HalSdioGetCmdAddr8703BSdio(PADAPTER padapter,u8 DeviceID,u32 Addr,u32 * pCmdAddr)28 static void HalSdioGetCmdAddr8703BSdio(
29 		PADAPTER			padapter,
30 		u8				DeviceID,
31 		u32				Addr,
32 		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  *	HalSdioGetCmdAddr8703BSdio()
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 		sd_read(pintfhdl, ftaddr, 8, ptmpbuf);
234 		_rtw_memcpy(&val, ptmpbuf + shift, 4);
235 		val = le32_to_cpu(val);
236 
237 		rtw_mfree(ptmpbuf, 8);
238 	}
239 
240 
241 	return val;
242 }
243 
sdio_readN(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * pbuf)244 s32 sdio_readN(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pbuf)
245 {
246 	PADAPTER padapter;
247 	u8 bMacPwrCtrlOn;
248 	u8 deviceId;
249 	u16 offset;
250 	u32 ftaddr;
251 	u8 shift;
252 	s32 err;
253 
254 
255 	padapter = pintfhdl->padapter;
256 	err = 0;
257 
258 	ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
259 
260 	bMacPwrCtrlOn = _FALSE;
261 	rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
262 	if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100))
263 	    || (_FALSE == bMacPwrCtrlOn)
264 #ifdef CONFIG_LPS_LCLK
265 	    || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
266 #endif
267 	   ) {
268 		err = sd_cmd52_read(pintfhdl, ftaddr, cnt, pbuf);
269 		return err;
270 	}
271 
272 	/* 4 bytes alignment */
273 	shift = ftaddr & 0x3;
274 	if (shift == 0)
275 		err = sd_read(pintfhdl, ftaddr, cnt, pbuf);
276 	else {
277 		u8 *ptmpbuf;
278 		u32 n;
279 
280 		ftaddr &= ~(u16)0x3;
281 		n = cnt + shift;
282 		ptmpbuf = rtw_malloc(n);
283 		if (NULL == ptmpbuf)
284 			return -1;
285 		err = sd_read(pintfhdl, ftaddr, n, ptmpbuf);
286 		if (!err)
287 			_rtw_memcpy(pbuf, ptmpbuf + shift, cnt);
288 		rtw_mfree(ptmpbuf, n);
289 	}
290 
291 
292 	return err;
293 }
294 
sdio_write8(struct intf_hdl * pintfhdl,u32 addr,u8 val)295 s32 sdio_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
296 {
297 	u32 ftaddr;
298 	s32 err;
299 
300 	ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
301 	err = 0;
302 	sd_write8(pintfhdl, ftaddr, val, &err);
303 
304 
305 	return err;
306 }
307 
sdio_write16(struct intf_hdl * pintfhdl,u32 addr,u16 val)308 s32 sdio_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
309 {
310 	u32 ftaddr;
311 	u8 shift;
312 	s32 err;
313 
314 	ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
315 	val = cpu_to_le16(val);
316 	err = sd_cmd52_write(pintfhdl, ftaddr, 2, (u8 *)&val);
317 
318 
319 	return err;
320 }
321 
sdio_write32(struct intf_hdl * pintfhdl,u32 addr,u32 val)322 s32 sdio_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
323 {
324 	PADAPTER padapter;
325 	u8 bMacPwrCtrlOn;
326 	u8 deviceId;
327 	u16 offset;
328 	u32 ftaddr;
329 	u8 shift;
330 	s32 err;
331 
332 
333 	padapter = pintfhdl->padapter;
334 	err = 0;
335 
336 	ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
337 
338 	bMacPwrCtrlOn = _FALSE;
339 	rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
340 	if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100))
341 	    || (_FALSE == bMacPwrCtrlOn)
342 #ifdef CONFIG_LPS_LCLK
343 	    || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
344 #endif
345 	   ) {
346 		val = cpu_to_le32(val);
347 		err = sd_cmd52_write(pintfhdl, ftaddr, 4, (u8 *)&val);
348 		return err;
349 	}
350 
351 	/* 4 bytes alignment */
352 	shift = ftaddr & 0x3;
353 #if 1
354 	if (shift == 0)
355 		sd_write32(pintfhdl, ftaddr, val, &err);
356 	else {
357 		val = cpu_to_le32(val);
358 		err = sd_cmd52_write(pintfhdl, ftaddr, 4, (u8 *)&val);
359 	}
360 #else
361 	if (shift == 0)
362 		sd_write32(pintfhdl, ftaddr, val, &err);
363 	else {
364 		u8 *ptmpbuf;
365 
366 		ptmpbuf = (u8 *)rtw_malloc(8);
367 		if (NULL == ptmpbuf)
368 			return -1;
369 
370 		ftaddr &= ~(u16)0x3;
371 		err = sd_read(pintfhdl, ftaddr, 8, ptmpbuf);
372 		if (err) {
373 			rtw_mfree(ptmpbuf, 8);
374 			return err;
375 		}
376 		val = cpu_to_le32(val);
377 		_rtw_memcpy(ptmpbuf + shift, &val, 4);
378 		err = sd_write(pintfhdl, ftaddr, 8, ptmpbuf);
379 
380 		rtw_mfree(ptmpbuf, 8);
381 	}
382 #endif
383 
384 
385 	return err;
386 }
387 
sdio_writeN(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * pbuf)388 s32 sdio_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pbuf)
389 {
390 	PADAPTER padapter;
391 	u8 bMacPwrCtrlOn;
392 	u8 deviceId;
393 	u16 offset;
394 	u32 ftaddr;
395 	u8 shift;
396 	s32 err;
397 
398 
399 	padapter = pintfhdl->padapter;
400 	err = 0;
401 
402 	ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
403 
404 	bMacPwrCtrlOn = _FALSE;
405 	rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
406 	if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100))
407 	    || (_FALSE == bMacPwrCtrlOn)
408 #ifdef CONFIG_LPS_LCLK
409 	    || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
410 #endif
411 	   ) {
412 		err = sd_cmd52_write(pintfhdl, ftaddr, cnt, pbuf);
413 		return err;
414 	}
415 
416 	shift = ftaddr & 0x3;
417 	if (shift == 0)
418 		err = sd_write(pintfhdl, ftaddr, cnt, pbuf);
419 	else {
420 		u8 *ptmpbuf;
421 		u32 n;
422 
423 		ftaddr &= ~(u16)0x3;
424 		n = cnt + shift;
425 		ptmpbuf = rtw_malloc(n);
426 		if (NULL == ptmpbuf)
427 			return -1;
428 		err = sd_read(pintfhdl, ftaddr, 4, ptmpbuf);
429 		if (err) {
430 			rtw_mfree(ptmpbuf, n);
431 			return err;
432 		}
433 		_rtw_memcpy(ptmpbuf + shift, pbuf, cnt);
434 		err = sd_write(pintfhdl, ftaddr, n, ptmpbuf);
435 		rtw_mfree(ptmpbuf, n);
436 	}
437 
438 
439 	return err;
440 }
441 
sdio_f0_read8(struct intf_hdl * pintfhdl,u32 addr)442 u8 sdio_f0_read8(struct intf_hdl *pintfhdl, u32 addr)
443 {
444 	u32 ftaddr;
445 	u8 val;
446 
447 	val = sd_f0_read8(pintfhdl, addr, NULL);
448 
449 
450 	return val;
451 }
452 
sdio_read_mem(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * rmem)453 void sdio_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
454 {
455 	s32 err;
456 
457 
458 	err = sdio_readN(pintfhdl, addr, cnt, rmem);
459 
460 }
461 
sdio_write_mem(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * wmem)462 void sdio_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
463 {
464 
465 	sdio_writeN(pintfhdl, addr, cnt, wmem);
466 
467 }
468 
469 /*
470  * Description:
471  *	Read from RX FIFO
472  *	Round read size to block size,
473  *	and make sure data transfer will be done in one command.
474  *
475  * Parameters:
476  *	pintfhdl	a pointer of intf_hdl
477  *	addr		port ID
478  *	cnt			size to read
479  *	rmem		address to put data
480  *
481  * Return:
482  *	_SUCCESS(1)		Success
483  *	_FAIL(0)		Fail
484  */
sdio_read_port(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * mem)485 static u32 sdio_read_port(
486 	struct intf_hdl *pintfhdl,
487 	u32 addr,
488 	u32 cnt,
489 	u8 *mem)
490 {
491 	PADAPTER padapter;
492 	PHAL_DATA_TYPE phal;
493 	u32 oldcnt;
494 #ifdef SDIO_DYNAMIC_ALLOC_MEM
495 	u8 *oldmem;
496 #endif
497 	s32 err;
498 
499 
500 	padapter = pintfhdl->padapter;
501 	phal = GET_HAL_DATA(padapter);
502 
503 	HalSdioGetCmdAddr8703BSdio(padapter, addr, phal->SdioRxFIFOCnt++, &addr);
504 
505 	oldcnt = cnt;
506 	cnt = rtw_sdio_cmd53_align_size(adapter_to_dvobj(padapter), cnt);
507 
508 	if (oldcnt != cnt) {
509 #ifdef SDIO_DYNAMIC_ALLOC_MEM
510 		oldmem = mem;
511 		mem = rtw_malloc(cnt);
512 		if (mem == NULL) {
513 			RTW_WARN("%s: allocate memory %d bytes fail!\n", __func__, cnt);
514 			mem = oldmem;
515 			oldmem == NULL;
516 		}
517 #else
518 		/* in this case, caller should gurante the buffer is big enough */
519 		/* to receive data after alignment */
520 #endif
521 	}
522 
523 	err = _sd_read(pintfhdl, addr, cnt, mem);
524 
525 #ifdef SDIO_DYNAMIC_ALLOC_MEM
526 	if ((oldcnt != cnt) && (oldmem)) {
527 		_rtw_memcpy(oldmem, mem, oldcnt);
528 		rtw_mfree(mem, cnt);
529 	}
530 #endif
531 
532 	if (err)
533 		return _FAIL;
534 	return _SUCCESS;
535 }
536 
537 /*
538  * Description:
539  *	Write to TX FIFO
540  *	Align write size block size,
541  *	and make sure data could be written in one command.
542  *
543  * Parameters:
544  *	pintfhdl	a pointer of intf_hdl
545  *	addr		port ID
546  *	cnt			size to write
547  *	wmem		data pointer to write
548  *
549  * Return:
550  *	_SUCCESS(1)		Success
551  *	_FAIL(0)		Fail
552  */
sdio_write_port(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * mem)553 static u32 sdio_write_port(
554 	struct intf_hdl *pintfhdl,
555 	u32 addr,
556 	u32 cnt,
557 	u8 *mem)
558 {
559 	PADAPTER padapter;
560 	s32 err;
561 	struct xmit_buf *xmitbuf = (struct xmit_buf *)mem;
562 
563 	padapter = pintfhdl->padapter;
564 
565 	if (!rtw_is_hw_init_completed(padapter)) {
566 		RTW_INFO("%s [addr=0x%x cnt=%d] padapter->hw_init_completed == _FALSE\n", __func__, addr, cnt);
567 		return _FAIL;
568 	}
569 
570 	cnt = _RND4(cnt);
571 	HalSdioGetCmdAddr8703BSdio(padapter, addr, cnt >> 2, &addr);
572 
573 	cnt = rtw_sdio_cmd53_align_size(adapter_to_dvobj(padapter), cnt);
574 
575 	err = sd_write(pintfhdl, addr, cnt, xmitbuf->pdata);
576 
577 	rtw_sctx_done_err(&xmitbuf->sctx,
578 		  err ? RTW_SCTX_DONE_WRITE_PORT_ERR : RTW_SCTX_DONE_SUCCESS);
579 
580 	if (err)
581 		return _FAIL;
582 	return _SUCCESS;
583 }
584 
sdio_set_intf_ops(_adapter * padapter,struct _io_ops * pops)585 void sdio_set_intf_ops(_adapter *padapter, struct _io_ops *pops)
586 {
587 
588 	pops->_read8 = &sdio_read8;
589 	pops->_read16 = &sdio_read16;
590 	pops->_read32 = &sdio_read32;
591 	pops->_read_mem = &sdio_read_mem;
592 	pops->_read_port = &sdio_read_port;
593 
594 	pops->_write8 = &sdio_write8;
595 	pops->_write16 = &sdio_write16;
596 	pops->_write32 = &sdio_write32;
597 	pops->_writeN = &sdio_writeN;
598 	pops->_write_mem = &sdio_write_mem;
599 	pops->_write_port = &sdio_write_port;
600 
601 	pops->_sd_f0_read8 = sdio_f0_read8;
602 
603 }
604 
605 /*
606  * Todo: align address to 4 bytes.
607  */
_sdio_local_read(PADAPTER padapter,u32 addr,u32 cnt,u8 * pbuf)608 s32 _sdio_local_read(
609 	PADAPTER	padapter,
610 	u32			addr,
611 	u32			cnt,
612 	u8			*pbuf)
613 {
614 	struct intf_hdl *pintfhdl;
615 	u8 bMacPwrCtrlOn;
616 	s32 err;
617 	u8 *ptmpbuf;
618 	u32 n;
619 
620 
621 	pintfhdl = &padapter->iopriv.intf;
622 
623 	HalSdioGetCmdAddr8703BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
624 
625 	bMacPwrCtrlOn = _FALSE;
626 	rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
627 	if (_FALSE == bMacPwrCtrlOn) {
628 		err = _sd_cmd52_read(pintfhdl, addr, cnt, pbuf);
629 		return err;
630 	}
631 
632 	n = RND4(cnt);
633 	ptmpbuf = (u8 *)rtw_malloc(n);
634 	if (!ptmpbuf)
635 		return -1;
636 
637 	err = _sd_read(pintfhdl, addr, n, ptmpbuf);
638 	if (!err)
639 		_rtw_memcpy(pbuf, ptmpbuf, cnt);
640 
641 	if (ptmpbuf)
642 		rtw_mfree(ptmpbuf, n);
643 
644 	return err;
645 }
646 
647 /*
648  * Todo: align address to 4 bytes.
649  */
sdio_local_read(PADAPTER padapter,u32 addr,u32 cnt,u8 * pbuf)650 s32 sdio_local_read(
651 	PADAPTER	padapter,
652 	u32			addr,
653 	u32			cnt,
654 	u8			*pbuf)
655 {
656 	struct intf_hdl *pintfhdl;
657 	u8 bMacPwrCtrlOn;
658 	s32 err;
659 	u8 *ptmpbuf;
660 	u32 n;
661 
662 	pintfhdl = &padapter->iopriv.intf;
663 
664 	HalSdioGetCmdAddr8703BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
665 
666 	bMacPwrCtrlOn = _FALSE;
667 	rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
668 	if ((_FALSE == bMacPwrCtrlOn)
669 #ifdef CONFIG_LPS_LCLK
670 	    || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
671 #endif
672 	   ) {
673 		err = sd_cmd52_read(pintfhdl, addr, cnt, pbuf);
674 		return err;
675 	}
676 
677 	n = RND4(cnt);
678 	ptmpbuf = (u8 *)rtw_malloc(n);
679 	if (!ptmpbuf)
680 		return -1;
681 
682 	err = sd_read(pintfhdl, addr, n, ptmpbuf);
683 	if (!err)
684 		_rtw_memcpy(pbuf, ptmpbuf, cnt);
685 
686 	if (ptmpbuf)
687 		rtw_mfree(ptmpbuf, n);
688 
689 	return err;
690 }
691 
692 /*
693  * Todo: align address to 4 bytes.
694  */
_sdio_local_write(PADAPTER padapter,u32 addr,u32 cnt,u8 * pbuf)695 s32 _sdio_local_write(
696 	PADAPTER	padapter,
697 	u32			addr,
698 	u32			cnt,
699 	u8			*pbuf)
700 {
701 	struct intf_hdl *pintfhdl;
702 	u8 bMacPwrCtrlOn;
703 	s32 err;
704 	u8 *ptmpbuf;
705 
706 	if (addr & 0x3)
707 		RTW_INFO("%s, address must be 4 bytes alignment\n", __FUNCTION__);
708 
709 	if (cnt  & 0x3)
710 		RTW_INFO("%s, size must be the multiple of 4\n", __FUNCTION__);
711 
712 	pintfhdl = &padapter->iopriv.intf;
713 
714 	HalSdioGetCmdAddr8703BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
715 
716 	bMacPwrCtrlOn = _FALSE;
717 	rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
718 	if ((_FALSE == bMacPwrCtrlOn)
719 #ifdef CONFIG_LPS_LCLK
720 	    || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
721 #endif
722 	   ) {
723 		err = _sd_cmd52_write(pintfhdl, addr, cnt, pbuf);
724 		return err;
725 	}
726 
727 	ptmpbuf = (u8 *)rtw_malloc(cnt);
728 	if (!ptmpbuf)
729 		return -1;
730 
731 	_rtw_memcpy(ptmpbuf, pbuf, cnt);
732 
733 	err = _sd_write(pintfhdl, addr, cnt, ptmpbuf);
734 
735 	if (ptmpbuf)
736 		rtw_mfree(ptmpbuf, cnt);
737 
738 	return err;
739 }
740 
741 /*
742  * Todo: align address to 4 bytes.
743  */
sdio_local_write(PADAPTER padapter,u32 addr,u32 cnt,u8 * pbuf)744 s32 sdio_local_write(
745 	PADAPTER	padapter,
746 	u32		addr,
747 	u32		cnt,
748 	u8		*pbuf)
749 {
750 	struct intf_hdl *pintfhdl;
751 	u8 bMacPwrCtrlOn;
752 	s32 err;
753 	u8 *ptmpbuf;
754 
755 	if (addr & 0x3)
756 		RTW_INFO("%s, address must be 4 bytes alignment\n", __FUNCTION__);
757 
758 	if (cnt  & 0x3)
759 		RTW_INFO("%s, size must be the multiple of 4\n", __FUNCTION__);
760 
761 	pintfhdl = &padapter->iopriv.intf;
762 
763 	HalSdioGetCmdAddr8703BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
764 
765 	bMacPwrCtrlOn = _FALSE;
766 	rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
767 	if ((_FALSE == bMacPwrCtrlOn)
768 #ifdef CONFIG_LPS_LCLK
769 	    || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
770 #endif
771 	   ) {
772 		err = sd_cmd52_write(pintfhdl, addr, cnt, pbuf);
773 		return err;
774 	}
775 
776 	ptmpbuf = (u8 *)rtw_malloc(cnt);
777 	if (!ptmpbuf)
778 		return -1;
779 
780 	_rtw_memcpy(ptmpbuf, pbuf, cnt);
781 
782 	err = sd_write(pintfhdl, addr, cnt, ptmpbuf);
783 
784 	if (ptmpbuf)
785 		rtw_mfree(ptmpbuf, cnt);
786 
787 	return err;
788 }
789 
SdioLocalCmd52Read1Byte(PADAPTER padapter,u32 addr)790 u8 SdioLocalCmd52Read1Byte(PADAPTER padapter, u32 addr)
791 {
792 	u8 val = 0;
793 	struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
794 
795 	HalSdioGetCmdAddr8703BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
796 	sd_cmd52_read(pintfhdl, addr, 1, &val);
797 
798 	return val;
799 }
800 
SdioLocalCmd52Read2Byte(PADAPTER padapter,u32 addr)801 u16 SdioLocalCmd52Read2Byte(PADAPTER padapter, u32 addr)
802 {
803 	u16 val = 0;
804 	struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
805 
806 	HalSdioGetCmdAddr8703BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
807 	sd_cmd52_read(pintfhdl, addr, 2, (u8 *)&val);
808 
809 	val = le16_to_cpu(val);
810 
811 	return val;
812 }
813 
SdioLocalCmd52Read4Byte(PADAPTER padapter,u32 addr)814 u32 SdioLocalCmd52Read4Byte(PADAPTER padapter, u32 addr)
815 {
816 	u32 val = 0;
817 	struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
818 
819 	HalSdioGetCmdAddr8703BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
820 	sd_cmd52_read(pintfhdl, addr, 4, (u8 *)&val);
821 
822 	val = le32_to_cpu(val);
823 
824 	return val;
825 }
826 
SdioLocalCmd53Read4Byte(PADAPTER padapter,u32 addr)827 u32 SdioLocalCmd53Read4Byte(PADAPTER padapter, u32 addr)
828 {
829 
830 	u8 bMacPwrCtrlOn;
831 	u32 val = 0;
832 	struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
833 
834 	HalSdioGetCmdAddr8703BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
835 	bMacPwrCtrlOn = _FALSE;
836 	rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
837 	if ((_FALSE == bMacPwrCtrlOn)
838 #ifdef CONFIG_LPS_LCLK
839 	    || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
840 #endif
841 	   ) {
842 		sd_cmd52_read(pintfhdl, addr, 4, (u8 *)&val);
843 		val = le32_to_cpu(val);
844 	} else
845 		val = sd_read32(pintfhdl, addr, NULL);
846 
847 	return val;
848 }
849 
SdioLocalCmd52Write1Byte(PADAPTER padapter,u32 addr,u8 v)850 void SdioLocalCmd52Write1Byte(PADAPTER padapter, u32 addr, u8 v)
851 {
852 	struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
853 
854 	HalSdioGetCmdAddr8703BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
855 	sd_cmd52_write(pintfhdl, addr, 1, &v);
856 }
857 
SdioLocalCmd52Write2Byte(PADAPTER padapter,u32 addr,u16 v)858 void SdioLocalCmd52Write2Byte(PADAPTER padapter, u32 addr, u16 v)
859 {
860 	struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
861 
862 	HalSdioGetCmdAddr8703BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
863 	v = cpu_to_le16(v);
864 	sd_cmd52_write(pintfhdl, addr, 2, (u8 *)&v);
865 }
866 
SdioLocalCmd52Write4Byte(PADAPTER padapter,u32 addr,u32 v)867 void SdioLocalCmd52Write4Byte(PADAPTER padapter, u32 addr, u32 v)
868 {
869 	struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
870 	HalSdioGetCmdAddr8703BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
871 	v = cpu_to_le32(v);
872 	sd_cmd52_write(pintfhdl, addr, 4, (u8 *)&v);
873 }
874 
875 #if 0
876 void
877 DumpLoggedInterruptHistory8703Sdio(
878 	PADAPTER		padapter
879 )
880 {
881 	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
882 	u32				DebugLevel = DBG_LOUD;
883 
884 	if (DBG_Var.DbgPrintIsr == 0)
885 		return;
886 
887 	DBG_ChkDrvResource(padapter);
888 
889 
890 }
891 
892 void
893 LogInterruptHistory8703Sdio(
894 	PADAPTER			padapter,
895 	PRT_ISR_CONTENT	pIsrContent
896 )
897 {
898 	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
899 
900 	if ((pHalData->IntrMask[0] & SDIO_HIMR_RX_REQUEST_MSK) &&
901 	    (pIsrContent->IntArray[0] & SDIO_HISR_RX_REQUEST))
902 		pHalData->InterruptLog.nISR_RX_REQUEST++;
903 	if ((pHalData->IntrMask[0] & SDIO_HIMR_AVAL_MSK) &&
904 	    (pIsrContent->IntArray[0] & SDIO_HISR_AVAL))
905 		pHalData->InterruptLog.nISR_AVAL++;
906 	if ((pHalData->IntrMask[0] & SDIO_HIMR_TXERR_MSK) &&
907 	    (pIsrContent->IntArray[0] & SDIO_HISR_TXERR))
908 		pHalData->InterruptLog.nISR_TXERR++;
909 	if ((pHalData->IntrMask[0] & SDIO_HIMR_RXERR_MSK) &&
910 	    (pIsrContent->IntArray[0] & SDIO_HISR_RXERR))
911 		pHalData->InterruptLog.nISR_RXERR++;
912 	if ((pHalData->IntrMask[0] & SDIO_HIMR_TXFOVW_MSK) &&
913 	    (pIsrContent->IntArray[0] & SDIO_HISR_TXFOVW))
914 		pHalData->InterruptLog.nISR_TXFOVW++;
915 	if ((pHalData->IntrMask[0] & SDIO_HIMR_RXFOVW_MSK) &&
916 	    (pIsrContent->IntArray[0] & SDIO_HISR_RXFOVW))
917 		pHalData->InterruptLog.nISR_RXFOVW++;
918 	if ((pHalData->IntrMask[0] & SDIO_HIMR_TXBCNOK_MSK) &&
919 	    (pIsrContent->IntArray[0] & SDIO_HISR_TXBCNOK))
920 		pHalData->InterruptLog.nISR_TXBCNOK++;
921 	if ((pHalData->IntrMask[0] & SDIO_HIMR_TXBCNERR_MSK) &&
922 	    (pIsrContent->IntArray[0] & SDIO_HISR_TXBCNERR))
923 		pHalData->InterruptLog.nISR_TXBCNERR++;
924 	if ((pHalData->IntrMask[0] & SDIO_HIMR_BCNERLY_INT_MSK) &&
925 	    (pIsrContent->IntArray[0] & SDIO_HISR_BCNERLY_INT))
926 		pHalData->InterruptLog.nISR_BCNERLY_INT++;
927 	if ((pHalData->IntrMask[0] & SDIO_HIMR_C2HCMD_MSK) &&
928 	    (pIsrContent->IntArray[0] & SDIO_HISR_C2HCMD))
929 		pHalData->InterruptLog.nISR_C2HCMD++;
930 	if ((pHalData->IntrMask[0] & SDIO_HIMR_CPWM1_MSK) &&
931 	    (pIsrContent->IntArray[0] & SDIO_HISR_CPWM1))
932 		pHalData->InterruptLog.nISR_CPWM1++;
933 	if ((pHalData->IntrMask[0] & SDIO_HIMR_CPWM2_MSK) &&
934 	    (pIsrContent->IntArray[0] & SDIO_HISR_CPWM2))
935 		pHalData->InterruptLog.nISR_CPWM2++;
936 	if ((pHalData->IntrMask[0] & SDIO_HIMR_HSISR_IND_MSK) &&
937 	    (pIsrContent->IntArray[0] & SDIO_HISR_HSISR_IND))
938 		pHalData->InterruptLog.nISR_HSISR_IND++;
939 	if ((pHalData->IntrMask[0] & SDIO_HIMR_GTINT3_IND_MSK) &&
940 	    (pIsrContent->IntArray[0] & SDIO_HISR_GTINT3_IND))
941 		pHalData->InterruptLog.nISR_GTINT3_IND++;
942 	if ((pHalData->IntrMask[0] & SDIO_HIMR_GTINT4_IND_MSK) &&
943 	    (pIsrContent->IntArray[0] & SDIO_HISR_GTINT4_IND))
944 		pHalData->InterruptLog.nISR_GTINT4_IND++;
945 	if ((pHalData->IntrMask[0] & SDIO_HIMR_PSTIMEOUT_MSK) &&
946 	    (pIsrContent->IntArray[0] & SDIO_HISR_PSTIMEOUT))
947 		pHalData->InterruptLog.nISR_PSTIMEOUT++;
948 	if ((pHalData->IntrMask[0] & SDIO_HIMR_OCPINT_MSK) &&
949 	    (pIsrContent->IntArray[0] & SDIO_HISR_OCPINT))
950 		pHalData->InterruptLog.nISR_OCPINT++;
951 	if ((pHalData->IntrMask[0] & SDIO_HIMR_ATIMEND_MSK) &&
952 	    (pIsrContent->IntArray[0] & SDIO_HISR_ATIMEND))
953 		pHalData->InterruptLog.nISR_ATIMEND++;
954 	if ((pHalData->IntrMask[0] & SDIO_HIMR_ATIMEND_E_MSK) &&
955 	    (pIsrContent->IntArray[0] & SDIO_HISR_ATIMEND_E))
956 		pHalData->InterruptLog.nISR_ATIMEND_E++;
957 	if ((pHalData->IntrMask[0] & SDIO_HIMR_CTWEND_MSK) &&
958 	    (pIsrContent->IntArray[0] & SDIO_HISR_CTWEND))
959 		pHalData->InterruptLog.nISR_CTWEND++;
960 
961 }
962 
963 void
964 DumpHardwareProfile8703Sdio(
965 		PADAPTER		padapter
966 )
967 {
968 	DumpLoggedInterruptHistory8703Sdio(padapter);
969 }
970 #endif
971 
ReadInterrupt8703BSdio(PADAPTER padapter,u32 * phisr)972 static s32 ReadInterrupt8703BSdio(PADAPTER padapter, u32 *phisr)
973 {
974 	u32 hisr, himr;
975 	u8 val8, hisr_len;
976 
977 
978 	if (phisr == NULL)
979 		return _FALSE;
980 
981 	himr = GET_HAL_DATA(padapter)->sdio_himr;
982 
983 	/* decide how many bytes need to be read */
984 	hisr_len = 0;
985 	while (himr) {
986 		hisr_len++;
987 		himr >>= 8;
988 	}
989 
990 	hisr = 0;
991 	while (hisr_len != 0) {
992 		hisr_len--;
993 		val8 = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_HISR + hisr_len);
994 		hisr |= (val8 << (8 * hisr_len));
995 	}
996 
997 	*phisr = hisr;
998 
999 	return _TRUE;
1000 }
1001 
1002 /*
1003  *	Description:
1004  *		Initialize SDIO Host Interrupt Mask configuration variables for future use.
1005  *
1006  *	Assumption:
1007  *		Using SDIO Local register ONLY for configuration.
1008  *
1009  *	Created by Roger, 2011.02.11.
1010  *   */
InitInterrupt8703BSdio(PADAPTER padapter)1011 void InitInterrupt8703BSdio(PADAPTER padapter)
1012 {
1013 	PHAL_DATA_TYPE pHalData;
1014 
1015 
1016 	pHalData = GET_HAL_DATA(padapter);
1017 	pHalData->sdio_himr = (u32)(\
1018 				    SDIO_HIMR_RX_REQUEST_MSK			|
1019 #ifdef CONFIG_SDIO_TX_ENABLE_AVAL_INT
1020 				    SDIO_HIMR_AVAL_MSK					|
1021 #endif
1022 				    /*								SDIO_HIMR_TXERR_MSK				|
1023 				     *								SDIO_HIMR_RXERR_MSK				|
1024 				     *								SDIO_HIMR_TXFOVW_MSK				|
1025 				     *								SDIO_HIMR_RXFOVW_MSK				|
1026 				     *								SDIO_HIMR_TXBCNOK_MSK				|
1027 				     *								SDIO_HIMR_TXBCNERR_MSK			|
1028 				     *								SDIO_HIMR_BCNERLY_INT_MSK			|
1029 				     *								SDIO_HIMR_C2HCMD_MSK				| */
1030 #if defined(CONFIG_LPS_LCLK) && !defined(CONFIG_DETECT_CPWM_BY_POLLING)
1031 				    SDIO_HIMR_CPWM1_MSK				|
1032 #endif /* CONFIG_LPS_LCLK && !CONFIG_DETECT_CPWM_BY_POLLING */
1033 #ifdef CONFIG_WOWLAN
1034 				    SDIO_HIMR_CPWM2_MSK				|
1035 #endif
1036 				    /*								SDIO_HIMR_HSISR_IND_MSK			|
1037 				     *								SDIO_HIMR_GTINT3_IND_MSK			|
1038 				     *								SDIO_HIMR_GTINT4_IND_MSK			|
1039 				     *								SDIO_HIMR_PSTIMEOUT_MSK			|
1040 				     *								SDIO_HIMR_OCPINT_MSK				|
1041 				     *								SDIO_HIMR_ATIMEND_MSK				|
1042 				     *								SDIO_HIMR_ATIMEND_E_MSK			|
1043 				     *								SDIO_HIMR_CTWEND_MSK				| */
1044 				    0);
1045 }
1046 
1047 /*
1048  *	Description:
1049  *		Initialize System Host Interrupt Mask configuration variables for future use.
1050  *
1051  *	Created by Roger, 2011.08.03.
1052  *   */
InitSysInterrupt8703BSdio(PADAPTER padapter)1053 void InitSysInterrupt8703BSdio(PADAPTER padapter)
1054 {
1055 	PHAL_DATA_TYPE pHalData;
1056 
1057 
1058 	pHalData = GET_HAL_DATA(padapter);
1059 
1060 	pHalData->SysIntrMask = (\
1061 				 /*							HSIMR_GPIO12_0_INT_EN			|
1062 				  *							HSIMR_SPS_OCP_INT_EN			|
1063 				  *							HSIMR_RON_INT_EN				|
1064 				  *							HSIMR_PDNINT_EN				|
1065 				  *							HSIMR_GPIO9_INT_EN				| */
1066 				 0);
1067 }
1068 
1069 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
1070 /*
1071  *	Description:
1072  *		Clear corresponding SDIO Host ISR interrupt service.
1073  *
1074  *	Assumption:
1075  *		Using SDIO Local register ONLY for configuration.
1076  *
1077  *	Created by Roger, 2011.02.11.
1078  *   */
ClearInterrupt8703BSdio(PADAPTER padapter)1079 void ClearInterrupt8703BSdio(PADAPTER padapter)
1080 {
1081 	PHAL_DATA_TYPE pHalData;
1082 	u8 *clear;
1083 
1084 
1085 	if (rtw_is_surprise_removed(padapter))
1086 		return;
1087 
1088 	pHalData = GET_HAL_DATA(padapter);
1089 	clear = rtw_zmalloc(4);
1090 
1091 	/* Clear corresponding HISR Content if needed */
1092 	*(u32 *)clear = cpu_to_le32(pHalData->sdio_hisr & MASK_SDIO_HISR_CLEAR);
1093 	if (*(u32 *)clear) {
1094 		/* Perform write one clear operation */
1095 		sdio_local_write(padapter, SDIO_REG_HISR, 4, clear);
1096 	}
1097 
1098 	rtw_mfree(clear, 4);
1099 }
1100 #endif
1101 
1102 /*
1103  *	Description:
1104  *		Clear corresponding system Host ISR interrupt service.
1105  *
1106  *
1107  *	Created by Roger, 2011.02.11.
1108  *   */
ClearSysInterrupt8703BSdio(PADAPTER padapter)1109 void ClearSysInterrupt8703BSdio(PADAPTER padapter)
1110 {
1111 	PHAL_DATA_TYPE pHalData;
1112 	u32 clear;
1113 
1114 
1115 	if (rtw_is_surprise_removed(padapter))
1116 		return;
1117 
1118 	pHalData = GET_HAL_DATA(padapter);
1119 
1120 	/* Clear corresponding HISR Content if needed */
1121 	clear = pHalData->SysIntrStatus & MASK_HSISR_CLEAR;
1122 	if (clear) {
1123 		/* Perform write one clear operation */
1124 		rtw_write32(padapter, REG_HSISR, clear);
1125 	}
1126 }
1127 
1128 /*
1129  *	Description:
1130  *		Enalbe SDIO Host Interrupt Mask configuration on SDIO local domain.
1131  *
1132  *	Assumption:
1133  *		1. Using SDIO Local register ONLY for configuration.
1134  *		2. PASSIVE LEVEL
1135  *
1136  *	Created by Roger, 2011.02.11.
1137  *   */
EnableInterrupt8703BSdio(PADAPTER padapter)1138 void EnableInterrupt8703BSdio(PADAPTER padapter)
1139 {
1140 	PHAL_DATA_TYPE pHalData;
1141 	u32 himr;
1142 
1143 	pHalData = GET_HAL_DATA(padapter);
1144 
1145 	himr = cpu_to_le32(pHalData->sdio_himr);
1146 	sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
1147 
1148 
1149 	/* Update current system IMR settings */
1150 	himr = rtw_read32(padapter, REG_HSIMR);
1151 	rtw_write32(padapter, REG_HSIMR, himr | pHalData->SysIntrMask);
1152 
1153 
1154 	/*  */
1155 	/* <Roger_Notes> There are some C2H CMDs have been sent before system interrupt is enabled, e.g., C2H, CPWM. */
1156 	/* So we need to clear all C2H events that FW has notified, otherwise FW won't schedule any commands anymore. */
1157 	/* 2011.10.19. */
1158 	/*  */
1159 	rtw_write8(padapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
1160 }
1161 
1162 /*
1163  *	Description:
1164  *		Disable SDIO Host IMR configuration to mask unnecessary interrupt service.
1165  *
1166  *	Assumption:
1167  *		Using SDIO Local register ONLY for configuration.
1168  *
1169  *	Created by Roger, 2011.02.11.
1170  *   */
DisableInterrupt8703BSdio(PADAPTER padapter)1171 void DisableInterrupt8703BSdio(PADAPTER padapter)
1172 {
1173 	u32 himr;
1174 
1175 	himr = cpu_to_le32(SDIO_HIMR_DISABLED);
1176 	sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
1177 
1178 }
1179 
1180 /*
1181  *	Description:
1182  *		Using 0x100 to check the power status of FW.
1183  *
1184  *	Assumption:
1185  *		Using SDIO Local register ONLY for configuration.
1186  *
1187  *	Created by Isaac, 2013.09.10.
1188  *   */
CheckIPSStatus(PADAPTER padapter)1189 u8 CheckIPSStatus(PADAPTER padapter)
1190 {
1191 	RTW_INFO("%s(): Read 0x100=0x%02x 0x86=0x%02x\n", __func__,
1192 		 rtw_read8(padapter, 0x100), rtw_read8(padapter, 0x86));
1193 
1194 	if (rtw_read8(padapter, 0x100) == 0xEA)
1195 		return _TRUE;
1196 	else
1197 		return _FALSE;
1198 }
1199 
1200 #ifdef CONFIG_WOWLAN
DisableInterruptButCpwm28703BSdio(PADAPTER padapter)1201 void DisableInterruptButCpwm28703BSdio(PADAPTER padapter)
1202 {
1203 	u32 himr, tmp;
1204 
1205 	sdio_local_read(padapter, SDIO_REG_HIMR, 4, (u8 *)&tmp);
1206 	RTW_INFO("DisableInterruptButCpwm28703BSdio(): Read SDIO_REG_HIMR: 0x%08x\n", tmp);
1207 
1208 	himr = cpu_to_le32(SDIO_HIMR_DISABLED) | SDIO_HIMR_CPWM2_MSK;
1209 	sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
1210 
1211 	sdio_local_read(padapter, SDIO_REG_HIMR, 4, (u8 *)&tmp);
1212 	RTW_INFO("DisableInterruptButCpwm28703BSdio(): Read again SDIO_REG_HIMR: 0x%08x\n", tmp);
1213 }
1214 #endif /* CONFIG_WOWLAN
1215  *
1216  *	Description:
1217  *		Update SDIO Host Interrupt Mask configuration on SDIO local domain.
1218  *
1219  *	Assumption:
1220  *		1. Using SDIO Local register ONLY for configuration.
1221  *		2. PASSIVE LEVEL
1222  *
1223  *	Created by Roger, 2011.02.11.
1224  *   */
UpdateInterruptMask8703BSdio(PADAPTER padapter,u32 AddMSR,u32 RemoveMSR)1225 void UpdateInterruptMask8703BSdio(PADAPTER padapter, u32 AddMSR, u32 RemoveMSR)
1226 {
1227 	HAL_DATA_TYPE *pHalData;
1228 
1229 	pHalData = GET_HAL_DATA(padapter);
1230 
1231 	if (AddMSR)
1232 		pHalData->sdio_himr |= AddMSR;
1233 
1234 	if (RemoveMSR)
1235 		pHalData->sdio_himr &= (~RemoveMSR);
1236 
1237 	DisableInterrupt8703BSdio(padapter);
1238 	EnableInterrupt8703BSdio(padapter);
1239 }
1240 
1241 #ifdef CONFIG_MAC_LOOPBACK_DRIVER
sd_recv_loopback(PADAPTER padapter,u32 size)1242 static void sd_recv_loopback(PADAPTER padapter, u32 size)
1243 {
1244 	PLOOPBACKDATA ploopback;
1245 	u32 readsize, allocsize;
1246 	u8 *preadbuf;
1247 
1248 
1249 	readsize = size;
1250 	RTW_INFO("%s: read size=%d\n", __func__, readsize);
1251 	allocsize = _RND(readsize, rtw_sdio_get_block_size(adapter_to_dvobj(padapter)));
1252 
1253 	ploopback = padapter->ploopback;
1254 	if (ploopback) {
1255 		ploopback->rxsize = readsize;
1256 		preadbuf = ploopback->rxbuf;
1257 	} else {
1258 		preadbuf = rtw_malloc(allocsize);
1259 		if (preadbuf == NULL) {
1260 			RTW_INFO("%s: malloc fail size=%d\n", __func__, allocsize);
1261 			return;
1262 		}
1263 	}
1264 
1265 	/*	rtw_read_port(padapter, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf); */
1266 	sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
1267 
1268 	if (ploopback)
1269 		_rtw_up_sema(&ploopback->sema);
1270 	else {
1271 		u32 i;
1272 
1273 		RTW_INFO("%s: drop pkt\n", __func__);
1274 		for (i = 0; i < readsize; i += 4) {
1275 			RTW_INFO("%08X", *(u32 *)(preadbuf + i));
1276 			if ((i + 4) & 0x1F)
1277 				printk(" ");
1278 			else
1279 				printk("\n");
1280 		}
1281 		printk("\n");
1282 		rtw_mfree(preadbuf, allocsize);
1283 	}
1284 }
1285 #endif /* CONFIG_MAC_LOOPBACK_DRIVER */
1286 
1287 #ifdef CONFIG_SDIO_RX_COPY
sd_recv_rxfifo(PADAPTER padapter,u32 size,struct recv_buf ** recvbuf_ret)1288 static u32 sd_recv_rxfifo(PADAPTER padapter, u32 size, struct recv_buf **recvbuf_ret)
1289 {
1290 	u32 readsize, ret;
1291 	u8 *preadbuf;
1292 	struct recv_priv *precvpriv;
1293 	struct recv_buf	*precvbuf;
1294 
1295 
1296 #if 0
1297 	readsize = size;
1298 #else
1299 	/* Patch for some SDIO Host 4 bytes issue */
1300 	/* ex. RK3188 */
1301 	readsize = RND4(size);
1302 #endif
1303 
1304 	/* 3 1. alloc recvbuf */
1305 	precvpriv = &padapter->recvpriv;
1306 	precvbuf = rtw_dequeue_recvbuf(&precvpriv->free_recv_buf_queue);
1307 	if (precvbuf == NULL) {
1308 		RTW_INFO("%s: recvbuf unavailable\n", __func__); //No free rece_buffer.
1309 		ret = RTW_RBUF_UNAVAIL;
1310 		goto exit;
1311 	}
1312 
1313 	/* 3 2. alloc skb */
1314 	if (precvbuf->pskb == NULL) {
1315 		SIZE_PTR tmpaddr = 0;
1316 		SIZE_PTR alignment = 0;
1317 
1318 		precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
1319 		if (precvbuf->pskb == NULL) {
1320 			RTW_INFO("%s: alloc_skb fail! read=%d\n", __FUNCTION__, readsize);
1321 			rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
1322 			ret = RTW_RBUF_PKT_UNAVAIL;
1323 			goto exit;
1324 		}
1325 
1326 		precvbuf->pskb->dev = padapter->pnetdev;
1327 
1328 		tmpaddr = (SIZE_PTR)precvbuf->pskb->data;
1329 		alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
1330 		skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
1331 	}
1332 
1333 	/* 3 3. read data from rxfifo */
1334 	preadbuf = precvbuf->pskb->data;
1335 	/*	rtw_read_port(padapter, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf); */
1336 	ret = sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
1337 	if (ret == _FAIL) {
1338 		rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
1339 		goto exit;
1340 	}
1341 
1342 	/* 3 4. init recvbuf */
1343 	precvbuf->len = size;
1344 	precvbuf->phead = precvbuf->pskb->head;
1345 	precvbuf->pdata = precvbuf->pskb->data;
1346 	skb_set_tail_pointer(precvbuf->pskb, size);
1347 	precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
1348 	precvbuf->pend = skb_end_pointer(precvbuf->pskb);
1349 
1350 	*recvbuf_ret = precvbuf;
1351 	exit:
1352 		return ret;
1353 }
1354 #else /* !CONFIG_SDIO_RX_COPY */
sd_recv_rxfifo(PADAPTER padapter,u32 size)1355 static struct recv_buf *sd_recv_rxfifo(PADAPTER padapter, u32 size)
1356 {
1357 	u32 readsize, allocsize, ret;
1358 	u8 *preadbuf;
1359 	_pkt *ppkt;
1360 	struct recv_priv *precvpriv;
1361 	struct recv_buf	*precvbuf;
1362 
1363 
1364 #if 0
1365 	readsize = size;
1366 #else
1367 	/* Patch for some SDIO Host 4 bytes issue */
1368 	/* ex. RK3188 */
1369 	readsize = RND4(size);
1370 #endif
1371 
1372 	/* 3 1. alloc skb */
1373 	/* align to block size */
1374 	allocsize = rtw_sdio_cmd53_align_size(adapter_to_dvobj(padapter), readsize);
1375 
1376 	ppkt = rtw_skb_alloc(allocsize);
1377 
1378 	if (ppkt == NULL) {
1379 		return NULL;
1380 	}
1381 
1382 	/* 3 2. read data from rxfifo */
1383 	preadbuf = skb_put(ppkt, size);
1384 	/*	rtw_read_port(padapter, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf); */
1385 	ret = sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
1386 	if (ret == _FAIL) {
1387 		rtw_skb_free(ppkt);
1388 		return NULL;
1389 	}
1390 
1391 	/* 3 3. alloc recvbuf */
1392 	precvpriv = &padapter->recvpriv;
1393 	precvbuf = rtw_dequeue_recvbuf(&precvpriv->free_recv_buf_queue);
1394 	if (precvbuf == NULL) {
1395 		rtw_skb_free(ppkt);
1396 		RTW_ERR("%s: alloc recvbuf FAIL!\n", __FUNCTION__);
1397 		return NULL;
1398 	}
1399 
1400 	/* 3 4. init recvbuf */
1401 	precvbuf->pskb = ppkt;
1402 
1403 	precvbuf->len = ppkt->len;
1404 
1405 	precvbuf->phead = ppkt->head;
1406 	precvbuf->pdata = ppkt->data;
1407 	precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
1408 	precvbuf->pend = skb_end_pointer(precvbuf->pskb);
1409 
1410 	return precvbuf;
1411 }
1412 #endif /* !CONFIG_SDIO_RX_COPY */
1413 
sd_rxhandler(PADAPTER padapter,struct recv_buf * precvbuf)1414 static void sd_rxhandler(PADAPTER padapter, struct recv_buf *precvbuf)
1415 {
1416 	struct recv_priv *precvpriv;
1417 	_queue *ppending_queue;
1418 
1419 
1420 	precvpriv = &padapter->recvpriv;
1421 	ppending_queue = &precvpriv->recv_buf_pending_queue;
1422 
1423 	/* 3 1. enqueue recvbuf */
1424 	rtw_enqueue_recvbuf(precvbuf, ppending_queue);//rx thread dequeue pending
1425 
1426 
1427 	/* 3 2. trigger recv hdl */
1428 #ifdef CONFIG_RECV_THREAD_MODE
1429 		_rtw_up_sema(&precvpriv->recv_sema);
1430 #else
1431 	#ifdef PLATFORM_LINUX
1432 	tasklet_schedule(&precvpriv->recv_tasklet);
1433 	#endif /* PLATFORM_LINUX */
1434 #endif /* CONFIG_RECV_THREAD_MODE */
1435 }
1436 
sd_int_dpc(PADAPTER padapter)1437 void sd_int_dpc(PADAPTER padapter)
1438 {
1439 	PHAL_DATA_TYPE phal;
1440 	struct dvobj_priv *dvobj;
1441 	struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
1442 	struct pwrctrl_priv *pwrctl;
1443 
1444 
1445 	phal = GET_HAL_DATA(padapter);
1446 	dvobj = adapter_to_dvobj(padapter);
1447 	pwrctl = dvobj_to_pwrctl(dvobj);
1448 
1449 #ifdef CONFIG_SDIO_TX_ENABLE_AVAL_INT
1450 	if (phal->sdio_hisr & SDIO_HISR_AVAL) {
1451 		/* _irqL irql; */
1452 		u8	freepage[4];
1453 
1454 		_sdio_local_read(padapter, SDIO_REG_FREE_TXPG, 4, freepage);
1455 		/* _enter_critical_bh(&phal->SdioTxFIFOFreePageLock, &irql); */
1456 		/* _rtw_memcpy(phal->SdioTxFIFOFreePage, freepage, 4); */
1457 		/* _exit_critical_bh(&phal->SdioTxFIFOFreePageLock, &irql); */
1458 		/* RTW_INFO("SDIO_HISR_AVAL, Tx Free Page = 0x%x%x%x%x\n", */
1459 		/*	freepage[0], */
1460 		/*	freepage[1], */
1461 		/*	freepage[2], */
1462 		/*	freepage[3]); */
1463 		_rtw_up_sema(&(padapter->xmitpriv.xmit_sema));
1464 	}
1465 #endif
1466 	if (phal->sdio_hisr & SDIO_HISR_CPWM1) {
1467 		struct reportpwrstate_parm report;
1468 
1469 #ifdef CONFIG_LPS_RPWM_TIMER
1470 		_cancel_timer_ex(&(pwrctl->pwr_rpwm_timer));
1471 #endif /* CONFIG_LPS_RPWM_TIMER */
1472 
1473 		report.state = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_HCPWM1_8703B);
1474 
1475 #ifdef CONFIG_LPS_LCLK
1476 		/* cpwm_int_hdl(padapter, &report); */
1477 		_set_workitem(&(pwrctl->cpwm_event));
1478 #endif
1479 	}
1480 
1481 	if (phal->sdio_hisr & SDIO_HISR_TXERR) {
1482 		u8 *status;
1483 		u32 addr;
1484 
1485 		status = rtw_malloc(4);
1486 		if (status) {
1487 			addr = REG_TXDMA_STATUS;
1488 			HalSdioGetCmdAddr8703BSdio(padapter, WLAN_IOREG_DEVICE_ID, addr, &addr);
1489 			_sd_read(pintfhdl, addr, 4, status);
1490 			_sd_write(pintfhdl, addr, 4, status);
1491 			RTW_INFO("%s: SDIO_HISR_TXERR (0x%08x)\n", __func__, le32_to_cpu(*(u32 *)status));
1492 			rtw_mfree(status, 4);
1493 		} else
1494 			RTW_INFO("%s: SDIO_HISR_TXERR, but can't allocate memory to read status!\n", __func__);
1495 	}
1496 
1497 	if (phal->sdio_hisr & SDIO_HISR_TXBCNOK)
1498 		RTW_INFO("%s: SDIO_HISR_TXBCNOK\n", __func__);
1499 
1500 	if (phal->sdio_hisr & SDIO_HISR_TXBCNERR)
1501 		RTW_INFO("%s: SDIO_HISR_TXBCNERR\n", __func__);
1502 
1503 #ifdef CONFIG_FW_C2H_REG
1504 	if (phal->sdio_hisr & SDIO_HISR_C2HCMD) {
1505 		RTW_INFO("%s: C2H Command\n", __func__);
1506 		sd_c2h_hisr_hdl(padapter);
1507 	}
1508 #endif
1509 
1510 	if (phal->sdio_hisr & SDIO_HISR_RXFOVW)
1511 		RTW_INFO("%s: Rx Overflow\n", __func__);
1512 	if (phal->sdio_hisr & SDIO_HISR_RXERR)
1513 		RTW_INFO("%s: Rx Error\n", __func__);
1514 
1515 	if (phal->sdio_hisr & SDIO_HISR_RX_REQUEST) {
1516 		struct recv_buf *precvbuf = NULL;
1517 		int alloc_fail_time = 0;
1518 		u32 hisr = 0, rx_cnt = 0, ret = 0;
1519 
1520 	/*		RTW_INFO("%s: RX Request, size=%d\n", __func__, phal->SdioRxFIFOSize); */
1521 		phal->sdio_hisr ^= SDIO_HISR_RX_REQUEST;
1522 		do {
1523 			phal->SdioRxFIFOSize = SdioLocalCmd52Read2Byte(padapter, SDIO_REG_RX0_REQ_LEN);
1524 			if (phal->SdioRxFIFOSize != 0) {
1525 #ifdef CONFIG_MAC_LOOPBACK_DRIVER
1526 				sd_recv_loopback(padapter, phal->SdioRxFIFOSize);
1527 #else
1528 				ret = sd_recv_rxfifo(padapter, phal->SdioRxFIFOSize, &precvbuf);
1529 				if (precvbuf) {
1530 					//RTW_INFO("phal->SdioRxFIFOSize:%d\n", phal->SdioRxFIFOSize);
1531 					sd_rxhandler(padapter, precvbuf);
1532 					phal->SdioRxFIFOSize = 0;
1533 					rx_cnt++;
1534 				} else {
1535 					alloc_fail_time++;
1536 					if (ret == RTW_RBUF_UNAVAIL || ret == RTW_RBUF_PKT_UNAVAIL)
1537 						rtw_msleep_os(10);
1538 					else {
1539 					RTW_INFO("%s: recv fail!(time=%d)\n", __func__, alloc_fail_time);
1540 						phal->SdioRxFIFOSize = 0;
1541 					}
1542 					if (alloc_fail_time >= 10 && rx_cnt != 0)
1543 						break;
1544 				}
1545 #endif
1546 			} else
1547 				break;
1548 
1549 			hisr = 0;
1550 			ReadInterrupt8703BSdio(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 	ReadInterrupt8703BSdio(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  *   */
HalQueryTxBufferStatus8703BSdio(PADAPTER padapter)1598 u8 HalQueryTxBufferStatus8703BSdio(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  *   */
HalQueryTxOQTBufferStatus8703BSdio(PADAPTER padapter)1620 u8 HalQueryTxOQTBufferStatus8703BSdio(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 		res = sd_recv_rxfifo(padapter, len, &precvbuf);
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