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 12 static 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 22 inline 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 29 u8 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 */ 66 s32 _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 */ 101 s32 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 */ 136 s32 _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 */ 171 s32 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 201 u8 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 233 u32 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 { 262 int i; 263 264 DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x, val = 0x%x\n", __func__, *err, addr, v); 265 266 *err = 0; 267 for (i = 0; i < SD_IO_TRY_CNT; i++) 268 { 269 if (claim_needed) sdio_claim_host(func); 270 v = sdio_readl(func, addr, err); 271 if (claim_needed) sdio_release_host(func); 272 273 if (*err == 0) { 274 rtw_reset_continual_io_error(psdiodev); 275 break; 276 } else { 277 DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x, val = 0x%x, try_cnt =%d\n", __func__, *err, addr, v, i); 278 if ((-ESHUTDOWN == *err) || (-ENODEV == *err)) { 279 padapter->bSurpriseRemoved = true; 280 } 281 282 if (rtw_inc_and_chk_continual_io_error(psdiodev) == true) { 283 padapter->bSurpriseRemoved = true; 284 break; 285 } 286 } 287 } 288 289 if (i == SD_IO_TRY_CNT) 290 DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x, val = 0x%x, try_cnt =%d\n", __func__, *err, addr, v, i); 291 else 292 DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x, val = 0x%x, try_cnt =%d\n", __func__, *err, addr, v, i); 293 294 } 295 return v; 296 } 297 298 void sd_write8(struct intf_hdl *pintfhdl, u32 addr, u8 v, s32 *err) 299 { 300 struct adapter *padapter; 301 struct dvobj_priv *psdiodev; 302 struct sdio_data *psdio; 303 struct sdio_func *func; 304 bool claim_needed; 305 306 padapter = pintfhdl->padapter; 307 psdiodev = pintfhdl->pintf_dev; 308 psdio = &psdiodev->intf_data; 309 310 if (padapter->bSurpriseRemoved) { 311 /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */ 312 return; 313 } 314 315 func = psdio->func; 316 claim_needed = rtw_sdio_claim_host_needed(func); 317 318 if (claim_needed) 319 sdio_claim_host(func); 320 sdio_writeb(func, v, addr, err); 321 if (claim_needed) 322 sdio_release_host(func); 323 if (err && *err) 324 DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x val = 0x%02x\n", __func__, *err, addr, v); 325 } 326 327 void sd_write32(struct intf_hdl *pintfhdl, u32 addr, u32 v, s32 *err) 328 { 329 struct adapter *padapter; 330 struct dvobj_priv *psdiodev; 331 struct sdio_data *psdio; 332 struct sdio_func *func; 333 bool claim_needed; 334 335 padapter = pintfhdl->padapter; 336 psdiodev = pintfhdl->pintf_dev; 337 psdio = &psdiodev->intf_data; 338 339 if (padapter->bSurpriseRemoved) { 340 /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */ 341 return; 342 } 343 344 func = psdio->func; 345 claim_needed = rtw_sdio_claim_host_needed(func); 346 347 if (claim_needed) 348 sdio_claim_host(func); 349 sdio_writel(func, v, addr, err); 350 if (claim_needed) 351 sdio_release_host(func); 352 353 if (err && *err) 354 { 355 int i; 356 357 DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x val = 0x%08x\n", __func__, *err, addr, v); 358 359 *err = 0; 360 for (i = 0; i < SD_IO_TRY_CNT; i++) 361 { 362 if (claim_needed) sdio_claim_host(func); 363 sdio_writel(func, v, addr, err); 364 if (claim_needed) sdio_release_host(func); 365 if (*err == 0) { 366 rtw_reset_continual_io_error(psdiodev); 367 break; 368 } else { 369 DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x, val = 0x%x, try_cnt =%d\n", __func__, *err, addr, v, i); 370 if ((-ESHUTDOWN == *err) || (-ENODEV == *err)) { 371 padapter->bSurpriseRemoved = true; 372 } 373 374 if (rtw_inc_and_chk_continual_io_error(psdiodev) == true) { 375 padapter->bSurpriseRemoved = true; 376 break; 377 } 378 } 379 } 380 381 if (i == SD_IO_TRY_CNT) 382 DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x val = 0x%08x, try_cnt =%d\n", __func__, *err, addr, v, i); 383 else 384 DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x val = 0x%08x, try_cnt =%d\n", __func__, *err, addr, v, i); 385 } 386 } 387 388 /* 389 * Use CMD53 to read data from SDIO device. 390 * This function MUST be called after sdio_claim_host() or 391 * in SDIO ISR(host had been claimed). 392 * 393 * Parameters: 394 *psdio pointer of SDIO_DATA 395 *addr address to read 396 *cnt amount to read 397 *pdata pointer to put data, this should be a "DMA:able scratch buffer"! 398 * 399 * Return: 400 *0 Success 401 *others Fail 402 */ 403 s32 _sd_read(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata) 404 { 405 struct adapter *padapter; 406 struct dvobj_priv *psdiodev; 407 struct sdio_data *psdio; 408 409 int err = -EPERM; 410 struct sdio_func *func; 411 412 padapter = pintfhdl->padapter; 413 psdiodev = pintfhdl->pintf_dev; 414 psdio = &psdiodev->intf_data; 415 416 if (padapter->bSurpriseRemoved) { 417 /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */ 418 return err; 419 } 420 421 func = psdio->func; 422 423 if (unlikely((cnt == 1) || (cnt == 2))) 424 { 425 int i; 426 u8 *pbuf = pdata; 427 428 for (i = 0; i < cnt; i++) 429 { 430 *(pbuf+i) = sdio_readb(func, addr+i, &err); 431 432 if (err) { 433 DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x\n", __func__, err, addr); 434 break; 435 } 436 } 437 return err; 438 } 439 440 err = sdio_memcpy_fromio(func, pdata, addr, cnt); 441 if (err) { 442 DBG_871X(KERN_ERR "%s: FAIL(%d)! ADDR =%#x Size =%d\n", __func__, err, addr, cnt); 443 } 444 return err; 445 } 446 447 /* 448 * Use CMD53 to read data from SDIO device. 449 * 450 * Parameters: 451 *psdio pointer of SDIO_DATA 452 *addr address to read 453 *cnt amount to read 454 *pdata pointer to put data, this should be a "DMA:able scratch buffer"! 455 * 456 * Return: 457 *0 Success 458 *others Fail 459 */ 460 s32 sd_read(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata) 461 { 462 struct adapter *padapter; 463 struct dvobj_priv *psdiodev; 464 struct sdio_data *psdio; 465 466 struct sdio_func *func; 467 bool claim_needed; 468 s32 err = -EPERM; 469 470 padapter = pintfhdl->padapter; 471 psdiodev = pintfhdl->pintf_dev; 472 psdio = &psdiodev->intf_data; 473 474 if (padapter->bSurpriseRemoved) { 475 /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */ 476 return err; 477 } 478 func = psdio->func; 479 claim_needed = rtw_sdio_claim_host_needed(func); 480 481 if (claim_needed) 482 sdio_claim_host(func); 483 err = _sd_read(pintfhdl, addr, cnt, pdata); 484 if (claim_needed) 485 sdio_release_host(func); 486 return err; 487 } 488 489 /* 490 * Use CMD53 to write data to SDIO device. 491 * This function MUST be called after sdio_claim_host() or 492 * in SDIO ISR(host had been claimed). 493 * 494 * Parameters: 495 *psdio pointer of SDIO_DATA 496 *addr address to write 497 *cnt amount to write 498 *pdata data pointer, this should be a "DMA:able scratch buffer"! 499 * 500 * Return: 501 *0 Success 502 *others Fail 503 */ 504 s32 _sd_write(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata) 505 { 506 struct adapter *padapter; 507 struct dvobj_priv *psdiodev; 508 struct sdio_data *psdio; 509 510 struct sdio_func *func; 511 u32 size; 512 s32 err = -EPERM; 513 514 padapter = pintfhdl->padapter; 515 psdiodev = pintfhdl->pintf_dev; 516 psdio = &psdiodev->intf_data; 517 518 if (padapter->bSurpriseRemoved) { 519 /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */ 520 return err; 521 } 522 523 func = psdio->func; 524 /* size = sdio_align_size(func, cnt); */ 525 526 if (unlikely((cnt == 1) || (cnt == 2))) 527 { 528 int i; 529 u8 *pbuf = pdata; 530 531 for (i = 0; i < cnt; i++) 532 { 533 sdio_writeb(func, *(pbuf+i), addr+i, &err); 534 if (err) { 535 DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x val = 0x%02x\n", __func__, err, addr, *(pbuf+i)); 536 break; 537 } 538 } 539 540 return err; 541 } 542 543 size = cnt; 544 err = sdio_memcpy_toio(func, addr, pdata, size); 545 if (err) { 546 DBG_871X(KERN_ERR "%s: FAIL(%d)! ADDR =%#x Size =%d(%d)\n", __func__, err, addr, cnt, size); 547 } 548 return err; 549 } 550 551 /* 552 * Use CMD53 to write data to SDIO device. 553 * 554 * Parameters: 555 * psdio pointer of SDIO_DATA 556 * addr address to write 557 * cnt amount to write 558 * pdata data pointer, this should be a "DMA:able scratch buffer"! 559 * 560 * Return: 561 * 0 Success 562 * others Fail 563 */ 564 s32 sd_write(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata) 565 { 566 struct adapter *padapter; 567 struct dvobj_priv *psdiodev; 568 struct sdio_data *psdio; 569 struct sdio_func *func; 570 bool claim_needed; 571 s32 err = -EPERM; 572 573 padapter = pintfhdl->padapter; 574 psdiodev = pintfhdl->pintf_dev; 575 psdio = &psdiodev->intf_data; 576 577 if (padapter->bSurpriseRemoved) { 578 /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */ 579 return err; 580 } 581 582 func = psdio->func; 583 claim_needed = rtw_sdio_claim_host_needed(func); 584 585 if (claim_needed) 586 sdio_claim_host(func); 587 err = _sd_write(pintfhdl, addr, cnt, pdata); 588 if (claim_needed) 589 sdio_release_host(func); 590 return err; 591 } 592