linux/drivers/staging/rtl8723bs/os_dep/sdio_ops_linux.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_LINUX_C_
   8
   9#include <drv_types.h>
  10#include <rtw_debug.h>
  11
  12static bool rtw_sdio_claim_host_needed(struct sdio_func *func)
  13{
  14        struct dvobj_priv *dvobj = sdio_get_drvdata(func);
  15        struct sdio_data *sdio_data = &dvobj->intf_data;
  16
  17        if (sdio_data->sys_sdio_irq_thd && sdio_data->sys_sdio_irq_thd == current)
  18                return false;
  19        return true;
  20}
  21
  22inline void rtw_sdio_set_irq_thd(struct dvobj_priv *dvobj, void *thd_hdl)
  23{
  24        struct sdio_data *sdio_data = &dvobj->intf_data;
  25
  26        sdio_data->sys_sdio_irq_thd = thd_hdl;
  27}
  28
  29u8 sd_f0_read8(struct intf_hdl *pintfhdl, u32 addr, s32 *err)
  30{
  31        struct adapter *padapter;
  32        struct dvobj_priv *psdiodev;
  33        struct sdio_data *psdio;
  34
  35        u8 v = 0;
  36        struct sdio_func *func;
  37        bool claim_needed;
  38
  39        padapter = pintfhdl->padapter;
  40        psdiodev = pintfhdl->pintf_dev;
  41        psdio = &psdiodev->intf_data;
  42
  43        if (padapter->bSurpriseRemoved) {
  44                /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
  45                return v;
  46        }
  47
  48        func = psdio->func;
  49        claim_needed = rtw_sdio_claim_host_needed(func);
  50
  51        if (claim_needed)
  52                sdio_claim_host(func);
  53        v = sdio_f0_readb(func, addr, err);
  54        if (claim_needed)
  55                sdio_release_host(func);
  56        if (err && *err)
  57                DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x\n", __func__, *err, addr);
  58        return v;
  59}
  60
  61/*
  62 * Return:
  63 *0             Success
  64 *others        Fail
  65 */
  66s32 _sd_cmd52_read(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pdata)
  67{
  68        struct adapter *padapter;
  69        struct dvobj_priv *psdiodev;
  70        struct sdio_data *psdio;
  71
  72        int err = 0, i;
  73        struct sdio_func *func;
  74
  75        padapter = pintfhdl->padapter;
  76        psdiodev = pintfhdl->pintf_dev;
  77        psdio = &psdiodev->intf_data;
  78
  79        if (padapter->bSurpriseRemoved) {
  80                /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
  81                return err;
  82        }
  83
  84        func = psdio->func;
  85
  86        for (i = 0; i < cnt; i++) {
  87                pdata[i] = sdio_readb(func, addr+i, &err);
  88                if (err) {
  89                        DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x\n", __func__, err, addr+i);
  90                        break;
  91                }
  92        }
  93        return err;
  94}
  95
  96/*
  97 * Return:
  98 *0             Success
  99 *others        Fail
 100 */
 101s32 sd_cmd52_read(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pdata)
 102{
 103        struct adapter *padapter;
 104        struct dvobj_priv *psdiodev;
 105        struct sdio_data *psdio;
 106
 107        int err = 0;
 108        struct sdio_func *func;
 109        bool claim_needed;
 110
 111        padapter = pintfhdl->padapter;
 112        psdiodev = pintfhdl->pintf_dev;
 113        psdio = &psdiodev->intf_data;
 114
 115        if (padapter->bSurpriseRemoved) {
 116                /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
 117                return err;
 118        }
 119
 120        func = psdio->func;
 121        claim_needed = rtw_sdio_claim_host_needed(func);
 122
 123        if (claim_needed)
 124                sdio_claim_host(func);
 125        err = _sd_cmd52_read(pintfhdl, addr, cnt, pdata);
 126        if (claim_needed)
 127                sdio_release_host(func);
 128        return err;
 129}
 130
 131/*
 132 * Return:
 133 *0             Success
 134 *others        Fail
 135 */
 136s32 _sd_cmd52_write(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pdata)
 137{
 138        struct adapter *padapter;
 139        struct dvobj_priv *psdiodev;
 140        struct sdio_data *psdio;
 141
 142        int err = 0, i;
 143        struct sdio_func *func;
 144
 145        padapter = pintfhdl->padapter;
 146        psdiodev = pintfhdl->pintf_dev;
 147        psdio = &psdiodev->intf_data;
 148
 149        if (padapter->bSurpriseRemoved) {
 150                /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
 151                return err;
 152        }
 153
 154        func = psdio->func;
 155
 156        for (i = 0; i < cnt; i++) {
 157                sdio_writeb(func, pdata[i], addr+i, &err);
 158                if (err) {
 159                        DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x val = 0x%02x\n", __func__, err, addr+i, pdata[i]);
 160                        break;
 161                }
 162        }
 163        return err;
 164}
 165
 166/*
 167 * Return:
 168 *0             Success
 169 *others        Fail
 170 */
 171s32 sd_cmd52_write(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pdata)
 172{
 173        struct adapter *padapter;
 174        struct dvobj_priv *psdiodev;
 175        struct sdio_data *psdio;
 176
 177        int err = 0;
 178        struct sdio_func *func;
 179        bool claim_needed;
 180
 181        padapter = pintfhdl->padapter;
 182        psdiodev = pintfhdl->pintf_dev;
 183        psdio = &psdiodev->intf_data;
 184
 185        if (padapter->bSurpriseRemoved) {
 186                /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
 187                return err;
 188        }
 189
 190        func = psdio->func;
 191        claim_needed = rtw_sdio_claim_host_needed(func);
 192
 193        if (claim_needed)
 194                sdio_claim_host(func);
 195        err = _sd_cmd52_write(pintfhdl, addr, cnt, pdata);
 196        if (claim_needed)
 197                sdio_release_host(func);
 198        return err;
 199}
 200
 201u8 sd_read8(struct intf_hdl *pintfhdl, u32 addr, s32 *err)
 202{
 203        struct adapter *padapter;
 204        struct dvobj_priv *psdiodev;
 205        struct sdio_data *psdio;
 206
 207        u8 v = 0;
 208        struct sdio_func *func;
 209        bool claim_needed;
 210
 211        padapter = pintfhdl->padapter;
 212        psdiodev = pintfhdl->pintf_dev;
 213        psdio = &psdiodev->intf_data;
 214
 215        if (padapter->bSurpriseRemoved) {
 216                /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
 217                return v;
 218        }
 219
 220        func = psdio->func;
 221        claim_needed = rtw_sdio_claim_host_needed(func);
 222
 223        if (claim_needed)
 224                sdio_claim_host(func);
 225        v = sdio_readb(func, addr, err);
 226        if (claim_needed)
 227                sdio_release_host(func);
 228        if (err && *err)
 229                DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x\n", __func__, *err, addr);
 230        return v;
 231}
 232
 233u32 sd_read32(struct intf_hdl *pintfhdl, u32 addr, s32 *err)
 234{
 235        struct adapter *padapter;
 236        struct dvobj_priv *psdiodev;
 237        struct sdio_data *psdio;
 238        u32 v = 0;
 239        struct sdio_func *func;
 240        bool claim_needed;
 241
 242        padapter = pintfhdl->padapter;
 243        psdiodev = pintfhdl->pintf_dev;
 244        psdio = &psdiodev->intf_data;
 245
 246        if (padapter->bSurpriseRemoved) {
 247                /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
 248                return v;
 249        }
 250
 251        func = psdio->func;
 252        claim_needed = rtw_sdio_claim_host_needed(func);
 253
 254        if (claim_needed)
 255                sdio_claim_host(func);
 256        v = sdio_readl(func, addr, err);
 257        if (claim_needed)
 258                sdio_release_host(func);
 259
 260        if (err && *err) {
 261                int i;
 262
 263                DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x, val = 0x%x\n", __func__, *err, addr, v);
 264
 265                *err = 0;
 266                for (i = 0; i < SD_IO_TRY_CNT; i++) {
 267                        if (claim_needed) sdio_claim_host(func);
 268                        v = sdio_readl(func, addr, err);
 269                        if (claim_needed) sdio_release_host(func);
 270
 271                        if (*err == 0) {
 272                                rtw_reset_continual_io_error(psdiodev);
 273                                break;
 274                        } else {
 275                                DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x, val = 0x%x, try_cnt =%d\n", __func__, *err, addr, v, i);
 276                                if ((-ESHUTDOWN == *err) || (-ENODEV == *err)) {
 277                                        padapter->bSurpriseRemoved = true;
 278                                }
 279
 280                                if (rtw_inc_and_chk_continual_io_error(psdiodev) == true) {
 281                                        padapter->bSurpriseRemoved = true;
 282                                        break;
 283                                }
 284                        }
 285                }
 286
 287                if (i == SD_IO_TRY_CNT)
 288                        DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x, val = 0x%x, try_cnt =%d\n", __func__, *err, addr, v, i);
 289                else
 290                        DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x, val = 0x%x, try_cnt =%d\n", __func__, *err, addr, v, i);
 291
 292        }
 293        return  v;
 294}
 295
 296void sd_write8(struct intf_hdl *pintfhdl, u32 addr, u8 v, s32 *err)
 297{
 298        struct adapter *padapter;
 299        struct dvobj_priv *psdiodev;
 300        struct sdio_data *psdio;
 301        struct sdio_func *func;
 302        bool claim_needed;
 303
 304        padapter = pintfhdl->padapter;
 305        psdiodev = pintfhdl->pintf_dev;
 306        psdio = &psdiodev->intf_data;
 307
 308        if (padapter->bSurpriseRemoved) {
 309                /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
 310                return;
 311        }
 312
 313        func = psdio->func;
 314        claim_needed = rtw_sdio_claim_host_needed(func);
 315
 316        if (claim_needed)
 317                sdio_claim_host(func);
 318        sdio_writeb(func, v, addr, err);
 319        if (claim_needed)
 320                sdio_release_host(func);
 321        if (err && *err)
 322                DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x val = 0x%02x\n", __func__, *err, addr, v);
 323}
 324
 325void sd_write32(struct intf_hdl *pintfhdl, u32 addr, u32 v, s32 *err)
 326{
 327        struct adapter *padapter;
 328        struct dvobj_priv *psdiodev;
 329        struct sdio_data *psdio;
 330        struct sdio_func *func;
 331        bool claim_needed;
 332
 333        padapter = pintfhdl->padapter;
 334        psdiodev = pintfhdl->pintf_dev;
 335        psdio = &psdiodev->intf_data;
 336
 337        if (padapter->bSurpriseRemoved) {
 338                /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
 339                return;
 340        }
 341
 342        func = psdio->func;
 343        claim_needed = rtw_sdio_claim_host_needed(func);
 344
 345        if (claim_needed)
 346                sdio_claim_host(func);
 347        sdio_writel(func, v, addr, err);
 348        if (claim_needed)
 349                sdio_release_host(func);
 350
 351        if (err && *err) {
 352                int i;
 353
 354                DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x val = 0x%08x\n", __func__, *err, addr, v);
 355
 356                *err = 0;
 357                for (i = 0; i < SD_IO_TRY_CNT; i++) {
 358                        if (claim_needed) sdio_claim_host(func);
 359                        sdio_writel(func, v, addr, err);
 360                        if (claim_needed) sdio_release_host(func);
 361                        if (*err == 0) {
 362                                rtw_reset_continual_io_error(psdiodev);
 363                                break;
 364                        } else {
 365                                DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x, val = 0x%x, try_cnt =%d\n", __func__, *err, addr, v, i);
 366                                if ((-ESHUTDOWN == *err) || (-ENODEV == *err)) {
 367                                        padapter->bSurpriseRemoved = true;
 368                                }
 369
 370                                if (rtw_inc_and_chk_continual_io_error(psdiodev) == true) {
 371                                        padapter->bSurpriseRemoved = true;
 372                                        break;
 373                                }
 374                        }
 375                }
 376
 377                if (i == SD_IO_TRY_CNT)
 378                        DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x val = 0x%08x, try_cnt =%d\n", __func__, *err, addr, v, i);
 379                else
 380                        DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x val = 0x%08x, try_cnt =%d\n", __func__, *err, addr, v, i);
 381        }
 382}
 383
 384/*
 385 * Use CMD53 to read data from SDIO device.
 386 * This function MUST be called after sdio_claim_host() or
 387 * in SDIO ISR(host had been claimed).
 388 *
 389 * Parameters:
 390 *psdio pointer of SDIO_DATA
 391 *addr  address to read
 392 *cnt           amount to read
 393 *pdata pointer to put data, this should be a "DMA:able scratch buffer"!
 394 *
 395 * Return:
 396 *0             Success
 397 *others        Fail
 398 */
 399s32 _sd_read(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
 400{
 401        struct adapter *padapter;
 402        struct dvobj_priv *psdiodev;
 403        struct sdio_data *psdio;
 404
 405        int err = -EPERM;
 406        struct sdio_func *func;
 407
 408        padapter = pintfhdl->padapter;
 409        psdiodev = pintfhdl->pintf_dev;
 410        psdio = &psdiodev->intf_data;
 411
 412        if (padapter->bSurpriseRemoved) {
 413                /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
 414                return err;
 415        }
 416
 417        func = psdio->func;
 418
 419        if (unlikely((cnt == 1) || (cnt == 2))) {
 420                int i;
 421                u8 *pbuf = pdata;
 422
 423                for (i = 0; i < cnt; i++) {
 424                        *(pbuf+i) = sdio_readb(func, addr+i, &err);
 425
 426                        if (err) {
 427                                DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x\n", __func__, err, addr);
 428                                break;
 429                        }
 430                }
 431                return err;
 432        }
 433
 434        err = sdio_memcpy_fromio(func, pdata, addr, cnt);
 435        if (err) {
 436                DBG_871X(KERN_ERR "%s: FAIL(%d)! ADDR =%#x Size =%d\n", __func__, err, addr, cnt);
 437        }
 438        return err;
 439}
 440
 441/*
 442 * Use CMD53 to read data from SDIO device.
 443 *
 444 * Parameters:
 445 *psdio pointer of SDIO_DATA
 446 *addr  address to read
 447 *cnt           amount to read
 448 *pdata pointer to put data, this should be a "DMA:able scratch buffer"!
 449 *
 450 * Return:
 451 *0             Success
 452 *others        Fail
 453 */
 454s32 sd_read(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
 455{
 456        struct adapter *padapter;
 457        struct dvobj_priv *psdiodev;
 458        struct sdio_data *psdio;
 459
 460        struct sdio_func *func;
 461        bool claim_needed;
 462        s32 err = -EPERM;
 463
 464        padapter = pintfhdl->padapter;
 465        psdiodev = pintfhdl->pintf_dev;
 466        psdio = &psdiodev->intf_data;
 467
 468        if (padapter->bSurpriseRemoved) {
 469                /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
 470                return err;
 471        }
 472        func = psdio->func;
 473        claim_needed = rtw_sdio_claim_host_needed(func);
 474
 475        if (claim_needed)
 476                sdio_claim_host(func);
 477        err = _sd_read(pintfhdl, addr, cnt, pdata);
 478        if (claim_needed)
 479                sdio_release_host(func);
 480        return err;
 481}
 482
 483/*
 484 * Use CMD53 to write data to SDIO device.
 485 * This function MUST be called after sdio_claim_host() or
 486 * in SDIO ISR(host had been claimed).
 487 *
 488 * Parameters:
 489 *psdio pointer of SDIO_DATA
 490 *addr  address to write
 491 *cnt           amount to write
 492 *pdata data pointer, this should be a "DMA:able scratch buffer"!
 493 *
 494 * Return:
 495 *0             Success
 496 *others        Fail
 497 */
 498s32 _sd_write(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
 499{
 500        struct adapter *padapter;
 501        struct dvobj_priv *psdiodev;
 502        struct sdio_data *psdio;
 503
 504        struct sdio_func *func;
 505        u32 size;
 506        s32 err =  -EPERM;
 507
 508        padapter = pintfhdl->padapter;
 509        psdiodev = pintfhdl->pintf_dev;
 510        psdio = &psdiodev->intf_data;
 511
 512        if (padapter->bSurpriseRemoved) {
 513                /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
 514                return err;
 515        }
 516
 517        func = psdio->func;
 518/*      size = sdio_align_size(func, cnt); */
 519
 520        if (unlikely((cnt == 1) || (cnt == 2))) {
 521                int i;
 522                u8 *pbuf = pdata;
 523
 524                for (i = 0; i < cnt; i++) {
 525                        sdio_writeb(func, *(pbuf+i), addr+i, &err);
 526                        if (err) {
 527                                DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x val = 0x%02x\n", __func__, err, addr, *(pbuf+i));
 528                                break;
 529                        }
 530                }
 531
 532                return err;
 533        }
 534
 535        size = cnt;
 536        err = sdio_memcpy_toio(func, addr, pdata, size);
 537        if (err) {
 538                DBG_871X(KERN_ERR "%s: FAIL(%d)! ADDR =%#x Size =%d(%d)\n", __func__, err, addr, cnt, size);
 539        }
 540        return err;
 541}
 542
 543/*
 544 * Use CMD53 to write data to SDIO device.
 545 *
 546 * Parameters:
 547 *  psdio       pointer of SDIO_DATA
 548 *  addr        address to write
 549 *  cnt         amount to write
 550 *  pdata       data pointer, this should be a "DMA:able scratch buffer"!
 551 *
 552 * Return:
 553 *  0           Success
 554 *  others      Fail
 555 */
 556s32 sd_write(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
 557{
 558        struct adapter *padapter;
 559        struct dvobj_priv *psdiodev;
 560        struct sdio_data *psdio;
 561        struct sdio_func *func;
 562        bool claim_needed;
 563        s32 err =  -EPERM;
 564
 565        padapter = pintfhdl->padapter;
 566        psdiodev = pintfhdl->pintf_dev;
 567        psdio = &psdiodev->intf_data;
 568
 569        if (padapter->bSurpriseRemoved) {
 570                /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
 571                return err;
 572        }
 573
 574        func = psdio->func;
 575        claim_needed = rtw_sdio_claim_host_needed(func);
 576
 577        if (claim_needed)
 578                sdio_claim_host(func);
 579        err = _sd_write(pintfhdl, addr, cnt, pdata);
 580        if (claim_needed)
 581                sdio_release_host(func);
 582        return err;
 583}
 584