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