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

source code of linux/drivers/staging/rtl8723bs/hal/sdio_ops.c