aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKishon Vijay Abraham I <kishon@ti.com>2018-02-05 07:50:19 -0500
committerUlf Hansson <ulf.hansson@linaro.org>2018-03-05 03:00:58 -0500
commit8d20b2eae6c47b09552364afa20511aa43f2367c (patch)
tree7bab335c864c71c4a149e782ccd3d804f53a367a
parent7d33c3581536b8193b9788a63a68e7bfc22cdc31 (diff)
mmc: sdhci_omap: Add support to set IODELAY values
The data manual of J6/J6 Eco recommends to set different IODELAY values depending on the mode in which the MMC/SD is enumerated in order to ensure IO timings are met. Add support to set the IODELAY values depending on the various MMC modes using the pinctrl APIs. Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/mmc/host/sdhci-omap.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c
index e24ae903f7ba..428849387992 100644
--- a/drivers/mmc/host/sdhci-omap.c
+++ b/drivers/mmc/host/sdhci-omap.c
@@ -25,6 +25,7 @@
25#include <linux/platform_device.h> 25#include <linux/platform_device.h>
26#include <linux/pm_runtime.h> 26#include <linux/pm_runtime.h>
27#include <linux/regulator/consumer.h> 27#include <linux/regulator/consumer.h>
28#include <linux/pinctrl/consumer.h>
28 29
29#include "sdhci-pltfm.h" 30#include "sdhci-pltfm.h"
30 31
@@ -90,8 +91,12 @@
90 91
91#define MAX_PHASE_DELAY 0x7C 92#define MAX_PHASE_DELAY 0x7C
92 93
94/* sdhci-omap controller flags */
95#define SDHCI_OMAP_REQUIRE_IODELAY BIT(0)
96
93struct sdhci_omap_data { 97struct sdhci_omap_data {
94 u32 offset; 98 u32 offset;
99 u8 flags;
95}; 100};
96 101
97struct sdhci_omap_host { 102struct sdhci_omap_host {
@@ -102,8 +107,16 @@ struct sdhci_omap_host {
102 struct sdhci_host *host; 107 struct sdhci_host *host;
103 u8 bus_mode; 108 u8 bus_mode;
104 u8 power_mode; 109 u8 power_mode;
110 u8 timing;
111 u8 flags;
112
113 struct pinctrl *pinctrl;
114 struct pinctrl_state **pinctrl_state;
105}; 115};
106 116
117static void sdhci_omap_start_clock(struct sdhci_omap_host *omap_host);
118static void sdhci_omap_stop_clock(struct sdhci_omap_host *omap_host);
119
107static inline u32 sdhci_omap_readl(struct sdhci_omap_host *host, 120static inline u32 sdhci_omap_readl(struct sdhci_omap_host *host,
108 unsigned int offset) 121 unsigned int offset)
109{ 122{
@@ -436,6 +449,31 @@ static int sdhci_omap_start_signal_voltage_switch(struct mmc_host *mmc,
436 return 0; 449 return 0;
437} 450}
438 451
452static void sdhci_omap_set_timing(struct sdhci_omap_host *omap_host, u8 timing)
453{
454 int ret;
455 struct pinctrl_state *pinctrl_state;
456 struct device *dev = omap_host->dev;
457
458 if (!(omap_host->flags & SDHCI_OMAP_REQUIRE_IODELAY))
459 return;
460
461 if (omap_host->timing == timing)
462 return;
463
464 sdhci_omap_stop_clock(omap_host);
465
466 pinctrl_state = omap_host->pinctrl_state[timing];
467 ret = pinctrl_select_state(omap_host->pinctrl, pinctrl_state);
468 if (ret) {
469 dev_err(dev, "failed to select pinctrl state\n");
470 return;
471 }
472
473 sdhci_omap_start_clock(omap_host);
474 omap_host->timing = timing;
475}
476
439static void sdhci_omap_set_power_mode(struct sdhci_omap_host *omap_host, 477static void sdhci_omap_set_power_mode(struct sdhci_omap_host *omap_host,
440 u8 power_mode) 478 u8 power_mode)
441{ 479{
@@ -472,6 +510,7 @@ static void sdhci_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
472 omap_host = sdhci_pltfm_priv(pltfm_host); 510 omap_host = sdhci_pltfm_priv(pltfm_host);
473 511
474 sdhci_omap_set_bus_mode(omap_host, ios->bus_mode); 512 sdhci_omap_set_bus_mode(omap_host, ios->bus_mode);
513 sdhci_omap_set_timing(omap_host, ios->timing);
475 sdhci_set_ios(mmc, ios); 514 sdhci_set_ios(mmc, ios);
476 sdhci_omap_set_power_mode(omap_host, ios->power_mode); 515 sdhci_omap_set_power_mode(omap_host, ios->power_mode);
477} 516}
@@ -680,6 +719,7 @@ static const struct sdhci_pltfm_data sdhci_omap_pdata = {
680 719
681static const struct sdhci_omap_data dra7_data = { 720static const struct sdhci_omap_data dra7_data = {
682 .offset = 0x200, 721 .offset = 0x200,
722 .flags = SDHCI_OMAP_REQUIRE_IODELAY,
683}; 723};
684 724
685static const struct of_device_id omap_sdhci_match[] = { 725static const struct of_device_id omap_sdhci_match[] = {
@@ -688,6 +728,108 @@ static const struct of_device_id omap_sdhci_match[] = {
688}; 728};
689MODULE_DEVICE_TABLE(of, omap_sdhci_match); 729MODULE_DEVICE_TABLE(of, omap_sdhci_match);
690 730
731static struct pinctrl_state
732*sdhci_omap_iodelay_pinctrl_state(struct sdhci_omap_host *omap_host, char *mode,
733 u32 *caps, u32 capmask)
734{
735 struct device *dev = omap_host->dev;
736 struct pinctrl_state *pinctrl_state = ERR_PTR(-ENODEV);
737
738 if (!(*caps & capmask))
739 goto ret;
740
741 pinctrl_state = pinctrl_lookup_state(omap_host->pinctrl, mode);
742 if (IS_ERR(pinctrl_state)) {
743 dev_err(dev, "no pinctrl state for %s mode", mode);
744 *caps &= ~capmask;
745 }
746
747ret:
748 return pinctrl_state;
749}
750
751static int sdhci_omap_config_iodelay_pinctrl_state(struct sdhci_omap_host
752 *omap_host)
753{
754 struct device *dev = omap_host->dev;
755 struct sdhci_host *host = omap_host->host;
756 struct mmc_host *mmc = host->mmc;
757 u32 *caps = &mmc->caps;
758 u32 *caps2 = &mmc->caps2;
759 struct pinctrl_state *state;
760 struct pinctrl_state **pinctrl_state;
761
762 if (!(omap_host->flags & SDHCI_OMAP_REQUIRE_IODELAY))
763 return 0;
764
765 pinctrl_state = devm_kzalloc(dev, sizeof(*pinctrl_state) *
766 (MMC_TIMING_MMC_HS200 + 1), GFP_KERNEL);
767 if (!pinctrl_state)
768 return -ENOMEM;
769
770 omap_host->pinctrl = devm_pinctrl_get(omap_host->dev);
771 if (IS_ERR(omap_host->pinctrl)) {
772 dev_err(dev, "Cannot get pinctrl\n");
773 return PTR_ERR(omap_host->pinctrl);
774 }
775
776 state = pinctrl_lookup_state(omap_host->pinctrl, "default");
777 if (IS_ERR(state)) {
778 dev_err(dev, "no pinctrl state for default mode\n");
779 return PTR_ERR(state);
780 }
781 pinctrl_state[MMC_TIMING_LEGACY] = state;
782
783 state = sdhci_omap_iodelay_pinctrl_state(omap_host, "sdr104", caps,
784 MMC_CAP_UHS_SDR104);
785 if (!IS_ERR(state))
786 pinctrl_state[MMC_TIMING_UHS_SDR104] = state;
787
788 state = sdhci_omap_iodelay_pinctrl_state(omap_host, "ddr50", caps,
789 MMC_CAP_UHS_DDR50);
790 if (!IS_ERR(state))
791 pinctrl_state[MMC_TIMING_UHS_DDR50] = state;
792
793 state = sdhci_omap_iodelay_pinctrl_state(omap_host, "sdr50", caps,
794 MMC_CAP_UHS_SDR50);
795 if (!IS_ERR(state))
796 pinctrl_state[MMC_TIMING_UHS_SDR50] = state;
797
798 state = sdhci_omap_iodelay_pinctrl_state(omap_host, "sdr25", caps,
799 MMC_CAP_UHS_SDR25);
800 if (!IS_ERR(state))
801 pinctrl_state[MMC_TIMING_UHS_SDR25] = state;
802
803 state = sdhci_omap_iodelay_pinctrl_state(omap_host, "sdr12", caps,
804 MMC_CAP_UHS_SDR12);
805 if (!IS_ERR(state))
806 pinctrl_state[MMC_TIMING_UHS_SDR12] = state;
807
808 state = sdhci_omap_iodelay_pinctrl_state(omap_host, "ddr_1_8v", caps,
809 MMC_CAP_1_8V_DDR);
810 if (!IS_ERR(state))
811 pinctrl_state[MMC_TIMING_MMC_DDR52] = state;
812
813 state = sdhci_omap_iodelay_pinctrl_state(omap_host, "hs", caps,
814 MMC_CAP_SD_HIGHSPEED);
815 if (!IS_ERR(state))
816 pinctrl_state[MMC_TIMING_SD_HS] = state;
817
818 state = sdhci_omap_iodelay_pinctrl_state(omap_host, "hs", caps,
819 MMC_CAP_MMC_HIGHSPEED);
820 if (!IS_ERR(state))
821 pinctrl_state[MMC_TIMING_MMC_HS] = state;
822
823 state = sdhci_omap_iodelay_pinctrl_state(omap_host, "hs200_1_8v", caps2,
824 MMC_CAP2_HS200_1_8V_SDR);
825 if (!IS_ERR(state))
826 pinctrl_state[MMC_TIMING_MMC_HS200] = state;
827
828 omap_host->pinctrl_state = pinctrl_state;
829
830 return 0;
831}
832
691static int sdhci_omap_probe(struct platform_device *pdev) 833static int sdhci_omap_probe(struct platform_device *pdev)
692{ 834{
693 int ret; 835 int ret;
@@ -724,6 +866,8 @@ static int sdhci_omap_probe(struct platform_device *pdev)
724 omap_host->base = host->ioaddr; 866 omap_host->base = host->ioaddr;
725 omap_host->dev = dev; 867 omap_host->dev = dev;
726 omap_host->power_mode = MMC_POWER_UNDEFINED; 868 omap_host->power_mode = MMC_POWER_UNDEFINED;
869 omap_host->timing = MMC_TIMING_LEGACY;
870 omap_host->flags = data->flags;
727 host->ioaddr += offset; 871 host->ioaddr += offset;
728 872
729 mmc = host->mmc; 873 mmc = host->mmc;
@@ -772,6 +916,10 @@ static int sdhci_omap_probe(struct platform_device *pdev)
772 goto err_put_sync; 916 goto err_put_sync;
773 } 917 }
774 918
919 ret = sdhci_omap_config_iodelay_pinctrl_state(omap_host);
920 if (ret)
921 goto err_put_sync;
922
775 host->mmc_host_ops.get_ro = mmc_gpio_get_ro; 923 host->mmc_host_ops.get_ro = mmc_gpio_get_ro;
776 host->mmc_host_ops.start_signal_voltage_switch = 924 host->mmc_host_ops.start_signal_voltage_switch =
777 sdhci_omap_start_signal_voltage_switch; 925 sdhci_omap_start_signal_voltage_switch;