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