All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sonny Rao <sonnyrao@chromium.org>
To: linux-mmc@vger.kernel.org
Cc: grundler@chromium.org, linux-samsung-soc@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, jh80.chung@samsung.com,
	cjb@laptop.org, tgih.jun@samsung.com, kgene.kim@samsung.com,
	joshi@samsung.com, t.figa@samsung.com, dianders@chromium.org,
	Yuvaraj Kumar C D <yuvaraj.cd@samsung.com>,
	Sonny Rao <sonnyrao@chromium.org>
Subject: [PATCH] mmc: dw_mmc: change to use recommended reset procedure
Date: Wed, 28 May 2014 17:35:09 -0700	[thread overview]
Message-ID: <1401323709-10345-1-git-send-email-sonnyrao@chromium.org> (raw)
In-Reply-To: <CAPz6YkW+eJjoUz0YRb_JOsKXMUhCe4hRUQVQLhZbkfo01fVnqg@mail.gmail.com>

This patch changes the fifo reset code to follow the reset procedure
outlined in the documentation of Synopsys Mobile storage host databook.

Signed-off-by: Sonny Rao <sonnyrao@chromium.org>
Signed-off-by: Yuvaraj Kumar C D <yuvaraj.cd@samsung.com>
---
v2: Add Generic DMA support
    per the documentation, move interrupt clear before wait
    make the test for DMA host->use_dma rather than host->using_dma
    add proper return values (although it appears no caller checks)
v3: rename fifo reset function, and change callers
    use this combined reset function in dw_mci_resume()
    just one caller left (probe), so get rid of dw_mci_ctrl_all_reset()
    use DMA reset bit for all systems which use DMA
    remove extra IDMAC reset in dw_mci_work_routine_card()
    do CIU clock update in error path, if CIU reset cleared

 drivers/mmc/host/dw_mmc.c | 85 +++++++++++++++++++++++++++++++++++------------
 drivers/mmc/host/dw_mmc.h |  1 +
 2 files changed, 64 insertions(+), 22 deletions(-)

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 55cd110..988492c 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -111,8 +111,7 @@ static const u8 tuning_blk_pattern_8bit[] = {
 	0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
 };
 
-static inline bool dw_mci_fifo_reset(struct dw_mci *host);
-static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host);
+static inline bool dw_mci_reset(struct dw_mci *host);
 
 #if defined(CONFIG_DEBUG_FS)
 static int dw_mci_req_show(struct seq_file *s, void *v)
@@ -1254,7 +1253,7 @@ static int dw_mci_data_complete(struct dw_mci *host, struct mmc_data *data)
 		 * After an error, there may be data lingering
 		 * in the FIFO
 		 */
-		dw_mci_fifo_reset(host);
+		dw_mci_reset(host);
 	} else {
 		data->bytes_xfered = data->blocks * data->blksz;
 		data->error = 0;
@@ -1371,7 +1370,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
 
 			/* CMD error in data command */
 			if (mrq->cmd->error && mrq->data)
-				dw_mci_fifo_reset(host);
+				dw_mci_reset(host);
 
 			host->cmd = NULL;
 			host->data = NULL;
@@ -1982,14 +1981,9 @@ static void dw_mci_work_routine_card(struct work_struct *work)
 			}
 
 			/* Power down slot */
-			if (present == 0) {
+			if (present == 0)
 				/* Clear down the FIFO */
-				dw_mci_fifo_reset(host);
-#ifdef CONFIG_MMC_DW_IDMAC
-				dw_mci_idmac_reset(host);
-#endif
-
-			}
+				dw_mci_reset(host);
 
 			spin_unlock_bh(&host->lock);
 
@@ -2323,8 +2317,11 @@ static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset)
 	return false;
 }
 
-static inline bool dw_mci_fifo_reset(struct dw_mci *host)
+static inline bool dw_mci_reset(struct dw_mci *host)
 {
+	u32 flags = SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET;
+	bool ret = false;
+
 	/*
 	 * Reseting generates a block interrupt, hence setting
 	 * the scatter-gather pointer to NULL.
@@ -2334,15 +2331,57 @@ static inline bool dw_mci_fifo_reset(struct dw_mci *host)
 		host->sg = NULL;
 	}
 
-	return dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET);
-}
+	if (host->use_dma)
+		flags |= SDMMC_CTRL_DMA_RESET;
 
-static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host)
-{
-	return dw_mci_ctrl_reset(host,
-				 SDMMC_CTRL_FIFO_RESET |
-				 SDMMC_CTRL_RESET |
-				 SDMMC_CTRL_DMA_RESET);
+	if (dw_mci_ctrl_reset(host, flags)) {
+		/*
+		 * In all cases we clear the RAWINTS register to clear any
+		 * interrupts.
+		 */
+		mci_writel(host, RINTSTS, 0xFFFFFFFF);
+
+		/* if using dma we wait for dma_req to clear */
+		if (host->use_dma) {
+			unsigned long timeout = jiffies + msecs_to_jiffies(500);
+			u32 status;
+			do {
+				status = mci_readl(host, STATUS);
+				if (!(status & SDMMC_STATUS_DMA_REQ))
+					break;
+				cpu_relax();
+			} while (time_before(jiffies, timeout));
+
+			if (status & SDMMC_STATUS_DMA_REQ) {
+				dev_err(host->dev,
+					"%s: Timeout waiting for dma_req to "
+					"clear during reset", __func__);
+				goto ciu_out;
+			}
+
+			/* when using DMA next we reset the fifo again */
+			if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET))
+				goto ciu_out;
+		}
+	} else {
+		dev_err(host->dev, "%s: Reset bits didn't clear", __func__);
+
+		/* if the controller reset bit did clear, then set clock regs */
+		if (!(mci_readl(host, CTRL) & SDMMC_CTRL_RESET))
+			goto ciu_out;
+	}
+
+	if (IS_ENABLED(CONFIG_MMC_DW_IDMAC))
+		/* It is also recommended that we reset and reprogram idmac */
+		dw_mci_idmac_reset(host);
+
+	ret = true;
+
+ciu_out:
+	/* After a CTRL reset we need to have CIU set clock registers  */
+	mci_send_cmd(host->cur_slot, SDMMC_CMD_UPD_CLK, 0);
+
+	return ret;
 }
 
 #ifdef CONFIG_OF
@@ -2432,6 +2471,7 @@ int dw_mci_probe(struct dw_mci *host)
 	const struct dw_mci_drv_data *drv_data = host->drv_data;
 	int width, i, ret = 0;
 	u32 fifo_size;
+	u32 flags;
 	int init_slots = 0;
 
 	if (!host->pdata) {
@@ -2555,7 +2595,8 @@ int dw_mci_probe(struct dw_mci *host)
 	}
 
 	/* Reset all blocks */
-	if (!dw_mci_ctrl_all_reset(host))
+	flags = SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET;
+	if (!dw_mci_ctrl_reset(host, flags))
 		return -ENODEV;
 
 	host->dma_ops = host->pdata->dma_ops;
@@ -2744,7 +2785,7 @@ int dw_mci_resume(struct dw_mci *host)
 		}
 	}
 
-	if (!dw_mci_ctrl_all_reset(host)) {
+	if (!dw_mci_reset(host)) {
 		ret = -ENODEV;
 		return ret;
 	}
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 6bf24ab..2505804 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -129,6 +129,7 @@
 #define SDMMC_CMD_INDX(n)		((n) & 0x1F)
 /* Status register defines */
 #define SDMMC_GET_FCNT(x)		(((x)>>17) & 0x1FFF)
+#define SDMMC_STATUS_DMA_REQ		BIT(31)
 /* FIFOTH register defines */
 #define SDMMC_SET_FIFOTH(m, r, t)	(((m) & 0x7) << 28 | \
 					 ((r) & 0xFFF) << 16 | \
-- 
1.8.3.2


WARNING: multiple messages have this Message-ID (diff)
From: sonnyrao@chromium.org (Sonny Rao)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH] mmc: dw_mmc: change to use recommended reset procedure
Date: Wed, 28 May 2014 17:35:09 -0700	[thread overview]
Message-ID: <1401323709-10345-1-git-send-email-sonnyrao@chromium.org> (raw)
In-Reply-To: <CAPz6YkW+eJjoUz0YRb_JOsKXMUhCe4hRUQVQLhZbkfo01fVnqg@mail.gmail.com>

This patch changes the fifo reset code to follow the reset procedure
outlined in the documentation of Synopsys Mobile storage host databook.

Signed-off-by: Sonny Rao <sonnyrao@chromium.org>
Signed-off-by: Yuvaraj Kumar C D <yuvaraj.cd@samsung.com>
---
v2: Add Generic DMA support
    per the documentation, move interrupt clear before wait
    make the test for DMA host->use_dma rather than host->using_dma
    add proper return values (although it appears no caller checks)
v3: rename fifo reset function, and change callers
    use this combined reset function in dw_mci_resume()
    just one caller left (probe), so get rid of dw_mci_ctrl_all_reset()
    use DMA reset bit for all systems which use DMA
    remove extra IDMAC reset in dw_mci_work_routine_card()
    do CIU clock update in error path, if CIU reset cleared

 drivers/mmc/host/dw_mmc.c | 85 +++++++++++++++++++++++++++++++++++------------
 drivers/mmc/host/dw_mmc.h |  1 +
 2 files changed, 64 insertions(+), 22 deletions(-)

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 55cd110..988492c 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -111,8 +111,7 @@ static const u8 tuning_blk_pattern_8bit[] = {
 	0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
 };
 
-static inline bool dw_mci_fifo_reset(struct dw_mci *host);
-static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host);
+static inline bool dw_mci_reset(struct dw_mci *host);
 
 #if defined(CONFIG_DEBUG_FS)
 static int dw_mci_req_show(struct seq_file *s, void *v)
@@ -1254,7 +1253,7 @@ static int dw_mci_data_complete(struct dw_mci *host, struct mmc_data *data)
 		 * After an error, there may be data lingering
 		 * in the FIFO
 		 */
-		dw_mci_fifo_reset(host);
+		dw_mci_reset(host);
 	} else {
 		data->bytes_xfered = data->blocks * data->blksz;
 		data->error = 0;
@@ -1371,7 +1370,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
 
 			/* CMD error in data command */
 			if (mrq->cmd->error && mrq->data)
-				dw_mci_fifo_reset(host);
+				dw_mci_reset(host);
 
 			host->cmd = NULL;
 			host->data = NULL;
@@ -1982,14 +1981,9 @@ static void dw_mci_work_routine_card(struct work_struct *work)
 			}
 
 			/* Power down slot */
-			if (present == 0) {
+			if (present == 0)
 				/* Clear down the FIFO */
-				dw_mci_fifo_reset(host);
-#ifdef CONFIG_MMC_DW_IDMAC
-				dw_mci_idmac_reset(host);
-#endif
-
-			}
+				dw_mci_reset(host);
 
 			spin_unlock_bh(&host->lock);
 
@@ -2323,8 +2317,11 @@ static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset)
 	return false;
 }
 
-static inline bool dw_mci_fifo_reset(struct dw_mci *host)
+static inline bool dw_mci_reset(struct dw_mci *host)
 {
+	u32 flags = SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET;
+	bool ret = false;
+
 	/*
 	 * Reseting generates a block interrupt, hence setting
 	 * the scatter-gather pointer to NULL.
@@ -2334,15 +2331,57 @@ static inline bool dw_mci_fifo_reset(struct dw_mci *host)
 		host->sg = NULL;
 	}
 
-	return dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET);
-}
+	if (host->use_dma)
+		flags |= SDMMC_CTRL_DMA_RESET;
 
-static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host)
-{
-	return dw_mci_ctrl_reset(host,
-				 SDMMC_CTRL_FIFO_RESET |
-				 SDMMC_CTRL_RESET |
-				 SDMMC_CTRL_DMA_RESET);
+	if (dw_mci_ctrl_reset(host, flags)) {
+		/*
+		 * In all cases we clear the RAWINTS register to clear any
+		 * interrupts.
+		 */
+		mci_writel(host, RINTSTS, 0xFFFFFFFF);
+
+		/* if using dma we wait for dma_req to clear */
+		if (host->use_dma) {
+			unsigned long timeout = jiffies + msecs_to_jiffies(500);
+			u32 status;
+			do {
+				status = mci_readl(host, STATUS);
+				if (!(status & SDMMC_STATUS_DMA_REQ))
+					break;
+				cpu_relax();
+			} while (time_before(jiffies, timeout));
+
+			if (status & SDMMC_STATUS_DMA_REQ) {
+				dev_err(host->dev,
+					"%s: Timeout waiting for dma_req to "
+					"clear during reset", __func__);
+				goto ciu_out;
+			}
+
+			/* when using DMA next we reset the fifo again */
+			if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET))
+				goto ciu_out;
+		}
+	} else {
+		dev_err(host->dev, "%s: Reset bits didn't clear", __func__);
+
+		/* if the controller reset bit did clear, then set clock regs */
+		if (!(mci_readl(host, CTRL) & SDMMC_CTRL_RESET))
+			goto ciu_out;
+	}
+
+	if (IS_ENABLED(CONFIG_MMC_DW_IDMAC))
+		/* It is also recommended that we reset and reprogram idmac */
+		dw_mci_idmac_reset(host);
+
+	ret = true;
+
+ciu_out:
+	/* After a CTRL reset we need to have CIU set clock registers  */
+	mci_send_cmd(host->cur_slot, SDMMC_CMD_UPD_CLK, 0);
+
+	return ret;
 }
 
 #ifdef CONFIG_OF
@@ -2432,6 +2471,7 @@ int dw_mci_probe(struct dw_mci *host)
 	const struct dw_mci_drv_data *drv_data = host->drv_data;
 	int width, i, ret = 0;
 	u32 fifo_size;
+	u32 flags;
 	int init_slots = 0;
 
 	if (!host->pdata) {
@@ -2555,7 +2595,8 @@ int dw_mci_probe(struct dw_mci *host)
 	}
 
 	/* Reset all blocks */
-	if (!dw_mci_ctrl_all_reset(host))
+	flags = SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET;
+	if (!dw_mci_ctrl_reset(host, flags))
 		return -ENODEV;
 
 	host->dma_ops = host->pdata->dma_ops;
@@ -2744,7 +2785,7 @@ int dw_mci_resume(struct dw_mci *host)
 		}
 	}
 
-	if (!dw_mci_ctrl_all_reset(host)) {
+	if (!dw_mci_reset(host)) {
 		ret = -ENODEV;
 		return ret;
 	}
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 6bf24ab..2505804 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -129,6 +129,7 @@
 #define SDMMC_CMD_INDX(n)		((n) & 0x1F)
 /* Status register defines */
 #define SDMMC_GET_FCNT(x)		(((x)>>17) & 0x1FFF)
+#define SDMMC_STATUS_DMA_REQ		BIT(31)
 /* FIFOTH register defines */
 #define SDMMC_SET_FIFOTH(m, r, t)	(((m) & 0x7) << 28 | \
 					 ((r) & 0xFFF) << 16 | \
-- 
1.8.3.2

  reply	other threads:[~2014-05-29  0:35 UTC|newest]

Thread overview: 75+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-05-13  1:38 [PATCHv2] mmc: dw_mmc: change to use recommended reset procedure Sonny Rao
2014-05-13  1:38 ` Sonny Rao
2014-05-13  5:02 ` Seungwon Jeon
2014-05-13  5:02   ` Seungwon Jeon
2014-05-13  7:16   ` Sonny Rao
2014-05-13  7:16     ` Sonny Rao
2014-05-13 11:09     ` Seungwon Jeon
2014-05-13 11:09       ` Seungwon Jeon
2014-05-17  0:36       ` Sonny Rao
2014-05-17  0:36         ` Sonny Rao
2014-05-20  1:49         ` Seungwon Jeon
2014-05-20  1:49           ` Seungwon Jeon
2014-05-22 18:54           ` Sonny Rao
2014-05-22 18:54             ` Sonny Rao
2014-05-29  0:35             ` Sonny Rao [this message]
2014-05-29  0:35               ` [PATCH] " Sonny Rao
2014-05-29  5:17               ` Jaehoon Chung
2014-05-29  5:17                 ` Jaehoon Chung
2014-06-09 21:35                 ` Sonny Rao
2014-06-09 21:35                   ` Sonny Rao
2014-06-09 22:00                   ` Sonny Rao
2014-06-09 22:00                     ` Sonny Rao
2014-07-10 12:28                     ` Seungwon Jeon
2014-07-10 12:28                       ` Seungwon Jeon
2014-07-10 22:35                       ` Sonny Rao
2014-07-10 22:35                         ` Sonny Rao
2014-07-11 10:20                         ` Seungwon Jeon
2014-07-11 10:20                           ` Seungwon Jeon
2014-07-11 19:48                           ` Sonny Rao
2014-07-11 19:48                             ` Sonny Rao
2014-07-11 20:53                             ` [PATCHv5] " Sonny Rao
2014-07-11 20:53                               ` Sonny Rao
2014-07-14  5:52                               ` Jaehoon Chung
2014-07-14  5:52                                 ` Jaehoon Chung
2014-07-14 22:06                                 ` [PATCHv6] " Sonny Rao
2014-07-14 22:06                                   ` Sonny Rao
2014-07-18 13:37                                   ` Seungwon Jeon
2014-07-18 13:37                                     ` Seungwon Jeon
2014-07-26  9:55                                   ` Ulf Hansson
2014-07-26  9:55                                     ` Ulf Hansson
2014-05-13  5:19 ` [PATCHv2] " Kukjin Kim
2014-05-13  5:19   ` Kukjin Kim
2014-05-13  8:46 ` Arnd Bergmann
2014-05-13  8:46   ` Arnd Bergmann
  -- strict thread matches above, loose matches on Subject: below --
2014-08-04 13:44 linux-next: build failure after merge of the mmc-uh tree Ulf Hansson
2014-08-05  1:19 ` [PATCH] mmc: dw_mmc: change to use recommended reset procedure Sonny Rao
2014-08-05  1:19   ` Sonny Rao
2014-08-07  8:40   ` Jaehoon Chung
2014-08-07  8:40     ` Jaehoon Chung
2014-08-11  7:55   ` Ulf Hansson
2014-08-11  7:55     ` Ulf Hansson
2014-08-11  7:55     ` Ulf Hansson
2014-03-26 11:46 Yuvaraj Kumar C D
2014-03-26 11:46 ` Yuvaraj Kumar C D
2014-05-08  9:40 ` Yuvaraj Kumar
2014-05-08  9:40   ` Yuvaraj Kumar
2014-05-09  1:15   ` Jaehoon Chung
2014-05-09  1:15     ` Jaehoon Chung
2014-05-09  1:34     ` Sonny Rao
2014-05-09  1:34       ` Sonny Rao
2014-05-09  4:27       ` Jaehoon Chung
2014-05-09  4:27         ` Jaehoon Chung
2014-05-09  7:32         ` Jaehoon Chung
2014-05-09  7:32           ` Jaehoon Chung
2014-05-10  3:36           ` Sonny Rao
2014-05-10  3:36             ` Sonny Rao
2014-05-10 14:08             ` Seungwon Jeon
2014-05-10 14:08               ` Seungwon Jeon
2014-05-12 21:14               ` Sonny Rao
2014-05-12 21:14                 ` Sonny Rao
2014-05-12 21:44             ` Sonny Rao
2014-05-12 21:44               ` Sonny Rao
2014-05-13  0:40               ` Sonny Rao
2014-05-13  0:40                 ` Sonny Rao
2014-05-13 10:13               ` James Hogan
2014-05-13 10:13                 ` James Hogan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1401323709-10345-1-git-send-email-sonnyrao@chromium.org \
    --to=sonnyrao@chromium.org \
    --cc=cjb@laptop.org \
    --cc=dianders@chromium.org \
    --cc=grundler@chromium.org \
    --cc=jh80.chung@samsung.com \
    --cc=joshi@samsung.com \
    --cc=kgene.kim@samsung.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=linux-samsung-soc@vger.kernel.org \
    --cc=t.figa@samsung.com \
    --cc=tgih.jun@samsung.com \
    --cc=yuvaraj.cd@samsung.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.