Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/816899/?format=api
{ "id": 816899, "url": "http://patchwork.ozlabs.org/api/patches/816899/?format=api", "web_url": "http://patchwork.ozlabs.org/project/uboot/patch/1506004213-22620-21-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": "<1506004213-22620-21-git-send-email-jjhiblot@ti.com>", "list_archive_url": null, "date": "2017-09-21T14:30:07", "name": "[U-Boot,v2,20/26] mmc: Add support for UHS modes", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "9015f217407facbfded6f1045266b83857efb20f", "submitter": { "id": 70508, "url": "http://patchwork.ozlabs.org/api/people/70508/?format=api", "name": "Jean-Jacques Hiblot", "email": "jjhiblot@ti.com" }, "delegate": { "id": 12423, "url": "http://patchwork.ozlabs.org/api/users/12423/?format=api", "username": "Jaehoon", "first_name": "Jaehoon", "last_name": "Chung", "email": "jh80.chung@samsung.com" }, "mbox": "http://patchwork.ozlabs.org/project/uboot/patch/1506004213-22620-21-git-send-email-jjhiblot@ti.com/mbox/", "series": [ { "id": 4400, "url": "http://patchwork.ozlabs.org/api/series/4400/?format=api", "web_url": "http://patchwork.ozlabs.org/project/uboot/list/?series=4400", "date": "2017-09-21T14:29:47", "name": "mmc: Add support for HS200 and UHS modes", "version": 2, "mbox": "http://patchwork.ozlabs.org/series/4400/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/816899/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/816899/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=\"et/LcV3J\";\n\tdkim-atps=neutral" ], "Received": [ "from lists.denx.de (dione.denx.de [81.169.180.215])\n\tby ozlabs.org (Postfix) with ESMTP id 3xyfPL6HtFz9sNc\n\tfor <incoming@patchwork.ozlabs.org>;\n\tFri, 22 Sep 2017 00:38:46 +1000 (AEST)", "by lists.denx.de (Postfix, from userid 105)\n\tid 764F7C21FFA; Thu, 21 Sep 2017 14:38:25 +0000 (UTC)", "from lists.denx.de (localhost [IPv6:::1])\n\tby lists.denx.de (Postfix) with ESMTP id A0C01C22005;\n\tThu, 21 Sep 2017 14:35:02 +0000 (UTC)", "by lists.denx.de (Postfix, from userid 105)\n\tid BAFCAC21FE8; Thu, 21 Sep 2017 14:32:16 +0000 (UTC)", "from fllnx209.ext.ti.com (fllnx209.ext.ti.com [198.47.19.16])\n\tby lists.denx.de (Postfix) with ESMTPS id 56054C21FD8\n\tfor <u-boot@lists.denx.de>; Thu, 21 Sep 2017 14:32:13 +0000 (UTC)", "from dflxv15.itg.ti.com ([128.247.5.124])\n\tby fllnx209.ext.ti.com (8.15.1/8.15.1) with ESMTP id v8LEVBhn032559; \n\tThu, 21 Sep 2017 09:31:11 -0500", "from DLEE107.ent.ti.com (dlee107.ent.ti.com [157.170.170.37])\n\tby dflxv15.itg.ti.com (8.14.3/8.13.8) with ESMTP id v8LEV5c7029293;\n\tThu, 21 Sep 2017 09:31:06 -0500", "from DLEE101.ent.ti.com (157.170.170.31) by DLEE107.ent.ti.com\n\t(157.170.170.37) 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 09:31:02 -0500", "from dflp32.itg.ti.com (10.64.6.15) by DLEE101.ent.ti.com\n\t(157.170.170.31) 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 09:31:03 -0500", "from localhost (ileax41-snat.itg.ti.com [10.172.224.153])\n\tby dflp32.itg.ti.com (8.14.3/8.13.8) with ESMTP id v8LEV1wd016614;\n\tThu, 21 Sep 2017 09:31:01 -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=1506004271;\n\tbh=YrMU1DIRKqroqYH0CtnfD7Xjxguv/FccPGYALg2wl7E=;\n\th=From:To:CC:Subject:Date:In-Reply-To:References;\n\tb=et/LcV3JhNLx8Qy3nJmYq2fNXhN+MvEHeyb9ZbDI8ZrDpX4vKqVpVD9MAwGbZZ/gw\n\tDmxE6iq8bGR68HThMXtgLoDqnuTUjH87G7bng3D5B4pttJ3PHlkm+Lc29ZLmAW/gxj\n\tAILrD8vcsINEHkfMaZ510o0790A1PdLrs5XngMkU=", "From": "Jean-Jacques Hiblot <jjhiblot@ti.com>", "To": "<jh80.chung@samsung.com>, <trini@konsulko.com>, <kishon@ti.com>,\n\t<sjg@chromium.org>", "Date": "Thu, 21 Sep 2017 16:30:07 +0200", "Message-ID": "<1506004213-22620-21-git-send-email-jjhiblot@ti.com>", "X-Mailer": "git-send-email 1.9.1", "In-Reply-To": "<1506004213-22620-1-git-send-email-jjhiblot@ti.com>", "References": "<1506004213-22620-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 v2 20/26] mmc: Add support for UHS modes", "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": "Add UHS modes to the list of supported modes, get the UHS capabilites of\nthe SDcard and implement the procedure to switch the voltage (UHS modes\nuse 1v8 IO lines)\nDuring the voltage switch procedure, DAT0 is used by the card to signal\nwhen it's ready. The optional card_busy() callback can be used to get this\ninformation from the host driver.\n\nSigned-off-by: Kishon Vijay Abraham I <kishon@ti.com>\nSigned-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>\nReviewed-by: Simon Glass <sjg@chromium.org>\n---\n drivers/mmc/mmc-uclass.c | 14 ++++\n drivers/mmc/mmc.c | 176 ++++++++++++++++++++++++++++++++++++++++++++---\n include/mmc.h | 40 ++++++++++-\n 3 files changed, 221 insertions(+), 9 deletions(-)", "diff": "diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c\nindex 60cc0ac..7856e0a 100644\n--- a/drivers/mmc/mmc-uclass.c\n+++ b/drivers/mmc/mmc-uclass.c\n@@ -64,6 +64,20 @@ void mmc_send_init_stream(struct mmc *mmc)\n \tdm_mmc_send_init_stream(mmc->dev);\n }\n \n+int dm_mmc_wait_dat0(struct udevice *dev, int state, int timeout)\n+{\n+\tstruct dm_mmc_ops *ops = mmc_get_ops(dev);\n+\n+\tif (!ops->wait_dat0)\n+\t\treturn -ENOSYS;\n+\treturn ops->wait_dat0(dev, state, timeout);\n+}\n+\n+int mmc_wait_dat0(struct mmc *mmc, int state, int timeout)\n+{\n+\treturn dm_mmc_wait_dat0(mmc->dev, state, timeout);\n+}\n+\n int dm_mmc_get_wp(struct udevice *dev)\n {\n \tstruct dm_mmc_ops *ops = mmc_get_ops(dev);\ndiff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c\nindex c663709..ca59e28 100644\n--- a/drivers/mmc/mmc.c\n+++ b/drivers/mmc/mmc.c\n@@ -57,6 +57,12 @@ struct blk_desc *mmc_get_blk_desc(struct mmc *mmc)\n #endif\n \n #if !CONFIG_IS_ENABLED(DM_MMC)\n+\n+static int mmc_wait_dat0(struct mmc *mmc, int state, int timeout)\n+{\n+\treturn -ENOSYS;\n+}\n+\n __weak int board_mmc_getwp(struct mmc *mmc)\n {\n \treturn -1;\n@@ -402,7 +408,67 @@ static int mmc_go_idle(struct mmc *mmc)\n \treturn 0;\n }\n \n-static int sd_send_op_cond(struct mmc *mmc)\n+static int mmc_switch_voltage(struct mmc *mmc, int signal_voltage)\n+{\n+\tstruct mmc_cmd cmd;\n+\tint err = 0;\n+\n+\t/*\n+\t * Send CMD11 only if the request is to switch the card to\n+\t * 1.8V signalling.\n+\t */\n+\tif (signal_voltage == MMC_SIGNAL_VOLTAGE_330)\n+\t\treturn mmc_set_signal_voltage(mmc, signal_voltage);\n+\n+\tcmd.cmdidx = SD_CMD_SWITCH_UHS18V;\n+\tcmd.cmdarg = 0;\n+\tcmd.resp_type = MMC_RSP_R1;\n+\n+\terr = mmc_send_cmd(mmc, &cmd, NULL);\n+\tif (err)\n+\t\treturn err;\n+\n+\tif (!mmc_host_is_spi(host) && (cmd.response[0] & MMC_STATUS_ERROR))\n+\t\treturn -EIO;\n+\n+\t/*\n+\t * The card should drive cmd and dat[0:3] low immediately\n+\t * after the response of cmd11, but wait 100 us to be sure\n+\t */\n+\terr = mmc_wait_dat0(mmc, 0, 100);\n+\tif (err == -ENOSYS)\n+\t\tudelay(100);\n+\telse if (err)\n+\t\treturn -ETIMEDOUT;\n+\n+\t/*\n+\t * During a signal voltage level switch, the clock must be gated\n+\t * for 5 ms according to the SD spec\n+\t */\n+\tmmc_set_clock(mmc, mmc->clock, true);\n+\n+\terr = mmc_set_signal_voltage(mmc, signal_voltage);\n+\tif (err)\n+\t\treturn err;\n+\n+\t/* Keep clock gated for at least 10 ms, though spec only says 5 ms */\n+\tmdelay(10);\n+\tmmc_set_clock(mmc, mmc->clock, false);\n+\n+\t/*\n+\t * Failure to switch is indicated by the card holding\n+\t * dat[0:3] low. Wait for at least 1 ms according to spec\n+\t */\n+\terr = mmc_wait_dat0(mmc, 1, 1000);\n+\tif (err == -ENOSYS)\n+\t\tudelay(1000);\n+\telse if (err)\n+\t\treturn -ETIMEDOUT;\n+\n+\treturn 0;\n+}\n+\n+static int sd_send_op_cond(struct mmc *mmc, bool uhs_en)\n {\n \tint timeout = 1000;\n \tint err;\n@@ -434,6 +500,9 @@ static int sd_send_op_cond(struct mmc *mmc)\n \t\tif (mmc->version == SD_VERSION_2)\n \t\t\tcmd.cmdarg |= OCR_HCS;\n \n+\t\tif (uhs_en)\n+\t\t\tcmd.cmdarg |= OCR_S18R;\n+\n \t\terr = mmc_send_cmd(mmc, &cmd, NULL);\n \n \t\tif (err)\n@@ -464,6 +533,13 @@ static int sd_send_op_cond(struct mmc *mmc)\n \n \tmmc->ocr = cmd.response[0];\n \n+\tif (uhs_en && !(mmc_host_is_spi(mmc)) && (cmd.response[0] & 0x41000000)\n+\t == 0x41000000) {\n+\t\terr = mmc_switch_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);\n+\t\tif (err)\n+\t\t\treturn err;\n+\t}\n+\n \tmmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);\n \tmmc->rca = 0;\n \n@@ -977,6 +1053,7 @@ static int sd_get_capabilities(struct mmc *mmc)\n \tALLOC_CACHE_ALIGN_BUFFER(uint, switch_status, 16);\n \tstruct mmc_data data;\n \tint timeout;\n+\tu32 sd3_bus_mode;\n \n \tmmc->card_caps = MMC_MODE_1BIT;\n \n@@ -1058,6 +1135,22 @@ retry_scr:\n \tif (__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED)\n \t\tmmc->card_caps |= MMC_CAP(SD_HS);\n \n+\t/* Version before 3.0 don't support UHS modes */\n+\tif (mmc->version < SD_VERSION_3)\n+\t\treturn 0;\n+\n+\tsd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f;\n+\tif (sd3_bus_mode & SD_MODE_UHS_SDR104)\n+\t\tmmc->card_caps |= MMC_CAP(UHS_SDR104);\n+\tif (sd3_bus_mode & SD_MODE_UHS_SDR50)\n+\t\tmmc->card_caps |= MMC_CAP(UHS_SDR50);\n+\tif (sd3_bus_mode & SD_MODE_UHS_SDR25)\n+\t\tmmc->card_caps |= MMC_CAP(UHS_SDR25);\n+\tif (sd3_bus_mode & SD_MODE_UHS_SDR12)\n+\t\tmmc->card_caps |= MMC_CAP(UHS_SDR12);\n+\tif (sd3_bus_mode & SD_MODE_UHS_DDR50)\n+\t\tmmc->card_caps |= MMC_CAP(UHS_DDR50);\n+\n \treturn 0;\n }\n \n@@ -1066,12 +1159,35 @@ static int sd_set_card_speed(struct mmc *mmc, enum bus_mode mode)\n \tint err;\n \n \tALLOC_CACHE_ALIGN_BUFFER(uint, switch_status, 16);\n+\tint speed;\n \n-\terr = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)switch_status);\n+\tswitch (mode) {\n+\tcase SD_LEGACY:\n+\tcase UHS_SDR12:\n+\t\tspeed = UHS_SDR12_BUS_SPEED;\n+\t\tbreak;\n+\tcase SD_HS:\n+\tcase UHS_SDR25:\n+\t\tspeed = UHS_SDR25_BUS_SPEED;\n+\t\tbreak;\n+\tcase UHS_SDR50:\n+\t\tspeed = UHS_SDR50_BUS_SPEED;\n+\t\tbreak;\n+\tcase UHS_DDR50:\n+\t\tspeed = UHS_DDR50_BUS_SPEED;\n+\t\tbreak;\n+\tcase UHS_SDR104:\n+\t\tspeed = UHS_SDR104_BUS_SPEED;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+\n+\terr = sd_switch(mmc, SD_SWITCH_SWITCH, 0, speed, (u8 *)switch_status);\n \tif (err)\n \t\treturn err;\n \n-\tif ((__be32_to_cpu(switch_status[4]) & 0x0f000000) != 0x01000000)\n+\tif ((__be32_to_cpu(switch_status[4]) >> 24) != speed)\n \t\treturn -ENOTSUPP;\n \n \treturn 0;\n@@ -1286,10 +1402,31 @@ static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)\n \n static const struct mode_width_tuning sd_modes_by_pref[] = {\n \t{\n+\t\t.mode = UHS_SDR104,\n+\t\t.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,\n+\t\t.tuning = MMC_CMD_SEND_TUNING_BLOCK\n+\t},\n+\t{\n+\t\t.mode = UHS_SDR50,\n+\t\t.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,\n+\t},\n+\t{\n+\t\t.mode = UHS_DDR50,\n+\t\t.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,\n+\t},\n+\t{\n+\t\t.mode = UHS_SDR25,\n+\t\t.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,\n+\t},\n+\t{\n \t\t.mode = SD_HS,\n \t\t.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,\n \t},\n \t{\n+\t\t.mode = UHS_SDR12,\n+\t\t.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,\n+\t},\n+\t{\n \t\t.mode = SD_LEGACY,\n \t\t.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,\n \t}\n@@ -1306,18 +1443,24 @@ static int sd_select_mode_and_width(struct mmc *mmc)\n \tint err;\n \tuint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT};\n \tconst struct mode_width_tuning *mwt;\n+\tbool uhs_en = (mmc->ocr & OCR_S18R) ? true : false;\n+\tuint caps;\n+\n \n \terr = sd_get_capabilities(mmc);\n \tif (err)\n \t\treturn err;\n \t/* Restrict card's capabilities by what the host can do */\n-\tmmc->card_caps &= (mmc->cfg->host_caps | MMC_MODE_1BIT);\n+\tcaps = mmc->card_caps & (mmc->cfg->host_caps | MMC_MODE_1BIT);\n \n-\tfor_each_sd_mode_by_pref(mmc->card_caps, mwt) {\n+\tif (!uhs_en)\n+\t\tcaps &= ~UHS_CAPS;\n+\n+\tfor_each_sd_mode_by_pref(caps, mwt) {\n \t\tuint *w;\n \n \t\tfor (w = widths; w < widths + ARRAY_SIZE(widths); w++) {\n-\t\t\tif (*w & mmc->card_caps & mwt->widths) {\n+\t\t\tif (*w & caps & mwt->widths) {\n \t\t\t\tdebug(\"trying mode %s width %d (at %d MHz)\\n\",\n \t\t\t\t mmc_mode_name(mwt->mode),\n \t\t\t\t bus_width(*w),\n@@ -1338,6 +1481,16 @@ static int sd_select_mode_and_width(struct mmc *mmc)\n \t\t\t\tmmc_select_mode(mmc, mwt->mode);\n \t\t\t\tmmc_set_clock(mmc, mmc->tran_speed, false);\n \n+\t\t\t\t/* execute tuning if needed */\n+\t\t\t\tif (mwt->tuning && !mmc_host_is_spi(mmc)) {\n+\t\t\t\t\terr = mmc_execute_tuning(mmc,\n+\t\t\t\t\t\t\t\t mwt->tuning);\n+\t\t\t\t\tif (err) {\n+\t\t\t\t\t\tdebug(\"tuning failed\\n\");\n+\t\t\t\t\t\tgoto error;\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\n \t\t\t\terr = sd_read_ssr(mmc);\n \t\t\t\tif (!err)\n \t\t\t\t\treturn 0;\n@@ -2000,7 +2153,7 @@ static int mmc_power_off(struct mmc *mmc)\n \t\tint ret = regulator_set_enable(mmc->vmmc_supply, false);\n \n \t\tif (ret) {\n-\t\t\tputs(\"Error disabling VMMC supply\\n\");\n+\t\t\tdebug(\"Error disabling VMMC supply\\n\");\n \t\t\treturn ret;\n \t\t}\n \t}\n@@ -2026,6 +2179,7 @@ static int mmc_power_cycle(struct mmc *mmc)\n int mmc_start_init(struct mmc *mmc)\n {\n \tbool no_card;\n+\tbool uhs_en = supports_uhs(mmc->cfg->host_caps);\n \tint err;\n \n \t/* we pretend there's no card when init is NULL */\n@@ -2065,6 +2219,7 @@ int mmc_start_init(struct mmc *mmc)\n #endif\n \tmmc->ddr_mode = 0;\n \n+retry:\n \tmmc_set_initial_state(mmc);\n \tmmc_send_init_stream(mmc);\n \n@@ -2081,7 +2236,12 @@ int mmc_start_init(struct mmc *mmc)\n \terr = mmc_send_if_cond(mmc);\n \n \t/* Now try to get the SD card's operating condition */\n-\terr = sd_send_op_cond(mmc);\n+\terr = sd_send_op_cond(mmc, uhs_en);\n+\tif (err && uhs_en) {\n+\t\tuhs_en = false;\n+\t\tmmc_power_cycle(mmc);\n+\t\tgoto retry;\n+\t}\n \n \t/* If the command timed out, we check for an MMC card */\n \tif (err == -ETIMEDOUT) {\ndiff --git a/include/mmc.h b/include/mmc.h\nindex 407fddf..ba4a13e8 100644\n--- a/include/mmc.h\n+++ b/include/mmc.h\n@@ -87,6 +87,7 @@\n #define MMC_CMD_SET_BLOCKLEN\t\t16\n #define MMC_CMD_READ_SINGLE_BLOCK\t17\n #define MMC_CMD_READ_MULTIPLE_BLOCK\t18\n+#define MMC_CMD_SEND_TUNING_BLOCK\t\t19\n #define MMC_CMD_SEND_TUNING_BLOCK_HS200\t21\n #define MMC_CMD_SET_BLOCK_COUNT 23\n #define MMC_CMD_WRITE_SINGLE_BLOCK\t24\n@@ -117,7 +118,8 @@\n \n static inline bool mmc_is_tuning_cmd(uint cmdidx)\n {\n-\tif (cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200)\n+\tif ((cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200) ||\n+\t (cmdidx == MMC_CMD_SEND_TUNING_BLOCK))\n \t\treturn true;\n \treturn false;\n }\n@@ -126,8 +128,22 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)\n #define SD_HIGHSPEED_BUSY\t0x00020000\n #define SD_HIGHSPEED_SUPPORTED\t0x00020000\n \n+#define UHS_SDR12_BUS_SPEED\t0\n+#define HIGH_SPEED_BUS_SPEED\t1\n+#define UHS_SDR25_BUS_SPEED\t1\n+#define UHS_SDR50_BUS_SPEED\t2\n+#define UHS_SDR104_BUS_SPEED\t3\n+#define UHS_DDR50_BUS_SPEED\t4\n+\n+#define SD_MODE_UHS_SDR12\tBIT(UHS_SDR12_BUS_SPEED)\n+#define SD_MODE_UHS_SDR25\tBIT(UHS_SDR25_BUS_SPEED)\n+#define SD_MODE_UHS_SDR50\tBIT(UHS_SDR50_BUS_SPEED)\n+#define SD_MODE_UHS_SDR104\tBIT(UHS_SDR104_BUS_SPEED)\n+#define SD_MODE_UHS_DDR50\tBIT(UHS_DDR50_BUS_SPEED)\n+\n #define OCR_BUSY\t\t0x80000000\n #define OCR_HCS\t\t\t0x40000000\n+#define OCR_S18R\t\t0x1000000\n #define OCR_VOLTAGE_MASK\t0x007FFF80\n #define OCR_ACCESS_MODE\t\t0x60000000\n \n@@ -410,6 +426,17 @@ struct dm_mmc_ops {\n \t * @return 0 if OK, -ve on error\n \t */\n \tint (*execute_tuning)(struct udevice *dev, uint opcode);\n+\n+\t/**\n+\t * wait_dat0() - wait until dat0 is in the target state\n+\t *\t\t(CLK must be running during the wait)\n+\t *\n+\t * @dev:\tDevice to check\n+\t * @state:\ttarget state\n+\t * @timeout:\ttimeout in us\n+\t * @return 0 if dat0 is in the target state, -ve on error\n+\t */\n+\tint (*wait_dat0)(struct udevice *dev, int state, int timeout);\n };\n \n #define mmc_get_ops(dev) ((struct dm_mmc_ops *)(dev)->driver->ops)\n@@ -421,6 +448,7 @@ void dm_mmc_send_init_stream(struct udevice *dev);\n int dm_mmc_get_cd(struct udevice *dev);\n int dm_mmc_get_wp(struct udevice *dev);\n int dm_mmc_execute_tuning(struct udevice *dev, uint opcode);\n+int dm_mmc_wait_dat0(struct udevice *dev, int state, int timeout);\n \n /* Transition functions for compatibility */\n int mmc_set_ios(struct mmc *mmc);\n@@ -428,6 +456,7 @@ void mmc_send_init_stream(struct mmc *mmc);\n int mmc_getcd(struct mmc *mmc);\n int mmc_getwp(struct mmc *mmc);\n int mmc_execute_tuning(struct mmc *mmc, uint opcode);\n+int mmc_wait_dat0(struct mmc *mmc, int state, int timeout);\n \n #else\n struct mmc_ops {\n@@ -486,6 +515,15 @@ static inline bool mmc_is_mode_ddr(enum bus_mode mode)\n \t\treturn false;\n }\n \n+#define UHS_CAPS (MMC_CAP(UHS_SDR12) | MMC_CAP(UHS_SDR25) | \\\n+\t\t MMC_CAP(UHS_SDR50) | MMC_CAP(UHS_SDR104) | \\\n+\t\t MMC_CAP(UHS_DDR50))\n+\n+static inline bool supports_uhs(uint caps)\n+{\n+\treturn (caps & UHS_CAPS) ? true : false;\n+}\n+\n /*\n * With CONFIG_DM_MMC enabled, struct mmc can be accessed from the MMC device\n * with mmc_get_mmc_dev().\n", "prefixes": [ "U-Boot", "v2", "20/26" ] }