diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-12-28 19:52:18 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-12-28 19:52:18 -0500 |
| commit | 00d59fde8532b2d42e80909d2e58678755e04da9 (patch) | |
| tree | 5383ad260f0d0abc2fb624f8cd528e46a950317c /drivers | |
| parent | 75f95da078b2891cd186f074ffc15a8e7c3f082d (diff) | |
| parent | 5215b2e952f3f94d74cac1a59494eb8ac647e216 (diff) | |
Merge tag 'mmc-v4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
Pull MMC updates from Ulf Hansson:
"This time, this pull request contains changes crossing subsystems and
archs/platforms, which is mainly because of a bigger modernization of
moving from legacy GPIO to GPIO descriptors for MMC (by Linus
Walleij).
Additionally, once again, I am funneling changes to
drivers/misc/cardreader/* and drivers/memstick/* through my MMC tree,
mostly due to that we lack a maintainer for these.
Summary:
MMC core:
- Cleanup BKOPS support
- Introduce MMC_CAP_SYNC_RUNTIME_PM
- slot-gpio: Delete legacy slot GPIO handling
MMC host:
- alcor: Add new mmc host driver for Alcor Micro PCI based cardreader
- bcm2835: Several improvements to better recover from errors
- jz4740: Rework and fixup pre|post_req support
- mediatek: Add support for SDIO IRQs
- meson-gx: Improve clock phase management
- meson-gx: Stop descriptor on errors
- mmci: Complete the sbc error path by sending a stop command
- renesas_sdhi/tmio: Fixup reset/resume operations
- renesas_sdhi: Add support for r8a774c0 and R7S9210
- renesas_sdhi: Whitelist R8A77990 SDHI
- renesas_sdhi: Fixup eMMC HS400 compatibility issues for H3 and M3-W
- rtsx_usb_sdmmc: Re-work card detection/removal support
- rtsx_usb_sdmmc: Re-work runtime PM support
- sdhci: Fix timeout loops for some variant drivers
- sdhci: Improve support for error handling due to failing commands
- sdhci-acpi/pci: Disable LED control for Intel BYT-based controllers
- sdhci_am654: Add new SDHCI variant driver to support TI's AM654 SOCs
- sdhci-of-esdhc: Add support for eMMC HS400 mode
- sdhci-omap: Fixup reset support
- sdhci-omap: Workaround errata regarding SDR104/HS200 tuning failures
- sdhci-msm: Fixup sporadic write transfers issues for SDR104/HS200
- sdhci-msm: Fixup dynamical clock gating issues
- various: Complete converting all hosts into using slot GPIO descriptors
Other:
- Move GPIO mmc platform data for mips/sh/arm to GPIO descriptors
- Add new Alcor Micro cardreader PCI driver
- Support runtime power management for memstick rtsx_usb_ms driver
- Use USB remote wakeups for card detection for rtsx_usb misc driver"
* tag 'mmc-v4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: (99 commits)
mmc: mediatek: Add MMC_CAP_SDIO_IRQ support
mmc: renesas_sdhi_internal_dmac: Whitelist r8a774c0
dt-bindings: mmc: renesas_sdhi: Add r8a774c0 support
mmc: core: Cleanup BKOPS support
mmc: core: Drop redundant check in mmc_send_hpi_cmd()
mmc: sdhci-omap: Workaround errata regarding SDR104/HS200 tuning failures (i929)
dt-bindings: sdhci-omap: Add note for cpu_thermal
mmc: sdhci-acpi: Disable LED control for Intel BYT-based controllers
mmc: sdhci-pci: Disable LED control for Intel BYT-based controllers
mmc: sdhci: Add quirk to disable LED control
mmc: mmci: add variant property to set command stop bit
misc: alcor_pci: fix spelling mistake "invailid" -> "invalid"
mmc: meson-gx: add signal resampling
mmc: meson-gx: align default phase on soc vendor tree
mmc: meson-gx: remove useless lock
mmc: meson-gx: make sure the descriptor is stopped on errors
mmc: sdhci_am654: Add Initial Support for AM654 SDHCI driver
dt-bindings: mmc: sdhci-of-arasan: Add deprecated message for AM65
dt-bindings: mmc: sdhci-am654: Document bindings for the host controllers on TI's AM654 SOCs
mmc: sdhci-msm: avoid unused function warning
...
Diffstat (limited to 'drivers')
54 files changed, 3075 insertions, 858 deletions
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 023a32cfac42..540166443c34 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c | |||
| @@ -449,7 +449,7 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) | |||
| 449 | 449 | ||
| 450 | gc->base = chip->gpio_start; | 450 | gc->base = chip->gpio_start; |
| 451 | gc->ngpio = gpios; | 451 | gc->ngpio = gpios; |
| 452 | gc->label = chip->client->name; | 452 | gc->label = dev_name(&chip->client->dev); |
| 453 | gc->parent = &chip->client->dev; | 453 | gc->parent = &chip->client->dev; |
| 454 | gc->owner = THIS_MODULE; | 454 | gc->owner = THIS_MODULE; |
| 455 | gc->names = chip->names; | 455 | gc->names = chip->names; |
diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c index 76382c858c35..1246d69ba187 100644 --- a/drivers/memstick/core/memstick.c +++ b/drivers/memstick/core/memstick.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
| 19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
| 20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
| 21 | #include <linux/pm_runtime.h> | ||
| 21 | 22 | ||
| 22 | #define DRIVER_NAME "memstick" | 23 | #define DRIVER_NAME "memstick" |
| 23 | 24 | ||
| @@ -436,6 +437,7 @@ static void memstick_check(struct work_struct *work) | |||
| 436 | struct memstick_dev *card; | 437 | struct memstick_dev *card; |
| 437 | 438 | ||
| 438 | dev_dbg(&host->dev, "memstick_check started\n"); | 439 | dev_dbg(&host->dev, "memstick_check started\n"); |
| 440 | pm_runtime_get_noresume(host->dev.parent); | ||
| 439 | mutex_lock(&host->lock); | 441 | mutex_lock(&host->lock); |
| 440 | if (!host->card) { | 442 | if (!host->card) { |
| 441 | if (memstick_power_on(host)) | 443 | if (memstick_power_on(host)) |
| @@ -479,6 +481,7 @@ out_power_off: | |||
| 479 | host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF); | 481 | host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF); |
| 480 | 482 | ||
| 481 | mutex_unlock(&host->lock); | 483 | mutex_unlock(&host->lock); |
| 484 | pm_runtime_put(host->dev.parent); | ||
| 482 | dev_dbg(&host->dev, "memstick_check finished\n"); | 485 | dev_dbg(&host->dev, "memstick_check finished\n"); |
| 483 | } | 486 | } |
| 484 | 487 | ||
diff --git a/drivers/memstick/host/rtsx_usb_ms.c b/drivers/memstick/host/rtsx_usb_ms.c index 4f64563df7de..97308dc28ccf 100644 --- a/drivers/memstick/host/rtsx_usb_ms.c +++ b/drivers/memstick/host/rtsx_usb_ms.c | |||
| @@ -40,15 +40,14 @@ struct rtsx_usb_ms { | |||
| 40 | 40 | ||
| 41 | struct mutex host_mutex; | 41 | struct mutex host_mutex; |
| 42 | struct work_struct handle_req; | 42 | struct work_struct handle_req; |
| 43 | 43 | struct delayed_work poll_card; | |
| 44 | struct task_struct *detect_ms; | ||
| 45 | struct completion detect_ms_exit; | ||
| 46 | 44 | ||
| 47 | u8 ssc_depth; | 45 | u8 ssc_depth; |
| 48 | unsigned int clock; | 46 | unsigned int clock; |
| 49 | int power_mode; | 47 | int power_mode; |
| 50 | unsigned char ifmode; | 48 | unsigned char ifmode; |
| 51 | bool eject; | 49 | bool eject; |
| 50 | bool system_suspending; | ||
| 52 | }; | 51 | }; |
| 53 | 52 | ||
| 54 | static inline struct device *ms_dev(struct rtsx_usb_ms *host) | 53 | static inline struct device *ms_dev(struct rtsx_usb_ms *host) |
| @@ -545,7 +544,7 @@ static void rtsx_usb_ms_handle_req(struct work_struct *work) | |||
| 545 | host->req->error); | 544 | host->req->error); |
| 546 | } | 545 | } |
| 547 | } while (!rc); | 546 | } while (!rc); |
| 548 | pm_runtime_put(ms_dev(host)); | 547 | pm_runtime_put_sync(ms_dev(host)); |
| 549 | } | 548 | } |
| 550 | 549 | ||
| 551 | } | 550 | } |
| @@ -585,14 +584,14 @@ static int rtsx_usb_ms_set_param(struct memstick_host *msh, | |||
| 585 | break; | 584 | break; |
| 586 | 585 | ||
| 587 | if (value == MEMSTICK_POWER_ON) { | 586 | if (value == MEMSTICK_POWER_ON) { |
| 588 | pm_runtime_get_sync(ms_dev(host)); | 587 | pm_runtime_get_noresume(ms_dev(host)); |
| 589 | err = ms_power_on(host); | 588 | err = ms_power_on(host); |
| 589 | if (err) | ||
| 590 | pm_runtime_put_noidle(ms_dev(host)); | ||
| 590 | } else if (value == MEMSTICK_POWER_OFF) { | 591 | } else if (value == MEMSTICK_POWER_OFF) { |
| 591 | err = ms_power_off(host); | 592 | err = ms_power_off(host); |
| 592 | if (host->msh->card) | 593 | if (!err) |
| 593 | pm_runtime_put_noidle(ms_dev(host)); | 594 | pm_runtime_put_noidle(ms_dev(host)); |
| 594 | else | ||
| 595 | pm_runtime_put(ms_dev(host)); | ||
| 596 | } else | 595 | } else |
| 597 | err = -EINVAL; | 596 | err = -EINVAL; |
| 598 | if (!err) | 597 | if (!err) |
| @@ -638,12 +637,16 @@ static int rtsx_usb_ms_set_param(struct memstick_host *msh, | |||
| 638 | } | 637 | } |
| 639 | out: | 638 | out: |
| 640 | mutex_unlock(&ucr->dev_mutex); | 639 | mutex_unlock(&ucr->dev_mutex); |
| 641 | pm_runtime_put(ms_dev(host)); | 640 | pm_runtime_put_sync(ms_dev(host)); |
| 642 | 641 | ||
| 643 | /* power-on delay */ | 642 | /* power-on delay */ |
| 644 | if (param == MEMSTICK_POWER && value == MEMSTICK_POWER_ON) | 643 | if (param == MEMSTICK_POWER && value == MEMSTICK_POWER_ON) { |
| 645 | usleep_range(10000, 12000); | 644 | usleep_range(10000, 12000); |
| 646 | 645 | ||
| 646 | if (!host->eject) | ||
| 647 | schedule_delayed_work(&host->poll_card, 100); | ||
| 648 | } | ||
| 649 | |||
| 647 | dev_dbg(ms_dev(host), "%s: return = %d\n", __func__, err); | 650 | dev_dbg(ms_dev(host), "%s: return = %d\n", __func__, err); |
| 648 | return err; | 651 | return err; |
| 649 | } | 652 | } |
| @@ -654,9 +657,24 @@ static int rtsx_usb_ms_suspend(struct device *dev) | |||
| 654 | struct rtsx_usb_ms *host = dev_get_drvdata(dev); | 657 | struct rtsx_usb_ms *host = dev_get_drvdata(dev); |
| 655 | struct memstick_host *msh = host->msh; | 658 | struct memstick_host *msh = host->msh; |
| 656 | 659 | ||
| 657 | dev_dbg(ms_dev(host), "--> %s\n", __func__); | 660 | /* Since we use rtsx_usb's resume callback to runtime resume its |
| 661 | * children to implement remote wakeup signaling, this causes | ||
| 662 | * rtsx_usb_ms' runtime resume callback runs after its suspend | ||
| 663 | * callback: | ||
| 664 | * rtsx_usb_ms_suspend() | ||
| 665 | * rtsx_usb_resume() | ||
| 666 | * -> rtsx_usb_ms_runtime_resume() | ||
| 667 | * -> memstick_detect_change() | ||
| 668 | * | ||
| 669 | * rtsx_usb_suspend() | ||
| 670 | * | ||
| 671 | * To avoid this, skip runtime resume/suspend if system suspend is | ||
| 672 | * underway. | ||
| 673 | */ | ||
| 658 | 674 | ||
| 675 | host->system_suspending = true; | ||
| 659 | memstick_suspend_host(msh); | 676 | memstick_suspend_host(msh); |
| 677 | |||
| 660 | return 0; | 678 | return 0; |
| 661 | } | 679 | } |
| 662 | 680 | ||
| @@ -665,58 +683,85 @@ static int rtsx_usb_ms_resume(struct device *dev) | |||
| 665 | struct rtsx_usb_ms *host = dev_get_drvdata(dev); | 683 | struct rtsx_usb_ms *host = dev_get_drvdata(dev); |
| 666 | struct memstick_host *msh = host->msh; | 684 | struct memstick_host *msh = host->msh; |
| 667 | 685 | ||
| 668 | dev_dbg(ms_dev(host), "--> %s\n", __func__); | ||
| 669 | |||
| 670 | memstick_resume_host(msh); | 686 | memstick_resume_host(msh); |
| 687 | host->system_suspending = false; | ||
| 688 | |||
| 671 | return 0; | 689 | return 0; |
| 672 | } | 690 | } |
| 673 | #endif /* CONFIG_PM_SLEEP */ | 691 | #endif /* CONFIG_PM_SLEEP */ |
| 674 | 692 | ||
| 675 | /* | 693 | #ifdef CONFIG_PM |
| 676 | * Thread function of ms card slot detection. The thread starts right after | 694 | static int rtsx_usb_ms_runtime_suspend(struct device *dev) |
| 677 | * successful host addition. It stops while the driver removal function sets | ||
| 678 | * host->eject true. | ||
| 679 | */ | ||
| 680 | static int rtsx_usb_detect_ms_card(void *__host) | ||
| 681 | { | 695 | { |
| 682 | struct rtsx_usb_ms *host = (struct rtsx_usb_ms *)__host; | 696 | struct rtsx_usb_ms *host = dev_get_drvdata(dev); |
| 697 | |||
| 698 | if (host->system_suspending) | ||
| 699 | return 0; | ||
| 700 | |||
| 701 | if (host->msh->card || host->power_mode != MEMSTICK_POWER_OFF) | ||
| 702 | return -EAGAIN; | ||
| 703 | |||
| 704 | return 0; | ||
| 705 | } | ||
| 706 | |||
| 707 | static int rtsx_usb_ms_runtime_resume(struct device *dev) | ||
| 708 | { | ||
| 709 | struct rtsx_usb_ms *host = dev_get_drvdata(dev); | ||
| 710 | |||
| 711 | |||
| 712 | if (host->system_suspending) | ||
| 713 | return 0; | ||
| 714 | |||
| 715 | memstick_detect_change(host->msh); | ||
| 716 | |||
| 717 | return 0; | ||
| 718 | } | ||
| 719 | #endif /* CONFIG_PM */ | ||
| 720 | |||
| 721 | static const struct dev_pm_ops rtsx_usb_ms_pm_ops = { | ||
| 722 | SET_SYSTEM_SLEEP_PM_OPS(rtsx_usb_ms_suspend, rtsx_usb_ms_resume) | ||
| 723 | SET_RUNTIME_PM_OPS(rtsx_usb_ms_runtime_suspend, rtsx_usb_ms_runtime_resume, NULL) | ||
| 724 | }; | ||
| 725 | |||
| 726 | |||
| 727 | static void rtsx_usb_ms_poll_card(struct work_struct *work) | ||
| 728 | { | ||
| 729 | struct rtsx_usb_ms *host = container_of(work, struct rtsx_usb_ms, | ||
| 730 | poll_card.work); | ||
| 683 | struct rtsx_ucr *ucr = host->ucr; | 731 | struct rtsx_ucr *ucr = host->ucr; |
| 684 | u8 val = 0; | ||
| 685 | int err; | 732 | int err; |
| 733 | u8 val; | ||
| 686 | 734 | ||
| 687 | for (;;) { | 735 | if (host->eject || host->power_mode != MEMSTICK_POWER_ON) |
| 688 | pm_runtime_get_sync(ms_dev(host)); | 736 | return; |
| 689 | mutex_lock(&ucr->dev_mutex); | ||
| 690 | |||
| 691 | /* Check pending MS card changes */ | ||
| 692 | err = rtsx_usb_read_register(ucr, CARD_INT_PEND, &val); | ||
| 693 | if (err) { | ||
| 694 | mutex_unlock(&ucr->dev_mutex); | ||
| 695 | goto poll_again; | ||
| 696 | } | ||
| 697 | 737 | ||
| 698 | /* Clear the pending */ | 738 | pm_runtime_get_sync(ms_dev(host)); |
| 699 | rtsx_usb_write_register(ucr, CARD_INT_PEND, | 739 | mutex_lock(&ucr->dev_mutex); |
| 700 | XD_INT | MS_INT | SD_INT, | ||
| 701 | XD_INT | MS_INT | SD_INT); | ||
| 702 | 740 | ||
| 741 | /* Check pending MS card changes */ | ||
| 742 | err = rtsx_usb_read_register(ucr, CARD_INT_PEND, &val); | ||
| 743 | if (err) { | ||
| 703 | mutex_unlock(&ucr->dev_mutex); | 744 | mutex_unlock(&ucr->dev_mutex); |
| 745 | goto poll_again; | ||
| 746 | } | ||
| 704 | 747 | ||
| 705 | if (val & MS_INT) { | 748 | /* Clear the pending */ |
| 706 | dev_dbg(ms_dev(host), "MS slot change detected\n"); | 749 | rtsx_usb_write_register(ucr, CARD_INT_PEND, |
| 707 | memstick_detect_change(host->msh); | 750 | XD_INT | MS_INT | SD_INT, |
| 708 | } | 751 | XD_INT | MS_INT | SD_INT); |
| 709 | 752 | ||
| 710 | poll_again: | 753 | mutex_unlock(&ucr->dev_mutex); |
| 711 | pm_runtime_put(ms_dev(host)); | ||
| 712 | if (host->eject) | ||
| 713 | break; | ||
| 714 | 754 | ||
| 715 | schedule_timeout_idle(HZ); | 755 | if (val & MS_INT) { |
| 756 | dev_dbg(ms_dev(host), "MS slot change detected\n"); | ||
| 757 | memstick_detect_change(host->msh); | ||
| 716 | } | 758 | } |
| 717 | 759 | ||
| 718 | complete(&host->detect_ms_exit); | 760 | poll_again: |
| 719 | return 0; | 761 | pm_runtime_put_sync(ms_dev(host)); |
| 762 | |||
| 763 | if (!host->eject && host->power_mode == MEMSTICK_POWER_ON) | ||
| 764 | schedule_delayed_work(&host->poll_card, 100); | ||
| 720 | } | 765 | } |
| 721 | 766 | ||
| 722 | static int rtsx_usb_ms_drv_probe(struct platform_device *pdev) | 767 | static int rtsx_usb_ms_drv_probe(struct platform_device *pdev) |
| @@ -747,45 +792,42 @@ static int rtsx_usb_ms_drv_probe(struct platform_device *pdev) | |||
| 747 | mutex_init(&host->host_mutex); | 792 | mutex_init(&host->host_mutex); |
| 748 | INIT_WORK(&host->handle_req, rtsx_usb_ms_handle_req); | 793 | INIT_WORK(&host->handle_req, rtsx_usb_ms_handle_req); |
| 749 | 794 | ||
| 750 | init_completion(&host->detect_ms_exit); | 795 | INIT_DELAYED_WORK(&host->poll_card, rtsx_usb_ms_poll_card); |
| 751 | host->detect_ms = kthread_create(rtsx_usb_detect_ms_card, host, | ||
| 752 | "rtsx_usb_ms_%d", pdev->id); | ||
| 753 | if (IS_ERR(host->detect_ms)) { | ||
| 754 | dev_dbg(&(pdev->dev), | ||
| 755 | "Unable to create polling thread.\n"); | ||
| 756 | err = PTR_ERR(host->detect_ms); | ||
| 757 | goto err_out; | ||
| 758 | } | ||
| 759 | 796 | ||
| 760 | msh->request = rtsx_usb_ms_request; | 797 | msh->request = rtsx_usb_ms_request; |
| 761 | msh->set_param = rtsx_usb_ms_set_param; | 798 | msh->set_param = rtsx_usb_ms_set_param; |
| 762 | msh->caps = MEMSTICK_CAP_PAR4; | 799 | msh->caps = MEMSTICK_CAP_PAR4; |
| 763 | 800 | ||
| 764 | pm_runtime_enable(&pdev->dev); | 801 | pm_runtime_get_noresume(ms_dev(host)); |
| 802 | pm_runtime_set_active(ms_dev(host)); | ||
| 803 | pm_runtime_enable(ms_dev(host)); | ||
| 804 | |||
| 765 | err = memstick_add_host(msh); | 805 | err = memstick_add_host(msh); |
| 766 | if (err) | 806 | if (err) |
| 767 | goto err_out; | 807 | goto err_out; |
| 768 | 808 | ||
| 769 | wake_up_process(host->detect_ms); | 809 | pm_runtime_put(ms_dev(host)); |
| 810 | |||
| 770 | return 0; | 811 | return 0; |
| 771 | err_out: | 812 | err_out: |
| 772 | memstick_free_host(msh); | 813 | memstick_free_host(msh); |
| 814 | pm_runtime_disable(ms_dev(host)); | ||
| 815 | pm_runtime_put_noidle(ms_dev(host)); | ||
| 773 | return err; | 816 | return err; |
| 774 | } | 817 | } |
| 775 | 818 | ||
| 776 | static int rtsx_usb_ms_drv_remove(struct platform_device *pdev) | 819 | static int rtsx_usb_ms_drv_remove(struct platform_device *pdev) |
| 777 | { | 820 | { |
| 778 | struct rtsx_usb_ms *host = platform_get_drvdata(pdev); | 821 | struct rtsx_usb_ms *host = platform_get_drvdata(pdev); |
| 779 | struct memstick_host *msh; | 822 | struct memstick_host *msh = host->msh; |
| 780 | int err; | 823 | int err; |
| 781 | 824 | ||
| 782 | msh = host->msh; | ||
| 783 | host->eject = true; | 825 | host->eject = true; |
| 784 | cancel_work_sync(&host->handle_req); | 826 | cancel_work_sync(&host->handle_req); |
| 785 | 827 | ||
| 786 | mutex_lock(&host->host_mutex); | 828 | mutex_lock(&host->host_mutex); |
| 787 | if (host->req) { | 829 | if (host->req) { |
| 788 | dev_dbg(&(pdev->dev), | 830 | dev_dbg(ms_dev(host), |
| 789 | "%s: Controller removed during transfer\n", | 831 | "%s: Controller removed during transfer\n", |
| 790 | dev_name(&msh->dev)); | 832 | dev_name(&msh->dev)); |
| 791 | host->req->error = -ENOMEDIUM; | 833 | host->req->error = -ENOMEDIUM; |
| @@ -797,7 +839,6 @@ static int rtsx_usb_ms_drv_remove(struct platform_device *pdev) | |||
| 797 | } | 839 | } |
| 798 | mutex_unlock(&host->host_mutex); | 840 | mutex_unlock(&host->host_mutex); |
| 799 | 841 | ||
| 800 | wait_for_completion(&host->detect_ms_exit); | ||
| 801 | memstick_remove_host(msh); | 842 | memstick_remove_host(msh); |
| 802 | memstick_free_host(msh); | 843 | memstick_free_host(msh); |
| 803 | 844 | ||
| @@ -807,18 +848,15 @@ static int rtsx_usb_ms_drv_remove(struct platform_device *pdev) | |||
| 807 | if (pm_runtime_active(ms_dev(host))) | 848 | if (pm_runtime_active(ms_dev(host))) |
| 808 | pm_runtime_put(ms_dev(host)); | 849 | pm_runtime_put(ms_dev(host)); |
| 809 | 850 | ||
| 810 | pm_runtime_disable(&pdev->dev); | 851 | pm_runtime_disable(ms_dev(host)); |
| 811 | platform_set_drvdata(pdev, NULL); | 852 | platform_set_drvdata(pdev, NULL); |
| 812 | 853 | ||
| 813 | dev_dbg(&(pdev->dev), | 854 | dev_dbg(ms_dev(host), |
| 814 | ": Realtek USB Memstick controller has been removed\n"); | 855 | ": Realtek USB Memstick controller has been removed\n"); |
| 815 | 856 | ||
| 816 | return 0; | 857 | return 0; |
| 817 | } | 858 | } |
| 818 | 859 | ||
| 819 | static SIMPLE_DEV_PM_OPS(rtsx_usb_ms_pm_ops, | ||
| 820 | rtsx_usb_ms_suspend, rtsx_usb_ms_resume); | ||
| 821 | |||
| 822 | static struct platform_device_id rtsx_usb_ms_ids[] = { | 860 | static struct platform_device_id rtsx_usb_ms_ids[] = { |
| 823 | { | 861 | { |
| 824 | .name = "rtsx_usb_ms", | 862 | .name = "rtsx_usb_ms", |
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index af22bbc3d00c..fe3134cf3008 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
| @@ -57,4 +57,4 @@ obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o | |||
| 57 | obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o | 57 | obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o |
| 58 | obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o | 58 | obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o |
| 59 | obj-$(CONFIG_OCXL) += ocxl/ | 59 | obj-$(CONFIG_OCXL) += ocxl/ |
| 60 | obj-$(CONFIG_MISC_RTSX) += cardreader/ | 60 | obj-y += cardreader/ |
diff --git a/drivers/misc/cardreader/Kconfig b/drivers/misc/cardreader/Kconfig index 69e815e32a8c..ed8993b5d058 100644 --- a/drivers/misc/cardreader/Kconfig +++ b/drivers/misc/cardreader/Kconfig | |||
| @@ -1,3 +1,14 @@ | |||
| 1 | config MISC_ALCOR_PCI | ||
| 2 | tristate "Alcor Micro/Alcor Link PCI-E card reader" | ||
| 3 | depends on PCI | ||
| 4 | select MFD_CORE | ||
| 5 | help | ||
| 6 | This supports for Alcor Micro PCI-Express card reader including au6601, | ||
| 7 | au6621. | ||
| 8 | Alcor Micro card readers support access to many types of memory cards, | ||
| 9 | such as Memory Stick, Memory Stick Pro, Secure Digital and | ||
| 10 | MultiMediaCard. | ||
| 11 | |||
| 1 | config MISC_RTSX_PCI | 12 | config MISC_RTSX_PCI |
| 2 | tristate "Realtek PCI-E card reader" | 13 | tristate "Realtek PCI-E card reader" |
| 3 | depends on PCI | 14 | depends on PCI |
diff --git a/drivers/misc/cardreader/Makefile b/drivers/misc/cardreader/Makefile index 9fabfcc6fa7a..9882d2a1025c 100644 --- a/drivers/misc/cardreader/Makefile +++ b/drivers/misc/cardreader/Makefile | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o rts5260.o | 1 | obj-$(CONFIG_MISC_ALCOR_PCI) += alcor_pci.o |
| 2 | |||
| 3 | obj-$(CONFIG_MISC_RTSX_PCI) += rtsx_pci.o | 2 | obj-$(CONFIG_MISC_RTSX_PCI) += rtsx_pci.o |
| 3 | rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o rts5260.o | ||
| 4 | obj-$(CONFIG_MISC_RTSX_USB) += rtsx_usb.o | 4 | obj-$(CONFIG_MISC_RTSX_USB) += rtsx_usb.o |
diff --git a/drivers/misc/cardreader/alcor_pci.c b/drivers/misc/cardreader/alcor_pci.c new file mode 100644 index 000000000000..bcb10fa4bc3a --- /dev/null +++ b/drivers/misc/cardreader/alcor_pci.c | |||
| @@ -0,0 +1,371 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0+ | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2018 Oleksij Rempel <linux@rempel-privat.de> | ||
| 4 | * | ||
| 5 | * Driver for Alcor Micro AU6601 and AU6621 controllers | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/delay.h> | ||
| 9 | #include <linux/interrupt.h> | ||
| 10 | #include <linux/io.h> | ||
| 11 | #include <linux/irq.h> | ||
| 12 | #include <linux/mfd/core.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/pci.h> | ||
| 15 | #include <linux/platform_device.h> | ||
| 16 | #include <linux/pm.h> | ||
| 17 | |||
| 18 | #include <linux/alcor_pci.h> | ||
| 19 | |||
| 20 | #define DRV_NAME_ALCOR_PCI "alcor_pci" | ||
| 21 | |||
| 22 | static DEFINE_IDA(alcor_pci_idr); | ||
| 23 | |||
| 24 | static struct mfd_cell alcor_pci_cells[] = { | ||
| 25 | [ALCOR_SD_CARD] = { | ||
| 26 | .name = DRV_NAME_ALCOR_PCI_SDMMC, | ||
| 27 | }, | ||
| 28 | [ALCOR_MS_CARD] = { | ||
| 29 | .name = DRV_NAME_ALCOR_PCI_MS, | ||
| 30 | }, | ||
| 31 | }; | ||
| 32 | |||
| 33 | static const struct alcor_dev_cfg alcor_cfg = { | ||
| 34 | .dma = 0, | ||
| 35 | }; | ||
| 36 | |||
| 37 | static const struct alcor_dev_cfg au6621_cfg = { | ||
| 38 | .dma = 1, | ||
| 39 | }; | ||
| 40 | |||
| 41 | static const struct pci_device_id pci_ids[] = { | ||
| 42 | { PCI_DEVICE(PCI_ID_ALCOR_MICRO, PCI_ID_AU6601), | ||
| 43 | .driver_data = (kernel_ulong_t)&alcor_cfg }, | ||
| 44 | { PCI_DEVICE(PCI_ID_ALCOR_MICRO, PCI_ID_AU6621), | ||
| 45 | .driver_data = (kernel_ulong_t)&au6621_cfg }, | ||
| 46 | { }, | ||
| 47 | }; | ||
| 48 | MODULE_DEVICE_TABLE(pci, pci_ids); | ||
| 49 | |||
| 50 | void alcor_write8(struct alcor_pci_priv *priv, u8 val, unsigned int addr) | ||
| 51 | { | ||
| 52 | writeb(val, priv->iobase + addr); | ||
| 53 | } | ||
| 54 | EXPORT_SYMBOL_GPL(alcor_write8); | ||
| 55 | |||
| 56 | void alcor_write16(struct alcor_pci_priv *priv, u16 val, unsigned int addr) | ||
| 57 | { | ||
| 58 | writew(val, priv->iobase + addr); | ||
| 59 | } | ||
| 60 | EXPORT_SYMBOL_GPL(alcor_write16); | ||
| 61 | |||
| 62 | void alcor_write32(struct alcor_pci_priv *priv, u32 val, unsigned int addr) | ||
| 63 | { | ||
| 64 | writel(val, priv->iobase + addr); | ||
| 65 | } | ||
| 66 | EXPORT_SYMBOL_GPL(alcor_write32); | ||
| 67 | |||
| 68 | void alcor_write32be(struct alcor_pci_priv *priv, u32 val, unsigned int addr) | ||
| 69 | { | ||
| 70 | iowrite32be(val, priv->iobase + addr); | ||
| 71 | } | ||
| 72 | EXPORT_SYMBOL_GPL(alcor_write32be); | ||
| 73 | |||
| 74 | u8 alcor_read8(struct alcor_pci_priv *priv, unsigned int addr) | ||
| 75 | { | ||
| 76 | return readb(priv->iobase + addr); | ||
| 77 | } | ||
| 78 | EXPORT_SYMBOL_GPL(alcor_read8); | ||
| 79 | |||
| 80 | u32 alcor_read32(struct alcor_pci_priv *priv, unsigned int addr) | ||
| 81 | { | ||
| 82 | return readl(priv->iobase + addr); | ||
| 83 | } | ||
| 84 | EXPORT_SYMBOL_GPL(alcor_read32); | ||
| 85 | |||
| 86 | u32 alcor_read32be(struct alcor_pci_priv *priv, unsigned int addr) | ||
| 87 | { | ||
| 88 | return ioread32be(priv->iobase + addr); | ||
| 89 | } | ||
| 90 | EXPORT_SYMBOL_GPL(alcor_read32be); | ||
| 91 | |||
| 92 | static int alcor_pci_find_cap_offset(struct alcor_pci_priv *priv, | ||
| 93 | struct pci_dev *pci) | ||
| 94 | { | ||
| 95 | int where; | ||
| 96 | u8 val8; | ||
| 97 | u32 val32; | ||
| 98 | |||
| 99 | where = ALCOR_CAP_START_OFFSET; | ||
| 100 | pci_read_config_byte(pci, where, &val8); | ||
| 101 | if (!val8) | ||
| 102 | return 0; | ||
| 103 | |||
| 104 | where = (int)val8; | ||
| 105 | while (1) { | ||
| 106 | pci_read_config_dword(pci, where, &val32); | ||
| 107 | if (val32 == 0xffffffff) { | ||
| 108 | dev_dbg(priv->dev, "find_cap_offset invalid value %x.\n", | ||
| 109 | val32); | ||
| 110 | return 0; | ||
| 111 | } | ||
| 112 | |||
| 113 | if ((val32 & 0xff) == 0x10) { | ||
| 114 | dev_dbg(priv->dev, "pcie cap offset: %x\n", where); | ||
| 115 | return where; | ||
| 116 | } | ||
| 117 | |||
| 118 | if ((val32 & 0xff00) == 0x00) { | ||
| 119 | dev_dbg(priv->dev, "pci_find_cap_offset invalid value %x.\n", | ||
| 120 | val32); | ||
| 121 | break; | ||
| 122 | } | ||
| 123 | where = (int)((val32 >> 8) & 0xff); | ||
| 124 | } | ||
| 125 | |||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | static void alcor_pci_init_check_aspm(struct alcor_pci_priv *priv) | ||
| 130 | { | ||
| 131 | struct pci_dev *pci; | ||
| 132 | int where; | ||
| 133 | u32 val32; | ||
| 134 | |||
| 135 | priv->pdev_cap_off = alcor_pci_find_cap_offset(priv, priv->pdev); | ||
| 136 | priv->parent_cap_off = alcor_pci_find_cap_offset(priv, | ||
| 137 | priv->parent_pdev); | ||
| 138 | |||
| 139 | if ((priv->pdev_cap_off == 0) || (priv->parent_cap_off == 0)) { | ||
| 140 | dev_dbg(priv->dev, "pci_cap_off: %x, parent_cap_off: %x\n", | ||
| 141 | priv->pdev_cap_off, priv->parent_cap_off); | ||
| 142 | return; | ||
| 143 | } | ||
| 144 | |||
| 145 | /* link capability */ | ||
| 146 | pci = priv->pdev; | ||
| 147 | where = priv->pdev_cap_off + ALCOR_PCIE_LINK_CAP_OFFSET; | ||
| 148 | pci_read_config_dword(pci, where, &val32); | ||
| 149 | priv->pdev_aspm_cap = (u8)(val32 >> 10) & 0x03; | ||
| 150 | |||
| 151 | pci = priv->parent_pdev; | ||
| 152 | where = priv->parent_cap_off + ALCOR_PCIE_LINK_CAP_OFFSET; | ||
| 153 | pci_read_config_dword(pci, where, &val32); | ||
| 154 | priv->parent_aspm_cap = (u8)(val32 >> 10) & 0x03; | ||
| 155 | |||
| 156 | if (priv->pdev_aspm_cap != priv->parent_aspm_cap) { | ||
| 157 | u8 aspm_cap; | ||
| 158 | |||
| 159 | dev_dbg(priv->dev, "pdev_aspm_cap: %x, parent_aspm_cap: %x\n", | ||
| 160 | priv->pdev_aspm_cap, priv->parent_aspm_cap); | ||
| 161 | aspm_cap = priv->pdev_aspm_cap & priv->parent_aspm_cap; | ||
| 162 | priv->pdev_aspm_cap = aspm_cap; | ||
| 163 | priv->parent_aspm_cap = aspm_cap; | ||
| 164 | } | ||
| 165 | |||
| 166 | dev_dbg(priv->dev, "ext_config_dev_aspm: %x, pdev_aspm_cap: %x\n", | ||
| 167 | priv->ext_config_dev_aspm, priv->pdev_aspm_cap); | ||
| 168 | priv->ext_config_dev_aspm &= priv->pdev_aspm_cap; | ||
| 169 | } | ||
| 170 | |||
| 171 | static void alcor_pci_aspm_ctrl(struct alcor_pci_priv *priv, u8 aspm_enable) | ||
| 172 | { | ||
| 173 | struct pci_dev *pci; | ||
| 174 | u8 aspm_ctrl, i; | ||
| 175 | int where; | ||
| 176 | u32 val32; | ||
| 177 | |||
| 178 | if ((!priv->pdev_cap_off) || (!priv->parent_cap_off)) { | ||
| 179 | dev_dbg(priv->dev, "pci_cap_off: %x, parent_cap_off: %x\n", | ||
| 180 | priv->pdev_cap_off, priv->parent_cap_off); | ||
| 181 | return; | ||
| 182 | } | ||
| 183 | |||
| 184 | if (!priv->pdev_aspm_cap) | ||
| 185 | return; | ||
| 186 | |||
| 187 | aspm_ctrl = 0; | ||
| 188 | if (aspm_enable) { | ||
| 189 | aspm_ctrl = priv->ext_config_dev_aspm; | ||
| 190 | |||
| 191 | if (!aspm_ctrl) { | ||
| 192 | dev_dbg(priv->dev, "aspm_ctrl == 0\n"); | ||
| 193 | return; | ||
| 194 | } | ||
| 195 | } | ||
| 196 | |||
| 197 | for (i = 0; i < 2; i++) { | ||
| 198 | |||
| 199 | if (i) { | ||
| 200 | pci = priv->parent_pdev; | ||
| 201 | where = priv->parent_cap_off | ||
| 202 | + ALCOR_PCIE_LINK_CTRL_OFFSET; | ||
| 203 | } else { | ||
| 204 | pci = priv->pdev; | ||
| 205 | where = priv->pdev_cap_off | ||
| 206 | + ALCOR_PCIE_LINK_CTRL_OFFSET; | ||
| 207 | } | ||
| 208 | |||
| 209 | pci_read_config_dword(pci, where, &val32); | ||
| 210 | val32 &= (~0x03); | ||
| 211 | val32 |= (aspm_ctrl & priv->pdev_aspm_cap); | ||
| 212 | pci_write_config_byte(pci, where, (u8)val32); | ||
| 213 | } | ||
| 214 | |||
| 215 | } | ||
| 216 | |||
| 217 | static inline void alcor_mask_sd_irqs(struct alcor_pci_priv *priv) | ||
| 218 | { | ||
| 219 | alcor_write32(priv, 0, AU6601_REG_INT_ENABLE); | ||
| 220 | } | ||
| 221 | |||
| 222 | static inline void alcor_unmask_sd_irqs(struct alcor_pci_priv *priv) | ||
| 223 | { | ||
| 224 | alcor_write32(priv, AU6601_INT_CMD_MASK | AU6601_INT_DATA_MASK | | ||
| 225 | AU6601_INT_CARD_INSERT | AU6601_INT_CARD_REMOVE | | ||
| 226 | AU6601_INT_OVER_CURRENT_ERR, | ||
| 227 | AU6601_REG_INT_ENABLE); | ||
| 228 | } | ||
| 229 | |||
| 230 | static inline void alcor_mask_ms_irqs(struct alcor_pci_priv *priv) | ||
| 231 | { | ||
| 232 | alcor_write32(priv, 0, AU6601_MS_INT_ENABLE); | ||
| 233 | } | ||
| 234 | |||
| 235 | static inline void alcor_unmask_ms_irqs(struct alcor_pci_priv *priv) | ||
| 236 | { | ||
| 237 | alcor_write32(priv, 0x3d00fa, AU6601_MS_INT_ENABLE); | ||
| 238 | } | ||
| 239 | |||
| 240 | static int alcor_pci_probe(struct pci_dev *pdev, | ||
| 241 | const struct pci_device_id *ent) | ||
| 242 | { | ||
| 243 | struct alcor_dev_cfg *cfg; | ||
| 244 | struct alcor_pci_priv *priv; | ||
| 245 | int ret, i, bar = 0; | ||
| 246 | |||
| 247 | cfg = (void *)ent->driver_data; | ||
| 248 | |||
| 249 | ret = pcim_enable_device(pdev); | ||
| 250 | if (ret) | ||
| 251 | return ret; | ||
| 252 | |||
| 253 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
| 254 | if (!priv) | ||
| 255 | return -ENOMEM; | ||
| 256 | |||
| 257 | ret = ida_simple_get(&alcor_pci_idr, 0, 0, GFP_KERNEL); | ||
| 258 | if (ret < 0) | ||
| 259 | return ret; | ||
| 260 | priv->id = ret; | ||
| 261 | |||
| 262 | priv->pdev = pdev; | ||
| 263 | priv->parent_pdev = pdev->bus->self; | ||
| 264 | priv->dev = &pdev->dev; | ||
| 265 | priv->cfg = cfg; | ||
| 266 | priv->irq = pdev->irq; | ||
| 267 | |||
| 268 | ret = pci_request_regions(pdev, DRV_NAME_ALCOR_PCI); | ||
| 269 | if (ret) { | ||
| 270 | dev_err(&pdev->dev, "Cannot request region\n"); | ||
| 271 | return -ENOMEM; | ||
| 272 | } | ||
| 273 | |||
| 274 | if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) { | ||
| 275 | dev_err(&pdev->dev, "BAR %d is not iomem. Aborting.\n", bar); | ||
| 276 | ret = -ENODEV; | ||
| 277 | goto error_release_regions; | ||
| 278 | } | ||
| 279 | |||
| 280 | priv->iobase = pcim_iomap(pdev, bar, 0); | ||
| 281 | if (!priv->iobase) { | ||
| 282 | ret = -ENOMEM; | ||
| 283 | goto error_release_regions; | ||
| 284 | } | ||
| 285 | |||
| 286 | /* make sure irqs are disabled */ | ||
| 287 | alcor_write32(priv, 0, AU6601_REG_INT_ENABLE); | ||
| 288 | alcor_write32(priv, 0, AU6601_MS_INT_ENABLE); | ||
| 289 | |||
| 290 | ret = dma_set_mask_and_coherent(priv->dev, AU6601_SDMA_MASK); | ||
| 291 | if (ret) { | ||
| 292 | dev_err(priv->dev, "Failed to set DMA mask\n"); | ||
| 293 | goto error_release_regions; | ||
| 294 | } | ||
| 295 | |||
| 296 | pci_set_master(pdev); | ||
| 297 | pci_set_drvdata(pdev, priv); | ||
| 298 | alcor_pci_init_check_aspm(priv); | ||
| 299 | |||
| 300 | for (i = 0; i < ARRAY_SIZE(alcor_pci_cells); i++) { | ||
| 301 | alcor_pci_cells[i].platform_data = priv; | ||
| 302 | alcor_pci_cells[i].pdata_size = sizeof(*priv); | ||
| 303 | } | ||
| 304 | ret = mfd_add_devices(&pdev->dev, priv->id, alcor_pci_cells, | ||
| 305 | ARRAY_SIZE(alcor_pci_cells), NULL, 0, NULL); | ||
| 306 | if (ret < 0) | ||
| 307 | goto error_release_regions; | ||
| 308 | |||
| 309 | alcor_pci_aspm_ctrl(priv, 0); | ||
| 310 | |||
| 311 | return 0; | ||
| 312 | |||
| 313 | error_release_regions: | ||
| 314 | pci_release_regions(pdev); | ||
| 315 | return ret; | ||
| 316 | } | ||
| 317 | |||
| 318 | static void alcor_pci_remove(struct pci_dev *pdev) | ||
| 319 | { | ||
| 320 | struct alcor_pci_priv *priv; | ||
| 321 | |||
| 322 | priv = pci_get_drvdata(pdev); | ||
| 323 | |||
| 324 | alcor_pci_aspm_ctrl(priv, 1); | ||
| 325 | |||
| 326 | mfd_remove_devices(&pdev->dev); | ||
| 327 | |||
| 328 | ida_simple_remove(&alcor_pci_idr, priv->id); | ||
| 329 | |||
| 330 | pci_release_regions(pdev); | ||
| 331 | pci_set_drvdata(pdev, NULL); | ||
| 332 | } | ||
| 333 | |||
| 334 | #ifdef CONFIG_PM_SLEEP | ||
| 335 | static int alcor_suspend(struct device *dev) | ||
| 336 | { | ||
| 337 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 338 | struct alcor_pci_priv *priv = pci_get_drvdata(pdev); | ||
| 339 | |||
| 340 | alcor_pci_aspm_ctrl(priv, 1); | ||
| 341 | return 0; | ||
| 342 | } | ||
| 343 | |||
| 344 | static int alcor_resume(struct device *dev) | ||
| 345 | { | ||
| 346 | |||
| 347 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 348 | struct alcor_pci_priv *priv = pci_get_drvdata(pdev); | ||
| 349 | |||
| 350 | alcor_pci_aspm_ctrl(priv, 0); | ||
| 351 | return 0; | ||
| 352 | } | ||
| 353 | #endif /* CONFIG_PM_SLEEP */ | ||
| 354 | |||
| 355 | static SIMPLE_DEV_PM_OPS(alcor_pci_pm_ops, alcor_suspend, alcor_resume); | ||
| 356 | |||
| 357 | static struct pci_driver alcor_driver = { | ||
| 358 | .name = DRV_NAME_ALCOR_PCI, | ||
| 359 | .id_table = pci_ids, | ||
| 360 | .probe = alcor_pci_probe, | ||
| 361 | .remove = alcor_pci_remove, | ||
| 362 | .driver = { | ||
| 363 | .pm = &alcor_pci_pm_ops | ||
| 364 | }, | ||
| 365 | }; | ||
| 366 | |||
| 367 | module_pci_driver(alcor_driver); | ||
| 368 | |||
| 369 | MODULE_AUTHOR("Oleksij Rempel <linux@rempel-privat.de>"); | ||
| 370 | MODULE_DESCRIPTION("PCI driver for Alcor Micro AU6601 Secure Digital Host Controller Interface"); | ||
| 371 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/misc/cardreader/rtsx_usb.c b/drivers/misc/cardreader/rtsx_usb.c index b97903ff1a72..f7a66f614085 100644 --- a/drivers/misc/cardreader/rtsx_usb.c +++ b/drivers/misc/cardreader/rtsx_usb.c | |||
| @@ -723,8 +723,15 @@ static int rtsx_usb_suspend(struct usb_interface *intf, pm_message_t message) | |||
| 723 | return 0; | 723 | return 0; |
| 724 | } | 724 | } |
| 725 | 725 | ||
| 726 | static int rtsx_usb_resume_child(struct device *dev, void *data) | ||
| 727 | { | ||
| 728 | pm_request_resume(dev); | ||
| 729 | return 0; | ||
| 730 | } | ||
| 731 | |||
| 726 | static int rtsx_usb_resume(struct usb_interface *intf) | 732 | static int rtsx_usb_resume(struct usb_interface *intf) |
| 727 | { | 733 | { |
| 734 | device_for_each_child(&intf->dev, NULL, rtsx_usb_resume_child); | ||
| 728 | return 0; | 735 | return 0; |
| 729 | } | 736 | } |
| 730 | 737 | ||
| @@ -734,6 +741,7 @@ static int rtsx_usb_reset_resume(struct usb_interface *intf) | |||
| 734 | (struct rtsx_ucr *)usb_get_intfdata(intf); | 741 | (struct rtsx_ucr *)usb_get_intfdata(intf); |
| 735 | 742 | ||
| 736 | rtsx_usb_reset_chip(ucr); | 743 | rtsx_usb_reset_chip(ucr); |
| 744 | device_for_each_child(&intf->dev, NULL, rtsx_usb_resume_child); | ||
| 737 | return 0; | 745 | return 0; |
| 738 | } | 746 | } |
| 739 | 747 | ||
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 62e7619d5a4d..aef1185f383d 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c | |||
| @@ -1960,7 +1960,7 @@ static void mmc_blk_urgent_bkops(struct mmc_queue *mq, | |||
| 1960 | struct mmc_queue_req *mqrq) | 1960 | struct mmc_queue_req *mqrq) |
| 1961 | { | 1961 | { |
| 1962 | if (mmc_blk_urgent_bkops_needed(mq, mqrq)) | 1962 | if (mmc_blk_urgent_bkops_needed(mq, mqrq)) |
| 1963 | mmc_start_bkops(mq->card, true); | 1963 | mmc_run_bkops(mq->card); |
| 1964 | } | 1964 | } |
| 1965 | 1965 | ||
| 1966 | void mmc_blk_mq_complete(struct request *req) | 1966 | void mmc_blk_mq_complete(struct request *req) |
diff --git a/drivers/mmc/core/card.h b/drivers/mmc/core/card.h index 1170feb8f969..eef301452406 100644 --- a/drivers/mmc/core/card.h +++ b/drivers/mmc/core/card.h | |||
| @@ -23,15 +23,13 @@ | |||
| 23 | #define MMC_STATE_BLOCKADDR (1<<2) /* card uses block-addressing */ | 23 | #define MMC_STATE_BLOCKADDR (1<<2) /* card uses block-addressing */ |
| 24 | #define MMC_CARD_SDXC (1<<3) /* card is SDXC */ | 24 | #define MMC_CARD_SDXC (1<<3) /* card is SDXC */ |
| 25 | #define MMC_CARD_REMOVED (1<<4) /* card has been removed */ | 25 | #define MMC_CARD_REMOVED (1<<4) /* card has been removed */ |
| 26 | #define MMC_STATE_DOING_BKOPS (1<<5) /* card is doing BKOPS */ | 26 | #define MMC_STATE_SUSPENDED (1<<5) /* card is suspended */ |
| 27 | #define MMC_STATE_SUSPENDED (1<<6) /* card is suspended */ | ||
| 28 | 27 | ||
| 29 | #define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT) | 28 | #define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT) |
| 30 | #define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY) | 29 | #define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY) |
| 31 | #define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR) | 30 | #define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR) |
| 32 | #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC) | 31 | #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC) |
| 33 | #define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED)) | 32 | #define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED)) |
| 34 | #define mmc_card_doing_bkops(c) ((c)->state & MMC_STATE_DOING_BKOPS) | ||
| 35 | #define mmc_card_suspended(c) ((c)->state & MMC_STATE_SUSPENDED) | 33 | #define mmc_card_suspended(c) ((c)->state & MMC_STATE_SUSPENDED) |
| 36 | 34 | ||
| 37 | #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) | 35 | #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) |
| @@ -39,8 +37,6 @@ | |||
| 39 | #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR) | 37 | #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR) |
| 40 | #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC) | 38 | #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC) |
| 41 | #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED) | 39 | #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED) |
| 42 | #define mmc_card_set_doing_bkops(c) ((c)->state |= MMC_STATE_DOING_BKOPS) | ||
| 43 | #define mmc_card_clr_doing_bkops(c) ((c)->state &= ~MMC_STATE_DOING_BKOPS) | ||
| 44 | #define mmc_card_set_suspended(c) ((c)->state |= MMC_STATE_SUSPENDED) | 40 | #define mmc_card_set_suspended(c) ((c)->state |= MMC_STATE_SUSPENDED) |
| 45 | #define mmc_card_clr_suspended(c) ((c)->state &= ~MMC_STATE_SUSPENDED) | 41 | #define mmc_card_clr_suspended(c) ((c)->state &= ~MMC_STATE_SUSPENDED) |
| 46 | 42 | ||
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 50a5c340307b..5bd58b95d318 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
| @@ -887,7 +887,10 @@ void mmc_release_host(struct mmc_host *host) | |||
| 887 | spin_unlock_irqrestore(&host->lock, flags); | 887 | spin_unlock_irqrestore(&host->lock, flags); |
| 888 | wake_up(&host->wq); | 888 | wake_up(&host->wq); |
| 889 | pm_runtime_mark_last_busy(mmc_dev(host)); | 889 | pm_runtime_mark_last_busy(mmc_dev(host)); |
| 890 | pm_runtime_put_autosuspend(mmc_dev(host)); | 890 | if (host->caps & MMC_CAP_SYNC_RUNTIME_PM) |
| 891 | pm_runtime_put_sync_suspend(mmc_dev(host)); | ||
| 892 | else | ||
| 893 | pm_runtime_put_autosuspend(mmc_dev(host)); | ||
| 891 | } | 894 | } |
| 892 | } | 895 | } |
| 893 | EXPORT_SYMBOL(mmc_release_host); | 896 | EXPORT_SYMBOL(mmc_release_host); |
| @@ -2413,20 +2416,6 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen) | |||
| 2413 | } | 2416 | } |
| 2414 | EXPORT_SYMBOL(mmc_set_blocklen); | 2417 | EXPORT_SYMBOL(mmc_set_blocklen); |
| 2415 | 2418 | ||
| 2416 | int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount, | ||
| 2417 | bool is_rel_write) | ||
| 2418 | { | ||
| 2419 | struct mmc_command cmd = {}; | ||
| 2420 | |||
| 2421 | cmd.opcode = MMC_SET_BLOCK_COUNT; | ||
| 2422 | cmd.arg = blockcount & 0x0000FFFF; | ||
| 2423 | if (is_rel_write) | ||
| 2424 | cmd.arg |= 1 << 31; | ||
| 2425 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; | ||
| 2426 | return mmc_wait_for_cmd(card->host, &cmd, 5); | ||
| 2427 | } | ||
| 2428 | EXPORT_SYMBOL(mmc_set_blockcount); | ||
| 2429 | |||
| 2430 | static void mmc_hw_reset_for_init(struct mmc_host *host) | 2419 | static void mmc_hw_reset_for_init(struct mmc_host *host) |
| 2431 | { | 2420 | { |
| 2432 | mmc_pwrseq_reset(host); | 2421 | mmc_pwrseq_reset(host); |
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 087ba68b2920..8fb6bc37f808 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h | |||
| @@ -118,8 +118,6 @@ int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from, | |||
| 118 | unsigned int mmc_calc_max_discard(struct mmc_card *card); | 118 | unsigned int mmc_calc_max_discard(struct mmc_card *card); |
| 119 | 119 | ||
| 120 | int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen); | 120 | int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen); |
| 121 | int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount, | ||
| 122 | bool is_rel_write); | ||
| 123 | 121 | ||
| 124 | int __mmc_claim_host(struct mmc_host *host, struct mmc_ctx *ctx, | 122 | int __mmc_claim_host(struct mmc_host *host, struct mmc_ctx *ctx, |
| 125 | atomic_t *abort); | 123 | atomic_t *abort); |
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 55997cf84b39..da892a599524 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
| @@ -1181,6 +1181,9 @@ static int mmc_select_hs400(struct mmc_card *card) | |||
| 1181 | if (err) | 1181 | if (err) |
| 1182 | goto out_err; | 1182 | goto out_err; |
| 1183 | 1183 | ||
| 1184 | if (host->ops->hs400_prepare_ddr) | ||
| 1185 | host->ops->hs400_prepare_ddr(host); | ||
| 1186 | |||
| 1184 | /* Switch card to DDR */ | 1187 | /* Switch card to DDR */ |
| 1185 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 1188 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
| 1186 | EXT_CSD_BUS_WIDTH, | 1189 | EXT_CSD_BUS_WIDTH, |
| @@ -2011,12 +2014,6 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) | |||
| 2011 | if (mmc_card_suspended(host->card)) | 2014 | if (mmc_card_suspended(host->card)) |
| 2012 | goto out; | 2015 | goto out; |
| 2013 | 2016 | ||
| 2014 | if (mmc_card_doing_bkops(host->card)) { | ||
| 2015 | err = mmc_stop_bkops(host->card); | ||
| 2016 | if (err) | ||
| 2017 | goto out; | ||
| 2018 | } | ||
| 2019 | |||
| 2020 | err = mmc_flush_cache(host->card); | 2017 | err = mmc_flush_cache(host->card); |
| 2021 | if (err) | 2018 | if (err) |
| 2022 | goto out; | 2019 | goto out; |
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 873b2aa0c155..9054329fe903 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c | |||
| @@ -802,12 +802,6 @@ static int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status) | |||
| 802 | unsigned int opcode; | 802 | unsigned int opcode; |
| 803 | int err; | 803 | int err; |
| 804 | 804 | ||
| 805 | if (!card->ext_csd.hpi) { | ||
| 806 | pr_warn("%s: Card didn't support HPI command\n", | ||
| 807 | mmc_hostname(card->host)); | ||
| 808 | return -EINVAL; | ||
| 809 | } | ||
| 810 | |||
| 811 | opcode = card->ext_csd.hpi_cmd; | 805 | opcode = card->ext_csd.hpi_cmd; |
| 812 | if (opcode == MMC_STOP_TRANSMISSION) | 806 | if (opcode == MMC_STOP_TRANSMISSION) |
| 813 | cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; | 807 | cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; |
| @@ -897,34 +891,6 @@ int mmc_can_ext_csd(struct mmc_card *card) | |||
| 897 | return (card && card->csd.mmca_vsn > CSD_SPEC_VER_3); | 891 | return (card && card->csd.mmca_vsn > CSD_SPEC_VER_3); |
| 898 | } | 892 | } |
| 899 | 893 | ||
| 900 | /** | ||
| 901 | * mmc_stop_bkops - stop ongoing BKOPS | ||
| 902 | * @card: MMC card to check BKOPS | ||
| 903 | * | ||
| 904 | * Send HPI command to stop ongoing background operations to | ||
| 905 | * allow rapid servicing of foreground operations, e.g. read/ | ||
| 906 | * writes. Wait until the card comes out of the programming state | ||
| 907 | * to avoid errors in servicing read/write requests. | ||
| 908 | */ | ||
| 909 | int mmc_stop_bkops(struct mmc_card *card) | ||
| 910 | { | ||
| 911 | int err = 0; | ||
| 912 | |||
| 913 | err = mmc_interrupt_hpi(card); | ||
| 914 | |||
| 915 | /* | ||
| 916 | * If err is EINVAL, we can't issue an HPI. | ||
| 917 | * It should complete the BKOPS. | ||
| 918 | */ | ||
| 919 | if (!err || (err == -EINVAL)) { | ||
| 920 | mmc_card_clr_doing_bkops(card); | ||
| 921 | mmc_retune_release(card->host); | ||
| 922 | err = 0; | ||
| 923 | } | ||
| 924 | |||
| 925 | return err; | ||
| 926 | } | ||
| 927 | |||
| 928 | static int mmc_read_bkops_status(struct mmc_card *card) | 894 | static int mmc_read_bkops_status(struct mmc_card *card) |
| 929 | { | 895 | { |
| 930 | int err; | 896 | int err; |
| @@ -941,22 +907,17 @@ static int mmc_read_bkops_status(struct mmc_card *card) | |||
| 941 | } | 907 | } |
| 942 | 908 | ||
| 943 | /** | 909 | /** |
| 944 | * mmc_start_bkops - start BKOPS for supported cards | 910 | * mmc_run_bkops - Run BKOPS for supported cards |
| 945 | * @card: MMC card to start BKOPS | 911 | * @card: MMC card to run BKOPS for |
| 946 | * @from_exception: A flag to indicate if this function was | ||
| 947 | * called due to an exception raised by the card | ||
| 948 | * | 912 | * |
| 949 | * Start background operations whenever requested. | 913 | * Run background operations synchronously for cards having manual BKOPS |
| 950 | * When the urgent BKOPS bit is set in a R1 command response | 914 | * enabled and in case it reports urgent BKOPS level. |
| 951 | * then background operations should be started immediately. | ||
| 952 | */ | 915 | */ |
| 953 | void mmc_start_bkops(struct mmc_card *card, bool from_exception) | 916 | void mmc_run_bkops(struct mmc_card *card) |
| 954 | { | 917 | { |
| 955 | int err; | 918 | int err; |
| 956 | int timeout; | ||
| 957 | bool use_busy_signal; | ||
| 958 | 919 | ||
| 959 | if (!card->ext_csd.man_bkops_en || mmc_card_doing_bkops(card)) | 920 | if (!card->ext_csd.man_bkops_en) |
| 960 | return; | 921 | return; |
| 961 | 922 | ||
| 962 | err = mmc_read_bkops_status(card); | 923 | err = mmc_read_bkops_status(card); |
| @@ -966,44 +927,26 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception) | |||
| 966 | return; | 927 | return; |
| 967 | } | 928 | } |
| 968 | 929 | ||
| 969 | if (!card->ext_csd.raw_bkops_status) | 930 | if (!card->ext_csd.raw_bkops_status || |
| 970 | return; | 931 | card->ext_csd.raw_bkops_status < EXT_CSD_BKOPS_LEVEL_2) |
| 971 | |||
| 972 | if (card->ext_csd.raw_bkops_status < EXT_CSD_BKOPS_LEVEL_2 && | ||
| 973 | from_exception) | ||
| 974 | return; | 932 | return; |
| 975 | 933 | ||
| 976 | if (card->ext_csd.raw_bkops_status >= EXT_CSD_BKOPS_LEVEL_2) { | ||
| 977 | timeout = MMC_OPS_TIMEOUT_MS; | ||
| 978 | use_busy_signal = true; | ||
| 979 | } else { | ||
| 980 | timeout = 0; | ||
| 981 | use_busy_signal = false; | ||
| 982 | } | ||
| 983 | |||
| 984 | mmc_retune_hold(card->host); | 934 | mmc_retune_hold(card->host); |
| 985 | 935 | ||
| 986 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 936 | /* |
| 987 | EXT_CSD_BKOPS_START, 1, timeout, 0, | 937 | * For urgent BKOPS status, LEVEL_2 and higher, let's execute |
| 988 | use_busy_signal, true, false); | 938 | * synchronously. Future wise, we may consider to start BKOPS, for less |
| 989 | if (err) { | 939 | * urgent levels by using an asynchronous background task, when idle. |
| 940 | */ | ||
| 941 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | ||
| 942 | EXT_CSD_BKOPS_START, 1, MMC_OPS_TIMEOUT_MS); | ||
| 943 | if (err) | ||
| 990 | pr_warn("%s: Error %d starting bkops\n", | 944 | pr_warn("%s: Error %d starting bkops\n", |
| 991 | mmc_hostname(card->host), err); | 945 | mmc_hostname(card->host), err); |
| 992 | mmc_retune_release(card->host); | ||
| 993 | return; | ||
| 994 | } | ||
| 995 | 946 | ||
| 996 | /* | 947 | mmc_retune_release(card->host); |
| 997 | * For urgent bkops status (LEVEL_2 and more) | ||
| 998 | * bkops executed synchronously, otherwise | ||
| 999 | * the operation is in progress | ||
| 1000 | */ | ||
| 1001 | if (!use_busy_signal) | ||
| 1002 | mmc_card_set_doing_bkops(card); | ||
| 1003 | else | ||
| 1004 | mmc_retune_release(card->host); | ||
| 1005 | } | 948 | } |
| 1006 | EXPORT_SYMBOL(mmc_start_bkops); | 949 | EXPORT_SYMBOL(mmc_run_bkops); |
| 1007 | 950 | ||
| 1008 | /* | 951 | /* |
| 1009 | * Flush the cache to the non-volatile storage. | 952 | * Flush the cache to the non-volatile storage. |
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index a1390d486381..018a5e3f66d6 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h | |||
| @@ -40,8 +40,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, | |||
| 40 | bool use_busy_signal, bool send_status, bool retry_crc_err); | 40 | bool use_busy_signal, bool send_status, bool retry_crc_err); |
| 41 | int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, | 41 | int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, |
| 42 | unsigned int timeout_ms); | 42 | unsigned int timeout_ms); |
| 43 | int mmc_stop_bkops(struct mmc_card *card); | 43 | void mmc_run_bkops(struct mmc_card *card); |
| 44 | void mmc_start_bkops(struct mmc_card *card, bool from_exception); | ||
| 45 | int mmc_flush_cache(struct mmc_card *card); | 44 | int mmc_flush_cache(struct mmc_card *card); |
| 46 | int mmc_cmdq_enable(struct mmc_card *card); | 45 | int mmc_cmdq_enable(struct mmc_card *card); |
| 47 | int mmc_cmdq_disable(struct mmc_card *card); | 46 | int mmc_cmdq_disable(struct mmc_card *card); |
diff --git a/drivers/mmc/core/mmc_test.c b/drivers/mmc/core/mmc_test.c index ef18daeaa4cc..eabb1cab1765 100644 --- a/drivers/mmc/core/mmc_test.c +++ b/drivers/mmc/core/mmc_test.c | |||
| @@ -3145,17 +3145,7 @@ static int mtf_testlist_show(struct seq_file *sf, void *data) | |||
| 3145 | return 0; | 3145 | return 0; |
| 3146 | } | 3146 | } |
| 3147 | 3147 | ||
| 3148 | static int mtf_testlist_open(struct inode *inode, struct file *file) | 3148 | DEFINE_SHOW_ATTRIBUTE(mtf_testlist); |
| 3149 | { | ||
| 3150 | return single_open(file, mtf_testlist_show, inode->i_private); | ||
| 3151 | } | ||
| 3152 | |||
| 3153 | static const struct file_operations mmc_test_fops_testlist = { | ||
| 3154 | .open = mtf_testlist_open, | ||
| 3155 | .read = seq_read, | ||
| 3156 | .llseek = seq_lseek, | ||
| 3157 | .release = single_release, | ||
| 3158 | }; | ||
| 3159 | 3149 | ||
| 3160 | static void mmc_test_free_dbgfs_file(struct mmc_card *card) | 3150 | static void mmc_test_free_dbgfs_file(struct mmc_card *card) |
| 3161 | { | 3151 | { |
| @@ -3216,7 +3206,7 @@ static int mmc_test_register_dbgfs_file(struct mmc_card *card) | |||
| 3216 | goto err; | 3206 | goto err; |
| 3217 | 3207 | ||
| 3218 | ret = __mmc_test_register_dbgfs_file(card, "testlist", S_IRUGO, | 3208 | ret = __mmc_test_register_dbgfs_file(card, "testlist", S_IRUGO, |
| 3219 | &mmc_test_fops_testlist); | 3209 | &mtf_testlist_fops); |
| 3220 | if (ret) | 3210 | if (ret) |
| 3221 | goto err; | 3211 | goto err; |
| 3222 | 3212 | ||
diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c index 86803a3a04dc..319ccd93383d 100644 --- a/drivers/mmc/core/slot-gpio.c +++ b/drivers/mmc/core/slot-gpio.c | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #include <linux/err.h> | 11 | #include <linux/err.h> |
| 12 | #include <linux/gpio.h> | ||
| 13 | #include <linux/gpio/consumer.h> | 12 | #include <linux/gpio/consumer.h> |
| 14 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
| 15 | #include <linux/jiffies.h> | 14 | #include <linux/jiffies.h> |
| @@ -27,8 +26,8 @@ struct mmc_gpio { | |||
| 27 | bool override_cd_active_level; | 26 | bool override_cd_active_level; |
| 28 | irqreturn_t (*cd_gpio_isr)(int irq, void *dev_id); | 27 | irqreturn_t (*cd_gpio_isr)(int irq, void *dev_id); |
| 29 | char *ro_label; | 28 | char *ro_label; |
| 29 | char *cd_label; | ||
| 30 | u32 cd_debounce_delay_ms; | 30 | u32 cd_debounce_delay_ms; |
| 31 | char cd_label[]; | ||
| 32 | }; | 31 | }; |
| 33 | 32 | ||
| 34 | static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) | 33 | static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) |
| @@ -45,15 +44,19 @@ static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) | |||
| 45 | 44 | ||
| 46 | int mmc_gpio_alloc(struct mmc_host *host) | 45 | int mmc_gpio_alloc(struct mmc_host *host) |
| 47 | { | 46 | { |
| 48 | size_t len = strlen(dev_name(host->parent)) + 4; | ||
| 49 | struct mmc_gpio *ctx = devm_kzalloc(host->parent, | 47 | struct mmc_gpio *ctx = devm_kzalloc(host->parent, |
| 50 | sizeof(*ctx) + 2 * len, GFP_KERNEL); | 48 | sizeof(*ctx), GFP_KERNEL); |
| 51 | 49 | ||
| 52 | if (ctx) { | 50 | if (ctx) { |
| 53 | ctx->ro_label = ctx->cd_label + len; | ||
| 54 | ctx->cd_debounce_delay_ms = 200; | 51 | ctx->cd_debounce_delay_ms = 200; |
| 55 | snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent)); | 52 | ctx->cd_label = devm_kasprintf(host->parent, GFP_KERNEL, |
| 56 | snprintf(ctx->ro_label, len, "%s ro", dev_name(host->parent)); | 53 | "%s cd", dev_name(host->parent)); |
| 54 | if (!ctx->cd_label) | ||
| 55 | return -ENOMEM; | ||
| 56 | ctx->ro_label = devm_kasprintf(host->parent, GFP_KERNEL, | ||
| 57 | "%s ro", dev_name(host->parent)); | ||
| 58 | if (!ctx->ro_label) | ||
| 59 | return -ENOMEM; | ||
| 57 | host->slot.handler_priv = ctx; | 60 | host->slot.handler_priv = ctx; |
| 58 | host->slot.cd_irq = -EINVAL; | 61 | host->slot.cd_irq = -EINVAL; |
| 59 | } | 62 | } |
| @@ -98,36 +101,6 @@ int mmc_gpio_get_cd(struct mmc_host *host) | |||
| 98 | } | 101 | } |
| 99 | EXPORT_SYMBOL(mmc_gpio_get_cd); | 102 | EXPORT_SYMBOL(mmc_gpio_get_cd); |
| 100 | 103 | ||
| 101 | /** | ||
| 102 | * mmc_gpio_request_ro - request a gpio for write-protection | ||
| 103 | * @host: mmc host | ||
| 104 | * @gpio: gpio number requested | ||
| 105 | * | ||
| 106 | * As devm_* managed functions are used in mmc_gpio_request_ro(), client | ||
| 107 | * drivers do not need to worry about freeing up memory. | ||
| 108 | * | ||
| 109 | * Returns zero on success, else an error. | ||
| 110 | */ | ||
| 111 | int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio) | ||
| 112 | { | ||
| 113 | struct mmc_gpio *ctx = host->slot.handler_priv; | ||
| 114 | int ret; | ||
| 115 | |||
| 116 | if (!gpio_is_valid(gpio)) | ||
| 117 | return -EINVAL; | ||
| 118 | |||
| 119 | ret = devm_gpio_request_one(host->parent, gpio, GPIOF_DIR_IN, | ||
| 120 | ctx->ro_label); | ||
| 121 | if (ret < 0) | ||
| 122 | return ret; | ||
| 123 | |||
| 124 | ctx->override_ro_active_level = true; | ||
| 125 | ctx->ro_gpio = gpio_to_desc(gpio); | ||
| 126 | |||
| 127 | return 0; | ||
| 128 | } | ||
| 129 | EXPORT_SYMBOL(mmc_gpio_request_ro); | ||
| 130 | |||
| 131 | void mmc_gpiod_request_cd_irq(struct mmc_host *host) | 104 | void mmc_gpiod_request_cd_irq(struct mmc_host *host) |
| 132 | { | 105 | { |
| 133 | struct mmc_gpio *ctx = host->slot.handler_priv; | 106 | struct mmc_gpio *ctx = host->slot.handler_priv; |
| @@ -197,50 +170,6 @@ void mmc_gpio_set_cd_isr(struct mmc_host *host, | |||
| 197 | EXPORT_SYMBOL(mmc_gpio_set_cd_isr); | 170 | EXPORT_SYMBOL(mmc_gpio_set_cd_isr); |
| 198 | 171 | ||
| 199 | /** | 172 | /** |
| 200 | * mmc_gpio_request_cd - request a gpio for card-detection | ||
| 201 | * @host: mmc host | ||
| 202 | * @gpio: gpio number requested | ||
| 203 | * @debounce: debounce time in microseconds | ||
| 204 | * | ||
| 205 | * As devm_* managed functions are used in mmc_gpio_request_cd(), client | ||
| 206 | * drivers do not need to worry about freeing up memory. | ||
| 207 | * | ||
| 208 | * If GPIO debouncing is desired, set the debounce parameter to a non-zero | ||
| 209 | * value. The caller is responsible for ensuring that the GPIO driver associated | ||
| 210 | * with the GPIO supports debouncing, otherwise an error will be returned. | ||
| 211 | * | ||
| 212 | * Returns zero on success, else an error. | ||
| 213 | */ | ||
| 214 | int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio, | ||
| 215 | unsigned int debounce) | ||
| 216 | { | ||
| 217 | struct mmc_gpio *ctx = host->slot.handler_priv; | ||
| 218 | int ret; | ||
| 219 | |||
| 220 | ret = devm_gpio_request_one(host->parent, gpio, GPIOF_DIR_IN, | ||
| 221 | ctx->cd_label); | ||
| 222 | if (ret < 0) | ||
| 223 | /* | ||
| 224 | * don't bother freeing memory. It might still get used by other | ||
| 225 | * slot functions, in any case it will be freed, when the device | ||
| 226 | * is destroyed. | ||
| 227 | */ | ||
| 228 | return ret; | ||
| 229 | |||
| 230 | if (debounce) { | ||
| 231 | ret = gpio_set_debounce(gpio, debounce); | ||
| 232 | if (ret < 0) | ||
| 233 | return ret; | ||
| 234 | } | ||
| 235 | |||
| 236 | ctx->override_cd_active_level = true; | ||
| 237 | ctx->cd_gpio = gpio_to_desc(gpio); | ||
| 238 | |||
| 239 | return 0; | ||
| 240 | } | ||
| 241 | EXPORT_SYMBOL(mmc_gpio_request_cd); | ||
| 242 | |||
| 243 | /** | ||
| 244 | * mmc_gpiod_request_cd - request a gpio descriptor for card-detection | 173 | * mmc_gpiod_request_cd - request a gpio descriptor for card-detection |
| 245 | * @host: mmc host | 174 | * @host: mmc host |
| 246 | * @con_id: function within the GPIO consumer | 175 | * @con_id: function within the GPIO consumer |
| @@ -250,8 +179,7 @@ EXPORT_SYMBOL(mmc_gpio_request_cd); | |||
| 250 | * @gpio_invert: will return whether the GPIO line is inverted or not, set | 179 | * @gpio_invert: will return whether the GPIO line is inverted or not, set |
| 251 | * to NULL to ignore | 180 | * to NULL to ignore |
| 252 | * | 181 | * |
| 253 | * Use this function in place of mmc_gpio_request_cd() to use the GPIO | 182 | * Note that this must be called prior to mmc_add_host() |
| 254 | * descriptor API. Note that it must be called prior to mmc_add_host() | ||
| 255 | * otherwise the caller must also call mmc_gpiod_request_cd_irq(). | 183 | * otherwise the caller must also call mmc_gpiod_request_cd_irq(). |
| 256 | * | 184 | * |
| 257 | * Returns zero on success, else an error. | 185 | * Returns zero on success, else an error. |
| @@ -302,9 +230,6 @@ EXPORT_SYMBOL(mmc_can_gpio_cd); | |||
| 302 | * @gpio_invert: will return whether the GPIO line is inverted or not, | 230 | * @gpio_invert: will return whether the GPIO line is inverted or not, |
| 303 | * set to NULL to ignore | 231 | * set to NULL to ignore |
| 304 | * | 232 | * |
| 305 | * Use this function in place of mmc_gpio_request_ro() to use the GPIO | ||
| 306 | * descriptor API. | ||
| 307 | * | ||
| 308 | * Returns zero on success, else an error. | 233 | * Returns zero on success, else an error. |
| 309 | */ | 234 | */ |
| 310 | int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, | 235 | int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, |
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 1b58739d9744..e26b8145efb3 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
| @@ -441,6 +441,13 @@ config MMC_WBSD | |||
| 441 | 441 | ||
| 442 | If unsure, say N. | 442 | If unsure, say N. |
| 443 | 443 | ||
| 444 | config MMC_ALCOR | ||
| 445 | tristate "Alcor Micro/Alcor Link SD/MMC controller" | ||
| 446 | depends on MISC_ALCOR_PCI | ||
| 447 | help | ||
| 448 | Say Y here to include driver code to support SD/MMC card interface | ||
| 449 | of Alcor Micro PCI-E card reader | ||
| 450 | |||
| 444 | config MMC_AU1X | 451 | config MMC_AU1X |
| 445 | tristate "Alchemy AU1XX0 MMC Card Interface support" | 452 | tristate "Alchemy AU1XX0 MMC Card Interface support" |
| 446 | depends on MIPS_ALCHEMY | 453 | depends on MIPS_ALCHEMY |
| @@ -646,13 +653,14 @@ config MMC_SDHI_SYS_DMAC | |||
| 646 | 653 | ||
| 647 | config MMC_SDHI_INTERNAL_DMAC | 654 | config MMC_SDHI_INTERNAL_DMAC |
| 648 | tristate "DMA for SDHI SD/SDIO controllers using on-chip bus mastering" | 655 | tristate "DMA for SDHI SD/SDIO controllers using on-chip bus mastering" |
| 649 | depends on ARM64 || ARCH_R8A77470 || COMPILE_TEST | 656 | depends on ARM64 || ARCH_R7S9210 || ARCH_R8A77470 || COMPILE_TEST |
| 650 | depends on MMC_SDHI | 657 | depends on MMC_SDHI |
| 651 | default MMC_SDHI if (ARM64 || ARCH_R8A77470) | 658 | default MMC_SDHI if (ARM64 || ARCH_R7S9210 || ARCH_R8A77470) |
| 652 | help | 659 | help |
| 653 | This provides DMA support for SDHI SD/SDIO controllers | 660 | This provides DMA support for SDHI SD/SDIO controllers |
| 654 | using on-chip bus mastering. This supports the controllers | 661 | using on-chip bus mastering. This supports the controllers |
| 655 | found in arm64 based SoCs. | 662 | found in arm64 based SoCs. This controller is also found in |
| 663 | some RZ family SoCs. | ||
| 656 | 664 | ||
| 657 | config MMC_UNIPHIER | 665 | config MMC_UNIPHIER |
| 658 | tristate "UniPhier SD/eMMC Host Controller support" | 666 | tristate "UniPhier SD/eMMC Host Controller support" |
| @@ -969,6 +977,8 @@ config MMC_SDHCI_XENON | |||
| 969 | config MMC_SDHCI_OMAP | 977 | config MMC_SDHCI_OMAP |
| 970 | tristate "TI SDHCI Controller Support" | 978 | tristate "TI SDHCI Controller Support" |
| 971 | depends on MMC_SDHCI_PLTFM && OF | 979 | depends on MMC_SDHCI_PLTFM && OF |
| 980 | select THERMAL | ||
| 981 | select TI_SOC_THERMAL | ||
| 972 | help | 982 | help |
| 973 | This selects the Secure Digital Host Controller Interface (SDHCI) | 983 | This selects the Secure Digital Host Controller Interface (SDHCI) |
| 974 | support present in TI's DRA7 SOCs. The controller supports | 984 | support present in TI's DRA7 SOCs. The controller supports |
| @@ -977,3 +987,15 @@ config MMC_SDHCI_OMAP | |||
| 977 | If you have a controller with this interface, say Y or M here. | 987 | If you have a controller with this interface, say Y or M here. |
| 978 | 988 | ||
| 979 | If unsure, say N. | 989 | If unsure, say N. |
| 990 | |||
| 991 | config MMC_SDHCI_AM654 | ||
| 992 | tristate "Support for the SDHCI Controller in TI's AM654 SOCs" | ||
| 993 | depends on MMC_SDHCI_PLTFM && OF | ||
| 994 | help | ||
| 995 | This selects the Secure Digital Host Controller Interface (SDHCI) | ||
| 996 | support present in TI's AM654 SOCs. The controller supports | ||
| 997 | SD/MMC/SDIO devices. | ||
| 998 | |||
| 999 | If you have a controller with this interface, say Y or M here. | ||
| 1000 | |||
| 1001 | If unsure, say N. | ||
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 720d37777098..73578718f119 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
| @@ -22,8 +22,10 @@ obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o | |||
| 22 | obj-$(CONFIG_MMC_SDHCI_SIRF) += sdhci-sirf.o | 22 | obj-$(CONFIG_MMC_SDHCI_SIRF) += sdhci-sirf.o |
| 23 | obj-$(CONFIG_MMC_SDHCI_F_SDH30) += sdhci_f_sdh30.o | 23 | obj-$(CONFIG_MMC_SDHCI_F_SDH30) += sdhci_f_sdh30.o |
| 24 | obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o | 24 | obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o |
| 25 | obj-$(CONFIG_MMC_SDHCI_AM654) += sdhci_am654.o | ||
| 25 | obj-$(CONFIG_MMC_WBSD) += wbsd.o | 26 | obj-$(CONFIG_MMC_WBSD) += wbsd.o |
| 26 | obj-$(CONFIG_MMC_AU1X) += au1xmmc.o | 27 | obj-$(CONFIG_MMC_AU1X) += au1xmmc.o |
| 28 | obj-$(CONFIG_MMC_ALCOR) += alcor.o | ||
| 27 | obj-$(CONFIG_MMC_MTK) += mtk-sd.o | 29 | obj-$(CONFIG_MMC_MTK) += mtk-sd.o |
| 28 | obj-$(CONFIG_MMC_OMAP) += omap.o | 30 | obj-$(CONFIG_MMC_OMAP) += omap.o |
| 29 | obj-$(CONFIG_MMC_OMAP_HS) += omap_hsmmc.o | 31 | obj-$(CONFIG_MMC_OMAP_HS) += omap_hsmmc.o |
diff --git a/drivers/mmc/host/alcor.c b/drivers/mmc/host/alcor.c new file mode 100644 index 000000000000..c712b7deb3a9 --- /dev/null +++ b/drivers/mmc/host/alcor.c | |||
| @@ -0,0 +1,1162 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0+ | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2018 Oleksij Rempel <linux@rempel-privat.de> | ||
| 4 | * | ||
| 5 | * Driver for Alcor Micro AU6601 and AU6621 controllers | ||
| 6 | */ | ||
| 7 | |||
| 8 | /* Note: this driver was created without any documentation. Based | ||
| 9 | * on sniffing, testing and in some cases mimic of original driver. | ||
| 10 | * As soon as some one with documentation or more experience in SD/MMC, or | ||
| 11 | * reverse engineering then me, please review this driver and question every | ||
| 12 | * thing what I did. 2018 Oleksij Rempel <linux@rempel-privat.de> | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/delay.h> | ||
| 16 | #include <linux/pci.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/io.h> | ||
| 19 | #include <linux/pm.h> | ||
| 20 | #include <linux/irq.h> | ||
| 21 | #include <linux/interrupt.h> | ||
| 22 | #include <linux/platform_device.h> | ||
| 23 | |||
| 24 | #include <linux/mmc/host.h> | ||
| 25 | #include <linux/mmc/mmc.h> | ||
| 26 | |||
| 27 | #include <linux/alcor_pci.h> | ||
| 28 | |||
| 29 | enum alcor_cookie { | ||
| 30 | COOKIE_UNMAPPED, | ||
| 31 | COOKIE_PRE_MAPPED, | ||
| 32 | COOKIE_MAPPED, | ||
| 33 | }; | ||
| 34 | |||
| 35 | struct alcor_pll_conf { | ||
| 36 | unsigned int clk_src_freq; | ||
| 37 | unsigned int clk_src_reg; | ||
| 38 | unsigned int min_div; | ||
| 39 | unsigned int max_div; | ||
| 40 | }; | ||
| 41 | |||
| 42 | struct alcor_sdmmc_host { | ||
| 43 | struct device *dev; | ||
| 44 | struct alcor_pci_priv *alcor_pci; | ||
| 45 | |||
| 46 | struct mmc_host *mmc; | ||
| 47 | struct mmc_request *mrq; | ||
| 48 | struct mmc_command *cmd; | ||
| 49 | struct mmc_data *data; | ||
| 50 | unsigned int dma_on:1; | ||
| 51 | unsigned int early_data:1; | ||
| 52 | |||
| 53 | struct mutex cmd_mutex; | ||
| 54 | |||
| 55 | struct delayed_work timeout_work; | ||
| 56 | |||
| 57 | struct sg_mapping_iter sg_miter; /* SG state for PIO */ | ||
| 58 | struct scatterlist *sg; | ||
| 59 | unsigned int blocks; /* remaining PIO blocks */ | ||
| 60 | int sg_count; | ||
| 61 | |||
| 62 | u32 irq_status_sd; | ||
| 63 | unsigned char cur_power_mode; | ||
| 64 | }; | ||
| 65 | |||
| 66 | static const struct alcor_pll_conf alcor_pll_cfg[] = { | ||
| 67 | /* MHZ, CLK src, max div, min div */ | ||
| 68 | { 31250000, AU6601_CLK_31_25_MHZ, 1, 511}, | ||
| 69 | { 48000000, AU6601_CLK_48_MHZ, 1, 511}, | ||
| 70 | {125000000, AU6601_CLK_125_MHZ, 1, 511}, | ||
| 71 | {384000000, AU6601_CLK_384_MHZ, 1, 511}, | ||
| 72 | }; | ||
| 73 | |||
| 74 | static inline void alcor_rmw8(struct alcor_sdmmc_host *host, unsigned int addr, | ||
| 75 | u8 clear, u8 set) | ||
| 76 | { | ||
| 77 | struct alcor_pci_priv *priv = host->alcor_pci; | ||
| 78 | u32 var; | ||
| 79 | |||
| 80 | var = alcor_read8(priv, addr); | ||
| 81 | var &= ~clear; | ||
| 82 | var |= set; | ||
| 83 | alcor_write8(priv, var, addr); | ||
| 84 | } | ||
| 85 | |||
| 86 | /* As soon as irqs are masked, some status updates may be missed. | ||
| 87 | * Use this with care. | ||
| 88 | */ | ||
| 89 | static inline void alcor_mask_sd_irqs(struct alcor_sdmmc_host *host) | ||
| 90 | { | ||
| 91 | struct alcor_pci_priv *priv = host->alcor_pci; | ||
| 92 | |||
| 93 | alcor_write32(priv, 0, AU6601_REG_INT_ENABLE); | ||
| 94 | } | ||
| 95 | |||
| 96 | static inline void alcor_unmask_sd_irqs(struct alcor_sdmmc_host *host) | ||
| 97 | { | ||
| 98 | struct alcor_pci_priv *priv = host->alcor_pci; | ||
| 99 | |||
| 100 | alcor_write32(priv, AU6601_INT_CMD_MASK | AU6601_INT_DATA_MASK | | ||
| 101 | AU6601_INT_CARD_INSERT | AU6601_INT_CARD_REMOVE | | ||
| 102 | AU6601_INT_OVER_CURRENT_ERR, | ||
| 103 | AU6601_REG_INT_ENABLE); | ||
| 104 | } | ||
| 105 | |||
| 106 | static void alcor_reset(struct alcor_sdmmc_host *host, u8 val) | ||
| 107 | { | ||
| 108 | struct alcor_pci_priv *priv = host->alcor_pci; | ||
| 109 | int i; | ||
| 110 | |||
| 111 | alcor_write8(priv, val | AU6601_BUF_CTRL_RESET, | ||
| 112 | AU6601_REG_SW_RESET); | ||
| 113 | for (i = 0; i < 100; i++) { | ||
| 114 | if (!(alcor_read8(priv, AU6601_REG_SW_RESET) & val)) | ||
| 115 | return; | ||
| 116 | udelay(50); | ||
| 117 | } | ||
| 118 | dev_err(host->dev, "%s: timeout\n", __func__); | ||
| 119 | } | ||
| 120 | |||
| 121 | static void alcor_data_set_dma(struct alcor_sdmmc_host *host) | ||
| 122 | { | ||
| 123 | struct alcor_pci_priv *priv = host->alcor_pci; | ||
| 124 | u32 addr; | ||
| 125 | |||
| 126 | if (!host->sg_count) | ||
| 127 | return; | ||
| 128 | |||
| 129 | if (!host->sg) { | ||
| 130 | dev_err(host->dev, "have blocks, but no SG\n"); | ||
| 131 | return; | ||
| 132 | } | ||
| 133 | |||
| 134 | if (!sg_dma_len(host->sg)) { | ||
| 135 | dev_err(host->dev, "DMA SG len == 0\n"); | ||
| 136 | return; | ||
| 137 | } | ||
| 138 | |||
| 139 | |||
| 140 | addr = (u32)sg_dma_address(host->sg); | ||
| 141 | |||
| 142 | alcor_write32(priv, addr, AU6601_REG_SDMA_ADDR); | ||
| 143 | host->sg = sg_next(host->sg); | ||
| 144 | host->sg_count--; | ||
| 145 | } | ||
| 146 | |||
| 147 | static void alcor_trigger_data_transfer(struct alcor_sdmmc_host *host, | ||
| 148 | bool early) | ||
| 149 | { | ||
| 150 | struct alcor_pci_priv *priv = host->alcor_pci; | ||
| 151 | struct mmc_data *data = host->data; | ||
| 152 | u8 ctrl = 0; | ||
| 153 | |||
| 154 | if (data->flags & MMC_DATA_WRITE) | ||
| 155 | ctrl |= AU6601_DATA_WRITE; | ||
| 156 | |||
| 157 | if (data->host_cookie == COOKIE_MAPPED) { | ||
| 158 | if (host->early_data) { | ||
| 159 | host->early_data = false; | ||
| 160 | return; | ||
| 161 | } | ||
| 162 | |||
| 163 | host->early_data = early; | ||
| 164 | |||
| 165 | alcor_data_set_dma(host); | ||
| 166 | ctrl |= AU6601_DATA_DMA_MODE; | ||
| 167 | host->dma_on = 1; | ||
| 168 | alcor_write32(priv, data->sg_count * 0x1000, | ||
| 169 | AU6601_REG_BLOCK_SIZE); | ||
| 170 | } else { | ||
| 171 | alcor_write32(priv, data->blksz, AU6601_REG_BLOCK_SIZE); | ||
| 172 | } | ||
| 173 | |||
| 174 | alcor_write8(priv, ctrl | AU6601_DATA_START_XFER, | ||
| 175 | AU6601_DATA_XFER_CTRL); | ||
| 176 | } | ||
| 177 | |||
| 178 | static void alcor_trf_block_pio(struct alcor_sdmmc_host *host, bool read) | ||
| 179 | { | ||
| 180 | struct alcor_pci_priv *priv = host->alcor_pci; | ||
| 181 | size_t blksize, len; | ||
| 182 | u8 *buf; | ||
| 183 | |||
| 184 | if (!host->blocks) | ||
| 185 | return; | ||
| 186 | |||
| 187 | if (host->dma_on) { | ||
| 188 | dev_err(host->dev, "configured DMA but got PIO request.\n"); | ||
| 189 | return; | ||
| 190 | } | ||
| 191 | |||
| 192 | if (!!(host->data->flags & MMC_DATA_READ) != read) { | ||
| 193 | dev_err(host->dev, "got unexpected direction %i != %i\n", | ||
| 194 | !!(host->data->flags & MMC_DATA_READ), read); | ||
| 195 | } | ||
| 196 | |||
| 197 | if (!sg_miter_next(&host->sg_miter)) | ||
| 198 | return; | ||
| 199 | |||
| 200 | blksize = host->data->blksz; | ||
| 201 | len = min(host->sg_miter.length, blksize); | ||
| 202 | |||
| 203 | dev_dbg(host->dev, "PIO, %s block size: 0x%zx\n", | ||
| 204 | read ? "read" : "write", blksize); | ||
| 205 | |||
| 206 | host->sg_miter.consumed = len; | ||
| 207 | host->blocks--; | ||
| 208 | |||
| 209 | buf = host->sg_miter.addr; | ||
| 210 | |||
| 211 | if (read) | ||
| 212 | ioread32_rep(priv->iobase + AU6601_REG_BUFFER, buf, len >> 2); | ||
| 213 | else | ||
| 214 | iowrite32_rep(priv->iobase + AU6601_REG_BUFFER, buf, len >> 2); | ||
| 215 | |||
| 216 | sg_miter_stop(&host->sg_miter); | ||
| 217 | } | ||
| 218 | |||
| 219 | static void alcor_prepare_sg_miter(struct alcor_sdmmc_host *host) | ||
| 220 | { | ||
| 221 | unsigned int flags = SG_MITER_ATOMIC; | ||
| 222 | struct mmc_data *data = host->data; | ||
| 223 | |||
| 224 | if (data->flags & MMC_DATA_READ) | ||
| 225 | flags |= SG_MITER_TO_SG; | ||
| 226 | else | ||
| 227 | flags |= SG_MITER_FROM_SG; | ||
| 228 | sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); | ||
| 229 | } | ||
| 230 | |||
| 231 | static void alcor_prepare_data(struct alcor_sdmmc_host *host, | ||
| 232 | struct mmc_command *cmd) | ||
| 233 | { | ||
| 234 | struct mmc_data *data = cmd->data; | ||
| 235 | |||
| 236 | if (!data) | ||
| 237 | return; | ||
| 238 | |||
| 239 | |||
| 240 | host->data = data; | ||
| 241 | host->data->bytes_xfered = 0; | ||
| 242 | host->blocks = data->blocks; | ||
| 243 | host->sg = data->sg; | ||
| 244 | host->sg_count = data->sg_count; | ||
| 245 | dev_dbg(host->dev, "prepare DATA: sg %i, blocks: %i\n", | ||
| 246 | host->sg_count, host->blocks); | ||
| 247 | |||
| 248 | if (data->host_cookie != COOKIE_MAPPED) | ||
| 249 | alcor_prepare_sg_miter(host); | ||
| 250 | |||
| 251 | alcor_trigger_data_transfer(host, true); | ||
| 252 | } | ||
| 253 | |||
| 254 | static void alcor_send_cmd(struct alcor_sdmmc_host *host, | ||
| 255 | struct mmc_command *cmd, bool set_timeout) | ||
| 256 | { | ||
| 257 | struct alcor_pci_priv *priv = host->alcor_pci; | ||
| 258 | unsigned long timeout = 0; | ||
| 259 | u8 ctrl = 0; | ||
| 260 | |||
| 261 | host->cmd = cmd; | ||
| 262 | alcor_prepare_data(host, cmd); | ||
| 263 | |||
| 264 | dev_dbg(host->dev, "send CMD. opcode: 0x%02x, arg; 0x%08x\n", | ||
| 265 | cmd->opcode, cmd->arg); | ||
| 266 | alcor_write8(priv, cmd->opcode | 0x40, AU6601_REG_CMD_OPCODE); | ||
| 267 | alcor_write32be(priv, cmd->arg, AU6601_REG_CMD_ARG); | ||
| 268 | |||
| 269 | switch (mmc_resp_type(cmd)) { | ||
| 270 | case MMC_RSP_NONE: | ||
| 271 | ctrl = AU6601_CMD_NO_RESP; | ||
| 272 | break; | ||
| 273 | case MMC_RSP_R1: | ||
| 274 | ctrl = AU6601_CMD_6_BYTE_CRC; | ||
| 275 | break; | ||
| 276 | case MMC_RSP_R1B: | ||
| 277 | ctrl = AU6601_CMD_6_BYTE_CRC | AU6601_CMD_STOP_WAIT_RDY; | ||
| 278 | break; | ||
| 279 | case MMC_RSP_R2: | ||
| 280 | ctrl = AU6601_CMD_17_BYTE_CRC; | ||
| 281 | break; | ||
| 282 | case MMC_RSP_R3: | ||
| 283 | ctrl = AU6601_CMD_6_BYTE_WO_CRC; | ||
| 284 | break; | ||
| 285 | default: | ||
| 286 | dev_err(host->dev, "%s: cmd->flag (0x%02x) is not valid\n", | ||
| 287 | mmc_hostname(host->mmc), mmc_resp_type(cmd)); | ||
| 288 | break; | ||
| 289 | } | ||
| 290 | |||
| 291 | if (set_timeout) { | ||
| 292 | if (!cmd->data && cmd->busy_timeout) | ||
| 293 | timeout = cmd->busy_timeout; | ||
| 294 | else | ||
| 295 | timeout = 10000; | ||
| 296 | |||
| 297 | schedule_delayed_work(&host->timeout_work, | ||
| 298 | msecs_to_jiffies(timeout)); | ||
| 299 | } | ||
| 300 | |||
| 301 | dev_dbg(host->dev, "xfer ctrl: 0x%02x; timeout: %lu\n", ctrl, timeout); | ||
| 302 | alcor_write8(priv, ctrl | AU6601_CMD_START_XFER, | ||
| 303 | AU6601_CMD_XFER_CTRL); | ||
| 304 | } | ||
| 305 | |||
| 306 | static void alcor_request_complete(struct alcor_sdmmc_host *host, | ||
| 307 | bool cancel_timeout) | ||
| 308 | { | ||
| 309 | struct mmc_request *mrq; | ||
| 310 | |||
| 311 | /* | ||
| 312 | * If this work gets rescheduled while running, it will | ||
| 313 | * be run again afterwards but without any active request. | ||
| 314 | */ | ||
| 315 | if (!host->mrq) | ||
| 316 | return; | ||
| 317 | |||
| 318 | if (cancel_timeout) | ||
| 319 | cancel_delayed_work(&host->timeout_work); | ||
| 320 | |||
| 321 | mrq = host->mrq; | ||
| 322 | |||
| 323 | host->mrq = NULL; | ||
| 324 | host->cmd = NULL; | ||
| 325 | host->data = NULL; | ||
| 326 | host->dma_on = 0; | ||
| 327 | |||
| 328 | mmc_request_done(host->mmc, mrq); | ||
| 329 | } | ||
| 330 | |||
| 331 | static void alcor_finish_data(struct alcor_sdmmc_host *host) | ||
| 332 | { | ||
| 333 | struct mmc_data *data; | ||
| 334 | |||
| 335 | data = host->data; | ||
| 336 | host->data = NULL; | ||
| 337 | host->dma_on = 0; | ||
| 338 | |||
| 339 | /* | ||
| 340 | * The specification states that the block count register must | ||
| 341 | * be updated, but it does not specify at what point in the | ||
| 342 | * data flow. That makes the register entirely useless to read | ||
| 343 | * back so we have to assume that nothing made it to the card | ||
| 344 | * in the event of an error. | ||
| 345 | */ | ||
| 346 | if (data->error) | ||
| 347 | data->bytes_xfered = 0; | ||
| 348 | else | ||
| 349 | data->bytes_xfered = data->blksz * data->blocks; | ||
| 350 | |||
| 351 | /* | ||
| 352 | * Need to send CMD12 if - | ||
| 353 | * a) open-ended multiblock transfer (no CMD23) | ||
| 354 | * b) error in multiblock transfer | ||
| 355 | */ | ||
| 356 | if (data->stop && | ||
| 357 | (data->error || | ||
| 358 | !host->mrq->sbc)) { | ||
| 359 | |||
| 360 | /* | ||
| 361 | * The controller needs a reset of internal state machines | ||
| 362 | * upon error conditions. | ||
| 363 | */ | ||
| 364 | if (data->error) | ||
| 365 | alcor_reset(host, AU6601_RESET_CMD | AU6601_RESET_DATA); | ||
| 366 | |||
| 367 | alcor_unmask_sd_irqs(host); | ||
| 368 | alcor_send_cmd(host, data->stop, false); | ||
| 369 | return; | ||
| 370 | } | ||
| 371 | |||
| 372 | alcor_request_complete(host, 1); | ||
| 373 | } | ||
| 374 | |||
| 375 | static void alcor_err_irq(struct alcor_sdmmc_host *host, u32 intmask) | ||
| 376 | { | ||
| 377 | dev_dbg(host->dev, "ERR IRQ %x\n", intmask); | ||
| 378 | |||
| 379 | if (host->cmd) { | ||
| 380 | if (intmask & AU6601_INT_CMD_TIMEOUT_ERR) | ||
| 381 | host->cmd->error = -ETIMEDOUT; | ||
| 382 | else | ||
| 383 | host->cmd->error = -EILSEQ; | ||
| 384 | } | ||
| 385 | |||
| 386 | if (host->data) { | ||
| 387 | if (intmask & AU6601_INT_DATA_TIMEOUT_ERR) | ||
| 388 | host->data->error = -ETIMEDOUT; | ||
| 389 | else | ||
| 390 | host->data->error = -EILSEQ; | ||
| 391 | |||
| 392 | host->data->bytes_xfered = 0; | ||
| 393 | } | ||
| 394 | |||
| 395 | alcor_reset(host, AU6601_RESET_CMD | AU6601_RESET_DATA); | ||
| 396 | alcor_request_complete(host, 1); | ||
| 397 | } | ||
| 398 | |||
| 399 | static int alcor_cmd_irq_done(struct alcor_sdmmc_host *host, u32 intmask) | ||
| 400 | { | ||
| 401 | struct alcor_pci_priv *priv = host->alcor_pci; | ||
| 402 | |||
| 403 | intmask &= AU6601_INT_CMD_END; | ||
| 404 | |||
| 405 | if (!intmask) | ||
| 406 | return true; | ||
| 407 | |||
| 408 | /* got CMD_END but no CMD is in progress, wake thread an process the | ||
| 409 | * error | ||
| 410 | */ | ||
| 411 | if (!host->cmd) | ||
| 412 | return false; | ||
| 413 | |||
| 414 | if (host->cmd->flags & MMC_RSP_PRESENT) { | ||
| 415 | struct mmc_command *cmd = host->cmd; | ||
| 416 | |||
| 417 | cmd->resp[0] = alcor_read32be(priv, AU6601_REG_CMD_RSP0); | ||
| 418 | dev_dbg(host->dev, "RSP0: 0x%04x\n", cmd->resp[0]); | ||
| 419 | if (host->cmd->flags & MMC_RSP_136) { | ||
| 420 | cmd->resp[1] = | ||
| 421 | alcor_read32be(priv, AU6601_REG_CMD_RSP1); | ||
| 422 | cmd->resp[2] = | ||
| 423 | alcor_read32be(priv, AU6601_REG_CMD_RSP2); | ||
| 424 | cmd->resp[3] = | ||
| 425 | alcor_read32be(priv, AU6601_REG_CMD_RSP3); | ||
| 426 | dev_dbg(host->dev, "RSP1,2,3: 0x%04x 0x%04x 0x%04x\n", | ||
| 427 | cmd->resp[1], cmd->resp[2], cmd->resp[3]); | ||
| 428 | } | ||
| 429 | |||
| 430 | } | ||
| 431 | |||
| 432 | host->cmd->error = 0; | ||
| 433 | |||
| 434 | /* Processed actual command. */ | ||
| 435 | if (!host->data) | ||
| 436 | return false; | ||
| 437 | |||
| 438 | alcor_trigger_data_transfer(host, false); | ||
| 439 | host->cmd = NULL; | ||
| 440 | return true; | ||
| 441 | } | ||
| 442 | |||
| 443 | static void alcor_cmd_irq_thread(struct alcor_sdmmc_host *host, u32 intmask) | ||
| 444 | { | ||
| 445 | intmask &= AU6601_INT_CMD_END; | ||
| 446 | |||
| 447 | if (!intmask) | ||
| 448 | return; | ||
| 449 | |||
| 450 | if (!host->cmd && intmask & AU6601_INT_CMD_END) { | ||
| 451 | dev_dbg(host->dev, "Got command interrupt 0x%08x even though no command operation was in progress.\n", | ||
| 452 | intmask); | ||
| 453 | } | ||
| 454 | |||
| 455 | /* Processed actual command. */ | ||
| 456 | if (!host->data) | ||
| 457 | alcor_request_complete(host, 1); | ||
| 458 | else | ||
| 459 | alcor_trigger_data_transfer(host, false); | ||
| 460 | host->cmd = NULL; | ||
| 461 | } | ||
| 462 | |||
| 463 | static int alcor_data_irq_done(struct alcor_sdmmc_host *host, u32 intmask) | ||
| 464 | { | ||
| 465 | u32 tmp; | ||
| 466 | |||
| 467 | intmask &= AU6601_INT_DATA_MASK; | ||
| 468 | |||
| 469 | /* nothing here to do */ | ||
| 470 | if (!intmask) | ||
| 471 | return 1; | ||
| 472 | |||
| 473 | /* we was too fast and got DATA_END after it was processed? | ||
| 474 | * lets ignore it for now. | ||
| 475 | */ | ||
| 476 | if (!host->data && intmask == AU6601_INT_DATA_END) | ||
| 477 | return 1; | ||
| 478 | |||
| 479 | /* looks like an error, so lets handle it. */ | ||
| 480 | if (!host->data) | ||
| 481 | return 0; | ||
| 482 | |||
| 483 | tmp = intmask & (AU6601_INT_READ_BUF_RDY | AU6601_INT_WRITE_BUF_RDY | ||
| 484 | | AU6601_INT_DMA_END); | ||
| 485 | switch (tmp) { | ||
| 486 | case 0: | ||
| 487 | break; | ||
| 488 | case AU6601_INT_READ_BUF_RDY: | ||
| 489 | alcor_trf_block_pio(host, true); | ||
| 490 | if (!host->blocks) | ||
| 491 | break; | ||
| 492 | alcor_trigger_data_transfer(host, false); | ||
| 493 | return 1; | ||
| 494 | case AU6601_INT_WRITE_BUF_RDY: | ||
| 495 | alcor_trf_block_pio(host, false); | ||
| 496 | if (!host->blocks) | ||
| 497 | break; | ||
| 498 | alcor_trigger_data_transfer(host, false); | ||
| 499 | return 1; | ||
| 500 | case AU6601_INT_DMA_END: | ||
| 501 | if (!host->sg_count) | ||
| 502 | break; | ||
| 503 | |||
| 504 | alcor_data_set_dma(host); | ||
| 505 | break; | ||
| 506 | default: | ||
| 507 | dev_err(host->dev, "Got READ_BUF_RDY and WRITE_BUF_RDY at same time\n"); | ||
| 508 | break; | ||
| 509 | } | ||
| 510 | |||
| 511 | if (intmask & AU6601_INT_DATA_END) | ||
| 512 | return 0; | ||
| 513 | |||
| 514 | return 1; | ||
| 515 | } | ||
| 516 | |||
| 517 | static void alcor_data_irq_thread(struct alcor_sdmmc_host *host, u32 intmask) | ||
| 518 | { | ||
| 519 | intmask &= AU6601_INT_DATA_MASK; | ||
| 520 | |||
| 521 | if (!intmask) | ||
| 522 | return; | ||
| 523 | |||
| 524 | if (!host->data) { | ||
| 525 | dev_dbg(host->dev, "Got data interrupt 0x%08x even though no data operation was in progress.\n", | ||
| 526 | intmask); | ||
| 527 | alcor_reset(host, AU6601_RESET_DATA); | ||
| 528 | return; | ||
| 529 | } | ||
| 530 | |||
| 531 | if (alcor_data_irq_done(host, intmask)) | ||
| 532 | return; | ||
| 533 | |||
| 534 | if ((intmask & AU6601_INT_DATA_END) || !host->blocks || | ||
| 535 | (host->dma_on && !host->sg_count)) | ||
| 536 | alcor_finish_data(host); | ||
| 537 | } | ||
| 538 | |||
| 539 | static void alcor_cd_irq(struct alcor_sdmmc_host *host, u32 intmask) | ||
| 540 | { | ||
| 541 | dev_dbg(host->dev, "card %s\n", | ||
| 542 | intmask & AU6601_INT_CARD_REMOVE ? "removed" : "inserted"); | ||
| 543 | |||
| 544 | if (host->mrq) { | ||
| 545 | dev_dbg(host->dev, "cancel all pending tasks.\n"); | ||
| 546 | |||
| 547 | if (host->data) | ||
| 548 | host->data->error = -ENOMEDIUM; | ||
| 549 | |||
| 550 | if (host->cmd) | ||
| 551 | host->cmd->error = -ENOMEDIUM; | ||
| 552 | else | ||
| 553 | host->mrq->cmd->error = -ENOMEDIUM; | ||
| 554 | |||
| 555 | alcor_request_complete(host, 1); | ||
| 556 | } | ||
| 557 | |||
| 558 | mmc_detect_change(host->mmc, msecs_to_jiffies(1)); | ||
| 559 | } | ||
| 560 | |||
| 561 | static irqreturn_t alcor_irq_thread(int irq, void *d) | ||
| 562 | { | ||
| 563 | struct alcor_sdmmc_host *host = d; | ||
| 564 | irqreturn_t ret = IRQ_HANDLED; | ||
| 565 | u32 intmask, tmp; | ||
| 566 | |||
| 567 | mutex_lock(&host->cmd_mutex); | ||
| 568 | |||
| 569 | intmask = host->irq_status_sd; | ||
| 570 | |||
| 571 | /* some thing bad */ | ||
| 572 | if (unlikely(!intmask || AU6601_INT_ALL_MASK == intmask)) { | ||
| 573 | dev_dbg(host->dev, "unexpected IRQ: 0x%04x\n", intmask); | ||
| 574 | ret = IRQ_NONE; | ||
| 575 | goto exit; | ||
| 576 | } | ||
| 577 | |||
| 578 | tmp = intmask & (AU6601_INT_CMD_MASK | AU6601_INT_DATA_MASK); | ||
| 579 | if (tmp) { | ||
| 580 | if (tmp & AU6601_INT_ERROR_MASK) | ||
| 581 | alcor_err_irq(host, tmp); | ||
| 582 | else { | ||
| 583 | alcor_cmd_irq_thread(host, tmp); | ||
| 584 | alcor_data_irq_thread(host, tmp); | ||
| 585 | } | ||
| 586 | intmask &= ~(AU6601_INT_CMD_MASK | AU6601_INT_DATA_MASK); | ||
| 587 | } | ||
| 588 | |||
| 589 | if (intmask & (AU6601_INT_CARD_INSERT | AU6601_INT_CARD_REMOVE)) { | ||
| 590 | alcor_cd_irq(host, intmask); | ||
| 591 | intmask &= ~(AU6601_INT_CARD_INSERT | AU6601_INT_CARD_REMOVE); | ||
| 592 | } | ||
| 593 | |||
| 594 | if (intmask & AU6601_INT_OVER_CURRENT_ERR) { | ||
| 595 | dev_warn(host->dev, | ||
| 596 | "warning: over current detected!\n"); | ||
| 597 | intmask &= ~AU6601_INT_OVER_CURRENT_ERR; | ||
| 598 | } | ||
| 599 | |||
| 600 | if (intmask) | ||
| 601 | dev_dbg(host->dev, "got not handled IRQ: 0x%04x\n", intmask); | ||
| 602 | |||
| 603 | exit: | ||
| 604 | mutex_unlock(&host->cmd_mutex); | ||
| 605 | alcor_unmask_sd_irqs(host); | ||
| 606 | return ret; | ||
| 607 | } | ||
| 608 | |||
| 609 | |||
| 610 | static irqreturn_t alcor_irq(int irq, void *d) | ||
| 611 | { | ||
| 612 | struct alcor_sdmmc_host *host = d; | ||
| 613 | struct alcor_pci_priv *priv = host->alcor_pci; | ||
| 614 | u32 status, tmp; | ||
| 615 | irqreturn_t ret; | ||
| 616 | int cmd_done, data_done; | ||
| 617 | |||
| 618 | status = alcor_read32(priv, AU6601_REG_INT_STATUS); | ||
| 619 | if (!status) | ||
| 620 | return IRQ_NONE; | ||
| 621 | |||
| 622 | alcor_write32(priv, status, AU6601_REG_INT_STATUS); | ||
| 623 | |||
| 624 | tmp = status & (AU6601_INT_READ_BUF_RDY | AU6601_INT_WRITE_BUF_RDY | ||
| 625 | | AU6601_INT_DATA_END | AU6601_INT_DMA_END | ||
| 626 | | AU6601_INT_CMD_END); | ||
| 627 | if (tmp == status) { | ||
| 628 | cmd_done = alcor_cmd_irq_done(host, tmp); | ||
| 629 | data_done = alcor_data_irq_done(host, tmp); | ||
| 630 | /* use fast path for simple tasks */ | ||
| 631 | if (cmd_done && data_done) { | ||
| 632 | ret = IRQ_HANDLED; | ||
| 633 | goto alcor_irq_done; | ||
| 634 | } | ||
| 635 | } | ||
| 636 | |||
| 637 | host->irq_status_sd = status; | ||
| 638 | ret = IRQ_WAKE_THREAD; | ||
| 639 | alcor_mask_sd_irqs(host); | ||
| 640 | alcor_irq_done: | ||
| 641 | return ret; | ||
| 642 | } | ||
| 643 | |||
| 644 | static void alcor_set_clock(struct alcor_sdmmc_host *host, unsigned int clock) | ||
| 645 | { | ||
| 646 | struct alcor_pci_priv *priv = host->alcor_pci; | ||
| 647 | int i, diff = 0x7fffffff, tmp_clock = 0; | ||
| 648 | u16 clk_src = 0; | ||
| 649 | u8 clk_div = 0; | ||
| 650 | |||
| 651 | if (clock == 0) { | ||
| 652 | alcor_write16(priv, 0, AU6601_CLK_SELECT); | ||
| 653 | return; | ||
| 654 | } | ||
| 655 | |||
| 656 | for (i = 0; i < ARRAY_SIZE(alcor_pll_cfg); i++) { | ||
| 657 | unsigned int tmp_div, tmp_diff; | ||
| 658 | const struct alcor_pll_conf *cfg = &alcor_pll_cfg[i]; | ||
| 659 | |||
| 660 | tmp_div = DIV_ROUND_UP(cfg->clk_src_freq, clock); | ||
| 661 | if (cfg->min_div > tmp_div || tmp_div > cfg->max_div) | ||
| 662 | continue; | ||
| 663 | |||
| 664 | tmp_clock = DIV_ROUND_UP(cfg->clk_src_freq, tmp_div); | ||
| 665 | tmp_diff = abs(clock - tmp_clock); | ||
| 666 | |||
| 667 | if (tmp_diff >= 0 && tmp_diff < diff) { | ||
| 668 | diff = tmp_diff; | ||
| 669 | clk_src = cfg->clk_src_reg; | ||
| 670 | clk_div = tmp_div; | ||
| 671 | } | ||
| 672 | } | ||
| 673 | |||
| 674 | clk_src |= ((clk_div - 1) << 8); | ||
| 675 | clk_src |= AU6601_CLK_ENABLE; | ||
| 676 | |||
| 677 | dev_dbg(host->dev, "set freq %d cal freq %d, use div %d, mod %x\n", | ||
| 678 | clock, tmp_clock, clk_div, clk_src); | ||
| 679 | |||
| 680 | alcor_write16(priv, clk_src, AU6601_CLK_SELECT); | ||
| 681 | |||
| 682 | } | ||
| 683 | |||
| 684 | static void alcor_set_timing(struct mmc_host *mmc, struct mmc_ios *ios) | ||
| 685 | { | ||
| 686 | struct alcor_sdmmc_host *host = mmc_priv(mmc); | ||
| 687 | |||
| 688 | if (ios->timing == MMC_TIMING_LEGACY) { | ||
| 689 | alcor_rmw8(host, AU6601_CLK_DELAY, | ||
| 690 | AU6601_CLK_POSITIVE_EDGE_ALL, 0); | ||
| 691 | } else { | ||
| 692 | alcor_rmw8(host, AU6601_CLK_DELAY, | ||
| 693 | 0, AU6601_CLK_POSITIVE_EDGE_ALL); | ||
| 694 | } | ||
| 695 | } | ||
| 696 | |||
| 697 | static void alcor_set_bus_width(struct mmc_host *mmc, struct mmc_ios *ios) | ||
| 698 | { | ||
| 699 | struct alcor_sdmmc_host *host = mmc_priv(mmc); | ||
| 700 | struct alcor_pci_priv *priv = host->alcor_pci; | ||
| 701 | |||
| 702 | if (ios->bus_width == MMC_BUS_WIDTH_1) { | ||
| 703 | alcor_write8(priv, 0, AU6601_REG_BUS_CTRL); | ||
| 704 | } else if (ios->bus_width == MMC_BUS_WIDTH_4) { | ||
| 705 | alcor_write8(priv, AU6601_BUS_WIDTH_4BIT, | ||
| 706 | AU6601_REG_BUS_CTRL); | ||
| 707 | } else | ||
| 708 | dev_err(host->dev, "Unknown BUS mode\n"); | ||
| 709 | |||
| 710 | } | ||
| 711 | |||
| 712 | static int alcor_card_busy(struct mmc_host *mmc) | ||
| 713 | { | ||
| 714 | struct alcor_sdmmc_host *host = mmc_priv(mmc); | ||
| 715 | struct alcor_pci_priv *priv = host->alcor_pci; | ||
| 716 | u8 status; | ||
| 717 | |||
| 718 | /* Check whether dat[0:3] low */ | ||
| 719 | status = alcor_read8(priv, AU6601_DATA_PIN_STATE); | ||
| 720 | |||
| 721 | return !(status & AU6601_BUS_STAT_DAT_MASK); | ||
| 722 | } | ||
| 723 | |||
| 724 | static int alcor_get_cd(struct mmc_host *mmc) | ||
| 725 | { | ||
| 726 | struct alcor_sdmmc_host *host = mmc_priv(mmc); | ||
| 727 | struct alcor_pci_priv *priv = host->alcor_pci; | ||
| 728 | u8 detect; | ||
| 729 | |||
| 730 | detect = alcor_read8(priv, AU6601_DETECT_STATUS) | ||
| 731 | & AU6601_DETECT_STATUS_M; | ||
| 732 | /* check if card is present then send command and data */ | ||
| 733 | return (detect == AU6601_SD_DETECTED); | ||
| 734 | } | ||
| 735 | |||
| 736 | static int alcor_get_ro(struct mmc_host *mmc) | ||
| 737 | { | ||
| 738 | struct alcor_sdmmc_host *host = mmc_priv(mmc); | ||
| 739 | struct alcor_pci_priv *priv = host->alcor_pci; | ||
| 740 | u8 status; | ||
| 741 | |||
| 742 | /* get write protect pin status */ | ||
| 743 | status = alcor_read8(priv, AU6601_INTERFACE_MODE_CTRL); | ||
| 744 | |||
| 745 | return !!(status & AU6601_SD_CARD_WP); | ||
| 746 | } | ||
| 747 | |||
| 748 | static void alcor_request(struct mmc_host *mmc, struct mmc_request *mrq) | ||
| 749 | { | ||
| 750 | struct alcor_sdmmc_host *host = mmc_priv(mmc); | ||
| 751 | |||
| 752 | mutex_lock(&host->cmd_mutex); | ||
| 753 | |||
| 754 | host->mrq = mrq; | ||
| 755 | |||
| 756 | /* check if card is present then send command and data */ | ||
| 757 | if (alcor_get_cd(mmc)) | ||
| 758 | alcor_send_cmd(host, mrq->cmd, true); | ||
| 759 | else { | ||
| 760 | mrq->cmd->error = -ENOMEDIUM; | ||
| 761 | alcor_request_complete(host, 1); | ||
| 762 | } | ||
| 763 | |||
| 764 | mutex_unlock(&host->cmd_mutex); | ||
| 765 | } | ||
| 766 | |||
| 767 | static void alcor_pre_req(struct mmc_host *mmc, | ||
| 768 | struct mmc_request *mrq) | ||
| 769 | { | ||
| 770 | struct alcor_sdmmc_host *host = mmc_priv(mmc); | ||
| 771 | struct mmc_data *data = mrq->data; | ||
| 772 | struct mmc_command *cmd = mrq->cmd; | ||
| 773 | struct scatterlist *sg; | ||
| 774 | unsigned int i, sg_len; | ||
| 775 | |||
| 776 | if (!data || !cmd) | ||
| 777 | return; | ||
| 778 | |||
| 779 | data->host_cookie = COOKIE_UNMAPPED; | ||
| 780 | |||
| 781 | /* FIXME: looks like the DMA engine works only with CMD18 */ | ||
| 782 | if (cmd->opcode != 18) | ||
| 783 | return; | ||
| 784 | /* | ||
| 785 | * We don't do DMA on "complex" transfers, i.e. with | ||
| 786 | * non-word-aligned buffers or lengths. Also, we don't bother | ||
| 787 | * with all the DMA setup overhead for short transfers. | ||
| 788 | */ | ||
| 789 | if (data->blocks * data->blksz < AU6601_MAX_DMA_BLOCK_SIZE) | ||
| 790 | return; | ||
| 791 | |||
| 792 | if (data->blksz & 3) | ||
| 793 | return; | ||
| 794 | |||
| 795 | for_each_sg(data->sg, sg, data->sg_len, i) { | ||
| 796 | if (sg->length != AU6601_MAX_DMA_BLOCK_SIZE) | ||
| 797 | return; | ||
| 798 | } | ||
| 799 | |||
| 800 | /* This data might be unmapped at this time */ | ||
| 801 | |||
| 802 | sg_len = dma_map_sg(host->dev, data->sg, data->sg_len, | ||
| 803 | mmc_get_dma_dir(data)); | ||
| 804 | if (sg_len) | ||
| 805 | data->host_cookie = COOKIE_MAPPED; | ||
| 806 | |||
| 807 | data->sg_count = sg_len; | ||
| 808 | } | ||
| 809 | |||
| 810 | static void alcor_post_req(struct mmc_host *mmc, | ||
| 811 | struct mmc_request *mrq, | ||
| 812 | int err) | ||
| 813 | { | ||
| 814 | struct alcor_sdmmc_host *host = mmc_priv(mmc); | ||
| 815 | struct mmc_data *data = mrq->data; | ||
| 816 | |||
| 817 | if (!data) | ||
| 818 | return; | ||
| 819 | |||
| 820 | if (data->host_cookie == COOKIE_MAPPED) { | ||
| 821 | dma_unmap_sg(host->dev, | ||
| 822 | data->sg, | ||
| 823 | data->sg_len, | ||
| 824 | mmc_get_dma_dir(data)); | ||
| 825 | } | ||
| 826 | |||
| 827 | data->host_cookie = COOKIE_UNMAPPED; | ||
| 828 | } | ||
| 829 | |||
| 830 | static void alcor_set_power_mode(struct mmc_host *mmc, struct mmc_ios *ios) | ||
| 831 | { | ||
| 832 | struct alcor_sdmmc_host *host = mmc_priv(mmc); | ||
| 833 | struct alcor_pci_priv *priv = host->alcor_pci; | ||
| 834 | |||
| 835 | switch (ios->power_mode) { | ||
| 836 | case MMC_POWER_OFF: | ||
| 837 | alcor_set_clock(host, ios->clock); | ||
| 838 | /* set all pins to input */ | ||
| 839 | alcor_write8(priv, 0, AU6601_OUTPUT_ENABLE); | ||
| 840 | /* turn of VDD */ | ||
| 841 | alcor_write8(priv, 0, AU6601_POWER_CONTROL); | ||
| 842 | break; | ||
| 843 | case MMC_POWER_UP: | ||
| 844 | break; | ||
| 845 | case MMC_POWER_ON: | ||
| 846 | /* This is most trickiest part. The order and timings of | ||
| 847 | * instructions seems to play important role. Any changes may | ||
| 848 | * confuse internal state engine if this HW. | ||
| 849 | * FIXME: If we will ever get access to documentation, then this | ||
| 850 | * part should be reviewed again. | ||
| 851 | */ | ||
| 852 | |||
| 853 | /* enable SD card mode */ | ||
| 854 | alcor_write8(priv, AU6601_SD_CARD, | ||
| 855 | AU6601_ACTIVE_CTRL); | ||
| 856 | /* set signal voltage to 3.3V */ | ||
| 857 | alcor_write8(priv, 0, AU6601_OPT); | ||
| 858 | /* no documentation about clk delay, for now just try to mimic | ||
| 859 | * original driver. | ||
| 860 | */ | ||
| 861 | alcor_write8(priv, 0x20, AU6601_CLK_DELAY); | ||
| 862 | /* set BUS width to 1 bit */ | ||
| 863 | alcor_write8(priv, 0, AU6601_REG_BUS_CTRL); | ||
| 864 | /* set CLK first time */ | ||
| 865 | alcor_set_clock(host, ios->clock); | ||
| 866 | /* power on VDD */ | ||
| 867 | alcor_write8(priv, AU6601_SD_CARD, | ||
| 868 | AU6601_POWER_CONTROL); | ||
| 869 | /* wait until the CLK will get stable */ | ||
| 870 | mdelay(20); | ||
| 871 | /* set CLK again, mimic original driver. */ | ||
| 872 | alcor_set_clock(host, ios->clock); | ||
| 873 | |||
| 874 | /* enable output */ | ||
| 875 | alcor_write8(priv, AU6601_SD_CARD, | ||
| 876 | AU6601_OUTPUT_ENABLE); | ||
| 877 | /* The clk will not work on au6621. We need to trigger data | ||
| 878 | * transfer. | ||
| 879 | */ | ||
| 880 | alcor_write8(priv, AU6601_DATA_WRITE, | ||
| 881 | AU6601_DATA_XFER_CTRL); | ||
| 882 | /* configure timeout. Not clear what exactly it means. */ | ||
| 883 | alcor_write8(priv, 0x7d, AU6601_TIME_OUT_CTRL); | ||
| 884 | mdelay(100); | ||
| 885 | break; | ||
| 886 | default: | ||
| 887 | dev_err(host->dev, "Unknown power parameter\n"); | ||
| 888 | } | ||
| 889 | } | ||
| 890 | |||
| 891 | static void alcor_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | ||
| 892 | { | ||
| 893 | struct alcor_sdmmc_host *host = mmc_priv(mmc); | ||
| 894 | |||
| 895 | mutex_lock(&host->cmd_mutex); | ||
| 896 | |||
| 897 | dev_dbg(host->dev, "set ios. bus width: %x, power mode: %x\n", | ||
| 898 | ios->bus_width, ios->power_mode); | ||
| 899 | |||
| 900 | if (ios->power_mode != host->cur_power_mode) { | ||
| 901 | alcor_set_power_mode(mmc, ios); | ||
| 902 | host->cur_power_mode = ios->power_mode; | ||
| 903 | } else { | ||
| 904 | alcor_set_timing(mmc, ios); | ||
| 905 | alcor_set_bus_width(mmc, ios); | ||
| 906 | alcor_set_clock(host, ios->clock); | ||
| 907 | } | ||
| 908 | |||
| 909 | mutex_unlock(&host->cmd_mutex); | ||
| 910 | } | ||
| 911 | |||
| 912 | static int alcor_signal_voltage_switch(struct mmc_host *mmc, | ||
| 913 | struct mmc_ios *ios) | ||
| 914 | { | ||
| 915 | struct alcor_sdmmc_host *host = mmc_priv(mmc); | ||
| 916 | |||
| 917 | mutex_lock(&host->cmd_mutex); | ||
| 918 | |||
| 919 | switch (ios->signal_voltage) { | ||
| 920 | case MMC_SIGNAL_VOLTAGE_330: | ||
| 921 | alcor_rmw8(host, AU6601_OPT, AU6601_OPT_SD_18V, 0); | ||
| 922 | break; | ||
| 923 | case MMC_SIGNAL_VOLTAGE_180: | ||
| 924 | alcor_rmw8(host, AU6601_OPT, 0, AU6601_OPT_SD_18V); | ||
| 925 | break; | ||
| 926 | default: | ||
| 927 | /* No signal voltage switch required */ | ||
| 928 | break; | ||
| 929 | } | ||
| 930 | |||
| 931 | mutex_unlock(&host->cmd_mutex); | ||
| 932 | return 0; | ||
| 933 | } | ||
| 934 | |||
| 935 | static const struct mmc_host_ops alcor_sdc_ops = { | ||
| 936 | .card_busy = alcor_card_busy, | ||
| 937 | .get_cd = alcor_get_cd, | ||
| 938 | .get_ro = alcor_get_ro, | ||
| 939 | .post_req = alcor_post_req, | ||
| 940 | .pre_req = alcor_pre_req, | ||
| 941 | .request = alcor_request, | ||
| 942 | .set_ios = alcor_set_ios, | ||
| 943 | .start_signal_voltage_switch = alcor_signal_voltage_switch, | ||
| 944 | }; | ||
| 945 | |||
| 946 | static void alcor_timeout_timer(struct work_struct *work) | ||
| 947 | { | ||
| 948 | struct delayed_work *d = to_delayed_work(work); | ||
| 949 | struct alcor_sdmmc_host *host = container_of(d, struct alcor_sdmmc_host, | ||
| 950 | timeout_work); | ||
| 951 | mutex_lock(&host->cmd_mutex); | ||
| 952 | |||
| 953 | dev_dbg(host->dev, "triggered timeout\n"); | ||
| 954 | if (host->mrq) { | ||
| 955 | dev_err(host->dev, "Timeout waiting for hardware interrupt.\n"); | ||
| 956 | |||
| 957 | if (host->data) { | ||
| 958 | host->data->error = -ETIMEDOUT; | ||
| 959 | } else { | ||
| 960 | if (host->cmd) | ||
| 961 | host->cmd->error = -ETIMEDOUT; | ||
| 962 | else | ||
| 963 | host->mrq->cmd->error = -ETIMEDOUT; | ||
| 964 | } | ||
| 965 | |||
| 966 | alcor_reset(host, AU6601_RESET_CMD | AU6601_RESET_DATA); | ||
| 967 | alcor_request_complete(host, 0); | ||
| 968 | } | ||
| 969 | |||
| 970 | mmiowb(); | ||
| 971 | mutex_unlock(&host->cmd_mutex); | ||
| 972 | } | ||
| 973 | |||
| 974 | static void alcor_hw_init(struct alcor_sdmmc_host *host) | ||
| 975 | { | ||
| 976 | struct alcor_pci_priv *priv = host->alcor_pci; | ||
| 977 | struct alcor_dev_cfg *cfg = priv->cfg; | ||
| 978 | |||
| 979 | /* FIXME: This part is a mimics HW init of original driver. | ||
| 980 | * If we will ever get access to documentation, then this part | ||
| 981 | * should be reviewed again. | ||
| 982 | */ | ||
| 983 | |||
| 984 | /* reset command state engine */ | ||
| 985 | alcor_reset(host, AU6601_RESET_CMD); | ||
| 986 | |||
| 987 | alcor_write8(priv, 0, AU6601_DMA_BOUNDARY); | ||
| 988 | /* enable sd card mode */ | ||
| 989 | alcor_write8(priv, AU6601_SD_CARD, AU6601_ACTIVE_CTRL); | ||
| 990 | |||
| 991 | /* set BUS width to 1 bit */ | ||
| 992 | alcor_write8(priv, 0, AU6601_REG_BUS_CTRL); | ||
| 993 | |||
| 994 | /* reset data state engine */ | ||
| 995 | alcor_reset(host, AU6601_RESET_DATA); | ||
| 996 | /* Not sure if a voodoo with AU6601_DMA_BOUNDARY is really needed */ | ||
| 997 | alcor_write8(priv, 0, AU6601_DMA_BOUNDARY); | ||
| 998 | |||
| 999 | alcor_write8(priv, 0, AU6601_INTERFACE_MODE_CTRL); | ||
| 1000 | /* not clear what we are doing here. */ | ||
| 1001 | alcor_write8(priv, 0x44, AU6601_PAD_DRIVE0); | ||
| 1002 | alcor_write8(priv, 0x44, AU6601_PAD_DRIVE1); | ||
| 1003 | alcor_write8(priv, 0x00, AU6601_PAD_DRIVE2); | ||
| 1004 | |||
| 1005 | /* for 6601 - dma_boundary; for 6621 - dma_page_cnt | ||
| 1006 | * exact meaning of this register is not clear. | ||
| 1007 | */ | ||
| 1008 | alcor_write8(priv, cfg->dma, AU6601_DMA_BOUNDARY); | ||
| 1009 | |||
| 1010 | /* make sure all pins are set to input and VDD is off */ | ||
| 1011 | alcor_write8(priv, 0, AU6601_OUTPUT_ENABLE); | ||
| 1012 | alcor_write8(priv, 0, AU6601_POWER_CONTROL); | ||
| 1013 | |||
| 1014 | alcor_write8(priv, AU6601_DETECT_EN, AU6601_DETECT_STATUS); | ||
| 1015 | /* now we should be safe to enable IRQs */ | ||
| 1016 | alcor_unmask_sd_irqs(host); | ||
| 1017 | } | ||
| 1018 | |||
| 1019 | static void alcor_hw_uninit(struct alcor_sdmmc_host *host) | ||
| 1020 | { | ||
| 1021 | struct alcor_pci_priv *priv = host->alcor_pci; | ||
| 1022 | |||
| 1023 | alcor_mask_sd_irqs(host); | ||
| 1024 | alcor_reset(host, AU6601_RESET_CMD | AU6601_RESET_DATA); | ||
| 1025 | |||
| 1026 | alcor_write8(priv, 0, AU6601_DETECT_STATUS); | ||
| 1027 | |||
| 1028 | alcor_write8(priv, 0, AU6601_OUTPUT_ENABLE); | ||
| 1029 | alcor_write8(priv, 0, AU6601_POWER_CONTROL); | ||
| 1030 | |||
| 1031 | alcor_write8(priv, 0, AU6601_OPT); | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | static void alcor_init_mmc(struct alcor_sdmmc_host *host) | ||
| 1035 | { | ||
| 1036 | struct mmc_host *mmc = host->mmc; | ||
| 1037 | |||
| 1038 | mmc->f_min = AU6601_MIN_CLOCK; | ||
| 1039 | mmc->f_max = AU6601_MAX_CLOCK; | ||
| 1040 | mmc->ocr_avail = MMC_VDD_33_34; | ||
| 1041 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED | ||
| 1042 | | MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 | ||
| 1043 | | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50; | ||
| 1044 | mmc->caps2 = MMC_CAP2_NO_SDIO; | ||
| 1045 | mmc->ops = &alcor_sdc_ops; | ||
| 1046 | |||
| 1047 | /* Hardware cannot do scatter lists */ | ||
| 1048 | mmc->max_segs = AU6601_MAX_DMA_SEGMENTS; | ||
| 1049 | mmc->max_seg_size = AU6601_MAX_DMA_BLOCK_SIZE; | ||
| 1050 | |||
| 1051 | mmc->max_blk_size = mmc->max_seg_size; | ||
| 1052 | mmc->max_blk_count = mmc->max_segs; | ||
| 1053 | |||
| 1054 | mmc->max_req_size = mmc->max_seg_size * mmc->max_segs; | ||
| 1055 | } | ||
| 1056 | |||
| 1057 | static int alcor_pci_sdmmc_drv_probe(struct platform_device *pdev) | ||
| 1058 | { | ||
| 1059 | struct alcor_pci_priv *priv = pdev->dev.platform_data; | ||
| 1060 | struct mmc_host *mmc; | ||
| 1061 | struct alcor_sdmmc_host *host; | ||
| 1062 | int ret; | ||
| 1063 | |||
| 1064 | mmc = mmc_alloc_host(sizeof(*host), &pdev->dev); | ||
| 1065 | if (!mmc) { | ||
| 1066 | dev_err(&pdev->dev, "Can't allocate MMC\n"); | ||
| 1067 | return -ENOMEM; | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | host = mmc_priv(mmc); | ||
| 1071 | host->mmc = mmc; | ||
| 1072 | host->dev = &pdev->dev; | ||
| 1073 | host->cur_power_mode = MMC_POWER_UNDEFINED; | ||
| 1074 | host->alcor_pci = priv; | ||
| 1075 | |||
| 1076 | /* make sure irqs are disabled */ | ||
| 1077 | alcor_write32(priv, 0, AU6601_REG_INT_ENABLE); | ||
| 1078 | alcor_write32(priv, 0, AU6601_MS_INT_ENABLE); | ||
| 1079 | |||
| 1080 | ret = devm_request_threaded_irq(&pdev->dev, priv->irq, | ||
| 1081 | alcor_irq, alcor_irq_thread, IRQF_SHARED, | ||
| 1082 | DRV_NAME_ALCOR_PCI_SDMMC, host); | ||
| 1083 | |||
| 1084 | if (ret) { | ||
| 1085 | dev_err(&pdev->dev, "Failed to get irq for data line\n"); | ||
| 1086 | return ret; | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | mutex_init(&host->cmd_mutex); | ||
| 1090 | INIT_DELAYED_WORK(&host->timeout_work, alcor_timeout_timer); | ||
| 1091 | |||
| 1092 | alcor_init_mmc(host); | ||
| 1093 | alcor_hw_init(host); | ||
| 1094 | |||
| 1095 | dev_set_drvdata(&pdev->dev, host); | ||
| 1096 | mmc_add_host(mmc); | ||
| 1097 | return 0; | ||
| 1098 | } | ||
| 1099 | |||
| 1100 | static int alcor_pci_sdmmc_drv_remove(struct platform_device *pdev) | ||
| 1101 | { | ||
| 1102 | struct alcor_sdmmc_host *host = dev_get_drvdata(&pdev->dev); | ||
| 1103 | |||
| 1104 | if (cancel_delayed_work_sync(&host->timeout_work)) | ||
| 1105 | alcor_request_complete(host, 0); | ||
| 1106 | |||
| 1107 | alcor_hw_uninit(host); | ||
| 1108 | mmc_remove_host(host->mmc); | ||
| 1109 | mmc_free_host(host->mmc); | ||
| 1110 | |||
| 1111 | return 0; | ||
| 1112 | } | ||
| 1113 | |||
| 1114 | #ifdef CONFIG_PM_SLEEP | ||
| 1115 | static int alcor_pci_sdmmc_suspend(struct device *dev) | ||
| 1116 | { | ||
| 1117 | struct alcor_sdmmc_host *host = dev_get_drvdata(dev); | ||
| 1118 | |||
| 1119 | if (cancel_delayed_work_sync(&host->timeout_work)) | ||
| 1120 | alcor_request_complete(host, 0); | ||
| 1121 | |||
| 1122 | alcor_hw_uninit(host); | ||
| 1123 | |||
| 1124 | return 0; | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | static int alcor_pci_sdmmc_resume(struct device *dev) | ||
| 1128 | { | ||
| 1129 | struct alcor_sdmmc_host *host = dev_get_drvdata(dev); | ||
| 1130 | |||
| 1131 | alcor_hw_init(host); | ||
| 1132 | |||
| 1133 | return 0; | ||
| 1134 | } | ||
| 1135 | #endif /* CONFIG_PM_SLEEP */ | ||
| 1136 | |||
| 1137 | static SIMPLE_DEV_PM_OPS(alcor_mmc_pm_ops, alcor_pci_sdmmc_suspend, | ||
| 1138 | alcor_pci_sdmmc_resume); | ||
| 1139 | |||
| 1140 | static const struct platform_device_id alcor_pci_sdmmc_ids[] = { | ||
| 1141 | { | ||
| 1142 | .name = DRV_NAME_ALCOR_PCI_SDMMC, | ||
| 1143 | }, { | ||
| 1144 | /* sentinel */ | ||
| 1145 | } | ||
| 1146 | }; | ||
| 1147 | MODULE_DEVICE_TABLE(platform, alcor_pci_sdmmc_ids); | ||
| 1148 | |||
| 1149 | static struct platform_driver alcor_pci_sdmmc_driver = { | ||
| 1150 | .probe = alcor_pci_sdmmc_drv_probe, | ||
| 1151 | .remove = alcor_pci_sdmmc_drv_remove, | ||
| 1152 | .id_table = alcor_pci_sdmmc_ids, | ||
| 1153 | .driver = { | ||
| 1154 | .name = DRV_NAME_ALCOR_PCI_SDMMC, | ||
| 1155 | .pm = &alcor_mmc_pm_ops | ||
| 1156 | }, | ||
| 1157 | }; | ||
| 1158 | module_platform_driver(alcor_pci_sdmmc_driver); | ||
| 1159 | |||
| 1160 | MODULE_AUTHOR("Oleksij Rempel <linux@rempel-privat.de>"); | ||
| 1161 | MODULE_DESCRIPTION("PCI driver for Alcor Micro AU6601 Secure Digital Host Controller Interface"); | ||
| 1162 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index be53044086c7..47189f9ed4e2 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
| @@ -446,18 +446,7 @@ static int atmci_req_show(struct seq_file *s, void *v) | |||
| 446 | return 0; | 446 | return 0; |
| 447 | } | 447 | } |
| 448 | 448 | ||
| 449 | static int atmci_req_open(struct inode *inode, struct file *file) | 449 | DEFINE_SHOW_ATTRIBUTE(atmci_req); |
| 450 | { | ||
| 451 | return single_open(file, atmci_req_show, inode->i_private); | ||
| 452 | } | ||
| 453 | |||
| 454 | static const struct file_operations atmci_req_fops = { | ||
| 455 | .owner = THIS_MODULE, | ||
| 456 | .open = atmci_req_open, | ||
| 457 | .read = seq_read, | ||
| 458 | .llseek = seq_lseek, | ||
| 459 | .release = single_release, | ||
| 460 | }; | ||
| 461 | 450 | ||
| 462 | static void atmci_show_status_reg(struct seq_file *s, | 451 | static void atmci_show_status_reg(struct seq_file *s, |
| 463 | const char *regname, u32 value) | 452 | const char *regname, u32 value) |
| @@ -583,18 +572,7 @@ static int atmci_regs_show(struct seq_file *s, void *v) | |||
| 583 | return ret; | 572 | return ret; |
| 584 | } | 573 | } |
| 585 | 574 | ||
| 586 | static int atmci_regs_open(struct inode *inode, struct file *file) | 575 | DEFINE_SHOW_ATTRIBUTE(atmci_regs); |
| 587 | { | ||
| 588 | return single_open(file, atmci_regs_show, inode->i_private); | ||
| 589 | } | ||
| 590 | |||
| 591 | static const struct file_operations atmci_regs_fops = { | ||
| 592 | .owner = THIS_MODULE, | ||
| 593 | .open = atmci_regs_open, | ||
| 594 | .read = seq_read, | ||
| 595 | .llseek = seq_lseek, | ||
| 596 | .release = single_release, | ||
| 597 | }; | ||
| 598 | 576 | ||
| 599 | static void atmci_init_debugfs(struct atmel_mci_slot *slot) | 577 | static void atmci_init_debugfs(struct atmel_mci_slot *slot) |
| 600 | { | 578 | { |
| @@ -608,13 +586,14 @@ static void atmci_init_debugfs(struct atmel_mci_slot *slot) | |||
| 608 | return; | 586 | return; |
| 609 | 587 | ||
| 610 | node = debugfs_create_file("regs", S_IRUSR, root, host, | 588 | node = debugfs_create_file("regs", S_IRUSR, root, host, |
| 611 | &atmci_regs_fops); | 589 | &atmci_regs_fops); |
| 612 | if (IS_ERR(node)) | 590 | if (IS_ERR(node)) |
| 613 | return; | 591 | return; |
| 614 | if (!node) | 592 | if (!node) |
| 615 | goto err; | 593 | goto err; |
| 616 | 594 | ||
| 617 | node = debugfs_create_file("req", S_IRUSR, root, slot, &atmci_req_fops); | 595 | node = debugfs_create_file("req", S_IRUSR, root, slot, |
| 596 | &atmci_req_fops); | ||
| 618 | if (!node) | 597 | if (!node) |
| 619 | goto err; | 598 | goto err; |
| 620 | 599 | ||
| @@ -1954,13 +1933,14 @@ static void atmci_tasklet_func(unsigned long priv) | |||
| 1954 | } | 1933 | } |
| 1955 | 1934 | ||
| 1956 | atmci_request_end(host, host->mrq); | 1935 | atmci_request_end(host, host->mrq); |
| 1957 | state = STATE_IDLE; | 1936 | goto unlock; /* atmci_request_end() sets host->state */ |
| 1958 | break; | 1937 | break; |
| 1959 | } | 1938 | } |
| 1960 | } while (state != prev_state); | 1939 | } while (state != prev_state); |
| 1961 | 1940 | ||
| 1962 | host->state = state; | 1941 | host->state = state; |
| 1963 | 1942 | ||
| 1943 | unlock: | ||
| 1964 | spin_unlock(&host->lock); | 1944 | spin_unlock(&host->lock); |
| 1965 | } | 1945 | } |
| 1966 | 1946 | ||
diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c index 768972af8b85..50293529d6de 100644 --- a/drivers/mmc/host/bcm2835.c +++ b/drivers/mmc/host/bcm2835.c | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 1 | /* | 2 | /* |
| 2 | * bcm2835 sdhost driver. | 3 | * bcm2835 sdhost driver. |
| 3 | * | 4 | * |
| @@ -25,18 +26,6 @@ | |||
| 25 | * sdhci-bcm2708.c by Broadcom | 26 | * sdhci-bcm2708.c by Broadcom |
| 26 | * sdhci-bcm2835.c by Stephen Warren and Oleksandr Tymoshenko | 27 | * sdhci-bcm2835.c by Stephen Warren and Oleksandr Tymoshenko |
| 27 | * sdhci.c and sdhci-pci.c by Pierre Ossman | 28 | * sdhci.c and sdhci-pci.c by Pierre Ossman |
| 28 | * | ||
| 29 | * This program is free software; you can redistribute it and/or modify it | ||
| 30 | * under the terms and conditions of the GNU General Public License, | ||
| 31 | * version 2, as published by the Free Software Foundation. | ||
| 32 | * | ||
| 33 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 34 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 35 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 36 | * more details. | ||
| 37 | * | ||
| 38 | * You should have received a copy of the GNU General Public License | ||
| 39 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 40 | */ | 29 | */ |
| 41 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
| 42 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
| @@ -286,6 +275,7 @@ static void bcm2835_reset(struct mmc_host *mmc) | |||
| 286 | 275 | ||
| 287 | if (host->dma_chan) | 276 | if (host->dma_chan) |
| 288 | dmaengine_terminate_sync(host->dma_chan); | 277 | dmaengine_terminate_sync(host->dma_chan); |
| 278 | host->dma_chan = NULL; | ||
| 289 | bcm2835_reset_internal(host); | 279 | bcm2835_reset_internal(host); |
| 290 | } | 280 | } |
| 291 | 281 | ||
| @@ -463,7 +453,7 @@ static void bcm2835_transfer_pio(struct bcm2835_host *host) | |||
| 463 | static | 453 | static |
| 464 | void bcm2835_prepare_dma(struct bcm2835_host *host, struct mmc_data *data) | 454 | void bcm2835_prepare_dma(struct bcm2835_host *host, struct mmc_data *data) |
| 465 | { | 455 | { |
| 466 | int len, dir_data, dir_slave; | 456 | int sg_len, dir_data, dir_slave; |
| 467 | struct dma_async_tx_descriptor *desc = NULL; | 457 | struct dma_async_tx_descriptor *desc = NULL; |
| 468 | struct dma_chan *dma_chan; | 458 | struct dma_chan *dma_chan; |
| 469 | 459 | ||
| @@ -509,23 +499,24 @@ void bcm2835_prepare_dma(struct bcm2835_host *host, struct mmc_data *data) | |||
| 509 | &host->dma_cfg_rx : | 499 | &host->dma_cfg_rx : |
| 510 | &host->dma_cfg_tx); | 500 | &host->dma_cfg_tx); |
| 511 | 501 | ||
| 512 | len = dma_map_sg(dma_chan->device->dev, data->sg, data->sg_len, | 502 | sg_len = dma_map_sg(dma_chan->device->dev, data->sg, data->sg_len, |
| 513 | dir_data); | 503 | dir_data); |
| 504 | if (!sg_len) | ||
| 505 | return; | ||
| 514 | 506 | ||
| 515 | if (len > 0) { | 507 | desc = dmaengine_prep_slave_sg(dma_chan, data->sg, sg_len, dir_slave, |
| 516 | desc = dmaengine_prep_slave_sg(dma_chan, data->sg, | 508 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
| 517 | len, dir_slave, | ||
| 518 | DMA_PREP_INTERRUPT | | ||
| 519 | DMA_CTRL_ACK); | ||
| 520 | } | ||
| 521 | 509 | ||
| 522 | if (desc) { | 510 | if (!desc) { |
| 523 | desc->callback = bcm2835_dma_complete; | 511 | dma_unmap_sg(dma_chan->device->dev, data->sg, sg_len, dir_data); |
| 524 | desc->callback_param = host; | 512 | return; |
| 525 | host->dma_desc = desc; | ||
| 526 | host->dma_chan = dma_chan; | ||
| 527 | host->dma_dir = dir_data; | ||
| 528 | } | 513 | } |
| 514 | |||
| 515 | desc->callback = bcm2835_dma_complete; | ||
| 516 | desc->callback_param = host; | ||
| 517 | host->dma_desc = desc; | ||
| 518 | host->dma_chan = dma_chan; | ||
| 519 | host->dma_dir = dir_data; | ||
| 529 | } | 520 | } |
| 530 | 521 | ||
| 531 | static void bcm2835_start_dma(struct bcm2835_host *host) | 522 | static void bcm2835_start_dma(struct bcm2835_host *host) |
| @@ -607,7 +598,7 @@ static void bcm2835_finish_request(struct bcm2835_host *host) | |||
| 607 | struct dma_chan *terminate_chan = NULL; | 598 | struct dma_chan *terminate_chan = NULL; |
| 608 | struct mmc_request *mrq; | 599 | struct mmc_request *mrq; |
| 609 | 600 | ||
| 610 | cancel_delayed_work(&host->timeout_work); | 601 | cancel_delayed_work_sync(&host->timeout_work); |
| 611 | 602 | ||
| 612 | mrq = host->mrq; | 603 | mrq = host->mrq; |
| 613 | 604 | ||
| @@ -772,6 +763,8 @@ static void bcm2835_finish_command(struct bcm2835_host *host) | |||
| 772 | 763 | ||
| 773 | if (!(sdhsts & SDHSTS_CRC7_ERROR) || | 764 | if (!(sdhsts & SDHSTS_CRC7_ERROR) || |
| 774 | (host->cmd->opcode != MMC_SEND_OP_COND)) { | 765 | (host->cmd->opcode != MMC_SEND_OP_COND)) { |
| 766 | u32 edm, fsm; | ||
| 767 | |||
| 775 | if (sdhsts & SDHSTS_CMD_TIME_OUT) { | 768 | if (sdhsts & SDHSTS_CMD_TIME_OUT) { |
| 776 | host->cmd->error = -ETIMEDOUT; | 769 | host->cmd->error = -ETIMEDOUT; |
| 777 | } else { | 770 | } else { |
| @@ -780,6 +773,13 @@ static void bcm2835_finish_command(struct bcm2835_host *host) | |||
| 780 | bcm2835_dumpregs(host); | 773 | bcm2835_dumpregs(host); |
| 781 | host->cmd->error = -EILSEQ; | 774 | host->cmd->error = -EILSEQ; |
| 782 | } | 775 | } |
| 776 | edm = readl(host->ioaddr + SDEDM); | ||
| 777 | fsm = edm & SDEDM_FSM_MASK; | ||
| 778 | if (fsm == SDEDM_FSM_READWAIT || | ||
| 779 | fsm == SDEDM_FSM_WRITESTART1) | ||
| 780 | /* Kick the FSM out of its wait */ | ||
| 781 | writel(edm | SDEDM_FORCE_DATA_MODE, | ||
| 782 | host->ioaddr + SDEDM); | ||
| 783 | bcm2835_finish_request(host); | 783 | bcm2835_finish_request(host); |
| 784 | return; | 784 | return; |
| 785 | } | 785 | } |
| @@ -837,6 +837,8 @@ static void bcm2835_timeout(struct work_struct *work) | |||
| 837 | dev_err(dev, "timeout waiting for hardware interrupt.\n"); | 837 | dev_err(dev, "timeout waiting for hardware interrupt.\n"); |
| 838 | bcm2835_dumpregs(host); | 838 | bcm2835_dumpregs(host); |
| 839 | 839 | ||
| 840 | bcm2835_reset(host->mmc); | ||
| 841 | |||
| 840 | if (host->data) { | 842 | if (host->data) { |
| 841 | host->data->error = -ETIMEDOUT; | 843 | host->data->error = -ETIMEDOUT; |
| 842 | bcm2835_finish_data(host); | 844 | bcm2835_finish_data(host); |
| @@ -1052,10 +1054,12 @@ static void bcm2835_dma_complete_work(struct work_struct *work) | |||
| 1052 | { | 1054 | { |
| 1053 | struct bcm2835_host *host = | 1055 | struct bcm2835_host *host = |
| 1054 | container_of(work, struct bcm2835_host, dma_work); | 1056 | container_of(work, struct bcm2835_host, dma_work); |
| 1055 | struct mmc_data *data = host->data; | 1057 | struct mmc_data *data; |
| 1056 | 1058 | ||
| 1057 | mutex_lock(&host->mutex); | 1059 | mutex_lock(&host->mutex); |
| 1058 | 1060 | ||
| 1061 | data = host->data; | ||
| 1062 | |||
| 1059 | if (host->dma_chan) { | 1063 | if (host->dma_chan) { |
| 1060 | dma_unmap_sg(host->dma_chan->device->dev, | 1064 | dma_unmap_sg(host->dma_chan->device->dev, |
| 1061 | data->sg, data->sg_len, | 1065 | data->sg, data->sg_len, |
| @@ -1180,9 +1184,6 @@ static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
| 1180 | return; | 1184 | return; |
| 1181 | } | 1185 | } |
| 1182 | 1186 | ||
| 1183 | if (host->use_dma && mrq->data && (mrq->data->blocks > PIO_THRESHOLD)) | ||
| 1184 | bcm2835_prepare_dma(host, mrq->data); | ||
| 1185 | |||
| 1186 | mutex_lock(&host->mutex); | 1187 | mutex_lock(&host->mutex); |
| 1187 | 1188 | ||
| 1188 | WARN_ON(host->mrq); | 1189 | WARN_ON(host->mrq); |
| @@ -1206,6 +1207,9 @@ static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
| 1206 | return; | 1207 | return; |
| 1207 | } | 1208 | } |
| 1208 | 1209 | ||
| 1210 | if (host->use_dma && mrq->data && (mrq->data->blocks > PIO_THRESHOLD)) | ||
| 1211 | bcm2835_prepare_dma(host, mrq->data); | ||
| 1212 | |||
| 1209 | host->use_sbc = !!mrq->sbc && host->mrq->data && | 1213 | host->use_sbc = !!mrq->sbc && host->mrq->data && |
| 1210 | (host->mrq->data->flags & MMC_DATA_READ); | 1214 | (host->mrq->data->flags & MMC_DATA_READ); |
| 1211 | if (host->use_sbc) { | 1215 | if (host->use_sbc) { |
| @@ -1445,6 +1449,9 @@ static int bcm2835_remove(struct platform_device *pdev) | |||
| 1445 | cancel_work_sync(&host->dma_work); | 1449 | cancel_work_sync(&host->dma_work); |
| 1446 | cancel_delayed_work_sync(&host->timeout_work); | 1450 | cancel_delayed_work_sync(&host->timeout_work); |
| 1447 | 1451 | ||
| 1452 | if (host->dma_chan_rxtx) | ||
| 1453 | dma_release_channel(host->dma_chan_rxtx); | ||
| 1454 | |||
| 1448 | mmc_free_host(host->mmc); | 1455 | mmc_free_host(host->mmc); |
| 1449 | platform_set_drvdata(pdev, NULL); | 1456 | platform_set_drvdata(pdev, NULL); |
| 1450 | 1457 | ||
diff --git a/drivers/mmc/host/dw_mmc-bluefield.c b/drivers/mmc/host/dw_mmc-bluefield.c index 54c3fbb4a391..ed8f2254b66a 100644 --- a/drivers/mmc/host/dw_mmc-bluefield.c +++ b/drivers/mmc/host/dw_mmc-bluefield.c | |||
| @@ -52,16 +52,7 @@ MODULE_DEVICE_TABLE(of, dw_mci_bluefield_match); | |||
| 52 | 52 | ||
| 53 | static int dw_mci_bluefield_probe(struct platform_device *pdev) | 53 | static int dw_mci_bluefield_probe(struct platform_device *pdev) |
| 54 | { | 54 | { |
| 55 | const struct dw_mci_drv_data *drv_data = NULL; | 55 | return dw_mci_pltfm_register(pdev, &bluefield_drv_data); |
| 56 | const struct of_device_id *match; | ||
| 57 | |||
| 58 | if (pdev->dev.of_node) { | ||
| 59 | match = of_match_node(dw_mci_bluefield_match, | ||
| 60 | pdev->dev.of_node); | ||
| 61 | drv_data = match->data; | ||
| 62 | } | ||
| 63 | |||
| 64 | return dw_mci_pltfm_register(pdev, drv_data); | ||
| 65 | } | 56 | } |
| 66 | 57 | ||
| 67 | static struct platform_driver dw_mci_bluefield_pltfm_driver = { | 58 | static struct platform_driver dw_mci_bluefield_pltfm_driver = { |
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index 0c1efd5100b7..33215d66afa2 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c | |||
| @@ -21,7 +21,7 @@ | |||
| 21 | #include <linux/dmaengine.h> | 21 | #include <linux/dmaengine.h> |
| 22 | #include <linux/dma-mapping.h> | 22 | #include <linux/dma-mapping.h> |
| 23 | #include <linux/err.h> | 23 | #include <linux/err.h> |
| 24 | #include <linux/gpio.h> | 24 | #include <linux/gpio/consumer.h> |
| 25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
| 26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
| 27 | #include <linux/irq.h> | 27 | #include <linux/irq.h> |
| @@ -126,9 +126,23 @@ enum jz4740_mmc_state { | |||
| 126 | JZ4740_MMC_STATE_DONE, | 126 | JZ4740_MMC_STATE_DONE, |
| 127 | }; | 127 | }; |
| 128 | 128 | ||
| 129 | struct jz4740_mmc_host_next { | 129 | /* |
| 130 | int sg_len; | 130 | * The MMC core allows to prepare a mmc_request while another mmc_request |
| 131 | s32 cookie; | 131 | * is in-flight. This is used via the pre_req/post_req hooks. |
| 132 | * This driver uses the pre_req/post_req hooks to map/unmap the mmc_request. | ||
| 133 | * Following what other drivers do (sdhci, dw_mmc) we use the following cookie | ||
| 134 | * flags to keep track of the mmc_request mapping state. | ||
| 135 | * | ||
| 136 | * COOKIE_UNMAPPED: the request is not mapped. | ||
| 137 | * COOKIE_PREMAPPED: the request was mapped in pre_req, | ||
| 138 | * and should be unmapped in post_req. | ||
| 139 | * COOKIE_MAPPED: the request was mapped in the irq handler, | ||
| 140 | * and should be unmapped before mmc_request_done is called.. | ||
| 141 | */ | ||
| 142 | enum jz4780_cookie { | ||
| 143 | COOKIE_UNMAPPED = 0, | ||
| 144 | COOKIE_PREMAPPED, | ||
| 145 | COOKIE_MAPPED, | ||
| 132 | }; | 146 | }; |
| 133 | 147 | ||
| 134 | struct jz4740_mmc_host { | 148 | struct jz4740_mmc_host { |
| @@ -136,6 +150,7 @@ struct jz4740_mmc_host { | |||
| 136 | struct platform_device *pdev; | 150 | struct platform_device *pdev; |
| 137 | struct jz4740_mmc_platform_data *pdata; | 151 | struct jz4740_mmc_platform_data *pdata; |
| 138 | struct clk *clk; | 152 | struct clk *clk; |
| 153 | struct gpio_desc *power; | ||
| 139 | 154 | ||
| 140 | enum jz4740_mmc_version version; | 155 | enum jz4740_mmc_version version; |
| 141 | 156 | ||
| @@ -162,9 +177,7 @@ struct jz4740_mmc_host { | |||
| 162 | /* DMA support */ | 177 | /* DMA support */ |
| 163 | struct dma_chan *dma_rx; | 178 | struct dma_chan *dma_rx; |
| 164 | struct dma_chan *dma_tx; | 179 | struct dma_chan *dma_tx; |
| 165 | struct jz4740_mmc_host_next next_data; | ||
| 166 | bool use_dma; | 180 | bool use_dma; |
| 167 | int sg_len; | ||
| 168 | 181 | ||
| 169 | /* The DMA trigger level is 8 words, that is to say, the DMA read | 182 | /* The DMA trigger level is 8 words, that is to say, the DMA read |
| 170 | * trigger is when data words in MSC_RXFIFO is >= 8 and the DMA write | 183 | * trigger is when data words in MSC_RXFIFO is >= 8 and the DMA write |
| @@ -226,9 +239,6 @@ static int jz4740_mmc_acquire_dma_channels(struct jz4740_mmc_host *host) | |||
| 226 | return PTR_ERR(host->dma_rx); | 239 | return PTR_ERR(host->dma_rx); |
| 227 | } | 240 | } |
| 228 | 241 | ||
| 229 | /* Initialize DMA pre request cookie */ | ||
| 230 | host->next_data.cookie = 1; | ||
| 231 | |||
| 232 | return 0; | 242 | return 0; |
| 233 | } | 243 | } |
| 234 | 244 | ||
| @@ -245,60 +255,44 @@ static void jz4740_mmc_dma_unmap(struct jz4740_mmc_host *host, | |||
| 245 | enum dma_data_direction dir = mmc_get_dma_dir(data); | 255 | enum dma_data_direction dir = mmc_get_dma_dir(data); |
| 246 | 256 | ||
| 247 | dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, dir); | 257 | dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, dir); |
| 258 | data->host_cookie = COOKIE_UNMAPPED; | ||
| 248 | } | 259 | } |
| 249 | 260 | ||
| 250 | /* Prepares DMA data for current/next transfer, returns non-zero on failure */ | 261 | /* Prepares DMA data for current or next transfer. |
| 262 | * A request can be in-flight when this is called. | ||
| 263 | */ | ||
| 251 | static int jz4740_mmc_prepare_dma_data(struct jz4740_mmc_host *host, | 264 | static int jz4740_mmc_prepare_dma_data(struct jz4740_mmc_host *host, |
| 252 | struct mmc_data *data, | 265 | struct mmc_data *data, |
| 253 | struct jz4740_mmc_host_next *next, | 266 | int cookie) |
| 254 | struct dma_chan *chan) | ||
| 255 | { | 267 | { |
| 256 | struct jz4740_mmc_host_next *next_data = &host->next_data; | 268 | struct dma_chan *chan = jz4740_mmc_get_dma_chan(host, data); |
| 257 | enum dma_data_direction dir = mmc_get_dma_dir(data); | 269 | enum dma_data_direction dir = mmc_get_dma_dir(data); |
| 258 | int sg_len; | 270 | int sg_count; |
| 259 | |||
| 260 | if (!next && data->host_cookie && | ||
| 261 | data->host_cookie != host->next_data.cookie) { | ||
| 262 | dev_warn(mmc_dev(host->mmc), | ||
| 263 | "[%s] invalid cookie: data->host_cookie %d host->next_data.cookie %d\n", | ||
| 264 | __func__, | ||
| 265 | data->host_cookie, | ||
| 266 | host->next_data.cookie); | ||
| 267 | data->host_cookie = 0; | ||
| 268 | } | ||
| 269 | 271 | ||
| 270 | /* Check if next job is already prepared */ | 272 | if (data->host_cookie == COOKIE_PREMAPPED) |
| 271 | if (next || data->host_cookie != host->next_data.cookie) { | 273 | return data->sg_count; |
| 272 | sg_len = dma_map_sg(chan->device->dev, | ||
| 273 | data->sg, | ||
| 274 | data->sg_len, | ||
| 275 | dir); | ||
| 276 | 274 | ||
| 277 | } else { | 275 | sg_count = dma_map_sg(chan->device->dev, |
| 278 | sg_len = next_data->sg_len; | 276 | data->sg, |
| 279 | next_data->sg_len = 0; | 277 | data->sg_len, |
| 280 | } | 278 | dir); |
| 281 | 279 | ||
| 282 | if (sg_len <= 0) { | 280 | if (sg_count <= 0) { |
| 283 | dev_err(mmc_dev(host->mmc), | 281 | dev_err(mmc_dev(host->mmc), |
| 284 | "Failed to map scatterlist for DMA operation\n"); | 282 | "Failed to map scatterlist for DMA operation\n"); |
| 285 | return -EINVAL; | 283 | return -EINVAL; |
| 286 | } | 284 | } |
| 287 | 285 | ||
| 288 | if (next) { | 286 | data->sg_count = sg_count; |
| 289 | next->sg_len = sg_len; | 287 | data->host_cookie = cookie; |
| 290 | data->host_cookie = ++next->cookie < 0 ? 1 : next->cookie; | ||
| 291 | } else | ||
| 292 | host->sg_len = sg_len; | ||
| 293 | 288 | ||
| 294 | return 0; | 289 | return data->sg_count; |
| 295 | } | 290 | } |
| 296 | 291 | ||
| 297 | static int jz4740_mmc_start_dma_transfer(struct jz4740_mmc_host *host, | 292 | static int jz4740_mmc_start_dma_transfer(struct jz4740_mmc_host *host, |
| 298 | struct mmc_data *data) | 293 | struct mmc_data *data) |
| 299 | { | 294 | { |
| 300 | int ret; | 295 | struct dma_chan *chan = jz4740_mmc_get_dma_chan(host, data); |
| 301 | struct dma_chan *chan; | ||
| 302 | struct dma_async_tx_descriptor *desc; | 296 | struct dma_async_tx_descriptor *desc; |
| 303 | struct dma_slave_config conf = { | 297 | struct dma_slave_config conf = { |
| 304 | .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, | 298 | .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, |
| @@ -306,29 +300,26 @@ static int jz4740_mmc_start_dma_transfer(struct jz4740_mmc_host *host, | |||
| 306 | .src_maxburst = JZ4740_MMC_FIFO_HALF_SIZE, | 300 | .src_maxburst = JZ4740_MMC_FIFO_HALF_SIZE, |
| 307 | .dst_maxburst = JZ4740_MMC_FIFO_HALF_SIZE, | 301 | .dst_maxburst = JZ4740_MMC_FIFO_HALF_SIZE, |
| 308 | }; | 302 | }; |
| 303 | int sg_count; | ||
| 309 | 304 | ||
| 310 | if (data->flags & MMC_DATA_WRITE) { | 305 | if (data->flags & MMC_DATA_WRITE) { |
| 311 | conf.direction = DMA_MEM_TO_DEV; | 306 | conf.direction = DMA_MEM_TO_DEV; |
| 312 | conf.dst_addr = host->mem_res->start + JZ_REG_MMC_TXFIFO; | 307 | conf.dst_addr = host->mem_res->start + JZ_REG_MMC_TXFIFO; |
| 313 | conf.slave_id = JZ4740_DMA_TYPE_MMC_TRANSMIT; | 308 | conf.slave_id = JZ4740_DMA_TYPE_MMC_TRANSMIT; |
| 314 | chan = host->dma_tx; | ||
| 315 | } else { | 309 | } else { |
| 316 | conf.direction = DMA_DEV_TO_MEM; | 310 | conf.direction = DMA_DEV_TO_MEM; |
| 317 | conf.src_addr = host->mem_res->start + JZ_REG_MMC_RXFIFO; | 311 | conf.src_addr = host->mem_res->start + JZ_REG_MMC_RXFIFO; |
| 318 | conf.slave_id = JZ4740_DMA_TYPE_MMC_RECEIVE; | 312 | conf.slave_id = JZ4740_DMA_TYPE_MMC_RECEIVE; |
| 319 | chan = host->dma_rx; | ||
| 320 | } | 313 | } |
| 321 | 314 | ||
| 322 | ret = jz4740_mmc_prepare_dma_data(host, data, NULL, chan); | 315 | sg_count = jz4740_mmc_prepare_dma_data(host, data, COOKIE_MAPPED); |
| 323 | if (ret) | 316 | if (sg_count < 0) |
| 324 | return ret; | 317 | return sg_count; |
| 325 | 318 | ||
| 326 | dmaengine_slave_config(chan, &conf); | 319 | dmaengine_slave_config(chan, &conf); |
| 327 | desc = dmaengine_prep_slave_sg(chan, | 320 | desc = dmaengine_prep_slave_sg(chan, data->sg, sg_count, |
| 328 | data->sg, | 321 | conf.direction, |
| 329 | host->sg_len, | 322 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
| 330 | conf.direction, | ||
| 331 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
| 332 | if (!desc) { | 323 | if (!desc) { |
| 333 | dev_err(mmc_dev(host->mmc), | 324 | dev_err(mmc_dev(host->mmc), |
| 334 | "Failed to allocate DMA %s descriptor", | 325 | "Failed to allocate DMA %s descriptor", |
| @@ -342,7 +333,8 @@ static int jz4740_mmc_start_dma_transfer(struct jz4740_mmc_host *host, | |||
| 342 | return 0; | 333 | return 0; |
| 343 | 334 | ||
| 344 | dma_unmap: | 335 | dma_unmap: |
| 345 | jz4740_mmc_dma_unmap(host, data); | 336 | if (data->host_cookie == COOKIE_MAPPED) |
| 337 | jz4740_mmc_dma_unmap(host, data); | ||
| 346 | return -ENOMEM; | 338 | return -ENOMEM; |
| 347 | } | 339 | } |
| 348 | 340 | ||
| @@ -351,16 +343,13 @@ static void jz4740_mmc_pre_request(struct mmc_host *mmc, | |||
| 351 | { | 343 | { |
| 352 | struct jz4740_mmc_host *host = mmc_priv(mmc); | 344 | struct jz4740_mmc_host *host = mmc_priv(mmc); |
| 353 | struct mmc_data *data = mrq->data; | 345 | struct mmc_data *data = mrq->data; |
| 354 | struct jz4740_mmc_host_next *next_data = &host->next_data; | ||
| 355 | 346 | ||
| 356 | BUG_ON(data->host_cookie); | 347 | if (!host->use_dma) |
| 357 | 348 | return; | |
| 358 | if (host->use_dma) { | ||
| 359 | struct dma_chan *chan = jz4740_mmc_get_dma_chan(host, data); | ||
| 360 | 349 | ||
| 361 | if (jz4740_mmc_prepare_dma_data(host, data, next_data, chan)) | 350 | data->host_cookie = COOKIE_UNMAPPED; |
| 362 | data->host_cookie = 0; | 351 | if (jz4740_mmc_prepare_dma_data(host, data, COOKIE_PREMAPPED) < 0) |
| 363 | } | 352 | data->host_cookie = COOKIE_UNMAPPED; |
| 364 | } | 353 | } |
| 365 | 354 | ||
| 366 | static void jz4740_mmc_post_request(struct mmc_host *mmc, | 355 | static void jz4740_mmc_post_request(struct mmc_host *mmc, |
| @@ -370,10 +359,8 @@ static void jz4740_mmc_post_request(struct mmc_host *mmc, | |||
| 370 | struct jz4740_mmc_host *host = mmc_priv(mmc); | 359 | struct jz4740_mmc_host *host = mmc_priv(mmc); |
| 371 | struct mmc_data *data = mrq->data; | 360 | struct mmc_data *data = mrq->data; |
| 372 | 361 | ||
| 373 | if (host->use_dma && data->host_cookie) { | 362 | if (data && data->host_cookie != COOKIE_UNMAPPED) |
| 374 | jz4740_mmc_dma_unmap(host, data); | 363 | jz4740_mmc_dma_unmap(host, data); |
| 375 | data->host_cookie = 0; | ||
| 376 | } | ||
| 377 | 364 | ||
| 378 | if (err) { | 365 | if (err) { |
| 379 | struct dma_chan *chan = jz4740_mmc_get_dma_chan(host, data); | 366 | struct dma_chan *chan = jz4740_mmc_get_dma_chan(host, data); |
| @@ -436,10 +423,14 @@ static void jz4740_mmc_reset(struct jz4740_mmc_host *host) | |||
| 436 | static void jz4740_mmc_request_done(struct jz4740_mmc_host *host) | 423 | static void jz4740_mmc_request_done(struct jz4740_mmc_host *host) |
| 437 | { | 424 | { |
| 438 | struct mmc_request *req; | 425 | struct mmc_request *req; |
| 426 | struct mmc_data *data; | ||
| 439 | 427 | ||
| 440 | req = host->req; | 428 | req = host->req; |
| 429 | data = req->data; | ||
| 441 | host->req = NULL; | 430 | host->req = NULL; |
| 442 | 431 | ||
| 432 | if (data && data->host_cookie == COOKIE_MAPPED) | ||
| 433 | jz4740_mmc_dma_unmap(host, data); | ||
| 443 | mmc_request_done(host->mmc, req); | 434 | mmc_request_done(host->mmc, req); |
| 444 | } | 435 | } |
| 445 | 436 | ||
| @@ -903,18 +894,16 @@ static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 903 | switch (ios->power_mode) { | 894 | switch (ios->power_mode) { |
| 904 | case MMC_POWER_UP: | 895 | case MMC_POWER_UP: |
| 905 | jz4740_mmc_reset(host); | 896 | jz4740_mmc_reset(host); |
| 906 | if (host->pdata && gpio_is_valid(host->pdata->gpio_power)) | 897 | if (host->power) |
| 907 | gpio_set_value(host->pdata->gpio_power, | 898 | gpiod_set_value(host->power, 1); |
| 908 | !host->pdata->power_active_low); | ||
| 909 | host->cmdat |= JZ_MMC_CMDAT_INIT; | 899 | host->cmdat |= JZ_MMC_CMDAT_INIT; |
| 910 | clk_prepare_enable(host->clk); | 900 | clk_prepare_enable(host->clk); |
| 911 | break; | 901 | break; |
| 912 | case MMC_POWER_ON: | 902 | case MMC_POWER_ON: |
| 913 | break; | 903 | break; |
| 914 | default: | 904 | default: |
| 915 | if (host->pdata && gpio_is_valid(host->pdata->gpio_power)) | 905 | if (host->power) |
| 916 | gpio_set_value(host->pdata->gpio_power, | 906 | gpiod_set_value(host->power, 0); |
| 917 | host->pdata->power_active_low); | ||
| 918 | clk_disable_unprepare(host->clk); | 907 | clk_disable_unprepare(host->clk); |
| 919 | break; | 908 | break; |
| 920 | } | 909 | } |
| @@ -947,30 +936,9 @@ static const struct mmc_host_ops jz4740_mmc_ops = { | |||
| 947 | .enable_sdio_irq = jz4740_mmc_enable_sdio_irq, | 936 | .enable_sdio_irq = jz4740_mmc_enable_sdio_irq, |
| 948 | }; | 937 | }; |
| 949 | 938 | ||
| 950 | static int jz4740_mmc_request_gpio(struct device *dev, int gpio, | 939 | static int jz4740_mmc_request_gpios(struct jz4740_mmc_host *host, |
| 951 | const char *name, bool output, int value) | 940 | struct mmc_host *mmc, |
| 952 | { | 941 | struct platform_device *pdev) |
| 953 | int ret; | ||
| 954 | |||
| 955 | if (!gpio_is_valid(gpio)) | ||
| 956 | return 0; | ||
| 957 | |||
| 958 | ret = gpio_request(gpio, name); | ||
| 959 | if (ret) { | ||
| 960 | dev_err(dev, "Failed to request %s gpio: %d\n", name, ret); | ||
| 961 | return ret; | ||
| 962 | } | ||
| 963 | |||
| 964 | if (output) | ||
| 965 | gpio_direction_output(gpio, value); | ||
| 966 | else | ||
| 967 | gpio_direction_input(gpio); | ||
| 968 | |||
| 969 | return 0; | ||
| 970 | } | ||
| 971 | |||
| 972 | static int jz4740_mmc_request_gpios(struct mmc_host *mmc, | ||
| 973 | struct platform_device *pdev) | ||
| 974 | { | 942 | { |
| 975 | struct jz4740_mmc_platform_data *pdata = dev_get_platdata(&pdev->dev); | 943 | struct jz4740_mmc_platform_data *pdata = dev_get_platdata(&pdev->dev); |
| 976 | int ret = 0; | 944 | int ret = 0; |
| @@ -983,31 +951,21 @@ static int jz4740_mmc_request_gpios(struct mmc_host *mmc, | |||
| 983 | if (!pdata->read_only_active_low) | 951 | if (!pdata->read_only_active_low) |
| 984 | mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; | 952 | mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; |
| 985 | 953 | ||
| 986 | if (gpio_is_valid(pdata->gpio_card_detect)) { | 954 | /* |
| 987 | ret = mmc_gpio_request_cd(mmc, pdata->gpio_card_detect, 0); | 955 | * Get optional card detect and write protect GPIOs, |
| 988 | if (ret) | 956 | * only back out on probe deferral. |
| 989 | return ret; | 957 | */ |
| 990 | } | 958 | ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0, NULL); |
| 991 | 959 | if (ret == -EPROBE_DEFER) | |
| 992 | if (gpio_is_valid(pdata->gpio_read_only)) { | 960 | return ret; |
| 993 | ret = mmc_gpio_request_ro(mmc, pdata->gpio_read_only); | ||
| 994 | if (ret) | ||
| 995 | return ret; | ||
| 996 | } | ||
| 997 | |||
| 998 | return jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_power, | ||
| 999 | "MMC read only", true, pdata->power_active_low); | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | static void jz4740_mmc_free_gpios(struct platform_device *pdev) | ||
| 1003 | { | ||
| 1004 | struct jz4740_mmc_platform_data *pdata = dev_get_platdata(&pdev->dev); | ||
| 1005 | 961 | ||
| 1006 | if (!pdata) | 962 | ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0, NULL); |
| 1007 | return; | 963 | if (ret == -EPROBE_DEFER) |
| 964 | return ret; | ||
| 1008 | 965 | ||
| 1009 | if (gpio_is_valid(pdata->gpio_power)) | 966 | host->power = devm_gpiod_get_optional(&pdev->dev, "power", |
| 1010 | gpio_free(pdata->gpio_power); | 967 | GPIOD_OUT_HIGH); |
| 968 | return PTR_ERR_OR_ZERO(host->power); | ||
| 1011 | } | 969 | } |
| 1012 | 970 | ||
| 1013 | static const struct of_device_id jz4740_mmc_of_match[] = { | 971 | static const struct of_device_id jz4740_mmc_of_match[] = { |
| @@ -1053,7 +1011,7 @@ static int jz4740_mmc_probe(struct platform_device* pdev) | |||
| 1053 | mmc->caps |= MMC_CAP_SDIO_IRQ; | 1011 | mmc->caps |= MMC_CAP_SDIO_IRQ; |
| 1054 | if (!(pdata && pdata->data_1bit)) | 1012 | if (!(pdata && pdata->data_1bit)) |
| 1055 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 1013 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
| 1056 | ret = jz4740_mmc_request_gpios(mmc, pdev); | 1014 | ret = jz4740_mmc_request_gpios(host, mmc, pdev); |
| 1057 | if (ret) | 1015 | if (ret) |
| 1058 | goto err_free_host; | 1016 | goto err_free_host; |
| 1059 | } | 1017 | } |
| @@ -1104,7 +1062,7 @@ static int jz4740_mmc_probe(struct platform_device* pdev) | |||
| 1104 | dev_name(&pdev->dev), host); | 1062 | dev_name(&pdev->dev), host); |
| 1105 | if (ret) { | 1063 | if (ret) { |
| 1106 | dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); | 1064 | dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); |
| 1107 | goto err_free_gpios; | 1065 | goto err_free_host; |
| 1108 | } | 1066 | } |
| 1109 | 1067 | ||
| 1110 | jz4740_mmc_clock_disable(host); | 1068 | jz4740_mmc_clock_disable(host); |
| @@ -1135,8 +1093,6 @@ err_release_dma: | |||
| 1135 | jz4740_mmc_release_dma_channels(host); | 1093 | jz4740_mmc_release_dma_channels(host); |
| 1136 | err_free_irq: | 1094 | err_free_irq: |
| 1137 | free_irq(host->irq, host); | 1095 | free_irq(host->irq, host); |
| 1138 | err_free_gpios: | ||
| 1139 | jz4740_mmc_free_gpios(pdev); | ||
| 1140 | err_free_host: | 1096 | err_free_host: |
| 1141 | mmc_free_host(mmc); | 1097 | mmc_free_host(mmc); |
| 1142 | 1098 | ||
| @@ -1155,8 +1111,6 @@ static int jz4740_mmc_remove(struct platform_device *pdev) | |||
| 1155 | 1111 | ||
| 1156 | free_irq(host->irq, host); | 1112 | free_irq(host->irq, host); |
| 1157 | 1113 | ||
| 1158 | jz4740_mmc_free_gpios(pdev); | ||
| 1159 | |||
| 1160 | if (host->use_dma) | 1114 | if (host->use_dma) |
| 1161 | jz4740_mmc_release_dma_channels(host); | 1115 | jz4740_mmc_release_dma_channels(host); |
| 1162 | 1116 | ||
diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index c201c378537e..c2690c1a50ff 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c | |||
| @@ -21,11 +21,11 @@ | |||
| 21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
| 22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
| 24 | #include <linux/delay.h> | ||
| 24 | #include <linux/device.h> | 25 | #include <linux/device.h> |
| 25 | #include <linux/of_device.h> | 26 | #include <linux/of_device.h> |
| 26 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
| 27 | #include <linux/ioport.h> | 28 | #include <linux/ioport.h> |
| 28 | #include <linux/spinlock.h> | ||
| 29 | #include <linux/dma-mapping.h> | 29 | #include <linux/dma-mapping.h> |
| 30 | #include <linux/mmc/host.h> | 30 | #include <linux/mmc/host.h> |
| 31 | #include <linux/mmc/mmc.h> | 31 | #include <linux/mmc/mmc.h> |
| @@ -66,6 +66,9 @@ | |||
| 66 | 66 | ||
| 67 | #define SD_EMMC_DELAY 0x4 | 67 | #define SD_EMMC_DELAY 0x4 |
| 68 | #define SD_EMMC_ADJUST 0x8 | 68 | #define SD_EMMC_ADJUST 0x8 |
| 69 | #define ADJUST_ADJ_DELAY_MASK GENMASK(21, 16) | ||
| 70 | #define ADJUST_DS_EN BIT(15) | ||
| 71 | #define ADJUST_ADJ_EN BIT(13) | ||
| 69 | 72 | ||
| 70 | #define SD_EMMC_DELAY1 0x4 | 73 | #define SD_EMMC_DELAY1 0x4 |
| 71 | #define SD_EMMC_DELAY2 0x8 | 74 | #define SD_EMMC_DELAY2 0x8 |
| @@ -90,9 +93,11 @@ | |||
| 90 | #define CFG_CLK_ALWAYS_ON BIT(18) | 93 | #define CFG_CLK_ALWAYS_ON BIT(18) |
| 91 | #define CFG_CHK_DS BIT(20) | 94 | #define CFG_CHK_DS BIT(20) |
| 92 | #define CFG_AUTO_CLK BIT(23) | 95 | #define CFG_AUTO_CLK BIT(23) |
| 96 | #define CFG_ERR_ABORT BIT(27) | ||
| 93 | 97 | ||
| 94 | #define SD_EMMC_STATUS 0x48 | 98 | #define SD_EMMC_STATUS 0x48 |
| 95 | #define STATUS_BUSY BIT(31) | 99 | #define STATUS_BUSY BIT(31) |
| 100 | #define STATUS_DESC_BUSY BIT(30) | ||
| 96 | #define STATUS_DATI GENMASK(23, 16) | 101 | #define STATUS_DATI GENMASK(23, 16) |
| 97 | 102 | ||
| 98 | #define SD_EMMC_IRQ_EN 0x4c | 103 | #define SD_EMMC_IRQ_EN 0x4c |
| @@ -141,6 +146,7 @@ struct meson_mmc_data { | |||
| 141 | unsigned int tx_delay_mask; | 146 | unsigned int tx_delay_mask; |
| 142 | unsigned int rx_delay_mask; | 147 | unsigned int rx_delay_mask; |
| 143 | unsigned int always_on; | 148 | unsigned int always_on; |
| 149 | unsigned int adjust; | ||
| 144 | }; | 150 | }; |
| 145 | 151 | ||
| 146 | struct sd_emmc_desc { | 152 | struct sd_emmc_desc { |
| @@ -156,7 +162,6 @@ struct meson_host { | |||
| 156 | struct mmc_host *mmc; | 162 | struct mmc_host *mmc; |
| 157 | struct mmc_command *cmd; | 163 | struct mmc_command *cmd; |
| 158 | 164 | ||
| 159 | spinlock_t lock; | ||
| 160 | void __iomem *regs; | 165 | void __iomem *regs; |
| 161 | struct clk *core_clk; | 166 | struct clk *core_clk; |
| 162 | struct clk *mmc_clk; | 167 | struct clk *mmc_clk; |
| @@ -633,14 +638,8 @@ static int meson_mmc_clk_init(struct meson_host *host) | |||
| 633 | if (ret) | 638 | if (ret) |
| 634 | return ret; | 639 | return ret; |
| 635 | 640 | ||
| 636 | /* | ||
| 637 | * Set phases : These values are mostly the datasheet recommended ones | ||
| 638 | * except for the Tx phase. Datasheet recommends 180 but some cards | ||
| 639 | * fail at initialisation with it. 270 works just fine, it fixes these | ||
| 640 | * initialisation issues and enable eMMC DDR52 mode. | ||
| 641 | */ | ||
| 642 | clk_set_phase(host->mmc_clk, 180); | 641 | clk_set_phase(host->mmc_clk, 180); |
| 643 | clk_set_phase(host->tx_clk, 270); | 642 | clk_set_phase(host->tx_clk, 0); |
| 644 | clk_set_phase(host->rx_clk, 0); | 643 | clk_set_phase(host->rx_clk, 0); |
| 645 | 644 | ||
| 646 | return clk_prepare_enable(host->mmc_clk); | 645 | return clk_prepare_enable(host->mmc_clk); |
| @@ -928,6 +927,7 @@ static void meson_mmc_start_cmd(struct mmc_host *mmc, struct mmc_command *cmd) | |||
| 928 | 927 | ||
| 929 | cmd_cfg |= FIELD_PREP(CMD_CFG_CMD_INDEX_MASK, cmd->opcode); | 928 | cmd_cfg |= FIELD_PREP(CMD_CFG_CMD_INDEX_MASK, cmd->opcode); |
| 930 | cmd_cfg |= CMD_CFG_OWNER; /* owned by CPU */ | 929 | cmd_cfg |= CMD_CFG_OWNER; /* owned by CPU */ |
| 930 | cmd_cfg |= CMD_CFG_ERROR; /* stop in case of error */ | ||
| 931 | 931 | ||
| 932 | meson_mmc_set_response_bits(cmd, &cmd_cfg); | 932 | meson_mmc_set_response_bits(cmd, &cmd_cfg); |
| 933 | 933 | ||
| @@ -1022,29 +1022,34 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) | |||
| 1022 | u32 irq_en, status, raw_status; | 1022 | u32 irq_en, status, raw_status; |
| 1023 | irqreturn_t ret = IRQ_NONE; | 1023 | irqreturn_t ret = IRQ_NONE; |
| 1024 | 1024 | ||
| 1025 | if (WARN_ON(!host) || WARN_ON(!host->cmd)) | 1025 | irq_en = readl(host->regs + SD_EMMC_IRQ_EN); |
| 1026 | raw_status = readl(host->regs + SD_EMMC_STATUS); | ||
| 1027 | status = raw_status & irq_en; | ||
| 1028 | |||
| 1029 | if (!status) { | ||
| 1030 | dev_dbg(host->dev, | ||
| 1031 | "Unexpected IRQ! irq_en 0x%08x - status 0x%08x\n", | ||
| 1032 | irq_en, raw_status); | ||
| 1026 | return IRQ_NONE; | 1033 | return IRQ_NONE; |
| 1034 | } | ||
| 1027 | 1035 | ||
| 1028 | spin_lock(&host->lock); | 1036 | if (WARN_ON(!host) || WARN_ON(!host->cmd)) |
| 1037 | return IRQ_NONE; | ||
| 1029 | 1038 | ||
| 1030 | cmd = host->cmd; | 1039 | cmd = host->cmd; |
| 1031 | data = cmd->data; | 1040 | data = cmd->data; |
| 1032 | irq_en = readl(host->regs + SD_EMMC_IRQ_EN); | ||
| 1033 | raw_status = readl(host->regs + SD_EMMC_STATUS); | ||
| 1034 | status = raw_status & irq_en; | ||
| 1035 | |||
| 1036 | cmd->error = 0; | 1041 | cmd->error = 0; |
| 1037 | if (status & IRQ_CRC_ERR) { | 1042 | if (status & IRQ_CRC_ERR) { |
| 1038 | dev_dbg(host->dev, "CRC Error - status 0x%08x\n", status); | 1043 | dev_dbg(host->dev, "CRC Error - status 0x%08x\n", status); |
| 1039 | cmd->error = -EILSEQ; | 1044 | cmd->error = -EILSEQ; |
| 1040 | ret = IRQ_HANDLED; | 1045 | ret = IRQ_WAKE_THREAD; |
| 1041 | goto out; | 1046 | goto out; |
| 1042 | } | 1047 | } |
| 1043 | 1048 | ||
| 1044 | if (status & IRQ_TIMEOUTS) { | 1049 | if (status & IRQ_TIMEOUTS) { |
| 1045 | dev_dbg(host->dev, "Timeout - status 0x%08x\n", status); | 1050 | dev_dbg(host->dev, "Timeout - status 0x%08x\n", status); |
| 1046 | cmd->error = -ETIMEDOUT; | 1051 | cmd->error = -ETIMEDOUT; |
| 1047 | ret = IRQ_HANDLED; | 1052 | ret = IRQ_WAKE_THREAD; |
| 1048 | goto out; | 1053 | goto out; |
| 1049 | } | 1054 | } |
| 1050 | 1055 | ||
| @@ -1069,17 +1074,48 @@ out: | |||
| 1069 | /* ack all enabled interrupts */ | 1074 | /* ack all enabled interrupts */ |
| 1070 | writel(irq_en, host->regs + SD_EMMC_STATUS); | 1075 | writel(irq_en, host->regs + SD_EMMC_STATUS); |
| 1071 | 1076 | ||
| 1077 | if (cmd->error) { | ||
| 1078 | /* Stop desc in case of errors */ | ||
| 1079 | u32 start = readl(host->regs + SD_EMMC_START); | ||
| 1080 | |||
| 1081 | start &= ~START_DESC_BUSY; | ||
| 1082 | writel(start, host->regs + SD_EMMC_START); | ||
| 1083 | } | ||
| 1084 | |||
| 1072 | if (ret == IRQ_HANDLED) | 1085 | if (ret == IRQ_HANDLED) |
| 1073 | meson_mmc_request_done(host->mmc, cmd->mrq); | 1086 | meson_mmc_request_done(host->mmc, cmd->mrq); |
| 1074 | else if (ret == IRQ_NONE) | ||
| 1075 | dev_warn(host->dev, | ||
| 1076 | "Unexpected IRQ! status=0x%08x, irq_en=0x%08x\n", | ||
| 1077 | raw_status, irq_en); | ||
| 1078 | 1087 | ||
| 1079 | spin_unlock(&host->lock); | ||
| 1080 | return ret; | 1088 | return ret; |
| 1081 | } | 1089 | } |
| 1082 | 1090 | ||
| 1091 | static int meson_mmc_wait_desc_stop(struct meson_host *host) | ||
| 1092 | { | ||
| 1093 | int loop; | ||
| 1094 | u32 status; | ||
| 1095 | |||
| 1096 | /* | ||
| 1097 | * It may sometimes take a while for it to actually halt. Here, we | ||
| 1098 | * are giving it 5ms to comply | ||
| 1099 | * | ||
| 1100 | * If we don't confirm the descriptor is stopped, it might raise new | ||
| 1101 | * IRQs after we have called mmc_request_done() which is bad. | ||
| 1102 | */ | ||
| 1103 | for (loop = 50; loop; loop--) { | ||
| 1104 | status = readl(host->regs + SD_EMMC_STATUS); | ||
| 1105 | if (status & (STATUS_BUSY | STATUS_DESC_BUSY)) | ||
| 1106 | udelay(100); | ||
| 1107 | else | ||
| 1108 | break; | ||
| 1109 | } | ||
| 1110 | |||
| 1111 | if (status & (STATUS_BUSY | STATUS_DESC_BUSY)) { | ||
| 1112 | dev_err(host->dev, "Timed out waiting for host to stop\n"); | ||
| 1113 | return -ETIMEDOUT; | ||
| 1114 | } | ||
| 1115 | |||
| 1116 | return 0; | ||
| 1117 | } | ||
| 1118 | |||
| 1083 | static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id) | 1119 | static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id) |
| 1084 | { | 1120 | { |
| 1085 | struct meson_host *host = dev_id; | 1121 | struct meson_host *host = dev_id; |
| @@ -1090,6 +1126,13 @@ static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id) | |||
| 1090 | if (WARN_ON(!cmd)) | 1126 | if (WARN_ON(!cmd)) |
| 1091 | return IRQ_NONE; | 1127 | return IRQ_NONE; |
| 1092 | 1128 | ||
| 1129 | if (cmd->error) { | ||
| 1130 | meson_mmc_wait_desc_stop(host); | ||
| 1131 | meson_mmc_request_done(host->mmc, cmd->mrq); | ||
| 1132 | |||
| 1133 | return IRQ_HANDLED; | ||
| 1134 | } | ||
| 1135 | |||
| 1093 | data = cmd->data; | 1136 | data = cmd->data; |
| 1094 | if (meson_mmc_bounce_buf_read(data)) { | 1137 | if (meson_mmc_bounce_buf_read(data)) { |
| 1095 | xfer_bytes = data->blksz * data->blocks; | 1138 | xfer_bytes = data->blksz * data->blocks; |
| @@ -1123,14 +1166,21 @@ static int meson_mmc_get_cd(struct mmc_host *mmc) | |||
| 1123 | 1166 | ||
| 1124 | static void meson_mmc_cfg_init(struct meson_host *host) | 1167 | static void meson_mmc_cfg_init(struct meson_host *host) |
| 1125 | { | 1168 | { |
| 1126 | u32 cfg = 0; | 1169 | u32 cfg = 0, adj = 0; |
| 1127 | 1170 | ||
| 1128 | cfg |= FIELD_PREP(CFG_RESP_TIMEOUT_MASK, | 1171 | cfg |= FIELD_PREP(CFG_RESP_TIMEOUT_MASK, |
| 1129 | ilog2(SD_EMMC_CFG_RESP_TIMEOUT)); | 1172 | ilog2(SD_EMMC_CFG_RESP_TIMEOUT)); |
| 1130 | cfg |= FIELD_PREP(CFG_RC_CC_MASK, ilog2(SD_EMMC_CFG_CMD_GAP)); | 1173 | cfg |= FIELD_PREP(CFG_RC_CC_MASK, ilog2(SD_EMMC_CFG_CMD_GAP)); |
| 1131 | cfg |= FIELD_PREP(CFG_BLK_LEN_MASK, ilog2(SD_EMMC_CFG_BLK_SIZE)); | 1174 | cfg |= FIELD_PREP(CFG_BLK_LEN_MASK, ilog2(SD_EMMC_CFG_BLK_SIZE)); |
| 1132 | 1175 | ||
| 1176 | /* abort chain on R/W errors */ | ||
| 1177 | cfg |= CFG_ERR_ABORT; | ||
| 1178 | |||
| 1133 | writel(cfg, host->regs + SD_EMMC_CFG); | 1179 | writel(cfg, host->regs + SD_EMMC_CFG); |
| 1180 | |||
| 1181 | /* enable signal resampling w/o delay */ | ||
| 1182 | adj = ADJUST_ADJ_EN; | ||
| 1183 | writel(adj, host->regs + host->data->adjust); | ||
| 1134 | } | 1184 | } |
| 1135 | 1185 | ||
| 1136 | static int meson_mmc_card_busy(struct mmc_host *mmc) | 1186 | static int meson_mmc_card_busy(struct mmc_host *mmc) |
| @@ -1191,8 +1241,6 @@ static int meson_mmc_probe(struct platform_device *pdev) | |||
| 1191 | host->dev = &pdev->dev; | 1241 | host->dev = &pdev->dev; |
| 1192 | dev_set_drvdata(&pdev->dev, host); | 1242 | dev_set_drvdata(&pdev->dev, host); |
| 1193 | 1243 | ||
| 1194 | spin_lock_init(&host->lock); | ||
| 1195 | |||
| 1196 | /* Get regulators and the supported OCR mask */ | 1244 | /* Get regulators and the supported OCR mask */ |
| 1197 | host->vqmmc_enabled = false; | 1245 | host->vqmmc_enabled = false; |
| 1198 | ret = mmc_regulator_get_supply(mmc); | 1246 | ret = mmc_regulator_get_supply(mmc); |
| @@ -1356,12 +1404,14 @@ static const struct meson_mmc_data meson_gx_data = { | |||
| 1356 | .tx_delay_mask = CLK_V2_TX_DELAY_MASK, | 1404 | .tx_delay_mask = CLK_V2_TX_DELAY_MASK, |
| 1357 | .rx_delay_mask = CLK_V2_RX_DELAY_MASK, | 1405 | .rx_delay_mask = CLK_V2_RX_DELAY_MASK, |
| 1358 | .always_on = CLK_V2_ALWAYS_ON, | 1406 | .always_on = CLK_V2_ALWAYS_ON, |
| 1407 | .adjust = SD_EMMC_ADJUST, | ||
| 1359 | }; | 1408 | }; |
| 1360 | 1409 | ||
| 1361 | static const struct meson_mmc_data meson_axg_data = { | 1410 | static const struct meson_mmc_data meson_axg_data = { |
| 1362 | .tx_delay_mask = CLK_V3_TX_DELAY_MASK, | 1411 | .tx_delay_mask = CLK_V3_TX_DELAY_MASK, |
| 1363 | .rx_delay_mask = CLK_V3_RX_DELAY_MASK, | 1412 | .rx_delay_mask = CLK_V3_RX_DELAY_MASK, |
| 1364 | .always_on = CLK_V3_ALWAYS_ON, | 1413 | .always_on = CLK_V3_ALWAYS_ON, |
| 1414 | .adjust = SD_EMMC_V3_ADJUST, | ||
| 1365 | }; | 1415 | }; |
| 1366 | 1416 | ||
| 1367 | static const struct of_device_id meson_mmc_of_match[] = { | 1417 | static const struct of_device_id meson_mmc_of_match[] = { |
diff --git a/drivers/mmc/host/meson-mx-sdio.c b/drivers/mmc/host/meson-mx-sdio.c index abe253c262a2..ec980bda071c 100644 --- a/drivers/mmc/host/meson-mx-sdio.c +++ b/drivers/mmc/host/meson-mx-sdio.c | |||
| @@ -596,6 +596,9 @@ static int meson_mx_mmc_register_clks(struct meson_mx_mmc_host *host) | |||
| 596 | init.name = devm_kasprintf(host->controller_dev, GFP_KERNEL, | 596 | init.name = devm_kasprintf(host->controller_dev, GFP_KERNEL, |
| 597 | "%s#fixed_factor", | 597 | "%s#fixed_factor", |
| 598 | dev_name(host->controller_dev)); | 598 | dev_name(host->controller_dev)); |
| 599 | if (!init.name) | ||
| 600 | return -ENOMEM; | ||
| 601 | |||
| 599 | init.ops = &clk_fixed_factor_ops; | 602 | init.ops = &clk_fixed_factor_ops; |
| 600 | init.flags = 0; | 603 | init.flags = 0; |
| 601 | init.parent_names = &clk_fixed_factor_parent; | 604 | init.parent_names = &clk_fixed_factor_parent; |
| @@ -612,6 +615,9 @@ static int meson_mx_mmc_register_clks(struct meson_mx_mmc_host *host) | |||
| 612 | clk_div_parent = __clk_get_name(host->fixed_factor_clk); | 615 | clk_div_parent = __clk_get_name(host->fixed_factor_clk); |
| 613 | init.name = devm_kasprintf(host->controller_dev, GFP_KERNEL, | 616 | init.name = devm_kasprintf(host->controller_dev, GFP_KERNEL, |
| 614 | "%s#div", dev_name(host->controller_dev)); | 617 | "%s#div", dev_name(host->controller_dev)); |
| 618 | if (!init.name) | ||
| 619 | return -ENOMEM; | ||
| 620 | |||
| 615 | init.ops = &clk_divider_ops; | 621 | init.ops = &clk_divider_ops; |
| 616 | init.flags = CLK_SET_RATE_PARENT; | 622 | init.flags = CLK_SET_RATE_PARENT; |
| 617 | init.parent_names = &clk_div_parent; | 623 | init.parent_names = &clk_div_parent; |
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 476e53d30128..10ba46b728e8 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c | |||
| @@ -1434,13 +1434,16 @@ static int mmc_spi_probe(struct spi_device *spi) | |||
| 1434 | if (status != 0) | 1434 | if (status != 0) |
| 1435 | goto fail_add_host; | 1435 | goto fail_add_host; |
| 1436 | 1436 | ||
| 1437 | if (host->pdata && host->pdata->flags & MMC_SPI_USE_CD_GPIO) { | 1437 | /* |
| 1438 | status = mmc_gpio_request_cd(mmc, host->pdata->cd_gpio, | 1438 | * Index 0 is card detect |
| 1439 | host->pdata->cd_debounce); | 1439 | * Old boardfiles were specifying 1 ms as debounce |
| 1440 | if (status != 0) | 1440 | */ |
| 1441 | goto fail_add_host; | 1441 | status = mmc_gpiod_request_cd(mmc, NULL, 0, false, 1, NULL); |
| 1442 | 1442 | if (status == -EPROBE_DEFER) | |
| 1443 | /* The platform has a CD GPIO signal that may support | 1443 | goto fail_add_host; |
| 1444 | if (!status) { | ||
| 1445 | /* | ||
| 1446 | * The platform has a CD GPIO signal that may support | ||
| 1444 | * interrupts, so let mmc_gpiod_request_cd_irq() decide | 1447 | * interrupts, so let mmc_gpiod_request_cd_irq() decide |
| 1445 | * if polling is needed or not. | 1448 | * if polling is needed or not. |
| 1446 | */ | 1449 | */ |
| @@ -1448,12 +1451,12 @@ static int mmc_spi_probe(struct spi_device *spi) | |||
| 1448 | mmc_gpiod_request_cd_irq(mmc); | 1451 | mmc_gpiod_request_cd_irq(mmc); |
| 1449 | } | 1452 | } |
| 1450 | 1453 | ||
| 1451 | if (host->pdata && host->pdata->flags & MMC_SPI_USE_RO_GPIO) { | 1454 | /* Index 1 is write protect/read only */ |
| 1455 | status = mmc_gpiod_request_ro(mmc, NULL, 1, false, 0, NULL); | ||
| 1456 | if (status == -EPROBE_DEFER) | ||
| 1457 | goto fail_add_host; | ||
| 1458 | if (!status) | ||
| 1452 | has_ro = true; | 1459 | has_ro = true; |
| 1453 | status = mmc_gpio_request_ro(mmc, host->pdata->ro_gpio); | ||
| 1454 | if (status != 0) | ||
| 1455 | goto fail_add_host; | ||
| 1456 | } | ||
| 1457 | 1460 | ||
| 1458 | dev_info(&spi->dev, "SD/MMC host %s%s%s%s%s\n", | 1461 | dev_info(&spi->dev, "SD/MMC host %s%s%s%s%s\n", |
| 1459 | dev_name(&mmc->class_dev), | 1462 | dev_name(&mmc->class_dev), |
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 82bab35fff41..e352f5ad5801 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/err.h> | 21 | #include <linux/err.h> |
| 22 | #include <linux/highmem.h> | 22 | #include <linux/highmem.h> |
| 23 | #include <linux/log2.h> | 23 | #include <linux/log2.h> |
| 24 | #include <linux/mmc/mmc.h> | ||
| 24 | #include <linux/mmc/pm.h> | 25 | #include <linux/mmc/pm.h> |
| 25 | #include <linux/mmc/host.h> | 26 | #include <linux/mmc/host.h> |
| 26 | #include <linux/mmc/card.h> | 27 | #include <linux/mmc/card.h> |
| @@ -274,6 +275,7 @@ static struct variant_data variant_stm32_sdmmc = { | |||
| 274 | .cmdreg_lrsp_crc = MCI_CPSM_STM32_LRSP_CRC, | 275 | .cmdreg_lrsp_crc = MCI_CPSM_STM32_LRSP_CRC, |
| 275 | .cmdreg_srsp_crc = MCI_CPSM_STM32_SRSP_CRC, | 276 | .cmdreg_srsp_crc = MCI_CPSM_STM32_SRSP_CRC, |
| 276 | .cmdreg_srsp = MCI_CPSM_STM32_SRSP, | 277 | .cmdreg_srsp = MCI_CPSM_STM32_SRSP, |
| 278 | .cmdreg_stop = MCI_CPSM_STM32_CMDSTOP, | ||
| 277 | .data_cmd_enable = MCI_CPSM_STM32_CMDTRANS, | 279 | .data_cmd_enable = MCI_CPSM_STM32_CMDTRANS, |
| 278 | .irq_pio_mask = MCI_IRQ_PIO_STM32_MASK, | 280 | .irq_pio_mask = MCI_IRQ_PIO_STM32_MASK, |
| 279 | .datactrl_first = true, | 281 | .datactrl_first = true, |
| @@ -1100,6 +1102,10 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c) | |||
| 1100 | mmci_reg_delay(host); | 1102 | mmci_reg_delay(host); |
| 1101 | } | 1103 | } |
| 1102 | 1104 | ||
| 1105 | if (host->variant->cmdreg_stop && | ||
| 1106 | cmd->opcode == MMC_STOP_TRANSMISSION) | ||
| 1107 | c |= host->variant->cmdreg_stop; | ||
| 1108 | |||
| 1103 | c |= cmd->opcode | host->variant->cmdreg_cpsm_enable; | 1109 | c |= cmd->opcode | host->variant->cmdreg_cpsm_enable; |
| 1104 | if (cmd->flags & MMC_RSP_PRESENT) { | 1110 | if (cmd->flags & MMC_RSP_PRESENT) { |
| 1105 | if (cmd->flags & MMC_RSP_136) | 1111 | if (cmd->flags & MMC_RSP_136) |
| @@ -1190,11 +1196,10 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, | |||
| 1190 | /* The error clause is handled above, success! */ | 1196 | /* The error clause is handled above, success! */ |
| 1191 | data->bytes_xfered = data->blksz * data->blocks; | 1197 | data->bytes_xfered = data->blksz * data->blocks; |
| 1192 | 1198 | ||
| 1193 | if (!data->stop || host->mrq->sbc) { | 1199 | if (!data->stop || (host->mrq->sbc && !data->error)) |
| 1194 | mmci_request_end(host, data->mrq); | 1200 | mmci_request_end(host, data->mrq); |
| 1195 | } else { | 1201 | else |
| 1196 | mmci_start_command(host, data->stop, 0); | 1202 | mmci_start_command(host, data->stop, 0); |
| 1197 | } | ||
| 1198 | } | 1203 | } |
| 1199 | } | 1204 | } |
| 1200 | 1205 | ||
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 550dd3914461..24229097d05c 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h | |||
| @@ -264,6 +264,7 @@ struct mmci_host; | |||
| 264 | * @cmdreg_lrsp_crc: enable value for long response with crc | 264 | * @cmdreg_lrsp_crc: enable value for long response with crc |
| 265 | * @cmdreg_srsp_crc: enable value for short response with crc | 265 | * @cmdreg_srsp_crc: enable value for short response with crc |
| 266 | * @cmdreg_srsp: enable value for short response without crc | 266 | * @cmdreg_srsp: enable value for short response without crc |
| 267 | * @cmdreg_stop: enable value for stop and abort transmission | ||
| 267 | * @datalength_bits: number of bits in the MMCIDATALENGTH register | 268 | * @datalength_bits: number of bits in the MMCIDATALENGTH register |
| 268 | * @fifosize: number of bytes that can be written when MMCI_TXFIFOEMPTY | 269 | * @fifosize: number of bytes that can be written when MMCI_TXFIFOEMPTY |
| 269 | * is asserted (likewise for RX) | 270 | * is asserted (likewise for RX) |
| @@ -316,6 +317,7 @@ struct variant_data { | |||
| 316 | unsigned int cmdreg_lrsp_crc; | 317 | unsigned int cmdreg_lrsp_crc; |
| 317 | unsigned int cmdreg_srsp_crc; | 318 | unsigned int cmdreg_srsp_crc; |
| 318 | unsigned int cmdreg_srsp; | 319 | unsigned int cmdreg_srsp; |
| 320 | unsigned int cmdreg_stop; | ||
| 319 | unsigned int datalength_bits; | 321 | unsigned int datalength_bits; |
| 320 | unsigned int fifosize; | 322 | unsigned int fifosize; |
| 321 | unsigned int fifohalfsize; | 323 | unsigned int fifohalfsize; |
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 6334cc752d8b..8afeaf81ae66 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c | |||
| @@ -1114,6 +1114,7 @@ static void msdc_start_command(struct msdc_host *host, | |||
| 1114 | struct mmc_request *mrq, struct mmc_command *cmd) | 1114 | struct mmc_request *mrq, struct mmc_command *cmd) |
| 1115 | { | 1115 | { |
| 1116 | u32 rawcmd; | 1116 | u32 rawcmd; |
| 1117 | unsigned long flags; | ||
| 1117 | 1118 | ||
| 1118 | WARN_ON(host->cmd); | 1119 | WARN_ON(host->cmd); |
| 1119 | host->cmd = cmd; | 1120 | host->cmd = cmd; |
| @@ -1131,7 +1132,10 @@ static void msdc_start_command(struct msdc_host *host, | |||
| 1131 | cmd->error = 0; | 1132 | cmd->error = 0; |
| 1132 | rawcmd = msdc_cmd_prepare_raw_cmd(host, mrq, cmd); | 1133 | rawcmd = msdc_cmd_prepare_raw_cmd(host, mrq, cmd); |
| 1133 | 1134 | ||
| 1135 | spin_lock_irqsave(&host->lock, flags); | ||
| 1134 | sdr_set_bits(host->base + MSDC_INTEN, cmd_ints_mask); | 1136 | sdr_set_bits(host->base + MSDC_INTEN, cmd_ints_mask); |
| 1137 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 1138 | |||
| 1135 | writel(cmd->arg, host->base + SDC_ARG); | 1139 | writel(cmd->arg, host->base + SDC_ARG); |
| 1136 | writel(rawcmd, host->base + SDC_CMD); | 1140 | writel(rawcmd, host->base + SDC_CMD); |
| 1137 | } | 1141 | } |
| @@ -1351,6 +1355,31 @@ static void msdc_request_timeout(struct work_struct *work) | |||
| 1351 | } | 1355 | } |
| 1352 | } | 1356 | } |
| 1353 | 1357 | ||
| 1358 | static void __msdc_enable_sdio_irq(struct mmc_host *mmc, int enb) | ||
| 1359 | { | ||
| 1360 | unsigned long flags; | ||
| 1361 | struct msdc_host *host = mmc_priv(mmc); | ||
| 1362 | |||
| 1363 | spin_lock_irqsave(&host->lock, flags); | ||
| 1364 | if (enb) | ||
| 1365 | sdr_set_bits(host->base + MSDC_INTEN, MSDC_INTEN_SDIOIRQ); | ||
| 1366 | else | ||
| 1367 | sdr_clr_bits(host->base + MSDC_INTEN, MSDC_INTEN_SDIOIRQ); | ||
| 1368 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 1369 | } | ||
| 1370 | |||
| 1371 | static void msdc_enable_sdio_irq(struct mmc_host *mmc, int enb) | ||
| 1372 | { | ||
| 1373 | struct msdc_host *host = mmc_priv(mmc); | ||
| 1374 | |||
| 1375 | __msdc_enable_sdio_irq(mmc, enb); | ||
| 1376 | |||
| 1377 | if (enb) | ||
| 1378 | pm_runtime_get_noresume(host->dev); | ||
| 1379 | else | ||
| 1380 | pm_runtime_put_noidle(host->dev); | ||
| 1381 | } | ||
| 1382 | |||
| 1354 | static irqreturn_t msdc_irq(int irq, void *dev_id) | 1383 | static irqreturn_t msdc_irq(int irq, void *dev_id) |
| 1355 | { | 1384 | { |
| 1356 | struct msdc_host *host = (struct msdc_host *) dev_id; | 1385 | struct msdc_host *host = (struct msdc_host *) dev_id; |
| @@ -1373,7 +1402,12 @@ static irqreturn_t msdc_irq(int irq, void *dev_id) | |||
| 1373 | data = host->data; | 1402 | data = host->data; |
| 1374 | spin_unlock_irqrestore(&host->lock, flags); | 1403 | spin_unlock_irqrestore(&host->lock, flags); |
| 1375 | 1404 | ||
| 1376 | if (!(events & event_mask)) | 1405 | if ((events & event_mask) & MSDC_INT_SDIOIRQ) { |
| 1406 | __msdc_enable_sdio_irq(host->mmc, 0); | ||
| 1407 | sdio_signal_irq(host->mmc); | ||
| 1408 | } | ||
| 1409 | |||
| 1410 | if (!(events & (event_mask & ~MSDC_INT_SDIOIRQ))) | ||
| 1377 | break; | 1411 | break; |
| 1378 | 1412 | ||
| 1379 | if (!mrq) { | 1413 | if (!mrq) { |
| @@ -1493,8 +1527,11 @@ static void msdc_init_hw(struct msdc_host *host) | |||
| 1493 | */ | 1527 | */ |
| 1494 | sdr_set_bits(host->base + SDC_CFG, SDC_CFG_SDIO); | 1528 | sdr_set_bits(host->base + SDC_CFG, SDC_CFG_SDIO); |
| 1495 | 1529 | ||
| 1496 | /* disable detect SDIO device interrupt function */ | 1530 | /* Config SDIO device detect interrupt function */ |
| 1497 | sdr_clr_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE); | 1531 | if (host->mmc->caps & MMC_CAP_SDIO_IRQ) |
| 1532 | sdr_set_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE); | ||
| 1533 | else | ||
| 1534 | sdr_clr_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE); | ||
| 1498 | 1535 | ||
| 1499 | /* Configure to default data timeout */ | 1536 | /* Configure to default data timeout */ |
| 1500 | sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, 3); | 1537 | sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, 3); |
| @@ -2013,6 +2050,11 @@ static void msdc_hw_reset(struct mmc_host *mmc) | |||
| 2013 | sdr_clr_bits(host->base + EMMC_IOCON, 1); | 2050 | sdr_clr_bits(host->base + EMMC_IOCON, 1); |
| 2014 | } | 2051 | } |
| 2015 | 2052 | ||
| 2053 | static void msdc_ack_sdio_irq(struct mmc_host *mmc) | ||
| 2054 | { | ||
| 2055 | __msdc_enable_sdio_irq(mmc, 1); | ||
| 2056 | } | ||
| 2057 | |||
| 2016 | static const struct mmc_host_ops mt_msdc_ops = { | 2058 | static const struct mmc_host_ops mt_msdc_ops = { |
| 2017 | .post_req = msdc_post_req, | 2059 | .post_req = msdc_post_req, |
| 2018 | .pre_req = msdc_pre_req, | 2060 | .pre_req = msdc_pre_req, |
| @@ -2020,6 +2062,8 @@ static const struct mmc_host_ops mt_msdc_ops = { | |||
| 2020 | .set_ios = msdc_ops_set_ios, | 2062 | .set_ios = msdc_ops_set_ios, |
| 2021 | .get_ro = mmc_gpio_get_ro, | 2063 | .get_ro = mmc_gpio_get_ro, |
| 2022 | .get_cd = mmc_gpio_get_cd, | 2064 | .get_cd = mmc_gpio_get_cd, |
| 2065 | .enable_sdio_irq = msdc_enable_sdio_irq, | ||
| 2066 | .ack_sdio_irq = msdc_ack_sdio_irq, | ||
| 2023 | .start_signal_voltage_switch = msdc_ops_switch_volt, | 2067 | .start_signal_voltage_switch = msdc_ops_switch_volt, |
| 2024 | .card_busy = msdc_card_busy, | 2068 | .card_busy = msdc_card_busy, |
| 2025 | .execute_tuning = msdc_execute_tuning, | 2069 | .execute_tuning = msdc_execute_tuning, |
| @@ -2147,6 +2191,9 @@ static int msdc_drv_probe(struct platform_device *pdev) | |||
| 2147 | else | 2191 | else |
| 2148 | mmc->f_min = DIV_ROUND_UP(host->src_clk_freq, 4 * 4095); | 2192 | mmc->f_min = DIV_ROUND_UP(host->src_clk_freq, 4 * 4095); |
| 2149 | 2193 | ||
| 2194 | if (mmc->caps & MMC_CAP_SDIO_IRQ) | ||
| 2195 | mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD; | ||
| 2196 | |||
| 2150 | mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23; | 2197 | mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23; |
| 2151 | /* MMC core transfer sizes tunable parameters */ | 2198 | /* MMC core transfer sizes tunable parameters */ |
| 2152 | mmc->max_segs = MAX_BD_NUM; | 2199 | mmc->max_segs = MAX_BD_NUM; |
diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c index c9eed8436b6b..b294b221f225 100644 --- a/drivers/mmc/host/of_mmc_spi.c +++ b/drivers/mmc/host/of_mmc_spi.c | |||
| @@ -16,9 +16,7 @@ | |||
| 16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
| 19 | #include <linux/gpio.h> | ||
| 20 | #include <linux/of.h> | 19 | #include <linux/of.h> |
| 21 | #include <linux/of_gpio.h> | ||
| 22 | #include <linux/of_irq.h> | 20 | #include <linux/of_irq.h> |
| 23 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
| 24 | #include <linux/spi/mmc_spi.h> | 22 | #include <linux/spi/mmc_spi.h> |
| @@ -32,15 +30,7 @@ | |||
| 32 | 30 | ||
| 33 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
| 34 | 32 | ||
| 35 | enum { | ||
| 36 | CD_GPIO = 0, | ||
| 37 | WP_GPIO, | ||
| 38 | NUM_GPIOS, | ||
| 39 | }; | ||
| 40 | |||
| 41 | struct of_mmc_spi { | 33 | struct of_mmc_spi { |
| 42 | int gpios[NUM_GPIOS]; | ||
| 43 | bool alow_gpios[NUM_GPIOS]; | ||
| 44 | int detect_irq; | 34 | int detect_irq; |
| 45 | struct mmc_spi_platform_data pdata; | 35 | struct mmc_spi_platform_data pdata; |
| 46 | }; | 36 | }; |
| @@ -102,30 +92,6 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi) | |||
| 102 | oms->pdata.ocr_mask |= mask; | 92 | oms->pdata.ocr_mask |= mask; |
| 103 | } | 93 | } |
| 104 | 94 | ||
| 105 | for (i = 0; i < ARRAY_SIZE(oms->gpios); i++) { | ||
| 106 | enum of_gpio_flags gpio_flags; | ||
| 107 | |||
| 108 | oms->gpios[i] = of_get_gpio_flags(np, i, &gpio_flags); | ||
| 109 | if (!gpio_is_valid(oms->gpios[i])) | ||
| 110 | continue; | ||
| 111 | |||
| 112 | if (gpio_flags & OF_GPIO_ACTIVE_LOW) | ||
| 113 | oms->alow_gpios[i] = true; | ||
| 114 | } | ||
| 115 | |||
| 116 | if (gpio_is_valid(oms->gpios[CD_GPIO])) { | ||
| 117 | oms->pdata.cd_gpio = oms->gpios[CD_GPIO]; | ||
| 118 | oms->pdata.flags |= MMC_SPI_USE_CD_GPIO; | ||
| 119 | if (!oms->alow_gpios[CD_GPIO]) | ||
| 120 | oms->pdata.caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; | ||
| 121 | } | ||
| 122 | if (gpio_is_valid(oms->gpios[WP_GPIO])) { | ||
| 123 | oms->pdata.ro_gpio = oms->gpios[WP_GPIO]; | ||
| 124 | oms->pdata.flags |= MMC_SPI_USE_RO_GPIO; | ||
| 125 | if (!oms->alow_gpios[WP_GPIO]) | ||
| 126 | oms->pdata.caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; | ||
| 127 | } | ||
| 128 | |||
| 129 | oms->detect_irq = irq_of_parse_and_map(np, 0); | 95 | oms->detect_irq = irq_of_parse_and_map(np, 0); |
| 130 | if (oms->detect_irq != 0) { | 96 | if (oms->detect_irq != 0) { |
| 131 | oms->pdata.init = of_mmc_spi_init; | 97 | oms->pdata.init = of_mmc_spi_init; |
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 3f4ea8f624be..29a1ddaa7466 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
| @@ -1652,7 +1652,7 @@ static struct mmc_host_ops omap_hsmmc_ops = { | |||
| 1652 | 1652 | ||
| 1653 | #ifdef CONFIG_DEBUG_FS | 1653 | #ifdef CONFIG_DEBUG_FS |
| 1654 | 1654 | ||
| 1655 | static int omap_hsmmc_regs_show(struct seq_file *s, void *data) | 1655 | static int mmc_regs_show(struct seq_file *s, void *data) |
| 1656 | { | 1656 | { |
| 1657 | struct mmc_host *mmc = s->private; | 1657 | struct mmc_host *mmc = s->private; |
| 1658 | struct omap_hsmmc_host *host = mmc_priv(mmc); | 1658 | struct omap_hsmmc_host *host = mmc_priv(mmc); |
| @@ -1691,17 +1691,7 @@ static int omap_hsmmc_regs_show(struct seq_file *s, void *data) | |||
| 1691 | return 0; | 1691 | return 0; |
| 1692 | } | 1692 | } |
| 1693 | 1693 | ||
| 1694 | static int omap_hsmmc_regs_open(struct inode *inode, struct file *file) | 1694 | DEFINE_SHOW_ATTRIBUTE(mmc_regs); |
| 1695 | { | ||
| 1696 | return single_open(file, omap_hsmmc_regs_show, inode->i_private); | ||
| 1697 | } | ||
| 1698 | |||
| 1699 | static const struct file_operations mmc_regs_fops = { | ||
| 1700 | .open = omap_hsmmc_regs_open, | ||
| 1701 | .read = seq_read, | ||
| 1702 | .llseek = seq_lseek, | ||
| 1703 | .release = single_release, | ||
| 1704 | }; | ||
| 1705 | 1695 | ||
| 1706 | static void omap_hsmmc_debugfs(struct mmc_host *mmc) | 1696 | static void omap_hsmmc_debugfs(struct mmc_host *mmc) |
| 1707 | { | 1697 | { |
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index f7ffbf1676b1..8779bbaa6b69 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c | |||
| @@ -30,10 +30,9 @@ | |||
| 30 | #include <linux/mmc/slot-gpio.h> | 30 | #include <linux/mmc/slot-gpio.h> |
| 31 | #include <linux/io.h> | 31 | #include <linux/io.h> |
| 32 | #include <linux/regulator/consumer.h> | 32 | #include <linux/regulator/consumer.h> |
| 33 | #include <linux/gpio.h> | 33 | #include <linux/gpio/consumer.h> |
| 34 | #include <linux/gfp.h> | 34 | #include <linux/gfp.h> |
| 35 | #include <linux/of.h> | 35 | #include <linux/of.h> |
| 36 | #include <linux/of_gpio.h> | ||
| 37 | #include <linux/of_device.h> | 36 | #include <linux/of_device.h> |
| 38 | 37 | ||
| 39 | #include <asm/sizes.h> | 38 | #include <asm/sizes.h> |
| @@ -63,6 +62,8 @@ struct pxamci_host { | |||
| 63 | unsigned int imask; | 62 | unsigned int imask; |
| 64 | unsigned int power_mode; | 63 | unsigned int power_mode; |
| 65 | unsigned long detect_delay_ms; | 64 | unsigned long detect_delay_ms; |
| 65 | bool use_ro_gpio; | ||
| 66 | struct gpio_desc *power; | ||
| 66 | struct pxamci_platform_data *pdata; | 67 | struct pxamci_platform_data *pdata; |
| 67 | 68 | ||
| 68 | struct mmc_request *mrq; | 69 | struct mmc_request *mrq; |
| @@ -101,16 +102,13 @@ static inline int pxamci_set_power(struct pxamci_host *host, | |||
| 101 | { | 102 | { |
| 102 | struct mmc_host *mmc = host->mmc; | 103 | struct mmc_host *mmc = host->mmc; |
| 103 | struct regulator *supply = mmc->supply.vmmc; | 104 | struct regulator *supply = mmc->supply.vmmc; |
| 104 | int on; | ||
| 105 | 105 | ||
| 106 | if (!IS_ERR(supply)) | 106 | if (!IS_ERR(supply)) |
| 107 | return mmc_regulator_set_ocr(mmc, supply, vdd); | 107 | return mmc_regulator_set_ocr(mmc, supply, vdd); |
| 108 | 108 | ||
| 109 | if (host->pdata && | 109 | if (host->power) { |
| 110 | gpio_is_valid(host->pdata->gpio_power)) { | 110 | bool on = !!((1 << vdd) & host->pdata->ocr_mask); |
| 111 | on = ((1 << vdd) & host->pdata->ocr_mask); | 111 | gpiod_set_value(host->power, on); |
| 112 | gpio_set_value(host->pdata->gpio_power, | ||
| 113 | !!on ^ host->pdata->gpio_power_invert); | ||
| 114 | } | 112 | } |
| 115 | 113 | ||
| 116 | if (host->pdata && host->pdata->setpower) | 114 | if (host->pdata && host->pdata->setpower) |
| @@ -432,7 +430,7 @@ static int pxamci_get_ro(struct mmc_host *mmc) | |||
| 432 | { | 430 | { |
| 433 | struct pxamci_host *host = mmc_priv(mmc); | 431 | struct pxamci_host *host = mmc_priv(mmc); |
| 434 | 432 | ||
| 435 | if (host->pdata && gpio_is_valid(host->pdata->gpio_card_ro)) | 433 | if (host->use_ro_gpio) |
| 436 | return mmc_gpio_get_ro(mmc); | 434 | return mmc_gpio_get_ro(mmc); |
| 437 | if (host->pdata && host->pdata->get_ro) | 435 | if (host->pdata && host->pdata->get_ro) |
| 438 | return !!host->pdata->get_ro(mmc_dev(mmc)); | 436 | return !!host->pdata->get_ro(mmc_dev(mmc)); |
| @@ -730,52 +728,38 @@ static int pxamci_probe(struct platform_device *pdev) | |||
| 730 | } | 728 | } |
| 731 | 729 | ||
| 732 | if (host->pdata) { | 730 | if (host->pdata) { |
| 733 | int gpio_cd = host->pdata->gpio_card_detect; | ||
| 734 | int gpio_ro = host->pdata->gpio_card_ro; | ||
| 735 | int gpio_power = host->pdata->gpio_power; | ||
| 736 | |||
| 737 | host->detect_delay_ms = host->pdata->detect_delay_ms; | 731 | host->detect_delay_ms = host->pdata->detect_delay_ms; |
| 738 | 732 | ||
| 739 | if (gpio_is_valid(gpio_power)) { | 733 | host->power = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW); |
| 740 | ret = devm_gpio_request(dev, gpio_power, | 734 | if (IS_ERR(host->power)) { |
| 741 | "mmc card power"); | 735 | dev_err(dev, "Failed requesting gpio_power\n"); |
| 742 | if (ret) { | 736 | goto out; |
| 743 | dev_err(dev, | ||
| 744 | "Failed requesting gpio_power %d\n", | ||
| 745 | gpio_power); | ||
| 746 | goto out; | ||
| 747 | } | ||
| 748 | gpio_direction_output(gpio_power, | ||
| 749 | host->pdata->gpio_power_invert); | ||
| 750 | } | 737 | } |
| 751 | 738 | ||
| 752 | if (gpio_is_valid(gpio_ro)) { | 739 | /* FIXME: should we pass detection delay to debounce? */ |
| 753 | ret = mmc_gpio_request_ro(mmc, gpio_ro); | 740 | ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0, NULL); |
| 754 | if (ret) { | 741 | if (ret && ret != -ENOENT) { |
| 755 | dev_err(dev, | 742 | dev_err(dev, "Failed requesting gpio_cd\n"); |
| 756 | "Failed requesting gpio_ro %d\n", | 743 | goto out; |
| 757 | gpio_ro); | ||
| 758 | goto out; | ||
| 759 | } else { | ||
| 760 | mmc->caps2 |= host->pdata->gpio_card_ro_invert ? | ||
| 761 | 0 : MMC_CAP2_RO_ACTIVE_HIGH; | ||
| 762 | } | ||
| 763 | } | 744 | } |
| 764 | 745 | ||
| 765 | if (gpio_is_valid(gpio_cd)) | 746 | ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0, NULL); |
| 766 | ret = mmc_gpio_request_cd(mmc, gpio_cd, 0); | 747 | if (ret && ret != -ENOENT) { |
| 767 | if (ret) { | 748 | dev_err(dev, "Failed requesting gpio_ro\n"); |
| 768 | dev_err(dev, "Failed requesting gpio_cd %d\n", | ||
| 769 | gpio_cd); | ||
| 770 | goto out; | 749 | goto out; |
| 771 | } | 750 | } |
| 751 | if (!ret) { | ||
| 752 | host->use_ro_gpio = true; | ||
| 753 | mmc->caps2 |= host->pdata->gpio_card_ro_invert ? | ||
| 754 | 0 : MMC_CAP2_RO_ACTIVE_HIGH; | ||
| 755 | } | ||
| 772 | 756 | ||
| 773 | if (host->pdata->init) | 757 | if (host->pdata->init) |
| 774 | host->pdata->init(dev, pxamci_detect_irq, mmc); | 758 | host->pdata->init(dev, pxamci_detect_irq, mmc); |
| 775 | 759 | ||
| 776 | if (gpio_is_valid(gpio_power) && host->pdata->setpower) | 760 | if (host->power && host->pdata->setpower) |
| 777 | dev_warn(dev, "gpio_power and setpower() both defined\n"); | 761 | dev_warn(dev, "gpio_power and setpower() both defined\n"); |
| 778 | if (gpio_is_valid(gpio_ro) && host->pdata->get_ro) | 762 | if (host->use_ro_gpio && host->pdata->get_ro) |
| 779 | dev_warn(dev, "gpio_ro and get_ro() both defined\n"); | 763 | dev_warn(dev, "gpio_ro and get_ro() both defined\n"); |
| 780 | } | 764 | } |
| 781 | 765 | ||
diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index d3ac43c3d0b6..31a351a20dc0 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/pinctrl/consumer.h> | 32 | #include <linux/pinctrl/consumer.h> |
| 33 | #include <linux/pinctrl/pinctrl-state.h> | 33 | #include <linux/pinctrl/pinctrl-state.h> |
| 34 | #include <linux/regulator/consumer.h> | 34 | #include <linux/regulator/consumer.h> |
| 35 | #include <linux/sys_soc.h> | ||
| 35 | 36 | ||
| 36 | #include "renesas_sdhi.h" | 37 | #include "renesas_sdhi.h" |
| 37 | #include "tmio_mmc.h" | 38 | #include "tmio_mmc.h" |
| @@ -45,6 +46,11 @@ | |||
| 45 | #define SDHI_VER_GEN3_SD 0xcc10 | 46 | #define SDHI_VER_GEN3_SD 0xcc10 |
| 46 | #define SDHI_VER_GEN3_SDMMC 0xcd10 | 47 | #define SDHI_VER_GEN3_SDMMC 0xcd10 |
| 47 | 48 | ||
| 49 | struct renesas_sdhi_quirks { | ||
| 50 | bool hs400_disabled; | ||
| 51 | bool hs400_4taps; | ||
| 52 | }; | ||
| 53 | |||
| 48 | static void renesas_sdhi_sdbuf_width(struct tmio_mmc_host *host, int width) | 54 | static void renesas_sdhi_sdbuf_width(struct tmio_mmc_host *host, int width) |
| 49 | { | 55 | { |
| 50 | u32 val; | 56 | u32 val; |
| @@ -163,15 +169,6 @@ static void renesas_sdhi_set_clock(struct tmio_mmc_host *host, | |||
| 163 | if (new_clock == 0) | 169 | if (new_clock == 0) |
| 164 | goto out; | 170 | goto out; |
| 165 | 171 | ||
| 166 | /* | ||
| 167 | * Both HS400 and HS200/SD104 set 200MHz, but some devices need to | ||
| 168 | * set 400MHz to distinguish the CPG settings in HS400. | ||
| 169 | */ | ||
| 170 | if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 && | ||
| 171 | host->pdata->flags & TMIO_MMC_HAVE_4TAP_HS400 && | ||
| 172 | new_clock == 200000000) | ||
| 173 | new_clock = 400000000; | ||
| 174 | |||
| 175 | clock = renesas_sdhi_clk_update(host, new_clock) / 512; | 172 | clock = renesas_sdhi_clk_update(host, new_clock) / 512; |
| 176 | 173 | ||
| 177 | for (clk = 0x80000080; new_clock >= (clock << 1); clk >>= 1) | 174 | for (clk = 0x80000080; new_clock >= (clock << 1); clk >>= 1) |
| @@ -532,6 +529,10 @@ static void renesas_sdhi_hw_reset(struct tmio_mmc_host *host) | |||
| 532 | sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL, | 529 | sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL, |
| 533 | ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN & | 530 | ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN & |
| 534 | sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL)); | 531 | sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL)); |
| 532 | |||
| 533 | if (host->pdata->flags & TMIO_MMC_MIN_RCAR2) | ||
| 534 | sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, | ||
| 535 | TMIO_MASK_INIT_RCAR2); | ||
| 535 | } | 536 | } |
| 536 | 537 | ||
| 537 | static int renesas_sdhi_wait_idle(struct tmio_mmc_host *host, u32 bit) | 538 | static int renesas_sdhi_wait_idle(struct tmio_mmc_host *host, u32 bit) |
| @@ -602,11 +603,31 @@ static void renesas_sdhi_enable_dma(struct tmio_mmc_host *host, bool enable) | |||
| 602 | renesas_sdhi_sdbuf_width(host, enable ? width : 16); | 603 | renesas_sdhi_sdbuf_width(host, enable ? width : 16); |
| 603 | } | 604 | } |
| 604 | 605 | ||
| 606 | static const struct renesas_sdhi_quirks sdhi_quirks_h3_m3w_es1 = { | ||
| 607 | .hs400_disabled = true, | ||
| 608 | .hs400_4taps = true, | ||
| 609 | }; | ||
| 610 | |||
| 611 | static const struct renesas_sdhi_quirks sdhi_quirks_h3_es2 = { | ||
| 612 | .hs400_disabled = false, | ||
| 613 | .hs400_4taps = true, | ||
| 614 | }; | ||
| 615 | |||
| 616 | static const struct soc_device_attribute sdhi_quirks_match[] = { | ||
| 617 | { .soc_id = "r8a7795", .revision = "ES1.*", .data = &sdhi_quirks_h3_m3w_es1 }, | ||
| 618 | { .soc_id = "r8a7795", .revision = "ES2.0", .data = &sdhi_quirks_h3_es2 }, | ||
| 619 | { .soc_id = "r8a7796", .revision = "ES1.0", .data = &sdhi_quirks_h3_m3w_es1 }, | ||
| 620 | { .soc_id = "r8a7796", .revision = "ES1.1", .data = &sdhi_quirks_h3_m3w_es1 }, | ||
| 621 | { /* Sentinel. */ }, | ||
| 622 | }; | ||
| 623 | |||
| 605 | int renesas_sdhi_probe(struct platform_device *pdev, | 624 | int renesas_sdhi_probe(struct platform_device *pdev, |
| 606 | const struct tmio_mmc_dma_ops *dma_ops) | 625 | const struct tmio_mmc_dma_ops *dma_ops) |
| 607 | { | 626 | { |
| 608 | struct tmio_mmc_data *mmd = pdev->dev.platform_data; | 627 | struct tmio_mmc_data *mmd = pdev->dev.platform_data; |
| 628 | const struct renesas_sdhi_quirks *quirks = NULL; | ||
| 609 | const struct renesas_sdhi_of_data *of_data; | 629 | const struct renesas_sdhi_of_data *of_data; |
| 630 | const struct soc_device_attribute *attr; | ||
| 610 | struct tmio_mmc_data *mmc_data; | 631 | struct tmio_mmc_data *mmc_data; |
| 611 | struct tmio_mmc_dma *dma_priv; | 632 | struct tmio_mmc_dma *dma_priv; |
| 612 | struct tmio_mmc_host *host; | 633 | struct tmio_mmc_host *host; |
| @@ -616,6 +637,10 @@ int renesas_sdhi_probe(struct platform_device *pdev, | |||
| 616 | 637 | ||
| 617 | of_data = of_device_get_match_data(&pdev->dev); | 638 | of_data = of_device_get_match_data(&pdev->dev); |
| 618 | 639 | ||
| 640 | attr = soc_device_match(sdhi_quirks_match); | ||
| 641 | if (attr) | ||
| 642 | quirks = attr->data; | ||
| 643 | |||
| 619 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 644 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 620 | if (!res) | 645 | if (!res) |
| 621 | return -EINVAL; | 646 | return -EINVAL; |
| @@ -681,6 +706,12 @@ int renesas_sdhi_probe(struct platform_device *pdev, | |||
| 681 | host->multi_io_quirk = renesas_sdhi_multi_io_quirk; | 706 | host->multi_io_quirk = renesas_sdhi_multi_io_quirk; |
| 682 | host->dma_ops = dma_ops; | 707 | host->dma_ops = dma_ops; |
| 683 | 708 | ||
| 709 | if (quirks && quirks->hs400_disabled) | ||
| 710 | host->mmc->caps2 &= ~(MMC_CAP2_HS400 | MMC_CAP2_HS400_ES); | ||
| 711 | |||
| 712 | if (quirks && quirks->hs400_4taps) | ||
| 713 | mmc_data->flags |= TMIO_MMC_HAVE_4TAP_HS400; | ||
| 714 | |||
| 684 | /* For some SoC, we disable internal WP. GPIO may override this */ | 715 | /* For some SoC, we disable internal WP. GPIO may override this */ |
| 685 | if (mmc_can_gpio_ro(host->mmc)) | 716 | if (mmc_can_gpio_ro(host->mmc)) |
| 686 | mmc_data->capabilities2 &= ~MMC_CAP2_NO_WRITE_PROTECT; | 717 | mmc_data->capabilities2 &= ~MMC_CAP2_NO_WRITE_PROTECT; |
| @@ -691,6 +722,7 @@ int renesas_sdhi_probe(struct platform_device *pdev, | |||
| 691 | host->ops.card_busy = renesas_sdhi_card_busy; | 722 | host->ops.card_busy = renesas_sdhi_card_busy; |
| 692 | host->ops.start_signal_voltage_switch = | 723 | host->ops.start_signal_voltage_switch = |
| 693 | renesas_sdhi_start_signal_voltage_switch; | 724 | renesas_sdhi_start_signal_voltage_switch; |
| 725 | host->sdcard_irq_setbit_mask = TMIO_STAT_ALWAYS_SET_27; | ||
| 694 | } | 726 | } |
| 695 | 727 | ||
| 696 | /* Orginally registers were 16 bit apart, could be 32 or 64 nowadays */ | 728 | /* Orginally registers were 16 bit apart, could be 32 or 64 nowadays */ |
diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index b6f54102bfdd..92c9b15252da 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c | |||
| @@ -34,7 +34,7 @@ | |||
| 34 | #define DTRAN_MODE_CH_NUM_CH0 0 /* "downstream" = for write commands */ | 34 | #define DTRAN_MODE_CH_NUM_CH0 0 /* "downstream" = for write commands */ |
| 35 | #define DTRAN_MODE_CH_NUM_CH1 BIT(16) /* "upstream" = for read commands */ | 35 | #define DTRAN_MODE_CH_NUM_CH1 BIT(16) /* "upstream" = for read commands */ |
| 36 | #define DTRAN_MODE_BUS_WIDTH (BIT(5) | BIT(4)) | 36 | #define DTRAN_MODE_BUS_WIDTH (BIT(5) | BIT(4)) |
| 37 | #define DTRAN_MODE_ADDR_MODE BIT(0) /* 1 = Increment address */ | 37 | #define DTRAN_MODE_ADDR_MODE BIT(0) /* 1 = Increment address, 0 = Fixed */ |
| 38 | 38 | ||
| 39 | /* DM_CM_DTRAN_CTRL */ | 39 | /* DM_CM_DTRAN_CTRL */ |
| 40 | #define DTRAN_CTRL_DM_START BIT(0) | 40 | #define DTRAN_CTRL_DM_START BIT(0) |
| @@ -73,6 +73,9 @@ static unsigned long global_flags; | |||
| 73 | #define SDHI_INTERNAL_DMAC_ONE_RX_ONLY 0 | 73 | #define SDHI_INTERNAL_DMAC_ONE_RX_ONLY 0 |
| 74 | #define SDHI_INTERNAL_DMAC_RX_IN_USE 1 | 74 | #define SDHI_INTERNAL_DMAC_RX_IN_USE 1 |
| 75 | 75 | ||
| 76 | /* RZ/A2 does not have the ADRR_MODE bit */ | ||
| 77 | #define SDHI_INTERNAL_DMAC_ADDR_MODE_FIXED_ONLY 2 | ||
| 78 | |||
| 76 | /* Definitions for sampling clocks */ | 79 | /* Definitions for sampling clocks */ |
| 77 | static struct renesas_sdhi_scc rcar_gen3_scc_taps[] = { | 80 | static struct renesas_sdhi_scc rcar_gen3_scc_taps[] = { |
| 78 | { | 81 | { |
| @@ -81,15 +84,14 @@ static struct renesas_sdhi_scc rcar_gen3_scc_taps[] = { | |||
| 81 | }, | 84 | }, |
| 82 | }; | 85 | }; |
| 83 | 86 | ||
| 84 | static const struct renesas_sdhi_of_data of_rcar_r8a7795_compatible = { | 87 | static const struct renesas_sdhi_of_data of_rza2_compatible = { |
| 85 | .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL | | 88 | .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL | |
| 86 | TMIO_MMC_HAVE_CBSY | TMIO_MMC_MIN_RCAR2 | | 89 | TMIO_MMC_HAVE_CBSY, |
| 87 | TMIO_MMC_HAVE_4TAP_HS400, | 90 | .tmio_ocr_mask = MMC_VDD_32_33, |
| 88 | .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | | 91 | .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | |
| 89 | MMC_CAP_CMD23, | 92 | MMC_CAP_CMD23, |
| 90 | .capabilities2 = MMC_CAP2_NO_WRITE_PROTECT, | ||
| 91 | .bus_shift = 2, | 93 | .bus_shift = 2, |
| 92 | .scc_offset = 0x1000, | 94 | .scc_offset = 0 - 0x1000, |
| 93 | .taps = rcar_gen3_scc_taps, | 95 | .taps = rcar_gen3_scc_taps, |
| 94 | .taps_num = ARRAY_SIZE(rcar_gen3_scc_taps), | 96 | .taps_num = ARRAY_SIZE(rcar_gen3_scc_taps), |
| 95 | /* DMAC can handle 0xffffffff blk count but only 1 segment */ | 97 | /* DMAC can handle 0xffffffff blk count but only 1 segment */ |
| @@ -113,9 +115,10 @@ static const struct renesas_sdhi_of_data of_rcar_gen3_compatible = { | |||
| 113 | }; | 115 | }; |
| 114 | 116 | ||
| 115 | static const struct of_device_id renesas_sdhi_internal_dmac_of_match[] = { | 117 | static const struct of_device_id renesas_sdhi_internal_dmac_of_match[] = { |
| 118 | { .compatible = "renesas,sdhi-r7s9210", .data = &of_rza2_compatible, }, | ||
| 116 | { .compatible = "renesas,sdhi-mmc-r8a77470", .data = &of_rcar_gen3_compatible, }, | 119 | { .compatible = "renesas,sdhi-mmc-r8a77470", .data = &of_rcar_gen3_compatible, }, |
| 117 | { .compatible = "renesas,sdhi-r8a7795", .data = &of_rcar_r8a7795_compatible, }, | 120 | { .compatible = "renesas,sdhi-r8a7795", .data = &of_rcar_gen3_compatible, }, |
| 118 | { .compatible = "renesas,sdhi-r8a7796", .data = &of_rcar_r8a7795_compatible, }, | 121 | { .compatible = "renesas,sdhi-r8a7796", .data = &of_rcar_gen3_compatible, }, |
| 119 | { .compatible = "renesas,rcar-gen3-sdhi", .data = &of_rcar_gen3_compatible, }, | 122 | { .compatible = "renesas,rcar-gen3-sdhi", .data = &of_rcar_gen3_compatible, }, |
| 120 | {}, | 123 | {}, |
| 121 | }; | 124 | }; |
| @@ -172,7 +175,10 @@ renesas_sdhi_internal_dmac_start_dma(struct tmio_mmc_host *host, | |||
| 172 | struct mmc_data *data) | 175 | struct mmc_data *data) |
| 173 | { | 176 | { |
| 174 | struct scatterlist *sg = host->sg_ptr; | 177 | struct scatterlist *sg = host->sg_ptr; |
| 175 | u32 dtran_mode = DTRAN_MODE_BUS_WIDTH | DTRAN_MODE_ADDR_MODE; | 178 | u32 dtran_mode = DTRAN_MODE_BUS_WIDTH; |
| 179 | |||
| 180 | if (!test_bit(SDHI_INTERNAL_DMAC_ADDR_MODE_FIXED_ONLY, &global_flags)) | ||
| 181 | dtran_mode |= DTRAN_MODE_ADDR_MODE; | ||
| 176 | 182 | ||
| 177 | if (!dma_map_sg(&host->pdev->dev, sg, host->sg_len, | 183 | if (!dma_map_sg(&host->pdev->dev, sg, host->sg_len, |
| 178 | mmc_get_dma_dir(data))) | 184 | mmc_get_dma_dir(data))) |
| @@ -292,18 +298,22 @@ static const struct tmio_mmc_dma_ops renesas_sdhi_internal_dmac_dma_ops = { | |||
| 292 | */ | 298 | */ |
| 293 | static const struct soc_device_attribute soc_whitelist[] = { | 299 | static const struct soc_device_attribute soc_whitelist[] = { |
| 294 | /* specific ones */ | 300 | /* specific ones */ |
| 301 | { .soc_id = "r7s9210", | ||
| 302 | .data = (void *)BIT(SDHI_INTERNAL_DMAC_ADDR_MODE_FIXED_ONLY) }, | ||
| 295 | { .soc_id = "r8a7795", .revision = "ES1.*", | 303 | { .soc_id = "r8a7795", .revision = "ES1.*", |
| 296 | .data = (void *)BIT(SDHI_INTERNAL_DMAC_ONE_RX_ONLY) }, | 304 | .data = (void *)BIT(SDHI_INTERNAL_DMAC_ONE_RX_ONLY) }, |
| 297 | { .soc_id = "r8a7796", .revision = "ES1.0", | 305 | { .soc_id = "r8a7796", .revision = "ES1.0", |
| 298 | .data = (void *)BIT(SDHI_INTERNAL_DMAC_ONE_RX_ONLY) }, | 306 | .data = (void *)BIT(SDHI_INTERNAL_DMAC_ONE_RX_ONLY) }, |
| 299 | /* generic ones */ | 307 | /* generic ones */ |
| 300 | { .soc_id = "r8a774a1" }, | 308 | { .soc_id = "r8a774a1" }, |
| 309 | { .soc_id = "r8a774c0" }, | ||
| 301 | { .soc_id = "r8a77470" }, | 310 | { .soc_id = "r8a77470" }, |
| 302 | { .soc_id = "r8a7795" }, | 311 | { .soc_id = "r8a7795" }, |
| 303 | { .soc_id = "r8a7796" }, | 312 | { .soc_id = "r8a7796" }, |
| 304 | { .soc_id = "r8a77965" }, | 313 | { .soc_id = "r8a77965" }, |
| 305 | { .soc_id = "r8a77970" }, | 314 | { .soc_id = "r8a77970" }, |
| 306 | { .soc_id = "r8a77980" }, | 315 | { .soc_id = "r8a77980" }, |
| 316 | { .soc_id = "r8a77990" }, | ||
| 307 | { .soc_id = "r8a77995" }, | 317 | { .soc_id = "r8a77995" }, |
| 308 | { /* sentinel */ } | 318 | { /* sentinel */ } |
| 309 | }; | 319 | }; |
diff --git a/drivers/mmc/host/renesas_sdhi_sys_dmac.c b/drivers/mmc/host/renesas_sdhi_sys_dmac.c index 1a4016f635d3..8471160316e0 100644 --- a/drivers/mmc/host/renesas_sdhi_sys_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_sys_dmac.c | |||
| @@ -75,19 +75,6 @@ static struct renesas_sdhi_scc rcar_gen3_scc_taps[] = { | |||
| 75 | }, | 75 | }, |
| 76 | }; | 76 | }; |
| 77 | 77 | ||
| 78 | static const struct renesas_sdhi_of_data of_rcar_r8a7795_compatible = { | ||
| 79 | .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL | | ||
| 80 | TMIO_MMC_HAVE_CBSY | TMIO_MMC_MIN_RCAR2 | | ||
| 81 | TMIO_MMC_HAVE_4TAP_HS400, | ||
| 82 | .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | | ||
| 83 | MMC_CAP_CMD23, | ||
| 84 | .capabilities2 = MMC_CAP2_NO_WRITE_PROTECT, | ||
| 85 | .bus_shift = 2, | ||
| 86 | .scc_offset = 0x1000, | ||
| 87 | .taps = rcar_gen3_scc_taps, | ||
| 88 | .taps_num = ARRAY_SIZE(rcar_gen3_scc_taps), | ||
| 89 | }; | ||
| 90 | |||
| 91 | static const struct renesas_sdhi_of_data of_rcar_gen3_compatible = { | 78 | static const struct renesas_sdhi_of_data of_rcar_gen3_compatible = { |
| 92 | .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL | | 79 | .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL | |
| 93 | TMIO_MMC_HAVE_CBSY | TMIO_MMC_MIN_RCAR2, | 80 | TMIO_MMC_HAVE_CBSY | TMIO_MMC_MIN_RCAR2, |
| @@ -114,8 +101,8 @@ static const struct of_device_id renesas_sdhi_sys_dmac_of_match[] = { | |||
| 114 | { .compatible = "renesas,sdhi-r8a7792", .data = &of_rcar_gen2_compatible, }, | 101 | { .compatible = "renesas,sdhi-r8a7792", .data = &of_rcar_gen2_compatible, }, |
| 115 | { .compatible = "renesas,sdhi-r8a7793", .data = &of_rcar_gen2_compatible, }, | 102 | { .compatible = "renesas,sdhi-r8a7793", .data = &of_rcar_gen2_compatible, }, |
| 116 | { .compatible = "renesas,sdhi-r8a7794", .data = &of_rcar_gen2_compatible, }, | 103 | { .compatible = "renesas,sdhi-r8a7794", .data = &of_rcar_gen2_compatible, }, |
| 117 | { .compatible = "renesas,sdhi-r8a7795", .data = &of_rcar_r8a7795_compatible, }, | 104 | { .compatible = "renesas,sdhi-r8a7795", .data = &of_rcar_gen3_compatible, }, |
| 118 | { .compatible = "renesas,sdhi-r8a7796", .data = &of_rcar_r8a7795_compatible, }, | 105 | { .compatible = "renesas,sdhi-r8a7796", .data = &of_rcar_gen3_compatible, }, |
| 119 | { .compatible = "renesas,rcar-gen1-sdhi", .data = &of_rcar_gen1_compatible, }, | 106 | { .compatible = "renesas,rcar-gen1-sdhi", .data = &of_rcar_gen1_compatible, }, |
| 120 | { .compatible = "renesas,rcar-gen2-sdhi", .data = &of_rcar_gen2_compatible, }, | 107 | { .compatible = "renesas,rcar-gen2-sdhi", .data = &of_rcar_gen2_compatible, }, |
| 121 | { .compatible = "renesas,rcar-gen3-sdhi", .data = &of_rcar_gen3_compatible, }, | 108 | { .compatible = "renesas,rcar-gen3-sdhi", .data = &of_rcar_gen3_compatible, }, |
| @@ -493,8 +480,7 @@ static const struct soc_device_attribute gen3_soc_whitelist[] = { | |||
| 493 | 480 | ||
| 494 | static int renesas_sdhi_sys_dmac_probe(struct platform_device *pdev) | 481 | static int renesas_sdhi_sys_dmac_probe(struct platform_device *pdev) |
| 495 | { | 482 | { |
| 496 | if ((of_device_get_match_data(&pdev->dev) == &of_rcar_gen3_compatible || | 483 | if (of_device_get_match_data(&pdev->dev) == &of_rcar_gen3_compatible && |
| 497 | of_device_get_match_data(&pdev->dev) == &of_rcar_r8a7795_compatible) && | ||
| 498 | !soc_device_match(gen3_soc_whitelist)) | 484 | !soc_device_match(gen3_soc_whitelist)) |
| 499 | return -ENODEV; | 485 | return -ENODEV; |
| 500 | 486 | ||
diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c index 9a3ff22dd0fe..669c6ab021c8 100644 --- a/drivers/mmc/host/rtsx_usb_sdmmc.c +++ b/drivers/mmc/host/rtsx_usb_sdmmc.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/mmc/sd.h> | 28 | #include <linux/mmc/sd.h> |
| 29 | #include <linux/mmc/card.h> | 29 | #include <linux/mmc/card.h> |
| 30 | #include <linux/scatterlist.h> | 30 | #include <linux/scatterlist.h> |
| 31 | #include <linux/pm.h> | ||
| 31 | #include <linux/pm_runtime.h> | 32 | #include <linux/pm_runtime.h> |
| 32 | 33 | ||
| 33 | #include <linux/rtsx_usb.h> | 34 | #include <linux/rtsx_usb.h> |
| @@ -1042,9 +1043,9 @@ static int sd_set_power_mode(struct rtsx_usb_sdmmc *host, | |||
| 1042 | 1043 | ||
| 1043 | if (power_mode == MMC_POWER_OFF) { | 1044 | if (power_mode == MMC_POWER_OFF) { |
| 1044 | err = sd_power_off(host); | 1045 | err = sd_power_off(host); |
| 1045 | pm_runtime_put(sdmmc_dev(host)); | 1046 | pm_runtime_put_noidle(sdmmc_dev(host)); |
| 1046 | } else { | 1047 | } else { |
| 1047 | pm_runtime_get_sync(sdmmc_dev(host)); | 1048 | pm_runtime_get_noresume(sdmmc_dev(host)); |
| 1048 | err = sd_power_on(host); | 1049 | err = sd_power_on(host); |
| 1049 | } | 1050 | } |
| 1050 | 1051 | ||
| @@ -1297,16 +1298,20 @@ static void rtsx_usb_update_led(struct work_struct *work) | |||
| 1297 | container_of(work, struct rtsx_usb_sdmmc, led_work); | 1298 | container_of(work, struct rtsx_usb_sdmmc, led_work); |
| 1298 | struct rtsx_ucr *ucr = host->ucr; | 1299 | struct rtsx_ucr *ucr = host->ucr; |
| 1299 | 1300 | ||
| 1300 | pm_runtime_get_sync(sdmmc_dev(host)); | 1301 | pm_runtime_get_noresume(sdmmc_dev(host)); |
| 1301 | mutex_lock(&ucr->dev_mutex); | 1302 | mutex_lock(&ucr->dev_mutex); |
| 1302 | 1303 | ||
| 1304 | if (host->power_mode == MMC_POWER_OFF) | ||
| 1305 | goto out; | ||
| 1306 | |||
| 1303 | if (host->led.brightness == LED_OFF) | 1307 | if (host->led.brightness == LED_OFF) |
| 1304 | rtsx_usb_turn_off_led(ucr); | 1308 | rtsx_usb_turn_off_led(ucr); |
| 1305 | else | 1309 | else |
| 1306 | rtsx_usb_turn_on_led(ucr); | 1310 | rtsx_usb_turn_on_led(ucr); |
| 1307 | 1311 | ||
| 1312 | out: | ||
| 1308 | mutex_unlock(&ucr->dev_mutex); | 1313 | mutex_unlock(&ucr->dev_mutex); |
| 1309 | pm_runtime_put(sdmmc_dev(host)); | 1314 | pm_runtime_put_sync_suspend(sdmmc_dev(host)); |
| 1310 | } | 1315 | } |
| 1311 | #endif | 1316 | #endif |
| 1312 | 1317 | ||
| @@ -1320,7 +1325,7 @@ static void rtsx_usb_init_host(struct rtsx_usb_sdmmc *host) | |||
| 1320 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED | | 1325 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED | |
| 1321 | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_BUS_WIDTH_TEST | | 1326 | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_BUS_WIDTH_TEST | |
| 1322 | MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 | | 1327 | MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 | |
| 1323 | MMC_CAP_NEEDS_POLL | MMC_CAP_ERASE; | 1328 | MMC_CAP_ERASE | MMC_CAP_SYNC_RUNTIME_PM; |
| 1324 | mmc->caps2 = MMC_CAP2_NO_PRESCAN_POWERUP | MMC_CAP2_FULL_PWR_CYCLE | | 1329 | mmc->caps2 = MMC_CAP2_NO_PRESCAN_POWERUP | MMC_CAP2_FULL_PWR_CYCLE | |
| 1325 | MMC_CAP2_NO_SDIO; | 1330 | MMC_CAP2_NO_SDIO; |
| 1326 | 1331 | ||
| @@ -1363,8 +1368,6 @@ static int rtsx_usb_sdmmc_drv_probe(struct platform_device *pdev) | |||
| 1363 | 1368 | ||
| 1364 | mutex_init(&host->host_mutex); | 1369 | mutex_init(&host->host_mutex); |
| 1365 | rtsx_usb_init_host(host); | 1370 | rtsx_usb_init_host(host); |
| 1366 | pm_runtime_use_autosuspend(&pdev->dev); | ||
| 1367 | pm_runtime_set_autosuspend_delay(&pdev->dev, 50); | ||
| 1368 | pm_runtime_enable(&pdev->dev); | 1371 | pm_runtime_enable(&pdev->dev); |
| 1369 | 1372 | ||
| 1370 | #ifdef RTSX_USB_USE_LEDS_CLASS | 1373 | #ifdef RTSX_USB_USE_LEDS_CLASS |
| @@ -1419,7 +1422,6 @@ static int rtsx_usb_sdmmc_drv_remove(struct platform_device *pdev) | |||
| 1419 | 1422 | ||
| 1420 | mmc_free_host(mmc); | 1423 | mmc_free_host(mmc); |
| 1421 | pm_runtime_disable(&pdev->dev); | 1424 | pm_runtime_disable(&pdev->dev); |
| 1422 | pm_runtime_dont_use_autosuspend(&pdev->dev); | ||
| 1423 | platform_set_drvdata(pdev, NULL); | 1425 | platform_set_drvdata(pdev, NULL); |
| 1424 | 1426 | ||
| 1425 | dev_dbg(&(pdev->dev), | 1427 | dev_dbg(&(pdev->dev), |
| @@ -1428,6 +1430,31 @@ static int rtsx_usb_sdmmc_drv_remove(struct platform_device *pdev) | |||
| 1428 | return 0; | 1430 | return 0; |
| 1429 | } | 1431 | } |
| 1430 | 1432 | ||
| 1433 | #ifdef CONFIG_PM | ||
| 1434 | static int rtsx_usb_sdmmc_runtime_suspend(struct device *dev) | ||
| 1435 | { | ||
| 1436 | struct rtsx_usb_sdmmc *host = dev_get_drvdata(dev); | ||
| 1437 | |||
| 1438 | host->mmc->caps &= ~MMC_CAP_NEEDS_POLL; | ||
| 1439 | return 0; | ||
| 1440 | } | ||
| 1441 | |||
| 1442 | static int rtsx_usb_sdmmc_runtime_resume(struct device *dev) | ||
| 1443 | { | ||
| 1444 | struct rtsx_usb_sdmmc *host = dev_get_drvdata(dev); | ||
| 1445 | |||
| 1446 | host->mmc->caps |= MMC_CAP_NEEDS_POLL; | ||
| 1447 | if (sdmmc_get_cd(host->mmc) == 1) | ||
| 1448 | mmc_detect_change(host->mmc, 0); | ||
| 1449 | return 0; | ||
| 1450 | } | ||
| 1451 | #endif | ||
| 1452 | |||
| 1453 | static const struct dev_pm_ops rtsx_usb_sdmmc_dev_pm_ops = { | ||
| 1454 | SET_RUNTIME_PM_OPS(rtsx_usb_sdmmc_runtime_suspend, | ||
| 1455 | rtsx_usb_sdmmc_runtime_resume, NULL) | ||
| 1456 | }; | ||
| 1457 | |||
| 1431 | static const struct platform_device_id rtsx_usb_sdmmc_ids[] = { | 1458 | static const struct platform_device_id rtsx_usb_sdmmc_ids[] = { |
| 1432 | { | 1459 | { |
| 1433 | .name = "rtsx_usb_sdmmc", | 1460 | .name = "rtsx_usb_sdmmc", |
| @@ -1443,6 +1470,7 @@ static struct platform_driver rtsx_usb_sdmmc_driver = { | |||
| 1443 | .id_table = rtsx_usb_sdmmc_ids, | 1470 | .id_table = rtsx_usb_sdmmc_ids, |
| 1444 | .driver = { | 1471 | .driver = { |
| 1445 | .name = "rtsx_usb_sdmmc", | 1472 | .name = "rtsx_usb_sdmmc", |
| 1473 | .pm = &rtsx_usb_sdmmc_dev_pm_ops, | ||
| 1446 | }, | 1474 | }, |
| 1447 | }; | 1475 | }; |
| 1448 | module_platform_driver(rtsx_usb_sdmmc_driver); | 1476 | module_platform_driver(rtsx_usb_sdmmc_driver); |
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index f77493604312..10f5219b3b40 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
| 27 | #include <linux/of.h> | 27 | #include <linux/of.h> |
| 28 | #include <linux/of_device.h> | 28 | #include <linux/of_device.h> |
| 29 | #include <linux/of_gpio.h> | ||
| 30 | #include <linux/mmc/slot-gpio.h> | 29 | #include <linux/mmc/slot-gpio.h> |
| 31 | 30 | ||
| 32 | #include <plat/gpio-cfg.h> | 31 | #include <plat/gpio-cfg.h> |
| @@ -1406,18 +1405,7 @@ static int s3cmci_state_show(struct seq_file *seq, void *v) | |||
| 1406 | return 0; | 1405 | return 0; |
| 1407 | } | 1406 | } |
| 1408 | 1407 | ||
| 1409 | static int s3cmci_state_open(struct inode *inode, struct file *file) | 1408 | DEFINE_SHOW_ATTRIBUTE(s3cmci_state); |
| 1410 | { | ||
| 1411 | return single_open(file, s3cmci_state_show, inode->i_private); | ||
| 1412 | } | ||
| 1413 | |||
| 1414 | static const struct file_operations s3cmci_fops_state = { | ||
| 1415 | .owner = THIS_MODULE, | ||
| 1416 | .open = s3cmci_state_open, | ||
| 1417 | .read = seq_read, | ||
| 1418 | .llseek = seq_lseek, | ||
| 1419 | .release = single_release, | ||
| 1420 | }; | ||
| 1421 | 1409 | ||
| 1422 | #define DBG_REG(_r) { .addr = S3C2410_SDI##_r, .name = #_r } | 1410 | #define DBG_REG(_r) { .addr = S3C2410_SDI##_r, .name = #_r } |
| 1423 | 1411 | ||
| @@ -1459,18 +1447,7 @@ static int s3cmci_regs_show(struct seq_file *seq, void *v) | |||
| 1459 | return 0; | 1447 | return 0; |
| 1460 | } | 1448 | } |
| 1461 | 1449 | ||
| 1462 | static int s3cmci_regs_open(struct inode *inode, struct file *file) | 1450 | DEFINE_SHOW_ATTRIBUTE(s3cmci_regs); |
| 1463 | { | ||
| 1464 | return single_open(file, s3cmci_regs_show, inode->i_private); | ||
| 1465 | } | ||
| 1466 | |||
| 1467 | static const struct file_operations s3cmci_fops_regs = { | ||
| 1468 | .owner = THIS_MODULE, | ||
| 1469 | .open = s3cmci_regs_open, | ||
| 1470 | .read = seq_read, | ||
| 1471 | .llseek = seq_lseek, | ||
| 1472 | .release = single_release, | ||
| 1473 | }; | ||
| 1474 | 1451 | ||
| 1475 | static void s3cmci_debugfs_attach(struct s3cmci_host *host) | 1452 | static void s3cmci_debugfs_attach(struct s3cmci_host *host) |
| 1476 | { | 1453 | { |
| @@ -1484,14 +1461,14 @@ static void s3cmci_debugfs_attach(struct s3cmci_host *host) | |||
| 1484 | 1461 | ||
| 1485 | host->debug_state = debugfs_create_file("state", 0444, | 1462 | host->debug_state = debugfs_create_file("state", 0444, |
| 1486 | host->debug_root, host, | 1463 | host->debug_root, host, |
| 1487 | &s3cmci_fops_state); | 1464 | &s3cmci_state_fops); |
| 1488 | 1465 | ||
| 1489 | if (IS_ERR(host->debug_state)) | 1466 | if (IS_ERR(host->debug_state)) |
| 1490 | dev_err(dev, "failed to create debug state file\n"); | 1467 | dev_err(dev, "failed to create debug state file\n"); |
| 1491 | 1468 | ||
| 1492 | host->debug_regs = debugfs_create_file("regs", 0444, | 1469 | host->debug_regs = debugfs_create_file("regs", 0444, |
| 1493 | host->debug_root, host, | 1470 | host->debug_root, host, |
| 1494 | &s3cmci_fops_regs); | 1471 | &s3cmci_regs_fops); |
| 1495 | 1472 | ||
| 1496 | if (IS_ERR(host->debug_regs)) | 1473 | if (IS_ERR(host->debug_regs)) |
| 1497 | dev_err(dev, "failed to create debug regs file\n"); | 1474 | dev_err(dev, "failed to create debug regs file\n"); |
| @@ -1545,25 +1522,19 @@ static int s3cmci_probe_pdata(struct s3cmci_host *host) | |||
| 1545 | if (pdata->wprotect_invert) | 1522 | if (pdata->wprotect_invert) |
| 1546 | mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; | 1523 | mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; |
| 1547 | 1524 | ||
| 1548 | if (pdata->detect_invert) | 1525 | /* If we get -ENOENT we have no card detect GPIO line */ |
| 1549 | mmc->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; | 1526 | ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0, NULL); |
| 1550 | 1527 | if (ret != -ENOENT) { | |
| 1551 | if (gpio_is_valid(pdata->gpio_detect)) { | 1528 | dev_err(&pdev->dev, "error requesting GPIO for CD %d\n", |
| 1552 | ret = mmc_gpio_request_cd(mmc, pdata->gpio_detect, 0); | 1529 | ret); |
| 1553 | if (ret) { | 1530 | return ret; |
| 1554 | dev_err(&pdev->dev, "error requesting GPIO for CD %d\n", | ||
| 1555 | ret); | ||
| 1556 | return ret; | ||
| 1557 | } | ||
| 1558 | } | 1531 | } |
| 1559 | 1532 | ||
| 1560 | if (gpio_is_valid(pdata->gpio_wprotect)) { | 1533 | ret = mmc_gpiod_request_ro(host->mmc, "wp", 0, false, 0, NULL); |
| 1561 | ret = mmc_gpio_request_ro(mmc, pdata->gpio_wprotect); | 1534 | if (ret != -ENOENT) { |
| 1562 | if (ret) { | 1535 | dev_err(&pdev->dev, "error requesting GPIO for WP %d\n", |
| 1563 | dev_err(&pdev->dev, "error requesting GPIO for WP %d\n", | 1536 | ret); |
| 1564 | ret); | 1537 | return ret; |
| 1565 | return ret; | ||
| 1566 | } | ||
| 1567 | } | 1538 | } |
| 1568 | 1539 | ||
| 1569 | return 0; | 1540 | return 0; |
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 057e24f4a620..6669e540851d 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c | |||
| @@ -437,7 +437,8 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = { | |||
| 437 | MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR | | 437 | MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR | |
| 438 | MMC_CAP_CMD_DURING_TFR | MMC_CAP_WAIT_WHILE_BUSY, | 438 | MMC_CAP_CMD_DURING_TFR | MMC_CAP_WAIT_WHILE_BUSY, |
| 439 | .flags = SDHCI_ACPI_RUNTIME_PM, | 439 | .flags = SDHCI_ACPI_RUNTIME_PM, |
| 440 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | 440 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | |
| 441 | SDHCI_QUIRK_NO_LED, | ||
| 441 | .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | | 442 | .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | |
| 442 | SDHCI_QUIRK2_STOP_WITH_TC | | 443 | SDHCI_QUIRK2_STOP_WITH_TC | |
| 443 | SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400, | 444 | SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400, |
| @@ -448,6 +449,7 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = { | |||
| 448 | 449 | ||
| 449 | static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = { | 450 | static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = { |
| 450 | .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION | | 451 | .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION | |
| 452 | SDHCI_QUIRK_NO_LED | | ||
| 451 | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | 453 | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, |
| 452 | .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON, | 454 | .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON, |
| 453 | .caps = MMC_CAP_NONREMOVABLE | MMC_CAP_POWER_OFF_CARD | | 455 | .caps = MMC_CAP_NONREMOVABLE | MMC_CAP_POWER_OFF_CARD | |
| @@ -462,7 +464,8 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = { | |||
| 462 | static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = { | 464 | static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = { |
| 463 | .flags = SDHCI_ACPI_SD_CD | SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL | | 465 | .flags = SDHCI_ACPI_SD_CD | SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL | |
| 464 | SDHCI_ACPI_RUNTIME_PM, | 466 | SDHCI_ACPI_RUNTIME_PM, |
| 465 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | 467 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | |
| 468 | SDHCI_QUIRK_NO_LED, | ||
| 466 | .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON | | 469 | .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON | |
| 467 | SDHCI_QUIRK2_STOP_WITH_TC, | 470 | SDHCI_QUIRK2_STOP_WITH_TC, |
| 468 | .caps = MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_AGGRESSIVE_PM, | 471 | .caps = MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_AGGRESSIVE_PM, |
diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c index 7a343b87b5e5..e2412875dac5 100644 --- a/drivers/mmc/host/sdhci-cadence.c +++ b/drivers/mmc/host/sdhci-cadence.c | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | #include <linux/bitfield.h> | 16 | #include <linux/bitfield.h> |
| 17 | #include <linux/bitops.h> | 17 | #include <linux/bits.h> |
| 18 | #include <linux/iopoll.h> | 18 | #include <linux/iopoll.h> |
| 19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| 20 | #include <linux/mmc/host.h> | 20 | #include <linux/mmc/host.h> |
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index f44e49014a44..d0d319398a54 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
| 13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
| 14 | #include <linux/clk.h> | 14 | #include <linux/clk.h> |
| 15 | #include <linux/gpio.h> | ||
| 16 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 17 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
| 18 | #include <linux/mmc/host.h> | 17 | #include <linux/mmc/host.h> |
| @@ -21,7 +20,6 @@ | |||
| 21 | #include <linux/mmc/slot-gpio.h> | 20 | #include <linux/mmc/slot-gpio.h> |
| 22 | #include <linux/of.h> | 21 | #include <linux/of.h> |
| 23 | #include <linux/of_device.h> | 22 | #include <linux/of_device.h> |
| 24 | #include <linux/of_gpio.h> | ||
| 25 | #include <linux/pinctrl/consumer.h> | 23 | #include <linux/pinctrl/consumer.h> |
| 26 | #include <linux/platform_data/mmc-esdhc-imx.h> | 24 | #include <linux/platform_data/mmc-esdhc-imx.h> |
| 27 | #include <linux/pm_runtime.h> | 25 | #include <linux/pm_runtime.h> |
| @@ -429,7 +427,7 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg) | |||
| 429 | val = readl(host->ioaddr + ESDHC_MIX_CTRL); | 427 | val = readl(host->ioaddr + ESDHC_MIX_CTRL); |
| 430 | else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) | 428 | else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) |
| 431 | /* the std tuning bits is in ACMD12_ERR for imx6sl */ | 429 | /* the std tuning bits is in ACMD12_ERR for imx6sl */ |
| 432 | val = readl(host->ioaddr + SDHCI_ACMD12_ERR); | 430 | val = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS); |
| 433 | } | 431 | } |
| 434 | 432 | ||
| 435 | if (val & ESDHC_MIX_CTRL_EXE_TUNE) | 433 | if (val & ESDHC_MIX_CTRL_EXE_TUNE) |
| @@ -494,7 +492,7 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) | |||
| 494 | } | 492 | } |
| 495 | writel(new_val , host->ioaddr + ESDHC_MIX_CTRL); | 493 | writel(new_val , host->ioaddr + ESDHC_MIX_CTRL); |
| 496 | } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { | 494 | } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { |
| 497 | u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR); | 495 | u32 v = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS); |
| 498 | u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); | 496 | u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); |
| 499 | if (val & SDHCI_CTRL_TUNED_CLK) { | 497 | if (val & SDHCI_CTRL_TUNED_CLK) { |
| 500 | v |= ESDHC_MIX_CTRL_SMPCLK_SEL; | 498 | v |= ESDHC_MIX_CTRL_SMPCLK_SEL; |
| @@ -512,7 +510,7 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) | |||
| 512 | v &= ~ESDHC_MIX_CTRL_EXE_TUNE; | 510 | v &= ~ESDHC_MIX_CTRL_EXE_TUNE; |
| 513 | } | 511 | } |
| 514 | 512 | ||
| 515 | writel(v, host->ioaddr + SDHCI_ACMD12_ERR); | 513 | writel(v, host->ioaddr + SDHCI_AUTO_CMD_STATUS); |
| 516 | writel(m, host->ioaddr + ESDHC_MIX_CTRL); | 514 | writel(m, host->ioaddr + ESDHC_MIX_CTRL); |
| 517 | } | 515 | } |
| 518 | return; | 516 | return; |
| @@ -957,9 +955,9 @@ static void esdhc_reset_tuning(struct sdhci_host *host) | |||
| 957 | writel(ctrl, host->ioaddr + ESDHC_MIX_CTRL); | 955 | writel(ctrl, host->ioaddr + ESDHC_MIX_CTRL); |
| 958 | writel(0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS); | 956 | writel(0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS); |
| 959 | } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { | 957 | } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { |
| 960 | ctrl = readl(host->ioaddr + SDHCI_ACMD12_ERR); | 958 | ctrl = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS); |
| 961 | ctrl &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; | 959 | ctrl &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; |
| 962 | writel(ctrl, host->ioaddr + SDHCI_ACMD12_ERR); | 960 | writel(ctrl, host->ioaddr + SDHCI_AUTO_CMD_STATUS); |
| 963 | } | 961 | } |
| 964 | } | 962 | } |
| 965 | } | 963 | } |
| @@ -1139,8 +1137,12 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, | |||
| 1139 | if (of_get_property(np, "fsl,wp-controller", NULL)) | 1137 | if (of_get_property(np, "fsl,wp-controller", NULL)) |
| 1140 | boarddata->wp_type = ESDHC_WP_CONTROLLER; | 1138 | boarddata->wp_type = ESDHC_WP_CONTROLLER; |
| 1141 | 1139 | ||
| 1142 | boarddata->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0); | 1140 | /* |
| 1143 | if (gpio_is_valid(boarddata->wp_gpio)) | 1141 | * If we have this property, then activate WP check. |
| 1142 | * Retrieveing and requesting the actual WP GPIO will happen | ||
| 1143 | * in the call to mmc_of_parse(). | ||
| 1144 | */ | ||
| 1145 | if (of_property_read_bool(np, "wp-gpios")) | ||
| 1144 | boarddata->wp_type = ESDHC_WP_GPIO; | 1146 | boarddata->wp_type = ESDHC_WP_GPIO; |
| 1145 | 1147 | ||
| 1146 | of_property_read_u32(np, "fsl,tuning-step", &boarddata->tuning_step); | 1148 | of_property_read_u32(np, "fsl,tuning-step", &boarddata->tuning_step); |
| @@ -1198,7 +1200,7 @@ static int sdhci_esdhc_imx_probe_nondt(struct platform_device *pdev, | |||
| 1198 | host->mmc->parent->platform_data); | 1200 | host->mmc->parent->platform_data); |
| 1199 | /* write_protect */ | 1201 | /* write_protect */ |
| 1200 | if (boarddata->wp_type == ESDHC_WP_GPIO) { | 1202 | if (boarddata->wp_type == ESDHC_WP_GPIO) { |
| 1201 | err = mmc_gpio_request_ro(host->mmc, boarddata->wp_gpio); | 1203 | err = mmc_gpiod_request_ro(host->mmc, "wp", 0, false, 0, NULL); |
| 1202 | if (err) { | 1204 | if (err) { |
| 1203 | dev_err(mmc_dev(host->mmc), | 1205 | dev_err(mmc_dev(host->mmc), |
| 1204 | "failed to request write-protect gpio!\n"); | 1206 | "failed to request write-protect gpio!\n"); |
| @@ -1210,7 +1212,7 @@ static int sdhci_esdhc_imx_probe_nondt(struct platform_device *pdev, | |||
| 1210 | /* card_detect */ | 1212 | /* card_detect */ |
| 1211 | switch (boarddata->cd_type) { | 1213 | switch (boarddata->cd_type) { |
| 1212 | case ESDHC_CD_GPIO: | 1214 | case ESDHC_CD_GPIO: |
| 1213 | err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio, 0); | 1215 | err = mmc_gpiod_request_cd(host->mmc, "cd", 0, false, 0, NULL); |
| 1214 | if (err) { | 1216 | if (err) { |
| 1215 | dev_err(mmc_dev(host->mmc), | 1217 | dev_err(mmc_dev(host->mmc), |
| 1216 | "failed to request card-detect gpio!\n"); | 1218 | "failed to request card-detect gpio!\n"); |
| @@ -1317,7 +1319,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) | |||
| 1317 | 1319 | ||
| 1318 | /* clear tuning bits in case ROM has set it already */ | 1320 | /* clear tuning bits in case ROM has set it already */ |
| 1319 | writel(0x0, host->ioaddr + ESDHC_MIX_CTRL); | 1321 | writel(0x0, host->ioaddr + ESDHC_MIX_CTRL); |
| 1320 | writel(0x0, host->ioaddr + SDHCI_ACMD12_ERR); | 1322 | writel(0x0, host->ioaddr + SDHCI_AUTO_CMD_STATUS); |
| 1321 | writel(0x0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS); | 1323 | writel(0x0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS); |
| 1322 | } | 1324 | } |
| 1323 | 1325 | ||
diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h index 3f16d9c90ba2..39dbbd6eaf28 100644 --- a/drivers/mmc/host/sdhci-esdhc.h +++ b/drivers/mmc/host/sdhci-esdhc.h | |||
| @@ -59,9 +59,33 @@ | |||
| 59 | 59 | ||
| 60 | /* Tuning Block Control Register */ | 60 | /* Tuning Block Control Register */ |
| 61 | #define ESDHC_TBCTL 0x120 | 61 | #define ESDHC_TBCTL 0x120 |
| 62 | #define ESDHC_HS400_WNDW_ADJUST 0x00000040 | ||
| 63 | #define ESDHC_HS400_MODE 0x00000010 | ||
| 62 | #define ESDHC_TB_EN 0x00000004 | 64 | #define ESDHC_TB_EN 0x00000004 |
| 63 | #define ESDHC_TBPTR 0x128 | 65 | #define ESDHC_TBPTR 0x128 |
| 64 | 66 | ||
| 67 | /* SD Clock Control Register */ | ||
| 68 | #define ESDHC_SDCLKCTL 0x144 | ||
| 69 | #define ESDHC_LPBK_CLK_SEL 0x80000000 | ||
| 70 | #define ESDHC_CMD_CLK_CTL 0x00008000 | ||
| 71 | |||
| 72 | /* SD Timing Control Register */ | ||
| 73 | #define ESDHC_SDTIMNGCTL 0x148 | ||
| 74 | #define ESDHC_FLW_CTL_BG 0x00008000 | ||
| 75 | |||
| 76 | /* DLL Config 0 Register */ | ||
| 77 | #define ESDHC_DLLCFG0 0x160 | ||
| 78 | #define ESDHC_DLL_ENABLE 0x80000000 | ||
| 79 | #define ESDHC_DLL_FREQ_SEL 0x08000000 | ||
| 80 | |||
| 81 | /* DLL Config 1 Register */ | ||
| 82 | #define ESDHC_DLLCFG1 0x164 | ||
| 83 | #define ESDHC_DLL_PD_PULSE_STRETCH_SEL 0x80000000 | ||
| 84 | |||
| 85 | /* DLL Status 0 Register */ | ||
| 86 | #define ESDHC_DLLSTAT0 0x170 | ||
| 87 | #define ESDHC_DLL_STS_SLV_LOCK 0x08000000 | ||
| 88 | |||
| 65 | /* Control Register for DMA transfer */ | 89 | /* Control Register for DMA transfer */ |
| 66 | #define ESDHC_DMA_SYSCTL 0x40c | 90 | #define ESDHC_DMA_SYSCTL 0x40c |
| 67 | #define ESDHC_PERIPHERAL_CLK_SEL 0x00080000 | 91 | #define ESDHC_PERIPHERAL_CLK_SEL 0x00080000 |
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 3cc8bfee6c18..d6c9ebd8d263 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c | |||
| @@ -232,6 +232,7 @@ struct sdhci_msm_variant_ops { | |||
| 232 | */ | 232 | */ |
| 233 | struct sdhci_msm_variant_info { | 233 | struct sdhci_msm_variant_info { |
| 234 | bool mci_removed; | 234 | bool mci_removed; |
| 235 | bool restore_dll_config; | ||
| 235 | const struct sdhci_msm_variant_ops *var_ops; | 236 | const struct sdhci_msm_variant_ops *var_ops; |
| 236 | const struct sdhci_msm_offset *offset; | 237 | const struct sdhci_msm_offset *offset; |
| 237 | }; | 238 | }; |
| @@ -256,8 +257,11 @@ struct sdhci_msm_host { | |||
| 256 | bool pwr_irq_flag; | 257 | bool pwr_irq_flag; |
| 257 | u32 caps_0; | 258 | u32 caps_0; |
| 258 | bool mci_removed; | 259 | bool mci_removed; |
| 260 | bool restore_dll_config; | ||
| 259 | const struct sdhci_msm_variant_ops *var_ops; | 261 | const struct sdhci_msm_variant_ops *var_ops; |
| 260 | const struct sdhci_msm_offset *offset; | 262 | const struct sdhci_msm_offset *offset; |
| 263 | bool use_cdr; | ||
| 264 | u32 transfer_mode; | ||
| 261 | }; | 265 | }; |
| 262 | 266 | ||
| 263 | static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host) | 267 | static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host) |
| @@ -1025,6 +1029,69 @@ out: | |||
| 1025 | return ret; | 1029 | return ret; |
| 1026 | } | 1030 | } |
| 1027 | 1031 | ||
| 1032 | static bool sdhci_msm_is_tuning_needed(struct sdhci_host *host) | ||
| 1033 | { | ||
| 1034 | struct mmc_ios *ios = &host->mmc->ios; | ||
| 1035 | |||
| 1036 | /* | ||
| 1037 | * Tuning is required for SDR104, HS200 and HS400 cards and | ||
| 1038 | * if clock frequency is greater than 100MHz in these modes. | ||
| 1039 | */ | ||
| 1040 | if (host->clock <= CORE_FREQ_100MHZ || | ||
| 1041 | !(ios->timing == MMC_TIMING_MMC_HS400 || | ||
| 1042 | ios->timing == MMC_TIMING_MMC_HS200 || | ||
| 1043 | ios->timing == MMC_TIMING_UHS_SDR104) || | ||
| 1044 | ios->enhanced_strobe) | ||
| 1045 | return false; | ||
| 1046 | |||
| 1047 | return true; | ||
| 1048 | } | ||
| 1049 | |||
| 1050 | static int sdhci_msm_restore_sdr_dll_config(struct sdhci_host *host) | ||
| 1051 | { | ||
| 1052 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 1053 | struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); | ||
| 1054 | int ret; | ||
| 1055 | |||
| 1056 | /* | ||
| 1057 | * SDR DLL comes into picture only for timing modes which needs | ||
| 1058 | * tuning. | ||
| 1059 | */ | ||
| 1060 | if (!sdhci_msm_is_tuning_needed(host)) | ||
| 1061 | return 0; | ||
| 1062 | |||
| 1063 | /* Reset the tuning block */ | ||
| 1064 | ret = msm_init_cm_dll(host); | ||
| 1065 | if (ret) | ||
| 1066 | return ret; | ||
| 1067 | |||
| 1068 | /* Restore the tuning block */ | ||
| 1069 | ret = msm_config_cm_dll_phase(host, msm_host->saved_tuning_phase); | ||
| 1070 | |||
| 1071 | return ret; | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | static void sdhci_msm_set_cdr(struct sdhci_host *host, bool enable) | ||
| 1075 | { | ||
| 1076 | const struct sdhci_msm_offset *msm_offset = sdhci_priv_msm_offset(host); | ||
| 1077 | u32 config, oldconfig = readl_relaxed(host->ioaddr + | ||
| 1078 | msm_offset->core_dll_config); | ||
| 1079 | |||
| 1080 | config = oldconfig; | ||
| 1081 | if (enable) { | ||
| 1082 | config |= CORE_CDR_EN; | ||
| 1083 | config &= ~CORE_CDR_EXT_EN; | ||
| 1084 | } else { | ||
| 1085 | config &= ~CORE_CDR_EN; | ||
| 1086 | config |= CORE_CDR_EXT_EN; | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | if (config != oldconfig) { | ||
| 1090 | writel_relaxed(config, host->ioaddr + | ||
| 1091 | msm_offset->core_dll_config); | ||
| 1092 | } | ||
| 1093 | } | ||
| 1094 | |||
| 1028 | static int sdhci_msm_execute_tuning(struct mmc_host *mmc, u32 opcode) | 1095 | static int sdhci_msm_execute_tuning(struct mmc_host *mmc, u32 opcode) |
| 1029 | { | 1096 | { |
| 1030 | struct sdhci_host *host = mmc_priv(mmc); | 1097 | struct sdhci_host *host = mmc_priv(mmc); |
| @@ -1035,15 +1102,14 @@ static int sdhci_msm_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
| 1035 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 1102 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
| 1036 | struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); | 1103 | struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); |
| 1037 | 1104 | ||
| 1038 | /* | 1105 | if (!sdhci_msm_is_tuning_needed(host)) { |
| 1039 | * Tuning is required for SDR104, HS200 and HS400 cards and | 1106 | msm_host->use_cdr = false; |
| 1040 | * if clock frequency is greater than 100MHz in these modes. | 1107 | sdhci_msm_set_cdr(host, false); |
| 1041 | */ | ||
| 1042 | if (host->clock <= CORE_FREQ_100MHZ || | ||
| 1043 | !(ios.timing == MMC_TIMING_MMC_HS400 || | ||
| 1044 | ios.timing == MMC_TIMING_MMC_HS200 || | ||
| 1045 | ios.timing == MMC_TIMING_UHS_SDR104)) | ||
| 1046 | return 0; | 1108 | return 0; |
| 1109 | } | ||
| 1110 | |||
| 1111 | /* Clock-Data-Recovery used to dynamically adjust RX sampling point */ | ||
| 1112 | msm_host->use_cdr = true; | ||
| 1047 | 1113 | ||
| 1048 | /* | 1114 | /* |
| 1049 | * For HS400 tuning in HS200 timing requires: | 1115 | * For HS400 tuning in HS200 timing requires: |
| @@ -1069,7 +1135,6 @@ retry: | |||
| 1069 | if (rc) | 1135 | if (rc) |
| 1070 | return rc; | 1136 | return rc; |
| 1071 | 1137 | ||
| 1072 | msm_host->saved_tuning_phase = phase; | ||
| 1073 | rc = mmc_send_tuning(mmc, opcode, NULL); | 1138 | rc = mmc_send_tuning(mmc, opcode, NULL); |
| 1074 | if (!rc) { | 1139 | if (!rc) { |
| 1075 | /* Tuning is successful at this tuning point */ | 1140 | /* Tuning is successful at this tuning point */ |
| @@ -1094,6 +1159,7 @@ retry: | |||
| 1094 | rc = msm_config_cm_dll_phase(host, phase); | 1159 | rc = msm_config_cm_dll_phase(host, phase); |
| 1095 | if (rc) | 1160 | if (rc) |
| 1096 | return rc; | 1161 | return rc; |
| 1162 | msm_host->saved_tuning_phase = phase; | ||
| 1097 | dev_dbg(mmc_dev(mmc), "%s: Setting the tuning phase to %d\n", | 1163 | dev_dbg(mmc_dev(mmc), "%s: Setting the tuning phase to %d\n", |
| 1098 | mmc_hostname(mmc), phase); | 1164 | mmc_hostname(mmc), phase); |
| 1099 | } else { | 1165 | } else { |
| @@ -1525,6 +1591,19 @@ static int __sdhci_msm_check_write(struct sdhci_host *host, u16 val, int reg) | |||
| 1525 | case SDHCI_POWER_CONTROL: | 1591 | case SDHCI_POWER_CONTROL: |
| 1526 | req_type = !val ? REQ_BUS_OFF : REQ_BUS_ON; | 1592 | req_type = !val ? REQ_BUS_OFF : REQ_BUS_ON; |
| 1527 | break; | 1593 | break; |
| 1594 | case SDHCI_TRANSFER_MODE: | ||
| 1595 | msm_host->transfer_mode = val; | ||
| 1596 | break; | ||
| 1597 | case SDHCI_COMMAND: | ||
| 1598 | if (!msm_host->use_cdr) | ||
| 1599 | break; | ||
| 1600 | if ((msm_host->transfer_mode & SDHCI_TRNS_READ) && | ||
| 1601 | SDHCI_GET_CMD(val) != MMC_SEND_TUNING_BLOCK_HS200 && | ||
| 1602 | SDHCI_GET_CMD(val) != MMC_SEND_TUNING_BLOCK) | ||
| 1603 | sdhci_msm_set_cdr(host, true); | ||
| 1604 | else | ||
| 1605 | sdhci_msm_set_cdr(host, false); | ||
| 1606 | break; | ||
| 1528 | } | 1607 | } |
| 1529 | 1608 | ||
| 1530 | if (req_type) { | 1609 | if (req_type) { |
| @@ -1616,7 +1695,6 @@ static const struct sdhci_msm_variant_ops v5_var_ops = { | |||
| 1616 | }; | 1695 | }; |
| 1617 | 1696 | ||
| 1618 | static const struct sdhci_msm_variant_info sdhci_msm_mci_var = { | 1697 | static const struct sdhci_msm_variant_info sdhci_msm_mci_var = { |
| 1619 | .mci_removed = false, | ||
| 1620 | .var_ops = &mci_var_ops, | 1698 | .var_ops = &mci_var_ops, |
| 1621 | .offset = &sdhci_msm_mci_offset, | 1699 | .offset = &sdhci_msm_mci_offset, |
| 1622 | }; | 1700 | }; |
| @@ -1627,9 +1705,17 @@ static const struct sdhci_msm_variant_info sdhci_msm_v5_var = { | |||
| 1627 | .offset = &sdhci_msm_v5_offset, | 1705 | .offset = &sdhci_msm_v5_offset, |
| 1628 | }; | 1706 | }; |
| 1629 | 1707 | ||
| 1708 | static const struct sdhci_msm_variant_info sdm845_sdhci_var = { | ||
| 1709 | .mci_removed = true, | ||
| 1710 | .restore_dll_config = true, | ||
| 1711 | .var_ops = &v5_var_ops, | ||
| 1712 | .offset = &sdhci_msm_v5_offset, | ||
| 1713 | }; | ||
| 1714 | |||
| 1630 | static const struct of_device_id sdhci_msm_dt_match[] = { | 1715 | static const struct of_device_id sdhci_msm_dt_match[] = { |
| 1631 | {.compatible = "qcom,sdhci-msm-v4", .data = &sdhci_msm_mci_var}, | 1716 | {.compatible = "qcom,sdhci-msm-v4", .data = &sdhci_msm_mci_var}, |
| 1632 | {.compatible = "qcom,sdhci-msm-v5", .data = &sdhci_msm_v5_var}, | 1717 | {.compatible = "qcom,sdhci-msm-v5", .data = &sdhci_msm_v5_var}, |
| 1718 | {.compatible = "qcom,sdm845-sdhci", .data = &sdm845_sdhci_var}, | ||
| 1633 | {}, | 1719 | {}, |
| 1634 | }; | 1720 | }; |
| 1635 | 1721 | ||
| @@ -1689,6 +1775,7 @@ static int sdhci_msm_probe(struct platform_device *pdev) | |||
| 1689 | var_info = of_device_get_match_data(&pdev->dev); | 1775 | var_info = of_device_get_match_data(&pdev->dev); |
| 1690 | 1776 | ||
| 1691 | msm_host->mci_removed = var_info->mci_removed; | 1777 | msm_host->mci_removed = var_info->mci_removed; |
| 1778 | msm_host->restore_dll_config = var_info->restore_dll_config; | ||
| 1692 | msm_host->var_ops = var_info->var_ops; | 1779 | msm_host->var_ops = var_info->var_ops; |
| 1693 | msm_host->offset = var_info->offset; | 1780 | msm_host->offset = var_info->offset; |
| 1694 | 1781 | ||
| @@ -1910,8 +1997,7 @@ static int sdhci_msm_remove(struct platform_device *pdev) | |||
| 1910 | return 0; | 1997 | return 0; |
| 1911 | } | 1998 | } |
| 1912 | 1999 | ||
| 1913 | #ifdef CONFIG_PM | 2000 | static __maybe_unused int sdhci_msm_runtime_suspend(struct device *dev) |
| 1914 | static int sdhci_msm_runtime_suspend(struct device *dev) | ||
| 1915 | { | 2001 | { |
| 1916 | struct sdhci_host *host = dev_get_drvdata(dev); | 2002 | struct sdhci_host *host = dev_get_drvdata(dev); |
| 1917 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 2003 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
| @@ -1923,16 +2009,26 @@ static int sdhci_msm_runtime_suspend(struct device *dev) | |||
| 1923 | return 0; | 2009 | return 0; |
| 1924 | } | 2010 | } |
| 1925 | 2011 | ||
| 1926 | static int sdhci_msm_runtime_resume(struct device *dev) | 2012 | static __maybe_unused int sdhci_msm_runtime_resume(struct device *dev) |
| 1927 | { | 2013 | { |
| 1928 | struct sdhci_host *host = dev_get_drvdata(dev); | 2014 | struct sdhci_host *host = dev_get_drvdata(dev); |
| 1929 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 2015 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
| 1930 | struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); | 2016 | struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); |
| 2017 | int ret; | ||
| 1931 | 2018 | ||
| 1932 | return clk_bulk_prepare_enable(ARRAY_SIZE(msm_host->bulk_clks), | 2019 | ret = clk_bulk_prepare_enable(ARRAY_SIZE(msm_host->bulk_clks), |
| 1933 | msm_host->bulk_clks); | 2020 | msm_host->bulk_clks); |
| 2021 | if (ret) | ||
| 2022 | return ret; | ||
| 2023 | /* | ||
| 2024 | * Whenever core-clock is gated dynamically, it's needed to | ||
| 2025 | * restore the SDR DLL settings when the clock is ungated. | ||
| 2026 | */ | ||
| 2027 | if (msm_host->restore_dll_config && msm_host->clk_rate) | ||
| 2028 | return sdhci_msm_restore_sdr_dll_config(host); | ||
| 2029 | |||
| 2030 | return 0; | ||
| 1934 | } | 2031 | } |
| 1935 | #endif | ||
| 1936 | 2032 | ||
| 1937 | static const struct dev_pm_ops sdhci_msm_pm_ops = { | 2033 | static const struct dev_pm_ops sdhci_msm_pm_ops = { |
| 1938 | SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, | 2034 | SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, |
diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index 142c4b802f31..c9e3e050ccc8 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c | |||
| @@ -231,25 +231,6 @@ static void sdhci_arasan_set_clock(struct sdhci_host *host, unsigned int clock) | |||
| 231 | } | 231 | } |
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | static void sdhci_arasan_am654_set_clock(struct sdhci_host *host, | ||
| 235 | unsigned int clock) | ||
| 236 | { | ||
| 237 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 238 | struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host); | ||
| 239 | |||
| 240 | if (sdhci_arasan->is_phy_on) { | ||
| 241 | phy_power_off(sdhci_arasan->phy); | ||
| 242 | sdhci_arasan->is_phy_on = false; | ||
| 243 | } | ||
| 244 | |||
| 245 | sdhci_set_clock(host, clock); | ||
| 246 | |||
| 247 | if (clock > PHY_CLK_TOO_SLOW_HZ) { | ||
| 248 | phy_power_on(sdhci_arasan->phy); | ||
| 249 | sdhci_arasan->is_phy_on = true; | ||
| 250 | } | ||
| 251 | } | ||
| 252 | |||
| 253 | static void sdhci_arasan_hs400_enhanced_strobe(struct mmc_host *mmc, | 234 | static void sdhci_arasan_hs400_enhanced_strobe(struct mmc_host *mmc, |
| 254 | struct mmc_ios *ios) | 235 | struct mmc_ios *ios) |
| 255 | { | 236 | { |
| @@ -335,29 +316,6 @@ static struct sdhci_arasan_of_data sdhci_arasan_data = { | |||
| 335 | .pdata = &sdhci_arasan_pdata, | 316 | .pdata = &sdhci_arasan_pdata, |
| 336 | }; | 317 | }; |
| 337 | 318 | ||
| 338 | static const struct sdhci_ops sdhci_arasan_am654_ops = { | ||
| 339 | .set_clock = sdhci_arasan_am654_set_clock, | ||
| 340 | .get_max_clock = sdhci_pltfm_clk_get_max_clock, | ||
| 341 | .get_timeout_clock = sdhci_pltfm_clk_get_max_clock, | ||
| 342 | .set_bus_width = sdhci_set_bus_width, | ||
| 343 | .reset = sdhci_arasan_reset, | ||
| 344 | .set_uhs_signaling = sdhci_set_uhs_signaling, | ||
| 345 | }; | ||
| 346 | |||
| 347 | static const struct sdhci_pltfm_data sdhci_arasan_am654_pdata = { | ||
| 348 | .ops = &sdhci_arasan_am654_ops, | ||
| 349 | .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | | ||
| 350 | SDHCI_QUIRK_INVERTED_WRITE_PROTECT | | ||
| 351 | SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12, | ||
| 352 | .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | | ||
| 353 | SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN | | ||
| 354 | SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400, | ||
| 355 | }; | ||
| 356 | |||
| 357 | static const struct sdhci_arasan_of_data sdhci_arasan_am654_data = { | ||
| 358 | .pdata = &sdhci_arasan_am654_pdata, | ||
| 359 | }; | ||
| 360 | |||
| 361 | static u32 sdhci_arasan_cqhci_irq(struct sdhci_host *host, u32 intmask) | 319 | static u32 sdhci_arasan_cqhci_irq(struct sdhci_host *host, u32 intmask) |
| 362 | { | 320 | { |
| 363 | int cmd_error = 0; | 321 | int cmd_error = 0; |
| @@ -520,10 +478,6 @@ static const struct of_device_id sdhci_arasan_of_match[] = { | |||
| 520 | .compatible = "rockchip,rk3399-sdhci-5.1", | 478 | .compatible = "rockchip,rk3399-sdhci-5.1", |
| 521 | .data = &sdhci_arasan_rk3399_data, | 479 | .data = &sdhci_arasan_rk3399_data, |
| 522 | }, | 480 | }, |
| 523 | { | ||
| 524 | .compatible = "ti,am654-sdhci-5.1", | ||
| 525 | .data = &sdhci_arasan_am654_data, | ||
| 526 | }, | ||
| 527 | /* Generic compatible below here */ | 481 | /* Generic compatible below here */ |
| 528 | { | 482 | { |
| 529 | .compatible = "arasan,sdhci-8.9a", | 483 | .compatible = "arasan,sdhci-8.9a", |
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 86fc9f022002..4e669b4edfc1 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c | |||
| @@ -78,6 +78,8 @@ struct sdhci_esdhc { | |||
| 78 | u8 vendor_ver; | 78 | u8 vendor_ver; |
| 79 | u8 spec_ver; | 79 | u8 spec_ver; |
| 80 | bool quirk_incorrect_hostver; | 80 | bool quirk_incorrect_hostver; |
| 81 | bool quirk_limited_clk_division; | ||
| 82 | bool quirk_unreliable_pulse_detection; | ||
| 81 | bool quirk_fixup_tuning; | 83 | bool quirk_fixup_tuning; |
| 82 | unsigned int peripheral_clock; | 84 | unsigned int peripheral_clock; |
| 83 | const struct esdhc_clk_fixup *clk_fixup; | 85 | const struct esdhc_clk_fixup *clk_fixup; |
| @@ -528,8 +530,12 @@ static void esdhc_clock_enable(struct sdhci_host *host, bool enable) | |||
| 528 | /* Wait max 20 ms */ | 530 | /* Wait max 20 ms */ |
| 529 | timeout = ktime_add_ms(ktime_get(), 20); | 531 | timeout = ktime_add_ms(ktime_get(), 20); |
| 530 | val = ESDHC_CLOCK_STABLE; | 532 | val = ESDHC_CLOCK_STABLE; |
| 531 | while (!(sdhci_readl(host, ESDHC_PRSSTAT) & val)) { | 533 | while (1) { |
| 532 | if (ktime_after(ktime_get(), timeout)) { | 534 | bool timedout = ktime_after(ktime_get(), timeout); |
| 535 | |||
| 536 | if (sdhci_readl(host, ESDHC_PRSSTAT) & val) | ||
| 537 | break; | ||
| 538 | if (timedout) { | ||
| 533 | pr_err("%s: Internal clock never stabilised.\n", | 539 | pr_err("%s: Internal clock never stabilised.\n", |
| 534 | mmc_hostname(host->mmc)); | 540 | mmc_hostname(host->mmc)); |
| 535 | break; | 541 | break; |
| @@ -544,6 +550,7 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) | |||
| 544 | struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); | 550 | struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); |
| 545 | int pre_div = 1; | 551 | int pre_div = 1; |
| 546 | int div = 1; | 552 | int div = 1; |
| 553 | int division; | ||
| 547 | ktime_t timeout; | 554 | ktime_t timeout; |
| 548 | long fixup = 0; | 555 | long fixup = 0; |
| 549 | u32 temp; | 556 | u32 temp; |
| @@ -579,6 +586,26 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) | |||
| 579 | while (host->max_clk / pre_div / div > clock && div < 16) | 586 | while (host->max_clk / pre_div / div > clock && div < 16) |
| 580 | div++; | 587 | div++; |
| 581 | 588 | ||
| 589 | if (esdhc->quirk_limited_clk_division && | ||
| 590 | clock == MMC_HS200_MAX_DTR && | ||
| 591 | (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 || | ||
| 592 | host->flags & SDHCI_HS400_TUNING)) { | ||
| 593 | division = pre_div * div; | ||
| 594 | if (division <= 4) { | ||
| 595 | pre_div = 4; | ||
| 596 | div = 1; | ||
| 597 | } else if (division <= 8) { | ||
| 598 | pre_div = 4; | ||
| 599 | div = 2; | ||
| 600 | } else if (division <= 12) { | ||
| 601 | pre_div = 4; | ||
| 602 | div = 3; | ||
| 603 | } else { | ||
| 604 | pr_warn("%s: using unsupported clock division.\n", | ||
| 605 | mmc_hostname(host->mmc)); | ||
| 606 | } | ||
| 607 | } | ||
| 608 | |||
| 582 | dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", | 609 | dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", |
| 583 | clock, host->max_clk / pre_div / div); | 610 | clock, host->max_clk / pre_div / div); |
| 584 | host->mmc->actual_clock = host->max_clk / pre_div / div; | 611 | host->mmc->actual_clock = host->max_clk / pre_div / div; |
| @@ -592,10 +619,36 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) | |||
| 592 | | (pre_div << ESDHC_PREDIV_SHIFT)); | 619 | | (pre_div << ESDHC_PREDIV_SHIFT)); |
| 593 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); | 620 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); |
| 594 | 621 | ||
| 622 | if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 && | ||
| 623 | clock == MMC_HS200_MAX_DTR) { | ||
| 624 | temp = sdhci_readl(host, ESDHC_TBCTL); | ||
| 625 | sdhci_writel(host, temp | ESDHC_HS400_MODE, ESDHC_TBCTL); | ||
| 626 | temp = sdhci_readl(host, ESDHC_SDCLKCTL); | ||
| 627 | sdhci_writel(host, temp | ESDHC_CMD_CLK_CTL, ESDHC_SDCLKCTL); | ||
| 628 | esdhc_clock_enable(host, true); | ||
| 629 | |||
| 630 | temp = sdhci_readl(host, ESDHC_DLLCFG0); | ||
| 631 | temp |= ESDHC_DLL_ENABLE; | ||
| 632 | if (host->mmc->actual_clock == MMC_HS200_MAX_DTR) | ||
| 633 | temp |= ESDHC_DLL_FREQ_SEL; | ||
| 634 | sdhci_writel(host, temp, ESDHC_DLLCFG0); | ||
| 635 | temp = sdhci_readl(host, ESDHC_TBCTL); | ||
| 636 | sdhci_writel(host, temp | ESDHC_HS400_WNDW_ADJUST, ESDHC_TBCTL); | ||
| 637 | |||
| 638 | esdhc_clock_enable(host, false); | ||
| 639 | temp = sdhci_readl(host, ESDHC_DMA_SYSCTL); | ||
| 640 | temp |= ESDHC_FLUSH_ASYNC_FIFO; | ||
| 641 | sdhci_writel(host, temp, ESDHC_DMA_SYSCTL); | ||
| 642 | } | ||
| 643 | |||
| 595 | /* Wait max 20 ms */ | 644 | /* Wait max 20 ms */ |
| 596 | timeout = ktime_add_ms(ktime_get(), 20); | 645 | timeout = ktime_add_ms(ktime_get(), 20); |
| 597 | while (!(sdhci_readl(host, ESDHC_PRSSTAT) & ESDHC_CLOCK_STABLE)) { | 646 | while (1) { |
| 598 | if (ktime_after(ktime_get(), timeout)) { | 647 | bool timedout = ktime_after(ktime_get(), timeout); |
| 648 | |||
| 649 | if (sdhci_readl(host, ESDHC_PRSSTAT) & ESDHC_CLOCK_STABLE) | ||
| 650 | break; | ||
| 651 | if (timedout) { | ||
| 599 | pr_err("%s: Internal clock never stabilised.\n", | 652 | pr_err("%s: Internal clock never stabilised.\n", |
| 600 | mmc_hostname(host->mmc)); | 653 | mmc_hostname(host->mmc)); |
| 601 | return; | 654 | return; |
| @@ -603,6 +656,7 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) | |||
| 603 | udelay(10); | 656 | udelay(10); |
| 604 | } | 657 | } |
| 605 | 658 | ||
| 659 | temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); | ||
| 606 | temp |= ESDHC_CLOCK_SDCLKEN; | 660 | temp |= ESDHC_CLOCK_SDCLKEN; |
| 607 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); | 661 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); |
| 608 | } | 662 | } |
| @@ -631,6 +685,8 @@ static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width) | |||
| 631 | 685 | ||
| 632 | static void esdhc_reset(struct sdhci_host *host, u8 mask) | 686 | static void esdhc_reset(struct sdhci_host *host, u8 mask) |
| 633 | { | 687 | { |
| 688 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 689 | struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); | ||
| 634 | u32 val; | 690 | u32 val; |
| 635 | 691 | ||
| 636 | sdhci_reset(host, mask); | 692 | sdhci_reset(host, mask); |
| @@ -642,6 +698,12 @@ static void esdhc_reset(struct sdhci_host *host, u8 mask) | |||
| 642 | val = sdhci_readl(host, ESDHC_TBCTL); | 698 | val = sdhci_readl(host, ESDHC_TBCTL); |
| 643 | val &= ~ESDHC_TB_EN; | 699 | val &= ~ESDHC_TB_EN; |
| 644 | sdhci_writel(host, val, ESDHC_TBCTL); | 700 | sdhci_writel(host, val, ESDHC_TBCTL); |
| 701 | |||
| 702 | if (esdhc->quirk_unreliable_pulse_detection) { | ||
| 703 | val = sdhci_readl(host, ESDHC_DLLCFG1); | ||
| 704 | val &= ~ESDHC_DLL_PD_PULSE_STRETCH_SEL; | ||
| 705 | sdhci_writel(host, val, ESDHC_DLLCFG1); | ||
| 706 | } | ||
| 645 | } | 707 | } |
| 646 | } | 708 | } |
| 647 | 709 | ||
| @@ -728,25 +790,50 @@ static struct soc_device_attribute soc_fixup_tuning[] = { | |||
| 728 | { }, | 790 | { }, |
| 729 | }; | 791 | }; |
| 730 | 792 | ||
| 731 | static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode) | 793 | static void esdhc_tuning_block_enable(struct sdhci_host *host, bool enable) |
| 732 | { | 794 | { |
| 733 | struct sdhci_host *host = mmc_priv(mmc); | ||
| 734 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 735 | struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); | ||
| 736 | u32 val; | 795 | u32 val; |
| 737 | 796 | ||
| 738 | /* Use tuning block for tuning procedure */ | ||
| 739 | esdhc_clock_enable(host, false); | 797 | esdhc_clock_enable(host, false); |
| 798 | |||
| 740 | val = sdhci_readl(host, ESDHC_DMA_SYSCTL); | 799 | val = sdhci_readl(host, ESDHC_DMA_SYSCTL); |
| 741 | val |= ESDHC_FLUSH_ASYNC_FIFO; | 800 | val |= ESDHC_FLUSH_ASYNC_FIFO; |
| 742 | sdhci_writel(host, val, ESDHC_DMA_SYSCTL); | 801 | sdhci_writel(host, val, ESDHC_DMA_SYSCTL); |
| 743 | 802 | ||
| 744 | val = sdhci_readl(host, ESDHC_TBCTL); | 803 | val = sdhci_readl(host, ESDHC_TBCTL); |
| 745 | val |= ESDHC_TB_EN; | 804 | if (enable) |
| 805 | val |= ESDHC_TB_EN; | ||
| 806 | else | ||
| 807 | val &= ~ESDHC_TB_EN; | ||
| 746 | sdhci_writel(host, val, ESDHC_TBCTL); | 808 | sdhci_writel(host, val, ESDHC_TBCTL); |
| 809 | |||
| 747 | esdhc_clock_enable(host, true); | 810 | esdhc_clock_enable(host, true); |
| 811 | } | ||
| 812 | |||
| 813 | static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode) | ||
| 814 | { | ||
| 815 | struct sdhci_host *host = mmc_priv(mmc); | ||
| 816 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 817 | struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); | ||
| 818 | bool hs400_tuning; | ||
| 819 | u32 val; | ||
| 820 | int ret; | ||
| 821 | |||
| 822 | if (esdhc->quirk_limited_clk_division && | ||
| 823 | host->flags & SDHCI_HS400_TUNING) | ||
| 824 | esdhc_of_set_clock(host, host->clock); | ||
| 825 | |||
| 826 | esdhc_tuning_block_enable(host, true); | ||
| 827 | |||
| 828 | hs400_tuning = host->flags & SDHCI_HS400_TUNING; | ||
| 829 | ret = sdhci_execute_tuning(mmc, opcode); | ||
| 830 | |||
| 831 | if (hs400_tuning) { | ||
| 832 | val = sdhci_readl(host, ESDHC_SDTIMNGCTL); | ||
| 833 | val |= ESDHC_FLW_CTL_BG; | ||
| 834 | sdhci_writel(host, val, ESDHC_SDTIMNGCTL); | ||
| 835 | } | ||
| 748 | 836 | ||
| 749 | sdhci_execute_tuning(mmc, opcode); | ||
| 750 | if (host->tuning_err == -EAGAIN && esdhc->quirk_fixup_tuning) { | 837 | if (host->tuning_err == -EAGAIN && esdhc->quirk_fixup_tuning) { |
| 751 | 838 | ||
| 752 | /* program TBPTR[TB_WNDW_END_PTR] = 3*DIV_RATIO and | 839 | /* program TBPTR[TB_WNDW_END_PTR] = 3*DIV_RATIO and |
| @@ -765,7 +852,16 @@ static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
| 765 | sdhci_writel(host, val, ESDHC_TBCTL); | 852 | sdhci_writel(host, val, ESDHC_TBCTL); |
| 766 | sdhci_execute_tuning(mmc, opcode); | 853 | sdhci_execute_tuning(mmc, opcode); |
| 767 | } | 854 | } |
| 768 | return 0; | 855 | return ret; |
| 856 | } | ||
| 857 | |||
| 858 | static void esdhc_set_uhs_signaling(struct sdhci_host *host, | ||
| 859 | unsigned int timing) | ||
| 860 | { | ||
| 861 | if (timing == MMC_TIMING_MMC_HS400) | ||
| 862 | esdhc_tuning_block_enable(host, true); | ||
| 863 | else | ||
| 864 | sdhci_set_uhs_signaling(host, timing); | ||
| 769 | } | 865 | } |
| 770 | 866 | ||
| 771 | #ifdef CONFIG_PM_SLEEP | 867 | #ifdef CONFIG_PM_SLEEP |
| @@ -814,7 +910,7 @@ static const struct sdhci_ops sdhci_esdhc_be_ops = { | |||
| 814 | .adma_workaround = esdhc_of_adma_workaround, | 910 | .adma_workaround = esdhc_of_adma_workaround, |
| 815 | .set_bus_width = esdhc_pltfm_set_bus_width, | 911 | .set_bus_width = esdhc_pltfm_set_bus_width, |
| 816 | .reset = esdhc_reset, | 912 | .reset = esdhc_reset, |
| 817 | .set_uhs_signaling = sdhci_set_uhs_signaling, | 913 | .set_uhs_signaling = esdhc_set_uhs_signaling, |
| 818 | }; | 914 | }; |
| 819 | 915 | ||
| 820 | static const struct sdhci_ops sdhci_esdhc_le_ops = { | 916 | static const struct sdhci_ops sdhci_esdhc_le_ops = { |
| @@ -831,7 +927,7 @@ static const struct sdhci_ops sdhci_esdhc_le_ops = { | |||
| 831 | .adma_workaround = esdhc_of_adma_workaround, | 927 | .adma_workaround = esdhc_of_adma_workaround, |
| 832 | .set_bus_width = esdhc_pltfm_set_bus_width, | 928 | .set_bus_width = esdhc_pltfm_set_bus_width, |
| 833 | .reset = esdhc_reset, | 929 | .reset = esdhc_reset, |
| 834 | .set_uhs_signaling = sdhci_set_uhs_signaling, | 930 | .set_uhs_signaling = esdhc_set_uhs_signaling, |
| 835 | }; | 931 | }; |
| 836 | 932 | ||
| 837 | static const struct sdhci_pltfm_data sdhci_esdhc_be_pdata = { | 933 | static const struct sdhci_pltfm_data sdhci_esdhc_be_pdata = { |
| @@ -857,6 +953,16 @@ static struct soc_device_attribute soc_incorrect_hostver[] = { | |||
| 857 | { }, | 953 | { }, |
| 858 | }; | 954 | }; |
| 859 | 955 | ||
| 956 | static struct soc_device_attribute soc_fixup_sdhc_clkdivs[] = { | ||
| 957 | { .family = "QorIQ LX2160A", .revision = "1.0", }, | ||
| 958 | { }, | ||
| 959 | }; | ||
| 960 | |||
| 961 | static struct soc_device_attribute soc_unreliable_pulse_detection[] = { | ||
| 962 | { .family = "QorIQ LX2160A", .revision = "1.0", }, | ||
| 963 | { }, | ||
| 964 | }; | ||
| 965 | |||
| 860 | static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host) | 966 | static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host) |
| 861 | { | 967 | { |
| 862 | const struct of_device_id *match; | 968 | const struct of_device_id *match; |
| @@ -879,6 +985,16 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host) | |||
| 879 | else | 985 | else |
| 880 | esdhc->quirk_incorrect_hostver = false; | 986 | esdhc->quirk_incorrect_hostver = false; |
| 881 | 987 | ||
| 988 | if (soc_device_match(soc_fixup_sdhc_clkdivs)) | ||
| 989 | esdhc->quirk_limited_clk_division = true; | ||
| 990 | else | ||
| 991 | esdhc->quirk_limited_clk_division = false; | ||
| 992 | |||
| 993 | if (soc_device_match(soc_unreliable_pulse_detection)) | ||
| 994 | esdhc->quirk_unreliable_pulse_detection = true; | ||
| 995 | else | ||
| 996 | esdhc->quirk_unreliable_pulse_detection = false; | ||
| 997 | |||
| 882 | match = of_match_node(sdhci_esdhc_of_match, pdev->dev.of_node); | 998 | match = of_match_node(sdhci_esdhc_of_match, pdev->dev.of_node); |
| 883 | if (match) | 999 | if (match) |
| 884 | esdhc->clk_fixup = match->data; | 1000 | esdhc->clk_fixup = match->data; |
| @@ -909,6 +1025,12 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host) | |||
| 909 | } | 1025 | } |
| 910 | } | 1026 | } |
| 911 | 1027 | ||
| 1028 | static int esdhc_hs400_prepare_ddr(struct mmc_host *mmc) | ||
| 1029 | { | ||
| 1030 | esdhc_tuning_block_enable(mmc_priv(mmc), false); | ||
| 1031 | return 0; | ||
| 1032 | } | ||
| 1033 | |||
| 912 | static int sdhci_esdhc_probe(struct platform_device *pdev) | 1034 | static int sdhci_esdhc_probe(struct platform_device *pdev) |
| 913 | { | 1035 | { |
| 914 | struct sdhci_host *host; | 1036 | struct sdhci_host *host; |
| @@ -932,6 +1054,7 @@ static int sdhci_esdhc_probe(struct platform_device *pdev) | |||
| 932 | host->mmc_host_ops.start_signal_voltage_switch = | 1054 | host->mmc_host_ops.start_signal_voltage_switch = |
| 933 | esdhc_signal_voltage_switch; | 1055 | esdhc_signal_voltage_switch; |
| 934 | host->mmc_host_ops.execute_tuning = esdhc_execute_tuning; | 1056 | host->mmc_host_ops.execute_tuning = esdhc_execute_tuning; |
| 1057 | host->mmc_host_ops.hs400_prepare_ddr = esdhc_hs400_prepare_ddr; | ||
| 935 | host->tuning_delay = 1; | 1058 | host->tuning_delay = 1; |
| 936 | 1059 | ||
| 937 | esdhc_init(pdev, host); | 1060 | esdhc_init(pdev, host); |
diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c index d264391616f9..c11c18a9aacb 100644 --- a/drivers/mmc/host/sdhci-omap.c +++ b/drivers/mmc/host/sdhci-omap.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/regulator/consumer.h> | 27 | #include <linux/regulator/consumer.h> |
| 28 | #include <linux/pinctrl/consumer.h> | 28 | #include <linux/pinctrl/consumer.h> |
| 29 | #include <linux/sys_soc.h> | 29 | #include <linux/sys_soc.h> |
| 30 | #include <linux/thermal.h> | ||
| 30 | 31 | ||
| 31 | #include "sdhci-pltfm.h" | 32 | #include "sdhci-pltfm.h" |
| 32 | 33 | ||
| @@ -115,6 +116,7 @@ struct sdhci_omap_host { | |||
| 115 | 116 | ||
| 116 | struct pinctrl *pinctrl; | 117 | struct pinctrl *pinctrl; |
| 117 | struct pinctrl_state **pinctrl_state; | 118 | struct pinctrl_state **pinctrl_state; |
| 119 | bool is_tuning; | ||
| 118 | }; | 120 | }; |
| 119 | 121 | ||
| 120 | static void sdhci_omap_start_clock(struct sdhci_omap_host *omap_host); | 122 | static void sdhci_omap_start_clock(struct sdhci_omap_host *omap_host); |
| @@ -220,8 +222,12 @@ static void sdhci_omap_conf_bus_power(struct sdhci_omap_host *omap_host, | |||
| 220 | 222 | ||
| 221 | /* wait 1ms */ | 223 | /* wait 1ms */ |
| 222 | timeout = ktime_add_ms(ktime_get(), SDHCI_OMAP_TIMEOUT); | 224 | timeout = ktime_add_ms(ktime_get(), SDHCI_OMAP_TIMEOUT); |
| 223 | while (!(sdhci_omap_readl(omap_host, SDHCI_OMAP_HCTL) & HCTL_SDBP)) { | 225 | while (1) { |
| 224 | if (WARN_ON(ktime_after(ktime_get(), timeout))) | 226 | bool timedout = ktime_after(ktime_get(), timeout); |
| 227 | |||
| 228 | if (sdhci_omap_readl(omap_host, SDHCI_OMAP_HCTL) & HCTL_SDBP) | ||
| 229 | break; | ||
| 230 | if (WARN_ON(timedout)) | ||
| 225 | return; | 231 | return; |
| 226 | usleep_range(5, 10); | 232 | usleep_range(5, 10); |
| 227 | } | 233 | } |
| @@ -285,19 +291,19 @@ static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
| 285 | struct sdhci_host *host = mmc_priv(mmc); | 291 | struct sdhci_host *host = mmc_priv(mmc); |
| 286 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 292 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
| 287 | struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); | 293 | struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); |
| 294 | struct thermal_zone_device *thermal_dev; | ||
| 288 | struct device *dev = omap_host->dev; | 295 | struct device *dev = omap_host->dev; |
| 289 | struct mmc_ios *ios = &mmc->ios; | 296 | struct mmc_ios *ios = &mmc->ios; |
| 290 | u32 start_window = 0, max_window = 0; | 297 | u32 start_window = 0, max_window = 0; |
| 298 | bool single_point_failure = false; | ||
| 291 | bool dcrc_was_enabled = false; | 299 | bool dcrc_was_enabled = false; |
| 292 | u8 cur_match, prev_match = 0; | 300 | u8 cur_match, prev_match = 0; |
| 293 | u32 length = 0, max_len = 0; | 301 | u32 length = 0, max_len = 0; |
| 294 | u32 phase_delay = 0; | 302 | u32 phase_delay = 0; |
| 303 | int temperature; | ||
| 295 | int ret = 0; | 304 | int ret = 0; |
| 296 | u32 reg; | 305 | u32 reg; |
| 297 | 306 | int i; | |
| 298 | pltfm_host = sdhci_priv(host); | ||
| 299 | omap_host = sdhci_pltfm_priv(pltfm_host); | ||
| 300 | dev = omap_host->dev; | ||
| 301 | 307 | ||
| 302 | /* clock tuning is not needed for upto 52MHz */ | 308 | /* clock tuning is not needed for upto 52MHz */ |
| 303 | if (ios->clock <= 52000000) | 309 | if (ios->clock <= 52000000) |
| @@ -307,6 +313,16 @@ static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
| 307 | if (ios->timing == MMC_TIMING_UHS_SDR50 && !(reg & CAPA2_TSDR50)) | 313 | if (ios->timing == MMC_TIMING_UHS_SDR50 && !(reg & CAPA2_TSDR50)) |
| 308 | return 0; | 314 | return 0; |
| 309 | 315 | ||
| 316 | thermal_dev = thermal_zone_get_zone_by_name("cpu_thermal"); | ||
| 317 | if (IS_ERR(thermal_dev)) { | ||
| 318 | dev_err(dev, "Unable to get thermal zone for tuning\n"); | ||
| 319 | return PTR_ERR(thermal_dev); | ||
| 320 | } | ||
| 321 | |||
| 322 | ret = thermal_zone_get_temp(thermal_dev, &temperature); | ||
| 323 | if (ret) | ||
| 324 | return ret; | ||
| 325 | |||
| 310 | reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_DLL); | 326 | reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_DLL); |
| 311 | reg |= DLL_SWT; | 327 | reg |= DLL_SWT; |
| 312 | sdhci_omap_writel(omap_host, SDHCI_OMAP_DLL, reg); | 328 | sdhci_omap_writel(omap_host, SDHCI_OMAP_DLL, reg); |
| @@ -322,6 +338,13 @@ static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
| 322 | dcrc_was_enabled = true; | 338 | dcrc_was_enabled = true; |
| 323 | } | 339 | } |
| 324 | 340 | ||
| 341 | omap_host->is_tuning = true; | ||
| 342 | |||
| 343 | /* | ||
| 344 | * Stage 1: Search for a maximum pass window ignoring any | ||
| 345 | * any single point failures. If the tuning value ends up | ||
| 346 | * near it, move away from it in stage 2 below | ||
| 347 | */ | ||
| 325 | while (phase_delay <= MAX_PHASE_DELAY) { | 348 | while (phase_delay <= MAX_PHASE_DELAY) { |
| 326 | sdhci_omap_set_dll(omap_host, phase_delay); | 349 | sdhci_omap_set_dll(omap_host, phase_delay); |
| 327 | 350 | ||
| @@ -329,10 +352,15 @@ static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
| 329 | if (cur_match) { | 352 | if (cur_match) { |
| 330 | if (prev_match) { | 353 | if (prev_match) { |
| 331 | length++; | 354 | length++; |
| 355 | } else if (single_point_failure) { | ||
| 356 | /* ignore single point failure */ | ||
| 357 | length++; | ||
| 332 | } else { | 358 | } else { |
| 333 | start_window = phase_delay; | 359 | start_window = phase_delay; |
| 334 | length = 1; | 360 | length = 1; |
| 335 | } | 361 | } |
| 362 | } else { | ||
| 363 | single_point_failure = prev_match; | ||
| 336 | } | 364 | } |
| 337 | 365 | ||
| 338 | if (length > max_len) { | 366 | if (length > max_len) { |
| @@ -350,18 +378,84 @@ static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
| 350 | goto tuning_error; | 378 | goto tuning_error; |
| 351 | } | 379 | } |
| 352 | 380 | ||
| 381 | /* | ||
| 382 | * Assign tuning value as a ratio of maximum pass window based | ||
| 383 | * on temperature | ||
| 384 | */ | ||
| 385 | if (temperature < -20000) | ||
| 386 | phase_delay = min(max_window + 4 * max_len - 24, | ||
| 387 | max_window + | ||
| 388 | DIV_ROUND_UP(13 * max_len, 16) * 4); | ||
| 389 | else if (temperature < 20000) | ||
| 390 | phase_delay = max_window + DIV_ROUND_UP(9 * max_len, 16) * 4; | ||
| 391 | else if (temperature < 40000) | ||
| 392 | phase_delay = max_window + DIV_ROUND_UP(8 * max_len, 16) * 4; | ||
| 393 | else if (temperature < 70000) | ||
| 394 | phase_delay = max_window + DIV_ROUND_UP(7 * max_len, 16) * 4; | ||
| 395 | else if (temperature < 90000) | ||
| 396 | phase_delay = max_window + DIV_ROUND_UP(5 * max_len, 16) * 4; | ||
| 397 | else if (temperature < 120000) | ||
| 398 | phase_delay = max_window + DIV_ROUND_UP(4 * max_len, 16) * 4; | ||
| 399 | else | ||
| 400 | phase_delay = max_window + DIV_ROUND_UP(3 * max_len, 16) * 4; | ||
| 401 | |||
| 402 | /* | ||
| 403 | * Stage 2: Search for a single point failure near the chosen tuning | ||
| 404 | * value in two steps. First in the +3 to +10 range and then in the | ||
| 405 | * +2 to -10 range. If found, move away from it in the appropriate | ||
| 406 | * direction by the appropriate amount depending on the temperature. | ||
| 407 | */ | ||
| 408 | for (i = 3; i <= 10; i++) { | ||
| 409 | sdhci_omap_set_dll(omap_host, phase_delay + i); | ||
| 410 | |||
| 411 | if (mmc_send_tuning(mmc, opcode, NULL)) { | ||
| 412 | if (temperature < 10000) | ||
| 413 | phase_delay += i + 6; | ||
| 414 | else if (temperature < 20000) | ||
| 415 | phase_delay += i - 12; | ||
| 416 | else if (temperature < 70000) | ||
| 417 | phase_delay += i - 8; | ||
| 418 | else | ||
| 419 | phase_delay += i - 6; | ||
| 420 | |||
| 421 | goto single_failure_found; | ||
| 422 | } | ||
| 423 | } | ||
| 424 | |||
| 425 | for (i = 2; i >= -10; i--) { | ||
| 426 | sdhci_omap_set_dll(omap_host, phase_delay + i); | ||
| 427 | |||
| 428 | if (mmc_send_tuning(mmc, opcode, NULL)) { | ||
| 429 | if (temperature < 10000) | ||
| 430 | phase_delay += i + 12; | ||
| 431 | else if (temperature < 20000) | ||
| 432 | phase_delay += i + 8; | ||
| 433 | else if (temperature < 70000) | ||
| 434 | phase_delay += i + 8; | ||
| 435 | else if (temperature < 90000) | ||
| 436 | phase_delay += i + 10; | ||
| 437 | else | ||
| 438 | phase_delay += i + 12; | ||
| 439 | |||
| 440 | goto single_failure_found; | ||
| 441 | } | ||
| 442 | } | ||
| 443 | |||
| 444 | single_failure_found: | ||
| 353 | reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_AC12); | 445 | reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_AC12); |
| 354 | if (!(reg & AC12_SCLK_SEL)) { | 446 | if (!(reg & AC12_SCLK_SEL)) { |
| 355 | ret = -EIO; | 447 | ret = -EIO; |
| 356 | goto tuning_error; | 448 | goto tuning_error; |
| 357 | } | 449 | } |
| 358 | 450 | ||
| 359 | phase_delay = max_window + 4 * (max_len >> 1); | ||
| 360 | sdhci_omap_set_dll(omap_host, phase_delay); | 451 | sdhci_omap_set_dll(omap_host, phase_delay); |
| 361 | 452 | ||
| 453 | omap_host->is_tuning = false; | ||
| 454 | |||
| 362 | goto ret; | 455 | goto ret; |
| 363 | 456 | ||
| 364 | tuning_error: | 457 | tuning_error: |
| 458 | omap_host->is_tuning = false; | ||
| 365 | dev_err(dev, "Tuning failed\n"); | 459 | dev_err(dev, "Tuning failed\n"); |
| 366 | sdhci_omap_disable_tuning(omap_host); | 460 | sdhci_omap_disable_tuning(omap_host); |
| 367 | 461 | ||
| @@ -653,8 +747,12 @@ static void sdhci_omap_init_74_clocks(struct sdhci_host *host, u8 power_mode) | |||
| 653 | 747 | ||
| 654 | /* wait 1ms */ | 748 | /* wait 1ms */ |
| 655 | timeout = ktime_add_ms(ktime_get(), SDHCI_OMAP_TIMEOUT); | 749 | timeout = ktime_add_ms(ktime_get(), SDHCI_OMAP_TIMEOUT); |
| 656 | while (!(sdhci_omap_readl(omap_host, SDHCI_OMAP_STAT) & INT_CC_EN)) { | 750 | while (1) { |
| 657 | if (WARN_ON(ktime_after(ktime_get(), timeout))) | 751 | bool timedout = ktime_after(ktime_get(), timeout); |
| 752 | |||
| 753 | if (sdhci_omap_readl(omap_host, SDHCI_OMAP_STAT) & INT_CC_EN) | ||
| 754 | break; | ||
| 755 | if (WARN_ON(timedout)) | ||
| 658 | return; | 756 | return; |
| 659 | usleep_range(5, 10); | 757 | usleep_range(5, 10); |
| 660 | } | 758 | } |
| @@ -687,6 +785,18 @@ static void sdhci_omap_set_uhs_signaling(struct sdhci_host *host, | |||
| 687 | sdhci_omap_start_clock(omap_host); | 785 | sdhci_omap_start_clock(omap_host); |
| 688 | } | 786 | } |
| 689 | 787 | ||
| 788 | void sdhci_omap_reset(struct sdhci_host *host, u8 mask) | ||
| 789 | { | ||
| 790 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 791 | struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); | ||
| 792 | |||
| 793 | /* Don't reset data lines during tuning operation */ | ||
| 794 | if (omap_host->is_tuning) | ||
| 795 | mask &= ~SDHCI_RESET_DATA; | ||
| 796 | |||
| 797 | sdhci_reset(host, mask); | ||
| 798 | } | ||
| 799 | |||
| 690 | static struct sdhci_ops sdhci_omap_ops = { | 800 | static struct sdhci_ops sdhci_omap_ops = { |
| 691 | .set_clock = sdhci_omap_set_clock, | 801 | .set_clock = sdhci_omap_set_clock, |
| 692 | .set_power = sdhci_omap_set_power, | 802 | .set_power = sdhci_omap_set_power, |
| @@ -695,7 +805,7 @@ static struct sdhci_ops sdhci_omap_ops = { | |||
| 695 | .get_min_clock = sdhci_omap_get_min_clock, | 805 | .get_min_clock = sdhci_omap_get_min_clock, |
| 696 | .set_bus_width = sdhci_omap_set_bus_width, | 806 | .set_bus_width = sdhci_omap_set_bus_width, |
| 697 | .platform_send_init_74_clocks = sdhci_omap_init_74_clocks, | 807 | .platform_send_init_74_clocks = sdhci_omap_init_74_clocks, |
| 698 | .reset = sdhci_reset, | 808 | .reset = sdhci_omap_reset, |
| 699 | .set_uhs_signaling = sdhci_omap_set_uhs_signaling, | 809 | .set_uhs_signaling = sdhci_omap_set_uhs_signaling, |
| 700 | }; | 810 | }; |
| 701 | 811 | ||
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index c4115bae5db1..2a6eba74b94e 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c | |||
| @@ -710,11 +710,15 @@ static int intel_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
| 710 | static void byt_probe_slot(struct sdhci_pci_slot *slot) | 710 | static void byt_probe_slot(struct sdhci_pci_slot *slot) |
| 711 | { | 711 | { |
| 712 | struct mmc_host_ops *ops = &slot->host->mmc_host_ops; | 712 | struct mmc_host_ops *ops = &slot->host->mmc_host_ops; |
| 713 | struct device *dev = &slot->chip->pdev->dev; | ||
| 714 | struct mmc_host *mmc = slot->host->mmc; | ||
| 713 | 715 | ||
| 714 | byt_read_dsm(slot); | 716 | byt_read_dsm(slot); |
| 715 | 717 | ||
| 716 | ops->execute_tuning = intel_execute_tuning; | 718 | ops->execute_tuning = intel_execute_tuning; |
| 717 | ops->start_signal_voltage_switch = intel_start_signal_voltage_switch; | 719 | ops->start_signal_voltage_switch = intel_start_signal_voltage_switch; |
| 720 | |||
| 721 | device_property_read_u32(dev, "max-frequency", &mmc->f_max); | ||
| 718 | } | 722 | } |
| 719 | 723 | ||
| 720 | static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot) | 724 | static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot) |
| @@ -937,7 +941,8 @@ static int byt_sd_probe_slot(struct sdhci_pci_slot *slot) | |||
| 937 | static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = { | 941 | static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = { |
| 938 | .allow_runtime_pm = true, | 942 | .allow_runtime_pm = true, |
| 939 | .probe_slot = byt_emmc_probe_slot, | 943 | .probe_slot = byt_emmc_probe_slot, |
| 940 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | 944 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | |
| 945 | SDHCI_QUIRK_NO_LED, | ||
| 941 | .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | | 946 | .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | |
| 942 | SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 | | 947 | SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 | |
| 943 | SDHCI_QUIRK2_STOP_WITH_TC, | 948 | SDHCI_QUIRK2_STOP_WITH_TC, |
| @@ -957,7 +962,8 @@ static const struct sdhci_pci_fixes sdhci_intel_glk_emmc = { | |||
| 957 | .runtime_suspend = glk_runtime_suspend, | 962 | .runtime_suspend = glk_runtime_suspend, |
| 958 | .runtime_resume = glk_runtime_resume, | 963 | .runtime_resume = glk_runtime_resume, |
| 959 | #endif | 964 | #endif |
| 960 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | 965 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | |
| 966 | SDHCI_QUIRK_NO_LED, | ||
| 961 | .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | | 967 | .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | |
| 962 | SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 | | 968 | SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 | |
| 963 | SDHCI_QUIRK2_STOP_WITH_TC, | 969 | SDHCI_QUIRK2_STOP_WITH_TC, |
| @@ -966,7 +972,8 @@ static const struct sdhci_pci_fixes sdhci_intel_glk_emmc = { | |||
| 966 | }; | 972 | }; |
| 967 | 973 | ||
| 968 | static const struct sdhci_pci_fixes sdhci_ni_byt_sdio = { | 974 | static const struct sdhci_pci_fixes sdhci_ni_byt_sdio = { |
| 969 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | 975 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | |
| 976 | SDHCI_QUIRK_NO_LED, | ||
| 970 | .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON | | 977 | .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON | |
| 971 | SDHCI_QUIRK2_PRESET_VALUE_BROKEN, | 978 | SDHCI_QUIRK2_PRESET_VALUE_BROKEN, |
| 972 | .allow_runtime_pm = true, | 979 | .allow_runtime_pm = true, |
| @@ -976,7 +983,8 @@ static const struct sdhci_pci_fixes sdhci_ni_byt_sdio = { | |||
| 976 | }; | 983 | }; |
| 977 | 984 | ||
| 978 | static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { | 985 | static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { |
| 979 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | 986 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | |
| 987 | SDHCI_QUIRK_NO_LED, | ||
| 980 | .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON | | 988 | .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON | |
| 981 | SDHCI_QUIRK2_PRESET_VALUE_BROKEN, | 989 | SDHCI_QUIRK2_PRESET_VALUE_BROKEN, |
| 982 | .allow_runtime_pm = true, | 990 | .allow_runtime_pm = true, |
| @@ -986,7 +994,8 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { | |||
| 986 | }; | 994 | }; |
| 987 | 995 | ||
| 988 | static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { | 996 | static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { |
| 989 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | 997 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | |
| 998 | SDHCI_QUIRK_NO_LED, | ||
| 990 | .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON | | 999 | .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON | |
| 991 | SDHCI_QUIRK2_PRESET_VALUE_BROKEN | | 1000 | SDHCI_QUIRK2_PRESET_VALUE_BROKEN | |
| 992 | SDHCI_QUIRK2_STOP_WITH_TC, | 1001 | SDHCI_QUIRK2_STOP_WITH_TC, |
diff --git a/drivers/mmc/host/sdhci-xenon-phy.c b/drivers/mmc/host/sdhci-xenon-phy.c index 5956e90380e8..5b5eb53a63d2 100644 --- a/drivers/mmc/host/sdhci-xenon-phy.c +++ b/drivers/mmc/host/sdhci-xenon-phy.c | |||
| @@ -357,9 +357,13 @@ static int xenon_emmc_phy_enable_dll(struct sdhci_host *host) | |||
| 357 | 357 | ||
| 358 | /* Wait max 32 ms */ | 358 | /* Wait max 32 ms */ |
| 359 | timeout = ktime_add_ms(ktime_get(), 32); | 359 | timeout = ktime_add_ms(ktime_get(), 32); |
| 360 | while (!(sdhci_readw(host, XENON_SLOT_EXT_PRESENT_STATE) & | 360 | while (1) { |
| 361 | XENON_DLL_LOCK_STATE)) { | 361 | bool timedout = ktime_after(ktime_get(), timeout); |
| 362 | if (ktime_after(ktime_get(), timeout)) { | 362 | |
| 363 | if (sdhci_readw(host, XENON_SLOT_EXT_PRESENT_STATE) & | ||
| 364 | XENON_DLL_LOCK_STATE) | ||
| 365 | break; | ||
| 366 | if (timedout) { | ||
| 363 | dev_err(mmc_dev(host->mmc), "Wait for DLL Lock time-out\n"); | 367 | dev_err(mmc_dev(host->mmc), "Wait for DLL Lock time-out\n"); |
| 364 | return -ETIMEDOUT; | 368 | return -ETIMEDOUT; |
| 365 | } | 369 | } |
diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c index 4d0791f6ec23..a0b5089b3274 100644 --- a/drivers/mmc/host/sdhci-xenon.c +++ b/drivers/mmc/host/sdhci-xenon.c | |||
| @@ -34,9 +34,13 @@ static int xenon_enable_internal_clk(struct sdhci_host *host) | |||
| 34 | sdhci_writel(host, reg, SDHCI_CLOCK_CONTROL); | 34 | sdhci_writel(host, reg, SDHCI_CLOCK_CONTROL); |
| 35 | /* Wait max 20 ms */ | 35 | /* Wait max 20 ms */ |
| 36 | timeout = ktime_add_ms(ktime_get(), 20); | 36 | timeout = ktime_add_ms(ktime_get(), 20); |
| 37 | while (!((reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) | 37 | while (1) { |
| 38 | & SDHCI_CLOCK_INT_STABLE)) { | 38 | bool timedout = ktime_after(ktime_get(), timeout); |
| 39 | if (ktime_after(ktime_get(), timeout)) { | 39 | |
| 40 | reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL); | ||
| 41 | if (reg & SDHCI_CLOCK_INT_STABLE) | ||
| 42 | break; | ||
| 43 | if (timedout) { | ||
| 40 | dev_err(mmc_dev(host->mmc), "Internal clock never stabilised.\n"); | 44 | dev_err(mmc_dev(host->mmc), "Internal clock never stabilised.\n"); |
| 41 | return -ETIMEDOUT; | 45 | return -ETIMEDOUT; |
| 42 | } | 46 | } |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index df05352b6a4a..a22e11a65658 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
| @@ -82,8 +82,8 @@ void sdhci_dumpregs(struct sdhci_host *host) | |||
| 82 | SDHCI_DUMP("Int enab: 0x%08x | Sig enab: 0x%08x\n", | 82 | SDHCI_DUMP("Int enab: 0x%08x | Sig enab: 0x%08x\n", |
| 83 | sdhci_readl(host, SDHCI_INT_ENABLE), | 83 | sdhci_readl(host, SDHCI_INT_ENABLE), |
| 84 | sdhci_readl(host, SDHCI_SIGNAL_ENABLE)); | 84 | sdhci_readl(host, SDHCI_SIGNAL_ENABLE)); |
| 85 | SDHCI_DUMP("AC12 err: 0x%08x | Slot int: 0x%08x\n", | 85 | SDHCI_DUMP("ACmd stat: 0x%08x | Slot int: 0x%08x\n", |
| 86 | sdhci_readw(host, SDHCI_ACMD12_ERR), | 86 | sdhci_readw(host, SDHCI_AUTO_CMD_STATUS), |
| 87 | sdhci_readw(host, SDHCI_SLOT_INT_STATUS)); | 87 | sdhci_readw(host, SDHCI_SLOT_INT_STATUS)); |
| 88 | SDHCI_DUMP("Caps: 0x%08x | Caps_1: 0x%08x\n", | 88 | SDHCI_DUMP("Caps: 0x%08x | Caps_1: 0x%08x\n", |
| 89 | sdhci_readl(host, SDHCI_CAPABILITIES), | 89 | sdhci_readl(host, SDHCI_CAPABILITIES), |
| @@ -349,6 +349,9 @@ static void __sdhci_led_activate(struct sdhci_host *host) | |||
| 349 | { | 349 | { |
| 350 | u8 ctrl; | 350 | u8 ctrl; |
| 351 | 351 | ||
| 352 | if (host->quirks & SDHCI_QUIRK_NO_LED) | ||
| 353 | return; | ||
| 354 | |||
| 352 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); | 355 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); |
| 353 | ctrl |= SDHCI_CTRL_LED; | 356 | ctrl |= SDHCI_CTRL_LED; |
| 354 | sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); | 357 | sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); |
| @@ -358,6 +361,9 @@ static void __sdhci_led_deactivate(struct sdhci_host *host) | |||
| 358 | { | 361 | { |
| 359 | u8 ctrl; | 362 | u8 ctrl; |
| 360 | 363 | ||
| 364 | if (host->quirks & SDHCI_QUIRK_NO_LED) | ||
| 365 | return; | ||
| 366 | |||
| 361 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); | 367 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); |
| 362 | ctrl &= ~SDHCI_CTRL_LED; | 368 | ctrl &= ~SDHCI_CTRL_LED; |
| 363 | sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); | 369 | sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); |
| @@ -387,6 +393,9 @@ static int sdhci_led_register(struct sdhci_host *host) | |||
| 387 | { | 393 | { |
| 388 | struct mmc_host *mmc = host->mmc; | 394 | struct mmc_host *mmc = host->mmc; |
| 389 | 395 | ||
| 396 | if (host->quirks & SDHCI_QUIRK_NO_LED) | ||
| 397 | return 0; | ||
| 398 | |||
| 390 | snprintf(host->led_name, sizeof(host->led_name), | 399 | snprintf(host->led_name, sizeof(host->led_name), |
| 391 | "%s::", mmc_hostname(mmc)); | 400 | "%s::", mmc_hostname(mmc)); |
| 392 | 401 | ||
| @@ -400,6 +409,9 @@ static int sdhci_led_register(struct sdhci_host *host) | |||
| 400 | 409 | ||
| 401 | static void sdhci_led_unregister(struct sdhci_host *host) | 410 | static void sdhci_led_unregister(struct sdhci_host *host) |
| 402 | { | 411 | { |
| 412 | if (host->quirks & SDHCI_QUIRK_NO_LED) | ||
| 413 | return; | ||
| 414 | |||
| 403 | led_classdev_unregister(&host->led); | 415 | led_classdev_unregister(&host->led); |
| 404 | } | 416 | } |
| 405 | 417 | ||
| @@ -933,6 +945,11 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host) | |||
| 933 | else | 945 | else |
| 934 | host->ier = (host->ier & ~dma_irqs) | pio_irqs; | 946 | host->ier = (host->ier & ~dma_irqs) | pio_irqs; |
| 935 | 947 | ||
| 948 | if (host->flags & (SDHCI_AUTO_CMD23 | SDHCI_AUTO_CMD12)) | ||
| 949 | host->ier |= SDHCI_INT_AUTO_CMD_ERR; | ||
| 950 | else | ||
| 951 | host->ier &= ~SDHCI_INT_AUTO_CMD_ERR; | ||
| 952 | |||
| 936 | sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); | 953 | sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); |
| 937 | sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); | 954 | sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); |
| 938 | } | 955 | } |
| @@ -1191,8 +1208,7 @@ static bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq) | |||
| 1191 | return (!(host->flags & SDHCI_DEVICE_DEAD) && | 1208 | return (!(host->flags & SDHCI_DEVICE_DEAD) && |
| 1192 | ((mrq->cmd && mrq->cmd->error) || | 1209 | ((mrq->cmd && mrq->cmd->error) || |
| 1193 | (mrq->sbc && mrq->sbc->error) || | 1210 | (mrq->sbc && mrq->sbc->error) || |
| 1194 | (mrq->data && ((mrq->data->error && !mrq->data->stop) || | 1211 | (mrq->data && mrq->data->stop && mrq->data->stop->error) || |
| 1195 | (mrq->data->stop && mrq->data->stop->error))) || | ||
| 1196 | (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))); | 1212 | (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))); |
| 1197 | } | 1213 | } |
| 1198 | 1214 | ||
| @@ -1244,6 +1260,16 @@ static void sdhci_finish_data(struct sdhci_host *host) | |||
| 1244 | host->data = NULL; | 1260 | host->data = NULL; |
| 1245 | host->data_cmd = NULL; | 1261 | host->data_cmd = NULL; |
| 1246 | 1262 | ||
| 1263 | /* | ||
| 1264 | * The controller needs a reset of internal state machines upon error | ||
| 1265 | * conditions. | ||
| 1266 | */ | ||
| 1267 | if (data->error) { | ||
| 1268 | if (!host->cmd || host->cmd == data_cmd) | ||
| 1269 | sdhci_do_reset(host, SDHCI_RESET_CMD); | ||
| 1270 | sdhci_do_reset(host, SDHCI_RESET_DATA); | ||
| 1271 | } | ||
| 1272 | |||
| 1247 | if ((host->flags & (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) == | 1273 | if ((host->flags & (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) == |
| 1248 | (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) | 1274 | (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) |
| 1249 | sdhci_adma_table_post(host, data); | 1275 | sdhci_adma_table_post(host, data); |
| @@ -1268,17 +1294,6 @@ static void sdhci_finish_data(struct sdhci_host *host) | |||
| 1268 | if (data->stop && | 1294 | if (data->stop && |
| 1269 | (data->error || | 1295 | (data->error || |
| 1270 | !data->mrq->sbc)) { | 1296 | !data->mrq->sbc)) { |
| 1271 | |||
| 1272 | /* | ||
| 1273 | * The controller needs a reset of internal state machines | ||
| 1274 | * upon error conditions. | ||
| 1275 | */ | ||
| 1276 | if (data->error) { | ||
| 1277 | if (!host->cmd || host->cmd == data_cmd) | ||
| 1278 | sdhci_do_reset(host, SDHCI_RESET_CMD); | ||
| 1279 | sdhci_do_reset(host, SDHCI_RESET_DATA); | ||
| 1280 | } | ||
| 1281 | |||
| 1282 | /* | 1297 | /* |
| 1283 | * 'cap_cmd_during_tfr' request must not use the command line | 1298 | * 'cap_cmd_during_tfr' request must not use the command line |
| 1284 | * after mmc_command_done() has been called. It is upper layer's | 1299 | * after mmc_command_done() has been called. It is upper layer's |
| @@ -2757,8 +2772,23 @@ static void sdhci_timeout_data_timer(struct timer_list *t) | |||
| 2757 | * * | 2772 | * * |
| 2758 | \*****************************************************************************/ | 2773 | \*****************************************************************************/ |
| 2759 | 2774 | ||
| 2760 | static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) | 2775 | static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p) |
| 2761 | { | 2776 | { |
| 2777 | /* Handle auto-CMD12 error */ | ||
| 2778 | if (intmask & SDHCI_INT_AUTO_CMD_ERR && host->data_cmd) { | ||
| 2779 | struct mmc_request *mrq = host->data_cmd->mrq; | ||
| 2780 | u16 auto_cmd_status = sdhci_readw(host, SDHCI_AUTO_CMD_STATUS); | ||
| 2781 | int data_err_bit = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ? | ||
| 2782 | SDHCI_INT_DATA_TIMEOUT : | ||
| 2783 | SDHCI_INT_DATA_CRC; | ||
| 2784 | |||
| 2785 | /* Treat auto-CMD12 error the same as data error */ | ||
| 2786 | if (!mrq->sbc && (host->flags & SDHCI_AUTO_CMD12)) { | ||
| 2787 | *intmask_p |= data_err_bit; | ||
| 2788 | return; | ||
| 2789 | } | ||
| 2790 | } | ||
| 2791 | |||
| 2762 | if (!host->cmd) { | 2792 | if (!host->cmd) { |
| 2763 | /* | 2793 | /* |
| 2764 | * SDHCI recovers from errors by resetting the cmd and data | 2794 | * SDHCI recovers from errors by resetting the cmd and data |
| @@ -2780,20 +2810,12 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) | |||
| 2780 | else | 2810 | else |
| 2781 | host->cmd->error = -EILSEQ; | 2811 | host->cmd->error = -EILSEQ; |
| 2782 | 2812 | ||
| 2783 | /* | 2813 | /* Treat data command CRC error the same as data CRC error */ |
| 2784 | * If this command initiates a data phase and a response | ||
| 2785 | * CRC error is signalled, the card can start transferring | ||
| 2786 | * data - the card may have received the command without | ||
| 2787 | * error. We must not terminate the mmc_request early. | ||
| 2788 | * | ||
| 2789 | * If the card did not receive the command or returned an | ||
| 2790 | * error which prevented it sending data, the data phase | ||
| 2791 | * will time out. | ||
| 2792 | */ | ||
| 2793 | if (host->cmd->data && | 2814 | if (host->cmd->data && |
| 2794 | (intmask & (SDHCI_INT_CRC | SDHCI_INT_TIMEOUT)) == | 2815 | (intmask & (SDHCI_INT_CRC | SDHCI_INT_TIMEOUT)) == |
| 2795 | SDHCI_INT_CRC) { | 2816 | SDHCI_INT_CRC) { |
| 2796 | host->cmd = NULL; | 2817 | host->cmd = NULL; |
| 2818 | *intmask_p |= SDHCI_INT_DATA_CRC; | ||
| 2797 | return; | 2819 | return; |
| 2798 | } | 2820 | } |
| 2799 | 2821 | ||
| @@ -2801,6 +2823,21 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) | |||
| 2801 | return; | 2823 | return; |
| 2802 | } | 2824 | } |
| 2803 | 2825 | ||
| 2826 | /* Handle auto-CMD23 error */ | ||
| 2827 | if (intmask & SDHCI_INT_AUTO_CMD_ERR) { | ||
| 2828 | struct mmc_request *mrq = host->cmd->mrq; | ||
| 2829 | u16 auto_cmd_status = sdhci_readw(host, SDHCI_AUTO_CMD_STATUS); | ||
| 2830 | int err = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ? | ||
| 2831 | -ETIMEDOUT : | ||
| 2832 | -EILSEQ; | ||
| 2833 | |||
| 2834 | if (mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) { | ||
| 2835 | mrq->sbc->error = err; | ||
| 2836 | sdhci_finish_mrq(host, mrq); | ||
| 2837 | return; | ||
| 2838 | } | ||
| 2839 | } | ||
| 2840 | |||
| 2804 | if (intmask & SDHCI_INT_RESPONSE) | 2841 | if (intmask & SDHCI_INT_RESPONSE) |
| 2805 | sdhci_finish_command(host); | 2842 | sdhci_finish_command(host); |
| 2806 | } | 2843 | } |
| @@ -3021,7 +3058,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) | |||
| 3021 | } | 3058 | } |
| 3022 | 3059 | ||
| 3023 | if (intmask & SDHCI_INT_CMD_MASK) | 3060 | if (intmask & SDHCI_INT_CMD_MASK) |
| 3024 | sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK); | 3061 | sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK, &intmask); |
| 3025 | 3062 | ||
| 3026 | if (intmask & SDHCI_INT_DATA_MASK) | 3063 | if (intmask & SDHCI_INT_DATA_MASK) |
| 3027 | sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); | 3064 | sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); |
| @@ -3541,7 +3578,7 @@ void __sdhci_read_caps(struct sdhci_host *host, u16 *ver, u32 *caps, u32 *caps1) | |||
| 3541 | } | 3578 | } |
| 3542 | EXPORT_SYMBOL_GPL(__sdhci_read_caps); | 3579 | EXPORT_SYMBOL_GPL(__sdhci_read_caps); |
| 3543 | 3580 | ||
| 3544 | static int sdhci_allocate_bounce_buffer(struct sdhci_host *host) | 3581 | static void sdhci_allocate_bounce_buffer(struct sdhci_host *host) |
| 3545 | { | 3582 | { |
| 3546 | struct mmc_host *mmc = host->mmc; | 3583 | struct mmc_host *mmc = host->mmc; |
| 3547 | unsigned int max_blocks; | 3584 | unsigned int max_blocks; |
| @@ -3579,7 +3616,7 @@ static int sdhci_allocate_bounce_buffer(struct sdhci_host *host) | |||
| 3579 | * Exiting with zero here makes sure we proceed with | 3616 | * Exiting with zero here makes sure we proceed with |
| 3580 | * mmc->max_segs == 1. | 3617 | * mmc->max_segs == 1. |
| 3581 | */ | 3618 | */ |
| 3582 | return 0; | 3619 | return; |
| 3583 | } | 3620 | } |
| 3584 | 3621 | ||
| 3585 | host->bounce_addr = dma_map_single(mmc->parent, | 3622 | host->bounce_addr = dma_map_single(mmc->parent, |
| @@ -3589,7 +3626,7 @@ static int sdhci_allocate_bounce_buffer(struct sdhci_host *host) | |||
| 3589 | ret = dma_mapping_error(mmc->parent, host->bounce_addr); | 3626 | ret = dma_mapping_error(mmc->parent, host->bounce_addr); |
| 3590 | if (ret) | 3627 | if (ret) |
| 3591 | /* Again fall back to max_segs == 1 */ | 3628 | /* Again fall back to max_segs == 1 */ |
| 3592 | return 0; | 3629 | return; |
| 3593 | host->bounce_buffer_size = bounce_size; | 3630 | host->bounce_buffer_size = bounce_size; |
| 3594 | 3631 | ||
| 3595 | /* Lie about this since we're bouncing */ | 3632 | /* Lie about this since we're bouncing */ |
| @@ -3599,8 +3636,6 @@ static int sdhci_allocate_bounce_buffer(struct sdhci_host *host) | |||
| 3599 | 3636 | ||
| 3600 | pr_info("%s bounce up to %u segments into one, max segment size %u bytes\n", | 3637 | pr_info("%s bounce up to %u segments into one, max segment size %u bytes\n", |
| 3601 | mmc_hostname(mmc), max_blocks, bounce_size); | 3638 | mmc_hostname(mmc), max_blocks, bounce_size); |
| 3602 | |||
| 3603 | return 0; | ||
| 3604 | } | 3639 | } |
| 3605 | 3640 | ||
| 3606 | static inline bool sdhci_can_64bit_dma(struct sdhci_host *host) | 3641 | static inline bool sdhci_can_64bit_dma(struct sdhci_host *host) |
| @@ -4134,12 +4169,9 @@ int sdhci_setup_host(struct sdhci_host *host) | |||
| 4134 | */ | 4169 | */ |
| 4135 | mmc->max_blk_count = (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535; | 4170 | mmc->max_blk_count = (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535; |
| 4136 | 4171 | ||
| 4137 | if (mmc->max_segs == 1) { | 4172 | if (mmc->max_segs == 1) |
| 4138 | /* This may alter mmc->*_blk_* parameters */ | 4173 | /* This may alter mmc->*_blk_* parameters */ |
| 4139 | ret = sdhci_allocate_bounce_buffer(host); | 4174 | sdhci_allocate_bounce_buffer(host); |
| 4140 | if (ret) | ||
| 4141 | return ret; | ||
| 4142 | } | ||
| 4143 | 4175 | ||
| 4144 | return 0; | 4176 | return 0; |
| 4145 | 4177 | ||
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index b001cf4d3d7e..6cc9a3c2ac66 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
| @@ -146,14 +146,15 @@ | |||
| 146 | #define SDHCI_INT_DATA_CRC 0x00200000 | 146 | #define SDHCI_INT_DATA_CRC 0x00200000 |
| 147 | #define SDHCI_INT_DATA_END_BIT 0x00400000 | 147 | #define SDHCI_INT_DATA_END_BIT 0x00400000 |
| 148 | #define SDHCI_INT_BUS_POWER 0x00800000 | 148 | #define SDHCI_INT_BUS_POWER 0x00800000 |
| 149 | #define SDHCI_INT_ACMD12ERR 0x01000000 | 149 | #define SDHCI_INT_AUTO_CMD_ERR 0x01000000 |
| 150 | #define SDHCI_INT_ADMA_ERROR 0x02000000 | 150 | #define SDHCI_INT_ADMA_ERROR 0x02000000 |
| 151 | 151 | ||
| 152 | #define SDHCI_INT_NORMAL_MASK 0x00007FFF | 152 | #define SDHCI_INT_NORMAL_MASK 0x00007FFF |
| 153 | #define SDHCI_INT_ERROR_MASK 0xFFFF8000 | 153 | #define SDHCI_INT_ERROR_MASK 0xFFFF8000 |
| 154 | 154 | ||
| 155 | #define SDHCI_INT_CMD_MASK (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | \ | 155 | #define SDHCI_INT_CMD_MASK (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | \ |
| 156 | SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX) | 156 | SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX | \ |
| 157 | SDHCI_INT_AUTO_CMD_ERR) | ||
| 157 | #define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \ | 158 | #define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \ |
| 158 | SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \ | 159 | SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \ |
| 159 | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \ | 160 | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \ |
| @@ -168,7 +169,11 @@ | |||
| 168 | 169 | ||
| 169 | #define SDHCI_CQE_INT_MASK (SDHCI_CQE_INT_ERR_MASK | SDHCI_INT_CQE) | 170 | #define SDHCI_CQE_INT_MASK (SDHCI_CQE_INT_ERR_MASK | SDHCI_INT_CQE) |
| 170 | 171 | ||
| 171 | #define SDHCI_ACMD12_ERR 0x3C | 172 | #define SDHCI_AUTO_CMD_STATUS 0x3C |
| 173 | #define SDHCI_AUTO_CMD_TIMEOUT 0x00000002 | ||
| 174 | #define SDHCI_AUTO_CMD_CRC 0x00000004 | ||
| 175 | #define SDHCI_AUTO_CMD_END_BIT 0x00000008 | ||
| 176 | #define SDHCI_AUTO_CMD_INDEX 0x00000010 | ||
| 172 | 177 | ||
| 173 | #define SDHCI_HOST_CONTROL2 0x3E | 178 | #define SDHCI_HOST_CONTROL2 0x3E |
| 174 | #define SDHCI_CTRL_UHS_MASK 0x0007 | 179 | #define SDHCI_CTRL_UHS_MASK 0x0007 |
| @@ -403,6 +408,8 @@ struct sdhci_host { | |||
| 403 | #define SDHCI_QUIRK_INVERTED_WRITE_PROTECT (1<<16) | 408 | #define SDHCI_QUIRK_INVERTED_WRITE_PROTECT (1<<16) |
| 404 | /* Controller does not like fast PIO transfers */ | 409 | /* Controller does not like fast PIO transfers */ |
| 405 | #define SDHCI_QUIRK_PIO_NEEDS_DELAY (1<<18) | 410 | #define SDHCI_QUIRK_PIO_NEEDS_DELAY (1<<18) |
| 411 | /* Controller does not have a LED */ | ||
| 412 | #define SDHCI_QUIRK_NO_LED (1<<19) | ||
| 406 | /* Controller has to be forced to use block size of 2048 bytes */ | 413 | /* Controller has to be forced to use block size of 2048 bytes */ |
| 407 | #define SDHCI_QUIRK_FORCE_BLK_SZ_2048 (1<<20) | 414 | #define SDHCI_QUIRK_FORCE_BLK_SZ_2048 (1<<20) |
| 408 | /* Controller cannot do multi-block transfers */ | 415 | /* Controller cannot do multi-block transfers */ |
diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c new file mode 100644 index 000000000000..8c05879850a0 --- /dev/null +++ b/drivers/mmc/host/sdhci_am654.c | |||
| @@ -0,0 +1,374 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * sdhci_am654.c - SDHCI driver for TI's AM654 SOCs | ||
| 4 | * | ||
| 5 | * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com | ||
| 6 | * | ||
| 7 | */ | ||
| 8 | #include <linux/clk.h> | ||
| 9 | #include <linux/module.h> | ||
| 10 | #include <linux/pm_runtime.h> | ||
| 11 | #include <linux/property.h> | ||
| 12 | #include <linux/regmap.h> | ||
| 13 | |||
| 14 | #include "sdhci-pltfm.h" | ||
| 15 | |||
| 16 | /* CTL_CFG Registers */ | ||
| 17 | #define CTL_CFG_2 0x14 | ||
| 18 | |||
| 19 | #define SLOTTYPE_MASK GENMASK(31, 30) | ||
| 20 | #define SLOTTYPE_EMBEDDED BIT(30) | ||
| 21 | |||
| 22 | /* PHY Registers */ | ||
| 23 | #define PHY_CTRL1 0x100 | ||
| 24 | #define PHY_CTRL2 0x104 | ||
| 25 | #define PHY_CTRL3 0x108 | ||
| 26 | #define PHY_CTRL4 0x10C | ||
| 27 | #define PHY_CTRL5 0x110 | ||
| 28 | #define PHY_CTRL6 0x114 | ||
| 29 | #define PHY_STAT1 0x130 | ||
| 30 | #define PHY_STAT2 0x134 | ||
| 31 | |||
| 32 | #define IOMUX_ENABLE_SHIFT 31 | ||
| 33 | #define IOMUX_ENABLE_MASK BIT(IOMUX_ENABLE_SHIFT) | ||
| 34 | #define OTAPDLYENA_SHIFT 20 | ||
| 35 | #define OTAPDLYENA_MASK BIT(OTAPDLYENA_SHIFT) | ||
| 36 | #define OTAPDLYSEL_SHIFT 12 | ||
| 37 | #define OTAPDLYSEL_MASK GENMASK(15, 12) | ||
| 38 | #define STRBSEL_SHIFT 24 | ||
| 39 | #define STRBSEL_MASK GENMASK(27, 24) | ||
| 40 | #define SEL50_SHIFT 8 | ||
| 41 | #define SEL50_MASK BIT(SEL50_SHIFT) | ||
| 42 | #define SEL100_SHIFT 9 | ||
| 43 | #define SEL100_MASK BIT(SEL100_SHIFT) | ||
| 44 | #define DLL_TRIM_ICP_SHIFT 4 | ||
| 45 | #define DLL_TRIM_ICP_MASK GENMASK(7, 4) | ||
| 46 | #define DR_TY_SHIFT 20 | ||
| 47 | #define DR_TY_MASK GENMASK(22, 20) | ||
| 48 | #define ENDLL_SHIFT 1 | ||
| 49 | #define ENDLL_MASK BIT(ENDLL_SHIFT) | ||
| 50 | #define DLLRDY_SHIFT 0 | ||
| 51 | #define DLLRDY_MASK BIT(DLLRDY_SHIFT) | ||
| 52 | #define PDB_SHIFT 0 | ||
| 53 | #define PDB_MASK BIT(PDB_SHIFT) | ||
| 54 | #define CALDONE_SHIFT 1 | ||
| 55 | #define CALDONE_MASK BIT(CALDONE_SHIFT) | ||
| 56 | #define RETRIM_SHIFT 17 | ||
| 57 | #define RETRIM_MASK BIT(RETRIM_SHIFT) | ||
| 58 | |||
| 59 | #define DRIVER_STRENGTH_50_OHM 0x0 | ||
| 60 | #define DRIVER_STRENGTH_33_OHM 0x1 | ||
| 61 | #define DRIVER_STRENGTH_66_OHM 0x2 | ||
| 62 | #define DRIVER_STRENGTH_100_OHM 0x3 | ||
| 63 | #define DRIVER_STRENGTH_40_OHM 0x4 | ||
| 64 | |||
| 65 | #define CLOCK_TOO_SLOW_HZ 400000 | ||
| 66 | |||
| 67 | static struct regmap_config sdhci_am654_regmap_config = { | ||
| 68 | .reg_bits = 32, | ||
| 69 | .val_bits = 32, | ||
| 70 | .reg_stride = 4, | ||
| 71 | .fast_io = true, | ||
| 72 | }; | ||
| 73 | |||
| 74 | struct sdhci_am654_data { | ||
| 75 | struct regmap *base; | ||
| 76 | int otap_del_sel; | ||
| 77 | int trm_icp; | ||
| 78 | int drv_strength; | ||
| 79 | bool dll_on; | ||
| 80 | }; | ||
| 81 | |||
| 82 | static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) | ||
| 83 | { | ||
| 84 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 85 | struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host); | ||
| 86 | int sel50, sel100; | ||
| 87 | u32 mask, val; | ||
| 88 | int ret; | ||
| 89 | |||
| 90 | if (sdhci_am654->dll_on) { | ||
| 91 | regmap_update_bits(sdhci_am654->base, PHY_CTRL1, | ||
| 92 | ENDLL_MASK, 0); | ||
| 93 | |||
| 94 | sdhci_am654->dll_on = false; | ||
| 95 | } | ||
| 96 | |||
| 97 | sdhci_set_clock(host, clock); | ||
| 98 | |||
| 99 | if (clock > CLOCK_TOO_SLOW_HZ) { | ||
| 100 | /* Setup DLL Output TAP delay */ | ||
| 101 | mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; | ||
| 102 | val = (1 << OTAPDLYENA_SHIFT) | | ||
| 103 | (sdhci_am654->otap_del_sel << OTAPDLYSEL_SHIFT); | ||
| 104 | regmap_update_bits(sdhci_am654->base, PHY_CTRL4, | ||
| 105 | mask, val); | ||
| 106 | switch (clock) { | ||
| 107 | case 200000000: | ||
| 108 | sel50 = 0; | ||
| 109 | sel100 = 0; | ||
| 110 | break; | ||
| 111 | case 100000000: | ||
| 112 | sel50 = 0; | ||
| 113 | sel100 = 1; | ||
| 114 | break; | ||
| 115 | default: | ||
| 116 | sel50 = 1; | ||
| 117 | sel100 = 0; | ||
| 118 | } | ||
| 119 | |||
| 120 | /* Configure PHY DLL frequency */ | ||
| 121 | mask = SEL50_MASK | SEL100_MASK; | ||
| 122 | val = (sel50 << SEL50_SHIFT) | (sel100 << SEL100_SHIFT); | ||
| 123 | regmap_update_bits(sdhci_am654->base, PHY_CTRL5, | ||
| 124 | mask, val); | ||
| 125 | /* Configure DLL TRIM */ | ||
| 126 | mask = DLL_TRIM_ICP_MASK; | ||
| 127 | val = sdhci_am654->trm_icp << DLL_TRIM_ICP_SHIFT; | ||
| 128 | |||
| 129 | /* Configure DLL driver strength */ | ||
| 130 | mask |= DR_TY_MASK; | ||
| 131 | val |= sdhci_am654->drv_strength << DR_TY_SHIFT; | ||
| 132 | regmap_update_bits(sdhci_am654->base, PHY_CTRL1, | ||
| 133 | mask, val); | ||
| 134 | /* Enable DLL */ | ||
| 135 | regmap_update_bits(sdhci_am654->base, PHY_CTRL1, | ||
| 136 | ENDLL_MASK, 0x1 << ENDLL_SHIFT); | ||
| 137 | /* | ||
| 138 | * Poll for DLL ready. Use a one second timeout. | ||
| 139 | * Works in all experiments done so far | ||
| 140 | */ | ||
| 141 | ret = regmap_read_poll_timeout(sdhci_am654->base, | ||
| 142 | PHY_STAT1, val, | ||
| 143 | val & DLLRDY_MASK, | ||
| 144 | 1000, 1000000); | ||
| 145 | |||
| 146 | sdhci_am654->dll_on = true; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | static void sdhci_am654_set_power(struct sdhci_host *host, unsigned char mode, | ||
| 151 | unsigned short vdd) | ||
| 152 | { | ||
| 153 | if (!IS_ERR(host->mmc->supply.vmmc)) { | ||
| 154 | struct mmc_host *mmc = host->mmc; | ||
| 155 | |||
| 156 | mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); | ||
| 157 | } | ||
| 158 | sdhci_set_power_noreg(host, mode, vdd); | ||
| 159 | } | ||
| 160 | |||
| 161 | struct sdhci_ops sdhci_am654_ops = { | ||
| 162 | .get_max_clock = sdhci_pltfm_clk_get_max_clock, | ||
| 163 | .get_timeout_clock = sdhci_pltfm_clk_get_max_clock, | ||
| 164 | .set_uhs_signaling = sdhci_set_uhs_signaling, | ||
| 165 | .set_bus_width = sdhci_set_bus_width, | ||
| 166 | .set_power = sdhci_am654_set_power, | ||
| 167 | .set_clock = sdhci_am654_set_clock, | ||
| 168 | .reset = sdhci_reset, | ||
| 169 | }; | ||
| 170 | |||
| 171 | static const struct sdhci_pltfm_data sdhci_am654_pdata = { | ||
| 172 | .ops = &sdhci_am654_ops, | ||
| 173 | .quirks = SDHCI_QUIRK_INVERTED_WRITE_PROTECT | | ||
| 174 | SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12, | ||
| 175 | .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, | ||
| 176 | }; | ||
| 177 | |||
| 178 | static int sdhci_am654_init(struct sdhci_host *host) | ||
| 179 | { | ||
| 180 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 181 | struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host); | ||
| 182 | u32 ctl_cfg_2 = 0; | ||
| 183 | u32 mask; | ||
| 184 | u32 val; | ||
| 185 | int ret; | ||
| 186 | |||
| 187 | /* Reset OTAP to default value */ | ||
| 188 | mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; | ||
| 189 | regmap_update_bits(sdhci_am654->base, PHY_CTRL4, | ||
| 190 | mask, 0x0); | ||
| 191 | |||
| 192 | regmap_read(sdhci_am654->base, PHY_STAT1, &val); | ||
| 193 | if (~val & CALDONE_MASK) { | ||
| 194 | /* Calibrate IO lines */ | ||
| 195 | regmap_update_bits(sdhci_am654->base, PHY_CTRL1, | ||
| 196 | PDB_MASK, PDB_MASK); | ||
| 197 | ret = regmap_read_poll_timeout(sdhci_am654->base, PHY_STAT1, | ||
| 198 | val, val & CALDONE_MASK, 1, 20); | ||
| 199 | if (ret) | ||
| 200 | return ret; | ||
| 201 | } | ||
| 202 | |||
| 203 | /* Enable pins by setting IO mux to 0 */ | ||
| 204 | regmap_update_bits(sdhci_am654->base, PHY_CTRL1, | ||
| 205 | IOMUX_ENABLE_MASK, 0); | ||
| 206 | |||
| 207 | /* Set slot type based on SD or eMMC */ | ||
| 208 | if (host->mmc->caps & MMC_CAP_NONREMOVABLE) | ||
| 209 | ctl_cfg_2 = SLOTTYPE_EMBEDDED; | ||
| 210 | |||
| 211 | regmap_update_bits(sdhci_am654->base, CTL_CFG_2, | ||
| 212 | ctl_cfg_2, SLOTTYPE_MASK); | ||
| 213 | |||
| 214 | return sdhci_add_host(host); | ||
| 215 | } | ||
| 216 | |||
| 217 | static int sdhci_am654_get_of_property(struct platform_device *pdev, | ||
| 218 | struct sdhci_am654_data *sdhci_am654) | ||
| 219 | { | ||
| 220 | struct device *dev = &pdev->dev; | ||
| 221 | int drv_strength; | ||
| 222 | int ret; | ||
| 223 | |||
| 224 | ret = device_property_read_u32(dev, "ti,trm-icp", | ||
| 225 | &sdhci_am654->trm_icp); | ||
| 226 | if (ret) | ||
| 227 | return ret; | ||
| 228 | |||
| 229 | ret = device_property_read_u32(dev, "ti,otap-del-sel", | ||
| 230 | &sdhci_am654->otap_del_sel); | ||
| 231 | if (ret) | ||
| 232 | return ret; | ||
| 233 | |||
| 234 | ret = device_property_read_u32(dev, "ti,driver-strength-ohm", | ||
| 235 | &drv_strength); | ||
| 236 | if (ret) | ||
| 237 | return ret; | ||
| 238 | |||
| 239 | switch (drv_strength) { | ||
| 240 | case 50: | ||
| 241 | sdhci_am654->drv_strength = DRIVER_STRENGTH_50_OHM; | ||
| 242 | break; | ||
| 243 | case 33: | ||
| 244 | sdhci_am654->drv_strength = DRIVER_STRENGTH_33_OHM; | ||
| 245 | break; | ||
| 246 | case 66: | ||
| 247 | sdhci_am654->drv_strength = DRIVER_STRENGTH_66_OHM; | ||
| 248 | break; | ||
| 249 | case 100: | ||
| 250 | sdhci_am654->drv_strength = DRIVER_STRENGTH_100_OHM; | ||
| 251 | break; | ||
| 252 | case 40: | ||
| 253 | sdhci_am654->drv_strength = DRIVER_STRENGTH_40_OHM; | ||
| 254 | break; | ||
| 255 | default: | ||
| 256 | dev_err(dev, "Invalid driver strength\n"); | ||
| 257 | return -EINVAL; | ||
| 258 | } | ||
| 259 | |||
| 260 | sdhci_get_of_property(pdev); | ||
| 261 | |||
| 262 | return 0; | ||
| 263 | } | ||
| 264 | |||
| 265 | static int sdhci_am654_probe(struct platform_device *pdev) | ||
| 266 | { | ||
| 267 | struct sdhci_pltfm_host *pltfm_host; | ||
| 268 | struct sdhci_am654_data *sdhci_am654; | ||
| 269 | struct sdhci_host *host; | ||
| 270 | struct resource *res; | ||
| 271 | struct clk *clk_xin; | ||
| 272 | struct device *dev = &pdev->dev; | ||
| 273 | void __iomem *base; | ||
| 274 | int ret; | ||
| 275 | |||
| 276 | host = sdhci_pltfm_init(pdev, &sdhci_am654_pdata, sizeof(*sdhci_am654)); | ||
| 277 | if (IS_ERR(host)) | ||
| 278 | return PTR_ERR(host); | ||
| 279 | |||
| 280 | pltfm_host = sdhci_priv(host); | ||
| 281 | sdhci_am654 = sdhci_pltfm_priv(pltfm_host); | ||
| 282 | |||
| 283 | clk_xin = devm_clk_get(dev, "clk_xin"); | ||
| 284 | if (IS_ERR(clk_xin)) { | ||
| 285 | dev_err(dev, "clk_xin clock not found.\n"); | ||
| 286 | ret = PTR_ERR(clk_xin); | ||
| 287 | goto err_pltfm_free; | ||
| 288 | } | ||
| 289 | |||
| 290 | pltfm_host->clk = clk_xin; | ||
| 291 | |||
| 292 | /* Clocks are enabled using pm_runtime */ | ||
| 293 | pm_runtime_enable(dev); | ||
| 294 | ret = pm_runtime_get_sync(dev); | ||
| 295 | if (ret < 0) { | ||
| 296 | pm_runtime_put_noidle(dev); | ||
| 297 | goto pm_runtime_disable; | ||
| 298 | } | ||
| 299 | |||
| 300 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 301 | base = devm_ioremap_resource(dev, res); | ||
| 302 | if (IS_ERR(base)) { | ||
| 303 | ret = PTR_ERR(base); | ||
| 304 | goto pm_runtime_put; | ||
| 305 | } | ||
| 306 | |||
| 307 | sdhci_am654->base = devm_regmap_init_mmio(dev, base, | ||
| 308 | &sdhci_am654_regmap_config); | ||
| 309 | if (IS_ERR(sdhci_am654->base)) { | ||
| 310 | dev_err(dev, "Failed to initialize regmap\n"); | ||
| 311 | ret = PTR_ERR(sdhci_am654->base); | ||
| 312 | goto pm_runtime_put; | ||
| 313 | } | ||
| 314 | |||
| 315 | ret = sdhci_am654_get_of_property(pdev, sdhci_am654); | ||
| 316 | if (ret) | ||
| 317 | goto pm_runtime_put; | ||
| 318 | |||
| 319 | ret = mmc_of_parse(host->mmc); | ||
| 320 | if (ret) { | ||
| 321 | dev_err(dev, "parsing dt failed (%d)\n", ret); | ||
| 322 | goto pm_runtime_put; | ||
| 323 | } | ||
| 324 | |||
| 325 | ret = sdhci_am654_init(host); | ||
| 326 | if (ret) | ||
| 327 | goto pm_runtime_put; | ||
| 328 | |||
| 329 | return 0; | ||
| 330 | |||
| 331 | pm_runtime_put: | ||
| 332 | pm_runtime_put_sync(dev); | ||
| 333 | pm_runtime_disable: | ||
| 334 | pm_runtime_disable(dev); | ||
| 335 | err_pltfm_free: | ||
| 336 | sdhci_pltfm_free(pdev); | ||
| 337 | return ret; | ||
| 338 | } | ||
| 339 | |||
| 340 | static int sdhci_am654_remove(struct platform_device *pdev) | ||
| 341 | { | ||
| 342 | struct sdhci_host *host = platform_get_drvdata(pdev); | ||
| 343 | int ret; | ||
| 344 | |||
| 345 | sdhci_remove_host(host, true); | ||
| 346 | ret = pm_runtime_put_sync(&pdev->dev); | ||
| 347 | if (ret < 0) | ||
| 348 | return ret; | ||
| 349 | |||
| 350 | pm_runtime_disable(&pdev->dev); | ||
| 351 | sdhci_pltfm_free(pdev); | ||
| 352 | |||
| 353 | return 0; | ||
| 354 | } | ||
| 355 | |||
| 356 | static const struct of_device_id sdhci_am654_of_match[] = { | ||
| 357 | { .compatible = "ti,am654-sdhci-5.1" }, | ||
| 358 | { /* sentinel */ } | ||
| 359 | }; | ||
| 360 | |||
| 361 | static struct platform_driver sdhci_am654_driver = { | ||
| 362 | .driver = { | ||
| 363 | .name = "sdhci-am654", | ||
| 364 | .of_match_table = sdhci_am654_of_match, | ||
| 365 | }, | ||
| 366 | .probe = sdhci_am654_probe, | ||
| 367 | .remove = sdhci_am654_remove, | ||
| 368 | }; | ||
| 369 | |||
| 370 | module_platform_driver(sdhci_am654_driver); | ||
| 371 | |||
| 372 | MODULE_DESCRIPTION("Driver for SDHCI Controller on TI's AM654 devices"); | ||
| 373 | MODULE_AUTHOR("Faiz Abbas <faiz_abbas@ti.com>"); | ||
| 374 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 1e317027bf53..c03529e3f01a 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h | |||
| @@ -70,6 +70,7 @@ | |||
| 70 | #define TMIO_STAT_DAT0 BIT(23) /* only known on R-Car so far */ | 70 | #define TMIO_STAT_DAT0 BIT(23) /* only known on R-Car so far */ |
| 71 | #define TMIO_STAT_RXRDY BIT(24) | 71 | #define TMIO_STAT_RXRDY BIT(24) |
| 72 | #define TMIO_STAT_TXRQ BIT(25) | 72 | #define TMIO_STAT_TXRQ BIT(25) |
| 73 | #define TMIO_STAT_ALWAYS_SET_27 BIT(27) /* only known on R-Car 2+ so far */ | ||
| 73 | #define TMIO_STAT_ILL_FUNC BIT(29) /* only when !TMIO_MMC_HAS_IDLE_WAIT */ | 74 | #define TMIO_STAT_ILL_FUNC BIT(29) /* only when !TMIO_MMC_HAS_IDLE_WAIT */ |
| 74 | #define TMIO_STAT_SCLKDIVEN BIT(29) /* only when TMIO_MMC_HAS_IDLE_WAIT */ | 75 | #define TMIO_STAT_SCLKDIVEN BIT(29) /* only when TMIO_MMC_HAS_IDLE_WAIT */ |
| 75 | #define TMIO_STAT_CMD_BUSY BIT(30) | 76 | #define TMIO_STAT_CMD_BUSY BIT(30) |
| @@ -96,6 +97,7 @@ | |||
| 96 | 97 | ||
| 97 | /* Define some IRQ masks */ | 98 | /* Define some IRQ masks */ |
| 98 | /* This is the mask used at reset by the chip */ | 99 | /* This is the mask used at reset by the chip */ |
| 100 | #define TMIO_MASK_INIT_RCAR2 0x8b7f031d /* Initial value for R-Car Gen2+ */ | ||
| 99 | #define TMIO_MASK_ALL 0x837f031d | 101 | #define TMIO_MASK_ALL 0x837f031d |
| 100 | #define TMIO_MASK_READOP (TMIO_STAT_RXRDY | TMIO_STAT_DATAEND) | 102 | #define TMIO_MASK_READOP (TMIO_STAT_RXRDY | TMIO_STAT_DATAEND) |
| 101 | #define TMIO_MASK_WRITEOP (TMIO_STAT_TXRQ | TMIO_STAT_DATAEND) | 103 | #define TMIO_MASK_WRITEOP (TMIO_STAT_TXRQ | TMIO_STAT_DATAEND) |
| @@ -153,6 +155,7 @@ struct tmio_mmc_host { | |||
| 153 | u32 sdcard_irq_mask; | 155 | u32 sdcard_irq_mask; |
| 154 | u32 sdio_irq_mask; | 156 | u32 sdio_irq_mask; |
| 155 | unsigned int clk_cache; | 157 | unsigned int clk_cache; |
| 158 | u32 sdcard_irq_setbit_mask; | ||
| 156 | 159 | ||
| 157 | spinlock_t lock; /* protect host private data */ | 160 | spinlock_t lock; /* protect host private data */ |
| 158 | unsigned long last_req_ts; | 161 | unsigned long last_req_ts; |
| @@ -267,6 +270,9 @@ static inline void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr, | |||
| 267 | static inline void sd_ctrl_write32_as_16_and_16(struct tmio_mmc_host *host, | 270 | static inline void sd_ctrl_write32_as_16_and_16(struct tmio_mmc_host *host, |
| 268 | int addr, u32 val) | 271 | int addr, u32 val) |
| 269 | { | 272 | { |
| 273 | if (addr == CTL_IRQ_MASK || addr == CTL_STATUS) | ||
| 274 | val |= host->sdcard_irq_setbit_mask; | ||
| 275 | |||
| 270 | iowrite16(val & 0xffff, host->ctl + (addr << host->bus_shift)); | 276 | iowrite16(val & 0xffff, host->ctl + (addr << host->bus_shift)); |
| 271 | iowrite16(val >> 16, host->ctl + ((addr + 2) << host->bus_shift)); | 277 | iowrite16(val >> 16, host->ctl + ((addr + 2) << host->bus_shift)); |
| 272 | } | 278 | } |
diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index 8d64f6196f33..085a0fab769c 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c | |||
| @@ -171,6 +171,18 @@ static void tmio_mmc_reset(struct tmio_mmc_host *host) | |||
| 171 | } | 171 | } |
| 172 | } | 172 | } |
| 173 | 173 | ||
| 174 | static void tmio_mmc_hw_reset(struct mmc_host *mmc) | ||
| 175 | { | ||
| 176 | struct tmio_mmc_host *host = mmc_priv(mmc); | ||
| 177 | |||
| 178 | host->reset(host); | ||
| 179 | |||
| 180 | tmio_mmc_abort_dma(host); | ||
| 181 | |||
| 182 | if (host->hw_reset) | ||
| 183 | host->hw_reset(host); | ||
| 184 | } | ||
| 185 | |||
| 174 | static void tmio_mmc_reset_work(struct work_struct *work) | 186 | static void tmio_mmc_reset_work(struct work_struct *work) |
| 175 | { | 187 | { |
| 176 | struct tmio_mmc_host *host = container_of(work, struct tmio_mmc_host, | 188 | struct tmio_mmc_host *host = container_of(work, struct tmio_mmc_host, |
| @@ -209,12 +221,11 @@ static void tmio_mmc_reset_work(struct work_struct *work) | |||
| 209 | 221 | ||
| 210 | spin_unlock_irqrestore(&host->lock, flags); | 222 | spin_unlock_irqrestore(&host->lock, flags); |
| 211 | 223 | ||
| 212 | host->reset(host); | 224 | tmio_mmc_hw_reset(host->mmc); |
| 213 | 225 | ||
| 214 | /* Ready for new calls */ | 226 | /* Ready for new calls */ |
| 215 | host->mrq = NULL; | 227 | host->mrq = NULL; |
| 216 | 228 | ||
| 217 | tmio_mmc_abort_dma(host); | ||
| 218 | mmc_request_done(host->mmc, mrq); | 229 | mmc_request_done(host->mmc, mrq); |
| 219 | } | 230 | } |
| 220 | 231 | ||
| @@ -696,14 +707,6 @@ static int tmio_mmc_start_data(struct tmio_mmc_host *host, | |||
| 696 | return 0; | 707 | return 0; |
| 697 | } | 708 | } |
| 698 | 709 | ||
| 699 | static void tmio_mmc_hw_reset(struct mmc_host *mmc) | ||
| 700 | { | ||
| 701 | struct tmio_mmc_host *host = mmc_priv(mmc); | ||
| 702 | |||
| 703 | if (host->hw_reset) | ||
| 704 | host->hw_reset(host); | ||
| 705 | } | ||
| 706 | |||
| 707 | static int tmio_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode) | 710 | static int tmio_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode) |
| 708 | { | 711 | { |
| 709 | struct tmio_mmc_host *host = mmc_priv(mmc); | 712 | struct tmio_mmc_host *host = mmc_priv(mmc); |
| @@ -734,8 +737,6 @@ static int tmio_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
| 734 | ret = mmc_send_tuning(mmc, opcode, NULL); | 737 | ret = mmc_send_tuning(mmc, opcode, NULL); |
| 735 | if (ret == 0) | 738 | if (ret == 0) |
| 736 | set_bit(i, host->taps); | 739 | set_bit(i, host->taps); |
| 737 | |||
| 738 | usleep_range(1000, 1200); | ||
| 739 | } | 740 | } |
| 740 | 741 | ||
| 741 | ret = host->select_tuning(host); | 742 | ret = host->select_tuning(host); |
| @@ -1167,11 +1168,13 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host) | |||
| 1167 | if (ret < 0) | 1168 | if (ret < 0) |
| 1168 | return ret; | 1169 | return ret; |
| 1169 | 1170 | ||
| 1170 | if (pdata->flags & TMIO_MMC_USE_GPIO_CD) { | 1171 | /* |
| 1171 | ret = mmc_gpio_request_cd(mmc, pdata->cd_gpio, 0); | 1172 | * Look for a card detect GPIO, if it fails with anything |
| 1172 | if (ret) | 1173 | * else than a probe deferral, just live without it. |
| 1173 | return ret; | 1174 | */ |
| 1174 | } | 1175 | ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0, NULL); |
| 1176 | if (ret == -EPROBE_DEFER) | ||
| 1177 | return ret; | ||
| 1175 | 1178 | ||
| 1176 | mmc->caps |= MMC_CAP_4_BIT_DATA | pdata->capabilities; | 1179 | mmc->caps |= MMC_CAP_4_BIT_DATA | pdata->capabilities; |
| 1177 | mmc->caps2 |= pdata->capabilities2; | 1180 | mmc->caps2 |= pdata->capabilities2; |
| @@ -1228,7 +1231,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host) | |||
| 1228 | _host->sdio_irq_mask = TMIO_SDIO_MASK_ALL; | 1231 | _host->sdio_irq_mask = TMIO_SDIO_MASK_ALL; |
| 1229 | 1232 | ||
| 1230 | _host->set_clock(_host, 0); | 1233 | _host->set_clock(_host, 0); |
| 1231 | _host->reset(_host); | 1234 | tmio_mmc_hw_reset(mmc); |
| 1232 | 1235 | ||
| 1233 | _host->sdcard_irq_mask = sd_ctrl_read16_and_16_as_32(_host, CTL_IRQ_MASK); | 1236 | _host->sdcard_irq_mask = sd_ctrl_read16_and_16_as_32(_host, CTL_IRQ_MASK); |
| 1234 | tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL); | 1237 | tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL); |
| @@ -1328,8 +1331,8 @@ int tmio_mmc_host_runtime_resume(struct device *dev) | |||
| 1328 | { | 1331 | { |
| 1329 | struct tmio_mmc_host *host = dev_get_drvdata(dev); | 1332 | struct tmio_mmc_host *host = dev_get_drvdata(dev); |
| 1330 | 1333 | ||
| 1331 | host->reset(host); | ||
| 1332 | tmio_mmc_clk_enable(host); | 1334 | tmio_mmc_clk_enable(host); |
| 1335 | tmio_mmc_hw_reset(host->mmc); | ||
| 1333 | 1336 | ||
| 1334 | if (host->clk_cache) | 1337 | if (host->clk_cache) |
| 1335 | host->set_clock(host, host->clk_cache); | 1338 | host->set_clock(host, host->clk_cache); |
