From patchwork Wed Nov 16 10:51:20 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 82476 Delivered-To: patches@linaro.org Received: by 10.140.97.165 with SMTP id m34csp82440qge; Wed, 16 Nov 2016 02:51:46 -0800 (PST) X-Received: by 10.194.72.100 with SMTP id c4mr1396167wjv.188.1479293506803; Wed, 16 Nov 2016 02:51:46 -0800 (PST) Return-Path: Received: from mail-wm0-x230.google.com (mail-wm0-x230.google.com. [2a00:1450:400c:c09::230]) by mx.google.com with ESMTPS id m65si6764963wme.8.2016.11.16.02.51.46 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 16 Nov 2016 02:51:46 -0800 (PST) Received-SPF: pass (google.com: domain of ulf.hansson@linaro.org designates 2a00:1450:400c:c09::230 as permitted sender) client-ip=2a00:1450:400c:c09::230; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: domain of ulf.hansson@linaro.org designates 2a00:1450:400c:c09::230 as permitted sender) smtp.mailfrom=ulf.hansson@linaro.org; dmarc=pass (p=NONE dis=NONE) header.from=linaro.org Received: by mail-wm0-x230.google.com with SMTP id a197so230842755wmd.0 for ; Wed, 16 Nov 2016 02:51:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=O9IE6i3mevMcODbo2Io2WX6TS/YHYF1NngRrjrd5oyY=; b=CMjrQtADmzffwWWyoGNVkTlpyzP4L5ApQQFnWqqq4/FMku4NFnJmna8H29ZFp6Td0X y77abiu+BjFESMIaH5FQRQ3nxYqp3vNAt7GizRIghbE26jP9ovl9LR2qtm4P4HMcOX1X 3kHEWhv1SMuZuvF0FH+aJZ6dsLOsaW6Ep6wkw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=O9IE6i3mevMcODbo2Io2WX6TS/YHYF1NngRrjrd5oyY=; b=fQ3rKrU5+lw7ch5iguRzWi6KiTgkwIntxpwmN6jT/gqlRuEtcIqIB2tTTrLLQp0fWg XQItEgyjHmmiSo5x6c5VQvPOR0NRD1xmzOkEWssQDqW60LHtpL8F5/I5ZTraPISvjPFB WOnpoTsJa07pBpuh2Dtnf8r0WU76z6I7f5YHrCXfmpZXXjQ2wE/a12zFZHib3VwsLBqi KCST6SLnZSI1r9HzZqKJmKFC5TYSZqFptggktBcEXAnBHjRrJl5C+rV3n2xPCaXj4fdD kFtCuwEJe59dfQG4u9SLepwJlW4mc7Jth2LDKTzWbQDBQqy2ZFuwWDlcpmPKWR2Eq/Fz VetA== X-Gm-Message-State: ABUngvece8kiSGKcYqAGjiAduTW3VlyW/oSQYgYSmUdadEJDi0MwkHWFUrP6YYvDGtwzKvwjYac= X-Received: by 10.25.151.69 with SMTP id z66mr856962lfd.98.1479293506322; Wed, 16 Nov 2016 02:51:46 -0800 (PST) Return-Path: Received: from uffe-Latitude-E6430s.ideon.se ([85.235.10.227]) by smtp.gmail.com with ESMTPSA id 34sm7711369lja.25.2016.11.16.02.51.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 16 Nov 2016 02:51:45 -0800 (PST) From: Ulf Hansson To: linux-mmc@vger.kernel.org, Ulf Hansson Cc: Jaehoon Chung , Adrian Hunter , Linus Walleij , Chaotian Jing , Stephen Boyd , Michael Walle , Yong Mao , Shawn Lin Subject: [PATCH 8/9] mmc: core: Allow CMD13 polling when switch to HS400 mode Date: Wed, 16 Nov 2016 11:51:20 +0100 Message-Id: <1479293481-20186-9-git-send-email-ulf.hansson@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1479293481-20186-1-git-send-email-ulf.hansson@linaro.org> References: <1479293481-20186-1-git-send-email-ulf.hansson@linaro.org> In cases when the mmc host doesn't support HW busy detection, polling for busy by using CMD13 is beneficial. The reasons have already been explained in earlier change logs. Moreover, when polling with CMD13 during bus timing changes, we should retry instead of fail when we get CRC errors. Switching from HS200 to HS400 and reverse includes several steps, where each step changes the bus speed timing. Let's improve the behaviour during these sequences, by allowing CMD13 polling for each of the step. Let's also make sure the CMD13 polling becomes retried, while receiving a CRC error. Signed-off-by: Ulf Hansson --- drivers/mmc/core/mmc.c | 87 +++++++++++++++----------------------------------- 1 file changed, 26 insertions(+), 61 deletions(-) -- 1.9.1 diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 0b26383..24b9e72 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1094,8 +1094,7 @@ static int mmc_select_hs_ddr(struct mmc_card *card) static int mmc_select_hs400(struct mmc_card *card) { struct mmc_host *host = card->host; - unsigned int max_dtr; - int err = 0; + int err; u8 val; /* @@ -1105,34 +1104,26 @@ static int mmc_select_hs400(struct mmc_card *card) host->ios.bus_width == MMC_BUS_WIDTH_8)) return 0; - /* Switch card to HS mode */ - val = EXT_CSD_TIMING_HS; - err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_HS_TIMING, val, - card->ext_csd.generic_cmd6_time, 0, - true, false, true); + /* + * Switch card to HS mode. + * First reduce to the HS frequency as CMD13 are sent to poll for busy + * and/or to validate the switch status. + */ + mmc_set_clock(host, card->ext_csd.hs_max_dtr); + err = mmc_select_hs(card); if (err) { pr_err("%s: switch to high-speed from hs200 failed, err:%d\n", mmc_hostname(host), err); return err; } - /* Set host controller to HS timing */ - mmc_set_timing(card->host, MMC_TIMING_MMC_HS); - - /* Reduce frequency to HS frequency */ - max_dtr = card->ext_csd.hs_max_dtr; - mmc_set_clock(host, max_dtr); - - err = mmc_switch_status(card); - if (err) - goto out_err; - - /* Switch card to DDR */ - err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_BUS_WIDTH, - EXT_CSD_DDR_BUS_WIDTH_8, - card->ext_csd.generic_cmd6_time); + /* Switch card to HS DDR */ + err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_BUS_WIDTH, + EXT_CSD_DDR_BUS_WIDTH_8, + card->ext_csd.generic_cmd6_time, + MMC_TIMING_MMC_DDR52, + true, true, true); if (err) { pr_err("%s: switch to bus width for hs400 failed, err:%d\n", mmc_hostname(host), err); @@ -1144,28 +1135,17 @@ static int mmc_select_hs400(struct mmc_card *card) card->drive_strength << EXT_CSD_DRV_STR_SHIFT; err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, - card->ext_csd.generic_cmd6_time, 0, - true, false, true); + card->ext_csd.generic_cmd6_time, + MMC_TIMING_MMC_HS400, + true, true, true); if (err) { pr_err("%s: switch to hs400 failed, err:%d\n", mmc_hostname(host), err); return err; } - /* Set host controller to HS400 timing and frequency */ - mmc_set_timing(host, MMC_TIMING_MMC_HS400); mmc_set_bus_speed(card); - - err = mmc_switch_status(card); - if (err) - goto out_err; - return 0; - -out_err: - pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host), - __func__, err); - return err; } int mmc_hs200_to_hs400(struct mmc_card *card) @@ -1187,27 +1167,17 @@ int mmc_hs400_to_hs200(struct mmc_card *card) /* Switch HS400 to HS DDR */ val = EXT_CSD_TIMING_HS; err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, - val, card->ext_csd.generic_cmd6_time, 0, - true, false, true); - if (err) - goto out_err; - - mmc_set_timing(host, MMC_TIMING_MMC_DDR52); - - err = mmc_switch_status(card); + val, card->ext_csd.generic_cmd6_time, + MMC_TIMING_MMC_DDR52, + true, true, true); if (err) goto out_err; /* Switch HS DDR to HS */ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_8, card->ext_csd.generic_cmd6_time, - 0, true, false, true); - if (err) - goto out_err; - - mmc_set_timing(host, MMC_TIMING_MMC_HS); - - err = mmc_switch_status(card); + MMC_TIMING_MMC_HS, + true, true, true); if (err) goto out_err; @@ -1215,14 +1185,9 @@ int mmc_hs400_to_hs200(struct mmc_card *card) val = EXT_CSD_TIMING_HS200 | card->drive_strength << EXT_CSD_DRV_STR_SHIFT; err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, - val, card->ext_csd.generic_cmd6_time, 0, - true, false, true); - if (err) - goto out_err; - - mmc_set_timing(host, MMC_TIMING_MMC_HS200); - - err = mmc_switch_status(card); + val, card->ext_csd.generic_cmd6_time, + MMC_TIMING_MMC_HS200, + true, true, true); if (err) goto out_err;