linux-omap.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/10] omap_hsmmc patches
@ 2009-03-12 16:22 Adrian Hunter
  2009-03-12 16:22 ` [PATCH 1/10] OMAP: HSMMC: Do dma cleanup also with data CRC errors Adrian Hunter
                   ` (10 more replies)
  0 siblings, 11 replies; 14+ messages in thread
From: Adrian Hunter @ 2009-03-12 16:22 UTC (permalink / raw)
  To: Pierre Ossman
  Cc: Jarkko Lavinen, Adrian Hunter, Grazvydas Ignotas, David Brownell,
	linux-omap Mailing List, Tony Lindgren, lkml

Here are 10 patches for omap_hsmmc.

They apply to the 'next' branch of Pierre Ossman's mmc tree.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/10] OMAP: HSMMC: Do dma cleanup also with data CRC errors
  2009-03-12 16:22 [PATCH 0/10] omap_hsmmc patches Adrian Hunter
@ 2009-03-12 16:22 ` Adrian Hunter
  2009-03-12 16:23 ` [PATCH 2/10] OMAP: HSMMC: Fix response type for busy after response Adrian Hunter
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Adrian Hunter @ 2009-03-12 16:22 UTC (permalink / raw)
  To: Pierre Ossman
  Cc: Jarkko Lavinen, Adrian Hunter, Grazvydas Ignotas, David Brownell,
	linux-omap Mailing List, Tony Lindgren, lkml

>From 93cfc8673d2f41527c1786de8f061bef88f9ac28 Mon Sep 17 00:00:00 2001
From: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Date: Fri, 5 Dec 2008 12:31:46 +0200
Subject: [PATCH] OMAP: HSMMC: Do dma cleanup also with data CRC errors

Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 576bfa7..5ff2ca2 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -332,9 +332,9 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
 /*
  * DMA clean up for command errors
  */
-static void mmc_dma_cleanup(struct mmc_omap_host *host)
+static void mmc_dma_cleanup(struct mmc_omap_host *host, int errno)
 {
-	host->data->error = -ETIMEDOUT;
+	host->data->error = errno;
 
 	if (host->use_dma && host->dma_ch != -1) {
 		dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len,
@@ -439,7 +439,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
 				end_cmd = 1;
 			}
 			if (host->data) {
-				mmc_dma_cleanup(host);
+				mmc_dma_cleanup(host, -ETIMEDOUT);
 				mmc_omap_reset_controller_fsm(host, SRD);
 			}
 		}
@@ -447,9 +447,9 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
 			(status & DATA_CRC)) {
 			if (host->data) {
 				if (status & DATA_TIMEOUT)
-					mmc_dma_cleanup(host);
+					mmc_dma_cleanup(host, -ETIMEDOUT);
 				else
-					host->data->error = -EILSEQ;
+					mmc_dma_cleanup(host, -EILSEQ);
 				mmc_omap_reset_controller_fsm(host, SRD);
 				end_trans = 1;
 			}
-- 
1.5.6.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/10] OMAP: HSMMC: Fix response type for busy after response
  2009-03-12 16:22 [PATCH 0/10] omap_hsmmc patches Adrian Hunter
  2009-03-12 16:22 ` [PATCH 1/10] OMAP: HSMMC: Do dma cleanup also with data CRC errors Adrian Hunter
@ 2009-03-12 16:23 ` Adrian Hunter
  2009-03-12 16:23 ` [PATCH 3/10] OMAP: HSMMC: Implement scatter-gather emulation Adrian Hunter
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Adrian Hunter @ 2009-03-12 16:23 UTC (permalink / raw)
  To: Pierre Ossman
  Cc: Jarkko Lavinen, Adrian Hunter, Grazvydas Ignotas, David Brownell,
	linux-omap Mailing List, Tony Lindgren, lkml

>From 3fcbf97e7275765c878d24837f95a15764dd20f5 Mon Sep 17 00:00:00 2001
From: Adrian Hunter <adrian.hunter@nokia.com>
Date: Mon, 12 Jan 2009 16:13:08 +0200
Subject: [PATCH] OMAP: HSMMC: Fix response type for busy after response

Some MMC commands result in the card becoming busy after
the response is received.  This needs to be specified
for the omap_hsmmc host controller, which is what this
patch does.  However, the effect is that some commands
with no data will cause a Transfer Complete (TC) interrupt
in addition to the Command Complete (CC) interrupt.
In order to deal with that, the irq handler has needed
a few changes also.

The benefit of this change is that the omap_hsmmc host
controller driver now waits for the TC interrupt while
the card is busy, so the mmc_block driver needs to poll
the card status just once instead of repeatedly.
i.e. the net result is more sleep and less cpu.

The command sequence for open-ended multi-block write
with DMA is now:

	Issue write command CMD25
	Receive CC interrupt
	Data is sent
	Receive TC interrupt (DMA is done)
	Issue stop command CMD12
	Receive CC interrupt
	Card is busy
	Receive TC interrupt
	Card is now ready for next transfer

Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   38 +++++++++++++++++++++++++++++---------
 1 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 5ff2ca2..1f84bd4 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -150,6 +150,7 @@ struct mmc_omap_host {
 	int			initstr;
 	int			slot_id;
 	int			dbclk_enabled;
+	int			response_busy;
 	struct	omap_mmc_platform_data	*pdata;
 };
 
@@ -244,10 +245,14 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd,
 	OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
 	OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
 
+	host->response_busy = 0;
 	if (cmd->flags & MMC_RSP_PRESENT) {
 		if (cmd->flags & MMC_RSP_136)
 			resptype = 1;
-		else
+		else if (cmd->flags & MMC_RSP_BUSY) {
+			resptype = 3;
+			host->response_busy = 1;
+		} else
 			resptype = 2;
 	}
 
@@ -282,6 +287,15 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd,
 static void
 mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
 {
+	if (!data) {
+		struct mmc_request *mrq = host->mrq;
+
+		host->mrq = NULL;
+		mmc_omap_fclk_lazy_disable(host);
+		mmc_request_done(host->mmc, mrq);
+		return;
+	}
+
 	host->data = NULL;
 
 	if (host->use_dma && host->dma_ch != -1)
@@ -323,7 +337,7 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
 			cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP10);
 		}
 	}
-	if (host->data == NULL || cmd->error) {
+	if ((host->data == NULL && !host->response_busy) || cmd->error) {
 		host->mrq = NULL;
 		mmc_request_done(host->mmc, cmd->mrq);
 	}
@@ -413,7 +427,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
 	struct mmc_data *data;
 	int end_cmd = 0, end_trans = 0, status;
 
-	if (host->cmd == NULL && host->data == NULL) {
+	if (host->mrq == NULL) {
 		OMAP_HSMMC_WRITE(host->base, STAT,
 			OMAP_HSMMC_READ(host->base, STAT));
 		return IRQ_HANDLED;
@@ -438,18 +452,24 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
 				}
 				end_cmd = 1;
 			}
-			if (host->data) {
-				mmc_dma_cleanup(host, -ETIMEDOUT);
+			if (host->data || host->response_busy) {
+				if (host->data)
+					mmc_dma_cleanup(host, -ETIMEDOUT);
+				host->response_busy = 0;
 				mmc_omap_reset_controller_fsm(host, SRD);
 			}
 		}
 		if ((status & DATA_TIMEOUT) ||
 			(status & DATA_CRC)) {
-			if (host->data) {
-				if (status & DATA_TIMEOUT)
-					mmc_dma_cleanup(host, -ETIMEDOUT);
+			if (host->data || host->response_busy) {
+				int err = (status & DATA_TIMEOUT) ?
+						-ETIMEDOUT : -EILSEQ;
+
+				if (host->data)
+					mmc_dma_cleanup(host, err);
 				else
-					mmc_dma_cleanup(host, -EILSEQ);
+					host->mrq->cmd->error = err;
+				host->response_busy = 0;
 				mmc_omap_reset_controller_fsm(host, SRD);
 				end_trans = 1;
 			}
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/10] OMAP: HSMMC: Implement scatter-gather emulation
  2009-03-12 16:22 [PATCH 0/10] omap_hsmmc patches Adrian Hunter
  2009-03-12 16:22 ` [PATCH 1/10] OMAP: HSMMC: Do dma cleanup also with data CRC errors Adrian Hunter
  2009-03-12 16:23 ` [PATCH 2/10] OMAP: HSMMC: Fix response type for busy after response Adrian Hunter
@ 2009-03-12 16:23 ` Adrian Hunter
  2009-03-12 16:23 ` [PATCH 4/10] OMAP: HSMMC: Add 8-bit bus width mode support Adrian Hunter
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Adrian Hunter @ 2009-03-12 16:23 UTC (permalink / raw)
  To: Pierre Ossman
  Cc: Jarkko Lavinen, Adrian Hunter, Grazvydas Ignotas, David Brownell,
	linux-omap Mailing List, Tony Lindgren, lkml

>From b123bde5b97520691535bec1cbe95f4f9160386e Mon Sep 17 00:00:00 2001
From: Juha Yrjola <juha.yrjola@solidboot.com>
Date: Fri, 14 Nov 2008 15:22:00 +0200
Subject: [PATCH] OMAP: HSMMC: Implement scatter-gather emulation

Instead of using the bounce buffer, using scatter-gather emulation
(as in the OMAP1/2 MMC driver) removes the need of one extra memory
copy and improves performance.

Signed-off-by: Juha Yrjola <juha.yrjola@solidboot.com>
---
 drivers/mmc/host/omap_hsmmc.c |  172 ++++++++++++++++++++++------------------
 1 files changed, 95 insertions(+), 77 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 1f84bd4..483e591 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -100,9 +100,6 @@
 #define OMAP_MMC1_DEVID		0
 #define OMAP_MMC2_DEVID		1
 
-#define OMAP_MMC_DATADIR_NONE	0
-#define OMAP_MMC_DATADIR_READ	1
-#define OMAP_MMC_DATADIR_WRITE	2
 #define MMC_TIMEOUT_MS		20
 #define OMAP_MMC_MASTER_CLOCK	96000000
 #define DRIVER_NAME		"mmci-omap-hs"
@@ -138,16 +135,14 @@ struct mmc_omap_host {
 	resource_size_t		mapbase;
 	unsigned int		id;
 	unsigned int		dma_len;
-	unsigned int		dma_dir;
+	unsigned int		dma_sg_idx;
 	unsigned char		bus_mode;
-	unsigned char		datadir;
 	u32			*buffer;
 	u32			bytesleft;
 	int			suspended;
 	int			irq;
 	int			carddetect;
 	int			use_dma, dma_ch;
-	int			initstr;
 	int			slot_id;
 	int			dbclk_enabled;
 	int			response_busy;
@@ -281,6 +276,15 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd,
 	OMAP_HSMMC_WRITE(host->base, CMD, cmdreg);
 }
 
+static int
+mmc_omap_get_dma_dir(struct mmc_omap_host *host, struct mmc_data *data)
+{
+	if (data->flags & MMC_DATA_WRITE)
+		return DMA_TO_DEVICE;
+	else
+		return DMA_FROM_DEVICE;
+}
+
 /*
  * Notify the transfer complete to MMC core
  */
@@ -300,9 +304,7 @@ mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
 
 	if (host->use_dma && host->dma_ch != -1)
 		dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
-			host->dma_dir);
-
-	host->datadir = OMAP_MMC_DATADIR_NONE;
+			mmc_omap_get_dma_dir(host, data));
 
 	if (!data->error)
 		data->bytes_xfered += data->blocks * (data->blksz);
@@ -352,13 +354,12 @@ static void mmc_dma_cleanup(struct mmc_omap_host *host, int errno)
 
 	if (host->use_dma && host->dma_ch != -1) {
 		dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len,
-			host->dma_dir);
+			mmc_omap_get_dma_dir(host, host->data));
 		omap_free_dma(host->dma_ch);
 		host->dma_ch = -1;
 		up(&host->sem);
 	}
 	host->data = NULL;
-	host->datadir = OMAP_MMC_DATADIR_NONE;
 }
 
 /*
@@ -592,6 +593,55 @@ static irqreturn_t omap_mmc_cd_handler(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static int mmc_omap_get_dma_sync_dev(struct mmc_omap_host *host,
+				     struct mmc_data *data)
+{
+	int sync_dev;
+
+	if (data->flags & MMC_DATA_WRITE) {
+		if (host->id == OMAP_MMC1_DEVID)
+			sync_dev = OMAP24XX_DMA_MMC1_TX;
+		else
+			sync_dev = OMAP24XX_DMA_MMC2_TX;
+	} else {
+		if (host->id == OMAP_MMC1_DEVID)
+			sync_dev = OMAP24XX_DMA_MMC1_RX;
+		else
+			sync_dev = OMAP24XX_DMA_MMC2_RX;
+	}
+	return sync_dev;
+}
+
+static void mmc_omap_config_dma_params(struct mmc_omap_host *host,
+				       struct mmc_data *data,
+				       struct scatterlist *sgl)
+{
+	int blksz, nblk, dma_ch;
+
+	dma_ch = host->dma_ch;
+	if (data->flags & MMC_DATA_WRITE) {
+		omap_set_dma_dest_params(dma_ch, 0, OMAP_DMA_AMODE_CONSTANT,
+			(host->mapbase + OMAP_HSMMC_DATA), 0, 0);
+		omap_set_dma_src_params(dma_ch, 0, OMAP_DMA_AMODE_POST_INC,
+			sg_dma_address(sgl), 0, 0);
+	} else {
+		omap_set_dma_src_params(dma_ch, 0, OMAP_DMA_AMODE_CONSTANT,
+					(host->mapbase + OMAP_HSMMC_DATA), 0, 0);
+		omap_set_dma_dest_params(dma_ch, 0, OMAP_DMA_AMODE_POST_INC,
+			sg_dma_address(sgl), 0, 0);
+	}
+
+	blksz = host->data->blksz;
+	nblk = sg_dma_len(sgl) / blksz;
+
+	omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32,
+			blksz / 4, nblk, OMAP_DMA_SYNC_FRAME,
+			mmc_omap_get_dma_sync_dev(host, data),
+			!(data->flags & MMC_DATA_WRITE));
+
+	omap_start_dma(dma_ch);
+}
+
 /*
  * DMA call back function
  */
@@ -605,6 +655,14 @@ static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data)
 	if (host->dma_ch < 0)
 		return;
 
+	host->dma_sg_idx++;
+	if (host->dma_sg_idx < host->dma_len) {
+		/* Fire up the next transfer. */
+		mmc_omap_config_dma_params(host, host->data,
+					   host->data->sg + host->dma_sg_idx);
+		return;
+	}
+
 	omap_free_dma(host->dma_ch);
 	host->dma_ch = -1;
 	/*
@@ -615,38 +673,28 @@ static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data)
 }
 
 /*
- * Configure dma src and destination parameters
- */
-static int mmc_omap_config_dma_param(int sync_dir, struct mmc_omap_host *host,
-				struct mmc_data *data)
-{
-	if (sync_dir == 0) {
-		omap_set_dma_dest_params(host->dma_ch, 0,
-			OMAP_DMA_AMODE_CONSTANT,
-			(host->mapbase + OMAP_HSMMC_DATA), 0, 0);
-		omap_set_dma_src_params(host->dma_ch, 0,
-			OMAP_DMA_AMODE_POST_INC,
-			sg_dma_address(&data->sg[0]), 0, 0);
-	} else {
-		omap_set_dma_src_params(host->dma_ch, 0,
-			OMAP_DMA_AMODE_CONSTANT,
-			(host->mapbase + OMAP_HSMMC_DATA), 0, 0);
-		omap_set_dma_dest_params(host->dma_ch, 0,
-			OMAP_DMA_AMODE_POST_INC,
-			sg_dma_address(&data->sg[0]), 0, 0);
-	}
-	return 0;
-}
-/*
  * Routine to configure and start DMA for the MMC card
  */
 static int
 mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req)
 {
-	int sync_dev, sync_dir = 0;
-	int dma_ch = 0, ret = 0, err = 1;
+	int dma_ch = 0, ret = 0, err = 1, i;
 	struct mmc_data *data = req->data;
 
+	/* Sanity check: all the SG entries must be aligned by block size. */
+	for (i = 0; i < host->dma_len; i++) {
+		struct scatterlist *sgl;
+
+		sgl = data->sg + i;
+		if (sgl->length % data->blksz)
+			return -EINVAL;
+	}
+	if ((data->blksz % 4) != 0)
+		/* REVISIT: The MMC buffer increments only when MSB is written.
+		 * Return error for blksz which is non multiple of four.
+		 */
+		return -EINVAL;
+
 	/*
 	 * If for some reason the DMA transfer is still active,
 	 * we wait for timeout period and free the dma
@@ -665,49 +713,22 @@ mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req)
 			return err;
 	}
 
-	if (!(data->flags & MMC_DATA_WRITE)) {
-		host->dma_dir = DMA_FROM_DEVICE;
-		if (host->id == OMAP_MMC1_DEVID)
-			sync_dev = OMAP24XX_DMA_MMC1_RX;
-		else
-			sync_dev = OMAP24XX_DMA_MMC2_RX;
-	} else {
-		host->dma_dir = DMA_TO_DEVICE;
-		if (host->id == OMAP_MMC1_DEVID)
-			sync_dev = OMAP24XX_DMA_MMC1_TX;
-		else
-			sync_dev = OMAP24XX_DMA_MMC2_TX;
-	}
-
-	ret = omap_request_dma(sync_dev, "MMC/SD", mmc_omap_dma_cb,
-			host, &dma_ch);
+	ret = omap_request_dma(mmc_omap_get_dma_sync_dev(host, data), "MMC/SD",
+			       mmc_omap_dma_cb,host, &dma_ch);
 	if (ret != 0) {
-		dev_dbg(mmc_dev(host->mmc),
+		dev_err(mmc_dev(host->mmc),
 			"%s: omap_request_dma() failed with %d\n",
 			mmc_hostname(host->mmc), ret);
 		return ret;
 	}
 
 	host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
-			data->sg_len, host->dma_dir);
+			data->sg_len, mmc_omap_get_dma_dir(host, data));
 	host->dma_ch = dma_ch;
+	host->dma_sg_idx = 0;
 
-	if (!(data->flags & MMC_DATA_WRITE))
-		mmc_omap_config_dma_param(1, host, data);
-	else
-		mmc_omap_config_dma_param(0, host, data);
-
-	if ((data->blksz % 4) == 0)
-		omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32,
-			(data->blksz / 4), data->blocks, OMAP_DMA_SYNC_FRAME,
-			sync_dev, sync_dir);
-	else
-		/* REVISIT: The MMC buffer increments only when MSB is written.
-		 * Return error for blksz which is non multiple of four.
-		 */
-		return -EINVAL;
+	mmc_omap_config_dma_params(host, data, data->sg);
 
-	omap_start_dma(dma_ch);
 	return 0;
 }
 
@@ -757,7 +778,6 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
 	host->data = req->data;
 
 	if (req->data == NULL) {
-		host->datadir = OMAP_MMC_DATADIR_NONE;
 		OMAP_HSMMC_WRITE(host->base, BLK, 0);
 		return 0;
 	}
@@ -766,9 +786,6 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
 					| (req->data->blocks << 16));
 	set_data_timeout(host, req);
 
-	host->datadir = (req->data->flags & MMC_DATA_WRITE) ?
-			OMAP_MMC_DATADIR_WRITE : OMAP_MMC_DATADIR_READ;
-
 	if (host->use_dma) {
 		ret = mmc_omap_start_dma_transfer(host, req);
 		if (ret != 0) {
@@ -1027,10 +1044,11 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
 		else
 			host->dbclk_enabled = 1;
 
-#ifdef CONFIG_MMC_BLOCK_BOUNCE
-	mmc->max_phys_segs = 1;
-	mmc->max_hw_segs = 1;
-#endif
+	/* Since we do only SG emulation, we can have as many segs
+	 * as we want. */
+	mmc->max_phys_segs = 1024;
+	mmc->max_hw_segs = 1024;
+
 	mmc->max_blk_size = 512;       /* Block Length at max can be 1024 */
 	mmc->max_blk_count = 0xFFFF;    /* No. of Blocks is 16 bits */
 	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
-- 
1.5.6.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 4/10] OMAP: HSMMC: Add 8-bit bus width mode support
  2009-03-12 16:22 [PATCH 0/10] omap_hsmmc patches Adrian Hunter
                   ` (2 preceding siblings ...)
  2009-03-12 16:23 ` [PATCH 3/10] OMAP: HSMMC: Implement scatter-gather emulation Adrian Hunter
@ 2009-03-12 16:23 ` Adrian Hunter
  2009-03-12 16:23 ` [PATCH 5/10] OMAP: HSMMC: Allow cover switch to cause rescan Adrian Hunter
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Adrian Hunter @ 2009-03-12 16:23 UTC (permalink / raw)
  To: Pierre Ossman
  Cc: Jarkko Lavinen, Adrian Hunter, Grazvydas Ignotas, David Brownell,
	linux-omap Mailing List, Tony Lindgren, lkml

>From 7961505a57b8a9dff7b6fc8bbee654165a1b05b2 Mon Sep 17 00:00:00 2001
From: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Date: Fri, 21 Nov 2008 16:49:54 +0200
Subject: [PATCH] OMAP: HSMMC: Add 8-bit bus width mode support

Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   12 +++++++++++-
 1 files changed, 11 insertions(+), 1 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 483e591..fd1657a 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -77,6 +77,7 @@
 #define MSBS			(1 << 5)
 #define BCE			(1 << 1)
 #define FOUR_BIT		(1 << 1)
+#define DW8			(1 << 5)
 #define CC			0x1
 #define TC			0x02
 #define OD			0x1
@@ -817,6 +818,7 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	u16 dsor = 0;
 	unsigned long regval;
 	unsigned long timeout;
+	u32 con;
 
 	switch (ios->power_mode) {
 	case MMC_POWER_OFF:
@@ -827,12 +829,18 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 		break;
 	}
 
+	con = OMAP_HSMMC_READ(host->base, CON);
 	switch (mmc->ios.bus_width) {
+	case MMC_BUS_WIDTH_8:
+		OMAP_HSMMC_WRITE(host->base, CON, con | DW8);
+		break;
 	case MMC_BUS_WIDTH_4:
+		OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
 		OMAP_HSMMC_WRITE(host->base, HCTL,
 			OMAP_HSMMC_READ(host->base, HCTL) | FOUR_BIT);
 		break;
 	case MMC_BUS_WIDTH_1:
+		OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
 		OMAP_HSMMC_WRITE(host->base, HCTL,
 			OMAP_HSMMC_READ(host->base, HCTL) & ~FOUR_BIT);
 		break;
@@ -1057,7 +1065,9 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
 	mmc->ocr_avail = mmc_slot(host).ocr_mask;
 	mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
 
-	if (pdata->slots[host->slot_id].wires >= 4)
+	if (pdata->slots[host->slot_id].wires >= 8)
+		mmc->caps |= MMC_CAP_8_BIT_DATA;
+	else if (pdata->slots[host->slot_id].wires >= 4)
 		mmc->caps |= MMC_CAP_4_BIT_DATA;
 
 	omap_hsmmc_init(host);
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 5/10] OMAP: HSMMC: Allow cover switch to cause rescan
  2009-03-12 16:22 [PATCH 0/10] omap_hsmmc patches Adrian Hunter
                   ` (3 preceding siblings ...)
  2009-03-12 16:23 ` [PATCH 4/10] OMAP: HSMMC: Add 8-bit bus width mode support Adrian Hunter
@ 2009-03-12 16:23 ` Adrian Hunter
  2009-03-12 16:23 ` [PATCH 6/10] OMAP: HSMMC: Do not prefix slot name Adrian Hunter
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Adrian Hunter @ 2009-03-12 16:23 UTC (permalink / raw)
  To: Pierre Ossman
  Cc: Jarkko Lavinen, Adrian Hunter, Grazvydas Ignotas, David Brownell,
	linux-omap Mailing List, Tony Lindgren, lkml

>From 702faf54a21016777bfedf94ea709b2f05b5aee2 Mon Sep 17 00:00:00 2001
From: Adrian Hunter <adrian.hunter@nokia.com>
Date: Mon, 26 Jan 2009 13:17:25 +0200
Subject: [PATCH] OMAP: HSMMC: Allow cover switch to cause rescan

Allow a cover switch to be used to cause a rescan of the
MMC slot.

Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   11 +++++++----
 1 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index fd1657a..f3e4e0f 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -571,7 +571,10 @@ static void mmc_omap_detect(struct work_struct *work)
 						mmc_carddetect_work);
 	struct omap_mmc_slot_data *slot = &mmc_slot(host);
 
-	host->carddetect = slot->card_detect(slot->card_detect_irq);
+	if (mmc_slot(host).card_detect)
+		host->carddetect = slot->card_detect(slot->card_detect_irq);
+	else
+		host->carddetect = -ENOSYS;
 
 	sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch");
 	if (host->carddetect) {
@@ -1089,7 +1092,7 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
 	}
 
 	/* Request IRQ for card detect */
-	if ((mmc_slot(host).card_detect_irq) && (mmc_slot(host).card_detect)) {
+	if ((mmc_slot(host).card_detect_irq)) {
 		ret = request_irq(mmc_slot(host).card_detect_irq,
 				  omap_mmc_cd_handler,
 				  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
@@ -1112,8 +1115,8 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
 		if (ret < 0)
 			goto err_slot_name;
 	}
-	if (mmc_slot(host).card_detect_irq && mmc_slot(host).card_detect &&
-			host->pdata->slots[host->slot_id].get_cover_state) {
+	if (mmc_slot(host).card_detect_irq &&
+	    host->pdata->slots[host->slot_id].get_cover_state) {
 		ret = device_create_file(&mmc->class_dev,
 					&dev_attr_cover_switch);
 		if (ret < 0)
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 6/10] OMAP: HSMMC: Do not prefix slot name
  2009-03-12 16:22 [PATCH 0/10] omap_hsmmc patches Adrian Hunter
                   ` (4 preceding siblings ...)
  2009-03-12 16:23 ` [PATCH 5/10] OMAP: HSMMC: Allow cover switch to cause rescan Adrian Hunter
@ 2009-03-12 16:23 ` Adrian Hunter
  2009-03-12 16:23 ` [PATCH 7/10] OMAP: HSMMC: Disable SDBP at suspend Adrian Hunter
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Adrian Hunter @ 2009-03-12 16:23 UTC (permalink / raw)
  To: Pierre Ossman
  Cc: Jarkko Lavinen, Adrian Hunter, Grazvydas Ignotas, David Brownell,
	linux-omap Mailing List, Tony Lindgren, lkml

>From b75cdf95103d5a76966bd505d9b945c47613613d Mon Sep 17 00:00:00 2001
From: Adrian Hunter <adrian.hunter@nokia.com>
Date: Fri, 30 Jan 2009 10:59:31 +0200
Subject: [PATCH] OMAP: HSMMC: Do not prefix slot name

Allow slot_name to be the same as the other OMAP
driver, by removing the redundant "slot:" prefix.

Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index f3e4e0f..7a9ca4f 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -216,7 +216,7 @@ mmc_omap_show_slot_name(struct device *dev, struct device_attribute *attr,
 	struct mmc_omap_host *host = mmc_priv(mmc);
 	struct omap_mmc_slot_data slot = host->pdata->slots[host->slot_id];
 
-	return sprintf(buf, "slot:%s\n", slot.name);
+	return sprintf(buf, "%s\n", slot.name);
 }
 
 static DEVICE_ATTR(slot_name, S_IRUGO, mmc_omap_show_slot_name, NULL);
-- 
1.5.6.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 7/10] OMAP: HSMMC: Disable SDBP at suspend
  2009-03-12 16:22 [PATCH 0/10] omap_hsmmc patches Adrian Hunter
                   ` (5 preceding siblings ...)
  2009-03-12 16:23 ` [PATCH 6/10] OMAP: HSMMC: Do not prefix slot name Adrian Hunter
@ 2009-03-12 16:23 ` Adrian Hunter
  2009-03-12 16:23 ` [PATCH 8/10] OMAP: HSMMC: Make driver support dynamic idle Adrian Hunter
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Adrian Hunter @ 2009-03-12 16:23 UTC (permalink / raw)
  To: Pierre Ossman
  Cc: Jarkko Lavinen, Adrian Hunter, Grazvydas Ignotas, David Brownell,
	linux-omap Mailing List, Tony Lindgren, lkml

>From 999afd472603ec1d572c34525e01d5215304addb Mon Sep 17 00:00:00 2001
From: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Date: Thu, 12 Mar 2009 15:30:58 +0200
Subject: [PATCH] OMAP: HSMMC: Disable SDBP at suspend

Turn off the bus power at suspend.

Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   16 ++--------------
 1 files changed, 2 insertions(+), 14 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 7a9ca4f..2832651 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -1214,20 +1214,8 @@ static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state)
 						" level suspend\n");
 			}
 
-			if (host->id == OMAP_MMC1_DEVID
-					&& !(OMAP_HSMMC_READ(host->base, HCTL)
-							& SDVSDET)) {
-				OMAP_HSMMC_WRITE(host->base, HCTL,
-					OMAP_HSMMC_READ(host->base, HCTL)
-					& SDVSCLR);
-				OMAP_HSMMC_WRITE(host->base, HCTL,
-					OMAP_HSMMC_READ(host->base, HCTL)
-					| SDVS30);
-				OMAP_HSMMC_WRITE(host->base, HCTL,
-					OMAP_HSMMC_READ(host->base, HCTL)
-					| SDBP);
-			}
-
+			OMAP_HSMMC_WRITE(host->base, HCTL,
+					 OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP);
 			clk_disable(host->fclk);
 			clk_disable(host->iclk);
 			clk_disable(host->dbclk);
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 8/10] OMAP: HSMMC: Make driver support dynamic idle
  2009-03-12 16:22 [PATCH 0/10] omap_hsmmc patches Adrian Hunter
                   ` (6 preceding siblings ...)
  2009-03-12 16:23 ` [PATCH 7/10] OMAP: HSMMC: Disable SDBP at suspend Adrian Hunter
@ 2009-03-12 16:23 ` Adrian Hunter
  2009-03-22 14:30   ` Pierre Ossman
  2009-03-12 16:23 ` [PATCH 9/10] OMAP: HSMMC: Fix MMC3 dma Adrian Hunter
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 14+ messages in thread
From: Adrian Hunter @ 2009-03-12 16:23 UTC (permalink / raw)
  To: Pierre Ossman
  Cc: Jarkko Lavinen, Adrian Hunter, Grazvydas Ignotas, David Brownell,
	linux-omap Mailing List, Tony Lindgren, lkml

>From 47b6de0fcfeb5948199dbed941847580bedc5315 Mon Sep 17 00:00:00 2001
From: Amit Kucheria <amit.kucheria@verdurent.com>
Date: Thu, 12 Mar 2009 15:47:39 +0200
Subject: [PATCH] OMAP: HSMMC: Make driver support dynamic idle

Add a timer that is kept active by MMC requests. FCLK is disabled on
timeout.

Signed-off-by: Amit Kucheria <amit.kucheria@verdurent.com>
Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   81 ++++++++++++++++++++++++++++++++++++-----
 1 files changed, 72 insertions(+), 9 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 2832651..0e47073 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -121,6 +121,9 @@
 #define OMAP_HSMMC_WRITE(base, reg, val) \
 	__raw_writel((val), (base) + OMAP_HSMMC_##reg)
 
+enum {OFF = 0, ON};
+#define IDLE_TIMEOUT (jiffies_to_msecs(10))
+
 struct mmc_omap_host {
 	struct	device		*dev;
 	struct	mmc_host	*mmc;
@@ -147,9 +150,52 @@ struct mmc_omap_host {
 	int			slot_id;
 	int			dbclk_enabled;
 	int			response_busy;
+
+	struct timer_list       idle_timer;
+	spinlock_t		clk_lock;     /* for changing enabled state */
+	unsigned int		fclk_enabled:1;
+
 	struct	omap_mmc_platform_data	*pdata;
 };
 
+static int mmc_omap_fclk_state(struct mmc_omap_host *host, unsigned int state)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&host->clk_lock, flags);
+	del_timer(&host->idle_timer);
+	if (host->fclk_enabled != state) {
+		if (state == ON) {
+			ret = clk_enable(host->fclk);
+			if (ret != 0)
+				goto err_out;
+
+			dev_dbg(mmc_dev(host->mmc), "mmc_fclk: enabled\n");
+		} else {
+			clk_disable(host->fclk);
+			dev_dbg(mmc_dev(host->mmc), "mmc_fclk: disabled\n");
+		}
+		host->fclk_enabled = state;
+	}
+
+err_out:
+	spin_unlock_irqrestore(&host->clk_lock, flags);
+	return ret;
+}
+
+static void mmc_omap_idle_timer(unsigned long data)
+{
+	struct mmc_omap_host *host = (struct mmc_omap_host *) data;
+
+	mmc_omap_fclk_state(host, OFF);
+}
+
+static void mmc_omap_fclk_lazy_disable(struct mmc_omap_host *host)
+{
+	mod_timer(&host->idle_timer, jiffies + IDLE_TIMEOUT);
+}
+
 /*
  * Stop clock to the card
  */
@@ -314,6 +360,7 @@ mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
 
 	if (!data->stop) {
 		host->mrq = NULL;
+		mmc_omap_fclk_lazy_disable(host);
 		mmc_request_done(host->mmc, data->mrq);
 		return;
 	}
@@ -342,6 +389,7 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
 	}
 	if ((host->data == NULL && !host->response_busy) || cmd->error) {
 		host->mrq = NULL;
+		mmc_omap_fclk_lazy_disable(host);
 		mmc_request_done(host->mmc, cmd->mrq);
 	}
 }
@@ -509,7 +557,7 @@ static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd)
 	int ret;
 
 	/* Disable the clocks */
-	clk_disable(host->fclk);
+	mmc_omap_fclk_state(host, OFF);
 	clk_disable(host->iclk);
 	clk_disable(host->dbclk);
 
@@ -523,7 +571,7 @@ static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd)
 	if (ret != 0)
 		goto err;
 
-	clk_enable(host->fclk);
+	mmc_omap_fclk_state(host, ON);
 	clk_enable(host->iclk);
 	clk_enable(host->dbclk);
 
@@ -577,12 +625,14 @@ static void mmc_omap_detect(struct work_struct *work)
 		host->carddetect = -ENOSYS;
 
 	sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch");
+	mmc_omap_fclk_state(host, ON);
 	if (host->carddetect) {
 		mmc_detect_change(host->mmc, (HZ * 200) / 1000);
 	} else {
 		mmc_omap_reset_controller_fsm(host, SRD);
 		mmc_detect_change(host->mmc, (HZ * 50) / 1000);
 	}
+	mmc_omap_fclk_lazy_disable(host);
 }
 
 /*
@@ -809,6 +859,7 @@ static void omap_mmc_request(struct mmc_host *mmc, struct mmc_request *req)
 
 	WARN_ON(host->mrq != NULL);
 	host->mrq = req;
+	mmc_omap_fclk_state(host, ON);
 	mmc_omap_prepare_data(host, req);
 	mmc_omap_start_command(host, req->cmd, req->data);
 }
@@ -823,6 +874,8 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	unsigned long timeout;
 	u32 con;
 
+	mmc_omap_fclk_state(host, ON);
+
 	switch (ios->power_mode) {
 	case MMC_POWER_OFF:
 		mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
@@ -901,6 +954,8 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
 		OMAP_HSMMC_WRITE(host->base, CON,
 				OMAP_HSMMC_READ(host->base, CON) | OD);
+
+	mmc_omap_fclk_lazy_disable(host);
 }
 
 static int omap_hsmmc_get_cd(struct mmc_host *mmc)
@@ -1029,14 +1084,18 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
 		goto err1;
 	}
 
-	if (clk_enable(host->fclk) != 0) {
+	spin_lock_init(&host->clk_lock);
+	setup_timer(&host->idle_timer, mmc_omap_idle_timer,
+		    (unsigned long) host);
+
+	if (mmc_omap_fclk_state(host, ON) != 0) {
 		clk_put(host->iclk);
 		clk_put(host->fclk);
 		goto err1;
 	}
 
 	if (clk_enable(host->iclk) != 0) {
-		clk_disable(host->fclk);
+		mmc_omap_fclk_state(host, OFF);
 		clk_put(host->iclk);
 		clk_put(host->fclk);
 		goto err1;
@@ -1122,6 +1181,7 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
 		if (ret < 0)
 			goto err_cover_switch;
 	}
+	mmc_omap_fclk_lazy_disable(host);
 
 	return 0;
 
@@ -1134,7 +1194,7 @@ err_irq_cd:
 err_irq_cd_init:
 	free_irq(host->irq, host);
 err_irq:
-	clk_disable(host->fclk);
+	mmc_omap_fclk_state(host, OFF);
 	clk_disable(host->iclk);
 	clk_put(host->fclk);
 	clk_put(host->iclk);
@@ -1167,7 +1227,7 @@ static int omap_mmc_remove(struct platform_device *pdev)
 			free_irq(mmc_slot(host).card_detect_irq, host);
 		flush_scheduled_work();
 
-		clk_disable(host->fclk);
+		mmc_omap_fclk_state(host, OFF);
 		clk_disable(host->iclk);
 		clk_put(host->fclk);
 		clk_put(host->iclk);
@@ -1202,6 +1262,7 @@ static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state)
 		if (ret == 0) {
 			host->suspended = 1;
 
+			mmc_omap_fclk_state(host, ON);
 			OMAP_HSMMC_WRITE(host->base, ISE, 0);
 			OMAP_HSMMC_WRITE(host->base, IE, 0);
 
@@ -1216,7 +1277,7 @@ static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state)
 
 			OMAP_HSMMC_WRITE(host->base, HCTL,
 					 OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP);
-			clk_disable(host->fclk);
+			mmc_omap_fclk_state(host, OFF);
 			clk_disable(host->iclk);
 			clk_disable(host->dbclk);
 		}
@@ -1236,13 +1297,13 @@ static int omap_mmc_resume(struct platform_device *pdev)
 
 	if (host) {
 
-		ret = clk_enable(host->fclk);
+		ret = mmc_omap_fclk_state(host, ON);
 		if (ret)
 			goto clk_en_err;
 
 		ret = clk_enable(host->iclk);
 		if (ret) {
-			clk_disable(host->fclk);
+			mmc_omap_fclk_state(host, OFF);
 			clk_put(host->fclk);
 			goto clk_en_err;
 		}
@@ -1264,6 +1325,8 @@ static int omap_mmc_resume(struct platform_device *pdev)
 		ret = mmc_resume_host(host->mmc);
 		if (ret == 0)
 			host->suspended = 0;
+
+		mmc_omap_fclk_lazy_disable(host);
 	}
 
 	return ret;
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 9/10] OMAP: HSMMC: Fix MMC3 dma
  2009-03-12 16:22 [PATCH 0/10] omap_hsmmc patches Adrian Hunter
                   ` (7 preceding siblings ...)
  2009-03-12 16:23 ` [PATCH 8/10] OMAP: HSMMC: Make driver support dynamic idle Adrian Hunter
@ 2009-03-12 16:23 ` Adrian Hunter
  2009-03-13 10:16   ` Adrian Hunter
  2009-03-12 16:24 ` [PATCH 10/10] OMAP: HSMMC: Wait for SDBP Adrian Hunter
  2009-03-22 14:31 ` [PATCH 0/10] omap_hsmmc patches Pierre Ossman
  10 siblings, 1 reply; 14+ messages in thread
From: Adrian Hunter @ 2009-03-12 16:23 UTC (permalink / raw)
  To: Pierre Ossman
  Cc: Jarkko Lavinen, Adrian Hunter, Grazvydas Ignotas, David Brownell,
	linux-omap Mailing List, Tony Lindgren, lkml

>From 6cdb22ab764bf852097674c26d521d3e8a1e5581 Mon Sep 17 00:00:00 2001
From: Grazvydas Ignotas <notasas at>
Date: Sat, 3 Jan 2009 10:36:13 +0000
Subject: [PATCH] OMAP: HSMMC: Fix MMC3 dma

Data transfers on third OMAP3 MMC controller don't work
because DMA line numbers are only defined for MMC1 and MMC2.
Fix that and store line numbers in mmc_omap_host structure
to reduce code size.
Tested on OMAP3 pandora board.

Signed-off-by: Grazvydas Ignotas <notasas <at> gmail.com>
---
 drivers/mmc/host/omap_hsmmc.c |   36 +++++++++++++++++++++++++-----------
 1 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 0e47073..91381f4 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -100,6 +100,7 @@
  */
 #define OMAP_MMC1_DEVID		0
 #define OMAP_MMC2_DEVID		1
+#define OMAP_MMC3_DEVID		2
 
 #define MMC_TIMEOUT_MS		20
 #define OMAP_MMC_MASTER_CLOCK	96000000
@@ -147,6 +148,7 @@ struct mmc_omap_host {
 	int			irq;
 	int			carddetect;
 	int			use_dma, dma_ch;
+	int			dma_line_tx, dma_line_rx;
 	int			slot_id;
 	int			dbclk_enabled;
 	int			response_busy;
@@ -652,17 +654,10 @@ static int mmc_omap_get_dma_sync_dev(struct mmc_omap_host *host,
 {
 	int sync_dev;
 
-	if (data->flags & MMC_DATA_WRITE) {
-		if (host->id == OMAP_MMC1_DEVID)
-			sync_dev = OMAP24XX_DMA_MMC1_TX;
-		else
-			sync_dev = OMAP24XX_DMA_MMC2_TX;
-	} else {
-		if (host->id == OMAP_MMC1_DEVID)
-			sync_dev = OMAP24XX_DMA_MMC1_RX;
-		else
-			sync_dev = OMAP24XX_DMA_MMC2_RX;
-	}
+	if (data->flags & MMC_DATA_WRITE)
+		sync_dev = host->dma_line_tx;
+	else
+		sync_dev = host->dma_line_rx;
 	return sync_dev;
 }
 
@@ -1134,6 +1129,25 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
 
 	omap_hsmmc_init(host);
 
+	/* Select DMA lines */
+	switch (host->id) {
+	case OMAP_MMC1_DEVID:
+		host->dma_line_tx = OMAP24XX_DMA_MMC1_TX;
+		host->dma_line_rx = OMAP24XX_DMA_MMC1_RX;
+		break;
+	case OMAP_MMC2_DEVID:
+		host->dma_line_tx = OMAP24XX_DMA_MMC2_TX;
+		host->dma_line_rx = OMAP24XX_DMA_MMC2_RX;
+		break;
+	case OMAP_MMC3_DEVID:
+		host->dma_line_tx = OMAP34XX_DMA_MMC3_TX;
+		host->dma_line_rx = OMAP34XX_DMA_MMC3_RX;
+		break;
+	default:
+		dev_err(mmc_dev(host->mmc), "Invalid MMC id\n");
+		goto err_irq;
+	}
+
 	/* Request IRQ for MMC operations */
 	ret = request_irq(host->irq, mmc_omap_irq, IRQF_DISABLED,
 			mmc_hostname(mmc), host);
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 10/10] OMAP: HSMMC: Wait for SDBP
  2009-03-12 16:22 [PATCH 0/10] omap_hsmmc patches Adrian Hunter
                   ` (8 preceding siblings ...)
  2009-03-12 16:23 ` [PATCH 9/10] OMAP: HSMMC: Fix MMC3 dma Adrian Hunter
@ 2009-03-12 16:24 ` Adrian Hunter
  2009-03-22 14:31 ` [PATCH 0/10] omap_hsmmc patches Pierre Ossman
  10 siblings, 0 replies; 14+ messages in thread
From: Adrian Hunter @ 2009-03-12 16:24 UTC (permalink / raw)
  To: Pierre Ossman
  Cc: Jarkko Lavinen, Adrian Hunter, Grazvydas Ignotas, David Brownell,
	linux-omap Mailing List, Tony Lindgren, lkml

>From e543f7849ab668fa0cbabc048e37e090e7b6f167 Mon Sep 17 00:00:00 2001
From: Adrian Hunter <adrian.hunter@nokia.com>
Date: Thu, 12 Mar 2009 17:08:26 +0200
Subject: [PATCH] OMAP: HSMMC: Wait for SDBP

It is necessary to wait for bus power before sending
any commands.

Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   20 +++++++++++++++-----
 1 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 91381f4..2f444c8 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -546,6 +546,19 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static void set_sd_bus_power(struct mmc_omap_host *host)
+{
+	unsigned long i;
+
+	OMAP_HSMMC_WRITE(host->base, HCTL,
+			 OMAP_HSMMC_READ(host->base, HCTL) | SDBP);
+	for (i = 0; i < loops_per_jiffy; i++) {
+		if (OMAP_HSMMC_READ(host->base, HCTL) & SDBP)
+			break;
+		cpu_relax();
+	}
+}
+
 /*
  * Switch MMC interface voltage ... only relevant for MMC1.
  *
@@ -602,9 +615,7 @@ static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd)
 		reg_val |= SDVS30;
 
 	OMAP_HSMMC_WRITE(host->base, HCTL, reg_val);
-
-	OMAP_HSMMC_WRITE(host->base, HCTL,
-		OMAP_HSMMC_READ(host->base, HCTL) | SDBP);
+	set_sd_bus_power(host);
 
 	return 0;
 err:
@@ -997,8 +1008,7 @@ static void omap_hsmmc_init(struct mmc_omap_host *host)
 	OMAP_HSMMC_WRITE(host->base, SYSCONFIG, value | AUTOIDLE);
 
 	/* Set SD bus power bit */
-	value = OMAP_HSMMC_READ(host->base, HCTL);
-	OMAP_HSMMC_WRITE(host->base, HCTL, value | SDBP);
+	set_sd_bus_power(host);
 }
 
 static struct mmc_host_ops mmc_omap_ops = {
-- 
1.5.6.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 9/10] OMAP: HSMMC: Fix MMC3 dma
  2009-03-12 16:23 ` [PATCH 9/10] OMAP: HSMMC: Fix MMC3 dma Adrian Hunter
@ 2009-03-13 10:16   ` Adrian Hunter
  0 siblings, 0 replies; 14+ messages in thread
From: Adrian Hunter @ 2009-03-13 10:16 UTC (permalink / raw)
  To: Hunter Adrian (Nokia-D/Helsinki)
  Cc: Pierre Ossman, Lavinen Jarkko (Nokia-D/Helsinki),
	Grazvydas Ignotas, David Brownell, linux-omap Mailing List,
	Tony Lindgren, lkml

>From 6cdb22ab764bf852097674c26d521d3e8a1e5581 Mon Sep 17 00:00:00 2001
From: Grazvydas Ignotas <notasas@gmail.com>
Date: Sat, 3 Jan 2009 10:36:13 +0000
Subject: [PATCH] OMAP: HSMMC: Fix MMC3 dma

Data transfers on third OMAP3 MMC controller don't work
because DMA line numbers are only defined for MMC1 and MMC2.
Fix that and store line numbers in mmc_omap_host structure
to reduce code size.
Tested on OMAP3 pandora board.

Signed-off-by: Grazvydas Ignotas <notasas@gmail.com>
---



This time with Grazvydas Ignotas email address fixed.



 drivers/mmc/host/omap_hsmmc.c |   36 +++++++++++++++++++++++++-----------
 1 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 0e47073..91381f4 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -100,6 +100,7 @@
  */
 #define OMAP_MMC1_DEVID		0
 #define OMAP_MMC2_DEVID		1
+#define OMAP_MMC3_DEVID		2
 
 #define MMC_TIMEOUT_MS		20
 #define OMAP_MMC_MASTER_CLOCK	96000000
@@ -147,6 +148,7 @@ struct mmc_omap_host {
 	int			irq;
 	int			carddetect;
 	int			use_dma, dma_ch;
+	int			dma_line_tx, dma_line_rx;
 	int			slot_id;
 	int			dbclk_enabled;
 	int			response_busy;
@@ -652,17 +654,10 @@ static int mmc_omap_get_dma_sync_dev(struct mmc_omap_host *host,
 {
 	int sync_dev;
 
-	if (data->flags & MMC_DATA_WRITE) {
-		if (host->id == OMAP_MMC1_DEVID)
-			sync_dev = OMAP24XX_DMA_MMC1_TX;
-		else
-			sync_dev = OMAP24XX_DMA_MMC2_TX;
-	} else {
-		if (host->id == OMAP_MMC1_DEVID)
-			sync_dev = OMAP24XX_DMA_MMC1_RX;
-		else
-			sync_dev = OMAP24XX_DMA_MMC2_RX;
-	}
+	if (data->flags & MMC_DATA_WRITE)
+		sync_dev = host->dma_line_tx;
+	else
+		sync_dev = host->dma_line_rx;
 	return sync_dev;
 }
 
@@ -1134,6 +1129,25 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
 
 	omap_hsmmc_init(host);
 
+	/* Select DMA lines */
+	switch (host->id) {
+	case OMAP_MMC1_DEVID:
+		host->dma_line_tx = OMAP24XX_DMA_MMC1_TX;
+		host->dma_line_rx = OMAP24XX_DMA_MMC1_RX;
+		break;
+	case OMAP_MMC2_DEVID:
+		host->dma_line_tx = OMAP24XX_DMA_MMC2_TX;
+		host->dma_line_rx = OMAP24XX_DMA_MMC2_RX;
+		break;
+	case OMAP_MMC3_DEVID:
+		host->dma_line_tx = OMAP34XX_DMA_MMC3_TX;
+		host->dma_line_rx = OMAP34XX_DMA_MMC3_RX;
+		break;
+	default:
+		dev_err(mmc_dev(host->mmc), "Invalid MMC id\n");
+		goto err_irq;
+	}
+
 	/* Request IRQ for MMC operations */
 	ret = request_irq(host->irq, mmc_omap_irq, IRQF_DISABLED,
 			mmc_hostname(mmc), host);
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 8/10] OMAP: HSMMC: Make driver support dynamic idle
  2009-03-12 16:23 ` [PATCH 8/10] OMAP: HSMMC: Make driver support dynamic idle Adrian Hunter
@ 2009-03-22 14:30   ` Pierre Ossman
  0 siblings, 0 replies; 14+ messages in thread
From: Pierre Ossman @ 2009-03-22 14:30 UTC (permalink / raw)
  Cc: Jarkko Lavinen, Adrian Hunter, Grazvydas Ignotas, David Brownell,
	linux-omap Mailing List, Tony Lindgren, lkml

On Thu, 12 Mar 2009 18:23:46 +0200
Adrian Hunter <adrian.hunter@nokia.com> wrote:

> From 47b6de0fcfeb5948199dbed941847580bedc5315 Mon Sep 17 00:00:00 2001
> From: Amit Kucheria <amit.kucheria@verdurent.com>
> Date: Thu, 12 Mar 2009 15:47:39 +0200
> Subject: [PATCH] OMAP: HSMMC: Make driver support dynamic idle
> 
> Add a timer that is kept active by MMC requests. FCLK is disabled on
> timeout.
> 
> Signed-off-by: Amit Kucheria <amit.kucheria@verdurent.com>
> Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
> Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
> ---

NAK. This should be implemented in the core where we get a consistent
behaviour across all hosts. The principle with a timeout is sound
though.

As for the current state of the driver, stop fiddling with the clock
when it isn't necessary.

Rgds
-- 
     -- Pierre Ossman

  Linux kernel, MMC maintainer        http://www.kernel.org
  rdesktop, core developer          http://www.rdesktop.org

  WARNING: This correspondence is being monitored by the
  Swedish government. Make sure your server uses encryption
  for SMTP traffic and consider using PGP for end-to-end
  encryption.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/10] omap_hsmmc patches
  2009-03-12 16:22 [PATCH 0/10] omap_hsmmc patches Adrian Hunter
                   ` (9 preceding siblings ...)
  2009-03-12 16:24 ` [PATCH 10/10] OMAP: HSMMC: Wait for SDBP Adrian Hunter
@ 2009-03-22 14:31 ` Pierre Ossman
  10 siblings, 0 replies; 14+ messages in thread
From: Pierre Ossman @ 2009-03-22 14:31 UTC (permalink / raw)
  Cc: Jarkko Lavinen, Adrian Hunter, Grazvydas Ignotas, David Brownell,
	linux-omap Mailing List, Tony Lindgren, lkml

On Thu, 12 Mar 2009 18:22:52 +0200
Adrian Hunter <adrian.hunter@nokia.com> wrote:

> Here are 10 patches for omap_hsmmc.
> 
> They apply to the 'next' branch of Pierre Ossman's mmc tree.

Queued everything except patch 8, thanks.

Rgds
-- 
     -- Pierre Ossman

  Linux kernel, MMC maintainer        http://www.kernel.org
  rdesktop, core developer          http://www.rdesktop.org

  WARNING: This correspondence is being monitored by the
  Swedish government. Make sure your server uses encryption
  for SMTP traffic and consider using PGP for end-to-end
  encryption.

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2009-03-22 14:31 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-03-12 16:22 [PATCH 0/10] omap_hsmmc patches Adrian Hunter
2009-03-12 16:22 ` [PATCH 1/10] OMAP: HSMMC: Do dma cleanup also with data CRC errors Adrian Hunter
2009-03-12 16:23 ` [PATCH 2/10] OMAP: HSMMC: Fix response type for busy after response Adrian Hunter
2009-03-12 16:23 ` [PATCH 3/10] OMAP: HSMMC: Implement scatter-gather emulation Adrian Hunter
2009-03-12 16:23 ` [PATCH 4/10] OMAP: HSMMC: Add 8-bit bus width mode support Adrian Hunter
2009-03-12 16:23 ` [PATCH 5/10] OMAP: HSMMC: Allow cover switch to cause rescan Adrian Hunter
2009-03-12 16:23 ` [PATCH 6/10] OMAP: HSMMC: Do not prefix slot name Adrian Hunter
2009-03-12 16:23 ` [PATCH 7/10] OMAP: HSMMC: Disable SDBP at suspend Adrian Hunter
2009-03-12 16:23 ` [PATCH 8/10] OMAP: HSMMC: Make driver support dynamic idle Adrian Hunter
2009-03-22 14:30   ` Pierre Ossman
2009-03-12 16:23 ` [PATCH 9/10] OMAP: HSMMC: Fix MMC3 dma Adrian Hunter
2009-03-13 10:16   ` Adrian Hunter
2009-03-12 16:24 ` [PATCH 10/10] OMAP: HSMMC: Wait for SDBP Adrian Hunter
2009-03-22 14:31 ` [PATCH 0/10] omap_hsmmc patches Pierre Ossman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).