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