From patchwork Mon Jan 4 02:50:54 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Shawn Lin X-Patchwork-Id: 7944821 Return-Path: X-Original-To: patchwork-linux-mmc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 07ED29F350 for ; Mon, 4 Jan 2016 02:56:10 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DC45120384 for ; Mon, 4 Jan 2016 02:56:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6330520361 for ; Mon, 4 Jan 2016 02:56:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752136AbcADC4G (ORCPT ); Sun, 3 Jan 2016 21:56:06 -0500 Received: from lucky1.263xmail.com ([211.157.147.132]:52084 "EHLO lucky1.263xmail.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751974AbcADC4F (ORCPT ); Sun, 3 Jan 2016 21:56:05 -0500 Received: from shawn.lin?rock-chips.com (unknown [192.168.167.78]) by lucky1.263xmail.com (Postfix) with SMTP id 7ABB05D15B; Mon, 4 Jan 2016 10:55:48 +0800 (CST) X-263anti-spam: KSV:0; X-MAIL-GRAY: 1 X-MAIL-DELIVERY: 0 X-KSVirus-check: 0 X-ABS-CHECKED: 4 X-ADDR-CHECKED: 0 Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.263.net (Postfix) with ESMTP id 075F0290F8; Mon, 4 Jan 2016 10:55:43 +0800 (CST) X-RL-SENDER: shawn.lin@rock-chips.com X-FST-TO: jh80.chung@samsung.com X-SENDER-IP: 58.22.7.114 X-LOGIN-NAME: shawn.lin@rock-chips.com X-UNIQUE-TAG: X-ATTACHMENT-NUM: 0 X-SENDER: lintao@rock-chips.com X-DNS-TYPE: 0 Received: from localhost.localdomain (unknown [58.22.7.114]) by smtp.263.net (Postfix) whith ESMTP id 234459BPCNY; Mon, 04 Jan 2016 10:55:44 +0800 (CST) From: Shawn Lin To: Jaehoon Chung , Ulf Hansson Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, Shawn Lin Subject: [PATCH v2] mmc: dw_mmc: add hw_reset support Date: Mon, 4 Jan 2016 10:50:54 +0800 Message-Id: <1451875854-12521-1-git-send-email-shawn.lin@rock-chips.com> X-Mailer: git-send-email 1.8.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch implement hw_reset function for DesignWare MMC controller. By adding this feature, mmc blk can do some basic recovery. From Synopsys DesignWare Cores Mobile Storage Host Databook (Section 7.4.4), we get the details: 1. Program CMD12 to end any transfer in process. 2. Wait for DTO, even if no response is sent back by the card. 3. Set the following resets: Software reset – BMOD[0] for IDMAC only DMA reset– CTRL[2] FIFO reset – CTRL[1] bits 4. Program the CARD_RESET register with a value of 0 for the bit corresponding to the card number; This can be done at any time when the card is connected to the controller. This programming asserts the RST_n signal and resets the card. 5. Wait for minimum of 1 ?s or cclk_in period, which ever is greater 6. After a minimum of 1 ?s, the application should program a value of 0 into the CARD_RESET register for the bit corresponding to the card number. This de-asserts the RST_n signal and takes the card out of reset. 7. The application can program a new CMD only after a minimum of 200 us after the de-assertion of the RST_n signal, as per the MMC 4.41 standard. HW reset producer will be call in mmc_init_card before mmc_go_idle. At that time?dw mmc hasn't update clk for itself, so CMD12 is inappropriate and unnecessary. Moreover, if mmc device runs into broken states, DRTO or RTO generated by previous cmd w/ data will make mmc core issue stop already. Then it will retry again and again, issue stop and card status again until the cmd's retry number decrease to zero. That will finally trigger HW reset producer if we declare MMC_CAP_HW_RESET. So there's no need to do step 1 and 2 for the reasons we mentioned above. This implementation can be easily tested by cutting off->On vmmc while doing data accessing in background to simulate that case. And dw_mmc can generate timeout interrupt and make mmc core trigger hw reset producer before re-init mmc card to recover itself. Signed-off-by: Shawn Lin --- Changes in v2: - remove unecessary mb - reduce time cost for hw_reset - combine SDMMC_CTRL_DMA_RESET and SDMMC_CTRL_FIFO_RESET drivers/mmc/host/dw_mmc.c | 25 +++++++++++++++++++++++++ drivers/mmc/host/dw_mmc.h | 4 ++++ 2 files changed, 29 insertions(+) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 7128351..98e75fc 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1477,6 +1477,30 @@ static int dw_mci_get_cd(struct mmc_host *mmc) return present; } +static void dw_mci_hw_reset(struct mmc_host *mmc) +{ + struct dw_mci_slot *slot = mmc_priv(mmc); + struct dw_mci *host = slot->host; + + if (host->use_dma == TRANS_MODE_IDMAC) + dw_mci_idmac_reset(host); + + if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_DMA_RESET | + SDMMC_CTRL_FIFO_RESET)) + return; + + /* + * According to eMMC spec, card reset procedure: + * tRstW >= 1us: RST_n pulse width + * tRSCA >= 200us: RST_n to Command time + * tRSTH >= 1us: RST_n high period + */ + mci_writel(slot->host, RST_N, SDMMC_RST_HWRESET); + usleep_range(1, 2); + mci_writel(slot->host, RST_N, SDMMC_RST_HWACTIVE); + usleep_range(200, 300); +} + static void dw_mci_init_card(struct mmc_host *mmc, struct mmc_card *card) { struct dw_mci_slot *slot = mmc_priv(mmc); @@ -1563,6 +1587,7 @@ static const struct mmc_host_ops dw_mci_ops = { .set_ios = dw_mci_set_ios, .get_ro = dw_mci_get_ro, .get_cd = dw_mci_get_cd, + .hw_reset = dw_mci_hw_reset, .enable_sdio_irq = dw_mci_enable_sdio_irq, .execute_tuning = dw_mci_execute_tuning, .card_busy = dw_mci_card_busy, diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index f695b58..684ee34 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -46,6 +46,7 @@ #define SDMMC_VERID 0x06c #define SDMMC_HCON 0x070 #define SDMMC_UHS_REG 0x074 +#define SDMMC_RST_N 0x078 #define SDMMC_BMOD 0x080 #define SDMMC_PLDMND 0x084 #define SDMMC_DBADDR 0x088 @@ -169,6 +170,9 @@ #define SDMMC_IDMAC_ENABLE BIT(7) #define SDMMC_IDMAC_FB BIT(1) #define SDMMC_IDMAC_SWRESET BIT(0) +/* H/W reset */ +#define SDMMC_RST_HWACTIVE 0x1 +#define SDMMC_RST_HWRESET 0x0 /* Version ID register define */ #define SDMMC_GET_VERID(x) ((x) & 0xFFFF) /* Card read threshold */