linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] mmc: mmci: Improvements for SDIO
@ 2011-10-24 14:33 Ulf Hansson
  2011-10-24 14:33 ` [PATCH 1/2] mmc: mmci: Support non-power-of-two block sizes for ux500v2 variant Ulf Hansson
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Ulf Hansson @ 2011-10-24 14:33 UTC (permalink / raw)
  To: linux-arm-kernel

For the ux500v2 variant of the PL18x block, non power of two block
sizes are now supported.

In addition constraints on buffer alignments is needed since access to the
PL18x FIFO must be done on a 4-byte aligned manner. Moreover to be able to
use DMA for buffers with not 32 bytes aligned sg element lengths, DMAREQCTL
must enabled.

Per Forlin (1):
  mmc: mmci: add constraints on alignment for SDIO

Stefan Nilsson XK (1):
  mmc: mmci: Support non-power-of-two block sizes for ux500v2 variant

 drivers/mmc/host/mmci.c |   56 +++++++++++++++++++++++++++++++++++++++++------
 drivers/mmc/host/mmci.h |    7 ++++++
 2 files changed, 56 insertions(+), 7 deletions(-)

-- 
1.7.5.4

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

* [PATCH 1/2] mmc: mmci: Support non-power-of-two block sizes for ux500v2 variant
  2011-10-24 14:33 [PATCH 0/2] mmc: mmci: Improvements for SDIO Ulf Hansson
@ 2011-10-24 14:33 ` Ulf Hansson
  2011-10-24 14:33 ` [PATCH 2/2] mmc: mmci: add constraints on alignment for SDIO Ulf Hansson
  2011-11-04 14:35 ` [PATCH 0/2] mmc: mmci: Improvements " Ulf Hansson
  2 siblings, 0 replies; 4+ messages in thread
From: Ulf Hansson @ 2011-10-24 14:33 UTC (permalink / raw)
  To: linux-arm-kernel

From: Stefan Nilsson XK <stefan.xk.nilsson@stericsson.com>

For the ux500v2 variant of the PL18x block, non power of two block
sizes are supported. This will make it possible to decrease data
overhead for SDIO transfers.

Signed-off-by: Stefan Nilsson XK <stefan.xk.nilsson@stericsson.com>
Signed-off-by: Ulf Hansson <ulf.hansson@stericsson.com>
---
 drivers/mmc/host/mmci.c |    9 +++++++--
 1 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 50b5f99..a6387b5 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -53,6 +53,7 @@ static unsigned int fmax = 515633;
  * @sdio: variant supports SDIO
  * @st_clkdiv: true if using a ST-specific clock divider algorithm
  * @blksz_datactrl16: true if Block size is at b16..b30 position in datactrl register
+ * @non_power_of_2_blksize: true if block sizes can be other than power of two
  */
 struct variant_data {
 	unsigned int		clkreg;
@@ -63,6 +64,7 @@ struct variant_data {
 	bool			sdio;
 	bool			st_clkdiv;
 	bool			blksz_datactrl16;
+	bool			non_power_of_2_blksize;
 };
 
 static struct variant_data variant_arm = {
@@ -104,6 +106,7 @@ static struct variant_data variant_ux500v2 = {
 	.sdio			= true,
 	.st_clkdiv		= true,
 	.blksz_datactrl16	= true,
+	.non_power_of_2_blksize	= true,
 };
 
 /*
@@ -594,7 +597,6 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
 	writel(host->size, base + MMCIDATALENGTH);
 
 	blksz_bits = ffs(data->blksz) - 1;
-	BUG_ON(1 << blksz_bits != data->blksz);
 
 	if (variant->blksz_datactrl16)
 		datactrl = MCI_DPSM_ENABLE | (data->blksz << 16);
@@ -974,11 +976,14 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
 static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
 	struct mmci_host *host = mmc_priv(mmc);
+	struct variant_data *variant = host->variant;
 	unsigned long flags;
 
 	WARN_ON(host->mrq != NULL);
 
-	if (mrq->data && !is_power_of_2(mrq->data->blksz)) {
+	if (mrq->data &&
+	    !variant->non_power_of_2_blksize &&
+	    !is_power_of_2(mrq->data->blksz)) {
 		dev_err(mmc_dev(mmc), "unsupported block size (%d bytes)\n",
 			mrq->data->blksz);
 		mrq->cmd->error = -EINVAL;
-- 
1.7.5.4

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

* [PATCH 2/2] mmc: mmci: add constraints on alignment for SDIO
  2011-10-24 14:33 [PATCH 0/2] mmc: mmci: Improvements for SDIO Ulf Hansson
  2011-10-24 14:33 ` [PATCH 1/2] mmc: mmci: Support non-power-of-two block sizes for ux500v2 variant Ulf Hansson
@ 2011-10-24 14:33 ` Ulf Hansson
  2011-11-04 14:35 ` [PATCH 0/2] mmc: mmci: Improvements " Ulf Hansson
  2 siblings, 0 replies; 4+ messages in thread
From: Ulf Hansson @ 2011-10-24 14:33 UTC (permalink / raw)
  To: linux-arm-kernel

From: Per Forlin <per.forlin@stericsson.com>

Buffers must be 4 bytes aligned due to restrictions that
the PL18x FIFO accesses must be done in a 4-byte aligned manner.
Enable DMA_REQCTL for SDIO to support write of not 32 bytes aligned
sg element lengths. In PIO mode any buffer length can be handled
as long as the buffer address is 4 byte aligned.

Signed-off-by: Ulf Hansson <ulf.hansson@stericsson.com>
Signed-off-by: Per Forlin <per.forlin@stericsson.com>
Signed-off-by: Stefan Nilsson XK <stefan.xk.nilsson@stericsson.com>
---
 drivers/mmc/host/mmci.c |   55 +++++++++++++++++++++++++++++++++++++++-------
 drivers/mmc/host/mmci.h |    7 ++++++
 2 files changed, 53 insertions(+), 9 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index a6387b5..1a46084 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -45,6 +45,7 @@ static unsigned int fmax = 515633;
  * struct variant_data - MMCI variant-specific quirks
  * @clkreg: default value for MCICLOCK register
  * @clkreg_enable: enable value for MMCICLOCK register
+ * @dma_sdio_req_ctrl: enable value for DMAREQCTL register for SDIO write
  * @datalength_bits: number of bits in the MMCIDATALENGTH register
  * @fifosize: number of bytes that can be written when MMCI_TXFIFOEMPTY
  *	      is asserted (likewise for RX)
@@ -58,6 +59,7 @@ static unsigned int fmax = 515633;
 struct variant_data {
 	unsigned int		clkreg;
 	unsigned int		clkreg_enable;
+	unsigned int		dma_sdio_req_ctrl;
 	unsigned int		datalength_bits;
 	unsigned int		fifosize;
 	unsigned int		fifohalfsize;
@@ -92,6 +94,7 @@ static struct variant_data variant_ux500 = {
 	.fifohalfsize		= 8 * 4,
 	.clkreg			= MCI_CLK_ENABLE,
 	.clkreg_enable		= MCI_ST_UX500_HWFCEN,
+	.dma_sdio_req_ctrl	= MCI_ST_DPSM_DMAREQCTL,
 	.datalength_bits	= 24,
 	.sdio			= true,
 	.st_clkdiv		= true,
@@ -102,6 +105,7 @@ static struct variant_data variant_ux500v2 = {
 	.fifohalfsize		= 8 * 4,
 	.clkreg			= MCI_CLK_ENABLE,
 	.clkreg_enable		= MCI_ST_UX500_HWFCEN,
+	.dma_sdio_req_ctrl	= MCI_ST_DPSM_DMAREQCTL,
 	.datalength_bits	= 24,
 	.sdio			= true,
 	.st_clkdiv		= true,
@@ -110,6 +114,31 @@ static struct variant_data variant_ux500v2 = {
 };
 
 /*
+ * Validate mmc prerequisites
+ */
+static int mmci_validate_data(struct mmci_host *host,
+			      struct mmc_data *data)
+{
+	if (!data)
+		return 0;
+
+	if (!host->variant->non_power_of_2_blksize &&
+	    !is_power_of_2(data->blksz)) {
+		dev_err(mmc_dev(host->mmc),
+			"unsupported block size (%d bytes)\n", data->blksz);
+		return -EINVAL;
+	}
+
+	if (data->sg->offset & 3) {
+		dev_err(mmc_dev(host->mmc),
+			"unsupported alginment (0x%x)\n", data->sg->offset);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
  * This must be called with host->lock held
  */
 static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired)
@@ -401,8 +430,12 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,
 	if (!chan)
 		return -EINVAL;
 
-	/* If less than or equal to the fifo size, don't bother with DMA */
-	if (data->blksz * data->blocks <= variant->fifosize)
+	/*
+	 * If less than or equal to the fifo size, don't bother with DMA
+	 * SDIO transfers may not be 4 bytes aligned, fall back to PIO
+	 */
+	if (data->blksz * data->blocks <= variant->fifosize ||
+	    (data->blksz * data->blocks) & 3)
 		return -EINVAL;
 
 	device = chan->device;
@@ -437,6 +470,7 @@ static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
 {
 	int ret;
 	struct mmc_data *data = host->data;
+	struct variant_data *variant = host->variant;
 
 	ret = mmci_dma_prep_data(host, host->data, NULL);
 	if (ret)
@@ -451,6 +485,11 @@ static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
 
 	datactrl |= MCI_DPSM_DMAENABLE;
 
+	/* Some hardware versions need special flags for SDIO DMA write */
+	if (variant->sdio && host->mmc->card && mmc_card_sdio(host->mmc->card)
+	    && (data->flags & MMC_DATA_WRITE))
+		datactrl |= variant->dma_sdio_req_ctrl;
+
 	/* Trigger the DMA transfer */
 	writel(datactrl, host->base + MMCIDATACTRL);
 
@@ -495,6 +534,9 @@ static void mmci_pre_request(struct mmc_host *mmc, struct mmc_request *mrq,
 	if (!data)
 		return;
 
+	if (mmci_validate_data(host, mrq->data))
+		return;
+
 	if (data->host_cookie) {
 		data->host_cookie = 0;
 		return;
@@ -976,17 +1018,12 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
 static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
 	struct mmci_host *host = mmc_priv(mmc);
-	struct variant_data *variant = host->variant;
 	unsigned long flags;
 
 	WARN_ON(host->mrq != NULL);
 
-	if (mrq->data &&
-	    !variant->non_power_of_2_blksize &&
-	    !is_power_of_2(mrq->data->blksz)) {
-		dev_err(mmc_dev(mmc), "unsupported block size (%d bytes)\n",
-			mrq->data->blksz);
-		mrq->cmd->error = -EINVAL;
+	mrq->cmd->error = mmci_validate_data(host, mrq->data);
+	if (mrq->cmd->error) {
 		mmc_request_done(mmc, mrq);
 		return;
 	}
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 79e4143..d2737f0 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -70,6 +70,13 @@
 #define MCI_ST_DPSM_RWMOD	(1 << 10)
 #define MCI_ST_DPSM_SDIOEN	(1 << 11)
 /* Control register extensions in the ST Micro Ux500 versions */
+/*
+ * DMA request control is required for write
+ * if transfer size is not 32 byte aligned.
+ * DMA request control is also needed if the total
+ * transfer size is 32 byte aligned but any of the
+ * sg element lengths are not aligned with 32 byte.
+ */
 #define MCI_ST_DPSM_DMAREQCTL	(1 << 12)
 #define MCI_ST_DPSM_DBOOTMODEEN	(1 << 13)
 #define MCI_ST_DPSM_BUSYMODE	(1 << 14)
-- 
1.7.5.4

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

* [PATCH 0/2] mmc: mmci: Improvements for SDIO
  2011-10-24 14:33 [PATCH 0/2] mmc: mmci: Improvements for SDIO Ulf Hansson
  2011-10-24 14:33 ` [PATCH 1/2] mmc: mmci: Support non-power-of-two block sizes for ux500v2 variant Ulf Hansson
  2011-10-24 14:33 ` [PATCH 2/2] mmc: mmci: add constraints on alignment for SDIO Ulf Hansson
@ 2011-11-04 14:35 ` Ulf Hansson
  2 siblings, 0 replies; 4+ messages in thread
From: Ulf Hansson @ 2011-11-04 14:35 UTC (permalink / raw)
  To: linux-arm-kernel

Is this patchserie considered OK?

-Russell, patches are available in your patchtracker.

Br
Ulf Hansson

Ulf HANSSON wrote:
> For the ux500v2 variant of the PL18x block, non power of two block
> sizes are now supported.
> 
> In addition constraints on buffer alignments is needed since access to the
> PL18x FIFO must be done on a 4-byte aligned manner. Moreover to be able to
> use DMA for buffers with not 32 bytes aligned sg element lengths, DMAREQCTL
> must enabled.
> 
> Per Forlin (1):
>   mmc: mmci: add constraints on alignment for SDIO
> 
> Stefan Nilsson XK (1):
>   mmc: mmci: Support non-power-of-two block sizes for ux500v2 variant
> 
>  drivers/mmc/host/mmci.c |   56 +++++++++++++++++++++++++++++++++++++++++------
>  drivers/mmc/host/mmci.h |    7 ++++++
>  2 files changed, 56 insertions(+), 7 deletions(-)
> 

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

end of thread, other threads:[~2011-11-04 14:35 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-10-24 14:33 [PATCH 0/2] mmc: mmci: Improvements for SDIO Ulf Hansson
2011-10-24 14:33 ` [PATCH 1/2] mmc: mmci: Support non-power-of-two block sizes for ux500v2 variant Ulf Hansson
2011-10-24 14:33 ` [PATCH 2/2] mmc: mmci: add constraints on alignment for SDIO Ulf Hansson
2011-11-04 14:35 ` [PATCH 0/2] mmc: mmci: Improvements " Ulf Hansson

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