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