From patchwork Thu Jan 14 01:08:02 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Shawn Lin X-Patchwork-Id: 8029051 Return-Path: X-Original-To: patchwork-linux-mmc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id AF0D8BEEE5 for ; Thu, 14 Jan 2016 01:13:49 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C4F90203F7 for ; Thu, 14 Jan 2016 01:13:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id DC195203DF for ; Thu, 14 Jan 2016 01:13:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755145AbcANBMz (ORCPT ); Wed, 13 Jan 2016 20:12:55 -0500 Received: from lucky1.263xmail.com ([211.157.147.130]:48174 "EHLO lucky1.263xmail.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752712AbcANBMw (ORCPT ); Wed, 13 Jan 2016 20:12:52 -0500 Received: from shawn.lin?rock-chips.com (unknown [192.168.167.11]) by lucky1.263xmail.com (Postfix) with SMTP id ECAA51E8A17; Thu, 14 Jan 2016 09:12:47 +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 D751747C; Thu, 14 Jan 2016 09:12:46 +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: <74c3a02da3106b2b2c5c59e9de52b0a0> 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 32653QV8HF; Thu, 14 Jan 2016 09:12:47 +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 v3] mmc: dw_mmc: add hw_reset support Date: Thu, 14 Jan 2016 09:08:02 +0800 Message-Id: <1452733682-3164-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=unavailable 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. Set the following resets: software reset – BMOD[0] for IDMAC only DMA reset– CTRL[2] FIFO reset – CTRL[1] bits Program the CARD_RESET register with a value of 0 for the bit corresponding to the card number; This programming asserts the RST_n signal and resets the card. After a minimum of 1 ?s, de-asserts the RST_n signal and takes the card out of reset. The application can program a new CMD only after a minimum of 200 us This implementation can be easily tested by cutting off->On vmmc while doing data accessing in background to simulate that case. Signed-off-by: Shawn Lin --- Changes in v3: - reset for each slot - simply the commit msg 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 | 29 +++++++++++++++++++++++++++++ drivers/mmc/host/dw_mmc.h | 3 +++ 2 files changed, 32 insertions(+) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 7128351..fddbcb6 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1477,6 +1477,34 @@ 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; + int reset; + + 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 + */ + reset = mci_readl(host, RST_N); + reset &= ~(SDMMC_RST_HWACTIVE << slot->id); + mci_writel(slot->host, RST_N, reset); + usleep_range(1, 2); + reset |= SDMMC_RST_HWACTIVE << slot->id; + mci_writel(slot->host, RST_N, reset); + 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 +1591,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..a14b7fc 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,8 @@ #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 /* Version ID register define */ #define SDMMC_GET_VERID(x) ((x) & 0xFFFF) /* Card read threshold */