1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  *******************************************************************************/
15 #define _SDIO_OPS_C_
16 
17 #include <drv_types.h>
18 #include <rtw_debug.h>
19 #include <rtl8723b_hal.h>
20 
21 /* define SDIO_DEBUG_IO 1 */
22 
23 
24 /*  */
25 /*  Description: */
26 /* 	The following mapping is for SDIO host local register space. */
27 /*  */
28 /*  Creadted by Roger, 2011.01.31. */
29 /*  */
30 static void HalSdioGetCmdAddr8723BSdio(
31 	struct adapter *adapter,
32 	u8 device_id,
33 	u32 addr,
34 	u32 *cmdaddr
35 )
36 {
37 	switch (device_id) {
38 	case SDIO_LOCAL_DEVICE_ID:
39 		*cmdaddr = ((SDIO_LOCAL_DEVICE_ID << 13) | (addr & SDIO_LOCAL_MSK));
40 		break;
41 
42 	case WLAN_IOREG_DEVICE_ID:
43 		*cmdaddr = ((WLAN_IOREG_DEVICE_ID << 13) | (addr & WLAN_IOREG_MSK));
44 		break;
45 
46 	case WLAN_TX_HIQ_DEVICE_ID:
47 		*cmdaddr = ((WLAN_TX_HIQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK));
48 		break;
49 
50 	case WLAN_TX_MIQ_DEVICE_ID:
51 		*cmdaddr = ((WLAN_TX_MIQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK));
52 		break;
53 
54 	case WLAN_TX_LOQ_DEVICE_ID:
55 		*cmdaddr = ((WLAN_TX_LOQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK));
56 		break;
57 
58 	case WLAN_RX0FF_DEVICE_ID:
59 		*cmdaddr = ((WLAN_RX0FF_DEVICE_ID << 13) | (addr & WLAN_RX0FF_MSK));
60 		break;
61 
62 	default:
63 		break;
64 	}
65 }
66 
67 static u8 get_deviceid(u32 addr)
68 {
69 	u8 devide_id;
70 	u16 pseudo_id;
71 
72 
73 	pseudo_id = (u16)(addr >> 16);
74 	switch (pseudo_id) {
75 	case 0x1025:
76 		devide_id = SDIO_LOCAL_DEVICE_ID;
77 		break;
78 
79 	case 0x1026:
80 		devide_id = WLAN_IOREG_DEVICE_ID;
81 		break;
82 
83 /* 		case 0x1027: */
84 /* 			devide_id = SDIO_FIRMWARE_FIFO; */
85 /* 			break; */
86 
87 	case 0x1031:
88 		devide_id = WLAN_TX_HIQ_DEVICE_ID;
89 		break;
90 
91 	case 0x1032:
92 		devide_id = WLAN_TX_MIQ_DEVICE_ID;
93 		break;
94 
95 	case 0x1033:
96 		devide_id = WLAN_TX_LOQ_DEVICE_ID;
97 		break;
98 
99 	case 0x1034:
100 		devide_id = WLAN_RX0FF_DEVICE_ID;
101 		break;
102 
103 	default:
104 /* 			devide_id = (u8)((addr >> 13) & 0xF); */
105 		devide_id = WLAN_IOREG_DEVICE_ID;
106 		break;
107 	}
108 
109 	return devide_id;
110 }
111 
112 /*
113  * Ref:
114  *HalSdioGetCmdAddr8723BSdio()
115  */
116 static u32 _cvrt2ftaddr(const u32 addr, u8 *pdevice_id, u16 *poffset)
117 {
118 	u8 device_id;
119 	u16 offset;
120 	u32 ftaddr;
121 
122 
123 	device_id = get_deviceid(addr);
124 	offset = 0;
125 
126 	switch (device_id) {
127 	case SDIO_LOCAL_DEVICE_ID:
128 		offset = addr & SDIO_LOCAL_MSK;
129 		break;
130 
131 	case WLAN_TX_HIQ_DEVICE_ID:
132 	case WLAN_TX_MIQ_DEVICE_ID:
133 	case WLAN_TX_LOQ_DEVICE_ID:
134 		offset = addr & WLAN_FIFO_MSK;
135 		break;
136 
137 	case WLAN_RX0FF_DEVICE_ID:
138 		offset = addr & WLAN_RX0FF_MSK;
139 		break;
140 
141 	case WLAN_IOREG_DEVICE_ID:
142 	default:
143 		device_id = WLAN_IOREG_DEVICE_ID;
144 		offset = addr & WLAN_IOREG_MSK;
145 		break;
146 	}
147 	ftaddr = (device_id << 13) | offset;
148 
149 	if (pdevice_id)
150 		*pdevice_id = device_id;
151 	if (poffset)
152 		*poffset = offset;
153 
154 	return ftaddr;
155 }
156 
157 static u8 sdio_read8(struct intf_hdl *intfhdl, u32 addr)
158 {
159 	u32 ftaddr;
160 	ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
161 
162 	return sd_read8(intfhdl, ftaddr, NULL);
163 }
164 
165 static u16 sdio_read16(struct intf_hdl *intfhdl, u32 addr)
166 {
167 	u32 ftaddr;
168 	__le16 le_tmp;
169 
170 	ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
171 	sd_cmd52_read(intfhdl, ftaddr, 2, (u8 *)&le_tmp);
172 
173 	return le16_to_cpu(le_tmp);
174 }
175 
176 static u32 sdio_read32(struct intf_hdl *intfhdl, u32 addr)
177 {
178 	struct adapter *adapter;
179 	u8 mac_pwr_ctrl_on;
180 	u8 device_id;
181 	u16 offset;
182 	u32 ftaddr;
183 	u8 shift;
184 	u32 val;
185 	s32 err;
186 	__le32 le_tmp;
187 
188 	adapter = intfhdl->padapter;
189 	ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
190 
191 	rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
192 	if (
193 		((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
194 		(!mac_pwr_ctrl_on) ||
195 		(adapter_to_pwrctl(adapter)->bFwCurrentInPSMode)
196 	) {
197 		err = sd_cmd52_read(intfhdl, ftaddr, 4, (u8 *)&le_tmp);
198 #ifdef SDIO_DEBUG_IO
199 		if (!err) {
200 #endif
201 			return le32_to_cpu(le_tmp);
202 #ifdef SDIO_DEBUG_IO
203 		}
204 
205 		DBG_8192C(KERN_ERR "%s: Mac Power off, Read FAIL(%d)! addr = 0x%x\n", __func__, err, addr);
206 		return SDIO_ERR_VAL32;
207 #endif
208 	}
209 
210 	/*  4 bytes alignment */
211 	shift = ftaddr & 0x3;
212 	if (shift == 0) {
213 		val = sd_read32(intfhdl, ftaddr, NULL);
214 	} else {
215 		u8 *tmpbuf;
216 
217 		tmpbuf = rtw_malloc(8);
218 		if (!tmpbuf) {
219 			DBG_8192C(KERN_ERR "%s: Allocate memory FAIL!(size =8) addr = 0x%x\n", __func__, addr);
220 			return SDIO_ERR_VAL32;
221 		}
222 
223 		ftaddr &= ~(u16)0x3;
224 		sd_read(intfhdl, ftaddr, 8, tmpbuf);
225 		memcpy(&le_tmp, tmpbuf+shift, 4);
226 		val = le32_to_cpu(le_tmp);
227 
228 		kfree(tmpbuf);
229 	}
230 	return val;
231 }
232 
233 static s32 sdio_readN(struct intf_hdl *intfhdl, u32 addr, u32 cnt, u8 *buf)
234 {
235 	struct adapter *adapter;
236 	u8 mac_pwr_ctrl_on;
237 	u8 device_id;
238 	u16 offset;
239 	u32 ftaddr;
240 	u8 shift;
241 	s32 err;
242 
243 	adapter = intfhdl->padapter;
244 	err = 0;
245 
246 	ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
247 
248 	rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
249 	if (
250 		((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
251 		(!mac_pwr_ctrl_on) ||
252 		(adapter_to_pwrctl(adapter)->bFwCurrentInPSMode)
253 	)
254 		return sd_cmd52_read(intfhdl, ftaddr, cnt, buf);
255 
256 	/*  4 bytes alignment */
257 	shift = ftaddr & 0x3;
258 	if (shift == 0) {
259 		err = sd_read(intfhdl, ftaddr, cnt, buf);
260 	} else {
261 		u8 *tmpbuf;
262 		u32 n;
263 
264 		ftaddr &= ~(u16)0x3;
265 		n = cnt + shift;
266 		tmpbuf = rtw_malloc(n);
267 		if (!tmpbuf)
268 			return -1;
269 
270 		err = sd_read(intfhdl, ftaddr, n, tmpbuf);
271 		if (!err)
272 			memcpy(buf, tmpbuf+shift, cnt);
273 		kfree(tmpbuf);
274 	}
275 	return err;
276 }
277 
278 static s32 sdio_write8(struct intf_hdl *intfhdl, u32 addr, u8 val)
279 {
280 	u32 ftaddr;
281 	s32 err;
282 
283 	ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
284 	sd_write8(intfhdl, ftaddr, val, &err);
285 
286 	return err;
287 }
288 
289 static s32 sdio_write16(struct intf_hdl *intfhdl, u32 addr, u16 val)
290 {
291 	u32 ftaddr;
292 	__le16 le_tmp;
293 
294 	ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
295 	le_tmp = cpu_to_le16(val);
296 	return sd_cmd52_write(intfhdl, ftaddr, 2, (u8 *)&le_tmp);
297 }
298 
299 static s32 sdio_write32(struct intf_hdl *intfhdl, u32 addr, u32 val)
300 {
301 	struct adapter *adapter;
302 	u8 mac_pwr_ctrl_on;
303 	u8 device_id;
304 	u16 offset;
305 	u32 ftaddr;
306 	u8 shift;
307 	s32 err;
308 	__le32 le_tmp;
309 
310 	adapter = intfhdl->padapter;
311 	err = 0;
312 
313 	ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
314 
315 	rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
316 	if (
317 		((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
318 		(!mac_pwr_ctrl_on) ||
319 		(adapter_to_pwrctl(adapter)->bFwCurrentInPSMode)
320 	) {
321 		le_tmp = cpu_to_le32(val);
322 
323 		return sd_cmd52_write(intfhdl, ftaddr, 4, (u8 *)&le_tmp);
324 	}
325 
326 	/*  4 bytes alignment */
327 	shift = ftaddr & 0x3;
328 	if (shift == 0) {
329 		sd_write32(intfhdl, ftaddr, val, &err);
330 	} else {
331 		le_tmp = cpu_to_le32(val);
332 		err = sd_cmd52_write(intfhdl, ftaddr, 4, (u8 *)&le_tmp);
333 	}
334 	return err;
335 }
336 
337 static s32 sdio_writeN(struct intf_hdl *intfhdl, u32 addr, u32 cnt, u8 *buf)
338 {
339 	struct adapter *adapter;
340 	u8 mac_pwr_ctrl_on;
341 	u8 device_id;
342 	u16 offset;
343 	u32 ftaddr;
344 	u8 shift;
345 	s32 err;
346 
347 	adapter = intfhdl->padapter;
348 	err = 0;
349 
350 	ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
351 
352 	rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
353 	if (
354 		((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
355 		(!mac_pwr_ctrl_on) ||
356 		(adapter_to_pwrctl(adapter)->bFwCurrentInPSMode)
357 	)
358 		return sd_cmd52_write(intfhdl, ftaddr, cnt, buf);
359 
360 	shift = ftaddr & 0x3;
361 	if (shift == 0) {
362 		err = sd_write(intfhdl, ftaddr, cnt, buf);
363 	} else {
364 		u8 *tmpbuf;
365 		u32 n;
366 
367 		ftaddr &= ~(u16)0x3;
368 		n = cnt + shift;
369 		tmpbuf = rtw_malloc(n);
370 		if (!tmpbuf)
371 			return -1;
372 		err = sd_read(intfhdl, ftaddr, 4, tmpbuf);
373 		if (err) {
374 			kfree(tmpbuf);
375 			return err;
376 		}
377 		memcpy(tmpbuf+shift, buf, cnt);
378 		err = sd_write(intfhdl, ftaddr, n, tmpbuf);
379 		kfree(tmpbuf);
380 	}
381 	return err;
382 }
383 
384 static u8 sdio_f0_read8(struct intf_hdl *intfhdl, u32 addr)
385 {
386 	return sd_f0_read8(intfhdl, addr, NULL);
387 }
388 
389 static void sdio_read_mem(
390 	struct intf_hdl *intfhdl,
391 	u32 addr,
392 	u32 cnt,
393 	u8 *rmem
394 )
395 {
396 	s32 err;
397 
398 	err = sdio_readN(intfhdl, addr, cnt, rmem);
399 	/* TODO: Report error is err not zero */
400 }
401 
402 static void sdio_write_mem(
403 	struct intf_hdl *intfhdl,
404 	u32 addr,
405 	u32 cnt,
406 	u8 *wmem
407 )
408 {
409 	sdio_writeN(intfhdl, addr, cnt, wmem);
410 }
411 
412 /*
413  * Description:
414  *Read from RX FIFO
415  *Round read size to block size,
416  *and make sure data transfer will be done in one command.
417  *
418  * Parameters:
419  *intfhdl	a pointer of intf_hdl
420  *addr		port ID
421  *cnt			size to read
422  *rmem		address to put data
423  *
424  * Return:
425  *_SUCCESS(1)		Success
426  *_FAIL(0)		Fail
427  */
428 static u32 sdio_read_port(
429 	struct intf_hdl *intfhdl,
430 	u32 addr,
431 	u32 cnt,
432 	u8 *mem
433 )
434 {
435 	struct adapter *adapter;
436 	PSDIO_DATA psdio;
437 	struct hal_com_data *hal;
438 	u32 oldcnt;
439 #ifdef SDIO_DYNAMIC_ALLOC_MEM
440 	u8 *oldmem;
441 #endif
442 	s32 err;
443 
444 
445 	adapter = intfhdl->padapter;
446 	psdio = &adapter_to_dvobj(adapter)->intf_data;
447 	hal = GET_HAL_DATA(adapter);
448 
449 	HalSdioGetCmdAddr8723BSdio(adapter, addr, hal->SdioRxFIFOCnt++, &addr);
450 
451 	oldcnt = cnt;
452 	if (cnt > psdio->block_transfer_len)
453 		cnt = _RND(cnt, psdio->block_transfer_len);
454 /* 	cnt = sdio_align_size(cnt); */
455 
456 	err = _sd_read(intfhdl, addr, cnt, mem);
457 
458 #ifdef SDIO_DYNAMIC_ALLOC_MEM
459 	if ((oldcnt != cnt) && (oldmem)) {
460 		memcpy(oldmem, mem, oldcnt);
461 		kfree(mem);
462 	}
463 #endif
464 
465 	if (err)
466 		return _FAIL;
467 	return _SUCCESS;
468 }
469 
470 /*
471  * Description:
472  *Write to TX FIFO
473  *Align write size block size,
474  *and make sure data could be written in one command.
475  *
476  * Parameters:
477  *intfhdl	a pointer of intf_hdl
478  *addr		port ID
479  *cnt			size to write
480  *wmem		data pointer to write
481  *
482  * Return:
483  *_SUCCESS(1)		Success
484  *_FAIL(0)		Fail
485  */
486 static u32 sdio_write_port(
487 	struct intf_hdl *intfhdl,
488 	u32 addr,
489 	u32 cnt,
490 	u8 *mem
491 )
492 {
493 	struct adapter *adapter;
494 	PSDIO_DATA psdio;
495 	s32 err;
496 	struct xmit_buf *xmitbuf = (struct xmit_buf *)mem;
497 
498 	adapter = intfhdl->padapter;
499 	psdio = &adapter_to_dvobj(adapter)->intf_data;
500 
501 	if (!adapter->hw_init_completed) {
502 		DBG_871X("%s [addr = 0x%x cnt =%d] adapter->hw_init_completed == false\n", __func__, addr, cnt);
503 		return _FAIL;
504 	}
505 
506 	cnt = _RND4(cnt);
507 	HalSdioGetCmdAddr8723BSdio(adapter, addr, cnt >> 2, &addr);
508 
509 	if (cnt > psdio->block_transfer_len)
510 		cnt = _RND(cnt, psdio->block_transfer_len);
511 /* 	cnt = sdio_align_size(cnt); */
512 
513 	err = sd_write(intfhdl, addr, cnt, xmitbuf->pdata);
514 
515 	rtw_sctx_done_err(
516 		&xmitbuf->sctx,
517 		err ? RTW_SCTX_DONE_WRITE_PORT_ERR : RTW_SCTX_DONE_SUCCESS
518 	);
519 
520 	if (err)
521 		return _FAIL;
522 	return _SUCCESS;
523 }
524 
525 void sdio_set_intf_ops(struct adapter *adapter, struct _io_ops *ops)
526 {
527 	ops->_read8 = &sdio_read8;
528 	ops->_read16 = &sdio_read16;
529 	ops->_read32 = &sdio_read32;
530 	ops->_read_mem = &sdio_read_mem;
531 	ops->_read_port = &sdio_read_port;
532 
533 	ops->_write8 = &sdio_write8;
534 	ops->_write16 = &sdio_write16;
535 	ops->_write32 = &sdio_write32;
536 	ops->_writeN = &sdio_writeN;
537 	ops->_write_mem = &sdio_write_mem;
538 	ops->_write_port = &sdio_write_port;
539 
540 	ops->_sd_f0_read8 = sdio_f0_read8;
541 }
542 
543 /*
544  * Todo: align address to 4 bytes.
545  */
546 static s32 _sdio_local_read(
547 	struct adapter *adapter,
548 	u32 addr,
549 	u32 cnt,
550 	u8 *buf
551 )
552 {
553 	struct intf_hdl *intfhdl;
554 	u8 mac_pwr_ctrl_on;
555 	s32 err;
556 	u8 *tmpbuf;
557 	u32 n;
558 
559 
560 	intfhdl = &adapter->iopriv.intf;
561 
562 	HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
563 
564 	rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
565 	if (!mac_pwr_ctrl_on)
566 		return _sd_cmd52_read(intfhdl, addr, cnt, buf);
567 
568 	n = RND4(cnt);
569 	tmpbuf = rtw_malloc(n);
570 	if (!tmpbuf)
571 		return (-1);
572 
573 	err = _sd_read(intfhdl, addr, n, tmpbuf);
574 	if (!err)
575 		memcpy(buf, tmpbuf, cnt);
576 
577 	kfree(tmpbuf);
578 
579 	return err;
580 }
581 
582 /*
583  * Todo: align address to 4 bytes.
584  */
585 s32 sdio_local_read(
586 	struct adapter *adapter,
587 	u32 addr,
588 	u32 cnt,
589 	u8 *buf
590 )
591 {
592 	struct intf_hdl *intfhdl;
593 	u8 mac_pwr_ctrl_on;
594 	s32 err;
595 	u8 *tmpbuf;
596 	u32 n;
597 
598 	intfhdl = &adapter->iopriv.intf;
599 
600 	HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
601 
602 	rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
603 	if (
604 		(!mac_pwr_ctrl_on) ||
605 		(adapter_to_pwrctl(adapter)->bFwCurrentInPSMode)
606 	)
607 		return sd_cmd52_read(intfhdl, addr, cnt, buf);
608 
609 	n = RND4(cnt);
610 	tmpbuf = rtw_malloc(n);
611 	if (!tmpbuf)
612 		return (-1);
613 
614 	err = sd_read(intfhdl, addr, n, tmpbuf);
615 	if (!err)
616 		memcpy(buf, tmpbuf, cnt);
617 
618 	kfree(tmpbuf);
619 
620 	return err;
621 }
622 
623 /*
624  * Todo: align address to 4 bytes.
625  */
626 s32 sdio_local_write(
627 	struct adapter *adapter,
628 	u32 addr,
629 	u32 cnt,
630 	u8 *buf
631 )
632 {
633 	struct intf_hdl *intfhdl;
634 	u8 mac_pwr_ctrl_on;
635 	s32 err;
636 	u8 *tmpbuf;
637 
638 	if (addr & 0x3)
639 		DBG_8192C("%s, address must be 4 bytes alignment\n", __func__);
640 
641 	if (cnt  & 0x3)
642 		DBG_8192C("%s, size must be the multiple of 4\n", __func__);
643 
644 	intfhdl = &adapter->iopriv.intf;
645 
646 	HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
647 
648 	rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
649 	if (
650 		(!mac_pwr_ctrl_on) ||
651 		(adapter_to_pwrctl(adapter)->bFwCurrentInPSMode)
652 	)
653 		return sd_cmd52_write(intfhdl, addr, cnt, buf);
654 
655 	tmpbuf = rtw_malloc(cnt);
656 	if (!tmpbuf)
657 		return (-1);
658 
659 	memcpy(tmpbuf, buf, cnt);
660 
661 	err = sd_write(intfhdl, addr, cnt, tmpbuf);
662 
663 	kfree(tmpbuf);
664 
665 	return err;
666 }
667 
668 u8 SdioLocalCmd52Read1Byte(struct adapter *adapter, u32 addr)
669 {
670 	u8 val = 0;
671 	struct intf_hdl *intfhdl = &adapter->iopriv.intf;
672 
673 	HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
674 	sd_cmd52_read(intfhdl, addr, 1, &val);
675 
676 	return val;
677 }
678 
679 static u16 SdioLocalCmd52Read2Byte(struct adapter *adapter, u32 addr)
680 {
681 	__le16 val = 0;
682 	struct intf_hdl *intfhdl = &adapter->iopriv.intf;
683 
684 	HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
685 	sd_cmd52_read(intfhdl, addr, 2, (u8 *)&val);
686 
687 	return le16_to_cpu(val);
688 }
689 
690 static u32 SdioLocalCmd53Read4Byte(struct adapter *adapter, u32 addr)
691 {
692 
693 	u8 mac_pwr_ctrl_on;
694 	u32 val = 0;
695 	struct intf_hdl *intfhdl = &adapter->iopriv.intf;
696 	__le32 le_tmp;
697 
698 	HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
699 	rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
700 	if (!mac_pwr_ctrl_on || adapter_to_pwrctl(adapter)->bFwCurrentInPSMode) {
701 		sd_cmd52_read(intfhdl, addr, 4, (u8 *)&le_tmp);
702 		val = le32_to_cpu(le_tmp);
703 	} else {
704 		val = sd_read32(intfhdl, addr, NULL);
705 	}
706 	return val;
707 }
708 
709 void SdioLocalCmd52Write1Byte(struct adapter *adapter, u32 addr, u8 v)
710 {
711 	struct intf_hdl *intfhdl = &adapter->iopriv.intf;
712 
713 	HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
714 	sd_cmd52_write(intfhdl, addr, 1, &v);
715 }
716 
717 static void SdioLocalCmd52Write4Byte(struct adapter *adapter, u32 addr, u32 v)
718 {
719 	struct intf_hdl *intfhdl = &adapter->iopriv.intf;
720 	__le32 le_tmp;
721 
722 	HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
723 	le_tmp = cpu_to_le32(v);
724 	sd_cmd52_write(intfhdl, addr, 4, (u8 *)&le_tmp);
725 }
726 
727 static s32 ReadInterrupt8723BSdio(struct adapter *adapter, u32 *phisr)
728 {
729 	u32 hisr, himr;
730 	u8 val8, hisr_len;
731 
732 
733 	if (!phisr)
734 		return false;
735 
736 	himr = GET_HAL_DATA(adapter)->sdio_himr;
737 
738 	/*  decide how many bytes need to be read */
739 	hisr_len = 0;
740 	while (himr) {
741 		hisr_len++;
742 		himr >>= 8;
743 	}
744 
745 	hisr = 0;
746 	while (hisr_len != 0) {
747 		hisr_len--;
748 		val8 = SdioLocalCmd52Read1Byte(adapter, SDIO_REG_HISR+hisr_len);
749 		hisr |= (val8 << (8*hisr_len));
750 	}
751 
752 	*phisr = hisr;
753 
754 	return true;
755 }
756 
757 /*  */
758 /* 	Description: */
759 /* 		Initialize SDIO Host Interrupt Mask configuration variables for future use. */
760 /*  */
761 /* 	Assumption: */
762 /* 		Using SDIO Local register ONLY for configuration. */
763 /*  */
764 /* 	Created by Roger, 2011.02.11. */
765 /*  */
766 void InitInterrupt8723BSdio(struct adapter *adapter)
767 {
768 	struct hal_com_data *haldata;
769 
770 
771 	haldata = GET_HAL_DATA(adapter);
772 	haldata->sdio_himr = (u32)(		\
773 								SDIO_HIMR_RX_REQUEST_MSK			|
774 								SDIO_HIMR_AVAL_MSK					|
775 /* 								SDIO_HIMR_TXERR_MSK				| */
776 /* 								SDIO_HIMR_RXERR_MSK				| */
777 /* 								SDIO_HIMR_TXFOVW_MSK				| */
778 /* 								SDIO_HIMR_RXFOVW_MSK				| */
779 /* 								SDIO_HIMR_TXBCNOK_MSK				| */
780 /* 								SDIO_HIMR_TXBCNERR_MSK			| */
781 /* 								SDIO_HIMR_BCNERLY_INT_MSK			| */
782 /* 								SDIO_HIMR_C2HCMD_MSK				| */
783 /* 								SDIO_HIMR_HSISR_IND_MSK			| */
784 /* 								SDIO_HIMR_GTINT3_IND_MSK			| */
785 /* 								SDIO_HIMR_GTINT4_IND_MSK			| */
786 /* 								SDIO_HIMR_PSTIMEOUT_MSK			| */
787 /* 								SDIO_HIMR_OCPINT_MSK				| */
788 /* 								SDIO_HIMR_ATIMEND_MSK				| */
789 /* 								SDIO_HIMR_ATIMEND_E_MSK			| */
790 /* 								SDIO_HIMR_CTWEND_MSK				| */
791 								0);
792 }
793 
794 /*  */
795 /* 	Description: */
796 /* 		Initialize System Host Interrupt Mask configuration variables for future use. */
797 /*  */
798 /* 	Created by Roger, 2011.08.03. */
799 /*  */
800 void InitSysInterrupt8723BSdio(struct adapter *adapter)
801 {
802 	struct hal_com_data *haldata;
803 
804 
805 	haldata = GET_HAL_DATA(adapter);
806 
807 	haldata->SysIntrMask = (		\
808 /* 							HSIMR_GPIO12_0_INT_EN			| */
809 /* 							HSIMR_SPS_OCP_INT_EN			| */
810 /* 							HSIMR_RON_INT_EN				| */
811 /* 							HSIMR_PDNINT_EN				| */
812 /* 							HSIMR_GPIO9_INT_EN				| */
813 							0);
814 }
815 
816 #ifdef CONFIG_WOWLAN
817 /*  */
818 /* 	Description: */
819 /* 		Clear corresponding SDIO Host ISR interrupt service. */
820 /*  */
821 /* 	Assumption: */
822 /* 		Using SDIO Local register ONLY for configuration. */
823 /*  */
824 /* 	Created by Roger, 2011.02.11. */
825 /*  */
826 void clearinterrupt8723bsdio(struct adapter *adapter)
827 {
828 	struct hal_com_data *haldata;
829 	u8 *clear;
830 
831 	if (adapter->bSurpriseRemoved)
832 		return;
833 
834 	haldata = GET_HAL_DATA(adapter);
835 	clear = rtw_zmalloc(4);
836 
837 	/*  Clear corresponding HISR Content if needed */
838 	*(__le32 *)clear = cpu_to_le32(haldata->sdio_hisr & MASK_SDIO_HISR_CLEAR);
839 	if (*(__le32 *)clear) {
840 		/*  Perform write one clear operation */
841 		sdio_local_write(padapter, SDIO_REG_HISR, 4, clear);
842 	}
843 
844 	kfree(clear);
845 }
846 #endif
847 
848 /*  */
849 /* 	Description: */
850 /* 		Enalbe SDIO Host Interrupt Mask configuration on SDIO local domain. */
851 /*  */
852 /* 	Assumption: */
853 /* 		1. Using SDIO Local register ONLY for configuration. */
854 /* 		2. PASSIVE LEVEL */
855 /*  */
856 /* 	Created by Roger, 2011.02.11. */
857 /*  */
858 void EnableInterrupt8723BSdio(struct adapter *adapter)
859 {
860 	struct hal_com_data *haldata;
861 	__le32 himr;
862 	u32 tmp;
863 
864 	haldata = GET_HAL_DATA(adapter);
865 
866 	himr = cpu_to_le32(haldata->sdio_himr);
867 	sdio_local_write(adapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
868 
869 	RT_TRACE(
870 		_module_hci_ops_c_,
871 		_drv_notice_,
872 		(
873 			"%s: enable SDIO HIMR = 0x%08X\n",
874 			__func__,
875 			haldata->sdio_himr
876 		)
877 	);
878 
879 	/*  Update current system IMR settings */
880 	tmp = rtw_read32(adapter, REG_HSIMR);
881 	rtw_write32(adapter, REG_HSIMR, tmp | haldata->SysIntrMask);
882 
883 	RT_TRACE(
884 		_module_hci_ops_c_,
885 		_drv_notice_,
886 		(
887 			"%s: enable HSIMR = 0x%08X\n",
888 			__func__,
889 			haldata->SysIntrMask
890 		)
891 	);
892 
893 	/*  */
894 	/*  <Roger_Notes> There are some C2H CMDs have been sent before system interrupt is enabled, e.g., C2H, CPWM. */
895 	/*  So we need to clear all C2H events that FW has notified, otherwise FW won't schedule any commands anymore. */
896 	/*  2011.10.19. */
897 	/*  */
898 	rtw_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
899 }
900 
901 /*  */
902 /* 	Description: */
903 /* 		Disable SDIO Host IMR configuration to mask unnecessary interrupt service. */
904 /*  */
905 /* 	Assumption: */
906 /* 		Using SDIO Local register ONLY for configuration. */
907 /*  */
908 /* 	Created by Roger, 2011.02.11. */
909 /*  */
910 void DisableInterrupt8723BSdio(struct adapter *adapter)
911 {
912 	__le32 himr;
913 
914 	himr = cpu_to_le32(SDIO_HIMR_DISABLED);
915 	sdio_local_write(adapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
916 }
917 
918 /*  */
919 /* 	Description: */
920 /* 		Using 0x100 to check the power status of FW. */
921 /*  */
922 /* 	Assumption: */
923 /* 		Using SDIO Local register ONLY for configuration. */
924 /*  */
925 /* 	Created by Isaac, 2013.09.10. */
926 /*  */
927 u8 CheckIPSStatus(struct adapter *adapter)
928 {
929 	DBG_871X(
930 		"%s(): Read 0x100 = 0x%02x 0x86 = 0x%02x\n",
931 		__func__,
932 		rtw_read8(adapter, 0x100),
933 		rtw_read8(adapter, 0x86)
934 	);
935 
936 	if (rtw_read8(adapter, 0x100) == 0xEA)
937 		return true;
938 	else
939 		return false;
940 }
941 
942 static struct recv_buf *sd_recv_rxfifo(struct adapter *adapter, u32 size)
943 {
944 	u32 readsize, ret;
945 	u8 *readbuf;
946 	struct recv_priv *recv_priv;
947 	struct recv_buf	*recvbuf;
948 
949 
950 	/*  Patch for some SDIO Host 4 bytes issue */
951 	/*  ex. RK3188 */
952 	readsize = RND4(size);
953 
954 	/* 3 1. alloc recvbuf */
955 	recv_priv = &adapter->recvpriv;
956 	recvbuf = rtw_dequeue_recvbuf(&recv_priv->free_recv_buf_queue);
957 	if (!recvbuf) {
958 		DBG_871X_LEVEL(_drv_err_, "%s: alloc recvbuf FAIL!\n", __func__);
959 		return NULL;
960 	}
961 
962 	/* 3 2. alloc skb */
963 	if (!recvbuf->pskb) {
964 		SIZE_PTR tmpaddr = 0;
965 		SIZE_PTR alignment = 0;
966 
967 		recvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
968 
969 		if (recvbuf->pskb) {
970 			recvbuf->pskb->dev = adapter->pnetdev;
971 
972 			tmpaddr = (SIZE_PTR)recvbuf->pskb->data;
973 			alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
974 			skb_reserve(recvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
975 		}
976 
977 		if (!recvbuf->pskb) {
978 			DBG_871X("%s: alloc_skb fail! read =%d\n", __func__, readsize);
979 			return NULL;
980 		}
981 	}
982 
983 	/* 3 3. read data from rxfifo */
984 	readbuf = recvbuf->pskb->data;
985 	ret = sdio_read_port(&adapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, readbuf);
986 	if (ret == _FAIL) {
987 		RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: read port FAIL!\n", __func__));
988 		return NULL;
989 	}
990 
991 
992 	/* 3 4. init recvbuf */
993 	recvbuf->len = size;
994 	recvbuf->phead = recvbuf->pskb->head;
995 	recvbuf->pdata = recvbuf->pskb->data;
996 	skb_set_tail_pointer(recvbuf->pskb, size);
997 	recvbuf->ptail = skb_tail_pointer(recvbuf->pskb);
998 	recvbuf->pend = skb_end_pointer(recvbuf->pskb);
999 
1000 	return recvbuf;
1001 }
1002 
1003 static void sd_rxhandler(struct adapter *adapter, struct recv_buf *recvbuf)
1004 {
1005 	struct recv_priv *recv_priv;
1006 	struct __queue *pending_queue;
1007 
1008 	recv_priv = &adapter->recvpriv;
1009 	pending_queue = &recv_priv->recv_buf_pending_queue;
1010 
1011 	/* 3 1. enqueue recvbuf */
1012 	rtw_enqueue_recvbuf(recvbuf, pending_queue);
1013 
1014 	/* 3 2. schedule tasklet */
1015 	tasklet_schedule(&recv_priv->recv_tasklet);
1016 }
1017 
1018 void sd_int_dpc(struct adapter *adapter)
1019 {
1020 	struct hal_com_data *hal;
1021 	struct dvobj_priv *dvobj;
1022 	struct intf_hdl *intfhdl = &adapter->iopriv.intf;
1023 	struct pwrctrl_priv *pwrctl;
1024 
1025 
1026 	hal = GET_HAL_DATA(adapter);
1027 	dvobj = adapter_to_dvobj(adapter);
1028 	pwrctl = dvobj_to_pwrctl(dvobj);
1029 
1030 	if (hal->sdio_hisr & SDIO_HISR_AVAL) {
1031 		u8 freepage[4];
1032 
1033 		_sdio_local_read(adapter, SDIO_REG_FREE_TXPG, 4, freepage);
1034 		up(&(adapter->xmitpriv.xmit_sema));
1035 	}
1036 
1037 	if (hal->sdio_hisr & SDIO_HISR_CPWM1) {
1038 		struct reportpwrstate_parm report;
1039 
1040 		u8 bcancelled;
1041 		_cancel_timer(&(pwrctl->pwr_rpwm_timer), &bcancelled);
1042 
1043 		report.state = SdioLocalCmd52Read1Byte(adapter, SDIO_REG_HCPWM1_8723B);
1044 
1045 		/* cpwm_int_hdl(adapter, &report); */
1046 		_set_workitem(&(pwrctl->cpwm_event));
1047 	}
1048 
1049 	if (hal->sdio_hisr & SDIO_HISR_TXERR) {
1050 		u8 *status;
1051 		u32 addr;
1052 
1053 		status = rtw_malloc(4);
1054 		if (status) {
1055 			addr = REG_TXDMA_STATUS;
1056 			HalSdioGetCmdAddr8723BSdio(adapter, WLAN_IOREG_DEVICE_ID, addr, &addr);
1057 			_sd_read(intfhdl, addr, 4, status);
1058 			_sd_write(intfhdl, addr, 4, status);
1059 			DBG_8192C("%s: SDIO_HISR_TXERR (0x%08x)\n", __func__, le32_to_cpu(*(u32 *)status));
1060 			kfree(status);
1061 		} else {
1062 			DBG_8192C("%s: SDIO_HISR_TXERR, but can't allocate memory to read status!\n", __func__);
1063 		}
1064 	}
1065 
1066 	if (hal->sdio_hisr & SDIO_HISR_TXBCNOK) {
1067 		DBG_8192C("%s: SDIO_HISR_TXBCNOK\n", __func__);
1068 	}
1069 
1070 	if (hal->sdio_hisr & SDIO_HISR_TXBCNERR) {
1071 		DBG_8192C("%s: SDIO_HISR_TXBCNERR\n", __func__);
1072 	}
1073 #ifndef CONFIG_C2H_PACKET_EN
1074 	if (hal->sdio_hisr & SDIO_HISR_C2HCMD) {
1075 		struct c2h_evt_hdr_88xx *c2h_evt;
1076 
1077 		DBG_8192C("%s: C2H Command\n", __func__);
1078 		c2h_evt = rtw_zmalloc(16);
1079 		if (c2h_evt != NULL) {
1080 			if (rtw_hal_c2h_evt_read(adapter, (u8 *)c2h_evt) == _SUCCESS) {
1081 				if (c2h_id_filter_ccx_8723b((u8 *)c2h_evt)) {
1082 					/* Handle CCX report here */
1083 					rtw_hal_c2h_handler(adapter, (u8 *)c2h_evt);
1084 					kfree((u8 *)c2h_evt);
1085 				} else {
1086 					rtw_c2h_wk_cmd(adapter, (u8 *)c2h_evt);
1087 				}
1088 			}
1089 		} else {
1090 			/* Error handling for malloc fail */
1091 			if (rtw_cbuf_push(adapter->evtpriv.c2h_queue, NULL) != _SUCCESS)
1092 				DBG_871X("%s rtw_cbuf_push fail\n", __func__);
1093 			_set_workitem(&adapter->evtpriv.c2h_wk);
1094 		}
1095 	}
1096 #endif
1097 
1098 	if (hal->sdio_hisr & SDIO_HISR_RXFOVW) {
1099 		DBG_8192C("%s: Rx Overflow\n", __func__);
1100 	}
1101 
1102 	if (hal->sdio_hisr & SDIO_HISR_RXERR) {
1103 		DBG_8192C("%s: Rx Error\n", __func__);
1104 	}
1105 
1106 	if (hal->sdio_hisr & SDIO_HISR_RX_REQUEST) {
1107 		struct recv_buf *recvbuf;
1108 		int alloc_fail_time = 0;
1109 		u32 hisr;
1110 
1111 /* 		DBG_8192C("%s: RX Request, size =%d\n", __func__, hal->SdioRxFIFOSize); */
1112 		hal->sdio_hisr ^= SDIO_HISR_RX_REQUEST;
1113 		do {
1114 			hal->SdioRxFIFOSize = SdioLocalCmd52Read2Byte(adapter, SDIO_REG_RX0_REQ_LEN);
1115 			if (hal->SdioRxFIFOSize != 0) {
1116 				recvbuf = sd_recv_rxfifo(adapter, hal->SdioRxFIFOSize);
1117 				if (recvbuf)
1118 					sd_rxhandler(adapter, recvbuf);
1119 				else {
1120 					alloc_fail_time++;
1121 					DBG_871X("recvbuf is Null for %d times because alloc memory failed\n", alloc_fail_time);
1122 					if (alloc_fail_time >= 10)
1123 						break;
1124 				}
1125 				hal->SdioRxFIFOSize = 0;
1126 			} else
1127 				break;
1128 
1129 			hisr = 0;
1130 			ReadInterrupt8723BSdio(adapter, &hisr);
1131 			hisr &= SDIO_HISR_RX_REQUEST;
1132 			if (!hisr)
1133 				break;
1134 		} while (1);
1135 
1136 		if (alloc_fail_time == 10)
1137 			DBG_871X("exit because alloc memory failed more than 10 times\n");
1138 
1139 	}
1140 }
1141 
1142 void sd_int_hdl(struct adapter *adapter)
1143 {
1144 	struct hal_com_data *hal;
1145 
1146 
1147 	if (
1148 		(adapter->bDriverStopped) || (adapter->bSurpriseRemoved)
1149 	)
1150 		return;
1151 
1152 	hal = GET_HAL_DATA(adapter);
1153 
1154 	hal->sdio_hisr = 0;
1155 	ReadInterrupt8723BSdio(adapter, &hal->sdio_hisr);
1156 
1157 	if (hal->sdio_hisr & hal->sdio_himr) {
1158 		u32 v32;
1159 
1160 		hal->sdio_hisr &= hal->sdio_himr;
1161 
1162 		/*  clear HISR */
1163 		v32 = hal->sdio_hisr & MASK_SDIO_HISR_CLEAR;
1164 		if (v32) {
1165 			SdioLocalCmd52Write4Byte(adapter, SDIO_REG_HISR, v32);
1166 		}
1167 
1168 		sd_int_dpc(adapter);
1169 	} else {
1170 		RT_TRACE(_module_hci_ops_c_, _drv_err_,
1171 				("%s: HISR(0x%08x) and HIMR(0x%08x) not match!\n",
1172 				__func__, hal->sdio_hisr, hal->sdio_himr));
1173 	}
1174 }
1175 
1176 /*  */
1177 /* 	Description: */
1178 /* 		Query SDIO Local register to query current the number of Free TxPacketBuffer page. */
1179 /*  */
1180 /* 	Assumption: */
1181 /* 		1. Running at PASSIVE_LEVEL */
1182 /* 		2. RT_TX_SPINLOCK is NOT acquired. */
1183 /*  */
1184 /* 	Created by Roger, 2011.01.28. */
1185 /*  */
1186 u8 HalQueryTxBufferStatus8723BSdio(struct adapter *adapter)
1187 {
1188 	struct hal_com_data *hal;
1189 	u32 numof_free_page;
1190 	/* _irql irql; */
1191 
1192 
1193 	hal = GET_HAL_DATA(adapter);
1194 
1195 	numof_free_page = SdioLocalCmd53Read4Byte(adapter, SDIO_REG_FREE_TXPG);
1196 
1197 	/* spin_lock_bh(&phal->SdioTxFIFOFreePageLock); */
1198 	memcpy(hal->SdioTxFIFOFreePage, &numof_free_page, 4);
1199 	RT_TRACE(_module_hci_ops_c_, _drv_notice_,
1200 			("%s: Free page for HIQ(%#x), MIDQ(%#x), LOWQ(%#x), PUBQ(%#x)\n",
1201 			__func__,
1202 			hal->SdioTxFIFOFreePage[HI_QUEUE_IDX],
1203 			hal->SdioTxFIFOFreePage[MID_QUEUE_IDX],
1204 			hal->SdioTxFIFOFreePage[LOW_QUEUE_IDX],
1205 			hal->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]));
1206 	/* spin_unlock_bh(&hal->SdioTxFIFOFreePageLock); */
1207 
1208 	return true;
1209 }
1210 
1211 /*  */
1212 /* 	Description: */
1213 /* 		Query SDIO Local register to get the current number of TX OQT Free Space. */
1214 /*  */
1215 u8 HalQueryTxOQTBufferStatus8723BSdio(struct adapter *adapter)
1216 {
1217 	struct hal_com_data *haldata = GET_HAL_DATA(adapter);
1218 
1219 	haldata->SdioTxOQTFreeSpace = SdioLocalCmd52Read1Byte(adapter, SDIO_REG_OQT_FREE_PG);
1220 	return true;
1221 }
1222 
1223 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
1224 u8 RecvOnePkt(struct adapter *adapter, u32 size)
1225 {
1226 	struct recv_buf *recvbuf;
1227 	struct dvobj_priv *sddev;
1228 	PSDIO_DATA psdio_data;
1229 	struct sdio_func *func;
1230 
1231 	u8 res = false;
1232 
1233 	DBG_871X("+%s: size: %d+\n", __func__, size);
1234 
1235 	if (!adapter) {
1236 		DBG_871X(KERN_ERR "%s: adapter is NULL!\n", __func__);
1237 		return false;
1238 	}
1239 
1240 	sddev = adapter_to_dvobj(adapter);
1241 	psdio_data = &sddev->intf_data;
1242 	func = psdio_data->func;
1243 
1244 	if (size) {
1245 		sdio_claim_host(func);
1246 		recvbuf = sd_recv_rxfifo(adapter, size);
1247 
1248 		if (recvbuf) {
1249 			/* printk("Completed Recv One Pkt.\n"); */
1250 			sd_rxhandler(adapter, recvbuf);
1251 			res = true;
1252 		} else {
1253 			res = false;
1254 		}
1255 		sdio_release_host(func);
1256 	}
1257 	DBG_871X("-%s-\n", __func__);
1258 	return res;
1259 }
1260 #endif /* CONFIG_WOWLAN */
1261