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