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