xref: /linux/drivers/staging/rtl8723bs/hal/sdio_ops.c (revision 52338415)
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 	struct sdio_data *psdio;
429 	struct hal_com_data *hal;
430 	u32 oldcnt;
431 	s32 err;
432 
433 
434 	adapter = intfhdl->padapter;
435 	psdio = &adapter_to_dvobj(adapter)->intf_data;
436 	hal = GET_HAL_DATA(adapter);
437 
438 	HalSdioGetCmdAddr8723BSdio(adapter, addr, hal->SdioRxFIFOCnt++, &addr);
439 
440 	oldcnt = cnt;
441 	if (cnt > psdio->block_transfer_len)
442 		cnt = _RND(cnt, psdio->block_transfer_len);
443 /* 	cnt = sdio_align_size(cnt); */
444 
445 	err = _sd_read(intfhdl, addr, cnt, mem);
446 
447 	if (err)
448 		return _FAIL;
449 	return _SUCCESS;
450 }
451 
452 /*
453  * Description:
454  *Write to TX FIFO
455  *Align write size block size,
456  *and make sure data could be written in one command.
457  *
458  * Parameters:
459  *intfhdl	a pointer of intf_hdl
460  *addr		port ID
461  *cnt			size to write
462  *wmem		data pointer to write
463  *
464  * Return:
465  *_SUCCESS(1)		Success
466  *_FAIL(0)		Fail
467  */
468 static u32 sdio_write_port(
469 	struct intf_hdl *intfhdl,
470 	u32 addr,
471 	u32 cnt,
472 	u8 *mem
473 )
474 {
475 	struct adapter *adapter;
476 	struct sdio_data *psdio;
477 	s32 err;
478 	struct xmit_buf *xmitbuf = (struct xmit_buf *)mem;
479 
480 	adapter = intfhdl->padapter;
481 	psdio = &adapter_to_dvobj(adapter)->intf_data;
482 
483 	if (!adapter->hw_init_completed) {
484 		DBG_871X("%s [addr = 0x%x cnt =%d] adapter->hw_init_completed == false\n", __func__, addr, cnt);
485 		return _FAIL;
486 	}
487 
488 	cnt = _RND4(cnt);
489 	HalSdioGetCmdAddr8723BSdio(adapter, addr, cnt >> 2, &addr);
490 
491 	if (cnt > psdio->block_transfer_len)
492 		cnt = _RND(cnt, psdio->block_transfer_len);
493 /* 	cnt = sdio_align_size(cnt); */
494 
495 	err = sd_write(intfhdl, addr, cnt, xmitbuf->pdata);
496 
497 	rtw_sctx_done_err(
498 		&xmitbuf->sctx,
499 		err ? RTW_SCTX_DONE_WRITE_PORT_ERR : RTW_SCTX_DONE_SUCCESS
500 	);
501 
502 	if (err)
503 		return _FAIL;
504 	return _SUCCESS;
505 }
506 
507 void sdio_set_intf_ops(struct adapter *adapter, struct _io_ops *ops)
508 {
509 	ops->_read8 = &sdio_read8;
510 	ops->_read16 = &sdio_read16;
511 	ops->_read32 = &sdio_read32;
512 	ops->_read_mem = &sdio_read_mem;
513 	ops->_read_port = &sdio_read_port;
514 
515 	ops->_write8 = &sdio_write8;
516 	ops->_write16 = &sdio_write16;
517 	ops->_write32 = &sdio_write32;
518 	ops->_writeN = &sdio_writeN;
519 	ops->_write_mem = &sdio_write_mem;
520 	ops->_write_port = &sdio_write_port;
521 
522 	ops->_sd_f0_read8 = sdio_f0_read8;
523 }
524 
525 /*
526  * Todo: align address to 4 bytes.
527  */
528 static s32 _sdio_local_read(
529 	struct adapter *adapter,
530 	u32 addr,
531 	u32 cnt,
532 	u8 *buf
533 )
534 {
535 	struct intf_hdl *intfhdl;
536 	u8 mac_pwr_ctrl_on;
537 	s32 err;
538 	u8 *tmpbuf;
539 	u32 n;
540 
541 
542 	intfhdl = &adapter->iopriv.intf;
543 
544 	HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
545 
546 	rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
547 	if (!mac_pwr_ctrl_on)
548 		return _sd_cmd52_read(intfhdl, addr, cnt, buf);
549 
550 	n = RND4(cnt);
551 	tmpbuf = rtw_malloc(n);
552 	if (!tmpbuf)
553 		return -1;
554 
555 	err = _sd_read(intfhdl, addr, n, tmpbuf);
556 	if (!err)
557 		memcpy(buf, tmpbuf, cnt);
558 
559 	kfree(tmpbuf);
560 
561 	return err;
562 }
563 
564 /*
565  * Todo: align address to 4 bytes.
566  */
567 s32 sdio_local_read(
568 	struct adapter *adapter,
569 	u32 addr,
570 	u32 cnt,
571 	u8 *buf
572 )
573 {
574 	struct intf_hdl *intfhdl;
575 	u8 mac_pwr_ctrl_on;
576 	s32 err;
577 	u8 *tmpbuf;
578 	u32 n;
579 
580 	intfhdl = &adapter->iopriv.intf;
581 
582 	HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
583 
584 	rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
585 	if (
586 		(!mac_pwr_ctrl_on) ||
587 		(adapter_to_pwrctl(adapter)->bFwCurrentInPSMode)
588 	)
589 		return sd_cmd52_read(intfhdl, addr, cnt, buf);
590 
591 	n = RND4(cnt);
592 	tmpbuf = rtw_malloc(n);
593 	if (!tmpbuf)
594 		return -1;
595 
596 	err = sd_read(intfhdl, addr, n, tmpbuf);
597 	if (!err)
598 		memcpy(buf, tmpbuf, cnt);
599 
600 	kfree(tmpbuf);
601 
602 	return err;
603 }
604 
605 /*
606  * Todo: align address to 4 bytes.
607  */
608 s32 sdio_local_write(
609 	struct adapter *adapter,
610 	u32 addr,
611 	u32 cnt,
612 	u8 *buf
613 )
614 {
615 	struct intf_hdl *intfhdl;
616 	u8 mac_pwr_ctrl_on;
617 	s32 err;
618 	u8 *tmpbuf;
619 
620 	if (addr & 0x3)
621 		DBG_8192C("%s, address must be 4 bytes alignment\n", __func__);
622 
623 	if (cnt  & 0x3)
624 		DBG_8192C("%s, size must be the multiple of 4\n", __func__);
625 
626 	intfhdl = &adapter->iopriv.intf;
627 
628 	HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
629 
630 	rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
631 	if (
632 		(!mac_pwr_ctrl_on) ||
633 		(adapter_to_pwrctl(adapter)->bFwCurrentInPSMode)
634 	)
635 		return sd_cmd52_write(intfhdl, addr, cnt, buf);
636 
637 	tmpbuf = rtw_malloc(cnt);
638 	if (!tmpbuf)
639 		return -1;
640 
641 	memcpy(tmpbuf, buf, cnt);
642 
643 	err = sd_write(intfhdl, addr, cnt, tmpbuf);
644 
645 	kfree(tmpbuf);
646 
647 	return err;
648 }
649 
650 u8 SdioLocalCmd52Read1Byte(struct adapter *adapter, u32 addr)
651 {
652 	u8 val = 0;
653 	struct intf_hdl *intfhdl = &adapter->iopriv.intf;
654 
655 	HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
656 	sd_cmd52_read(intfhdl, addr, 1, &val);
657 
658 	return val;
659 }
660 
661 static u16 SdioLocalCmd52Read2Byte(struct adapter *adapter, u32 addr)
662 {
663 	__le16 val = 0;
664 	struct intf_hdl *intfhdl = &adapter->iopriv.intf;
665 
666 	HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
667 	sd_cmd52_read(intfhdl, addr, 2, (u8 *)&val);
668 
669 	return le16_to_cpu(val);
670 }
671 
672 static u32 SdioLocalCmd53Read4Byte(struct adapter *adapter, u32 addr)
673 {
674 
675 	u8 mac_pwr_ctrl_on;
676 	u32 val = 0;
677 	struct intf_hdl *intfhdl = &adapter->iopriv.intf;
678 	__le32 le_tmp;
679 
680 	HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
681 	rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
682 	if (!mac_pwr_ctrl_on || adapter_to_pwrctl(adapter)->bFwCurrentInPSMode) {
683 		sd_cmd52_read(intfhdl, addr, 4, (u8 *)&le_tmp);
684 		val = le32_to_cpu(le_tmp);
685 	} else {
686 		val = sd_read32(intfhdl, addr, NULL);
687 	}
688 	return val;
689 }
690 
691 void SdioLocalCmd52Write1Byte(struct adapter *adapter, u32 addr, u8 v)
692 {
693 	struct intf_hdl *intfhdl = &adapter->iopriv.intf;
694 
695 	HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
696 	sd_cmd52_write(intfhdl, addr, 1, &v);
697 }
698 
699 static void SdioLocalCmd52Write4Byte(struct adapter *adapter, u32 addr, u32 v)
700 {
701 	struct intf_hdl *intfhdl = &adapter->iopriv.intf;
702 	__le32 le_tmp;
703 
704 	HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
705 	le_tmp = cpu_to_le32(v);
706 	sd_cmd52_write(intfhdl, addr, 4, (u8 *)&le_tmp);
707 }
708 
709 static s32 ReadInterrupt8723BSdio(struct adapter *adapter, u32 *phisr)
710 {
711 	u32 hisr, himr;
712 	u8 val8, hisr_len;
713 
714 
715 	if (!phisr)
716 		return false;
717 
718 	himr = GET_HAL_DATA(adapter)->sdio_himr;
719 
720 	/*  decide how many bytes need to be read */
721 	hisr_len = 0;
722 	while (himr) {
723 		hisr_len++;
724 		himr >>= 8;
725 	}
726 
727 	hisr = 0;
728 	while (hisr_len != 0) {
729 		hisr_len--;
730 		val8 = SdioLocalCmd52Read1Byte(adapter, SDIO_REG_HISR + hisr_len);
731 		hisr |= (val8 << (8 * hisr_len));
732 	}
733 
734 	*phisr = hisr;
735 
736 	return true;
737 }
738 
739 /*  */
740 /* 	Description: */
741 /* 		Initialize SDIO Host Interrupt Mask configuration variables for future use. */
742 /*  */
743 /* 	Assumption: */
744 /* 		Using SDIO Local register ONLY for configuration. */
745 /*  */
746 /* 	Created by Roger, 2011.02.11. */
747 /*  */
748 void InitInterrupt8723BSdio(struct adapter *adapter)
749 {
750 	struct hal_com_data *haldata;
751 
752 
753 	haldata = GET_HAL_DATA(adapter);
754 	haldata->sdio_himr = (u32)(		\
755 								SDIO_HIMR_RX_REQUEST_MSK			|
756 								SDIO_HIMR_AVAL_MSK					|
757 /* 								SDIO_HIMR_TXERR_MSK				| */
758 /* 								SDIO_HIMR_RXERR_MSK				| */
759 /* 								SDIO_HIMR_TXFOVW_MSK				| */
760 /* 								SDIO_HIMR_RXFOVW_MSK				| */
761 /* 								SDIO_HIMR_TXBCNOK_MSK				| */
762 /* 								SDIO_HIMR_TXBCNERR_MSK			| */
763 /* 								SDIO_HIMR_BCNERLY_INT_MSK			| */
764 /* 								SDIO_HIMR_C2HCMD_MSK				| */
765 /* 								SDIO_HIMR_HSISR_IND_MSK			| */
766 /* 								SDIO_HIMR_GTINT3_IND_MSK			| */
767 /* 								SDIO_HIMR_GTINT4_IND_MSK			| */
768 /* 								SDIO_HIMR_PSTIMEOUT_MSK			| */
769 /* 								SDIO_HIMR_OCPINT_MSK				| */
770 /* 								SDIO_HIMR_ATIMEND_MSK				| */
771 /* 								SDIO_HIMR_ATIMEND_E_MSK			| */
772 /* 								SDIO_HIMR_CTWEND_MSK				| */
773 								0);
774 }
775 
776 /*  */
777 /* 	Description: */
778 /* 		Initialize System Host Interrupt Mask configuration variables for future use. */
779 /*  */
780 /* 	Created by Roger, 2011.08.03. */
781 /*  */
782 void InitSysInterrupt8723BSdio(struct adapter *adapter)
783 {
784 	struct hal_com_data *haldata;
785 
786 
787 	haldata = GET_HAL_DATA(adapter);
788 
789 	haldata->SysIntrMask = (		\
790 /* 							HSIMR_GPIO12_0_INT_EN			| */
791 /* 							HSIMR_SPS_OCP_INT_EN			| */
792 /* 							HSIMR_RON_INT_EN				| */
793 /* 							HSIMR_PDNINT_EN				| */
794 /* 							HSIMR_GPIO9_INT_EN				| */
795 							0);
796 }
797 
798 /*  */
799 /* 	Description: */
800 /* 		Enalbe SDIO Host Interrupt Mask configuration on SDIO local domain. */
801 /*  */
802 /* 	Assumption: */
803 /* 		1. Using SDIO Local register ONLY for configuration. */
804 /* 		2. PASSIVE LEVEL */
805 /*  */
806 /* 	Created by Roger, 2011.02.11. */
807 /*  */
808 void EnableInterrupt8723BSdio(struct adapter *adapter)
809 {
810 	struct hal_com_data *haldata;
811 	__le32 himr;
812 	u32 tmp;
813 
814 	haldata = GET_HAL_DATA(adapter);
815 
816 	himr = cpu_to_le32(haldata->sdio_himr);
817 	sdio_local_write(adapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
818 
819 	RT_TRACE(
820 		_module_hci_ops_c_,
821 		_drv_notice_,
822 		(
823 			"%s: enable SDIO HIMR = 0x%08X\n",
824 			__func__,
825 			haldata->sdio_himr
826 		)
827 	);
828 
829 	/*  Update current system IMR settings */
830 	tmp = rtw_read32(adapter, REG_HSIMR);
831 	rtw_write32(adapter, REG_HSIMR, tmp | haldata->SysIntrMask);
832 
833 	RT_TRACE(
834 		_module_hci_ops_c_,
835 		_drv_notice_,
836 		(
837 			"%s: enable HSIMR = 0x%08X\n",
838 			__func__,
839 			haldata->SysIntrMask
840 		)
841 	);
842 
843 	/*  */
844 	/*  <Roger_Notes> There are some C2H CMDs have been sent before system interrupt is enabled, e.g., C2H, CPWM. */
845 	/*  So we need to clear all C2H events that FW has notified, otherwise FW won't schedule any commands anymore. */
846 	/*  2011.10.19. */
847 	/*  */
848 	rtw_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
849 }
850 
851 /*  */
852 /* 	Description: */
853 /* 		Disable SDIO Host IMR configuration to mask unnecessary interrupt service. */
854 /*  */
855 /* 	Assumption: */
856 /* 		Using SDIO Local register ONLY for configuration. */
857 /*  */
858 /* 	Created by Roger, 2011.02.11. */
859 /*  */
860 void DisableInterrupt8723BSdio(struct adapter *adapter)
861 {
862 	__le32 himr;
863 
864 	himr = cpu_to_le32(SDIO_HIMR_DISABLED);
865 	sdio_local_write(adapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
866 }
867 
868 /*  */
869 /* 	Description: */
870 /* 		Using 0x100 to check the power status of FW. */
871 /*  */
872 /* 	Assumption: */
873 /* 		Using SDIO Local register ONLY for configuration. */
874 /*  */
875 /* 	Created by Isaac, 2013.09.10. */
876 /*  */
877 u8 CheckIPSStatus(struct adapter *adapter)
878 {
879 	DBG_871X(
880 		"%s(): Read 0x100 = 0x%02x 0x86 = 0x%02x\n",
881 		__func__,
882 		rtw_read8(adapter, 0x100),
883 		rtw_read8(adapter, 0x86)
884 	);
885 
886 	if (rtw_read8(adapter, 0x100) == 0xEA)
887 		return true;
888 	else
889 		return false;
890 }
891 
892 static struct recv_buf *sd_recv_rxfifo(struct adapter *adapter, u32 size)
893 {
894 	u32 readsize, ret;
895 	u8 *readbuf;
896 	struct recv_priv *recv_priv;
897 	struct recv_buf	*recvbuf;
898 
899 
900 	/*  Patch for some SDIO Host 4 bytes issue */
901 	/*  ex. RK3188 */
902 	readsize = RND4(size);
903 
904 	/* 3 1. alloc recvbuf */
905 	recv_priv = &adapter->recvpriv;
906 	recvbuf = rtw_dequeue_recvbuf(&recv_priv->free_recv_buf_queue);
907 	if (!recvbuf) {
908 		DBG_871X_LEVEL(_drv_err_, "%s: alloc recvbuf FAIL!\n", __func__);
909 		return NULL;
910 	}
911 
912 	/* 3 2. alloc skb */
913 	if (!recvbuf->pskb) {
914 		SIZE_PTR tmpaddr = 0;
915 		SIZE_PTR alignment = 0;
916 
917 		recvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
918 
919 		if (recvbuf->pskb) {
920 			recvbuf->pskb->dev = adapter->pnetdev;
921 
922 			tmpaddr = (SIZE_PTR)recvbuf->pskb->data;
923 			alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
924 			skb_reserve(recvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
925 		}
926 
927 		if (!recvbuf->pskb) {
928 			DBG_871X("%s: alloc_skb fail! read =%d\n", __func__, readsize);
929 			return NULL;
930 		}
931 	}
932 
933 	/* 3 3. read data from rxfifo */
934 	readbuf = recvbuf->pskb->data;
935 	ret = sdio_read_port(&adapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, readbuf);
936 	if (ret == _FAIL) {
937 		RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: read port FAIL!\n", __func__));
938 		return NULL;
939 	}
940 
941 
942 	/* 3 4. init recvbuf */
943 	recvbuf->len = size;
944 	recvbuf->phead = recvbuf->pskb->head;
945 	recvbuf->pdata = recvbuf->pskb->data;
946 	skb_set_tail_pointer(recvbuf->pskb, size);
947 	recvbuf->ptail = skb_tail_pointer(recvbuf->pskb);
948 	recvbuf->pend = skb_end_pointer(recvbuf->pskb);
949 
950 	return recvbuf;
951 }
952 
953 static void sd_rxhandler(struct adapter *adapter, struct recv_buf *recvbuf)
954 {
955 	struct recv_priv *recv_priv;
956 	struct __queue *pending_queue;
957 
958 	recv_priv = &adapter->recvpriv;
959 	pending_queue = &recv_priv->recv_buf_pending_queue;
960 
961 	/* 3 1. enqueue recvbuf */
962 	rtw_enqueue_recvbuf(recvbuf, pending_queue);
963 
964 	/* 3 2. schedule tasklet */
965 	tasklet_schedule(&recv_priv->recv_tasklet);
966 }
967 
968 void sd_int_dpc(struct adapter *adapter)
969 {
970 	struct hal_com_data *hal;
971 	struct dvobj_priv *dvobj;
972 	struct intf_hdl *intfhdl = &adapter->iopriv.intf;
973 	struct pwrctrl_priv *pwrctl;
974 
975 
976 	hal = GET_HAL_DATA(adapter);
977 	dvobj = adapter_to_dvobj(adapter);
978 	pwrctl = dvobj_to_pwrctl(dvobj);
979 
980 	if (hal->sdio_hisr & SDIO_HISR_AVAL) {
981 		u8 freepage[4];
982 
983 		_sdio_local_read(adapter, SDIO_REG_FREE_TXPG, 4, freepage);
984 		complete(&(adapter->xmitpriv.xmit_comp));
985 	}
986 
987 	if (hal->sdio_hisr & SDIO_HISR_CPWM1) {
988 		struct reportpwrstate_parm report;
989 
990 		u8 bcancelled;
991 		_cancel_timer(&(pwrctl->pwr_rpwm_timer), &bcancelled);
992 
993 		report.state = SdioLocalCmd52Read1Byte(adapter, SDIO_REG_HCPWM1_8723B);
994 
995 		/* cpwm_int_hdl(adapter, &report); */
996 		_set_workitem(&(pwrctl->cpwm_event));
997 	}
998 
999 	if (hal->sdio_hisr & SDIO_HISR_TXERR) {
1000 		u8 *status;
1001 		u32 addr;
1002 
1003 		status = rtw_malloc(4);
1004 		if (status) {
1005 			addr = REG_TXDMA_STATUS;
1006 			HalSdioGetCmdAddr8723BSdio(adapter, WLAN_IOREG_DEVICE_ID, addr, &addr);
1007 			_sd_read(intfhdl, addr, 4, status);
1008 			_sd_write(intfhdl, addr, 4, status);
1009 			DBG_8192C("%s: SDIO_HISR_TXERR (0x%08x)\n", __func__, le32_to_cpu(*(u32 *)status));
1010 			kfree(status);
1011 		} else {
1012 			DBG_8192C("%s: SDIO_HISR_TXERR, but can't allocate memory to read status!\n", __func__);
1013 		}
1014 	}
1015 
1016 	if (hal->sdio_hisr & SDIO_HISR_TXBCNOK)
1017 		DBG_8192C("%s: SDIO_HISR_TXBCNOK\n", __func__);
1018 
1019 	if (hal->sdio_hisr & SDIO_HISR_TXBCNERR)
1020 		DBG_8192C("%s: SDIO_HISR_TXBCNERR\n", __func__);
1021 #ifndef CONFIG_C2H_PACKET_EN
1022 	if (hal->sdio_hisr & SDIO_HISR_C2HCMD) {
1023 		struct c2h_evt_hdr_88xx *c2h_evt;
1024 
1025 		DBG_8192C("%s: C2H Command\n", __func__);
1026 		c2h_evt = rtw_zmalloc(16);
1027 		if (c2h_evt) {
1028 			if (c2h_evt_read_88xx(adapter, (u8 *)c2h_evt) == _SUCCESS) {
1029 				if (c2h_id_filter_ccx_8723b((u8 *)c2h_evt)) {
1030 					/* Handle CCX report here */
1031 					rtw_hal_c2h_handler(adapter, (u8 *)c2h_evt);
1032 					kfree((u8 *)c2h_evt);
1033 				} else {
1034 					rtw_c2h_wk_cmd(adapter, (u8 *)c2h_evt);
1035 				}
1036 			}
1037 		} else {
1038 			/* Error handling for malloc fail */
1039 			if (rtw_cbuf_push(adapter->evtpriv.c2h_queue, NULL) != _SUCCESS)
1040 				DBG_871X("%s rtw_cbuf_push fail\n", __func__);
1041 			_set_workitem(&adapter->evtpriv.c2h_wk);
1042 		}
1043 	}
1044 #endif
1045 
1046 	if (hal->sdio_hisr & SDIO_HISR_RXFOVW)
1047 		DBG_8192C("%s: Rx Overflow\n", __func__);
1048 
1049 	if (hal->sdio_hisr & SDIO_HISR_RXERR)
1050 		DBG_8192C("%s: Rx Error\n", __func__);
1051 
1052 
1053 	if (hal->sdio_hisr & SDIO_HISR_RX_REQUEST) {
1054 		struct recv_buf *recvbuf;
1055 		int alloc_fail_time = 0;
1056 		u32 hisr;
1057 
1058 /* 		DBG_8192C("%s: RX Request, size =%d\n", __func__, hal->SdioRxFIFOSize); */
1059 		hal->sdio_hisr ^= SDIO_HISR_RX_REQUEST;
1060 		do {
1061 			hal->SdioRxFIFOSize = SdioLocalCmd52Read2Byte(adapter, SDIO_REG_RX0_REQ_LEN);
1062 			if (hal->SdioRxFIFOSize != 0) {
1063 				recvbuf = sd_recv_rxfifo(adapter, hal->SdioRxFIFOSize);
1064 				if (recvbuf)
1065 					sd_rxhandler(adapter, recvbuf);
1066 				else {
1067 					alloc_fail_time++;
1068 					DBG_871X("recvbuf is Null for %d times because alloc memory failed\n", alloc_fail_time);
1069 					if (alloc_fail_time >= 10)
1070 						break;
1071 				}
1072 				hal->SdioRxFIFOSize = 0;
1073 			} else
1074 				break;
1075 
1076 			hisr = 0;
1077 			ReadInterrupt8723BSdio(adapter, &hisr);
1078 			hisr &= SDIO_HISR_RX_REQUEST;
1079 			if (!hisr)
1080 				break;
1081 		} while (1);
1082 
1083 		if (alloc_fail_time == 10)
1084 			DBG_871X("exit because alloc memory failed more than 10 times\n");
1085 
1086 	}
1087 }
1088 
1089 void sd_int_hdl(struct adapter *adapter)
1090 {
1091 	struct hal_com_data *hal;
1092 
1093 
1094 	if (
1095 		(adapter->bDriverStopped) || (adapter->bSurpriseRemoved)
1096 	)
1097 		return;
1098 
1099 	hal = GET_HAL_DATA(adapter);
1100 
1101 	hal->sdio_hisr = 0;
1102 	ReadInterrupt8723BSdio(adapter, &hal->sdio_hisr);
1103 
1104 	if (hal->sdio_hisr & hal->sdio_himr) {
1105 		u32 v32;
1106 
1107 		hal->sdio_hisr &= hal->sdio_himr;
1108 
1109 		/*  clear HISR */
1110 		v32 = hal->sdio_hisr & MASK_SDIO_HISR_CLEAR;
1111 		if (v32)
1112 			SdioLocalCmd52Write4Byte(adapter, SDIO_REG_HISR, v32);
1113 
1114 		sd_int_dpc(adapter);
1115 	} else {
1116 		RT_TRACE(_module_hci_ops_c_, _drv_err_,
1117 				("%s: HISR(0x%08x) and HIMR(0x%08x) not match!\n",
1118 				__func__, hal->sdio_hisr, hal->sdio_himr));
1119 	}
1120 }
1121 
1122 /*  */
1123 /* 	Description: */
1124 /* 		Query SDIO Local register to query current the number of Free TxPacketBuffer page. */
1125 /*  */
1126 /* 	Assumption: */
1127 /* 		1. Running at PASSIVE_LEVEL */
1128 /* 		2. RT_TX_SPINLOCK is NOT acquired. */
1129 /*  */
1130 /* 	Created by Roger, 2011.01.28. */
1131 /*  */
1132 u8 HalQueryTxBufferStatus8723BSdio(struct adapter *adapter)
1133 {
1134 	struct hal_com_data *hal;
1135 	u32 numof_free_page;
1136 	/* _irql irql; */
1137 
1138 
1139 	hal = GET_HAL_DATA(adapter);
1140 
1141 	numof_free_page = SdioLocalCmd53Read4Byte(adapter, SDIO_REG_FREE_TXPG);
1142 
1143 	/* spin_lock_bh(&phal->SdioTxFIFOFreePageLock); */
1144 	memcpy(hal->SdioTxFIFOFreePage, &numof_free_page, 4);
1145 	RT_TRACE(_module_hci_ops_c_, _drv_notice_,
1146 			("%s: Free page for HIQ(%#x), MIDQ(%#x), LOWQ(%#x), PUBQ(%#x)\n",
1147 			__func__,
1148 			hal->SdioTxFIFOFreePage[HI_QUEUE_IDX],
1149 			hal->SdioTxFIFOFreePage[MID_QUEUE_IDX],
1150 			hal->SdioTxFIFOFreePage[LOW_QUEUE_IDX],
1151 			hal->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]));
1152 	/* spin_unlock_bh(&hal->SdioTxFIFOFreePageLock); */
1153 
1154 	return true;
1155 }
1156 
1157 /*  */
1158 /* 	Description: */
1159 /* 		Query SDIO Local register to get the current number of TX OQT Free Space. */
1160 /*  */
1161 void HalQueryTxOQTBufferStatus8723BSdio(struct adapter *adapter)
1162 {
1163 	struct hal_com_data *haldata = GET_HAL_DATA(adapter);
1164 
1165 	haldata->SdioTxOQTFreeSpace = SdioLocalCmd52Read1Byte(adapter, SDIO_REG_OQT_FREE_PG);
1166 }
1167 
1168 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
1169 u8 RecvOnePkt(struct adapter *adapter, u32 size)
1170 {
1171 	struct recv_buf *recvbuf;
1172 	struct dvobj_priv *sddev;
1173 	struct sdio_func *func;
1174 
1175 	u8 res = false;
1176 
1177 	DBG_871X("+%s: size: %d+\n", __func__, size);
1178 
1179 	if (!adapter) {
1180 		DBG_871X(KERN_ERR "%s: adapter is NULL!\n", __func__);
1181 		return false;
1182 	}
1183 
1184 	sddev = adapter_to_dvobj(adapter);
1185 	psdio_data = &sddev->intf_data;
1186 	func = psdio_data->func;
1187 
1188 	if (size) {
1189 		sdio_claim_host(func);
1190 		recvbuf = sd_recv_rxfifo(adapter, size);
1191 
1192 		if (recvbuf) {
1193 			/* printk("Completed Recv One Pkt.\n"); */
1194 			sd_rxhandler(adapter, recvbuf);
1195 			res = true;
1196 		} else {
1197 			res = false;
1198 		}
1199 		sdio_release_host(func);
1200 	}
1201 	DBG_871X("-%s-\n", __func__);
1202 	return res;
1203 }
1204 #endif /* CONFIG_WOWLAN */
1205