1 // SPDX-License-Identifier: GPL-2.0 2 /****************************************************************************** 3 * 4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. 5 * 6 *******************************************************************************/ 7 #define _SDIO_OPS_C_ 8 9 #include <drv_types.h> 10 #include <rtw_debug.h> 11 #include <rtl8723b_hal.h> 12 13 /* define SDIO_DEBUG_IO 1 */ 14 15 16 /* */ 17 /* Description: */ 18 /* The following mapping is for SDIO host local register space. */ 19 /* */ 20 /* Creadted by Roger, 2011.01.31. */ 21 /* */ 22 static void HalSdioGetCmdAddr8723BSdio( 23 struct adapter *adapter, 24 u8 device_id, 25 u32 addr, 26 u32 *cmdaddr 27 ) 28 { 29 switch (device_id) { 30 case SDIO_LOCAL_DEVICE_ID: 31 *cmdaddr = ((SDIO_LOCAL_DEVICE_ID << 13) | (addr & SDIO_LOCAL_MSK)); 32 break; 33 34 case WLAN_IOREG_DEVICE_ID: 35 *cmdaddr = ((WLAN_IOREG_DEVICE_ID << 13) | (addr & WLAN_IOREG_MSK)); 36 break; 37 38 case WLAN_TX_HIQ_DEVICE_ID: 39 *cmdaddr = ((WLAN_TX_HIQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK)); 40 break; 41 42 case WLAN_TX_MIQ_DEVICE_ID: 43 *cmdaddr = ((WLAN_TX_MIQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK)); 44 break; 45 46 case WLAN_TX_LOQ_DEVICE_ID: 47 *cmdaddr = ((WLAN_TX_LOQ_DEVICE_ID << 13) | (addr & WLAN_FIFO_MSK)); 48 break; 49 50 case WLAN_RX0FF_DEVICE_ID: 51 *cmdaddr = ((WLAN_RX0FF_DEVICE_ID << 13) | (addr & WLAN_RX0FF_MSK)); 52 break; 53 54 default: 55 break; 56 } 57 } 58 59 static u8 get_deviceid(u32 addr) 60 { 61 u8 devide_id; 62 u16 pseudo_id; 63 64 65 pseudo_id = (u16)(addr >> 16); 66 switch (pseudo_id) { 67 case 0x1025: 68 devide_id = SDIO_LOCAL_DEVICE_ID; 69 break; 70 71 case 0x1026: 72 devide_id = WLAN_IOREG_DEVICE_ID; 73 break; 74 75 /* case 0x1027: */ 76 /* devide_id = SDIO_FIRMWARE_FIFO; */ 77 /* break; */ 78 79 case 0x1031: 80 devide_id = WLAN_TX_HIQ_DEVICE_ID; 81 break; 82 83 case 0x1032: 84 devide_id = WLAN_TX_MIQ_DEVICE_ID; 85 break; 86 87 case 0x1033: 88 devide_id = WLAN_TX_LOQ_DEVICE_ID; 89 break; 90 91 case 0x1034: 92 devide_id = WLAN_RX0FF_DEVICE_ID; 93 break; 94 95 default: 96 /* devide_id = (u8)((addr >> 13) & 0xF); */ 97 devide_id = WLAN_IOREG_DEVICE_ID; 98 break; 99 } 100 101 return devide_id; 102 } 103 104 /* 105 * Ref: 106 *HalSdioGetCmdAddr8723BSdio() 107 */ 108 static u32 _cvrt2ftaddr(const u32 addr, u8 *pdevice_id, u16 *poffset) 109 { 110 u8 device_id; 111 u16 offset; 112 u32 ftaddr; 113 114 115 device_id = get_deviceid(addr); 116 offset = 0; 117 118 switch (device_id) { 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: 135 device_id = WLAN_IOREG_DEVICE_ID; 136 offset = addr & WLAN_IOREG_MSK; 137 break; 138 } 139 ftaddr = (device_id << 13) | offset; 140 141 if (pdevice_id) 142 *pdevice_id = device_id; 143 if (poffset) 144 *poffset = offset; 145 146 return ftaddr; 147 } 148 149 static u8 sdio_read8(struct intf_hdl *intfhdl, u32 addr) 150 { 151 u32 ftaddr; 152 ftaddr = _cvrt2ftaddr(addr, NULL, NULL); 153 154 return sd_read8(intfhdl, ftaddr, NULL); 155 } 156 157 static u16 sdio_read16(struct intf_hdl *intfhdl, u32 addr) 158 { 159 u32 ftaddr; 160 __le16 le_tmp; 161 162 ftaddr = _cvrt2ftaddr(addr, NULL, NULL); 163 sd_cmd52_read(intfhdl, ftaddr, 2, (u8 *)&le_tmp); 164 165 return le16_to_cpu(le_tmp); 166 } 167 168 static u32 sdio_read32(struct intf_hdl *intfhdl, u32 addr) 169 { 170 struct adapter *adapter; 171 u8 mac_pwr_ctrl_on; 172 u8 device_id; 173 u16 offset; 174 u32 ftaddr; 175 u8 shift; 176 u32 val; 177 s32 err; 178 __le32 le_tmp; 179 180 adapter = intfhdl->padapter; 181 ftaddr = _cvrt2ftaddr(addr, &device_id, &offset); 182 183 rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on); 184 if ( 185 ((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) || 186 (!mac_pwr_ctrl_on) || 187 (adapter_to_pwrctl(adapter)->bFwCurrentInPSMode) 188 ) { 189 err = sd_cmd52_read(intfhdl, ftaddr, 4, (u8 *)&le_tmp); 190 #ifdef SDIO_DEBUG_IO 191 if (!err) { 192 #endif 193 return le32_to_cpu(le_tmp); 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) { 205 val = sd_read32(intfhdl, ftaddr, NULL); 206 } else { 207 u8 *tmpbuf; 208 209 tmpbuf = rtw_malloc(8); 210 if (!tmpbuf) { 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; 216 sd_read(intfhdl, ftaddr, 8, tmpbuf); 217 memcpy(&le_tmp, tmpbuf+shift, 4); 218 val = le32_to_cpu(le_tmp); 219 220 kfree(tmpbuf); 221 } 222 return val; 223 } 224 225 static s32 sdio_readN(struct intf_hdl *intfhdl, u32 addr, u32 cnt, u8 *buf) 226 { 227 struct adapter *adapter; 228 u8 mac_pwr_ctrl_on; 229 u8 device_id; 230 u16 offset; 231 u32 ftaddr; 232 u8 shift; 233 s32 err; 234 235 adapter = intfhdl->padapter; 236 err = 0; 237 238 ftaddr = _cvrt2ftaddr(addr, &device_id, &offset); 239 240 rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on); 241 if ( 242 ((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) || 243 (!mac_pwr_ctrl_on) || 244 (adapter_to_pwrctl(adapter)->bFwCurrentInPSMode) 245 ) 246 return sd_cmd52_read(intfhdl, ftaddr, cnt, buf); 247 248 /* 4 bytes alignment */ 249 shift = ftaddr & 0x3; 250 if (shift == 0) { 251 err = sd_read(intfhdl, ftaddr, cnt, buf); 252 } else { 253 u8 *tmpbuf; 254 u32 n; 255 256 ftaddr &= ~(u16)0x3; 257 n = cnt + shift; 258 tmpbuf = rtw_malloc(n); 259 if (!tmpbuf) 260 return -1; 261 262 err = sd_read(intfhdl, ftaddr, n, tmpbuf); 263 if (!err) 264 memcpy(buf, tmpbuf+shift, cnt); 265 kfree(tmpbuf); 266 } 267 return err; 268 } 269 270 static s32 sdio_write8(struct intf_hdl *intfhdl, u32 addr, u8 val) 271 { 272 u32 ftaddr; 273 s32 err; 274 275 ftaddr = _cvrt2ftaddr(addr, NULL, NULL); 276 sd_write8(intfhdl, ftaddr, val, &err); 277 278 return err; 279 } 280 281 static s32 sdio_write16(struct intf_hdl *intfhdl, u32 addr, u16 val) 282 { 283 u32 ftaddr; 284 __le16 le_tmp; 285 286 ftaddr = _cvrt2ftaddr(addr, NULL, NULL); 287 le_tmp = cpu_to_le16(val); 288 return sd_cmd52_write(intfhdl, ftaddr, 2, (u8 *)&le_tmp); 289 } 290 291 static s32 sdio_write32(struct intf_hdl *intfhdl, u32 addr, u32 val) 292 { 293 struct adapter *adapter; 294 u8 mac_pwr_ctrl_on; 295 u8 device_id; 296 u16 offset; 297 u32 ftaddr; 298 u8 shift; 299 s32 err; 300 __le32 le_tmp; 301 302 adapter = intfhdl->padapter; 303 err = 0; 304 305 ftaddr = _cvrt2ftaddr(addr, &device_id, &offset); 306 307 rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on); 308 if ( 309 ((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) || 310 (!mac_pwr_ctrl_on) || 311 (adapter_to_pwrctl(adapter)->bFwCurrentInPSMode) 312 ) { 313 le_tmp = cpu_to_le32(val); 314 315 return sd_cmd52_write(intfhdl, ftaddr, 4, (u8 *)&le_tmp); 316 } 317 318 /* 4 bytes alignment */ 319 shift = ftaddr & 0x3; 320 if (shift == 0) { 321 sd_write32(intfhdl, ftaddr, val, &err); 322 } else { 323 le_tmp = cpu_to_le32(val); 324 err = sd_cmd52_write(intfhdl, ftaddr, 4, (u8 *)&le_tmp); 325 } 326 return err; 327 } 328 329 static s32 sdio_writeN(struct intf_hdl *intfhdl, u32 addr, u32 cnt, u8 *buf) 330 { 331 struct adapter *adapter; 332 u8 mac_pwr_ctrl_on; 333 u8 device_id; 334 u16 offset; 335 u32 ftaddr; 336 u8 shift; 337 s32 err; 338 339 adapter = intfhdl->padapter; 340 err = 0; 341 342 ftaddr = _cvrt2ftaddr(addr, &device_id, &offset); 343 344 rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on); 345 if ( 346 ((device_id == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) || 347 (!mac_pwr_ctrl_on) || 348 (adapter_to_pwrctl(adapter)->bFwCurrentInPSMode) 349 ) 350 return sd_cmd52_write(intfhdl, ftaddr, cnt, buf); 351 352 shift = ftaddr & 0x3; 353 if (shift == 0) { 354 err = sd_write(intfhdl, ftaddr, cnt, buf); 355 } else { 356 u8 *tmpbuf; 357 u32 n; 358 359 ftaddr &= ~(u16)0x3; 360 n = cnt + shift; 361 tmpbuf = rtw_malloc(n); 362 if (!tmpbuf) 363 return -1; 364 err = sd_read(intfhdl, ftaddr, 4, tmpbuf); 365 if (err) { 366 kfree(tmpbuf); 367 return err; 368 } 369 memcpy(tmpbuf+shift, buf, cnt); 370 err = sd_write(intfhdl, ftaddr, n, tmpbuf); 371 kfree(tmpbuf); 372 } 373 return err; 374 } 375 376 static u8 sdio_f0_read8(struct intf_hdl *intfhdl, u32 addr) 377 { 378 return sd_f0_read8(intfhdl, addr, NULL); 379 } 380 381 static void sdio_read_mem( 382 struct intf_hdl *intfhdl, 383 u32 addr, 384 u32 cnt, 385 u8 *rmem 386 ) 387 { 388 s32 err; 389 390 err = sdio_readN(intfhdl, addr, cnt, rmem); 391 /* TODO: Report error is err not zero */ 392 } 393 394 static void sdio_write_mem( 395 struct intf_hdl *intfhdl, 396 u32 addr, 397 u32 cnt, 398 u8 *wmem 399 ) 400 { 401 sdio_writeN(intfhdl, addr, cnt, wmem); 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: 411 *intfhdl a pointer of intf_hdl 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 */ 420 static u32 sdio_read_port( 421 struct intf_hdl *intfhdl, 422 u32 addr, 423 u32 cnt, 424 u8 *mem 425 ) 426 { 427 struct adapter *adapter; 428 PSDIO_DATA psdio; 429 struct hal_com_data *hal; 430 u32 oldcnt; 431 #ifdef SDIO_DYNAMIC_ALLOC_MEM 432 u8 *oldmem; 433 #endif 434 s32 err; 435 436 437 adapter = intfhdl->padapter; 438 psdio = &adapter_to_dvobj(adapter)->intf_data; 439 hal = GET_HAL_DATA(adapter); 440 441 HalSdioGetCmdAddr8723BSdio(adapter, addr, hal->SdioRxFIFOCnt++, &addr); 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 448 err = _sd_read(intfhdl, addr, cnt, mem); 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: 469 *intfhdl a pointer of intf_hdl 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 */ 478 static u32 sdio_write_port( 479 struct intf_hdl *intfhdl, 480 u32 addr, 481 u32 cnt, 482 u8 *mem 483 ) 484 { 485 struct adapter *adapter; 486 PSDIO_DATA psdio; 487 s32 err; 488 struct xmit_buf *xmitbuf = (struct xmit_buf *)mem; 489 490 adapter = intfhdl->padapter; 491 psdio = &adapter_to_dvobj(adapter)->intf_data; 492 493 if (!adapter->hw_init_completed) { 494 DBG_871X("%s [addr = 0x%x cnt =%d] adapter->hw_init_completed == false\n", __func__, addr, cnt); 495 return _FAIL; 496 } 497 498 cnt = _RND4(cnt); 499 HalSdioGetCmdAddr8723BSdio(adapter, addr, cnt >> 2, &addr); 500 501 if (cnt > psdio->block_transfer_len) 502 cnt = _RND(cnt, psdio->block_transfer_len); 503 /* cnt = sdio_align_size(cnt); */ 504 505 err = sd_write(intfhdl, addr, cnt, xmitbuf->pdata); 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 517 void sdio_set_intf_ops(struct adapter *adapter, struct _io_ops *ops) 518 { 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; 533 } 534 535 /* 536 * Todo: align address to 4 bytes. 537 */ 538 static s32 _sdio_local_read( 539 struct adapter *adapter, 540 u32 addr, 541 u32 cnt, 542 u8 *buf 543 ) 544 { 545 struct intf_hdl *intfhdl; 546 u8 mac_pwr_ctrl_on; 547 s32 err; 548 u8 *tmpbuf; 549 u32 n; 550 551 552 intfhdl = &adapter->iopriv.intf; 553 554 HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr); 555 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); 559 560 n = RND4(cnt); 561 tmpbuf = rtw_malloc(n); 562 if (!tmpbuf) 563 return (-1); 564 565 err = _sd_read(intfhdl, addr, n, tmpbuf); 566 if (!err) 567 memcpy(buf, tmpbuf, cnt); 568 569 kfree(tmpbuf); 570 571 return err; 572 } 573 574 /* 575 * Todo: align address to 4 bytes. 576 */ 577 s32 sdio_local_read( 578 struct adapter *adapter, 579 u32 addr, 580 u32 cnt, 581 u8 *buf 582 ) 583 { 584 struct intf_hdl *intfhdl; 585 u8 mac_pwr_ctrl_on; 586 s32 err; 587 u8 *tmpbuf; 588 u32 n; 589 590 intfhdl = &adapter->iopriv.intf; 591 592 HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr); 593 594 rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on); 595 if ( 596 (!mac_pwr_ctrl_on) || 597 (adapter_to_pwrctl(adapter)->bFwCurrentInPSMode) 598 ) 599 return sd_cmd52_read(intfhdl, addr, cnt, buf); 600 601 n = RND4(cnt); 602 tmpbuf = rtw_malloc(n); 603 if (!tmpbuf) 604 return (-1); 605 606 err = sd_read(intfhdl, addr, n, tmpbuf); 607 if (!err) 608 memcpy(buf, tmpbuf, cnt); 609 610 kfree(tmpbuf); 611 612 return err; 613 } 614 615 /* 616 * Todo: align address to 4 bytes. 617 */ 618 s32 sdio_local_write( 619 struct adapter *adapter, 620 u32 addr, 621 u32 cnt, 622 u8 *buf 623 ) 624 { 625 struct intf_hdl *intfhdl; 626 u8 mac_pwr_ctrl_on; 627 s32 err; 628 u8 *tmpbuf; 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 636 intfhdl = &adapter->iopriv.intf; 637 638 HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr); 639 640 rtw_hal_get_hwreg(adapter, HW_VAR_APFM_ON_MAC, &mac_pwr_ctrl_on); 641 if ( 642 (!mac_pwr_ctrl_on) || 643 (adapter_to_pwrctl(adapter)->bFwCurrentInPSMode) 644 ) 645 return sd_cmd52_write(intfhdl, addr, cnt, buf); 646 647 tmpbuf = rtw_malloc(cnt); 648 if (!tmpbuf) 649 return (-1); 650 651 memcpy(tmpbuf, buf, cnt); 652 653 err = sd_write(intfhdl, addr, cnt, tmpbuf); 654 655 kfree(tmpbuf); 656 657 return err; 658 } 659 660 u8 SdioLocalCmd52Read1Byte(struct adapter *adapter, u32 addr) 661 { 662 u8 val = 0; 663 struct intf_hdl *intfhdl = &adapter->iopriv.intf; 664 665 HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr); 666 sd_cmd52_read(intfhdl, addr, 1, &val); 667 668 return val; 669 } 670 671 static u16 SdioLocalCmd52Read2Byte(struct adapter *adapter, u32 addr) 672 { 673 __le16 val = 0; 674 struct intf_hdl *intfhdl = &adapter->iopriv.intf; 675 676 HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr); 677 sd_cmd52_read(intfhdl, addr, 2, (u8 *)&val); 678 679 return le16_to_cpu(val); 680 } 681 682 static u32 SdioLocalCmd53Read4Byte(struct adapter *adapter, u32 addr) 683 { 684 685 u8 mac_pwr_ctrl_on; 686 u32 val = 0; 687 struct intf_hdl *intfhdl = &adapter->iopriv.intf; 688 __le32 le_tmp; 689 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); 694 val = le32_to_cpu(le_tmp); 695 } else { 696 val = sd_read32(intfhdl, addr, NULL); 697 } 698 return val; 699 } 700 701 void SdioLocalCmd52Write1Byte(struct adapter *adapter, u32 addr, u8 v) 702 { 703 struct intf_hdl *intfhdl = &adapter->iopriv.intf; 704 705 HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr); 706 sd_cmd52_write(intfhdl, addr, 1, &v); 707 } 708 709 static void SdioLocalCmd52Write4Byte(struct adapter *adapter, u32 addr, u32 v) 710 { 711 struct intf_hdl *intfhdl = &adapter->iopriv.intf; 712 __le32 le_tmp; 713 714 HalSdioGetCmdAddr8723BSdio(adapter, SDIO_LOCAL_DEVICE_ID, addr, &addr); 715 le_tmp = cpu_to_le32(v); 716 sd_cmd52_write(intfhdl, addr, 4, (u8 *)&le_tmp); 717 } 718 719 static s32 ReadInterrupt8723BSdio(struct adapter *adapter, u32 *phisr) 720 { 721 u32 hisr, himr; 722 u8 val8, hisr_len; 723 724 725 if (!phisr) 726 return false; 727 728 himr = GET_HAL_DATA(adapter)->sdio_himr; 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--; 740 val8 = SdioLocalCmd52Read1Byte(adapter, SDIO_REG_HISR+hisr_len); 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 /* */ 758 void InitInterrupt8723BSdio(struct adapter *adapter) 759 { 760 struct hal_com_data *haldata; 761 762 763 haldata = GET_HAL_DATA(adapter); 764 haldata->sdio_himr = (u32)( \ 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 /* */ 792 void InitSysInterrupt8723BSdio(struct adapter *adapter) 793 { 794 struct hal_com_data *haldata; 795 796 797 haldata = GET_HAL_DATA(adapter); 798 799 haldata->SysIntrMask = ( \ 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 /* */ 818 void clearinterrupt8723bsdio(struct adapter *adapter) 819 { 820 struct hal_com_data *haldata; 821 u8 *clear; 822 823 if (adapter->bSurpriseRemoved) 824 return; 825 826 haldata = GET_HAL_DATA(adapter); 827 clear = rtw_zmalloc(4); 828 829 /* Clear corresponding HISR Content if needed */ 830 *(__le32 *)clear = cpu_to_le32(haldata->sdio_hisr & MASK_SDIO_HISR_CLEAR); 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 /* */ 850 void EnableInterrupt8723BSdio(struct adapter *adapter) 851 { 852 struct hal_com_data *haldata; 853 __le32 himr; 854 u32 tmp; 855 856 haldata = GET_HAL_DATA(adapter); 857 858 himr = cpu_to_le32(haldata->sdio_himr); 859 sdio_local_write(adapter, SDIO_REG_HIMR, 4, (u8 *)&himr); 860 861 RT_TRACE( 862 _module_hci_ops_c_, 863 _drv_notice_, 864 ( 865 "%s: enable SDIO HIMR = 0x%08X\n", 866 __func__, 867 haldata->sdio_himr 868 ) 869 ); 870 871 /* Update current system IMR settings */ 872 tmp = rtw_read32(adapter, REG_HSIMR); 873 rtw_write32(adapter, REG_HSIMR, tmp | haldata->SysIntrMask); 874 875 RT_TRACE( 876 _module_hci_ops_c_, 877 _drv_notice_, 878 ( 879 "%s: enable HSIMR = 0x%08X\n", 880 __func__, 881 haldata->SysIntrMask 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 /* */ 890 rtw_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE); 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 /* */ 902 void DisableInterrupt8723BSdio(struct adapter *adapter) 903 { 904 __le32 himr; 905 906 himr = cpu_to_le32(SDIO_HIMR_DISABLED); 907 sdio_local_write(adapter, SDIO_REG_HIMR, 4, (u8 *)&himr); 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 /* */ 919 u8 CheckIPSStatus(struct adapter *adapter) 920 { 921 DBG_871X( 922 "%s(): Read 0x100 = 0x%02x 0x86 = 0x%02x\n", 923 __func__, 924 rtw_read8(adapter, 0x100), 925 rtw_read8(adapter, 0x86) 926 ); 927 928 if (rtw_read8(adapter, 0x100) == 0xEA) 929 return true; 930 else 931 return false; 932 } 933 934 static struct recv_buf *sd_recv_rxfifo(struct adapter *adapter, u32 size) 935 { 936 u32 readsize, ret; 937 u8 *readbuf; 938 struct recv_priv *recv_priv; 939 struct recv_buf *recvbuf; 940 941 942 /* Patch for some SDIO Host 4 bytes issue */ 943 /* ex. RK3188 */ 944 readsize = RND4(size); 945 946 /* 3 1. alloc recvbuf */ 947 recv_priv = &adapter->recvpriv; 948 recvbuf = rtw_dequeue_recvbuf(&recv_priv->free_recv_buf_queue); 949 if (!recvbuf) { 950 DBG_871X_LEVEL(_drv_err_, "%s: alloc recvbuf FAIL!\n", __func__); 951 return NULL; 952 } 953 954 /* 3 2. alloc skb */ 955 if (!recvbuf->pskb) { 956 SIZE_PTR tmpaddr = 0; 957 SIZE_PTR alignment = 0; 958 959 recvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ); 960 961 if (recvbuf->pskb) { 962 recvbuf->pskb->dev = adapter->pnetdev; 963 964 tmpaddr = (SIZE_PTR)recvbuf->pskb->data; 965 alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1); 966 skb_reserve(recvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment)); 967 } 968 969 if (!recvbuf->pskb) { 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 */ 976 readbuf = recvbuf->pskb->data; 977 ret = sdio_read_port(&adapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, readbuf); 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 */ 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; 993 } 994 995 static void sd_rxhandler(struct adapter *adapter, struct recv_buf *recvbuf) 996 { 997 struct recv_priv *recv_priv; 998 struct __queue *pending_queue; 999 1000 recv_priv = &adapter->recvpriv; 1001 pending_queue = &recv_priv->recv_buf_pending_queue; 1002 1003 /* 3 1. enqueue recvbuf */ 1004 rtw_enqueue_recvbuf(recvbuf, pending_queue); 1005 1006 /* 3 2. schedule tasklet */ 1007 tasklet_schedule(&recv_priv->recv_tasklet); 1008 } 1009 1010 void sd_int_dpc(struct adapter *adapter) 1011 { 1012 struct hal_com_data *hal; 1013 struct dvobj_priv *dvobj; 1014 struct intf_hdl *intfhdl = &adapter->iopriv.intf; 1015 struct pwrctrl_priv *pwrctl; 1016 1017 1018 hal = GET_HAL_DATA(adapter); 1019 dvobj = adapter_to_dvobj(adapter); 1020 pwrctl = dvobj_to_pwrctl(dvobj); 1021 1022 if (hal->sdio_hisr & SDIO_HISR_AVAL) { 1023 u8 freepage[4]; 1024 1025 _sdio_local_read(adapter, SDIO_REG_FREE_TXPG, 4, freepage); 1026 up(&(adapter->xmitpriv.xmit_sema)); 1027 } 1028 1029 if (hal->sdio_hisr & SDIO_HISR_CPWM1) { 1030 struct reportpwrstate_parm report; 1031 1032 u8 bcancelled; 1033 _cancel_timer(&(pwrctl->pwr_rpwm_timer), &bcancelled); 1034 1035 report.state = SdioLocalCmd52Read1Byte(adapter, SDIO_REG_HCPWM1_8723B); 1036 1037 /* cpwm_int_hdl(adapter, &report); */ 1038 _set_workitem(&(pwrctl->cpwm_event)); 1039 } 1040 1041 if (hal->sdio_hisr & SDIO_HISR_TXERR) { 1042 u8 *status; 1043 u32 addr; 1044 1045 status = rtw_malloc(4); 1046 if (status) { 1047 addr = REG_TXDMA_STATUS; 1048 HalSdioGetCmdAddr8723BSdio(adapter, WLAN_IOREG_DEVICE_ID, addr, &addr); 1049 _sd_read(intfhdl, addr, 4, status); 1050 _sd_write(intfhdl, addr, 4, status); 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 1058 if (hal->sdio_hisr & SDIO_HISR_TXBCNOK) { 1059 DBG_8192C("%s: SDIO_HISR_TXBCNOK\n", __func__); 1060 } 1061 1062 if (hal->sdio_hisr & SDIO_HISR_TXBCNERR) { 1063 DBG_8192C("%s: SDIO_HISR_TXBCNERR\n", __func__); 1064 } 1065 #ifndef CONFIG_C2H_PACKET_EN 1066 if (hal->sdio_hisr & SDIO_HISR_C2HCMD) { 1067 struct c2h_evt_hdr_88xx *c2h_evt; 1068 1069 DBG_8192C("%s: C2H Command\n", __func__); 1070 c2h_evt = rtw_zmalloc(16); 1071 if (c2h_evt != NULL) { 1072 if (rtw_hal_c2h_evt_read(adapter, (u8 *)c2h_evt) == _SUCCESS) { 1073 if (c2h_id_filter_ccx_8723b((u8 *)c2h_evt)) { 1074 /* Handle CCX report here */ 1075 rtw_hal_c2h_handler(adapter, (u8 *)c2h_evt); 1076 kfree((u8 *)c2h_evt); 1077 } else { 1078 rtw_c2h_wk_cmd(adapter, (u8 *)c2h_evt); 1079 } 1080 } 1081 } else { 1082 /* Error handling for malloc fail */ 1083 if (rtw_cbuf_push(adapter->evtpriv.c2h_queue, NULL) != _SUCCESS) 1084 DBG_871X("%s rtw_cbuf_push fail\n", __func__); 1085 _set_workitem(&adapter->evtpriv.c2h_wk); 1086 } 1087 } 1088 #endif 1089 1090 if (hal->sdio_hisr & SDIO_HISR_RXFOVW) { 1091 DBG_8192C("%s: Rx Overflow\n", __func__); 1092 } 1093 1094 if (hal->sdio_hisr & SDIO_HISR_RXERR) { 1095 DBG_8192C("%s: Rx Error\n", __func__); 1096 } 1097 1098 if (hal->sdio_hisr & SDIO_HISR_RX_REQUEST) { 1099 struct recv_buf *recvbuf; 1100 int alloc_fail_time = 0; 1101 u32 hisr; 1102 1103 /* DBG_8192C("%s: RX Request, size =%d\n", __func__, hal->SdioRxFIFOSize); */ 1104 hal->sdio_hisr ^= SDIO_HISR_RX_REQUEST; 1105 do { 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); 1111 else { 1112 alloc_fail_time++; 1113 DBG_871X("recvbuf is Null for %d times because alloc memory failed\n", alloc_fail_time); 1114 if (alloc_fail_time >= 10) 1115 break; 1116 } 1117 hal->SdioRxFIFOSize = 0; 1118 } else 1119 break; 1120 1121 hisr = 0; 1122 ReadInterrupt8723BSdio(adapter, &hisr); 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 1134 void sd_int_hdl(struct adapter *adapter) 1135 { 1136 struct hal_com_data *hal; 1137 1138 1139 if ( 1140 (adapter->bDriverStopped) || (adapter->bSurpriseRemoved) 1141 ) 1142 return; 1143 1144 hal = GET_HAL_DATA(adapter); 1145 1146 hal->sdio_hisr = 0; 1147 ReadInterrupt8723BSdio(adapter, &hal->sdio_hisr); 1148 1149 if (hal->sdio_hisr & hal->sdio_himr) { 1150 u32 v32; 1151 1152 hal->sdio_hisr &= hal->sdio_himr; 1153 1154 /* clear HISR */ 1155 v32 = hal->sdio_hisr & MASK_SDIO_HISR_CLEAR; 1156 if (v32) { 1157 SdioLocalCmd52Write4Byte(adapter, SDIO_REG_HISR, v32); 1158 } 1159 1160 sd_int_dpc(adapter); 1161 } else { 1162 RT_TRACE(_module_hci_ops_c_, _drv_err_, 1163 ("%s: HISR(0x%08x) and HIMR(0x%08x) not match!\n", 1164 __func__, hal->sdio_hisr, hal->sdio_himr)); 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 /* */ 1178 u8 HalQueryTxBufferStatus8723BSdio(struct adapter *adapter) 1179 { 1180 struct hal_com_data *hal; 1181 u32 numof_free_page; 1182 /* _irql irql; */ 1183 1184 1185 hal = GET_HAL_DATA(adapter); 1186 1187 numof_free_page = SdioLocalCmd53Read4Byte(adapter, SDIO_REG_FREE_TXPG); 1188 1189 /* spin_lock_bh(&phal->SdioTxFIFOFreePageLock); */ 1190 memcpy(hal->SdioTxFIFOFreePage, &numof_free_page, 4); 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__, 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); */ 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 /* */ 1207 u8 HalQueryTxOQTBufferStatus8723BSdio(struct adapter *adapter) 1208 { 1209 struct hal_com_data *haldata = GET_HAL_DATA(adapter); 1210 1211 haldata->SdioTxOQTFreeSpace = SdioLocalCmd52Read1Byte(adapter, SDIO_REG_OQT_FREE_PG); 1212 return true; 1213 } 1214 1215 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) 1216 u8 RecvOnePkt(struct adapter *adapter, u32 size) 1217 { 1218 struct recv_buf *recvbuf; 1219 struct dvobj_priv *sddev; 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 1227 if (!adapter) { 1228 DBG_871X(KERN_ERR "%s: adapter is NULL!\n", __func__); 1229 return false; 1230 } 1231 1232 sddev = adapter_to_dvobj(adapter); 1233 psdio_data = &sddev->intf_data; 1234 func = psdio_data->func; 1235 1236 if (size) { 1237 sdio_claim_host(func); 1238 recvbuf = sd_recv_rxfifo(adapter, size); 1239 1240 if (recvbuf) { 1241 /* printk("Completed Recv One Pkt.\n"); */ 1242 sd_rxhandler(adapter, recvbuf); 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 */ 1253