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