diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-09 11:39:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-09 11:39:39 -0400 |
commit | 97e18dc007546fce8e99098480b921a02ebb3037 (patch) | |
tree | f38c022d034e0172e83f6972983577f790f24dac /drivers/mfd | |
parent | 042f7b7cbd1e531278a09c449563165ba1f07673 (diff) | |
parent | c67480173f72e883235dd0ad09d90156c8f87600 (diff) |
Merge tag 'mmc-updates-for-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc
Pull MMC updates from Chris Ball:
"MMC highlights for 3.15:
Core:
- CONFIG_MMC_UNSAFE_RESUME=y is now default behavior
- DT bindings for SDHCI UHS, eMMC HS200, high-speed DDR, at 1.8/1.2V
- Add GPIO descriptor based slot-gpio card detect API
Drivers:
- dw_mmc: Refactor SOCFPGA support as a variant inside dw_mmc-pltfm.c
- mmci: Support HW busy detection on ux500
- omap: Support MMC_ERASE
- omap_hsmmc: Support MMC_PM_KEEP_POWER, MMC_PM_WAKE_SDIO_IRQ, (a)cmd23
- rtsx: Support pre-req/post-req async
- sdhci: Add support for Realtek RTS5250 controllers
- sdhci-acpi: Add support for 80860F16, fix 80860F14/SDIO card detect
- sdhci-msm: Add new driver for Qualcomm SDHCI chipset support
- sdhci-pxav3: Add support for Marvell Armada 380 and 385 SoCs"
* tag 'mmc-updates-for-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (102 commits)
mmc: sdhci-acpi: Intel SDIO has broken card detect
mmc: sdhci-pxav3: add support for the Armada 38x SDHCI controller
mmc: sdhci-msm: Add platform_execute_tuning implementation
mmc: sdhci-msm: Initial support for Qualcomm chipsets
mmc: sdhci-msm: Qualcomm SDHCI binding documentation
sdhci: only reprogram retuning timer when flag is set
mmc: rename ARCH_BCM to ARCH_BCM_MOBILE
mmc: sdhci: Allow for irq being shared
mmc: sdhci-acpi: Add device id 80860F16
mmc: sdhci-acpi: Fix broken card detect for ACPI HID 80860F14
mmc: slot-gpio: Add GPIO descriptor based CD GPIO API
mmc: slot-gpio: Split out CD IRQ request into a separate function
mmc: slot-gpio: Record GPIO descriptors instead of GPIO numbers
Revert "dts: socfpga: Add support for SD/MMC on the SOCFPGA platform"
mmc: sdhci-spear: use generic card detection gpio support
mmc: sdhci-spear: remove support for power gpio
mmc: sdhci-spear: simplify resource handling
mmc: sdhci-spear: fix platform_data usage
mmc: sdhci-spear: fix error handling paths for DT
mmc: sdhci-bcm-kona: fix build errors when built-in
...
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/rtsx_pcr.c | 132 |
1 files changed, 91 insertions, 41 deletions
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index 1d15735f9ef9..c9de3d598ea5 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c | |||
@@ -338,58 +338,28 @@ 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 | u8 dir; | 341 | int err = 0, count; |
342 | int err = 0, i, count; | ||
343 | long timeleft; | 342 | long timeleft; |
344 | unsigned long flags; | 343 | 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; | ||
359 | 344 | ||
360 | if (read) { | 345 | count = rtsx_pci_dma_map_sg(pcr, sglist, num_sg, 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); | ||
369 | if (count < 1) { | 346 | if (count < 1) { |
370 | dev_err(&(pcr->pci->dev), "scatterlist map failed\n"); | 347 | dev_err(&(pcr->pci->dev), "scatterlist map failed\n"); |
371 | return -EINVAL; | 348 | return -EINVAL; |
372 | } | 349 | } |
373 | dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count); | 350 | dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count); |
374 | 351 | ||
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 | } | ||
382 | 352 | ||
383 | spin_lock_irqsave(&pcr->lock, flags); | 353 | spin_lock_irqsave(&pcr->lock, flags); |
384 | 354 | ||
385 | pcr->done = &trans_done; | 355 | pcr->done = &trans_done; |
386 | pcr->trans_result = TRANS_NOT_READY; | 356 | pcr->trans_result = TRANS_NOT_READY; |
387 | init_completion(&trans_done); | 357 | init_completion(&trans_done); |
388 | rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr); | ||
389 | rtsx_pci_writel(pcr, RTSX_HDBCTLR, val); | ||
390 | 358 | ||
391 | spin_unlock_irqrestore(&pcr->lock, flags); | 359 | spin_unlock_irqrestore(&pcr->lock, flags); |
392 | 360 | ||
361 | rtsx_pci_dma_transfer(pcr, sglist, count, read); | ||
362 | |||
393 | timeleft = wait_for_completion_interruptible_timeout( | 363 | timeleft = wait_for_completion_interruptible_timeout( |
394 | &trans_done, msecs_to_jiffies(timeout)); | 364 | &trans_done, msecs_to_jiffies(timeout)); |
395 | if (timeleft <= 0) { | 365 | if (timeleft <= 0) { |
@@ -413,7 +383,7 @@ out: | |||
413 | pcr->done = NULL; | 383 | pcr->done = NULL; |
414 | spin_unlock_irqrestore(&pcr->lock, flags); | 384 | spin_unlock_irqrestore(&pcr->lock, flags); |
415 | 385 | ||
416 | dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir); | 386 | rtsx_pci_dma_unmap_sg(pcr, sglist, num_sg, read); |
417 | 387 | ||
418 | if ((err < 0) && (err != -ENODEV)) | 388 | if ((err < 0) && (err != -ENODEV)) |
419 | rtsx_pci_stop_cmd(pcr); | 389 | rtsx_pci_stop_cmd(pcr); |
@@ -425,6 +395,73 @@ out: | |||
425 | } | 395 | } |
426 | EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data); | 396 | EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data); |
427 | 397 | ||
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 | |||
428 | int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len) | 465 | int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len) |
429 | { | 466 | { |
430 | int err; | 467 | int err; |
@@ -836,6 +873,8 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id) | |||
836 | int_reg = rtsx_pci_readl(pcr, RTSX_BIPR); | 873 | int_reg = rtsx_pci_readl(pcr, RTSX_BIPR); |
837 | /* Clear interrupt flag */ | 874 | /* Clear interrupt flag */ |
838 | rtsx_pci_writel(pcr, RTSX_BIPR, int_reg); | 875 | rtsx_pci_writel(pcr, RTSX_BIPR, int_reg); |
876 | dev_dbg(&pcr->pci->dev, "=========== BIPR 0x%8x ==========\n", int_reg); | ||
877 | |||
839 | if ((int_reg & pcr->bier) == 0) { | 878 | if ((int_reg & pcr->bier) == 0) { |
840 | spin_unlock(&pcr->lock); | 879 | spin_unlock(&pcr->lock); |
841 | return IRQ_NONE; | 880 | return IRQ_NONE; |
@@ -866,17 +905,28 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id) | |||
866 | } | 905 | } |
867 | 906 | ||
868 | if (int_reg & (NEED_COMPLETE_INT | DELINK_INT)) { | 907 | if (int_reg & (NEED_COMPLETE_INT | DELINK_INT)) { |
869 | if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) { | 908 | if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) |
870 | pcr->trans_result = TRANS_RESULT_FAIL; | 909 | pcr->trans_result = TRANS_RESULT_FAIL; |
871 | if (pcr->done) | 910 | else if (int_reg & TRANS_OK_INT) |
872 | complete(pcr->done); | ||
873 | } else if (int_reg & TRANS_OK_INT) { | ||
874 | pcr->trans_result = TRANS_RESULT_OK; | 911 | pcr->trans_result = TRANS_RESULT_OK; |
875 | if (pcr->done) | 912 | |
876 | complete(pcr->done); | 913 | if (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); | ||
877 | } | 926 | } |
878 | } | 927 | } |
879 | 928 | ||
929 | |||
880 | if (pcr->card_inserted || pcr->card_removed) | 930 | if (pcr->card_inserted || pcr->card_removed) |
881 | schedule_delayed_work(&pcr->carddet_work, | 931 | schedule_delayed_work(&pcr->carddet_work, |
882 | msecs_to_jiffies(200)); | 932 | msecs_to_jiffies(200)); |