linux-mmc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] ARM: MXC: mxcmmc: misc cleanups
@ 2010-03-30 18:31 Daniel Mack
  2010-03-30 18:32 ` [PATCH 2/3] ARM: MXC: mxcmmc: Teach the driver SDIO operations Daniel Mack
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Daniel Mack @ 2010-03-30 18:31 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-mmc, Daniel Mack, Sascha Hauer, Dan Williams, Volker Ernst,
	Jiri Kosina

Add some more debug information and fix a couple of coding style things
in mxcmmc.c.

Signed-off-by: Daniel Mack <daniel@caiaq.de>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Volker Ernst <volker.ernst@txtr.com>
Cc: Jiri Kosina <jkosina@suse.cz>
---
 drivers/mmc/host/mxcmmc.c |   28 +++++++++++++++++-----------
 1 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index 2df9041..21037ff 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -151,6 +151,8 @@ static void mxcmci_softreset(struct mxcmci_host *host)
 {
 	int i;
 
+	dev_dbg(mmc_dev(host->mmc), "mxcmci_softreset\n");
+
 	/* reset sequence */
 	writew(STR_STP_CLK_RESET, host->base + MMC_REG_STR_STP_CLK);
 	writew(STR_STP_CLK_RESET | STR_STP_CLK_START_CLK,
@@ -290,21 +292,29 @@ static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat)
 		dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n",
 				stat);
 		if (stat & STATUS_CRC_READ_ERR) {
+			dev_err(mmc_dev(host->mmc), "%s: -EILSEQ\n", __func__);
 			data->error = -EILSEQ;
 		} else if (stat & STATUS_CRC_WRITE_ERR) {
 			u32 err_code = (stat >> 9) & 0x3;
-			if (err_code == 2) /* No CRC response */
+			if (err_code == 2) { /* No CRC response */
+				dev_err(mmc_dev(host->mmc),
+					"%s: No CRC -ETIMEDOUT\n", __func__);
 				data->error = -ETIMEDOUT;
-			else
+			} else {
+				dev_err(mmc_dev(host->mmc),
+					"%s: -EILSEQ\n", __func__);
 				data->error = -EILSEQ;
+			}
 		} else if (stat & STATUS_TIME_OUT_READ) {
+			dev_err(mmc_dev(host->mmc),
+				"%s: read -ETIMEDOUT\n", __func__);
 			data->error = -ETIMEDOUT;
 		} else {
+			dev_err(mmc_dev(host->mmc), "%s: -EIO\n", __func__);
 			data->error = -EIO;
 		}
-	} else {
+	} else
 		data->bytes_xfered = host->datasize;
-	}
 
 	data_error = data->error;
 
@@ -433,8 +443,6 @@ static int mxcmci_transfer_data(struct mxcmci_host *host)
 	struct scatterlist *sg;
 	int stat, i;
 
-	host->datasize = 0;
-
 	host->data = data;
 	host->datasize = 0;
 
@@ -471,9 +479,8 @@ static void mxcmci_datawork(struct work_struct *work)
 			mxcmci_finish_request(host, host->req);
 			return;
 		}
-	} else {
+	} else
 		mxcmci_finish_request(host, host->req);
-	}
 }
 
 #ifdef HAS_DMA
@@ -495,9 +502,8 @@ static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat)
 			mxcmci_finish_request(host, host->req);
 			return;
 		}
-	} else {
+	} else
 		mxcmci_finish_request(host, host->req);
-	}
 }
 #endif /* HAS_DMA */
 
@@ -512,7 +518,7 @@ static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat)
 	}
 
 	/* For the DMA case the DMA engine handles the data transfer
-	 * automatically. For non DMA we have to do it ourselves.
+	 * automatically. For non DMA we have to to it ourselves.
 	 * Don't do it in interrupt context though.
 	 */
 	if (!mxcmci_use_dma(host) && host->data)
-- 
1.7.0


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

* [PATCH 2/3] ARM: MXC: mxcmmc: Teach the driver SDIO operations
  2010-03-30 18:31 [PATCH 1/3] ARM: MXC: mxcmmc: misc cleanups Daniel Mack
@ 2010-03-30 18:32 ` Daniel Mack
  2010-03-31 13:03   ` Sascha Hauer
  2010-03-30 18:32 ` [PATCH 3/3] ARM: MXC: mxcmmc: work around a bug in the SDHC busy line handling Daniel Mack
  2010-03-31 12:38 ` [PATCH 1/3] ARM: MXC: mxcmmc: misc cleanups Sascha Hauer
  2 siblings, 1 reply; 8+ messages in thread
From: Daniel Mack @ 2010-03-30 18:32 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-mmc, Daniel Mack, Sascha Hauer, Dan Williams, Volker Ernst,
	Jiri Kosina

Successfully tested on MX31 hardware using libertas SDIO peripherals.

Signed-off-by: Daniel Mack <daniel@caiaq.de>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Volker Ernst <volker.ernst@txtr.com>
Cc: Jiri Kosina <jkosina@suse.cz>
---
 drivers/mmc/host/mxcmmc.c |   55 ++++++++++++++++++++++++++++++++++++--------
 1 files changed, 45 insertions(+), 10 deletions(-)

diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index 21037ff..83a4545 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -119,6 +119,7 @@ struct mxcmci_host {
 	int			detect_irq;
 	int			dma;
 	int			do_dma;
+	int			use_sdio;
 	unsigned int		power_mode;
 	struct imxmmc_platform_data *pdata;
 
@@ -138,6 +139,7 @@ struct mxcmci_host {
 	int			clock;
 
 	struct work_struct	datawork;
+	spinlock_t		lock;
 };
 
 static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios);
@@ -226,6 +228,8 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
 static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd,
 		unsigned int cmdat)
 {
+	u32 int_cntr;
+
 	WARN_ON(host->cmd != NULL);
 	host->cmd = cmd;
 
@@ -249,13 +253,15 @@ static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd,
 		return -EINVAL;
 	}
 
+	int_cntr = INT_END_CMD_RES_EN;
+
 	if (mxcmci_use_dma(host))
-		writel(INT_READ_OP_EN | INT_WRITE_OP_DONE_EN |
-				INT_END_CMD_RES_EN,
-				host->base + MMC_REG_INT_CNTR);
-	else
-		writel(INT_END_CMD_RES_EN, host->base + MMC_REG_INT_CNTR);
+		int_cntr |= INT_READ_OP_EN | INT_WRITE_OP_DONE_EN;
+
+	if (host->use_sdio)
+		int_cntr |= INT_SDIO_IRQ_EN;
 
+	writel(int_cntr, host->base + MMC_REG_INT_CNTR);
 	writew(cmd->opcode, host->base + MMC_REG_CMD);
 	writel(cmd->arg, host->base + MMC_REG_ARG);
 	writew(cmdat, host->base + MMC_REG_CMD_DAT_CONT);
@@ -266,7 +272,12 @@ static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd,
 static void mxcmci_finish_request(struct mxcmci_host *host,
 		struct mmc_request *req)
 {
-	writel(0, host->base + MMC_REG_INT_CNTR);
+	u32 int_cntr = 0;
+
+	if (host->use_sdio)
+		int_cntr |= INT_SDIO_IRQ_EN;
+
+	writel(int_cntr, host->base + MMC_REG_INT_CNTR);
 
 	host->req = NULL;
 	host->cmd = NULL;
@@ -536,8 +547,12 @@ static irqreturn_t mxcmci_irq(int irq, void *devid)
 
 	dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat);
 
+	if ((stat & STATUS_SDIO_INT_ACTIVE) && host->use_sdio)
+		mmc_signal_sdio_irq(host->mmc);
+
 	if (stat & STATUS_END_CMD_RESP)
 		mxcmci_cmd_done(host, stat);
+
 #ifdef HAS_DMA
 	if (mxcmci_use_dma(host) &&
 		  (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE)))
@@ -674,11 +689,30 @@ static int mxcmci_get_ro(struct mmc_host *mmc)
 	return -ENOSYS;
 }
 
+static void mxcmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+	struct mxcmci_host *host = mmc_priv(mmc);
+	unsigned long flags;
+	u32 int_cntr;
+
+	spin_lock_irqsave(&host->lock, flags);
+	host->use_sdio = enable;
+	int_cntr = readl(host->base + MMC_REG_INT_CNTR);
+
+	if (enable)
+		int_cntr |= INT_SDIO_IRQ_EN;
+	else
+		int_cntr &= ~INT_SDIO_IRQ_EN;
+
+	writel(int_cntr, host->base + MMC_REG_INT_CNTR);
+	spin_unlock_irqrestore(&host->lock, flags);
+}
 
 static const struct mmc_host_ops mxcmci_ops = {
-	.request	= mxcmci_request,
-	.set_ios	= mxcmci_set_ios,
-	.get_ro		= mxcmci_get_ro,
+	.request		= mxcmci_request,
+	.set_ios		= mxcmci_set_ios,
+	.get_ro			= mxcmci_get_ro,
+	.enable_sdio_irq	= mxcmci_enable_sdio_irq,
 };
 
 static int mxcmci_probe(struct platform_device *pdev)
@@ -706,7 +740,7 @@ static int mxcmci_probe(struct platform_device *pdev)
 	}
 
 	mmc->ops = &mxcmci_ops;
-	mmc->caps = MMC_CAP_4_BIT_DATA;
+	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
 
 	/* MMC core transfer sizes tunable parameters */
 	mmc->max_hw_segs = 64;
@@ -725,6 +759,7 @@ static int mxcmci_probe(struct platform_device *pdev)
 
 	host->mmc = mmc;
 	host->pdata = pdev->dev.platform_data;
+	spin_lock_init(&host->lock);
 
 	if (host->pdata && host->pdata->ocr_avail)
 		mmc->ocr_avail = host->pdata->ocr_avail;
-- 
1.7.0


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

* [PATCH 3/3] ARM: MXC: mxcmmc: work around a bug in the SDHC busy line handling
  2010-03-30 18:31 [PATCH 1/3] ARM: MXC: mxcmmc: misc cleanups Daniel Mack
  2010-03-30 18:32 ` [PATCH 2/3] ARM: MXC: mxcmmc: Teach the driver SDIO operations Daniel Mack
@ 2010-03-30 18:32 ` Daniel Mack
  2010-03-31 12:38 ` [PATCH 1/3] ARM: MXC: mxcmmc: misc cleanups Sascha Hauer
  2 siblings, 0 replies; 8+ messages in thread
From: Daniel Mack @ 2010-03-30 18:32 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-mmc, Daniel Mack, Sascha Hauer, Dan Williams, Volker Ernst,
	Jiri Kosina

MX3 SoCs have a silicon bug which corrupts CRC calculation of
multi-block transfers when connected SDIO peripheral doesn't drive the
BUSY line as required by the specs.

One way to prevent this is to only allow 1-bit transfers.

Another way is playing tricks with the DMA engine, but this isn't
mainline yet. So for now, we live with the performance drawback of 1-bit
transfers until a nicer solution is found.

This patch introduces a new host controller callback 'init_card' which
is for now only called from mmc_sdio_init_card().

Signed-off-by: Daniel Mack <daniel@caiaq.de>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Volker Ernst <volker.ernst@txtr.com>
Cc: Jiri Kosina <jkosina@suse.cz>
---
 drivers/mmc/core/sdio.c   |    6 ++++++
 drivers/mmc/host/mxcmmc.c |   14 ++++++++++++++
 include/linux/mmc/host.h  |    3 +++
 3 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 2dd4cfe..b9dee28 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -296,6 +296,12 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
 	card->type = MMC_TYPE_SDIO;
 
 	/*
+	 * Call the optional HC's init_card function to handle quirks.
+	 */
+	if (host->ops->init_card)
+		host->ops->init_card(host, card);
+
+	/*
 	 * For native busses:  set card RCA and quit open drain mode.
 	 */
 	if (!powered_resume && !mmc_host_is_spi(host)) {
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index 83a4545..f584c1b 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -708,11 +708,25 @@ static void mxcmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
 	spin_unlock_irqrestore(&host->lock, flags);
 }
 
+static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card)
+{
+	/*
+	 * MX3 SoCs have a silicon bug which corrupts CRC calculation of
+	 * multi-block transfers when connected SDIO peripheral doesn't
+	 * drive the BUSY line as required by the specs.
+	 * One way to prevent this is to only allow 1-bit transfers.
+	 */
+
+	if (cpu_is_mx3() && card->type == MMC_TYPE_SDIO)
+		host->caps &= ~MMC_CAP_4_BIT_DATA;
+}
+
 static const struct mmc_host_ops mxcmci_ops = {
 	.request		= mxcmci_request,
 	.set_ios		= mxcmci_set_ios,
 	.get_ro			= mxcmci_get_ro,
 	.enable_sdio_irq	= mxcmci_enable_sdio_irq,
+	.init_card		= mxcmci_init_card,
 };
 
 static int mxcmci_probe(struct platform_device *pdev)
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 43eaf5c..3196c84 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -108,6 +108,9 @@ struct mmc_host_ops {
 	int	(*get_cd)(struct mmc_host *host);
 
 	void	(*enable_sdio_irq)(struct mmc_host *host, int enable);
+
+	/* optional callback for HC quirks */
+	void	(*init_card)(struct mmc_host *host, struct mmc_card *card);
 };
 
 struct mmc_card;
-- 
1.7.0


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

* Re: [PATCH 1/3] ARM: MXC: mxcmmc: misc cleanups
  2010-03-30 18:31 [PATCH 1/3] ARM: MXC: mxcmmc: misc cleanups Daniel Mack
  2010-03-30 18:32 ` [PATCH 2/3] ARM: MXC: mxcmmc: Teach the driver SDIO operations Daniel Mack
  2010-03-30 18:32 ` [PATCH 3/3] ARM: MXC: mxcmmc: work around a bug in the SDHC busy line handling Daniel Mack
@ 2010-03-31 12:38 ` Sascha Hauer
  2010-03-31 13:02   ` Daniel Mack
  2 siblings, 1 reply; 8+ messages in thread
From: Sascha Hauer @ 2010-03-31 12:38 UTC (permalink / raw)
  To: Daniel Mack
  Cc: linux-arm-kernel, linux-mmc, Dan Williams, Volker Ernst,
	Jiri Kosina

Hi Daniel,

On Tue, Mar 30, 2010 at 08:31:59PM +0200, Daniel Mack wrote:
> Add some more debug information and fix a couple of coding style things
> in mxcmmc.c.
> 
> Signed-off-by: Daniel Mack <daniel@caiaq.de>
> Cc: Sascha Hauer <s.hauer@pengutronix.de>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Cc: Volker Ernst <volker.ernst@txtr.com>
> Cc: Jiri Kosina <jkosina@suse.cz>
> ---
>  drivers/mmc/host/mxcmmc.c |   28 +++++++++++++++++-----------
>  1 files changed, 17 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
> index 2df9041..21037ff 100644
> --- a/drivers/mmc/host/mxcmmc.c
> +++ b/drivers/mmc/host/mxcmmc.c
> @@ -151,6 +151,8 @@ static void mxcmci_softreset(struct mxcmci_host *host)
>  {
>  	int i;
>  
> +	dev_dbg(mmc_dev(host->mmc), "mxcmci_softreset\n");
> +
>  	/* reset sequence */
>  	writew(STR_STP_CLK_RESET, host->base + MMC_REG_STR_STP_CLK);
>  	writew(STR_STP_CLK_RESET | STR_STP_CLK_START_CLK,
> @@ -290,21 +292,29 @@ static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat)
>  		dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n",
>  				stat);
>  		if (stat & STATUS_CRC_READ_ERR) {
> +			dev_err(mmc_dev(host->mmc), "%s: -EILSEQ\n", __func__);
>  			data->error = -EILSEQ;
>  		} else if (stat & STATUS_CRC_WRITE_ERR) {
>  			u32 err_code = (stat >> 9) & 0x3;
> -			if (err_code == 2) /* No CRC response */
> +			if (err_code == 2) { /* No CRC response */
> +				dev_err(mmc_dev(host->mmc),
> +					"%s: No CRC -ETIMEDOUT\n", __func__);
>  				data->error = -ETIMEDOUT;
> -			else
> +			} else {
> +				dev_err(mmc_dev(host->mmc),
> +					"%s: -EILSEQ\n", __func__);
>  				data->error = -EILSEQ;
> +			}
>  		} else if (stat & STATUS_TIME_OUT_READ) {
> +			dev_err(mmc_dev(host->mmc),
> +				"%s: read -ETIMEDOUT\n", __func__);
>  			data->error = -ETIMEDOUT;
>  		} else {
> +			dev_err(mmc_dev(host->mmc), "%s: -EIO\n", __func__);

Do we really want to have these messages with dev_err? In the subject
you are talking about debug output.

>  			data->error = -EIO;
>  		}
> -	} else {
> +	} else
>  		data->bytes_xfered = host->datasize;
> -	}

Documentation/CodingStyle says that if braces are used in one branch of
a conditional then they should be used in both branches.
I personally don't care much about this statement but I think we should
leave it as is. Otherwise some day someone wants to change it back
according to the coding style.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* Re: [PATCH 1/3] ARM: MXC: mxcmmc: misc cleanups
  2010-03-31 12:38 ` [PATCH 1/3] ARM: MXC: mxcmmc: misc cleanups Sascha Hauer
@ 2010-03-31 13:02   ` Daniel Mack
  0 siblings, 0 replies; 8+ messages in thread
From: Daniel Mack @ 2010-03-31 13:02 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: linux-arm-kernel, linux-mmc, Dan Williams, Volker Ernst,
	Jiri Kosina

On Wed, Mar 31, 2010 at 02:38:56PM +0200, Sascha Hauer wrote:
> On Tue, Mar 30, 2010 at 08:31:59PM +0200, Daniel Mack wrote:
> > +			dev_err(mmc_dev(host->mmc),
> > +				"%s: read -ETIMEDOUT\n", __func__);
> >  			data->error = -ETIMEDOUT;
> >  		} else {
> > +			dev_err(mmc_dev(host->mmc), "%s: -EIO\n", __func__);
> 
> Do we really want to have these messages with dev_err? In the subject
> you are talking about debug output.

This _is_ definitely an error if get there, so I'll rather change the
commit message ;)

> 
> >  			data->error = -EIO;
> >  		}
> > -	} else {
> > +	} else
> >  		data->bytes_xfered = host->datasize;
> > -	}
> 
> Documentation/CodingStyle says that if braces are used in one branch of
> a conditional then they should be used in both branches.
> I personally don't care much about this statement but I think we should
> leave it as is. Otherwise some day someone wants to change it back
> according to the coding style.

Ok, true. I'll fix this (and the commit message) and resend.

Thanks,
Daniel

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

* Re: [PATCH 2/3] ARM: MXC: mxcmmc: Teach the driver SDIO operations
  2010-03-30 18:32 ` [PATCH 2/3] ARM: MXC: mxcmmc: Teach the driver SDIO operations Daniel Mack
@ 2010-03-31 13:03   ` Sascha Hauer
  2010-03-31 13:29     ` Daniel Mack
  0 siblings, 1 reply; 8+ messages in thread
From: Sascha Hauer @ 2010-03-31 13:03 UTC (permalink / raw)
  To: Daniel Mack
  Cc: linux-arm-kernel, linux-mmc, Dan Williams, Volker Ernst,
	Jiri Kosina

On Tue, Mar 30, 2010 at 08:32:00PM +0200, Daniel Mack wrote:
> Successfully tested on MX31 hardware using libertas SDIO peripherals.
> 
> Signed-off-by: Daniel Mack <daniel@caiaq.de>
> Cc: Sascha Hauer <s.hauer@pengutronix.de>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Cc: Volker Ernst <volker.ernst@txtr.com>
> Cc: Jiri Kosina <jkosina@suse.cz>
> ---
>  drivers/mmc/host/mxcmmc.c |   55 ++++++++++++++++++++++++++++++++++++--------
>  1 files changed, 45 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
> index 21037ff..83a4545 100644
> --- a/drivers/mmc/host/mxcmmc.c
> +++ b/drivers/mmc/host/mxcmmc.c
> @@ -119,6 +119,7 @@ struct mxcmci_host {
>  	int			detect_irq;
>  	int			dma;
>  	int			do_dma;
> +	int			use_sdio;
>  	unsigned int		power_mode;
>  	struct imxmmc_platform_data *pdata;
>  
> @@ -138,6 +139,7 @@ struct mxcmci_host {
>  	int			clock;
>  
>  	struct work_struct	datawork;
> +	spinlock_t		lock;
>  };
>  
>  static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios);
> @@ -226,6 +228,8 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
>  static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd,
>  		unsigned int cmdat)
>  {
> +	u32 int_cntr;
> +
>  	WARN_ON(host->cmd != NULL);
>  	host->cmd = cmd;
>  
> @@ -249,13 +253,15 @@ static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd,
>  		return -EINVAL;
>  	}
>  
> +	int_cntr = INT_END_CMD_RES_EN;
> +
>  	if (mxcmci_use_dma(host))
> -		writel(INT_READ_OP_EN | INT_WRITE_OP_DONE_EN |
> -				INT_END_CMD_RES_EN,
> -				host->base + MMC_REG_INT_CNTR);
> -	else
> -		writel(INT_END_CMD_RES_EN, host->base + MMC_REG_INT_CNTR);
> +		int_cntr |= INT_READ_OP_EN | INT_WRITE_OP_DONE_EN;
> +
> +	if (host->use_sdio)
> +		int_cntr |= INT_SDIO_IRQ_EN;
>  
> +	writel(int_cntr, host->base + MMC_REG_INT_CNTR);
>  	writew(cmd->opcode, host->base + MMC_REG_CMD);
>  	writel(cmd->arg, host->base + MMC_REG_ARG);
>  	writew(cmdat, host->base + MMC_REG_CMD_DAT_CONT);
> @@ -266,7 +272,12 @@ static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd,
>  static void mxcmci_finish_request(struct mxcmci_host *host,
>  		struct mmc_request *req)
>  {
> -	writel(0, host->base + MMC_REG_INT_CNTR);
> +	u32 int_cntr = 0;
> +
> +	if (host->use_sdio)
> +		int_cntr |= INT_SDIO_IRQ_EN;
> +
> +	writel(int_cntr, host->base + MMC_REG_INT_CNTR);
>  
>  	host->req = NULL;
>  	host->cmd = NULL;
> @@ -536,8 +547,12 @@ static irqreturn_t mxcmci_irq(int irq, void *devid)
>  
>  	dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat);
>  
> +	if ((stat & STATUS_SDIO_INT_ACTIVE) && host->use_sdio)
> +		mmc_signal_sdio_irq(host->mmc);
> +
>  	if (stat & STATUS_END_CMD_RESP)
>  		mxcmci_cmd_done(host, stat);
> +
>  #ifdef HAS_DMA
>  	if (mxcmci_use_dma(host) &&
>  		  (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE)))
> @@ -674,11 +689,30 @@ static int mxcmci_get_ro(struct mmc_host *mmc)
>  	return -ENOSYS;
>  }
>  
> +static void mxcmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
> +{
> +	struct mxcmci_host *host = mmc_priv(mmc);
> +	unsigned long flags;
> +	u32 int_cntr;
> +
> +	spin_lock_irqsave(&host->lock, flags);
> +	host->use_sdio = enable;
> +	int_cntr = readl(host->base + MMC_REG_INT_CNTR);
> +
> +	if (enable)
> +		int_cntr |= INT_SDIO_IRQ_EN;
> +	else
> +		int_cntr &= ~INT_SDIO_IRQ_EN;
> +
> +	writel(int_cntr, host->base + MMC_REG_INT_CNTR);
> +	spin_unlock_irqrestore(&host->lock, flags);

The other places where MMC_REG_INT_CNTR is touched should be protected
by this spinlock aswell.

Sascha

> +}
>  
>  static const struct mmc_host_ops mxcmci_ops = {
> -	.request	= mxcmci_request,
> -	.set_ios	= mxcmci_set_ios,
> -	.get_ro		= mxcmci_get_ro,
> +	.request		= mxcmci_request,
> +	.set_ios		= mxcmci_set_ios,
> +	.get_ro			= mxcmci_get_ro,
> +	.enable_sdio_irq	= mxcmci_enable_sdio_irq,
>  };
>  
>  static int mxcmci_probe(struct platform_device *pdev)
> @@ -706,7 +740,7 @@ static int mxcmci_probe(struct platform_device *pdev)
>  	}
>  
>  	mmc->ops = &mxcmci_ops;
> -	mmc->caps = MMC_CAP_4_BIT_DATA;
> +	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
>  
>  	/* MMC core transfer sizes tunable parameters */
>  	mmc->max_hw_segs = 64;
> @@ -725,6 +759,7 @@ static int mxcmci_probe(struct platform_device *pdev)
>  
>  	host->mmc = mmc;
>  	host->pdata = pdev->dev.platform_data;
> +	spin_lock_init(&host->lock);
>  
>  	if (host->pdata && host->pdata->ocr_avail)
>  		mmc->ocr_avail = host->pdata->ocr_avail;
> -- 
> 1.7.0
> 
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* Re: [PATCH 2/3] ARM: MXC: mxcmmc: Teach the driver SDIO operations
  2010-03-31 13:03   ` Sascha Hauer
@ 2010-03-31 13:29     ` Daniel Mack
  2010-03-31 16:41       ` Michał Mirosław
  0 siblings, 1 reply; 8+ messages in thread
From: Daniel Mack @ 2010-03-31 13:29 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: linux-arm-kernel, linux-mmc, Dan Williams, Volker Ernst,
	Jiri Kosina

On Wed, Mar 31, 2010 at 03:03:39PM +0200, Sascha Hauer wrote:
> On Tue, Mar 30, 2010 at 08:32:00PM +0200, Daniel Mack wrote:
> > +static void mxcmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
> > +{
> > +	struct mxcmci_host *host = mmc_priv(mmc);
> > +	unsigned long flags;
> > +	u32 int_cntr;
> > +
> > +	spin_lock_irqsave(&host->lock, flags);
> > +	host->use_sdio = enable;
> > +	int_cntr = readl(host->base + MMC_REG_INT_CNTR);
> > +
> > +	if (enable)
> > +		int_cntr |= INT_SDIO_IRQ_EN;
> > +	else
> > +		int_cntr &= ~INT_SDIO_IRQ_EN;
> > +
> > +	writel(int_cntr, host->base + MMC_REG_INT_CNTR);
> > +	spin_unlock_irqrestore(&host->lock, flags);
> 
> The other places where MMC_REG_INT_CNTR is touched should be protected
> by this spinlock aswell.

Hmm, all other place don't do a read/modify/write cycle, so I'd say the
don't need protection?

Daniel

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

* Re: [PATCH 2/3] ARM: MXC: mxcmmc: Teach the driver SDIO operations
  2010-03-31 13:29     ` Daniel Mack
@ 2010-03-31 16:41       ` Michał Mirosław
  0 siblings, 0 replies; 8+ messages in thread
From: Michał Mirosław @ 2010-03-31 16:41 UTC (permalink / raw)
  To: Daniel Mack
  Cc: Sascha Hauer, linux-arm-kernel, linux-mmc, Dan Williams,
	Volker Ernst, Jiri Kosina

2010/3/31 Daniel Mack <daniel@caiaq.de>:
> On Wed, Mar 31, 2010 at 03:03:39PM +0200, Sascha Hauer wrote:
>> On Tue, Mar 30, 2010 at 08:32:00PM +0200, Daniel Mack wrote:
>> > +static void mxcmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
>> > +{
>> > +   struct mxcmci_host *host = mmc_priv(mmc);
>> > +   unsigned long flags;
>> > +   u32 int_cntr;
>> > +
>> > +   spin_lock_irqsave(&host->lock, flags);
>> > +   host->use_sdio = enable;
>> > +   int_cntr = readl(host->base + MMC_REG_INT_CNTR);
>> > +
>> > +   if (enable)
>> > +           int_cntr |= INT_SDIO_IRQ_EN;
>> > +   else
>> > +           int_cntr &= ~INT_SDIO_IRQ_EN;
>> > +
>> > +   writel(int_cntr, host->base + MMC_REG_INT_CNTR);
>> > +   spin_unlock_irqrestore(&host->lock, flags);
>>
>> The other places where MMC_REG_INT_CNTR is touched should be protected
>> by this spinlock aswell.
> Hmm, all other place don't do a read/modify/write cycle, so I'd say the
> don't need protection?

If you miss spinlocks around the unconditional writes they might
happen between your readl() and writel().

Best Regards,
Michał Mirosław

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

end of thread, other threads:[~2010-03-31 16:41 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-03-30 18:31 [PATCH 1/3] ARM: MXC: mxcmmc: misc cleanups Daniel Mack
2010-03-30 18:32 ` [PATCH 2/3] ARM: MXC: mxcmmc: Teach the driver SDIO operations Daniel Mack
2010-03-31 13:03   ` Sascha Hauer
2010-03-31 13:29     ` Daniel Mack
2010-03-31 16:41       ` Michał Mirosław
2010-03-30 18:32 ` [PATCH 3/3] ARM: MXC: mxcmmc: work around a bug in the SDHC busy line handling Daniel Mack
2010-03-31 12:38 ` [PATCH 1/3] ARM: MXC: mxcmmc: misc cleanups Sascha Hauer
2010-03-31 13:02   ` Daniel Mack

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