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 <sthumma@codeaurora.org>
diff --git a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
index 5712aa2..35ac0ec 100644
--- a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
+++ b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
@@ -23,7 +23,9 @@
- 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, <supply> can be vdd (flash core voltage) or vdd-io (I/O voltage).
- qcom,sdcc-<supply>-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 68f96db..2c19a80 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 a734547..562f13c 100644
--- a/arch/arm/include/asm/mach/mmc.h
+++ b/arch/arm/include/asm/mach/mmc.h
@@ -142,6 +142,8 @@
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 d6daeae..d198314 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -4670,9 +4670,9 @@
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 @@
&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 @@
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 @@
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;