OSDN Git Service

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