Received: by 2002:a05:6a11:4021:0:0:0:0 with SMTP id ky33csp2601224pxb; Fri, 17 Sep 2021 13:45:51 -0700 (PDT) X-Google-Smtp-Source: ABdhPJycKGNQcNLHyMAuVs2oIMm1VA954tPJkFH+NhBPs/mIiuFU2H+ITmVcl3+WMO7pmh34RA1r X-Received: by 2002:a17:906:f88a:: with SMTP id lg10mr14643519ejb.13.1631911551708; Fri, 17 Sep 2021 13:45:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1631911551; cv=none; d=google.com; s=arc-20160816; b=DC/Q4dpXiyaw6b/ybAHhdWQOZ8Ojs6XH/LOrxWLTEe3SQhMF021h9vQeqGbWyUwksA Poa9ZTjw9M/m/dGJfe27VpoWS0uOrWEr8G1JlYmzS6zGqDoRSqOjVshbw096lcVZ6Oxf XR0Nb8xAdUNFqD0wtEzoMZa2fohufWK7FyVt0NqcLUf7YBZKwPkGalJnR4oRibO4CfSx JHNwIsOLDb87Oe7OxPE3ChErCU1MTak07fDoQ6Azg/bPlUS8tGWpHJD3MDKYWjqmN/ng yMUbNSUWcvg+jxSDuRAU4FCo2tPLe5DU4iZ1rmChs81opb/YGmwZxNYabQbQKlKLS3c0 Rjsw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=dWDmYhgxmpF3lGds6p6XJLSwmqB315IchoPRRLEak+Q=; b=pYJ3nnThiqtNWqsD5nfiKgkcuhxG6XChpkvRSlThGomzai/rT3EL+1ZmiyvprARflp JQiaJxXc+j16wr4qrhNvDBXNZVE5A2R/butGZQH9Nvi09jPgluDLKGU01EjAszATkbMl 9v/V79quMj/wXm33Kh0WUDFznjN/q0tYp2nLaIKlE54CTrhqM/dUDsnTPM+5n4tsTOkk w+4Lh9Bk9lWlKILY4EBBmYFOSN4TrryqkFWYwcp5NKrXhwbxjyUhnhwwHIAQMHHkoHYv l4Sj3vfwsqtsIz4jOHQ+yzV+T+t5X6O7DuggrVYZeuJUvUjfeiNtBj8OgtYg7OmmhCEH QSWA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=mediatek.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id n15si8769415ejd.124.2021.09.17.13.45.24; Fri, 17 Sep 2021 13:45:51 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=mediatek.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244447AbhIQMkW (ORCPT + 99 others); Fri, 17 Sep 2021 08:40:22 -0400 Received: from mailgw01.mediatek.com ([60.244.123.138]:39374 "EHLO mailgw01.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S233162AbhIQMkU (ORCPT ); Fri, 17 Sep 2021 08:40:20 -0400 X-UUID: 3293024e88d54a11b24b152e45fa9f50-20210917 X-UUID: 3293024e88d54a11b24b152e45fa9f50-20210917 Received: from mtkmbs10n2.mediatek.inc [(172.21.101.183)] by mailgw01.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 1268936350; Fri, 17 Sep 2021 20:38:56 +0800 Received: from mtkcas07.mediatek.inc (172.21.101.84) by mtkmbs06n1.mediatek.inc (172.21.101.129) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Fri, 17 Sep 2021 20:38:55 +0800 Received: from localhost.localdomain (10.17.3.154) by mtkcas07.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Fri, 17 Sep 2021 20:38:54 +0800 From: Wenbin Mei To: Ulf Hansson , Rob Herring , Matthias Brugger CC: Chaotian Jing , Avri Altman , Wenbin Mei , Wolfram Sang , Yoshihiro Shimoda , Linus Walleij , Yue Hu , Bean Huo , Adrian Hunter , , , , , Subject: [PATCH 3/3] mmc: mediatek: Add HS400 online tuning support Date: Fri, 17 Sep 2021 20:38:51 +0800 Message-ID: <20210917123851.22741-4-wenbin.mei@mediatek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210917123851.22741-1-wenbin.mei@mediatek.com> References: <20210917123851.22741-1-wenbin.mei@mediatek.com> MIME-Version: 1.0 Content-Transfer-Encoding: 7BIT Content-Type: text/plain; charset=US-ASCII X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org According to JEDEC Spec, there is no need to do tuning under HS400 mode since the Rx signal is aligned with the DS signal. However, MediaTek's IC need set its "DS delay" internally to ensure it can latch Rx signal correctly. In previous version, We provide an "hs400-ds-delay" in device tree to cover different chipset/PCB design, and it works fine in most cases. But, with the development of process technology and the big VCore voltage scale range(may have 0.7V/0.6V/0.55V), it is difficult to find a suitable "hs400-ds-delay" to cover all of IC corner cases(SSSS/TTTT/FFFF). So that We must have the ability to do hs400 online tuning. Signed-off-by: Wenbin Mei Reviewed-by: Chaotian Jing --- drivers/mmc/host/mtk-sd.c | 79 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 4dfc246c5f95..5f98f869545d 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -258,6 +258,7 @@ #define MSDC_PAD_TUNE_RD_SEL (0x1 << 13) /* RW */ #define MSDC_PAD_TUNE_CMD_SEL (0x1 << 21) /* RW */ +#define PAD_DS_TUNE_DLY_SEL (0x1 << 0) /* RW */ #define PAD_DS_TUNE_DLY1 (0x1f << 2) /* RW */ #define PAD_DS_TUNE_DLY2 (0x1f << 7) /* RW */ #define PAD_DS_TUNE_DLY3 (0x1f << 12) /* RW */ @@ -301,6 +302,11 @@ #define PAD_CMD_RD_RXDLY_SEL (0x1 << 11) /* RW */ #define PAD_CMD_TX_DLY (0x1f << 12) /* RW */ +/* EMMC50_PAD_DS_TUNE mask */ +#define PAD_DS_DLY_SEL (0x1 << 16) /* RW */ +#define PAD_DS_DLY1 (0x1f << 10) /* RW */ +#define PAD_DS_DLY3 (0x1f << 0) /* RW */ + #define REQ_CMD_EIO (0x1 << 0) #define REQ_CMD_TMO (0x1 << 1) #define REQ_DAT_ERR (0x1 << 2) @@ -448,11 +454,13 @@ struct msdc_host { bool vqmmc_enabled; u32 latch_ck; u32 hs400_ds_delay; + u32 hs400_ds_dly3; u32 hs200_cmd_int_delay; /* cmd internal delay for HS200/SDR104 */ u32 hs400_cmd_int_delay; /* cmd internal delay for HS400 */ bool hs400_cmd_resp_sel_rising; /* cmd response sample selection for HS400 */ bool hs400_mode; /* current eMMC will run at hs400 mode */ + bool hs400_tuning; /* hs400 mode online tuning */ bool internal_cd; /* Use internal card-detect logic */ bool cqhci; /* support eMMC hw cmdq */ struct msdc_save_para save_para; /* used when gate HCLK */ @@ -1190,7 +1198,8 @@ static bool msdc_cmd_done(struct msdc_host *host, int events, if (!sbc_error && !(events & MSDC_INT_CMDRDY)) { if (events & MSDC_INT_CMDTMO || (cmd->opcode != MMC_SEND_TUNING_BLOCK && - cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200)) + cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200 && + !host->hs400_tuning)) /* * should not clear fifo/interrupt as the tune data * may have alreay come when cmd19/cmd21 gets response @@ -1287,7 +1296,8 @@ static void msdc_cmd_next(struct msdc_host *host, if ((cmd->error && !(cmd->error == -EILSEQ && (cmd->opcode == MMC_SEND_TUNING_BLOCK || - cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200))) || + cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200 || + host->hs400_tuning))) || (mrq->sbc && mrq->sbc->error)) msdc_request_done(host, mrq); else if (cmd == mrq->sbc) @@ -2251,6 +2261,67 @@ static int msdc_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) return 0; } +static int msdc_execute_hs400_tuning(struct mmc_host *mmc, struct mmc_card *card) +{ + struct msdc_host *host = mmc_priv(mmc); + struct msdc_delay_phase dly1_delay; + u32 val, result_dly1 = 0; + u8 *ext_csd; + int i, ret; + + if (host->top_base) { + sdr_set_bits(host->top_base + EMMC50_PAD_DS_TUNE, + PAD_DS_DLY_SEL); + if (host->hs400_ds_dly3) + sdr_set_field(host->top_base + EMMC50_PAD_DS_TUNE, + PAD_DS_DLY3, host->hs400_ds_dly3); + } else { + sdr_set_bits(host->base + PAD_DS_TUNE, PAD_DS_TUNE_DLY_SEL); + if (host->hs400_ds_dly3) + sdr_set_field(host->base + PAD_DS_TUNE, + PAD_DS_TUNE_DLY3, host->hs400_ds_dly3); + } + + host->hs400_tuning = true; + for (i = 0; i < PAD_DELAY_MAX; i++) { + if (host->top_base) + sdr_set_field(host->top_base + EMMC50_PAD_DS_TUNE, + PAD_DS_DLY1, i); + else + sdr_set_field(host->base + PAD_DS_TUNE, + PAD_DS_TUNE_DLY1, i); + ret = mmc_get_ext_csd(card, &ext_csd); + if (!ret) + result_dly1 |= (1 << i); + } + host->hs400_tuning = false; + + dly1_delay = get_best_delay(host, result_dly1); + if (dly1_delay.maxlen == 0) { + dev_err(host->dev, "Failed to get DLY1 delay!\n"); + goto fail; + } + if (host->top_base) + sdr_set_field(host->top_base + EMMC50_PAD_DS_TUNE, + PAD_DS_DLY1, dly1_delay.final_phase); + else + sdr_set_field(host->base + PAD_DS_TUNE, + PAD_DS_TUNE_DLY1, dly1_delay.final_phase); + + if (host->top_base) + val = readl(host->top_base + EMMC50_PAD_DS_TUNE); + else + val = readl(host->base + PAD_DS_TUNE); + + dev_info(host->dev, "Fianl PAD_DS_TUNE: 0x%x\n", val); + + return 0; + +fail: + dev_err(host->dev, "Failed to tuning DS pin delay!\n"); + return -EIO; +} + static void msdc_hw_reset(struct mmc_host *mmc) { struct msdc_host *host = mmc_priv(mmc); @@ -2377,6 +2448,7 @@ static const struct mmc_host_ops mt_msdc_ops = { .card_busy = msdc_card_busy, .execute_tuning = msdc_execute_tuning, .prepare_hs400_tuning = msdc_prepare_hs400_tuning, + .execute_hs400_tuning = msdc_execute_hs400_tuning, .hw_reset = msdc_hw_reset, }; @@ -2396,6 +2468,9 @@ static void msdc_of_property_parse(struct platform_device *pdev, of_property_read_u32(pdev->dev.of_node, "hs400-ds-delay", &host->hs400_ds_delay); + of_property_read_u32(pdev->dev.of_node, "mediatek,hs400-ds-dly3", + &host->hs400_ds_dly3); + of_property_read_u32(pdev->dev.of_node, "mediatek,hs200-cmd-int-delay", &host->hs200_cmd_int_delay); -- 2.25.1