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