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