* [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).