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