diff mbox

[RFC,2/2] mmc: sdhi: on RCar, make use of CBSY bit

Message ID 1453808801-12510-3-git-send-email-wsa@the-dreams.de (mailing list archive)
State RFC
Delegated to: Geert Uytterhoeven
Headers show

Commit Message

Wolfram Sang Jan. 26, 2016, 11:46 a.m. UTC
From: Wolfram Sang <wsa+renesas@sang-engineering.com>

Most registers need to wait until the command is completed, not
necessarily until the bus is free. RCar SoCs can signal that via the
CBSY bit, so let's use it instead of SCLKDIVEN to save a few ns of
delay.

Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
---
 drivers/mmc/host/sh_mobile_sdhi.c | 15 +++++++++++----
 include/linux/mmc/tmio.h          |  3 +++
 2 files changed, 14 insertions(+), 4 deletions(-)

Comments

Dirk Behme Jan. 26, 2016, 4:56 p.m. UTC | #1
On 26.01.2016 12:46, Wolfram Sang wrote:
> From: Wolfram Sang <wsa+renesas@sang-engineering.com>
>
> Most registers need to wait until the command is completed, not
> necessarily until the bus is free. RCar SoCs can signal that via the
> CBSY bit, so let's use it instead of SCLKDIVEN to save a few ns of
> delay.
>
> Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
> ---
>   drivers/mmc/host/sh_mobile_sdhi.c | 15 +++++++++++----
>   include/linux/mmc/tmio.h          |  3 +++
>   2 files changed, 14 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
> index 12419acb8ac9f5..dd08e945b2d3dd 100644
> --- a/drivers/mmc/host/sh_mobile_sdhi.c
> +++ b/drivers/mmc/host/sh_mobile_sdhi.c
> @@ -156,11 +156,13 @@ static void sh_mobile_sdhi_clk_disable(struct platform_device *pdev)
>   	clk_disable_unprepare(priv->clk);
>   }
>
> -static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host)
> +static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host, u16 bit)
>   {
>   	int timeout = 1000;
> +	/* CBSY is set when busy, SCLKDIVEN is cleared when busy */
> +	u16 wait_state = (bit == STATUS2_CBSY ? STATUS2_CBSY : 0);
>
> -	while (--timeout && !(sd_ctrl_read16(host, CTL_STATUS2) & (1 << 13)))
> +	while (--timeout && (sd_ctrl_read16(host, CTL_STATUS2) & bit) == wait_state)
>   		udelay(1);
>
>   	if (!timeout) {
> @@ -173,18 +175,23 @@ static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host)
>
>   static int sh_mobile_sdhi_write16_hook(struct tmio_mmc_host *host, int addr)
>   {
> +	u16 bit = STATUS2_SCLKDIVEN;
> +
>   	switch (addr)
>   	{
>   	case CTL_SD_CMD:
>   	case CTL_STOP_INTERNAL_ACTION:
>   	case CTL_XFER_BLK_COUNT:
> -	case CTL_SD_CARD_CLK_CTL:
>   	case CTL_SD_XFER_LEN:
>   	case CTL_SD_MEM_CARD_OPT:
>   	case CTL_TRANSACTION_CTL:
>   	case CTL_DMA_ENABLE:
>   	case EXT_ACC:
> -		return sh_mobile_sdhi_wait_idle(host);
> +		if (host->pdata->flags & TMIO_MMC_IS_RCAR)
> +			bit = STATUS2_CBSY;
> +		/* fallthrough */
> +	case CTL_SD_CARD_CLK_CTL:
> +		return sh_mobile_sdhi_wait_idle(host, bit);


I had to re-read the manual to get an idea what's special with 
CTL_SD_CARD_CLK_CTL so that it's done this way.

Maybe we should mention this in the commit message? E.g.

"Most registers except CTL_SD_CARD_CLK_CTL need to wait until ..."

?

Best regards

Dirk



>   	}
>
>   	return 0;
> diff --git a/include/linux/mmc/tmio.h b/include/linux/mmc/tmio.h
> index 5f5cd80e976500..6ae480d6fec891 100644
> --- a/include/linux/mmc/tmio.h
> +++ b/include/linux/mmc/tmio.h
> @@ -63,6 +63,9 @@
>   #define TMIO_STAT_CMD_BUSY      0x40000000
>   #define TMIO_STAT_ILL_ACCESS    0x80000000
>
> +#define STATUS2_CBSY		BIT(14)		/* only known on RCar */
> +#define STATUS2_SCLKDIVEN	BIT(13)
> +
>   #define	CLK_CTL_DIV_MASK	0xff
>   #define	CLK_CTL_SCLKEN		BIT(8)
>
>
diff mbox

Patch

diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index 12419acb8ac9f5..dd08e945b2d3dd 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -156,11 +156,13 @@  static void sh_mobile_sdhi_clk_disable(struct platform_device *pdev)
 	clk_disable_unprepare(priv->clk);
 }
 
-static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host)
+static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host, u16 bit)
 {
 	int timeout = 1000;
+	/* CBSY is set when busy, SCLKDIVEN is cleared when busy */
+	u16 wait_state = (bit == STATUS2_CBSY ? STATUS2_CBSY : 0);
 
-	while (--timeout && !(sd_ctrl_read16(host, CTL_STATUS2) & (1 << 13)))
+	while (--timeout && (sd_ctrl_read16(host, CTL_STATUS2) & bit) == wait_state)
 		udelay(1);
 
 	if (!timeout) {
@@ -173,18 +175,23 @@  static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host)
 
 static int sh_mobile_sdhi_write16_hook(struct tmio_mmc_host *host, int addr)
 {
+	u16 bit = STATUS2_SCLKDIVEN;
+
 	switch (addr)
 	{
 	case CTL_SD_CMD:
 	case CTL_STOP_INTERNAL_ACTION:
 	case CTL_XFER_BLK_COUNT:
-	case CTL_SD_CARD_CLK_CTL:
 	case CTL_SD_XFER_LEN:
 	case CTL_SD_MEM_CARD_OPT:
 	case CTL_TRANSACTION_CTL:
 	case CTL_DMA_ENABLE:
 	case EXT_ACC:
-		return sh_mobile_sdhi_wait_idle(host);
+		if (host->pdata->flags & TMIO_MMC_IS_RCAR)
+			bit = STATUS2_CBSY;
+		/* fallthrough */
+	case CTL_SD_CARD_CLK_CTL:
+		return sh_mobile_sdhi_wait_idle(host, bit);
 	}
 
 	return 0;
diff --git a/include/linux/mmc/tmio.h b/include/linux/mmc/tmio.h
index 5f5cd80e976500..6ae480d6fec891 100644
--- a/include/linux/mmc/tmio.h
+++ b/include/linux/mmc/tmio.h
@@ -63,6 +63,9 @@ 
 #define TMIO_STAT_CMD_BUSY      0x40000000
 #define TMIO_STAT_ILL_ACCESS    0x80000000
 
+#define STATUS2_CBSY		BIT(14)		/* only known on RCar */
+#define STATUS2_SCLKDIVEN	BIT(13)
+
 #define	CLK_CTL_DIV_MASK	0xff
 #define	CLK_CTL_SCLKEN		BIT(8)