aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sdhci-esdhc-imx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/sdhci-esdhc-imx.c')
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c210
1 files changed, 104 insertions, 106 deletions
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index faf0cb910c96..c6b9f6492e1a 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -581,13 +581,8 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
581static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host) 581static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host)
582{ 582{
583 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 583 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
584 struct pltfm_imx_data *imx_data = pltfm_host->priv;
585 struct esdhc_platform_data *boarddata = &imx_data->boarddata;
586 584
587 if (boarddata->f_max && (boarddata->f_max < pltfm_host->clock)) 585 return pltfm_host->clock;
588 return boarddata->f_max;
589 else
590 return pltfm_host->clock;
591} 586}
592 587
593static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host) 588static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
@@ -878,34 +873,19 @@ static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
878static int 873static int
879sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, 874sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
880 struct sdhci_host *host, 875 struct sdhci_host *host,
881 struct esdhc_platform_data *boarddata) 876 struct pltfm_imx_data *imx_data)
882{ 877{
883 struct device_node *np = pdev->dev.of_node; 878 struct device_node *np = pdev->dev.of_node;
884 879 struct esdhc_platform_data *boarddata = &imx_data->boarddata;
885 if (!np) 880 int ret;
886 return -ENODEV;
887
888 if (of_get_property(np, "non-removable", NULL))
889 boarddata->cd_type = ESDHC_CD_PERMANENT;
890
891 if (of_get_property(np, "fsl,cd-controller", NULL))
892 boarddata->cd_type = ESDHC_CD_CONTROLLER;
893 881
894 if (of_get_property(np, "fsl,wp-controller", NULL)) 882 if (of_get_property(np, "fsl,wp-controller", NULL))
895 boarddata->wp_type = ESDHC_WP_CONTROLLER; 883 boarddata->wp_type = ESDHC_WP_CONTROLLER;
896 884
897 boarddata->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
898 if (gpio_is_valid(boarddata->cd_gpio))
899 boarddata->cd_type = ESDHC_CD_GPIO;
900
901 boarddata->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0); 885 boarddata->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
902 if (gpio_is_valid(boarddata->wp_gpio)) 886 if (gpio_is_valid(boarddata->wp_gpio))
903 boarddata->wp_type = ESDHC_WP_GPIO; 887 boarddata->wp_type = ESDHC_WP_GPIO;
904 888
905 of_property_read_u32(np, "bus-width", &boarddata->max_bus_width);
906
907 of_property_read_u32(np, "max-frequency", &boarddata->f_max);
908
909 if (of_find_property(np, "no-1-8-v", NULL)) 889 if (of_find_property(np, "no-1-8-v", NULL))
910 boarddata->support_vsel = false; 890 boarddata->support_vsel = false;
911 else 891 else
@@ -916,29 +896,119 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
916 896
917 mmc_of_parse_voltage(np, &host->ocr_mask); 897 mmc_of_parse_voltage(np, &host->ocr_mask);
918 898
899 /* sdr50 and sdr104 needs work on 1.8v signal voltage */
900 if ((boarddata->support_vsel) && esdhc_is_usdhc(imx_data) &&
901 !IS_ERR(imx_data->pins_default)) {
902 imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl,
903 ESDHC_PINCTRL_STATE_100MHZ);
904 imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl,
905 ESDHC_PINCTRL_STATE_200MHZ);
906 if (IS_ERR(imx_data->pins_100mhz) ||
907 IS_ERR(imx_data->pins_200mhz)) {
908 dev_warn(mmc_dev(host->mmc),
909 "could not get ultra high speed state, work on normal mode\n");
910 /*
911 * fall back to not support uhs by specify no 1.8v quirk
912 */
913 host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
914 }
915 } else {
916 host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
917 }
918
919 /* call to generic mmc_of_parse to support additional capabilities */ 919 /* call to generic mmc_of_parse to support additional capabilities */
920 return mmc_of_parse(host->mmc); 920 ret = mmc_of_parse(host->mmc);
921 if (ret)
922 return ret;
923
924 if (!IS_ERR_VALUE(mmc_gpio_get_cd(host->mmc)))
925 host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
926
927 return 0;
921} 928}
922#else 929#else
923static inline int 930static inline int
924sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, 931sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
925 struct sdhci_host *host, 932 struct sdhci_host *host,
926 struct esdhc_platform_data *boarddata) 933 struct pltfm_imx_data *imx_data)
927{ 934{
928 return -ENODEV; 935 return -ENODEV;
929} 936}
930#endif 937#endif
931 938
939static int sdhci_esdhc_imx_probe_nondt(struct platform_device *pdev,
940 struct sdhci_host *host,
941 struct pltfm_imx_data *imx_data)
942{
943 struct esdhc_platform_data *boarddata = &imx_data->boarddata;
944 int err;
945
946 if (!host->mmc->parent->platform_data) {
947 dev_err(mmc_dev(host->mmc), "no board data!\n");
948 return -EINVAL;
949 }
950
951 imx_data->boarddata = *((struct esdhc_platform_data *)
952 host->mmc->parent->platform_data);
953 /* write_protect */
954 if (boarddata->wp_type == ESDHC_WP_GPIO) {
955 err = mmc_gpio_request_ro(host->mmc, boarddata->wp_gpio);
956 if (err) {
957 dev_err(mmc_dev(host->mmc),
958 "failed to request write-protect gpio!\n");
959 return err;
960 }
961 host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
962 }
963
964 /* card_detect */
965 switch (boarddata->cd_type) {
966 case ESDHC_CD_GPIO:
967 err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio, 0);
968 if (err) {
969 dev_err(mmc_dev(host->mmc),
970 "failed to request card-detect gpio!\n");
971 return err;
972 }
973 /* fall through */
974
975 case ESDHC_CD_CONTROLLER:
976 /* we have a working card_detect back */
977 host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
978 break;
979
980 case ESDHC_CD_PERMANENT:
981 host->mmc->caps |= MMC_CAP_NONREMOVABLE;
982 break;
983
984 case ESDHC_CD_NONE:
985 break;
986 }
987
988 switch (boarddata->max_bus_width) {
989 case 8:
990 host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA;
991 break;
992 case 4:
993 host->mmc->caps |= MMC_CAP_4_BIT_DATA;
994 break;
995 case 1:
996 default:
997 host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
998 break;
999 }
1000
1001 return 0;
1002}
1003
932static int sdhci_esdhc_imx_probe(struct platform_device *pdev) 1004static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
933{ 1005{
934 const struct of_device_id *of_id = 1006 const struct of_device_id *of_id =
935 of_match_device(imx_esdhc_dt_ids, &pdev->dev); 1007 of_match_device(imx_esdhc_dt_ids, &pdev->dev);
936 struct sdhci_pltfm_host *pltfm_host; 1008 struct sdhci_pltfm_host *pltfm_host;
937 struct sdhci_host *host; 1009 struct sdhci_host *host;
938 struct esdhc_platform_data *boarddata;
939 int err; 1010 int err;
940 struct pltfm_imx_data *imx_data; 1011 struct pltfm_imx_data *imx_data;
941 bool dt = true;
942 1012
943 host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata, 0); 1013 host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata, 0);
944 if (IS_ERR(host)) 1014 if (IS_ERR(host))
@@ -1030,84 +1100,12 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
1030 if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536) 1100 if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536)
1031 host->quirks |= SDHCI_QUIRK_BROKEN_ADMA; 1101 host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
1032 1102
1033 boarddata = &imx_data->boarddata; 1103 if (of_id)
1034 if (sdhci_esdhc_imx_probe_dt(pdev, host, boarddata) < 0) { 1104 err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data);
1035 if (!host->mmc->parent->platform_data) { 1105 else
1036 dev_err(mmc_dev(host->mmc), "no board data!\n"); 1106 err = sdhci_esdhc_imx_probe_nondt(pdev, host, imx_data);
1037 err = -EINVAL; 1107 if (err)
1038 goto disable_clk; 1108 goto disable_clk;
1039 }
1040 imx_data->boarddata = *((struct esdhc_platform_data *)
1041 host->mmc->parent->platform_data);
1042 dt = false;
1043 }
1044 /* write_protect */
1045 if (boarddata->wp_type == ESDHC_WP_GPIO && !dt) {
1046 err = mmc_gpio_request_ro(host->mmc, boarddata->wp_gpio);
1047 if (err) {
1048 dev_err(mmc_dev(host->mmc),
1049 "failed to request write-protect gpio!\n");
1050 goto disable_clk;
1051 }
1052 host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
1053 }
1054
1055 /* card_detect */
1056 switch (boarddata->cd_type) {
1057 case ESDHC_CD_GPIO:
1058 if (dt)
1059 break;
1060 err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio, 0);
1061 if (err) {
1062 dev_err(mmc_dev(host->mmc),
1063 "failed to request card-detect gpio!\n");
1064 goto disable_clk;
1065 }
1066 /* fall through */
1067
1068 case ESDHC_CD_CONTROLLER:
1069 /* we have a working card_detect back */
1070 host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
1071 break;
1072
1073 case ESDHC_CD_PERMANENT:
1074 host->mmc->caps |= MMC_CAP_NONREMOVABLE;
1075 break;
1076
1077 case ESDHC_CD_NONE:
1078 break;
1079 }
1080
1081 switch (boarddata->max_bus_width) {
1082 case 8:
1083 host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA;
1084 break;
1085 case 4:
1086 host->mmc->caps |= MMC_CAP_4_BIT_DATA;
1087 break;
1088 case 1:
1089 default:
1090 host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
1091 break;
1092 }
1093
1094 /* sdr50 and sdr104 needs work on 1.8v signal voltage */
1095 if ((boarddata->support_vsel) && esdhc_is_usdhc(imx_data) &&
1096 !IS_ERR(imx_data->pins_default)) {
1097 imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl,
1098 ESDHC_PINCTRL_STATE_100MHZ);
1099 imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl,
1100 ESDHC_PINCTRL_STATE_200MHZ);
1101 if (IS_ERR(imx_data->pins_100mhz) ||
1102 IS_ERR(imx_data->pins_200mhz)) {
1103 dev_warn(mmc_dev(host->mmc),
1104 "could not get ultra high speed state, work on normal mode\n");
1105 /* fall back to not support uhs by specify no 1.8v quirk */
1106 host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
1107 }
1108 } else {
1109 host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
1110 }
1111 1109
1112 err = sdhci_add_host(host); 1110 err = sdhci_add_host(host);
1113 if (err) 1111 if (err)