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