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