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