Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/816971/?format=api
{ "id": 816971, "url": "http://patchwork.ozlabs.org/api/patches/816971/?format=api", "web_url": "http://patchwork.ozlabs.org/project/uboot/patch/1506007346-10037-12-git-send-email-jjhiblot@ti.com/", "project": { "id": 18, "url": "http://patchwork.ozlabs.org/api/projects/18/?format=api", "name": "U-Boot", "link_name": "uboot", "list_id": "u-boot.lists.denx.de", "list_email": "u-boot@lists.denx.de", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<1506007346-10037-12-git-send-email-jjhiblot@ti.com>", "list_archive_url": null, "date": "2017-09-21T15:22:14", "name": "[U-Boot,11/23] mmc: omap_hsmmc: Add support to set IODELAY values", "commit_ref": null, "pull_url": null, "state": "changes-requested", "archived": false, "hash": "4fe8e3177a94ed720d2c9215d386bc35d5a0f7c5", "submitter": { "id": 70508, "url": "http://patchwork.ozlabs.org/api/people/70508/?format=api", "name": "Jean-Jacques Hiblot", "email": "jjhiblot@ti.com" }, "delegate": { "id": 3651, "url": "http://patchwork.ozlabs.org/api/users/3651/?format=api", "username": "trini", "first_name": "Tom", "last_name": "Rini", "email": "trini@ti.com" }, "mbox": "http://patchwork.ozlabs.org/project/uboot/patch/1506007346-10037-12-git-send-email-jjhiblot@ti.com/mbox/", "series": [ { "id": 4414, "url": "http://patchwork.ozlabs.org/api/series/4414/?format=api", "web_url": "http://patchwork.ozlabs.org/project/uboot/list/?series=4414", "date": "2017-09-21T15:22:03", "name": "mmc: omap5: Add support for UHS and HS200 modes", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/4414/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/816971/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/816971/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<u-boot-bounces@lists.denx.de>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org", "Authentication-Results": [ "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=lists.denx.de\n\t(client-ip=81.169.180.215; helo=lists.denx.de;\n\tenvelope-from=u-boot-bounces@lists.denx.de;\n\treceiver=<UNKNOWN>)", "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=ti.com header.i=@ti.com header.b=\"UnK2yUAW\";\n\tdkim-atps=neutral" ], "Received": [ "from lists.denx.de (dione.denx.de [81.169.180.215])\n\tby ozlabs.org (Postfix) with ESMTP id 3xygc0371Hz9t49\n\tfor <incoming@patchwork.ozlabs.org>;\n\tFri, 22 Sep 2017 01:33:04 +1000 (AEST)", "by lists.denx.de (Postfix, from userid 105)\n\tid 370F2C220C2; Thu, 21 Sep 2017 15:24:31 +0000 (UTC)", "from lists.denx.de (localhost [IPv6:::1])\n\tby lists.denx.de (Postfix) with ESMTP id E406FC22050;\n\tThu, 21 Sep 2017 15:23:41 +0000 (UTC)", "by lists.denx.de (Postfix, from userid 105)\n\tid CEB16C21F67; Thu, 21 Sep 2017 15:23:00 +0000 (UTC)", "from lelnx193.ext.ti.com (lelnx193.ext.ti.com [198.47.27.77])\n\tby lists.denx.de (Postfix) with ESMTPS id 5DE76C22027\n\tfor <u-boot@lists.denx.de>; Thu, 21 Sep 2017 15:22:56 +0000 (UTC)", "from dflxv15.itg.ti.com ([128.247.5.124])\n\tby lelnx193.ext.ti.com (8.15.1/8.15.1) with ESMTP id v8LFMsuh007936; \n\tThu, 21 Sep 2017 10:22:54 -0500", "from DLEE104.ent.ti.com (dlee104.ent.ti.com [157.170.170.34])\n\tby dflxv15.itg.ti.com (8.14.3/8.13.8) with ESMTP id v8LFMrdH009488;\n\tThu, 21 Sep 2017 10:22:53 -0500", "from DLEE106.ent.ti.com (157.170.170.36) by DLEE104.ent.ti.com\n\t(157.170.170.34) with Microsoft SMTP Server (version=TLS1_2,\n\tcipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.1.845.34;\n\tThu, 21 Sep 2017 10:22:53 -0500", "from dflp33.itg.ti.com (10.64.6.16) by DLEE106.ent.ti.com\n\t(157.170.170.36) with Microsoft SMTP Server (version=TLS1_0,\n\tcipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.845.34 via Frontend\n\tTransport; Thu, 21 Sep 2017 10:22:53 -0500", "from localhost (ileax41-snat.itg.ti.com [10.172.224.153])\n\tby dflp33.itg.ti.com (8.14.3/8.13.8) with ESMTP id v8LFMqHi022918;\n\tThu, 21 Sep 2017 10:22:53 -0500" ], "X-Spam-Checker-Version": "SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de", "X-Spam-Level": "", "X-Spam-Status": "No, score=0.0 required=5.0 tests=RCVD_IN_DNSWL_NONE,\n\tT_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ti.com;\n\ts=ti-com-17Q1; t=1506007374;\n\tbh=7JKcrDIm0NZCIEv+WNjgsKrgziVictTDtMmC0/6RIUQ=;\n\th=From:To:CC:Subject:Date:In-Reply-To:References;\n\tb=UnK2yUAWtWBa0R0JdSLNU4A/g8Z/oUcgpuQ9wzZeJO8pVrQDKwyilLvvZTRFp5n8p\n\tz55kkhiZUwUX0oGVazbelb2kJnc6jxNVM6Sem/lAOdlmAGXP2CFWmX8uBeFVO80V6t\n\tdmSI1wBFTqwuYv/JwLtX9/u/vW+5KEin0qskqGTE=", "From": "Jean-Jacques Hiblot <jjhiblot@ti.com>", "To": "<jh80.chung@samsung.com>, <trini@konsulko.com>, <kishon@ti.com>,\n\t<sjg@chromium.org>, <lokeshvutla@ti.com>", "Date": "Thu, 21 Sep 2017 17:22:14 +0200", "Message-ID": "<1506007346-10037-12-git-send-email-jjhiblot@ti.com>", "X-Mailer": "git-send-email 1.9.1", "In-Reply-To": "<1506007346-10037-1-git-send-email-jjhiblot@ti.com>", "References": "<1506007346-10037-1-git-send-email-jjhiblot@ti.com>", "MIME-Version": "1.0", "X-EXCLAIMER-MD-CONFIG": "e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180", "Cc": "u-boot@lists.denx.de", "Subject": "[U-Boot] [PATCH 11/23] mmc: omap_hsmmc: Add support to set IODELAY\n\tvalues", "X-BeenThere": "u-boot@lists.denx.de", "X-Mailman-Version": "2.1.18", "Precedence": "list", "List-Id": "U-Boot discussion <u-boot.lists.denx.de>", "List-Unsubscribe": "<https://lists.denx.de/options/u-boot>,\n\t<mailto:u-boot-request@lists.denx.de?subject=unsubscribe>", "List-Archive": "<http://lists.denx.de/pipermail/u-boot/>", "List-Post": "<mailto:u-boot@lists.denx.de>", "List-Help": "<mailto:u-boot-request@lists.denx.de?subject=help>", "List-Subscribe": "<https://lists.denx.de/listinfo/u-boot>,\n\t<mailto:u-boot-request@lists.denx.de?subject=subscribe>", "Content-Type": "text/plain; charset=\"utf-8\"", "Content-Transfer-Encoding": "base64", "Errors-To": "u-boot-bounces@lists.denx.de", "Sender": "\"U-Boot\" <u-boot-bounces@lists.denx.de>" }, "content": "From: Kishon Vijay Abraham I <kishon@ti.com>\n\nThe data manual of J6/J6 Eco recommends to set different IODELAY values\ndepending on the mode in which the MMC/SD is enumerated in order to\nensure IO timings are met.\n\nAdd support to parse mux values and iodelay values from device tree\nand set these depending on the enumerated MMC mode.\n\nSigned-off-by: Kishon Vijay Abraham I <kishon@ti.com>\nSigned-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>\n---\n drivers/mmc/omap_hsmmc.c | 372 +++++++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 372 insertions(+)", "diff": "diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c\nindex 734854b..67ba31e 100644\n--- a/drivers/mmc/omap_hsmmc.c\n+++ b/drivers/mmc/omap_hsmmc.c\n@@ -34,6 +34,10 @@\n #include <palmas.h>\n #include <asm/io.h>\n #include <asm/arch/mmc_host_def.h>\n+#ifdef CONFIG_OMAP54XX\n+#include <asm/arch/mux_dra7xx.h>\n+#include <asm/arch/dra7xx_iodelay.h>\n+#endif\n #if !defined(CONFIG_SOC_KEYSTONE)\n #include <asm/gpio.h>\n #include <asm/arch/sys_proto.h>\n@@ -57,6 +61,15 @@ DECLARE_GLOBAL_DATA_PTR;\n #define SYSCTL_SRC\t(1 << 25)\n #define SYSCTL_SRD\t(1 << 26)\n \n+#ifdef CONFIG_IODELAY_RECALIBRATION\n+struct omap_hsmmc_pinctrl_state {\n+\tstruct pad_conf_entry *padconf;\n+\tint npads;\n+\tstruct iodelay_cfg_entry *iodelay;\n+\tint niodelays;\n+};\n+#endif\n+\n struct omap_hsmmc_data {\n \tstruct hsmmc *base_addr;\n #if !CONFIG_IS_ENABLED(DM_MMC)\n@@ -83,6 +96,17 @@ struct omap_hsmmc_data {\n \tstruct omap_hsmmc_adma_desc *adma_desc_table;\n \tuint desc_slot;\n #endif\n+#ifdef CONFIG_IODELAY_RECALIBRATION\n+\tstruct omap_hsmmc_pinctrl_state *default_pinctrl_state;\n+\tstruct omap_hsmmc_pinctrl_state *hs_pinctrl_state;\n+\tstruct omap_hsmmc_pinctrl_state *hs200_1_8v_pinctrl_state;\n+\tstruct omap_hsmmc_pinctrl_state *ddr_1_8v_pinctrl_state;\n+\tstruct omap_hsmmc_pinctrl_state *sdr12_pinctrl_state;\n+\tstruct omap_hsmmc_pinctrl_state *sdr25_pinctrl_state;\n+\tstruct omap_hsmmc_pinctrl_state *ddr50_pinctrl_state;\n+\tstruct omap_hsmmc_pinctrl_state *sdr50_pinctrl_state;\n+\tstruct omap_hsmmc_pinctrl_state *sdr104_pinctrl_state;\n+#endif\n };\n \n #ifndef CONFIG_OMAP34XX\n@@ -93,6 +117,10 @@ struct omap_hsmmc_adma_desc {\n \tu32 addr;\n };\n \n+struct omap_mmc_of_data {\n+\tu8 controller_flags;\n+};\n+\n #define ADMA_MAX_LEN\t63488\n \n /* Decriptor table defines */\n@@ -119,6 +147,7 @@ struct omap_hsmmc_adma_desc {\n #define OMAP_HSMMC_SUPPORTS_DUAL_VOLT\t\tBIT(0)\n #define OMAP_HSMMC_NO_1_8_V\t\t\tBIT(1)\n #define OMAP_HSMMC_USE_ADMA\t\t\tBIT(2)\n+#define OMAP_HSMMC_REQUIRE_IODELAY\t\tBIT(3)\n \n static int mmc_read_data(struct hsmmc *mmc_base, char *buf, unsigned int size);\n static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,\n@@ -261,6 +290,56 @@ void mmc_init_stream(struct hsmmc *mmc_base)\n }\n \n #if CONFIG_IS_ENABLED(DM_MMC)\n+#ifdef CONFIG_IODELAY_RECALIBRATION\n+static void omap_hsmmc_io_recalibrate(struct mmc *mmc)\n+{\n+\tstruct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);\n+\tstruct omap_hsmmc_pinctrl_state *pinctrl_state;\n+\n+\tswitch (priv->mode) {\n+\tcase MMC_HS_200:\n+\t\tpinctrl_state = priv->hs200_1_8v_pinctrl_state;\n+\t\tbreak;\n+\tcase UHS_SDR104:\n+\t\tpinctrl_state = priv->sdr104_pinctrl_state;\n+\t\tbreak;\n+\tcase UHS_SDR50:\n+\t\tpinctrl_state = priv->sdr50_pinctrl_state;\n+\t\tbreak;\n+\tcase UHS_DDR50:\n+\t\tpinctrl_state = priv->ddr50_pinctrl_state;\n+\t\tbreak;\n+\tcase UHS_SDR25:\n+\t\tpinctrl_state = priv->sdr25_pinctrl_state;\n+\t\tbreak;\n+\tcase UHS_SDR12:\n+\t\tpinctrl_state = priv->sdr12_pinctrl_state;\n+\t\tbreak;\n+\tcase SD_HS:\n+\tcase MMC_HS:\n+\tcase MMC_HS_52:\n+\t\tpinctrl_state = priv->hs_pinctrl_state;\n+\t\tbreak;\n+\tcase MMC_DDR_52:\n+\t\tpinctrl_state = priv->ddr_1_8v_pinctrl_state;\n+\tdefault:\n+\t\tpinctrl_state = priv->default_pinctrl_state;\n+\t\tbreak;\n+\t}\n+\n+\tif (priv->controller_flags & OMAP_HSMMC_REQUIRE_IODELAY) {\n+\t\tif (pinctrl_state->iodelay)\n+\t\t\tlate_recalibrate_iodelay(pinctrl_state->padconf,\n+\t\t\t\t\t\t pinctrl_state->npads,\n+\t\t\t\t\t\t pinctrl_state->iodelay,\n+\t\t\t\t\t\t pinctrl_state->niodelays);\n+\t\telse\n+\t\t\tdo_set_mux32((*ctrl)->control_padconf_core_base,\n+\t\t\t\t pinctrl_state->padconf,\n+\t\t\t\t pinctrl_state->npads);\n+\t}\n+}\n+#endif\n static void omap_hsmmc_set_timing(struct mmc *mmc)\n {\n \tu32 val;\n@@ -269,6 +348,7 @@ static void omap_hsmmc_set_timing(struct mmc *mmc)\n \n \tmmc_base = priv->base_addr;\n \n+\tomap_hsmmc_stop_clock(mmc_base);\n \tval = readl(&mmc_base->ac12);\n \tval &= ~AC12_UHSMC_MASK;\n \tpriv->mode = mmc->selected_mode;\n@@ -306,6 +386,11 @@ static void omap_hsmmc_set_timing(struct mmc *mmc)\n \t\tbreak;\n \t}\n \twritel(val, &mmc_base->ac12);\n+\n+#ifdef CONFIG_IODELAY_RECALIBRATION\n+\tomap_hsmmc_io_recalibrate(mmc);\n+#endif\n+\tomap_hsmmc_start_clock(mmc_base);\n }\n \n static void omap_hsmmc_conf_bus_power(struct mmc *mmc)\n@@ -1284,10 +1369,271 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,\n \treturn 0;\n }\n #else\n+\n+#ifdef CONFIG_IODELAY_RECALIBRATION\n+static struct pad_conf_entry *\n+omap_hsmmc_get_pad_conf_entry(const fdt32_t *pinctrl, int count)\n+{\n+\tint index = 0;\n+\tstruct pad_conf_entry *padconf;\n+\n+\tpadconf = (struct pad_conf_entry *)malloc(sizeof(*padconf) * count);\n+\tif (!padconf) {\n+\t\tdebug(\"failed to allocate memory\\n\");\n+\t\treturn 0;\n+\t}\n+\n+\twhile (index < count) {\n+\t\tpadconf[index].offset = fdt32_to_cpu(pinctrl[2 * index]);\n+\t\tpadconf[index].val = fdt32_to_cpu(pinctrl[2 * index + 1]);\n+\t\tindex++;\n+\t}\n+\n+\treturn padconf;\n+}\n+\n+static struct iodelay_cfg_entry *\n+omap_hsmmc_get_iodelay_cfg_entry(const fdt32_t *pinctrl, int count)\n+{\n+\tint index = 0;\n+\tstruct iodelay_cfg_entry *iodelay;\n+\n+\tiodelay = (struct iodelay_cfg_entry *)malloc(sizeof(*iodelay) * count);\n+\tif (!iodelay) {\n+\t\tdebug(\"failed to allocate memory\\n\");\n+\t\treturn 0;\n+\t}\n+\n+\twhile (index < count) {\n+\t\tiodelay[index].offset = fdt32_to_cpu(pinctrl[3 * index]);\n+\t\tiodelay[index].a_delay = fdt32_to_cpu(pinctrl[3 * index + 1]);\n+\t\tiodelay[index].g_delay = fdt32_to_cpu(pinctrl[3 * index + 2]);\n+\t\tindex++;\n+\t}\n+\n+\treturn iodelay;\n+}\n+\n+static const fdt32_t *omap_hsmmc_get_pinctrl_entry(u32 phandle,\n+\t\t\t\t\t\t const char *name, int *len)\n+{\n+\tconst void *fdt = gd->fdt_blob;\n+\tint offset;\n+\tconst fdt32_t *pinctrl;\n+\n+\toffset = fdt_node_offset_by_phandle(fdt, phandle);\n+\tif (offset < 0) {\n+\t\tdebug(\"failed to get pinctrl node %s.\\n\",\n+\t\t fdt_strerror(offset));\n+\t\treturn 0;\n+\t}\n+\n+\tpinctrl = fdt_getprop(fdt, offset, name, len);\n+\tif (!pinctrl) {\n+\t\tdebug(\"failed to get property %s\\n\", name);\n+\t\treturn 0;\n+\t}\n+\n+\treturn pinctrl;\n+}\n+\n+static uint32_t omap_hsmmc_get_pad_conf_phandle(struct mmc *mmc,\n+\t\t\t\t\t\tchar *prop_name)\n+{\n+\tconst void *fdt = gd->fdt_blob;\n+\tconst __be32 *phandle;\n+\tint node = dev_of_offset(mmc->dev);\n+\n+\tphandle = fdt_getprop(fdt, node, prop_name, NULL);\n+\tif (!phandle) {\n+\t\tdebug(\"failed to get property %s\\n\", prop_name);\n+\t\treturn 0;\n+\t}\n+\n+\treturn fdt32_to_cpu(*phandle);\n+}\n+\n+static uint32_t omap_hsmmc_get_iodelay_phandle(struct mmc *mmc,\n+\t\t\t\t\t char *prop_name)\n+{\n+\tconst void *fdt = gd->fdt_blob;\n+\tconst __be32 *phandle;\n+\tint len;\n+\tint count;\n+\tint node = dev_of_offset(mmc->dev);\n+\n+\tphandle = fdt_getprop(fdt, node, prop_name, &len);\n+\tif (!phandle) {\n+\t\tdebug(\"failed to get property %s\\n\", prop_name);\n+\t\treturn 0;\n+\t}\n+\n+\t/* No manual mode iodelay values if count < 2 */\n+\tcount = len / sizeof(*phandle);\n+\tif (count < 2)\n+\t\treturn 0;\n+\n+\treturn fdt32_to_cpu(*(phandle + 1));\n+}\n+\n+static struct pad_conf_entry *\n+omap_hsmmc_get_pad_conf(struct mmc *mmc, char *prop_name, int *npads)\n+{\n+\tint len;\n+\tint count;\n+\tstruct pad_conf_entry *padconf;\n+\tu32 phandle;\n+\tconst fdt32_t *pinctrl;\n+\n+\tphandle = omap_hsmmc_get_pad_conf_phandle(mmc, prop_name);\n+\tif (!phandle)\n+\t\treturn ERR_PTR(-EINVAL);\n+\n+\tpinctrl = omap_hsmmc_get_pinctrl_entry(phandle, \"pinctrl-single,pins\",\n+\t\t\t\t\t &len);\n+\tif (!pinctrl)\n+\t\treturn ERR_PTR(-EINVAL);\n+\n+\tcount = (len / sizeof(*pinctrl)) / 2;\n+\tpadconf = omap_hsmmc_get_pad_conf_entry(pinctrl, count);\n+\tif (!padconf)\n+\t\treturn ERR_PTR(-EINVAL);\n+\n+\t*npads = count;\n+\n+\treturn padconf;\n+}\n+\n+static struct iodelay_cfg_entry *\n+omap_hsmmc_get_iodelay(struct mmc *mmc, char *prop_name, int *niodelay)\n+{\n+\tint len;\n+\tint count;\n+\tstruct iodelay_cfg_entry *iodelay;\n+\tu32 phandle;\n+\tconst fdt32_t *pinctrl;\n+\n+\tphandle = omap_hsmmc_get_iodelay_phandle(mmc, prop_name);\n+\t/* Not all modes have manual mode iodelay values. So its not fatal */\n+\tif (!phandle)\n+\t\treturn 0;\n+\n+\tpinctrl = omap_hsmmc_get_pinctrl_entry(phandle, \"pinctrl-pin-array\",\n+\t\t\t\t\t &len);\n+\tif (!pinctrl)\n+\t\treturn ERR_PTR(-EINVAL);\n+\n+\tcount = (len / sizeof(*pinctrl)) / 3;\n+\tiodelay = omap_hsmmc_get_iodelay_cfg_entry(pinctrl, count);\n+\tif (!iodelay)\n+\t\treturn ERR_PTR(-EINVAL);\n+\n+\t*niodelay = count;\n+\n+\treturn iodelay;\n+}\n+\n+static struct omap_hsmmc_pinctrl_state *\n+omap_hsmmc_get_pinctrl_by_mode(struct mmc *mmc, char *mode)\n+{\n+\tint index;\n+\tint npads = 0;\n+\tint niodelays = 0;\n+\tconst void *fdt = gd->fdt_blob;\n+\tint node = dev_of_offset(mmc->dev);\n+\tchar prop_name[11];\n+\tstruct omap_hsmmc_pinctrl_state *pinctrl_state;\n+\n+\tpinctrl_state = (struct omap_hsmmc_pinctrl_state *)\n+\t\t\t malloc(sizeof(*pinctrl_state));\n+\tif (!pinctrl_state) {\n+\t\tdebug(\"failed to allocate memory\\n\");\n+\t\treturn 0;\n+\t}\n+\n+\tindex = fdt_stringlist_search(fdt, node, \"pinctrl-names\", mode);\n+\tif (index < 0) {\n+\t\tdebug(\"fail to find %s mode %s\\n\", mode, fdt_strerror(index));\n+\t\tgoto err_pinctrl_state;\n+\t}\n+\n+\tsprintf(prop_name, \"pinctrl-%d\", index);\n+\n+\tpinctrl_state->padconf = omap_hsmmc_get_pad_conf(mmc, prop_name,\n+\t\t\t\t\t\t\t &npads);\n+\tif (IS_ERR(pinctrl_state->padconf))\n+\t\tgoto err_pinctrl_state;\n+\tpinctrl_state->npads = npads;\n+\n+\tpinctrl_state->iodelay = omap_hsmmc_get_iodelay(mmc, prop_name,\n+\t\t\t\t\t\t\t&niodelays);\n+\tif (IS_ERR(pinctrl_state->iodelay))\n+\t\tgoto err_padconf;\n+\tpinctrl_state->niodelays = niodelays;\n+\n+\treturn pinctrl_state;\n+\n+err_padconf:\n+\tkfree(pinctrl_state->padconf);\n+\n+err_pinctrl_state:\n+\tkfree(pinctrl_state);\n+\treturn 0;\n+}\n+\n+#define OMAP_HSMMC_SETUP_PINCTRL(capmask, mode)\t\t\t\\\n+\tdo {\t\t\t\t\t\t\t\\\n+\t\tstruct omap_hsmmc_pinctrl_state *s;\t\t\\\n+\t\tif (!(cfg->host_caps & capmask))\t\t\\\n+\t\t\tbreak;\t\t\t\t\t\\\n+\t\t\t\t\t\t\t\t\\\n+\t\ts = omap_hsmmc_get_pinctrl_by_mode(mmc, #mode);\t\\\n+\t\tif (!s) {\t\t\t\t\t\\\n+\t\t\tdebug(\"%s: no pinctrl for %s\\n\",\t\\\n+\t\t\t mmc->dev->name, #mode);\t\t\\\n+\t\t\tcfg->host_caps &= ~(capmask);\t\t\\\n+\t\t} else {\t\t\t\t\t\\\n+\t\t\tpriv->mode##_pinctrl_state = s;\t\t\\\n+\t\t}\t\t\t\t\t\t\\\n+\t} while (0)\n+\n+static int omap_hsmmc_get_pinctrl_state(struct mmc *mmc)\n+{\n+\tstruct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);\n+\tstruct mmc_config *cfg = omap_hsmmc_get_cfg(mmc);\n+\tstruct omap_hsmmc_pinctrl_state *default_pinctrl;\n+\n+\tif (!(priv->controller_flags & OMAP_HSMMC_REQUIRE_IODELAY))\n+\t\treturn 0;\n+\n+\tdefault_pinctrl = omap_hsmmc_get_pinctrl_by_mode(mmc, \"default\");\n+\tif (!default_pinctrl) {\n+\t\tprintf(\"no pinctrl state for default mode\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tpriv->default_pinctrl_state = default_pinctrl;\n+\n+\tOMAP_HSMMC_SETUP_PINCTRL(MMC_CAP(UHS_SDR104), sdr104);\n+\tOMAP_HSMMC_SETUP_PINCTRL(MMC_CAP(UHS_SDR50), sdr50);\n+\tOMAP_HSMMC_SETUP_PINCTRL(MMC_CAP(UHS_DDR50), ddr50);\n+\tOMAP_HSMMC_SETUP_PINCTRL(MMC_CAP(UHS_SDR25), sdr25);\n+\tOMAP_HSMMC_SETUP_PINCTRL(MMC_CAP(UHS_SDR12), sdr12);\n+\n+\tOMAP_HSMMC_SETUP_PINCTRL(MMC_CAP(MMC_HS_200), hs200_1_8v);\n+\tOMAP_HSMMC_SETUP_PINCTRL(MMC_CAP(MMC_DDR_52), ddr_1_8v);\n+\tOMAP_HSMMC_SETUP_PINCTRL(MMC_MODE_HS, hs);\n+\n+\treturn 0;\n+}\n+#endif\n+\n #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)\n static int omap_hsmmc_ofdata_to_platdata(struct udevice *dev)\n {\n \tstruct omap_hsmmc_plat *plat = dev_get_platdata(dev);\n+\tstruct omap_mmc_of_data *of_data = (void *)dev_get_driver_data(dev);\n+\n \tstruct mmc_config *cfg = &plat->cfg;\n \tconst void *fdt = gd->fdt_blob;\n \tint node = dev_of_offset(dev);\n@@ -1309,6 +1655,8 @@ static int omap_hsmmc_ofdata_to_platdata(struct udevice *dev)\n \t\tplat->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT;\n \tif (fdtdec_get_bool(fdt, node, \"no-1-8-v\"))\n \t\tplat->controller_flags |= OMAP_HSMMC_NO_1_8_V;\n+\tif (of_data)\n+\t\tplat->controller_flags |= of_data->controller_flags;\n \n #ifdef OMAP_HSMMC_USE_GPIO\n \tplat->cd_inverted = fdtdec_get_bool(fdt, node, \"cd-inverted\");\n@@ -1334,9 +1682,13 @@ static int omap_hsmmc_probe(struct udevice *dev)\n \tstruct omap_hsmmc_data *priv = dev_get_priv(dev);\n \tstruct mmc_config *cfg = &plat->cfg;\n \tstruct mmc *mmc;\n+#ifdef CONFIG_IODELAY_RECALIBRATION\n+\tint ret;\n+#endif\n \n \tcfg->name = \"OMAP SD/MMC\";\n \tpriv->base_addr = plat->base_addr;\n+\tpriv->controller_flags = plat->controller_flags;\n #ifdef OMAP_HSMMC_USE_GPIO\n \tpriv->cd_inverted = plat->cd_inverted;\n #endif\n@@ -1357,14 +1709,34 @@ static int omap_hsmmc_probe(struct udevice *dev)\n \tmmc->dev = dev;\n \tupriv->mmc = mmc;\n \n+#ifdef CONFIG_IODELAY_RECALIBRATION\n+\tret = omap_hsmmc_get_pinctrl_state(mmc);\n+\t/*\n+\t * disable high speed modes for the platforms that require IO delay\n+\t * and for which we don't have this information\n+\t */\n+\tif ((ret < 0) &&\n+\t (priv->controller_flags & OMAP_HSMMC_REQUIRE_IODELAY)) {\n+\t\tpriv->controller_flags &= ~OMAP_HSMMC_REQUIRE_IODELAY;\n+\t\tcfg->host_caps &= ~(MMC_CAP(MMC_HS_200) | MMC_CAP(MMC_DDR_52) |\n+\t\t\t\t UHS_CAPS);\n+\t}\n+#endif\n+\n \treturn omap_hsmmc_init_setup(mmc);\n }\n \n #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)\n+\n+static const struct omap_mmc_of_data dra7_mmc_of_data = {\n+\t.controller_flags = OMAP_HSMMC_REQUIRE_IODELAY,\n+};\n+\n static const struct udevice_id omap_hsmmc_ids[] = {\n \t{ .compatible = \"ti,omap3-hsmmc\" },\n \t{ .compatible = \"ti,omap4-hsmmc\" },\n \t{ .compatible = \"ti,am33xx-hsmmc\" },\n+\t{ .compatible = \"ti,dra7-hsmmc\", .data = (ulong)&dra7_mmc_of_data },\n \t{ }\n };\n #endif\n", "prefixes": [ "U-Boot", "11/23" ] }