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