diff options
Diffstat (limited to 'drivers/mfd/rtsx_pcr.c')
| -rw-r--r-- | drivers/mfd/rtsx_pcr.c | 132 |
1 files changed, 41 insertions, 91 deletions
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index c9de3d598ea5..1d15735f9ef9 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c | |||
| @@ -338,28 +338,58 @@ int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist, | |||
| 338 | int num_sg, bool read, int timeout) | 338 | int num_sg, bool read, int timeout) |
| 339 | { | 339 | { |
| 340 | struct completion trans_done; | 340 | struct completion trans_done; |
| 341 | int err = 0, count; | 341 | u8 dir; |
| 342 | int err = 0, i, count; | ||
| 342 | long timeleft; | 343 | long timeleft; |
| 343 | unsigned long flags; | 344 | unsigned long flags; |
| 345 | struct scatterlist *sg; | ||
| 346 | enum dma_data_direction dma_dir; | ||
| 347 | u32 val; | ||
| 348 | dma_addr_t addr; | ||
| 349 | unsigned int len; | ||
| 350 | |||
| 351 | dev_dbg(&(pcr->pci->dev), "--> %s: num_sg = %d\n", __func__, num_sg); | ||
| 352 | |||
| 353 | /* don't transfer data during abort processing */ | ||
| 354 | if (pcr->remove_pci) | ||
| 355 | return -EINVAL; | ||
| 356 | |||
| 357 | if ((sglist == NULL) || (num_sg <= 0)) | ||
| 358 | return -EINVAL; | ||
| 344 | 359 | ||
| 345 | count = rtsx_pci_dma_map_sg(pcr, sglist, num_sg, read); | 360 | if (read) { |
| 361 | dir = DEVICE_TO_HOST; | ||
| 362 | dma_dir = DMA_FROM_DEVICE; | ||
| 363 | } else { | ||
| 364 | dir = HOST_TO_DEVICE; | ||
| 365 | dma_dir = DMA_TO_DEVICE; | ||
| 366 | } | ||
| 367 | |||
| 368 | count = dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir); | ||
| 346 | if (count < 1) { | 369 | if (count < 1) { |
| 347 | dev_err(&(pcr->pci->dev), "scatterlist map failed\n"); | 370 | dev_err(&(pcr->pci->dev), "scatterlist map failed\n"); |
| 348 | return -EINVAL; | 371 | return -EINVAL; |
| 349 | } | 372 | } |
| 350 | dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count); | 373 | dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count); |
| 351 | 374 | ||
| 375 | val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE; | ||
| 376 | pcr->sgi = 0; | ||
| 377 | for_each_sg(sglist, sg, count, i) { | ||
| 378 | addr = sg_dma_address(sg); | ||
| 379 | len = sg_dma_len(sg); | ||
| 380 | rtsx_pci_add_sg_tbl(pcr, addr, len, i == count - 1); | ||
| 381 | } | ||
| 352 | 382 | ||
| 353 | spin_lock_irqsave(&pcr->lock, flags); | 383 | spin_lock_irqsave(&pcr->lock, flags); |
| 354 | 384 | ||
| 355 | pcr->done = &trans_done; | 385 | pcr->done = &trans_done; |
| 356 | pcr->trans_result = TRANS_NOT_READY; | 386 | pcr->trans_result = TRANS_NOT_READY; |
| 357 | init_completion(&trans_done); | 387 | init_completion(&trans_done); |
| 388 | rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr); | ||
| 389 | rtsx_pci_writel(pcr, RTSX_HDBCTLR, val); | ||
| 358 | 390 | ||
| 359 | spin_unlock_irqrestore(&pcr->lock, flags); | 391 | spin_unlock_irqrestore(&pcr->lock, flags); |
| 360 | 392 | ||
| 361 | rtsx_pci_dma_transfer(pcr, sglist, count, read); | ||
| 362 | |||
| 363 | timeleft = wait_for_completion_interruptible_timeout( | 393 | timeleft = wait_for_completion_interruptible_timeout( |
| 364 | &trans_done, msecs_to_jiffies(timeout)); | 394 | &trans_done, msecs_to_jiffies(timeout)); |
| 365 | if (timeleft <= 0) { | 395 | if (timeleft <= 0) { |
| @@ -383,7 +413,7 @@ out: | |||
| 383 | pcr->done = NULL; | 413 | pcr->done = NULL; |
| 384 | spin_unlock_irqrestore(&pcr->lock, flags); | 414 | spin_unlock_irqrestore(&pcr->lock, flags); |
| 385 | 415 | ||
| 386 | rtsx_pci_dma_unmap_sg(pcr, sglist, num_sg, read); | 416 | dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir); |
| 387 | 417 | ||
| 388 | if ((err < 0) && (err != -ENODEV)) | 418 | if ((err < 0) && (err != -ENODEV)) |
| 389 | rtsx_pci_stop_cmd(pcr); | 419 | rtsx_pci_stop_cmd(pcr); |
| @@ -395,73 +425,6 @@ out: | |||
| 395 | } | 425 | } |
| 396 | EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data); | 426 | EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data); |
| 397 | 427 | ||
| 398 | int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist, | ||
| 399 | int num_sg, bool read) | ||
| 400 | { | ||
| 401 | enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | ||
| 402 | |||
| 403 | if (pcr->remove_pci) | ||
| 404 | return -EINVAL; | ||
| 405 | |||
| 406 | if ((sglist == NULL) || num_sg < 1) | ||
| 407 | return -EINVAL; | ||
| 408 | |||
| 409 | return dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dir); | ||
| 410 | } | ||
| 411 | EXPORT_SYMBOL_GPL(rtsx_pci_dma_map_sg); | ||
| 412 | |||
| 413 | int rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist, | ||
| 414 | int num_sg, bool read) | ||
| 415 | { | ||
| 416 | enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | ||
| 417 | |||
| 418 | if (pcr->remove_pci) | ||
| 419 | return -EINVAL; | ||
| 420 | |||
| 421 | if (sglist == NULL || num_sg < 1) | ||
| 422 | return -EINVAL; | ||
| 423 | |||
| 424 | dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dir); | ||
| 425 | return num_sg; | ||
| 426 | } | ||
| 427 | EXPORT_SYMBOL_GPL(rtsx_pci_dma_unmap_sg); | ||
| 428 | |||
| 429 | int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist, | ||
| 430 | int sg_count, bool read) | ||
| 431 | { | ||
| 432 | struct scatterlist *sg; | ||
| 433 | dma_addr_t addr; | ||
| 434 | unsigned int len; | ||
| 435 | int i; | ||
| 436 | u32 val; | ||
| 437 | u8 dir = read ? DEVICE_TO_HOST : HOST_TO_DEVICE; | ||
| 438 | unsigned long flags; | ||
| 439 | |||
| 440 | if (pcr->remove_pci) | ||
| 441 | return -EINVAL; | ||
| 442 | |||
| 443 | if ((sglist == NULL) || (sg_count < 1)) | ||
| 444 | return -EINVAL; | ||
| 445 | |||
| 446 | val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE; | ||
| 447 | pcr->sgi = 0; | ||
| 448 | for_each_sg(sglist, sg, sg_count, i) { | ||
| 449 | addr = sg_dma_address(sg); | ||
| 450 | len = sg_dma_len(sg); | ||
| 451 | rtsx_pci_add_sg_tbl(pcr, addr, len, i == sg_count - 1); | ||
| 452 | } | ||
| 453 | |||
| 454 | spin_lock_irqsave(&pcr->lock, flags); | ||
| 455 | |||
| 456 | rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr); | ||
| 457 | rtsx_pci_writel(pcr, RTSX_HDBCTLR, val); | ||
| 458 | |||
| 459 | spin_unlock_irqrestore(&pcr->lock, flags); | ||
| 460 | |||
| 461 | return 0; | ||
| 462 | } | ||
| 463 | EXPORT_SYMBOL_GPL(rtsx_pci_dma_transfer); | ||
| 464 | |||
| 465 | int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len) | 428 | int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len) |
| 466 | { | 429 | { |
| 467 | int err; | 430 | int err; |
| @@ -873,8 +836,6 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id) | |||
| 873 | int_reg = rtsx_pci_readl(pcr, RTSX_BIPR); | 836 | int_reg = rtsx_pci_readl(pcr, RTSX_BIPR); |
| 874 | /* Clear interrupt flag */ | 837 | /* Clear interrupt flag */ |
| 875 | rtsx_pci_writel(pcr, RTSX_BIPR, int_reg); | 838 | rtsx_pci_writel(pcr, RTSX_BIPR, int_reg); |
| 876 | dev_dbg(&pcr->pci->dev, "=========== BIPR 0x%8x ==========\n", int_reg); | ||
| 877 | |||
| 878 | if ((int_reg & pcr->bier) == 0) { | 839 | if ((int_reg & pcr->bier) == 0) { |
| 879 | spin_unlock(&pcr->lock); | 840 | spin_unlock(&pcr->lock); |
| 880 | return IRQ_NONE; | 841 | return IRQ_NONE; |
| @@ -905,28 +866,17 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id) | |||
| 905 | } | 866 | } |
| 906 | 867 | ||
| 907 | if (int_reg & (NEED_COMPLETE_INT | DELINK_INT)) { | 868 | if (int_reg & (NEED_COMPLETE_INT | DELINK_INT)) { |
| 908 | if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) | 869 | if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) { |
| 909 | pcr->trans_result = TRANS_RESULT_FAIL; | 870 | pcr->trans_result = TRANS_RESULT_FAIL; |
| 910 | else if (int_reg & TRANS_OK_INT) | 871 | if (pcr->done) |
| 872 | complete(pcr->done); | ||
| 873 | } else if (int_reg & TRANS_OK_INT) { | ||
| 911 | pcr->trans_result = TRANS_RESULT_OK; | 874 | pcr->trans_result = TRANS_RESULT_OK; |
| 912 | 875 | if (pcr->done) | |
| 913 | if (pcr->done) | 876 | complete(pcr->done); |
| 914 | complete(pcr->done); | ||
| 915 | |||
| 916 | if (int_reg & SD_EXIST) { | ||
| 917 | struct rtsx_slot *slot = &pcr->slots[RTSX_SD_CARD]; | ||
| 918 | if (slot && slot->done_transfer) | ||
| 919 | slot->done_transfer(slot->p_dev); | ||
| 920 | } | ||
| 921 | |||
| 922 | if (int_reg & MS_EXIST) { | ||
| 923 | struct rtsx_slot *slot = &pcr->slots[RTSX_SD_CARD]; | ||
| 924 | if (slot && slot->done_transfer) | ||
| 925 | slot->done_transfer(slot->p_dev); | ||
| 926 | } | 877 | } |
| 927 | } | 878 | } |
| 928 | 879 | ||
| 929 | |||
| 930 | if (pcr->card_inserted || pcr->card_removed) | 880 | if (pcr->card_inserted || pcr->card_removed) |
| 931 | schedule_delayed_work(&pcr->carddet_work, | 881 | schedule_delayed_work(&pcr->carddet_work, |
| 932 | msecs_to_jiffies(200)); | 882 | msecs_to_jiffies(200)); |
