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