mbox series

[V4,0/7] mmc: add support for sdhci 4.0

Message ID 1532340508-8749-1-git-send-email-zhang.chunyan@linaro.org
Headers show
Series mmc: add support for sdhci 4.0 | expand

Message

Chunyan Zhang July 23, 2018, 10:08 a.m. UTC
From the SD host controller version 4.0 on, SDHCI implementation either
is version 3 compatible or version 4 mode. This patch-set covers those
changes which are common for SDHCI 4.0 version, regardless of whether
they are used with SD or eMMC storage devices.

This patchset also added a new sdhci driver for Spreadtrum's controller
which supports v4.0 mode.

This patchset has been tested on Spreadtrum's mobile phone, emmc can be
initialized, mounted, read and written, with these changes for common
sdhci framework and sdhci-sprd driver.

Changes from V3:
* Addressed comments from Adrian:
- set "Host Control 2" when enabled v4 mode, and do the same for reset-for-all in sdhci_do_reset();
- Moved "v4_mode" above to the private;
- Change the subject of patch 2/7;
- Use %pad to pirnt dma_addr_t;
- Adjusted to not clear SDHCI_USE_SDMA for v4 mode in sdhci_setup_host();
- Changed the function name to sdhci_can_64bit_dma() instead of sdhci_use_64bit_dma;
- Adjusted to write SDHCI_CTRL_64BIT_ADDR when we decide to use 64-bit DMA in V4 mode,
  rather than check the register to decide if use 64-bit DMA;
- Added a comments for using dma_zalloc_coherent() to replace dma_alloc_coherent();
- Added SDHCI_SPEC_420;
- Set 16-bit block count register to zero conditionally when using 32-bit block count;
- Adjusted to Use 32-bit block count register only for v4.10 v4 mode;
- Added the rules used for AUTO CMD23/12 to AUTO CMD as well;
- Moved the selection of Host Control 2 register CMD23 Enable to sdhci_init() from Spreadtrum's driver;
- Used usleep_range() to replace udelay();
- Added the checks for clk_prepare_enable().
* Added comments for Spreadtrum's specific changes to the register SDHCI_SOFTWARE_RESET;

Changes from V2:
* Addressed comments from Adrian:
- Added sdhci_enable_v4_mode() for enabling v4 mode instead of determining by reading from registers;
- Added support for 64-bit SDMA address in v4 mode;
- Dropped the changes of ADMA2 data aglinment;
- Added support for "Auto Cmd Auto Select".
* Rebased on v4.18-rc2.
* Dealt with a few issues in sdhci-sprd:
- Save return value of mmc_of_parse();
- Add checking for clk_prepare_enable();
- Use BIT() macro instead.

Changes from v1:
* Addressed comments from Ulf:
 - Add dt-bindings for Spreadtrum sdhci;
 - Use assigned-clocks* DT bindings to set default source of sdio clock;
 - Removed unuseful print;
 - Removed two functions which are not used;
 - Add back the missing pm_runtime_put_autosuspend() after adding sdhci host.

* Changed Spreadtrum sdhci driver name to sdhci-sprd.

Chunyan Zhang (7):
  mmc: sdhci: add sd host v4 mode
  mmc: sdhci: Change SDMA address register for v4 mode
  mmc: sdhci: add ADMA2 64-bit addressing support for V4 mode
  mmc: sdhci: add 32-bit block count support for v4 mode
  mmc: sdhci: add Auto CMD Auto Select support
  mmc: sdhci-sprd: added Spreadtrum's initial host controller
  dt-bindings: sdhci-sprd: Add bindings for the sdhci-sprd controller

 .../devicetree/bindings/mmc/sdhci-sprd.txt         |  41 ++
 drivers/mmc/host/Kconfig                           |  13 +
 drivers/mmc/host/Makefile                          |   1 +
 drivers/mmc/host/sdhci-sprd.c                      | 455 +++++++++++++++++++++
 drivers/mmc/host/sdhci.c                           | 223 +++++++---
 drivers/mmc/host/sdhci.h                           |  23 +-
 6 files changed, 708 insertions(+), 48 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mmc/sdhci-sprd.txt
 create mode 100644 drivers/mmc/host/sdhci-sprd.c

-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Adrian Hunter July 30, 2018, 1:05 p.m. UTC | #1
On 23/07/18 13:08, Chunyan Zhang wrote:
> ADMA2 64-bit addressing support is divided into V3 mode and V4 mode.

> So there are two kinds of descriptors for ADMA2 64-bit addressing

> i.e. 96-bit Descriptor for V3 mode, and 128-bit Descriptor for V4

> mode. 128-bit Descriptor is aligned to 8-byte.

> 

> For V4 mode, ADMA2 64-bit addressing is enabled via Host Control 2

> register.

> 

> Signed-off-by: Chunyan Zhang <zhang.chunyan@linaro.org>

> ---

>  drivers/mmc/host/sdhci.c | 90 ++++++++++++++++++++++++++++++++++--------------

>  drivers/mmc/host/sdhci.h | 15 ++++++--

>  2 files changed, 78 insertions(+), 27 deletions(-)

> 

> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c

> index 9cb17c0..ce71afa 100644

> --- a/drivers/mmc/host/sdhci.c

> +++ b/drivers/mmc/host/sdhci.c

> @@ -271,6 +271,46 @@ static void sdhci_set_default_irqs(struct sdhci_host *host)

>  	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);

>  }

>  

> +static void sdhci_config_dma(struct sdhci_host *host)

> +{

> +	u8 ctrl;

> +	u16 ctrl2;

> +

> +	if (host->version < SDHCI_SPEC_200)

> +		return;

> +

> +	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);

> +

> +	/*

> +	 * Always adjust the DMA selection as some controllers

> +	 * (e.g. JMicron) can't do PIO properly when the selection

> +	 * is ADMA.

> +	 */

> +	ctrl &= ~SDHCI_CTRL_DMA_MASK;

> +	if ((host->flags & SDHCI_REQ_USE_DMA) &&


	if (!(host->flags & SDHCI_REQ_USE_DMA))
		goto out;

> +	    (host->flags & SDHCI_USE_ADMA))

> +		ctrl |= SDHCI_CTRL_ADMA32;


	/* Note if DMA Select is zero then SDMA is selected */
	if (host->flags & SDHCI_USE_ADMA)
		ctrl |= SDHCI_CTRL_ADMA32;

> +

> +	if (host->flags & SDHCI_USE_64_BIT_DMA) {

> +		/*

> +		 * If v4 mode, all supported DMA can be 64-bit addressing if

> +		 * controller supports 64-bit system address, otherwise only

> +		 * ADMA can support 64-bit addressing.

> +		 */

> +		if (host->v4_mode) {

> +			ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);

> +			ctrl2 |= SDHCI_CTRL_64BIT_ADDR;

> +			sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);

> +		} else {

> +			if ((host->flags & SDHCI_REQ_USE_DMA) &&


The 'else' and 'if' should be together i.e.

		} else if (host->flags & SDHCI_USE_ADMA) {
			/*
			 * Don't need to undo SDHCI_CTRL_ADMA32 in order to set
			 * SDHCI_CTRL_ADMA64.
			 */
			ctrl |= SDHCI_CTRL_ADMA64;
		}

> +			    (host->flags & SDHCI_USE_ADMA))

> +				ctrl |= SDHCI_CTRL_ADMA64;

> +		}

> +	}

> +


out:

> +	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);

> +}

> +

>  static void sdhci_init(struct sdhci_host *host, int soft)

>  {

>  	struct mmc_host *mmc = host->mmc;

> @@ -916,7 +956,6 @@ static void sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)

>  

>  static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)

>  {

> -	u8 ctrl;

>  	struct mmc_data *data = cmd->data;

>  

>  	host->data_timeout = 0;

> @@ -1012,25 +1051,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)

>  		}

>  	}

>  

> -	/*

> -	 * Always adjust the DMA selection as some controllers

> -	 * (e.g. JMicron) can't do PIO properly when the selection

> -	 * is ADMA.

> -	 */

> -	if (host->version >= SDHCI_SPEC_200) {

> -		ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);

> -		ctrl &= ~SDHCI_CTRL_DMA_MASK;

> -		if ((host->flags & SDHCI_REQ_USE_DMA) &&

> -			(host->flags & SDHCI_USE_ADMA)) {

> -			if (host->flags & SDHCI_USE_64_BIT_DMA)

> -				ctrl |= SDHCI_CTRL_ADMA64;

> -			else

> -				ctrl |= SDHCI_CTRL_ADMA32;

> -		} else {

> -			ctrl |= SDHCI_CTRL_SDMA;

> -		}

> -		sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);

> -	}

> +	sdhci_config_dma(host);

>  

>  	if (!(host->flags & SDHCI_REQ_USE_DMA)) {

>  		int flags;

> @@ -3503,6 +3524,19 @@ static int sdhci_allocate_bounce_buffer(struct sdhci_host *host)

>  	return 0;

>  }

>  

> +static inline bool sdhci_can_64bit_dma(struct sdhci_host *host)

> +{

> +	/*

> +	 * According to SD Host Controller spec v4.10, bit[27] added from

> +	 * version 4.10 in Capabilities Register is used as 64-bit System

> +	 * Address support for V4 mode.

> +	 */

> +	if (host->version >= SDHCI_SPEC_410 && host->v4_mode)

> +		return host->caps & SDHCI_CAN_64BIT_V4;

> +

> +	return host->caps & SDHCI_CAN_64BIT;

> +}

> +

>  int sdhci_setup_host(struct sdhci_host *host)

>  {

>  	struct mmc_host *mmc;

> @@ -3539,7 +3573,7 @@ int sdhci_setup_host(struct sdhci_host *host)

>  

>  	override_timeout_clk = host->timeout_clk;

>  

> -	if (host->version > SDHCI_SPEC_300) {

> +	if (host->version > SDHCI_SPEC_420) {


Please make this and the addition of the SDHCI_SPEC_4xx defines
a separate patch.

>  		pr_err("%s: Unknown controller version (%d). You may experience problems.\n",

>  		       mmc_hostname(mmc), host->version);

>  	}

> @@ -3574,7 +3608,7 @@ int sdhci_setup_host(struct sdhci_host *host)

>  	 * SDHCI_QUIRK2_BROKEN_64_BIT_DMA must be left to the drivers to

>  	 * implement.

>  	 */

> -	if (host->caps & SDHCI_CAN_64BIT)

> +	if (sdhci_can_64bit_dma(host))

>  		host->flags |= SDHCI_USE_64_BIT_DMA;

>  

>  	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {

> @@ -3608,8 +3642,8 @@ int sdhci_setup_host(struct sdhci_host *host)

>  		 */

>  		if (host->flags & SDHCI_USE_64_BIT_DMA) {

>  			host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) *

> -					      SDHCI_ADMA2_64_DESC_SZ;

> -			host->desc_sz = SDHCI_ADMA2_64_DESC_SZ;

> +					      SDHCI_ADMA2_64_DESC_SZ(host);

> +			host->desc_sz = SDHCI_ADMA2_64_DESC_SZ(host);

>  		} else {

>  			host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) *

>  					      SDHCI_ADMA2_32_DESC_SZ;

> @@ -3617,7 +3651,13 @@ int sdhci_setup_host(struct sdhci_host *host)

>  		}

>  

>  		host->align_buffer_sz = SDHCI_MAX_SEGS * SDHCI_ADMA2_ALIGN;

> -		buf = dma_alloc_coherent(mmc_dev(mmc), host->align_buffer_sz +

> +		/*

> +		 * Host Controller Version 4.00 or later can support 128-bit

> +		 * and 96-bit Descriptor for 64-bit addressing mode. 128-bit

> +		 * Descriptor is for v4 mode, and high 32-bit of it is reserved

> +		 * according to the specification v4.10.

> +		 */


But the point is zalloc() lets us skip writing the reserved bits.
How about:

		/*
		 * Use zalloc to zero the reserved high 32-bits of 128-bit
		 * descriptors so that they never need to be written.
		 */

> +		buf = dma_zalloc_coherent(mmc_dev(mmc), host->align_buffer_sz +

>  					 host->adma_table_sz, &dma, GFP_KERNEL);

>  		if (!buf) {

>  			pr_warn("%s: Unable to allocate ADMA buffers - falling back to standard DMA\n",

> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h

> index 519d939..23318ff 100644

> --- a/drivers/mmc/host/sdhci.h

> +++ b/drivers/mmc/host/sdhci.h

> @@ -185,6 +185,7 @@

>  #define  SDHCI_CTRL_EXEC_TUNING		0x0040

>  #define  SDHCI_CTRL_TUNED_CLK		0x0080

>  #define  SDHCI_CTRL_V4_MODE		0x1000

> +#define  SDHCI_CTRL_64BIT_ADDR		0x2000

>  #define  SDHCI_CTRL_PRESET_VAL_ENABLE	0x8000

>  

>  #define SDHCI_CAPABILITIES	0x40

> @@ -205,6 +206,7 @@

>  #define  SDHCI_CAN_VDD_330	0x01000000

>  #define  SDHCI_CAN_VDD_300	0x02000000

>  #define  SDHCI_CAN_VDD_180	0x04000000

> +#define  SDHCI_CAN_64BIT_V4	0x08000000

>  #define  SDHCI_CAN_64BIT	0x10000000

>  

>  #define  SDHCI_SUPPORT_SDR50	0x00000001

> @@ -271,6 +273,9 @@

>  #define   SDHCI_SPEC_100	0

>  #define   SDHCI_SPEC_200	1

>  #define   SDHCI_SPEC_300	2

> +#define   SDHCI_SPEC_400	3

> +#define   SDHCI_SPEC_410	4

> +#define   SDHCI_SPEC_420	5

>  

>  /*

>   * End of controller registers.

> @@ -306,8 +311,14 @@ struct sdhci_adma2_32_desc {

>   */

>  #define SDHCI_ADMA2_DESC_ALIGN	8

>  

> -/* ADMA2 64-bit DMA descriptor size */

> -#define SDHCI_ADMA2_64_DESC_SZ	12

> +/*

> + * ADMA2 64-bit DMA descriptor size

> + * According to SD Host Controller spec v4.10, there are two kinds of

> + * descriptors for 64-bit addressing mode: 96-bit Descriptor and 128-bit

> + * Descriptor, if Host Version 4 Enable is set in the Host Control 2

> + * register, 128-bit Descriptor will be selected.

> + */

> +#define SDHCI_ADMA2_64_DESC_SZ(host)	((host)->v4_mode ? 16 : 12)

>  

>  /*

>   * ADMA2 64-bit descriptor. Note 12-byte descriptor can't always be 8-byte

> 


--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Chunyan Zhang July 31, 2018, 7:04 a.m. UTC | #2
Hi Adrian,

On 30 July 2018 at 21:06, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 23/07/18 13:08, Chunyan Zhang wrote:

>> As SD Host Controller Specification v4.10 documents:

>> Host Controller Version 4.10 defines this "Auto CMD Auto Select" mode.

>> Selection of Auto CMD depends on setting of CMD23 Enable in the Host

>> Control 2 register which indicates whether card supports CMD23. If CMD23

>> Enable =1, Auto CMD23 is used and if CMD23 Enable =0, Auto CMD12 is

>> used. In case of Version 4.10 or later, use of Auto CMD Auto Select is

>> recommended rather than use of Auto CMD12 Enable or Auto CMD23

>> Enable.

>>

>> This patch add this new mode support.

>>

>> Signed-off-by: Chunyan Zhang <zhang.chunyan@linaro.org>

>> ---

>>  drivers/mmc/host/sdhci.c | 61 +++++++++++++++++++++++++++++++++++++++---------

>>  drivers/mmc/host/sdhci.h |  2 ++

>>  2 files changed, 52 insertions(+), 11 deletions(-)

>>

>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c

>> index 5acea3d..5c60590 100644

>> --- a/drivers/mmc/host/sdhci.c

>> +++ b/drivers/mmc/host/sdhci.c

>> @@ -311,6 +311,23 @@ static void sdhci_config_dma(struct sdhci_host *host)

>>       sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);

>>  }

>>

>> +static void sdhci_enable_cmd23(struct sdhci_host *host)

>> +{

>> +     u16 ctrl2;

>> +

>> +     /*

>> +      * This is used along with "Auto CMD Auto Select" feature,

>> +      * which is introduced from v4.10, if card supports CMD23,

>> +      * Auto CMD23 should be used instead of Auto CMD12.

>> +      */

>> +     if (host->version >= SDHCI_SPEC_410 &&

>> +         (host->mmc->caps & MMC_CAP_CMD23)) {

>

> That is the host capability.  It needs to be the card capability.


Could you please elaborate the issue?

I thought we're setting for host here.  Do you mean we need to see the
card capability?

>

>> +             ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);

>> +             ctrl2 |= SDHCI_CMD23_ENABLE;

>> +             sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);

>> +     }

>> +}

>> +

>>  static void sdhci_init(struct sdhci_host *host, int soft)

>>  {

>>       struct mmc_host *mmc = host->mmc;

>> @@ -329,6 +346,8 @@ static void sdhci_init(struct sdhci_host *host, int soft)

>>               host->clock = 0;

>>               mmc->ops->set_ios(mmc, &mmc->ios);

>>       }

>> +

>> +     sdhci_enable_cmd23(host);

>>  }

>>

>>  static void sdhci_reinit(struct sdhci_host *host)

>> @@ -1093,6 +1112,36 @@ static inline bool sdhci_auto_cmd12(struct sdhci_host *host,

>>              !mrq->cap_cmd_during_tfr;

>>  }

>>

>> +static inline void sdhci_auto_cmd_select(struct sdhci_host *host,

>> +                                      struct mmc_command *cmd,

>> +                                      u16 *mode)

>> +{

>> +     bool use_cmd12 = sdhci_auto_cmd12(host, cmd->mrq) &&

>> +                      (cmd->opcode != SD_IO_RW_EXTENDED);

>> +     bool use_cmd23 = cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23);

>> +

>> +     /*

>> +      * In case of Version 4.10 or later, use of 'Auto CMD Auto

>> +      * Select' is recommended rather than use of 'Auto CMD12

>> +      * Enable' or 'Auto CMD23 Enable'.

>> +      */

>> +     if (host->version >= SDHCI_SPEC_410 && (use_cmd12 || use_cmd23)) {

>> +             *mode |= SDHCI_TRNS_AUTO_SEL;

>

> As noted in patch 4, the CMD23 argument is not just the block count for eMMC.


Probably I haven't got your point...

From what I understand, auto_sel mode doesn't need argument2. Doesn't
this work for eMMC?

The test platform I used was just eMMC only, haven't found problem.

Thanks,
Chunyan

>

>> +             return;

>> +     }

>> +

>> +     /*

>> +      * If we are sending CMD23, CMD12 never gets sent

>> +      * on successful completion (so no Auto-CMD12).

>> +      */

>> +     if (use_cmd12) {

>> +             *mode |= SDHCI_TRNS_AUTO_CMD12;

>> +     } else if (use_cmd23) {

>> +             *mode |= SDHCI_TRNS_AUTO_CMD23;

>> +             sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2);

>> +     }

>> +}

>> +

>>  static void sdhci_set_transfer_mode(struct sdhci_host *host,

>>       struct mmc_command *cmd)

>>  {

>> @@ -1119,17 +1168,7 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,

>>

>>       if (mmc_op_multi(cmd->opcode) || data->blocks > 1) {

>>               mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI;

>> -             /*

>> -              * If we are sending CMD23, CMD12 never gets sent

>> -              * on successful completion (so no Auto-CMD12).

>> -              */

>> -             if (sdhci_auto_cmd12(host, cmd->mrq) &&

>> -                 (cmd->opcode != SD_IO_RW_EXTENDED))

>> -                     mode |= SDHCI_TRNS_AUTO_CMD12;

>> -             else if (cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) {

>> -                     mode |= SDHCI_TRNS_AUTO_CMD23;

>> -                     sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2);

>> -             }

>> +             sdhci_auto_cmd_select(host, cmd, &mode);

>>       }

>>

>>       if (data->flags & MMC_DATA_READ)

>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h

>> index 81aae07..a8f4ec2 100644

>> --- a/drivers/mmc/host/sdhci.h

>> +++ b/drivers/mmc/host/sdhci.h

>> @@ -42,6 +42,7 @@

>>  #define  SDHCI_TRNS_BLK_CNT_EN       0x02

>>  #define  SDHCI_TRNS_AUTO_CMD12       0x04

>>  #define  SDHCI_TRNS_AUTO_CMD23       0x08

>> +#define  SDHCI_TRNS_AUTO_SEL 0x0C

>>  #define  SDHCI_TRNS_READ     0x10

>>  #define  SDHCI_TRNS_MULTI    0x20

>>

>> @@ -185,6 +186,7 @@

>>  #define   SDHCI_CTRL_DRV_TYPE_D              0x0030

>>  #define  SDHCI_CTRL_EXEC_TUNING              0x0040

>>  #define  SDHCI_CTRL_TUNED_CLK                0x0080

>> +#define  SDHCI_CMD23_ENABLE          0x0800

>>  #define  SDHCI_CTRL_V4_MODE          0x1000

>>  #define  SDHCI_CTRL_64BIT_ADDR               0x2000

>>  #define  SDHCI_CTRL_PRESET_VAL_ENABLE        0x8000

>>

>

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Adrian Hunter July 31, 2018, 8:05 a.m. UTC | #3
On 31/07/18 10:04, Chunyan Zhang wrote:
> Hi Adrian,

> 

> On 30 July 2018 at 21:06, Adrian Hunter <adrian.hunter@intel.com> wrote:

>> On 23/07/18 13:08, Chunyan Zhang wrote:

>>> As SD Host Controller Specification v4.10 documents:

>>> Host Controller Version 4.10 defines this "Auto CMD Auto Select" mode.

>>> Selection of Auto CMD depends on setting of CMD23 Enable in the Host

>>> Control 2 register which indicates whether card supports CMD23. If CMD23

>>> Enable =1, Auto CMD23 is used and if CMD23 Enable =0, Auto CMD12 is

>>> used. In case of Version 4.10 or later, use of Auto CMD Auto Select is

>>> recommended rather than use of Auto CMD12 Enable or Auto CMD23

>>> Enable.

>>>

>>> This patch add this new mode support.

>>>

>>> Signed-off-by: Chunyan Zhang <zhang.chunyan@linaro.org>

>>> ---

>>>  drivers/mmc/host/sdhci.c | 61 +++++++++++++++++++++++++++++++++++++++---------

>>>  drivers/mmc/host/sdhci.h |  2 ++

>>>  2 files changed, 52 insertions(+), 11 deletions(-)

>>>

>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c

>>> index 5acea3d..5c60590 100644

>>> --- a/drivers/mmc/host/sdhci.c

>>> +++ b/drivers/mmc/host/sdhci.c

>>> @@ -311,6 +311,23 @@ static void sdhci_config_dma(struct sdhci_host *host)

>>>       sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);

>>>  }

>>>

>>> +static void sdhci_enable_cmd23(struct sdhci_host *host)

>>> +{

>>> +     u16 ctrl2;

>>> +

>>> +     /*

>>> +      * This is used along with "Auto CMD Auto Select" feature,

>>> +      * which is introduced from v4.10, if card supports CMD23,

>>> +      * Auto CMD23 should be used instead of Auto CMD12.

>>> +      */

>>> +     if (host->version >= SDHCI_SPEC_410 &&

>>> +         (host->mmc->caps & MMC_CAP_CMD23)) {

>>

>> That is the host capability.  It needs to be the card capability.

> 

> Could you please elaborate the issue?

> 

> I thought we're setting for host here.  Do you mean we need to see the

> card capability?


Yes. SDHCI_TRNS_AUTO_SEL selects auto-CMD23 or auto-CMD12 based on this
setting, so this must reflect the card's capability.

> 

>>

>>> +             ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);

>>> +             ctrl2 |= SDHCI_CMD23_ENABLE;

>>> +             sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);

>>> +     }

>>> +}

>>> +

>>>  static void sdhci_init(struct sdhci_host *host, int soft)

>>>  {

>>>       struct mmc_host *mmc = host->mmc;

>>> @@ -329,6 +346,8 @@ static void sdhci_init(struct sdhci_host *host, int soft)

>>>               host->clock = 0;

>>>               mmc->ops->set_ios(mmc, &mmc->ios);

>>>       }

>>> +

>>> +     sdhci_enable_cmd23(host);

>>>  }

>>>

>>>  static void sdhci_reinit(struct sdhci_host *host)

>>> @@ -1093,6 +1112,36 @@ static inline bool sdhci_auto_cmd12(struct sdhci_host *host,

>>>              !mrq->cap_cmd_during_tfr;

>>>  }

>>>

>>> +static inline void sdhci_auto_cmd_select(struct sdhci_host *host,

>>> +                                      struct mmc_command *cmd,

>>> +                                      u16 *mode)

>>> +{

>>> +     bool use_cmd12 = sdhci_auto_cmd12(host, cmd->mrq) &&

>>> +                      (cmd->opcode != SD_IO_RW_EXTENDED);

>>> +     bool use_cmd23 = cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23);

>>> +

>>> +     /*

>>> +      * In case of Version 4.10 or later, use of 'Auto CMD Auto

>>> +      * Select' is recommended rather than use of 'Auto CMD12

>>> +      * Enable' or 'Auto CMD23 Enable'.

>>> +      */

>>> +     if (host->version >= SDHCI_SPEC_410 && (use_cmd12 || use_cmd23)) {

>>> +             *mode |= SDHCI_TRNS_AUTO_SEL;

>>

>> As noted in patch 4, the CMD23 argument is not just the block count for eMMC.

> 

> Probably I haven't got your point...

> 

>>From what I understand, auto_sel mode doesn't need argument2. Doesn't

> this work for eMMC?


CMD23 always needs an argument

> 

> The test platform I used was just eMMC only, haven't found problem.


Because the bits that are missing from the CMD23 argument (reliable write,
context id, etc) will not make the command fail.

> 

> Thanks,

> Chunyan

> 

>>

>>> +             return;

>>> +     }

>>> +

>>> +     /*

>>> +      * If we are sending CMD23, CMD12 never gets sent

>>> +      * on successful completion (so no Auto-CMD12).

>>> +      */

>>> +     if (use_cmd12) {

>>> +             *mode |= SDHCI_TRNS_AUTO_CMD12;

>>> +     } else if (use_cmd23) {

>>> +             *mode |= SDHCI_TRNS_AUTO_CMD23;

>>> +             sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2);

>>> +     }

>>> +}

>>> +

>>>  static void sdhci_set_transfer_mode(struct sdhci_host *host,

>>>       struct mmc_command *cmd)

>>>  {

>>> @@ -1119,17 +1168,7 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,

>>>

>>>       if (mmc_op_multi(cmd->opcode) || data->blocks > 1) {

>>>               mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI;

>>> -             /*

>>> -              * If we are sending CMD23, CMD12 never gets sent

>>> -              * on successful completion (so no Auto-CMD12).

>>> -              */

>>> -             if (sdhci_auto_cmd12(host, cmd->mrq) &&

>>> -                 (cmd->opcode != SD_IO_RW_EXTENDED))

>>> -                     mode |= SDHCI_TRNS_AUTO_CMD12;

>>> -             else if (cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) {

>>> -                     mode |= SDHCI_TRNS_AUTO_CMD23;

>>> -                     sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2);

>>> -             }

>>> +             sdhci_auto_cmd_select(host, cmd, &mode);

>>>       }

>>>

>>>       if (data->flags & MMC_DATA_READ)

>>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h

>>> index 81aae07..a8f4ec2 100644

>>> --- a/drivers/mmc/host/sdhci.h

>>> +++ b/drivers/mmc/host/sdhci.h

>>> @@ -42,6 +42,7 @@

>>>  #define  SDHCI_TRNS_BLK_CNT_EN       0x02

>>>  #define  SDHCI_TRNS_AUTO_CMD12       0x04

>>>  #define  SDHCI_TRNS_AUTO_CMD23       0x08

>>> +#define  SDHCI_TRNS_AUTO_SEL 0x0C

>>>  #define  SDHCI_TRNS_READ     0x10

>>>  #define  SDHCI_TRNS_MULTI    0x20

>>>

>>> @@ -185,6 +186,7 @@

>>>  #define   SDHCI_CTRL_DRV_TYPE_D              0x0030

>>>  #define  SDHCI_CTRL_EXEC_TUNING              0x0040

>>>  #define  SDHCI_CTRL_TUNED_CLK                0x0080

>>> +#define  SDHCI_CMD23_ENABLE          0x0800

>>>  #define  SDHCI_CTRL_V4_MODE          0x1000

>>>  #define  SDHCI_CTRL_64BIT_ADDR               0x2000

>>>  #define  SDHCI_CTRL_PRESET_VAL_ENABLE        0x8000

>>>

>>

> 


--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Chunyan Zhang July 31, 2018, 8:36 a.m. UTC | #4
On 31 July 2018 at 16:05, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 31/07/18 10:04, Chunyan Zhang wrote:

>> Hi Adrian,

>>

>> On 30 July 2018 at 21:06, Adrian Hunter <adrian.hunter@intel.com> wrote:

>>> On 23/07/18 13:08, Chunyan Zhang wrote:

>>>> As SD Host Controller Specification v4.10 documents:

>>>> Host Controller Version 4.10 defines this "Auto CMD Auto Select" mode.

>>>> Selection of Auto CMD depends on setting of CMD23 Enable in the Host

>>>> Control 2 register which indicates whether card supports CMD23. If CMD23

>>>> Enable =1, Auto CMD23 is used and if CMD23 Enable =0, Auto CMD12 is

>>>> used. In case of Version 4.10 or later, use of Auto CMD Auto Select is

>>>> recommended rather than use of Auto CMD12 Enable or Auto CMD23

>>>> Enable.

>>>>

>>>> This patch add this new mode support.

>>>>

>>>> Signed-off-by: Chunyan Zhang <zhang.chunyan@linaro.org>

>>>> ---

>>>>  drivers/mmc/host/sdhci.c | 61 +++++++++++++++++++++++++++++++++++++++---------

>>>>  drivers/mmc/host/sdhci.h |  2 ++

>>>>  2 files changed, 52 insertions(+), 11 deletions(-)

>>>>

>>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c

>>>> index 5acea3d..5c60590 100644

>>>> --- a/drivers/mmc/host/sdhci.c

>>>> +++ b/drivers/mmc/host/sdhci.c

>>>> @@ -311,6 +311,23 @@ static void sdhci_config_dma(struct sdhci_host *host)

>>>>       sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);

>>>>  }

>>>>

>>>> +static void sdhci_enable_cmd23(struct sdhci_host *host)

>>>> +{

>>>> +     u16 ctrl2;

>>>> +

>>>> +     /*

>>>> +      * This is used along with "Auto CMD Auto Select" feature,

>>>> +      * which is introduced from v4.10, if card supports CMD23,

>>>> +      * Auto CMD23 should be used instead of Auto CMD12.

>>>> +      */

>>>> +     if (host->version >= SDHCI_SPEC_410 &&

>>>> +         (host->mmc->caps & MMC_CAP_CMD23)) {

>>>

>>> That is the host capability.  It needs to be the card capability.

>>

>> Could you please elaborate the issue?

>>

>> I thought we're setting for host here.  Do you mean we need to see the

>> card capability?

>

> Yes. SDHCI_TRNS_AUTO_SEL selects auto-CMD23 or auto-CMD12 based on this

> setting, so this must reflect the card's capability.


Got it, but how to know if the card supports CMD23?

>

>>

>>>

>>>> +             ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);

>>>> +             ctrl2 |= SDHCI_CMD23_ENABLE;

>>>> +             sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);

>>>> +     }

>>>> +}

>>>> +

>>>>  static void sdhci_init(struct sdhci_host *host, int soft)

>>>>  {

>>>>       struct mmc_host *mmc = host->mmc;

>>>> @@ -329,6 +346,8 @@ static void sdhci_init(struct sdhci_host *host, int soft)

>>>>               host->clock = 0;

>>>>               mmc->ops->set_ios(mmc, &mmc->ios);

>>>>       }

>>>> +

>>>> +     sdhci_enable_cmd23(host);

>>>>  }

>>>>

>>>>  static void sdhci_reinit(struct sdhci_host *host)

>>>> @@ -1093,6 +1112,36 @@ static inline bool sdhci_auto_cmd12(struct sdhci_host *host,

>>>>              !mrq->cap_cmd_during_tfr;

>>>>  }

>>>>

>>>> +static inline void sdhci_auto_cmd_select(struct sdhci_host *host,

>>>> +                                      struct mmc_command *cmd,

>>>> +                                      u16 *mode)

>>>> +{

>>>> +     bool use_cmd12 = sdhci_auto_cmd12(host, cmd->mrq) &&

>>>> +                      (cmd->opcode != SD_IO_RW_EXTENDED);

>>>> +     bool use_cmd23 = cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23);

>>>> +

>>>> +     /*

>>>> +      * In case of Version 4.10 or later, use of 'Auto CMD Auto

>>>> +      * Select' is recommended rather than use of 'Auto CMD12

>>>> +      * Enable' or 'Auto CMD23 Enable'.

>>>> +      */

>>>> +     if (host->version >= SDHCI_SPEC_410 && (use_cmd12 || use_cmd23)) {

>>>> +             *mode |= SDHCI_TRNS_AUTO_SEL;

>>>

>>> As noted in patch 4, the CMD23 argument is not just the block count for eMMC.

>>

>> Probably I haven't got your point...

>>

>>>From what I understand, auto_sel mode doesn't need argument2. Doesn't

>> this work for eMMC?

>

> CMD23 always needs an argument


But setting argument for CMD23 will cover the block count value we set
before, that will lead mounting emmc to fail.

>

>>

>> The test platform I used was just eMMC only, haven't found problem.

>

> Because the bits that are missing from the CMD23 argument (reliable write,

> context id, etc) will not make the command fail.

>

>>

>> Thanks,

>> Chunyan

>>

>>>

>>>> +             return;

>>>> +     }

>>>> +

>>>> +     /*

>>>> +      * If we are sending CMD23, CMD12 never gets sent

>>>> +      * on successful completion (so no Auto-CMD12).

>>>> +      */

>>>> +     if (use_cmd12) {

>>>> +             *mode |= SDHCI_TRNS_AUTO_CMD12;

>>>> +     } else if (use_cmd23) {

>>>> +             *mode |= SDHCI_TRNS_AUTO_CMD23;

>>>> +             sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2);

>>>> +     }

>>>> +}

>>>> +

>>>>  static void sdhci_set_transfer_mode(struct sdhci_host *host,

>>>>       struct mmc_command *cmd)

>>>>  {

>>>> @@ -1119,17 +1168,7 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,

>>>>

>>>>       if (mmc_op_multi(cmd->opcode) || data->blocks > 1) {

>>>>               mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI;

>>>> -             /*

>>>> -              * If we are sending CMD23, CMD12 never gets sent

>>>> -              * on successful completion (so no Auto-CMD12).

>>>> -              */

>>>> -             if (sdhci_auto_cmd12(host, cmd->mrq) &&

>>>> -                 (cmd->opcode != SD_IO_RW_EXTENDED))

>>>> -                     mode |= SDHCI_TRNS_AUTO_CMD12;

>>>> -             else if (cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) {

>>>> -                     mode |= SDHCI_TRNS_AUTO_CMD23;

>>>> -                     sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2);

>>>> -             }

>>>> +             sdhci_auto_cmd_select(host, cmd, &mode);

>>>>       }

>>>>

>>>>       if (data->flags & MMC_DATA_READ)

>>>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h

>>>> index 81aae07..a8f4ec2 100644

>>>> --- a/drivers/mmc/host/sdhci.h

>>>> +++ b/drivers/mmc/host/sdhci.h

>>>> @@ -42,6 +42,7 @@

>>>>  #define  SDHCI_TRNS_BLK_CNT_EN       0x02

>>>>  #define  SDHCI_TRNS_AUTO_CMD12       0x04

>>>>  #define  SDHCI_TRNS_AUTO_CMD23       0x08

>>>> +#define  SDHCI_TRNS_AUTO_SEL 0x0C

>>>>  #define  SDHCI_TRNS_READ     0x10

>>>>  #define  SDHCI_TRNS_MULTI    0x20

>>>>

>>>> @@ -185,6 +186,7 @@

>>>>  #define   SDHCI_CTRL_DRV_TYPE_D              0x0030

>>>>  #define  SDHCI_CTRL_EXEC_TUNING              0x0040

>>>>  #define  SDHCI_CTRL_TUNED_CLK                0x0080

>>>> +#define  SDHCI_CMD23_ENABLE          0x0800

>>>>  #define  SDHCI_CTRL_V4_MODE          0x1000

>>>>  #define  SDHCI_CTRL_64BIT_ADDR               0x2000

>>>>  #define  SDHCI_CTRL_PRESET_VAL_ENABLE        0x8000

>>>>

>>>

>>

>

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Adrian Hunter July 31, 2018, 8:56 a.m. UTC | #5
On 31/07/18 11:36, Chunyan Zhang wrote:
> On 31 July 2018 at 16:05, Adrian Hunter <adrian.hunter@intel.com> wrote:

>> On 31/07/18 10:04, Chunyan Zhang wrote:

>>> Hi Adrian,

>>>

>>> On 30 July 2018 at 21:06, Adrian Hunter <adrian.hunter@intel.com> wrote:

>>>> On 23/07/18 13:08, Chunyan Zhang wrote:

>>>>> As SD Host Controller Specification v4.10 documents:

>>>>> Host Controller Version 4.10 defines this "Auto CMD Auto Select" mode.

>>>>> Selection of Auto CMD depends on setting of CMD23 Enable in the Host

>>>>> Control 2 register which indicates whether card supports CMD23. If CMD23

>>>>> Enable =1, Auto CMD23 is used and if CMD23 Enable =0, Auto CMD12 is

>>>>> used. In case of Version 4.10 or later, use of Auto CMD Auto Select is

>>>>> recommended rather than use of Auto CMD12 Enable or Auto CMD23

>>>>> Enable.

>>>>>

>>>>> This patch add this new mode support.

>>>>>

>>>>> Signed-off-by: Chunyan Zhang <zhang.chunyan@linaro.org>

>>>>> ---

>>>>>  drivers/mmc/host/sdhci.c | 61 +++++++++++++++++++++++++++++++++++++++---------

>>>>>  drivers/mmc/host/sdhci.h |  2 ++

>>>>>  2 files changed, 52 insertions(+), 11 deletions(-)

>>>>>

>>>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c

>>>>> index 5acea3d..5c60590 100644

>>>>> --- a/drivers/mmc/host/sdhci.c

>>>>> +++ b/drivers/mmc/host/sdhci.c

>>>>> @@ -311,6 +311,23 @@ static void sdhci_config_dma(struct sdhci_host *host)

>>>>>       sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);

>>>>>  }

>>>>>

>>>>> +static void sdhci_enable_cmd23(struct sdhci_host *host)

>>>>> +{

>>>>> +     u16 ctrl2;

>>>>> +

>>>>> +     /*

>>>>> +      * This is used along with "Auto CMD Auto Select" feature,

>>>>> +      * which is introduced from v4.10, if card supports CMD23,

>>>>> +      * Auto CMD23 should be used instead of Auto CMD12.

>>>>> +      */

>>>>> +     if (host->version >= SDHCI_SPEC_410 &&

>>>>> +         (host->mmc->caps & MMC_CAP_CMD23)) {

>>>>

>>>> That is the host capability.  It needs to be the card capability.

>>>

>>> Could you please elaborate the issue?

>>>

>>> I thought we're setting for host here.  Do you mean we need to see the

>>> card capability?

>>

>> Yes. SDHCI_TRNS_AUTO_SEL selects auto-CMD23 or auto-CMD12 based on this

>> setting, so this must reflect the card's capability.

> 

> Got it, but how to know if the card supports CMD23?


At the moment the only way of knowing is if a request is received with mrq->sbc

> 

>>

>>>

>>>>

>>>>> +             ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);

>>>>> +             ctrl2 |= SDHCI_CMD23_ENABLE;

>>>>> +             sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);

>>>>> +     }

>>>>> +}

>>>>> +

>>>>>  static void sdhci_init(struct sdhci_host *host, int soft)

>>>>>  {

>>>>>       struct mmc_host *mmc = host->mmc;

>>>>> @@ -329,6 +346,8 @@ static void sdhci_init(struct sdhci_host *host, int soft)

>>>>>               host->clock = 0;

>>>>>               mmc->ops->set_ios(mmc, &mmc->ios);

>>>>>       }

>>>>> +

>>>>> +     sdhci_enable_cmd23(host);

>>>>>  }

>>>>>

>>>>>  static void sdhci_reinit(struct sdhci_host *host)

>>>>> @@ -1093,6 +1112,36 @@ static inline bool sdhci_auto_cmd12(struct sdhci_host *host,

>>>>>              !mrq->cap_cmd_during_tfr;

>>>>>  }

>>>>>

>>>>> +static inline void sdhci_auto_cmd_select(struct sdhci_host *host,

>>>>> +                                      struct mmc_command *cmd,

>>>>> +                                      u16 *mode)

>>>>> +{

>>>>> +     bool use_cmd12 = sdhci_auto_cmd12(host, cmd->mrq) &&

>>>>> +                      (cmd->opcode != SD_IO_RW_EXTENDED);

>>>>> +     bool use_cmd23 = cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23);

>>>>> +

>>>>> +     /*

>>>>> +      * In case of Version 4.10 or later, use of 'Auto CMD Auto

>>>>> +      * Select' is recommended rather than use of 'Auto CMD12

>>>>> +      * Enable' or 'Auto CMD23 Enable'.

>>>>> +      */

>>>>> +     if (host->version >= SDHCI_SPEC_410 && (use_cmd12 || use_cmd23)) {

>>>>> +             *mode |= SDHCI_TRNS_AUTO_SEL;

>>>>

>>>> As noted in patch 4, the CMD23 argument is not just the block count for eMMC.

>>>

>>> Probably I haven't got your point...

>>>

>>> >From what I understand, auto_sel mode doesn't need argument2. Doesn't

>>> this work for eMMC?

>>

>> CMD23 always needs an argument

> 

> But setting argument for CMD23 will cover the block count value we set

> before, that will lead mounting emmc to fail.


Does it fail because it contains cmd->mrq->sbc->arg or does it fail because
it gets written twice?

> 

>>

>>>

>>> The test platform I used was just eMMC only, haven't found problem.

>>

>> Because the bits that are missing from the CMD23 argument (reliable write,

>> context id, etc) will not make the command fail.

>>

>>>

>>> Thanks,

>>> Chunyan

>>>

>>>>

>>>>> +             return;

>>>>> +     }

>>>>> +

>>>>> +     /*

>>>>> +      * If we are sending CMD23, CMD12 never gets sent

>>>>> +      * on successful completion (so no Auto-CMD12).

>>>>> +      */

>>>>> +     if (use_cmd12) {

>>>>> +             *mode |= SDHCI_TRNS_AUTO_CMD12;

>>>>> +     } else if (use_cmd23) {

>>>>> +             *mode |= SDHCI_TRNS_AUTO_CMD23;

>>>>> +             sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2);

>>>>> +     }

>>>>> +}

>>>>> +

>>>>>  static void sdhci_set_transfer_mode(struct sdhci_host *host,

>>>>>       struct mmc_command *cmd)

>>>>>  {

>>>>> @@ -1119,17 +1168,7 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,

>>>>>

>>>>>       if (mmc_op_multi(cmd->opcode) || data->blocks > 1) {

>>>>>               mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI;

>>>>> -             /*

>>>>> -              * If we are sending CMD23, CMD12 never gets sent

>>>>> -              * on successful completion (so no Auto-CMD12).

>>>>> -              */

>>>>> -             if (sdhci_auto_cmd12(host, cmd->mrq) &&

>>>>> -                 (cmd->opcode != SD_IO_RW_EXTENDED))

>>>>> -                     mode |= SDHCI_TRNS_AUTO_CMD12;

>>>>> -             else if (cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) {

>>>>> -                     mode |= SDHCI_TRNS_AUTO_CMD23;

>>>>> -                     sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2);

>>>>> -             }

>>>>> +             sdhci_auto_cmd_select(host, cmd, &mode);

>>>>>       }

>>>>>

>>>>>       if (data->flags & MMC_DATA_READ)

>>>>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h

>>>>> index 81aae07..a8f4ec2 100644

>>>>> --- a/drivers/mmc/host/sdhci.h

>>>>> +++ b/drivers/mmc/host/sdhci.h

>>>>> @@ -42,6 +42,7 @@

>>>>>  #define  SDHCI_TRNS_BLK_CNT_EN       0x02

>>>>>  #define  SDHCI_TRNS_AUTO_CMD12       0x04

>>>>>  #define  SDHCI_TRNS_AUTO_CMD23       0x08

>>>>> +#define  SDHCI_TRNS_AUTO_SEL 0x0C

>>>>>  #define  SDHCI_TRNS_READ     0x10

>>>>>  #define  SDHCI_TRNS_MULTI    0x20

>>>>>

>>>>> @@ -185,6 +186,7 @@

>>>>>  #define   SDHCI_CTRL_DRV_TYPE_D              0x0030

>>>>>  #define  SDHCI_CTRL_EXEC_TUNING              0x0040

>>>>>  #define  SDHCI_CTRL_TUNED_CLK                0x0080

>>>>> +#define  SDHCI_CMD23_ENABLE          0x0800

>>>>>  #define  SDHCI_CTRL_V4_MODE          0x1000

>>>>>  #define  SDHCI_CTRL_64BIT_ADDR               0x2000

>>>>>  #define  SDHCI_CTRL_PRESET_VAL_ENABLE        0x8000

>>>>>

>>>>

>>>

>>

> 


--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Chunyan Zhang July 31, 2018, 9:20 a.m. UTC | #6
On 31 July 2018 at 16:56, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 31/07/18 11:36, Chunyan Zhang wrote:

>> On 31 July 2018 at 16:05, Adrian Hunter <adrian.hunter@intel.com> wrote:

>>> On 31/07/18 10:04, Chunyan Zhang wrote:

>>>> Hi Adrian,

>>>>

>>>> On 30 July 2018 at 21:06, Adrian Hunter <adrian.hunter@intel.com> wrote:

>>>>> On 23/07/18 13:08, Chunyan Zhang wrote:

>>>>>> As SD Host Controller Specification v4.10 documents:

>>>>>> Host Controller Version 4.10 defines this "Auto CMD Auto Select" mode.

>>>>>> Selection of Auto CMD depends on setting of CMD23 Enable in the Host

>>>>>> Control 2 register which indicates whether card supports CMD23. If CMD23

>>>>>> Enable =1, Auto CMD23 is used and if CMD23 Enable =0, Auto CMD12 is

>>>>>> used. In case of Version 4.10 or later, use of Auto CMD Auto Select is

>>>>>> recommended rather than use of Auto CMD12 Enable or Auto CMD23

>>>>>> Enable.

>>>>>>

>>>>>> This patch add this new mode support.

>>>>>>

>>>>>> Signed-off-by: Chunyan Zhang <zhang.chunyan@linaro.org>

>>>>>> ---

>>>>>>  drivers/mmc/host/sdhci.c | 61 +++++++++++++++++++++++++++++++++++++++---------

>>>>>>  drivers/mmc/host/sdhci.h |  2 ++

>>>>>>  2 files changed, 52 insertions(+), 11 deletions(-)

>>>>>>

>>>>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c

>>>>>> index 5acea3d..5c60590 100644

>>>>>> --- a/drivers/mmc/host/sdhci.c

>>>>>> +++ b/drivers/mmc/host/sdhci.c

>>>>>> @@ -311,6 +311,23 @@ static void sdhci_config_dma(struct sdhci_host *host)

>>>>>>       sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);

>>>>>>  }

>>>>>>

>>>>>> +static void sdhci_enable_cmd23(struct sdhci_host *host)

>>>>>> +{

>>>>>> +     u16 ctrl2;

>>>>>> +

>>>>>> +     /*

>>>>>> +      * This is used along with "Auto CMD Auto Select" feature,

>>>>>> +      * which is introduced from v4.10, if card supports CMD23,

>>>>>> +      * Auto CMD23 should be used instead of Auto CMD12.

>>>>>> +      */

>>>>>> +     if (host->version >= SDHCI_SPEC_410 &&

>>>>>> +         (host->mmc->caps & MMC_CAP_CMD23)) {

>>>>>

>>>>> That is the host capability.  It needs to be the card capability.

>>>>

>>>> Could you please elaborate the issue?

>>>>

>>>> I thought we're setting for host here.  Do you mean we need to see the

>>>> card capability?

>>>

>>> Yes. SDHCI_TRNS_AUTO_SEL selects auto-CMD23 or auto-CMD12 based on this

>>> setting, so this must reflect the card's capability.

>>

>> Got it, but how to know if the card supports CMD23?

>

> At the moment the only way of knowing is if a request is received with mrq->sbc

>

>>

>>>

>>>>

>>>>>

>>>>>> +             ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);

>>>>>> +             ctrl2 |= SDHCI_CMD23_ENABLE;

>>>>>> +             sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);

>>>>>> +     }

>>>>>> +}

>>>>>> +

>>>>>>  static void sdhci_init(struct sdhci_host *host, int soft)

>>>>>>  {

>>>>>>       struct mmc_host *mmc = host->mmc;

>>>>>> @@ -329,6 +346,8 @@ static void sdhci_init(struct sdhci_host *host, int soft)

>>>>>>               host->clock = 0;

>>>>>>               mmc->ops->set_ios(mmc, &mmc->ios);

>>>>>>       }

>>>>>> +

>>>>>> +     sdhci_enable_cmd23(host);

>>>>>>  }

>>>>>>

>>>>>>  static void sdhci_reinit(struct sdhci_host *host)

>>>>>> @@ -1093,6 +1112,36 @@ static inline bool sdhci_auto_cmd12(struct sdhci_host *host,

>>>>>>              !mrq->cap_cmd_during_tfr;

>>>>>>  }

>>>>>>

>>>>>> +static inline void sdhci_auto_cmd_select(struct sdhci_host *host,

>>>>>> +                                      struct mmc_command *cmd,

>>>>>> +                                      u16 *mode)

>>>>>> +{

>>>>>> +     bool use_cmd12 = sdhci_auto_cmd12(host, cmd->mrq) &&

>>>>>> +                      (cmd->opcode != SD_IO_RW_EXTENDED);

>>>>>> +     bool use_cmd23 = cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23);

>>>>>> +

>>>>>> +     /*

>>>>>> +      * In case of Version 4.10 or later, use of 'Auto CMD Auto

>>>>>> +      * Select' is recommended rather than use of 'Auto CMD12

>>>>>> +      * Enable' or 'Auto CMD23 Enable'.

>>>>>> +      */

>>>>>> +     if (host->version >= SDHCI_SPEC_410 && (use_cmd12 || use_cmd23)) {

>>>>>> +             *mode |= SDHCI_TRNS_AUTO_SEL;

>>>>>

>>>>> As noted in patch 4, the CMD23 argument is not just the block count for eMMC.

>>>>

>>>> Probably I haven't got your point...

>>>>

>>>> >From what I understand, auto_sel mode doesn't need argument2. Doesn't

>>>> this work for eMMC?

>>>

>>> CMD23 always needs an argument

>>

>> But setting argument for CMD23 will cover the block count value we set

>> before, that will lead mounting emmc to fail.

>

> Does it fail because it contains cmd->mrq->sbc->arg or does it fail because

> it gets written twice?


Seems that the argument is too big compared with block count, hardware
think it is a super block count.

More details of the error information:
https://www.irccloud.com/pastebin/uYlVEUsP/

>

>>

>>>

>>>>

>>>> The test platform I used was just eMMC only, haven't found problem.

>>>

>>> Because the bits that are missing from the CMD23 argument (reliable write,

>>> context id, etc) will not make the command fail.

>>>

>>>>

>>>> Thanks,

>>>> Chunyan

>>>>

>>>>>

>>>>>> +             return;

>>>>>> +     }

>>>>>> +

>>>>>> +     /*

>>>>>> +      * If we are sending CMD23, CMD12 never gets sent

>>>>>> +      * on successful completion (so no Auto-CMD12).

>>>>>> +      */

>>>>>> +     if (use_cmd12) {

>>>>>> +             *mode |= SDHCI_TRNS_AUTO_CMD12;

>>>>>> +     } else if (use_cmd23) {

>>>>>> +             *mode |= SDHCI_TRNS_AUTO_CMD23;

>>>>>> +             sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2);

>>>>>> +     }

>>>>>> +}

>>>>>> +

>>>>>>  static void sdhci_set_transfer_mode(struct sdhci_host *host,

>>>>>>       struct mmc_command *cmd)

>>>>>>  {

>>>>>> @@ -1119,17 +1168,7 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,

>>>>>>

>>>>>>       if (mmc_op_multi(cmd->opcode) || data->blocks > 1) {

>>>>>>               mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI;

>>>>>> -             /*

>>>>>> -              * If we are sending CMD23, CMD12 never gets sent

>>>>>> -              * on successful completion (so no Auto-CMD12).

>>>>>> -              */

>>>>>> -             if (sdhci_auto_cmd12(host, cmd->mrq) &&

>>>>>> -                 (cmd->opcode != SD_IO_RW_EXTENDED))

>>>>>> -                     mode |= SDHCI_TRNS_AUTO_CMD12;

>>>>>> -             else if (cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) {

>>>>>> -                     mode |= SDHCI_TRNS_AUTO_CMD23;

>>>>>> -                     sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2);

>>>>>> -             }

>>>>>> +             sdhci_auto_cmd_select(host, cmd, &mode);

>>>>>>       }

>>>>>>

>>>>>>       if (data->flags & MMC_DATA_READ)

>>>>>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h

>>>>>> index 81aae07..a8f4ec2 100644

>>>>>> --- a/drivers/mmc/host/sdhci.h

>>>>>> +++ b/drivers/mmc/host/sdhci.h

>>>>>> @@ -42,6 +42,7 @@

>>>>>>  #define  SDHCI_TRNS_BLK_CNT_EN       0x02

>>>>>>  #define  SDHCI_TRNS_AUTO_CMD12       0x04

>>>>>>  #define  SDHCI_TRNS_AUTO_CMD23       0x08

>>>>>> +#define  SDHCI_TRNS_AUTO_SEL 0x0C

>>>>>>  #define  SDHCI_TRNS_READ     0x10

>>>>>>  #define  SDHCI_TRNS_MULTI    0x20

>>>>>>

>>>>>> @@ -185,6 +186,7 @@

>>>>>>  #define   SDHCI_CTRL_DRV_TYPE_D              0x0030

>>>>>>  #define  SDHCI_CTRL_EXEC_TUNING              0x0040

>>>>>>  #define  SDHCI_CTRL_TUNED_CLK                0x0080

>>>>>> +#define  SDHCI_CMD23_ENABLE          0x0800

>>>>>>  #define  SDHCI_CTRL_V4_MODE          0x1000

>>>>>>  #define  SDHCI_CTRL_64BIT_ADDR               0x2000

>>>>>>  #define  SDHCI_CTRL_PRESET_VAL_ENABLE        0x8000

>>>>>>

>>>>>

>>>>

>>>

>>

>

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Chunyan Zhang July 31, 2018, 9:27 a.m. UTC | #7
On 31 July 2018 at 16:56, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 31/07/18 11:36, Chunyan Zhang wrote:

>> On 31 July 2018 at 16:05, Adrian Hunter <adrian.hunter@intel.com> wrote:

>>> On 31/07/18 10:04, Chunyan Zhang wrote:

>>>> Hi Adrian,

>>>>

>>>> On 30 July 2018 at 21:06, Adrian Hunter <adrian.hunter@intel.com> wrote:

>>>>> On 23/07/18 13:08, Chunyan Zhang wrote:

>>>>>> As SD Host Controller Specification v4.10 documents:

>>>>>> Host Controller Version 4.10 defines this "Auto CMD Auto Select" mode.

>>>>>> Selection of Auto CMD depends on setting of CMD23 Enable in the Host

>>>>>> Control 2 register which indicates whether card supports CMD23. If CMD23

>>>>>> Enable =1, Auto CMD23 is used and if CMD23 Enable =0, Auto CMD12 is

>>>>>> used. In case of Version 4.10 or later, use of Auto CMD Auto Select is

>>>>>> recommended rather than use of Auto CMD12 Enable or Auto CMD23

>>>>>> Enable.

>>>>>>

>>>>>> This patch add this new mode support.

>>>>>>

>>>>>> Signed-off-by: Chunyan Zhang <zhang.chunyan@linaro.org>

>>>>>> ---

>>>>>>  drivers/mmc/host/sdhci.c | 61 +++++++++++++++++++++++++++++++++++++++---------

>>>>>>  drivers/mmc/host/sdhci.h |  2 ++

>>>>>>  2 files changed, 52 insertions(+), 11 deletions(-)

>>>>>>

>>>>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c

>>>>>> index 5acea3d..5c60590 100644

>>>>>> --- a/drivers/mmc/host/sdhci.c

>>>>>> +++ b/drivers/mmc/host/sdhci.c

>>>>>> @@ -311,6 +311,23 @@ static void sdhci_config_dma(struct sdhci_host *host)

>>>>>>       sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);

>>>>>>  }

>>>>>>

>>>>>> +static void sdhci_enable_cmd23(struct sdhci_host *host)

>>>>>> +{

>>>>>> +     u16 ctrl2;

>>>>>> +

>>>>>> +     /*

>>>>>> +      * This is used along with "Auto CMD Auto Select" feature,

>>>>>> +      * which is introduced from v4.10, if card supports CMD23,

>>>>>> +      * Auto CMD23 should be used instead of Auto CMD12.

>>>>>> +      */

>>>>>> +     if (host->version >= SDHCI_SPEC_410 &&

>>>>>> +         (host->mmc->caps & MMC_CAP_CMD23)) {

>>>>>

>>>>> That is the host capability.  It needs to be the card capability.

>>>>

>>>> Could you please elaborate the issue?

>>>>

>>>> I thought we're setting for host here.  Do you mean we need to see the

>>>> card capability?

>>>

>>> Yes. SDHCI_TRNS_AUTO_SEL selects auto-CMD23 or auto-CMD12 based on this

>>> setting, so this must reflect the card's capability.

>>

>> Got it, but how to know if the card supports CMD23?

>

> At the moment the only way of knowing is if a request is received with mrq->sbc


Ok. I will move this setting to sdhci_auto_cmd_select() for use_cmd23 is true.

>

>>

>>>

>>>>

>>>>>

>>>>>> +             ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);

>>>>>> +             ctrl2 |= SDHCI_CMD23_ENABLE;

>>>>>> +             sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);

>>>>>> +     }

>>>>>> +}

>>>>>> +

>>>>>>  static void sdhci_init(struct sdhci_host *host, int soft)

>>>>>>  {

>>>>>>       struct mmc_host *mmc = host->mmc;

>>>>>> @@ -329,6 +346,8 @@ static void sdhci_init(struct sdhci_host *host, int soft)

>>>>>>               host->clock = 0;

>>>>>>               mmc->ops->set_ios(mmc, &mmc->ios);

>>>>>>       }

>>>>>> +

>>>>>> +     sdhci_enable_cmd23(host);

>>>>>>  }

>>>>>>

>>>>>>  static void sdhci_reinit(struct sdhci_host *host)

>>>>>> @@ -1093,6 +1112,36 @@ static inline bool sdhci_auto_cmd12(struct sdhci_host *host,

>>>>>>              !mrq->cap_cmd_during_tfr;

>>>>>>  }

>>>>>>

>>>>>> +static inline void sdhci_auto_cmd_select(struct sdhci_host *host,

>>>>>> +                                      struct mmc_command *cmd,

>>>>>> +                                      u16 *mode)

>>>>>> +{

>>>>>> +     bool use_cmd12 = sdhci_auto_cmd12(host, cmd->mrq) &&

>>>>>> +                      (cmd->opcode != SD_IO_RW_EXTENDED);

>>>>>> +     bool use_cmd23 = cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23);

>>>>>> +

>>>>>> +     /*

>>>>>> +      * In case of Version 4.10 or later, use of 'Auto CMD Auto

>>>>>> +      * Select' is recommended rather than use of 'Auto CMD12

>>>>>> +      * Enable' or 'Auto CMD23 Enable'.

>>>>>> +      */

>>>>>> +     if (host->version >= SDHCI_SPEC_410 && (use_cmd12 || use_cmd23)) {

>>>>>> +             *mode |= SDHCI_TRNS_AUTO_SEL;

>>>>>

>>>>> As noted in patch 4, the CMD23 argument is not just the block count for eMMC.

>>>>

>>>> Probably I haven't got your point...

>>>>

>>>> >From what I understand, auto_sel mode doesn't need argument2. Doesn't

>>>> this work for eMMC?

>>>

>>> CMD23 always needs an argument

>>

>> But setting argument for CMD23 will cover the block count value we set

>> before, that will lead mounting emmc to fail.

>

> Does it fail because it contains cmd->mrq->sbc->arg or does it fail because

> it gets written twice?

>

>>

>>>

>>>>

>>>> The test platform I used was just eMMC only, haven't found problem.

>>>

>>> Because the bits that are missing from the CMD23 argument (reliable write,

>>> context id, etc) will not make the command fail.

>>>

>>>>

>>>> Thanks,

>>>> Chunyan

>>>>

>>>>>

>>>>>> +             return;

>>>>>> +     }

>>>>>> +

>>>>>> +     /*

>>>>>> +      * If we are sending CMD23, CMD12 never gets sent

>>>>>> +      * on successful completion (so no Auto-CMD12).

>>>>>> +      */

>>>>>> +     if (use_cmd12) {

>>>>>> +             *mode |= SDHCI_TRNS_AUTO_CMD12;

>>>>>> +     } else if (use_cmd23) {

>>>>>> +             *mode |= SDHCI_TRNS_AUTO_CMD23;

>>>>>> +             sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2);

>>>>>> +     }

>>>>>> +}

>>>>>> +

>>>>>>  static void sdhci_set_transfer_mode(struct sdhci_host *host,

>>>>>>       struct mmc_command *cmd)

>>>>>>  {

>>>>>> @@ -1119,17 +1168,7 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,

>>>>>>

>>>>>>       if (mmc_op_multi(cmd->opcode) || data->blocks > 1) {

>>>>>>               mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI;

>>>>>> -             /*

>>>>>> -              * If we are sending CMD23, CMD12 never gets sent

>>>>>> -              * on successful completion (so no Auto-CMD12).

>>>>>> -              */

>>>>>> -             if (sdhci_auto_cmd12(host, cmd->mrq) &&

>>>>>> -                 (cmd->opcode != SD_IO_RW_EXTENDED))

>>>>>> -                     mode |= SDHCI_TRNS_AUTO_CMD12;

>>>>>> -             else if (cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) {

>>>>>> -                     mode |= SDHCI_TRNS_AUTO_CMD23;

>>>>>> -                     sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2);

>>>>>> -             }

>>>>>> +             sdhci_auto_cmd_select(host, cmd, &mode);

>>>>>>       }

>>>>>>

>>>>>>       if (data->flags & MMC_DATA_READ)

>>>>>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h

>>>>>> index 81aae07..a8f4ec2 100644

>>>>>> --- a/drivers/mmc/host/sdhci.h

>>>>>> +++ b/drivers/mmc/host/sdhci.h

>>>>>> @@ -42,6 +42,7 @@

>>>>>>  #define  SDHCI_TRNS_BLK_CNT_EN       0x02

>>>>>>  #define  SDHCI_TRNS_AUTO_CMD12       0x04

>>>>>>  #define  SDHCI_TRNS_AUTO_CMD23       0x08

>>>>>> +#define  SDHCI_TRNS_AUTO_SEL 0x0C

>>>>>>  #define  SDHCI_TRNS_READ     0x10

>>>>>>  #define  SDHCI_TRNS_MULTI    0x20

>>>>>>

>>>>>> @@ -185,6 +186,7 @@

>>>>>>  #define   SDHCI_CTRL_DRV_TYPE_D              0x0030

>>>>>>  #define  SDHCI_CTRL_EXEC_TUNING              0x0040

>>>>>>  #define  SDHCI_CTRL_TUNED_CLK                0x0080

>>>>>> +#define  SDHCI_CMD23_ENABLE          0x0800

>>>>>>  #define  SDHCI_CTRL_V4_MODE          0x1000

>>>>>>  #define  SDHCI_CTRL_64BIT_ADDR               0x2000

>>>>>>  #define  SDHCI_CTRL_PRESET_VAL_ENABLE        0x8000

>>>>>>

>>>>>

>>>>

>>>

>>

>

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Adrian Hunter July 31, 2018, 9:36 a.m. UTC | #8
On 31/07/18 12:20, Chunyan Zhang wrote:
> On 31 July 2018 at 16:56, Adrian Hunter <adrian.hunter@intel.com> wrote:

>> On 31/07/18 11:36, Chunyan Zhang wrote:

>>> On 31 July 2018 at 16:05, Adrian Hunter <adrian.hunter@intel.com> wrote:

>>>> On 31/07/18 10:04, Chunyan Zhang wrote:

>>>>> Hi Adrian,

>>>>>

>>>>> On 30 July 2018 at 21:06, Adrian Hunter <adrian.hunter@intel.com> wrote:

>>>>>> On 23/07/18 13:08, Chunyan Zhang wrote:

>>>>>>> As SD Host Controller Specification v4.10 documents:

>>>>>>> Host Controller Version 4.10 defines this "Auto CMD Auto Select" mode.

>>>>>>> Selection of Auto CMD depends on setting of CMD23 Enable in the Host

>>>>>>> Control 2 register which indicates whether card supports CMD23. If CMD23

>>>>>>> Enable =1, Auto CMD23 is used and if CMD23 Enable =0, Auto CMD12 is

>>>>>>> used. In case of Version 4.10 or later, use of Auto CMD Auto Select is

>>>>>>> recommended rather than use of Auto CMD12 Enable or Auto CMD23

>>>>>>> Enable.

>>>>>>>

>>>>>>> This patch add this new mode support.

>>>>>>>

>>>>>>> Signed-off-by: Chunyan Zhang <zhang.chunyan@linaro.org>

>>>>>>> ---

>>>>>>>  drivers/mmc/host/sdhci.c | 61 +++++++++++++++++++++++++++++++++++++++---------

>>>>>>>  drivers/mmc/host/sdhci.h |  2 ++

>>>>>>>  2 files changed, 52 insertions(+), 11 deletions(-)

>>>>>>>

>>>>>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c

>>>>>>> index 5acea3d..5c60590 100644

>>>>>>> --- a/drivers/mmc/host/sdhci.c

>>>>>>> +++ b/drivers/mmc/host/sdhci.c

>>>>>>> @@ -311,6 +311,23 @@ static void sdhci_config_dma(struct sdhci_host *host)

>>>>>>>       sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);

>>>>>>>  }

>>>>>>>

>>>>>>> +static void sdhci_enable_cmd23(struct sdhci_host *host)

>>>>>>> +{

>>>>>>> +     u16 ctrl2;

>>>>>>> +

>>>>>>> +     /*

>>>>>>> +      * This is used along with "Auto CMD Auto Select" feature,

>>>>>>> +      * which is introduced from v4.10, if card supports CMD23,

>>>>>>> +      * Auto CMD23 should be used instead of Auto CMD12.

>>>>>>> +      */

>>>>>>> +     if (host->version >= SDHCI_SPEC_410 &&

>>>>>>> +         (host->mmc->caps & MMC_CAP_CMD23)) {

>>>>>>

>>>>>> That is the host capability.  It needs to be the card capability.

>>>>>

>>>>> Could you please elaborate the issue?

>>>>>

>>>>> I thought we're setting for host here.  Do you mean we need to see the

>>>>> card capability?

>>>>

>>>> Yes. SDHCI_TRNS_AUTO_SEL selects auto-CMD23 or auto-CMD12 based on this

>>>> setting, so this must reflect the card's capability.

>>>

>>> Got it, but how to know if the card supports CMD23?

>>

>> At the moment the only way of knowing is if a request is received with mrq->sbc

>>

>>>

>>>>

>>>>>

>>>>>>

>>>>>>> +             ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);

>>>>>>> +             ctrl2 |= SDHCI_CMD23_ENABLE;

>>>>>>> +             sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);

>>>>>>> +     }

>>>>>>> +}

>>>>>>> +

>>>>>>>  static void sdhci_init(struct sdhci_host *host, int soft)

>>>>>>>  {

>>>>>>>       struct mmc_host *mmc = host->mmc;

>>>>>>> @@ -329,6 +346,8 @@ static void sdhci_init(struct sdhci_host *host, int soft)

>>>>>>>               host->clock = 0;

>>>>>>>               mmc->ops->set_ios(mmc, &mmc->ios);

>>>>>>>       }

>>>>>>> +

>>>>>>> +     sdhci_enable_cmd23(host);

>>>>>>>  }

>>>>>>>

>>>>>>>  static void sdhci_reinit(struct sdhci_host *host)

>>>>>>> @@ -1093,6 +1112,36 @@ static inline bool sdhci_auto_cmd12(struct sdhci_host *host,

>>>>>>>              !mrq->cap_cmd_during_tfr;

>>>>>>>  }

>>>>>>>

>>>>>>> +static inline void sdhci_auto_cmd_select(struct sdhci_host *host,

>>>>>>> +                                      struct mmc_command *cmd,

>>>>>>> +                                      u16 *mode)

>>>>>>> +{

>>>>>>> +     bool use_cmd12 = sdhci_auto_cmd12(host, cmd->mrq) &&

>>>>>>> +                      (cmd->opcode != SD_IO_RW_EXTENDED);

>>>>>>> +     bool use_cmd23 = cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23);

>>>>>>> +

>>>>>>> +     /*

>>>>>>> +      * In case of Version 4.10 or later, use of 'Auto CMD Auto

>>>>>>> +      * Select' is recommended rather than use of 'Auto CMD12

>>>>>>> +      * Enable' or 'Auto CMD23 Enable'.

>>>>>>> +      */

>>>>>>> +     if (host->version >= SDHCI_SPEC_410 && (use_cmd12 || use_cmd23)) {

>>>>>>> +             *mode |= SDHCI_TRNS_AUTO_SEL;

>>>>>>

>>>>>> As noted in patch 4, the CMD23 argument is not just the block count for eMMC.

>>>>>

>>>>> Probably I haven't got your point...

>>>>>

>>>>> >From what I understand, auto_sel mode doesn't need argument2. Doesn't

>>>>> this work for eMMC?

>>>>

>>>> CMD23 always needs an argument

>>>

>>> But setting argument for CMD23 will cover the block count value we set

>>> before, that will lead mounting emmc to fail.

>>

>> Does it fail because it contains cmd->mrq->sbc->arg or does it fail because

>> it gets written twice?

> 

> Seems that the argument is too big compared with block count, hardware

> think it is a super block count.

> 

> More details of the error information:

> https://www.irccloud.com/pastebin/uYlVEUsP/


Does it work with auto-CMD23 instead of auto-CMD-auto-select?
Does it work if the 16-bit block count register is used?

Obviously, if we can't pass the CMD23 argument correctly then we can't use
auto-CMD23.

> 

>>

>>>

>>>>

>>>>>

>>>>> The test platform I used was just eMMC only, haven't found problem.

>>>>

>>>> Because the bits that are missing from the CMD23 argument (reliable write,

>>>> context id, etc) will not make the command fail.

>>>>

>>>>>

>>>>> Thanks,

>>>>> Chunyan

>>>>>

>>>>>>

>>>>>>> +             return;

>>>>>>> +     }

>>>>>>> +

>>>>>>> +     /*

>>>>>>> +      * If we are sending CMD23, CMD12 never gets sent

>>>>>>> +      * on successful completion (so no Auto-CMD12).

>>>>>>> +      */

>>>>>>> +     if (use_cmd12) {

>>>>>>> +             *mode |= SDHCI_TRNS_AUTO_CMD12;

>>>>>>> +     } else if (use_cmd23) {

>>>>>>> +             *mode |= SDHCI_TRNS_AUTO_CMD23;

>>>>>>> +             sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2);

>>>>>>> +     }

>>>>>>> +}

>>>>>>> +

>>>>>>>  static void sdhci_set_transfer_mode(struct sdhci_host *host,

>>>>>>>       struct mmc_command *cmd)

>>>>>>>  {

>>>>>>> @@ -1119,17 +1168,7 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,

>>>>>>>

>>>>>>>       if (mmc_op_multi(cmd->opcode) || data->blocks > 1) {

>>>>>>>               mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI;

>>>>>>> -             /*

>>>>>>> -              * If we are sending CMD23, CMD12 never gets sent

>>>>>>> -              * on successful completion (so no Auto-CMD12).

>>>>>>> -              */

>>>>>>> -             if (sdhci_auto_cmd12(host, cmd->mrq) &&

>>>>>>> -                 (cmd->opcode != SD_IO_RW_EXTENDED))

>>>>>>> -                     mode |= SDHCI_TRNS_AUTO_CMD12;

>>>>>>> -             else if (cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) {

>>>>>>> -                     mode |= SDHCI_TRNS_AUTO_CMD23;

>>>>>>> -                     sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2);

>>>>>>> -             }

>>>>>>> +             sdhci_auto_cmd_select(host, cmd, &mode);

>>>>>>>       }

>>>>>>>

>>>>>>>       if (data->flags & MMC_DATA_READ)

>>>>>>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h

>>>>>>> index 81aae07..a8f4ec2 100644

>>>>>>> --- a/drivers/mmc/host/sdhci.h

>>>>>>> +++ b/drivers/mmc/host/sdhci.h

>>>>>>> @@ -42,6 +42,7 @@

>>>>>>>  #define  SDHCI_TRNS_BLK_CNT_EN       0x02

>>>>>>>  #define  SDHCI_TRNS_AUTO_CMD12       0x04

>>>>>>>  #define  SDHCI_TRNS_AUTO_CMD23       0x08

>>>>>>> +#define  SDHCI_TRNS_AUTO_SEL 0x0C

>>>>>>>  #define  SDHCI_TRNS_READ     0x10

>>>>>>>  #define  SDHCI_TRNS_MULTI    0x20

>>>>>>>

>>>>>>> @@ -185,6 +186,7 @@

>>>>>>>  #define   SDHCI_CTRL_DRV_TYPE_D              0x0030

>>>>>>>  #define  SDHCI_CTRL_EXEC_TUNING              0x0040

>>>>>>>  #define  SDHCI_CTRL_TUNED_CLK                0x0080

>>>>>>> +#define  SDHCI_CMD23_ENABLE          0x0800

>>>>>>>  #define  SDHCI_CTRL_V4_MODE          0x1000

>>>>>>>  #define  SDHCI_CTRL_64BIT_ADDR               0x2000

>>>>>>>  #define  SDHCI_CTRL_PRESET_VAL_ENABLE        0x8000

>>>>>>>

>>>>>>

>>>>>

>>>>

>>>

>>

> 


--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Chunyan Zhang Aug. 1, 2018, 9:26 a.m. UTC | #9
On 31 July 2018 at 17:36, Adrian Hunter <adrian.hunter@intel.com> wrote:
> On 31/07/18 12:20, Chunyan Zhang wrote:

>> On 31 July 2018 at 16:56, Adrian Hunter <adrian.hunter@intel.com> wrote:

>>> On 31/07/18 11:36, Chunyan Zhang wrote:

>>>> On 31 July 2018 at 16:05, Adrian Hunter <adrian.hunter@intel.com> wrote:

>>>>> On 31/07/18 10:04, Chunyan Zhang wrote:

>>>>>> Hi Adrian,

>>>>>>

>>>>>> On 30 July 2018 at 21:06, Adrian Hunter <adrian.hunter@intel.com> wrote:

>>>>>>> On 23/07/18 13:08, Chunyan Zhang wrote:

>>>>>>>> As SD Host Controller Specification v4.10 documents:

>>>>>>>> Host Controller Version 4.10 defines this "Auto CMD Auto Select" mode.

>>>>>>>> Selection of Auto CMD depends on setting of CMD23 Enable in the Host

>>>>>>>> Control 2 register which indicates whether card supports CMD23. If CMD23

>>>>>>>> Enable =1, Auto CMD23 is used and if CMD23 Enable =0, Auto CMD12 is

>>>>>>>> used. In case of Version 4.10 or later, use of Auto CMD Auto Select is

>>>>>>>> recommended rather than use of Auto CMD12 Enable or Auto CMD23

>>>>>>>> Enable.

>>>>>>>>

>>>>>>>> This patch add this new mode support.

>>>>>>>>

>>>>>>>> Signed-off-by: Chunyan Zhang <zhang.chunyan@linaro.org>

>>>>>>>> ---

>>>>>>>>  drivers/mmc/host/sdhci.c | 61 +++++++++++++++++++++++++++++++++++++++---------

>>>>>>>>  drivers/mmc/host/sdhci.h |  2 ++

>>>>>>>>  2 files changed, 52 insertions(+), 11 deletions(-)

>>>>>>>>

>>>>>>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c

>>>>>>>> index 5acea3d..5c60590 100644

>>>>>>>> --- a/drivers/mmc/host/sdhci.c

>>>>>>>> +++ b/drivers/mmc/host/sdhci.c

>>>>>>>> @@ -311,6 +311,23 @@ static void sdhci_config_dma(struct sdhci_host *host)

>>>>>>>>       sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);

>>>>>>>>  }

>>>>>>>>

>>>>>>>> +static void sdhci_enable_cmd23(struct sdhci_host *host)

>>>>>>>> +{

>>>>>>>> +     u16 ctrl2;

>>>>>>>> +

>>>>>>>> +     /*

>>>>>>>> +      * This is used along with "Auto CMD Auto Select" feature,

>>>>>>>> +      * which is introduced from v4.10, if card supports CMD23,

>>>>>>>> +      * Auto CMD23 should be used instead of Auto CMD12.

>>>>>>>> +      */

>>>>>>>> +     if (host->version >= SDHCI_SPEC_410 &&

>>>>>>>> +         (host->mmc->caps & MMC_CAP_CMD23)) {

>>>>>>>

>>>>>>> That is the host capability.  It needs to be the card capability.

>>>>>>

>>>>>> Could you please elaborate the issue?

>>>>>>

>>>>>> I thought we're setting for host here.  Do you mean we need to see the

>>>>>> card capability?

>>>>>

>>>>> Yes. SDHCI_TRNS_AUTO_SEL selects auto-CMD23 or auto-CMD12 based on this

>>>>> setting, so this must reflect the card's capability.

>>>>

>>>> Got it, but how to know if the card supports CMD23?

>>>

>>> At the moment the only way of knowing is if a request is received with mrq->sbc

>>>

>>>>

>>>>>

>>>>>>

>>>>>>>

>>>>>>>> +             ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);

>>>>>>>> +             ctrl2 |= SDHCI_CMD23_ENABLE;

>>>>>>>> +             sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);

>>>>>>>> +     }

>>>>>>>> +}

>>>>>>>> +

>>>>>>>>  static void sdhci_init(struct sdhci_host *host, int soft)

>>>>>>>>  {

>>>>>>>>       struct mmc_host *mmc = host->mmc;

>>>>>>>> @@ -329,6 +346,8 @@ static void sdhci_init(struct sdhci_host *host, int soft)

>>>>>>>>               host->clock = 0;

>>>>>>>>               mmc->ops->set_ios(mmc, &mmc->ios);

>>>>>>>>       }

>>>>>>>> +

>>>>>>>> +     sdhci_enable_cmd23(host);

>>>>>>>>  }

>>>>>>>>

>>>>>>>>  static void sdhci_reinit(struct sdhci_host *host)

>>>>>>>> @@ -1093,6 +1112,36 @@ static inline bool sdhci_auto_cmd12(struct sdhci_host *host,

>>>>>>>>              !mrq->cap_cmd_during_tfr;

>>>>>>>>  }

>>>>>>>>

>>>>>>>> +static inline void sdhci_auto_cmd_select(struct sdhci_host *host,

>>>>>>>> +                                      struct mmc_command *cmd,

>>>>>>>> +                                      u16 *mode)

>>>>>>>> +{

>>>>>>>> +     bool use_cmd12 = sdhci_auto_cmd12(host, cmd->mrq) &&

>>>>>>>> +                      (cmd->opcode != SD_IO_RW_EXTENDED);

>>>>>>>> +     bool use_cmd23 = cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23);

>>>>>>>> +

>>>>>>>> +     /*

>>>>>>>> +      * In case of Version 4.10 or later, use of 'Auto CMD Auto

>>>>>>>> +      * Select' is recommended rather than use of 'Auto CMD12

>>>>>>>> +      * Enable' or 'Auto CMD23 Enable'.

>>>>>>>> +      */

>>>>>>>> +     if (host->version >= SDHCI_SPEC_410 && (use_cmd12 || use_cmd23)) {

>>>>>>>> +             *mode |= SDHCI_TRNS_AUTO_SEL;

>>>>>>>

>>>>>>> As noted in patch 4, the CMD23 argument is not just the block count for eMMC.

>>>>>>

>>>>>> Probably I haven't got your point...

>>>>>>

>>>>>> >From what I understand, auto_sel mode doesn't need argument2. Doesn't

>>>>>> this work for eMMC?

>>>>>

>>>>> CMD23 always needs an argument

>>>>

>>>> But setting argument for CMD23 will cover the block count value we set

>>>> before, that will lead mounting emmc to fail.

>>>

>>> Does it fail because it contains cmd->mrq->sbc->arg or does it fail because

>>> it gets written twice?

>>

>> Seems that the argument is too big compared with block count, hardware

>> think it is a super block count.

>>

>> More details of the error information:

>> https://www.irccloud.com/pastebin/uYlVEUsP/

>

> Does it work with auto-CMD23 instead of auto-CMD-auto-select?


No, so long as SDHCI_32BIT_BLK_CNT was set with cmd->mrq->sbc->arg
which is a big value, it would report error "I/O error while writing
superblock" when mounting emmc.

> Does it work if the 16-bit block count register is used?


16-bit block count register is Read Only on my board :-(

>

> Obviously, if we can't pass the CMD23 argument correctly then we can't use

> auto-CMD23.


On my board, if argument2 was limited to the maximum of 65535, then
everything works, otherwise I would see an error "EXT4-fs
(mmcblk0p28): I/O error while writing superblock".  Haven't found the
root cause. I will continue to look at the problem, any comments would
be appreciated.

Thanks,
Chunyan

>

>>

>>>

>>>>

>>>>>

>>>>>>

>>>>>> The test platform I used was just eMMC only, haven't found problem.

>>>>>

>>>>> Because the bits that are missing from the CMD23 argument (reliable write,

>>>>> context id, etc) will not make the command fail.

>>>>>

>>>>>>

>>>>>> Thanks,

>>>>>> Chunyan

>>>>>>

>>>>>>>

>>>>>>>> +             return;

>>>>>>>> +     }

>>>>>>>> +

>>>>>>>> +     /*

>>>>>>>> +      * If we are sending CMD23, CMD12 never gets sent

>>>>>>>> +      * on successful completion (so no Auto-CMD12).

>>>>>>>> +      */

>>>>>>>> +     if (use_cmd12) {

>>>>>>>> +             *mode |= SDHCI_TRNS_AUTO_CMD12;

>>>>>>>> +     } else if (use_cmd23) {

>>>>>>>> +             *mode |= SDHCI_TRNS_AUTO_CMD23;

>>>>>>>> +             sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2);

>>>>>>>> +     }

>>>>>>>> +}

>>>>>>>> +

>>>>>>>>  static void sdhci_set_transfer_mode(struct sdhci_host *host,

>>>>>>>>       struct mmc_command *cmd)

>>>>>>>>  {

>>>>>>>> @@ -1119,17 +1168,7 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,

>>>>>>>>

>>>>>>>>       if (mmc_op_multi(cmd->opcode) || data->blocks > 1) {

>>>>>>>>               mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI;

>>>>>>>> -             /*

>>>>>>>> -              * If we are sending CMD23, CMD12 never gets sent

>>>>>>>> -              * on successful completion (so no Auto-CMD12).

>>>>>>>> -              */

>>>>>>>> -             if (sdhci_auto_cmd12(host, cmd->mrq) &&

>>>>>>>> -                 (cmd->opcode != SD_IO_RW_EXTENDED))

>>>>>>>> -                     mode |= SDHCI_TRNS_AUTO_CMD12;

>>>>>>>> -             else if (cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) {

>>>>>>>> -                     mode |= SDHCI_TRNS_AUTO_CMD23;

>>>>>>>> -                     sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2);

>>>>>>>> -             }

>>>>>>>> +             sdhci_auto_cmd_select(host, cmd, &mode);

>>>>>>>>       }

>>>>>>>>

>>>>>>>>       if (data->flags & MMC_DATA_READ)

>>>>>>>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h

>>>>>>>> index 81aae07..a8f4ec2 100644

>>>>>>>> --- a/drivers/mmc/host/sdhci.h

>>>>>>>> +++ b/drivers/mmc/host/sdhci.h

>>>>>>>> @@ -42,6 +42,7 @@

>>>>>>>>  #define  SDHCI_TRNS_BLK_CNT_EN       0x02

>>>>>>>>  #define  SDHCI_TRNS_AUTO_CMD12       0x04

>>>>>>>>  #define  SDHCI_TRNS_AUTO_CMD23       0x08

>>>>>>>> +#define  SDHCI_TRNS_AUTO_SEL 0x0C

>>>>>>>>  #define  SDHCI_TRNS_READ     0x10

>>>>>>>>  #define  SDHCI_TRNS_MULTI    0x20

>>>>>>>>

>>>>>>>> @@ -185,6 +186,7 @@

>>>>>>>>  #define   SDHCI_CTRL_DRV_TYPE_D              0x0030

>>>>>>>>  #define  SDHCI_CTRL_EXEC_TUNING              0x0040

>>>>>>>>  #define  SDHCI_CTRL_TUNED_CLK                0x0080

>>>>>>>> +#define  SDHCI_CMD23_ENABLE          0x0800

>>>>>>>>  #define  SDHCI_CTRL_V4_MODE          0x1000

>>>>>>>>  #define  SDHCI_CTRL_64BIT_ADDR               0x2000

>>>>>>>>  #define  SDHCI_CTRL_PRESET_VAL_ENABLE        0x8000

>>>>>>>>

>>>>>>>

>>>>>>

>>>>>

>>>>

>>>

>>

>

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html