1// SPDX-License-Identifier: GPL-2.0
2/******************************************************************************
3 *
4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5 *
6 *******************************************************************************/
7#include <drv_types.h>
8#include <rtw_debug.h>
9#include <rtl8723b_hal.h>
10
11/*  */
12/*  Description: */
13/*	The following mapping is for SDIO host local register space. */
14/*  */
15/*  Creadted by Roger, 2011.01.31. */
16/*  */
17static void hal_sdio_get_cmd_addr_8723b(
18	struct adapter *adapter,
19	u8 device_id,
20	u32 addr,
21	u32 *cmdaddr
22)
23{
24	switch (device_id) {
25	case SDIO_LOCAL_DEVICE_ID:
26		*cmdaddr = ((SDIO_LOCAL_DEVICE_ID << 13) | (addr & SDIO_LOCAL_MSK));
27		break;
28
29	case WLAN_IOREG_DEVICE_ID:
30		*cmdaddr = ((WLAN_IOREG_DEVICE_ID << 13) | (addr & WLAN_IOREG_MSK));
31		break;
32
33	case WLAN_TX_HIQ_DEVICE_ID:
34		*cmdaddr = ((WLAN_TX_HIQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK));
35		break;
36
37	case WLAN_TX_MIQ_DEVICE_ID:
38		*cmdaddr = ((WLAN_TX_MIQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK));
39		break;
40
41	case WLAN_TX_LOQ_DEVICE_ID:
42		*cmdaddr = ((WLAN_TX_LOQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK));
43		break;
44
45	case WLAN_RX0FF_DEVICE_ID:
46		*cmdaddr = ((WLAN_RX0FF_DEVICE_ID << 13) | (addr & WLAN_RX0FF_MSK));
47		break;
48
49	default:
50		break;
51	}
52}
53
54static u8 get_deviceid(u32 addr)
55{
56	u8 devide_id;
57	u16 pseudo_id;
58
59	pseudo_id = (u16)(addr >> 16);
60	switch (pseudo_id) {
61	case 0x1025:
62		devide_id = SDIO_LOCAL_DEVICE_ID;
63		break;
64
65	case 0x1026:
66		devide_id = WLAN_IOREG_DEVICE_ID;
67		break;
68
69	case 0x1031:
70		devide_id = WLAN_TX_HIQ_DEVICE_ID;
71		break;
72
73	case 0x1032:
74		devide_id = WLAN_TX_MIQ_DEVICE_ID;
75		break;
76
77	case 0x1033:
78		devide_id = WLAN_TX_LOQ_DEVICE_ID;
79		break;
80
81	case 0x1034:
82		devide_id = WLAN_RX0FF_DEVICE_ID;
83		break;
84
85	default:
86		devide_id = WLAN_IOREG_DEVICE_ID;
87		break;
88	}
89
90	return devide_id;
91}
92
93static u32 _cvrt2ftaddr(const u32 addr, u8 *pdevice_id, u16 *poffset)
94{
95	u8 device_id;
96	u16 offset;
97	u32 ftaddr;
98
99	device_id = get_deviceid(addr);
100	offset = 0;
101
102	switch (device_id) {
103	case SDIO_LOCAL_DEVICE_ID:
104		offset = addr & SDIO_LOCAL_MSK;
105		break;
106
107	case WLAN_TX_HIQ_DEVICE_ID:
108	case WLAN_TX_MIQ_DEVICE_ID:
109	case WLAN_TX_LOQ_DEVICE_ID:
110		offset = addr & WLAN_FIFO_MSK;
111		break;
112
113	case WLAN_RX0FF_DEVICE_ID:
114		offset = addr & WLAN_RX0FF_MSK;
115		break;
116
117	case WLAN_IOREG_DEVICE_ID:
118	default:
119		device_id = WLAN_IOREG_DEVICE_ID;
120		offset = addr & WLAN_IOREG_MSK;
121		break;
122	}
123	ftaddr = (device_id << 13) | offset;
124
125	if (pdevice_id)
126		*pdevice_id = device_id;
127	if (poffset)
128		*poffset = offset;
129
130	return ftaddr;
131}
132
133static u8 sdio_read8(struct intf_hdl *intfhdl, u32 addr)
134{
135	u32 ftaddr;
136	ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
137
138	return sd_read8(intfhdl, ftaddr, NULL);
139}
140
141static u16 sdio_read16(struct intf_hdl *intfhdl, u32 addr)
142{
143	u32 ftaddr;
144	__le16 le_tmp;
145
146	ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
147	sd_cmd52_read(intfhdl, ftaddr, 2, (u8 *)&le_tmp);
148
149	return le16_to_cpu(le_tmp);
150}
151
152static u32 sdio_read32(struct intf_hdl *intfhdl, u32 addr)
153{
154	struct adapter *adapter;
155	u8 mac_pwr_ctrl_on;
156	u8 device_id;
157	u16 offset;
158	u32 ftaddr;
159	u8 shift;
160	u32 val;
161	s32 __maybe_unused err;
162	__le32 le_tmp;
163
164	adapter = intfhdl->padapter;
165	ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
166
167	rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
168	if (
169		((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
170		(!mac_pwr_ctrl_on) ||
171		(adapter_to_pwrctl(adapter)->fw_current_in_ps_mode)
172	) {
173		err = sd_cmd52_read(intfhdl, ftaddr, 4, (u8 *)&le_tmp);
174		return le32_to_cpu(le_tmp);
175	}
176
177	/*  4 bytes alignment */
178	shift = ftaddr & 0x3;
179	if (shift == 0) {
180		val = sd_read32(intfhdl, ftaddr, NULL);
181	} else {
182		u8 *tmpbuf;
183
184		tmpbuf = rtw_malloc(8);
185		if (!tmpbuf)
186			return SDIO_ERR_VAL32;
187
188		ftaddr &= ~(u16)0x3;
189		sd_read(intfhdl, ftaddr, 8, tmpbuf);
190		memcpy(&le_tmp, tmpbuf + shift, 4);
191		val = le32_to_cpu(le_tmp);
192
193		kfree(tmpbuf);
194	}
195	return val;
196}
197
198static s32 sdio_readN(struct intf_hdl *intfhdl, u32 addr, u32 cnt, u8 *buf)
199{
200	struct adapter *adapter;
201	u8 mac_pwr_ctrl_on;
202	u8 device_id;
203	u16 offset;
204	u32 ftaddr;
205	u8 shift;
206	s32 err;
207
208	adapter = intfhdl->padapter;
209	err = 0;
210
211	ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
212
213	rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
214	if (
215		((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
216		(!mac_pwr_ctrl_on) ||
217		(adapter_to_pwrctl(adapter)->fw_current_in_ps_mode)
218	)
219		return sd_cmd52_read(intfhdl, ftaddr, cnt, buf);
220
221	/*  4 bytes alignment */
222	shift = ftaddr & 0x3;
223	if (shift == 0) {
224		err = sd_read(intfhdl, ftaddr, cnt, buf);
225	} else {
226		u8 *tmpbuf;
227		u32 n;
228
229		ftaddr &= ~(u16)0x3;
230		n = cnt + shift;
231		tmpbuf = rtw_malloc(n);
232		if (!tmpbuf)
233			return -1;
234
235		err = sd_read(intfhdl, ftaddr, n, tmpbuf);
236		if (!err)
237			memcpy(buf, tmpbuf + shift, cnt);
238		kfree(tmpbuf);
239	}
240	return err;
241}
242
243static s32 sdio_write8(struct intf_hdl *intfhdl, u32 addr, u8 val)
244{
245	u32 ftaddr;
246	s32 err;
247
248	ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
249	sd_write8(intfhdl, ftaddr, val, &err);
250
251	return err;
252}
253
254static s32 sdio_write16(struct intf_hdl *intfhdl, u32 addr, u16 val)
255{
256	u32 ftaddr;
257	__le16 le_tmp;
258
259	ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
260	le_tmp = cpu_to_le16(val);
261	return sd_cmd52_write(intfhdl, ftaddr, 2, (u8 *)&le_tmp);
262}
263
264static s32 sdio_write32(struct intf_hdl *intfhdl, u32 addr, u32 val)
265{
266	struct adapter *adapter;
267	u8 mac_pwr_ctrl_on;
268	u8 device_id;
269	u16 offset;
270	u32 ftaddr;
271	u8 shift;
272	s32 err;
273	__le32 le_tmp;
274
275	adapter = intfhdl->padapter;
276	err = 0;
277
278	ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
279
280	rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
281	if (
282		((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
283		(!mac_pwr_ctrl_on) ||
284		(adapter_to_pwrctl(adapter)->fw_current_in_ps_mode)
285	) {
286		le_tmp = cpu_to_le32(val);
287
288		return sd_cmd52_write(intfhdl, ftaddr, 4, (u8 *)&le_tmp);
289	}
290
291	/*  4 bytes alignment */
292	shift = ftaddr & 0x3;
293	if (shift == 0) {
294		sd_write32(intfhdl, ftaddr, val, &err);
295	} else {
296		le_tmp = cpu_to_le32(val);
297		err = sd_cmd52_write(intfhdl, ftaddr, 4, (u8 *)&le_tmp);
298	}
299	return err;
300}
301
302static s32 sdio_writeN(struct intf_hdl *intfhdl, u32 addr, u32 cnt, u8 *buf)
303{
304	struct adapter *adapter;
305	u8 mac_pwr_ctrl_on;
306	u8 device_id;
307	u16 offset;
308	u32 ftaddr;
309	u8 shift;
310	s32 err;
311
312	adapter = intfhdl->padapter;
313	err = 0;
314
315	ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
316
317	rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
318	if (
319		((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
320		(!mac_pwr_ctrl_on) ||
321		(adapter_to_pwrctl(adapter)->fw_current_in_ps_mode)
322	)
323		return sd_cmd52_write(intfhdl, ftaddr, cnt, buf);
324
325	shift = ftaddr & 0x3;
326	if (shift == 0) {
327		err = sd_write(intfhdl, ftaddr, cnt, buf);
328	} else {
329		u8 *tmpbuf;
330		u32 n;
331
332		ftaddr &= ~(u16)0x3;
333		n = cnt + shift;
334		tmpbuf = rtw_malloc(n);
335		if (!tmpbuf)
336			return -1;
337		err = sd_read(intfhdl, ftaddr, 4, tmpbuf);
338		if (err) {
339			kfree(tmpbuf);
340			return err;
341		}
342		memcpy(tmpbuf + shift, buf, cnt);
343		err = sd_write(intfhdl, ftaddr, n, tmpbuf);
344		kfree(tmpbuf);
345	}
346	return err;
347}
348
349static void sdio_read_mem(
350	struct intf_hdl *intfhdl,
351	u32 addr,
352	u32 cnt,
353	u8 *rmem
354)
355{
356	sdio_readN(intfhdl, addr, cnt, rmem);
357}
358
359static void sdio_write_mem(
360	struct intf_hdl *intfhdl,
361	u32 addr,
362	u32 cnt,
363	u8 *wmem
364)
365{
366	sdio_writeN(intfhdl, addr, cnt, wmem);
367}
368
369/*
370 * Description:
371 *Read from RX FIFO
372 *Round read size to block size,
373 *and make sure data transfer will be done in one command.
374 *
375 * Parameters:
376 *intfhdl	a pointer of intf_hdl
377 *addr		port ID
378 *cnt			size to read
379 *rmem		address to put data
380 *
381 * Return:
382 *_SUCCESS(1)		Success
383 *_FAIL(0)		Fail
384 */
385static u32 sdio_read_port(
386	struct intf_hdl *intfhdl,
387	u32 addr,
388	u32 cnt,
389	u8 *mem
390)
391{
392	struct adapter *adapter;
393	struct sdio_data *psdio;
394	struct hal_com_data *hal;
395	s32 err;
396
397	adapter = intfhdl->padapter;
398	psdio = &adapter_to_dvobj(adapter)->intf_data;
399	hal = GET_HAL_DATA(adapter);
400
401	hal_sdio_get_cmd_addr_8723b(adapter, addr, hal->SdioRxFIFOCnt++, &addr);
402
403	if (cnt > psdio->block_transfer_len)
404		cnt = _RND(cnt, psdio->block_transfer_len);
405
406	err = _sd_read(intfhdl, addr, cnt, mem);
407
408	if (err)
409		return _FAIL;
410	return _SUCCESS;
411}
412
413/*
414 * Description:
415 *Write to TX FIFO
416 *Align write size block size,
417 *and make sure data could be written in one command.
418 *
419 * Parameters:
420 *intfhdl	a pointer of intf_hdl
421 *addr		port ID
422 *cnt			size to write
423 *wmem		data pointer to write
424 *
425 * Return:
426 *_SUCCESS(1)		Success
427 *_FAIL(0)		Fail
428 */
429static u32 sdio_write_port(
430	struct intf_hdl *intfhdl,
431	u32 addr,
432	u32 cnt,
433	u8 *mem
434)
435{
436	struct adapter *adapter;
437	struct sdio_data *psdio;
438	s32 err;
439	struct xmit_buf *xmitbuf = (struct xmit_buf *)mem;
440
441	adapter = intfhdl->padapter;
442	psdio = &adapter_to_dvobj(adapter)->intf_data;
443
444	if (!adapter->hw_init_completed)
445		return _FAIL;
446
447	cnt = round_up(cnt, 4);
448	hal_sdio_get_cmd_addr_8723b(adapter, addr, cnt >> 2, &addr);
449
450	if (cnt > psdio->block_transfer_len)
451		cnt = _RND(cnt, psdio->block_transfer_len);
452
453	err = sd_write(intfhdl, addr, cnt, xmitbuf->pdata);
454
455	rtw_sctx_done_err(
456		&xmitbuf->sctx,
457		err ? RTW_SCTX_DONE_WRITE_PORT_ERR : RTW_SCTX_DONE_SUCCESS
458	);
459
460	if (err)
461		return _FAIL;
462	return _SUCCESS;
463}
464
465void sdio_set_intf_ops(struct adapter *adapter, struct _io_ops *ops)
466{
467	ops->_read8 = &sdio_read8;
468	ops->_read16 = &sdio_read16;
469	ops->_read32 = &sdio_read32;
470	ops->_read_mem = &sdio_read_mem;
471	ops->_read_port = &sdio_read_port;
472
473	ops->_write8 = &sdio_write8;
474	ops->_write16 = &sdio_write16;
475	ops->_write32 = &sdio_write32;
476	ops->_writeN = &sdio_writeN;
477	ops->_write_mem = &sdio_write_mem;
478	ops->_write_port = &sdio_write_port;
479}
480
481/*
482 * Todo: align address to 4 bytes.
483 */
484static s32 _sdio_local_read(
485	struct adapter *adapter,
486	u32 addr,
487	u32 cnt,
488	u8 *buf
489)
490{
491	struct intf_hdl *intfhdl;
492	u8 mac_pwr_ctrl_on;
493	s32 err;
494	u8 *tmpbuf;
495	u32 n;
496
497	intfhdl = &adapter->iopriv.intf;
498
499	hal_sdio_get_cmd_addr_8723b(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
500
501	rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
502	if (!mac_pwr_ctrl_on)
503		return _sd_cmd52_read(intfhdl, addr, cnt, buf);
504
505	n = round_up(cnt, 4);
506	tmpbuf = rtw_malloc(n);
507	if (!tmpbuf)
508		return -1;
509
510	err = _sd_read(intfhdl, addr, n, tmpbuf);
511	if (!err)
512		memcpy(buf, tmpbuf, cnt);
513
514	kfree(tmpbuf);
515
516	return err;
517}
518
519/*
520 * Todo: align address to 4 bytes.
521 */
522s32 sdio_local_read(
523	struct adapter *adapter,
524	u32 addr,
525	u32 cnt,
526	u8 *buf
527)
528{
529	struct intf_hdl *intfhdl;
530	u8 mac_pwr_ctrl_on;
531	s32 err;
532	u8 *tmpbuf;
533	u32 n;
534
535	intfhdl = &adapter->iopriv.intf;
536
537	hal_sdio_get_cmd_addr_8723b(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
538
539	rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
540	if (
541		(!mac_pwr_ctrl_on) ||
542		(adapter_to_pwrctl(adapter)->fw_current_in_ps_mode)
543	)
544		return sd_cmd52_read(intfhdl, addr, cnt, buf);
545
546	n = round_up(cnt, 4);
547	tmpbuf = rtw_malloc(n);
548	if (!tmpbuf)
549		return -1;
550
551	err = sd_read(intfhdl, addr, n, tmpbuf);
552	if (!err)
553		memcpy(buf, tmpbuf, cnt);
554
555	kfree(tmpbuf);
556
557	return err;
558}
559
560/*
561 * Todo: align address to 4 bytes.
562 */
563s32 sdio_local_write(
564	struct adapter *adapter,
565	u32 addr,
566	u32 cnt,
567	u8 *buf
568)
569{
570	struct intf_hdl *intfhdl;
571	u8 mac_pwr_ctrl_on;
572	s32 err;
573	u8 *tmpbuf;
574
575	intfhdl = &adapter->iopriv.intf;
576
577	hal_sdio_get_cmd_addr_8723b(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
578
579	rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
580	if (
581		(!mac_pwr_ctrl_on) ||
582		(adapter_to_pwrctl(adapter)->fw_current_in_ps_mode)
583	)
584		return sd_cmd52_write(intfhdl, addr, cnt, buf);
585
586	tmpbuf = rtw_malloc(cnt);
587	if (!tmpbuf)
588		return -1;
589
590	memcpy(tmpbuf, buf, cnt);
591
592	err = sd_write(intfhdl, addr, cnt, tmpbuf);
593
594	kfree(tmpbuf);
595
596	return err;
597}
598
599u8 SdioLocalCmd52Read1Byte(struct adapter *adapter, u32 addr)
600{
601	u8 val = 0;
602	struct intf_hdl *intfhdl = &adapter->iopriv.intf;
603
604	hal_sdio_get_cmd_addr_8723b(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
605	sd_cmd52_read(intfhdl, addr, 1, &val);
606
607	return val;
608}
609
610static u16 sdio_local_cmd52_read2byte(struct adapter *adapter, u32 addr)
611{
612	__le16 val = 0;
613	struct intf_hdl *intfhdl = &adapter->iopriv.intf;
614
615	hal_sdio_get_cmd_addr_8723b(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
616	sd_cmd52_read(intfhdl, addr, 2, (u8 *)&val);
617
618	return le16_to_cpu(val);
619}
620
621static u32 sdio_local_cmd53_read4byte(struct adapter *adapter, u32 addr)
622{
623
624	u8 mac_pwr_ctrl_on;
625	u32 val = 0;
626	struct intf_hdl *intfhdl = &adapter->iopriv.intf;
627	__le32 le_tmp;
628
629	hal_sdio_get_cmd_addr_8723b(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
630	rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on);
631	if (!mac_pwr_ctrl_on || adapter_to_pwrctl(adapter)->fw_current_in_ps_mode) {
632		sd_cmd52_read(intfhdl, addr, 4, (u8 *)&le_tmp);
633		val = le32_to_cpu(le_tmp);
634	} else {
635		val = sd_read32(intfhdl, addr, NULL);
636	}
637	return val;
638}
639
640void SdioLocalCmd52Write1Byte(struct adapter *adapter, u32 addr, u8 v)
641{
642	struct intf_hdl *intfhdl = &adapter->iopriv.intf;
643
644	hal_sdio_get_cmd_addr_8723b(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
645	sd_cmd52_write(intfhdl, addr, 1, &v);
646}
647
648static void sdio_local_cmd52_write4byte(struct adapter *adapter, u32 addr, u32 v)
649{
650	struct intf_hdl *intfhdl = &adapter->iopriv.intf;
651	__le32 le_tmp;
652
653	hal_sdio_get_cmd_addr_8723b(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
654	le_tmp = cpu_to_le32(v);
655	sd_cmd52_write(intfhdl, addr, 4, (u8 *)&le_tmp);
656}
657
658static s32 read_interrupt_8723b_sdio(struct adapter *adapter, u32 *phisr)
659{
660	u32 hisr, himr;
661	u8 val8, hisr_len;
662
663	if (!phisr)
664		return false;
665
666	himr = GET_HAL_DATA(adapter)->sdio_himr;
667
668	/*  decide how many bytes need to be read */
669	hisr_len = 0;
670	while (himr) {
671		hisr_len++;
672		himr >>= 8;
673	}
674
675	hisr = 0;
676	while (hisr_len != 0) {
677		hisr_len--;
678		val8 = SdioLocalCmd52Read1Byte(adapter, SDIO_REG_HISR + hisr_len);
679		hisr |= (val8 << (8 * hisr_len));
680	}
681
682	*phisr = hisr;
683
684	return true;
685}
686
687/*  */
688/*	Description: */
689/*		Initialize SDIO Host Interrupt Mask configuration variables for future use. */
690/*  */
691/*	Assumption: */
692/*		Using SDIO Local register ONLY for configuration. */
693/*  */
694/*	Created by Roger, 2011.02.11. */
695/*  */
696void InitInterrupt8723BSdio(struct adapter *adapter)
697{
698	struct hal_com_data *haldata;
699
700	haldata = GET_HAL_DATA(adapter);
701	haldata->sdio_himr = (u32)(SDIO_HIMR_RX_REQUEST_MSK	|
702				   SDIO_HIMR_AVAL_MSK		|
703				   0);
704}
705
706/*  */
707/*	Description: */
708/*		Initialize System Host Interrupt Mask configuration variables for future use. */
709/*  */
710/*	Created by Roger, 2011.08.03. */
711/*  */
712void InitSysInterrupt8723BSdio(struct adapter *adapter)
713{
714	struct hal_com_data *haldata;
715
716	haldata = GET_HAL_DATA(adapter);
717
718	haldata->SysIntrMask = (0);
719}
720
721/*  */
722/*	Description: */
723/*		Enalbe SDIO Host Interrupt Mask configuration on SDIO local domain. */
724/*  */
725/*	Assumption: */
726/*		1. Using SDIO Local register ONLY for configuration. */
727/*		2. PASSIVE LEVEL */
728/*  */
729/*	Created by Roger, 2011.02.11. */
730/*  */
731void EnableInterrupt8723BSdio(struct adapter *adapter)
732{
733	struct hal_com_data *haldata;
734	__le32 himr;
735	u32 tmp;
736
737	haldata = GET_HAL_DATA(adapter);
738
739	himr = cpu_to_le32(haldata->sdio_himr);
740	sdio_local_write(adapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
741
742	/*  Update current system IMR settings */
743	tmp = rtw_read32(adapter, REG_HSIMR);
744	rtw_write32(adapter, REG_HSIMR, tmp | haldata->SysIntrMask);
745
746	/*  */
747	/*  <Roger_Notes> There are some C2H CMDs have been sent before system interrupt is enabled, e.g., C2H, CPWM. */
748	/*  So we need to clear all C2H events that FW has notified, otherwise FW won't schedule any commands anymore. */
749	/*  2011.10.19. */
750	/*  */
751	rtw_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
752}
753
754/*  */
755/*	Description: */
756/*		Disable SDIO Host IMR configuration to mask unnecessary interrupt service. */
757/*  */
758/*	Assumption: */
759/*		Using SDIO Local register ONLY for configuration. */
760/*  */
761/*	Created by Roger, 2011.02.11. */
762/*  */
763void DisableInterrupt8723BSdio(struct adapter *adapter)
764{
765	__le32 himr;
766
767	himr = cpu_to_le32(SDIO_HIMR_DISABLED);
768	sdio_local_write(adapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
769}
770
771/*  */
772/*	Description: */
773/*		Using 0x100 to check the power status of FW. */
774/*  */
775/*	Assumption: */
776/*		Using SDIO Local register ONLY for configuration. */
777/*  */
778/*	Created by Isaac, 2013.09.10. */
779/*  */
780u8 CheckIPSStatus(struct adapter *adapter)
781{
782	if (rtw_read8(adapter, 0x100) == 0xEA)
783		return true;
784	else
785		return false;
786}
787
788static struct recv_buf *sd_recv_rxfifo(struct adapter *adapter, u32 size)
789{
790	u32 readsize, ret;
791	u8 *readbuf;
792	struct recv_priv *recv_priv;
793	struct recv_buf	*recvbuf;
794
795	/*  Patch for some SDIO Host 4 bytes issue */
796	/*  ex. RK3188 */
797	readsize = round_up(size, 4);
798
799	/* 3 1. alloc recvbuf */
800	recv_priv = &adapter->recvpriv;
801	recvbuf = rtw_dequeue_recvbuf(&recv_priv->free_recv_buf_queue);
802	if (!recvbuf) {
803		netdev_err(adapter->pnetdev, "%s: alloc recvbuf FAIL!\n",
804			   __func__);
805		return NULL;
806	}
807
808	/* 3 2. alloc skb */
809	if (!recvbuf->pskb) {
810		SIZE_PTR tmpaddr = 0;
811		SIZE_PTR alignment = 0;
812
813		recvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
814		if (!recvbuf->pskb)
815			return NULL;
816
817		recvbuf->pskb->dev = adapter->pnetdev;
818
819		tmpaddr = (SIZE_PTR)recvbuf->pskb->data;
820		alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
821		skb_reserve(recvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
822	}
823
824	/* 3 3. read data from rxfifo */
825	readbuf = recvbuf->pskb->data;
826	ret = sdio_read_port(&adapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, readbuf);
827	if (ret == _FAIL)
828		return NULL;
829
830	/* 3 4. init recvbuf */
831	recvbuf->len = size;
832	recvbuf->phead = recvbuf->pskb->head;
833	recvbuf->pdata = recvbuf->pskb->data;
834	skb_set_tail_pointer(recvbuf->pskb, size);
835	recvbuf->ptail = skb_tail_pointer(recvbuf->pskb);
836	recvbuf->pend = skb_end_pointer(recvbuf->pskb);
837
838	return recvbuf;
839}
840
841static void sd_rxhandler(struct adapter *adapter, struct recv_buf *recvbuf)
842{
843	struct recv_priv *recv_priv;
844	struct __queue *pending_queue;
845
846	recv_priv = &adapter->recvpriv;
847	pending_queue = &recv_priv->recv_buf_pending_queue;
848
849	/* 3 1. enqueue recvbuf */
850	rtw_enqueue_recvbuf(recvbuf, pending_queue);
851
852	/* 3 2. schedule tasklet */
853	tasklet_schedule(&recv_priv->recv_tasklet);
854}
855
856void sd_int_dpc(struct adapter *adapter)
857{
858	struct hal_com_data *hal;
859	struct dvobj_priv *dvobj;
860	struct intf_hdl *intfhdl = &adapter->iopriv.intf;
861	struct pwrctrl_priv *pwrctl;
862
863	hal = GET_HAL_DATA(adapter);
864	dvobj = adapter_to_dvobj(adapter);
865	pwrctl = dvobj_to_pwrctl(dvobj);
866
867	if (hal->sdio_hisr & SDIO_HISR_AVAL) {
868		u8 freepage[4];
869
870		_sdio_local_read(adapter, SDIO_REG_FREE_TXPG, 4, freepage);
871		complete(&(adapter->xmitpriv.xmit_comp));
872	}
873
874	if (hal->sdio_hisr & SDIO_HISR_CPWM1) {
875		del_timer_sync(&(pwrctl->pwr_rpwm_timer));
876
877		SdioLocalCmd52Read1Byte(adapter, SDIO_REG_HCPWM1_8723B);
878
879		_set_workitem(&(pwrctl->cpwm_event));
880	}
881
882	if (hal->sdio_hisr & SDIO_HISR_TXERR) {
883		u8 *status;
884		u32 addr;
885
886		status = rtw_malloc(4);
887		if (status) {
888			addr = REG_TXDMA_STATUS;
889			hal_sdio_get_cmd_addr_8723b(adapter, WLAN_IOREG_DEVICE_ID, addr, &addr);
890			_sd_read(intfhdl, addr, 4, status);
891			_sd_write(intfhdl, addr, 4, status);
892			kfree(status);
893		}
894	}
895
896	if (hal->sdio_hisr & SDIO_HISR_C2HCMD) {
897		struct c2h_evt_hdr_88xx *c2h_evt;
898
899		c2h_evt = rtw_zmalloc(16);
900		if (c2h_evt) {
901			if (c2h_evt_read_88xx(adapter, (u8 *)c2h_evt) == _SUCCESS) {
902				if (c2h_id_filter_ccx_8723b((u8 *)c2h_evt)) {
903					/* Handle CCX report here */
904					rtw_hal_c2h_handler(adapter, (u8 *)c2h_evt);
905					kfree(c2h_evt);
906				} else {
907					rtw_c2h_wk_cmd(adapter, (u8 *)c2h_evt);
908				}
909			} else {
910				kfree(c2h_evt);
911			}
912		} else {
913			/* Error handling for malloc fail */
914			rtw_cbuf_push(adapter->evtpriv.c2h_queue, NULL);
915			_set_workitem(&adapter->evtpriv.c2h_wk);
916		}
917	}
918
919	if (hal->sdio_hisr & SDIO_HISR_RX_REQUEST) {
920		struct recv_buf *recvbuf;
921		int alloc_fail_time = 0;
922		u32 hisr;
923
924		hal->sdio_hisr ^= SDIO_HISR_RX_REQUEST;
925		do {
926			hal->SdioRxFIFOSize = sdio_local_cmd52_read2byte(adapter, SDIO_REG_RX0_REQ_LEN);
927			if (hal->SdioRxFIFOSize != 0) {
928				recvbuf = sd_recv_rxfifo(adapter, hal->SdioRxFIFOSize);
929				if (recvbuf)
930					sd_rxhandler(adapter, recvbuf);
931				else {
932					alloc_fail_time++;
933					if (alloc_fail_time >= 10)
934						break;
935				}
936				hal->SdioRxFIFOSize = 0;
937			} else
938				break;
939
940			hisr = 0;
941			read_interrupt_8723b_sdio(adapter, &hisr);
942			hisr &= SDIO_HISR_RX_REQUEST;
943			if (!hisr)
944				break;
945		} while (1);
946	}
947}
948
949void sd_int_hdl(struct adapter *adapter)
950{
951	struct hal_com_data *hal;
952
953	if (
954		(adapter->bDriverStopped) || (adapter->bSurpriseRemoved)
955	)
956		return;
957
958	hal = GET_HAL_DATA(adapter);
959
960	hal->sdio_hisr = 0;
961	read_interrupt_8723b_sdio(adapter, &hal->sdio_hisr);
962
963	if (hal->sdio_hisr & hal->sdio_himr) {
964		u32 v32;
965
966		hal->sdio_hisr &= hal->sdio_himr;
967
968		/*  clear HISR */
969		v32 = hal->sdio_hisr & MASK_SDIO_HISR_CLEAR;
970		if (v32)
971			sdio_local_cmd52_write4byte(adapter, SDIO_REG_HISR, v32);
972
973		sd_int_dpc(adapter);
974	}
975}
976
977/*  */
978/*	Description: */
979/*		Query SDIO Local register to query current the number of Free TxPacketBuffer page. */
980/*  */
981/*	Assumption: */
982/*		1. Running at PASSIVE_LEVEL */
983/*		2. RT_TX_SPINLOCK is NOT acquired. */
984/*  */
985/*	Created by Roger, 2011.01.28. */
986/*  */
987u8 HalQueryTxBufferStatus8723BSdio(struct adapter *adapter)
988{
989	struct hal_com_data *hal;
990	u32 numof_free_page;
991
992	hal = GET_HAL_DATA(adapter);
993
994	numof_free_page = sdio_local_cmd53_read4byte(adapter, SDIO_REG_FREE_TXPG);
995
996	memcpy(hal->SdioTxFIFOFreePage, &numof_free_page, 4);
997
998	return true;
999}
1000
1001/*  */
1002/*	Description: */
1003/*		Query SDIO Local register to get the current number of TX OQT Free Space. */
1004/*  */
1005void HalQueryTxOQTBufferStatus8723BSdio(struct adapter *adapter)
1006{
1007	struct hal_com_data *haldata = GET_HAL_DATA(adapter);
1008
1009	haldata->SdioTxOQTFreeSpace = SdioLocalCmd52Read1Byte(adapter, SDIO_REG_OQT_FREE_PG);
1010}
1011
1012
1013