8723BU: Update 8723BU wifi driver to version v4.3.16_14189.20150519_BTCOEX2015119...
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8723au / hal / rtl8723a / sdio / sdio_ops.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *******************************************************************************/
19 #define _SDIO_OPS_C_
20
21 #include <drv_types.h>
22 #include <sdio_ops.h>
23 #include <rtl8723a_spec.h>
24 #include <rtl8723a_hal.h>
25
26 //#define SDIO_DEBUG_IO 1
27
28 //
29 // Description:
30 //      The following mapping is for SDIO host local register space.
31 //
32 // Creadted by Roger, 2011.01.31.
33 //
34 static void HalSdioGetCmdAddr8723ASdio(
35         IN      PADAPTER                        padapter,
36         IN      u8                              DeviceID,
37         IN      u32                             Addr,
38         OUT     u32*                            pCmdAddr
39         )
40 {
41         switch (DeviceID)
42         {
43                 case SDIO_LOCAL_DEVICE_ID:
44                         *pCmdAddr = ((SDIO_LOCAL_DEVICE_ID << 13) | (Addr & SDIO_LOCAL_MSK));
45                         break;
46
47                 case WLAN_IOREG_DEVICE_ID:
48                         *pCmdAddr = ((WLAN_IOREG_DEVICE_ID << 13) | (Addr & WLAN_IOREG_MSK));
49                         break;
50
51                 case WLAN_TX_HIQ_DEVICE_ID:
52                         *pCmdAddr = ((WLAN_TX_HIQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK));
53                         break;
54
55                 case WLAN_TX_MIQ_DEVICE_ID:
56                         *pCmdAddr = ((WLAN_TX_MIQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK));
57                         break;
58
59                 case WLAN_TX_LOQ_DEVICE_ID:
60                         *pCmdAddr = ((WLAN_TX_LOQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK));
61                         break;
62
63                 case WLAN_RX0FF_DEVICE_ID:
64                         *pCmdAddr = ((WLAN_RX0FF_DEVICE_ID << 13) | (Addr & WLAN_RX0FF_MSK));
65                         break;
66
67                 default:
68                         break;
69         }
70 }
71
72 static u8 get_deviceid(u32 addr)
73 {
74         u8 devideId;
75         u16 pseudoId;
76
77
78         pseudoId = (u16)(addr >> 16);
79         switch (pseudoId)
80         {
81                 case 0x1025:
82                         devideId = SDIO_LOCAL_DEVICE_ID;
83                         break;
84
85                 case 0x1026:
86                         devideId = WLAN_IOREG_DEVICE_ID;
87                         break;
88
89 //              case 0x1027:
90 //                      devideId = SDIO_FIRMWARE_FIFO;
91 //                      break;
92
93                 case 0x1031:
94                         devideId = WLAN_TX_HIQ_DEVICE_ID;
95                         break;
96
97                 case 0x1032:
98                         devideId = WLAN_TX_MIQ_DEVICE_ID;
99                         break;
100
101                 case 0x1033:
102                         devideId = WLAN_TX_LOQ_DEVICE_ID;
103                         break;
104
105                 case 0x1034:
106                         devideId = WLAN_RX0FF_DEVICE_ID;
107                         break;
108
109                 default:
110 //                      devideId = (u8)((addr >> 13) & 0xF);
111                         devideId = WLAN_IOREG_DEVICE_ID;
112                         break;
113         }
114
115         return devideId;
116 }
117
118 /*
119  * Ref:
120  *      HalSdioGetCmdAddr8723ASdio()
121  */
122 static u32 _cvrt2ftaddr(const u32 addr, u8 *pdeviceId, u16 *poffset)
123 {
124         u8 deviceId;
125         u16 offset;
126         u32 ftaddr;
127
128
129         deviceId = get_deviceid(addr);
130         offset = 0;
131
132         switch (deviceId)
133         {
134                 case SDIO_LOCAL_DEVICE_ID:
135                         offset = addr & SDIO_LOCAL_MSK;
136                         break;
137
138                 case WLAN_TX_HIQ_DEVICE_ID:
139                 case WLAN_TX_MIQ_DEVICE_ID:
140                 case WLAN_TX_LOQ_DEVICE_ID:
141                         offset = addr & WLAN_FIFO_MSK;
142                         break;
143
144                 case WLAN_RX0FF_DEVICE_ID:
145                         offset = addr & WLAN_RX0FF_MSK;
146                         break;
147
148                 case WLAN_IOREG_DEVICE_ID:
149                 default:
150                         deviceId = WLAN_IOREG_DEVICE_ID;
151                         offset = addr & WLAN_IOREG_MSK;
152                         break;
153         }
154         ftaddr = (deviceId << 13) | offset;
155
156         if (pdeviceId) *pdeviceId = deviceId;
157         if (poffset) *poffset = offset;
158
159         return ftaddr;
160 }
161
162 u8 sdio_read8(struct intf_hdl *pintfhdl, u32 addr)
163 {
164         u32 ftaddr;
165         u8 val;
166
167 _func_enter_;
168         ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
169         val = sd_read8(pintfhdl, ftaddr, NULL);
170
171 _func_exit_;
172
173         return val;
174 }
175
176 u16 sdio_read16(struct intf_hdl *pintfhdl, u32 addr)
177 {
178         u32 ftaddr;
179         u16 val;
180
181 _func_enter_;
182
183         ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
184         sd_cmd52_read(pintfhdl, ftaddr, 2, (u8*)&val);
185         val = le16_to_cpu(val);
186
187 _func_exit_;
188
189         return val;
190 }
191
192 u32 sdio_read32(struct intf_hdl *pintfhdl, u32 addr)
193 {
194         PADAPTER padapter;
195         u8 bMacPwrCtrlOn;
196         u8 deviceId;
197         u16 offset;
198         u32 ftaddr;
199         u8 shift;
200         u32 val;
201         s32 err;
202
203 _func_enter_;
204
205         padapter = pintfhdl->padapter;
206
207         ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
208
209         rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
210         if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100))
211                 || (_FALSE == bMacPwrCtrlOn)
212 #ifdef CONFIG_LPS_LCLK
213                 || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
214 #endif
215                 )
216         {
217                 err = sd_cmd52_read(pintfhdl, ftaddr, 4, (u8*)&val);
218 #ifdef SDIO_DEBUG_IO
219                 if (!err) {
220 #endif
221                         val = le32_to_cpu(val);
222                         return val;
223 #ifdef SDIO_DEBUG_IO
224                 }
225
226                 DBG_8192C(KERN_ERR "%s: Mac Power off, Read FAIL(%d)! addr=0x%x\n", __func__, err, addr);
227                 return SDIO_ERR_VAL32;
228 #endif
229         }
230
231         // 4 bytes alignment
232         shift = ftaddr & 0x3;
233         if (shift == 0) {
234                 val = sd_read32(pintfhdl, ftaddr, NULL);
235         } else {
236                 u8 *ptmpbuf;
237
238                 ptmpbuf = (u8*)rtw_malloc(8);
239                 if (NULL == ptmpbuf) {
240                         DBG_8192C(KERN_ERR "%s: Allocate memory FAIL!(size=8) addr=0x%x\n", __func__, addr);
241                         return SDIO_ERR_VAL32;
242                 }
243
244                 ftaddr &= ~(u16)0x3;
245                 sd_read(pintfhdl, ftaddr, 8, ptmpbuf);
246                 _rtw_memcpy(&val, ptmpbuf+shift, 4);
247                 val = le32_to_cpu(val);
248
249                 rtw_mfree(ptmpbuf, 8);
250         }
251
252 _func_exit_;
253
254         return val;
255 }
256
257 s32 sdio_readN(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pbuf)
258 {
259         PADAPTER padapter;
260         u8 bMacPwrCtrlOn;
261         u8 deviceId;
262         u16 offset;
263         u32 ftaddr;
264         u8 shift;
265         s32 err;
266
267 _func_enter_;
268
269         padapter = pintfhdl->padapter;
270         err = 0;
271
272         ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
273
274         rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
275         if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100))
276                 || (_FALSE == bMacPwrCtrlOn)
277 #ifdef CONFIG_LPS_LCLK
278                 || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
279 #endif
280                 )
281         {
282                 err = sd_cmd52_read(pintfhdl, ftaddr, cnt, pbuf);
283                 return err;
284         }
285
286         // 4 bytes alignment
287         shift = ftaddr & 0x3;
288         if (shift == 0) {
289                 err = sd_read(pintfhdl, ftaddr, cnt, pbuf);
290         } else {
291                 u8 *ptmpbuf;
292                 u32 n;
293
294                 ftaddr &= ~(u16)0x3;
295                 n = cnt + shift;
296                 ptmpbuf = rtw_malloc(n);
297                 if (NULL == ptmpbuf) return -1;
298                 err = sd_read(pintfhdl, ftaddr, n, ptmpbuf);
299                 if (!err)
300                         _rtw_memcpy(pbuf, ptmpbuf+shift, cnt);
301                 rtw_mfree(ptmpbuf, n);
302         }
303
304 _func_exit_;
305
306         return err;
307 }
308
309 s32 sdio_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
310 {
311         u32 ftaddr;
312         s32 err;
313
314 _func_enter_;
315
316         ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
317         sd_write8(pintfhdl, ftaddr, val, &err);
318
319 _func_exit_;
320
321         return err;
322 }
323
324 s32 sdio_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
325 {
326         u32 ftaddr;
327         u8 shift;
328         s32 err;
329
330 _func_enter_;
331
332         ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
333         val = cpu_to_le16(val);
334         err = sd_cmd52_write(pintfhdl, ftaddr, 2, (u8*)&val);
335
336 _func_exit_;
337
338         return err;
339 }
340
341 s32 sdio_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
342 {
343         PADAPTER padapter;
344         u8 bMacPwrCtrlOn;
345         u8 deviceId;
346         u16 offset;
347         u32 ftaddr;
348         u8 shift;
349         s32 err;
350
351 _func_enter_;
352
353         padapter = pintfhdl->padapter;
354         err = 0;
355
356         ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
357
358         rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
359         if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100))
360                 || (_FALSE == bMacPwrCtrlOn)
361 #ifdef CONFIG_LPS_LCLK
362                 || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
363 #endif
364                 )
365         {
366                 val = cpu_to_le32(val);
367                 err = sd_cmd52_write(pintfhdl, ftaddr, 4, (u8*)&val);
368                 return err;
369         }
370
371         // 4 bytes alignment
372         shift = ftaddr & 0x3;
373 #if 1
374         if (shift == 0)
375         {
376                 sd_write32(pintfhdl, ftaddr, val, &err);
377         }
378         else
379         {
380                 val = cpu_to_le32(val);
381                 err = sd_cmd52_write(pintfhdl, ftaddr, 4, (u8*)&val);
382         }
383 #else
384         if (shift == 0) {
385                 sd_write32(pintfhdl, ftaddr, val, &err);
386         } else {
387                 u8 *ptmpbuf;
388
389                 ptmpbuf = (u8*)rtw_malloc(8);
390                 if (NULL == ptmpbuf) return (-1);
391
392                 ftaddr &= ~(u16)0x3;
393                 err = sd_read(pintfhdl, ftaddr, 8, ptmpbuf);
394                 if (err) {
395                         rtw_mfree(ptmpbuf, 8);
396                         return err;
397                 }
398                 val = cpu_to_le32(val);
399                 _rtw_memcpy(ptmpbuf+shift, &val, 4);
400                 err = sd_write(pintfhdl, ftaddr, 8, ptmpbuf);
401
402                 rtw_mfree(ptmpbuf, 8);
403         }
404 #endif
405
406 _func_exit_;
407
408         return err;
409 }
410
411 s32 sdio_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8* pbuf)
412 {
413         PADAPTER padapter;
414         u8 bMacPwrCtrlOn;
415         u8 deviceId;
416         u16 offset;
417         u32 ftaddr;
418         u8 shift;
419         s32 err;
420
421 _func_enter_;
422
423         padapter = pintfhdl->padapter;
424         err = 0;
425
426         ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
427
428         rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
429         if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100))
430                 || (_FALSE == bMacPwrCtrlOn)
431 #ifdef CONFIG_LPS_LCLK
432                 || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
433 #endif
434                 )
435         {
436                 err = sd_cmd52_write(pintfhdl, ftaddr, cnt, pbuf);
437                 return err;
438         }
439
440         shift = ftaddr & 0x3;
441         if (shift == 0) {
442                 err = sd_write(pintfhdl, ftaddr, cnt, pbuf);
443         } else {
444                 u8 *ptmpbuf;
445                 u32 n;
446
447                 ftaddr &= ~(u16)0x3;
448                 n = cnt + shift;
449                 ptmpbuf = rtw_malloc(n);
450                 if (NULL == ptmpbuf) return -1;
451                 err = sd_read(pintfhdl, ftaddr, 4, ptmpbuf);
452                 if (err) {
453                         rtw_mfree(ptmpbuf, n);
454                         return err;
455                 }
456                 _rtw_memcpy(ptmpbuf+shift, pbuf, cnt);
457                 err = sd_write(pintfhdl, ftaddr, n, ptmpbuf);
458                 rtw_mfree(ptmpbuf, n);
459         }
460
461 _func_exit_;
462
463         return err;
464 }
465
466 void sdio_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
467 {
468         s32 err;
469
470 _func_enter_;
471
472         err = sdio_readN(pintfhdl, addr, cnt, rmem);
473
474 _func_exit_;
475 }
476
477 void sdio_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
478 {
479 _func_enter_;
480
481         sdio_writeN(pintfhdl, addr, cnt, wmem);
482
483 _func_exit_;
484 }
485
486 /*
487  * Description:
488  *      Read from RX FIFO
489  *      Round read size to block size,
490  *      and make sure data transfer will be done in one command.
491  *
492  * Parameters:
493  *      pintfhdl        a pointer of intf_hdl
494  *      addr            port ID
495  *      cnt                     size to read
496  *      rmem            address to put data
497  *
498  * Return:
499  *      _SUCCESS(1)             Success
500  *      _FAIL(0)                Fail
501  */
502 static u32 sdio_read_port(
503         struct intf_hdl *pintfhdl,
504         u32 addr,
505         u32 cnt,
506         u8 *mem)
507 {
508         PADAPTER padapter;
509         PSDIO_DATA psdio;
510         PHAL_DATA_TYPE phal;
511         u32 oldcnt;
512 #ifdef SDIO_DYNAMIC_ALLOC_MEM
513         u8 *oldmem;
514 #endif
515         s32 err;
516
517
518         padapter = pintfhdl->padapter;
519         psdio = &adapter_to_dvobj(padapter)->intf_data;
520         phal = GET_HAL_DATA(padapter);
521
522         HalSdioGetCmdAddr8723ASdio(padapter, addr, phal->SdioRxFIFOCnt++, &addr);
523
524         oldcnt = cnt;
525         if (cnt > psdio->block_transfer_len)
526                 cnt = _RND(cnt, psdio->block_transfer_len);
527 //      cnt = sdio_align_size(cnt);
528
529         if (oldcnt != cnt) {
530 #ifdef SDIO_DYNAMIC_ALLOC_MEM
531                 oldmem = mem;
532                 mem = rtw_malloc(cnt);
533                 if (mem == NULL) {
534                         DBG_8192C(KERN_WARNING "%s: allocate memory %d bytes fail!\n", __func__, cnt);
535                         mem = oldmem;
536                         oldmem == NULL;
537                 }
538 #else
539                 // in this case, caller should gurante the buffer is big enough
540                 // to receive data after alignment
541 #endif
542         }
543
544         err = _sd_read(pintfhdl, addr, cnt, mem);
545
546 #ifdef SDIO_DYNAMIC_ALLOC_MEM
547         if ((oldcnt != cnt) && (oldmem)) {
548                 _rtw_memcpy(oldmem, mem, oldcnt);
549                 rtw_mfree(mem, cnt);
550         }
551 #endif
552
553         if (err) return _FAIL;
554         return _SUCCESS;
555 }
556
557 /*
558  * Description:
559  *      Write to TX FIFO
560  *      Align write size block size,
561  *      and make sure data could be written in one command.
562  *
563  * Parameters:
564  *      pintfhdl        a pointer of intf_hdl
565  *      addr            port ID
566  *      cnt                     size to write
567  *      wmem            data pointer to write
568  *
569  * Return:
570  *      _SUCCESS(1)             Success
571  *      _FAIL(0)                Fail
572  */
573 static u32 sdio_write_port(
574         struct intf_hdl *pintfhdl,
575         u32 addr,
576         u32 cnt,
577         u8 *mem)
578 {
579         PADAPTER padapter;
580         PSDIO_DATA psdio;
581         s32 err;
582         struct xmit_buf *xmitbuf = (struct xmit_buf *)mem;
583
584         padapter = pintfhdl->padapter;
585         psdio = &adapter_to_dvobj(padapter)->intf_data;
586
587         if(padapter->hw_init_completed == _FALSE)
588         {
589                 DBG_871X("%s [addr=0x%x cnt=%d] padapter->hw_init_completed == _FALSE    \n",__func__,addr,cnt);
590                 return _FAIL;
591         }
592
593         cnt = _RND4(cnt);
594         HalSdioGetCmdAddr8723ASdio(padapter, addr, cnt >> 2, &addr);
595
596         if (cnt > psdio->block_transfer_len)
597                 cnt = _RND(cnt, psdio->block_transfer_len);
598 //      cnt = sdio_align_size(cnt);
599
600         err = sd_write(pintfhdl, addr, cnt, xmitbuf->pdata);
601
602         rtw_sctx_done_err(&xmitbuf->sctx,
603                 err ? RTW_SCTX_DONE_WRITE_PORT_ERR : RTW_SCTX_DONE_SUCCESS);
604
605         if (err) return _FAIL;
606         return _SUCCESS;
607 }
608
609 void sdio_set_intf_ops(struct _io_ops *pops)
610 {
611 _func_enter_;
612
613         pops->_read8 = &sdio_read8;
614         pops->_read16 = &sdio_read16;
615         pops->_read32 = &sdio_read32;
616         pops->_read_mem = &sdio_read_mem;
617         pops->_read_port = &sdio_read_port;
618
619         pops->_write8 = &sdio_write8;
620         pops->_write16 = &sdio_write16;
621         pops->_write32 = &sdio_write32;
622         pops->_writeN = &sdio_writeN;
623         pops->_write_mem = &sdio_write_mem;
624         pops->_write_port = &sdio_write_port;
625
626 _func_exit_;
627 }
628
629 /*
630  * Todo: align address to 4 bytes.
631  */
632 s32 _sdio_local_read(
633         PADAPTER        padapter,
634         u32                     addr,
635         u32                     cnt,
636         u8                      *pbuf)
637 {
638         struct intf_hdl * pintfhdl;
639         u8 bMacPwrCtrlOn;
640         s32 err;
641         u8 *ptmpbuf;
642         u32 n;
643
644         pintfhdl=&padapter->iopriv.intf;
645         
646         HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
647
648         rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
649         if (_FALSE == bMacPwrCtrlOn)
650         {
651                 err = _sd_cmd52_read(pintfhdl, addr, cnt, pbuf);
652                 return err;
653         }
654
655         n = RND4(cnt);
656         ptmpbuf = (u8*)rtw_malloc(n);
657         if (!ptmpbuf)
658                 return (-1);
659
660         err = _sd_read(pintfhdl, addr, n, ptmpbuf);
661         if (!err)
662                 _rtw_memcpy(pbuf, ptmpbuf, cnt);
663
664         if (ptmpbuf)
665                 rtw_mfree(ptmpbuf, n);
666
667         return err;
668 }
669
670 /*
671  * Todo: align address to 4 bytes.
672  */
673 s32 sdio_local_read(
674         PADAPTER        padapter,
675         u32                     addr,
676         u32                     cnt,
677         u8                      *pbuf)
678 {
679         struct intf_hdl * pintfhdl;
680         u8 bMacPwrCtrlOn;
681         s32 err;
682         u8 *ptmpbuf;
683         u32 n;
684
685         pintfhdl=&padapter->iopriv.intf;
686         HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
687
688         rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
689         if ((_FALSE == bMacPwrCtrlOn)
690 #ifdef CONFIG_LPS_LCLK
691                 || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
692 #endif
693                 )
694         {
695                 err = sd_cmd52_read(pintfhdl, addr, cnt, pbuf);
696                 return err;
697         }
698
699         n = RND4(cnt);
700         ptmpbuf = (u8*)rtw_malloc(n);
701         if (!ptmpbuf)
702                 return (-1);
703
704         err = sd_read(pintfhdl, addr, n, ptmpbuf);
705         if (!err)
706                 _rtw_memcpy(pbuf, ptmpbuf, cnt);
707
708         if (ptmpbuf)
709                 rtw_mfree(ptmpbuf, n);
710
711         return err;
712 }
713
714 /*
715  * Todo: align address to 4 bytes.
716  */
717 s32 _sdio_local_write(
718         PADAPTER        padapter,
719         u32                     addr,
720         u32                     cnt,
721         u8                      *pbuf)
722 {
723         struct intf_hdl * pintfhdl;
724         u8 bMacPwrCtrlOn;
725         s32 err;
726         u8 *ptmpbuf;
727
728         if(addr & 0x3)
729                 DBG_8192C("%s, address must be 4 bytes alignment\n", __FUNCTION__);
730
731         if(cnt  & 0x3)
732                 DBG_8192C("%s, size must be the multiple of 4 \n", __FUNCTION__);
733
734         pintfhdl=&padapter->iopriv.intf;
735         HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
736
737         rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
738         if ((_FALSE == bMacPwrCtrlOn)
739 #ifdef CONFIG_LPS_LCLK
740                 || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
741 #endif
742                 )
743         {
744                 err = _sd_cmd52_write(pintfhdl, addr, cnt, pbuf);
745                 return err;
746         }
747
748         ptmpbuf = (u8*)rtw_malloc(cnt);
749         if (!ptmpbuf)
750                 return (-1);
751
752         _rtw_memcpy(ptmpbuf, pbuf, cnt);
753
754         err = _sd_write(pintfhdl, addr, cnt, ptmpbuf);
755
756         if (ptmpbuf)
757                 rtw_mfree(ptmpbuf, cnt);
758
759         return err;
760 }
761
762 /*
763  * Todo: align address to 4 bytes.
764  */
765 s32 sdio_local_write(
766         PADAPTER        padapter,
767         u32             addr,
768         u32             cnt,
769         u8              *pbuf)
770 {
771         struct intf_hdl * pintfhdl;     
772         u8 bMacPwrCtrlOn;
773         s32 err;
774         u8 *ptmpbuf;
775
776         if(addr & 0x3)
777                 DBG_8192C("%s, address must be 4 bytes alignment\n", __FUNCTION__);
778
779         if(cnt  & 0x3)
780                 DBG_8192C("%s, size must be the multiple of 4 \n", __FUNCTION__);
781
782         pintfhdl=&padapter->iopriv.intf;
783         
784         HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
785
786         rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
787         if ((_FALSE == bMacPwrCtrlOn)
788 #ifdef CONFIG_LPS_LCLK
789                 || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
790 #endif
791                 )
792         {
793                 err = sd_cmd52_write(pintfhdl, addr, cnt, pbuf);
794                 return err;
795         }
796
797         ptmpbuf = (u8*)rtw_malloc(cnt);
798         if (!ptmpbuf)
799                 return (-1);
800
801         _rtw_memcpy(ptmpbuf, pbuf, cnt);
802
803         err = sd_write(pintfhdl, addr, cnt, ptmpbuf);
804
805         if (ptmpbuf)
806                 rtw_mfree(ptmpbuf, cnt);
807
808         return err;
809 }
810
811 u8 SdioLocalCmd52Read1Byte(PADAPTER padapter, u32 addr)
812 {
813         struct intf_hdl * pintfhdl;
814         u8 val = 0;
815
816         pintfhdl=&padapter->iopriv.intf;
817         HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
818         sd_cmd52_read(pintfhdl, addr, 1, &val);
819
820         return val;
821 }
822
823 u16 SdioLocalCmd52Read2Byte(PADAPTER padapter, u32 addr)
824 {
825         struct intf_hdl * pintfhdl;
826         u16 val = 0;
827
828         pintfhdl=&padapter->iopriv.intf;
829         HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
830         sd_cmd52_read(pintfhdl, addr, 2, (u8*)&val);
831
832         val = le16_to_cpu(val);
833
834         return val;
835 }
836
837 u32 SdioLocalCmd52Read4Byte(PADAPTER padapter, u32 addr)
838 {
839         struct intf_hdl * pintfhdl;
840         u32 val = 0;
841
842         pintfhdl=&padapter->iopriv.intf;
843         HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
844         sd_cmd52_read(pintfhdl, addr, 4, (u8*)&val);
845
846         val = le32_to_cpu(val);
847
848         return val;
849 }
850
851 u32 SdioLocalCmd53Read4Byte(PADAPTER padapter, u32 addr)
852 {
853         struct intf_hdl * pintfhdl;
854         u8 bMacPwrCtrlOn;
855         u32 val=0;
856
857         pintfhdl=&padapter->iopriv.intf;
858         HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
859         rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
860         if ((_FALSE == bMacPwrCtrlOn)
861 #ifdef CONFIG_LPS_LCLK
862                 || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
863 #endif
864                 )
865         {
866                 sd_cmd52_read(pintfhdl, addr, 4, (u8*)&val);
867                 val = le32_to_cpu(val);
868         }
869         else
870                 val = sd_read32(pintfhdl, addr, NULL);
871
872         return val;
873 }
874
875 void SdioLocalCmd52Write1Byte(PADAPTER padapter, u32 addr, u8 v)
876 {
877         struct intf_hdl * pintfhdl;
878
879         pintfhdl=&padapter->iopriv.intf;
880         HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
881         sd_cmd52_write(pintfhdl, addr, 1, &v);
882 }
883
884 void SdioLocalCmd52Write2Byte(PADAPTER padapter, u32 addr, u16 v)
885 {
886         struct intf_hdl * pintfhdl;
887
888         pintfhdl=&padapter->iopriv.intf;
889         HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
890         v = cpu_to_le16(v);
891         sd_cmd52_write(pintfhdl, addr, 2, (u8*)&v);
892 }
893
894 void SdioLocalCmd52Write4Byte(PADAPTER padapter, u32 addr, u32 v)
895 {
896         struct intf_hdl * pintfhdl;
897
898         pintfhdl=&padapter->iopriv.intf;
899         HalSdioGetCmdAddr8723ASdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
900         v = cpu_to_le32(v);
901         sd_cmd52_write(pintfhdl, addr, 4, (u8*)&v);
902 }
903
904 #if 0
905 void
906 DumpLoggedInterruptHistory8723Sdio(
907         PADAPTER                padapter
908 )
909 {
910         HAL_DATA_TYPE   *pHalData=GET_HAL_DATA(padapter);
911         u4Byte                          DebugLevel = DBG_LOUD;
912
913         if (DBG_Var.DbgPrintIsr == 0)
914                 return;
915
916         DBG_ChkDrvResource(padapter);
917
918
919         if(pHalData->InterruptLog.nISR_RX_REQUEST)
920                 RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# RX_REQUEST[%ld]\t\n", pHalData->InterruptLog.nISR_RX_REQUEST));
921
922         if(pHalData->InterruptLog.nISR_AVAL)
923                 RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# AVAL[%ld]\t\n", pHalData->InterruptLog.nISR_AVAL));
924
925         if(pHalData->InterruptLog.nISR_TXERR)
926                 RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# TXERR[%ld]\t\n", pHalData->InterruptLog.nISR_TXERR));
927
928         if(pHalData->InterruptLog.nISR_RXERR)
929                 RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# RXERR[%ld]\t\n", pHalData->InterruptLog.nISR_RXERR));
930
931         if(pHalData->InterruptLog.nISR_TXFOVW)
932                 RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# TXFOVW[%ld]\t\n", pHalData->InterruptLog.nISR_TXFOVW));
933
934         if(pHalData->InterruptLog.nISR_RXFOVW)
935                 RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# RXFOVW[%ld]\t\n", pHalData->InterruptLog.nISR_RXFOVW));
936
937         if(pHalData->InterruptLog.nISR_TXBCNOK)
938                 RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# TXBCNOK[%ld]\t\n", pHalData->InterruptLog.nISR_TXBCNOK));
939
940         if(pHalData->InterruptLog.nISR_TXBCNERR)
941                 RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# TXBCNERR[%ld]\t\n", pHalData->InterruptLog.nISR_TXBCNERR));
942
943         if(pHalData->InterruptLog.nISR_BCNERLY_INT)
944                 RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# BCNERLY_INT[%ld]\t\n", pHalData->InterruptLog.nISR_BCNERLY_INT));
945
946         if(pHalData->InterruptLog.nISR_C2HCMD)
947                 RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# C2HCMD[%ld]\t\n", pHalData->InterruptLog.nISR_C2HCMD));
948
949         if(pHalData->InterruptLog.nISR_CPWM1)
950                 RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# CPWM1L[%ld]\t\n", pHalData->InterruptLog.nISR_CPWM1));
951
952         if(pHalData->InterruptLog.nISR_CPWM2)
953                 RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# CPWM2[%ld]\t\n", pHalData->InterruptLog.nISR_CPWM2));
954
955         if(pHalData->InterruptLog.nISR_HSISR_IND)
956                 RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# HSISR_IND[%ld]\t\n", pHalData->InterruptLog.nISR_HSISR_IND));
957
958         if(pHalData->InterruptLog.nISR_GTINT3_IND)
959                 RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# GTINT3_IND[%ld]\t\n", pHalData->InterruptLog.nISR_GTINT3_IND));
960
961         if(pHalData->InterruptLog.nISR_GTINT4_IND)
962                 RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# GTINT4_IND[%ld]\t\n", pHalData->InterruptLog.nISR_GTINT4_IND));
963
964         if(pHalData->InterruptLog.nISR_PSTIMEOUT)
965                 RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# PSTIMEOUT[%ld]\t\n", pHalData->InterruptLog.nISR_PSTIMEOUT));
966
967         if(pHalData->InterruptLog.nISR_OCPINT)
968                 RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# OCPINT[%ld]\t\n", pHalData->InterruptLog.nISR_OCPINT));
969
970         if(pHalData->InterruptLog.nISR_ATIMEND)
971                 RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# ATIMEND[%ld]\t\n", pHalData->InterruptLog.nISR_ATIMEND));
972
973         if(pHalData->InterruptLog.nISR_ATIMEND_E)
974                 RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# ATIMEND_E[%ld]\t\n", pHalData->InterruptLog.nISR_ATIMEND_E));
975
976         if(pHalData->InterruptLog.nISR_CTWEND)
977                 RT_TRACE(COMP_SEND|COMP_RECV, DebugLevel, ("# CTWEND[%ld]\t\n", pHalData->InterruptLog.nISR_CTWEND));
978 }
979
980 void
981 LogInterruptHistory8723Sdio(
982         PADAPTER                        padapter,
983         PRT_ISR_CONTENT pIsrContent
984 )
985 {
986         HAL_DATA_TYPE   *pHalData=GET_HAL_DATA(padapter);
987
988         if((pHalData->IntrMask[0] & SDIO_HIMR_RX_REQUEST_MSK) &&
989                 (pIsrContent->IntArray[0] & SDIO_HISR_RX_REQUEST))
990                 pHalData->InterruptLog.nISR_RX_REQUEST ++;
991         if((pHalData->IntrMask[0] & SDIO_HIMR_AVAL_MSK) &&
992                 (pIsrContent->IntArray[0] & SDIO_HISR_AVAL))
993                 pHalData->InterruptLog.nISR_AVAL++;
994         if((pHalData->IntrMask[0] & SDIO_HIMR_TXERR_MSK) &&
995                 (pIsrContent->IntArray[0] & SDIO_HISR_TXERR))
996                 pHalData->InterruptLog.nISR_TXERR++;
997         if((pHalData->IntrMask[0] & SDIO_HIMR_RXERR_MSK) &&
998                 (pIsrContent->IntArray[0] & SDIO_HISR_RXERR))
999                 pHalData->InterruptLog.nISR_RXERR++;
1000         if((pHalData->IntrMask[0] & SDIO_HIMR_TXFOVW_MSK) &&
1001                 (pIsrContent->IntArray[0] & SDIO_HISR_TXFOVW))
1002                 pHalData->InterruptLog.nISR_TXFOVW++;
1003         if((pHalData->IntrMask[0] & SDIO_HIMR_RXFOVW_MSK) &&
1004                 (pIsrContent->IntArray[0] & SDIO_HISR_RXFOVW))
1005                 pHalData->InterruptLog.nISR_RXFOVW++;
1006         if((pHalData->IntrMask[0] & SDIO_HIMR_TXBCNOK_MSK) &&
1007                 (pIsrContent->IntArray[0] & SDIO_HISR_TXBCNOK))
1008                 pHalData->InterruptLog.nISR_TXBCNOK++;
1009         if((pHalData->IntrMask[0] & SDIO_HIMR_TXBCNERR_MSK) &&
1010                 (pIsrContent->IntArray[0] & SDIO_HISR_TXBCNERR))
1011                 pHalData->InterruptLog.nISR_TXBCNERR++;
1012         if((pHalData->IntrMask[0] & SDIO_HIMR_BCNERLY_INT_MSK) &&
1013                 (pIsrContent->IntArray[0] & SDIO_HISR_BCNERLY_INT))
1014                 pHalData->InterruptLog.nISR_BCNERLY_INT ++;
1015         if((pHalData->IntrMask[0] & SDIO_HIMR_C2HCMD_MSK) &&
1016                 (pIsrContent->IntArray[0] & SDIO_HISR_C2HCMD))
1017                 pHalData->InterruptLog.nISR_C2HCMD++;
1018         if((pHalData->IntrMask[0] & SDIO_HIMR_CPWM1_MSK) &&
1019                 (pIsrContent->IntArray[0] & SDIO_HISR_CPWM1))
1020                 pHalData->InterruptLog.nISR_CPWM1++;
1021         if((pHalData->IntrMask[0] & SDIO_HIMR_CPWM2_MSK) &&
1022                 (pIsrContent->IntArray[0] & SDIO_HISR_CPWM2))
1023                 pHalData->InterruptLog.nISR_CPWM2++;
1024         if((pHalData->IntrMask[0] & SDIO_HIMR_HSISR_IND_MSK) &&
1025                 (pIsrContent->IntArray[0] & SDIO_HISR_HSISR_IND))
1026                 pHalData->InterruptLog.nISR_HSISR_IND++;
1027         if((pHalData->IntrMask[0] & SDIO_HIMR_GTINT3_IND_MSK) &&
1028                 (pIsrContent->IntArray[0] & SDIO_HISR_GTINT3_IND))
1029                 pHalData->InterruptLog.nISR_GTINT3_IND++;
1030         if((pHalData->IntrMask[0] & SDIO_HIMR_GTINT4_IND_MSK) &&
1031                 (pIsrContent->IntArray[0] & SDIO_HISR_GTINT4_IND))
1032                 pHalData->InterruptLog.nISR_GTINT4_IND++;
1033         if((pHalData->IntrMask[0] & SDIO_HIMR_PSTIMEOUT_MSK) &&
1034                 (pIsrContent->IntArray[0] & SDIO_HISR_PSTIMEOUT))
1035                 pHalData->InterruptLog.nISR_PSTIMEOUT++;
1036         if((pHalData->IntrMask[0] & SDIO_HIMR_OCPINT_MSK) &&
1037                 (pIsrContent->IntArray[0] & SDIO_HISR_OCPINT))
1038                 pHalData->InterruptLog.nISR_OCPINT++;
1039         if((pHalData->IntrMask[0] & SDIO_HIMR_ATIMEND_MSK) &&
1040                 (pIsrContent->IntArray[0] & SDIO_HISR_ATIMEND))
1041                 pHalData->InterruptLog.nISR_ATIMEND++;
1042         if((pHalData->IntrMask[0] & SDIO_HIMR_ATIMEND_E_MSK) &&
1043                 (pIsrContent->IntArray[0] & SDIO_HISR_ATIMEND_E))
1044                 pHalData->InterruptLog.nISR_ATIMEND_E++;
1045         if((pHalData->IntrMask[0] & SDIO_HIMR_CTWEND_MSK) &&
1046                 (pIsrContent->IntArray[0] & SDIO_HISR_CTWEND))
1047                 pHalData->InterruptLog.nISR_CTWEND++;
1048
1049 }
1050
1051 void
1052 DumpHardwareProfile8723Sdio(
1053         IN      PADAPTER                padapter
1054 )
1055 {
1056         DumpLoggedInterruptHistory8723Sdio(padapter);
1057 }
1058 #endif
1059
1060 //
1061 //      Description:
1062 //              Initialize SDIO Host Interrupt Mask configuration variables for future use.
1063 //
1064 //      Assumption:
1065 //              Using SDIO Local register ONLY for configuration.
1066 //
1067 //      Created by Roger, 2011.02.11.
1068 //
1069 void InitInterrupt8723ASdio(PADAPTER padapter)
1070 {
1071         PHAL_DATA_TYPE pHalData;
1072
1073
1074         pHalData = GET_HAL_DATA(padapter);
1075         pHalData->sdio_himr = (u32)(                    \
1076                                                                 SDIO_HIMR_RX_REQUEST_MSK                        |
1077 //                                                              SDIO_HIMR_AVAL_MSK                                      |
1078 //                                                              SDIO_HIMR_TXERR_MSK                             |
1079 //                                                              SDIO_HIMR_RXERR_MSK                             |
1080 //                                                              SDIO_HIMR_TXFOVW_MSK                            |
1081 //                                                              SDIO_HIMR_RXFOVW_MSK                            |
1082 //                                                              SDIO_HIMR_TXBCNOK_MSK                           |
1083 //                                                              SDIO_HIMR_TXBCNERR_MSK                  |
1084 //                                                              SDIO_HIMR_BCNERLY_INT_MSK                       |
1085 #ifndef CONFIG_DETECT_C2H_BY_POLLING
1086 #if defined( CONFIG_BT_COEXIST) || defined(CONFIG_MP_INCLUDED)
1087                                                                 SDIO_HIMR_C2HCMD_MSK                            |
1088 #endif
1089 #endif
1090 #ifndef CONFIG_DETECT_CPWM_BY_POLLING
1091 #ifdef CONFIG_LPS_LCLK
1092                                                                 SDIO_HIMR_CPWM1_MSK                             |
1093 //                                                              SDIO_HIMR_CPWM2_MSK                             |
1094 #endif
1095 #endif
1096 //                                                              SDIO_HIMR_HSISR_IND_MSK                 |
1097 //                                                              SDIO_HIMR_GTINT3_IND_MSK                        |
1098 //                                                              SDIO_HIMR_GTINT4_IND_MSK                        |
1099 //                                                              SDIO_HIMR_PSTIMEOUT_MSK                 |
1100 //                                                              SDIO_HIMR_OCPINT_MSK                            |
1101 //                                                              SDIO_HIMR_ATIMEND_MSK                           |
1102 //                                                              SDIO_HIMR_ATIMEND_E_MSK                 |
1103 //                                                              SDIO_HIMR_CTWEND_MSK                            |
1104                                                                 0);
1105 }
1106
1107 //
1108 //      Description:
1109 //              Initialize System Host Interrupt Mask configuration variables for future use.
1110 //
1111 //      Created by Roger, 2011.08.03.
1112 //
1113 void InitSysInterrupt8723ASdio(PADAPTER padapter)
1114 {
1115         PHAL_DATA_TYPE pHalData;
1116
1117
1118         pHalData = GET_HAL_DATA(padapter);
1119
1120         pHalData->SysIntrMask = (                       \
1121 //                                                      HSIMR_GPIO12_0_INT_EN                   |
1122 //                                                      HSIMR_SPS_OCP_INT_EN                    |
1123 //                                                      HSIMR_RON_INT_EN                                |
1124 //                                                      HSIMR_PDNINT_EN                         |
1125 //                                                      HSIMR_GPIO9_INT_EN                              |
1126                                                         0);
1127 }
1128
1129 //
1130 //      Description:
1131 //              Clear corresponding SDIO Host ISR interrupt service.
1132 //
1133 //      Assumption:
1134 //              Using SDIO Local register ONLY for configuration.
1135 //
1136 //      Created by Roger, 2011.02.11.
1137 //
1138 void ClearInterrupt8723ASdio(PADAPTER padapter)
1139 {
1140         PHAL_DATA_TYPE pHalData;
1141         u8 *clear;
1142
1143
1144         if (_TRUE == padapter->bSurpriseRemoved)
1145                 return;
1146
1147         pHalData = GET_HAL_DATA(padapter);
1148         clear = rtw_zmalloc(4);
1149
1150         // Clear corresponding HISR Content if needed
1151         *(u32*)clear = cpu_to_le32(pHalData->sdio_hisr & MASK_SDIO_HISR_CLEAR);
1152         if (*(u32*)clear)
1153         {
1154                 // Perform write one clear operation
1155                 sdio_local_write(padapter, SDIO_REG_HISR, 4, clear);
1156         }
1157
1158         rtw_mfree(clear, 4);
1159 }
1160
1161 //
1162 //      Description:
1163 //              Clear corresponding system Host ISR interrupt service.
1164 //
1165 //
1166 //      Created by Roger, 2011.02.11.
1167 //
1168 void ClearSysInterrupt8723ASdio(PADAPTER padapter)
1169 {
1170         PHAL_DATA_TYPE pHalData;
1171         u32 clear;
1172
1173
1174         if (_TRUE == padapter->bSurpriseRemoved)
1175                 return;
1176
1177         pHalData = GET_HAL_DATA(padapter);
1178
1179         // Clear corresponding HISR Content if needed
1180         clear = pHalData->SysIntrStatus & MASK_HSISR_CLEAR;
1181         if (clear)
1182         {
1183                 // Perform write one clear operation
1184                 rtw_write32(padapter, REG_HSISR, clear);
1185         }
1186 }
1187
1188 //
1189 //      Description:
1190 //              Enalbe SDIO Host Interrupt Mask configuration on SDIO local domain.
1191 //
1192 //      Assumption:
1193 //              1. Using SDIO Local register ONLY for configuration.
1194 //              2. PASSIVE LEVEL
1195 //
1196 //      Created by Roger, 2011.02.11.
1197 //
1198 void EnableInterrupt8723ASdio(PADAPTER padapter)
1199 {
1200         PHAL_DATA_TYPE pHalData;
1201         u32 himr;
1202
1203 #ifdef CONFIG_CONCURRENT_MODE
1204         if ((padapter->isprimary == _FALSE) && padapter->pbuddy_adapter){
1205                 padapter = padapter->pbuddy_adapter;
1206         }
1207 #endif
1208         pHalData = GET_HAL_DATA(padapter);
1209
1210         himr = cpu_to_le32(pHalData->sdio_himr);
1211         sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8*)&himr);
1212
1213         RT_TRACE(_module_hci_ops_c_, _drv_notice_,
1214                 ("%s: enable SDIO HIMR=0x%08X\n", __FUNCTION__, pHalData->sdio_himr));
1215
1216         // Update current system IMR settings
1217         himr = rtw_read32(padapter, REG_HSIMR);
1218         rtw_write32(padapter, REG_HSIMR, himr|pHalData->SysIntrMask);
1219
1220         RT_TRACE(_module_hci_ops_c_, _drv_notice_,
1221                 ("%s: enable HSIMR=0x%08X\n", __FUNCTION__, pHalData->SysIntrMask));
1222
1223         //
1224         // <Roger_Notes> There are some C2H CMDs have been sent before system interrupt is enabled, e.g., C2H, CPWM.
1225         // So we need to clear all C2H events that FW has notified, otherwise FW won't schedule any commands anymore.
1226         // 2011.10.19.
1227         //
1228         rtw_write8(padapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
1229 }
1230
1231 //
1232 //      Description:
1233 //              Disable SDIO Host IMR configuration to mask unnecessary interrupt service.
1234 //
1235 //      Assumption:
1236 //              Using SDIO Local register ONLY for configuration.
1237 //
1238 //      Created by Roger, 2011.02.11.
1239 //
1240 void DisableInterrupt8723ASdio(PADAPTER padapter)
1241 {
1242         u32 himr;
1243
1244 #ifdef CONFIG_CONCURRENT_MODE
1245         if ((padapter->isprimary == _FALSE) && padapter->pbuddy_adapter){
1246                 padapter = padapter->pbuddy_adapter;
1247         }
1248 #endif
1249         himr = cpu_to_le32(SDIO_HIMR_DISABLED);
1250         sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8*)&himr);
1251
1252 }
1253
1254 //
1255 //      Description:
1256 //              Update SDIO Host Interrupt Mask configuration on SDIO local domain.
1257 //
1258 //      Assumption:
1259 //              1. Using SDIO Local register ONLY for configuration.
1260 //              2. PASSIVE LEVEL
1261 //
1262 //      Created by Roger, 2011.02.11.
1263 //
1264 void UpdateInterruptMask8723ASdio(PADAPTER padapter, u32 AddMSR, u32 RemoveMSR)
1265 {
1266         HAL_DATA_TYPE *pHalData;
1267
1268 #ifdef CONFIG_CONCURRENT_MODE
1269         if ((padapter->isprimary == _FALSE) && padapter->pbuddy_adapter){
1270                 padapter = padapter->pbuddy_adapter;
1271         }
1272 #endif
1273         pHalData = GET_HAL_DATA(padapter);
1274
1275         if (AddMSR)
1276                 pHalData->sdio_himr |= AddMSR;
1277
1278         if (RemoveMSR)
1279                 pHalData->sdio_himr &= (~RemoveMSR);
1280
1281         DisableInterrupt8723ASdio(padapter);
1282         EnableInterrupt8723ASdio(padapter);
1283 }
1284
1285 #ifdef CONFIG_MAC_LOOPBACK_DRIVER
1286 static void sd_recv_loopback(PADAPTER padapter, u32 size)
1287 {
1288         PLOOPBACKDATA ploopback;
1289         u32 readsize, allocsize;
1290         u8 *preadbuf;
1291
1292
1293         readsize = size;
1294         DBG_8192C("%s: read size=%d\n", __func__, readsize);
1295         allocsize = _RND(readsize, adapter_to_dvobj(padapter)->intf_data.block_transfer_len);
1296
1297         ploopback = padapter->ploopback;
1298         if (ploopback) {
1299                 ploopback->rxsize = readsize;
1300                 preadbuf = ploopback->rxbuf;
1301         }
1302         else {
1303                 preadbuf = rtw_malloc(allocsize);
1304                 if (preadbuf == NULL) {
1305                         DBG_8192C("%s: malloc fail size=%d\n", __func__, allocsize);
1306                         return;
1307                 }
1308         }
1309
1310 //      rtw_read_port(padapter, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
1311         sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
1312
1313         if (ploopback)
1314                 _rtw_up_sema(&ploopback->sema);
1315         else {
1316                 u32 i;
1317
1318                 DBG_8192C("%s: drop pkt\n", __func__);
1319                 for (i = 0; i < readsize; i+=4) {
1320                         DBG_8192C("%08X", *(u32*)(preadbuf + i));
1321                         if ((i+4) & 0x1F) printk(" ");
1322                         else printk("\n");
1323                 }
1324                 printk("\n");
1325                 rtw_mfree(preadbuf, allocsize);
1326         }
1327 }
1328 #endif // CONFIG_MAC_LOOPBACK_DRIVER
1329
1330 #ifdef CONFIG_SDIO_RX_COPY
1331 static struct recv_buf* sd_recv_rxfifo(PADAPTER padapter, u32 size)
1332 {
1333         u32 readsize, ret;
1334         u8 *preadbuf;
1335         struct recv_priv *precvpriv;
1336         struct recv_buf *precvbuf;
1337
1338
1339         readsize = size;
1340
1341         //3 1. alloc recvbuf
1342         precvpriv = &padapter->recvpriv;
1343         precvbuf = rtw_dequeue_recvbuf(&precvpriv->free_recv_buf_queue);
1344         if (precvbuf == NULL) {
1345                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: alloc recvbuf FAIL!\n", __FUNCTION__));
1346                 return NULL;
1347         }
1348
1349         //3 2. alloc skb
1350         if (precvbuf->pskb == NULL) {
1351                 SIZE_PTR tmpaddr=0;
1352                 SIZE_PTR alignment=0;
1353
1354                 precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
1355
1356                 if(precvbuf->pskb)
1357                 {
1358                         precvbuf->pskb->dev = padapter->pnetdev;
1359
1360                         tmpaddr = (SIZE_PTR)precvbuf->pskb->data;
1361                         alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
1362                         skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
1363                 }
1364
1365                 if (precvbuf->pskb == NULL) {
1366                         DBG_871X("%s: alloc_skb fail! read=%d\n", __FUNCTION__, readsize);
1367                         return NULL;
1368                 }
1369         }
1370
1371         //3 3. read data from rxfifo
1372         preadbuf = precvbuf->pskb->data;
1373 //      rtw_read_port(padapter, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
1374         ret = sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
1375         if (ret == _FAIL) {
1376                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: read port FAIL!\n", __FUNCTION__));
1377                 return NULL;
1378         }
1379         
1380
1381         //3 4. init recvbuf
1382         precvbuf->len = readsize;
1383         precvbuf->phead = precvbuf->pskb->head;
1384         precvbuf->pdata = precvbuf->pskb->data;
1385         skb_set_tail_pointer(precvbuf->pskb, readsize);
1386         precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
1387         precvbuf->pend = skb_end_pointer(precvbuf->pskb);
1388
1389         return precvbuf;
1390 }
1391 #else
1392 static struct recv_buf* sd_recv_rxfifo(PADAPTER padapter, u32 size)
1393 {
1394         u32 readsize, allocsize, ret;
1395         u8 *preadbuf;
1396         _pkt *ppkt;
1397         struct recv_priv *precvpriv;
1398         struct recv_buf *precvbuf;
1399
1400
1401         readsize = size;
1402
1403         //3 1. alloc skb
1404         // align to block size
1405         allocsize = _RND(readsize, adapter_to_dvobj(padapter)->intf_data.block_transfer_len);
1406
1407         ppkt = rtw_skb_alloc(allocsize);
1408
1409         if (ppkt == NULL) {
1410                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: alloc_skb fail! alloc=%d read=%d\n", __FUNCTION__, allocsize, readsize));
1411                 return NULL;
1412         }
1413
1414         //3 2. read data from rxfifo
1415         preadbuf = skb_put(ppkt, readsize);
1416 //      rtw_read_port(padapter, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
1417         ret = sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
1418         if (ret == _FAIL) {
1419                 rtw_skb_free(ppkt);
1420                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: read port FAIL!\n", __FUNCTION__));
1421                 return NULL;
1422         }
1423
1424         //3 3. alloc recvbuf
1425         precvpriv = &padapter->recvpriv;
1426         precvbuf = rtw_dequeue_recvbuf(&precvpriv->free_recv_buf_queue);
1427         if (precvbuf == NULL) {
1428                 rtw_skb_free(ppkt);
1429                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: alloc recvbuf FAIL!\n", __FUNCTION__));
1430                 return NULL;
1431         }
1432
1433         //3 4. init recvbuf
1434         precvbuf->pskb = ppkt;
1435
1436         precvbuf->len = ppkt->len;
1437
1438         precvbuf->phead = ppkt->head;
1439         precvbuf->pdata = ppkt->data;
1440         precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
1441         precvbuf->pend = skb_end_pointer(precvbuf->pskb);
1442
1443         return precvbuf;
1444 }
1445 #endif
1446
1447 static void sd_rxhandler(PADAPTER padapter, struct recv_buf *precvbuf)
1448 {
1449 #ifdef CONFIG_DIRECT_RECV
1450         rtl8723as_recv(padapter, precvbuf);
1451 #else //!CONFIG_DIRECT_RECV
1452         struct recv_priv *precvpriv;
1453         _queue *ppending_queue;
1454
1455
1456         precvpriv = &padapter->recvpriv;
1457         ppending_queue = &precvpriv->recv_buf_pending_queue;
1458
1459         //3 1. enqueue recvbuf
1460         rtw_enqueue_recvbuf(precvbuf, ppending_queue);
1461
1462         //3 2. schedule tasklet
1463 #ifdef PLATFORM_LINUX
1464         tasklet_schedule(&precvpriv->recv_tasklet);
1465 #endif
1466 #endif //!CONFIG_DIRECT_RECV
1467
1468 }
1469
1470 void sd_int_dpc(PADAPTER padapter)
1471 {
1472         HAL_DATA_TYPE *phal;
1473
1474         struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1475         struct intf_hdl * pintfhdl=&padapter->iopriv.intf;
1476         phal = GET_HAL_DATA(padapter);
1477
1478         if (phal->sdio_hisr & SDIO_HISR_CPWM1)
1479         {
1480                 struct reportpwrstate_parm report;
1481
1482 #ifdef CONFIG_LPS_RPWM_TIMER
1483                 u8 bcancelled;
1484                 _cancel_timer(&(adapter_to_pwrctl(padapter)->pwr_rpwm_timer), &bcancelled);
1485 #endif // CONFIG_LPS_RPWM_TIMER
1486
1487                 _sdio_local_read(padapter, SDIO_REG_HCPWM1, 1, &report.state);
1488
1489 #ifdef CONFIG_LPS_LCLK
1490                 //cpwm_int_hdl(padapter, &report);
1491                 _set_workitem(&(adapter_to_pwrctl(padapter)->cpwm_event));
1492 #endif
1493         }
1494
1495         if (phal->sdio_hisr & SDIO_HISR_TXERR)
1496         {
1497                 u8 *status;
1498                 u32 addr;
1499
1500                 status = rtw_malloc(4);
1501                 if (status)
1502                 {
1503                         addr = REG_TXDMA_STATUS;
1504                         HalSdioGetCmdAddr8723ASdio(padapter, WLAN_IOREG_DEVICE_ID, addr, &addr);
1505                         _sd_read(pintfhdl, addr, 4, status);
1506                         _sd_write(pintfhdl, addr, 4, status);
1507                         DBG_8192C("%s: SDIO_HISR_TXERR (0x%08x)\n", __func__, le32_to_cpu(*(u32*)status));
1508                         rtw_mfree(status, 4);
1509                 } else {
1510                         DBG_8192C("%s: SDIO_HISR_TXERR, but can't allocate memory to read status!\n", __func__);
1511                 }
1512         }
1513
1514         if (phal->sdio_hisr & SDIO_HISR_TXBCNOK)
1515         {
1516                 DBG_8192C("%s: SDIO_HISR_TXBCNOK\n", __func__);
1517         }
1518
1519         if (phal->sdio_hisr & SDIO_HISR_TXBCNERR)
1520         {
1521                 DBG_8192C("%s: SDIO_HISR_TXBCNERR\n", __func__);
1522         }
1523
1524         if (phal->sdio_hisr & SDIO_HISR_C2HCMD)
1525         {
1526                 struct c2h_evt_hdr *c2h_evt;
1527
1528                 if ((c2h_evt = (struct c2h_evt_hdr *)rtw_zmalloc(16)) != NULL) {
1529                         if (c2h_evt_read(padapter, (u8 *)c2h_evt) == _SUCCESS) {
1530                                 if (c2h_id_filter_ccx_8723a(c2h_evt->id)) {
1531                                         /* Handle CCX report here */
1532                                         rtw_hal_c2h_handler(padapter, c2h_evt);
1533                                         rtw_mfree((u8*)c2h_evt, 16);
1534                                 } else {
1535                                         rtw_c2h_wk_cmd(padapter, (u8 *)c2h_evt);
1536                                 }
1537                         }
1538                         else
1539                         {
1540                                 rtw_mfree((u8*)c2h_evt, 16);
1541                         }
1542                 } else {
1543                         /* Error handling for malloc fail */
1544                         if (rtw_cbuf_push(padapter->evtpriv.c2h_queue, (void*)NULL) != _SUCCESS)
1545                                 DBG_871X("%s rtw_cbuf_push fail\n", __func__);
1546                         _set_workitem(&padapter->evtpriv.c2h_wk);
1547                 }
1548         }
1549
1550         if (phal->sdio_hisr & SDIO_HISR_RX_REQUEST)
1551         {
1552                 struct recv_buf *precvbuf;
1553                 u16 val=0;
1554
1555 //              DBG_8192C("%s: RX Request, size=%d\n", __func__, phal->SdioRxFIFOSize);
1556                 phal->sdio_hisr ^= SDIO_HISR_RX_REQUEST;
1557                 do{
1558                         if (phal->SdioRxFIFOSize == 0)
1559                         {
1560                                 _sdio_local_read(padapter, SDIO_REG_RX0_REQ_LEN, 2, (u8*)&val);
1561                                 phal->SdioRxFIFOSize = le16_to_cpu(val);
1562                                 DBG_8192C("%s: RX_REQUEST, read RXFIFOsize again size=%d\n", __func__, phal->SdioRxFIFOSize);
1563                         }
1564
1565                         if (phal->SdioRxFIFOSize != 0)
1566                         {
1567 #ifdef CONFIG_MAC_LOOPBACK_DRIVER
1568                                 sd_recv_loopback(padapter, phal->SdioRxFIFOSize);
1569 #else
1570                                 precvbuf = sd_recv_rxfifo(padapter, phal->SdioRxFIFOSize);
1571                                 if (precvbuf)
1572                                         sd_rxhandler(padapter, precvbuf);
1573                                 else
1574                                         break;
1575 #endif
1576                         }
1577                         _sdio_local_read(padapter, SDIO_REG_RX0_REQ_LEN, 2, (u8*)&val);
1578                         phal->SdioRxFIFOSize = le16_to_cpu(val);
1579                 }while(phal->SdioRxFIFOSize !=0);
1580         }
1581 }
1582
1583 void sd_int_hdl(PADAPTER padapter)
1584 {
1585         u8 data[6];
1586         HAL_DATA_TYPE *phal;
1587
1588
1589         if ((padapter->bDriverStopped == _TRUE) ||
1590             (padapter->bSurpriseRemoved == _TRUE))
1591                 return;
1592
1593         phal = GET_HAL_DATA(padapter);
1594
1595         _sdio_local_read(padapter, SDIO_REG_HISR, 6, data);
1596         phal->sdio_hisr = le32_to_cpu(*(u32*)data);
1597         phal->SdioRxFIFOSize = le16_to_cpu(*(u16*)&data[4]);
1598
1599         if (phal->sdio_hisr & phal->sdio_himr)
1600         {
1601                 u32 v32;
1602
1603                 phal->sdio_hisr &= phal->sdio_himr;
1604
1605                 // clear HISR
1606                 v32 = phal->sdio_hisr & MASK_SDIO_HISR_CLEAR;
1607                 if (v32) {
1608                         v32 = cpu_to_le32(v32);
1609                         _sdio_local_write(padapter, SDIO_REG_HISR, 4, (u8*)&v32);
1610                 }
1611
1612                 sd_int_dpc(padapter);
1613         } else {
1614                 RT_TRACE(_module_hci_ops_c_, _drv_err_,
1615                                 ("%s: HISR(0x%08x) and HIMR(0x%08x) not match!\n",
1616                                 __FUNCTION__, phal->sdio_hisr, phal->sdio_himr));
1617         }
1618 }
1619
1620 //
1621 //      Description:
1622 //              Query SDIO Local register to query current the number of Free TxPacketBuffer page.
1623 //
1624 //      Assumption:
1625 //              1. Running at PASSIVE_LEVEL
1626 //              2. RT_TX_SPINLOCK is NOT acquired.
1627 //
1628 //      Created by Roger, 2011.01.28.
1629 //
1630 u8 HalQueryTxBufferStatus8723ASdio(PADAPTER padapter)
1631 {
1632         PHAL_DATA_TYPE phal;
1633         u32 NumOfFreePage;
1634 //      _irqL irql;
1635
1636
1637         phal = GET_HAL_DATA(padapter);
1638
1639         NumOfFreePage = SdioLocalCmd53Read4Byte(padapter, SDIO_REG_FREE_TXPG);
1640
1641 //      _enter_critical_bh(&phal->SdioTxFIFOFreePageLock, &irql);
1642         _rtw_memcpy(phal->SdioTxFIFOFreePage, &NumOfFreePage, 4);
1643         RT_TRACE(_module_hci_ops_c_, _drv_notice_,
1644                         ("%s: Free page for HIQ(%#x),MIDQ(%#x),LOWQ(%#x),PUBQ(%#x)\n",
1645                         __FUNCTION__,
1646                         phal->SdioTxFIFOFreePage[HI_QUEUE_IDX],
1647                         phal->SdioTxFIFOFreePage[MID_QUEUE_IDX],
1648                         phal->SdioTxFIFOFreePage[LOW_QUEUE_IDX],
1649                         phal->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]));
1650 //      _exit_critical_bh(&phal->SdioTxFIFOFreePageLock, &irql);
1651
1652         return _TRUE;
1653 }
1654