From abbc58b0aaae92e2608d80d76c9bec052705abae Mon Sep 17 00:00:00 2001 From: Sujit Reddy Thumma Date: Wed, 30 May 2012 13:04:34 +0530 Subject: [PATCH] arm/dt: msm8974: add support for SD/eMMC bus speed modes SDC1 supports following bus speed modes: - HS200 at 1.8V - DDR at 1.8V SDC2 supports following bus speed modes: - SDR12, SDR25, SDR50, SDR104, DDR50 Change-Id: I648435fc00f6b11634cb3d0c41106ecb0868143f Signed-off-by: Sujit Reddy Thumma --- .../devicetree/bindings/mmc/msm_sdcc.txt | 4 +- arch/arm/boot/dts/msm8974.dtsi | 7 ++- arch/arm/include/asm/mach/mmc.h | 2 + drivers/mmc/host/msm_sdcc.c | 55 ++++++++++++++++--- 4 files changed, 58 insertions(+), 10 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt index 5712aa2081c..35ac0ec60ca 100644 --- a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt +++ b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt @@ -23,7 +23,9 @@ Optional Properties: - qcom,sdcc-nonremovable - specifies whether the card in slot is hot pluggable or hard wired. - qcom,sdcc-disable_cmd23 - disable sending CMD23 to card when controller can't support it. - - qcom,sdcc-hs200 - enable eMMC4.5 HS200 bus speed mode + - qcom,sdcc-bus-speed-mode - specifies supported bus speed modes by host. + - qcom,sdcc-current-limit - specifies max. current the host can drive. + - qcom,sdcc-xpc - specifies if the host can supply more than 150mA for SDXC cards. In the following, can be vdd (flash core voltage) or vdd-io (I/O voltage). - qcom,sdcc--always_on - specifies whether supply should be kept "on" always. diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi index 68f96db6328..2c19a8088cb 100644 --- a/arch/arm/boot/dts/msm8974.dtsi +++ b/arch/arm/boot/dts/msm8974.dtsi @@ -96,8 +96,8 @@ qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000 200000000>; qcom,sdcc-sup-voltages = <2950 2950>; qcom,sdcc-bus-width = <8>; - qcom,sdcc-hs200; qcom,sdcc-nonremovable; + qcom,sdcc-bus-speed-mode = "HS200_1p8v", "DDR_1p8v"; }; qcom,sdcc@f98a4000 { @@ -119,6 +119,9 @@ qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000 200000000>; qcom,sdcc-sup-voltages = <2950 2950>; qcom,sdcc-bus-width = <4>; + qcom,sdcc-xpc; + qcom,sdcc-bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104"; + qcom,sdcc-current-limit = <800>; }; qcom,sdcc@f9864000 { @@ -130,6 +133,7 @@ qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000>; qcom,sdcc-sup-voltages = <1800 1800>; qcom,sdcc-bus-width = <4>; + qcom,sdcc-bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50"; status = "disable"; }; @@ -142,6 +146,7 @@ qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000>; qcom,sdcc-sup-voltages = <1800 1800>; qcom,sdcc-bus-width = <4>; + qcom,sdcc-bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50"; status = "disable"; }; diff --git a/arch/arm/include/asm/mach/mmc.h b/arch/arm/include/asm/mach/mmc.h index a734547a8ac..562f13caf1a 100644 --- a/arch/arm/include/asm/mach/mmc.h +++ b/arch/arm/include/asm/mach/mmc.h @@ -142,6 +142,8 @@ struct mmc_platform_data { unsigned int xpc_cap; /* Supported UHS-I Modes */ unsigned int uhs_caps; + /* More capabilities */ + unsigned int uhs_caps2; void (*sdio_lpm_gpio_setup)(struct device *, unsigned int); unsigned int status_irq; unsigned int status_gpio; diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c index d6daeae6fd8..d198314b4ac 100644 --- a/drivers/mmc/host/msm_sdcc.c +++ b/drivers/mmc/host/msm_sdcc.c @@ -4670,9 +4670,9 @@ static struct mmc_platform_data *msmsdcc_populate_pdata(struct device *dev) int i, ret; struct mmc_platform_data *pdata; struct device_node *np = dev->of_node; - u32 bus_width = 0; + u32 bus_width = 0, current_limit = 0; u32 *clk_table, *sup_voltages; - int clk_table_len, sup_volt_len; + int clk_table_len, sup_volt_len, len; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) { @@ -4770,6 +4770,50 @@ static struct mmc_platform_data *msmsdcc_populate_pdata(struct device *dev) &pdata->vreg_data->vdd_io_data, "vdd-io")) goto err; + len = of_property_count_strings(np, "qcom,sdcc-bus-speed-mode"); + + for (i = 0; i < len; i++) { + const char *name = NULL; + + of_property_read_string_index(np, + "qcom,sdcc-bus-speed-mode", i, &name); + if (!name) + continue; + + if (!strncmp(name, "SDR12", sizeof("SDR12"))) + pdata->uhs_caps |= MMC_CAP_UHS_SDR12; + else if (!strncmp(name, "SDR25", sizeof("SDR25"))) + pdata->uhs_caps |= MMC_CAP_UHS_SDR25; + else if (!strncmp(name, "SDR50", sizeof("SDR50"))) + pdata->uhs_caps |= MMC_CAP_UHS_SDR50; + else if (!strncmp(name, "DDR50", sizeof("DDR50"))) + pdata->uhs_caps |= MMC_CAP_UHS_DDR50; + else if (!strncmp(name, "SDR104", sizeof("SDR104"))) + pdata->uhs_caps |= MMC_CAP_UHS_SDR104; + else if (!strncmp(name, "HS200_1p8v", sizeof("HS200_1p8v"))) + pdata->uhs_caps2 |= MMC_CAP2_HS200_1_8V_SDR; + else if (!strncmp(name, "HS200_1p2v", sizeof("HS200_1p2v"))) + pdata->uhs_caps2 |= MMC_CAP2_HS200_1_2V_SDR; + else if (!strncmp(name, "DDR_1p8v", sizeof("DDR_1p8v"))) + pdata->uhs_caps |= MMC_CAP_1_8V_DDR + | MMC_CAP_UHS_DDR50; + else if (!strncmp(name, "DDR_1p2v", sizeof("DDR_1p2v"))) + pdata->uhs_caps |= MMC_CAP_1_2V_DDR + | MMC_CAP_UHS_DDR50; + } + + of_property_read_u32(np, "qcom,sdcc-current-limit", ¤t_limit); + if (current_limit == 800) + pdata->uhs_caps |= MMC_CAP_MAX_CURRENT_800; + else if (current_limit == 600) + pdata->uhs_caps |= MMC_CAP_MAX_CURRENT_600; + else if (current_limit == 400) + pdata->uhs_caps |= MMC_CAP_MAX_CURRENT_400; + else if (current_limit == 200) + pdata->uhs_caps |= MMC_CAP_MAX_CURRENT_200; + + if (of_get_property(np, "qcom,sdcc-xpc", NULL)) + pdata->xpc_cap = true; if (of_get_property(np, "qcom,sdcc-nonremovable", NULL)) pdata->nonremovable = true; if (of_get_property(np, "qcom,sdcc-disable_cmd23", NULL)) @@ -5082,6 +5126,7 @@ msmsdcc_probe(struct platform_device *pdev) mmc->caps |= MMC_CAP_CMD23; mmc->caps |= plat->uhs_caps; + mmc->caps2 |= plat->uhs_caps2; /* * XPC controls the maximum current in the default speed mode of SDXC * card. XPC=0 means 100mA (max.) but speed class is not supported. @@ -5096,12 +5141,6 @@ msmsdcc_probe(struct platform_device *pdev) mmc->caps2 |= (MMC_CAP2_BOOTPART_NOACC | MMC_CAP2_DETECT_ON_ERR); mmc->caps2 |= MMC_CAP2_SANITIZE; - if (pdev->dev.of_node) { - if (of_get_property((&pdev->dev)->of_node, - "qcom,sdcc-hs200", NULL)) - mmc->caps2 |= MMC_CAP2_HS200_1_8V_SDR; - } - if (plat->nonremovable) mmc->caps |= MMC_CAP_NONREMOVABLE; mmc->caps |= MMC_CAP_SDIO_IRQ;